Merge pull request #261 from martinbremmer/merge
Merge master into security
This commit is contained in:
commit
992d2b6e55
128 changed files with 6936 additions and 2075 deletions
26
.travis.yml
26
.travis.yml
|
|
@ -68,9 +68,9 @@ linux_clang: &linux_clang
|
|||
install:
|
||||
- pip install conan --upgrade --user
|
||||
|
||||
osx_xcode10_2: &osx_xcode10_2
|
||||
osx_xcode10_3: &osx_xcode10_3
|
||||
os: osx
|
||||
osx_image: xcode10.2
|
||||
osx_image: xcode10.3
|
||||
compiler: clang
|
||||
addons:
|
||||
homebrew:
|
||||
|
|
@ -147,9 +147,9 @@ jobs:
|
|||
env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, SSL=YES, GENERATOR="Unix Makefiles" ]
|
||||
- <<: *linux_clang
|
||||
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, GENERATOR="Unix Makefiles" ]
|
||||
- <<: *osx_xcode10_2
|
||||
- <<: *osx_xcode10_3
|
||||
env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, SSL=YES, GENERATOR="Unix Makefiles" ]
|
||||
- <<: *osx_xcode10_2
|
||||
- <<: *osx_xcode10_3
|
||||
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, GENERATOR="Unix Makefiles" ]
|
||||
- <<: *windows_vs2017
|
||||
env: [ ARCH=x86, ASAN=none, BUILD_TYPE=Debug, SSL=YES, GENERATOR="Visual Studio 15 2017" ]
|
||||
|
|
@ -162,6 +162,22 @@ before_script:
|
|||
- conan profile new default --detect
|
||||
- conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan
|
||||
|
||||
# Notes on test settings:
|
||||
# - CYCLONEDDS_URI:
|
||||
# - EnableExpensiveChecks: for the few horrendously expensive (but pretty thorough)
|
||||
# integrity checks, in particular on the WHC and the RHC, but there may be more
|
||||
# - config to stderr: gives the configuration used when running the test in conjunction
|
||||
# with "--output-on-failure" (sadly that still doesn't output the failed
|
||||
# assertions ...)
|
||||
# - -j 4: run 4 tests in parallel, this saves quite a bit of time because the VMs are
|
||||
# all dual-core
|
||||
# - --output-on-failed: print whatever output the test generated when it failed, which
|
||||
# can obviously be quite helpful for debugging
|
||||
# - -E ...: regex of tests to exclude:
|
||||
# CUnit_ddsrt_random_default_random: performs a Chi-square test on the output of
|
||||
# the random generator, but this does produce the odd failure (it should!). The
|
||||
# code has been vetted, the test has been run a great many times (with the odd
|
||||
# failure), and so we now simply skip the test to avoid the spurious failures.
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
|
|
@ -184,7 +200,7 @@ script:
|
|||
${SCAN_BUILD} cmake --build . --config ${BUILD_TYPE} --target install
|
||||
;;
|
||||
esac
|
||||
- CYCLONEDDS_URI='<CycloneDDS><Domain><Internal><EnableExpensiveChecks>all</EnableExpensiveChecks></Internal><Tracing><Verbosity>config</Verbosity><OutputFile>stderr</OutputFile></Tracing></Domain></CycloneDDS>' ctest -j 4 --output-on-failure -T test -C ${BUILD_TYPE}
|
||||
- CYCLONEDDS_URI='<CycloneDDS><Domain><Internal><EnableExpensiveChecks>all</EnableExpensiveChecks></Internal><Tracing><Verbosity>config</Verbosity><OutputFile>stderr</OutputFile></Tracing></Domain></CycloneDDS>' ctest -j 4 --output-on-failure -T test -E '^CUnit_ddsrt_random_default_random$' -C ${BUILD_TYPE}
|
||||
- if [ "${ASAN}" != "none" ]; then
|
||||
CMAKE_LINKER_FLAGS="-DCMAKE_LINKER_FLAGS=-fsanitize=${USE_SANITIZER}";
|
||||
CMAKE_C_FLAGS="-DCMAKE_C_FLAGS=-fsanitize=${USE_SANITIZER}";
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ The Java-based components are the preprocessor and a configurator tool. The run
|
|||
pure C code, so there is no need to have Java available on "target" machines. If desired, it is
|
||||
possible to do a build without Java or Maven installed by defining ``BUILD_IDLC=NO`` and
|
||||
``BUILD_CONFTOOL=NO``, but that effectively only gets you the core library. For the
|
||||
current [ROS2 RMW layer](https://github.com/atolab/rmw_cyclonedds), that is sufficient.
|
||||
current [ROS2 RMW layer](https://github.com/ros2/rmw_cyclonedds), that is sufficient.
|
||||
|
||||
To obtain Eclipse Cyclone DDS, do
|
||||
|
||||
|
|
|
|||
|
|
@ -47,4 +47,4 @@ build_script:
|
|||
|
||||
test_script:
|
||||
- set "CYCLONEDDS_URI=<CycloneDDS><Domain><Internal><EnableExpensiveChecks>all</EnableExpensiveChecks></Internal><Tracing><Verbosity>config</Verbosity><OutputFile>stderr</OutputFile></Tracing></Domain></CycloneDDS>"
|
||||
- ctest --output-on-failure --parallel 4 --test-action test --build-config %CONFIGURATION%
|
||||
- ctest --output-on-failure --parallel 4 --exclude-regex "^CUnit_ddsrt_random_default_random$" --test-action test --build-config %CONFIGURATION%
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"name": "cyclonedds"
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[requires]
|
||||
cunit/2.1-3@bincrafters/stable
|
||||
OpenSSL/1.1.1a@conan/stable
|
||||
OpenSSL/1.1.1c@conan/stable
|
||||
|
||||
[generators]
|
||||
cmake
|
||||
|
|
|
|||
25
package.xml
Normal file
25
package.xml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="3">
|
||||
<name>cyclonedds</name>
|
||||
<version>0.1.0</version>
|
||||
<description>Eclipse Cyclone DDS is a very performant and robust open-source DDS implementation. Cyclone DDS is developed completely in the open as an Eclipse IoT project.</description>
|
||||
<maintainer email="cyclonedds-dev@eclipse.org">Eclipse Foundation, Inc.</maintainer>
|
||||
<license>Eclipse Public License 2.0</license>
|
||||
|
||||
<url type="website">https://projects.eclipse.org/projects/iot.cyclonedds</url>
|
||||
<url type="bugtracker">https://github.com/eclipse-cyclonedds/cyclonedds/issues</url>
|
||||
<url type="repository">https://github.com/eclipse-cyclonedds/cyclonedds</url>
|
||||
|
||||
<buildtool_depend>cmake</buildtool_depend>
|
||||
<buildtool_depend>java</buildtool_depend>
|
||||
<buildtool_depend>maven</buildtool_depend>
|
||||
<depend>openssl</depend>
|
||||
<test_depend>libcunit-dev</test_depend>
|
||||
<doc_depend>python3-sphinx</doc_depend>
|
||||
|
||||
<export>
|
||||
<build_type>cmake</build_type>
|
||||
</export>
|
||||
</package>
|
||||
|
||||
|
|
@ -50,6 +50,7 @@ PREPEND(hdrs_public_ddsc "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/dd
|
|||
ddsc/dds_public_qos.h
|
||||
ddsc/dds_public_qosdefs.h
|
||||
ddsc/dds_public_status.h
|
||||
ddsc/dds_rhc.h
|
||||
)
|
||||
|
||||
PREPEND(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src"
|
||||
|
|
@ -67,7 +68,6 @@ PREPEND(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src"
|
|||
dds__readcond.h
|
||||
dds__guardcond.h
|
||||
dds__reader.h
|
||||
dds__rhc.h
|
||||
dds__rhc_default.h
|
||||
dds__stream.h
|
||||
dds__subscriber.h
|
||||
|
|
|
|||
|
|
@ -49,19 +49,9 @@ typedef int32_t dds_entity_t;
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct dds_rhc;
|
||||
struct ddsi_serdata;
|
||||
|
||||
/**
|
||||
* @brief Returns the default domain identifier.
|
||||
*
|
||||
* The default domain identifier can be configured in the configuration file
|
||||
* or be set through an evironment variable ({DDSC_PROJECT_NAME_NOSPACE_CAPS}_DOMAIN).
|
||||
*
|
||||
* @returns Default domain identifier
|
||||
*/
|
||||
DDS_EXPORT dds_domainid_t dds_domain_default (void);
|
||||
|
||||
|
||||
#define DDS_MIN_PSEUDO_HANDLE ((dds_entity_t) 0x7fff0000)
|
||||
|
||||
/* @defgroup builtintopic_constants Convenience constants for referring to builtin topics
|
||||
|
|
@ -77,6 +67,9 @@ DDS_EXPORT dds_domainid_t dds_domain_default (void);
|
|||
#define DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION ((dds_entity_t) (DDS_MIN_PSEUDO_HANDLE + 4))
|
||||
/** @}*/
|
||||
|
||||
/** Special handle representing the entity corresponding to the CycloneDDS library itself */
|
||||
#define DDS_CYCLONEDDS_HANDLE ((dds_entity_t) (DDS_MIN_PSEUDO_HANDLE + 256))
|
||||
|
||||
/** @name Communication Status definitions
|
||||
@{**/
|
||||
typedef enum dds_status_id {
|
||||
|
|
@ -733,7 +726,7 @@ dds_set_listener(dds_entity_t entity, const dds_listener_t * listener);
|
|||
* If no configuration file exists, the default domain is configured as 0.
|
||||
*
|
||||
*
|
||||
* @param[in] domain The domain in which to create the participant (can be DDS_DOMAIN_DEFAULT). Valid values for domain id are between 0 and 230. DDS_DOMAIN_DEFAULT is for using the domain in the configuration.
|
||||
* @param[in] domain The domain in which to create the participant (can be DDS_DOMAIN_DEFAULT). DDS_DOMAIN_DEFAULT is for using the domain in the configuration.
|
||||
* @param[in] qos The QoS to set on the new participant (can be NULL).
|
||||
* @param[in] listener Any listener functions associated with the new participant (can be NULL).
|
||||
|
||||
|
|
@ -750,6 +743,33 @@ dds_create_participant(
|
|||
const dds_qos_t *qos,
|
||||
const dds_listener_t *listener);
|
||||
|
||||
/**
|
||||
* @brief Creates a domain with a given configuration
|
||||
*
|
||||
* To explicitly create a domain based on a configuration passed as a string.
|
||||
* Normally, the domain is created implicitly on the first call to
|
||||
* dds_create_particiant based on the configuration specified throught
|
||||
* the environment. This function allows to by-pass this behaviour.
|
||||
*
|
||||
*
|
||||
* @param[in] domain The domain to be created. DEFAULT_DOMAIN is not allowed.
|
||||
* @param[in] config A configuration string containing file names and/or XML fragments representing the configuration.
|
||||
*
|
||||
* @returns A return code
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* The domain with the domain identifier has been created from
|
||||
* given configuration string.
|
||||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
* Illegal value for domain id or the configfile parameter is NULL.
|
||||
* @retval DDS_PRECONDITION_NOT_MET
|
||||
* The domain already existed and cannot be created again.
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* An internal error has occurred.
|
||||
*/
|
||||
DDS_EXPORT dds_return_t
|
||||
dds_create_domain(const dds_domainid_t domain, const char *config);
|
||||
|
||||
/**
|
||||
* @brief Get entity parent.
|
||||
*
|
||||
|
|
@ -871,7 +891,8 @@ dds_get_children(dds_entity_t entity, dds_entity_t *children, size_t size);
|
|||
* DataReaders), etc are also attached to that domain.
|
||||
*
|
||||
* This function will return the original domain ID when called on
|
||||
* any of the entities within that hierarchy.
|
||||
* any of the entities within that hierarchy. For entities not associated
|
||||
* with a domain, the id is set to DDS_DOMAIN_DEFAULT.
|
||||
*
|
||||
* @param[in] entity Entity from which to get its children.
|
||||
* @param[out] id Pointer to put the domain ID in.
|
||||
|
|
@ -1202,6 +1223,34 @@ dds_create_reader(
|
|||
const dds_qos_t *qos,
|
||||
const dds_listener_t *listener);
|
||||
|
||||
/**
|
||||
* @brief Creates a new instance of a DDS reader with a custom history cache.
|
||||
*
|
||||
* This implicit subscriber will be deleted automatically when the created reader
|
||||
* is deleted.
|
||||
*
|
||||
* @param[in] participant_or_subscriber The participant or subscriber on which the reader is being created.
|
||||
* @param[in] topic The topic to read.
|
||||
* @param[in] qos The QoS to set on the new reader (can be NULL).
|
||||
* @param[in] listener Any listener functions associated with the new reader (can be NULL).
|
||||
* @param[in] rhc Reader history cache to use, reader becomes the owner
|
||||
*
|
||||
* @returns A valid reader handle or an error code.
|
||||
*
|
||||
* @retval >0
|
||||
* A valid reader handle.
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* An internal error occurred.
|
||||
*/
|
||||
/* TODO: Complete list of error codes */
|
||||
DDS_EXPORT dds_entity_t
|
||||
dds_create_reader_rhc(
|
||||
dds_entity_t participant_or_subscriber,
|
||||
dds_entity_t topic,
|
||||
const dds_qos_t *qos,
|
||||
const dds_listener_t *listener,
|
||||
struct dds_rhc *rhc);
|
||||
|
||||
/**
|
||||
* @brief Wait until reader receives all historic data
|
||||
*
|
||||
|
|
|
|||
|
|
@ -108,7 +108,9 @@ typedef enum dds_entity_kind
|
|||
DDS_KIND_COND_READ,
|
||||
DDS_KIND_COND_QUERY,
|
||||
DDS_KIND_COND_GUARD,
|
||||
DDS_KIND_WAITSET
|
||||
DDS_KIND_WAITSET,
|
||||
DDS_KIND_DOMAIN,
|
||||
DDS_KIND_CYCLONEDDS
|
||||
} dds_entity_kind_t;
|
||||
|
||||
/* Handles are opaque pointers to implementation types */
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@
|
|||
#define _DDS_RHC_H_
|
||||
|
||||
#include "dds/ddsrt/static_assert.h"
|
||||
#include "dds/ddsi/q_rhc.h"
|
||||
#include "dds__types.h" /* for dds_readcond */
|
||||
#include "dds/ddsi/ddsi_rhc.h"
|
||||
|
||||
#define NO_STATE_MASK_SET (DDS_ANY_STATE + 1)
|
||||
|
||||
|
|
@ -23,42 +22,50 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
struct dds_rhc;
|
||||
struct dds_readcond;
|
||||
struct dds_reader;
|
||||
struct ddsi_tkmap;
|
||||
|
||||
typedef dds_return_t (*dds_rhc_associate_t) (struct dds_rhc *rhc, struct dds_reader *reader, const struct ddsi_sertopic *topic, struct ddsi_tkmap *tkmap);
|
||||
typedef int (*dds_rhc_read_t) (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond);
|
||||
typedef int (*dds_rhc_take_t) (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond);
|
||||
typedef int (*dds_rhc_takecdr_t) (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle);
|
||||
|
||||
typedef bool (*dds_rhc_add_readcondition_t) (struct dds_readcond *cond);
|
||||
typedef void (*dds_rhc_remove_readcondition_t) (struct dds_readcond *cond);
|
||||
typedef bool (*dds_rhc_add_readcondition_t) (struct dds_rhc *rhc, struct dds_readcond *cond);
|
||||
typedef void (*dds_rhc_remove_readcondition_t) (struct dds_rhc *rhc, struct dds_readcond *cond);
|
||||
|
||||
typedef uint32_t (*dds_rhc_lock_samples_t) (struct dds_rhc *rhc);
|
||||
|
||||
struct dds_rhc_ops {
|
||||
/* A copy of DDSI rhc ops comes first so we can use either interface without
|
||||
additional indirections */
|
||||
struct rhc_ops rhc_ops;
|
||||
struct ddsi_rhc_ops rhc_ops;
|
||||
dds_rhc_read_t read;
|
||||
dds_rhc_take_t take;
|
||||
dds_rhc_takecdr_t takecdr;
|
||||
dds_rhc_add_readcondition_t add_readcondition;
|
||||
dds_rhc_remove_readcondition_t remove_readcondition;
|
||||
dds_rhc_lock_samples_t lock_samples;
|
||||
dds_rhc_associate_t associate;
|
||||
};
|
||||
|
||||
struct dds_rhc {
|
||||
union {
|
||||
const struct dds_rhc_ops *ops;
|
||||
struct rhc rhc;
|
||||
struct ddsi_rhc rhc;
|
||||
} common;
|
||||
};
|
||||
|
||||
DDSRT_STATIC_ASSERT (offsetof (struct dds_rhc, common.ops) == offsetof (struct rhc, ops));
|
||||
DDSRT_STATIC_ASSERT (offsetof (struct dds_rhc, common.ops) == offsetof (struct ddsi_rhc, ops));
|
||||
|
||||
DDS_EXPORT inline bool dds_rhc_store (struct dds_rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk) {
|
||||
return rhc->common.ops->rhc_ops.store (&rhc->common.rhc, pwr_info, sample, tk);
|
||||
DDS_EXPORT inline dds_return_t dds_rhc_associate (struct dds_rhc *rhc, struct dds_reader *reader, const struct ddsi_sertopic *topic, struct ddsi_tkmap *tkmap) {
|
||||
return rhc->common.ops->associate (rhc, reader, topic, tkmap);
|
||||
}
|
||||
DDS_EXPORT inline void dds_rhc_unregister_wr (struct dds_rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info) {
|
||||
rhc->common.ops->rhc_ops.unregister_wr (&rhc->common.rhc, pwr_info);
|
||||
DDS_EXPORT inline bool dds_rhc_store (struct dds_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk) {
|
||||
return rhc->common.ops->rhc_ops.store (&rhc->common.rhc, wrinfo, sample, tk);
|
||||
}
|
||||
DDS_EXPORT inline void dds_rhc_unregister_wr (struct dds_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo) {
|
||||
rhc->common.ops->rhc_ops.unregister_wr (&rhc->common.rhc, wrinfo);
|
||||
}
|
||||
DDS_EXPORT inline void dds_rhc_relinquish_ownership (struct dds_rhc * __restrict rhc, const uint64_t wr_iid) {
|
||||
rhc->common.ops->rhc_ops.relinquish_ownership (&rhc->common.rhc, wr_iid);
|
||||
|
|
@ -78,16 +85,18 @@ DDS_EXPORT inline int dds_rhc_take (struct dds_rhc *rhc, bool lock, void **value
|
|||
DDS_EXPORT inline int dds_rhc_takecdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) {
|
||||
return rhc->common.ops->takecdr (rhc, lock, values, info_seq, max_samples, sample_states, view_states, instance_states, handle);
|
||||
}
|
||||
DDS_EXPORT inline bool dds_rhc_add_readcondition (struct dds_readcond *cond) {
|
||||
return cond->m_rhc->common.ops->add_readcondition (cond);
|
||||
DDS_EXPORT inline bool dds_rhc_add_readcondition (struct dds_rhc *rhc, struct dds_readcond *cond) {
|
||||
return rhc->common.ops->add_readcondition (rhc, cond);
|
||||
}
|
||||
DDS_EXPORT inline void dds_rhc_remove_readcondition (struct dds_readcond *cond) {
|
||||
cond->m_rhc->common.ops->remove_readcondition (cond);
|
||||
DDS_EXPORT inline void dds_rhc_remove_readcondition (struct dds_rhc *rhc, struct dds_readcond *cond) {
|
||||
rhc->common.ops->remove_readcondition (rhc, cond);
|
||||
}
|
||||
DDS_EXPORT inline uint32_t dds_rhc_lock_samples (struct dds_rhc *rhc) {
|
||||
return rhc->common.ops->lock_samples (rhc);
|
||||
}
|
||||
|
||||
DDS_EXPORT void dds_reader_data_available_cb (struct dds_reader *rd);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
@ -18,8 +18,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
DDS_EXPORT dds_return_t dds_domain_create (dds_domain **domain_out, dds_domainid_t id);
|
||||
DDS_EXPORT void dds_domain_free (dds_domain *domain);
|
||||
DDS_EXPORT dds_return_t dds_domain_create_internal (dds_domain **domain_out, dds_domainid_t id, bool use_existing, const char *config) ddsrt_nonnull((1,4));
|
||||
DDS_EXPORT dds_domain *dds_domain_find_locked (dds_domainid_t id);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ dds_entity_init(
|
|||
const dds_listener_t *listener,
|
||||
status_mask_t mask);
|
||||
|
||||
DDS_EXPORT void dds_entity_init_complete (dds_entity *entity);
|
||||
|
||||
DDS_EXPORT void
|
||||
dds_entity_register_child (
|
||||
dds_entity *parent,
|
||||
|
|
@ -46,7 +48,6 @@ dds_entity_add_ref_locked(dds_entity *e);
|
|||
*x = (type_ *) e; \
|
||||
return DDS_RETCODE_OK; \
|
||||
} \
|
||||
\
|
||||
qualifier_ void type_##_unlock (type_ *x) \
|
||||
{ \
|
||||
dds_entity_unlock (&x->m_entity); \
|
||||
|
|
@ -78,6 +79,18 @@ DDS_EXPORT void dds_entity_status_signal (dds_entity *e, uint32_t status);
|
|||
|
||||
DDS_EXPORT void dds_entity_invoke_listener (const dds_entity *entity, enum dds_status_id which, const void *vst);
|
||||
|
||||
DDS_EXPORT dds_participant *dds_entity_participant (dds_entity *e);
|
||||
DDS_EXPORT void dds_entity_final_deinit_before_free (dds_entity *e);
|
||||
DDS_EXPORT bool dds_entity_in_scope (const dds_entity *e, const dds_entity *root);
|
||||
|
||||
enum delete_impl_state {
|
||||
DIS_EXPLICIT, /* explicit delete on this entity */
|
||||
DIS_FROM_PARENT, /* called because the parent is being deleted */
|
||||
DIS_IMPLICIT /* called from child; delete if implicit w/o children */
|
||||
};
|
||||
|
||||
DDS_EXPORT dds_return_t dds_delete_impl_pinned (dds_entity *e, enum delete_impl_state delstate);
|
||||
|
||||
DDS_EXPORT dds_return_t
|
||||
dds_entity_pin (
|
||||
dds_entity_t hdl,
|
||||
|
|
@ -98,23 +111,16 @@ dds_entity_unlock(dds_entity *e);
|
|||
DDS_EXPORT dds_return_t
|
||||
dds_entity_observer_register(
|
||||
dds_entity *observed,
|
||||
dds_entity *observer,
|
||||
dds_entity_callback cb,
|
||||
dds_entity_delete_callback delete_cb);
|
||||
dds_waitset *observer,
|
||||
dds_entity_callback_t cb,
|
||||
dds_entity_attach_callback_t attach_cb, void *attach_arg,
|
||||
dds_entity_delete_callback_t delete_cb);
|
||||
|
||||
DDS_EXPORT dds_return_t
|
||||
dds_entity_observer_unregister(
|
||||
dds_entity *observed,
|
||||
dds_entity *observer);
|
||||
|
||||
DDS_EXPORT dds_return_t
|
||||
dds_delete_impl(
|
||||
dds_entity_t entity,
|
||||
bool keep_if_explicit);
|
||||
|
||||
DDS_EXPORT dds_domain *
|
||||
dds__entity_domain(
|
||||
dds_entity* e);
|
||||
dds_waitset *observer,
|
||||
bool invoke_delete_cb);
|
||||
|
||||
DDS_EXPORT dds_return_t
|
||||
dds_generic_unimplemented_operation_manykinds(
|
||||
|
|
|
|||
|
|
@ -69,6 +69,13 @@ typedef int32_t dds_handle_t;
|
|||
* This handlelink is invalid after the related handle is deleted and should
|
||||
* never be used afterwards.
|
||||
*/
|
||||
|
||||
/* Closing & closed can be combined, but having two gives a means for enforcing
|
||||
that close() be called first, then close_wait(), and then delete(). */
|
||||
#define HDL_FLAG_CLOSING (0x80000000u)
|
||||
#define HDL_FLAG_CLOSED (0x40000000u)
|
||||
#define HDL_FLAG_PENDING (0x20000000u)
|
||||
|
||||
struct dds_handle_link {
|
||||
dds_handle_t hdl;
|
||||
ddsrt_atomic_uint32_t cnt_flags;
|
||||
|
|
@ -112,6 +119,15 @@ dds_handle_create(
|
|||
struct dds_handle_link *link);
|
||||
|
||||
|
||||
/*
|
||||
* Register a specific handle.
|
||||
*/
|
||||
DDS_EXPORT dds_return_t
|
||||
dds_handle_register_special (
|
||||
struct dds_handle_link *link, dds_handle_t handle);
|
||||
|
||||
DDS_EXPORT void dds_handle_unpend (struct dds_handle_link *link);
|
||||
|
||||
/*
|
||||
* This will close the handle. All information remains, only new claims will
|
||||
* fail.
|
||||
|
|
@ -119,10 +135,9 @@ dds_handle_create(
|
|||
* This is a noop on an already closed handle.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
dds_handle_close(
|
||||
dds_handle_close_wait (
|
||||
struct dds_handle_link *link);
|
||||
|
||||
|
||||
/*
|
||||
* This will remove the handle related information from the server administration
|
||||
* to free up space.
|
||||
|
|
@ -134,8 +149,7 @@ dds_handle_close(
|
|||
*/
|
||||
DDS_EXPORT int32_t
|
||||
dds_handle_delete(
|
||||
struct dds_handle_link *link,
|
||||
dds_time_t timeout);
|
||||
struct dds_handle_link *link);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -149,6 +163,11 @@ dds_handle_pin(
|
|||
dds_handle_t hdl,
|
||||
struct dds_handle_link **entity);
|
||||
|
||||
DDS_EXPORT int32_t
|
||||
dds_handle_pin_and_ref(
|
||||
dds_handle_t hdl,
|
||||
struct dds_handle_link **entity);
|
||||
|
||||
|
||||
DDS_EXPORT void
|
||||
dds_handle_repin(
|
||||
|
|
@ -172,14 +191,15 @@ dds_handle_unpin(
|
|||
* break of your process and release the handle, making the deletion
|
||||
* possible.
|
||||
*/
|
||||
DDS_EXPORT bool
|
||||
dds_handle_is_closed(
|
||||
struct dds_handle_link *link);
|
||||
|
||||
|
||||
DDS_EXPORT void dds_handle_add_ref (struct dds_handle_link *link);
|
||||
DDS_EXPORT bool dds_handle_drop_ref (struct dds_handle_link *link);
|
||||
|
||||
DDS_EXPORT inline bool dds_handle_is_closed (struct dds_handle_link *link) {
|
||||
return (ddsrt_atomic_ld32 (&link->cnt_flags) & (HDL_FLAG_CLOSED | HDL_FLAG_CLOSING)) != 0;
|
||||
}
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -19,27 +19,15 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/**
|
||||
*Description : Initialization function, called from main. This operation
|
||||
*initializes all the required DDS resources,
|
||||
*handles configuration of domainid based on the input passed, parses and
|
||||
*configures middleware from a xml file and initializes required resources.
|
||||
*Description : Initializes the library and constructs the global
|
||||
*pseudo-entity identified by DDS_CYCLONEDDS_HANDLE with one reference
|
||||
*that must (eventually) be released by calling dds_delete on that handle.
|
||||
*
|
||||
*Arguments :
|
||||
*-# Returns 0 on success or a non-zero error status
|
||||
**/
|
||||
dds_return_t dds_init (void);
|
||||
|
||||
/* Finalization function, called from main */
|
||||
|
||||
/**
|
||||
*Description : Finalization function, called from main. This operation
|
||||
*releases all the resources used by DDS.
|
||||
*
|
||||
*Arguments :
|
||||
*-# None
|
||||
**/
|
||||
void dds_fini (void);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ struct status_cb_data;
|
|||
|
||||
void dds_reader_status_cb (void *entity, const struct status_cb_data * data);
|
||||
|
||||
void dds_reader_data_available_cb (struct dds_reader *entity);
|
||||
|
||||
/*
|
||||
dds_reader_lock_samples: Returns number of samples in read cache and locks the
|
||||
reader cache to make sure that the samples content doesn't change.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ extern "C" {
|
|||
|
||||
struct ddsi_serdata_builtintopic {
|
||||
struct ddsi_serdata c;
|
||||
nn_guid_t key;
|
||||
ddsi_guid_t key;
|
||||
dds_instance_handle_t pphandle;
|
||||
dds_qos_t xqos;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@ void dds_stream_extract_keyhash (dds_istream_t * __restrict is, dds_keyhash_t *
|
|||
|
||||
void dds_stream_read_key (dds_istream_t * __restrict is, char * __restrict sample, const struct ddsi_sertopic_default * __restrict topic);
|
||||
|
||||
size_t dds_stream_print_key (dds_istream_t * __restrict is, const struct ddsi_sertopic_default * __restrict topic, char * __restrict buf, size_t size);
|
||||
|
||||
size_t dds_stream_print_sample (dds_istream_t * __restrict is, const struct ddsi_sertopic_default * __restrict topic, char * __restrict buf, size_t size);
|
||||
|
||||
/* For marshalling op code handling */
|
||||
|
||||
#define DDS_OP_MASK 0xff000000
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ struct dds_guardcond;
|
|||
struct dds_statuscond;
|
||||
|
||||
struct ddsi_sertopic;
|
||||
struct rhc;
|
||||
struct ddsi_rhc;
|
||||
|
||||
typedef uint16_t status_mask_t;
|
||||
typedef ddsrt_atomic_uint32_t status_and_enabled_t;
|
||||
|
|
@ -90,47 +90,32 @@ struct dds_listener {
|
|||
|
||||
/* Entity flag values */
|
||||
|
||||
#define DDS_ENTITY_ENABLED 0x0001u
|
||||
#define DDS_ENTITY_IMPLICIT 0x0002u
|
||||
|
||||
typedef struct dds_domain {
|
||||
/* FIXME: protected by dds_global.lock -- for now */
|
||||
ddsrt_avl_node_t m_node;
|
||||
dds_domainid_t m_id;
|
||||
ddsrt_avl_tree_t m_topics;
|
||||
ddsrt_avl_tree_t m_ppants;
|
||||
uint32_t m_refc;
|
||||
struct cfgst *cfgst;
|
||||
|
||||
struct ddsi_sertopic *builtin_participant_topic;
|
||||
struct ddsi_sertopic *builtin_reader_topic;
|
||||
struct ddsi_sertopic *builtin_writer_topic;
|
||||
|
||||
struct local_orphan_writer *builtintopic_writer_participant;
|
||||
struct local_orphan_writer *builtintopic_writer_publications;
|
||||
struct local_orphan_writer *builtintopic_writer_subscriptions;
|
||||
|
||||
struct ddsi_builtin_topic_interface btif;
|
||||
struct q_globals gv;
|
||||
} dds_domain;
|
||||
#define DDS_ENTITY_ENABLED ((uint32_t) 0x1) /* DDS "enabled" state */
|
||||
#define DDS_ENTITY_IMPLICIT ((uint32_t) 0x2) /* implicit ones get deleted when the last child is deleted */
|
||||
|
||||
struct dds_domain;
|
||||
struct dds_entity;
|
||||
|
||||
typedef struct dds_entity_deriver {
|
||||
/* Close can be used to terminate (blocking) actions on a entity before actually deleting it. */
|
||||
dds_return_t (*close)(struct dds_entity *e) ddsrt_nonnull_all;
|
||||
/* Pending close can be used to terminate (blocking) actions on a entity before actually deleting it. */
|
||||
void (*interrupt) (struct dds_entity *e) ddsrt_nonnull_all;
|
||||
/* Close can be used to do ... */
|
||||
void (*close) (struct dds_entity *e) ddsrt_nonnull_all;
|
||||
/* Delete is used to actually free the entity. */
|
||||
dds_return_t (*delete)(struct dds_entity *e) ddsrt_nonnull_all;
|
||||
dds_return_t (*set_qos)(struct dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
|
||||
dds_return_t (*validate_status)(uint32_t mask);
|
||||
dds_return_t (*delete) (struct dds_entity *e) ddsrt_nonnull_all;
|
||||
dds_return_t (*set_qos) (struct dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
|
||||
dds_return_t (*validate_status) (uint32_t mask);
|
||||
} dds_entity_deriver;
|
||||
|
||||
typedef void (*dds_entity_callback)(struct dds_entity *observer, dds_entity_t observed, uint32_t status);
|
||||
typedef void (*dds_entity_delete_callback)(struct dds_entity *observer, dds_entity_t observed);
|
||||
struct dds_waitset;
|
||||
typedef void (*dds_entity_callback_t) (struct dds_waitset *observer, dds_entity_t observed, uint32_t status);
|
||||
typedef bool (*dds_entity_attach_callback_t) (struct dds_waitset *observer, struct dds_entity *observed, void *attach_arg);
|
||||
typedef void (*dds_entity_delete_callback_t) (struct dds_waitset *observer, dds_entity_t observed);
|
||||
|
||||
typedef struct dds_entity_observer {
|
||||
dds_entity_callback m_cb;
|
||||
dds_entity_delete_callback m_delete_cb;
|
||||
struct dds_entity *m_observer;
|
||||
dds_entity_callback_t m_cb;
|
||||
dds_entity_delete_callback_t m_delete_cb;
|
||||
struct dds_waitset *m_observer;
|
||||
struct dds_entity_observer *m_next;
|
||||
} dds_entity_observer;
|
||||
|
||||
|
|
@ -141,10 +126,9 @@ typedef struct dds_entity {
|
|||
struct dds_entity *m_parent; /* constant */
|
||||
ddsrt_avl_node_t m_avlnode_child; /* [m_mutex of m_parent] */
|
||||
ddsrt_avl_tree_t m_children; /* [m_mutex] tree on m_iid using m_avlnode_child */
|
||||
struct dds_entity *m_participant; /* constant */
|
||||
struct dds_domain *m_domain; /* constant */
|
||||
dds_qos_t *m_qos; /* [m_mutex] */
|
||||
nn_guid_t m_guid; /* unique (if not 0) and constant; FIXME: set during creation, but possibly after becoming visible */
|
||||
ddsi_guid_t m_guid; /* unique (if not 0) and constant; FIXME: set during creation, but possibly after becoming visible */
|
||||
dds_instance_handle_t m_iid; /* unique for all time, constant; FIXME: like GUID */
|
||||
uint32_t m_flags; /* [m_mutex] */
|
||||
|
||||
|
|
@ -154,6 +138,7 @@ typedef struct dds_entity {
|
|||
(no hierarchical relationship there)
|
||||
- locking topic::m_mutex while holding {reader,writer}::m_mutex
|
||||
- locking observers_lock while holding m_mutex
|
||||
- locking waitset::wait_lock
|
||||
*/
|
||||
ddsrt_mutex_t m_mutex;
|
||||
ddsrt_cond_t m_cond;
|
||||
|
|
@ -167,6 +152,7 @@ typedef struct dds_entity {
|
|||
ddsrt_cond_t m_observers_cond;
|
||||
dds_listener_t m_listener; /* [m_observers_lock] */
|
||||
uint32_t m_cb_count; /* [m_observers_lock] */
|
||||
uint32_t m_cb_pending_count; /* [m_observers_lock] */
|
||||
dds_entity_observer *m_observers; /* [m_observers_lock] */
|
||||
} dds_entity;
|
||||
|
||||
|
|
@ -182,16 +168,21 @@ extern const struct dds_entity_deriver dds_entity_deriver_publisher;
|
|||
extern const struct dds_entity_deriver dds_entity_deriver_readcondition;
|
||||
extern const struct dds_entity_deriver dds_entity_deriver_guardcondition;
|
||||
extern const struct dds_entity_deriver dds_entity_deriver_waitset;
|
||||
extern const struct dds_entity_deriver dds_entity_deriver_domain;
|
||||
extern const struct dds_entity_deriver dds_entity_deriver_cyclonedds;
|
||||
extern const struct dds_entity_deriver *dds_entity_deriver_table[];
|
||||
|
||||
dds_return_t dds_entity_deriver_dummy_close (struct dds_entity *e);
|
||||
void dds_entity_deriver_dummy_interrupt (struct dds_entity *e);
|
||||
void dds_entity_deriver_dummy_close (struct dds_entity *e);
|
||||
dds_return_t dds_entity_deriver_dummy_delete (struct dds_entity *e);
|
||||
dds_return_t dds_entity_deriver_dummy_set_qos (struct dds_entity *e, const dds_qos_t *qos, bool enabled);
|
||||
dds_return_t dds_entity_deriver_dummy_validate_status (uint32_t mask);
|
||||
|
||||
|
||||
inline dds_return_t dds_entity_deriver_close (struct dds_entity *e) {
|
||||
return (dds_entity_deriver_table[e->m_kind]->close) (e);
|
||||
inline void dds_entity_deriver_interrupt (struct dds_entity *e) {
|
||||
(dds_entity_deriver_table[e->m_kind]->interrupt) (e);
|
||||
}
|
||||
inline void dds_entity_deriver_close (struct dds_entity *e) {
|
||||
(dds_entity_deriver_table[e->m_kind]->close) (e);
|
||||
}
|
||||
inline dds_return_t dds_entity_deriver_delete (struct dds_entity *e) {
|
||||
return dds_entity_deriver_table[e->m_kind]->delete (e);
|
||||
|
|
@ -209,6 +200,36 @@ inline bool dds_entity_supports_validate_status (struct dds_entity *e) {
|
|||
return dds_entity_deriver_table[e->m_kind]->validate_status != dds_entity_deriver_dummy_validate_status;
|
||||
}
|
||||
|
||||
typedef struct dds_cyclonedds_entity {
|
||||
struct dds_entity m_entity;
|
||||
|
||||
ddsrt_mutex_t m_mutex;
|
||||
ddsrt_cond_t m_cond;
|
||||
ddsrt_avl_tree_t m_domains;
|
||||
uint32_t threadmon_count;
|
||||
struct ddsi_threadmon *threadmon;
|
||||
} dds_cyclonedds_entity;
|
||||
|
||||
typedef struct dds_domain {
|
||||
struct dds_entity m_entity;
|
||||
|
||||
ddsrt_avl_node_t m_node; /* for dds_global.m_domains */
|
||||
dds_domainid_t m_id;
|
||||
ddsrt_avl_tree_t m_topics;
|
||||
struct cfgst *cfgst;
|
||||
|
||||
struct ddsi_sertopic *builtin_participant_topic;
|
||||
struct ddsi_sertopic *builtin_reader_topic;
|
||||
struct ddsi_sertopic *builtin_writer_topic;
|
||||
|
||||
struct local_orphan_writer *builtintopic_writer_participant;
|
||||
struct local_orphan_writer *builtintopic_writer_publications;
|
||||
struct local_orphan_writer *builtintopic_writer_subscriptions;
|
||||
|
||||
struct ddsi_builtin_topic_interface btif;
|
||||
struct q_globals gv;
|
||||
} dds_domain;
|
||||
|
||||
typedef struct dds_subscriber {
|
||||
struct dds_entity m_entity;
|
||||
} dds_subscriber;
|
||||
|
|
@ -279,12 +300,10 @@ typedef uint32_t dds_querycond_mask_t;
|
|||
|
||||
typedef struct dds_readcond {
|
||||
dds_entity m_entity;
|
||||
struct dds_rhc *m_rhc;
|
||||
uint32_t m_qminv;
|
||||
uint32_t m_sample_states;
|
||||
uint32_t m_view_states;
|
||||
uint32_t m_instance_states;
|
||||
nn_guid_t m_rd_guid;
|
||||
struct dds_readcond *m_next;
|
||||
struct {
|
||||
dds_querycondition_filter_fn m_filter;
|
||||
|
|
@ -304,22 +323,18 @@ typedef struct dds_attachment {
|
|||
|
||||
typedef struct dds_waitset {
|
||||
dds_entity m_entity;
|
||||
size_t nentities; /* [m_entity.m_mutex] */
|
||||
size_t ntriggered; /* [m_entity.m_mutex] */
|
||||
dds_attachment *entities; /* [m_entity.m_mutex] 0 .. ntriggered are triggred, ntriggred .. nentities are not */
|
||||
|
||||
/* Need a lock other than m_entity.m_mutex because the locking order an entity lock may not be
|
||||
acquired while holding an ancestor's lock, but a waitset must be capable of triggering on
|
||||
events on its parent */
|
||||
ddsrt_mutex_t wait_lock;
|
||||
ddsrt_cond_t wait_cond;
|
||||
size_t nentities; /* [wait_lock] */
|
||||
size_t ntriggered; /* [wait_lock] */
|
||||
dds_attachment *entities; /* [wait_lock] 0 .. ntriggered are triggred, ntriggred .. nentities are not */
|
||||
} dds_waitset;
|
||||
|
||||
/* Globals */
|
||||
|
||||
typedef struct dds_globals {
|
||||
int32_t m_init_count;
|
||||
ddsrt_avl_tree_t m_domains;
|
||||
ddsrt_mutex_t m_mutex;
|
||||
uint32_t threadmon_count;
|
||||
struct ddsi_threadmon *threadmon;
|
||||
} dds_globals;
|
||||
|
||||
DDS_EXPORT extern dds_globals dds_global;
|
||||
DDS_EXPORT extern dds_cyclonedds_entity dds_global;
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "dds__participant.h"
|
||||
#include "dds__types.h"
|
||||
#include "dds__builtin.h"
|
||||
#include "dds__entity.h"
|
||||
#include "dds__subscriber.h"
|
||||
#include "dds__write.h"
|
||||
#include "dds__writer.h"
|
||||
|
|
@ -46,9 +47,15 @@ dds_entity_t dds__get_builtin_topic (dds_entity_t entity, dds_entity_t topic)
|
|||
dds_entity_t tp;
|
||||
dds_return_t rc;
|
||||
dds_entity *e;
|
||||
dds_participant *par;
|
||||
|
||||
if ((rc = dds_entity_pin (entity, &e)) < 0)
|
||||
return rc;
|
||||
if ((par = dds_entity_participant (e)) == NULL)
|
||||
{
|
||||
dds_entity_unpin (e);
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
}
|
||||
|
||||
struct ddsi_sertopic *sertopic;
|
||||
switch (topic)
|
||||
|
|
@ -69,7 +76,7 @@ dds_entity_t dds__get_builtin_topic (dds_entity_t entity, dds_entity_t topic)
|
|||
}
|
||||
|
||||
dds_qos_t *qos = dds__create_builtin_qos ();
|
||||
tp = dds_create_topic_arbitrary (e->m_participant->m_hdllink.hdl, sertopic, qos, NULL, NULL);
|
||||
tp = dds_create_topic_arbitrary (par->m_entity.m_hdllink.hdl, sertopic, qos, NULL, NULL);
|
||||
dds_delete_qos (qos);
|
||||
dds_entity_unpin (e);
|
||||
return tp;
|
||||
|
|
@ -155,7 +162,7 @@ static bool dds__builtin_is_builtintopic (const struct ddsi_sertopic *tp, void *
|
|||
return tp->ops == &ddsi_sertopic_ops_builtintopic;
|
||||
}
|
||||
|
||||
static bool dds__builtin_is_visible (const nn_guid_t *guid, nn_vendorid_t vendorid, void *vdomain)
|
||||
static bool dds__builtin_is_visible (const ddsi_guid_t *guid, nn_vendorid_t vendorid, void *vdomain)
|
||||
{
|
||||
(void) vdomain;
|
||||
if (is_builtin_endpoint (guid->entityid, vendorid))
|
||||
|
|
@ -163,7 +170,7 @@ static bool dds__builtin_is_visible (const nn_guid_t *guid, nn_vendorid_t vendor
|
|||
return true;
|
||||
}
|
||||
|
||||
static struct ddsi_tkmap_instance *dds__builtin_get_tkmap_entry (const struct nn_guid *guid, void *vdomain)
|
||||
static struct ddsi_tkmap_instance *dds__builtin_get_tkmap_entry (const struct ddsi_guid *guid, void *vdomain)
|
||||
{
|
||||
struct dds_domain *domain = vdomain;
|
||||
struct ddsi_tkmap_instance *tk;
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@
|
|||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/environ.h"
|
||||
#include "dds/ddsrt/process.h"
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds__init.h"
|
||||
#include "dds__rhc.h"
|
||||
#include "dds/ddsc/dds_rhc.h"
|
||||
#include "dds__domain.h"
|
||||
#include "dds__builtin.h"
|
||||
#include "dds__whc_builtintopic.h"
|
||||
#include "dds__entity.h"
|
||||
#include "dds/ddsi/ddsi_iid.h"
|
||||
#include "dds/ddsi/ddsi_tkmap.h"
|
||||
#include "dds/ddsi/ddsi_serdata.h"
|
||||
|
|
@ -27,7 +27,16 @@
|
|||
#include "dds/ddsi/q_config.h"
|
||||
#include "dds/ddsi/q_gc.h"
|
||||
#include "dds/ddsi/q_globals.h"
|
||||
#include "dds/version.h"
|
||||
|
||||
static dds_return_t dds_domain_free (dds_entity *vdomain);
|
||||
|
||||
const struct dds_entity_deriver dds_entity_deriver_domain = {
|
||||
.interrupt = dds_entity_deriver_dummy_interrupt,
|
||||
.close = dds_entity_deriver_dummy_close,
|
||||
.delete = dds_domain_free,
|
||||
.set_qos = dds_entity_deriver_dummy_set_qos,
|
||||
.validate_status = dds_entity_deriver_dummy_validate_status
|
||||
};
|
||||
|
||||
static int dds_domain_compare (const void *va, const void *vb)
|
||||
{
|
||||
|
|
@ -39,14 +48,20 @@ static int dds_domain_compare (const void *va, const void *vb)
|
|||
static const ddsrt_avl_treedef_t dds_domaintree_def = DDSRT_AVL_TREEDEF_INITIALIZER (
|
||||
offsetof (dds_domain, m_node), offsetof (dds_domain, m_id), dds_domain_compare, 0);
|
||||
|
||||
static dds_return_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_id)
|
||||
static dds_return_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_id, const char *config)
|
||||
{
|
||||
dds_return_t ret = DDS_RETCODE_OK;
|
||||
char * uri = NULL;
|
||||
uint32_t len;
|
||||
dds_entity_t domain_handle;
|
||||
|
||||
if ((domain_handle = dds_entity_init (&domain->m_entity, &dds_global.m_entity, DDS_KIND_DOMAIN, NULL, NULL, 0)) < 0)
|
||||
return domain_handle;
|
||||
domain->m_entity.m_domain = domain;
|
||||
domain->m_entity.m_flags |= DDS_ENTITY_IMPLICIT;
|
||||
domain->m_entity.m_iid = ddsi_iid_gen ();
|
||||
|
||||
domain->gv.tstart = now ();
|
||||
domain->m_refc = 1;
|
||||
ddsrt_avl_init (&dds_topictree_def, &domain->m_topics);
|
||||
|
||||
/* | domain_id | domain id in config | result
|
||||
|
|
@ -72,8 +87,7 @@ static dds_return_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i
|
|||
a value (if nothing has been set previously, it a warning is good
|
||||
enough) */
|
||||
|
||||
(void) ddsrt_getenv ("CYCLONEDDS_URI", &uri);
|
||||
domain->cfgst = config_init (uri, &domain->gv.config, domain_id);
|
||||
domain->cfgst = config_init (config, &domain->gv.config, domain_id);
|
||||
if (domain->cfgst == NULL)
|
||||
{
|
||||
DDS_ILOG (DDS_LC_CONFIG, domain_id, "Failed to parse configuration XML file %s\n", uri);
|
||||
|
|
@ -152,9 +166,9 @@ static dds_return_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i
|
|||
|
||||
if (domain->gv.config.liveliness_monitoring)
|
||||
ddsi_threadmon_register_domain (dds_global.threadmon, &domain->gv);
|
||||
dds_entity_init_complete (&domain->m_entity);
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
rtps_stop (&domain->gv);
|
||||
fail_rtps_start:
|
||||
if (domain->gv.config.liveliness_monitoring && dds_global.threadmon_count == 1)
|
||||
ddsi_threadmon_stop (dds_global.threadmon);
|
||||
|
|
@ -170,43 +184,23 @@ fail_rtps_init:
|
|||
fail_rtps_config:
|
||||
config_fini (domain->cfgst);
|
||||
fail_config:
|
||||
dds_handle_delete (&domain->m_entity.m_hdllink);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dds_domain_fini (struct dds_domain *domain)
|
||||
{
|
||||
rtps_stop (&domain->gv);
|
||||
dds__builtin_fini (domain);
|
||||
|
||||
if (domain->gv.config.liveliness_monitoring)
|
||||
ddsi_threadmon_unregister_domain (dds_global.threadmon, &domain->gv);
|
||||
|
||||
rtps_fini (&domain->gv);
|
||||
|
||||
ddsrt_mutex_lock (&dds_global.m_mutex);
|
||||
if (domain->gv.config.liveliness_monitoring && --dds_global.threadmon_count == 0)
|
||||
{
|
||||
ddsi_threadmon_stop (dds_global.threadmon);
|
||||
ddsi_threadmon_free (dds_global.threadmon);
|
||||
}
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
|
||||
config_fini (domain->cfgst);
|
||||
}
|
||||
|
||||
dds_domain *dds_domain_find_locked (dds_domainid_t id)
|
||||
{
|
||||
return ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &id);
|
||||
}
|
||||
|
||||
dds_return_t dds_domain_create (dds_domain **domain_out, dds_domainid_t id)
|
||||
dds_return_t dds_domain_create_internal (dds_domain **domain_out, dds_domainid_t id, bool use_existing, const char *config)
|
||||
{
|
||||
struct dds_domain *dom = NULL;
|
||||
struct dds_domain *dom;
|
||||
dds_return_t ret;
|
||||
|
||||
/* FIXME: should perhaps lock parent object just like everywhere */
|
||||
ddsrt_mutex_lock (&dds_global.m_mutex);
|
||||
|
||||
/* FIXME: hack around default domain ids, not yet being able to handle multiple domains simultaneously */
|
||||
retry:
|
||||
if (id != DDS_DOMAIN_DEFAULT)
|
||||
{
|
||||
if ((dom = dds_domain_find_locked (id)) == NULL)
|
||||
|
|
@ -225,41 +219,94 @@ dds_return_t dds_domain_create (dds_domain **domain_out, dds_domainid_t id)
|
|||
switch (ret)
|
||||
{
|
||||
case DDS_RETCODE_OK:
|
||||
dom->m_refc++;
|
||||
*domain_out = dom;
|
||||
break;
|
||||
case DDS_RETCODE_NOT_FOUND:
|
||||
dom = dds_alloc (sizeof (*dom));
|
||||
if ((ret = dds_domain_init (dom, id)) < 0)
|
||||
dds_free (dom);
|
||||
if (!use_existing)
|
||||
{
|
||||
ret = DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
break;
|
||||
}
|
||||
ddsrt_mutex_lock (&dom->m_entity.m_mutex);
|
||||
if (dds_handle_is_closed (&dom->m_entity.m_hdllink))
|
||||
{
|
||||
ddsrt_mutex_unlock (&dom->m_entity.m_mutex);
|
||||
ddsrt_cond_wait (&dds_global.m_cond, &dds_global.m_mutex);
|
||||
goto retry;
|
||||
}
|
||||
else
|
||||
{
|
||||
ddsrt_avl_insert (&dds_domaintree_def, &dds_global.m_domains, dom);
|
||||
dds_entity_add_ref_locked (&dom->m_entity);
|
||||
ddsrt_mutex_unlock (&dom->m_entity.m_mutex);
|
||||
*domain_out = dom;
|
||||
}
|
||||
break;
|
||||
case DDS_RETCODE_PRECONDITION_NOT_MET:
|
||||
DDS_ILOG (DDS_LC_ERROR, id, "Inconsistent domain configuration detected: domain on configuration: %"PRIu32", domain %"PRIu32"\n", dom->m_id, id);
|
||||
case DDS_RETCODE_NOT_FOUND:
|
||||
dom = dds_alloc (sizeof (*dom));
|
||||
if ((ret = dds_domain_init (dom, id, config)) < 0)
|
||||
dds_free (dom);
|
||||
else
|
||||
{
|
||||
ddsrt_mutex_lock (&dom->m_entity.m_mutex);
|
||||
ddsrt_avl_insert (&dds_domaintree_def, &dds_global.m_domains, dom);
|
||||
dds_entity_register_child (&dds_global.m_entity, &dom->m_entity);
|
||||
dds_entity_add_ref_locked (&dom->m_entity);
|
||||
ddsrt_mutex_unlock (&dom->m_entity.m_mutex);
|
||||
*domain_out = dom;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dds_domain_free (dds_domain *domain)
|
||||
dds_return_t dds_create_domain(const dds_domainid_t domain, const char *config)
|
||||
{
|
||||
dds_domain *dom;
|
||||
dds_entity_t ret;
|
||||
|
||||
if (domain == DDS_DOMAIN_DEFAULT || config == NULL)
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
|
||||
/* Make sure DDS instance is initialized. */
|
||||
if ((ret = dds_init ()) < 0)
|
||||
goto err_dds_init;
|
||||
|
||||
if ((ret = dds_domain_create_internal (&dom, domain, false, config)) < 0)
|
||||
goto err_domain_create;
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
err_domain_create:
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
err_dds_init:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static dds_return_t dds_domain_free (dds_entity *vdomain)
|
||||
{
|
||||
struct dds_domain *domain = (struct dds_domain *) vdomain;
|
||||
rtps_stop (&domain->gv);
|
||||
dds__builtin_fini (domain);
|
||||
|
||||
if (domain->gv.config.liveliness_monitoring)
|
||||
ddsi_threadmon_unregister_domain (dds_global.threadmon, &domain->gv);
|
||||
|
||||
rtps_fini (&domain->gv);
|
||||
|
||||
/* tearing down the top-level object has more consequences, so it waits until signalled that all
|
||||
domains have been removed */
|
||||
ddsrt_mutex_lock (&dds_global.m_mutex);
|
||||
if (--domain->m_refc != 0)
|
||||
if (domain->gv.config.liveliness_monitoring && --dds_global.threadmon_count == 0)
|
||||
{
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
ddsrt_avl_delete (&dds_domaintree_def, &dds_global.m_domains, domain);
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
dds_domain_fini (domain);
|
||||
dds_free (domain);
|
||||
ddsi_threadmon_stop (dds_global.threadmon);
|
||||
ddsi_threadmon_free (dds_global.threadmon);
|
||||
}
|
||||
|
||||
ddsrt_avl_delete (&dds_domaintree_def, &dds_global.m_domains, domain);
|
||||
dds_entity_final_deinit_before_free (vdomain);
|
||||
config_fini (domain->cfgst);
|
||||
dds_free (vdomain);
|
||||
ddsrt_cond_broadcast (&dds_global.m_cond);
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
return DDS_RETCODE_NO_DATA;
|
||||
}
|
||||
|
||||
#include "dds__entity.h"
|
||||
|
|
@ -295,7 +342,8 @@ void dds_write_set_batch (bool enable)
|
|||
/* FIXME: get channels + latency budget working and get rid of this; in the mean time, any ugly hack will do. */
|
||||
struct dds_domain *dom;
|
||||
dds_domainid_t next_id = 0;
|
||||
dds_init ();
|
||||
if (dds_init () < 0)
|
||||
return;
|
||||
ddsrt_mutex_lock (&dds_global.m_mutex);
|
||||
while ((dom = ddsrt_avl_lookup_succ_eq (&dds_domaintree_def, &dds_global.m_domains, &next_id)) != NULL)
|
||||
{
|
||||
|
|
@ -306,7 +354,7 @@ void dds_write_set_batch (bool enable)
|
|||
|
||||
dds_instance_handle_t last_iid = 0;
|
||||
struct dds_entity *e;
|
||||
while (dom && (e = ddsrt_avl_lookup_succ (&dds_entity_children_td, &dom->m_ppants, &last_iid)) != NULL)
|
||||
while (dom && (e = ddsrt_avl_lookup_succ (&dds_entity_children_td, &dom->m_entity.m_children, &last_iid)) != NULL)
|
||||
{
|
||||
struct dds_entity *x;
|
||||
last_iid = e->m_iid;
|
||||
|
|
@ -321,5 +369,5 @@ void dds_write_set_batch (bool enable)
|
|||
}
|
||||
}
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
dds_fini ();
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,10 +40,15 @@ const struct dds_entity_deriver *dds_entity_deriver_table[] = {
|
|||
[DDS_KIND_COND_QUERY] = &dds_entity_deriver_readcondition,
|
||||
[DDS_KIND_COND_GUARD] = &dds_entity_deriver_guardcondition,
|
||||
[DDS_KIND_WAITSET] = &dds_entity_deriver_waitset,
|
||||
[DDS_KIND_DOMAIN] = &dds_entity_deriver_domain,
|
||||
[DDS_KIND_CYCLONEDDS] = &dds_entity_deriver_cyclonedds
|
||||
};
|
||||
|
||||
dds_return_t dds_entity_deriver_dummy_close (struct dds_entity *e) {
|
||||
(void) e; return DDS_RETCODE_OK;
|
||||
void dds_entity_deriver_dummy_interrupt (struct dds_entity *e) {
|
||||
(void) e;
|
||||
}
|
||||
void dds_entity_deriver_dummy_close (struct dds_entity *e) {
|
||||
(void) e;
|
||||
}
|
||||
dds_return_t dds_entity_deriver_dummy_delete (struct dds_entity *e) {
|
||||
(void) e; return DDS_RETCODE_OK;
|
||||
|
|
@ -55,7 +60,8 @@ dds_return_t dds_entity_deriver_dummy_validate_status (uint32_t mask) {
|
|||
(void) mask; return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
}
|
||||
|
||||
extern inline dds_return_t dds_entity_deriver_close (struct dds_entity *e);
|
||||
extern inline void dds_entity_deriver_interrupt (struct dds_entity *e);
|
||||
extern inline void dds_entity_deriver_close (struct dds_entity *e);
|
||||
extern inline dds_return_t dds_entity_deriver_delete (struct dds_entity *e);
|
||||
extern inline dds_return_t dds_entity_deriver_set_qos (struct dds_entity *e, const dds_qos_t *qos, bool enabled);
|
||||
extern inline dds_return_t dds_entity_deriver_validate_status (struct dds_entity *e, uint32_t mask);
|
||||
|
|
@ -73,23 +79,12 @@ const ddsrt_avl_treedef_t dds_entity_children_td = DDSRT_AVL_TREEDEF_INITIALIZER
|
|||
|
||||
static void dds_entity_observers_signal (dds_entity *observed, uint32_t status);
|
||||
static void dds_entity_observers_signal_delete (dds_entity *observed);
|
||||
static void dds_entity_observers_delete (dds_entity *observed);
|
||||
|
||||
void dds_entity_add_ref_locked (dds_entity *e)
|
||||
{
|
||||
dds_handle_add_ref (&e->m_hdllink);
|
||||
}
|
||||
|
||||
dds_domain *dds__entity_domain (dds_entity *e)
|
||||
{
|
||||
return e->m_domain;
|
||||
}
|
||||
|
||||
static dds_entity *dds__nonself_parent (dds_entity *e)
|
||||
{
|
||||
return e->m_parent == e ? NULL : e->m_parent;
|
||||
}
|
||||
|
||||
static bool entity_has_status (const dds_entity *e)
|
||||
{
|
||||
switch (e->m_kind)
|
||||
|
|
@ -105,6 +100,8 @@ static bool entity_has_status (const dds_entity *e)
|
|||
case DDS_KIND_COND_QUERY:
|
||||
case DDS_KIND_COND_GUARD:
|
||||
case DDS_KIND_WAITSET:
|
||||
case DDS_KIND_DOMAIN:
|
||||
case DDS_KIND_CYCLONEDDS:
|
||||
break;
|
||||
case DDS_KIND_DONTCARE:
|
||||
abort ();
|
||||
|
|
@ -117,12 +114,13 @@ dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind
|
|||
{
|
||||
dds_handle_t handle;
|
||||
|
||||
assert ((kind == DDS_KIND_PARTICIPANT) == (parent == NULL));
|
||||
assert ((kind == DDS_KIND_CYCLONEDDS) == (parent == NULL));
|
||||
assert (e);
|
||||
|
||||
e->m_kind = kind;
|
||||
e->m_qos = qos;
|
||||
e->m_cb_count = 0;
|
||||
e->m_cb_pending_count = 0;
|
||||
e->m_observers = NULL;
|
||||
|
||||
/* TODO: CHAM-96: Implement dynamic enabling of entity. */
|
||||
|
|
@ -143,14 +141,14 @@ dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind
|
|||
{
|
||||
e->m_parent = parent;
|
||||
e->m_domain = parent->m_domain;
|
||||
e->m_participant = parent->m_participant;
|
||||
ddsrt_avl_init (&dds_entity_children_td, &e->m_children);
|
||||
}
|
||||
else
|
||||
{
|
||||
e->m_participant = e;
|
||||
e->m_parent = e;
|
||||
assert (kind == DDS_KIND_CYCLONEDDS);
|
||||
e->m_parent = NULL;
|
||||
e->m_domain = NULL;
|
||||
}
|
||||
ddsrt_avl_init (&dds_entity_children_td, &e->m_children);
|
||||
|
||||
dds_reset_listener (&e->m_listener);
|
||||
if (listener)
|
||||
|
|
@ -162,13 +160,26 @@ dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind
|
|||
ddsrt_mutex_unlock (&parent->m_observers_lock);
|
||||
}
|
||||
|
||||
if ((handle = dds_handle_create (&e->m_hdllink)) <= 0)
|
||||
return (dds_entity_t) handle;
|
||||
if (kind == DDS_KIND_CYCLONEDDS)
|
||||
{
|
||||
if ((handle = dds_handle_register_special (&e->m_hdllink, DDS_CYCLONEDDS_HANDLE)) <= 0)
|
||||
return (dds_entity_t) handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((handle = dds_handle_create (&e->m_hdllink)) <= 0)
|
||||
return (dds_entity_t) handle;
|
||||
}
|
||||
|
||||
/* An dds_handle_t is directly used as dds_entity_t. */
|
||||
return (dds_entity_t) handle;
|
||||
}
|
||||
|
||||
void dds_entity_init_complete (dds_entity *entity)
|
||||
{
|
||||
dds_handle_unpend (&entity->m_hdllink);
|
||||
}
|
||||
|
||||
void dds_entity_register_child (dds_entity *parent, dds_entity *child)
|
||||
{
|
||||
assert (child->m_iid != 0);
|
||||
|
|
@ -176,11 +187,6 @@ void dds_entity_register_child (dds_entity *parent, dds_entity *child)
|
|||
ddsrt_avl_insert (&dds_entity_children_td, &parent->m_children, child);
|
||||
}
|
||||
|
||||
dds_return_t dds_delete (dds_entity_t entity)
|
||||
{
|
||||
return dds_delete_impl (entity, false);
|
||||
}
|
||||
|
||||
static dds_entity *next_non_topic_child (ddsrt_avl_tree_t *remaining_children)
|
||||
{
|
||||
ddsrt_avl_iter_t it;
|
||||
|
|
@ -192,45 +198,145 @@ static dds_entity *next_non_topic_child (ddsrt_avl_tree_t *remaining_children)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit)
|
||||
#define TRACE_DELETE 0 /* FIXME: use DDS_LOG for this */
|
||||
#if TRACE_DELETE
|
||||
static const char *entity_kindstr (dds_entity_kind_t kind)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case DDS_KIND_TOPIC: return "topic";
|
||||
case DDS_KIND_READER: return "reader";
|
||||
case DDS_KIND_WRITER: return "writer";
|
||||
case DDS_KIND_PUBLISHER: return "publisher";
|
||||
case DDS_KIND_SUBSCRIBER: return "subscriber";
|
||||
case DDS_KIND_PARTICIPANT: return "participant";
|
||||
case DDS_KIND_COND_READ: return "readcond";
|
||||
case DDS_KIND_COND_QUERY: return "querycond";
|
||||
case DDS_KIND_COND_GUARD: return "guardcond";
|
||||
case DDS_KIND_WAITSET: return "waitset";
|
||||
case DDS_KIND_DOMAIN: return "domain";
|
||||
case DDS_KIND_CYCLONEDDS: return "cyclonedds";
|
||||
case DDS_KIND_DONTCARE: break;
|
||||
}
|
||||
return "UNDEF";
|
||||
}
|
||||
|
||||
static void print_delete (const dds_entity *e, enum delete_impl_state delstate , dds_instance_handle_t iid)
|
||||
{
|
||||
unsigned cm = ddsrt_atomic_ld32 (&e->m_hdllink.cnt_flags);
|
||||
printf ("delete(%p, delstate %s, iid %"PRIx64"): %s%s %d pin %u refc %u %s %s\n",
|
||||
(void *) e, (delstate == DIS_IMPLICIT) ? "implicit" : (delstate == DIS_EXPLICIT) ? "explicit" : "from_parent", iid,
|
||||
entity_kindstr (e->m_kind), (e->m_flags & DDS_ENTITY_IMPLICIT) ? " [implicit]" : "",
|
||||
e->m_hdllink.hdl, cm & 0xfff, (cm >> 12) & 0xffff, (cm & 0x80000000) ? "closed" : "open",
|
||||
ddsrt_avl_is_empty (&e->m_children) ? "childless" : "has-children");
|
||||
}
|
||||
#endif
|
||||
|
||||
static dds_return_t dds_delete_impl (dds_entity_t entity, enum delete_impl_state delstate);
|
||||
|
||||
dds_return_t dds_delete (dds_entity_t entity)
|
||||
{
|
||||
return dds_delete_impl (entity, DIS_EXPLICIT);
|
||||
}
|
||||
|
||||
void dds_entity_final_deinit_before_free (dds_entity *e)
|
||||
{
|
||||
dds_delete_qos (e->m_qos);
|
||||
ddsrt_cond_destroy (&e->m_cond);
|
||||
ddsrt_cond_destroy (&e->m_observers_cond);
|
||||
ddsrt_mutex_destroy (&e->m_mutex);
|
||||
ddsrt_mutex_destroy (&e->m_observers_lock);
|
||||
}
|
||||
|
||||
static dds_return_t dds_delete_impl (dds_entity_t entity, enum delete_impl_state delstate)
|
||||
{
|
||||
dds_time_t timeout = DDS_SECS(10);
|
||||
dds_entity *e;
|
||||
dds_return_t ret;
|
||||
if ((ret = dds_entity_pin (entity, &e)) < 0)
|
||||
return ret;
|
||||
else
|
||||
return dds_delete_impl_pinned (e, delstate);
|
||||
}
|
||||
|
||||
dds_return_t dds_delete_impl_pinned (dds_entity *e, enum delete_impl_state delstate)
|
||||
{
|
||||
dds_entity *child;
|
||||
dds_return_t ret;
|
||||
dds_return_t rc;
|
||||
|
||||
if ((rc = dds_entity_pin (entity, &e)) < 0)
|
||||
return rc;
|
||||
/* Any number of threads pinning it, possibly in delete, or having pinned it and
|
||||
trying to acquire m_mutex */
|
||||
|
||||
ddsrt_mutex_lock (&e->m_mutex);
|
||||
if (keep_if_explicit == true && (e->m_flags & DDS_ENTITY_IMPLICIT) == 0)
|
||||
#if TRACE_DELETE
|
||||
print_delete (e, delstate, iid);
|
||||
#endif
|
||||
|
||||
/* If another thread was racing us in delete, it will have set the CLOSING flag
|
||||
while holding m_mutex and we had better bail out. */
|
||||
if (dds_handle_is_closed (&e->m_hdllink))
|
||||
{
|
||||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
dds_entity_unpin (e);
|
||||
dds_entity_unlock (e);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
/* Ignore children calling up to delete an implicit parent if there are still
|
||||
(or again) children */
|
||||
if (delstate == DIS_IMPLICIT)
|
||||
{
|
||||
if (!((e->m_flags & DDS_ENTITY_IMPLICIT) && ddsrt_avl_is_empty (&e->m_children)))
|
||||
{
|
||||
dds_entity_unlock (e);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Drop reference, atomically setting CLOSING if no other references remain.
|
||||
FIXME: that's not quite right: this is really only for topics. After a call
|
||||
to delete, the handle ought to become invalid even if the topic stays (and
|
||||
should perhaps even be revivable via find_topic). */
|
||||
if (! dds_handle_drop_ref (&e->m_hdllink))
|
||||
{
|
||||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
dds_entity_unpin (e);
|
||||
dds_entity_unlock (e);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
/* No threads pinning it anymore, no need to worry about other threads deleting
|
||||
it, but there can still be plenty of threads that have it pinned and are
|
||||
trying to acquire m_mutex to do their thing (including creating children,
|
||||
attaching to waitsets, &c.) */
|
||||
|
||||
assert (dds_handle_is_closed (&e->m_hdllink));
|
||||
|
||||
/* Trigger blocked threads (and, still, delete DDSI reader/writer to trigger
|
||||
continued cleanup -- while that's quite safe given that GUIDs don't get
|
||||
reused quickly, it needs an update) */
|
||||
dds_entity_deriver_interrupt (e);
|
||||
|
||||
/* Prevent further listener invocations; dds_set_status_mask locks m_mutex and
|
||||
checks for a pending delete to guarantee that once we clear the mask here,
|
||||
no new listener invocations will occur beyond those already in progress.
|
||||
(FIXME: or committed to? I think in-progress only, better check.) */
|
||||
ddsrt_mutex_lock (&e->m_observers_lock);
|
||||
if (entity_has_status (e))
|
||||
ddsrt_atomic_and32 (&e->m_status.m_status_and_mask, SAM_STATUS_MASK);
|
||||
dds_reset_listener (&e->m_listener);
|
||||
|
||||
/* Signal observers that this entity will be deleted and wait for
|
||||
all listeners to complete. */
|
||||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
dds_entity_observers_signal_delete (e);
|
||||
while (e->m_cb_count > 0)
|
||||
|
||||
/* wait for all listeners to complete - FIXME: rely on pincount instead?
|
||||
that would require all listeners to pin the entity instead, but it
|
||||
would prevent them from doing much. */
|
||||
while (e->m_cb_pending_count > 0)
|
||||
ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock);
|
||||
ddsrt_mutex_unlock (&e->m_observers_lock);
|
||||
|
||||
/* Wait for all other threads to unpin the entity */
|
||||
dds_handle_close_wait (&e->m_hdllink);
|
||||
|
||||
/* Pin count dropped to one with CLOSING flag set: no other threads still
|
||||
in operations involving this entity */
|
||||
dds_entity_observers_signal_delete (e);
|
||||
dds_entity_deriver_close (e);
|
||||
|
||||
/*
|
||||
* Recursively delete children.
|
||||
*
|
||||
|
|
@ -248,106 +354,123 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit)
|
|||
*
|
||||
* To circumvent the problem. We ignore topics in the first loop.
|
||||
*/
|
||||
ret = DDS_RETCODE_OK;
|
||||
ddsrt_mutex_lock (&e->m_mutex);
|
||||
while ((child = next_non_topic_child (&e->m_children)) && ret == DDS_RETCODE_OK)
|
||||
while ((child = next_non_topic_child (&e->m_children)) != NULL)
|
||||
{
|
||||
/* FIXME: dds_delete can fail if the child is being deleted in parallel, in which case: wait */
|
||||
dds_entity_t child_handle = child->m_hdllink.hdl;
|
||||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
ret = dds_delete (child_handle);
|
||||
(void) dds_delete_impl (child_handle, DIS_FROM_PARENT);
|
||||
ddsrt_mutex_lock (&e->m_mutex);
|
||||
}
|
||||
while ((child = ddsrt_avl_find_min (&dds_entity_children_td, &e->m_children)) != NULL && ret == DDS_RETCODE_OK)
|
||||
while ((child = ddsrt_avl_find_min (&dds_entity_children_td, &e->m_children)) != NULL)
|
||||
{
|
||||
assert (dds_entity_kind (child) == DDS_KIND_TOPIC);
|
||||
dds_entity_t child_handle = child->m_hdllink.hdl;
|
||||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
ret = dds_delete (child_handle);
|
||||
(void) dds_delete_impl (child_handle, DIS_FROM_PARENT);
|
||||
ddsrt_mutex_lock (&e->m_mutex);
|
||||
}
|
||||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
if (ret == DDS_RETCODE_OK)
|
||||
ret = dds_entity_deriver_close (e);
|
||||
|
||||
dds_entity_unpin (e);
|
||||
if (ret == DDS_RETCODE_OK)
|
||||
/* The dds_handle_delete will wait until the last active claim on that handle is
|
||||
released. It is possible that this last release will be done by a thread that was
|
||||
kicked during the close(). */
|
||||
ret = dds_handle_delete (&e->m_hdllink);
|
||||
assert (ret == DDS_RETCODE_OK);
|
||||
(void) ret;
|
||||
|
||||
/* Remove from parent; schedule deletion of parent if it was created implicitly, no
|
||||
longer has any remaining children, and we didn't arrive here as a consequence of
|
||||
deleting the parent. */
|
||||
dds_entity *parent_to_delete = NULL;
|
||||
if (e->m_parent != NULL)
|
||||
{
|
||||
/* The dds_handle_delete will wait until the last active claim on that handle
|
||||
* is released. It is possible that this last release will be done by a thread
|
||||
* that was kicked during the close(). */
|
||||
if ((ret = dds_handle_delete (&e->m_hdllink, timeout)) != DDS_RETCODE_OK)
|
||||
return ret;
|
||||
}
|
||||
struct dds_entity * const p = e->m_parent;
|
||||
|
||||
if (ret == DDS_RETCODE_OK)
|
||||
{
|
||||
/* Remove all possible observers. */
|
||||
dds_entity_observers_delete (e);
|
||||
ddsrt_mutex_lock (&p->m_mutex);
|
||||
assert (ddsrt_avl_lookup (&dds_entity_children_td, &p->m_children, &e->m_iid) != NULL);
|
||||
ddsrt_avl_delete (&dds_entity_children_td, &p->m_children, e);
|
||||
/* trigger parent in case it is waiting in delete */
|
||||
ddsrt_cond_broadcast (&p->m_cond);
|
||||
|
||||
/* Remove from parent */
|
||||
dds_entity *parent;
|
||||
if ((parent = dds__nonself_parent(e)) != NULL)
|
||||
if (delstate != DIS_FROM_PARENT && (p->m_flags & DDS_ENTITY_IMPLICIT) && ddsrt_avl_is_empty (&p->m_children))
|
||||
{
|
||||
ddsrt_mutex_lock (&parent->m_mutex);
|
||||
assert (ddsrt_avl_lookup (&dds_entity_children_td, &parent->m_children, &e->m_iid) != NULL);
|
||||
ddsrt_avl_delete (&dds_entity_children_td, &parent->m_children, e);
|
||||
ddsrt_mutex_unlock (&parent->m_mutex);
|
||||
if ((ret = dds_entity_pin (p->m_hdllink.hdl, &parent_to_delete)) < 0)
|
||||
parent_to_delete = NULL;
|
||||
}
|
||||
|
||||
/* Do some specific deletion when needed. */
|
||||
ret = dds_entity_deriver_delete (e);
|
||||
ddsrt_mutex_unlock (&p->m_mutex);
|
||||
}
|
||||
|
||||
if (ret == DDS_RETCODE_OK)
|
||||
/* Do some specific deletion when needed */
|
||||
ret = dds_entity_deriver_delete (e);
|
||||
if (ret == DDS_RETCODE_NO_DATA)
|
||||
{
|
||||
dds_delete_qos (e->m_qos);
|
||||
ddsrt_cond_destroy (&e->m_cond);
|
||||
ddsrt_cond_destroy (&e->m_observers_cond);
|
||||
ddsrt_mutex_destroy (&e->m_mutex);
|
||||
ddsrt_mutex_destroy (&e->m_observers_lock);
|
||||
/* Bootstrapping and its inverse are always a tricky business, and here it is no different:
|
||||
deleting the pseudo-top-level object tears down all kinds of stuff that is supposed to
|
||||
remain in existence (like the entire platform abstraction) and so it must be the final
|
||||
call. Thus, we rely on it to call "dds_entity_final_deinit_before_free" and return a
|
||||
special error code that we don't pass on to the caller. */
|
||||
ret = DDS_RETCODE_OK;
|
||||
}
|
||||
else if (ret != DDS_RETCODE_OK)
|
||||
{
|
||||
if (parent_to_delete)
|
||||
dds_entity_unpin (parent_to_delete);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
dds_entity_final_deinit_before_free (e);
|
||||
dds_free (e);
|
||||
}
|
||||
|
||||
return ret;
|
||||
assert (ret == DDS_RETCODE_OK);
|
||||
(void) ret;
|
||||
return (parent_to_delete != NULL) ? dds_delete_impl_pinned (parent_to_delete, DIS_IMPLICIT) : DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
bool dds_entity_in_scope (const dds_entity *e, const dds_entity *root)
|
||||
{
|
||||
/* An entity is not an ancestor of itself */
|
||||
while (e != NULL && e != root)
|
||||
e = e->m_parent;
|
||||
return (e != NULL);
|
||||
}
|
||||
|
||||
dds_entity_t dds_get_parent (dds_entity_t entity)
|
||||
{
|
||||
dds_entity *e;
|
||||
dds_return_t rc;
|
||||
if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK)
|
||||
if ((rc = dds_entity_pin (entity, &e)) != DDS_RETCODE_OK)
|
||||
return rc;
|
||||
else
|
||||
{
|
||||
dds_entity *parent;
|
||||
dds_entity_t hdl;
|
||||
if ((parent = dds__nonself_parent(e)) == NULL)
|
||||
hdl = DDS_ENTITY_NIL;
|
||||
else
|
||||
{
|
||||
dds_entity *x;
|
||||
hdl = parent->m_hdllink.hdl;
|
||||
if (dds_entity_lock (hdl, DDS_KIND_DONTCARE, &x) == DDS_RETCODE_OK)
|
||||
{
|
||||
parent->m_flags &= ~DDS_ENTITY_IMPLICIT;
|
||||
dds_entity_unlock (parent);
|
||||
}
|
||||
}
|
||||
dds_entity_unlock (e);
|
||||
dds_entity_t hdl = e->m_parent ? e->m_parent->m_hdllink.hdl : 0;
|
||||
dds_entity_unpin (e);
|
||||
return hdl;
|
||||
}
|
||||
}
|
||||
|
||||
dds_participant *dds_entity_participant (dds_entity *e)
|
||||
{
|
||||
while (e && dds_entity_kind (e) != DDS_KIND_PARTICIPANT)
|
||||
e = e->m_parent;
|
||||
return (dds_participant *) e;
|
||||
}
|
||||
|
||||
dds_entity_t dds_get_participant (dds_entity_t entity)
|
||||
{
|
||||
dds_entity *e;
|
||||
dds_return_t rc;
|
||||
if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK)
|
||||
if ((rc = dds_entity_pin (entity, &e)) != DDS_RETCODE_OK)
|
||||
return rc;
|
||||
else
|
||||
{
|
||||
dds_entity_t hdl = e->m_participant->m_hdllink.hdl;
|
||||
dds_entity_unlock (e);
|
||||
dds_participant *par = dds_entity_participant (e);
|
||||
dds_entity_t hdl = par ? par->m_entity.m_hdllink.hdl : 0;
|
||||
dds_entity_unpin (e);
|
||||
return hdl;
|
||||
}
|
||||
}
|
||||
|
|
@ -357,42 +480,28 @@ dds_return_t dds_get_children (dds_entity_t entity, dds_entity_t *children, size
|
|||
dds_entity *e;
|
||||
dds_return_t rc;
|
||||
|
||||
if (children != NULL && (size <= 0 || size >= INT32_MAX))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
if (children == NULL && size != 0)
|
||||
if ((children != NULL && (size == 0 || size > INT32_MAX)) || (children == NULL && size != 0))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
|
||||
if ((rc = dds_entity_pin (entity, &e)) != DDS_RETCODE_OK)
|
||||
return rc;
|
||||
else
|
||||
{
|
||||
/* FIXME: fix the implicit/explicit stuff so the set_explicit isn't needed; and then this can also be done with a regular iterator & without unlocking */
|
||||
ddsrt_avl_iter_t it;
|
||||
size_t n = 0;
|
||||
dds_instance_handle_t last_iid = 0;
|
||||
struct dds_entity *c;
|
||||
ddsrt_mutex_lock (&e->m_mutex);
|
||||
while ((c = ddsrt_avl_lookup_succ (&dds_entity_children_td, &e->m_children, &last_iid)) != NULL)
|
||||
for (c = ddsrt_avl_iter_first (&dds_entity_children_td, &e->m_children, &it); c != NULL; c = ddsrt_avl_iter_next (&it))
|
||||
{
|
||||
last_iid = c->m_iid;
|
||||
if (n < size)
|
||||
struct dds_entity *tmp;
|
||||
/* Attempt at pinning the entity will fail if it is still pending */
|
||||
if (dds_entity_pin (c->m_hdllink.hdl, &tmp) == DDS_RETCODE_OK)
|
||||
{
|
||||
dds_entity *x;
|
||||
/* Claim child handle to guarantee the child entity remains valid; as we unlock "e" only when we manage to claim the child, and the child has to remain in existence until we release it, "c" remains a valid pointer despite the unlocking. */
|
||||
if (dds_entity_pin (c->m_hdllink.hdl, &x) == DDS_RETCODE_OK)
|
||||
{
|
||||
assert (x == c);
|
||||
if (n < size)
|
||||
children[n] = c->m_hdllink.hdl;
|
||||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
|
||||
ddsrt_mutex_lock (&c->m_mutex);
|
||||
c->m_flags &= ~DDS_ENTITY_IMPLICIT;
|
||||
ddsrt_mutex_unlock (&c->m_mutex);
|
||||
|
||||
ddsrt_mutex_lock (&e->m_mutex);
|
||||
dds_entity_unpin (c);
|
||||
}
|
||||
n++;
|
||||
dds_entity_unpin (tmp);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
dds_entity_unpin (e);
|
||||
|
|
@ -423,6 +532,8 @@ static uint64_t entity_kind_qos_mask (dds_entity_kind_t kind)
|
|||
case DDS_KIND_COND_QUERY:
|
||||
case DDS_KIND_COND_GUARD:
|
||||
case DDS_KIND_WAITSET:
|
||||
case DDS_KIND_DOMAIN:
|
||||
case DDS_KIND_CYCLONEDDS:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -603,7 +714,8 @@ dds_return_t dds_set_qos (dds_entity_t entity, const dds_qos_t *qos)
|
|||
{
|
||||
case DDS_KIND_TOPIC: {
|
||||
dds_entity *pp;
|
||||
if (dds_entity_pin (e->m_participant->m_hdllink.hdl, &pp) == DDS_RETCODE_OK)
|
||||
assert (dds_entity_kind (e->m_parent) == DDS_KIND_PARTICIPANT);
|
||||
if (dds_entity_pin (e->m_parent->m_hdllink.hdl, &pp) == DDS_RETCODE_OK)
|
||||
{
|
||||
pushdown_topic_qos (pp, e);
|
||||
dds_entity_unpin (pp);
|
||||
|
|
@ -763,7 +875,7 @@ static void pushdown_listener (dds_entity *e)
|
|||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
|
||||
ddsrt_mutex_lock (&c->m_observers_lock);
|
||||
while (c->m_cb_count > 0)
|
||||
while (c->m_cb_pending_count > 0)
|
||||
ddsrt_cond_wait (&c->m_observers_cond, &c->m_observers_lock);
|
||||
|
||||
ddsrt_mutex_lock (&e->m_observers_lock);
|
||||
|
|
@ -791,7 +903,7 @@ dds_return_t dds_set_listener (dds_entity_t entity, const dds_listener_t *listen
|
|||
return rc;
|
||||
|
||||
ddsrt_mutex_lock (&e->m_observers_lock);
|
||||
while (e->m_cb_count > 0)
|
||||
while (e->m_cb_pending_count > 0)
|
||||
ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock);
|
||||
|
||||
/* new listener is constructed by combining "listener" with the ancestral listeners;
|
||||
|
|
@ -801,7 +913,7 @@ dds_return_t dds_set_listener (dds_entity_t entity, const dds_listener_t *listen
|
|||
if (listener)
|
||||
dds_merge_listener (&e->m_listener, listener);
|
||||
x = e;
|
||||
while (dds_entity_kind (x) != DDS_KIND_PARTICIPANT)
|
||||
while (dds_entity_kind (x) != DDS_KIND_CYCLONEDDS)
|
||||
{
|
||||
x = x->m_parent;
|
||||
ddsrt_mutex_lock (&x->m_observers_lock);
|
||||
|
|
@ -892,17 +1004,26 @@ dds_return_t dds_set_status_mask (dds_entity_t entity, uint32_t mask)
|
|||
if ((mask & ~SAM_STATUS_MASK) != 0)
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
|
||||
if ((ret = dds_entity_pin (entity, &e)) != DDS_RETCODE_OK)
|
||||
if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK)
|
||||
return ret;
|
||||
|
||||
if (dds_handle_is_closed (&e->m_hdllink))
|
||||
{
|
||||
/* The sole reason for locking the mutex was so we can do this atomically with
|
||||
respect to dds_delete (which in turn requires checking whether the handle
|
||||
is still open), because delete relies on the mask to shut down all listener
|
||||
invocations. */
|
||||
dds_entity_unlock (e);
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
}
|
||||
|
||||
if ((ret = dds_entity_deriver_validate_status (e, mask)) == DDS_RETCODE_OK)
|
||||
{
|
||||
assert (entity_has_status (e));
|
||||
ddsrt_mutex_lock (&e->m_observers_lock);
|
||||
while (e->m_cb_count > 0)
|
||||
while (e->m_cb_pending_count > 0)
|
||||
ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock);
|
||||
|
||||
/* Don't block internal status triggers. */
|
||||
uint32_t old, new;
|
||||
do {
|
||||
old = ddsrt_atomic_ld32 (&e->m_status.m_status_and_mask);
|
||||
|
|
@ -910,7 +1031,7 @@ dds_return_t dds_set_status_mask (dds_entity_t entity, uint32_t mask)
|
|||
} while (!ddsrt_atomic_cas32 (&e->m_status.m_status_and_mask, old, new));
|
||||
ddsrt_mutex_unlock (&e->m_observers_lock);
|
||||
}
|
||||
dds_entity_unpin (e);
|
||||
dds_entity_unlock (e);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -946,7 +1067,6 @@ static dds_return_t dds_readtake_status (dds_entity_t entity, uint32_t *status,
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
dds_return_t dds_read_status (dds_entity_t entity, uint32_t *status, uint32_t mask)
|
||||
{
|
||||
return dds_readtake_status (entity, status, mask, false);
|
||||
|
|
@ -965,11 +1085,11 @@ dds_return_t dds_get_domainid (dds_entity_t entity, dds_domainid_t *id)
|
|||
if (id == NULL)
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
|
||||
if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK)
|
||||
if ((rc = dds_entity_pin (entity, &e)) != DDS_RETCODE_OK)
|
||||
return rc;
|
||||
|
||||
*id = e->m_domain->m_id;
|
||||
dds_entity_unlock(e);
|
||||
*id = e->m_domain ? e->m_domain->m_id : DDS_DOMAIN_DEFAULT;
|
||||
dds_entity_unpin (e);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1029,7 +1149,7 @@ dds_return_t dds_entity_lock (dds_entity_t hdl, dds_entity_kind_t kind, dds_enti
|
|||
void dds_entity_unlock (dds_entity *e)
|
||||
{
|
||||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
dds_handle_unpin (&e->m_hdllink);
|
||||
dds_entity_unpin (e);
|
||||
}
|
||||
|
||||
dds_return_t dds_triggered (dds_entity_t entity)
|
||||
|
|
@ -1047,7 +1167,7 @@ dds_return_t dds_triggered (dds_entity_t entity)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool in_observer_list_p (const struct dds_entity *observed, const dds_entity *observer)
|
||||
static bool in_observer_list_p (const struct dds_entity *observed, const dds_waitset *observer)
|
||||
{
|
||||
dds_entity_observer *cur;
|
||||
for (cur = observed->m_observers; cur != NULL; cur = cur->m_next)
|
||||
|
|
@ -1056,13 +1176,15 @@ static bool in_observer_list_p (const struct dds_entity *observed, const dds_ent
|
|||
return false;
|
||||
}
|
||||
|
||||
dds_return_t dds_entity_observer_register (dds_entity *observed, dds_entity *observer, dds_entity_callback cb, dds_entity_delete_callback delete_cb)
|
||||
dds_return_t dds_entity_observer_register (dds_entity *observed, dds_waitset *observer, dds_entity_callback_t cb, dds_entity_attach_callback_t attach_cb, void *attach_arg, dds_entity_delete_callback_t delete_cb)
|
||||
{
|
||||
dds_return_t rc;
|
||||
assert (observed);
|
||||
ddsrt_mutex_lock (&observed->m_observers_lock);
|
||||
if (in_observer_list_p (observed, observer))
|
||||
rc = DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
else if (!attach_cb (observer, observed, attach_arg))
|
||||
rc = DDS_RETCODE_BAD_PARAMETER;
|
||||
else
|
||||
{
|
||||
dds_entity_observer *o = ddsrt_malloc (sizeof (dds_entity_observer));
|
||||
|
|
@ -1077,7 +1199,7 @@ dds_return_t dds_entity_observer_register (dds_entity *observed, dds_entity *obs
|
|||
return rc;
|
||||
}
|
||||
|
||||
dds_return_t dds_entity_observer_unregister (dds_entity *observed, dds_entity *observer)
|
||||
dds_return_t dds_entity_observer_unregister (dds_entity *observed, dds_waitset *observer, bool invoke_delete_cb)
|
||||
{
|
||||
dds_return_t rc;
|
||||
dds_entity_observer *prev, *idx;
|
||||
|
|
@ -1098,6 +1220,8 @@ dds_return_t dds_entity_observer_unregister (dds_entity *observed, dds_entity *o
|
|||
observed->m_observers = idx->m_next;
|
||||
else
|
||||
prev->m_next = idx->m_next;
|
||||
if (invoke_delete_cb)
|
||||
idx->m_delete_cb (idx->m_observer, observed->m_hdllink.hdl);
|
||||
ddsrt_free (idx);
|
||||
rc = DDS_RETCODE_OK;
|
||||
}
|
||||
|
|
@ -1105,21 +1229,6 @@ dds_return_t dds_entity_observer_unregister (dds_entity *observed, dds_entity *o
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void dds_entity_observers_delete (dds_entity *observed)
|
||||
{
|
||||
dds_entity_observer *idx;
|
||||
ddsrt_mutex_lock (&observed->m_observers_lock);
|
||||
idx = observed->m_observers;
|
||||
while (idx != NULL)
|
||||
{
|
||||
dds_entity_observer *next = idx->m_next;
|
||||
ddsrt_free (idx);
|
||||
idx = next;
|
||||
}
|
||||
observed->m_observers = NULL;
|
||||
ddsrt_mutex_unlock (&observed->m_observers_lock);
|
||||
}
|
||||
|
||||
static void dds_entity_observers_signal (dds_entity *observed, uint32_t status)
|
||||
{
|
||||
for (dds_entity_observer *idx = observed->m_observers; idx; idx = idx->m_next)
|
||||
|
|
@ -1128,8 +1237,16 @@ static void dds_entity_observers_signal (dds_entity *observed, uint32_t status)
|
|||
|
||||
static void dds_entity_observers_signal_delete (dds_entity *observed)
|
||||
{
|
||||
for (dds_entity_observer *idx = observed->m_observers; idx; idx = idx->m_next)
|
||||
dds_entity_observer *idx;
|
||||
idx = observed->m_observers;
|
||||
while (idx != NULL)
|
||||
{
|
||||
dds_entity_observer *next = idx->m_next;
|
||||
idx->m_delete_cb (idx->m_observer, observed->m_hdllink.hdl);
|
||||
ddsrt_free (idx);
|
||||
idx = next;
|
||||
}
|
||||
observed->m_observers = NULL;
|
||||
}
|
||||
|
||||
void dds_entity_status_signal (dds_entity *e, uint32_t status)
|
||||
|
|
@ -1158,11 +1275,13 @@ void dds_entity_trigger_set (dds_entity *e, uint32_t t)
|
|||
{
|
||||
assert (! entity_has_status (e));
|
||||
uint32_t oldst;
|
||||
ddsrt_mutex_lock (&e->m_observers_lock);
|
||||
do {
|
||||
oldst = ddsrt_atomic_ld32 (&e->m_status.m_trigger);
|
||||
} while (!ddsrt_atomic_cas32 (&e->m_status.m_trigger, oldst, t));
|
||||
if (oldst == 0 && t != 0)
|
||||
dds_entity_observers_signal (e, t);
|
||||
ddsrt_mutex_unlock (&e->m_observers_lock);
|
||||
}
|
||||
|
||||
dds_entity_t dds_get_topic (dds_entity_t entity)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "dds__init.h"
|
||||
#include "dds__reader.h"
|
||||
#include "dds__guardcond.h"
|
||||
#include "dds__participant.h"
|
||||
|
|
@ -22,28 +23,53 @@
|
|||
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_guardcond)
|
||||
|
||||
const struct dds_entity_deriver dds_entity_deriver_guardcondition = {
|
||||
.interrupt = dds_entity_deriver_dummy_interrupt,
|
||||
.close = dds_entity_deriver_dummy_close,
|
||||
.delete = dds_entity_deriver_dummy_delete,
|
||||
.set_qos = dds_entity_deriver_dummy_set_qos,
|
||||
.validate_status = dds_entity_deriver_dummy_validate_status
|
||||
};
|
||||
|
||||
dds_entity_t dds_create_guardcondition (dds_entity_t participant)
|
||||
dds_entity_t dds_create_guardcondition (dds_entity_t owner)
|
||||
{
|
||||
dds_participant *pp;
|
||||
dds_entity *e;
|
||||
dds_return_t rc;
|
||||
|
||||
if ((rc = dds_participant_lock (participant, &pp)) != DDS_RETCODE_OK)
|
||||
/* If the owner is any ordinary (allowed) entity, the library is already initialised and calling
|
||||
init here is cheap. If it is DDS_CYCLONEDDS_HANDLE, we may have to initialise the library, so
|
||||
have to call it. If it is some bogus value and the library is not initialised yet ... so be
|
||||
it. Naturally, this requires us to call delete on DDS_CYCLONEDDS_HANDLE afterward. */
|
||||
if ((rc = dds_init ()) < 0)
|
||||
return rc;
|
||||
else
|
||||
|
||||
if ((rc = dds_entity_lock (owner, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK)
|
||||
goto err_entity_lock;
|
||||
|
||||
switch (dds_entity_kind (e))
|
||||
{
|
||||
dds_guardcond *gcond = dds_alloc (sizeof (*gcond));
|
||||
dds_entity_t hdl = dds_entity_init (&gcond->m_entity, &pp->m_entity, DDS_KIND_COND_GUARD, NULL, NULL, 0);
|
||||
gcond->m_entity.m_iid = ddsi_iid_gen ();
|
||||
dds_entity_register_child (&pp->m_entity, &gcond->m_entity);
|
||||
dds_participant_unlock (pp);
|
||||
return hdl;
|
||||
case DDS_KIND_CYCLONEDDS:
|
||||
case DDS_KIND_DOMAIN:
|
||||
case DDS_KIND_PARTICIPANT:
|
||||
break;
|
||||
default:
|
||||
rc = DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
goto err_entity_kind;
|
||||
}
|
||||
|
||||
dds_guardcond *gcond = dds_alloc (sizeof (*gcond));
|
||||
dds_entity_t hdl = dds_entity_init (&gcond->m_entity, e, DDS_KIND_COND_GUARD, NULL, NULL, 0);
|
||||
gcond->m_entity.m_iid = ddsi_iid_gen ();
|
||||
dds_entity_register_child (e, &gcond->m_entity);
|
||||
dds_entity_init_complete (&gcond->m_entity);
|
||||
dds_entity_unlock (e);
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
return hdl;
|
||||
|
||||
err_entity_kind:
|
||||
dds_entity_unlock (e);
|
||||
err_entity_lock:
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
return rc;
|
||||
}
|
||||
|
||||
dds_return_t dds_set_guardcondition (dds_entity_t condition, bool triggered)
|
||||
|
|
|
|||
|
|
@ -20,27 +20,10 @@
|
|||
#include "dds__handles.h"
|
||||
#include "dds__types.h"
|
||||
|
||||
/* FIXME: this code isn't really correct when USE_CHH is set:
|
||||
- the DDS entity code doesn't really play by the awake/asleep mechanism
|
||||
- there is no provision in the code for a handle being deleted concurrent to a lookup,
|
||||
that is, deleting handle links should also go through the GC
|
||||
entity framework needs a fair bit of rewriting anyway ... */
|
||||
#define USE_CHH 0
|
||||
|
||||
#define HDL_FLAG_CLOSED (0x80000000u)
|
||||
|
||||
/* ref count: # outstanding references to this handle/object (not so sure it is
|
||||
ideal to have a one-to-one mapping between the two, but that is what the rest
|
||||
of the code assumes at the moment); so this limits one to having, e.g., no
|
||||
more than 64k endpoints referencing the same topic */
|
||||
#define HDL_REFCOUNT_MASK (0x0ffff000u)
|
||||
#define HDL_REFCOUNT_UNIT (0x00001000u)
|
||||
#define HDL_REFCOUNT_SHIFT 12
|
||||
|
||||
/* pin count: # concurrent operations, so allowing up to 4096 threads had better
|
||||
be enough ... */
|
||||
#define HDL_PINCOUNT_MASK (0x00000fffu)
|
||||
#define HDL_PINCOUNT_UNIT (0x00000001u)
|
||||
|
||||
/* Maximum number of handles is INT32_MAX - 1, but as the allocator relies on a
|
||||
random generator for finding a free one, the time spent in the dds_handle_create
|
||||
|
|
@ -50,11 +33,7 @@
|
|||
#define MAX_HANDLES (INT32_MAX / 128)
|
||||
|
||||
struct dds_handle_server {
|
||||
#if USE_CHH
|
||||
struct ddsrt_chh *ht;
|
||||
#else
|
||||
struct ddsrt_hh *ht;
|
||||
#endif
|
||||
size_t count;
|
||||
ddsrt_mutex_t lock;
|
||||
ddsrt_cond_t cond;
|
||||
|
|
@ -78,45 +57,46 @@ static int handle_equal (const void *va, const void *vb)
|
|||
|
||||
dds_return_t dds_handle_server_init (void)
|
||||
{
|
||||
#if USE_CHH
|
||||
handles.ht = ddsrt_chh_new (128, handle_hash, handle_equal, free_via_gc);
|
||||
#else
|
||||
handles.ht = ddsrt_hh_new (128, handle_hash, handle_equal);
|
||||
#endif
|
||||
handles.count = 0;
|
||||
ddsrt_mutex_init (&handles.lock);
|
||||
ddsrt_cond_init (&handles.cond);
|
||||
/* called with ddsrt's singleton mutex held (see dds_init/fini) */
|
||||
if (handles.ht == NULL)
|
||||
{
|
||||
handles.ht = ddsrt_hh_new (128, handle_hash, handle_equal);
|
||||
handles.count = 0;
|
||||
ddsrt_mutex_init (&handles.lock);
|
||||
ddsrt_cond_init (&handles.cond);
|
||||
}
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
void dds_handle_server_fini (void)
|
||||
{
|
||||
#if USE_CHH
|
||||
/* called with ddsrt's singleton mutex held (see dds_init/fini) */
|
||||
if (handles.ht != NULL)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
struct ddsrt_chh_iter it;
|
||||
assert (ddsrt_chh_iter_first (handles.ht, &it) == NULL);
|
||||
struct ddsrt_hh_iter it;
|
||||
for (struct dds_handle_link *link = ddsrt_hh_iter_first (handles.ht, &it); link != NULL; link = ddsrt_hh_iter_next (&it))
|
||||
{
|
||||
uint32_t cf = ddsrt_atomic_ld32 (&link->cnt_flags);
|
||||
DDS_ERROR ("handle %"PRId32" pin %"PRIu32" refc %"PRIu32"%s%s%s\n", link->hdl,
|
||||
cf & HDL_PINCOUNT_MASK, (cf & HDL_REFCOUNT_MASK) >> HDL_REFCOUNT_SHIFT,
|
||||
cf & HDL_FLAG_PENDING ? " pending" : "",
|
||||
cf & HDL_FLAG_CLOSING ? " closing" : "",
|
||||
cf & HDL_FLAG_CLOSED ? " closed" : "");
|
||||
}
|
||||
assert (ddsrt_hh_iter_first (handles.ht, &it) == NULL);
|
||||
#endif
|
||||
ddsrt_chh_free (handles.ht);
|
||||
#else /* USE_CHH */
|
||||
#ifndef NDEBUG
|
||||
struct ddsrt_hh_iter it;
|
||||
assert (ddsrt_hh_iter_first (handles.ht, &it) == NULL);
|
||||
#endif
|
||||
ddsrt_hh_free (handles.ht);
|
||||
#endif /* USE_CHH */
|
||||
ddsrt_cond_destroy (&handles.cond);
|
||||
ddsrt_mutex_destroy (&handles.lock);
|
||||
handles.ht = NULL;
|
||||
ddsrt_hh_free (handles.ht);
|
||||
ddsrt_cond_destroy (&handles.cond);
|
||||
ddsrt_mutex_destroy (&handles.lock);
|
||||
handles.ht = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_CHH
|
||||
static bool hhadd (struct ddsrt_chh *ht, void *elem) { return ddsrt_chh_add (ht, elem); }
|
||||
#else
|
||||
static bool hhadd (struct ddsrt_hh *ht, void *elem) { return ddsrt_hh_add (ht, elem); }
|
||||
#endif
|
||||
static dds_handle_t dds_handle_create_int (struct dds_handle_link *link)
|
||||
{
|
||||
ddsrt_atomic_st32 (&link->cnt_flags, HDL_REFCOUNT_UNIT);
|
||||
ddsrt_atomic_st32 (&link->cnt_flags, HDL_FLAG_PENDING | HDL_REFCOUNT_UNIT | 1u);
|
||||
do {
|
||||
do {
|
||||
link->hdl = (int32_t) (ddsrt_random () & INT32_MAX);
|
||||
|
|
@ -127,13 +107,7 @@ static dds_handle_t dds_handle_create_int (struct dds_handle_link *link)
|
|||
|
||||
dds_handle_t dds_handle_create (struct dds_handle_link *link)
|
||||
{
|
||||
#if USE_CHH
|
||||
struct thread_state1 * const ts1 = lookup_thread_state ();
|
||||
#endif
|
||||
dds_handle_t ret;
|
||||
#if USE_CHH
|
||||
thread_state_awake (ts1);
|
||||
#endif
|
||||
ddsrt_mutex_lock (&handles.lock);
|
||||
if (handles.count == MAX_HANDLES)
|
||||
{
|
||||
|
|
@ -143,55 +117,67 @@ dds_handle_t dds_handle_create (struct dds_handle_link *link)
|
|||
else
|
||||
{
|
||||
handles.count++;
|
||||
#if USE_CHH
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
ret = dds_handle_create_int (link);
|
||||
#else
|
||||
ret = dds_handle_create_int (link);
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
#endif
|
||||
assert (ret > 0);
|
||||
}
|
||||
#if USE_CHH
|
||||
thread_state_asleep (ts1);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dds_handle_close (struct dds_handle_link *link)
|
||||
dds_return_t dds_handle_register_special (struct dds_handle_link *link, dds_handle_t handle)
|
||||
{
|
||||
ddsrt_atomic_or32 (&link->cnt_flags, HDL_FLAG_CLOSED);
|
||||
dds_return_t ret;
|
||||
if (handle <= 0)
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
ddsrt_mutex_lock (&handles.lock);
|
||||
if (handles.count == MAX_HANDLES)
|
||||
{
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
ret = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
}
|
||||
else
|
||||
{
|
||||
handles.count++;
|
||||
ddsrt_atomic_st32 (&link->cnt_flags, HDL_FLAG_PENDING | HDL_REFCOUNT_UNIT | 1u);
|
||||
link->hdl = handle;
|
||||
if (hhadd (handles.ht, link))
|
||||
ret = handle;
|
||||
else
|
||||
ret = DDS_RETCODE_BAD_PARAMETER;
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
assert (ret > 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout)
|
||||
void dds_handle_unpend (struct dds_handle_link *link)
|
||||
{
|
||||
#if USE_CHH
|
||||
struct thread_state1 * const ts1 = lookup_thread_state ();
|
||||
#ifndef NDEBUG
|
||||
uint32_t cf = ddsrt_atomic_ld32 (&link->cnt_flags);
|
||||
assert ((cf & HDL_FLAG_PENDING));
|
||||
assert (!(cf & HDL_FLAG_CLOSED));
|
||||
assert (!(cf & HDL_FLAG_CLOSING));
|
||||
assert ((cf & HDL_REFCOUNT_MASK) >= HDL_REFCOUNT_UNIT);
|
||||
assert ((cf & HDL_PINCOUNT_MASK) >= 1u);
|
||||
#endif
|
||||
assert (ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_FLAG_CLOSED);
|
||||
ddsrt_mutex_lock (&handles.lock);
|
||||
if ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_PINCOUNT_MASK) != 0)
|
||||
ddsrt_atomic_and32 (&link->cnt_flags, ~HDL_FLAG_PENDING);
|
||||
dds_handle_unpin (link);
|
||||
}
|
||||
|
||||
int32_t dds_handle_delete (struct dds_handle_link *link)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
uint32_t cf = ddsrt_atomic_ld32 (&link->cnt_flags);
|
||||
if (!(cf & HDL_FLAG_PENDING))
|
||||
{
|
||||
/* FIXME: there is no sensible solution when this times out, so it must
|
||||
never do that ... */
|
||||
const dds_time_t abstimeout = dds_time () + timeout;
|
||||
while ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_PINCOUNT_MASK) != 0)
|
||||
{
|
||||
if (!ddsrt_cond_waituntil (&handles.cond, &handles.lock, abstimeout))
|
||||
{
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
fprintf (stderr, "** timeout in handle_delete **\n");
|
||||
return DDS_RETCODE_TIMEOUT;
|
||||
}
|
||||
}
|
||||
assert (cf & HDL_FLAG_CLOSING);
|
||||
assert (cf & HDL_FLAG_CLOSED);
|
||||
assert ((cf & HDL_REFCOUNT_MASK) == 0u);
|
||||
}
|
||||
#if USE_CHH
|
||||
thread_state_awake (ts1);
|
||||
int x = ddsrt_chh_remove (handles.ht, link);
|
||||
thread_state_asleep (ts1);
|
||||
#else
|
||||
int x = ddsrt_hh_remove (handles.ht, link);
|
||||
assert ((cf & HDL_PINCOUNT_MASK) == 1u);
|
||||
#endif
|
||||
ddsrt_mutex_lock (&handles.lock);
|
||||
int x = ddsrt_hh_remove (handles.ht, link);
|
||||
assert(x);
|
||||
(void)x;
|
||||
assert (handles.count > 0);
|
||||
|
|
@ -200,11 +186,8 @@ int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout)
|
|||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
int32_t dds_handle_pin (dds_handle_t hdl, struct dds_handle_link **link)
|
||||
static int32_t dds_handle_pin_int (dds_handle_t hdl, uint32_t delta, struct dds_handle_link **link)
|
||||
{
|
||||
#if USE_CHH
|
||||
struct thread_state1 * const ts1 = lookup_thread_state ();
|
||||
#endif
|
||||
struct dds_handle_link dummy = { .hdl = hdl };
|
||||
int32_t rc;
|
||||
/* it makes sense to check here for initialization: the first thing any operation
|
||||
|
|
@ -218,41 +201,41 @@ int32_t dds_handle_pin (dds_handle_t hdl, struct dds_handle_link **link)
|
|||
if (handles.ht == NULL)
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
|
||||
#if USE_CHH
|
||||
thread_state_awake (ts1);
|
||||
*link = ddsrt_chh_lookup (handles.ht, &dummy);
|
||||
#else
|
||||
ddsrt_mutex_lock (&handles.lock);
|
||||
*link = ddsrt_hh_lookup (handles.ht, &dummy);
|
||||
#endif
|
||||
if (*link == NULL)
|
||||
rc = DDS_RETCODE_BAD_PARAMETER;
|
||||
else
|
||||
{
|
||||
uint32_t cnt_flags;
|
||||
uint32_t cf;
|
||||
/* Assume success; bail out if the object turns out to be in the process of
|
||||
being deleted */
|
||||
rc = DDS_RETCODE_OK;
|
||||
do {
|
||||
cnt_flags = ddsrt_atomic_ld32 (&(*link)->cnt_flags);
|
||||
if (cnt_flags & HDL_FLAG_CLOSED)
|
||||
cf = ddsrt_atomic_ld32 (&(*link)->cnt_flags);
|
||||
if (cf & (HDL_FLAG_CLOSED | HDL_FLAG_CLOSING | HDL_FLAG_PENDING))
|
||||
{
|
||||
rc = DDS_RETCODE_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
} while (!ddsrt_atomic_cas32 (&(*link)->cnt_flags, cnt_flags, cnt_flags + HDL_PINCOUNT_UNIT));
|
||||
} while (!ddsrt_atomic_cas32 (&(*link)->cnt_flags, cf, cf + delta));
|
||||
}
|
||||
#if USE_CHH
|
||||
thread_state_asleep (ts1);
|
||||
#else
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
int32_t dds_handle_pin (dds_handle_t hdl, struct dds_handle_link **link)
|
||||
{
|
||||
return dds_handle_pin_int (hdl, 1u, link);
|
||||
}
|
||||
|
||||
int32_t dds_handle_pin_and_ref (dds_handle_t hdl, struct dds_handle_link **link)
|
||||
{
|
||||
return dds_handle_pin_int (hdl, HDL_REFCOUNT_UNIT + 1u, link);
|
||||
}
|
||||
|
||||
void dds_handle_repin (struct dds_handle_link *link)
|
||||
{
|
||||
DDSRT_STATIC_ASSERT (HDL_PINCOUNT_UNIT == 1);
|
||||
uint32_t x = ddsrt_atomic_inc32_nv (&link->cnt_flags);
|
||||
assert (!(x & HDL_FLAG_CLOSED));
|
||||
(void) x;
|
||||
|
|
@ -260,13 +243,20 @@ void dds_handle_repin (struct dds_handle_link *link)
|
|||
|
||||
void dds_handle_unpin (struct dds_handle_link *link)
|
||||
{
|
||||
DDSRT_STATIC_ASSERT (HDL_PINCOUNT_UNIT == 1);
|
||||
if ((ddsrt_atomic_dec32_ov (&link->cnt_flags) & (HDL_FLAG_CLOSED | HDL_PINCOUNT_MASK)) == (HDL_FLAG_CLOSED | HDL_PINCOUNT_UNIT))
|
||||
#ifndef NDEBUG
|
||||
uint32_t cf = ddsrt_atomic_ld32 (&link->cnt_flags);
|
||||
assert (!(cf & HDL_FLAG_CLOSED));
|
||||
if (cf & HDL_FLAG_CLOSING)
|
||||
assert ((cf & HDL_PINCOUNT_MASK) > 1u);
|
||||
else
|
||||
assert ((cf & HDL_PINCOUNT_MASK) >= 1u);
|
||||
#endif
|
||||
ddsrt_mutex_lock (&handles.lock);
|
||||
if ((ddsrt_atomic_dec32_nv (&link->cnt_flags) & (HDL_FLAG_CLOSING | HDL_PINCOUNT_MASK)) == (HDL_FLAG_CLOSING | 1u))
|
||||
{
|
||||
ddsrt_mutex_lock (&handles.lock);
|
||||
ddsrt_cond_broadcast (&handles.cond);
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
}
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
}
|
||||
|
||||
void dds_handle_add_ref (struct dds_handle_link *link)
|
||||
|
|
@ -283,12 +273,27 @@ bool dds_handle_drop_ref (struct dds_handle_link *link)
|
|||
if ((old & HDL_REFCOUNT_MASK) != HDL_REFCOUNT_UNIT)
|
||||
new = old - HDL_REFCOUNT_UNIT;
|
||||
else
|
||||
new = (old - HDL_REFCOUNT_UNIT) | HDL_FLAG_CLOSED;
|
||||
new = (old - HDL_REFCOUNT_UNIT) | HDL_FLAG_CLOSING;
|
||||
} while (!ddsrt_atomic_cas32 (&link->cnt_flags, old, new));
|
||||
return (new & HDL_REFCOUNT_MASK) == 0;
|
||||
}
|
||||
|
||||
bool dds_handle_is_closed (struct dds_handle_link *link)
|
||||
void dds_handle_close_wait (struct dds_handle_link *link)
|
||||
{
|
||||
return (ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_FLAG_CLOSED) != 0;
|
||||
#ifndef NDEBUG
|
||||
uint32_t cf = ddsrt_atomic_ld32 (&link->cnt_flags);
|
||||
assert ((cf & HDL_FLAG_CLOSING));
|
||||
assert (!(cf & HDL_FLAG_CLOSED));
|
||||
assert ((cf & HDL_REFCOUNT_MASK) == 0u);
|
||||
assert ((cf & HDL_PINCOUNT_MASK) >= 1u);
|
||||
#endif
|
||||
ddsrt_mutex_lock (&handles.lock);
|
||||
while ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_PINCOUNT_MASK) != 1u)
|
||||
ddsrt_cond_wait (&handles.cond, &handles.lock);
|
||||
/* only one thread may call close_wait on a given handle */
|
||||
assert (!(ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_FLAG_CLOSED));
|
||||
ddsrt_atomic_or32 (&link->cnt_flags, HDL_FLAG_CLOSED);
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
}
|
||||
|
||||
extern inline bool dds_handle_is_closed (struct dds_handle_link *link);
|
||||
|
|
|
|||
|
|
@ -18,10 +18,11 @@
|
|||
#include "dds/ddsrt/process.h"
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds__init.h"
|
||||
#include "dds__rhc.h"
|
||||
#include "dds/ddsc/dds_rhc.h"
|
||||
#include "dds__domain.h"
|
||||
#include "dds__builtin.h"
|
||||
#include "dds__whc_builtintopic.h"
|
||||
#include "dds__entity.h"
|
||||
#include "dds/ddsi/ddsi_iid.h"
|
||||
#include "dds/ddsi/ddsi_tkmap.h"
|
||||
#include "dds/ddsi/ddsi_serdata.h"
|
||||
|
|
@ -32,10 +33,49 @@
|
|||
#include "dds/ddsi/q_globals.h"
|
||||
#include "dds/version.h"
|
||||
|
||||
#define DOMAIN_ID_MIN 0
|
||||
#define DOMAIN_ID_MAX 230
|
||||
static void dds_close (struct dds_entity *e);
|
||||
static dds_return_t dds_fini (struct dds_entity *e);
|
||||
|
||||
dds_globals dds_global;
|
||||
const struct dds_entity_deriver dds_entity_deriver_cyclonedds = {
|
||||
.interrupt = dds_entity_deriver_dummy_interrupt,
|
||||
.close = dds_close,
|
||||
.delete = dds_fini,
|
||||
.set_qos = dds_entity_deriver_dummy_set_qos,
|
||||
.validate_status = dds_entity_deriver_dummy_validate_status
|
||||
};
|
||||
|
||||
dds_cyclonedds_entity dds_global;
|
||||
|
||||
#define CDDS_STATE_ZERO 0u
|
||||
#define CDDS_STATE_STARTING 1u
|
||||
#define CDDS_STATE_READY 2u
|
||||
#define CDDS_STATE_STOPPING 3u
|
||||
static ddsrt_atomic_uint32_t dds_state = DDSRT_ATOMIC_UINT32_INIT (CDDS_STATE_ZERO);
|
||||
|
||||
static void common_cleanup (void)
|
||||
{
|
||||
if (thread_states_fini ())
|
||||
dds_handle_server_fini ();
|
||||
|
||||
ddsi_iid_fini ();
|
||||
ddsrt_cond_destroy (&dds_global.m_cond);
|
||||
ddsrt_mutex_destroy (&dds_global.m_mutex);
|
||||
|
||||
ddsrt_atomic_st32 (&dds_state, CDDS_STATE_ZERO);
|
||||
ddsrt_cond_broadcast (ddsrt_get_singleton_cond ());
|
||||
}
|
||||
|
||||
static bool cyclonedds_entity_ready (uint32_t s)
|
||||
{
|
||||
assert (s != CDDS_STATE_ZERO);
|
||||
if (s == CDDS_STATE_STARTING || s == CDDS_STATE_STOPPING)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
struct dds_handle_link *x;
|
||||
return dds_handle_pin_and_ref (DDS_CYCLONEDDS_HANDLE, &x) == DDS_RETCODE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
dds_return_t dds_init (void)
|
||||
{
|
||||
|
|
@ -43,18 +83,34 @@ dds_return_t dds_init (void)
|
|||
|
||||
ddsrt_init ();
|
||||
ddsrt_mutex_t * const init_mutex = ddsrt_get_singleton_mutex ();
|
||||
ddsrt_cond_t * const init_cond = ddsrt_get_singleton_cond ();
|
||||
|
||||
ddsrt_mutex_lock (init_mutex);
|
||||
if (dds_global.m_init_count++ != 0)
|
||||
uint32_t s = ddsrt_atomic_ld32 (&dds_state);
|
||||
while (s != CDDS_STATE_ZERO && !cyclonedds_entity_ready (s))
|
||||
{
|
||||
ddsrt_mutex_unlock (init_mutex);
|
||||
return DDS_RETCODE_OK;
|
||||
ddsrt_cond_wait (init_cond, init_mutex);
|
||||
s = ddsrt_atomic_ld32 (&dds_state);
|
||||
}
|
||||
switch (s)
|
||||
{
|
||||
case CDDS_STATE_READY:
|
||||
assert (dds_global.m_entity.m_hdllink.hdl == DDS_CYCLONEDDS_HANDLE);
|
||||
ddsrt_mutex_unlock (init_mutex);
|
||||
return DDS_RETCODE_OK;
|
||||
case CDDS_STATE_ZERO:
|
||||
ddsrt_atomic_st32 (&dds_state, CDDS_STATE_STARTING);
|
||||
break;
|
||||
default:
|
||||
ddsrt_mutex_unlock (init_mutex);
|
||||
ddsrt_fini ();
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
ddsrt_mutex_init (&dds_global.m_mutex);
|
||||
ddsrt_cond_init (&dds_global.m_cond);
|
||||
ddsi_iid_init ();
|
||||
thread_states_init_static ();
|
||||
thread_states_init (64);
|
||||
upgrade_main_thread ();
|
||||
|
||||
if (dds_handle_server_init () != DDS_RETCODE_OK)
|
||||
{
|
||||
|
|
@ -63,30 +119,48 @@ dds_return_t dds_init (void)
|
|||
goto fail_handleserver;
|
||||
}
|
||||
|
||||
dds_entity_init (&dds_global.m_entity, NULL, DDS_KIND_CYCLONEDDS, NULL, NULL, 0);
|
||||
dds_global.m_entity.m_iid = ddsi_iid_gen ();
|
||||
dds_global.m_entity.m_flags = DDS_ENTITY_IMPLICIT;
|
||||
dds_handle_repin (&dds_global.m_entity.m_hdllink);
|
||||
dds_entity_add_ref_locked (&dds_global.m_entity);
|
||||
dds_entity_init_complete (&dds_global.m_entity);
|
||||
ddsrt_atomic_st32 (&dds_state, CDDS_STATE_READY);
|
||||
ddsrt_mutex_unlock (init_mutex);
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
fail_handleserver:
|
||||
ddsrt_mutex_destroy (&dds_global.m_mutex);
|
||||
dds_global.m_init_count--;
|
||||
common_cleanup ();
|
||||
ddsrt_mutex_unlock (init_mutex);
|
||||
ddsrt_fini ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern void dds_fini (void)
|
||||
static void dds_close (struct dds_entity *e)
|
||||
{
|
||||
(void) e;
|
||||
assert (ddsrt_atomic_ld32 (&dds_state) == CDDS_STATE_READY);
|
||||
ddsrt_atomic_st32 (&dds_state, CDDS_STATE_STOPPING);
|
||||
}
|
||||
|
||||
static dds_return_t dds_fini (struct dds_entity *e)
|
||||
{
|
||||
(void) e;
|
||||
ddsrt_mutex_t * const init_mutex = ddsrt_get_singleton_mutex ();
|
||||
/* If there are multiple domains shutting down simultaneously, the one "deleting" the top-level
|
||||
entity (and thus arriving here) may have overtaken another thread that is still in the process
|
||||
of deleting its domain object. For most entities such races are not an issue, but here we tear
|
||||
down the run-time, so here we must wait until everyone else is out. */
|
||||
ddsrt_mutex_lock (&dds_global.m_mutex);
|
||||
while (!ddsrt_avl_is_empty (&dds_global.m_domains))
|
||||
ddsrt_cond_wait (&dds_global.m_cond, &dds_global.m_mutex);
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
|
||||
ddsrt_mutex_lock (init_mutex);
|
||||
assert (dds_global.m_init_count > 0);
|
||||
if (--dds_global.m_init_count == 0)
|
||||
{
|
||||
dds_handle_server_fini ();
|
||||
downgrade_main_thread ();
|
||||
thread_states_fini ();
|
||||
ddsi_iid_fini ();
|
||||
ddsrt_mutex_destroy (&dds_global.m_mutex);
|
||||
}
|
||||
assert (ddsrt_atomic_ld32 (&dds_state) == CDDS_STATE_STOPPING);
|
||||
dds_entity_final_deinit_before_free (e);
|
||||
common_cleanup ();
|
||||
ddsrt_mutex_unlock (init_mutex);
|
||||
ddsrt_fini ();
|
||||
return DDS_RETCODE_NO_DATA;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include "dds__entity.h"
|
||||
#include "dds__write.h"
|
||||
#include "dds__writer.h"
|
||||
#include "dds__rhc.h"
|
||||
#include "dds/ddsc/dds_rhc.h"
|
||||
#include "dds/ddsi/ddsi_tkmap.h"
|
||||
#include "dds/ddsi/ddsi_serdata.h"
|
||||
#include "dds/ddsi/q_entity.h"
|
||||
|
|
|
|||
|
|
@ -27,15 +27,14 @@ dds_return_t dds_get_matched_subscriptions (dds_entity_t writer, dds_instance_ha
|
|||
{
|
||||
dds_writer *wr;
|
||||
dds_return_t rc;
|
||||
if (rds == NULL && nrds > 0)
|
||||
if ((rds != NULL && (nrds == 0 || nrds > INT32_MAX)) || (rds == NULL && nrds != 0))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
|
||||
return rc;
|
||||
else
|
||||
{
|
||||
const struct ephash *gh = wr->m_entity.m_domain->gv.guid_hash;
|
||||
const int32_t nrds_max = (nrds > INT32_MAX) ? INT32_MAX : (int32_t) nrds;
|
||||
int32_t nrds_act = 0;
|
||||
size_t nrds_act = 0;
|
||||
ddsrt_avl_iter_t it;
|
||||
/* FIXME: this ought not be so tightly coupled to the lower layer */
|
||||
thread_state_awake (lookup_thread_state (), &wr->m_entity.m_domain->gv);
|
||||
|
|
@ -47,7 +46,7 @@ dds_return_t dds_get_matched_subscriptions (dds_entity_t writer, dds_instance_ha
|
|||
struct proxy_reader *prd;
|
||||
if ((prd = ephash_lookup_proxy_reader_guid (gh, &m->prd_guid)) != NULL)
|
||||
{
|
||||
if (nrds_act < nrds_max)
|
||||
if (nrds_act < nrds)
|
||||
rds[nrds_act] = prd->e.iid;
|
||||
nrds_act++;
|
||||
}
|
||||
|
|
@ -59,7 +58,7 @@ dds_return_t dds_get_matched_subscriptions (dds_entity_t writer, dds_instance_ha
|
|||
struct reader *rd;
|
||||
if ((rd = ephash_lookup_reader_guid (gh, &m->rd_guid)) != NULL)
|
||||
{
|
||||
if (nrds_act < nrds_max)
|
||||
if (nrds_act < nrds)
|
||||
rds[nrds_act] = rd->e.iid;
|
||||
nrds_act++;
|
||||
}
|
||||
|
|
@ -67,7 +66,10 @@ dds_return_t dds_get_matched_subscriptions (dds_entity_t writer, dds_instance_ha
|
|||
ddsrt_mutex_unlock (&wr->m_wr->e.lock);
|
||||
thread_state_asleep (lookup_thread_state ());
|
||||
dds_writer_unlock (wr);
|
||||
return nrds_act;
|
||||
/* FIXME: is it really true that there can not be more than INT32_MAX matching readers?
|
||||
(in practice it'll come to a halt long before that) */
|
||||
assert (nrds_act <= INT32_MAX);
|
||||
return (dds_return_t) nrds_act;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -75,15 +77,14 @@ dds_return_t dds_get_matched_publications (dds_entity_t reader, dds_instance_han
|
|||
{
|
||||
dds_reader *rd;
|
||||
dds_return_t rc;
|
||||
if (wrs == NULL && nwrs > 0)
|
||||
if ((wrs != NULL && (nwrs == 0 || nwrs > INT32_MAX)) || (wrs == NULL && nwrs != 0))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
if ((rc = dds_reader_lock (reader, &rd)) != DDS_RETCODE_OK)
|
||||
return rc;
|
||||
else
|
||||
{
|
||||
const struct ephash *gh = rd->m_entity.m_domain->gv.guid_hash;
|
||||
const int32_t nwrs_max = (nwrs > INT32_MAX) ? INT32_MAX : (int32_t) nwrs;
|
||||
int32_t nwrs_act = 0;
|
||||
size_t nwrs_act = 0;
|
||||
ddsrt_avl_iter_t it;
|
||||
/* FIXME: this ought not be so tightly coupled to the lower layer */
|
||||
thread_state_awake (lookup_thread_state (), &rd->m_entity.m_domain->gv);
|
||||
|
|
@ -95,7 +96,7 @@ dds_return_t dds_get_matched_publications (dds_entity_t reader, dds_instance_han
|
|||
struct proxy_writer *pwr;
|
||||
if ((pwr = ephash_lookup_proxy_writer_guid (gh, &m->pwr_guid)) != NULL)
|
||||
{
|
||||
if (nwrs_act < nwrs_max)
|
||||
if (nwrs_act < nwrs)
|
||||
wrs[nwrs_act] = pwr->e.iid;
|
||||
nwrs_act++;
|
||||
}
|
||||
|
|
@ -107,7 +108,7 @@ dds_return_t dds_get_matched_publications (dds_entity_t reader, dds_instance_han
|
|||
struct writer *wr;
|
||||
if ((wr = ephash_lookup_writer_guid (gh, &m->wr_guid)) != NULL)
|
||||
{
|
||||
if (nwrs_act < nwrs_max)
|
||||
if (nwrs_act < nwrs)
|
||||
wrs[nwrs_act] = wr->e.iid;
|
||||
nwrs_act++;
|
||||
}
|
||||
|
|
@ -115,14 +116,17 @@ dds_return_t dds_get_matched_publications (dds_entity_t reader, dds_instance_han
|
|||
ddsrt_mutex_unlock (&rd->m_rd->e.lock);
|
||||
thread_state_asleep (lookup_thread_state ());
|
||||
dds_reader_unlock (rd);
|
||||
return nwrs_act;
|
||||
/* FIXME: is it really true that there can not be more than INT32_MAX matching readers?
|
||||
(in practice it'll come to a halt long before that) */
|
||||
assert (nwrs_act <= INT32_MAX);
|
||||
return (dds_return_t) nwrs_act;
|
||||
}
|
||||
}
|
||||
|
||||
static dds_builtintopic_endpoint_t *make_builtintopic_endpoint (const nn_guid_t *guid, const nn_guid_t *ppguid, dds_instance_handle_t ppiid, const dds_qos_t *qos)
|
||||
static dds_builtintopic_endpoint_t *make_builtintopic_endpoint (const ddsi_guid_t *guid, const ddsi_guid_t *ppguid, dds_instance_handle_t ppiid, const dds_qos_t *qos)
|
||||
{
|
||||
dds_builtintopic_endpoint_t *ep;
|
||||
nn_guid_t tmp;
|
||||
ddsi_guid_t tmp;
|
||||
ep = dds_alloc (sizeof (*ep));
|
||||
tmp = nn_hton_guid (*guid);
|
||||
memcpy (&ep->key, &tmp, sizeof (ep->key));
|
||||
|
|
|
|||
|
|
@ -12,11 +12,13 @@
|
|||
#include <assert.h>
|
||||
|
||||
#include "dds/ddsrt/cdtors.h"
|
||||
#include "dds/ddsrt/environ.h"
|
||||
#include "dds/ddsi/q_entity.h"
|
||||
#include "dds/ddsi/q_thread.h"
|
||||
#include "dds/ddsi/q_config.h"
|
||||
#include "dds/ddsi/q_plist.h"
|
||||
#include "dds/ddsi/q_globals.h"
|
||||
#include "dds/version.h"
|
||||
#include "dds__init.h"
|
||||
#include "dds__domain.h"
|
||||
#include "dds__participant.h"
|
||||
|
|
@ -42,14 +44,7 @@ static dds_return_t dds_participant_delete (dds_entity *e)
|
|||
thread_state_awake (lookup_thread_state (), &e->m_domain->gv);
|
||||
if ((ret = delete_participant (&e->m_domain->gv, &e->m_guid)) < 0)
|
||||
DDS_CERROR (&e->m_domain->gv.logconfig, "dds_participant_delete: internal error %"PRId32"\n", ret);
|
||||
ddsrt_mutex_lock (&dds_global.m_mutex);
|
||||
ddsrt_avl_delete (&dds_entity_children_td, &e->m_domain->m_ppants, e);
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
thread_state_asleep (lookup_thread_state ());
|
||||
|
||||
/* Every dds_init needs a dds_fini. */
|
||||
dds_domain_free (e->m_domain);
|
||||
dds_fini ();
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
|
|
@ -74,6 +69,7 @@ static dds_return_t dds_participant_qos_set (dds_entity *e, const dds_qos_t *qos
|
|||
}
|
||||
|
||||
const struct dds_entity_deriver dds_entity_deriver_participant = {
|
||||
.interrupt = dds_entity_deriver_dummy_interrupt,
|
||||
.close = dds_entity_deriver_dummy_close,
|
||||
.delete = dds_participant_delete,
|
||||
.set_qos = dds_participant_qos_set,
|
||||
|
|
@ -84,16 +80,19 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_
|
|||
{
|
||||
dds_domain *dom;
|
||||
dds_entity_t ret;
|
||||
nn_guid_t guid;
|
||||
ddsi_guid_t guid;
|
||||
dds_participant * pp;
|
||||
nn_plist_t plist;
|
||||
dds_qos_t *new_qos = NULL;
|
||||
char *config = "";
|
||||
|
||||
/* Make sure DDS instance is initialized. */
|
||||
if ((ret = dds_init ()) < 0)
|
||||
goto err_dds_init;
|
||||
|
||||
if ((ret = dds_domain_create (&dom, domain)) < 0)
|
||||
(void) ddsrt_getenv (DDS_PROJECT_NAME_NOSPACE_CAPS"_URI", &config);
|
||||
|
||||
if ((ret = dds_domain_create_internal (&dom, domain, true, config)) < 0)
|
||||
goto err_domain_create;
|
||||
|
||||
new_qos = dds_create_qos ();
|
||||
|
|
@ -118,7 +117,7 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_
|
|||
}
|
||||
|
||||
pp = dds_alloc (sizeof (*pp));
|
||||
if ((ret = dds_entity_init (&pp->m_entity, NULL, DDS_KIND_PARTICIPANT, new_qos, listener, DDS_PARTICIPANT_STATUS_MASK)) < 0)
|
||||
if ((ret = dds_entity_init (&pp->m_entity, &dom->m_entity, DDS_KIND_PARTICIPANT, new_qos, listener, DDS_PARTICIPANT_STATUS_MASK)) < 0)
|
||||
goto err_entity_init;
|
||||
|
||||
pp->m_entity.m_guid = guid;
|
||||
|
|
@ -127,9 +126,14 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_
|
|||
pp->m_builtin_subscriber = 0;
|
||||
|
||||
/* Add participant to extent */
|
||||
ddsrt_mutex_lock (&dds_global.m_mutex);
|
||||
ddsrt_avl_insert (&dds_entity_children_td, &dom->m_ppants, &pp->m_entity);
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
ddsrt_mutex_lock (&dds_global.m_entity.m_mutex);
|
||||
dds_entity_register_child (&dom->m_entity, &pp->m_entity);
|
||||
ddsrt_mutex_unlock (&dds_global.m_entity.m_mutex);
|
||||
|
||||
dds_entity_init_complete (&pp->m_entity);
|
||||
/* drop temporary extra ref to domain, dds_init */
|
||||
dds_delete (dom->m_entity.m_hdllink.hdl);
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
return ret;
|
||||
|
||||
err_entity_init:
|
||||
|
|
@ -137,43 +141,40 @@ err_entity_init:
|
|||
err_new_participant:
|
||||
err_qos_validation:
|
||||
dds_delete_qos (new_qos);
|
||||
dds_domain_free (dom);
|
||||
dds_delete (dom->m_entity.m_hdllink.hdl);
|
||||
err_domain_create:
|
||||
dds_fini ();
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
err_dds_init:
|
||||
return ret;
|
||||
}
|
||||
|
||||
dds_entity_t dds_lookup_participant (dds_domainid_t domain_id, dds_entity_t *participants, size_t size)
|
||||
dds_return_t dds_lookup_participant (dds_domainid_t domain_id, dds_entity_t *participants, size_t size)
|
||||
{
|
||||
if ((participants != NULL && (size <= 0 || size >= INT32_MAX)) || (participants == NULL && size != 0))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
dds_return_t ret;
|
||||
|
||||
ddsrt_init ();
|
||||
ddsrt_mutex_t * const init_mutex = ddsrt_get_singleton_mutex ();
|
||||
if ((participants != NULL && (size == 0 || size >= INT32_MAX)) || (participants == NULL && size != 0))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
|
||||
if (participants)
|
||||
participants[0] = 0;
|
||||
|
||||
dds_return_t ret = 0;
|
||||
ddsrt_mutex_lock (init_mutex);
|
||||
if (dds_global.m_init_count > 0)
|
||||
if ((ret = dds_init ()) < 0)
|
||||
return ret;
|
||||
|
||||
ret = 0;
|
||||
struct dds_domain *dom;
|
||||
ddsrt_mutex_lock (&dds_global.m_mutex);
|
||||
if ((dom = dds_domain_find_locked (domain_id)) != NULL)
|
||||
{
|
||||
struct dds_domain *dom;
|
||||
ddsrt_mutex_lock (&dds_global.m_mutex);
|
||||
if ((dom = dds_domain_find_locked (domain_id)) != NULL)
|
||||
ddsrt_avl_iter_t it;
|
||||
for (dds_entity *e = ddsrt_avl_iter_first (&dds_entity_children_td, &dom->m_entity.m_children, &it); e != NULL; e = ddsrt_avl_iter_next (&it))
|
||||
{
|
||||
ddsrt_avl_iter_t it;
|
||||
for (dds_entity *e = ddsrt_avl_iter_first (&dds_entity_children_td, &dom->m_ppants, &it); e != NULL; e = ddsrt_avl_iter_next (&it))
|
||||
{
|
||||
if ((size_t) ret < size)
|
||||
participants[ret] = e->m_hdllink.hdl;
|
||||
ret++;
|
||||
}
|
||||
if ((size_t) ret < size)
|
||||
participants[ret] = e->m_hdllink.hdl;
|
||||
ret++;
|
||||
}
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
}
|
||||
ddsrt_mutex_unlock (init_mutex);
|
||||
ddsrt_fini ();
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ static dds_return_t dds_publisher_status_validate (uint32_t mask)
|
|||
}
|
||||
|
||||
const struct dds_entity_deriver dds_entity_deriver_publisher = {
|
||||
.interrupt = dds_entity_deriver_dummy_interrupt,
|
||||
.close = dds_entity_deriver_dummy_close,
|
||||
.delete = dds_entity_deriver_dummy_delete,
|
||||
.set_qos = dds_publisher_qos_set,
|
||||
|
|
@ -69,6 +70,7 @@ dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qo
|
|||
hdl = dds_entity_init (&pub->m_entity, &par->m_entity, DDS_KIND_PUBLISHER, new_qos, listener, DDS_PUBLISHER_STATUS_MASK);
|
||||
pub->m_entity.m_iid = ddsi_iid_gen ();
|
||||
dds_entity_register_child (&par->m_entity, &pub->m_entity);
|
||||
dds_entity_init_complete (&pub->m_entity);
|
||||
dds_participant_unlock (par);
|
||||
return hdl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,8 +33,9 @@ dds_entity_t dds_create_querycondition (dds_entity_t reader, uint32_t mask, dds_
|
|||
dds_entity_t hdl;
|
||||
dds_readcond *cond = dds_create_readcond (r, DDS_KIND_COND_QUERY, mask, filter);
|
||||
assert (cond);
|
||||
dds_reader_unlock (r);
|
||||
hdl = cond->m_entity.m_hdllink.hdl;
|
||||
dds_entity_init_complete (&cond->m_entity);
|
||||
dds_reader_unlock (r);
|
||||
return hdl;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
#include "dds__entity.h"
|
||||
#include "dds__reader.h"
|
||||
#include "dds/ddsi/ddsi_tkmap.h"
|
||||
#include "dds__rhc.h"
|
||||
#include "dds/ddsc/dds_rhc.h"
|
||||
#include "dds/ddsi/q_thread.h"
|
||||
#include "dds/ddsi/q_ephash.h"
|
||||
#include "dds/ddsi/q_entity.h"
|
||||
|
|
@ -130,7 +130,7 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition,
|
|||
if (nodata_cleanups & NC_CLEAR_LOAN_OUT)
|
||||
rd->m_loan_out = false;
|
||||
if (nodata_cleanups & NC_FREE_BUF)
|
||||
ddsi_sertopic_free_samples (rd->m_topic->m_stopic, buf[0], maxs, DDS_FREE_ALL);
|
||||
ddsi_sertopic_free_samples (rd->m_topic->m_stopic, buf, maxs, DDS_FREE_ALL);
|
||||
if (nodata_cleanups & NC_RESET_BUF)
|
||||
buf[0] = NULL;
|
||||
ddsrt_mutex_unlock (&rd->m_entity.m_mutex);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
#include <assert.h>
|
||||
#include "dds__reader.h"
|
||||
#include "dds__readcond.h"
|
||||
#include "dds__rhc.h"
|
||||
#include "dds/ddsc/dds_rhc.h"
|
||||
#include "dds__entity.h"
|
||||
#include "dds/ddsi/ddsi_iid.h"
|
||||
#include "dds/ddsi/q_ephash.h"
|
||||
|
|
@ -23,11 +23,14 @@ static dds_return_t dds_readcond_delete (dds_entity *e) ddsrt_nonnull_all;
|
|||
|
||||
static dds_return_t dds_readcond_delete (dds_entity *e)
|
||||
{
|
||||
dds_rhc_remove_readcondition ((dds_readcond *) e);
|
||||
struct dds_reader * const rd = (struct dds_reader *) e->m_parent;
|
||||
assert (dds_entity_kind (&rd->m_entity) == DDS_KIND_READER);
|
||||
dds_rhc_remove_readcondition (rd->m_rhc, (dds_readcond *) e);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
const struct dds_entity_deriver dds_entity_deriver_readcondition = {
|
||||
.interrupt = dds_entity_deriver_dummy_interrupt,
|
||||
.close = dds_entity_deriver_dummy_close,
|
||||
.delete = dds_readcond_delete,
|
||||
.set_qos = dds_entity_deriver_dummy_set_qos,
|
||||
|
|
@ -41,17 +44,15 @@ dds_readcond *dds_create_readcond (dds_reader *rd, dds_entity_kind_t kind, uint3
|
|||
(void) dds_entity_init (&cond->m_entity, &rd->m_entity, kind, NULL, NULL, 0);
|
||||
cond->m_entity.m_iid = ddsi_iid_gen ();
|
||||
dds_entity_register_child (&rd->m_entity, &cond->m_entity);
|
||||
cond->m_rhc = rd->m_rhc;
|
||||
cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE;
|
||||
cond->m_view_states = mask & DDS_ANY_VIEW_STATE;
|
||||
cond->m_instance_states = mask & DDS_ANY_INSTANCE_STATE;
|
||||
cond->m_rd_guid = rd->m_entity.m_guid;
|
||||
if (kind == DDS_KIND_COND_QUERY)
|
||||
{
|
||||
cond->m_query.m_filter = filter;
|
||||
cond->m_query.m_qcmask = 0;
|
||||
}
|
||||
if (!dds_rhc_add_readcondition (cond))
|
||||
if (!dds_rhc_add_readcondition (rd->m_rhc, cond))
|
||||
{
|
||||
/* FIXME: current entity management code can't deal with an error late in the creation of the
|
||||
entity because it doesn't allow deleting it again ... */
|
||||
|
|
@ -72,6 +73,7 @@ dds_entity_t dds_create_readcondition (dds_entity_t reader, uint32_t mask)
|
|||
dds_readcond *cond = dds_create_readcond(rd, DDS_KIND_COND_READ, mask, 0);
|
||||
assert (cond);
|
||||
hdl = cond->m_entity.m_hdllink.hdl;
|
||||
dds_entity_init_complete (&cond->m_entity);
|
||||
dds_reader_unlock (rd);
|
||||
return hdl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#include "dds__reader.h"
|
||||
#include "dds__listener.h"
|
||||
#include "dds__init.h"
|
||||
#include "dds__rhc.h"
|
||||
#include "dds/ddsc/dds_rhc.h"
|
||||
#include "dds__rhc_default.h"
|
||||
#include "dds__topic.h"
|
||||
#include "dds__get_status.h"
|
||||
|
|
@ -40,16 +40,21 @@ DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_reader)
|
|||
DDS_SAMPLE_LOST_STATUS |\
|
||||
DDS_SUBSCRIPTION_MATCHED_STATUS)
|
||||
|
||||
static dds_return_t dds_reader_close (dds_entity *e) ddsrt_nonnull_all;
|
||||
static void dds_reader_close (dds_entity *e) ddsrt_nonnull_all;
|
||||
|
||||
static dds_return_t dds_reader_close (dds_entity *e)
|
||||
static void dds_reader_close (dds_entity *e)
|
||||
{
|
||||
dds_return_t ret = DDS_RETCODE_OK;
|
||||
struct dds_reader * const rd = (struct dds_reader *) e;
|
||||
assert (rd->m_rd != NULL);
|
||||
|
||||
thread_state_awake (lookup_thread_state (), &e->m_domain->gv);
|
||||
if (delete_reader (&e->m_domain->gv, &e->m_guid) != 0)
|
||||
ret = DDS_RETCODE_ERROR;
|
||||
(void) delete_reader (&e->m_domain->gv, &e->m_guid);
|
||||
thread_state_asleep (lookup_thread_state ());
|
||||
return ret;
|
||||
|
||||
ddsrt_mutex_lock (&e->m_mutex);
|
||||
while (rd->m_rd != NULL)
|
||||
ddsrt_cond_wait (&e->m_cond, &e->m_mutex);
|
||||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
}
|
||||
|
||||
static dds_return_t dds_reader_delete (dds_entity *e) ddsrt_nonnull_all;
|
||||
|
|
@ -57,17 +62,12 @@ static dds_return_t dds_reader_delete (dds_entity *e) ddsrt_nonnull_all;
|
|||
static dds_return_t dds_reader_delete (dds_entity *e)
|
||||
{
|
||||
dds_reader * const rd = (dds_reader *) e;
|
||||
dds_return_t ret;
|
||||
if ((ret = dds_delete (rd->m_topic->m_entity.m_hdllink.hdl)) == DDS_RETCODE_OK)
|
||||
{
|
||||
/* Delete an implicitly created parent; for normal ones, this is expected
|
||||
to fail with BAD_PARAMETER - FIXME: there must be a cleaner way */
|
||||
ret = dds_delete_impl (e->m_parent->m_hdllink.hdl, true);
|
||||
if (ret == DDS_RETCODE_BAD_PARAMETER)
|
||||
ret = DDS_RETCODE_OK;
|
||||
}
|
||||
(void) dds_delete (rd->m_topic->m_entity.m_hdllink.hdl);
|
||||
dds_free (rd->m_loan);
|
||||
return ret;
|
||||
thread_state_awake (lookup_thread_state (), &e->m_domain->gv);
|
||||
dds_rhc_free (rd->m_rhc);
|
||||
thread_state_asleep (lookup_thread_state ());
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
static dds_return_t dds_reader_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
|
||||
|
|
@ -97,11 +97,14 @@ void dds_reader_data_available_cb (struct dds_reader *rd)
|
|||
overhead really matters. Otherwise, it is pretty much like
|
||||
dds_reader_status_cb. */
|
||||
|
||||
const bool data_av_enabled = (ddsrt_atomic_ld32 (&rd->m_entity.m_status.m_status_and_mask) & (DDS_DATA_AVAILABLE_STATUS << SAM_ENABLED_SHIFT));
|
||||
if (!data_av_enabled)
|
||||
const uint32_t data_av_enabled = (ddsrt_atomic_ld32 (&rd->m_entity.m_status.m_status_and_mask) & (DDS_DATA_AVAILABLE_STATUS << SAM_ENABLED_SHIFT));
|
||||
if (data_av_enabled == 0)
|
||||
return;
|
||||
|
||||
ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
|
||||
rd->m_entity.m_cb_pending_count++;
|
||||
|
||||
/* FIXME: why wait if no listener is set? */
|
||||
while (rd->m_entity.m_cb_count > 0)
|
||||
ddsrt_cond_wait (&rd->m_entity.m_observers_cond, &rd->m_entity.m_observers_lock);
|
||||
rd->m_entity.m_cb_count++;
|
||||
|
|
@ -111,20 +114,25 @@ void dds_reader_data_available_cb (struct dds_reader *rd)
|
|||
if (lst->on_data_on_readers)
|
||||
{
|
||||
ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
|
||||
|
||||
ddsrt_mutex_lock (&sub->m_observers_lock);
|
||||
while (sub->m_cb_count > 0)
|
||||
ddsrt_cond_wait (&sub->m_observers_cond, &sub->m_observers_lock);
|
||||
sub->m_cb_count++;
|
||||
const uint32_t data_on_rds_enabled = (ddsrt_atomic_ld32 (&sub->m_status.m_status_and_mask) & (DDS_DATA_ON_READERS_STATUS << SAM_ENABLED_SHIFT));
|
||||
if (data_on_rds_enabled)
|
||||
{
|
||||
sub->m_cb_pending_count++;
|
||||
while (sub->m_cb_count > 0)
|
||||
ddsrt_cond_wait (&sub->m_observers_cond, &sub->m_observers_lock);
|
||||
sub->m_cb_count++;
|
||||
ddsrt_mutex_unlock (&sub->m_observers_lock);
|
||||
|
||||
lst->on_data_on_readers (sub->m_hdllink.hdl, lst->on_data_on_readers_arg);
|
||||
|
||||
ddsrt_mutex_lock (&sub->m_observers_lock);
|
||||
sub->m_cb_count--;
|
||||
sub->m_cb_pending_count--;
|
||||
ddsrt_cond_broadcast (&sub->m_observers_cond);
|
||||
}
|
||||
ddsrt_mutex_unlock (&sub->m_observers_lock);
|
||||
|
||||
lst->on_data_on_readers (sub->m_hdllink.hdl, lst->on_data_on_readers_arg);
|
||||
|
||||
ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
|
||||
ddsrt_mutex_lock (&sub->m_observers_lock);
|
||||
sub->m_cb_count--;
|
||||
ddsrt_cond_broadcast (&sub->m_observers_cond);
|
||||
ddsrt_mutex_unlock (&sub->m_observers_lock);
|
||||
}
|
||||
else if (rd->m_entity.m_listener.on_data_available)
|
||||
{
|
||||
|
|
@ -141,24 +149,28 @@ void dds_reader_data_available_cb (struct dds_reader *rd)
|
|||
}
|
||||
|
||||
rd->m_entity.m_cb_count--;
|
||||
rd->m_entity.m_cb_pending_count--;
|
||||
ddsrt_cond_broadcast (&rd->m_entity.m_observers_cond);
|
||||
ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
|
||||
}
|
||||
|
||||
void dds_reader_status_cb (void *ventity, const status_cb_data_t *data)
|
||||
{
|
||||
struct dds_entity * const entity = ventity;
|
||||
dds_reader * const rd = ventity;
|
||||
|
||||
/* When data is NULL, it means that the DDSI reader is deleted. */
|
||||
if (data == NULL)
|
||||
{
|
||||
/* Release the initial claim that was done during the create. This
|
||||
* will indicate that further API deletion is now possible. */
|
||||
dds_handle_unpin (&entity->m_hdllink);
|
||||
ddsrt_mutex_lock (&rd->m_entity.m_mutex);
|
||||
rd->m_rd = NULL;
|
||||
ddsrt_cond_broadcast (&rd->m_entity.m_cond);
|
||||
ddsrt_mutex_unlock (&rd->m_entity.m_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
struct dds_listener const * const lst = &entity->m_listener;
|
||||
struct dds_listener const * const lst = &rd->m_entity.m_listener;
|
||||
enum dds_status_id status_id = (enum dds_status_id) data->raw_status_id;
|
||||
bool invoke = false;
|
||||
void *vst = NULL;
|
||||
|
|
@ -175,13 +187,12 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data)
|
|||
m_observers_lock for the duration of the listener call itself,
|
||||
and that similarly the listener function and argument pointers
|
||||
are stable */
|
||||
ddsrt_mutex_lock (&entity->m_observers_lock);
|
||||
while (entity->m_cb_count > 0)
|
||||
ddsrt_cond_wait (&entity->m_observers_cond, &entity->m_observers_lock);
|
||||
entity->m_cb_count++;
|
||||
/* FIXME: why do this if no listener is set? */
|
||||
ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
|
||||
while (rd->m_entity.m_cb_count > 0)
|
||||
ddsrt_cond_wait (&rd->m_entity.m_observers_cond, &rd->m_entity.m_observers_lock);
|
||||
|
||||
/* Update status metrics. */
|
||||
dds_reader * const rd = (dds_reader *) entity;
|
||||
switch (status_id) {
|
||||
case DDS_REQUESTED_DEADLINE_MISSED_STATUS_ID: {
|
||||
struct dds_requested_deadline_missed_status * const st = vst = &rd->m_requested_deadline_missed_status;
|
||||
|
|
@ -265,36 +276,46 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data)
|
|||
assert (0);
|
||||
}
|
||||
|
||||
if (invoke)
|
||||
const uint32_t enabled = (ddsrt_atomic_ld32 (&rd->m_entity.m_status.m_status_and_mask) & ((1u << status_id) << SAM_ENABLED_SHIFT));
|
||||
if (!enabled)
|
||||
{
|
||||
ddsrt_mutex_unlock (&entity->m_observers_lock);
|
||||
dds_entity_invoke_listener (entity, status_id, vst);
|
||||
ddsrt_mutex_lock (&entity->m_observers_lock);
|
||||
/* Don't invoke listeners or set status flag if masked */
|
||||
}
|
||||
else if (invoke)
|
||||
{
|
||||
rd->m_entity.m_cb_pending_count++;
|
||||
rd->m_entity.m_cb_count++;
|
||||
ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
|
||||
dds_entity_invoke_listener (&rd->m_entity, status_id, vst);
|
||||
ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
|
||||
rd->m_entity.m_cb_count--;
|
||||
rd->m_entity.m_cb_pending_count--;
|
||||
*reset[0] = 0;
|
||||
if (reset[1])
|
||||
*reset[1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
dds_entity_status_set (entity, (status_mask_t) (1u << status_id));
|
||||
dds_entity_status_set (&rd->m_entity, (status_mask_t) (1u << status_id));
|
||||
}
|
||||
|
||||
entity->m_cb_count--;
|
||||
ddsrt_cond_broadcast (&entity->m_observers_cond);
|
||||
ddsrt_mutex_unlock (&entity->m_observers_lock);
|
||||
ddsrt_cond_broadcast (&rd->m_entity.m_observers_cond);
|
||||
ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
|
||||
}
|
||||
|
||||
const struct dds_entity_deriver dds_entity_deriver_reader = {
|
||||
.interrupt = dds_entity_deriver_dummy_interrupt,
|
||||
.close = dds_reader_close,
|
||||
.delete = dds_reader_delete,
|
||||
.set_qos = dds_reader_qos_set,
|
||||
.validate_status = dds_reader_status_validate
|
||||
};
|
||||
|
||||
dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_entity_t topic, const dds_qos_t *qos, const dds_listener_t *listener)
|
||||
static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscriber, dds_entity_t topic, const dds_qos_t *qos, const dds_listener_t *listener, struct dds_rhc *rhc)
|
||||
{
|
||||
dds_qos_t *rqos;
|
||||
dds_subscriber *sub = NULL;
|
||||
dds_participant *pp;
|
||||
dds_entity_t subscriber;
|
||||
dds_reader *rd;
|
||||
dds_topic *tp;
|
||||
|
|
@ -347,8 +368,12 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti
|
|||
goto err_tp_lock;
|
||||
}
|
||||
assert (tp->m_stopic);
|
||||
/* FIXME: domain check */
|
||||
assert (sub->m_entity.m_domain == tp->m_entity.m_domain);
|
||||
pp = dds_entity_participant (&sub->m_entity);
|
||||
if (pp != dds_entity_participant (&tp->m_entity))
|
||||
{
|
||||
reader = DDS_RETCODE_BAD_PARAMETER;
|
||||
goto err_pp_mismatch;
|
||||
}
|
||||
|
||||
/* Merge qos from topic and subscriber, dds_copy_qos only fails when it is passed a null
|
||||
argument, but that isn't the case here */
|
||||
|
|
@ -378,28 +403,29 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti
|
|||
goto err_bad_qos;
|
||||
}
|
||||
|
||||
/* Create reader and associated read cache */
|
||||
/* Create reader and associated read cache (if not provided by caller) */
|
||||
rd = dds_alloc (sizeof (*rd));
|
||||
reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, rqos, listener, DDS_READER_STATUS_MASK);
|
||||
rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED;
|
||||
rd->m_topic = tp;
|
||||
rd->m_rhc = dds_rhc_default_new (rd, tp->m_stopic);
|
||||
rd->m_rhc = rhc ? rhc : dds_rhc_default_new (rd, tp->m_stopic);
|
||||
if (dds_rhc_associate (rd->m_rhc, rd, tp->m_stopic, rd->m_entity.m_domain->gv.m_tkmap) < 0)
|
||||
{
|
||||
/* FIXME: see also create_querycond, need to be able to undo entity_init */
|
||||
abort ();
|
||||
}
|
||||
dds_entity_add_ref_locked (&tp->m_entity);
|
||||
|
||||
/* Extra claim of this reader to make sure that the delete waits until DDSI
|
||||
has deleted its reader as well. This can be known through the callback. */
|
||||
dds_handle_repin (&rd->m_entity.m_hdllink);
|
||||
|
||||
ddsrt_mutex_unlock (&tp->m_entity.m_mutex);
|
||||
ddsrt_mutex_unlock (&sub->m_entity.m_mutex);
|
||||
/* FIXME: listeners can come too soon ... should set mask based on listeners
|
||||
then atomically set the listeners, save the mask to a pending set and clear
|
||||
it; and then invoke those listeners that are in the pending set */
|
||||
dds_entity_init_complete (&rd->m_entity);
|
||||
|
||||
thread_state_awake (lookup_thread_state (), &sub->m_entity.m_domain->gv);
|
||||
ret = new_reader (&rd->m_rd, &rd->m_entity.m_domain->gv, &rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, rqos, &rd->m_rhc->common.rhc, dds_reader_status_cb, rd);
|
||||
ddsrt_mutex_lock (&sub->m_entity.m_mutex);
|
||||
ddsrt_mutex_lock (&tp->m_entity.m_mutex);
|
||||
ret = new_reader (&rd->m_rd, &rd->m_entity.m_domain->gv, &rd->m_entity.m_guid, NULL, &pp->m_entity.m_guid, tp->m_stopic, rqos, &rd->m_rhc->common.rhc, dds_reader_status_cb, rd);
|
||||
assert (ret == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */
|
||||
thread_state_asleep (lookup_thread_state ());
|
||||
|
||||
|
||||
rd->m_entity.m_iid = get_entity_instance_id (&rd->m_entity.m_domain->gv, &rd->m_entity.m_guid);
|
||||
dds_entity_register_child (&sub->m_entity, &rd->m_entity);
|
||||
|
||||
|
|
@ -414,6 +440,7 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti
|
|||
return reader;
|
||||
|
||||
err_bad_qos:
|
||||
err_pp_mismatch:
|
||||
dds_topic_unlock (tp);
|
||||
err_tp_lock:
|
||||
dds_subscriber_unlock (sub);
|
||||
|
|
@ -438,7 +465,7 @@ void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb
|
|||
|
||||
dds_reader *dds_rd = (dds_reader *) dds_entity;
|
||||
struct reader *rd = dds_rd->m_rd;
|
||||
nn_guid_t pwrguid;
|
||||
ddsi_guid_t pwrguid;
|
||||
struct proxy_writer *pwr;
|
||||
struct rd_pwr_match *m;
|
||||
memset (&pwrguid, 0, sizeof (pwrguid));
|
||||
|
|
@ -451,7 +478,7 @@ void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb
|
|||
/* have to be careful walking the tree -- pretty is different, but
|
||||
I want to check this before I write a lookup_succ function. */
|
||||
struct rd_pwr_match *m_next;
|
||||
nn_guid_t pwrguid_next;
|
||||
ddsi_guid_t pwrguid_next;
|
||||
pwrguid = m->pwr_guid;
|
||||
if ((m_next = ddsrt_avl_find_succ (&rd_writers_treedef, &rd->writers, m)) != NULL)
|
||||
pwrguid_next = m_next->pwr_guid;
|
||||
|
|
@ -475,6 +502,18 @@ void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb
|
|||
dds_entity_unpin (dds_entity);
|
||||
}
|
||||
|
||||
dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_entity_t topic, const dds_qos_t *qos, const dds_listener_t *listener)
|
||||
{
|
||||
return dds_create_reader_int (participant_or_subscriber, topic, qos, listener, NULL);
|
||||
}
|
||||
|
||||
dds_entity_t dds_create_reader_rhc (dds_entity_t participant_or_subscriber, dds_entity_t topic, const dds_qos_t *qos, const dds_listener_t *listener, struct dds_rhc *rhc)
|
||||
{
|
||||
if (rhc == NULL)
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
return dds_create_reader_int (participant_or_subscriber, topic, qos, listener, rhc);
|
||||
}
|
||||
|
||||
uint32_t dds_reader_lock_samples (dds_entity_t reader)
|
||||
{
|
||||
dds_reader *rd;
|
||||
|
|
|
|||
|
|
@ -11,17 +11,18 @@
|
|||
*/
|
||||
|
||||
#include "dds/dds.h"
|
||||
#include "dds/ddsi/q_rhc.h"
|
||||
#include "dds__rhc.h"
|
||||
#include "dds/ddsi/ddsi_rhc.h"
|
||||
#include "dds/ddsc/dds_rhc.h"
|
||||
|
||||
extern inline bool dds_rhc_store (struct dds_rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk);
|
||||
extern inline void dds_rhc_unregister_wr (struct dds_rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info);
|
||||
extern inline dds_return_t dds_rhc_associate (struct dds_rhc *rhc, struct dds_reader *reader, const struct ddsi_sertopic *topic, struct ddsi_tkmap *tkmap);
|
||||
extern inline bool dds_rhc_store (struct dds_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict pwr_info, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk);
|
||||
extern inline void dds_rhc_unregister_wr (struct dds_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict pwr_info);
|
||||
extern inline void dds_rhc_relinquish_ownership (struct dds_rhc * __restrict rhc, const uint64_t wr_iid);
|
||||
extern inline void dds_rhc_set_qos (struct dds_rhc *rhc, const struct dds_qos *qos);
|
||||
extern inline void dds_rhc_free (struct dds_rhc *rhc);
|
||||
extern inline int dds_rhc_read (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond);
|
||||
extern inline int dds_rhc_take (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond);
|
||||
extern inline int dds_rhc_read (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond);
|
||||
extern inline int dds_rhc_take (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond);
|
||||
extern inline int dds_rhc_takecdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle);
|
||||
extern inline bool dds_rhc_add_readcondition (struct dds_readcond *cond);
|
||||
extern inline void dds_rhc_remove_readcondition (struct dds_readcond *cond);
|
||||
extern inline bool dds_rhc_add_readcondition (struct dds_rhc *rhc, struct dds_readcond *cond);
|
||||
extern inline void dds_rhc_remove_readcondition (struct dds_rhc *rhc, struct dds_readcond *cond);
|
||||
extern inline uint32_t dds_rhc_lock_samples (struct dds_rhc *rhc);
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@
|
|||
|
||||
#include "dds__entity.h"
|
||||
#include "dds__reader.h"
|
||||
#include "dds__rhc.h"
|
||||
#include "dds/ddsc/dds_rhc.h"
|
||||
#include "dds__rhc_default.h"
|
||||
#include "dds/ddsi/ddsi_tkmap.h"
|
||||
#include "dds/ddsrt/hopscotch.h"
|
||||
#include "dds/ddsrt/avl.h"
|
||||
#include "dds/ddsi/q_rhc.h"
|
||||
#include "dds/ddsi/ddsi_rhc.h"
|
||||
#include "dds/ddsi/q_xqos.h"
|
||||
#include "dds/ddsi/q_unused.h"
|
||||
#include "dds/ddsi/q_config.h"
|
||||
|
|
@ -263,7 +263,7 @@ struct rhc_instance {
|
|||
uint32_t disposed_gen; /* bloody generation counters - worst invention of mankind */
|
||||
uint32_t no_writers_gen; /* __/ */
|
||||
int32_t strength; /* "current" ownership strength */
|
||||
nn_guid_t wr_guid; /* guid of last writer (if wr_iid != 0 then wr_guid is the corresponding guid, else undef) */
|
||||
ddsi_guid_t wr_guid; /* guid of last writer (if wr_iid != 0 then wr_guid is the corresponding guid, else undef) */
|
||||
nn_wctime_t tstamp; /* source time stamp of last update */
|
||||
struct rhc_instance *next; /* next non-empty instance in arbitrary ordering */
|
||||
struct rhc_instance *prev;
|
||||
|
|
@ -346,30 +346,30 @@ struct trigger_info_post {
|
|||
};
|
||||
|
||||
static void dds_rhc_default_free (struct dds_rhc_default *rhc);
|
||||
static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk);
|
||||
static void dds_rhc_default_unregister_wr (struct dds_rhc_default * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info);
|
||||
static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk);
|
||||
static void dds_rhc_default_unregister_wr (struct dds_rhc_default * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo);
|
||||
static void dds_rhc_default_relinquish_ownership (struct dds_rhc_default * __restrict rhc, const uint64_t wr_iid);
|
||||
static void dds_rhc_default_set_qos (struct dds_rhc_default *rhc, const struct dds_qos *qos);
|
||||
static int dds_rhc_default_read (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond);
|
||||
static int dds_rhc_default_take (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond);
|
||||
static int dds_rhc_default_takecdr (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle);
|
||||
static bool dds_rhc_default_add_readcondition (dds_readcond *cond);
|
||||
static void dds_rhc_default_remove_readcondition (dds_readcond *cond);
|
||||
static bool dds_rhc_default_add_readcondition (struct dds_rhc_default *rhc, dds_readcond *cond);
|
||||
static void dds_rhc_default_remove_readcondition (struct dds_rhc_default *rhc, dds_readcond *cond);
|
||||
static uint32_t dds_rhc_default_lock_samples (struct dds_rhc_default *rhc);
|
||||
|
||||
static void dds_rhc_default_free_wrap (struct rhc *rhc) {
|
||||
static void dds_rhc_default_free_wrap (struct ddsi_rhc *rhc) {
|
||||
dds_rhc_default_free ((struct dds_rhc_default *) rhc);
|
||||
}
|
||||
static bool dds_rhc_default_store_wrap (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk) {
|
||||
return dds_rhc_default_store ((struct dds_rhc_default *) rhc, pwr_info, sample, tk);
|
||||
static bool dds_rhc_default_store_wrap (struct ddsi_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk) {
|
||||
return dds_rhc_default_store ((struct dds_rhc_default *) rhc, wrinfo, sample, tk);
|
||||
}
|
||||
static void dds_rhc_default_unregister_wr_wrap (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info) {
|
||||
dds_rhc_default_unregister_wr ((struct dds_rhc_default *) rhc, pwr_info);
|
||||
static void dds_rhc_default_unregister_wr_wrap (struct ddsi_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo) {
|
||||
dds_rhc_default_unregister_wr ((struct dds_rhc_default *) rhc, wrinfo);
|
||||
}
|
||||
static void dds_rhc_default_relinquish_ownership_wrap (struct rhc * __restrict rhc, const uint64_t wr_iid) {
|
||||
static void dds_rhc_default_relinquish_ownership_wrap (struct ddsi_rhc * __restrict rhc, const uint64_t wr_iid) {
|
||||
dds_rhc_default_relinquish_ownership ((struct dds_rhc_default *) rhc, wr_iid);
|
||||
}
|
||||
static void dds_rhc_default_set_qos_wrap (struct rhc *rhc, const struct dds_qos *qos) {
|
||||
static void dds_rhc_default_set_qos_wrap (struct ddsi_rhc *rhc, const struct dds_qos *qos) {
|
||||
dds_rhc_default_set_qos ((struct dds_rhc_default *) rhc, qos);
|
||||
}
|
||||
static int dds_rhc_default_read_wrap (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) {
|
||||
|
|
@ -381,15 +381,21 @@ static int dds_rhc_default_take_wrap (struct dds_rhc *rhc, bool lock, void **val
|
|||
static int dds_rhc_default_takecdr_wrap (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) {
|
||||
return dds_rhc_default_takecdr ((struct dds_rhc_default *) rhc, lock, values, info_seq, max_samples, sample_states, view_states, instance_states, handle);
|
||||
}
|
||||
static bool dds_rhc_default_add_readcondition_wrap (dds_readcond *cond) {
|
||||
return dds_rhc_default_add_readcondition (cond);
|
||||
static bool dds_rhc_default_add_readcondition_wrap (struct dds_rhc *rhc, dds_readcond *cond) {
|
||||
return dds_rhc_default_add_readcondition ((struct dds_rhc_default *) rhc, cond);
|
||||
}
|
||||
static void dds_rhc_default_remove_readcondition_wrap (dds_readcond *cond) {
|
||||
dds_rhc_default_remove_readcondition (cond);
|
||||
static void dds_rhc_default_remove_readcondition_wrap (struct dds_rhc *rhc, dds_readcond *cond) {
|
||||
dds_rhc_default_remove_readcondition ((struct dds_rhc_default *) rhc, cond);
|
||||
}
|
||||
static uint32_t dds_rhc_default_lock_samples_wrap (struct dds_rhc *rhc) {
|
||||
return dds_rhc_default_lock_samples ((struct dds_rhc_default *) rhc);
|
||||
}
|
||||
static dds_return_t dds_rhc_default_associate (struct dds_rhc *rhc, dds_reader *reader, const struct ddsi_sertopic *topic, struct ddsi_tkmap *tkmap)
|
||||
{
|
||||
/* ignored out of laziness */
|
||||
(void) rhc; (void) reader; (void) topic; (void) tkmap;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
static const struct dds_rhc_ops dds_rhc_default_ops = {
|
||||
.rhc_ops = {
|
||||
|
|
@ -404,7 +410,8 @@ static const struct dds_rhc_ops dds_rhc_default_ops = {
|
|||
.takecdr = dds_rhc_default_takecdr_wrap,
|
||||
.add_readcondition = dds_rhc_default_add_readcondition_wrap,
|
||||
.remove_readcondition = dds_rhc_default_remove_readcondition_wrap,
|
||||
.lock_samples = dds_rhc_default_lock_samples_wrap
|
||||
.lock_samples = dds_rhc_default_lock_samples_wrap,
|
||||
.associate = dds_rhc_default_associate
|
||||
};
|
||||
|
||||
static unsigned qmask_of_sample (const struct rhc_sample *s)
|
||||
|
|
@ -758,7 +765,7 @@ static bool trigger_info_differs (const struct dds_rhc_default *rhc, const struc
|
|||
trig_qc->dec_sample_read != trig_qc->inc_sample_read);
|
||||
}
|
||||
|
||||
static bool add_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst, const struct proxy_writer_info *pwr_info, const struct ddsi_serdata *sample, status_cb_data_t *cb_data, struct trigger_info_qcond *trig_qc)
|
||||
static bool add_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst, const struct ddsi_writer_info *wrinfo, const struct ddsi_serdata *sample, status_cb_data_t *cb_data, struct trigger_info_qcond *trig_qc)
|
||||
{
|
||||
struct rhc_sample *s;
|
||||
|
||||
|
|
@ -832,7 +839,7 @@ static bool add_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst,
|
|||
}
|
||||
|
||||
s->sample = ddsi_serdata_ref (sample); /* drops const (tho refcount does change) */
|
||||
s->wr_iid = pwr_info->iid;
|
||||
s->wr_iid = wrinfo->iid;
|
||||
s->isread = false;
|
||||
s->disposed_gen = inst->disposed_gen;
|
||||
s->no_writers_gen = inst->no_writers_gen;
|
||||
|
|
@ -867,12 +874,12 @@ static bool content_filter_accepts (const dds_reader *reader, const struct ddsi_
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int inst_accepts_sample_by_writer_guid (const struct rhc_instance *inst, const struct proxy_writer_info *pwr_info)
|
||||
static int inst_accepts_sample_by_writer_guid (const struct rhc_instance *inst, const struct ddsi_writer_info *wrinfo)
|
||||
{
|
||||
return (inst->wr_iid_islive && inst->wr_iid == pwr_info->iid) || memcmp (&pwr_info->guid, &inst->wr_guid, sizeof (inst->wr_guid)) < 0;
|
||||
return (inst->wr_iid_islive && inst->wr_iid == wrinfo->iid) || memcmp (&wrinfo->guid, &inst->wr_guid, sizeof (inst->wr_guid)) < 0;
|
||||
}
|
||||
|
||||
static int inst_accepts_sample (const struct dds_rhc_default *rhc, const struct rhc_instance *inst, const struct proxy_writer_info *pwr_info, const struct ddsi_serdata *sample, const bool has_data)
|
||||
static int inst_accepts_sample (const struct dds_rhc_default *rhc, const struct rhc_instance *inst, const struct ddsi_writer_info *wrinfo, const struct ddsi_serdata *sample, const bool has_data)
|
||||
{
|
||||
if (rhc->by_source_ordering)
|
||||
{
|
||||
|
|
@ -884,7 +891,7 @@ static int inst_accepts_sample (const struct dds_rhc_default *rhc, const struct
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
else if (inst_accepts_sample_by_writer_guid (inst, pwr_info))
|
||||
else if (inst_accepts_sample_by_writer_guid (inst, wrinfo))
|
||||
{
|
||||
/* ok */
|
||||
}
|
||||
|
|
@ -893,14 +900,14 @@ static int inst_accepts_sample (const struct dds_rhc_default *rhc, const struct
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
if (rhc->exclusive_ownership && inst->wr_iid_islive && inst->wr_iid != pwr_info->iid)
|
||||
if (rhc->exclusive_ownership && inst->wr_iid_islive && inst->wr_iid != wrinfo->iid)
|
||||
{
|
||||
int32_t strength = pwr_info->ownership_strength;
|
||||
int32_t strength = wrinfo->ownership_strength;
|
||||
if (strength > inst->strength) {
|
||||
/* ok */
|
||||
} else if (strength < inst->strength) {
|
||||
return 0;
|
||||
} else if (inst_accepts_sample_by_writer_guid (inst, pwr_info)) {
|
||||
} else if (inst_accepts_sample_by_writer_guid (inst, wrinfo)) {
|
||||
/* ok */
|
||||
} else {
|
||||
return 0;
|
||||
|
|
@ -913,17 +920,17 @@ static int inst_accepts_sample (const struct dds_rhc_default *rhc, const struct
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void update_inst (struct rhc_instance *inst, const struct proxy_writer_info * __restrict pwr_info, bool wr_iid_valid, nn_wctime_t tstamp)
|
||||
static void update_inst (struct rhc_instance *inst, const struct ddsi_writer_info * __restrict wrinfo, bool wr_iid_valid, nn_wctime_t tstamp)
|
||||
{
|
||||
inst->tstamp = tstamp;
|
||||
inst->wr_iid_islive = wr_iid_valid;
|
||||
if (wr_iid_valid)
|
||||
{
|
||||
inst->wr_iid = pwr_info->iid;
|
||||
if (inst->wr_iid != pwr_info->iid)
|
||||
inst->wr_guid = pwr_info->guid;
|
||||
inst->wr_iid = wrinfo->iid;
|
||||
if (inst->wr_iid != wrinfo->iid)
|
||||
inst->wr_guid = wrinfo->guid;
|
||||
}
|
||||
inst->strength = pwr_info->ownership_strength;
|
||||
inst->strength = wrinfo->ownership_strength;
|
||||
}
|
||||
|
||||
static void drop_instance_noupdate_no_writers (struct dds_rhc_default *rhc, struct rhc_instance *inst)
|
||||
|
|
@ -1109,13 +1116,13 @@ static int rhc_unregister_isreg_w_sideeffects (struct dds_rhc_default *rhc, cons
|
|||
}
|
||||
}
|
||||
|
||||
static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_instance *inst, const struct proxy_writer_info * __restrict pwr_info, nn_wctime_t tstamp, struct trigger_info_qcond *trig_qc, bool *nda)
|
||||
static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_instance *inst, const struct ddsi_writer_info * __restrict wrinfo, nn_wctime_t tstamp, struct trigger_info_qcond *trig_qc, bool *nda)
|
||||
{
|
||||
assert (inst->wrcount > 0);
|
||||
|
||||
if (--inst->wrcount > 0)
|
||||
{
|
||||
if (inst->wr_iid_islive && pwr_info->iid == inst->wr_iid)
|
||||
if (inst->wr_iid_islive && wrinfo->iid == inst->wr_iid)
|
||||
{
|
||||
/* Next register will have to do real work before we have a cached
|
||||
wr_iid again */
|
||||
|
|
@ -1142,7 +1149,7 @@ static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_in
|
|||
if (inst->latest == NULL || inst->latest->isread)
|
||||
{
|
||||
inst_set_invsample (rhc, inst, trig_qc, nda);
|
||||
update_inst (inst, pwr_info, false, tstamp);
|
||||
update_inst (inst, wrinfo, false, tstamp);
|
||||
}
|
||||
if (!inst->isdisposed)
|
||||
{
|
||||
|
|
@ -1164,7 +1171,7 @@ static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_in
|
|||
TRACE (",#0,empty,nowriters");
|
||||
assert (inst_is_empty (inst));
|
||||
inst_set_invsample (rhc, inst, trig_qc, nda);
|
||||
update_inst (inst, pwr_info, false, tstamp);
|
||||
update_inst (inst, wrinfo, false, tstamp);
|
||||
account_for_empty_to_nonempty_transition (rhc, inst);
|
||||
inst->wr_iid_islive = 0;
|
||||
return 0;
|
||||
|
|
@ -1172,18 +1179,18 @@ static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_in
|
|||
}
|
||||
}
|
||||
|
||||
static bool dds_rhc_unregister (struct dds_rhc_default *rhc, struct rhc_instance *inst, const struct proxy_writer_info * __restrict pwr_info, nn_wctime_t tstamp, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc)
|
||||
static bool dds_rhc_unregister (struct dds_rhc_default *rhc, struct rhc_instance *inst, const struct ddsi_writer_info * __restrict wrinfo, nn_wctime_t tstamp, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc)
|
||||
{
|
||||
bool notify_data_available = false;
|
||||
|
||||
/* 'post' always gets set; instance may have been freed upon return. */
|
||||
TRACE (" unregister:");
|
||||
if (!rhc_unregister_isreg_w_sideeffects (rhc, inst, pwr_info->iid))
|
||||
if (!rhc_unregister_isreg_w_sideeffects (rhc, inst, wrinfo->iid))
|
||||
{
|
||||
/* other registrations remain */
|
||||
get_trigger_info_cmn (&post->c, inst);
|
||||
}
|
||||
else if (rhc_unregister_updateinst (rhc, inst, pwr_info, tstamp, trig_qc, ¬ify_data_available))
|
||||
else if (rhc_unregister_updateinst (rhc, inst, wrinfo, tstamp, trig_qc, ¬ify_data_available))
|
||||
{
|
||||
/* instance dropped */
|
||||
init_trigger_info_cmn_nonmatch (&post->c);
|
||||
|
|
@ -1196,7 +1203,7 @@ static bool dds_rhc_unregister (struct dds_rhc_default *rhc, struct rhc_instance
|
|||
return notify_data_available;
|
||||
}
|
||||
|
||||
static struct rhc_instance *alloc_new_instance (const struct dds_rhc_default *rhc, const struct proxy_writer_info *pwr_info, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk)
|
||||
static struct rhc_instance *alloc_new_instance (const struct dds_rhc_default *rhc, const struct ddsi_writer_info *wrinfo, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk)
|
||||
{
|
||||
struct rhc_instance *inst;
|
||||
|
||||
|
|
@ -1210,11 +1217,11 @@ static struct rhc_instance *alloc_new_instance (const struct dds_rhc_default *rh
|
|||
inst->isnew = 1;
|
||||
inst->a_sample_free = 1;
|
||||
inst->conds = 0;
|
||||
inst->wr_iid = pwr_info->iid;
|
||||
inst->wr_iid = wrinfo->iid;
|
||||
inst->wr_iid_islive = (inst->wrcount != 0);
|
||||
inst->wr_guid = pwr_info->guid;
|
||||
inst->wr_guid = wrinfo->guid;
|
||||
inst->tstamp = serdata->timestamp;
|
||||
inst->strength = pwr_info->ownership_strength;
|
||||
inst->strength = wrinfo->ownership_strength;
|
||||
|
||||
if (rhc->nqconds != 0)
|
||||
{
|
||||
|
|
@ -1230,7 +1237,7 @@ static struct rhc_instance *alloc_new_instance (const struct dds_rhc_default *rh
|
|||
return inst;
|
||||
}
|
||||
|
||||
static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst, struct dds_rhc_default *rhc, const struct proxy_writer_info *pwr_info, struct ddsi_serdata *sample, struct ddsi_tkmap_instance *tk, const bool has_data, status_cb_data_t *cb_data, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc)
|
||||
static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst, struct dds_rhc_default *rhc, const struct ddsi_writer_info *wrinfo, struct ddsi_serdata *sample, struct ddsi_tkmap_instance *tk, const bool has_data, status_cb_data_t *cb_data, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc)
|
||||
{
|
||||
struct rhc_instance *inst;
|
||||
int ret;
|
||||
|
|
@ -1265,10 +1272,10 @@ static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst
|
|||
return RHC_REJECTED;
|
||||
}
|
||||
|
||||
inst = alloc_new_instance (rhc, pwr_info, sample, tk);
|
||||
inst = alloc_new_instance (rhc, wrinfo, sample, tk);
|
||||
if (has_data)
|
||||
{
|
||||
if (!add_sample (rhc, inst, pwr_info, sample, cb_data, trig_qc))
|
||||
if (!add_sample (rhc, inst, wrinfo, sample, cb_data, trig_qc))
|
||||
{
|
||||
free_empty_instance (inst, rhc);
|
||||
return RHC_REJECTED;
|
||||
|
|
@ -1298,9 +1305,9 @@ static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst
|
|||
delivered (true unless a reliable sample rejected).
|
||||
*/
|
||||
|
||||
static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk)
|
||||
static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk)
|
||||
{
|
||||
const uint64_t wr_iid = pwr_info->iid;
|
||||
const uint64_t wr_iid = wrinfo->iid;
|
||||
const unsigned statusinfo = sample->statusinfo;
|
||||
const bool has_data = (sample->kind == SDK_DATA);
|
||||
const int is_dispose = (statusinfo & NN_STATUSINFO_DISPOSE) != 0;
|
||||
|
|
@ -1347,7 +1354,7 @@ static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, cons
|
|||
else
|
||||
{
|
||||
TRACE (" new instance");
|
||||
stored = rhc_store_new_instance (&inst, rhc, pwr_info, sample, tk, has_data, &cb_data, &post, &trig_qc);
|
||||
stored = rhc_store_new_instance (&inst, rhc, wrinfo, sample, tk, has_data, &cb_data, &post, &trig_qc);
|
||||
if (stored != RHC_STORED)
|
||||
{
|
||||
goto error_or_nochange;
|
||||
|
|
@ -1356,7 +1363,7 @@ static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, cons
|
|||
notify_data_available = true;
|
||||
}
|
||||
}
|
||||
else if (!inst_accepts_sample (rhc, inst, pwr_info, sample, has_data))
|
||||
else if (!inst_accepts_sample (rhc, inst, wrinfo, sample, has_data))
|
||||
{
|
||||
/* Rejected samples (and disposes) should still register the writer;
|
||||
unregister *must* be processed, or we have a memory leak. (We
|
||||
|
|
@ -1372,7 +1379,7 @@ static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, cons
|
|||
}
|
||||
if (statusinfo & NN_STATUSINFO_UNREGISTER)
|
||||
{
|
||||
if (dds_rhc_unregister (rhc, inst, pwr_info, sample->timestamp, &post, &trig_qc))
|
||||
if (dds_rhc_unregister (rhc, inst, wrinfo, sample->timestamp, &post, &trig_qc))
|
||||
notify_data_available = true;
|
||||
}
|
||||
else
|
||||
|
|
@ -1450,7 +1457,7 @@ static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, cons
|
|||
if (has_data)
|
||||
{
|
||||
TRACE (" add_sample");
|
||||
if (!add_sample (rhc, inst, pwr_info, sample, &cb_data, &trig_qc))
|
||||
if (!add_sample (rhc, inst, wrinfo, sample, &cb_data, &trig_qc))
|
||||
{
|
||||
TRACE ("(reject)");
|
||||
stored = RHC_REJECTED;
|
||||
|
|
@ -1469,7 +1476,7 @@ static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, cons
|
|||
if (inst_became_disposed && inst->latest == NULL)
|
||||
inst_set_invsample (rhc, inst, &trig_qc, ¬ify_data_available);
|
||||
|
||||
update_inst (inst, pwr_info, true, sample->timestamp);
|
||||
update_inst (inst, wrinfo, true, sample->timestamp);
|
||||
|
||||
/* Can only add samples => only need to give special treatment
|
||||
to instances that were empty before. It is, however, not
|
||||
|
|
@ -1513,7 +1520,7 @@ static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, cons
|
|||
mean an application reading "x" after the write and reading it
|
||||
again after the unregister will see a change in the
|
||||
no_writers_generation field? */
|
||||
dds_rhc_unregister (rhc, inst, pwr_info, sample->timestamp, &post, &trig_qc);
|
||||
dds_rhc_unregister (rhc, inst, wrinfo, sample->timestamp, &post, &trig_qc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1559,7 +1566,7 @@ error_or_nochange:
|
|||
return delivered;
|
||||
}
|
||||
|
||||
static void dds_rhc_default_unregister_wr (struct dds_rhc_default * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info)
|
||||
static void dds_rhc_default_unregister_wr (struct dds_rhc_default * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo)
|
||||
{
|
||||
/* Only to be called when writer with ID WR_IID has died.
|
||||
|
||||
|
|
@ -1579,8 +1586,8 @@ static void dds_rhc_default_unregister_wr (struct dds_rhc_default * __restrict r
|
|||
bool notify_data_available = false;
|
||||
struct rhc_instance *inst;
|
||||
struct ddsrt_hh_iter iter;
|
||||
const uint64_t wr_iid = pwr_info->iid;
|
||||
const int auto_dispose = pwr_info->auto_dispose;
|
||||
const uint64_t wr_iid = wrinfo->iid;
|
||||
const int auto_dispose = wrinfo->auto_dispose;
|
||||
|
||||
size_t ntriggers = SIZE_MAX;
|
||||
|
||||
|
|
@ -1620,7 +1627,7 @@ static void dds_rhc_default_unregister_wr (struct dds_rhc_default * __restrict r
|
|||
}
|
||||
}
|
||||
|
||||
dds_rhc_unregister (rhc, inst, pwr_info, inst->tstamp, &post, &trig_qc);
|
||||
dds_rhc_unregister (rhc, inst, wrinfo, inst->tstamp, &post, &trig_qc);
|
||||
|
||||
TRACE ("\n");
|
||||
|
||||
|
|
@ -2292,13 +2299,12 @@ static bool cond_is_sample_state_dependent (const struct dds_readcond *cond)
|
|||
}
|
||||
}
|
||||
|
||||
static bool dds_rhc_default_add_readcondition (dds_readcond *cond)
|
||||
static bool dds_rhc_default_add_readcondition (struct dds_rhc_default *rhc, dds_readcond *cond)
|
||||
{
|
||||
/* On the assumption that a readcondition will be attached to a
|
||||
waitset for nearly all of its life, we keep track of all
|
||||
readconditions on a reader in one set, without distinguishing
|
||||
between those attached to a waitset or not. */
|
||||
struct dds_rhc_default *rhc = (struct dds_rhc_default *) cond->m_rhc;
|
||||
struct ddsrt_hh_iter it;
|
||||
|
||||
assert ((dds_entity_kind (&cond->m_entity) == DDS_KIND_COND_READ && cond->m_query.m_filter == 0) ||
|
||||
|
|
@ -2397,9 +2403,8 @@ static bool dds_rhc_default_add_readcondition (dds_readcond *cond)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void dds_rhc_default_remove_readcondition (dds_readcond *cond)
|
||||
static void dds_rhc_default_remove_readcondition (struct dds_rhc_default *rhc, dds_readcond *cond)
|
||||
{
|
||||
struct dds_rhc_default *rhc = (struct dds_rhc_default *) cond->m_rhc;
|
||||
dds_readcond **ptr;
|
||||
ddsrt_mutex_lock (&rhc->lock);
|
||||
ptr = &rhc->conds;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ static const uint64_t unihashconsts[] = {
|
|||
UINT64_C (16728792139623414127)
|
||||
};
|
||||
|
||||
static uint32_t hash_guid (const nn_guid_t *g)
|
||||
static uint32_t hash_guid (const ddsi_guid_t *g)
|
||||
{
|
||||
return
|
||||
(uint32_t) (((((uint32_t) g->prefix.u[0] + unihashconsts[0]) *
|
||||
|
|
@ -131,7 +131,7 @@ static struct ddsi_serdata *ddsi_serdata_builtin_from_keyhash (const struct ddsi
|
|||
/* FIXME: not quite elegant to manage the creation of a serdata for a built-in topic via this function, but I also find it quite unelegant to let from_sample read straight from the underlying internal entity, and to_sample convert to the external format ... I could claim the internal entity is the "serialised form", but that forces wrapping it in a fragchain in one way or another, which, though possible, is also a bit lacking in elegance. */
|
||||
const struct ddsi_sertopic_builtintopic *tp = (const struct ddsi_sertopic_builtintopic *)tpcmn;
|
||||
/* keyhash must in host format (which the GUIDs always are internally) */
|
||||
struct entity_common *entity = ephash_lookup_guid_untyped (tp->gv->guid_hash, (const nn_guid_t *) keyhash->value);
|
||||
struct entity_common *entity = ephash_lookup_guid_untyped (tp->gv->guid_hash, (const ddsi_guid_t *) keyhash->value);
|
||||
struct ddsi_serdata_builtintopic *d = serdata_builtin_new(tp, entity ? SDK_DATA : SDK_KEY);
|
||||
memcpy (&d->key, keyhash->value, sizeof (d->key));
|
||||
if (entity)
|
||||
|
|
@ -175,9 +175,9 @@ static struct ddsi_serdata *serdata_builtin_to_topicless (const struct ddsi_serd
|
|||
return ddsi_serdata_ref (serdata_common);
|
||||
}
|
||||
|
||||
static void convkey (dds_builtintopic_guid_t *key, const nn_guid_t *guid)
|
||||
static void convkey (dds_builtintopic_guid_t *key, const ddsi_guid_t *guid)
|
||||
{
|
||||
nn_guid_t tmp;
|
||||
ddsi_guid_t tmp;
|
||||
tmp = nn_hton_guid (*guid);
|
||||
memcpy (key, &tmp, sizeof (*key));
|
||||
}
|
||||
|
|
@ -214,7 +214,7 @@ static bool to_sample_pp (const struct ddsi_serdata_builtintopic *d, struct dds_
|
|||
|
||||
static bool to_sample_endpoint (const struct ddsi_serdata_builtintopic *d, struct dds_builtintopic_endpoint *sample)
|
||||
{
|
||||
nn_guid_t ppguid;
|
||||
ddsi_guid_t ppguid;
|
||||
convkey (&sample->key, &d->key);
|
||||
ppguid = d->key;
|
||||
ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
|
||||
|
|
@ -276,6 +276,12 @@ static void serdata_builtin_to_ser_unref (struct ddsi_serdata *serdata_common, c
|
|||
(void)serdata_common; (void)ref;
|
||||
}
|
||||
|
||||
static size_t serdata_builtin_topic_print (const struct ddsi_sertopic *topic, const struct ddsi_serdata *serdata_common, char *buf, size_t size)
|
||||
{
|
||||
(void)topic; (void)serdata_common;
|
||||
return (size_t) snprintf (buf, size, "(blob)");
|
||||
}
|
||||
|
||||
const struct ddsi_serdata_ops ddsi_serdata_ops_builtintopic = {
|
||||
.get_size = serdata_builtin_get_size,
|
||||
.eqkey = serdata_builtin_eqkey,
|
||||
|
|
@ -288,5 +294,6 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_builtintopic = {
|
|||
.to_ser_ref = serdata_builtin_to_ser_ref,
|
||||
.to_ser_unref = serdata_builtin_to_ser_unref,
|
||||
.to_topicless = serdata_builtin_to_topicless,
|
||||
.topicless_to_sample = serdata_builtin_topicless_to_sample
|
||||
.topicless_to_sample = serdata_builtin_topicless_to_sample,
|
||||
.print = serdata_builtin_topic_print
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "dds/ddsrt/endian.h"
|
||||
#include "dds/ddsrt/md5.h"
|
||||
|
|
@ -1608,6 +1609,292 @@ void dds_stream_extract_keyhash (dds_istream_t * __restrict is, dds_keyhash_t *
|
|||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************************
|
||||
**
|
||||
** Pretty-printing
|
||||
**
|
||||
*******************************************************************************************/
|
||||
|
||||
/* Returns true if buffer not yet exhausted, false otherwise */
|
||||
static bool prtf (char * __restrict *buf, size_t * __restrict bufsize, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
if (*bufsize == 0)
|
||||
return false;
|
||||
va_start (ap, fmt);
|
||||
int n = vsnprintf (*buf, *bufsize, fmt, ap);
|
||||
va_end (ap);
|
||||
if (n < 0)
|
||||
{
|
||||
**buf = 0;
|
||||
return false;
|
||||
}
|
||||
else if ((size_t) n <= *bufsize)
|
||||
{
|
||||
*buf += (size_t) n;
|
||||
*bufsize -= (size_t) n;
|
||||
return (*bufsize > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
*buf += *bufsize;
|
||||
*bufsize = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool prtf_str (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is)
|
||||
{
|
||||
size_t sz = dds_is_get4 (is);
|
||||
bool ret = prtf (buf, bufsize, "\"%s\"", is->m_buffer + is->m_index);
|
||||
is->m_index += (uint32_t) sz;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t isprint_runlen (const unsigned char *s, size_t n)
|
||||
{
|
||||
size_t m;
|
||||
for (m = 0; m < n && s[m] != '"' && isprint (s[m]); m++)
|
||||
;
|
||||
return m;
|
||||
}
|
||||
|
||||
static bool prtf_simple (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is, enum dds_stream_typecode type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DDS_OP_VAL_1BY: return prtf (buf, bufsize, "%"PRIu8, dds_is_get1 (is));
|
||||
case DDS_OP_VAL_2BY: return prtf (buf, bufsize, "%"PRIu16, dds_is_get2 (is));
|
||||
case DDS_OP_VAL_4BY: return prtf (buf, bufsize, "%"PRIu32, dds_is_get4 (is));
|
||||
case DDS_OP_VAL_8BY: return prtf (buf, bufsize, "%"PRIu64, dds_is_get8 (is));
|
||||
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: return prtf_str (buf, bufsize, is);
|
||||
case DDS_OP_VAL_ARR: case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU:
|
||||
abort ();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool prtf_simple_array (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is, uint32_t num, enum dds_stream_typecode type)
|
||||
{
|
||||
bool cont = prtf (buf, bufsize, "{");
|
||||
switch (type)
|
||||
{
|
||||
case DDS_OP_VAL_1BY: {
|
||||
size_t i = 0, j;
|
||||
while (cont && i < num)
|
||||
{
|
||||
size_t m = isprint_runlen ((unsigned char *) (is->m_buffer + is->m_index), num - i);
|
||||
if (m >= 4)
|
||||
{
|
||||
cont = prtf (buf, bufsize, "%s\"", i != 0 ? "," : "");
|
||||
for (j = 0; cont && j < m; j++)
|
||||
cont = prtf (buf, bufsize, "%c", is->m_buffer[is->m_index + j]);
|
||||
cont = prtf (buf, bufsize, "\"");
|
||||
is->m_index += (uint32_t) m;
|
||||
i += m;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i != 0)
|
||||
(void) prtf (buf, bufsize, ",");
|
||||
cont = prtf_simple (buf, bufsize, is, type);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
||||
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST:
|
||||
for (size_t i = 0; cont && i < num; i++)
|
||||
{
|
||||
if (i != 0)
|
||||
(void) prtf (buf, bufsize, ",");
|
||||
cont = prtf_simple (buf, bufsize, is, type);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
break;
|
||||
}
|
||||
return cont;
|
||||
}
|
||||
|
||||
static bool dds_stream_print_sample1 (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is, const uint32_t * __restrict ops, bool add_braces);
|
||||
|
||||
static const uint32_t *prtf_seq (char * __restrict *buf, size_t *bufsize, dds_istream_t * __restrict is, const uint32_t * __restrict ops, uint32_t insn)
|
||||
{
|
||||
const enum dds_stream_typecode subtype = DDS_OP_SUBTYPE (insn);
|
||||
uint32_t num;
|
||||
num = dds_is_get4 (is);
|
||||
if (num == 0)
|
||||
{
|
||||
prtf (buf, bufsize, "{}");
|
||||
return skip_sequence_insns (ops, insn);
|
||||
}
|
||||
switch (subtype)
|
||||
{
|
||||
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
||||
prtf_simple_array (buf, bufsize, is, num, subtype);
|
||||
return ops + 2;
|
||||
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST:
|
||||
prtf_simple_array (buf, bufsize, is, num, subtype);
|
||||
return ops + (subtype == DDS_OP_VAL_STR ? 2 : 3);
|
||||
case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: {
|
||||
const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]);
|
||||
uint32_t const * const jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]);
|
||||
bool cont = prtf (buf, bufsize, "{");
|
||||
for (uint32_t i = 0; cont && i < num; i++)
|
||||
{
|
||||
if (i > 0) prtf (buf, bufsize, ",");
|
||||
cont = dds_stream_print_sample1 (buf, bufsize, is, jsr_ops, subtype == DDS_OP_VAL_STU);
|
||||
}
|
||||
prtf (buf, bufsize, "}");
|
||||
return ops + (jmp ? jmp : 4); /* FIXME: why would jmp be 0? */
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const uint32_t *prtf_arr (char * __restrict *buf, size_t *bufsize, dds_istream_t * __restrict is, const uint32_t * __restrict ops, uint32_t insn)
|
||||
{
|
||||
const enum dds_stream_typecode subtype = DDS_OP_SUBTYPE (insn);
|
||||
const uint32_t num = ops[2];
|
||||
switch (subtype)
|
||||
{
|
||||
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
||||
prtf_simple_array (buf, bufsize, is, num, subtype);
|
||||
return ops + 3;
|
||||
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST:
|
||||
prtf_simple_array (buf, bufsize, is, num, subtype);
|
||||
return ops + (subtype == DDS_OP_VAL_STR ? 3 : 5);
|
||||
case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: {
|
||||
const uint32_t *jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]);
|
||||
const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]);
|
||||
bool cont = prtf (buf, bufsize, "{");
|
||||
for (uint32_t i = 0; cont && i < num; i++)
|
||||
{
|
||||
if (i > 0) prtf (buf, bufsize, ",");
|
||||
cont = dds_stream_print_sample1 (buf, bufsize, is, jsr_ops, subtype == DDS_OP_VAL_STU);
|
||||
}
|
||||
prtf (buf, bufsize, "}");
|
||||
return ops + (jmp ? jmp : 5);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const uint32_t *prtf_uni (char * __restrict *buf, size_t *bufsize, dds_istream_t * __restrict is, const uint32_t * __restrict ops, uint32_t insn)
|
||||
{
|
||||
const uint32_t disc = read_union_discriminant (is, DDS_OP_SUBTYPE (insn));
|
||||
uint32_t const * const jeq_op = find_union_case (ops, disc);
|
||||
prtf (buf, bufsize, "%"PRIu32":", disc);
|
||||
ops += DDS_OP_ADR_JMP (ops[3]);
|
||||
if (jeq_op)
|
||||
{
|
||||
const enum dds_stream_typecode valtype = DDS_JEQ_TYPE (jeq_op[0]);
|
||||
switch (valtype)
|
||||
{
|
||||
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
||||
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST:
|
||||
prtf_simple (buf, bufsize, is, valtype);
|
||||
break;
|
||||
case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU:
|
||||
dds_stream_print_sample1 (buf, bufsize, is, jeq_op + DDS_OP_ADR_JSR (jeq_op[0]), valtype == DDS_OP_VAL_STU);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
static bool dds_stream_print_sample1 (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is, const uint32_t * __restrict ops, bool add_braces)
|
||||
{
|
||||
uint32_t insn;
|
||||
bool cont = true;
|
||||
bool needs_comma = false;
|
||||
if (add_braces)
|
||||
prtf (buf, bufsize, "{");
|
||||
while (cont && (insn = *ops) != DDS_OP_RTS)
|
||||
{
|
||||
if (needs_comma)
|
||||
prtf (buf, bufsize, ",");
|
||||
needs_comma = true;
|
||||
switch (DDS_OP (insn))
|
||||
{
|
||||
case DDS_OP_ADR: {
|
||||
switch (DDS_OP_TYPE (insn))
|
||||
{
|
||||
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
||||
case DDS_OP_VAL_STR:
|
||||
cont = prtf_simple (buf, bufsize, is, DDS_OP_TYPE (insn));
|
||||
ops += 2;
|
||||
break;
|
||||
case DDS_OP_VAL_BST:
|
||||
cont = prtf_simple (buf, bufsize, is, DDS_OP_TYPE (insn));
|
||||
ops += 3;
|
||||
break;
|
||||
case DDS_OP_VAL_SEQ:
|
||||
ops = prtf_seq (buf, bufsize, is, ops, insn);
|
||||
break;
|
||||
case DDS_OP_VAL_ARR:
|
||||
ops = prtf_arr (buf, bufsize, is, ops, insn);
|
||||
break;
|
||||
case DDS_OP_VAL_UNI:
|
||||
ops = prtf_uni (buf, bufsize, is, ops, insn);
|
||||
break;
|
||||
case DDS_OP_VAL_STU:
|
||||
abort ();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DDS_OP_JSR: {
|
||||
cont = dds_stream_print_sample1 (buf, bufsize, is, ops + DDS_OP_JUMP (insn), true);
|
||||
ops++;
|
||||
break;
|
||||
}
|
||||
case DDS_OP_RTS: case DDS_OP_JEQ: {
|
||||
abort ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (add_braces)
|
||||
prtf (buf, bufsize, "}");
|
||||
return cont;
|
||||
}
|
||||
|
||||
size_t dds_stream_print_sample (dds_istream_t * __restrict is, const struct ddsi_sertopic_default * __restrict topic, char * __restrict buf, size_t bufsize)
|
||||
{
|
||||
dds_stream_print_sample1 (&buf, &bufsize, is, topic->type->m_ops, true);
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
size_t dds_stream_print_key (dds_istream_t * __restrict is, const struct ddsi_sertopic_default * __restrict topic, char * __restrict buf, size_t bufsize)
|
||||
{
|
||||
const dds_topic_descriptor_t *desc = topic->type;
|
||||
bool cont = prtf (&buf, &bufsize, ":k:{");
|
||||
for (uint32_t i = 0; cont && i < desc->m_nkeys; i++)
|
||||
{
|
||||
const uint32_t *op = desc->m_ops + desc->m_keys[i].m_index;
|
||||
assert (insn_key_ok_p (*op));
|
||||
switch (DDS_OP_TYPE (*op))
|
||||
{
|
||||
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
||||
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST:
|
||||
cont = prtf_simple (&buf, &bufsize, is, DDS_OP_TYPE (*op));
|
||||
break;
|
||||
case DDS_OP_VAL_ARR:
|
||||
cont = prtf_simple_array (&buf, &bufsize, is, op[2], DDS_OP_SUBTYPE (*op));
|
||||
break;
|
||||
case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU:
|
||||
abort ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
prtf (&buf, &bufsize, "}");
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
/*******************************************************************************************
|
||||
**
|
||||
** Stuff to make it possible to treat a ddsi_serdata_default as a stream
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ static dds_return_t dds_subscriber_status_validate (uint32_t mask)
|
|||
}
|
||||
|
||||
const struct dds_entity_deriver dds_entity_deriver_subscriber = {
|
||||
.interrupt = dds_entity_deriver_dummy_interrupt,
|
||||
.close = dds_entity_deriver_dummy_close,
|
||||
.delete = dds_entity_deriver_dummy_delete,
|
||||
.set_qos = dds_subscriber_qos_set,
|
||||
|
|
@ -66,6 +67,7 @@ dds_entity_t dds__create_subscriber_l (dds_participant *participant, const dds_q
|
|||
subscriber = dds_entity_init (&sub->m_entity, &participant->m_entity, DDS_KIND_SUBSCRIBER, new_qos, listener, DDS_SUBSCRIBER_STATUS_MASK);
|
||||
sub->m_entity.m_iid = ddsi_iid_gen ();
|
||||
dds_entity_register_child (&participant->m_entity, &sub->m_entity);
|
||||
dds_entity_init_complete (&sub->m_entity);
|
||||
return subscriber;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ static bool dds_find_topic_check_and_add_ref (dds_entity_t participant, dds_enti
|
|||
return false;
|
||||
|
||||
bool ret;
|
||||
if (tp->m_entity.m_participant->m_hdllink.hdl != participant || strcmp (tp->m_stopic->name, name) != 0)
|
||||
if (dds_entity_participant (&tp->m_entity)->m_entity.m_hdllink.hdl != participant || strcmp (tp->m_stopic->name, name) != 0)
|
||||
ret = false;
|
||||
else
|
||||
{
|
||||
|
|
@ -243,7 +243,7 @@ static bool sertopic_equivalent (const struct ddsi_sertopic *a, const struct dds
|
|||
return true;
|
||||
}
|
||||
|
||||
static dds_return_t create_topic_topic_arbirary_check_sertopic (dds_entity_t participant, dds_entity_t topic, struct ddsi_sertopic *sertopic, const dds_qos_t *qos)
|
||||
static dds_return_t create_topic_topic_arbitrary_check_sertopic (dds_entity_t participant, dds_entity_t topic, struct ddsi_sertopic *sertopic, const dds_qos_t *qos)
|
||||
{
|
||||
dds_topic *tp;
|
||||
dds_return_t ret;
|
||||
|
|
@ -251,7 +251,7 @@ static dds_return_t create_topic_topic_arbirary_check_sertopic (dds_entity_t par
|
|||
if (dds_topic_lock (topic, &tp) < 0)
|
||||
return DDS_RETCODE_NOT_FOUND;
|
||||
|
||||
if (tp->m_entity.m_participant->m_hdllink.hdl != participant)
|
||||
if (dds_entity_participant (&tp->m_entity)->m_entity.m_hdllink.hdl != participant)
|
||||
ret = DDS_RETCODE_NOT_FOUND;
|
||||
else if (!sertopic_equivalent (tp->m_stopic, sertopic))
|
||||
ret = DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
|
|
@ -272,6 +272,7 @@ static dds_return_t create_topic_topic_arbirary_check_sertopic (dds_entity_t par
|
|||
}
|
||||
|
||||
const struct dds_entity_deriver dds_entity_deriver_topic = {
|
||||
.interrupt = dds_entity_deriver_dummy_interrupt,
|
||||
.close = dds_entity_deriver_dummy_close,
|
||||
.delete = dds_topic_delete,
|
||||
.set_qos = dds_topic_qos_set,
|
||||
|
|
@ -296,6 +297,14 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s
|
|||
existing topic's compatibility */
|
||||
if ((rc = dds_entity_pin (participant, &par_ent)) < 0)
|
||||
return rc;
|
||||
/* Verify that we've been given a participant, not strictly necessary
|
||||
because dds_participant_lock below checks it, but this is more
|
||||
obvious */
|
||||
if (dds_entity_kind (par_ent) != DDS_KIND_PARTICIPANT)
|
||||
{
|
||||
dds_entity_unpin (par_ent);
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
}
|
||||
|
||||
new_qos = dds_create_qos ();
|
||||
if (qos)
|
||||
|
|
@ -351,7 +360,7 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s
|
|||
for the various scary cases. */
|
||||
dds_participant_unlock (par);
|
||||
|
||||
rc = create_topic_topic_arbirary_check_sertopic (participant, topic, sertopic, new_qos);
|
||||
rc = create_topic_topic_arbitrary_check_sertopic (participant, topic, sertopic, new_qos);
|
||||
switch (rc)
|
||||
{
|
||||
case DDS_RETCODE_OK: /* duplicate definition */
|
||||
|
|
@ -439,6 +448,8 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s
|
|||
nn_plist_fini (&plist);
|
||||
}
|
||||
thread_state_asleep (lookup_thread_state ());
|
||||
|
||||
dds_entity_init_complete (&top->m_entity);
|
||||
dds_participant_unlock (par);
|
||||
dds_entity_unpin (par_ent);
|
||||
return hdl;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
* Copyright(c) 2006 to 2019 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
|
|
@ -17,11 +17,10 @@
|
|||
#include "dds__participant.h"
|
||||
#include "dds__querycond.h"
|
||||
#include "dds__readcond.h"
|
||||
#include "dds__rhc.h"
|
||||
#include "dds__init.h"
|
||||
#include "dds/ddsc/dds_rhc.h"
|
||||
#include "dds/ddsi/ddsi_iid.h"
|
||||
|
||||
DEFINE_ENTITY_LOCK_UNLOCK (static, dds_waitset, DDS_KIND_WAITSET)
|
||||
|
||||
static bool is_triggered (struct dds_entity *e)
|
||||
{
|
||||
bool t;
|
||||
|
|
@ -63,7 +62,7 @@ static dds_return_t dds_waitset_wait_impl (dds_entity_t waitset, dds_attach_t *x
|
|||
}
|
||||
|
||||
/* Move any previously but no longer triggering entities back to the observed list */
|
||||
ddsrt_mutex_lock (&ws->m_entity.m_mutex);
|
||||
ddsrt_mutex_lock (&ws->wait_lock);
|
||||
ws->ntriggered = 0;
|
||||
for (size_t i = 0; i < ws->nentities; i++)
|
||||
{
|
||||
|
|
@ -76,83 +75,195 @@ static dds_return_t dds_waitset_wait_impl (dds_entity_t waitset, dds_attach_t *x
|
|||
}
|
||||
|
||||
/* Only wait/keep waiting when we have something to observe and there aren't any triggers yet. */
|
||||
while (ws->nentities > 0 && ws->ntriggered == 0)
|
||||
if (!ddsrt_cond_waituntil (&ws->m_entity.m_cond, &ws->m_entity.m_mutex, abstimeout))
|
||||
while (ws->nentities > 0 && ws->ntriggered == 0 && !dds_handle_is_closed (&ws->m_entity.m_hdllink))
|
||||
if (!ddsrt_cond_waituntil (&ws->wait_cond, &ws->wait_lock, abstimeout))
|
||||
break;
|
||||
|
||||
ret = (int32_t) ws->ntriggered;
|
||||
for (size_t i = 0; i < ws->ntriggered && i < nxs; i++)
|
||||
xs[i] = ws->entities[i].arg;
|
||||
ddsrt_mutex_unlock (&ws->m_entity.m_mutex);
|
||||
ddsrt_mutex_unlock (&ws->wait_lock);
|
||||
dds_entity_unpin (&ws->m_entity);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static dds_return_t dds_waitset_close (struct dds_entity *e)
|
||||
static void dds_waitset_interrupt (struct dds_entity *e)
|
||||
{
|
||||
/* deep in the process of deleting the entity, so this is the only thread */
|
||||
dds_waitset *ws = (dds_waitset *) e;
|
||||
for (size_t i = 0; i < ws->nentities; i++)
|
||||
(void) dds_entity_observer_unregister (ws->entities[i].entity, &ws->m_entity);
|
||||
return DDS_RETCODE_OK;
|
||||
ddsrt_mutex_lock (&ws->wait_lock);
|
||||
assert (dds_handle_is_closed (&ws->m_entity.m_hdllink));
|
||||
ddsrt_cond_broadcast (&ws->wait_cond);
|
||||
ddsrt_mutex_unlock (&ws->wait_lock);
|
||||
}
|
||||
|
||||
static void dds_waitset_close (struct dds_entity *e)
|
||||
{
|
||||
dds_waitset *ws = (dds_waitset *) e;
|
||||
ddsrt_mutex_lock (&ws->wait_lock);
|
||||
while (ws->nentities > 0)
|
||||
{
|
||||
dds_entity *observed;
|
||||
if (dds_entity_pin (ws->entities[0].handle, &observed) < 0)
|
||||
{
|
||||
/* can't be pinned => being deleted => will be removed from wait set soon enough
|
||||
and go through delete_observer (which will trigger the condition variable) */
|
||||
ddsrt_cond_wait (&ws->wait_cond, &ws->wait_lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* entity will remain in existence */
|
||||
ddsrt_mutex_unlock (&ws->wait_lock);
|
||||
(void) dds_entity_observer_unregister (observed, ws, true);
|
||||
ddsrt_mutex_lock (&ws->wait_lock);
|
||||
assert (ws->nentities == 0 || ws->entities[0].entity != observed);
|
||||
dds_entity_unpin (observed);
|
||||
}
|
||||
}
|
||||
ddsrt_mutex_unlock (&ws->wait_lock);
|
||||
}
|
||||
|
||||
static dds_return_t dds_waitset_delete (struct dds_entity *e)
|
||||
{
|
||||
/* deep in the process of deleting the entity, so this is the only thread */
|
||||
dds_waitset *ws = (dds_waitset *) e;
|
||||
ddsrt_mutex_destroy (&ws->wait_lock);
|
||||
ddsrt_cond_destroy (&ws->wait_cond);
|
||||
ddsrt_free (ws->entities);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
const struct dds_entity_deriver dds_entity_deriver_waitset = {
|
||||
.interrupt = dds_waitset_interrupt,
|
||||
.close = dds_waitset_close,
|
||||
.delete = dds_waitset_delete,
|
||||
.set_qos = dds_entity_deriver_dummy_set_qos,
|
||||
.validate_status = dds_entity_deriver_dummy_validate_status
|
||||
};
|
||||
|
||||
dds_entity_t dds_create_waitset (dds_entity_t participant)
|
||||
dds_entity_t dds_create_waitset (dds_entity_t owner)
|
||||
{
|
||||
dds_entity_t hdl;
|
||||
dds_participant *par;
|
||||
dds_entity *e;
|
||||
dds_return_t rc;
|
||||
|
||||
if ((rc = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK)
|
||||
/* If the owner is any ordinary (allowed) entity, the library is already initialised and calling
|
||||
init here is cheap. If it is DDS_CYCLONEDDS_HANDLE, we may have to initialise the library, so
|
||||
have to call it. If it is some bogus value and the library is not initialised yet ... so be
|
||||
it. Naturally, this requires us to call delete on DDS_CYCLONEDDS_HANDLE afterward. */
|
||||
if ((rc = dds_init ()) < 0)
|
||||
return rc;
|
||||
|
||||
if ((rc = dds_entity_lock (owner, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK)
|
||||
goto err_entity_lock;
|
||||
|
||||
switch (dds_entity_kind (e))
|
||||
{
|
||||
case DDS_KIND_CYCLONEDDS:
|
||||
case DDS_KIND_DOMAIN:
|
||||
case DDS_KIND_PARTICIPANT:
|
||||
break;
|
||||
default:
|
||||
rc = DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
goto err_entity_kind;
|
||||
}
|
||||
|
||||
dds_waitset *waitset = dds_alloc (sizeof (*waitset));
|
||||
hdl = dds_entity_init (&waitset->m_entity, &par->m_entity, DDS_KIND_WAITSET, NULL, NULL, 0);
|
||||
dds_entity_t hdl = dds_entity_init (&waitset->m_entity, e, DDS_KIND_WAITSET, NULL, NULL, 0);
|
||||
ddsrt_mutex_init (&waitset->wait_lock);
|
||||
ddsrt_cond_init (&waitset->wait_cond);
|
||||
waitset->m_entity.m_iid = ddsi_iid_gen ();
|
||||
dds_entity_register_child (&par->m_entity, &waitset->m_entity);
|
||||
dds_entity_register_child (e, &waitset->m_entity);
|
||||
waitset->nentities = 0;
|
||||
waitset->ntriggered = 0;
|
||||
waitset->entities = NULL;
|
||||
dds_participant_unlock (par);
|
||||
dds_entity_init_complete (&waitset->m_entity);
|
||||
dds_entity_unlock (e);
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
return hdl;
|
||||
|
||||
err_entity_kind:
|
||||
dds_entity_unlock (e);
|
||||
err_entity_lock:
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
return rc;
|
||||
}
|
||||
|
||||
dds_return_t dds_waitset_get_entities (dds_entity_t waitset, dds_entity_t *entities, size_t size)
|
||||
{
|
||||
dds_return_t ret;
|
||||
dds_waitset *ws;
|
||||
|
||||
if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK)
|
||||
dds_entity *wsent;
|
||||
if ((ret = dds_entity_pin (waitset, &wsent)) < 0)
|
||||
return ret;
|
||||
|
||||
if (entities != NULL)
|
||||
else if (dds_entity_kind (wsent) != DDS_KIND_WAITSET)
|
||||
{
|
||||
for (size_t i = 0; i < ws->nentities && i < size; i++)
|
||||
entities[i] = ws->entities[i].handle;
|
||||
dds_entity_unpin (wsent);
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
dds_waitset *ws = (dds_waitset *) wsent;
|
||||
ddsrt_mutex_lock (&ws->wait_lock);
|
||||
if (entities != NULL)
|
||||
{
|
||||
for (size_t i = 0; i < ws->nentities && i < size; i++)
|
||||
entities[i] = ws->entities[i].handle;
|
||||
}
|
||||
ret = (int32_t) ws->nentities;
|
||||
ddsrt_mutex_unlock (&ws->wait_lock);
|
||||
dds_entity_unpin (&ws->m_entity);
|
||||
return ret;
|
||||
}
|
||||
ret = (int32_t) ws->nentities;
|
||||
dds_waitset_unlock (ws);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dds_waitset_remove (dds_waitset *ws, dds_entity_t observed)
|
||||
/* This is called when the observed entity signals a status change. */
|
||||
static void dds_waitset_observer (struct dds_waitset *ws, dds_entity_t observed, uint32_t status)
|
||||
{
|
||||
(void) status;
|
||||
|
||||
ddsrt_mutex_lock (&ws->wait_lock);
|
||||
/* Move observed entity to triggered list. */
|
||||
size_t i;
|
||||
for (i = 0; i < ws->nentities; i++)
|
||||
if (ws->entities[i].handle == observed)
|
||||
break;
|
||||
if (i < ws->nentities && i >= ws->ntriggered)
|
||||
{
|
||||
dds_attachment tmp = ws->entities[i];
|
||||
ws->entities[i] = ws->entities[ws->ntriggered];
|
||||
ws->entities[ws->ntriggered++] = tmp;
|
||||
}
|
||||
/* Trigger waitset to wake up. */
|
||||
ddsrt_cond_broadcast (&ws->wait_cond);
|
||||
ddsrt_mutex_unlock (&ws->wait_lock);
|
||||
}
|
||||
|
||||
struct dds_waitset_attach_observer_arg {
|
||||
dds_attach_t x;
|
||||
};
|
||||
|
||||
static bool dds_waitset_attach_observer (struct dds_waitset *ws, struct dds_entity *observed, void *varg)
|
||||
{
|
||||
struct dds_waitset_attach_observer_arg *arg = varg;
|
||||
ddsrt_mutex_lock (&ws->wait_lock);
|
||||
ws->entities = ddsrt_realloc (ws->entities, (ws->nentities + 1) * sizeof (*ws->entities));
|
||||
ws->entities[ws->nentities].arg = arg->x;
|
||||
ws->entities[ws->nentities].entity = observed;
|
||||
ws->entities[ws->nentities].handle = observed->m_hdllink.hdl;
|
||||
ws->nentities++;
|
||||
if (is_triggered (observed))
|
||||
{
|
||||
const size_t i = ws->nentities - 1;
|
||||
dds_attachment tmp = ws->entities[i];
|
||||
ws->entities[i] = ws->entities[ws->ntriggered];
|
||||
ws->entities[ws->ntriggered++] = tmp;
|
||||
}
|
||||
ddsrt_cond_broadcast (&ws->wait_cond);
|
||||
ddsrt_mutex_unlock (&ws->wait_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dds_waitset_delete_observer (struct dds_waitset *ws, dds_entity_t observed)
|
||||
{
|
||||
size_t i;
|
||||
ddsrt_mutex_lock (&ws->wait_lock);
|
||||
for (i = 0; i < ws->nentities; i++)
|
||||
if (ws->entities[i].handle == observed)
|
||||
break;
|
||||
|
|
@ -167,118 +278,85 @@ static void dds_waitset_remove (dds_waitset *ws, dds_entity_t observed)
|
|||
{
|
||||
ws->entities[i] = ws->entities[--ws->nentities];
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is called when the observed entity signals a status change. */
|
||||
static void dds_waitset_observer (dds_entity *ent, dds_entity_t observed, uint32_t status)
|
||||
{
|
||||
assert (dds_entity_kind (ent) == DDS_KIND_WAITSET);
|
||||
dds_waitset *ws = (dds_waitset *) ent;
|
||||
(void) status;
|
||||
|
||||
ddsrt_mutex_lock (&ws->m_entity.m_mutex);
|
||||
/* Move observed entity to triggered list. */
|
||||
size_t i;
|
||||
for (i = 0; i < ws->nentities; i++)
|
||||
if (ws->entities[i].handle == observed)
|
||||
break;
|
||||
if (i < ws->nentities && i >= ws->ntriggered)
|
||||
{
|
||||
dds_attachment tmp = ws->entities[i];
|
||||
ws->entities[i] = ws->entities[ws->ntriggered];
|
||||
ws->entities[ws->ntriggered++] = tmp;
|
||||
}
|
||||
/* Trigger waitset to wake up. */
|
||||
ddsrt_cond_broadcast (&ws->m_entity.m_cond);
|
||||
ddsrt_mutex_unlock (&ws->m_entity.m_mutex);
|
||||
}
|
||||
|
||||
static void dds_waitset_delete_observer (dds_entity *ent, dds_entity_t observed)
|
||||
{
|
||||
assert (dds_entity_kind (ent) == DDS_KIND_WAITSET);
|
||||
dds_waitset *ws = (dds_waitset *) ent;
|
||||
ddsrt_mutex_lock (&ws->m_entity.m_mutex);
|
||||
/* Remove this observed entity, which is being deleted, from the waitset. */
|
||||
dds_waitset_remove (ws, observed);
|
||||
/* Our registration to this observed entity will be removed automatically. */
|
||||
/* Trigger waitset to wake up. */
|
||||
ddsrt_cond_broadcast (&ws->m_entity.m_cond);
|
||||
ddsrt_mutex_unlock (&ws->m_entity.m_mutex);
|
||||
ddsrt_cond_broadcast (&ws->wait_cond);
|
||||
ddsrt_mutex_unlock (&ws->wait_lock);
|
||||
}
|
||||
|
||||
dds_return_t dds_waitset_attach (dds_entity_t waitset, dds_entity_t entity, dds_attach_t x)
|
||||
{
|
||||
dds_entity *wsent;
|
||||
dds_entity *e;
|
||||
dds_waitset *ws;
|
||||
dds_return_t ret;
|
||||
|
||||
if ((ret = dds_waitset_lock (waitset, &ws)) < 0)
|
||||
if ((ret = dds_entity_pin (waitset, &wsent)) < 0)
|
||||
return ret;
|
||||
|
||||
if (waitset == entity)
|
||||
e = &ws->m_entity;
|
||||
else if ((ret = dds_entity_pin (entity, &e)) < 0)
|
||||
goto err_waitset;
|
||||
|
||||
/* This will fail if given entity is already attached (or deleted). */
|
||||
if ((ret = dds_entity_observer_register (e, &ws->m_entity, dds_waitset_observer, dds_waitset_delete_observer)) != DDS_RETCODE_OK)
|
||||
goto err_entity;
|
||||
|
||||
ws->entities = ddsrt_realloc (ws->entities, (ws->nentities + 1) * sizeof (*ws->entities));
|
||||
ws->entities[ws->nentities].arg = x;
|
||||
ws->entities[ws->nentities].entity = e;
|
||||
ws->entities[ws->nentities].handle = e->m_hdllink.hdl;
|
||||
ws->nentities++;
|
||||
if (is_triggered (e))
|
||||
else if (dds_entity_kind (wsent) != DDS_KIND_WAITSET)
|
||||
{
|
||||
const size_t i = ws->nentities - 1;
|
||||
dds_attachment tmp = ws->entities[i];
|
||||
ws->entities[i] = ws->entities[ws->ntriggered];
|
||||
ws->entities[ws->ntriggered++] = tmp;
|
||||
dds_entity_unpin (wsent);
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
}
|
||||
ddsrt_cond_broadcast (&ws->m_entity.m_cond);
|
||||
else
|
||||
{
|
||||
dds_waitset *ws = (dds_waitset *) wsent;
|
||||
|
||||
err_entity:
|
||||
if (e != &ws->m_entity)
|
||||
if ((ret = dds_entity_pin (entity, &e)) < 0)
|
||||
goto err_entity;
|
||||
|
||||
/* Entity must be "in scope": within the participant, domain or (self-evidently true) Cyclone DDS,
|
||||
depending on the parent of the waitset, so that one can't use a waitset created in participant
|
||||
A to wait for entities in participant B, &c. While there is no technical obstacle (though
|
||||
there might be one for cross-domain use one day), it seems rather unhygienic practice. */
|
||||
if (!dds_entity_in_scope (e, ws->m_entity.m_parent))
|
||||
{
|
||||
ret = DDS_RETCODE_BAD_PARAMETER;
|
||||
goto err_scope;
|
||||
}
|
||||
|
||||
/* This will fail if given entity is already attached (or deleted). */
|
||||
struct dds_waitset_attach_observer_arg attach_arg = { .x = x };
|
||||
ret = dds_entity_observer_register (e, ws, dds_waitset_observer, dds_waitset_attach_observer, &attach_arg, dds_waitset_delete_observer);
|
||||
|
||||
err_scope:
|
||||
dds_entity_unpin (e);
|
||||
err_waitset:
|
||||
dds_waitset_unlock (ws);
|
||||
return ret;
|
||||
err_entity:
|
||||
dds_entity_unpin (&ws->m_entity);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
dds_return_t dds_waitset_detach (dds_entity_t waitset, dds_entity_t entity)
|
||||
{
|
||||
dds_waitset *ws;
|
||||
dds_entity *e;
|
||||
dds_entity *wsent;
|
||||
dds_return_t ret;
|
||||
|
||||
if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK)
|
||||
if ((ret = dds_entity_pin (waitset, &wsent)) != DDS_RETCODE_OK)
|
||||
return ret;
|
||||
|
||||
/* Possibly fails when entity was not attached. */
|
||||
if (waitset == entity)
|
||||
ret = dds_entity_observer_unregister (&ws->m_entity, &ws->m_entity);
|
||||
else if ((ret = dds_entity_pin (entity, &e)) < 0)
|
||||
; /* entity invalid */
|
||||
else
|
||||
else if (dds_entity_kind (wsent) != DDS_KIND_WAITSET)
|
||||
{
|
||||
ret = dds_entity_observer_unregister (e, &ws->m_entity);
|
||||
dds_entity_unpin (e);
|
||||
}
|
||||
|
||||
if (ret == DDS_RETCODE_OK)
|
||||
{
|
||||
dds_waitset_remove (ws, entity);
|
||||
dds_entity_unpin (wsent);
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ret != DDS_RETCODE_PRECONDITION_NOT_MET)
|
||||
dds_waitset *ws = (dds_waitset *) wsent;
|
||||
dds_entity *e;
|
||||
/* Possibly fails when entity was not attached. */
|
||||
if (waitset == entity)
|
||||
ret = dds_entity_observer_unregister (&ws->m_entity, ws, true);
|
||||
else if ((ret = dds_entity_pin (entity, &e)) < 0)
|
||||
; /* entity invalid */
|
||||
else
|
||||
{
|
||||
ret = dds_entity_observer_unregister (e, ws, true);
|
||||
dds_entity_unpin (e);
|
||||
}
|
||||
|
||||
dds_entity_unpin (&ws->m_entity);
|
||||
if (ret != DDS_RETCODE_OK && ret != DDS_RETCODE_PRECONDITION_NOT_MET)
|
||||
ret = DDS_RETCODE_BAD_PARAMETER;
|
||||
return ret;
|
||||
}
|
||||
dds_waitset_unlock (ws);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dds_return_t dds_waitset_wait_until (dds_entity_t waitset, dds_attach_t *xs, size_t nxs, dds_time_t abstimeout)
|
||||
|
|
@ -299,7 +377,6 @@ dds_return_t dds_waitset_set_trigger (dds_entity_t waitset, bool trigger)
|
|||
{
|
||||
dds_entity *ent;
|
||||
dds_return_t rc;
|
||||
|
||||
if ((rc = dds_entity_pin (waitset, &ent)) != DDS_RETCODE_OK)
|
||||
return rc;
|
||||
else if (dds_entity_kind (ent) != DDS_KIND_WAITSET)
|
||||
|
|
@ -307,11 +384,10 @@ dds_return_t dds_waitset_set_trigger (dds_entity_t waitset, bool trigger)
|
|||
dds_entity_unpin (ent);
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
}
|
||||
|
||||
ddsrt_mutex_lock (&ent->m_observers_lock);
|
||||
dds_entity_trigger_set (ent, trigger);
|
||||
ddsrt_mutex_unlock (&ent->m_observers_lock);
|
||||
|
||||
dds_entity_unpin (ent);
|
||||
return DDS_RETCODE_OK;
|
||||
else
|
||||
{
|
||||
dds_entity_trigger_set (ent, trigger);
|
||||
dds_entity_unpin (ent);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -981,21 +981,14 @@ static uint32_t whc_default_remove_acked_messages_full (struct whc_impl *whc, se
|
|||
/* Delete it - but this may not result in deleting the index node as
|
||||
there must still be a more recent one available */
|
||||
#ifndef NDEBUG
|
||||
struct whc_node whcn_template;
|
||||
union {
|
||||
struct whc_idxnode idxn;
|
||||
char pad[sizeof (struct whc_idxnode) + sizeof (struct whc_node *)];
|
||||
} template;
|
||||
template.idxn.headidx = 0;
|
||||
template.idxn.hist[0] = &whcn_template;
|
||||
whcn_template.serdata = ddsi_serdata_ref (oldn->serdata);
|
||||
struct whc_idxnode template;
|
||||
template.iid = idxn->iid;
|
||||
assert (oldn->seq < whcn->seq);
|
||||
#endif
|
||||
TRACE (" del %p %"PRId64, (void *) oldn, oldn->seq);
|
||||
whc_delete_one (whc, oldn);
|
||||
#ifndef NDEBUG
|
||||
assert (ddsrt_hh_lookup (whc->idx_hash, &template) == idxn);
|
||||
ddsi_serdata_unref (whcn_template.serdata);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include "dds/ddsi/ddsi_tkmap.h"
|
||||
#include "dds/ddsi/q_thread.h"
|
||||
#include "dds/ddsi/q_xmsg.h"
|
||||
#include "dds/ddsi/q_rhc.h"
|
||||
#include "dds/ddsi/ddsi_rhc.h"
|
||||
#include "dds/ddsi/ddsi_serdata.h"
|
||||
#include "dds__stream.h"
|
||||
#include "dds/ddsi/q_transmit.h"
|
||||
|
|
@ -71,9 +71,9 @@ dds_return_t dds_write_ts (dds_entity_t writer, const void *data, dds_time_t tim
|
|||
return ret;
|
||||
}
|
||||
|
||||
static dds_return_t try_store (struct rhc *rhc, const struct proxy_writer_info *pwr_info, struct ddsi_serdata *payload, struct ddsi_tkmap_instance *tk, dds_duration_t *max_block_ms)
|
||||
static dds_return_t try_store (struct ddsi_rhc *rhc, const struct ddsi_writer_info *pwr_info, struct ddsi_serdata *payload, struct ddsi_tkmap_instance *tk, dds_duration_t *max_block_ms)
|
||||
{
|
||||
while (! rhc_store (rhc, pwr_info, payload, tk))
|
||||
while (! ddsi_rhc_store (rhc, pwr_info, payload, tk))
|
||||
{
|
||||
if (*max_block_ms > 0)
|
||||
{
|
||||
|
|
@ -98,8 +98,8 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay
|
|||
if (rdary[0])
|
||||
{
|
||||
dds_duration_t max_block_ms = wr->xqos->reliability.max_blocking_time;
|
||||
struct proxy_writer_info pwr_info;
|
||||
make_proxy_writer_info (&pwr_info, &wr->e, wr->xqos);
|
||||
struct ddsi_writer_info pwr_info;
|
||||
ddsi_make_writer_info (&pwr_info, &wr->e, wr->xqos);
|
||||
for (uint32_t i = 0; rdary[i]; i++) {
|
||||
DDS_CTRACE (&wr->e.gv->logconfig, "reader "PGUIDFMT"\n", PGUID (rdary[i]->e.guid));
|
||||
if ((ret = try_store (rdary[i]->rhc, &pwr_info, payload, tk, &max_block_ms)) != DDS_RETCODE_OK)
|
||||
|
|
@ -120,11 +120,11 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay
|
|||
reliable samples that are rejected are simply discarded. */
|
||||
ddsrt_avl_iter_t it;
|
||||
struct pwr_rd_match *m;
|
||||
struct proxy_writer_info pwr_info;
|
||||
struct ddsi_writer_info wrinfo;
|
||||
const struct ephash *gh = wr->e.gv->guid_hash;
|
||||
dds_duration_t max_block_ms = wr->xqos->reliability.max_blocking_time;
|
||||
ddsrt_mutex_unlock (&wr->rdary.rdary_lock);
|
||||
make_proxy_writer_info (&pwr_info, &wr->e, wr->xqos);
|
||||
ddsi_make_writer_info (&wrinfo, &wr->e, wr->xqos);
|
||||
ddsrt_mutex_lock (&wr->e.lock);
|
||||
for (m = ddsrt_avl_iter_first (&wr_local_readers_treedef, &wr->local_readers, &it); m != NULL; m = ddsrt_avl_iter_next (&it))
|
||||
{
|
||||
|
|
@ -133,7 +133,7 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay
|
|||
{
|
||||
DDS_CTRACE (&wr->e.gv->logconfig, "reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid));
|
||||
/* Copied the return value ignore from DDSI deliver_user_data () function. */
|
||||
if ((ret = try_store (rd->rhc, &pwr_info, payload, tk, &max_block_ms)) != DDS_RETCODE_OK)
|
||||
if ((ret = try_store (rd->rhc, &wrinfo, payload, tk, &max_block_ms)) != DDS_RETCODE_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,34 +51,36 @@ static dds_return_t dds_writer_status_validate (uint32_t mask)
|
|||
|
||||
static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data)
|
||||
{
|
||||
struct dds_entity * const entity = ventity;
|
||||
dds_writer * const wr = ventity;
|
||||
|
||||
/* When data is NULL, it means that the writer is deleted. */
|
||||
/* When data is NULL, it means that the DDSI reader is deleted. */
|
||||
if (data == NULL)
|
||||
{
|
||||
/* Release the initial claim that was done during the create. This
|
||||
* will indicate that further API deletion is now possible. */
|
||||
dds_handle_unpin (&entity->m_hdllink);
|
||||
ddsrt_mutex_lock (&wr->m_entity.m_mutex);
|
||||
wr->m_wr = NULL;
|
||||
ddsrt_cond_broadcast (&wr->m_entity.m_cond);
|
||||
ddsrt_mutex_unlock (&wr->m_entity.m_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
struct dds_listener const * const lst = &entity->m_listener;
|
||||
struct dds_listener const * const lst = &wr->m_entity.m_listener;
|
||||
enum dds_status_id status_id = (enum dds_status_id) data->raw_status_id;
|
||||
bool invoke = false;
|
||||
void *vst = NULL;
|
||||
int32_t *reset[2] = { NULL, NULL };
|
||||
|
||||
ddsrt_mutex_lock (&entity->m_observers_lock);
|
||||
while (entity->m_cb_count > 0)
|
||||
ddsrt_cond_wait (&entity->m_observers_cond, &entity->m_observers_lock);
|
||||
entity->m_cb_count++;
|
||||
/* FIXME: why wait if no listener is set? */
|
||||
ddsrt_mutex_lock (&wr->m_entity.m_observers_lock);
|
||||
while (wr->m_entity.m_cb_count > 0)
|
||||
ddsrt_cond_wait (&wr->m_entity.m_observers_cond, &wr->m_entity.m_observers_lock);
|
||||
|
||||
/* Reset the status for possible Listener call.
|
||||
* When a listener is not called, the status will be set (again). */
|
||||
dds_entity_status_reset (entity, (status_mask_t) (1u << status_id));
|
||||
dds_entity_status_reset (&wr->m_entity, (status_mask_t) (1u << status_id));
|
||||
|
||||
/* Update status metrics. */
|
||||
dds_writer * const wr = (dds_writer *) entity;
|
||||
switch (status_id)
|
||||
{
|
||||
case DDS_OFFERED_DEADLINE_MISSED_STATUS_ID: {
|
||||
|
|
@ -136,23 +138,31 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data)
|
|||
assert (0);
|
||||
}
|
||||
|
||||
if (invoke)
|
||||
const uint32_t enabled = (ddsrt_atomic_ld32 (&wr->m_entity.m_status.m_status_and_mask) & ((1u << status_id) << SAM_ENABLED_SHIFT));
|
||||
if (enabled == 0)
|
||||
{
|
||||
ddsrt_mutex_unlock (&entity->m_observers_lock);
|
||||
dds_entity_invoke_listener(entity, status_id, vst);
|
||||
ddsrt_mutex_lock (&entity->m_observers_lock);
|
||||
/* Don't invoke listeners or set status flag if masked */
|
||||
}
|
||||
else if (invoke)
|
||||
{
|
||||
wr->m_entity.m_cb_pending_count++;
|
||||
wr->m_entity.m_cb_count++;
|
||||
ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock);
|
||||
dds_entity_invoke_listener (&wr->m_entity, status_id, vst);
|
||||
ddsrt_mutex_lock (&wr->m_entity.m_observers_lock);
|
||||
wr->m_entity.m_cb_count--;
|
||||
wr->m_entity.m_cb_pending_count--;
|
||||
*reset[0] = 0;
|
||||
if (reset[1])
|
||||
*reset[1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
dds_entity_status_set (entity, (status_mask_t) (1u << status_id));
|
||||
dds_entity_status_set (&wr->m_entity, (status_mask_t) (1u << status_id));
|
||||
}
|
||||
|
||||
entity->m_cb_count--;
|
||||
ddsrt_cond_broadcast (&entity->m_observers_cond);
|
||||
ddsrt_mutex_unlock (&entity->m_observers_lock);
|
||||
ddsrt_cond_broadcast (&wr->m_entity.m_observers_cond);
|
||||
ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock);
|
||||
}
|
||||
|
||||
static uint32_t get_bandwidth_limit (dds_transport_priority_qospolicy_t transport_priority)
|
||||
|
|
@ -166,18 +176,32 @@ static uint32_t get_bandwidth_limit (dds_transport_priority_qospolicy_t transpor
|
|||
#endif
|
||||
}
|
||||
|
||||
static dds_return_t dds_writer_close (dds_entity *e) ddsrt_nonnull_all;
|
||||
static void dds_writer_interrupt (dds_entity *e) ddsrt_nonnull_all;
|
||||
|
||||
static dds_return_t dds_writer_close (dds_entity *e)
|
||||
static void dds_writer_interrupt (dds_entity *e)
|
||||
{
|
||||
dds_writer * const wr = (dds_writer *) e;
|
||||
dds_return_t ret;
|
||||
thread_state_awake (lookup_thread_state (), &e->m_domain->gv);
|
||||
nn_xpack_send (wr->m_xp, false);
|
||||
if ((ret = delete_writer (&e->m_domain->gv, &e->m_guid)) < 0)
|
||||
ret = DDS_RETCODE_ERROR;
|
||||
struct q_globals * const gv = &e->m_domain->gv;
|
||||
thread_state_awake (lookup_thread_state (), gv);
|
||||
unblock_throttled_writer (gv, &e->m_guid);
|
||||
thread_state_asleep (lookup_thread_state ());
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dds_writer_close (dds_entity *e) ddsrt_nonnull_all;
|
||||
|
||||
static void dds_writer_close (dds_entity *e)
|
||||
{
|
||||
struct dds_writer * const wr = (struct dds_writer *) e;
|
||||
struct q_globals * const gv = &e->m_domain->gv;
|
||||
struct thread_state1 * const ts1 = lookup_thread_state ();
|
||||
thread_state_awake (ts1, gv);
|
||||
nn_xpack_send (wr->m_xp, false);
|
||||
(void) delete_writer (gv, &e->m_guid);
|
||||
thread_state_asleep (ts1);
|
||||
|
||||
ddsrt_mutex_lock (&e->m_mutex);
|
||||
while (wr->m_wr != NULL)
|
||||
ddsrt_cond_wait (&e->m_cond, &e->m_mutex);
|
||||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
}
|
||||
|
||||
static dds_return_t dds_writer_delete (dds_entity *e) ddsrt_nonnull_all;
|
||||
|
|
@ -190,12 +214,7 @@ static dds_return_t dds_writer_delete (dds_entity *e)
|
|||
thread_state_awake (lookup_thread_state (), &e->m_domain->gv);
|
||||
nn_xpack_free (wr->m_xp);
|
||||
thread_state_asleep (lookup_thread_state ());
|
||||
if ((ret = dds_delete (wr->m_topic->m_entity.m_hdllink.hdl)) == DDS_RETCODE_OK)
|
||||
{
|
||||
ret = dds_delete_impl (e->m_parent->m_hdllink.hdl, true);
|
||||
if (ret == DDS_RETCODE_BAD_PARAMETER)
|
||||
ret = DDS_RETCODE_OK;
|
||||
}
|
||||
ret = dds_delete (wr->m_topic->m_entity.m_hdllink.hdl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -238,6 +257,7 @@ static struct whc *make_whc (struct dds_domain *dom, const dds_qos_t *qos)
|
|||
}
|
||||
|
||||
const struct dds_entity_deriver dds_entity_deriver_writer = {
|
||||
.interrupt = dds_writer_interrupt,
|
||||
.close = dds_writer_close,
|
||||
.delete = dds_writer_delete,
|
||||
.set_qos = dds_writer_qos_set,
|
||||
|
|
@ -251,6 +271,7 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
|
|||
dds_writer *wr;
|
||||
dds_entity_t writer;
|
||||
dds_publisher *pub = NULL;
|
||||
dds_participant *pp;
|
||||
dds_topic *tp;
|
||||
dds_entity_t publisher;
|
||||
|
||||
|
|
@ -259,7 +280,7 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
|
|||
if ((rc = dds_entity_pin (participant_or_publisher, &p_or_p)) != DDS_RETCODE_OK)
|
||||
return rc;
|
||||
if (dds_entity_kind (p_or_p) == DDS_KIND_PARTICIPANT)
|
||||
publisher = dds_create_publisher(participant_or_publisher, qos, NULL);
|
||||
publisher = dds_create_publisher (participant_or_publisher, qos, NULL);
|
||||
else
|
||||
publisher = participant_or_publisher;
|
||||
dds_entity_unpin (p_or_p);
|
||||
|
|
@ -274,9 +295,14 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
|
|||
|
||||
if ((rc = dds_topic_lock (topic, &tp)) != DDS_RETCODE_OK)
|
||||
goto err_tp_lock;
|
||||
|
||||
assert (tp->m_stopic);
|
||||
assert (pub->m_entity.m_domain == tp->m_entity.m_domain);
|
||||
|
||||
pp = dds_entity_participant (&pub->m_entity);
|
||||
if (pp != dds_entity_participant (&tp->m_entity))
|
||||
{
|
||||
rc = DDS_RETCODE_BAD_PARAMETER;
|
||||
goto err_pp_mismatch;
|
||||
}
|
||||
|
||||
/* Merge Topic & Publisher qos */
|
||||
wqos = dds_create_qos ();
|
||||
|
|
@ -304,34 +330,26 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
|
|||
wr->m_whc = make_whc (pub->m_entity.m_domain, wqos);
|
||||
wr->whc_batch = pub->m_entity.m_domain->gv.config.whc_batch;
|
||||
|
||||
/* Extra claim of this writer to make sure that the delete waits until DDSI
|
||||
* has deleted its writer as well. This can be known through the callback. */
|
||||
dds_handle_repin (&wr->m_entity.m_hdllink);
|
||||
|
||||
ddsrt_mutex_unlock (&tp->m_entity.m_mutex);
|
||||
ddsrt_mutex_unlock (&pub->m_entity.m_mutex);
|
||||
|
||||
thread_state_awake (lookup_thread_state (), &pub->m_entity.m_domain->gv);
|
||||
rc = new_writer (&wr->m_wr, &wr->m_entity.m_domain->gv, &wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr);
|
||||
ddsrt_mutex_lock (&pub->m_entity.m_mutex);
|
||||
ddsrt_mutex_lock (&tp->m_entity.m_mutex);
|
||||
rc = new_writer (&wr->m_wr, &wr->m_entity.m_domain->gv, &wr->m_entity.m_guid, NULL, &pp->m_entity.m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr);
|
||||
assert(rc == DDS_RETCODE_OK);
|
||||
thread_state_asleep (lookup_thread_state ());
|
||||
|
||||
wr->m_entity.m_iid = get_entity_instance_id (&wr->m_entity.m_domain->gv, &wr->m_entity.m_guid);
|
||||
dds_entity_register_child (&pub->m_entity, &wr->m_entity);
|
||||
|
||||
dds_entity_init_complete (&wr->m_entity);
|
||||
dds_topic_unlock (tp);
|
||||
dds_publisher_unlock (pub);
|
||||
return writer;
|
||||
|
||||
err_bad_qos:
|
||||
err_pp_mismatch:
|
||||
dds_topic_unlock (tp);
|
||||
err_tp_lock:
|
||||
dds_publisher_unlock (pub);
|
||||
if ((pub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){
|
||||
(void )dds_delete (publisher);
|
||||
}
|
||||
if ((pub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0)
|
||||
(void) dds_delete (publisher);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ set(ddsc_test_sources
|
|||
"builtin_topics.c"
|
||||
"config.c"
|
||||
"dispose.c"
|
||||
"domain.c"
|
||||
"entity_api.c"
|
||||
"entity_hierarchy.c"
|
||||
"entity_status.c"
|
||||
|
|
@ -30,6 +31,7 @@ set(ddsc_test_sources
|
|||
"publisher.c"
|
||||
"qos.c"
|
||||
"querycondition.c"
|
||||
"guardcondition.c"
|
||||
"readcondition.c"
|
||||
"reader.c"
|
||||
"reader_iterator.c"
|
||||
|
|
@ -45,6 +47,7 @@ set(ddsc_test_sources
|
|||
"unregister.c"
|
||||
"unsupported.c"
|
||||
"waitset.c"
|
||||
"waitset_torture.c"
|
||||
"write.c"
|
||||
"writer.c")
|
||||
|
||||
|
|
|
|||
|
|
@ -308,3 +308,35 @@ CU_Test(ddsc_builtin_topics, builtin_qos, .init = setup, .fini = teardown)
|
|||
CU_ASSERT_FATAL(dds_sub_subscriber > 0);
|
||||
check_default_qos_of_builtin_entity(dds_sub_subscriber, 0);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_builtin_topics, read_nothing)
|
||||
{
|
||||
dds_entity_t pp;
|
||||
dds_entity_t rd;
|
||||
dds_return_t ret;
|
||||
dds_sample_info_t si;
|
||||
void *raw1, *raw2;
|
||||
int32_t n1, n2;
|
||||
|
||||
pp = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
|
||||
CU_ASSERT_FATAL (pp > 0);
|
||||
rd = dds_create_reader (pp, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL);
|
||||
CU_ASSERT_FATAL (rd > 0);
|
||||
|
||||
/* Can't guarantee there's no other process around with a publication, but
|
||||
we can take until nothing remains. The point is checking handling of
|
||||
freeing memory when a loan was outstanding, memory had to be allocated,
|
||||
and subsequently had to be freed because of an absence of data. */
|
||||
raw1 = raw2 = NULL;
|
||||
n1 = dds_take (rd, &raw1, &si, 1, 1);
|
||||
CU_ASSERT_FATAL (n1 >= 0);
|
||||
n2 = dds_take (rd, &raw2, &si, 1, 1);
|
||||
CU_ASSERT_FATAL (n2 >= 0);
|
||||
ret = dds_return_loan (rd, &raw1, n1);
|
||||
CU_ASSERT_FATAL (ret == 0);
|
||||
ret = dds_return_loan (rd, &raw2, n2);
|
||||
CU_ASSERT_FATAL (ret == 0);
|
||||
|
||||
ret = dds_delete (pp);
|
||||
CU_ASSERT_FATAL (ret == 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,3 +75,46 @@ CU_Test(ddsc_config, simple_udp, .init = ddsrt_init, .fini = ddsrt_fini) {
|
|||
|
||||
dds_delete(participant);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_config, user_config, .init = ddsrt_init, .fini = ddsrt_fini) {
|
||||
|
||||
CU_ASSERT_FATAL(dds_create_domain(1,
|
||||
"<"DDS_PROJECT_NAME"><Domain><Id>any</Id></Domain>"
|
||||
"<DDSI2E><Internal><MaxParticipants>2</MaxParticipants></Internal></DDSI2E>"
|
||||
"</"DDS_PROJECT_NAME">") == DDS_RETCODE_OK);
|
||||
|
||||
dds_entity_t participant_1;
|
||||
dds_entity_t participant_2;
|
||||
dds_entity_t participant_3;
|
||||
|
||||
participant_1 = dds_create_participant(1, NULL, NULL);
|
||||
|
||||
CU_ASSERT_FATAL(participant_1 > 0);
|
||||
|
||||
participant_2 = dds_create_participant(1, NULL, NULL);
|
||||
|
||||
CU_ASSERT_FATAL(participant_2 > 0);
|
||||
|
||||
participant_3 = dds_create_participant(1, NULL, NULL);
|
||||
|
||||
CU_ASSERT(participant_3 <= 0);
|
||||
|
||||
dds_delete(participant_3);
|
||||
dds_delete(participant_2);
|
||||
dds_delete(participant_1);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_config, incorrect_config, .init = ddsrt_init, .fini = ddsrt_fini) {
|
||||
|
||||
CU_ASSERT_FATAL(dds_create_domain(1, NULL) == DDS_RETCODE_BAD_PARAMETER);
|
||||
CU_ASSERT_FATAL(dds_create_domain(1, "<CycloneDDS incorrect XML") != DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL(dds_create_domain(DDS_DOMAIN_DEFAULT,
|
||||
"<"DDS_PROJECT_NAME"><Domain><Id>any</Id></Domain>"
|
||||
"<DDSI2E><Internal><MaxParticipants>2</MaxParticipants></Internal></DDSI2E>"
|
||||
"</"DDS_PROJECT_NAME">") == DDS_RETCODE_BAD_PARAMETER);
|
||||
CU_ASSERT_FATAL(dds_create_domain(2,
|
||||
"<"DDS_PROJECT_NAME"><Domain><Id>any</Id></Domain>"
|
||||
"<DDSI2E><Internal><MaxParticipants>2</MaxParticipants></Internal></DDSI2E>"
|
||||
"</"DDS_PROJECT_NAME">") == DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL(dds_create_domain(2, "") == DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
}
|
||||
|
|
|
|||
142
src/core/ddsc/tests/domain.c
Normal file
142
src/core/ddsc/tests/domain.c
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright(c) 2019 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dds/dds.h"
|
||||
#include "CUnit/Test.h"
|
||||
#include "config_env.h"
|
||||
#include "dds/version.h"
|
||||
#include "dds/ddsrt/environ.h"
|
||||
|
||||
CU_Test(ddsc_domain, get_domainid)
|
||||
{
|
||||
dds_entity_t pp, d, x;
|
||||
dds_return_t rc;
|
||||
uint32_t did;
|
||||
pp = dds_create_participant (0, NULL, NULL);
|
||||
CU_ASSERT_FATAL (pp > 0);
|
||||
d = dds_get_parent (pp);
|
||||
CU_ASSERT_FATAL (d > 0);
|
||||
x = dds_get_parent (d);
|
||||
CU_ASSERT_FATAL (x == DDS_CYCLONEDDS_HANDLE);
|
||||
x = dds_get_parent (x);
|
||||
CU_ASSERT_FATAL (x == 0);
|
||||
|
||||
rc = dds_get_domainid (pp, &did);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL (did == 0);
|
||||
rc = dds_get_domainid (d, &did);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL (did == 0);
|
||||
rc = dds_get_domainid (DDS_CYCLONEDDS_HANDLE, &did);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL (did == DDS_DOMAIN_DEFAULT);
|
||||
rc = dds_delete (pp);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_domain, delete_domain0)
|
||||
{
|
||||
dds_entity_t pp[3], d[3];
|
||||
dds_return_t rc;
|
||||
uint32_t did;
|
||||
for (dds_domainid_t i = 0; i < (dds_domainid_t) (sizeof (pp) / sizeof (pp[0])); i++)
|
||||
{
|
||||
pp[i] = dds_create_participant (0, NULL, NULL);
|
||||
CU_ASSERT_FATAL (pp[i] > 0);
|
||||
d[i] = dds_get_parent (pp[i]);
|
||||
CU_ASSERT_FATAL (d[i] > 0);
|
||||
if (i > 0)
|
||||
CU_ASSERT_FATAL (d[i] == d[i-1]);
|
||||
}
|
||||
rc = dds_delete (pp[0]);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = dds_get_domainid (pp[0], &did);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_BAD_PARAMETER);
|
||||
for (size_t i = 1; i < sizeof (pp) / sizeof (pp[0]); i++)
|
||||
{
|
||||
rc = dds_get_domainid (pp[i], &did);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL (did == 0);
|
||||
}
|
||||
rc = dds_delete (d[1]);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_OK);
|
||||
/* Deleting the domain should delete all participants in it as well,
|
||||
and as there is only a single domain in this test, that should
|
||||
de-initialize the library.
|
||||
|
||||
A non-initialized library returns PRECONDITION_NOT_MET; an
|
||||
initialized one given an invalid handle returns BAD_PARAMETER,
|
||||
so we can distinguish the two cases. */
|
||||
rc = dds_get_domainid (pp[1], &did);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_domain, delete_domainM)
|
||||
{
|
||||
dds_entity_t pp[3], d[3], x;
|
||||
dds_return_t rc;
|
||||
uint32_t did;
|
||||
for (dds_domainid_t i = 0; i < (dds_domainid_t) (sizeof (pp) / sizeof (pp[0])); i++)
|
||||
{
|
||||
pp[i] = dds_create_participant (i, NULL, NULL);
|
||||
CU_ASSERT_FATAL (pp[i] > 0);
|
||||
d[i] = dds_get_parent (pp[i]);
|
||||
CU_ASSERT_FATAL (d[i] > 0);
|
||||
for (dds_domainid_t j = 0; j < i; j++)
|
||||
CU_ASSERT_FATAL (d[i] != d[j]);
|
||||
}
|
||||
|
||||
/* deleting participant 0 should tear down domain 0, but nothing else */
|
||||
rc = dds_delete (pp[0]);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = dds_get_domainid (pp[0], &did);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_BAD_PARAMETER);
|
||||
rc = dds_get_domainid (d[0], &did);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_BAD_PARAMETER);
|
||||
|
||||
/* deleting domain should delete participant 1, but leave domain 2 alone */
|
||||
rc = dds_delete (d[1]);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = dds_get_domainid (pp[1], &did);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_BAD_PARAMETER);
|
||||
x = dds_get_parent (pp[2]);
|
||||
CU_ASSERT_FATAL (x == d[2]);
|
||||
|
||||
/* after deleting participant 2, everything should be gone */
|
||||
rc = dds_delete (pp[2]);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_OK);
|
||||
rc = dds_get_domainid (pp[1], &did);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_domain, delete_cyclonedds)
|
||||
{
|
||||
dds_entity_t pp[3], d[3];
|
||||
dds_return_t rc;
|
||||
uint32_t did;
|
||||
for (dds_domainid_t i = 0; i < (dds_domainid_t) (sizeof (pp) / sizeof (pp[0])); i++)
|
||||
{
|
||||
pp[i] = dds_create_participant (i, NULL, NULL);
|
||||
CU_ASSERT_FATAL (pp[i] > 0);
|
||||
d[i] = dds_get_parent (pp[i]);
|
||||
CU_ASSERT_FATAL (d[i] > 0);
|
||||
for (dds_domainid_t j = 0; j < i; j++)
|
||||
CU_ASSERT_FATAL (d[i] != d[j]);
|
||||
}
|
||||
|
||||
/* deleting participant 0 should tear down domain 0, but nothing else */
|
||||
rc = dds_delete (DDS_CYCLONEDDS_HANDLE);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = dds_get_domainid (pp[0], &did);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
}
|
||||
|
|
@ -290,9 +290,12 @@ CU_Test(ddsc_entity, get_entities, .init = create_entity, .fini = delete_entity)
|
|||
par = dds_get_parent (0);
|
||||
CU_ASSERT_EQUAL_FATAL(par, DDS_RETCODE_BAD_PARAMETER);
|
||||
|
||||
/* Get Parent, a participant doesn't have a parent. */
|
||||
/* Get Parent, a participant always has a parent (the domain). */
|
||||
par = dds_get_parent (entity);
|
||||
CU_ASSERT_EQUAL_FATAL(par, DDS_ENTITY_NIL);
|
||||
CU_ASSERT_NOT_EQUAL_FATAL(par, DDS_HANDLE_NIL);
|
||||
/* The domain has a parent: the pseudo-entity for the library */
|
||||
par = dds_get_parent (par);
|
||||
CU_ASSERT_EQUAL_FATAL(par, DDS_CYCLONEDDS_HANDLE);
|
||||
|
||||
/* ---------- Get Participant ------------ */
|
||||
|
||||
|
|
|
|||
|
|
@ -313,7 +313,11 @@ CU_Test(ddsc_entity_get_parent, participant, .init=hierarchy_init, .fini=hierarc
|
|||
{
|
||||
dds_entity_t parent;
|
||||
parent = dds_get_parent(g_participant);
|
||||
CU_ASSERT_EQUAL_FATAL(parent, DDS_ENTITY_NIL);
|
||||
CU_ASSERT_NOT_EQUAL_FATAL(parent, DDS_ENTITY_NIL);
|
||||
parent = dds_get_parent(parent);
|
||||
CU_ASSERT_NOT_EQUAL_FATAL(parent, DDS_ENTITY_NIL);
|
||||
parent = dds_get_parent(parent);
|
||||
CU_ASSERT_NOT_EQUAL_FATAL(parent, DDS_CYCLONEDDS_HANDLE);
|
||||
}
|
||||
/*************************************************************************************************/
|
||||
|
||||
|
|
@ -362,13 +366,15 @@ CU_Test(ddsc_entity_get_children, null, .init=hierarchy_init, .fini=hierarchy_fi
|
|||
/*************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
#if SIZE_MAX > INT32_MAX
|
||||
CU_Test(ddsc_entity_get_children, invalid_size, .init=hierarchy_init, .fini=hierarchy_fini)
|
||||
{
|
||||
dds_return_t ret;
|
||||
dds_entity_t child;
|
||||
ret = dds_get_children(g_participant, &child, INT32_MAX);
|
||||
ret = dds_get_children(g_participant, &child, SIZE_MAX);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER);
|
||||
}
|
||||
#endif
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
|
@ -866,9 +872,8 @@ CU_Test(ddsc_entity_get_children, implicit_publisher)
|
|||
dds_delete(writer);
|
||||
|
||||
ret = dds_get_children(participant, child2, 2);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, 2);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, 1);
|
||||
CU_ASSERT_FATAL( (child2[0] == child[0]) || (child2[0] == child[1]) );
|
||||
CU_ASSERT_FATAL( (child2[1] == child[0]) || (child2[1] == child[1]) );
|
||||
|
||||
dds_delete(topic);
|
||||
dds_delete(participant);
|
||||
|
|
@ -911,9 +916,8 @@ CU_Test(ddsc_entity_get_children, implicit_subscriber)
|
|||
dds_delete(reader);
|
||||
|
||||
ret = dds_get_children(participant, child2, 2);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, 2);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, 1);
|
||||
CU_ASSERT_FATAL( (child2[0] == child[0]) || (child2[0] == child[1]) );
|
||||
CU_ASSERT_FATAL( (child2[1] == child[0]) || (child2[1] == child[1]) );
|
||||
|
||||
dds_delete(topic);
|
||||
dds_delete(participant);
|
||||
|
|
@ -947,7 +951,7 @@ CU_Test(ddsc_entity_get_parent, implicit_publisher)
|
|||
dds_delete(writer);
|
||||
|
||||
ret = dds_delete(parent);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER);
|
||||
dds_delete(participant);
|
||||
}
|
||||
/*************************************************************************************************/
|
||||
|
|
@ -978,7 +982,7 @@ CU_Test(ddsc_entity_get_parent, implicit_subscriber)
|
|||
dds_delete(reader);
|
||||
|
||||
ret = dds_delete(parent);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER);
|
||||
dds_delete(participant);
|
||||
|
||||
}
|
||||
|
|
|
|||
187
src/core/ddsc/tests/guardcondition.c
Normal file
187
src/core/ddsc/tests/guardcondition.c
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "dds/dds.h"
|
||||
#include "CUnit/Theory.h"
|
||||
#include "RoundTrip.h"
|
||||
|
||||
#include "dds/ddsrt/cdtors.h"
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/process.h"
|
||||
#include "dds/ddsrt/threads.h"
|
||||
#include "dds/ddsrt/atomics.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
|
||||
CU_Test (ddsc_guardcond_create, cyclonedds)
|
||||
{
|
||||
dds_entity_t gc;
|
||||
dds_return_t rc;
|
||||
/* Expect an uninitialised library */
|
||||
rc = dds_get_parent (DDS_CYCLONEDDS_HANDLE);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
gc = dds_create_guardcondition (DDS_CYCLONEDDS_HANDLE);
|
||||
CU_ASSERT_FATAL (gc > 0);
|
||||
rc = dds_delete (DDS_CYCLONEDDS_HANDLE);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
/* And the same afterward */
|
||||
rc = dds_get_parent (DDS_CYCLONEDDS_HANDLE);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
}
|
||||
|
||||
CU_Test (ddsc_guardcond_create, domain)
|
||||
{
|
||||
dds_entity_t par, dom, gc;
|
||||
dds_return_t rc;
|
||||
par = dds_create_participant (0, NULL, NULL);
|
||||
CU_ASSERT_FATAL (par > 0);
|
||||
dom = dds_get_parent (par);
|
||||
CU_ASSERT_FATAL (dom > 0);
|
||||
gc = dds_create_guardcondition (dom);
|
||||
CU_ASSERT_FATAL (gc > 0);
|
||||
rc = dds_delete (dom);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
}
|
||||
|
||||
CU_Test (ddsc_guardcond_create, participant)
|
||||
{
|
||||
dds_entity_t par, gc;
|
||||
dds_return_t rc;
|
||||
par = dds_create_participant (0, NULL, NULL);
|
||||
CU_ASSERT_FATAL (par > 0);
|
||||
gc = dds_create_guardcondition (par);
|
||||
CU_ASSERT_FATAL (gc > 0);
|
||||
rc = dds_delete (par);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
}
|
||||
|
||||
CU_Test (ddsc_guardcond, set_trigger)
|
||||
{
|
||||
dds_entity_t par, gc;
|
||||
dds_return_t rc;
|
||||
bool trig;
|
||||
par = dds_create_participant (0, NULL, NULL);
|
||||
CU_ASSERT_FATAL (par > 0);
|
||||
gc = dds_create_guardcondition (par);
|
||||
CU_ASSERT_FATAL (gc > 0);
|
||||
rc = dds_read_guardcondition (gc, &trig);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
CU_ASSERT (!trig);
|
||||
rc = dds_set_guardcondition (gc, true);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = dds_read_guardcondition (gc, &trig);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
CU_ASSERT (trig);
|
||||
rc = dds_delete (par);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
}
|
||||
|
||||
CU_Test (ddsc_guardcond, take_trigger)
|
||||
{
|
||||
dds_entity_t par, gc;
|
||||
dds_return_t rc;
|
||||
bool trig;
|
||||
par = dds_create_participant (0, NULL, NULL);
|
||||
CU_ASSERT_FATAL (par > 0);
|
||||
gc = dds_create_guardcondition (par);
|
||||
CU_ASSERT_FATAL (gc > 0);
|
||||
rc = dds_read_guardcondition (gc, &trig);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
CU_ASSERT (!trig);
|
||||
rc = dds_set_guardcondition (gc, true);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = dds_take_guardcondition (gc, &trig);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
CU_ASSERT (trig);
|
||||
rc = dds_read_guardcondition (gc, &trig);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
CU_ASSERT (!trig);
|
||||
rc = dds_delete (par);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
}
|
||||
|
||||
CU_Test (ddsc_guardcond, waitset)
|
||||
{
|
||||
dds_entity_t par, gc, ws;
|
||||
dds_attach_t xs[1];
|
||||
dds_return_t rc;
|
||||
par = dds_create_participant (0, NULL, NULL);
|
||||
CU_ASSERT_FATAL (par > 0);
|
||||
gc = dds_create_guardcondition (par);
|
||||
CU_ASSERT_FATAL (gc > 0);
|
||||
ws = dds_create_waitset (par);
|
||||
CU_ASSERT_FATAL (ws > 0);
|
||||
rc = dds_waitset_attach (ws, gc, gc);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
/* guard cond not triggered: waitset should return 0 */
|
||||
rc = dds_waitset_wait (ws, xs, 1, 0);
|
||||
CU_ASSERT (rc == 0);
|
||||
rc = dds_set_guardcondition (gc, true);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
/* guard triggered: waitset should return it */
|
||||
rc = dds_waitset_wait (ws, xs, 1, 0);
|
||||
CU_ASSERT (rc == 1);
|
||||
CU_ASSERT (xs[0] == gc);
|
||||
rc = dds_delete (par);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
}
|
||||
|
||||
struct guardcond_thread_arg {
|
||||
dds_entity_t gc;
|
||||
dds_return_t ret;
|
||||
};
|
||||
|
||||
static uint32_t guardcond_thread (void *varg)
|
||||
{
|
||||
struct guardcond_thread_arg *arg = varg;
|
||||
/* 200ms sleep is hopefully always long enough for the main thread to
|
||||
enter wait() and block; a further 1800ms (see wait call) similarly
|
||||
for the guard condition to actually trigger it. */
|
||||
dds_sleepfor (DDS_MSECS (200));
|
||||
arg->ret = dds_set_guardcondition (arg->gc, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CU_Test (ddsc_guardcond, waitset_thread)
|
||||
{
|
||||
dds_entity_t par, gc, ws;
|
||||
dds_attach_t xs[1];
|
||||
dds_return_t rc;
|
||||
ddsrt_thread_t tid;
|
||||
ddsrt_threadattr_t tattr;
|
||||
|
||||
par = dds_create_participant (0, NULL, NULL);
|
||||
CU_ASSERT_FATAL (par > 0);
|
||||
gc = dds_create_guardcondition (par);
|
||||
CU_ASSERT_FATAL (gc > 0);
|
||||
ws = dds_create_waitset (par);
|
||||
CU_ASSERT_FATAL (ws > 0);
|
||||
rc = dds_waitset_attach (ws, gc, gc);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
|
||||
struct guardcond_thread_arg arg = { .gc = gc };
|
||||
ddsrt_threadattr_init (&tattr);
|
||||
rc = ddsrt_thread_create (&tid, "guardcond_thread", &tattr, guardcond_thread, &arg);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
|
||||
rc = dds_waitset_wait (ws, xs, 1, DDS_SECS (2));
|
||||
CU_ASSERT (rc == 1);
|
||||
CU_ASSERT (xs[0] == gc);
|
||||
|
||||
rc = ddsrt_thread_join (tid, NULL);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
CU_ASSERT_FATAL (arg.ret == 0);
|
||||
|
||||
rc = dds_delete (par);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
}
|
||||
|
|
@ -132,6 +132,7 @@ CU_Test(ddsc_instance_get_key, registered_instance, .init=setup, .fini=teardown)
|
|||
ret = dds_instance_get_key(writer, handle, &key_data);
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(key_data.ip);
|
||||
assert (key_data.ip != NULL); /* for the benefit of clang's static analyzer */
|
||||
CU_ASSERT_STRING_EQUAL_FATAL(key_data.ip, data.ip);
|
||||
CU_ASSERT_EQUAL_FATAL(key_data.port, data.port);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
|
|
@ -162,6 +163,7 @@ CU_Test(ddsc_instance_get_key, readcondition, .init=setup, .fini=teardown)
|
|||
ret = dds_instance_get_key(readcondition, handle, &key_data);
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(key_data.ip);
|
||||
assert (key_data.ip != NULL); /* for the benefit of clang's static analyzer */
|
||||
CU_ASSERT_STRING_EQUAL_FATAL(key_data.ip, data.ip);
|
||||
CU_ASSERT_EQUAL_FATAL(key_data.port, data.port);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
|
|
@ -192,6 +194,7 @@ CU_Test(ddsc_instance_get_key, querycondition, .init=setup, .fini=teardown)
|
|||
ret = dds_instance_get_key(querycondition, handle, &key_data);
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(key_data.ip);
|
||||
assert (key_data.ip != NULL); /* for the benefit of clang's static analyzer */
|
||||
CU_ASSERT_STRING_EQUAL_FATAL(key_data.ip, data.ip);
|
||||
CU_ASSERT_EQUAL_FATAL(key_data.port, data.port);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
|
|
|
|||
|
|
@ -727,7 +727,9 @@ CU_Test(ddsc_listener, publication_matched, .init=init_triggering_test, .fini=fi
|
|||
CU_ASSERT_EQUAL_FATAL(publication_matched.last_subscription_handle, reader_hdl);
|
||||
|
||||
/* Reset the trigger flags. */
|
||||
ddsrt_mutex_lock(&g_mutex);
|
||||
cb_called = 0;
|
||||
ddsrt_mutex_unlock(&g_mutex);
|
||||
|
||||
/* Un-match the publication by deleting the reader. */
|
||||
dds_delete(g_reader);
|
||||
|
|
@ -789,7 +791,9 @@ CU_Test(ddsc_listener, subscription_matched, .init=init_triggering_test, .fini=f
|
|||
CU_ASSERT_EQUAL_FATAL(subscription_matched.last_publication_handle, writer_hdl);
|
||||
|
||||
/* Reset the trigger flags. */
|
||||
ddsrt_mutex_lock(&g_mutex);
|
||||
cb_called = 0;
|
||||
ddsrt_mutex_unlock(&g_mutex);
|
||||
|
||||
/* Un-match the subscription by deleting the writer. */
|
||||
dds_delete(g_writer);
|
||||
|
|
@ -903,8 +907,10 @@ CU_Test(ddsc_listener, data_available, .init=init_triggering_test, .fini=fini_tr
|
|||
|
||||
/* Deleting the writer causes unregisters (or dispose+unregister), and those
|
||||
should trigger DATA_AVAILABLE as well */
|
||||
ddsrt_mutex_lock(&g_mutex);
|
||||
cb_called = 0;
|
||||
cb_reader = 0;
|
||||
ddsrt_mutex_unlock(&g_mutex);
|
||||
ret = dds_delete (g_writer);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
g_writer = 0;
|
||||
|
|
@ -942,8 +948,10 @@ CU_Test(ddsc_listener, data_available_delete_writer, .init=init_triggering_test,
|
|||
CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader);
|
||||
|
||||
/* Deleting the writer must trigger DATA_AVAILABLE as well */
|
||||
ddsrt_mutex_lock(&g_mutex);
|
||||
cb_called = 0;
|
||||
cb_reader = 0;
|
||||
ddsrt_mutex_unlock(&g_mutex);
|
||||
ret = dds_delete (g_writer);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
g_writer = 0;
|
||||
|
|
@ -991,8 +999,10 @@ CU_Test(ddsc_listener, data_available_delete_writer_disposed, .init=init_trigger
|
|||
} while (ret > 0);
|
||||
|
||||
/* Deleting the writer should not trigger DATA_AVAILABLE with all instances empty & disposed */
|
||||
ddsrt_mutex_lock(&g_mutex);
|
||||
cb_called = 0;
|
||||
cb_reader = 0;
|
||||
ddsrt_mutex_unlock(&g_mutex);
|
||||
ret = dds_delete (g_writer);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
g_writer = 0;
|
||||
|
|
@ -1174,7 +1184,9 @@ CU_Test(ddsc_listener, liveliness_changed, .init=init_triggering_test, .fini=fin
|
|||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.last_publication_handle, writer_hdl);
|
||||
|
||||
/* Reset the trigger flags. */
|
||||
ddsrt_mutex_lock(&g_mutex);
|
||||
cb_called = 0;
|
||||
ddsrt_mutex_unlock(&g_mutex);
|
||||
|
||||
/* Change liveliness again by deleting the writer. */
|
||||
dds_delete(g_writer);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ CU_Test(ddsc_participant, create_with_no_conf_no_env)
|
|||
dds_domainid_t domain_id;
|
||||
dds_domainid_t valid_domain=3;
|
||||
|
||||
ddsrt_unsetenv(DDS_PROJECT_NAME_NOSPACE_CAPS"_URI");
|
||||
status = ddsrt_unsetenv(DDS_PROJECT_NAME_NOSPACE_CAPS"_URI");
|
||||
CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK);
|
||||
|
||||
//valid specific domain value
|
||||
participant2 = dds_create_participant (valid_domain, NULL, NULL);
|
||||
|
|
|
|||
|
|
@ -277,7 +277,50 @@ CU_Theory((dds_entity_t *par, dds_entity_t *top), ddsc_reader_create, non_partic
|
|||
}
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
CU_Test(ddsc_reader_create, wrong_participant, .init=reader_init, .fini=reader_fini)
|
||||
{
|
||||
dds_entity_t participant2 = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
|
||||
CU_ASSERT_FATAL(participant2 > 0);
|
||||
dds_entity_t reader = dds_create_reader(participant2, g_topic, NULL, NULL);
|
||||
CU_ASSERT_EQUAL_FATAL(reader, DDS_RETCODE_BAD_PARAMETER);
|
||||
dds_delete(participant2);
|
||||
}
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
CU_Test(ddsc_reader_create, participant_mismatch)
|
||||
{
|
||||
dds_entity_t par1 = 0;
|
||||
dds_entity_t par2 = 0;
|
||||
dds_entity_t sub1 = 0;
|
||||
dds_entity_t top2 = 0;
|
||||
dds_entity_t reader = 0;
|
||||
char name[100];
|
||||
|
||||
par1 = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
|
||||
CU_ASSERT_FATAL(par1 > 0);
|
||||
par2 = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
|
||||
CU_ASSERT_FATAL(par2 > 0);
|
||||
|
||||
sub1 = dds_create_subscriber(par1, NULL, NULL);
|
||||
CU_ASSERT_FATAL(sub1 > 0);
|
||||
|
||||
top2 = dds_create_topic(par2, &Space_Type1_desc, create_topic_name("ddsc_reader_participant_mismatch", name, sizeof name), NULL, NULL);
|
||||
CU_ASSERT_FATAL(top2 > 0);
|
||||
|
||||
/* Create reader with participant mismatch. */
|
||||
reader = dds_create_reader(sub1, top2, NULL, NULL);
|
||||
|
||||
/* Expect the creation to have failed. */
|
||||
CU_ASSERT_FATAL(reader <= 0);
|
||||
|
||||
dds_delete(top2);
|
||||
dds_delete(sub1);
|
||||
dds_delete(par2);
|
||||
dds_delete(par1);
|
||||
}
|
||||
/*************************************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -256,6 +256,39 @@ CU_Theory((dds_entity_t *par), ddsc_waitset_create, non_participants, .init=ddsc
|
|||
}
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
CU_Test (ddsc_waitset_create, domain)
|
||||
{
|
||||
dds_entity_t par, dom, ws;
|
||||
dds_return_t rc;
|
||||
par = dds_create_participant (0, NULL, NULL);
|
||||
CU_ASSERT_FATAL (par > 0);
|
||||
dom = dds_get_parent (par);
|
||||
CU_ASSERT_FATAL (dom > 0);
|
||||
ws = dds_create_waitset (dom);
|
||||
CU_ASSERT_FATAL (ws > 0);
|
||||
rc = dds_delete (dom);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
}
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
CU_Test (ddsc_waitset_create, cyclonedds)
|
||||
{
|
||||
dds_entity_t ws;
|
||||
dds_return_t rc;
|
||||
/* Expect an uninitialised library */
|
||||
rc = dds_get_parent (DDS_CYCLONEDDS_HANDLE);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
ws = dds_create_waitset (DDS_CYCLONEDDS_HANDLE);
|
||||
CU_ASSERT_FATAL (ws > 0);
|
||||
rc = dds_delete (DDS_CYCLONEDDS_HANDLE);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
/* And the same afterward */
|
||||
rc = dds_get_parent (DDS_CYCLONEDDS_HANDLE);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
}
|
||||
/*************************************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
|
|
@ -318,6 +351,52 @@ CU_Test(ddsc_waitset_attach, deleted_waitset, .init=ddsc_waitset_basic_init, .fi
|
|||
}
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
CU_TheoryDataPoints(ddsc_waitset_attach, scoping) = {
|
||||
CU_DataPoints (int, -9, -1, -2, 0, 0, 2), /* owner: -9: lib, -1: dom0, -2: dom1 */
|
||||
CU_DataPoints (int, 0, 0, 2, 0, 0, 2), /* ok1: participant one can attach */
|
||||
CU_DataPoints (int, 3, 1, 3, -1, -1, -1), /* ok2: other participant one can attach, or -1 */
|
||||
CU_DataPoints (int, -1, 2, 0, 1, 2, 0), /* fail: participant that one cannot attach, or -1 */
|
||||
};
|
||||
CU_Theory ((int owner, int ok1, int ok2, int fail), ddsc_waitset_attach, scoping)
|
||||
{
|
||||
dds_entity_t par[4], dom[2], ws, ownh;
|
||||
dds_return_t rc;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
par[2*i+j] = dds_create_participant ((dds_domainid_t) i, NULL, NULL);
|
||||
CU_ASSERT_FATAL (par[2*i+j] > 0);
|
||||
}
|
||||
dom[i] = dds_get_parent (par[2*i]);
|
||||
CU_ASSERT_FATAL (dom[i] > 0);
|
||||
}
|
||||
if (owner == -9) {
|
||||
ownh = DDS_CYCLONEDDS_HANDLE;
|
||||
} else if (owner < 0) {
|
||||
ownh = dom[-owner - 1];
|
||||
} else {
|
||||
ownh = par[owner];
|
||||
}
|
||||
printf ("%d %d %d %d | %"PRId32"\n", owner, ok1, ok2, fail, ownh);
|
||||
ws = dds_create_waitset (ownh);
|
||||
CU_ASSERT_FATAL (ws > 0);
|
||||
rc = dds_waitset_attach (ws, par[ok1], 0);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
if (ok2 >= 0) {
|
||||
rc = dds_waitset_attach (ws, par[ok2], 1);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
}
|
||||
if (fail >= 0) {
|
||||
rc = dds_waitset_attach (ws, par[fail], 2);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_BAD_PARAMETER);
|
||||
}
|
||||
rc = dds_delete (DDS_CYCLONEDDS_HANDLE);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = dds_get_parent (DDS_CYCLONEDDS_HANDLE);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
}
|
||||
/*************************************************************************************************/
|
||||
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
|
|
|
|||
398
src/core/ddsc/tests/waitset_torture.c
Normal file
398
src/core/ddsc/tests/waitset_torture.c
Normal file
|
|
@ -0,0 +1,398 @@
|
|||
/*
|
||||
* Copyright(c) 2019 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "dds/dds.h"
|
||||
#include "CUnit/Theory.h"
|
||||
#include "RoundTrip.h"
|
||||
|
||||
#include "dds/ddsrt/cdtors.h"
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/process.h"
|
||||
#include "dds/ddsrt/threads.h"
|
||||
#include "dds/ddsrt/atomics.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
#include "dds/ddsrt/random.h"
|
||||
|
||||
#define N_WAITSETS 20
|
||||
#define N_ENTITIES 32
|
||||
|
||||
#define N_GUARDCONDS 20
|
||||
#define N_SUBSCRIBERS 4
|
||||
#define N_READERS 4
|
||||
#define N_READCONDS 4
|
||||
|
||||
static dds_entity_t ppant;
|
||||
static dds_entity_t topic;
|
||||
|
||||
static ddsrt_atomic_uint32_t terminate;
|
||||
static ddsrt_atomic_uint32_t waitsets[N_WAITSETS];
|
||||
static ddsrt_atomic_uint32_t entities[N_ENTITIES], signalled;
|
||||
|
||||
static ddsrt_atomic_uint32_t attach_ok, detach_ok, settrig_ok;
|
||||
static ddsrt_atomic_uint32_t create_ent_ok[5], delete_ent_ok[5];
|
||||
static ddsrt_atomic_uint32_t create_ws_ok, delete_ws_ok;
|
||||
|
||||
#define RESERVED ((uint32_t) 0xffffffffu)
|
||||
|
||||
static void init_prng (ddsrt_prng_t *prng)
|
||||
{
|
||||
ddsrt_prng_seed_t prng_seed;
|
||||
for (size_t i = 0; i < sizeof (prng_seed.key) / sizeof (prng_seed.key[0]); i++)
|
||||
prng_seed.key[i] = ddsrt_random ();
|
||||
ddsrt_prng_init (prng, &prng_seed);
|
||||
}
|
||||
|
||||
static void choose_index (uint32_t *p_idx, uint32_t *p_handle, ddsrt_prng_t *prng, ddsrt_atomic_uint32_t elems[], size_t nelems)
|
||||
{
|
||||
uint32_t idx, h, h1;
|
||||
retry_idx:
|
||||
idx = ddsrt_prng_random (prng) % (uint32_t) nelems;
|
||||
retry_cas:
|
||||
h = ddsrt_atomic_ld32 (&elems[idx]);
|
||||
if (h == 0)
|
||||
h1 = RESERVED;
|
||||
else if ((int32_t) h > 0)
|
||||
h1 = 0;
|
||||
else
|
||||
goto retry_idx;
|
||||
if (!ddsrt_atomic_cas32 (&elems[idx], h, h1))
|
||||
goto retry_cas;
|
||||
*p_idx = idx;
|
||||
*p_handle = h;
|
||||
}
|
||||
|
||||
static dds_entity_t pick_a_subscriber (void)
|
||||
{
|
||||
uint32_t idx = ddsrt_random () % N_SUBSCRIBERS;
|
||||
uint32_t x = ddsrt_atomic_ld32 (&entities[N_GUARDCONDS + idx]);
|
||||
return (dds_entity_t) x;
|
||||
}
|
||||
|
||||
static dds_entity_t pick_a_reader (void)
|
||||
{
|
||||
uint32_t idx = ddsrt_random () % N_READERS;
|
||||
uint32_t x = ddsrt_atomic_ld32 (&entities[N_GUARDCONDS + N_SUBSCRIBERS + idx]);
|
||||
return (dds_entity_t) x;
|
||||
}
|
||||
|
||||
static int index_to_counter_index (uint32_t idx)
|
||||
{
|
||||
if (idx < N_GUARDCONDS)
|
||||
return 0;
|
||||
else if (idx < N_GUARDCONDS + N_SUBSCRIBERS)
|
||||
return 1;
|
||||
else if (idx < N_GUARDCONDS + N_SUBSCRIBERS + N_READERS)
|
||||
return 2;
|
||||
else
|
||||
return 4;
|
||||
}
|
||||
|
||||
static uint32_t guardcond_create_delete_thread (void *varg)
|
||||
{
|
||||
(void) varg;
|
||||
ddsrt_prng_t prng;
|
||||
init_prng (&prng);
|
||||
while (!ddsrt_atomic_ld32 (&terminate))
|
||||
{
|
||||
uint32_t idx, handle;
|
||||
choose_index (&idx, &handle, &prng, entities, N_ENTITIES);
|
||||
if (handle == 0)
|
||||
{
|
||||
dds_entity_t ent = 0, parent = 0;
|
||||
|
||||
if (idx < N_GUARDCONDS)
|
||||
ent = dds_create_guardcondition (DDS_CYCLONEDDS_HANDLE);
|
||||
else if (idx < N_GUARDCONDS + N_SUBSCRIBERS)
|
||||
ent = dds_create_subscriber (ppant, NULL, NULL);
|
||||
else if (idx < N_GUARDCONDS + N_SUBSCRIBERS + N_READERS)
|
||||
{
|
||||
if ((parent = pick_a_subscriber ()) == 0)
|
||||
parent = ppant;
|
||||
ent = dds_create_reader (parent, topic, NULL, NULL);
|
||||
}
|
||||
else if ((parent = pick_a_reader ()) != 0)
|
||||
{
|
||||
ent = dds_create_readcondition (parent, DDS_ANY_STATE);
|
||||
}
|
||||
|
||||
if (ent > 0)
|
||||
{
|
||||
ddsrt_atomic_inc32 (&create_ent_ok[index_to_counter_index (idx) + (parent == ppant)]);
|
||||
ddsrt_atomic_st32 (&entities[idx], (uint32_t) ent);
|
||||
}
|
||||
else if (ent < 0 && idx < N_GUARDCONDS)
|
||||
{
|
||||
fprintf (stderr, "dds_create_guardcondition failed: %s\n", dds_strretcode (ent));
|
||||
ddsrt_atomic_st32 (&terminate, 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dds_return_t rc = dds_delete ((dds_entity_t) handle);
|
||||
if (rc == 0)
|
||||
ddsrt_atomic_inc32 (&delete_ent_ok[index_to_counter_index (idx)]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t waitset_create_delete_thread (void *varg)
|
||||
{
|
||||
(void) varg;
|
||||
ddsrt_prng_t prng;
|
||||
init_prng (&prng);
|
||||
while (!ddsrt_atomic_ld32 (&terminate))
|
||||
{
|
||||
uint32_t idx, handle;
|
||||
choose_index (&idx, &handle, &prng, waitsets, N_WAITSETS);
|
||||
if (handle == 0)
|
||||
{
|
||||
dds_entity_t ws = dds_create_waitset (DDS_CYCLONEDDS_HANDLE);
|
||||
if (ws < 0)
|
||||
{
|
||||
fprintf (stderr, "dds_create_waitset failed: %s\n", dds_strretcode (ws));
|
||||
ddsrt_atomic_st32 (&terminate, 1);
|
||||
return 1;
|
||||
}
|
||||
ddsrt_atomic_inc32 (&create_ws_ok);
|
||||
ddsrt_atomic_st32 (&waitsets[idx], (uint32_t) ws);
|
||||
}
|
||||
else
|
||||
{
|
||||
dds_return_t rc = dds_delete ((dds_entity_t) handle);
|
||||
if (rc == 0)
|
||||
ddsrt_atomic_inc32 (&delete_ws_ok);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t guardcond_trigger_thread (void *varg)
|
||||
{
|
||||
(void) varg;
|
||||
ddsrt_prng_t prng;
|
||||
init_prng (&prng);
|
||||
while (!ddsrt_atomic_ld32 (&terminate))
|
||||
{
|
||||
uint32_t idx = ddsrt_prng_random (&prng) % N_ENTITIES;
|
||||
uint32_t h = ddsrt_atomic_ld32 (&entities[idx]);
|
||||
if ((int32_t) h <= 0)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
uint32_t s, s1;
|
||||
do {
|
||||
s = ddsrt_atomic_ld32 (&signalled);
|
||||
s1 = s ^ (1u << idx);
|
||||
} while (!ddsrt_atomic_cas32 (&signalled, s, s1));
|
||||
dds_return_t rc = dds_set_guardcondition ((dds_entity_t) h, (s & (1u << idx)) ? false : true);
|
||||
if (rc == 0)
|
||||
ddsrt_atomic_inc32 (&settrig_ok);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t waitset_attach_detach_thread (void *varg)
|
||||
{
|
||||
(void) varg;
|
||||
ddsrt_prng_t prng;
|
||||
init_prng (&prng);
|
||||
while (!ddsrt_atomic_ld32 (&terminate))
|
||||
{
|
||||
uint32_t wsidx = ddsrt_prng_random (&prng) % N_WAITSETS;
|
||||
uint32_t wsh = ddsrt_atomic_ld32 (&waitsets[wsidx]);
|
||||
if ((int32_t) wsh <= 0)
|
||||
continue;
|
||||
|
||||
uint32_t gcidx = ddsrt_prng_random (&prng) % N_ENTITIES;
|
||||
uint32_t gch = ddsrt_atomic_ld32 (&entities[gcidx]);
|
||||
if ((int32_t) gch <= 0)
|
||||
continue;
|
||||
|
||||
dds_return_t rc;
|
||||
rc = dds_waitset_detach ((dds_entity_t) wsh, (dds_entity_t) gch);
|
||||
if (rc == 0)
|
||||
{
|
||||
ddsrt_atomic_inc32 (&detach_ok);
|
||||
}
|
||||
else if (rc != DDS_RETCODE_PRECONDITION_NOT_MET && rc != DDS_RETCODE_BAD_PARAMETER)
|
||||
{
|
||||
/* attempts at attaching a guard condition twice or detaching an unattached
|
||||
one are expected, and those result in a PRECONDITION_NOT_MET */
|
||||
fprintf (stderr, "dds_waitset_detach 0x%"PRIx32" 0x%"PRIx32" failed: %s\n", (dds_entity_t) wsh, (dds_entity_t) gch, dds_strretcode (rc));
|
||||
ddsrt_atomic_st32 (&terminate, 1);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* should imply it is already attached, so try detaching */
|
||||
rc = dds_waitset_attach ((dds_entity_t) wsh, (dds_entity_t) gch, 0);
|
||||
if (rc == 0)
|
||||
{
|
||||
ddsrt_atomic_inc32 (&attach_ok);
|
||||
}
|
||||
else if (rc != DDS_RETCODE_PRECONDITION_NOT_MET && rc != DDS_RETCODE_BAD_PARAMETER)
|
||||
{
|
||||
fprintf (stderr, "dds_waitset_attach 0x%"PRIx32" 0x%"PRIx32" failed: %s\n", (dds_entity_t) wsh, (dds_entity_t) gch, dds_strretcode (rc));
|
||||
ddsrt_atomic_st32 (&terminate, 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
CU_Test (ddsc_waitset, torture)
|
||||
{
|
||||
dds_return_t rc;
|
||||
ddsrt_thread_t tids[8];
|
||||
ddsrt_threadattr_t tattr;
|
||||
ddsrt_threadattr_init (&tattr);
|
||||
|
||||
/* This keeps the library initialised -- it shouldn't be necessary */
|
||||
ppant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
|
||||
CU_ASSERT_FATAL (ppant > 0);
|
||||
topic = dds_create_topic (ppant, &RoundTripModule_DataType_desc, "waitset_torture_topic", NULL, NULL);
|
||||
CU_ASSERT_FATAL (topic > 0);
|
||||
|
||||
rc = ddsrt_thread_create (&tids[0], "gc_cd", &tattr, guardcond_create_delete_thread, 0);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = ddsrt_thread_create (&tids[1], "gc_cd", &tattr, guardcond_create_delete_thread, 0);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = ddsrt_thread_create (&tids[2], "ws_cd", &tattr, waitset_create_delete_thread, 0);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = ddsrt_thread_create (&tids[3], "ws_cd", &tattr, waitset_create_delete_thread, 0);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = ddsrt_thread_create (&tids[4], "gc_t", &tattr, guardcond_trigger_thread, 0);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = ddsrt_thread_create (&tids[5], "gc_t", &tattr, guardcond_trigger_thread, 0);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = ddsrt_thread_create (&tids[6], "ws_ad", &tattr, waitset_attach_detach_thread, 0);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = ddsrt_thread_create (&tids[7], "ws_ad", &tattr, waitset_attach_detach_thread, 0);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
|
||||
uint32_t wait_err = 0, wait_ok[N_ENTITIES + 1] = { 0 };
|
||||
dds_time_t tstop = dds_time () + DDS_SECS (5);
|
||||
while (dds_time () < tstop && !ddsrt_atomic_ld32 (&terminate))
|
||||
{
|
||||
/* Try waiting on the waitset in slot 0 if it exists (it shouldn't make much
|
||||
difference which waitset we use; this is easy). There are never more than
|
||||
N_ENTITIES guard conditions, so there are also never more than that many
|
||||
triggering entities, and so we can easily do a small histogram. (The longer
|
||||
you run it, the longer the tail of triggering entities one expects.)
|
||||
|
||||
Error handling: the waitset may be deleted in between loading the handle
|
||||
and pinning it wait(), so BAD_PARAMETER is to be expected. If the "extragc"
|
||||
isn't there to ensure the library stays initialised, it is even possible
|
||||
that we get PRECONDITION_NOT_MET if it just so happened that with the
|
||||
deleting of that waitset, no entities remain at all. */
|
||||
dds_entity_t ws = (dds_entity_t) ddsrt_atomic_ld32 (&waitsets[0]);
|
||||
if (ws > 0)
|
||||
{
|
||||
int32_t n = dds_waitset_wait (ws, NULL, 0, DDS_MSECS (10));
|
||||
if (!((rc >= 0 && rc <= N_ENTITIES) || rc == DDS_RETCODE_BAD_PARAMETER))
|
||||
{
|
||||
fprintf (stderr, "dds_waitset_wait failed: %s\n", dds_strretcode (rc));
|
||||
ddsrt_atomic_st32 (&terminate, 1);
|
||||
rc = DDS_RETCODE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n >= 0)
|
||||
wait_ok[n]++;
|
||||
else
|
||||
wait_err++;
|
||||
}
|
||||
}
|
||||
}
|
||||
ddsrt_atomic_st32 (&terminate, 1);
|
||||
CU_ASSERT (rc != DDS_RETCODE_ERROR);
|
||||
|
||||
for (size_t i = 0; i < sizeof (tids) / sizeof (tids[0]); i++)
|
||||
{
|
||||
uint32_t retval;
|
||||
rc = ddsrt_thread_join (tids[i], &retval);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
CU_ASSERT (retval == 0);
|
||||
}
|
||||
|
||||
/* The threads don't bother to clean up, so delete whatever guard conditions and
|
||||
waitsets happen to still exist. Passing garbage into dds_delete is supposed
|
||||
to work, so don't bother with any validation or error checking. */
|
||||
for (uint32_t i = 0; i < N_ENTITIES; i++)
|
||||
{
|
||||
if (dds_delete ((dds_entity_t) ddsrt_atomic_ld32 (&entities[i])) == DDS_RETCODE_OK)
|
||||
ddsrt_atomic_inc32 (&delete_ent_ok[index_to_counter_index (i)]);
|
||||
}
|
||||
for (uint32_t i = 0; i < N_WAITSETS; i++)
|
||||
{
|
||||
if (dds_delete ((dds_entity_t) ddsrt_atomic_ld32 (&waitsets[i])) == DDS_RETCODE_OK)
|
||||
ddsrt_atomic_inc32 (&delete_ws_ok);
|
||||
}
|
||||
|
||||
/* All we should be left within the participant is the topic */
|
||||
rc = dds_delete (topic);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_OK);
|
||||
rc = dds_get_children (ppant, NULL, 0);
|
||||
CU_ASSERT_FATAL (rc == 0);
|
||||
rc = dds_delete (ppant);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_OK);
|
||||
|
||||
printf ("attach %"PRIu32" detach %"PRIu32" settrig %"PRIu32"\n", ddsrt_atomic_ld32 (&attach_ok), ddsrt_atomic_ld32 (&detach_ok), ddsrt_atomic_ld32 (&settrig_ok));
|
||||
printf ("create/delete ent");
|
||||
uint32_t create_ent_ok_sum = 0;
|
||||
for (size_t i = 0; i < sizeof (create_ent_ok) / sizeof (create_ent_ok[0]); i++)
|
||||
{
|
||||
uint32_t c = ddsrt_atomic_ld32 (&create_ent_ok[i]);
|
||||
create_ent_ok_sum += c;
|
||||
printf (" %"PRIu32"/%"PRIu32, c, ddsrt_atomic_ld32 (&delete_ent_ok[i]));
|
||||
}
|
||||
printf ("\n");
|
||||
|
||||
{
|
||||
uint32_t rd_cr_sub = ddsrt_atomic_ld32 (&create_ent_ok[2]);
|
||||
uint32_t rd_cr_ppant = ddsrt_atomic_ld32 (&create_ent_ok[3]);
|
||||
uint32_t rd_del = ddsrt_atomic_ld32 (&delete_ent_ok[2]);
|
||||
uint32_t sub_del = ddsrt_atomic_ld32 (&delete_ent_ok[1]);
|
||||
CU_ASSERT (rd_del <= rd_cr_sub + rd_cr_ppant); /* can't have deleted more readers than were created */
|
||||
CU_ASSERT (rd_del >= rd_cr_ppant); /* readers created with ppant as owner must have been deleted explicitly */
|
||||
CU_ASSERT (rd_del - rd_cr_ppant <= sub_del); /* other readers may have been deleted by deleting a sub */
|
||||
}
|
||||
|
||||
printf ("create/delete ws %"PRIu32"/%"PRIu32"\n", ddsrt_atomic_ld32 (&create_ws_ok), ddsrt_atomic_ld32 (&delete_ws_ok));
|
||||
printf ("wait {err %"PRIu32"}", wait_err);
|
||||
uint32_t wait_ok_sum = 0;
|
||||
for (size_t i = 0; i < sizeof (wait_ok) / sizeof (wait_ok[0]); i++)
|
||||
{
|
||||
wait_ok_sum += wait_ok[i];
|
||||
printf (" %"PRIu32, wait_ok[i]);
|
||||
}
|
||||
printf ("\n");
|
||||
|
||||
/* Running on Windows on the CI infrastructure has very little concurrency, but Linux
|
||||
and macOS seem ok. The thresholds here appear to be sufficiently low to not give
|
||||
many spurious failures, while still being sanity check that at least something
|
||||
happened. */
|
||||
CU_ASSERT (ddsrt_atomic_ld32 (&attach_ok) +
|
||||
ddsrt_atomic_ld32 (&settrig_ok) +
|
||||
ddsrt_atomic_ld32 (&create_ws_ok) +
|
||||
create_ent_ok_sum +
|
||||
wait_ok_sum > 1000);
|
||||
|
||||
rc = dds_get_parent (DDS_CYCLONEDDS_HANDLE);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
}
|
||||
|
|
@ -72,6 +72,15 @@ CU_Test(ddsc_create_writer, participant, .init = setup, .fini = teardown)
|
|||
CU_ASSERT_FATAL(writer > 0);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_create_writer, wrong_participant, .init = setup, .fini = teardown)
|
||||
{
|
||||
dds_entity_t participant2 = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
|
||||
CU_ASSERT_FATAL(participant2 > 0);
|
||||
writer = dds_create_writer(participant2, topic, NULL, NULL);
|
||||
CU_ASSERT_EQUAL_FATAL(writer, DDS_RETCODE_BAD_PARAMETER);
|
||||
dds_delete(participant2);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_create_writer, publisher, .init = setup, .fini = teardown)
|
||||
{
|
||||
writer = dds_create_writer(publisher, topic, NULL, NULL);
|
||||
|
|
@ -107,3 +116,27 @@ CU_Test(ddsc_create_writer, deleted_topic, .init = setup, .fini = teardown)
|
|||
writer = dds_create_writer(publisher, topic, NULL, NULL);
|
||||
CU_ASSERT_EQUAL_FATAL(writer, DDS_RETCODE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
|
||||
CU_Test(ddsc_create_writer, participant_mismatch, .init = setup, .fini = teardown)
|
||||
{
|
||||
dds_entity_t l_par = 0;
|
||||
dds_entity_t l_pub = 0;
|
||||
|
||||
/* The call to setup() created the global topic. */
|
||||
|
||||
/* Create publisher on local participant. */
|
||||
l_par = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
|
||||
CU_ASSERT_FATAL(l_par > 0);
|
||||
l_pub = dds_create_publisher(l_par, NULL, NULL);
|
||||
CU_ASSERT_FATAL(l_pub > 0);
|
||||
|
||||
/* Create writer with local publisher and global topic. */
|
||||
writer = dds_create_writer(l_pub, topic, NULL, NULL);
|
||||
|
||||
/* Expect the creation to have failed. */
|
||||
CU_ASSERT_FATAL(writer <= 0);
|
||||
|
||||
dds_delete(l_pub);
|
||||
dds_delete(l_par);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src"
|
|||
ddsi_tkmap.c
|
||||
ddsi_vendor.c
|
||||
ddsi_threadmon.c
|
||||
ddsi_rhc.c
|
||||
q_addrset.c
|
||||
q_bitset_inlines.c
|
||||
q_bswap.c
|
||||
|
|
@ -53,7 +54,6 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src"
|
|||
q_transmit.c
|
||||
q_inverse_uint32_set.c
|
||||
q_whc.c
|
||||
q_rhc.c
|
||||
q_xevent.c
|
||||
q_xmsg.c
|
||||
q_freelist.c
|
||||
|
|
@ -70,6 +70,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi"
|
|||
ddsi_raweth.h
|
||||
ddsi_ipaddr.h
|
||||
ddsi_mcgroup.h
|
||||
ddsi_plist_generic.h
|
||||
ddsi_serdata.h
|
||||
ddsi_sertopic.h
|
||||
ddsi_serdata_default.h
|
||||
|
|
@ -78,6 +79,8 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi"
|
|||
ddsi_vendor.h
|
||||
ddsi_threadmon.h
|
||||
ddsi_builtin_topic_if.h
|
||||
ddsi_rhc.h
|
||||
ddsi_guid.h
|
||||
q_addrset.h
|
||||
q_bitset.h
|
||||
q_bswap.h
|
||||
|
|
@ -102,7 +105,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi"
|
|||
q_qosmatch.h
|
||||
q_radmin.h
|
||||
q_receive.h
|
||||
q_rhc.h
|
||||
q_rtps.h
|
||||
q_security.h
|
||||
q_sockwaitset.h
|
||||
|
|
@ -128,3 +130,8 @@ install(
|
|||
DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include/dds"
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT dev)
|
||||
|
||||
# TODO: improve test inclusion.
|
||||
if((BUILD_TESTING) AND ((NOT DEFINED MSVC_VERSION) OR (MSVC_VERSION GREATER "1800")))
|
||||
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/tests")
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -22,24 +22,24 @@ extern "C" {
|
|||
struct entity_common;
|
||||
struct ddsi_tkmap_instance;
|
||||
struct ddsi_sertopic;
|
||||
struct nn_guid;
|
||||
struct ddsi_guid;
|
||||
|
||||
struct ddsi_builtin_topic_interface {
|
||||
void *arg;
|
||||
|
||||
bool (*builtintopic_is_builtintopic) (const struct ddsi_sertopic *topic, void *arg);
|
||||
bool (*builtintopic_is_visible) (const struct nn_guid *guid, nn_vendorid_t vendorid, void *arg);
|
||||
struct ddsi_tkmap_instance * (*builtintopic_get_tkmap_entry) (const struct nn_guid *guid, void *arg);
|
||||
bool (*builtintopic_is_visible) (const struct ddsi_guid *guid, nn_vendorid_t vendorid, void *arg);
|
||||
struct ddsi_tkmap_instance * (*builtintopic_get_tkmap_entry) (const struct ddsi_guid *guid, void *arg);
|
||||
void (*builtintopic_write) (const struct entity_common *e, nn_wctime_t timestamp, bool alive, void *arg);
|
||||
};
|
||||
|
||||
inline bool builtintopic_is_visible (const struct ddsi_builtin_topic_interface *btif, const struct nn_guid *guid, nn_vendorid_t vendorid) {
|
||||
inline bool builtintopic_is_visible (const struct ddsi_builtin_topic_interface *btif, const struct ddsi_guid *guid, nn_vendorid_t vendorid) {
|
||||
return btif ? btif->builtintopic_is_visible (guid, vendorid, btif->arg) : false;
|
||||
}
|
||||
inline bool builtintopic_is_builtintopic (const struct ddsi_builtin_topic_interface *btif, const struct ddsi_sertopic *topic) {
|
||||
return btif ? btif->builtintopic_is_builtintopic (topic, btif->arg) : false;
|
||||
}
|
||||
inline struct ddsi_tkmap_instance *builtintopic_get_tkmap_entry (const struct ddsi_builtin_topic_interface *btif, const struct nn_guid *guid) {
|
||||
inline struct ddsi_tkmap_instance *builtintopic_get_tkmap_entry (const struct ddsi_builtin_topic_interface *btif, const struct ddsi_guid *guid) {
|
||||
return btif ? btif->builtintopic_get_tkmap_entry (guid, btif->arg) : NULL;
|
||||
}
|
||||
inline void builtintopic_write (const struct ddsi_builtin_topic_interface *btif, const struct entity_common *e, nn_wctime_t timestamp, bool alive) {
|
||||
|
|
|
|||
37
src/core/ddsi/include/dds/ddsi/ddsi_guid.h
Normal file
37
src/core/ddsi/include/dds/ddsi/ddsi_guid.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright(c) 2019 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSI_GUID_H
|
||||
#define DDSI_GUID_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef union ddsi_guid_prefix {
|
||||
unsigned char s[12];
|
||||
uint32_t u[3];
|
||||
} ddsi_guid_prefix_t;
|
||||
typedef union ddsi_entityid {
|
||||
uint32_t u;
|
||||
} ddsi_entityid_t;
|
||||
typedef struct ddsi_guid {
|
||||
ddsi_guid_prefix_t prefix;
|
||||
ddsi_entityid_t entityid;
|
||||
} ddsi_guid_t;
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
67
src/core/ddsi/include/dds/ddsi/ddsi_plist_generic.h
Normal file
67
src/core/ddsi/include/dds/ddsi/ddsi_plist_generic.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright(c) 2019 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSI_PLIST_GENERIC_H
|
||||
#define DDSI_PLIST_GENERIC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "dds/export.h"
|
||||
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Instructions for the generic serializer (&c) that handles most parameters.
|
||||
The "packed" attribute means single-byte instructions on GCC and Clang. */
|
||||
enum pserop {
|
||||
XSTOP,
|
||||
XO, /* octet sequence */
|
||||
XS, /* string */
|
||||
XE1, XE2, XE3, /* enum 0..1, 0..2, 0..3 */
|
||||
Xi, Xix2, Xix3, Xix4, /* int32_t, 1 .. 4 in a row */
|
||||
Xu, Xux2, Xux3, Xux4, Xux5, /* uint32_t, 1 .. 5 in a row */
|
||||
XD, XDx2, /* duration, 1 .. 2 in a row */
|
||||
Xo, Xox2, /* octet, 1 .. 2 in a row */
|
||||
Xb, Xbx2, /* boolean, 1 .. 2 in a row */
|
||||
XbCOND, /* boolean: compare to ignore remainder if false (for use_... flags) */
|
||||
XbPROP, /* boolean: omit in serialized form; skip serialization if false; always true on deserialize */
|
||||
XG, /* GUID */
|
||||
XK, /* keyhash */
|
||||
XQ, /* arbitary non-nested sequence */
|
||||
Xopt, /* remainder is optional on deser, 0-init if not present */
|
||||
} ddsrt_attribute_packed;
|
||||
|
||||
inline bool pserop_seralign_is_1 (enum pserop op) {
|
||||
/* NB: XbPROP is never serialized, so its alignment is irrelevant. If ever there
|
||||
is a need to allow calling this function when op = XbPROP, it needs to be changed
|
||||
to taking the address of the pserop, and in that case inspect the following
|
||||
operator */
|
||||
assert (op != XbPROP && op != Xopt && op != XSTOP);
|
||||
return (op >= Xo && op <= XK);
|
||||
}
|
||||
|
||||
DDS_EXPORT void plist_fini_generic (void * __restrict dst, const enum pserop *desc, bool aliased);
|
||||
DDS_EXPORT dds_return_t plist_deser_generic (void * __restrict dst, const void * __restrict src, size_t srcsize, bool bswap, const enum pserop * __restrict desc);
|
||||
DDS_EXPORT dds_return_t plist_ser_generic (void **dst, size_t *dstsize, const void *src, const enum pserop * __restrict desc);
|
||||
DDS_EXPORT dds_return_t plist_unalias_generic (void * __restrict dst, const enum pserop * __restrict desc);
|
||||
DDS_EXPORT bool plist_equal_generic (const void *srcx, const void *srcy, const enum pserop * __restrict desc);
|
||||
DDS_EXPORT size_t plist_memsize_generic (const enum pserop * __restrict desc);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
81
src/core/ddsi/include/dds/ddsi/ddsi_rhc.h
Normal file
81
src/core/ddsi/include/dds/ddsi/ddsi_rhc.h
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSI_RHC_H
|
||||
#define DDSI_RHC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "dds/export.h"
|
||||
|
||||
/* DDS_EXPORT inline i.c.w. __attributes__((visibility...)) and some compilers: */
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
#include "dds/ddsi/ddsi_guid.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct dds_qos;
|
||||
struct ddsi_rhc;
|
||||
struct ddsi_tkmap_instance;
|
||||
struct ddsi_serdata;
|
||||
struct ddsi_sertopic;
|
||||
|
||||
struct ddsi_writer_info
|
||||
{
|
||||
ddsi_guid_t guid;
|
||||
bool auto_dispose;
|
||||
int32_t ownership_strength;
|
||||
uint64_t iid;
|
||||
};
|
||||
|
||||
typedef void (*ddsi_rhc_free_t) (struct ddsi_rhc *rhc);
|
||||
typedef bool (*ddsi_rhc_store_t) (struct ddsi_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk);
|
||||
typedef void (*ddsi_rhc_unregister_wr_t) (struct ddsi_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo);
|
||||
typedef void (*ddsi_rhc_relinquish_ownership_t) (struct ddsi_rhc * __restrict rhc, const uint64_t wr_iid);
|
||||
typedef void (*ddsi_rhc_set_qos_t) (struct ddsi_rhc *rhc, const struct dds_qos *qos);
|
||||
|
||||
struct ddsi_rhc_ops {
|
||||
ddsi_rhc_store_t store;
|
||||
ddsi_rhc_unregister_wr_t unregister_wr;
|
||||
ddsi_rhc_relinquish_ownership_t relinquish_ownership;
|
||||
ddsi_rhc_set_qos_t set_qos;
|
||||
ddsi_rhc_free_t free;
|
||||
};
|
||||
|
||||
struct ddsi_rhc {
|
||||
const struct ddsi_rhc_ops *ops;
|
||||
};
|
||||
|
||||
DDS_EXPORT inline bool ddsi_rhc_store (struct ddsi_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk) {
|
||||
return rhc->ops->store (rhc, wrinfo, sample, tk);
|
||||
}
|
||||
DDS_EXPORT inline void ddsi_rhc_unregister_wr (struct ddsi_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo) {
|
||||
rhc->ops->unregister_wr (rhc, wrinfo);
|
||||
}
|
||||
DDS_EXPORT inline void ddsi_rhc_relinquish_ownership (struct ddsi_rhc * __restrict rhc, const uint64_t wr_iid) {
|
||||
rhc->ops->relinquish_ownership (rhc, wr_iid);
|
||||
}
|
||||
DDS_EXPORT inline void ddsi_rhc_set_qos (struct ddsi_rhc *rhc, const struct dds_qos *qos) {
|
||||
rhc->ops->set_qos (rhc, qos);
|
||||
}
|
||||
DDS_EXPORT inline void ddsi_rhc_free (struct ddsi_rhc *rhc) {
|
||||
rhc->ops->free (rhc);
|
||||
}
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSI_RHC_H */
|
||||
|
|
@ -123,6 +123,15 @@ typedef bool (*ddsi_serdata_topicless_to_sample_t) (const struct ddsi_sertopic *
|
|||
computing equijoins across topics much simpler). */
|
||||
typedef bool (*ddsi_serdata_eqkey_t) (const struct ddsi_serdata *a, const struct ddsi_serdata *b);
|
||||
|
||||
/* Print a serdata into the provided buffer (truncating as necessary)
|
||||
- topic is present for supporting printing of "topicless" samples
|
||||
- buf != NULL, bufsize > 0 on input
|
||||
- buf must always be terminated with a nul character on return
|
||||
- returns the number of characters (excluding the terminating 0) needed to print it
|
||||
in full (or, as an optimization, it may pretend that it has printed it in full,
|
||||
returning bufsize-1) if it had to truncate) */
|
||||
typedef size_t (*ddsi_serdata_print_t) (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, char *buf, size_t size);
|
||||
|
||||
struct ddsi_serdata_ops {
|
||||
ddsi_serdata_eqkey_t eqkey;
|
||||
ddsi_serdata_size_t get_size;
|
||||
|
|
@ -136,8 +145,11 @@ struct ddsi_serdata_ops {
|
|||
ddsi_serdata_to_topicless_t to_topicless;
|
||||
ddsi_serdata_topicless_to_sample_t topicless_to_sample;
|
||||
ddsi_serdata_free_t free;
|
||||
ddsi_serdata_print_t print;
|
||||
};
|
||||
|
||||
#define DDSI_SERDATA_HAS_PRINT 1
|
||||
|
||||
DDS_EXPORT void ddsi_serdata_init (struct ddsi_serdata *d, const struct ddsi_sertopic *tp, enum ddsi_serdata_kind kind);
|
||||
|
||||
DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_ref (const struct ddsi_serdata *serdata_const) {
|
||||
|
|
@ -195,6 +207,20 @@ DDS_EXPORT inline bool ddsi_serdata_eqkey (const struct ddsi_serdata *a, const s
|
|||
return a->ops->eqkey (a, b);
|
||||
}
|
||||
|
||||
DDS_EXPORT inline bool ddsi_serdata_print (const struct ddsi_serdata *d, char *buf, size_t size) {
|
||||
return d->ops->print (d->topic, d, buf, size);
|
||||
}
|
||||
|
||||
DDS_EXPORT inline bool ddsi_serdata_print_topicless (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, char *buf, size_t size) {
|
||||
if (d->ops->print)
|
||||
return d->ops->print (topic, d, buf, size);
|
||||
else
|
||||
{
|
||||
buf[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ typedef struct {
|
|||
uint8_t id[2];
|
||||
} nn_vendorid_t;
|
||||
|
||||
|
||||
/* All existing vendor codes have the major part equal to 1 (and this will probably be true for a long, long time) */
|
||||
#define NN_VENDORID_MINOR_RTI 0x01
|
||||
#define NN_VENDORID_MINOR_PRISMTECH_OSPL 0x02
|
||||
|
|
@ -38,8 +39,15 @@ typedef struct {
|
|||
#define NN_VENDORID_MINOR_ECLIPSE 0x10
|
||||
#define NN_VENDORID_MINOR_PRISMTECH_CLOUD 0x20
|
||||
|
||||
#if defined(_WIN32) && defined(__cplusplus)
|
||||
#define NN_VENDORID(vendor) {{ 0x01, NN_VENDORID_MINOR_##vendor }}
|
||||
#define NN_VENDORID_UNKNOWN {{ 0x00, 0x00 }}
|
||||
#else
|
||||
#define NN_VENDORID(vendor) ((nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_##vendor }})
|
||||
#define NN_VENDORID_UNKNOWN ((nn_vendorid_t) {{ 0x00, 0x00 }})
|
||||
#define NN_VENDORID_ECLIPSE ((nn_vendorid_t) {{ 0x01, 0x10 }})
|
||||
#endif
|
||||
|
||||
#define NN_VENDORID_ECLIPSE NN_VENDORID (ECLIPSE)
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
|
|
@ -49,32 +57,32 @@ inline bool vendor_equals (nn_vendorid_t a, nn_vendorid_t b) {
|
|||
return ((a.id[0] << 8) | a.id[1]) == ((b.id[0] << 8) | b.id[1]);
|
||||
}
|
||||
inline bool vendor_is_eclipse (nn_vendorid_t vendor) {
|
||||
return vendor_equals (vendor, NN_VENDORID_ECLIPSE);
|
||||
return vendor_equals (vendor, NN_VENDORID (ECLIPSE));
|
||||
}
|
||||
inline bool vendor_is_rti (nn_vendorid_t vendor) {
|
||||
return vendor_equals (vendor, (nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_RTI }});
|
||||
return vendor_equals (vendor, NN_VENDORID (RTI));
|
||||
}
|
||||
inline bool vendor_is_opensplice (nn_vendorid_t vendor) {
|
||||
return vendor_equals (vendor, (nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_PRISMTECH_OSPL }});
|
||||
return vendor_equals (vendor, NN_VENDORID (PRISMTECH_OSPL));
|
||||
}
|
||||
inline bool vendor_is_twinoaks (nn_vendorid_t vendor) {
|
||||
return vendor_equals (vendor, (nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_TWINOAKS }});
|
||||
return vendor_equals (vendor, NN_VENDORID (TWINOAKS));
|
||||
}
|
||||
inline bool vendor_is_eprosima (nn_vendorid_t vendor) {
|
||||
return vendor_equals (vendor, (nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_EPROSIMA }});
|
||||
return vendor_equals (vendor, NN_VENDORID (EPROSIMA));
|
||||
}
|
||||
inline bool vendor_is_cloud (nn_vendorid_t vendor) {
|
||||
return vendor_equals (vendor, (nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_PRISMTECH_CLOUD }});
|
||||
return vendor_equals (vendor, NN_VENDORID (PRISMTECH_CLOUD));
|
||||
}
|
||||
inline bool vendor_is_eclipse_or_opensplice (nn_vendorid_t vendor) {
|
||||
return vendor_is_eclipse (vendor) | vendor_is_opensplice (vendor);
|
||||
}
|
||||
inline bool vendor_is_prismtech (nn_vendorid_t vendor) {
|
||||
return (vendor_equals (vendor, (nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_PRISMTECH_OSPL }}) ||
|
||||
vendor_equals (vendor, (nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_PRISMTECH_LITE }}) ||
|
||||
vendor_equals (vendor, (nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_PRISMTECH_GATEWAY }}) ||
|
||||
vendor_equals (vendor, (nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_PRISMTECH_JAVA }}) ||
|
||||
vendor_equals (vendor, (nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_PRISMTECH_CLOUD }}));
|
||||
return (vendor_equals (vendor, NN_VENDORID (PRISMTECH_OSPL)) ||
|
||||
vendor_equals (vendor, NN_VENDORID (PRISMTECH_LITE)) ||
|
||||
vendor_equals (vendor, NN_VENDORID (PRISMTECH_GATEWAY)) ||
|
||||
vendor_equals (vendor, NN_VENDORID (PRISMTECH_JAVA)) ||
|
||||
vendor_equals (vendor, NN_VENDORID (PRISMTECH_CLOUD)));
|
||||
}
|
||||
inline bool vendor_is_eclipse_or_prismtech (nn_vendorid_t vendor) {
|
||||
return vendor_is_eclipse (vendor) || vendor_is_prismtech (vendor);
|
||||
|
|
|
|||
|
|
@ -88,12 +88,12 @@ inline void bswapSN (nn_sequence_number_t *sn)
|
|||
#define fromBE8u(x) (x)
|
||||
#endif
|
||||
|
||||
nn_guid_prefix_t nn_hton_guid_prefix (nn_guid_prefix_t p);
|
||||
nn_guid_prefix_t nn_ntoh_guid_prefix (nn_guid_prefix_t p);
|
||||
nn_entityid_t nn_hton_entityid (nn_entityid_t e);
|
||||
nn_entityid_t nn_ntoh_entityid (nn_entityid_t e);
|
||||
nn_guid_t nn_hton_guid (nn_guid_t g);
|
||||
nn_guid_t nn_ntoh_guid (nn_guid_t g);
|
||||
ddsi_guid_prefix_t nn_hton_guid_prefix (ddsi_guid_prefix_t p);
|
||||
ddsi_guid_prefix_t nn_ntoh_guid_prefix (ddsi_guid_prefix_t p);
|
||||
ddsi_entityid_t nn_hton_entityid (ddsi_entityid_t e);
|
||||
ddsi_entityid_t nn_ntoh_entityid (ddsi_entityid_t e);
|
||||
ddsi_guid_t nn_hton_guid (ddsi_guid_t g);
|
||||
ddsi_guid_t nn_ntoh_guid (ddsi_guid_t g);
|
||||
|
||||
void bswap_sequence_number_set_hdr (nn_sequence_number_set_header_t *snset);
|
||||
void bswap_sequence_number_set_bitmap (nn_sequence_number_set_header_t *snset, uint32_t *bits);
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ struct config
|
|||
|
||||
struct cfgst;
|
||||
|
||||
struct cfgst *config_init (const char *configfile, struct config *cfg, uint32_t domid);
|
||||
struct cfgst *config_init (const char *config, struct config *cfg, uint32_t domid) ddsrt_nonnull((1,2));
|
||||
void config_print_cfgst (struct cfgst *cfgst, const struct ddsrt_log_cfg *logcfg);
|
||||
void config_free_source_info (struct cfgst *cfgst);
|
||||
void config_fini (struct cfgst *cfgst);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ int sedp_dispose_unregister_reader (struct reader *rd);
|
|||
int sedp_write_topic (struct participant *pp, const struct nn_plist *datap);
|
||||
int sedp_write_cm_participant (struct participant *pp, int alive);
|
||||
|
||||
int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const nn_guid_t *rdguid, void *qarg);
|
||||
int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const ddsi_guid_t *rdguid, void *qarg);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,12 +59,12 @@ typedef void (*status_cb_t) (void *entity, const status_cb_data_t *data);
|
|||
|
||||
struct prd_wr_match {
|
||||
ddsrt_avl_node_t avlnode;
|
||||
nn_guid_t wr_guid;
|
||||
ddsi_guid_t wr_guid;
|
||||
};
|
||||
|
||||
struct rd_pwr_match {
|
||||
ddsrt_avl_node_t avlnode;
|
||||
nn_guid_t pwr_guid;
|
||||
ddsi_guid_t pwr_guid;
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
nn_locator_t ssm_mc_loc;
|
||||
nn_locator_t ssm_src_loc;
|
||||
|
|
@ -73,17 +73,17 @@ struct rd_pwr_match {
|
|||
|
||||
struct wr_rd_match {
|
||||
ddsrt_avl_node_t avlnode;
|
||||
nn_guid_t rd_guid;
|
||||
ddsi_guid_t rd_guid;
|
||||
};
|
||||
|
||||
struct rd_wr_match {
|
||||
ddsrt_avl_node_t avlnode;
|
||||
nn_guid_t wr_guid;
|
||||
ddsi_guid_t wr_guid;
|
||||
};
|
||||
|
||||
struct wr_prd_match {
|
||||
ddsrt_avl_node_t avlnode;
|
||||
nn_guid_t prd_guid; /* guid of the proxy reader */
|
||||
ddsi_guid_t prd_guid; /* guid of the proxy reader */
|
||||
unsigned assumed_in_sync: 1; /* set to 1 upon receipt of ack not nack'ing msgs */
|
||||
unsigned has_replied_to_hb: 1; /* we must keep sending HBs until all readers have this set */
|
||||
unsigned all_have_replied_to_hb: 1; /* true iff 'has_replied_to_hb' for all readers in subtree */
|
||||
|
|
@ -91,8 +91,8 @@ struct wr_prd_match {
|
|||
seqno_t min_seq; /* smallest ack'd seq nr in subtree */
|
||||
seqno_t max_seq; /* sort-of highest ack'd seq nr in subtree (see augment function) */
|
||||
seqno_t seq; /* highest acknowledged seq nr */
|
||||
int num_reliable_readers_where_seq_equals_max;
|
||||
nn_guid_t arbitrary_unacked_reader;
|
||||
int32_t num_reliable_readers_where_seq_equals_max;
|
||||
ddsi_guid_t arbitrary_unacked_reader;
|
||||
nn_count_t next_acknack; /* next acceptable acknack sequence number */
|
||||
nn_count_t next_nackfrag; /* next acceptable nackfrag sequence number */
|
||||
nn_etime_t t_acknack_accepted; /* (local) time an acknack was last accepted */
|
||||
|
|
@ -110,7 +110,7 @@ enum pwr_rd_match_syncstate {
|
|||
|
||||
struct pwr_rd_match {
|
||||
ddsrt_avl_node_t avlnode;
|
||||
nn_guid_t rd_guid;
|
||||
ddsi_guid_t rd_guid;
|
||||
nn_mtime_t tcreate;
|
||||
nn_count_t count; /* most recent acknack sequence number */
|
||||
nn_count_t next_heartbeat; /* next acceptable heartbeat (see also add_proxy_writer_to_reader) */
|
||||
|
|
@ -134,7 +134,7 @@ struct ddsi_tkmap_instance;
|
|||
|
||||
struct entity_common {
|
||||
enum entity_kind kind;
|
||||
nn_guid_t guid;
|
||||
ddsi_guid_t guid;
|
||||
nn_wctime_t tupdate; /* timestamp of last update */
|
||||
char *name;
|
||||
uint64_t iid;
|
||||
|
|
@ -188,7 +188,7 @@ struct participant
|
|||
|
||||
struct endpoint_common {
|
||||
struct participant *pp;
|
||||
nn_guid_t group_guid;
|
||||
ddsi_guid_t group_guid;
|
||||
};
|
||||
|
||||
struct generic_endpoint { /* FIXME: currently only local endpoints; proxies use entity_common + proxy_endpoint common */
|
||||
|
|
@ -198,6 +198,7 @@ struct generic_endpoint { /* FIXME: currently only local endpoints; proxies use
|
|||
|
||||
enum writer_state {
|
||||
WRST_OPERATIONAL, /* normal situation */
|
||||
WRST_INTERRUPT, /* will be deleted, unblock throttle_writer but do not do anything further */
|
||||
WRST_LINGERING, /* writer deletion has been requested but still has unack'd data */
|
||||
WRST_DELETING /* writer is actually being deleted (removed from hash table) */
|
||||
};
|
||||
|
|
@ -259,7 +260,7 @@ struct writer
|
|||
uint32_t whc_low, whc_high; /* watermarks for WHC in bytes (counting only unack'd data) */
|
||||
nn_etime_t t_rexmit_end; /* time of last 1->0 transition of "retransmitting" */
|
||||
nn_etime_t t_whc_high_upd; /* time "whc_high" was last updated for controlled ramp-up of throughput */
|
||||
int num_reliable_readers; /* number of matching reliable PROXY readers */
|
||||
int32_t num_reliable_readers; /* number of matching reliable PROXY readers */
|
||||
ddsrt_avl_tree_t readers; /* all matching PROXY readers, see struct wr_prd_match */
|
||||
ddsrt_avl_tree_t local_readers; /* all matching LOCAL readers, see struct wr_rd_match */
|
||||
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
||||
|
|
@ -281,7 +282,7 @@ struct reader
|
|||
struct endpoint_common c;
|
||||
status_cb_t status_cb;
|
||||
void * status_cb_entity;
|
||||
struct rhc * rhc; /* reader history, tracks registrations and data */
|
||||
struct ddsi_rhc * rhc; /* reader history, tracks registrations and data */
|
||||
struct dds_qos *xqos;
|
||||
unsigned reliable: 1; /* 1 iff reader is reliable */
|
||||
unsigned handle_as_transient_local: 1; /* 1 iff reader wants historical data from proxy writers */
|
||||
|
|
@ -306,7 +307,7 @@ struct proxy_participant
|
|||
nn_vendorid_t vendor; /* vendor code from discovery */
|
||||
unsigned bes; /* built-in endpoint set */
|
||||
unsigned prismtech_bes; /* prismtech-specific extension of built-in endpoints set */
|
||||
nn_guid_t privileged_pp_guid; /* if this PP depends on another PP for its SEDP writing */
|
||||
ddsi_guid_t privileged_pp_guid; /* if this PP depends on another PP for its SEDP writing */
|
||||
struct nn_plist *plist; /* settings/QoS for this participant */
|
||||
ddsrt_atomic_voidp_t lease; /* lease object for this participant, for automatic leases */
|
||||
struct addrset *as_default; /* default address set to use for user data traffic */
|
||||
|
|
@ -333,7 +334,7 @@ struct proxy_participant
|
|||
participant. */
|
||||
struct proxy_group {
|
||||
ddsrt_avl_node_t avlnode;
|
||||
nn_guid_t guid;
|
||||
ddsi_guid_t guid;
|
||||
char *name;
|
||||
struct proxy_participant *proxypp; /* uncounted backref to proxy participant */
|
||||
struct dds_qos *xqos; /* publisher/subscriber QoS */
|
||||
|
|
@ -345,9 +346,8 @@ struct proxy_endpoint_common
|
|||
struct proxy_endpoint_common *next_ep; /* next \ endpoint belonging to this proxy participant */
|
||||
struct proxy_endpoint_common *prev_ep; /* prev / -- this is in arbitrary ordering */
|
||||
struct dds_qos *xqos; /* proxy endpoint QoS lives here; FIXME: local ones should have it moved to common as well */
|
||||
struct ddsi_sertopic * topic; /* topic may be NULL: for built-ins, but also for never-yet matched proxies (so we don't have to know the topic; when we match, we certainly do know) */
|
||||
struct addrset *as; /* address set to use for communicating with this endpoint */
|
||||
nn_guid_t group_guid; /* 0:0:0:0 if not available */
|
||||
ddsi_guid_t group_guid; /* 0:0:0:0 if not available */
|
||||
nn_vendorid_t vendor; /* cached from proxypp->vendor */
|
||||
seqno_t seq; /* sequence number of most recent SEDP message */
|
||||
};
|
||||
|
|
@ -356,8 +356,8 @@ struct proxy_writer {
|
|||
struct entity_common e;
|
||||
struct proxy_endpoint_common c;
|
||||
ddsrt_avl_tree_t readers; /* matching LOCAL readers, see pwr_rd_match */
|
||||
int n_reliable_readers; /* number of those that are reliable */
|
||||
int n_readers_out_of_sync; /* number of those that require special handling (accepting historical data, waiting for historical data set to become complete) */
|
||||
int32_t n_reliable_readers; /* number of those that are reliable */
|
||||
int32_t n_readers_out_of_sync; /* number of those that require special handling (accepting historical data, waiting for historical data set to become complete) */
|
||||
seqno_t last_seq; /* highest known seq published by the writer, not last delivered */
|
||||
uint32_t last_fragnum; /* last known frag for last_seq, or ~0u if last_seq not partial */
|
||||
nn_count_t nackfragcount; /* last nackfrag seq number */
|
||||
|
|
@ -400,17 +400,18 @@ extern const ddsrt_avl_treedef_t deleted_participants_treedef;
|
|||
#define DPG_LOCAL 1
|
||||
#define DPG_REMOTE 2
|
||||
struct deleted_participants_admin;
|
||||
struct deleted_participants_admin *deleted_participants_admin_new (int64_t delay);
|
||||
struct deleted_participants_admin *deleted_participants_admin_new (const ddsrt_log_cfg_t *logcfg, int64_t delay);
|
||||
void deleted_participants_admin_free (struct deleted_participants_admin *admin);
|
||||
int is_deleted_participant_guid (struct deleted_participants_admin *admin, const struct nn_guid *guid, unsigned for_what);
|
||||
int is_deleted_participant_guid (struct deleted_participants_admin *admin, const struct ddsi_guid *guid, unsigned for_what);
|
||||
|
||||
nn_entityid_t to_entityid (unsigned u);
|
||||
int is_builtin_entityid (nn_entityid_t id, nn_vendorid_t vendorid);
|
||||
int is_builtin_endpoint (nn_entityid_t id, nn_vendorid_t vendorid);
|
||||
bool is_null_guid (const ddsi_guid_t *guid);
|
||||
ddsi_entityid_t to_entityid (unsigned u);
|
||||
int is_builtin_entityid (ddsi_entityid_t id, nn_vendorid_t vendorid);
|
||||
int is_builtin_endpoint (ddsi_entityid_t id, nn_vendorid_t vendorid);
|
||||
bool is_local_orphan_endpoint (const struct entity_common *e);
|
||||
int is_writer_entityid (nn_entityid_t id);
|
||||
int is_reader_entityid (nn_entityid_t id);
|
||||
int is_keyed_endpoint_entityid (nn_entityid_t id);
|
||||
int is_writer_entityid (ddsi_entityid_t id);
|
||||
int is_reader_entityid (ddsi_entityid_t id);
|
||||
int is_keyed_endpoint_entityid (ddsi_entityid_t id);
|
||||
nn_vendorid_t get_entity_vendorid (const struct entity_common *e);
|
||||
|
||||
/* Interface for glue code between the OpenSplice kernel and the DDSI
|
||||
|
|
@ -491,7 +492,7 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e);
|
|||
* @retval DDS_RETCODE_OUT_OF_RESOURCES
|
||||
* The configured maximum number of participants has been reached.
|
||||
*/
|
||||
dds_return_t new_participant_guid (const nn_guid_t *ppguid, struct q_globals *gv, unsigned flags, const struct nn_plist *plist);
|
||||
dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals *gv, unsigned flags, const struct nn_plist *plist);
|
||||
|
||||
/**
|
||||
* @brief Create a new participant in the domain. See also new_participant_guid.
|
||||
|
|
@ -515,7 +516,7 @@ dds_return_t new_participant_guid (const nn_guid_t *ppguid, struct q_globals *gv
|
|||
* @retval DDS_RETCODE_OUT_OF_RESOURCES
|
||||
* The configured maximum number of participants has been reached.
|
||||
*/
|
||||
dds_return_t new_participant (struct nn_guid *ppguid, struct q_globals *gv, unsigned flags, const struct nn_plist *plist);
|
||||
dds_return_t new_participant (struct ddsi_guid *ppguid, struct q_globals *gv, unsigned flags, const struct nn_plist *plist);
|
||||
|
||||
/**
|
||||
* @brief Initiate the deletion of the participant:
|
||||
|
|
@ -541,9 +542,9 @@ dds_return_t new_participant (struct nn_guid *ppguid, struct q_globals *gv, unsi
|
|||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
* ppguid lookup failed.
|
||||
*/
|
||||
dds_return_t delete_participant (struct q_globals *gv, const struct nn_guid *ppguid);
|
||||
dds_return_t delete_participant (struct q_globals *gv, const struct ddsi_guid *ppguid);
|
||||
void update_participant_plist (struct participant *pp, const struct nn_plist *plist);
|
||||
uint64_t get_entity_instance_id (const struct q_globals *gv, const struct nn_guid *guid);
|
||||
uint64_t get_entity_instance_id (const struct q_globals *gv, const struct ddsi_guid *guid);
|
||||
|
||||
/* To obtain the builtin writer to be used for publishing SPDP, SEDP,
|
||||
PMD stuff for PP and its endpoints, given the entityid. If PP has
|
||||
|
|
@ -554,9 +555,9 @@ struct writer *get_builtin_writer (const struct participant *pp, unsigned entity
|
|||
GUID "ppguid". May return NULL if participant unknown or
|
||||
writer/reader already known. */
|
||||
|
||||
dds_return_t new_writer (struct writer **wr_out, struct q_globals *gv, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg);
|
||||
dds_return_t new_writer (struct writer **wr_out, struct q_globals *gv, struct ddsi_guid *wrguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg);
|
||||
|
||||
dds_return_t new_reader (struct reader **rd_out, struct q_globals *gv, struct nn_guid *rdguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct rhc * rhc, status_cb_t status_cb, void *status_cb_arg);
|
||||
dds_return_t new_reader (struct reader **rd_out, struct q_globals *gv, struct ddsi_guid *rdguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct ddsi_rhc * rhc, status_cb_t status_cb, void *status_cb_arg);
|
||||
|
||||
void update_reader_qos (struct reader *rd, const struct dds_qos *xqos);
|
||||
void update_writer_qos (struct writer *wr, const struct dds_qos *xqos);
|
||||
|
|
@ -569,16 +570,17 @@ int writer_must_have_hb_scheduled (const struct writer *wr, const struct whc_sta
|
|||
void writer_set_retransmitting (struct writer *wr);
|
||||
void writer_clear_retransmitting (struct writer *wr);
|
||||
|
||||
dds_return_t delete_writer (struct q_globals *gv, const struct nn_guid *guid);
|
||||
dds_return_t delete_writer_nolinger (struct q_globals *gv, const struct nn_guid *guid);
|
||||
dds_return_t unblock_throttled_writer (struct q_globals *gv, const struct ddsi_guid *guid);
|
||||
dds_return_t delete_writer (struct q_globals *gv, const struct ddsi_guid *guid);
|
||||
dds_return_t delete_writer_nolinger (struct q_globals *gv, const struct ddsi_guid *guid);
|
||||
dds_return_t delete_writer_nolinger_locked (struct writer *wr);
|
||||
|
||||
dds_return_t delete_reader (struct q_globals *gv, const struct nn_guid *guid);
|
||||
dds_return_t delete_reader (struct q_globals *gv, const struct ddsi_guid *guid);
|
||||
|
||||
struct local_orphan_writer {
|
||||
struct writer wr;
|
||||
};
|
||||
struct local_orphan_writer *new_local_orphan_writer (struct q_globals *gv, nn_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc);
|
||||
struct local_orphan_writer *new_local_orphan_writer (struct q_globals *gv, ddsi_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc);
|
||||
void delete_local_orphan_writer (struct local_orphan_writer *wr);
|
||||
|
||||
/* To create or delete a new proxy participant: "guid" MUST have the
|
||||
|
|
@ -605,8 +607,8 @@ void delete_local_orphan_writer (struct local_orphan_writer *wr);
|
|||
/* Set when this proxy participant is not to be announced on the built-in topics yet */
|
||||
#define CF_PROXYPP_NO_SPDP (1 << 3)
|
||||
|
||||
void new_proxy_participant (struct q_globals *gv, const struct nn_guid *guid, unsigned bes, unsigned prismtech_bes, const struct nn_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct nn_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq);
|
||||
int delete_proxy_participant_by_guid (struct q_globals *gv, const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit);
|
||||
void new_proxy_participant (struct q_globals *gv, const struct ddsi_guid *guid, unsigned bes, unsigned prismtech_bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct nn_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq);
|
||||
int delete_proxy_participant_by_guid (struct q_globals *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit);
|
||||
|
||||
enum update_proxy_participant_source {
|
||||
UPD_PROXYPP_SPDP,
|
||||
|
|
@ -621,8 +623,8 @@ void purge_proxy_participants (struct q_globals *gv, const nn_locator_t *loc, bo
|
|||
|
||||
/* To create a new proxy writer or reader; the proxy participant is
|
||||
determined from the GUID and must exist. */
|
||||
int new_proxy_writer (struct q_globals *gv, const struct nn_guid *ppguid, const struct nn_guid *guid, struct addrset *as, const struct nn_plist *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp, seqno_t seq);
|
||||
int new_proxy_reader (struct q_globals *gv, const struct nn_guid *ppguid, const struct nn_guid *guid, struct addrset *as, const struct nn_plist *plist, nn_wctime_t timestamp, seqno_t seq
|
||||
int new_proxy_writer (struct q_globals *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const struct nn_plist *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp, seqno_t seq);
|
||||
int new_proxy_reader (struct q_globals *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const struct nn_plist *plist, nn_wctime_t timestamp, seqno_t seq
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
, int favours_ssm
|
||||
#endif
|
||||
|
|
@ -633,22 +635,24 @@ int new_proxy_reader (struct q_globals *gv, const struct nn_guid *ppguid, const
|
|||
reader or writer. Actual deletion is scheduled in the future, when
|
||||
no outstanding references may still exist (determined by checking
|
||||
thread progress, &c.). */
|
||||
int delete_proxy_writer (struct q_globals *gv, const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit);
|
||||
int delete_proxy_reader (struct q_globals *gv, const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit);
|
||||
int delete_proxy_writer (struct q_globals *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit);
|
||||
int delete_proxy_reader (struct q_globals *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit);
|
||||
|
||||
void update_proxy_reader (struct proxy_reader *prd, seqno_t seq, struct addrset *as, const struct dds_qos *xqos, nn_wctime_t timestamp);
|
||||
void update_proxy_writer (struct proxy_writer *pwr, seqno_t seq, struct addrset *as, const struct dds_qos *xqos, nn_wctime_t timestamp);
|
||||
|
||||
int new_proxy_group (const struct nn_guid *guid, const char *name, const struct dds_qos *xqos, nn_wctime_t timestamp);
|
||||
void delete_proxy_group (struct ephash *guid_hash, const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit);
|
||||
int new_proxy_group (const struct ddsi_guid *guid, const char *name, const struct dds_qos *xqos, nn_wctime_t timestamp);
|
||||
void delete_proxy_group (struct ephash *guid_hash, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit);
|
||||
|
||||
/* Call this to empty all address sets of all writers to stop all outgoing traffic, or to
|
||||
rebuild them all (which only makes sense after previously having emptied them all). */
|
||||
void rebuild_or_clear_writer_addrsets(struct q_globals *gv, int rebuild);
|
||||
|
||||
|
||||
void local_reader_ary_setfastpath_ok (struct local_reader_ary *x, bool fastpath_ok);
|
||||
|
||||
struct ddsi_writer_info;
|
||||
DDS_EXPORT void ddsi_make_writer_info(struct ddsi_writer_info *wrinfo, const struct entity_common *e, const struct dds_qos *xqos);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ struct writer;
|
|||
struct proxy_participant;
|
||||
struct proxy_reader;
|
||||
struct proxy_writer;
|
||||
struct nn_guid;
|
||||
struct ddsi_guid;
|
||||
|
||||
enum entity_kind {
|
||||
EK_PARTICIPANT,
|
||||
|
|
@ -80,15 +80,15 @@ void ephash_remove_reader_guid (struct ephash *eh, struct reader *rd);
|
|||
void ephash_remove_proxy_writer_guid (struct ephash *eh, struct proxy_writer *pwr);
|
||||
void ephash_remove_proxy_reader_guid (struct ephash *eh, struct proxy_reader *prd);
|
||||
|
||||
void *ephash_lookup_guid_untyped (const struct ephash *eh, const struct nn_guid *guid);
|
||||
void *ephash_lookup_guid (const struct ephash *eh, const struct nn_guid *guid, enum entity_kind kind);
|
||||
void *ephash_lookup_guid_untyped (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
void *ephash_lookup_guid (const struct ephash *eh, const struct ddsi_guid *guid, enum entity_kind kind);
|
||||
|
||||
struct participant *ephash_lookup_participant_guid (const struct ephash *eh, const struct nn_guid *guid);
|
||||
struct proxy_participant *ephash_lookup_proxy_participant_guid (const struct ephash *eh, const struct nn_guid *guid);
|
||||
struct writer *ephash_lookup_writer_guid (const struct ephash *eh, const struct nn_guid *guid);
|
||||
struct reader *ephash_lookup_reader_guid (const struct ephash *eh, const struct nn_guid *guid);
|
||||
struct proxy_writer *ephash_lookup_proxy_writer_guid (const struct ephash *eh, const struct nn_guid *guid);
|
||||
struct proxy_reader *ephash_lookup_proxy_reader_guid (const struct ephash *eh, const struct nn_guid *guid);
|
||||
struct participant *ephash_lookup_participant_guid (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
struct proxy_participant *ephash_lookup_proxy_participant_guid (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
struct writer *ephash_lookup_writer_guid (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
struct reader *ephash_lookup_reader_guid (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
struct proxy_writer *ephash_lookup_proxy_writer_guid (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
struct proxy_reader *ephash_lookup_proxy_reader_guid (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
|
||||
|
||||
/* Enumeration of entries in the hash table:
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ struct q_globals {
|
|||
|
||||
/* GUID to be used in next call to new_participant; also protected
|
||||
by privileged_pp_lock */
|
||||
struct nn_guid next_ppguid;
|
||||
struct ddsi_guid ppguid_base;
|
||||
|
||||
/* number of up, non-loopback, IPv4/IPv6 interfaces, the index of
|
||||
the selected/preferred one, and the discovered interfaces. */
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ typedef struct nn_prismtech_participant_version_info
|
|||
} nn_prismtech_participant_version_info_t;
|
||||
|
||||
typedef struct nn_prismtech_eotgroup_tid {
|
||||
nn_entityid_t writer_entityid;
|
||||
ddsi_entityid_t writer_entityid;
|
||||
uint32_t transactionId;
|
||||
} nn_prismtech_eotgroup_tid_t;
|
||||
|
||||
|
|
@ -140,9 +140,9 @@ typedef struct nn_plist {
|
|||
uint32_t participant_builtin_endpoints;
|
||||
dds_duration_t participant_lease_duration;
|
||||
/* nn_content_filter_property_t content_filter_property; */
|
||||
nn_guid_t participant_guid;
|
||||
nn_guid_t endpoint_guid;
|
||||
nn_guid_t group_guid;
|
||||
ddsi_guid_t participant_guid;
|
||||
ddsi_guid_t endpoint_guid;
|
||||
ddsi_guid_t group_guid;
|
||||
#if 0 /* reserved, rather than NIY */
|
||||
nn_entityid_t participant_entityid;
|
||||
nn_entityid_t group_entityid;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#define NN_PROTOCOL_H
|
||||
|
||||
#include "dds/ddsrt/endian.h"
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsi/q_feature_check.h"
|
||||
|
||||
#include "dds/ddsi/q_rtps.h"
|
||||
|
|
@ -115,7 +116,7 @@ typedef struct Header {
|
|||
nn_protocolid_t protocol;
|
||||
nn_protocol_version_t version;
|
||||
nn_vendorid_t vendorid;
|
||||
nn_guid_prefix_t guid_prefix;
|
||||
ddsi_guid_prefix_t guid_prefix;
|
||||
} Header_t;
|
||||
#if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN
|
||||
#define NN_PROTOCOLID_AS_UINT32 (((uint32_t)'R' << 0) | ((uint32_t)'T' << 8) | ((uint32_t)'P' << 16) | ((uint32_t)'S' << 24))
|
||||
|
|
@ -161,12 +162,12 @@ typedef struct InfoTimestamp {
|
|||
|
||||
typedef struct EntityId {
|
||||
SubmessageHeader_t smhdr;
|
||||
nn_entityid_t entityid;
|
||||
ddsi_entityid_t entityid;
|
||||
} EntityId_t;
|
||||
|
||||
typedef struct InfoDST {
|
||||
SubmessageHeader_t smhdr;
|
||||
nn_guid_prefix_t guid_prefix;
|
||||
ddsi_guid_prefix_t guid_prefix;
|
||||
} InfoDST_t;
|
||||
|
||||
typedef struct InfoSRC {
|
||||
|
|
@ -174,7 +175,7 @@ typedef struct InfoSRC {
|
|||
unsigned unused;
|
||||
nn_protocol_version_t version;
|
||||
nn_vendorid_t vendorid;
|
||||
nn_guid_prefix_t guid_prefix;
|
||||
ddsi_guid_prefix_t guid_prefix;
|
||||
} InfoSRC_t;
|
||||
|
||||
#if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN
|
||||
|
|
@ -196,8 +197,8 @@ typedef struct Data_DataFrag_common {
|
|||
SubmessageHeader_t smhdr;
|
||||
uint16_t extraFlags;
|
||||
uint16_t octetsToInlineQos;
|
||||
nn_entityid_t readerId;
|
||||
nn_entityid_t writerId;
|
||||
ddsi_entityid_t readerId;
|
||||
ddsi_entityid_t writerId;
|
||||
nn_sequence_number_t writerSN;
|
||||
} Data_DataFrag_common_t;
|
||||
|
||||
|
|
@ -223,26 +224,30 @@ typedef struct MsgLen {
|
|||
uint32_t length;
|
||||
} MsgLen_t;
|
||||
|
||||
DDSRT_WARNING_MSVC_OFF(4200)
|
||||
typedef struct AckNack {
|
||||
SubmessageHeader_t smhdr;
|
||||
nn_entityid_t readerId;
|
||||
nn_entityid_t writerId;
|
||||
ddsi_entityid_t readerId;
|
||||
ddsi_entityid_t writerId;
|
||||
nn_sequence_number_set_header_t readerSNState;
|
||||
uint32_t bits[];
|
||||
/* nn_count_t count; */
|
||||
} AckNack_t;
|
||||
DDSRT_WARNING_MSVC_ON(4200)
|
||||
#define ACKNACK_FLAG_FINAL 0x02u
|
||||
#define ACKNACK_SIZE(numbits) (offsetof (AckNack_t, bits) + NN_SEQUENCE_NUMBER_SET_BITS_SIZE (numbits) + 4)
|
||||
#define ACKNACK_SIZE_MAX ACKNACK_SIZE (256u)
|
||||
|
||||
DDSRT_WARNING_MSVC_OFF(4200)
|
||||
typedef struct Gap {
|
||||
SubmessageHeader_t smhdr;
|
||||
nn_entityid_t readerId;
|
||||
nn_entityid_t writerId;
|
||||
ddsi_entityid_t readerId;
|
||||
ddsi_entityid_t writerId;
|
||||
nn_sequence_number_t gapStart;
|
||||
nn_sequence_number_set_header_t gapList;
|
||||
uint32_t bits[];
|
||||
} Gap_t;
|
||||
DDSRT_WARNING_MSVC_ON(4200)
|
||||
#define GAP_SIZE(numbits) (offsetof (Gap_t, bits) + NN_SEQUENCE_NUMBER_SET_BITS_SIZE (numbits))
|
||||
#define GAP_SIZE_MAX GAP_SIZE (256u)
|
||||
|
||||
|
|
@ -254,8 +259,8 @@ typedef struct InfoTS {
|
|||
|
||||
typedef struct Heartbeat {
|
||||
SubmessageHeader_t smhdr;
|
||||
nn_entityid_t readerId;
|
||||
nn_entityid_t writerId;
|
||||
ddsi_entityid_t readerId;
|
||||
ddsi_entityid_t writerId;
|
||||
nn_sequence_number_t firstSN;
|
||||
nn_sequence_number_t lastSN;
|
||||
nn_count_t count;
|
||||
|
|
@ -265,22 +270,24 @@ typedef struct Heartbeat {
|
|||
|
||||
typedef struct HeartbeatFrag {
|
||||
SubmessageHeader_t smhdr;
|
||||
nn_entityid_t readerId;
|
||||
nn_entityid_t writerId;
|
||||
ddsi_entityid_t readerId;
|
||||
ddsi_entityid_t writerId;
|
||||
nn_sequence_number_t writerSN;
|
||||
nn_fragment_number_t lastFragmentNum;
|
||||
nn_count_t count;
|
||||
} HeartbeatFrag_t;
|
||||
|
||||
DDSRT_WARNING_MSVC_OFF(4200)
|
||||
typedef struct NackFrag {
|
||||
SubmessageHeader_t smhdr;
|
||||
nn_entityid_t readerId;
|
||||
nn_entityid_t writerId;
|
||||
ddsi_entityid_t readerId;
|
||||
ddsi_entityid_t writerId;
|
||||
nn_sequence_number_t writerSN;
|
||||
nn_fragment_number_set_header_t fragmentNumberState;
|
||||
uint32_t bits[];
|
||||
/* nn_count_t count; */
|
||||
} NackFrag_t;
|
||||
DDSRT_WARNING_MSVC_ON(4200)
|
||||
#define NACKFRAG_SIZE(numbits) (offsetof (NackFrag_t, bits) + NN_FRAGMENT_NUMBER_SET_BITS_SIZE (numbits) + 4)
|
||||
#define NACKFRAG_SIZE_MAX NACKFRAG_SIZE (256u)
|
||||
|
||||
|
|
@ -305,12 +312,14 @@ typedef union Submessage {
|
|||
PT_InfoContainer_t pt_infocontainer;
|
||||
} Submessage_t;
|
||||
|
||||
DDSRT_WARNING_MSVC_OFF(4200)
|
||||
typedef struct ParticipantMessageData {
|
||||
nn_guid_prefix_t participantGuidPrefix;
|
||||
ddsi_guid_prefix_t participantGuidPrefix;
|
||||
uint32_t kind; /* really 4 octets */
|
||||
uint32_t length;
|
||||
char value[];
|
||||
} ParticipantMessageData_t;
|
||||
DDSRT_WARNING_MSVC_ON(4200)
|
||||
#define PARTICIPANT_MESSAGE_DATA_KIND_UNKNOWN 0x0u
|
||||
#define PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE 0x1u
|
||||
#define PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE 0x2u
|
||||
|
|
|
|||
|
|
@ -30,14 +30,14 @@ struct nn_rsample_info;
|
|||
struct nn_defrag;
|
||||
struct nn_reorder;
|
||||
struct nn_dqueue;
|
||||
struct nn_guid;
|
||||
struct ddsi_guid;
|
||||
|
||||
struct proxy_writer;
|
||||
|
||||
struct nn_fragment_number_set;
|
||||
struct nn_sequence_number_set;
|
||||
|
||||
typedef int (*nn_dqueue_handler_t) (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const struct nn_guid *rdguid, void *qarg);
|
||||
typedef int (*nn_dqueue_handler_t) (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const struct ddsi_guid *rdguid, void *qarg);
|
||||
|
||||
struct nn_rmsg_chunk {
|
||||
struct nn_rbuf *rbuf;
|
||||
|
|
@ -102,8 +102,8 @@ struct nn_rmsg {
|
|||
#define NN_RMSG_PAYLOADOFF(m, o) (NN_RMSG_PAYLOAD (m) + (o))
|
||||
|
||||
struct receiver_state {
|
||||
nn_guid_prefix_t src_guid_prefix; /* 12 */
|
||||
nn_guid_prefix_t dst_guid_prefix; /* 12 */
|
||||
ddsi_guid_prefix_t src_guid_prefix; /* 12 */
|
||||
ddsi_guid_prefix_t dst_guid_prefix; /* 12 */
|
||||
struct addrset *reply_locators; /* 4/8 */
|
||||
int forme; /* 4 */
|
||||
nn_vendorid_t vendor; /* 2 */
|
||||
|
|
@ -234,7 +234,7 @@ void nn_dqueue_free (struct nn_dqueue *q);
|
|||
bool nn_dqueue_enqueue_deferred_wakeup (struct nn_dqueue *q, struct nn_rsample_chain *sc, nn_reorder_result_t rres);
|
||||
void dd_dqueue_enqueue_trigger (struct nn_dqueue *q);
|
||||
void nn_dqueue_enqueue (struct nn_dqueue *q, struct nn_rsample_chain *sc, nn_reorder_result_t rres);
|
||||
void nn_dqueue_enqueue1 (struct nn_dqueue *q, const nn_guid_t *rdguid, struct nn_rsample_chain *sc, nn_reorder_result_t rres);
|
||||
void nn_dqueue_enqueue1 (struct nn_dqueue *q, const ddsi_guid_t *rdguid, struct nn_rsample_chain *sc, nn_reorder_result_t rres);
|
||||
void nn_dqueue_enqueue_callback (struct nn_dqueue *q, nn_dqueue_callback_t cb, void *arg);
|
||||
int nn_dqueue_is_full (struct nn_dqueue *q);
|
||||
void nn_dqueue_wait_until_empty_if_full (struct nn_dqueue *q);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ struct recv_thread_arg;
|
|||
void trigger_recv_threads (const struct q_globals *gv);
|
||||
uint32_t recv_thread (void *vrecv_thread_arg);
|
||||
uint32_t listen_thread (struct ddsi_tran_listener * listener);
|
||||
int user_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const nn_guid_t *rdguid, void *qarg);
|
||||
int user_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const ddsi_guid_t *rdguid, void *qarg);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef Q_RHC_H
|
||||
#define Q_RHC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "dds/export.h"
|
||||
|
||||
/* DDS_EXPORT inline i.c.w. __attributes__((visibility...)) and some compilers: */
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
|
||||
#include "dds/ddsi/q_rtps.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct dds_qos;
|
||||
struct ddsi_tkmap_instance;
|
||||
struct ddsi_serdata;
|
||||
struct ddsi_sertopic;
|
||||
struct entity_common;
|
||||
|
||||
struct proxy_writer_info
|
||||
{
|
||||
nn_guid_t guid;
|
||||
bool auto_dispose;
|
||||
int32_t ownership_strength;
|
||||
uint64_t iid;
|
||||
};
|
||||
|
||||
struct rhc;
|
||||
|
||||
typedef void (*rhc_free_t) (struct rhc *rhc);
|
||||
typedef bool (*rhc_store_t) (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk);
|
||||
typedef void (*rhc_unregister_wr_t) (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info);
|
||||
typedef void (*rhc_relinquish_ownership_t) (struct rhc * __restrict rhc, const uint64_t wr_iid);
|
||||
typedef void (*rhc_set_qos_t) (struct rhc *rhc, const struct dds_qos *qos);
|
||||
|
||||
struct rhc_ops {
|
||||
rhc_store_t store;
|
||||
rhc_unregister_wr_t unregister_wr;
|
||||
rhc_relinquish_ownership_t relinquish_ownership;
|
||||
rhc_set_qos_t set_qos;
|
||||
rhc_free_t free;
|
||||
};
|
||||
|
||||
struct rhc {
|
||||
const struct rhc_ops *ops;
|
||||
};
|
||||
|
||||
DDS_EXPORT inline bool rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk) {
|
||||
return rhc->ops->store (rhc, pwr_info, sample, tk);
|
||||
}
|
||||
DDS_EXPORT inline void rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info) {
|
||||
rhc->ops->unregister_wr (rhc, pwr_info);
|
||||
}
|
||||
DDS_EXPORT inline void rhc_relinquish_ownership (struct rhc * __restrict rhc, const uint64_t wr_iid) {
|
||||
rhc->ops->relinquish_ownership (rhc, wr_iid);
|
||||
}
|
||||
DDS_EXPORT inline void rhc_set_qos (struct rhc *rhc, const struct dds_qos *qos) {
|
||||
rhc->ops->set_qos (rhc, qos);
|
||||
}
|
||||
DDS_EXPORT inline void rhc_free (struct rhc *rhc) {
|
||||
rhc->ops->free (rhc);
|
||||
}
|
||||
|
||||
DDS_EXPORT void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct dds_qos *xqos);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* Q_RHC_H */
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
#define NN_RTPS_H
|
||||
|
||||
#include "dds/ddsi/ddsi_vendor.h"
|
||||
#include "dds/ddsi/ddsi_guid.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
|
|
@ -21,17 +22,6 @@ extern "C" {
|
|||
typedef struct {
|
||||
uint8_t major, minor;
|
||||
} nn_protocol_version_t;
|
||||
typedef union nn_guid_prefix {
|
||||
unsigned char s[12];
|
||||
uint32_t u[3];
|
||||
} nn_guid_prefix_t;
|
||||
typedef union nn_entityid {
|
||||
uint32_t u;
|
||||
} nn_entityid_t;
|
||||
typedef struct nn_guid {
|
||||
nn_guid_prefix_t prefix;
|
||||
nn_entityid_t entityid;
|
||||
} nn_guid_t;
|
||||
typedef int64_t seqno_t;
|
||||
#define MAX_SEQ_NUMBER INT64_MAX
|
||||
|
||||
|
|
|
|||
|
|
@ -98,12 +98,9 @@ struct thread_states {
|
|||
extern DDS_EXPORT struct thread_states thread_states;
|
||||
extern ddsrt_thread_local struct thread_state1 *tsd_thread_state;
|
||||
|
||||
DDS_EXPORT void thread_states_init_static (void);
|
||||
DDS_EXPORT void thread_states_init (unsigned maxthreads);
|
||||
DDS_EXPORT void thread_states_fini (void);
|
||||
DDS_EXPORT bool thread_states_fini (void);
|
||||
|
||||
DDS_EXPORT void upgrade_main_thread (void);
|
||||
DDS_EXPORT void downgrade_main_thread (void);
|
||||
DDS_EXPORT const struct config_thread_properties_listelem *lookup_thread_properties (const struct config *config, const char *name);
|
||||
DDS_EXPORT dds_return_t create_thread_with_properties (struct thread_state1 **ts1, struct config_thread_properties_listelem const * const tprops, const char *name, uint32_t (*f) (void *arg), void *arg);
|
||||
DDS_EXPORT dds_return_t create_thread (struct thread_state1 **ts, const struct q_globals *gv, const char *name, uint32_t (*f) (void *arg), void *arg);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ int write_sample_nogc_notk (struct thread_state1 * const ts1, struct nn_xpack *x
|
|||
/* When calling the following functions, wr->lock must be held */
|
||||
dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, unsigned fragnum, struct proxy_reader *prd,struct nn_xmsg **msg, int isnew);
|
||||
int enqueue_sample_wrlock_held (struct writer *wr, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew);
|
||||
void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_state *whcst, int hbansreq, nn_entityid_t dst, int issync);
|
||||
void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_state *whcst, int hbansreq, ddsi_entityid_t dst, int issync);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ DDS_EXPORT dds_return_t xeventq_start (struct xeventq *evq, const char *name); /
|
|||
DDS_EXPORT void xeventq_stop (struct xeventq *evq);
|
||||
|
||||
DDS_EXPORT void qxev_msg (struct xeventq *evq, struct nn_xmsg *msg);
|
||||
DDS_EXPORT void qxev_pwr_entityid (struct proxy_writer * pwr, nn_guid_prefix_t * id);
|
||||
DDS_EXPORT void qxev_prd_entityid (struct proxy_reader * prd, nn_guid_prefix_t * id);
|
||||
DDS_EXPORT void qxev_pwr_entityid (struct proxy_writer * pwr, ddsi_guid_prefix_t * id);
|
||||
DDS_EXPORT void qxev_prd_entityid (struct proxy_reader * prd, ddsi_guid_prefix_t * id);
|
||||
|
||||
/* Returns 1 if queued, 0 otherwise (no point in returning the
|
||||
event, you can't do anything with it anyway) */
|
||||
|
|
@ -57,11 +57,11 @@ DDS_EXPORT int qxev_msg_rexmit_wrlock_held (struct xeventq *evq, struct nn_xmsg
|
|||
DDS_EXPORT void delete_xevent (struct xevent *ev);
|
||||
DDS_EXPORT int resched_xevent_if_earlier (struct xevent *ev, nn_mtime_t tsched);
|
||||
|
||||
DDS_EXPORT struct xevent *qxev_heartbeat (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *wr_guid);
|
||||
DDS_EXPORT struct xevent *qxev_acknack (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *pwr_guid, const nn_guid_t *rd_guid);
|
||||
DDS_EXPORT struct xevent *qxev_spdp (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *pp_guid, const nn_guid_t *proxypp_guid);
|
||||
DDS_EXPORT struct xevent *qxev_pmd_update (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *pp_guid);
|
||||
DDS_EXPORT struct xevent *qxev_delete_writer (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *guid);
|
||||
DDS_EXPORT struct xevent *qxev_heartbeat (struct xeventq *evq, nn_mtime_t tsched, const ddsi_guid_t *wr_guid);
|
||||
DDS_EXPORT struct xevent *qxev_acknack (struct xeventq *evq, nn_mtime_t tsched, const ddsi_guid_t *pwr_guid, const ddsi_guid_t *rd_guid);
|
||||
DDS_EXPORT struct xevent *qxev_spdp (struct xeventq *evq, nn_mtime_t tsched, const ddsi_guid_t *pp_guid, const ddsi_guid_t *proxypp_guid);
|
||||
DDS_EXPORT struct xevent *qxev_pmd_update (struct xeventq *evq, nn_mtime_t tsched, const ddsi_guid_t *pp_guid);
|
||||
DDS_EXPORT struct xevent *qxev_delete_writer (struct xeventq *evq, nn_mtime_t tsched, const ddsi_guid_t *guid);
|
||||
|
||||
/* cb will be called with now = T_NEVER if the event is still enqueued when when xeventq_free starts cleaning up */
|
||||
DDS_EXPORT struct xevent *qxev_callback (struct xeventq *evq, nn_mtime_t tsched, void (*cb) (struct xevent *xev, void *arg, nn_mtime_t now), void *arg);
|
||||
|
|
|
|||
|
|
@ -54,10 +54,10 @@ void nn_xmsgpool_free (struct nn_xmsgpool *pool);
|
|||
/* To allocate a new xmsg from the pool; if expected_size is NOT
|
||||
exceeded, no reallocs will be performed, else the address of the
|
||||
xmsg may change because of reallocing when appending to it. */
|
||||
struct nn_xmsg *nn_xmsg_new (struct nn_xmsgpool *pool, const nn_guid_prefix_t *src_guid_prefix, size_t expected_size, enum nn_xmsg_kind kind);
|
||||
struct nn_xmsg *nn_xmsg_new (struct nn_xmsgpool *pool, const ddsi_guid_prefix_t *src_guid_prefix, size_t expected_size, enum nn_xmsg_kind kind);
|
||||
|
||||
/* For sending to a particular destination (participant) */
|
||||
void nn_xmsg_setdst1 (struct nn_xmsg *m, const nn_guid_prefix_t *gp, const nn_locator_t *addr);
|
||||
void nn_xmsg_setdst1 (struct nn_xmsg *m, const ddsi_guid_prefix_t *gp, const nn_locator_t *addr);
|
||||
|
||||
/* For sending to a particular proxy reader; this is a convenience
|
||||
routine that extracts a suitable address from the proxy reader's
|
||||
|
|
@ -80,7 +80,7 @@ int nn_xmsg_setencoderid (struct nn_xmsg *msg, uint32_t encoderid);
|
|||
M must be a rexmit, and for all rexmits this must be called. It is
|
||||
a separate function because the location may only become known at a
|
||||
late-ish stage in the construction of the message. */
|
||||
void nn_xmsg_set_data_readerId (struct nn_xmsg *m, nn_entityid_t *readerId);
|
||||
void nn_xmsg_set_data_readerId (struct nn_xmsg *m, ddsi_entityid_t *readerId);
|
||||
|
||||
/* If M and MADD are both xmsg's containing the same retransmit
|
||||
message, this will merge the destination embedded in MADD into M.
|
||||
|
|
@ -97,8 +97,8 @@ int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct q_globals *gv, struct
|
|||
/* To set writer ids for updating last transmitted sequence number;
|
||||
wrfragid is 0 based, unlike DDSI but like other places where
|
||||
fragment numbers are handled internally. */
|
||||
void nn_xmsg_setwriterseq (struct nn_xmsg *msg, const nn_guid_t *wrguid, seqno_t wrseq);
|
||||
void nn_xmsg_setwriterseq_fragid (struct nn_xmsg *msg, const nn_guid_t *wrguid, seqno_t wrseq, nn_fragment_number_t wrfragid);
|
||||
void nn_xmsg_setwriterseq (struct nn_xmsg *msg, const ddsi_guid_t *wrguid, seqno_t wrseq);
|
||||
void nn_xmsg_setwriterseq_fragid (struct nn_xmsg *msg, const ddsi_guid_t *wrguid, seqno_t wrseq, nn_fragment_number_t wrfragid);
|
||||
|
||||
/* Comparison function for retransmits: orders messages on writer
|
||||
guid, sequence number and fragment id */
|
||||
|
|
@ -109,7 +109,7 @@ size_t nn_xmsg_size (const struct nn_xmsg *m);
|
|||
void *nn_xmsg_payload (size_t *sz, struct nn_xmsg *m);
|
||||
void nn_xmsg_payload_to_plistsample (struct ddsi_plist_sample *dst, nn_parameterid_t keyparam, const struct nn_xmsg *m);
|
||||
enum nn_xmsg_kind nn_xmsg_kind (const struct nn_xmsg *m);
|
||||
void nn_xmsg_guid_seq_fragid (const struct nn_xmsg *m, nn_guid_t *wrguid, seqno_t *wrseq, nn_fragment_number_t *wrfragid);
|
||||
void nn_xmsg_guid_seq_fragid (const struct nn_xmsg *m, ddsi_guid_t *wrguid, seqno_t *wrseq, nn_fragment_number_t *wrfragid);
|
||||
|
||||
void *nn_xmsg_submsg_from_marker (struct nn_xmsg *msg, struct nn_xmsg_marker marker);
|
||||
void *nn_xmsg_append (struct nn_xmsg *m, struct nn_xmsg_marker *marker, size_t sz);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,41 @@ typedef ddsi_octetseq_t dds_userdata_qospolicy_t;
|
|||
typedef ddsi_octetseq_t dds_topicdata_qospolicy_t;
|
||||
typedef ddsi_octetseq_t dds_groupdata_qospolicy_t;
|
||||
|
||||
typedef struct dds_property {
|
||||
/* The propagate boolean will not be send over the wire.
|
||||
* When the value is 'false', the complete struct shouldn't be send.
|
||||
* It has to be the first variable within the structure because it
|
||||
* is mapped to XbPROP in the serialiser. */
|
||||
unsigned char propagate;
|
||||
char *name;
|
||||
char *value;
|
||||
} dds_property_t;
|
||||
|
||||
typedef struct dds_propertyseq {
|
||||
uint32_t n;
|
||||
dds_property_t *props;
|
||||
} dds_propertyseq_t;
|
||||
|
||||
typedef struct dds_binaryproperty {
|
||||
/* The propagate boolean will not be send over the wire.
|
||||
* When the value is 'false', the complete struct shouldn't be send.
|
||||
* It has to be the first variable within the structure because it
|
||||
* is mapped to XbPROP in the serialiser. */
|
||||
unsigned char propagate;
|
||||
char *name;
|
||||
ddsi_octetseq_t value;
|
||||
} dds_binaryproperty_t;
|
||||
|
||||
typedef struct dds_binarypropertyseq {
|
||||
uint32_t n;
|
||||
dds_binaryproperty_t *props;
|
||||
} dds_binarypropertyseq_t;
|
||||
|
||||
typedef struct dds_property_qospolicy {
|
||||
dds_propertyseq_t value;
|
||||
dds_binarypropertyseq_t binary_value;
|
||||
} dds_property_qospolicy_t;
|
||||
|
||||
typedef struct dds_durability_qospolicy {
|
||||
dds_durability_kind_t kind;
|
||||
} dds_durability_qospolicy_t;
|
||||
|
|
@ -212,6 +247,7 @@ typedef struct dds_ignorelocal_qospolicy {
|
|||
#define QP_PRISMTECH_SUBSCRIPTION_KEYS ((uint64_t)1 << 25)
|
||||
#define QP_PRISMTECH_ENTITY_FACTORY ((uint64_t)1 << 27)
|
||||
#define QP_CYCLONE_IGNORELOCAL ((uint64_t)1 << 30)
|
||||
#define QP_PROPERTY_LIST ((uint64_t)1 << 31)
|
||||
|
||||
/* Partition QoS is not RxO according to the specification (DDS 1.2,
|
||||
section 7.1.3), but communication will not take place unless it
|
||||
|
|
@ -263,6 +299,7 @@ struct dds_qos {
|
|||
/*x xR*/dds_subscription_keys_qospolicy_t subscription_keys;
|
||||
/*x xR*/dds_reader_lifespan_qospolicy_t reader_lifespan;
|
||||
/* x */dds_ignorelocal_qospolicy_t ignorelocal;
|
||||
/*xxx */dds_property_qospolicy_t property;
|
||||
};
|
||||
|
||||
struct nn_xmsg;
|
||||
|
|
|
|||
|
|
@ -211,7 +211,12 @@ static ddsi_tran_conn_t ddsi_raweth_create_conn (ddsi_tran_factory_t fact, uint3
|
|||
return NULL;
|
||||
}
|
||||
|
||||
uc = (ddsi_raweth_conn_t) ddsrt_malloc (sizeof (*uc));
|
||||
if ((uc = (ddsi_raweth_conn_t) ddsrt_malloc (sizeof (*uc))) == NULL)
|
||||
{
|
||||
ddsrt_close(sock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset (uc, 0, sizeof (*uc));
|
||||
uc->m_sock = sock;
|
||||
uc->m_ifindex = addr.sll_ifindex;
|
||||
|
|
@ -226,7 +231,7 @@ static ddsi_tran_conn_t ddsi_raweth_create_conn (ddsi_tran_factory_t fact, uint3
|
|||
uc->m_base.m_disable_multiplexing_fn = 0;
|
||||
|
||||
DDS_CTRACE (&fact->gv->logconfig, "ddsi_raweth_create_conn %s socket %d port %u\n", mcast ? "multicast" : "unicast", uc->m_sock, uc->m_base.m_base.m_port);
|
||||
return uc ? &uc->m_base : NULL;
|
||||
return &uc->m_base;
|
||||
}
|
||||
|
||||
static int isbroadcast(const nn_locator_t *loc)
|
||||
|
|
|
|||
18
src/core/ddsi/src/ddsi_rhc.c
Normal file
18
src/core/ddsi/src/ddsi_rhc.c
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "dds/ddsi/ddsi_rhc.h"
|
||||
|
||||
extern inline void ddsi_rhc_free (struct ddsi_rhc *rhc);
|
||||
extern inline bool ddsi_rhc_store (struct ddsi_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk);
|
||||
extern inline void ddsi_rhc_unregister_wr (struct ddsi_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo);
|
||||
extern inline void ddsi_rhc_relinquish_ownership (struct ddsi_rhc * __restrict rhc, const uint64_t wr_iid);
|
||||
extern inline void ddsi_rhc_set_qos (struct ddsi_rhc *rhc, const struct dds_qos *qos);
|
||||
|
|
@ -45,3 +45,5 @@ extern inline void ddsi_serdata_to_ser_unref (struct ddsi_serdata *d, const ddsr
|
|||
extern inline bool ddsi_serdata_to_sample (const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim);
|
||||
extern inline bool ddsi_serdata_topicless_to_sample (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim);
|
||||
extern inline bool ddsi_serdata_eqkey (const struct ddsi_serdata *a, const struct ddsi_serdata *b);
|
||||
extern inline bool ddsi_serdata_print (const struct ddsi_serdata *d, char *buf, size_t size);
|
||||
extern inline bool ddsi_serdata_print_topicless (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, char *buf, size_t size);
|
||||
|
|
|
|||
|
|
@ -453,6 +453,7 @@ static struct ddsi_serdata *serdata_default_from_sample_plist (const struct ddsi
|
|||
#ifndef NDEBUG
|
||||
size_t keysize;
|
||||
#endif
|
||||
assert(rawkey);
|
||||
switch (sample->keyparam)
|
||||
{
|
||||
case PID_PARTICIPANT_GUID:
|
||||
|
|
@ -629,6 +630,32 @@ static bool serdata_default_topicless_to_sample_cdr_nokey (const struct ddsi_ser
|
|||
return true;
|
||||
}
|
||||
|
||||
static size_t serdata_default_print_cdr (const struct ddsi_sertopic *sertopic_common, const struct ddsi_serdata *serdata_common, char *buf, size_t size)
|
||||
{
|
||||
const struct ddsi_serdata_default *d = (const struct ddsi_serdata_default *)serdata_common;
|
||||
const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)sertopic_common;
|
||||
dds_istream_t is;
|
||||
dds_istream_from_serdata_default (&is, d);
|
||||
if (d->c.kind == SDK_KEY)
|
||||
return dds_stream_print_key (&is, tp, buf, size);
|
||||
else
|
||||
return dds_stream_print_sample (&is, tp, buf, size);
|
||||
}
|
||||
|
||||
static size_t serdata_default_print_plist (const struct ddsi_sertopic *sertopic_common, const struct ddsi_serdata *serdata_common, char *buf, size_t size)
|
||||
{
|
||||
/* FIXME: should change q_plist.c to print to a string instead of a log, and then drop the
|
||||
logging of QoS in the rest of code, instead relying on this */
|
||||
(void)sertopic_common; (void)serdata_common;
|
||||
return (size_t) snprintf (buf, size, "(plist)");
|
||||
}
|
||||
|
||||
static size_t serdata_default_print_raw (const struct ddsi_sertopic *sertopic_common, const struct ddsi_serdata *serdata_common, char *buf, size_t size)
|
||||
{
|
||||
(void)sertopic_common; (void)serdata_common;
|
||||
return (size_t) snprintf (buf, size, "(blob)");
|
||||
}
|
||||
|
||||
const struct ddsi_serdata_ops ddsi_serdata_ops_cdr = {
|
||||
.get_size = serdata_default_get_size,
|
||||
.eqkey = serdata_default_eqkey,
|
||||
|
|
@ -641,7 +668,8 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_cdr = {
|
|||
.to_ser_ref = serdata_default_to_ser_ref,
|
||||
.to_ser_unref = serdata_default_to_ser_unref,
|
||||
.to_topicless = serdata_default_to_topicless,
|
||||
.topicless_to_sample = serdata_default_topicless_to_sample_cdr
|
||||
.topicless_to_sample = serdata_default_topicless_to_sample_cdr,
|
||||
.print = serdata_default_print_cdr
|
||||
};
|
||||
|
||||
const struct ddsi_serdata_ops ddsi_serdata_ops_cdr_nokey = {
|
||||
|
|
@ -656,7 +684,8 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_cdr_nokey = {
|
|||
.to_ser_ref = serdata_default_to_ser_ref,
|
||||
.to_ser_unref = serdata_default_to_ser_unref,
|
||||
.to_topicless = serdata_default_to_topicless,
|
||||
.topicless_to_sample = serdata_default_topicless_to_sample_cdr_nokey
|
||||
.topicless_to_sample = serdata_default_topicless_to_sample_cdr_nokey,
|
||||
.print = serdata_default_print_cdr
|
||||
};
|
||||
|
||||
const struct ddsi_serdata_ops ddsi_serdata_ops_plist = {
|
||||
|
|
@ -671,7 +700,8 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_plist = {
|
|||
.to_ser_ref = serdata_default_to_ser_ref,
|
||||
.to_ser_unref = serdata_default_to_ser_unref,
|
||||
.to_topicless = serdata_default_to_topicless,
|
||||
.topicless_to_sample = 0
|
||||
.topicless_to_sample = 0,
|
||||
.print = serdata_default_print_plist
|
||||
};
|
||||
|
||||
const struct ddsi_serdata_ops ddsi_serdata_ops_rawcdr = {
|
||||
|
|
@ -686,5 +716,6 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_rawcdr = {
|
|||
.to_ser_ref = serdata_default_to_ser_ref,
|
||||
.to_ser_unref = serdata_default_to_ser_unref,
|
||||
.to_topicless = serdata_default_to_topicless,
|
||||
.topicless_to_sample = 0
|
||||
.topicless_to_sample = 0,
|
||||
.print = serdata_default_print_raw
|
||||
};
|
||||
|
|
|
|||
|
|
@ -554,8 +554,9 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const nn_locator_t *d
|
|||
|
||||
/* If not connected attempt to conect */
|
||||
|
||||
if ((conn->m_sock == DDSRT_INVALID_SOCKET) && ! conn->m_base.m_server)
|
||||
if (conn->m_sock == DDSRT_INVALID_SOCKET)
|
||||
{
|
||||
assert (!conn->m_base.m_server);
|
||||
ddsi_tcp_conn_connect (conn, &msg);
|
||||
if (conn->m_sock == DDSRT_INVALID_SOCKET)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ void ddsi_threadmon_unregister_domain (struct ddsi_threadmon *sl, const struct q
|
|||
dummy.gv = gv;
|
||||
struct threadmon_domain *tmdom = ddsrt_hh_lookup (sl->domains, &dummy);
|
||||
assert (tmdom);
|
||||
ddsrt_hh_remove (sl->domains, tmdom);
|
||||
(void) ddsrt_hh_remove (sl->domains, tmdom);
|
||||
ddsrt_mutex_unlock (&sl->lock);
|
||||
ddsrt_free (tmdom);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
#include "dds/ddsi/q_bswap.h"
|
||||
|
||||
nn_guid_prefix_t nn_hton_guid_prefix (nn_guid_prefix_t p)
|
||||
ddsi_guid_prefix_t nn_hton_guid_prefix (ddsi_guid_prefix_t p)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 3; i++)
|
||||
|
|
@ -19,7 +19,7 @@ nn_guid_prefix_t nn_hton_guid_prefix (nn_guid_prefix_t p)
|
|||
return p;
|
||||
}
|
||||
|
||||
nn_guid_prefix_t nn_ntoh_guid_prefix (nn_guid_prefix_t p)
|
||||
ddsi_guid_prefix_t nn_ntoh_guid_prefix (ddsi_guid_prefix_t p)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 3; i++)
|
||||
|
|
@ -27,26 +27,26 @@ nn_guid_prefix_t nn_ntoh_guid_prefix (nn_guid_prefix_t p)
|
|||
return p;
|
||||
}
|
||||
|
||||
nn_entityid_t nn_hton_entityid (nn_entityid_t e)
|
||||
ddsi_entityid_t nn_hton_entityid (ddsi_entityid_t e)
|
||||
{
|
||||
e.u = toBE4u (e.u);
|
||||
return e;
|
||||
}
|
||||
|
||||
nn_entityid_t nn_ntoh_entityid (nn_entityid_t e)
|
||||
ddsi_entityid_t nn_ntoh_entityid (ddsi_entityid_t e)
|
||||
{
|
||||
e.u = fromBE4u (e.u);
|
||||
return e;
|
||||
}
|
||||
|
||||
nn_guid_t nn_hton_guid (nn_guid_t g)
|
||||
ddsi_guid_t nn_hton_guid (ddsi_guid_t g)
|
||||
{
|
||||
g.prefix = nn_hton_guid_prefix (g.prefix);
|
||||
g.entityid = nn_hton_entityid (g.entityid);
|
||||
return g;
|
||||
}
|
||||
|
||||
nn_guid_t nn_ntoh_guid (nn_guid_t g)
|
||||
ddsi_guid_t nn_ntoh_guid (ddsi_guid_t g)
|
||||
{
|
||||
g.prefix = nn_ntoh_guid_prefix (g.prefix);
|
||||
g.entityid = nn_ntoh_entityid (g.entityid);
|
||||
|
|
|
|||
|
|
@ -1012,6 +1012,8 @@ static size_t cfg_note_vsnprintf (struct cfg_note_buf *bb, const char *fmt, va_l
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void cfg_note_snprintf (struct cfg_note_buf *bb, const char *fmt, ...) ddsrt_attribute_format ((printf, 2, 3));
|
||||
|
||||
static void cfg_note_snprintf (struct cfg_note_buf *bb, const char *fmt, ...)
|
||||
{
|
||||
/* The reason the 2nd call to os_vsnprintf is here and not inside
|
||||
|
|
@ -1123,6 +1125,8 @@ static size_t cfg_note (struct cfgst *cfgst, uint32_t cat, size_t bsz, const cha
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void cfg_warning (struct cfgst *cfgst, const char *fmt, ...) ddsrt_attribute_format ((printf, 2, 3));
|
||||
|
||||
static void cfg_warning (struct cfgst *cfgst, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
|
@ -1134,6 +1138,8 @@ static void cfg_warning (struct cfgst *cfgst, const char *fmt, ...)
|
|||
} while (bsz > 0);
|
||||
}
|
||||
|
||||
static enum update_result cfg_error (struct cfgst *cfgst, const char *fmt, ...) ddsrt_attribute_format ((printf, 2, 3));
|
||||
|
||||
static enum update_result cfg_error (struct cfgst *cfgst, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
|
@ -1146,6 +1152,8 @@ static enum update_result cfg_error (struct cfgst *cfgst, const char *fmt, ...)
|
|||
return URES_ERROR;
|
||||
}
|
||||
|
||||
static void cfg_logelem (struct cfgst *cfgst, uint32_t sources, const char *fmt, ...) ddsrt_attribute_format ((printf, 3, 4));
|
||||
|
||||
static void cfg_logelem (struct cfgst *cfgst, uint32_t sources, const char *fmt, ...)
|
||||
{
|
||||
/* 89 = 1 + 2 + 31 + 1 + 10 + 2*22: the number of characters in
|
||||
|
|
@ -1317,14 +1325,17 @@ static enum update_result do_uint32_bitset (struct cfgst *cfgst, uint32_t *cats,
|
|||
char *copy = ddsrt_strdup (value), *cursor = copy, *tok;
|
||||
while ((tok = ddsrt_strsep (&cursor, ",")) != NULL)
|
||||
{
|
||||
const int idx = list_index (names, tok);
|
||||
const int idx = list_index (names, tok[0] == '-' ? tok+1 : tok);
|
||||
if (idx < 0)
|
||||
{
|
||||
const enum update_result ret = cfg_error (cfgst, "'%s' in '%s' undefined", tok, value);
|
||||
ddsrt_free (copy);
|
||||
return ret;
|
||||
}
|
||||
*cats |= codes[idx];
|
||||
if (tok[0] == '-')
|
||||
*cats &= ~codes[idx];
|
||||
else
|
||||
*cats |= codes[idx];
|
||||
}
|
||||
ddsrt_free (copy);
|
||||
return URES_SUCCESS;
|
||||
|
|
@ -1441,7 +1452,7 @@ static void pf_int64_unit (struct cfgst *cfgst, int64_t value, uint32_t sources,
|
|||
}
|
||||
assert (m > 0);
|
||||
assert (unit != NULL);
|
||||
cfg_logelem (cfgst, sources, "%lld %s", value / m, unit);
|
||||
cfg_logelem (cfgst, sources, "%"PRId64" %s", value / m, unit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1517,10 +1528,10 @@ GENERIC_ENUM_CTYPE (standards_conformance, enum nn_standards_conformance)
|
|||
|
||||
/* "trace" is special: it enables (nearly) everything */
|
||||
static const char *tracemask_names[] = {
|
||||
"fatal", "error", "warning", "info", "config", "discovery", "data", "radmin", "timing", "traffic", "topic", "tcp", "plist", "whc", "throttle", "rhc", "trace", NULL
|
||||
"fatal", "error", "warning", "info", "config", "discovery", "data", "radmin", "timing", "traffic", "topic", "tcp", "plist", "whc", "throttle", "rhc", "content", "trace", NULL
|
||||
};
|
||||
static const uint32_t tracemask_codes[] = {
|
||||
DDS_LC_FATAL, DDS_LC_ERROR, DDS_LC_WARNING, DDS_LC_INFO, DDS_LC_CONFIG, DDS_LC_DISCOVERY, DDS_LC_DATA, DDS_LC_RADMIN, DDS_LC_TIMING, DDS_LC_TRAFFIC, DDS_LC_TOPIC, DDS_LC_TCP, DDS_LC_PLIST, DDS_LC_WHC, DDS_LC_THROTTLE, DDS_LC_RHC, DDS_LC_ALL
|
||||
DDS_LC_FATAL, DDS_LC_ERROR, DDS_LC_WARNING, DDS_LC_INFO, DDS_LC_CONFIG, DDS_LC_DISCOVERY, DDS_LC_DATA, DDS_LC_RADMIN, DDS_LC_TIMING, DDS_LC_TRAFFIC, DDS_LC_TOPIC, DDS_LC_TCP, DDS_LC_PLIST, DDS_LC_WHC, DDS_LC_THROTTLE, DDS_LC_RHC, DDS_LC_CONTENT, DDS_LC_ALL
|
||||
};
|
||||
|
||||
static enum update_result uf_tracemask (struct cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value)
|
||||
|
|
@ -2383,6 +2394,8 @@ static int proc_elem_open (void *varg, UNUSED_ARG (uintptr_t parentinfo), UNUSED
|
|||
cfgst_push (cfgst, 0, &root_cfgelems[0], cfgst_parent (cfgst));
|
||||
cfgst->implicit_toplevel = ITL_INSERTED_2;
|
||||
}
|
||||
cfgst->source = (cfgst->source == 0) ? 1 : cfgst->source << 1;
|
||||
cfgst->first_data_in_source = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2691,10 +2704,13 @@ static FILE *config_open_file (char *tok, char **cursor, uint32_t domid)
|
|||
return fp;
|
||||
}
|
||||
|
||||
struct cfgst *config_init (const char *configfile, struct config *cfg, uint32_t domid)
|
||||
struct cfgst *config_init (const char *config, struct config *cfg, uint32_t domid)
|
||||
{
|
||||
int ok = 1;
|
||||
struct cfgst *cfgst;
|
||||
char env_input[32];
|
||||
char *copy, *cursor;
|
||||
struct ddsrt_xmlp_callbacks cb;
|
||||
|
||||
memset (cfg, 0, sizeof (*cfg));
|
||||
|
||||
|
|
@ -2715,72 +2731,67 @@ struct cfgst *config_init (const char *configfile, struct config *cfg, uint32_t
|
|||
ends up on the right value */
|
||||
cfgst->cfg->domainId = domid;
|
||||
|
||||
/* configfile == NULL will get you the default configuration */
|
||||
if (configfile) {
|
||||
char env_input[32];
|
||||
char *copy = ddsrt_strdup (configfile), *cursor = copy;
|
||||
struct ddsrt_xmlp_callbacks cb;
|
||||
cb.attr = proc_attr;
|
||||
cb.elem_close = proc_elem_close;
|
||||
cb.elem_data = proc_elem_data;
|
||||
cb.elem_open = proc_elem_open;
|
||||
cb.error = proc_error;
|
||||
|
||||
cb.attr = proc_attr;
|
||||
cb.elem_close = proc_elem_close;
|
||||
cb.elem_data = proc_elem_data;
|
||||
cb.elem_open = proc_elem_open;
|
||||
cb.error = proc_error;
|
||||
|
||||
while (*cursor && (isspace ((unsigned char) *cursor) || *cursor == ','))
|
||||
cursor++;
|
||||
while (ok && cursor && cursor[0])
|
||||
copy = ddsrt_strdup (config);
|
||||
cursor = copy;
|
||||
while (*cursor && (isspace ((unsigned char) *cursor) || *cursor == ','))
|
||||
cursor++;
|
||||
while (ok && cursor && cursor[0])
|
||||
{
|
||||
struct ddsrt_xmlp_state *qx;
|
||||
FILE *fp;
|
||||
char *tok;
|
||||
tok = cursor;
|
||||
if (tok[0] == '<')
|
||||
{
|
||||
struct ddsrt_xmlp_state *qx;
|
||||
FILE *fp;
|
||||
char *tok;
|
||||
tok = cursor;
|
||||
if (tok[0] == '<')
|
||||
{
|
||||
/* Read XML directly from input string */
|
||||
qx = ddsrt_xmlp_new_string (tok, cfgst, &cb);
|
||||
ddsrt_xmlp_set_options (qx, DDSRT_XMLP_ANONYMOUS_CLOSE_TAG | DDSRT_XMLP_MISSING_CLOSE_AS_EOF);
|
||||
fp = NULL;
|
||||
snprintf (env_input, sizeof (env_input), "CYCLONEDDS_URI+%u", (unsigned) (tok - copy));
|
||||
cfgst->input = env_input;
|
||||
cfgst->line = 1;
|
||||
}
|
||||
else if ((fp = config_open_file (tok, &cursor, domid)) == NULL)
|
||||
{
|
||||
ddsrt_free (copy);
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
qx = ddsrt_xmlp_new_file (fp, cfgst, &cb);
|
||||
cfgst->input = tok;
|
||||
cfgst->line = 1;
|
||||
}
|
||||
|
||||
cfgst->implicit_toplevel = (fp == NULL) ? ITL_ALLOWED : ITL_DISALLOWED;
|
||||
cfgst->first_data_in_source = true;
|
||||
cfgst_push (cfgst, 0, &root_cfgelem, cfgst->cfg);
|
||||
ok = (ddsrt_xmlp_parse (qx) >= 0) && !cfgst->error;
|
||||
assert (!ok ||
|
||||
(cfgst->path_depth == 1 && cfgst->implicit_toplevel == ITL_DISALLOWED) ||
|
||||
(cfgst->path_depth == 1 + (int) cfgst->implicit_toplevel));
|
||||
/* Pop until stack empty: error handling is rather brutal */
|
||||
while (cfgst->path_depth > 0)
|
||||
cfgst_pop (cfgst);
|
||||
if (fp != NULL)
|
||||
fclose (fp);
|
||||
else if (ok)
|
||||
cursor = tok + ddsrt_xmlp_get_bufpos (qx);
|
||||
ddsrt_xmlp_free (qx);
|
||||
assert (fp == NULL || cfgst->implicit_toplevel <= ITL_ALLOWED);
|
||||
if (cursor)
|
||||
{
|
||||
while (*cursor && (isspace ((unsigned char) cursor[0]) || cursor[0] == ','))
|
||||
cursor++;
|
||||
}
|
||||
/* Read XML directly from input string */
|
||||
qx = ddsrt_xmlp_new_string (tok, cfgst, &cb);
|
||||
ddsrt_xmlp_set_options (qx, DDSRT_XMLP_ANONYMOUS_CLOSE_TAG | DDSRT_XMLP_MISSING_CLOSE_AS_EOF);
|
||||
fp = NULL;
|
||||
snprintf (env_input, sizeof (env_input), "CYCLONEDDS_URI+%u", (unsigned) (tok - copy));
|
||||
cfgst->input = env_input;
|
||||
cfgst->line = 1;
|
||||
}
|
||||
else if ((fp = config_open_file (tok, &cursor, domid)) == NULL)
|
||||
{
|
||||
ddsrt_free (copy);
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
qx = ddsrt_xmlp_new_file (fp, cfgst, &cb);
|
||||
cfgst->input = tok;
|
||||
cfgst->line = 1;
|
||||
}
|
||||
|
||||
cfgst->implicit_toplevel = (fp == NULL) ? ITL_ALLOWED : ITL_DISALLOWED;
|
||||
cfgst->first_data_in_source = true;
|
||||
cfgst_push (cfgst, 0, &root_cfgelem, cfgst->cfg);
|
||||
ok = (ddsrt_xmlp_parse (qx) >= 0) && !cfgst->error;
|
||||
assert (!ok ||
|
||||
(cfgst->path_depth == 1 && cfgst->implicit_toplevel == ITL_DISALLOWED) ||
|
||||
(cfgst->path_depth == 1 + (int) cfgst->implicit_toplevel));
|
||||
/* Pop until stack empty: error handling is rather brutal */
|
||||
while (cfgst->path_depth > 0)
|
||||
cfgst_pop (cfgst);
|
||||
if (fp != NULL)
|
||||
fclose (fp);
|
||||
else if (ok)
|
||||
cursor = tok + ddsrt_xmlp_get_bufpos (qx);
|
||||
ddsrt_xmlp_free (qx);
|
||||
assert (fp == NULL || cfgst->implicit_toplevel <= ITL_ALLOWED);
|
||||
if (cursor)
|
||||
{
|
||||
while (*cursor && (isspace ((unsigned char) cursor[0]) || cursor[0] == ','))
|
||||
cursor++;
|
||||
}
|
||||
ddsrt_free (copy);
|
||||
}
|
||||
ddsrt_free (copy);
|
||||
|
||||
/* Set defaults for everything not set that we have a default value
|
||||
for, signal errors for things unset but without a default. */
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "dds/ddsrt/md5.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsrt/avl.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
#include "dds/ddsi/q_protocol.h"
|
||||
#include "dds/ddsi/q_rtps.h"
|
||||
#include "dds/ddsi/q_misc.h"
|
||||
|
|
@ -302,8 +303,8 @@ int spdp_write (struct participant *pp)
|
|||
ps.prismtech_participant_version_info.flags |= NN_PRISMTECH_FL_PARTICIPANT_IS_DDSI2;
|
||||
ddsrt_mutex_unlock (&pp->e.gv->privileged_pp_lock);
|
||||
|
||||
ddsrt_gethostname(node, sizeof(node)-1);
|
||||
node[sizeof(node)-1] = '\0';
|
||||
if (ddsrt_gethostname(node, sizeof(node)-1) < 0)
|
||||
ddsrt_strlcpy (node, "unknown", sizeof (node));
|
||||
size = strlen(node) + strlen(DDS_VERSION) + strlen(DDS_HOST_NAME) + strlen(DDS_TARGET_NAME) + 4; /* + ///'\0' */
|
||||
ps.prismtech_participant_version_info.internals = ddsrt_malloc(size);
|
||||
(void) snprintf(ps.prismtech_participant_version_info.internals, size, "%s/%s/%s/%s", node, DDS_VERSION, DDS_HOST_NAME, DDS_TARGET_NAME);
|
||||
|
|
@ -352,7 +353,7 @@ int spdp_dispose_unregister (struct participant *pp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static unsigned pseudo_random_delay (const nn_guid_t *x, const nn_guid_t *y, nn_mtime_t tnow)
|
||||
static unsigned pseudo_random_delay (const ddsi_guid_t *x, const ddsi_guid_t *y, nn_mtime_t tnow)
|
||||
{
|
||||
/* You know, an ordinary random generator would be even better, but
|
||||
the C library doesn't have a reentrant one and I don't feel like
|
||||
|
|
@ -381,7 +382,7 @@ static unsigned pseudo_random_delay (const nn_guid_t *x, const nn_guid_t *y, nn_
|
|||
return (unsigned) (m >> 32);
|
||||
}
|
||||
|
||||
static void respond_to_spdp (const struct q_globals *gv, const nn_guid_t *dest_proxypp_guid)
|
||||
static void respond_to_spdp (const struct q_globals *gv, const ddsi_guid_t *dest_proxypp_guid)
|
||||
{
|
||||
struct ephash_enum_participant est;
|
||||
struct participant *pp;
|
||||
|
|
@ -409,10 +410,9 @@ static void respond_to_spdp (const struct q_globals *gv, const nn_guid_t *dest_p
|
|||
static int handle_SPDP_dead (const struct receiver_state *rst, nn_wctime_t timestamp, const nn_plist_t *datap, unsigned statusinfo)
|
||||
{
|
||||
struct q_globals * const gv = rst->gv;
|
||||
nn_guid_t guid;
|
||||
ddsi_guid_t guid;
|
||||
|
||||
if (!(gv->logconfig.c.mask & DDS_LC_DISCOVERY))
|
||||
GVLOGDISC ("SPDP ST%x", statusinfo);
|
||||
GVLOGDISC ("SPDP ST%x", statusinfo);
|
||||
|
||||
if (datap->present & PP_PARTICIPANT_GUID)
|
||||
{
|
||||
|
|
@ -455,7 +455,7 @@ static void allowmulticast_aware_add_to_addrset (const struct q_globals *gv, uin
|
|||
add_to_addrset (gv, as, loc);
|
||||
}
|
||||
|
||||
static struct proxy_participant *find_ddsi2_proxy_participant (const struct ephash *guid_hash, const nn_guid_t *ppguid)
|
||||
static struct proxy_participant *find_ddsi2_proxy_participant (const struct ephash *guid_hash, const ddsi_guid_t *ppguid)
|
||||
{
|
||||
struct ephash_enum_proxy_participant it;
|
||||
struct proxy_participant *pp;
|
||||
|
|
@ -469,7 +469,7 @@ static struct proxy_participant *find_ddsi2_proxy_participant (const struct epha
|
|||
return pp;
|
||||
}
|
||||
|
||||
static void make_participants_dependent_on_ddsi2 (struct q_globals *gv, const nn_guid_t *ddsi2guid, nn_wctime_t timestamp)
|
||||
static void make_participants_dependent_on_ddsi2 (struct q_globals *gv, const ddsi_guid_t *ddsi2guid, nn_wctime_t timestamp)
|
||||
{
|
||||
struct ephash_enum_proxy_participant it;
|
||||
struct proxy_participant *pp, *d2pp;
|
||||
|
|
@ -514,17 +514,16 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_
|
|||
NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER |
|
||||
NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER;
|
||||
struct addrset *as_meta, *as_default;
|
||||
struct proxy_participant *proxypp;
|
||||
unsigned builtin_endpoint_set;
|
||||
unsigned prismtech_builtin_endpoint_set;
|
||||
nn_guid_t privileged_pp_guid;
|
||||
ddsi_guid_t privileged_pp_guid;
|
||||
dds_duration_t lease_duration;
|
||||
unsigned custom_flags = 0;
|
||||
|
||||
if (!(datap->present & PP_PARTICIPANT_GUID) || !(datap->present & PP_BUILTIN_ENDPOINT_SET))
|
||||
{
|
||||
GVWARNING ("data (SPDP, vendor %u.%u): no/invalid payload\n", rst->vendor.id[0], rst->vendor.id[1]);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* At some point the RTI implementation didn't mention
|
||||
|
|
@ -563,49 +562,56 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_
|
|||
prismtech_builtin_endpoint_set |= NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER | NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER;
|
||||
}
|
||||
|
||||
/* Local SPDP packets may be looped back, and that may include ones
|
||||
currently being deleted. The first thing that happens when
|
||||
deleting a participant is removing it from the hash table, and
|
||||
consequently the looped back packet may appear to be from an
|
||||
unknown participant. So we handle that, too. */
|
||||
|
||||
if (is_deleted_participant_guid (gv->deleted_participants, &datap->participant_guid, DPG_REMOTE))
|
||||
/* Do we know this GUID already? */
|
||||
{
|
||||
RSTTRACE ("SPDP ST0 "PGUIDFMT" (recently deleted)", PGUID (datap->participant_guid));
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
int islocal = 0;
|
||||
if (ephash_lookup_participant_guid (gv->guid_hash, &datap->participant_guid))
|
||||
islocal = 1;
|
||||
if (islocal)
|
||||
struct entity_common *existing_entity;
|
||||
if ((existing_entity = ephash_lookup_guid_untyped (gv->guid_hash, &datap->participant_guid)) == NULL)
|
||||
{
|
||||
RSTTRACE ("SPDP ST0 "PGUIDFMT" (local %d)", PGUID (datap->participant_guid), islocal);
|
||||
/* Local SPDP packets may be looped back, and that can include ones
|
||||
for participants currently being deleted. The first thing that
|
||||
happens when deleting a participant is removing it from the hash
|
||||
table, and consequently the looped back packet may appear to be
|
||||
from an unknown participant. So we handle that. */
|
||||
if (is_deleted_participant_guid (gv->deleted_participants, &datap->participant_guid, DPG_REMOTE))
|
||||
{
|
||||
RSTTRACE ("SPDP ST0 "PGUIDFMT" (recently deleted)", PGUID (datap->participant_guid));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (existing_entity->kind == EK_PARTICIPANT)
|
||||
{
|
||||
RSTTRACE ("SPDP ST0 "PGUIDFMT" (local)", PGUID (datap->participant_guid));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((proxypp = ephash_lookup_proxy_participant_guid (gv->guid_hash, &datap->participant_guid)) != NULL)
|
||||
{
|
||||
/* SPDP processing is so different from normal processing that we
|
||||
are even skipping the automatic lease renewal. Therefore do it
|
||||
regardless of
|
||||
gv.config.arrival_of_data_asserts_pp_and_ep_liveliness. */
|
||||
RSTTRACE ("SPDP ST0 "PGUIDFMT" (known)", PGUID (datap->participant_guid));
|
||||
lease_renew (ddsrt_atomic_ldvoidp (&proxypp->lease), now_et ());
|
||||
ddsrt_mutex_lock (&proxypp->e.lock);
|
||||
if (proxypp->implicitly_created || seq > proxypp->seq)
|
||||
else if (existing_entity->kind == EK_PROXY_PARTICIPANT)
|
||||
{
|
||||
if (proxypp->implicitly_created)
|
||||
GVLOGDISC (" (NEW was-implicitly-created)");
|
||||
else
|
||||
GVLOGDISC (" (update)");
|
||||
proxypp->implicitly_created = 0;
|
||||
update_proxy_participant_plist_locked (proxypp, seq, datap, UPD_PROXYPP_SPDP, timestamp);
|
||||
struct proxy_participant *proxypp = (struct proxy_participant *) existing_entity;
|
||||
int interesting = 0;
|
||||
RSTTRACE ("SPDP ST0 "PGUIDFMT" (known)", PGUID (datap->participant_guid));
|
||||
/* SPDP processing is so different from normal processing that we are
|
||||
even skipping the automatic lease renewal. Therefore do it regardless
|
||||
of gv.config.arrival_of_data_asserts_pp_and_ep_liveliness. */
|
||||
lease_renew (ddsrt_atomic_ldvoidp (&proxypp->lease), now_et ());
|
||||
ddsrt_mutex_lock (&proxypp->e.lock);
|
||||
if (proxypp->implicitly_created || seq > proxypp->seq)
|
||||
{
|
||||
interesting = 1;
|
||||
if (!(gv->logconfig.c.mask & DDS_LC_TRACE))
|
||||
GVLOGDISC ("SPDP ST0 "PGUIDFMT, PGUID (datap->participant_guid));
|
||||
GVLOGDISC (proxypp->implicitly_created ? " (NEW was-implicitly-created)" : " (update)");
|
||||
proxypp->implicitly_created = 0;
|
||||
update_proxy_participant_plist_locked (proxypp, seq, datap, UPD_PROXYPP_SPDP, timestamp);
|
||||
}
|
||||
ddsrt_mutex_unlock (&proxypp->e.lock);
|
||||
return interesting;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* mismatch on entity kind: that should never have gotten past the
|
||||
input validation */
|
||||
GVWARNING ("data (SPDP, vendor %u.%u): "PGUIDFMT" kind mismatch\n", rst->vendor.id[0], rst->vendor.id[1], PGUID (datap->participant_guid));
|
||||
return 0;
|
||||
}
|
||||
ddsrt_mutex_unlock (&proxypp->e.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GVLOGDISC ("SPDP ST0 "PGUIDFMT" bes %x ptbes %x NEW", PGUID (datap->participant_guid), builtin_endpoint_set, prismtech_builtin_endpoint_set);
|
||||
|
|
@ -646,7 +652,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_
|
|||
privileged_pp_guid.prefix = rst->src_guid_prefix;
|
||||
privileged_pp_guid.entityid.u = NN_ENTITYID_PARTICIPANT;
|
||||
if ((builtin_endpoint_set & bes_sedp_announcer_mask) != bes_sedp_announcer_mask &&
|
||||
memcmp (&privileged_pp_guid, &datap->participant_guid, sizeof (nn_guid_t)) != 0)
|
||||
memcmp (&privileged_pp_guid, &datap->participant_guid, sizeof (ddsi_guid_t)) != 0)
|
||||
{
|
||||
GVLOGDISC (" (depends on "PGUIDFMT")", PGUID (privileged_pp_guid));
|
||||
/* never expire lease for this proxy: it won't actually expire
|
||||
|
|
@ -791,10 +797,9 @@ static void handle_SPDP (const struct receiver_state *rst, seqno_t seq, nn_wctim
|
|||
{
|
||||
struct q_globals * const gv = rst->gv;
|
||||
const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */
|
||||
RSTTRACE("SPDP ST%x", statusinfo);
|
||||
if (data == NULL)
|
||||
{
|
||||
RSTTRACE(" no payload?\n");
|
||||
RSTTRACE ("SPDP ST%x no payload?\n", statusinfo);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
|
@ -881,7 +886,7 @@ static void add_locator_to_ps (const nn_locator_t *loc, void *varg)
|
|||
|
||||
static int sedp_write_endpoint
|
||||
(
|
||||
struct writer *wr, int alive, const nn_guid_t *epguid,
|
||||
struct writer *wr, int alive, const ddsi_guid_t *epguid,
|
||||
const struct entity_common *common, const struct endpoint_common *epcommon,
|
||||
const dds_qos_t *xqos, struct addrset *as)
|
||||
{
|
||||
|
|
@ -1040,9 +1045,9 @@ static const char *durability_to_string (dds_durability_kind_t k)
|
|||
return "undefined-durability";
|
||||
}
|
||||
|
||||
static struct proxy_participant *implicitly_create_proxypp (struct q_globals *gv, const nn_guid_t *ppguid, nn_plist_t *datap /* note: potentially modifies datap */, const nn_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp, seqno_t seq)
|
||||
static struct proxy_participant *implicitly_create_proxypp (struct q_globals *gv, const ddsi_guid_t *ppguid, nn_plist_t *datap /* note: potentially modifies datap */, const ddsi_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp, seqno_t seq)
|
||||
{
|
||||
nn_guid_t privguid;
|
||||
ddsi_guid_t privguid;
|
||||
nn_plist_t pp_plist;
|
||||
|
||||
if (memcmp (&ppguid->prefix, src_guid_prefix, sizeof (ppguid->prefix)) == 0)
|
||||
|
|
@ -1120,14 +1125,14 @@ static struct proxy_participant *implicitly_create_proxypp (struct q_globals *gv
|
|||
return ephash_lookup_proxy_participant_guid (gv->guid_hash, ppguid);
|
||||
}
|
||||
|
||||
static void handle_SEDP_alive (const struct receiver_state *rst, seqno_t seq, nn_plist_t *datap /* note: potentially modifies datap */, const nn_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp)
|
||||
static void handle_SEDP_alive (const struct receiver_state *rst, seqno_t seq, nn_plist_t *datap /* note: potentially modifies datap */, const ddsi_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp)
|
||||
{
|
||||
#define E(msg, lbl) do { GVLOGDISC (msg); goto lbl; } while (0)
|
||||
struct q_globals * const gv = rst->gv;
|
||||
struct proxy_participant *pp;
|
||||
struct proxy_writer * pwr = NULL;
|
||||
struct proxy_reader * prd = NULL;
|
||||
nn_guid_t ppguid;
|
||||
ddsi_guid_t ppguid;
|
||||
dds_qos_t *xqos;
|
||||
int reliable;
|
||||
struct addrset *as;
|
||||
|
|
@ -1466,7 +1471,7 @@ int sedp_write_cm_participant (struct participant *pp, int alive)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void handle_SEDP_CM (const struct receiver_state *rst, nn_entityid_t wr_entity_id, nn_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len)
|
||||
static void handle_SEDP_CM (const struct receiver_state *rst, ddsi_entityid_t wr_entity_id, nn_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len)
|
||||
{
|
||||
struct q_globals * const gv = rst->gv;
|
||||
const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */
|
||||
|
|
@ -1552,7 +1557,7 @@ static int defragment (unsigned char **datap, const struct nn_rdata *fragchain,
|
|||
}
|
||||
}
|
||||
|
||||
int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, UNUSED_ARG (const nn_guid_t *rdguid), UNUSED_ARG (void *qarg))
|
||||
int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, UNUSED_ARG (const ddsi_guid_t *rdguid), UNUSED_ARG (void *qarg))
|
||||
{
|
||||
struct q_globals * const gv = sampleinfo->rst->gv;
|
||||
struct proxy_writer *pwr;
|
||||
|
|
@ -1564,7 +1569,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str
|
|||
} keyhash_payload;
|
||||
unsigned statusinfo;
|
||||
int need_keyhash;
|
||||
nn_guid_t srcguid;
|
||||
ddsi_guid_t srcguid;
|
||||
Data_DataFrag_common_t *msg;
|
||||
unsigned char data_smhdr_flags;
|
||||
nn_plist_t qos;
|
||||
|
|
@ -1643,7 +1648,6 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str
|
|||
|
||||
/* Built-ins still do their own deserialization (SPDP <=> pwr ==
|
||||
NULL)). */
|
||||
assert (pwr == NULL || pwr->c.topic == NULL);
|
||||
if (statusinfo == 0)
|
||||
{
|
||||
if (datasz == 0 || !(data_smhdr_flags & DATA_FLAG_DATAFLAG))
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ struct debug_monitor {
|
|||
int stop;
|
||||
};
|
||||
|
||||
static int cpf (ddsi_tran_conn_t conn, const char *fmt, ...) ddsrt_attribute_format ((printf, 2, 3));
|
||||
|
||||
static int cpf (ddsi_tran_conn_t conn, const char *fmt, ...)
|
||||
{
|
||||
nn_locator_t loc;
|
||||
|
|
@ -107,35 +109,34 @@ static int print_addrset_if_notempty (ddsi_tran_conn_t conn, const char *prefix,
|
|||
return print_addrset (conn, prefix, as, suffix);
|
||||
}
|
||||
|
||||
static int print_any_endpoint_common (ddsi_tran_conn_t conn, const char *label, const struct entity_common *e,
|
||||
const struct dds_qos *xqos, const struct ddsi_sertopic *topic)
|
||||
static int print_any_endpoint_common (ddsi_tran_conn_t conn, const char *label, const struct entity_common *e, const struct dds_qos *xqos)
|
||||
{
|
||||
int x = 0;
|
||||
x += cpf (conn, " %s %x:%x:%x:%x ", label, PGUID (e->guid));
|
||||
x += cpf (conn, " %s "PGUIDFMT" ", label, PGUID (e->guid));
|
||||
if (xqos->present & QP_PARTITION)
|
||||
{
|
||||
if (xqos->partition.n > 1) cpf (conn, "{");
|
||||
for (uint32_t i = 0; i < xqos->partition.n; i++)
|
||||
x += cpf (conn, "%s%s", i == 0 ? "" : ",", xqos->partition.strs[i]);
|
||||
if (xqos->partition.n > 1) cpf (conn, "}");
|
||||
x += cpf (conn, ".%s/%s",
|
||||
topic && topic->name ? topic->name : (xqos->present & QP_TOPIC_NAME) ? xqos->topic_name : "(null)",
|
||||
topic && topic->type_name ? topic->type_name : (xqos->present & QP_TYPE_NAME) ? xqos->type_name : "(null)");
|
||||
const char *topic_name = (xqos->present & QP_TOPIC_NAME) ? xqos->topic_name : "null";
|
||||
const char *topic_typename = (xqos->present & QP_TYPE_NAME) ? xqos->type_name : "null";
|
||||
x += cpf (conn, ".%s/%s", topic_name, topic_typename);
|
||||
}
|
||||
cpf (conn, "\n");
|
||||
return x;
|
||||
}
|
||||
|
||||
static int print_endpoint_common (ddsi_tran_conn_t conn, const char *label, const struct entity_common *e, const struct endpoint_common *c, const struct dds_qos *xqos, const struct ddsi_sertopic *topic)
|
||||
static int print_endpoint_common (ddsi_tran_conn_t conn, const char *label, const struct entity_common *e, const struct endpoint_common *c, const struct dds_qos *xqos)
|
||||
{
|
||||
DDSRT_UNUSED_ARG (c);
|
||||
return print_any_endpoint_common (conn, label, e, xqos, topic);
|
||||
return print_any_endpoint_common (conn, label, e, xqos);
|
||||
}
|
||||
|
||||
static int print_proxy_endpoint_common (ddsi_tran_conn_t conn, const char *label, const struct entity_common *e, const struct proxy_endpoint_common *c)
|
||||
{
|
||||
int x = 0;
|
||||
x += print_any_endpoint_common (conn, label, e, c->xqos, c->topic);
|
||||
x += print_any_endpoint_common (conn, label, e, c->xqos);
|
||||
x += print_addrset_if_notempty (conn, " as", c->as, "\n");
|
||||
return x;
|
||||
}
|
||||
|
|
@ -151,7 +152,7 @@ static int print_participants (struct thread_state1 * const ts1, struct q_global
|
|||
while ((p = ephash_enum_participant_next (&e)) != NULL)
|
||||
{
|
||||
ddsrt_mutex_lock (&p->e.lock);
|
||||
x += cpf (conn, "pp %x:%x:%x:%x %s%s\n", PGUID (p->e.guid), p->e.name, p->is_ddsi2_pp ? " [ddsi2]" : "");
|
||||
x += cpf (conn, "pp "PGUIDFMT" %s%s\n", PGUID (p->e.guid), p->e.name, p->is_ddsi2_pp ? " [ddsi2]" : "");
|
||||
ddsrt_mutex_unlock (&p->e.lock);
|
||||
|
||||
{
|
||||
|
|
@ -165,12 +166,12 @@ static int print_participants (struct thread_state1 * const ts1, struct q_global
|
|||
if (r->c.pp != p)
|
||||
continue;
|
||||
ddsrt_mutex_lock (&r->e.lock);
|
||||
print_endpoint_common (conn, "rd", &r->e, &r->c, r->xqos, r->topic);
|
||||
print_endpoint_common (conn, "rd", &r->e, &r->c, r->xqos);
|
||||
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
||||
x += print_addrset_if_notempty (conn, " as", r->as, "\n");
|
||||
#endif
|
||||
for (m = ddsrt_avl_iter_first (&rd_writers_treedef, &r->writers, &writ); m; m = ddsrt_avl_iter_next (&writ))
|
||||
x += cpf (conn, " pwr %x:%x:%x:%x\n", PGUID (m->pwr_guid));
|
||||
x += cpf (conn, " pwr "PGUIDFMT"\n", PGUID (m->pwr_guid));
|
||||
ddsrt_mutex_unlock (&r->e.lock);
|
||||
}
|
||||
ephash_enum_reader_fini (&er);
|
||||
|
|
@ -188,22 +189,22 @@ static int print_participants (struct thread_state1 * const ts1, struct q_global
|
|||
if (w->c.pp != p)
|
||||
continue;
|
||||
ddsrt_mutex_lock (&w->e.lock);
|
||||
print_endpoint_common (conn, "wr", &w->e, &w->c, w->xqos, w->topic);
|
||||
print_endpoint_common (conn, "wr", &w->e, &w->c, w->xqos);
|
||||
whc_get_state(w->whc, &whcst);
|
||||
x += cpf (conn, " whc [%lld,%lld] unacked %"PRIuSIZE"%s [%u,%u] seq %lld seq_xmit %lld cs_seq %lld\n",
|
||||
x += cpf (conn, " whc [%"PRId64",%"PRId64"] unacked %"PRIuSIZE"%s [%"PRIu32",%"PRIu32"] seq %"PRId64" seq_xmit %"PRId64" cs_seq %"PRId64"\n",
|
||||
whcst.min_seq, whcst.max_seq, whcst.unacked_bytes,
|
||||
w->throttling ? " THROTTLING" : "",
|
||||
w->whc_low, w->whc_high,
|
||||
w->seq, READ_SEQ_XMIT(w), w->cs_seq);
|
||||
if (w->reliable)
|
||||
{
|
||||
x += cpf (conn, " hb %u ackhb %lld hb %lld wr %lld sched %lld #rel %d\n",
|
||||
w->hbcontrol.hbs_since_last_write, w->hbcontrol.t_of_last_ackhb,
|
||||
w->hbcontrol.t_of_last_hb, w->hbcontrol.t_of_last_write,
|
||||
w->hbcontrol.tsched, w->num_reliable_readers);
|
||||
x += cpf (conn, " #acks %u #nacks %u #rexmit %u #lost %u #throttle %u\n",
|
||||
x += cpf (conn, " hb %"PRIu32" ackhb %"PRId64" hb %"PRId64" wr %"PRId64" sched %"PRId64" #rel %"PRId32"\n",
|
||||
w->hbcontrol.hbs_since_last_write, w->hbcontrol.t_of_last_ackhb.v,
|
||||
w->hbcontrol.t_of_last_hb.v, w->hbcontrol.t_of_last_write.v,
|
||||
w->hbcontrol.tsched.v, w->num_reliable_readers);
|
||||
x += cpf (conn, " #acks %"PRIu32" #nacks %"PRIu32" #rexmit %"PRIu32" #lost %"PRIu32" #throttle %"PRIu32"\n",
|
||||
w->num_acks_received, w->num_nacks_received, w->rexmit_count, w->rexmit_lost_count, w->throttle_count);
|
||||
x += cpf (conn, " max-drop-seq %lld\n", writer_max_drop_seq (w));
|
||||
x += cpf (conn, " max-drop-seq %"PRId64"\n", writer_max_drop_seq (w));
|
||||
}
|
||||
x += print_addrset_if_notempty (conn, " as", w->as, "\n");
|
||||
for (m = ddsrt_avl_iter_first (&wr_readers_treedef, &w->readers, &rdit); m; m = ddsrt_avl_iter_next (&rdit))
|
||||
|
|
@ -213,7 +214,7 @@ static int print_participants (struct thread_state1 * const ts1, struct q_global
|
|||
wr_prd_flags[1] = m->assumed_in_sync ? 's' : '.';
|
||||
wr_prd_flags[2] = m->has_replied_to_hb ? 'a' : '.'; /* a = ack seen */
|
||||
wr_prd_flags[3] = 0;
|
||||
x += cpf (conn, " prd %x:%x:%x:%x %s @ %lld [%lld,%lld] #nacks %u\n",
|
||||
x += cpf (conn, " prd "PGUIDFMT" %s @ %"PRId64" [%"PRId64",%"PRId64"] #nacks %"PRIu32"\n",
|
||||
PGUID (m->prd_guid), wr_prd_flags, m->seq, m->min_seq, m->max_seq, m->rexmit_requests);
|
||||
}
|
||||
ddsrt_mutex_unlock (&w->e.lock);
|
||||
|
|
@ -236,7 +237,7 @@ static int print_proxy_participants (struct thread_state1 * const ts1, struct q_
|
|||
while ((p = ephash_enum_proxy_participant_next (&e)) != NULL)
|
||||
{
|
||||
ddsrt_mutex_lock (&p->e.lock);
|
||||
x += cpf (conn, "proxypp %x:%x:%x:%x%s\n", PGUID (p->e.guid), p->is_ddsi2_pp ? " [ddsi2]" : "");
|
||||
x += cpf (conn, "proxypp "PGUIDFMT"%s\n", PGUID (p->e.guid), p->is_ddsi2_pp ? " [ddsi2]" : "");
|
||||
ddsrt_mutex_unlock (&p->e.lock);
|
||||
x += print_addrset (conn, " as data", p->as_default, "");
|
||||
x += print_addrset (conn, " meta", p->as_default, "\n");
|
||||
|
|
@ -254,7 +255,7 @@ static int print_proxy_participants (struct thread_state1 * const ts1, struct q_
|
|||
ddsrt_mutex_lock (&r->e.lock);
|
||||
print_proxy_endpoint_common (conn, "prd", &r->e, &r->c);
|
||||
for (m = ddsrt_avl_iter_first (&rd_writers_treedef, &r->writers, &writ); m; m = ddsrt_avl_iter_next (&writ))
|
||||
x += cpf (conn, " wr %x:%x:%x:%x\n", PGUID (m->wr_guid));
|
||||
x += cpf (conn, " wr "PGUIDFMT"\n", PGUID (m->wr_guid));
|
||||
ddsrt_mutex_unlock (&r->e.lock);
|
||||
}
|
||||
ephash_enum_proxy_reader_fini (&er);
|
||||
|
|
@ -272,20 +273,20 @@ static int print_proxy_participants (struct thread_state1 * const ts1, struct q_
|
|||
continue;
|
||||
ddsrt_mutex_lock (&w->e.lock);
|
||||
print_proxy_endpoint_common (conn, "pwr", &w->e, &w->c);
|
||||
x += cpf (conn, " last_seq %lld last_fragnum %u\n", w->last_seq, w->last_fragnum);
|
||||
x += cpf (conn, " last_seq %"PRId64" last_fragnum %"PRIu32"\n", w->last_seq, w->last_fragnum);
|
||||
for (m = ddsrt_avl_iter_first (&wr_readers_treedef, &w->readers, &rdit); m; m = ddsrt_avl_iter_next (&rdit))
|
||||
{
|
||||
x += cpf (conn, " rd %x:%x:%x:%x (nack %lld %lld)\n",
|
||||
PGUID (m->rd_guid), m->seq_last_nack, m->t_last_nack);
|
||||
x += cpf (conn, " rd "PGUIDFMT" (nack %"PRId64" %"PRId64")\n",
|
||||
PGUID (m->rd_guid), m->seq_last_nack, m->t_last_nack.v);
|
||||
switch (m->in_sync)
|
||||
{
|
||||
case PRMSS_SYNC:
|
||||
break;
|
||||
case PRMSS_TLCATCHUP:
|
||||
x += cpf (conn, " tl-catchup end_of_tl_seq %lld\n", m->u.not_in_sync.end_of_tl_seq);
|
||||
x += cpf (conn, " tl-catchup end_of_tl_seq %"PRId64"\n", m->u.not_in_sync.end_of_tl_seq);
|
||||
break;
|
||||
case PRMSS_OUT_OF_SYNC:
|
||||
x += cpf (conn, " out-of-sync end_of_tl_seq %lld\n", m->u.not_in_sync.end_of_tl_seq);
|
||||
x += cpf (conn, " out-of-sync end_of_tl_seq %"PRId64"\n", m->u.not_in_sync.end_of_tl_seq);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
#include "dds/ddsi/ddsi_mcgroup.h"
|
||||
#include "dds/ddsi/q_receive.h"
|
||||
#include "dds/ddsi/ddsi_udp.h" /* nn_mc4gen_address_t */
|
||||
#include "dds/ddsi/q_rhc.h"
|
||||
#include "dds/ddsi/ddsi_rhc.h"
|
||||
|
||||
#include "dds/ddsi/sysdeps.h"
|
||||
#include "dds__whc.h"
|
||||
|
|
@ -51,7 +51,7 @@
|
|||
|
||||
struct deleted_participant {
|
||||
ddsrt_avl_node_t avlnode;
|
||||
nn_guid_t guid;
|
||||
ddsi_guid_t guid;
|
||||
unsigned for_what;
|
||||
nn_mtime_t t_prune;
|
||||
};
|
||||
|
|
@ -59,6 +59,7 @@ struct deleted_participant {
|
|||
struct deleted_participants_admin {
|
||||
ddsrt_mutex_t deleted_participants_lock;
|
||||
ddsrt_avl_tree_t deleted_participants;
|
||||
const ddsrt_log_cfg_t *logcfg;
|
||||
int64_t delay;
|
||||
};
|
||||
|
||||
|
|
@ -92,10 +93,10 @@ static const unsigned prismtech_builtin_writers_besmask =
|
|||
NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER |
|
||||
NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER;
|
||||
|
||||
static dds_return_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc, status_cb_t status_cb, void *status_cbarg);
|
||||
static dds_return_t new_reader_guid (struct reader **rd_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct rhc *rhc, status_cb_t status_cb, void *status_cbarg);
|
||||
static struct participant *ref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity);
|
||||
static void unref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity);
|
||||
static dds_return_t new_writer_guid (struct writer **wr_out, const struct ddsi_guid *guid, const struct ddsi_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc, status_cb_t status_cb, void *status_cbarg);
|
||||
static dds_return_t new_reader_guid (struct reader **rd_out, const struct ddsi_guid *guid, const struct ddsi_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct ddsi_rhc *rhc, status_cb_t status_cb, void *status_cbarg);
|
||||
static struct participant *ref_participant (struct participant *pp, const struct ddsi_guid *guid_of_refing_entity);
|
||||
static void unref_participant (struct participant *pp, const struct ddsi_guid *guid_of_refing_entity);
|
||||
|
||||
static int gcreq_participant (struct participant *pp);
|
||||
static int gcreq_writer (struct writer *wr);
|
||||
|
|
@ -104,24 +105,29 @@ static int gcreq_proxy_participant (struct proxy_participant *proxypp);
|
|||
static int gcreq_proxy_writer (struct proxy_writer *pwr);
|
||||
static int gcreq_proxy_reader (struct proxy_reader *prd);
|
||||
|
||||
extern inline bool builtintopic_is_visible (const struct ddsi_builtin_topic_interface *btif, const struct nn_guid *guid, nn_vendorid_t vendorid);
|
||||
extern inline bool builtintopic_is_visible (const struct ddsi_builtin_topic_interface *btif, const struct ddsi_guid *guid, nn_vendorid_t vendorid);
|
||||
extern inline bool builtintopic_is_builtintopic (const struct ddsi_builtin_topic_interface *btif, const struct ddsi_sertopic *topic);
|
||||
extern inline struct ddsi_tkmap_instance *builtintopic_get_tkmap_entry (const struct ddsi_builtin_topic_interface *btif, const struct nn_guid *guid);
|
||||
extern inline struct ddsi_tkmap_instance *builtintopic_get_tkmap_entry (const struct ddsi_builtin_topic_interface *btif, const struct ddsi_guid *guid);
|
||||
extern inline void builtintopic_write (const struct ddsi_builtin_topic_interface *btif, const struct entity_common *e, nn_wctime_t timestamp, bool alive);
|
||||
|
||||
static int compare_guid (const void *va, const void *vb)
|
||||
{
|
||||
return memcmp (va, vb, sizeof (nn_guid_t));
|
||||
return memcmp (va, vb, sizeof (ddsi_guid_t));
|
||||
}
|
||||
|
||||
nn_entityid_t to_entityid (unsigned u)
|
||||
bool is_null_guid (const ddsi_guid_t *guid)
|
||||
{
|
||||
nn_entityid_t e;
|
||||
return guid->prefix.u[0] == 0 && guid->prefix.u[1] == 0 && guid->prefix.u[2] == 0 && guid->entityid.u == 0;
|
||||
}
|
||||
|
||||
ddsi_entityid_t to_entityid (unsigned u)
|
||||
{
|
||||
ddsi_entityid_t e;
|
||||
e.u = u;
|
||||
return e;
|
||||
}
|
||||
|
||||
int is_writer_entityid (nn_entityid_t id)
|
||||
int is_writer_entityid (ddsi_entityid_t id)
|
||||
{
|
||||
switch (id.u & NN_ENTITYID_KIND_MASK)
|
||||
{
|
||||
|
|
@ -133,7 +139,7 @@ int is_writer_entityid (nn_entityid_t id)
|
|||
}
|
||||
}
|
||||
|
||||
int is_reader_entityid (nn_entityid_t id)
|
||||
int is_reader_entityid (ddsi_entityid_t id)
|
||||
{
|
||||
switch (id.u & NN_ENTITYID_KIND_MASK)
|
||||
{
|
||||
|
|
@ -145,7 +151,7 @@ int is_reader_entityid (nn_entityid_t id)
|
|||
}
|
||||
}
|
||||
|
||||
int is_keyed_endpoint_entityid (nn_entityid_t id)
|
||||
int is_keyed_endpoint_entityid (ddsi_entityid_t id)
|
||||
{
|
||||
switch (id.u & NN_ENTITYID_KIND_MASK)
|
||||
{
|
||||
|
|
@ -160,7 +166,7 @@ int is_keyed_endpoint_entityid (nn_entityid_t id)
|
|||
}
|
||||
}
|
||||
|
||||
int is_builtin_entityid (nn_entityid_t id, nn_vendorid_t vendorid)
|
||||
int is_builtin_entityid (ddsi_entityid_t id, nn_vendorid_t vendorid)
|
||||
{
|
||||
if ((id.u & NN_ENTITYID_SOURCE_MASK) == NN_ENTITYID_SOURCE_BUILTIN)
|
||||
return 1;
|
||||
|
|
@ -175,7 +181,7 @@ int is_builtin_entityid (nn_entityid_t id, nn_vendorid_t vendorid)
|
|||
}
|
||||
}
|
||||
|
||||
int is_builtin_endpoint (nn_entityid_t id, nn_vendorid_t vendorid)
|
||||
int is_builtin_endpoint (ddsi_entityid_t id, nn_vendorid_t vendorid)
|
||||
{
|
||||
return is_builtin_entityid (id, vendorid) && id.u != NN_ENTITYID_PARTICIPANT;
|
||||
}
|
||||
|
|
@ -186,7 +192,7 @@ bool is_local_orphan_endpoint (const struct entity_common *e)
|
|||
is_builtin_endpoint (e->guid.entityid, NN_VENDORID_ECLIPSE));
|
||||
}
|
||||
|
||||
static void entity_common_init (struct entity_common *e, struct q_globals *gv, const struct nn_guid *guid, const char *name, enum entity_kind kind, nn_wctime_t tcreate, nn_vendorid_t vendorid, bool onlylocal)
|
||||
static void entity_common_init (struct entity_common *e, struct q_globals *gv, const struct ddsi_guid *guid, const char *name, enum entity_kind kind, nn_wctime_t tcreate, nn_vendorid_t vendorid, bool onlylocal)
|
||||
{
|
||||
e->guid = *guid;
|
||||
e->kind = kind;
|
||||
|
|
@ -296,13 +302,22 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e)
|
|||
return NN_VENDORID_UNKNOWN;
|
||||
}
|
||||
|
||||
void ddsi_make_writer_info(struct ddsi_writer_info *wrinfo, const struct entity_common *e, const struct dds_qos *xqos)
|
||||
{
|
||||
wrinfo->guid = e->guid;
|
||||
wrinfo->ownership_strength = xqos->ownership_strength.value;
|
||||
wrinfo->auto_dispose = xqos->writer_data_lifecycle.autodispose_unregistered_instances;
|
||||
wrinfo->iid = e->iid;
|
||||
}
|
||||
|
||||
/* DELETED PARTICIPANTS --------------------------------------------- */
|
||||
|
||||
struct deleted_participants_admin *deleted_participants_admin_new (int64_t delay)
|
||||
struct deleted_participants_admin *deleted_participants_admin_new (const ddsrt_log_cfg_t *logcfg, int64_t delay)
|
||||
{
|
||||
struct deleted_participants_admin *admin = ddsrt_malloc (sizeof (*admin));
|
||||
ddsrt_mutex_init (&admin->deleted_participants_lock);
|
||||
ddsrt_avl_init (&deleted_participants_treedef, &admin->deleted_participants);
|
||||
admin->logcfg = logcfg;
|
||||
admin->delay = delay;
|
||||
return admin;
|
||||
}
|
||||
|
|
@ -326,6 +341,7 @@ static void prune_deleted_participant_guids_unlocked (struct deleted_participant
|
|||
struct deleted_participant *dpp1 = ddsrt_avl_find_succ (&deleted_participants_treedef, &admin->deleted_participants, dpp);
|
||||
if (dpp->t_prune.v < tnow.v)
|
||||
{
|
||||
DDS_CLOG (DDS_LC_DISCOVERY, admin->logcfg, "prune_deleted_participant_guid("PGUIDFMT")\n", PGUID (dpp->guid));
|
||||
ddsrt_avl_delete (&deleted_participants_treedef, &admin->deleted_participants, dpp);
|
||||
ddsrt_free (dpp);
|
||||
}
|
||||
|
|
@ -340,7 +356,7 @@ static void prune_deleted_participant_guids (struct deleted_participants_admin *
|
|||
ddsrt_mutex_unlock (&admin->deleted_participants_lock);
|
||||
}
|
||||
|
||||
static void remember_deleted_participant_guid (struct deleted_participants_admin *admin, const struct nn_guid *guid)
|
||||
static void remember_deleted_participant_guid (struct deleted_participants_admin *admin, const struct ddsi_guid *guid)
|
||||
{
|
||||
struct deleted_participant *n;
|
||||
ddsrt_avl_ipath_t path;
|
||||
|
|
@ -358,7 +374,7 @@ static void remember_deleted_participant_guid (struct deleted_participants_admin
|
|||
ddsrt_mutex_unlock (&admin->deleted_participants_lock);
|
||||
}
|
||||
|
||||
int is_deleted_participant_guid (struct deleted_participants_admin *admin, const struct nn_guid *guid, unsigned for_what)
|
||||
int is_deleted_participant_guid (struct deleted_participants_admin *admin, const struct ddsi_guid *guid, unsigned for_what)
|
||||
{
|
||||
struct deleted_participant *n;
|
||||
int known;
|
||||
|
|
@ -372,17 +388,16 @@ int is_deleted_participant_guid (struct deleted_participants_admin *admin, const
|
|||
return known;
|
||||
}
|
||||
|
||||
static void remove_deleted_participant_guid (ddsrt_log_cfg_t *logcfg, struct deleted_participants_admin *admin, const struct nn_guid *guid, unsigned for_what)
|
||||
static void remove_deleted_participant_guid (struct deleted_participants_admin *admin, const struct ddsi_guid *guid, unsigned for_what)
|
||||
{
|
||||
struct deleted_participant *n;
|
||||
DDS_CLOG (DDS_LC_DISCOVERY, logcfg, "remove_deleted_participant_guid("PGUIDFMT" for_what=%x)\n", PGUID (*guid), for_what);
|
||||
DDS_CLOG (DDS_LC_DISCOVERY, admin->logcfg, "remove_deleted_participant_guid("PGUIDFMT" for_what=%x)\n", PGUID (*guid), for_what);
|
||||
ddsrt_mutex_lock (&admin->deleted_participants_lock);
|
||||
if ((n = ddsrt_avl_lookup (&deleted_participants_treedef, &admin->deleted_participants, guid)) != NULL)
|
||||
n->t_prune = add_duration_to_mtime (now_mt (), admin->delay);
|
||||
ddsrt_mutex_unlock (&admin->deleted_participants_lock);
|
||||
}
|
||||
|
||||
|
||||
/* PARTICIPANT ------------------------------------------------------ */
|
||||
|
||||
static bool update_qos_locked (struct entity_common *e, dds_qos_t *ent_qos, const dds_qos_t *xqos, nn_wctime_t timestamp)
|
||||
|
|
@ -417,7 +432,7 @@ static bool update_qos_locked (struct entity_common *e, dds_qos_t *ent_qos, cons
|
|||
return true;
|
||||
}
|
||||
|
||||
static dds_return_t pp_allocate_entityid(nn_entityid_t *id, uint32_t kind, struct participant *pp)
|
||||
static dds_return_t pp_allocate_entityid(ddsi_entityid_t *id, uint32_t kind, struct participant *pp)
|
||||
{
|
||||
uint32_t id1;
|
||||
int ret = 0;
|
||||
|
|
@ -436,17 +451,17 @@ static dds_return_t pp_allocate_entityid(nn_entityid_t *id, uint32_t kind, struc
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void pp_release_entityid(struct participant *pp, nn_entityid_t id)
|
||||
static void pp_release_entityid(struct participant *pp, ddsi_entityid_t id)
|
||||
{
|
||||
ddsrt_mutex_lock (&pp->e.lock);
|
||||
inverse_uint32_set_free(&pp->avail_entityids.x, id.u / NN_ENTITYID_ALLOCSTEP);
|
||||
ddsrt_mutex_unlock (&pp->e.lock);
|
||||
}
|
||||
|
||||
dds_return_t new_participant_guid (const nn_guid_t *ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist)
|
||||
dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist)
|
||||
{
|
||||
struct participant *pp;
|
||||
nn_guid_t subguid, group_guid;
|
||||
ddsi_guid_t subguid, group_guid;
|
||||
|
||||
/* no reserved bits may be set */
|
||||
assert ((flags & ~(RTPS_PF_NO_BUILTIN_READERS | RTPS_PF_NO_BUILTIN_WRITERS | RTPS_PF_PRIVILEGED_PP | RTPS_PF_IS_DDSI2_PP | RTPS_PF_ONLY_LOCAL)) == 0);
|
||||
|
|
@ -699,20 +714,16 @@ dds_return_t new_participant_guid (const nn_guid_t *ppguid, struct q_globals *gv
|
|||
return 0;
|
||||
}
|
||||
|
||||
dds_return_t new_participant (nn_guid_t *p_ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist)
|
||||
dds_return_t new_participant (ddsi_guid_t *p_ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist)
|
||||
{
|
||||
nn_guid_t ppguid;
|
||||
|
||||
ddsrt_mutex_lock (&gv->privileged_pp_lock);
|
||||
ppguid = gv->next_ppguid;
|
||||
if (gv->next_ppguid.prefix.u[2]++ == ~0u)
|
||||
{
|
||||
ddsrt_mutex_unlock (&gv->privileged_pp_lock);
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
}
|
||||
ddsrt_mutex_unlock (&gv->privileged_pp_lock);
|
||||
*p_ppguid = ppguid;
|
||||
|
||||
union { uint64_t u64; uint32_t u32[2]; } u;
|
||||
u.u32[0] = gv->ppguid_base.prefix.u[1];
|
||||
u.u32[1] = gv->ppguid_base.prefix.u[2];
|
||||
u.u64 += ddsi_iid_gen ();
|
||||
p_ppguid->prefix.u[0] = gv->ppguid_base.prefix.u[0];
|
||||
p_ppguid->prefix.u[1] = u.u32[0];
|
||||
p_ppguid->prefix.u[2] = u.u32[1];
|
||||
p_ppguid->entityid.u = NN_ENTITYID_PARTICIPANT;
|
||||
return new_participant_guid (p_ppguid, gv, flags, plist);
|
||||
}
|
||||
|
||||
|
|
@ -724,9 +735,9 @@ void update_participant_plist (struct participant *pp, const nn_plist_t *plist)
|
|||
ddsrt_mutex_unlock (&pp->e.lock);
|
||||
}
|
||||
|
||||
static void delete_builtin_endpoint (struct q_globals *gv, const struct nn_guid *ppguid, unsigned entityid)
|
||||
static void delete_builtin_endpoint (struct q_globals *gv, const struct ddsi_guid *ppguid, unsigned entityid)
|
||||
{
|
||||
nn_guid_t guid;
|
||||
ddsi_guid_t guid;
|
||||
guid.prefix = ppguid->prefix;
|
||||
guid.entityid.u = entityid;
|
||||
assert (is_builtin_entityid (to_entityid (entityid), NN_VENDORID_ECLIPSE));
|
||||
|
|
@ -736,9 +747,9 @@ static void delete_builtin_endpoint (struct q_globals *gv, const struct nn_guid
|
|||
(void)delete_reader (gv, &guid);
|
||||
}
|
||||
|
||||
static struct participant *ref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity)
|
||||
static struct participant *ref_participant (struct participant *pp, const struct ddsi_guid *guid_of_refing_entity)
|
||||
{
|
||||
nn_guid_t stguid;
|
||||
ddsi_guid_t stguid;
|
||||
ddsrt_mutex_lock (&pp->refc_lock);
|
||||
if (guid_of_refing_entity && is_builtin_endpoint (guid_of_refing_entity->entityid, NN_VENDORID_ECLIPSE))
|
||||
pp->builtin_refc++;
|
||||
|
|
@ -755,7 +766,7 @@ static struct participant *ref_participant (struct participant *pp, const struct
|
|||
return pp;
|
||||
}
|
||||
|
||||
static void unref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity)
|
||||
static void unref_participant (struct participant *pp, const struct ddsi_guid *guid_of_refing_entity)
|
||||
{
|
||||
static const unsigned builtin_endpoints_tab[] = {
|
||||
NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER,
|
||||
|
|
@ -776,7 +787,7 @@ static void unref_participant (struct participant *pp, const struct nn_guid *gui
|
|||
NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER,
|
||||
NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_READER
|
||||
};
|
||||
nn_guid_t stguid;
|
||||
ddsi_guid_t stguid;
|
||||
|
||||
ddsrt_mutex_lock (&pp->refc_lock);
|
||||
if (guid_of_refing_entity && is_builtin_endpoint (guid_of_refing_entity->entityid, NN_VENDORID_ECLIPSE))
|
||||
|
|
@ -889,7 +900,7 @@ static void unref_participant (struct participant *pp, const struct nn_guid *gui
|
|||
ddsrt_free (pp->plist);
|
||||
ddsrt_mutex_destroy (&pp->refc_lock);
|
||||
entity_common_fini (&pp->e);
|
||||
remove_deleted_participant_guid (&pp->e.gv->logconfig, pp->e.gv->deleted_participants, &pp->e.guid, DPG_LOCAL);
|
||||
remove_deleted_participant_guid (pp->e.gv->deleted_participants, &pp->e.guid, DPG_LOCAL);
|
||||
inverse_uint32_set_fini(&pp->avail_entityids.x);
|
||||
ddsrt_free (pp);
|
||||
}
|
||||
|
|
@ -907,9 +918,10 @@ static void gc_delete_participant (struct gcreq *gcreq)
|
|||
unref_participant (pp, NULL);
|
||||
}
|
||||
|
||||
dds_return_t delete_participant (struct q_globals *gv, const struct nn_guid *ppguid)
|
||||
dds_return_t delete_participant (struct q_globals *gv, const struct ddsi_guid *ppguid)
|
||||
{
|
||||
struct participant *pp;
|
||||
GVLOGDISC ("delete_participant("PGUIDFMT")\n", PGUID (*ppguid));
|
||||
if ((pp = ephash_lookup_participant_guid (gv->guid_hash, ppguid)) == NULL)
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
builtintopic_write (gv->builtin_topic_interface, &pp->e, now(), false);
|
||||
|
|
@ -921,7 +933,7 @@ dds_return_t delete_participant (struct q_globals *gv, const struct nn_guid *ppg
|
|||
|
||||
struct writer *get_builtin_writer (const struct participant *pp, unsigned entityid)
|
||||
{
|
||||
nn_guid_t bwr_guid;
|
||||
ddsi_guid_t bwr_guid;
|
||||
unsigned bes_mask = 0, prismtech_bes_mask = 0;
|
||||
|
||||
if (pp->e.onlylocal) {
|
||||
|
|
@ -1391,7 +1403,7 @@ static void free_wr_rd_match (struct wr_rd_match *m)
|
|||
if (m) ddsrt_free (m);
|
||||
}
|
||||
|
||||
static void writer_drop_connection (const struct nn_guid *wr_guid, const struct proxy_reader *prd)
|
||||
static void writer_drop_connection (const struct ddsi_guid *wr_guid, const struct proxy_reader *prd)
|
||||
{
|
||||
struct writer *wr;
|
||||
if ((wr = ephash_lookup_writer_guid (prd->e.gv->guid_hash, wr_guid)) != NULL)
|
||||
|
|
@ -1421,7 +1433,7 @@ static void writer_drop_connection (const struct nn_guid *wr_guid, const struct
|
|||
}
|
||||
}
|
||||
|
||||
static void writer_drop_local_connection (const struct nn_guid *wr_guid, struct reader *rd)
|
||||
static void writer_drop_local_connection (const struct ddsi_guid *wr_guid, struct reader *rd)
|
||||
{
|
||||
/* Only called by gc_delete_reader, so we actually have a reader pointer */
|
||||
struct writer *wr;
|
||||
|
|
@ -1448,7 +1460,7 @@ static void writer_drop_local_connection (const struct nn_guid *wr_guid, struct
|
|||
}
|
||||
}
|
||||
|
||||
static void reader_drop_connection (const struct nn_guid *rd_guid, const struct proxy_writer *pwr)
|
||||
static void reader_drop_connection (const struct ddsi_guid *rd_guid, const struct proxy_writer *pwr)
|
||||
{
|
||||
struct reader *rd;
|
||||
if ((rd = ephash_lookup_reader_guid (pwr->e.gv->guid_hash, rd_guid)) != NULL)
|
||||
|
|
@ -1458,31 +1470,33 @@ static void reader_drop_connection (const struct nn_guid *rd_guid, const struct
|
|||
if ((m = ddsrt_avl_lookup (&rd_writers_treedef, &rd->writers, &pwr->e.guid)) != NULL)
|
||||
ddsrt_avl_delete (&rd_writers_treedef, &rd->writers, m);
|
||||
ddsrt_mutex_unlock (&rd->e.lock);
|
||||
if (m != NULL)
|
||||
{
|
||||
if (rd->rhc)
|
||||
{
|
||||
struct ddsi_writer_info wrinfo;
|
||||
ddsi_make_writer_info (&wrinfo, &pwr->e, pwr->c.xqos);
|
||||
ddsi_rhc_unregister_wr (rd->rhc, &wrinfo);
|
||||
}
|
||||
if (rd->status_cb)
|
||||
{
|
||||
status_cb_data_t data;
|
||||
|
||||
data.add = false;
|
||||
data.handle = pwr->e.iid;
|
||||
|
||||
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
|
||||
data.raw_status_id = (int) DDS_SUBSCRIPTION_MATCHED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
}
|
||||
}
|
||||
free_rd_pwr_match (pwr->e.gv, m);
|
||||
|
||||
if (rd->rhc)
|
||||
{
|
||||
struct proxy_writer_info pwr_info;
|
||||
make_proxy_writer_info(&pwr_info, &pwr->e, pwr->c.xqos);
|
||||
rhc_unregister_wr (rd->rhc, &pwr_info);
|
||||
}
|
||||
if (rd->status_cb)
|
||||
{
|
||||
status_cb_data_t data;
|
||||
|
||||
data.add = false;
|
||||
data.handle = pwr->e.iid;
|
||||
|
||||
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
|
||||
data.raw_status_id = (int) DDS_SUBSCRIPTION_MATCHED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reader_drop_local_connection (const struct nn_guid *rd_guid, const struct writer *wr)
|
||||
static void reader_drop_local_connection (const struct ddsi_guid *rd_guid, const struct writer *wr)
|
||||
{
|
||||
struct reader *rd;
|
||||
if ((rd = ephash_lookup_reader_guid (wr->e.gv->guid_hash, rd_guid)) != NULL)
|
||||
|
|
@ -1492,32 +1506,34 @@ static void reader_drop_local_connection (const struct nn_guid *rd_guid, const s
|
|||
if ((m = ddsrt_avl_lookup (&rd_local_writers_treedef, &rd->local_writers, &wr->e.guid)) != NULL)
|
||||
ddsrt_avl_delete (&rd_local_writers_treedef, &rd->local_writers, m);
|
||||
ddsrt_mutex_unlock (&rd->e.lock);
|
||||
if (m != NULL)
|
||||
{
|
||||
if (rd->rhc)
|
||||
{
|
||||
/* FIXME: */
|
||||
struct ddsi_writer_info wrinfo;
|
||||
ddsi_make_writer_info (&wrinfo, &wr->e, wr->xqos);
|
||||
ddsi_rhc_unregister_wr (rd->rhc, &wrinfo);
|
||||
}
|
||||
if (rd->status_cb)
|
||||
{
|
||||
status_cb_data_t data;
|
||||
|
||||
data.add = false;
|
||||
data.handle = wr->e.iid;
|
||||
|
||||
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
|
||||
data.raw_status_id = (int) DDS_SUBSCRIPTION_MATCHED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
}
|
||||
}
|
||||
free_rd_wr_match (m);
|
||||
|
||||
if (rd->rhc)
|
||||
{
|
||||
/* FIXME: */
|
||||
struct proxy_writer_info pwr_info;
|
||||
make_proxy_writer_info(&pwr_info, &wr->e, wr->xqos);
|
||||
rhc_unregister_wr (rd->rhc, &pwr_info);
|
||||
}
|
||||
if (rd->status_cb)
|
||||
{
|
||||
status_cb_data_t data;
|
||||
|
||||
data.add = false;
|
||||
data.handle = wr->e.iid;
|
||||
|
||||
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
|
||||
data.raw_status_id = (int) DDS_SUBSCRIPTION_MATCHED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_reader_init_acknack_count (const ddsrt_log_cfg_t *logcfg, const struct ephash *guid_hash, const struct nn_guid *rd_guid, nn_count_t count)
|
||||
static void update_reader_init_acknack_count (const ddsrt_log_cfg_t *logcfg, const struct ephash *guid_hash, const struct ddsi_guid *rd_guid, nn_count_t count)
|
||||
{
|
||||
struct reader *rd;
|
||||
|
||||
|
|
@ -1539,7 +1555,7 @@ static void update_reader_init_acknack_count (const ddsrt_log_cfg_t *logcfg, con
|
|||
}
|
||||
}
|
||||
|
||||
static void proxy_writer_drop_connection (const struct nn_guid *pwr_guid, struct reader *rd)
|
||||
static void proxy_writer_drop_connection (const struct ddsi_guid *pwr_guid, struct reader *rd)
|
||||
{
|
||||
/* Only called by gc_delete_reader, so we actually have a reader pointer */
|
||||
struct proxy_writer *pwr;
|
||||
|
|
@ -1574,7 +1590,7 @@ static void proxy_writer_drop_connection (const struct nn_guid *pwr_guid, struct
|
|||
}
|
||||
}
|
||||
|
||||
static void proxy_reader_drop_connection (const struct nn_guid *prd_guid, struct writer *wr)
|
||||
static void proxy_reader_drop_connection (const struct ddsi_guid *prd_guid, struct writer *wr)
|
||||
{
|
||||
struct proxy_reader *prd;
|
||||
if ((prd = ephash_lookup_proxy_reader_guid (wr->e.gv->guid_hash, prd_guid)) != NULL)
|
||||
|
|
@ -1719,12 +1735,12 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd)
|
|||
whc_sample_iter_init(wr->whc, &it);
|
||||
while (whc_sample_iter_borrow_next(&it, &sample))
|
||||
{
|
||||
struct proxy_writer_info pwr_info;
|
||||
struct ddsi_writer_info wrinfo;
|
||||
struct ddsi_serdata *payload = sample.serdata;
|
||||
/* FIXME: whc has tk reference in its index nodes, which is what we really should be iterating over anyway, and so we don't really have to look them up anymore */
|
||||
struct ddsi_tkmap_instance *tk = ddsi_tkmap_lookup_instance_ref (tkmap, payload);
|
||||
make_proxy_writer_info (&pwr_info, &wr->e, wr->xqos);
|
||||
(void) rhc_store (rd->rhc, &pwr_info, payload, tk);
|
||||
ddsi_make_writer_info (&wrinfo, &wr->e, wr->xqos);
|
||||
(void) ddsi_rhc_store (rd->rhc, &wrinfo, payload, tk);
|
||||
ddsi_tkmap_instance_unref (tkmap, tk);
|
||||
}
|
||||
}
|
||||
|
|
@ -1777,24 +1793,24 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr,
|
|||
ddsrt_mutex_unlock (&rd->e.lock);
|
||||
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
if (rd->favours_ssm && pwr->supports_ssm)
|
||||
{
|
||||
/* pwr->supports_ssm is set if addrset_contains_ssm(pwr->ssm), so
|
||||
if (rd->favours_ssm && pwr->supports_ssm)
|
||||
{
|
||||
/* pwr->supports_ssm is set if addrset_contains_ssm(pwr->ssm), so
|
||||
any_ssm must succeed. */
|
||||
if (!addrset_any_uc (pwr->c.as, &m->ssm_src_loc))
|
||||
assert (0);
|
||||
if (!addrset_any_ssm (rd->e.gv, pwr->c.as, &m->ssm_mc_loc))
|
||||
assert (0);
|
||||
/* FIXME: for now, assume that the ports match for datasock_mc --
|
||||
if (!addrset_any_uc (pwr->c.as, &m->ssm_src_loc))
|
||||
assert (0);
|
||||
if (!addrset_any_ssm (rd->e.gv, pwr->c.as, &m->ssm_mc_loc))
|
||||
assert (0);
|
||||
/* FIXME: for now, assume that the ports match for datasock_mc --
|
||||
't would be better to dynamically create and destroy sockets on
|
||||
an as needed basis. */
|
||||
ddsi_join_mc (rd->e.gv, rd->e.gv->mship, rd->e.gv->data_conn_mc, &m->ssm_src_loc, &m->ssm_mc_loc);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_unspec_locator (&m->ssm_src_loc);
|
||||
set_unspec_locator (&m->ssm_mc_loc);
|
||||
}
|
||||
ddsi_join_mc (rd->e.gv, rd->e.gv->mship, rd->e.gv->data_conn_mc, &m->ssm_src_loc, &m->ssm_mc_loc);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_unspec_locator (&m->ssm_src_loc);
|
||||
set_unspec_locator (&m->ssm_mc_loc);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rd->status_cb)
|
||||
|
|
@ -1855,8 +1871,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader
|
|||
if (ddsrt_avl_lookup_ipath (&pwr_readers_treedef, &pwr->readers, &rd->e.guid, &path))
|
||||
goto already_matched;
|
||||
|
||||
if (pwr->c.topic == NULL && rd->topic)
|
||||
pwr->c.topic = ddsi_sertopic_ref (rd->topic);
|
||||
assert (rd->topic || is_builtin_endpoint (rd->e.guid.entityid, NN_VENDORID_ECLIPSE));
|
||||
if (pwr->ddsi2direct_cb == 0 && rd->ddsi2direct_cb != 0)
|
||||
{
|
||||
pwr->ddsi2direct_cb = rd->ddsi2direct_cb;
|
||||
|
|
@ -1891,7 +1906,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader
|
|||
/* builtins really don't care about multiple copies or anything */
|
||||
m->in_sync = PRMSS_SYNC;
|
||||
}
|
||||
else if (!pwr->have_seen_heartbeat)
|
||||
else if (!pwr->have_seen_heartbeat || !rd->handle_as_transient_local)
|
||||
{
|
||||
/* Proxy writer hasn't seen a heartbeat yet: means we have no
|
||||
clue from what sequence number to start accepting data, nor
|
||||
|
|
@ -1920,14 +1935,6 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader
|
|||
m->in_sync = PRMSS_SYNC;
|
||||
m->u.not_in_sync.end_of_tl_seq = MAX_SEQ_NUMBER;
|
||||
}
|
||||
else if (!rd->handle_as_transient_local)
|
||||
{
|
||||
/* volatile reader, writer has seen a heartbeat: it's in sync
|
||||
(there is a risk of it getting some historical data: that
|
||||
happens to be cached in the writer's reorder admin at this
|
||||
point) */
|
||||
m->in_sync = PRMSS_SYNC;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* transient-local reader; range of sequence numbers is already
|
||||
|
|
@ -1981,7 +1988,6 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader
|
|||
return;
|
||||
|
||||
already_matched:
|
||||
assert (is_builtin_entityid (pwr->e.guid.entityid, pwr->c.vendor) ? (pwr->c.topic == NULL) : (pwr->c.topic != NULL));
|
||||
ELOGDISC (pwr, " proxy_writer_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT") - already connected\n",
|
||||
PGUID (pwr->e.guid), PGUID (rd->e.guid));
|
||||
ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
|
|
@ -1996,8 +2002,6 @@ static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer
|
|||
|
||||
m->wr_guid = wr->e.guid;
|
||||
ddsrt_mutex_lock (&prd->e.lock);
|
||||
if (prd->c.topic == NULL)
|
||||
prd->c.topic = ddsi_sertopic_ref (wr->topic);
|
||||
if (ddsrt_avl_lookup_ipath (&prd_writers_treedef, &prd->writers, &wr->e.guid, &path))
|
||||
{
|
||||
ELOGDISC (prd, " proxy_reader_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - already connected\n",
|
||||
|
|
@ -2007,6 +2011,7 @@ static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer
|
|||
}
|
||||
else
|
||||
{
|
||||
assert (wr->topic || is_builtin_endpoint (wr->e.guid.entityid, NN_VENDORID_ECLIPSE));
|
||||
ELOGDISC (prd, " proxy_reader_add_connection(wr "PGUIDFMT" prd "PGUIDFMT")\n",
|
||||
PGUID (wr->e.guid), PGUID (prd->e.guid));
|
||||
ddsrt_avl_insert_ipath (&prd_writers_treedef, &prd->writers, m, &path);
|
||||
|
|
@ -2015,9 +2020,9 @@ static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer
|
|||
}
|
||||
}
|
||||
|
||||
static nn_entityid_t builtin_entityid_match (nn_entityid_t x)
|
||||
static ddsi_entityid_t builtin_entityid_match (ddsi_entityid_t x)
|
||||
{
|
||||
nn_entityid_t res;
|
||||
ddsi_entityid_t res;
|
||||
res.u = 0;
|
||||
switch (x.u)
|
||||
{
|
||||
|
|
@ -2164,7 +2169,7 @@ static void connect_proxy_writer_with_reader (struct proxy_writer *pwr, struct r
|
|||
proxy_writer_add_connection (pwr, rd, tnow, init_count);
|
||||
}
|
||||
|
||||
static bool ignore_local_p (const nn_guid_t *guid1, const nn_guid_t *guid2, const struct dds_qos *xqos1, const struct dds_qos *xqos2)
|
||||
static bool ignore_local_p (const ddsi_guid_t *guid1, const ddsi_guid_t *guid2, const struct dds_qos *xqos1, const struct dds_qos *xqos2)
|
||||
{
|
||||
assert (xqos1->present & QP_CYCLONE_IGNORELOCAL);
|
||||
assert (xqos2->present & QP_CYCLONE_IGNORELOCAL);
|
||||
|
|
@ -2383,7 +2388,7 @@ static void generic_do_match (struct entity_common *e, nn_mtime_t tnow)
|
|||
else
|
||||
{
|
||||
/* Built-ins have fixed QoS */
|
||||
nn_entityid_t tgt_ent = builtin_entityid_match (e->guid.entityid);
|
||||
ddsi_entityid_t tgt_ent = builtin_entityid_match (e->guid.entityid);
|
||||
enum entity_kind pkind = generic_do_match_isproxy (e) ? EK_PARTICIPANT : EK_PROXY_PARTICIPANT;
|
||||
EELOGDISC (e, "match_%s_with_%ss(%s "PGUIDFMT") scanning %sparticipants tgt=%"PRIx32"\n",
|
||||
generic_do_match_kindstr_us (e->kind), generic_do_match_kindstr_us (mkind),
|
||||
|
|
@ -2396,7 +2401,7 @@ static void generic_do_match (struct entity_common *e, nn_mtime_t tnow)
|
|||
ephash_enum_init (&est, guid_hash, pkind);
|
||||
while ((ep = ephash_enum_next (&est)) != NULL)
|
||||
{
|
||||
nn_guid_t tgt_guid;
|
||||
ddsi_guid_t tgt_guid;
|
||||
tgt_guid.prefix = ep->guid.prefix;
|
||||
tgt_guid.entityid = tgt_ent;
|
||||
if ((em = ephash_lookup_guid (guid_hash, &tgt_guid, mkind)) != NULL)
|
||||
|
|
@ -2463,7 +2468,7 @@ static void match_proxy_reader_with_writers (struct proxy_reader *prd, nn_mtime_
|
|||
|
||||
/* ENDPOINT --------------------------------------------------------- */
|
||||
|
||||
static void new_reader_writer_common (const struct ddsrt_log_cfg *logcfg, const struct nn_guid *guid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos)
|
||||
static void new_reader_writer_common (const struct ddsrt_log_cfg *logcfg, const struct ddsi_guid *guid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos)
|
||||
{
|
||||
const char *partition = "(default)";
|
||||
const char *partition_suffix = "";
|
||||
|
|
@ -2489,7 +2494,7 @@ static void new_reader_writer_common (const struct ddsrt_log_cfg *logcfg, const
|
|||
topic ? topic->type_name : "(null)");
|
||||
}
|
||||
|
||||
static void endpoint_common_init (struct entity_common *e, struct endpoint_common *c, struct q_globals *gv, enum entity_kind kind, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, bool onlylocal)
|
||||
static void endpoint_common_init (struct entity_common *e, struct endpoint_common *c, struct q_globals *gv, enum entity_kind kind, const struct ddsi_guid *guid, const struct ddsi_guid *group_guid, struct participant *pp, bool onlylocal)
|
||||
{
|
||||
entity_common_init (e, gv, guid, NULL, kind, now (), NN_VENDORID_ECLIPSE, pp->e.onlylocal || onlylocal);
|
||||
c->pp = ref_participant (pp, &e->guid);
|
||||
|
|
@ -2878,7 +2883,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se
|
|||
local_reader_ary_init (&wr->rdary);
|
||||
}
|
||||
|
||||
static dds_return_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc, status_cb_t status_cb, void *status_entity)
|
||||
static dds_return_t new_writer_guid (struct writer **wr_out, const struct ddsi_guid *guid, const struct ddsi_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc, status_cb_t status_cb, void *status_entity)
|
||||
{
|
||||
struct writer *wr;
|
||||
nn_mtime_t tnow = now_mt ();
|
||||
|
|
@ -2929,7 +2934,7 @@ static dds_return_t new_writer_guid (struct writer **wr_out, const struct nn_gui
|
|||
return 0;
|
||||
}
|
||||
|
||||
dds_return_t new_writer (struct writer **wr_out, struct q_globals *gv, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg)
|
||||
dds_return_t new_writer (struct writer **wr_out, struct q_globals *gv, struct ddsi_guid *wrguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg)
|
||||
{
|
||||
struct participant *pp;
|
||||
dds_return_t rc;
|
||||
|
|
@ -2951,9 +2956,9 @@ dds_return_t new_writer (struct writer **wr_out, struct q_globals *gv, struct nn
|
|||
return new_writer_guid (wr_out, wrguid, group_guid, pp, topic, xqos, whc, status_cb, status_cb_arg);
|
||||
}
|
||||
|
||||
struct local_orphan_writer *new_local_orphan_writer (struct q_globals *gv, nn_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc)
|
||||
struct local_orphan_writer *new_local_orphan_writer (struct q_globals *gv, ddsi_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc)
|
||||
{
|
||||
nn_guid_t guid;
|
||||
ddsi_guid_t guid;
|
||||
struct local_orphan_writer *lowr;
|
||||
struct writer *wr;
|
||||
nn_mtime_t tnow = now_mt ();
|
||||
|
|
@ -3072,6 +3077,22 @@ static void writer_set_state (struct writer *wr, enum writer_state newstate)
|
|||
wr->state = newstate;
|
||||
}
|
||||
|
||||
dds_return_t unblock_throttled_writer (struct q_globals *gv, const struct ddsi_guid *guid)
|
||||
{
|
||||
struct writer *wr;
|
||||
assert (is_writer_entityid (guid->entityid));
|
||||
if ((wr = ephash_lookup_writer_guid (gv->guid_hash, guid)) == NULL)
|
||||
{
|
||||
GVLOGDISC ("unblock_throttled_writer(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid));
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
}
|
||||
GVLOGDISC ("unblock_throttled_writer(guid "PGUIDFMT") ...\n", PGUID (*guid));
|
||||
ddsrt_mutex_lock (&wr->e.lock);
|
||||
writer_set_state (wr, WRST_INTERRUPT);
|
||||
ddsrt_mutex_unlock (&wr->e.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dds_return_t delete_writer_nolinger_locked (struct writer *wr)
|
||||
{
|
||||
ELOGDISC (wr, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (wr->e.guid));
|
||||
|
|
@ -3084,7 +3105,7 @@ dds_return_t delete_writer_nolinger_locked (struct writer *wr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
dds_return_t delete_writer_nolinger (struct q_globals *gv, const struct nn_guid *guid)
|
||||
dds_return_t delete_writer_nolinger (struct q_globals *gv, const struct ddsi_guid *guid)
|
||||
{
|
||||
struct writer *wr;
|
||||
/* We take no care to ensure application writers are not deleted
|
||||
|
|
@ -3108,12 +3129,13 @@ dds_return_t delete_writer_nolinger (struct q_globals *gv, const struct nn_guid
|
|||
|
||||
void delete_local_orphan_writer (struct local_orphan_writer *lowr)
|
||||
{
|
||||
assert (thread_is_awake ());
|
||||
ddsrt_mutex_lock (&lowr->wr.e.lock);
|
||||
delete_writer_nolinger_locked (&lowr->wr);
|
||||
ddsrt_mutex_unlock (&lowr->wr.e.lock);
|
||||
}
|
||||
|
||||
dds_return_t delete_writer (struct q_globals *gv, const struct nn_guid *guid)
|
||||
dds_return_t delete_writer (struct q_globals *gv, const struct ddsi_guid *guid)
|
||||
{
|
||||
struct writer *wr;
|
||||
struct whc_state whcst;
|
||||
|
|
@ -3261,12 +3283,12 @@ static void leave_mcast_helper (const nn_locator_t *n, void *varg)
|
|||
static dds_return_t new_reader_guid
|
||||
(
|
||||
struct reader **rd_out,
|
||||
const struct nn_guid *guid,
|
||||
const struct nn_guid *group_guid,
|
||||
const struct ddsi_guid *guid,
|
||||
const struct ddsi_guid *group_guid,
|
||||
struct participant *pp,
|
||||
const struct ddsi_sertopic *topic,
|
||||
const struct dds_qos *xqos,
|
||||
struct rhc *rhc,
|
||||
struct ddsi_rhc *rhc,
|
||||
status_cb_t status_cb,
|
||||
void * status_entity
|
||||
)
|
||||
|
|
@ -3322,7 +3344,7 @@ static dds_return_t new_reader_guid
|
|||
/* set rhc qos for reader */
|
||||
if (rhc)
|
||||
{
|
||||
rhc_set_qos (rd->rhc, rd->xqos);
|
||||
ddsi_rhc_set_qos (rd->rhc, rd->xqos);
|
||||
}
|
||||
assert (rd->xqos->present & QP_LIVELINESS);
|
||||
if (rd->xqos->liveliness.kind != DDS_LIVELINESS_AUTOMATIC || rd->xqos->liveliness.lease_duration != T_NEVER)
|
||||
|
|
@ -3403,12 +3425,12 @@ dds_return_t new_reader
|
|||
(
|
||||
struct reader **rd_out,
|
||||
struct q_globals *gv,
|
||||
struct nn_guid *rdguid,
|
||||
const struct nn_guid *group_guid,
|
||||
const struct nn_guid *ppguid,
|
||||
struct ddsi_guid *rdguid,
|
||||
const struct ddsi_guid *group_guid,
|
||||
const struct ddsi_guid *ppguid,
|
||||
const struct ddsi_sertopic *topic,
|
||||
const struct dds_qos *xqos,
|
||||
struct rhc * rhc,
|
||||
struct ddsi_rhc * rhc,
|
||||
status_cb_t status_cb,
|
||||
void * status_cbarg
|
||||
)
|
||||
|
|
@ -3461,9 +3483,9 @@ static void gc_delete_reader (struct gcreq *gcreq)
|
|||
addrset_forall (rd->as, leave_mcast_helper, &arg);
|
||||
}
|
||||
#endif
|
||||
if (rd->rhc)
|
||||
if (rd->rhc && is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE))
|
||||
{
|
||||
rhc_free (rd->rhc);
|
||||
ddsi_rhc_free (rd->rhc);
|
||||
}
|
||||
if (rd->status_cb)
|
||||
{
|
||||
|
|
@ -3481,7 +3503,7 @@ static void gc_delete_reader (struct gcreq *gcreq)
|
|||
ddsrt_free (rd);
|
||||
}
|
||||
|
||||
dds_return_t delete_reader (struct q_globals *gv, const struct nn_guid *guid)
|
||||
dds_return_t delete_reader (struct q_globals *gv, const struct ddsi_guid *guid)
|
||||
{
|
||||
struct reader *rd;
|
||||
assert (!is_writer_entityid (guid->entityid));
|
||||
|
|
@ -3544,10 +3566,10 @@ void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct
|
|||
void new_proxy_participant
|
||||
(
|
||||
struct q_globals *gv,
|
||||
const struct nn_guid *ppguid,
|
||||
const struct ddsi_guid *ppguid,
|
||||
unsigned bes,
|
||||
unsigned prismtech_bes,
|
||||
const struct nn_guid *privileged_pp_guid,
|
||||
const struct ddsi_guid *privileged_pp_guid,
|
||||
struct addrset *as_default,
|
||||
struct addrset *as_meta,
|
||||
const nn_plist_t *plist,
|
||||
|
|
@ -3696,7 +3718,7 @@ void new_proxy_participant
|
|||
const struct bestab *te = &bestab[i];
|
||||
if ((proxypp->bes & te->besflag) || (proxypp->prismtech_bes & te->prismtech_besflag))
|
||||
{
|
||||
nn_guid_t guid1;
|
||||
ddsi_guid_t guid1;
|
||||
guid1.prefix = proxypp->e.guid.prefix;
|
||||
guid1.entityid.u = te->entityid;
|
||||
assert (is_builtin_entityid (guid1.entityid, proxypp->vendor));
|
||||
|
|
@ -3815,7 +3837,7 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p
|
|||
if (proxypp->owns_lease)
|
||||
lease_free (ddsrt_atomic_ldvoidp (&proxypp->lease));
|
||||
entity_common_fini (&proxypp->e);
|
||||
remove_deleted_participant_guid (&proxypp->e.gv->logconfig, proxypp->e.gv->deleted_participants, &proxypp->e.guid, DPG_LOCAL | DPG_REMOTE);
|
||||
remove_deleted_participant_guid (proxypp->e.gv->deleted_participants, &proxypp->e.guid, DPG_LOCAL | DPG_REMOTE);
|
||||
ddsrt_free (proxypp);
|
||||
}
|
||||
else if (proxypp->endpoints == NULL && proxypp->implicitly_created)
|
||||
|
|
@ -3959,7 +3981,7 @@ void purge_proxy_participants (struct q_globals *gv, const nn_locator_t *loc, bo
|
|||
thread_state_asleep (ts1);
|
||||
}
|
||||
|
||||
int delete_proxy_participant_by_guid (struct q_globals *gv, const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit)
|
||||
int delete_proxy_participant_by_guid (struct q_globals *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit)
|
||||
{
|
||||
struct proxy_participant *ppt;
|
||||
|
||||
|
|
@ -3982,7 +4004,7 @@ int delete_proxy_participant_by_guid (struct q_globals *gv, const struct nn_guid
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint64_t get_entity_instance_id (const struct q_globals *gv, const struct nn_guid *guid)
|
||||
uint64_t get_entity_instance_id (const struct q_globals *gv, const struct ddsi_guid *guid)
|
||||
{
|
||||
struct thread_state1 *ts1 = lookup_thread_state ();
|
||||
struct entity_common *e;
|
||||
|
|
@ -3996,7 +4018,7 @@ uint64_t get_entity_instance_id (const struct q_globals *gv, const struct nn_gui
|
|||
|
||||
/* PROXY-ENDPOINT --------------------------------------------------- */
|
||||
|
||||
static void proxy_endpoint_common_init (struct entity_common *e, struct proxy_endpoint_common *c, enum entity_kind kind, const struct nn_guid *guid, nn_wctime_t tcreate, seqno_t seq, struct proxy_participant *proxypp, struct addrset *as, const nn_plist_t *plist)
|
||||
static void proxy_endpoint_common_init (struct entity_common *e, struct proxy_endpoint_common *c, enum entity_kind kind, const struct ddsi_guid *guid, nn_wctime_t tcreate, seqno_t seq, struct proxy_participant *proxypp, struct addrset *as, const nn_plist_t *plist)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
|
|
@ -4009,7 +4031,6 @@ static void proxy_endpoint_common_init (struct entity_common *e, struct proxy_en
|
|||
entity_common_init (e, proxypp->e.gv, guid, name, kind, tcreate, proxypp->vendor, false);
|
||||
c->xqos = nn_xqos_dup (&plist->qos);
|
||||
c->as = ref_addrset (as);
|
||||
c->topic = NULL; /* set from first matching reader/writer */
|
||||
c->vendor = proxypp->vendor;
|
||||
c->seq = seq;
|
||||
|
||||
|
|
@ -4024,18 +4045,15 @@ static void proxy_endpoint_common_init (struct entity_common *e, struct proxy_en
|
|||
static void proxy_endpoint_common_fini (struct entity_common *e, struct proxy_endpoint_common *c)
|
||||
{
|
||||
unref_proxy_participant (c->proxypp, c);
|
||||
|
||||
ddsi_sertopic_unref (c->topic);
|
||||
nn_xqos_fini (c->xqos);
|
||||
ddsrt_free (c->xqos);
|
||||
unref_addrset (c->as);
|
||||
|
||||
entity_common_fini (e);
|
||||
}
|
||||
|
||||
/* PROXY-WRITER ----------------------------------------------------- */
|
||||
|
||||
int new_proxy_writer (struct q_globals *gv, const struct nn_guid *ppguid, const struct nn_guid *guid, struct addrset *as, const nn_plist_t *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp, seqno_t seq)
|
||||
int new_proxy_writer (struct q_globals *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const nn_plist_t *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp, seqno_t seq)
|
||||
{
|
||||
struct proxy_participant *proxypp;
|
||||
struct proxy_writer *pwr;
|
||||
|
|
@ -4168,7 +4186,7 @@ void update_proxy_writer (struct proxy_writer *pwr, seqno_t seq, struct addrset
|
|||
void update_proxy_reader (struct proxy_reader *prd, seqno_t seq, struct addrset *as, const struct dds_qos *xqos, nn_wctime_t timestamp)
|
||||
{
|
||||
struct prd_wr_match * m;
|
||||
nn_guid_t wrguid;
|
||||
ddsi_guid_t wrguid;
|
||||
|
||||
memset (&wrguid, 0, sizeof (wrguid));
|
||||
|
||||
|
|
@ -4185,11 +4203,11 @@ void update_proxy_reader (struct proxy_reader *prd, seqno_t seq, struct addrset
|
|||
prd->c.as = as;
|
||||
|
||||
/* Rebuild writer endpoints */
|
||||
|
||||
|
||||
while ((m = ddsrt_avl_lookup_succ_eq (&prd_writers_treedef, &prd->writers, &wrguid)) != NULL)
|
||||
{
|
||||
struct prd_wr_match *next;
|
||||
nn_guid_t guid_next;
|
||||
ddsi_guid_t guid_next;
|
||||
struct writer * wr;
|
||||
|
||||
wrguid = m->wr_guid;
|
||||
|
|
@ -4244,7 +4262,7 @@ static void gc_delete_proxy_writer (struct gcreq *gcreq)
|
|||
ddsrt_free (pwr);
|
||||
}
|
||||
|
||||
int delete_proxy_writer (struct q_globals *gv, const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit)
|
||||
int delete_proxy_writer (struct q_globals *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit)
|
||||
{
|
||||
struct proxy_writer *pwr;
|
||||
(void)isimplicit;
|
||||
|
|
@ -4271,7 +4289,7 @@ int delete_proxy_writer (struct q_globals *gv, const struct nn_guid *guid, nn_wc
|
|||
|
||||
/* PROXY-READER ----------------------------------------------------- */
|
||||
|
||||
int new_proxy_reader (struct q_globals *gv, const struct nn_guid *ppguid, const struct nn_guid *guid, struct addrset *as, const nn_plist_t *plist, nn_wctime_t timestamp, seqno_t seq
|
||||
int new_proxy_reader (struct q_globals *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const nn_plist_t *plist, nn_wctime_t timestamp, seqno_t seq
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
, int favours_ssm
|
||||
#endif
|
||||
|
|
@ -4313,7 +4331,7 @@ int new_proxy_reader (struct q_globals *gv, const struct nn_guid *ppguid, const
|
|||
|
||||
static void proxy_reader_set_delete_and_ack_all_messages (struct proxy_reader *prd)
|
||||
{
|
||||
nn_guid_t wrguid;
|
||||
ddsi_guid_t wrguid;
|
||||
struct writer *wr;
|
||||
struct prd_wr_match *m;
|
||||
|
||||
|
|
@ -4325,7 +4343,7 @@ static void proxy_reader_set_delete_and_ack_all_messages (struct proxy_reader *p
|
|||
/* have to be careful walking the tree -- pretty is different, but
|
||||
I want to check this before I write a lookup_succ function. */
|
||||
struct prd_wr_match *m_a_next;
|
||||
nn_guid_t wrguid_next;
|
||||
ddsi_guid_t wrguid_next;
|
||||
wrguid = m->wr_guid;
|
||||
if ((m_a_next = ddsrt_avl_find_succ (&prd_writers_treedef, &prd->writers, m)) != NULL)
|
||||
wrguid_next = m_a_next->wr_guid;
|
||||
|
|
@ -4377,7 +4395,7 @@ static void gc_delete_proxy_reader (struct gcreq *gcreq)
|
|||
ddsrt_free (prd);
|
||||
}
|
||||
|
||||
int delete_proxy_reader (struct q_globals *gv, const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit)
|
||||
int delete_proxy_reader (struct q_globals *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit)
|
||||
{
|
||||
struct proxy_reader *prd;
|
||||
(void)isimplicit;
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ static void ephash_guid_remove (struct ephash *gh, struct entity_common *e)
|
|||
assert (x);
|
||||
}
|
||||
|
||||
void *ephash_lookup_guid_untyped (const struct ephash *gh, const struct nn_guid *guid)
|
||||
void *ephash_lookup_guid_untyped (const struct ephash *gh, const struct ddsi_guid *guid)
|
||||
{
|
||||
/* FIXME: could (now) require guid to be first in entity_common; entity_common already is first in entity */
|
||||
struct entity_common e;
|
||||
|
|
@ -122,7 +122,7 @@ void *ephash_lookup_guid_untyped (const struct ephash *gh, const struct nn_guid
|
|||
return ddsrt_chh_lookup (gh->hash, &e);
|
||||
}
|
||||
|
||||
static void *ephash_lookup_guid_int (const struct ephash *gh, const struct nn_guid *guid, enum entity_kind kind)
|
||||
static void *ephash_lookup_guid_int (const struct ephash *gh, const struct ddsi_guid *guid, enum entity_kind kind)
|
||||
{
|
||||
struct entity_common *res;
|
||||
if ((res = ephash_lookup_guid_untyped (gh, guid)) != NULL && res->kind == kind)
|
||||
|
|
@ -131,7 +131,7 @@ static void *ephash_lookup_guid_int (const struct ephash *gh, const struct nn_gu
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void *ephash_lookup_guid (const struct ephash *gh, const struct nn_guid *guid, enum entity_kind kind)
|
||||
void *ephash_lookup_guid (const struct ephash *gh, const struct ddsi_guid *guid, enum entity_kind kind)
|
||||
{
|
||||
return ephash_lookup_guid_int (gh, guid, kind);
|
||||
}
|
||||
|
|
@ -196,42 +196,42 @@ void ephash_remove_proxy_reader_guid (struct ephash *gh, struct proxy_reader *pr
|
|||
ephash_guid_remove (gh, &prd->e);
|
||||
}
|
||||
|
||||
struct participant *ephash_lookup_participant_guid (const struct ephash *gh, const struct nn_guid *guid)
|
||||
struct participant *ephash_lookup_participant_guid (const struct ephash *gh, const struct ddsi_guid *guid)
|
||||
{
|
||||
assert (guid->entityid.u == NN_ENTITYID_PARTICIPANT);
|
||||
assert (offsetof (struct participant, e) == 0);
|
||||
return ephash_lookup_guid_int (gh, guid, EK_PARTICIPANT);
|
||||
}
|
||||
|
||||
struct proxy_participant *ephash_lookup_proxy_participant_guid (const struct ephash *gh, const struct nn_guid *guid)
|
||||
struct proxy_participant *ephash_lookup_proxy_participant_guid (const struct ephash *gh, const struct ddsi_guid *guid)
|
||||
{
|
||||
assert (guid->entityid.u == NN_ENTITYID_PARTICIPANT);
|
||||
assert (offsetof (struct proxy_participant, e) == 0);
|
||||
return ephash_lookup_guid_int (gh, guid, EK_PROXY_PARTICIPANT);
|
||||
}
|
||||
|
||||
struct writer *ephash_lookup_writer_guid (const struct ephash *gh, const struct nn_guid *guid)
|
||||
struct writer *ephash_lookup_writer_guid (const struct ephash *gh, const struct ddsi_guid *guid)
|
||||
{
|
||||
assert (is_writer_entityid (guid->entityid));
|
||||
assert (offsetof (struct writer, e) == 0);
|
||||
return ephash_lookup_guid_int (gh, guid, EK_WRITER);
|
||||
}
|
||||
|
||||
struct reader *ephash_lookup_reader_guid (const struct ephash *gh, const struct nn_guid *guid)
|
||||
struct reader *ephash_lookup_reader_guid (const struct ephash *gh, const struct ddsi_guid *guid)
|
||||
{
|
||||
assert (is_reader_entityid (guid->entityid));
|
||||
assert (offsetof (struct reader, e) == 0);
|
||||
return ephash_lookup_guid_int (gh, guid, EK_READER);
|
||||
}
|
||||
|
||||
struct proxy_writer *ephash_lookup_proxy_writer_guid (const struct ephash *gh, const struct nn_guid *guid)
|
||||
struct proxy_writer *ephash_lookup_proxy_writer_guid (const struct ephash *gh, const struct ddsi_guid *guid)
|
||||
{
|
||||
assert (is_writer_entityid (guid->entityid));
|
||||
assert (offsetof (struct proxy_writer, e) == 0);
|
||||
return ephash_lookup_guid_int (gh, guid, EK_PROXY_WRITER);
|
||||
}
|
||||
|
||||
struct proxy_reader *ephash_lookup_proxy_reader_guid (const struct ephash *gh, const struct nn_guid *guid)
|
||||
struct proxy_reader *ephash_lookup_proxy_reader_guid (const struct ephash *gh, const struct ddsi_guid *guid)
|
||||
{
|
||||
assert (is_reader_entityid (guid->entityid));
|
||||
assert (offsetof (struct proxy_reader, e) == 0);
|
||||
|
|
|
|||
|
|
@ -949,7 +949,7 @@ int rtps_init (struct q_globals *gv)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
assert ((gv->config.allowMulticast & AMC_DEFAULT) == 0);
|
||||
if (set_recvips (gv) < 0)
|
||||
goto err_set_recvips;
|
||||
|
|
@ -1027,17 +1027,45 @@ int rtps_init (struct q_globals *gv)
|
|||
ddsrt_mutex_init (&gv->participant_set_lock);
|
||||
ddsrt_cond_init (&gv->participant_set_cond);
|
||||
lease_management_init (gv);
|
||||
gv->deleted_participants = deleted_participants_admin_new (gv->config.prune_deleted_ppant.delay);
|
||||
gv->deleted_participants = deleted_participants_admin_new (&gv->logconfig, gv->config.prune_deleted_ppant.delay);
|
||||
gv->guid_hash = ephash_new (gv);
|
||||
|
||||
ddsrt_mutex_init (&gv->privileged_pp_lock);
|
||||
gv->privileged_pp = NULL;
|
||||
|
||||
/* Template PP guid -- protected by privileged_pp_lock for simplicity */
|
||||
gv->next_ppguid.prefix.u[0] = locator_to_hopefully_unique_uint32 (&gv->ownloc);
|
||||
gv->next_ppguid.prefix.u[1] = (unsigned) ddsrt_getpid ();
|
||||
gv->next_ppguid.prefix.u[2] = 1;
|
||||
gv->next_ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
|
||||
/* Base participant GUID. IID initialisation should be from a really good random
|
||||
generator and yield almost-unique numbers, and with a fallback of using process
|
||||
id, timestamp and a counter, so incorporating that should do a lot to construct
|
||||
a pseudo-random ID. (The assumption here is that feeding pseudo-random data in
|
||||
MD5 will not change the randomness ...) Mix in the network configuration to
|
||||
make machines with very reproducible boot sequences and low-resolution clocks
|
||||
distinguishable.
|
||||
|
||||
This base is kept constant, prefix.u[1] and prefix.u[2] are then treated as a
|
||||
64-bit unsigned integer to which we add IIDs to generate a hopping sequence
|
||||
that won't repeat in the lifetime of the process. Seems like it ought to work
|
||||
to keep the risks of collisions low. */
|
||||
{
|
||||
uint64_t iid = toBE8u (ddsi_iid_gen ());
|
||||
ddsrt_md5_state_t st;
|
||||
ddsrt_md5_byte_t digest[16];
|
||||
ddsrt_md5_init (&st);
|
||||
ddsrt_md5_append (&st, (const ddsrt_md5_byte_t *) &iid, sizeof (iid));
|
||||
for (int i = 0; i < gv->n_interfaces; i++)
|
||||
{
|
||||
const struct nn_interface *intf = &gv->interfaces[i];
|
||||
ddsrt_md5_append (&st, (const ddsrt_md5_byte_t *) &intf->loc.kind, sizeof (intf->loc.kind));
|
||||
ddsrt_md5_append (&st, (const ddsrt_md5_byte_t *) intf->loc.address, sizeof (intf->loc.address));
|
||||
}
|
||||
ddsrt_md5_finish (&st, digest);
|
||||
/* DDSI 2.2 requires the first two bytes of the GUID to be set to the vendor
|
||||
code -- a terrible waste of entropy ... */
|
||||
gv->ppguid_base.prefix.s[0] = NN_VENDORID_ECLIPSE.id[0];
|
||||
gv->ppguid_base.prefix.s[1] = NN_VENDORID_ECLIPSE.id[1];
|
||||
DDSRT_STATIC_ASSERT (sizeof (gv->ppguid_base.prefix.s) > 2 && sizeof (gv->ppguid_base.prefix.s) - 2 <= sizeof (digest));
|
||||
memcpy (&gv->ppguid_base.prefix.s[2], digest, sizeof (gv->ppguid_base.prefix.s) - 2);
|
||||
gv->ppguid_base.entityid.u = NN_ENTITYID_PARTICIPANT;
|
||||
}
|
||||
|
||||
ddsrt_mutex_init (&gv->lock);
|
||||
ddsrt_mutex_init (&gv->spdp_lock);
|
||||
|
|
@ -1107,7 +1135,7 @@ int rtps_init (struct q_globals *gv)
|
|||
if (gv->m_factory->m_connless)
|
||||
{
|
||||
if (!(gv->config.many_sockets_mode == MSM_NO_UNICAST && gv->config.allowMulticast))
|
||||
GVTRACE ("Unicast Ports: discovery %"PRIu32" data %"PRIu32"\n", ddsi_conn_port (gv->disc_conn_uc), ddsi_conn_port (gv->data_conn_uc));
|
||||
GVLOG (DDS_LC_CONFIG, "Unicast Ports: discovery %"PRIu32" data %"PRIu32"\n", ddsi_conn_port (gv->disc_conn_uc), ddsi_conn_port (gv->data_conn_uc));
|
||||
|
||||
if (gv->config.allowMulticast)
|
||||
{
|
||||
|
|
@ -1161,7 +1189,7 @@ int rtps_init (struct q_globals *gv)
|
|||
/* Create shared transmit connection */
|
||||
|
||||
gv->tev_conn = gv->data_conn_uc;
|
||||
GVTRACE ("Timed event transmit port: %d\n", (int) ddsi_conn_port (gv->tev_conn));
|
||||
GVLOG (DDS_LC_CONFIG, "Timed event transmit port: %d\n", (int) ddsi_conn_port (gv->tev_conn));
|
||||
|
||||
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
|
||||
{
|
||||
|
|
@ -1189,7 +1217,7 @@ int rtps_init (struct q_globals *gv)
|
|||
{
|
||||
chptr->transmit_conn = gv->data_conn_uc;
|
||||
}
|
||||
GVTRACE ("channel %s: transmit port %d\n", chptr->name, (int) ddsi_tran_port (chptr->transmit_conn));
|
||||
GVLOG (DDS_LC_CONFIG, "channel %s: transmit port %d\n", chptr->name, (int) ddsi_tran_port (chptr->transmit_conn));
|
||||
|
||||
#ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING
|
||||
if (chptr->auxiliary_bandwidth_limit > 0 || lookup_thread_properties (tname))
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ int64_t check_and_handle_lease_expiration (struct q_globals *gv, nn_etime_t tnow
|
|||
ddsrt_mutex_lock (&gv->leaseheap_lock);
|
||||
while ((l = ddsrt_fibheap_min (&lease_fhdef, &gv->leaseheap)) != NULL && l->tsched.v <= tnowE.v)
|
||||
{
|
||||
nn_guid_t g = l->entity->guid;
|
||||
ddsi_guid_t g = l->entity->guid;
|
||||
enum entity_kind k = l->entity->kind;
|
||||
|
||||
assert (l->tsched.v != TSCHED_NOT_ON_HEAP);
|
||||
|
|
@ -303,7 +303,7 @@ void handle_PMD (const struct receiver_state *rst, nn_wctime_t timestamp, uint32
|
|||
const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */
|
||||
const int bswap = (data->identifier == CDR_LE) ^ (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN);
|
||||
struct proxy_participant *pp;
|
||||
nn_guid_t ppguid;
|
||||
ddsi_guid_t ppguid;
|
||||
RSTTRACE (" PMD ST%x", statusinfo);
|
||||
if (data->identifier != CDR_LE && data->identifier != CDR_BE)
|
||||
{
|
||||
|
|
@ -318,7 +318,7 @@ void handle_PMD (const struct receiver_state *rst, nn_wctime_t timestamp, uint32
|
|||
else
|
||||
{
|
||||
const ParticipantMessageData_t *pmd = (ParticipantMessageData_t *) (data + 1);
|
||||
nn_guid_prefix_t p = nn_ntoh_guid_prefix (pmd->participantGuidPrefix);
|
||||
ddsi_guid_prefix_t p = nn_ntoh_guid_prefix (pmd->participantGuidPrefix);
|
||||
uint32_t kind = ntohl (pmd->kind);
|
||||
uint32_t length = bswap ? bswap4u (pmd->length) : pmd->length;
|
||||
RSTTRACE (" pp %"PRIx32":%"PRIx32":%"PRIx32" kind %u data %u", p.u[0], p.u[1], p.u[2], kind, length);
|
||||
|
|
@ -346,11 +346,11 @@ void handle_PMD (const struct receiver_state *rst, nn_wctime_t timestamp, uint32
|
|||
case NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER:
|
||||
/* Serialized key; BE or LE doesn't matter as both fields are
|
||||
defined as octets. */
|
||||
if (len < sizeof (struct CDRHeader) + sizeof (nn_guid_prefix_t))
|
||||
if (len < sizeof (struct CDRHeader) + sizeof (ddsi_guid_prefix_t))
|
||||
debug_print_rawdata (rst->gv, " SHORT3", data, len);
|
||||
else
|
||||
{
|
||||
ppguid.prefix = nn_ntoh_guid_prefix (*((nn_guid_prefix_t *) (data + 1)));
|
||||
ppguid.prefix = nn_ntoh_guid_prefix (*((ddsi_guid_prefix_t *) (data + 1)));
|
||||
ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
|
||||
if (delete_proxy_participant_by_guid (rst->gv, &ppguid, timestamp, 0) < 0)
|
||||
RSTTRACE (" unknown");
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
#include "dds/ddsrt/avl.h"
|
||||
#include "dds/ddsi/q_misc.h" /* for vendor_is_... */
|
||||
|
||||
#include "dds/ddsi/ddsi_plist_generic.h"
|
||||
|
||||
/* I am tempted to change LENGTH_UNLIMITED to 0 in the API (with -1
|
||||
supported for backwards compatibility) ... on the wire however
|
||||
it must be -1 */
|
||||
|
|
@ -88,25 +90,6 @@ struct flagset {
|
|||
uint64_t wanted;
|
||||
};
|
||||
|
||||
/* Instructions for the generic serializer (&c) that handles most parameters.
|
||||
The "packed" attribute means single-byte instructions on GCC and Clang. */
|
||||
enum pserop {
|
||||
XSTOP,
|
||||
XO, /* octet sequence */
|
||||
XS, /* string */
|
||||
XZ, /* string sequence */
|
||||
XE1, XE2, XE3, /* enum 0..1, 0..2, 0..3 */
|
||||
Xl, /* length, int32_t, -1 or >= 1 */
|
||||
Xi, Xix2, Xix3, Xix4, /* int32_t, 1 .. 4 in a row */
|
||||
Xu, Xux2, Xux3, Xux4, Xux5, /* uint32_t, 1 .. 5 in a row */
|
||||
XD, XDx2, /* duration, 1 .. 2 in a row */
|
||||
Xo, Xox2, /* octet, 1 .. 2 in a row */
|
||||
Xb, Xbx2, /* boolean, 1 .. 2 in a row */
|
||||
XbCOND, /* boolean: compare to ignore remainder if false (for use_... flags) */
|
||||
XG, /* GUID */
|
||||
XK /* keyhash */
|
||||
} ddsrt_attribute_packed;
|
||||
|
||||
struct piddesc {
|
||||
nn_parameterid_t pid; /* parameter id or PID_PAD if strictly local */
|
||||
uint16_t flags; /* see PDF_xxx flags */
|
||||
|
|
@ -115,10 +98,10 @@ struct piddesc {
|
|||
size_t plist_offset; /* offset from start of nn_plist_t */
|
||||
size_t size; /* in-memory size for copying */
|
||||
union {
|
||||
/* descriptor for generic code: 4 is enough for the current set of
|
||||
/* descriptor for generic code: 12 is enough for the current set of
|
||||
parameters, compiler will warn if one ever tries to use more than
|
||||
will fit; on non-GCC/Clang and 32-bits machines */
|
||||
const enum pserop desc[4];
|
||||
will fit */
|
||||
const enum pserop desc[12];
|
||||
struct {
|
||||
dds_return_t (*deser) (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff);
|
||||
dds_return_t (*ser) (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff);
|
||||
|
|
@ -131,6 +114,8 @@ struct piddesc {
|
|||
dds_return_t (*deser_validate_xform) (void * __restrict dst, const struct dd * __restrict dd);
|
||||
};
|
||||
|
||||
extern inline bool pserop_seralign_is_1 (enum pserop op);
|
||||
|
||||
static void log_octetseq (uint32_t cat, const struct ddsrt_log_cfg *logcfg, uint32_t n, const unsigned char *xs);
|
||||
static dds_return_t validate_history_qospolicy (const dds_history_qospolicy_t *q);
|
||||
static dds_return_t validate_resource_limits_qospolicy (const dds_resource_limits_qospolicy_t *q);
|
||||
|
|
@ -325,7 +310,47 @@ static dds_return_t fini_locator (void * __restrict dst, size_t * __restrict dst
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void fini_generic_partial (void * __restrict dst, size_t * __restrict dstoff, const enum pserop *desc, const enum pserop * const desc_end, bool aliased)
|
||||
static size_t ser_generic_srcsize (const enum pserop * __restrict desc)
|
||||
{
|
||||
size_t srcoff = 0, srcalign = 0;
|
||||
#define SIMPLE(basecase_, type_) do { \
|
||||
const uint32_t cnt = 1 + (uint32_t) (*desc - (basecase_)); \
|
||||
const size_t align = alignof (type_); \
|
||||
srcalign = (align > srcalign) ? align : srcalign; \
|
||||
srcoff = (srcoff + align - 1) & ~(align - 1); \
|
||||
srcoff += cnt * sizeof (type_); \
|
||||
} while (0)
|
||||
while (true)
|
||||
{
|
||||
switch (*desc)
|
||||
{
|
||||
case XSTOP: return (srcoff + srcalign - 1) & ~(srcalign - 1);
|
||||
case XO: SIMPLE (XO, ddsi_octetseq_t); break;
|
||||
case XS: SIMPLE (XS, const char *); break;
|
||||
case XE1: case XE2: case XE3: SIMPLE (*desc, unsigned); break;
|
||||
case Xi: case Xix2: case Xix3: case Xix4: SIMPLE (Xi, int32_t); break;
|
||||
case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE (Xu, uint32_t); break;
|
||||
case XD: case XDx2: SIMPLE (XD, dds_duration_t); break;
|
||||
case Xo: case Xox2: SIMPLE (Xo, unsigned char); break;
|
||||
case Xb: case Xbx2: SIMPLE (Xb, unsigned char); break;
|
||||
case XbCOND: SIMPLE (XbCOND, unsigned char); break;
|
||||
case XG: SIMPLE (XG, ddsi_guid_t); break;
|
||||
case XK: SIMPLE (XK, nn_keyhash_t); break;
|
||||
case XbPROP: SIMPLE (XbPROP, unsigned char); break;
|
||||
case XQ: SIMPLE (XQ, ddsi_octetseq_t); while (*++desc != XSTOP) { } break;
|
||||
case Xopt: break;
|
||||
}
|
||||
desc++;
|
||||
}
|
||||
#undef SIMPLE
|
||||
}
|
||||
|
||||
size_t plist_memsize_generic (const enum pserop * __restrict desc)
|
||||
{
|
||||
return ser_generic_srcsize (desc);
|
||||
}
|
||||
|
||||
static void fini_generic_embeddable (void * __restrict dst, size_t * __restrict dstoff, const enum pserop *desc, const enum pserop * const desc_end, bool aliased)
|
||||
{
|
||||
#define COMPLEX(basecase_, type_, cleanup_unaliased_, cleanup_always_) do { \
|
||||
type_ *x = deser_generic_dst (dst, dstoff, alignof (type_)); \
|
||||
|
|
@ -344,17 +369,29 @@ static void fini_generic_partial (void * __restrict dst, size_t * __restrict dst
|
|||
case XSTOP: return;
|
||||
case XO: COMPLEX (XO, ddsi_octetseq_t, ddsrt_free (x->value), (void) 0); break;
|
||||
case XS: COMPLEX (XS, char *, ddsrt_free (*x), (void) 0); break;
|
||||
case XZ: COMPLEX (XZ, ddsi_stringseq_t, { for (uint32_t i = 0; i < x->n; i++) ddsrt_free (x->strs[i]); }, ddsrt_free (x->strs)); break;
|
||||
case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, (void) 0, (void) 0); break;
|
||||
case Xi: case Xix2: case Xix3: case Xix4: SIMPLE (Xi, int32_t); break;
|
||||
case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE (Xu, uint32_t); break;
|
||||
case Xl: SIMPLE (Xl, int32_t); break;
|
||||
case XD: case XDx2: SIMPLE (XD, dds_duration_t); break;
|
||||
case Xo: case Xox2: SIMPLE (Xo, unsigned char); break;
|
||||
case Xb: case Xbx2: SIMPLE (Xb, unsigned char); break;
|
||||
case XbCOND: SIMPLE (XbCOND, unsigned char); break;
|
||||
case XG: SIMPLE (XG, nn_guid_t); break;
|
||||
case XG: SIMPLE (XG, ddsi_guid_t); break;
|
||||
case XK: SIMPLE (XK, nn_keyhash_t); break;
|
||||
case XbPROP: SIMPLE (XbPROP, unsigned char); break;
|
||||
case XQ:
|
||||
/* non-nested, so never a need to deallocate only some of the entries and no complications
|
||||
in locating the end of the sequence element description */
|
||||
COMPLEX (XQ, ddsi_octetseq_t, {
|
||||
const size_t elem_size = ser_generic_srcsize (desc + 1);
|
||||
for (uint32_t i = 0; i < x->length; i++) {
|
||||
size_t elem_off = i * elem_size;
|
||||
fini_generic_embeddable (x->value, &elem_off, desc + 1, desc_end, aliased);
|
||||
}
|
||||
}, ddsrt_free (x->value));
|
||||
while (desc + 1 != desc_end && *++desc != XSTOP) { }
|
||||
break;
|
||||
case Xopt: break;
|
||||
}
|
||||
desc++;
|
||||
}
|
||||
|
|
@ -362,6 +399,26 @@ static void fini_generic_partial (void * __restrict dst, size_t * __restrict dst
|
|||
#undef COMPLEX
|
||||
}
|
||||
|
||||
static size_t pserop_memalign (enum pserop op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case XO: case XQ: return alignof (ddsi_octetseq_t);
|
||||
case XS: return alignof (char *);
|
||||
case XG: return alignof (ddsi_guid_t);
|
||||
case XK: return alignof (nn_keyhash_t);
|
||||
case Xb: case Xbx2: return 1;
|
||||
case Xo: case Xox2: return 1;
|
||||
case XbCOND: case XbPROP: return 1;
|
||||
case XE1: case XE2: case XE3: return sizeof (uint32_t);
|
||||
case Xi: case Xix2: case Xix3: case Xix4: return sizeof (int32_t);
|
||||
case Xu: case Xux2: case Xux3: case Xux4: case Xux5: return sizeof (uint32_t);
|
||||
case XD: case XDx2: return alignof (dds_duration_t);
|
||||
case XSTOP: case Xopt: assert (0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff, const enum pserop * __restrict desc)
|
||||
{
|
||||
enum pserop const * const desc_in = desc;
|
||||
|
|
@ -376,8 +433,7 @@ static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict ds
|
|||
switch (*desc)
|
||||
{
|
||||
case XSTOP:
|
||||
*flagset->present |= flag;
|
||||
return 0;
|
||||
goto success;
|
||||
case XO: { /* octet sequence */
|
||||
ddsi_octetseq_t * const x = deser_generic_dst (dst, dstoff, alignof (ddsi_octetseq_t));
|
||||
if (deser_uint32 (&x->length, dd, srcoff) < 0 || dd->bufsz - *srcoff < x->length)
|
||||
|
|
@ -400,22 +456,6 @@ static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict ds
|
|||
*dstoff += sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case XZ: { /* string sequence: repeatedly read a string */
|
||||
ddsi_stringseq_t * const x = deser_generic_dst (dst, dstoff, alignof (ddsi_stringseq_t));
|
||||
/* sequence of string: length <data> length <data> ..., where each length is aligned
|
||||
to a multiple of 4 bytes and the lengths are all at least 1, therefore all but the
|
||||
last entry need 8 bytes and the final one at least 5; checking this protects us
|
||||
against allocating large amount of memory */
|
||||
if (deser_uint32 (&x->n, dd, srcoff) < 0 || x->n > (dd->bufsz - *srcoff + 7) / 8)
|
||||
goto fail;
|
||||
x->strs = x->n ? ddsrt_malloc (x->n * sizeof (*x->strs)) : NULL;
|
||||
size_t tmpoff = 0;
|
||||
for (uint32_t i = 0; i < x->n; i++)
|
||||
if (deser_generic (x->strs, &tmpoff, flagset, flag, dd, srcoff, (enum pserop []) { XS, XSTOP }) < 0)
|
||||
goto fail;
|
||||
*dstoff += sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case XE1: case XE2: case XE3: { /* enum with max allowed value */
|
||||
unsigned * const x = deser_generic_dst (dst, dstoff, alignof (int));
|
||||
const uint32_t maxval = 1 + (uint32_t) (*desc - XE1);
|
||||
|
|
@ -444,15 +484,6 @@ static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict ds
|
|||
*dstoff += cnt * sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case Xl: { /* length(s): int32_t, -1 or >= 1 */
|
||||
int32_t * const x = deser_generic_dst (dst, dstoff, alignof (uint32_t));
|
||||
const uint32_t cnt = 1 + (uint32_t) (*desc - Xl);
|
||||
for (uint32_t i = 0; i < cnt; i++)
|
||||
if (deser_uint32 ((uint32_t *) &x[i], dd, srcoff) < 0 || (x[i] < 1 && x[i] != DDS_LENGTH_UNLIMITED))
|
||||
goto fail;
|
||||
*dstoff += cnt * sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case XD: case XDx2: { /* duration(s): int64_t <=> int32_t.uint32_t (seconds.fraction) */
|
||||
dds_duration_t * const x = deser_generic_dst (dst, dstoff, alignof (dds_duration_t));
|
||||
const uint32_t cnt = 1 + (uint32_t) (*desc - XD);
|
||||
|
|
@ -491,8 +522,14 @@ static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict ds
|
|||
*dstoff += cnt * sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case XbPROP: { /* "propagate" flag, boolean, implied in serialized representation */
|
||||
unsigned char * const x = deser_generic_dst (dst, dstoff, alignof (unsigned char));
|
||||
*x = 1;
|
||||
*dstoff += sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case XG: { /* GUID */
|
||||
nn_guid_t * const x = deser_generic_dst (dst, dstoff, alignof (nn_guid_t));
|
||||
ddsi_guid_t * const x = deser_generic_dst (dst, dstoff, alignof (ddsi_guid_t));
|
||||
if (dd->bufsz - *srcoff < sizeof (*x))
|
||||
goto fail;
|
||||
memcpy (x, dd->buf + *srcoff, sizeof (*x));
|
||||
|
|
@ -510,61 +547,139 @@ static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict ds
|
|||
*dstoff += sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case XQ: { /* non-nested but otherwise arbitrary sequence, so no nested mallocs */
|
||||
ddsi_octetseq_t * const x = deser_generic_dst (dst, dstoff, alignof (ddsi_octetseq_t));
|
||||
if (deser_uint32 (&x->length, dd, srcoff) < 0 || x->length > dd->bufsz - *srcoff)
|
||||
goto fail;
|
||||
const size_t elem_size = ser_generic_srcsize (desc + 1);
|
||||
x->value = x->length ? ddsrt_malloc (x->length * elem_size) : NULL;
|
||||
for (uint32_t i = 0; i < x->length; i++)
|
||||
{
|
||||
size_t elem_off = i * elem_size;
|
||||
if (deser_generic (x->value, &elem_off, flagset, flag, dd, srcoff, desc + 1) < 0)
|
||||
{
|
||||
ddsrt_free (x->value);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
*dstoff += sizeof (*x);
|
||||
while (*++desc != XSTOP) { }
|
||||
break;
|
||||
}
|
||||
case Xopt: { /* remainder is optional; alignment is very nearly always 4 */
|
||||
bool end_of_input;
|
||||
if (pserop_seralign_is_1 (desc[1]))
|
||||
end_of_input = (*srcoff + 1 > dd->bufsz);
|
||||
else
|
||||
{
|
||||
*srcoff = (*srcoff + 3) & ~(size_t)3;
|
||||
end_of_input = (*srcoff + 4 > dd->bufsz);
|
||||
}
|
||||
if (end_of_input)
|
||||
{
|
||||
void * const x = deser_generic_dst (dst, dstoff, pserop_memalign (desc[1]));
|
||||
size_t rem_size = ser_generic_srcsize (desc + 1);
|
||||
memset (x, 0, rem_size);
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
}
|
||||
desc++;
|
||||
}
|
||||
success:
|
||||
*flagset->present |= flag;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
fini_generic_partial (dst, &dstoff_in, desc_in, desc, *flagset->aliased & flag);
|
||||
fini_generic_embeddable (dst, &dstoff_in, desc_in, desc, *flagset->aliased & flag);
|
||||
*flagset->present &= ~flag;
|
||||
*flagset->aliased &= ~flag;
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
static size_t ser_generic_size (const void *src, size_t srcoff, const enum pserop * __restrict desc)
|
||||
dds_return_t plist_deser_generic (void * __restrict dst, const void * __restrict src, size_t srcsize, bool bswap, const enum pserop * __restrict desc)
|
||||
{
|
||||
struct dd dd = {
|
||||
.buf = src,
|
||||
.bufsz = srcsize,
|
||||
.bswap = bswap,
|
||||
.protocol_version = {0,0},
|
||||
.vendorid = NN_VENDORID_ECLIPSE,
|
||||
.factory = NULL
|
||||
};
|
||||
uint64_t present = 0, aliased = 0;
|
||||
struct flagset fs = { .present = &present, .aliased = &aliased, .wanted = 1 };
|
||||
size_t dstoff = 0, srcoff = 0;
|
||||
return deser_generic (dst, &dstoff, &fs, 1, &dd, &srcoff, desc);
|
||||
}
|
||||
|
||||
static void ser_generic_size_embeddable (size_t *dstoff, const void *src, size_t srcoff, const enum pserop * __restrict desc)
|
||||
{
|
||||
size_t dstoff = 0;
|
||||
#define COMPLEX(basecase_, type_, dstoff_update_) do { \
|
||||
type_ const *x = deser_generic_src (src, &srcoff, alignof (type_)); \
|
||||
const uint32_t cnt = 1 + (uint32_t) (*desc - (basecase_)); \
|
||||
for (uint32_t xi = 0; xi < cnt; xi++, x++) { dstoff_update_; } \
|
||||
srcoff += cnt * sizeof (*x); \
|
||||
} while (0)
|
||||
#define SIMPLE1(basecase_, type_) COMPLEX (basecase_, type_, dstoff = dstoff + sizeof (*x))
|
||||
#define SIMPLE4(basecase_, type_) COMPLEX (basecase_, type_, dstoff = align4size (dstoff) + sizeof (*x))
|
||||
#define SIMPLE1(basecase_, type_) COMPLEX (basecase_, type_, *dstoff = *dstoff + sizeof (*x))
|
||||
#define SIMPLE4(basecase_, type_) COMPLEX (basecase_, type_, *dstoff = align4size (*dstoff) + sizeof (*x))
|
||||
while (true)
|
||||
{
|
||||
switch (*desc)
|
||||
{
|
||||
case XSTOP: return dstoff;
|
||||
case XO: COMPLEX (XO, ddsi_octetseq_t, dstoff = align4size (dstoff) + 4 + x->length); break;
|
||||
case XS: COMPLEX (XS, const char *, dstoff = align4size (dstoff) + 4 + strlen (*x) + 1); break;
|
||||
case XZ: COMPLEX (XZ, ddsi_stringseq_t, {
|
||||
dstoff = align4size (dstoff) + 4;
|
||||
for (uint32_t i = 0; i < x->n; i++)
|
||||
dstoff = align4size (dstoff) + 4 + strlen (x->strs[i]) + 1;
|
||||
}); break;
|
||||
case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, dstoff = align4size (dstoff) + 4); break;
|
||||
case XSTOP: return;
|
||||
case XO: COMPLEX (XO, ddsi_octetseq_t, *dstoff = align4size (*dstoff) + 4 + x->length); break;
|
||||
case XS: COMPLEX (XS, const char *, *dstoff = align4size (*dstoff) + 4 + strlen (*x) + 1); break;
|
||||
case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, *dstoff = align4size (*dstoff) + 4); break;
|
||||
case Xi: case Xix2: case Xix3: case Xix4: SIMPLE4 (Xi, int32_t); break;
|
||||
case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE4 (Xu, uint32_t); break;
|
||||
case Xl: SIMPLE4 (Xl, int32_t); break;
|
||||
case XD: case XDx2: SIMPLE4 (XD, dds_duration_t); break;
|
||||
case Xo: case Xox2: SIMPLE1 (Xo, unsigned char); break;
|
||||
case Xb: case Xbx2: SIMPLE1 (Xb, unsigned char); break;
|
||||
case XbCOND: SIMPLE1 (XbCOND, unsigned char); break;
|
||||
case XG: SIMPLE1 (XG, nn_guid_t); break;
|
||||
case XG: SIMPLE1 (XG, ddsi_guid_t); break;
|
||||
case XK: SIMPLE1 (XK, nn_keyhash_t); break;
|
||||
case XbPROP: /* "propagate" boolean: when 'false'; no serialisation; no size; force early out */
|
||||
COMPLEX (XbPROP, unsigned char, if (! *x) return); break;
|
||||
case XQ: COMPLEX (XQ, ddsi_octetseq_t, {
|
||||
const size_t elem_size = ser_generic_srcsize (desc + 1);
|
||||
*dstoff = align4size (*dstoff) + 4;
|
||||
for (uint32_t i = 0; i < x->length; i++)
|
||||
ser_generic_size_embeddable (dstoff, x->value, i * elem_size, desc + 1);
|
||||
}); while (*++desc != XSTOP) { } break;
|
||||
case Xopt: break;
|
||||
}
|
||||
desc++;
|
||||
}
|
||||
#undef SIMPLE
|
||||
#undef SIMPLE4
|
||||
#undef SIMPLE1
|
||||
#undef COMPLEX
|
||||
}
|
||||
|
||||
static dds_return_t ser_generic (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff, const enum pserop * __restrict desc)
|
||||
static size_t ser_generic_size (const void *src, size_t srcoff, const enum pserop * __restrict desc)
|
||||
{
|
||||
char * const data = nn_xmsg_addpar (xmsg, pid, ser_generic_size (src, srcoff, desc));
|
||||
size_t dstoff = 0;
|
||||
ser_generic_size_embeddable (&dstoff, src, srcoff, desc);
|
||||
return dstoff;
|
||||
}
|
||||
|
||||
static uint32_t ser_generic_count (const ddsi_octetseq_t *src, size_t elem_size, const enum pserop * __restrict desc)
|
||||
{
|
||||
/* This whole thing exists solely for dealing with the vile "propagate" boolean, which must come first in an
|
||||
element, or one can't deserialize it at all. Therefore, if desc doesn't start with XbPROP, all "length"
|
||||
elements are included in the output */
|
||||
if (*desc != XbPROP)
|
||||
return src->length;
|
||||
/* and if it does start with XbPROP, only those for which it is true are included */
|
||||
uint32_t count = 0;
|
||||
for (uint32_t i = 0; i < src->length; i++)
|
||||
if (src->value[i * elem_size])
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, const void *src, size_t srcoff, const enum pserop * __restrict desc)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
switch (*desc)
|
||||
|
|
@ -573,134 +688,151 @@ static dds_return_t ser_generic (struct nn_xmsg *xmsg, nn_parameterid_t pid, con
|
|||
return 0;
|
||||
case XO: { /* octet sequence */
|
||||
ddsi_octetseq_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_octetseq_t));
|
||||
char * const p = ser_generic_align4 (data, &dstoff);
|
||||
char * const p = ser_generic_align4 (data, dstoff);
|
||||
*((uint32_t *) p) = x->length;
|
||||
if (x->length) memcpy (p + 4, x->value, x->length);
|
||||
dstoff += 4 + x->length;
|
||||
*dstoff += 4 + x->length;
|
||||
srcoff += sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case XS: { /* string */
|
||||
char const * const * const x = deser_generic_src (src, &srcoff, alignof (char *));
|
||||
const uint32_t size = (uint32_t) (strlen (*x) + 1);
|
||||
char * const p = ser_generic_align4 (data, &dstoff);
|
||||
char * const p = ser_generic_align4 (data, dstoff);
|
||||
*((uint32_t *) p) = size;
|
||||
memcpy (p + 4, *x, size);
|
||||
dstoff += 4 + size;
|
||||
srcoff += sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case XZ: { /* string sequence */
|
||||
ddsi_stringseq_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_stringseq_t));
|
||||
char * const p = ser_generic_align4 (data, &dstoff);
|
||||
*((uint32_t *) p) = x->n;
|
||||
dstoff += 4;
|
||||
for (uint32_t i = 0; i < x->n; i++)
|
||||
{
|
||||
char * const q = ser_generic_align4 (data, &dstoff);
|
||||
const uint32_t size = (uint32_t) (strlen (x->strs[i]) + 1);
|
||||
*((uint32_t *) q) = size;
|
||||
memcpy (q + 4, x->strs[i], size);
|
||||
dstoff += 4 + size;
|
||||
}
|
||||
*dstoff += 4 + size;
|
||||
srcoff += sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case XE1: case XE2: case XE3: { /* enum */
|
||||
unsigned const * const x = deser_generic_src (src, &srcoff, alignof (unsigned));
|
||||
uint32_t * const p = ser_generic_align4 (data, &dstoff);
|
||||
uint32_t * const p = ser_generic_align4 (data, dstoff);
|
||||
*p = (uint32_t) *x;
|
||||
dstoff += 4;
|
||||
*dstoff += 4;
|
||||
srcoff += sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case Xi: case Xix2: case Xix3: case Xix4: { /* int32_t(s) */
|
||||
int32_t const * const x = deser_generic_src (src, &srcoff, alignof (int32_t));
|
||||
const uint32_t cnt = 1 + (uint32_t) (*desc - Xi);
|
||||
int32_t * const p = ser_generic_align4 (data, &dstoff);
|
||||
int32_t * const p = ser_generic_align4 (data, dstoff);
|
||||
for (uint32_t i = 0; i < cnt; i++)
|
||||
p[i] = x[i];
|
||||
dstoff += cnt * sizeof (*x);
|
||||
*dstoff += cnt * sizeof (*x);
|
||||
srcoff += cnt * sizeof (*x);
|
||||
break;
|
||||
}
|
||||
|
||||
case Xu: case Xux2: case Xux3: case Xux4: case Xux5: { /* uint32_t(s) */
|
||||
uint32_t const * const x = deser_generic_src (src, &srcoff, alignof (uint32_t));
|
||||
const uint32_t cnt = 1 + (uint32_t) (*desc - Xu);
|
||||
uint32_t * const p = ser_generic_align4 (data, &dstoff);
|
||||
uint32_t * const p = ser_generic_align4 (data, dstoff);
|
||||
for (uint32_t i = 0; i < cnt; i++)
|
||||
p[i] = x[i];
|
||||
dstoff += cnt * sizeof (*x);
|
||||
srcoff += cnt * sizeof (*x);
|
||||
break;
|
||||
}
|
||||
|
||||
case Xl: { /* int32_t(s) */
|
||||
int32_t const * const x = deser_generic_src (src, &srcoff, alignof (uint32_t));
|
||||
const uint32_t cnt = 1 + (uint32_t) (*desc - Xu);
|
||||
int32_t * const p = ser_generic_align4 (data, &dstoff);
|
||||
for (uint32_t i = 0; i < cnt; i++)
|
||||
p[i] = x[i];
|
||||
dstoff += cnt * sizeof (*x);
|
||||
*dstoff += cnt * sizeof (*x);
|
||||
srcoff += cnt * sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case XD: case XDx2: { /* duration(s): int64_t <=> int32_t.uint32_t (seconds.fraction) */
|
||||
dds_duration_t const * const x = deser_generic_src (src, &srcoff, alignof (dds_duration_t));
|
||||
const uint32_t cnt = 1 + (uint32_t) (*desc - XD);
|
||||
uint32_t * const p = ser_generic_align4 (data, &dstoff);
|
||||
uint32_t * const p = ser_generic_align4 (data, dstoff);
|
||||
for (uint32_t i = 0; i < cnt; i++)
|
||||
{
|
||||
ddsi_duration_t tmp = nn_to_ddsi_duration (x[i]);
|
||||
p[2 * i + 0] = (uint32_t) tmp.seconds;
|
||||
p[2 * i + 1] = tmp.fraction;
|
||||
}
|
||||
dstoff += 2 * cnt * sizeof (uint32_t);
|
||||
*dstoff += 2 * cnt * sizeof (uint32_t);
|
||||
srcoff += cnt * sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case Xo: case Xox2: { /* octet(s) */
|
||||
unsigned char const * const x = deser_generic_src (src, &srcoff, alignof (unsigned char));
|
||||
const uint32_t cnt = 1 + (uint32_t) (*desc - Xo);
|
||||
char * const p = data + dstoff;
|
||||
char * const p = data + *dstoff;
|
||||
memcpy (p, x, cnt);
|
||||
dstoff += cnt;
|
||||
*dstoff += cnt;
|
||||
srcoff += cnt * sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case Xb: case Xbx2: case XbCOND: { /* boolean(s) */
|
||||
unsigned char const * const x = deser_generic_src (src, &srcoff, alignof (unsigned char));
|
||||
const uint32_t cnt = (*desc == Xbx2) ? 2 : 1; /* <<<< beware! */
|
||||
char * const p = data + dstoff;
|
||||
char * const p = data + *dstoff;
|
||||
memcpy (p, x, cnt);
|
||||
dstoff += cnt;
|
||||
*dstoff += cnt;
|
||||
srcoff += cnt * sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case XbPROP: { /* "propagate" boolean: don't serialize, skip it and everything that follows if false */
|
||||
unsigned char const * const x = deser_generic_src (src, &srcoff, alignof (unsigned char));
|
||||
if (! *x) return 0;
|
||||
srcoff++;
|
||||
break;
|
||||
}
|
||||
case XG: { /* GUID */
|
||||
nn_guid_t const * const x = deser_generic_src (src, &srcoff, alignof (nn_guid_t));
|
||||
const nn_guid_t xn = nn_hton_guid (*x);
|
||||
char * const p = data + dstoff;
|
||||
ddsi_guid_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_guid_t));
|
||||
const ddsi_guid_t xn = nn_hton_guid (*x);
|
||||
char * const p = data + *dstoff;
|
||||
memcpy (p, &xn, sizeof (xn));
|
||||
dstoff += sizeof (xn);
|
||||
*dstoff += sizeof (xn);
|
||||
srcoff += sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case XK: { /* keyhash */
|
||||
nn_keyhash_t const * const x = deser_generic_src (src, &srcoff, alignof (nn_keyhash_t));
|
||||
char * const p = data + dstoff;
|
||||
char * const p = data + *dstoff;
|
||||
memcpy (p, x, sizeof (*x));
|
||||
dstoff += sizeof (*x);
|
||||
*dstoff += sizeof (*x);
|
||||
srcoff += sizeof (*x);
|
||||
break;
|
||||
}
|
||||
case XQ: {
|
||||
ddsi_octetseq_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_octetseq_t));
|
||||
char * const p = ser_generic_align4 (data, dstoff);
|
||||
*dstoff += 4;
|
||||
if (x->length == 0)
|
||||
*((uint32_t *) p) = 0;
|
||||
else
|
||||
{
|
||||
const size_t elem_size = ser_generic_srcsize (desc + 1);
|
||||
*((uint32_t *) p) = ser_generic_count (x, elem_size, desc + 1);
|
||||
for (uint32_t i = 0; i < x->length; i++)
|
||||
ser_generic_embeddable (data, dstoff, x->value, i * elem_size, desc + 1);
|
||||
}
|
||||
srcoff += sizeof (*x);
|
||||
while (*++desc != XSTOP) { }
|
||||
break;
|
||||
}
|
||||
case Xopt:
|
||||
break;
|
||||
}
|
||||
desc++;
|
||||
}
|
||||
}
|
||||
|
||||
static dds_return_t unalias_generic (void * __restrict dst, size_t * __restrict dstoff, const enum pserop * __restrict desc)
|
||||
static dds_return_t ser_generic (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff, const enum pserop * __restrict desc)
|
||||
{
|
||||
char * const data = nn_xmsg_addpar (xmsg, pid, ser_generic_size (src, srcoff, desc));
|
||||
size_t dstoff = 0;
|
||||
return ser_generic_embeddable (data, &dstoff, src, srcoff, desc);
|
||||
}
|
||||
|
||||
dds_return_t plist_ser_generic (void **dst, size_t *dstsize, const void *src, const enum pserop * __restrict desc)
|
||||
{
|
||||
const size_t srcoff = 0;
|
||||
size_t dstoff = 0;
|
||||
dds_return_t ret;
|
||||
*dstsize = ser_generic_size (src, srcoff, desc);
|
||||
if ((*dst = ddsrt_malloc (*dstsize == 0 ? 1 : *dstsize)) == NULL)
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
ret = ser_generic_embeddable (*dst, &dstoff, src, srcoff, desc);
|
||||
assert (dstoff == *dstsize);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static dds_return_t unalias_generic (void * __restrict dst, size_t * __restrict dstoff, bool gen_seq_aliased, const enum pserop * __restrict desc)
|
||||
{
|
||||
#define COMPLEX(basecase_, type_, ...) do { \
|
||||
type_ *x = deser_generic_dst (dst, dstoff, alignof (type_)); \
|
||||
|
|
@ -717,21 +849,36 @@ static dds_return_t unalias_generic (void * __restrict dst, size_t * __restrict
|
|||
return 0;
|
||||
case XO: COMPLEX (XO, ddsi_octetseq_t, if (x->value) { x->value = ddsrt_memdup (x->value, x->length); }); break;
|
||||
case XS: COMPLEX (XS, char *, if (*x) { *x = ddsrt_strdup (*x); }); break;
|
||||
case XZ: COMPLEX (XZ, ddsi_stringseq_t, if (x->n) {
|
||||
x->strs = ddsrt_memdup (x->strs, x->n * sizeof (*x->strs));
|
||||
for (uint32_t i = 0; i < x->n; i++)
|
||||
x->strs[i] = ddsrt_strdup (x->strs[i]);
|
||||
}); break;
|
||||
case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, (void) 0); break;
|
||||
case Xi: case Xix2: case Xix3: case Xix4: SIMPLE (Xi, int32_t); break;
|
||||
case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE (Xu, uint32_t); break;
|
||||
case Xl: SIMPLE (Xl, int32_t); break;
|
||||
case XD: case XDx2: SIMPLE (XD, dds_duration_t); break;
|
||||
case Xo: case Xox2: SIMPLE (Xo, unsigned char); break;
|
||||
case Xb: case Xbx2: SIMPLE (Xb, unsigned char); break;
|
||||
case XbCOND: SIMPLE (XbCOND, unsigned char); break;
|
||||
case XG: SIMPLE (XG, nn_guid_t); break;
|
||||
case XbPROP: SIMPLE (XbPROP, unsigned char); break;
|
||||
case XG: SIMPLE (XG, ddsi_guid_t); break;
|
||||
case XK: SIMPLE (XK, nn_keyhash_t); break;
|
||||
case XQ: COMPLEX (XQ, ddsi_octetseq_t, if (x->length) {
|
||||
const size_t elem_size = ser_generic_srcsize (desc + 1);
|
||||
if (gen_seq_aliased)
|
||||
{
|
||||
/* The memory for the elements of a generic sequence are owned by the plist, the only aliased bits
|
||||
are the strings (XS) and octet sequences (XO) embedded in the elements. So in principle, an
|
||||
unalias operation on a generic sequence should only operate on the elements of the sequence,
|
||||
not on the sequence buffer itself.
|
||||
|
||||
However, the "mergein_missing" operation (and consequently the copy & dup operations) memcpy the
|
||||
source, then pretend it is aliased. In this case, the sequence buffer is aliased, rather than
|
||||
private, and hence a new copy needs to be allocated. */
|
||||
x->value = ddsrt_memdup (x->value, x->length * elem_size);
|
||||
}
|
||||
for (uint32_t i = 0; i < x->length; i++) {
|
||||
size_t elem_off = i * elem_size;
|
||||
unalias_generic (x->value, &elem_off, gen_seq_aliased, desc + 1);
|
||||
}
|
||||
}); while (*++desc != XSTOP) { } break;
|
||||
case Xopt: break;
|
||||
}
|
||||
desc++;
|
||||
}
|
||||
|
|
@ -739,13 +886,19 @@ static dds_return_t unalias_generic (void * __restrict dst, size_t * __restrict
|
|||
#undef COMPLEX
|
||||
}
|
||||
|
||||
dds_return_t plist_unalias_generic (void * __restrict dst, const enum pserop * __restrict desc)
|
||||
{
|
||||
size_t dstoff = 0;
|
||||
return unalias_generic (dst, &dstoff, false, desc);
|
||||
}
|
||||
|
||||
static bool unalias_generic_required (const enum pserop * __restrict desc)
|
||||
{
|
||||
while (*desc != XSTOP)
|
||||
{
|
||||
switch (*desc++)
|
||||
{
|
||||
case XO: case XS: case XZ:
|
||||
case XO: case XS: case XQ:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -762,10 +915,16 @@ static bool fini_generic_required (const enum pserop * __restrict desc)
|
|||
|
||||
static dds_return_t fini_generic (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const enum pserop * __restrict desc)
|
||||
{
|
||||
fini_generic_partial (dst, dstoff, desc, NULL, *flagset->aliased & flag);
|
||||
fini_generic_embeddable (dst, dstoff, desc, NULL, *flagset->aliased & flag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void plist_fini_generic (void * __restrict dst, const enum pserop *desc, bool aliased)
|
||||
{
|
||||
size_t dstoff = 0;
|
||||
fini_generic_embeddable (dst, &dstoff, desc, NULL, aliased);
|
||||
}
|
||||
|
||||
static dds_return_t valid_generic (const void *src, size_t srcoff, const enum pserop * __restrict desc)
|
||||
{
|
||||
#define COMPLEX(basecase_, type_, cond_stmts_) do { \
|
||||
|
|
@ -783,23 +942,29 @@ static dds_return_t valid_generic (const void *src, size_t srcoff, const enum ps
|
|||
case XSTOP: return 0;
|
||||
case XO: SIMPLE (XO, ddsi_octetseq_t, (x->length == 0) == (x->value == NULL)); break;
|
||||
case XS: SIMPLE (XS, const char *, *x != NULL); break;
|
||||
case XZ: COMPLEX (XZ, ddsi_stringseq_t, {
|
||||
if ((x->n == 0) != (x->strs == NULL))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
for (uint32_t i = 0; i < x->n; i++)
|
||||
if (x->strs[i] == NULL)
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
}); break;
|
||||
case XE1: case XE2: case XE3: SIMPLE (*desc, unsigned, *x <= 1 + (unsigned) *desc - XE1); break;
|
||||
case Xi: case Xix2: case Xix3: case Xix4: TRIVIAL (Xi, int32_t); break;
|
||||
case Xu: case Xux2: case Xux3: case Xux4: case Xux5: TRIVIAL (Xu, uint32_t); break;
|
||||
case Xl: SIMPLE (Xl, int32_t, *x == DDS_LENGTH_UNLIMITED || *x > 1); break;
|
||||
case XD: case XDx2: SIMPLE (XD, dds_duration_t, *x >= 0); break;
|
||||
case Xo: case Xox2: TRIVIAL (Xo, unsigned char); break;
|
||||
case Xb: case Xbx2: SIMPLE (Xb, unsigned char, *x == 0 || *x == 1); break;
|
||||
case XbCOND: SIMPLE (XbCOND, unsigned char, *x == 0 || *x == 1); break;
|
||||
case XG: TRIVIAL (XG, nn_guid_t); break;
|
||||
case XbPROP: SIMPLE (XbPROP, unsigned char, *x == 0 || *x == 1); break;
|
||||
case XG: TRIVIAL (XG, ddsi_guid_t); break;
|
||||
case XK: TRIVIAL (XK, nn_keyhash_t); break;
|
||||
case XQ: COMPLEX (XQ, ddsi_octetseq_t, {
|
||||
if ((x->length == 0) != (x->value == NULL))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
if (x->length) {
|
||||
const size_t elem_size = ser_generic_srcsize (desc + 1);
|
||||
dds_return_t ret;
|
||||
for (uint32_t i = 0; i < x->length; i++) {
|
||||
if ((ret = valid_generic (x->value, i * elem_size, desc + 1)) != 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}); while (*++desc != XSTOP) { } break;
|
||||
case Xopt: break;
|
||||
}
|
||||
desc++;
|
||||
}
|
||||
|
|
@ -833,19 +998,9 @@ static bool equal_generic (const void *srcx, const void *srcy, size_t srcoff, co
|
|||
case XS:
|
||||
SIMPLE (XS, const char *, strcmp (*x, *y) == 0);
|
||||
break;
|
||||
case XZ:
|
||||
COMPLEX (XZ, ddsi_stringseq_t, {
|
||||
if (x->n != y->n)
|
||||
return false;
|
||||
for (uint32_t i = 0; i < x->n; i++)
|
||||
if (strcmp (x->strs[i], y->strs[i]) != 0)
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case XE1: case XE2: case XE3: TRIVIAL (*desc, unsigned); break;
|
||||
case Xi: case Xix2: case Xix3: case Xix4: TRIVIAL (Xi, int32_t); break;
|
||||
case Xu: case Xux2: case Xux3: case Xux4: case Xux5: TRIVIAL (Xu, uint32_t); break;
|
||||
case Xl: TRIVIAL (Xl, int32_t); break;
|
||||
case XD: case XDx2: TRIVIAL (XD, dds_duration_t); break;
|
||||
case Xo: case Xox2: TRIVIAL (Xo, unsigned char); break;
|
||||
case Xb: case Xbx2: TRIVIAL (Xb, unsigned char); break;
|
||||
|
|
@ -857,8 +1012,21 @@ static bool equal_generic (const void *srcx, const void *srcy, size_t srcoff, co
|
|||
return true;
|
||||
});
|
||||
break;
|
||||
case XG: SIMPLE (XG, nn_guid_t, memcmp (x, y, sizeof (*x))); break;
|
||||
case XK: SIMPLE (XK, nn_keyhash_t, memcmp (x, y, sizeof (*x))); break;
|
||||
case XbPROP: TRIVIAL (XbPROP, unsigned char); break;
|
||||
case XG: SIMPLE (XG, ddsi_guid_t, memcmp (x, y, sizeof (*x)) == 0); break;
|
||||
case XK: SIMPLE (XK, nn_keyhash_t, memcmp (x, y, sizeof (*x)) == 0); break;
|
||||
case XQ: COMPLEX (XQ, ddsi_octetseq_t, {
|
||||
if (x->length != y->length)
|
||||
return false;
|
||||
if (x->length) {
|
||||
const size_t elem_size = ser_generic_srcsize (desc + 1);
|
||||
for (uint32_t i = 0; i < x->length; i++) {
|
||||
if (!equal_generic (x->value, y->value, i * elem_size, desc + 1))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}); while (*++desc != XSTOP) { } break;
|
||||
case Xopt: break;
|
||||
}
|
||||
desc++;
|
||||
}
|
||||
|
|
@ -867,6 +1035,11 @@ static bool equal_generic (const void *srcx, const void *srcy, size_t srcoff, co
|
|||
#undef COMPLEX
|
||||
}
|
||||
|
||||
bool plist_equal_generic (const void *srcx, const void *srcy, const enum pserop * __restrict desc)
|
||||
{
|
||||
return equal_generic (srcx, srcy, 0, desc);
|
||||
}
|
||||
|
||||
#define membersize(type, member) sizeof (((type *) 0)->member)
|
||||
#define ENTRY(PFX_, NAME_, member_, flag_, validate_, ...) \
|
||||
{ PID_##NAME_, flag_, PFX_##_##NAME_, #NAME_, offsetof (struct nn_plist, member_), \
|
||||
|
|
@ -904,7 +1077,7 @@ static dds_return_t dvx_resource_limits (void * __restrict dst, const struct dd
|
|||
|
||||
static dds_return_t dvx_participant_guid (void * __restrict dst, const struct dd * __restrict dd)
|
||||
{
|
||||
const nn_guid_t *g = dst;
|
||||
const ddsi_guid_t *g = dst;
|
||||
(void) dd;
|
||||
if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0)
|
||||
return (g->entityid.u == 0) ? 0 : DDS_RETCODE_BAD_PARAMETER;
|
||||
|
|
@ -914,7 +1087,7 @@ static dds_return_t dvx_participant_guid (void * __restrict dst, const struct dd
|
|||
|
||||
static dds_return_t dvx_group_guid (void * __restrict dst, const struct dd * __restrict dd)
|
||||
{
|
||||
const nn_guid_t *g = dst;
|
||||
const ddsi_guid_t *g = dst;
|
||||
(void) dd;
|
||||
if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0)
|
||||
return (g->entityid.u == 0) ? 0 : DDS_RETCODE_BAD_PARAMETER;
|
||||
|
|
@ -924,7 +1097,7 @@ static dds_return_t dvx_group_guid (void * __restrict dst, const struct dd * __r
|
|||
|
||||
static dds_return_t dvx_endpoint_guid (void * __restrict dst, const struct dd * __restrict dd)
|
||||
{
|
||||
nn_guid_t *g = dst;
|
||||
ddsi_guid_t *g = dst;
|
||||
if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0)
|
||||
return (g->entityid.u == 0) ? 0 : DDS_RETCODE_BAD_PARAMETER;
|
||||
switch (g->entityid.u & NN_ENTITYID_KIND_MASK)
|
||||
|
|
@ -951,6 +1124,7 @@ static dds_return_t dvx_reader_favours_ssm (void * __restrict dst, const struct
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Standardized parameters -- QoS _MUST_ come first (nn_plist_init_tables verifies this) because
|
||||
it allows early-out when processing a dds_qos_t instead of an nn_plist_t */
|
||||
static const struct piddesc piddesc_omg[] = {
|
||||
|
|
@ -966,6 +1140,9 @@ static const struct piddesc piddesc_omg[] = {
|
|||
QP (DEADLINE, deadline, XD),
|
||||
QP (LATENCY_BUDGET, latency_budget, XD),
|
||||
QP (LIVELINESS, liveliness, XE2, XD),
|
||||
/* Property list used to be of type [(String,String]), security changed into ([String,String],Maybe [(String,[Word8])]),
|
||||
the "Xopt" here is to allow both forms on input, with an assumed empty second sequence if the old form was received */
|
||||
QP (PROPERTY_LIST, property, XQ, XbPROP, XS, XS, XSTOP, Xopt, XQ, XbPROP, XS, XO, XSTOP),
|
||||
/* Reliability encoding does not follow the rules (best-effort/reliable map to 1/2 instead of 0/1 */
|
||||
{ PID_RELIABILITY, PDF_QOS | PDF_FUNCTION, QP_RELIABILITY, "RELIABILITY",
|
||||
offsetof (struct nn_plist, qos.reliability), membersize (struct nn_plist, qos.reliability),
|
||||
|
|
@ -978,7 +1155,7 @@ static const struct piddesc piddesc_omg[] = {
|
|||
QP (OWNERSHIP, ownership, XE1),
|
||||
QP (OWNERSHIP_STRENGTH, ownership_strength, Xi),
|
||||
QP (PRESENTATION, presentation, XE2, Xbx2),
|
||||
QP (PARTITION, partition, XZ),
|
||||
QP (PARTITION, partition, XQ, XS, XSTOP),
|
||||
QP (TIME_BASED_FILTER, time_based_filter, XD),
|
||||
QP (TRANSPORT_PRIORITY, transport_priority, Xi),
|
||||
PP (PROTOCOL_VERSION, protocol_version, Xox2),
|
||||
|
|
@ -1038,7 +1215,7 @@ static const struct piddesc piddesc_eclipse[] = {
|
|||
QP (PRISMTECH_READER_LIFESPAN, reader_lifespan, Xb, XD),
|
||||
QP (PRISMTECH_WRITER_DATA_LIFECYCLE, writer_data_lifecycle, Xb),
|
||||
QP (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle, XDx2),
|
||||
QP (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys, XbCOND, XZ),
|
||||
QP (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys, XbCOND, XQ, XS, XSTOP),
|
||||
{ PID_PAD, PDF_QOS, QP_CYCLONE_IGNORELOCAL, "CYCLONE_IGNORELOCAL",
|
||||
offsetof (struct nn_plist, qos.ignorelocal), membersize (struct nn_plist, qos.ignorelocal),
|
||||
{ .desc = { XE2, XSTOP } }, 0 },
|
||||
|
|
@ -1057,7 +1234,7 @@ static const struct piddesc piddesc_prismtech[] = {
|
|||
QP (PRISMTECH_READER_LIFESPAN, reader_lifespan, Xb, XD),
|
||||
QP (PRISMTECH_WRITER_DATA_LIFECYCLE, writer_data_lifecycle, Xb),
|
||||
QP (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle, XDx2),
|
||||
QP (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys, XbCOND, XZ),
|
||||
QP (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys, XbCOND, XQ, XS, XSTOP),
|
||||
PP (PRISMTECH_BUILTIN_ENDPOINT_SET, prismtech_builtin_endpoint_set, Xu),
|
||||
PP (PRISMTECH_PARTICIPANT_VERSION_INFO, prismtech_participant_version_info, Xux5, XS),
|
||||
PP (PRISMTECH_EXEC_NAME, exec_name, XS),
|
||||
|
|
@ -1141,8 +1318,8 @@ static const struct piddesc_index piddesc_vendor_index[] = {
|
|||
/* List of entries that require unalias, fini processing;
|
||||
initialized by nn_plist_init_tables; will assert when
|
||||
table too small or too large */
|
||||
static const struct piddesc *piddesc_unalias[18];
|
||||
static const struct piddesc *piddesc_fini[18];
|
||||
static const struct piddesc *piddesc_unalias[19];
|
||||
static const struct piddesc *piddesc_fini[19];
|
||||
static ddsrt_once_t table_init_control = DDSRT_ONCE_INIT;
|
||||
|
||||
static nn_parameterid_t pid_without_flags (nn_parameterid_t pid)
|
||||
|
|
@ -1268,7 +1445,7 @@ static void plist_or_xqos_fini (void * __restrict dst, size_t shift, uint64_t pm
|
|||
if (shift > 0)
|
||||
{
|
||||
dds_qos_t *qos = dst;
|
||||
pfs = (struct flagset) { 0 };
|
||||
pfs = (struct flagset) { NULL, NULL, 0 };
|
||||
qfs = (struct flagset) { .present = &qos->present, .aliased = &qos->aliased };
|
||||
}
|
||||
else
|
||||
|
|
@ -1310,7 +1487,7 @@ static void plist_or_xqos_unalias (void * __restrict dst, size_t shift)
|
|||
if (shift > 0)
|
||||
{
|
||||
dds_qos_t *qos = dst;
|
||||
pfs = (struct flagset) { 0 };
|
||||
pfs = (struct flagset) { NULL, NULL, 0 };
|
||||
qfs = (struct flagset) { .present = &qos->present, .aliased = &qos->aliased };
|
||||
}
|
||||
else
|
||||
|
|
@ -1331,7 +1508,7 @@ static void plist_or_xqos_unalias (void * __restrict dst, size_t shift)
|
|||
if ((*fs->present & entry->present_flag) && (*fs->aliased & entry->present_flag))
|
||||
{
|
||||
if (!(entry->flags & PDF_FUNCTION))
|
||||
unalias_generic (dst, &dstoff, entry->op.desc);
|
||||
unalias_generic (dst, &dstoff, false, entry->op.desc);
|
||||
else if (entry->op.f.unalias)
|
||||
entry->op.f.unalias (dst, &dstoff);
|
||||
*fs->aliased &= ~entry->present_flag;
|
||||
|
|
@ -1354,9 +1531,9 @@ static void plist_or_xqos_mergein_missing (void * __restrict dst, const void * _
|
|||
{
|
||||
dds_qos_t *qos_dst = dst;
|
||||
const dds_qos_t *qos_src = src;
|
||||
pfs_dst = (struct flagset) { 0 };
|
||||
pfs_dst = (struct flagset) { NULL, NULL, 0 };
|
||||
qfs_dst = (struct flagset) { .present = &qos_dst->present, .aliased = &qos_dst->aliased };
|
||||
pfs_src = (struct flagset) { 0 };
|
||||
pfs_src = (struct flagset) { NULL, NULL, 0 };
|
||||
qfs_src = (struct flagset) { .present = (uint64_t *) &qos_src->present, .aliased = (uint64_t *) &qos_src->aliased };
|
||||
}
|
||||
else
|
||||
|
|
@ -1389,15 +1566,15 @@ static void plist_or_xqos_mergein_missing (void * __restrict dst, const void * _
|
|||
if (!(*fs_dst->present & entry->present_flag) && (*fs_src->present & mask & entry->present_flag))
|
||||
{
|
||||
/* bitwise copy, mark as aliased & unalias; have to unalias fields one-by-one rather than
|
||||
do this for all fields and call "unalias" on the entire object because fields that are
|
||||
already present may be aliased, and it would be somewhat impolite to change that.
|
||||
do this for all fields and call "unalias" on the entire object because fields that are
|
||||
already present may be aliased, and it would be somewhat impolite to change that.
|
||||
|
||||
Note: dst & src have the same type, so offset in src is the same;
|
||||
Note: unalias may have to look at */
|
||||
Note: dst & src have the same type, so offset in src is the same;
|
||||
Note: unalias may have to look at */
|
||||
memcpy ((char *) dst + dstoff, (const char *) src + dstoff, entry->size);
|
||||
*fs_dst->present |= entry->present_flag;
|
||||
if (!(entry->flags & PDF_FUNCTION))
|
||||
unalias_generic (dst, &dstoff, entry->op.desc);
|
||||
unalias_generic (dst, &dstoff, true, entry->op.desc);
|
||||
else if (entry->op.f.unalias)
|
||||
entry->op.f.unalias (dst, &dstoff);
|
||||
}
|
||||
|
|
@ -2228,7 +2405,7 @@ const unsigned char *nn_plist_findparam_native_unchecked (const void *src, nn_pa
|
|||
const nn_parameter_t *par = src;
|
||||
while (par->parameterid != pid)
|
||||
{
|
||||
if (pid == PID_SENTINEL)
|
||||
if (par->parameterid == PID_SENTINEL)
|
||||
return NULL;
|
||||
par = (const nn_parameter_t *) ((const char *) (par + 1) + par->length);
|
||||
}
|
||||
|
|
@ -2763,6 +2940,29 @@ void nn_log_xqos (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qo
|
|||
});
|
||||
DO (PRISMTECH_ENTITY_FACTORY, { LOGB1 ("entity_factory=%u", xqos->entity_factory.autoenable_created_entities); });
|
||||
DO (CYCLONE_IGNORELOCAL, { LOGB1 ("ignorelocal=%u", xqos->ignorelocal.value); });
|
||||
DO (PROPERTY_LIST, {
|
||||
LOGB0 ("property_list={");
|
||||
DDS_CLOG (cat, logcfg, "value={");
|
||||
for (uint32_t i = 0; i < xqos->property.value.n; i++) {
|
||||
DDS_CLOG (cat, logcfg, "%s{%s,%s,%u}",
|
||||
(i == 0) ? "" : ",",
|
||||
xqos->property.value.props[i].name,
|
||||
xqos->property.value.props[i].value,
|
||||
xqos->property.value.props[i].propagate);
|
||||
}
|
||||
DDS_CLOG (cat, logcfg, "}");
|
||||
DDS_CLOG (cat, logcfg, "binary_value={");
|
||||
for (uint32_t i = 0; i < xqos->property.binary_value.n; i++) {
|
||||
DDS_CLOG (cat, logcfg, "%s{%s,(%u,%p),%u}",
|
||||
(i == 0) ? "" : ",",
|
||||
xqos->property.binary_value.props[i].name,
|
||||
xqos->property.binary_value.props[i].value.length,
|
||||
xqos->property.binary_value.props[i].value.value,
|
||||
xqos->property.binary_value.props[i].propagate);
|
||||
}
|
||||
DDS_CLOG (cat, logcfg, "}");
|
||||
DDS_CLOG (cat, logcfg, "}");
|
||||
});
|
||||
|
||||
#undef PRINTARG_DUR
|
||||
#undef FMT_DUR
|
||||
|
|
|
|||
|
|
@ -2407,7 +2407,7 @@ struct nn_dqueue_bubble {
|
|||
void *arg;
|
||||
} cb;
|
||||
struct {
|
||||
nn_guid_t rdguid;
|
||||
ddsi_guid_t rdguid;
|
||||
uint32_t count;
|
||||
} rdguid;
|
||||
} u;
|
||||
|
|
@ -2429,7 +2429,7 @@ static uint32_t dqueue_thread (struct nn_dqueue *q)
|
|||
struct q_globals const * const gv = ddsrt_atomic_ldvoidp (&ts1->gv);
|
||||
nn_mtime_t next_thread_cputime = { 0 };
|
||||
int keepgoing = 1;
|
||||
nn_guid_t rdguid, *prdguid = NULL;
|
||||
ddsi_guid_t rdguid, *prdguid = NULL;
|
||||
uint32_t rdguid_count = 0;
|
||||
|
||||
ddsrt_mutex_lock (&q->lock);
|
||||
|
|
@ -2631,7 +2631,7 @@ void nn_dqueue_enqueue_callback (struct nn_dqueue *q, nn_dqueue_callback_t cb, v
|
|||
nn_dqueue_enqueue_bubble (q, b);
|
||||
}
|
||||
|
||||
void nn_dqueue_enqueue1 (struct nn_dqueue *q, const nn_guid_t *rdguid, struct nn_rsample_chain *sc, nn_reorder_result_t rres)
|
||||
void nn_dqueue_enqueue1 (struct nn_dqueue *q, const ddsi_guid_t *rdguid, struct nn_rsample_chain *sc, nn_reorder_result_t rres)
|
||||
{
|
||||
struct nn_dqueue_bubble *b;
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
#include "dds/ddsi/q_entity.h"
|
||||
#include "dds/ddsi/q_xmsg.h"
|
||||
#include "dds/ddsi/q_receive.h"
|
||||
#include "dds/ddsi/q_rhc.h"
|
||||
#include "dds/ddsi/ddsi_rhc.h"
|
||||
|
||||
#include "dds/ddsi/q_transmit.h"
|
||||
#include "dds/ddsi/q_globals.h"
|
||||
|
|
@ -74,7 +74,7 @@ Notes:
|
|||
|
||||
*/
|
||||
|
||||
static void deliver_user_data_synchronously (struct nn_rsample_chain *sc, const nn_guid_t *rdguid);
|
||||
static void deliver_user_data_synchronously (struct nn_rsample_chain *sc, const ddsi_guid_t *rdguid);
|
||||
|
||||
static void maybe_set_reader_in_sync (struct proxy_writer *pwr, struct pwr_rd_match *wn, seqno_t last_deliv_seq)
|
||||
{
|
||||
|
|
@ -285,7 +285,7 @@ static int valid_NackFrag (NackFrag_t *msg, size_t size, int byteswap)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void set_sampleinfo_proxy_writer (struct nn_rsample_info *sampleinfo, nn_guid_t *pwr_guid)
|
||||
static void set_sampleinfo_proxy_writer (struct nn_rsample_info *sampleinfo, ddsi_guid_t *pwr_guid)
|
||||
{
|
||||
struct proxy_writer * pwr = ephash_lookup_proxy_writer_guid (sampleinfo->rst->gv->guid_hash, pwr_guid);
|
||||
sampleinfo->pwr = pwr;
|
||||
|
|
@ -294,7 +294,7 @@ static void set_sampleinfo_proxy_writer (struct nn_rsample_info *sampleinfo, nn_
|
|||
static int valid_Data (const struct receiver_state *rst, struct nn_rmsg *rmsg, Data_t *msg, size_t size, int byteswap, struct nn_rsample_info *sampleinfo, unsigned char **payloadp)
|
||||
{
|
||||
/* on success: sampleinfo->{seq,rst,statusinfo,pt_wr_info_zoff,bswap,complex_qos} all set */
|
||||
nn_guid_t pwr_guid;
|
||||
ddsi_guid_t pwr_guid;
|
||||
unsigned char *ptr;
|
||||
|
||||
if (size < sizeof (*msg))
|
||||
|
|
@ -405,7 +405,7 @@ static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rms
|
|||
{
|
||||
/* on success: sampleinfo->{rst,statusinfo,pt_wr_info_zoff,bswap,complex_qos} all set */
|
||||
uint32_t payloadsz;
|
||||
nn_guid_t pwr_guid;
|
||||
ddsi_guid_t pwr_guid;
|
||||
unsigned char *ptr;
|
||||
|
||||
if (size < sizeof (*msg))
|
||||
|
|
@ -628,7 +628,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
|
|||
struct proxy_reader *prd;
|
||||
struct wr_prd_match *rn;
|
||||
struct writer *wr;
|
||||
nn_guid_t src, dst;
|
||||
ddsi_guid_t src, dst;
|
||||
seqno_t seqbase;
|
||||
seqno_t seq_xmit;
|
||||
nn_count_t *countp;
|
||||
|
|
@ -991,7 +991,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void handle_forall_destinations (const nn_guid_t *dst, struct proxy_writer *pwr, ddsrt_avl_walk_t fun, void *arg)
|
||||
static void handle_forall_destinations (const ddsi_guid_t *dst, struct proxy_writer *pwr, ddsrt_avl_walk_t fun, void *arg)
|
||||
{
|
||||
/* prefix: id: to:
|
||||
0 0 all matched readers
|
||||
|
|
@ -1023,7 +1023,7 @@ static void handle_forall_destinations (const nn_guid_t *dst, struct proxy_write
|
|||
break;
|
||||
case (1 << 1) | 0: /* all within one participant: walk a range of keyvalues */
|
||||
{
|
||||
nn_guid_t a, b;
|
||||
ddsi_guid_t a, b;
|
||||
a = *dst; a.entityid.u = 0;
|
||||
b = *dst; b.entityid.u = ~0u;
|
||||
ddsrt_avl_walk_range (&pwr_readers_treedef, &pwr->readers, &a, &b, fun, arg);
|
||||
|
|
@ -1071,7 +1071,7 @@ static void handle_Heartbeat_helper (struct pwr_rd_match * const wn, struct hand
|
|||
refseq = nn_reorder_next_seq (pwr->reorder) - 1;
|
||||
else
|
||||
refseq = nn_reorder_next_seq (wn->u.not_in_sync.reorder) - 1;
|
||||
RSTTRACE (" "PGUIDFMT"@%"PRId64"%s", PGUID (wn->rd_guid), refseq, (wn->in_sync == PRMSS_SYNC) ? "(sync)" : (wn->in_sync == PRMSS_TLCATCHUP) ? "(tlcatchup)" : "");
|
||||
RSTTRACE (" "PGUIDFMT"@%"PRId64"%s", PGUID (wn->rd_guid), refseq, (wn->in_sync == PRMSS_SYNC) ? "(sync)" : (wn->in_sync == PRMSS_TLCATCHUP) ? "(tlcatchup)" : "");
|
||||
|
||||
/* Reschedule AckNack transmit if deemed appropriate; unreliable
|
||||
readers have acknack_xevent == NULL and can't do this.
|
||||
|
|
@ -1124,7 +1124,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct
|
|||
const seqno_t lastseq = fromSN (msg->lastSN);
|
||||
struct handle_Heartbeat_helper_arg arg;
|
||||
struct proxy_writer *pwr;
|
||||
nn_guid_t src, dst;
|
||||
ddsi_guid_t src, dst;
|
||||
|
||||
src.prefix = rst->src_guid_prefix;
|
||||
src.entityid = msg->writerId;
|
||||
|
|
@ -1261,7 +1261,7 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime
|
|||
{
|
||||
const seqno_t seq = fromSN (msg->writerSN);
|
||||
const nn_fragment_number_t fragnum = msg->lastFragmentNum - 1; /* we do 0-based */
|
||||
nn_guid_t src, dst;
|
||||
ddsi_guid_t src, dst;
|
||||
struct proxy_writer *pwr;
|
||||
|
||||
src.prefix = rst->src_guid_prefix;
|
||||
|
|
@ -1374,7 +1374,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N
|
|||
struct wr_prd_match *rn;
|
||||
struct writer *wr;
|
||||
struct whc_borrowed_sample sample;
|
||||
nn_guid_t src, dst;
|
||||
ddsi_guid_t src, dst;
|
||||
nn_count_t *countp;
|
||||
seqno_t seq = fromSN (msg->writerSN);
|
||||
|
||||
|
|
@ -1490,7 +1490,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int handle_InfoDST (struct receiver_state *rst, const InfoDST_t *msg, const nn_guid_prefix_t *dst_prefix)
|
||||
static int handle_InfoDST (struct receiver_state *rst, const InfoDST_t *msg, const ddsi_guid_prefix_t *dst_prefix)
|
||||
{
|
||||
rst->dst_guid_prefix = nn_ntoh_guid_prefix (msg->guid_prefix);
|
||||
RSTTRACE ("INFODST(%"PRIx32":%"PRIx32":%"PRIx32")", PGUIDPREFIX (rst->dst_guid_prefix));
|
||||
|
|
@ -1502,7 +1502,7 @@ static int handle_InfoDST (struct receiver_state *rst, const InfoDST_t *msg, con
|
|||
}
|
||||
else
|
||||
{
|
||||
nn_guid_t dst;
|
||||
ddsi_guid_t dst;
|
||||
dst.prefix = rst->dst_guid_prefix;
|
||||
dst.entityid = to_entityid(NN_ENTITYID_PARTICIPANT);
|
||||
rst->forme = (ephash_lookup_participant_guid (rst->gv->guid_hash, &dst) != NULL ||
|
||||
|
|
@ -1623,7 +1623,7 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm
|
|||
|
||||
struct proxy_writer *pwr;
|
||||
struct pwr_rd_match *wn;
|
||||
nn_guid_t src, dst;
|
||||
ddsi_guid_t src, dst;
|
||||
seqno_t gapstart, listbase;
|
||||
int32_t last_included_rel;
|
||||
uint32_t listidx;
|
||||
|
|
@ -1739,16 +1739,10 @@ static struct ddsi_serdata *get_serdata (struct ddsi_sertopic const * const topi
|
|||
return sd;
|
||||
}
|
||||
|
||||
static struct ddsi_serdata *extract_sample_from_data
|
||||
(
|
||||
const struct nn_rsample_info *sampleinfo, unsigned char data_smhdr_flags,
|
||||
const nn_plist_t *qos, const struct nn_rdata *fragchain, unsigned statusinfo,
|
||||
nn_wctime_t tstamp, struct ddsi_sertopic const * const topic
|
||||
)
|
||||
static struct ddsi_serdata *new_sample_from_data (struct ddsi_tkmap_instance **tk1, struct q_globals *gv, const struct nn_rsample_info *sampleinfo, unsigned char data_smhdr_flags, const nn_plist_t *qos, const struct nn_rdata *fragchain, unsigned statusinfo, nn_wctime_t tstamp, struct ddsi_sertopic const * const topic)
|
||||
{
|
||||
static const nn_guid_t null_guid = {{{0,0,0,0,0,0,0,0,0,0,0,0}},{0}};
|
||||
const char *failmsg = NULL;
|
||||
struct ddsi_serdata * sample = NULL;
|
||||
struct ddsi_serdata *sample = NULL;
|
||||
|
||||
if (statusinfo == 0)
|
||||
{
|
||||
|
|
@ -1756,8 +1750,11 @@ static struct ddsi_serdata *extract_sample_from_data
|
|||
if (!(data_smhdr_flags & DATA_FLAG_DATAFLAG) || sampleinfo->size == 0)
|
||||
{
|
||||
const struct proxy_writer *pwr = sampleinfo->pwr;
|
||||
nn_guid_t guid = pwr ? pwr->e.guid : null_guid; /* can't be null _yet_, but that might change some day */
|
||||
DDS_CTRACE (&sampleinfo->rst->gv->logconfig,
|
||||
ddsi_guid_t guid;
|
||||
/* pwr can't currently be null, but that might change some day, and this being
|
||||
an error path, it doesn't hurt to survive that */
|
||||
if (pwr) guid = pwr->e.guid; else memset (&guid, 0, sizeof (guid));
|
||||
DDS_CTRACE (&gv->logconfig,
|
||||
"data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": write without proper payload (data_smhdr_flags 0x%x size %"PRIu32")\n",
|
||||
sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
|
||||
PGUID (guid), sampleinfo->seq,
|
||||
|
|
@ -1785,7 +1782,7 @@ static struct ddsi_serdata *extract_sample_from_data
|
|||
{
|
||||
/* RTI always tries to make us survive on the keyhash. RTI must
|
||||
mend its ways. */
|
||||
if (NN_STRICT_P (sampleinfo->rst->gv->config))
|
||||
if (NN_STRICT_P (gv->config))
|
||||
failmsg = "no content";
|
||||
else if (!(qos->present & PP_KEYHASH))
|
||||
failmsg = "qos present but without keyhash";
|
||||
|
|
@ -1805,17 +1802,47 @@ static struct ddsi_serdata *extract_sample_from_data
|
|||
{
|
||||
/* No message => error out */
|
||||
const struct proxy_writer *pwr = sampleinfo->pwr;
|
||||
nn_guid_t guid = pwr ? pwr->e.guid : null_guid; /* can't be null _yet_, but that might change some day */
|
||||
DDS_CWARNING (&sampleinfo->rst->gv->logconfig,
|
||||
ddsi_guid_t guid;
|
||||
if (pwr) guid = pwr->e.guid; else memset (&guid, 0, sizeof (guid));
|
||||
DDS_CWARNING (&gv->logconfig,
|
||||
"data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": deserialization %s/%s failed (%s)\n",
|
||||
sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
|
||||
PGUID (guid), sampleinfo->seq,
|
||||
topic->name, topic->type_name,
|
||||
failmsg ? failmsg : "for reasons unknown");
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*tk1 = ddsi_tkmap_lookup_instance_ref (gv->m_tkmap, sample)) == NULL)
|
||||
{
|
||||
ddsi_serdata_unref (sample);
|
||||
sample = NULL;
|
||||
}
|
||||
else if (gv->logconfig.c.mask & DDS_LC_TRACE)
|
||||
{
|
||||
const struct proxy_writer *pwr = sampleinfo->pwr;
|
||||
ddsi_guid_t guid;
|
||||
char tmp[1024];
|
||||
size_t res = 0;
|
||||
tmp[0] = 0;
|
||||
if (gv->logconfig.c.mask & DDS_LC_CONTENT)
|
||||
res = ddsi_serdata_print (sample, tmp, sizeof (tmp));
|
||||
if (pwr) guid = pwr->e.guid; else memset (&guid, 0, sizeof (guid));
|
||||
GVTRACE ("data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": ST%x %s/%s:%s%s",
|
||||
sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
|
||||
PGUID (guid), sampleinfo->seq, statusinfo, topic->name, topic->type_name,
|
||||
tmp, res < sizeof (tmp) ? "" : "(trunc)");
|
||||
}
|
||||
}
|
||||
return sample;
|
||||
}
|
||||
|
||||
static void free_sample_after_store (struct q_globals *gv, struct ddsi_serdata *sample, struct ddsi_tkmap_instance *tk)
|
||||
{
|
||||
ddsi_tkmap_instance_unref (gv->m_tkmap, tk);
|
||||
ddsi_serdata_unref (sample);
|
||||
}
|
||||
|
||||
unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr)
|
||||
{
|
||||
switch ((SubmessageKind_t) smhdr->submessageId)
|
||||
|
|
@ -1837,17 +1864,36 @@ unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr)
|
|||
}
|
||||
}
|
||||
|
||||
static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const nn_guid_t *rdguid, int pwr_locked)
|
||||
static struct reader *proxy_writer_first_in_sync_reader (struct proxy_writer *pwr, ddsrt_avl_iter_t *it)
|
||||
{
|
||||
struct pwr_rd_match *m;
|
||||
struct reader *rd;
|
||||
for (m = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, it); m != NULL; m = ddsrt_avl_iter_next (it))
|
||||
if (m->in_sync == PRMSS_SYNC && (rd = ephash_lookup_reader_guid (pwr->e.gv->guid_hash, &m->rd_guid)) != NULL)
|
||||
return rd;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct reader *proxy_writer_next_in_sync_reader (struct proxy_writer *pwr, ddsrt_avl_iter_t *it)
|
||||
{
|
||||
struct pwr_rd_match *m;
|
||||
struct reader *rd;
|
||||
for (m = ddsrt_avl_iter_next (it); m != NULL; m = ddsrt_avl_iter_next (it))
|
||||
if (m->in_sync == PRMSS_SYNC && (rd = ephash_lookup_reader_guid (pwr->e.gv->guid_hash, &m->rd_guid)) != NULL)
|
||||
return rd;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const ddsi_guid_t *rdguid, int pwr_locked)
|
||||
{
|
||||
struct receiver_state const * const rst = sampleinfo->rst;
|
||||
struct q_globals * const gv = rst->gv;
|
||||
struct proxy_writer * const pwr = sampleinfo->pwr;
|
||||
struct ddsi_sertopic const * const topic = pwr->c.topic;
|
||||
unsigned statusinfo;
|
||||
Data_DataFrag_common_t *msg;
|
||||
unsigned char data_smhdr_flags;
|
||||
nn_plist_t qos;
|
||||
int need_keyhash;
|
||||
struct ddsi_serdata * payload;
|
||||
|
||||
if (pwr->ddsi2direct_cb)
|
||||
{
|
||||
|
|
@ -1855,22 +1901,11 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* NOTE: pwr->e.lock need not be held for correct processing (though
|
||||
it may be useful to hold it for maintaining order all the way to
|
||||
v_groupWrite): guid is constant, set_vmsg_header() explains about
|
||||
the qos issue (and will have to deal with that); and
|
||||
pwr->groupset takes care of itself. FIXME: groupset may be
|
||||
taking care of itself, but it is currently doing so in an
|
||||
annoyingly simplistic manner ... */
|
||||
|
||||
/* FIXME: fragments are now handled by copying the message to
|
||||
freshly malloced memory (see defragment()) ... that'll have to
|
||||
change eventually */
|
||||
assert (fragchain->min == 0);
|
||||
assert (!is_builtin_entityid (pwr->e.guid.entityid, pwr->c.vendor));
|
||||
/* Can only get here if at some point readers existed => topic can't
|
||||
still be NULL, even if there are no readers at the moment */
|
||||
assert (topic != NULL);
|
||||
|
||||
/* Luckily, the Data header (up to inline QoS) is a prefix of the
|
||||
DataFrag header, so for the fixed-position things that we're
|
||||
|
|
@ -1906,81 +1941,65 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st
|
|||
src.encoding = (msg->smhdr.flags & SMFLAG_ENDIANNESS) ? PL_CDR_LE : PL_CDR_BE;
|
||||
src.buf = NN_RMSG_PAYLOADOFF (fragchain->rmsg, qos_offset);
|
||||
src.bufsz = NN_RDATA_PAYLOAD_OFF (fragchain) - qos_offset;
|
||||
src.strict = NN_STRICT_P (rst->gv->config);
|
||||
src.factory = rst->gv->m_factory;
|
||||
src.logconfig = &rst->gv->logconfig;
|
||||
src.strict = NN_STRICT_P (gv->config);
|
||||
src.factory = gv->m_factory;
|
||||
src.logconfig = &gv->logconfig;
|
||||
if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH | PP_COHERENT_SET, 0, &src)) < 0)
|
||||
{
|
||||
if (plist_ret != DDS_RETCODE_UNSUPPORTED)
|
||||
DDS_CWARNING (&sampleinfo->rst->gv->logconfig,
|
||||
"data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n",
|
||||
src.vendorid.id[0], src.vendorid.id[1], PGUID (pwr->e.guid), sampleinfo->seq);
|
||||
GVWARNING ("data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n",
|
||||
src.vendorid.id[0], src.vendorid.id[1], PGUID (pwr->e.guid), sampleinfo->seq);
|
||||
return 0;
|
||||
}
|
||||
statusinfo = (qos.present & PP_STATUSINFO) ? qos.statusinfo : 0;
|
||||
}
|
||||
|
||||
/* Note: deserializing done potentially many times for a historical
|
||||
data sample (once per reader that cares about that data). For
|
||||
now, this is accepted as sufficiently abnormal behaviour to not
|
||||
worry about it. */
|
||||
{
|
||||
nn_wctime_t tstamp;
|
||||
if (sampleinfo->timestamp.v != NN_WCTIME_INVALID.v)
|
||||
tstamp = sampleinfo->timestamp;
|
||||
else
|
||||
tstamp.v = 0;
|
||||
payload = extract_sample_from_data (sampleinfo, data_smhdr_flags, &qos, fragchain, statusinfo, tstamp, topic);
|
||||
}
|
||||
if (payload == NULL)
|
||||
{
|
||||
goto no_payload;
|
||||
}
|
||||
/* FIXME: should it be 0, local wall clock time or INVALID? */
|
||||
const nn_wctime_t tstamp = (sampleinfo->timestamp.v != NN_WCTIME_INVALID.v) ? sampleinfo->timestamp : ((nn_wctime_t) {0});
|
||||
struct ddsi_writer_info wrinfo;
|
||||
ddsi_make_writer_info (&wrinfo, &pwr->e, pwr->c.xqos);
|
||||
|
||||
/* Generate the DDS_SampleInfo (which is faked to some extent
|
||||
because we don't actually have a data reader) */
|
||||
struct ddsi_tkmap_instance *tk;
|
||||
if ((tk = ddsi_tkmap_lookup_instance_ref (pwr->e.gv->m_tkmap, payload)) != NULL)
|
||||
if (rdguid == NULL)
|
||||
{
|
||||
struct proxy_writer_info pwr_info;
|
||||
make_proxy_writer_info (&pwr_info, &pwr->e, pwr->c.xqos);
|
||||
|
||||
if (rdguid == NULL)
|
||||
/* FIXME: Retry loop, for re-delivery of rejected reliable samples. Is a
|
||||
temporary hack till throttling back of writer is implemented (with late
|
||||
acknowledgement of sample and nack). */
|
||||
retry:
|
||||
ddsrt_mutex_lock (&pwr->rdary.rdary_lock);
|
||||
if (pwr->rdary.fastpath_ok)
|
||||
{
|
||||
ETRACE (pwr, " %"PRId64"=>EVERYONE\n", sampleinfo->seq);
|
||||
|
||||
/* FIXME: pwr->rdary is an array of pointers to attached
|
||||
readers. There's only one thread delivering data for the
|
||||
proxy writer (as long as there is only one receive thread),
|
||||
so could get away with not locking at all, and doing safe
|
||||
updates + GC of rdary instead. */
|
||||
|
||||
/* Retry loop, for re-delivery of rejected reliable samples. Is a
|
||||
temporary hack till throttling back of writer is implemented
|
||||
(with late acknowledgement of sample and nack). */
|
||||
retry:
|
||||
|
||||
ddsrt_mutex_lock (&pwr->rdary.rdary_lock);
|
||||
if (pwr->rdary.fastpath_ok)
|
||||
struct reader ** const rdary = pwr->rdary.rdary;
|
||||
if (rdary[0])
|
||||
{
|
||||
struct reader ** const rdary = pwr->rdary.rdary;
|
||||
for (uint32_t i = 0; rdary[i]; i++)
|
||||
struct ddsi_serdata *payload;
|
||||
struct ddsi_tkmap_instance *tk;
|
||||
if ((payload = new_sample_from_data (&tk, gv, sampleinfo, data_smhdr_flags, &qos, fragchain, statusinfo, tstamp, rdary[0]->topic)) != NULL)
|
||||
{
|
||||
ETRACE (pwr, "reader "PGUIDFMT"\n", PGUID (rdary[i]->e.guid));
|
||||
if (!rhc_store (rdary[i]->rhc, &pwr_info, payload, tk))
|
||||
{
|
||||
if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
ddsrt_mutex_unlock (&pwr->rdary.rdary_lock);
|
||||
dds_sleepfor (DDS_MSECS (10));
|
||||
if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock);
|
||||
goto retry;
|
||||
}
|
||||
ETRACE (pwr, " => EVERYONE\n");
|
||||
uint32_t i = 0;
|
||||
do {
|
||||
if (!ddsi_rhc_store (rdary[i]->rhc, &wrinfo, payload, tk))
|
||||
{
|
||||
if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
ddsrt_mutex_unlock (&pwr->rdary.rdary_lock);
|
||||
/* It is painful to drop the sample, but there is no guarantee that the readers
|
||||
will still be there after unlocking; indeed, it is even possible that the
|
||||
topic definition got replaced in the meantime. Fortunately, this is in
|
||||
the midst of a FIXME for many other reasons. */
|
||||
free_sample_after_store (gv, payload, tk);
|
||||
dds_sleepfor (DDS_MSECS (10));
|
||||
if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock);
|
||||
goto retry;
|
||||
}
|
||||
} while (rdary[++i]);
|
||||
free_sample_after_store (gv, payload, tk);
|
||||
}
|
||||
ddsrt_mutex_unlock (&pwr->rdary.rdary_lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* When deleting, pwr is no longer accessible via the hash
|
||||
ddsrt_mutex_unlock (&pwr->rdary.rdary_lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* When deleting, pwr is no longer accessible via the hash
|
||||
tables, and consequently, a reader may be deleted without
|
||||
it being possible to remove it from rdary. The primary
|
||||
reason rdary exists is to avoid locking the proxy writer
|
||||
|
|
@ -1988,51 +2007,72 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st
|
|||
we fall back to using the GUIDs so that we can deliver all
|
||||
samples we received from it. As writer being deleted any
|
||||
reliable samples that are rejected are simply discarded. */
|
||||
ddsrt_avl_iter_t it;
|
||||
struct pwr_rd_match *m;
|
||||
ddsrt_mutex_unlock (&pwr->rdary.rdary_lock);
|
||||
if (!pwr_locked) ddsrt_mutex_lock (&pwr->e.lock);
|
||||
for (m = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); m != NULL; m = ddsrt_avl_iter_next (&it))
|
||||
ddsrt_avl_iter_t it;
|
||||
struct reader *rd;
|
||||
ddsrt_mutex_unlock (&pwr->rdary.rdary_lock);
|
||||
if (!pwr_locked) ddsrt_mutex_lock (&pwr->e.lock);
|
||||
if ((rd = proxy_writer_first_in_sync_reader (pwr, &it)) != NULL)
|
||||
{
|
||||
struct ddsi_serdata *payload;
|
||||
struct ddsi_tkmap_instance *tk;
|
||||
if ((payload = new_sample_from_data (&tk, gv, sampleinfo, data_smhdr_flags, &qos, fragchain, statusinfo, tstamp, rd->topic)) != NULL)
|
||||
{
|
||||
struct reader *rd;
|
||||
if ((rd = ephash_lookup_reader_guid (pwr->e.gv->guid_hash, &m->rd_guid)) != NULL && m->in_sync == PRMSS_SYNC)
|
||||
ETRACE (pwr, " =>");
|
||||
do {
|
||||
ETRACE (pwr, " "PGUIDFMT, PGUID (rd->e.guid));
|
||||
(void) ddsi_rhc_store (rd->rhc, &wrinfo, payload, tk);
|
||||
rd = proxy_writer_next_in_sync_reader (pwr, &it);
|
||||
} while (rd != NULL);
|
||||
free_sample_after_store (gv, payload, tk);
|
||||
ETRACE (pwr, "\n");
|
||||
}
|
||||
}
|
||||
if (!pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
}
|
||||
|
||||
ddsrt_atomic_st32 (&pwr->next_deliv_seq_lowword, (uint32_t) (sampleinfo->seq + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
struct reader *rd = ephash_lookup_reader_guid (gv->guid_hash, rdguid);
|
||||
if (rd != NULL)
|
||||
{
|
||||
struct ddsi_serdata *payload;
|
||||
struct ddsi_tkmap_instance *tk;
|
||||
if ((payload = new_sample_from_data (&tk, gv, sampleinfo, data_smhdr_flags, &qos, fragchain, statusinfo, tstamp, rd->topic)) != NULL)
|
||||
{
|
||||
ETRACE (pwr, " =>"PGUIDFMT"\n", PGUID (*rdguid));
|
||||
/* FIXME: why look up rd,pwr again? Their states remains valid while the thread stays
|
||||
"awake" (although a delete can be initiated), and blocking like this is a stopgap
|
||||
anyway -- quite possibly to abort once either is deleted */
|
||||
while (!ddsi_rhc_store (rd->rhc, &wrinfo, payload, tk))
|
||||
{
|
||||
if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
dds_sleepfor (DDS_MSECS (1));
|
||||
if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock);
|
||||
if (ephash_lookup_reader_guid (gv->guid_hash, rdguid) == NULL ||
|
||||
ephash_lookup_proxy_writer_guid (gv->guid_hash, &pwr->e.guid) == NULL)
|
||||
{
|
||||
ETRACE (pwr, "reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid));
|
||||
(void) rhc_store (rd->rhc, &pwr_info, payload, tk);
|
||||
/* give up when reader or proxy writer no longer accessible */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
}
|
||||
|
||||
ddsrt_atomic_st32 (&pwr->next_deliv_seq_lowword, (uint32_t) (sampleinfo->seq + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
struct reader *rd = ephash_lookup_reader_guid (pwr->e.gv->guid_hash, rdguid);
|
||||
ETRACE (pwr, " %"PRId64"=>"PGUIDFMT"%s\n", sampleinfo->seq, PGUID (*rdguid), rd ? "" : "?");
|
||||
while (rd && ! rhc_store (rd->rhc, &pwr_info, payload, tk) && ephash_lookup_proxy_writer_guid (pwr->e.gv->guid_hash, &pwr->e.guid))
|
||||
{
|
||||
if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
dds_sleepfor (DDS_MSECS (1));
|
||||
if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock);
|
||||
free_sample_after_store (gv, payload, tk);
|
||||
}
|
||||
}
|
||||
ddsi_tkmap_instance_unref (pwr->e.gv->m_tkmap, tk);
|
||||
}
|
||||
ddsi_serdata_unref (payload);
|
||||
no_payload:
|
||||
nn_plist_fini (&qos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const nn_guid_t *rdguid, UNUSED_ARG (void *qarg))
|
||||
int user_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const ddsi_guid_t *rdguid, UNUSED_ARG (void *qarg))
|
||||
{
|
||||
int res;
|
||||
res = deliver_user_data (sampleinfo, fragchain, rdguid, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void deliver_user_data_synchronously (struct nn_rsample_chain *sc, const nn_guid_t *rdguid)
|
||||
static void deliver_user_data_synchronously (struct nn_rsample_chain *sc, const ddsi_guid_t *rdguid)
|
||||
{
|
||||
while (sc->first)
|
||||
{
|
||||
|
|
@ -2073,7 +2113,7 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct
|
|||
{
|
||||
struct proxy_writer *pwr;
|
||||
struct nn_rsample *rsample;
|
||||
nn_guid_t dst;
|
||||
ddsi_guid_t dst;
|
||||
|
||||
dst.prefix = rst->dst_guid_prefix;
|
||||
dst.entityid = msg->readerId;
|
||||
|
|
@ -2081,7 +2121,7 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct
|
|||
pwr = sampleinfo->pwr;
|
||||
if (pwr == NULL)
|
||||
{
|
||||
nn_guid_t src;
|
||||
ddsi_guid_t src;
|
||||
src.prefix = rst->src_guid_prefix;
|
||||
src.entityid = msg->writerId;
|
||||
RSTTRACE (" "PGUIDFMT"? -> "PGUIDFMT, PGUID (src), PGUID (dst));
|
||||
|
|
@ -2293,7 +2333,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con
|
|||
effect seems a reasonable approach. */
|
||||
int refc_adjust = 0;
|
||||
struct nn_rdata *gap = nn_rdata_newgap (rmsg);
|
||||
nn_guid_t dst;
|
||||
ddsi_guid_t dst;
|
||||
struct pwr_rd_match *wn;
|
||||
int gap_was_valuable;
|
||||
|
||||
|
|
@ -2308,8 +2348,8 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con
|
|||
|
||||
if (gap_was_valuable)
|
||||
{
|
||||
const char *tname = pwr->c.topic ? pwr->c.topic->name : "(null)";
|
||||
const char *ttname = pwr->c.topic ? pwr->c.topic->type_name : "(null)";
|
||||
const char *tname = (pwr->c.xqos->present & QP_TOPIC_NAME) ? pwr->c.xqos->topic_name : "(null)";
|
||||
const char *ttname = (pwr->c.xqos->present & QP_TYPE_NAME) ? pwr->c.xqos->type_name : "(null)";
|
||||
DDS_CWARNING (&rst->gv->logconfig, "dropping oversize (%"PRIu32" > %"PRIu32") sample %"PRId64" from remote writer "PGUIDFMT" %s/%s\n",
|
||||
sampleinfo->size, rst->gv->config.max_sample_size, sampleinfo->seq,
|
||||
PGUIDPREFIX (rst->src_guid_prefix), msg->writerId.u,
|
||||
|
|
@ -2397,7 +2437,7 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct
|
|||
payload_offset = submsg_offset + (unsigned) size;
|
||||
|
||||
begin = (msg->fragmentStartingNum - 1) * msg->fragmentSize;
|
||||
if (msg->fragmentSize * msg->fragmentsInSubmessage > ((unsigned char *) msg + size - datap)) {
|
||||
if ((uint32_t) msg->fragmentSize * msg->fragmentsInSubmessage > (uint32_t) ((unsigned char *) msg + size - datap)) {
|
||||
/* this happens for the last fragment (which usually is short) --
|
||||
and is included here merely as a sanity check, because that
|
||||
would mean the computed endp1'd be larger than the sample
|
||||
|
|
@ -2587,8 +2627,8 @@ static int handle_submsg_sequence
|
|||
const nn_locator_t *srcloc,
|
||||
nn_wctime_t tnowWC,
|
||||
nn_etime_t tnowE,
|
||||
const nn_guid_prefix_t * const src_prefix,
|
||||
const nn_guid_prefix_t * const dst_prefix,
|
||||
const ddsi_guid_prefix_t * const src_prefix,
|
||||
const ddsi_guid_prefix_t * const dst_prefix,
|
||||
unsigned char * const msg /* NOT const - we may byteswap it */,
|
||||
const size_t len,
|
||||
unsigned char * submsg /* aliases somewhere in msg */,
|
||||
|
|
@ -2897,7 +2937,7 @@ malformed_asleep:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static bool do_packet (struct thread_state1 * const ts1, struct q_globals *gv, ddsi_tran_conn_t conn, const nn_guid_prefix_t *guidprefix, struct nn_rbufpool *rbpool)
|
||||
static bool do_packet (struct thread_state1 * const ts1, struct q_globals *gv, ddsi_tran_conn_t conn, const ddsi_guid_prefix_t *guidprefix, struct nn_rbufpool *rbpool)
|
||||
{
|
||||
/* UDP max packet size is 64kB */
|
||||
|
||||
|
|
@ -3017,7 +3057,7 @@ static bool do_packet (struct thread_state1 * const ts1, struct q_globals *gv, d
|
|||
struct local_participant_desc
|
||||
{
|
||||
ddsi_tran_conn_t m_conn;
|
||||
nn_guid_prefix_t guid_prefix;
|
||||
ddsi_guid_prefix_t guid_prefix;
|
||||
};
|
||||
|
||||
static int local_participant_cmp (const void *va, const void *vb)
|
||||
|
|
@ -3369,7 +3409,7 @@ uint32_t recv_thread (void *vrecv_thread_arg)
|
|||
ddsi_tran_conn_t conn;
|
||||
while ((idx = os_sockWaitsetNextEvent (ctx, &conn)) >= 0)
|
||||
{
|
||||
const nn_guid_prefix_t *guid_prefix;
|
||||
const ddsi_guid_prefix_t *guid_prefix;
|
||||
if (((unsigned)idx < num_fixed) || gv->config.many_sockets_mode != MSM_MANY_UNICAST)
|
||||
guid_prefix = NULL;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "dds/ddsi/q_rhc.h"
|
||||
#include "dds/ddsi/q_xqos.h"
|
||||
#include "dds/ddsi/q_entity.h"
|
||||
|
||||
extern inline void rhc_free (struct rhc *rhc);
|
||||
extern inline bool rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk);
|
||||
extern inline void rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info);
|
||||
extern inline void rhc_relinquish_ownership (struct rhc * __restrict rhc, const uint64_t wr_iid);
|
||||
extern inline void rhc_set_qos (struct rhc *rhc, const struct dds_qos *qos);
|
||||
|
||||
void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct dds_qos *xqos)
|
||||
{
|
||||
pwr_info->guid = e->guid;
|
||||
pwr_info->ownership_strength = xqos->ownership_strength.value;
|
||||
pwr_info->auto_dispose = xqos->writer_data_lifecycle.autodispose_unregistered_instances;
|
||||
pwr_info->iid = e->iid;
|
||||
}
|
||||
|
|
@ -618,12 +618,23 @@ static void os_sockWaitsetNewSet (os_sockWaitsetSet * set)
|
|||
set->n = 1;
|
||||
}
|
||||
|
||||
static void os_sockWaitsetFreeSet (os_sockWaitsetSet * set)
|
||||
{
|
||||
ddsrt_free (set->fds);
|
||||
ddsrt_free (set->conns);
|
||||
}
|
||||
|
||||
static void os_sockWaitsetNewCtx (os_sockWaitsetCtx ctx)
|
||||
{
|
||||
os_sockWaitsetNewSet (&ctx->set);
|
||||
FD_ZERO (&ctx->rdset);
|
||||
}
|
||||
|
||||
static void os_sockWaitsetFreeCtx (os_sockWaitsetCtx ctx)
|
||||
{
|
||||
os_sockWaitsetFreeSet (&ctx->set);
|
||||
}
|
||||
|
||||
os_sockWaitset os_sockWaitsetNew (void)
|
||||
{
|
||||
int result;
|
||||
|
|
@ -642,40 +653,16 @@ os_sockWaitset os_sockWaitsetNew (void)
|
|||
ws->pipe[0] = -1;
|
||||
ws->pipe[1] = -1;
|
||||
result = 0;
|
||||
#elif defined(__VXWORKS__)
|
||||
int make_pipe (int pfd[2])
|
||||
{
|
||||
char pipename[OSPL_PIPENAMESIZE];
|
||||
int pipecount=0;
|
||||
do
|
||||
{
|
||||
snprintf ((char*)&pipename, sizeof(pipename), "/pipe/ospl%d", pipecount++ );
|
||||
}
|
||||
while ((result = pipeDevCreate ((char*) &pipename, 1, 1)) == -1 && os_getErrno() == EINVAL);
|
||||
if (result != -1)
|
||||
{
|
||||
result = open ((char*) &pipename, O_RDWR, 0644);
|
||||
if (result != -1)
|
||||
{
|
||||
ws->pipe[0] = result;
|
||||
result = open ((char*) &pipename, O_RDWR, 0644);
|
||||
if (result != -1)
|
||||
{
|
||||
ws->pipe[1] = result;
|
||||
}
|
||||
else
|
||||
{
|
||||
close (ws->pipe[0]);
|
||||
pipeDevDelete (pipename, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
result = make_pipe (ws->pipe);
|
||||
#endif
|
||||
assert (result != -1);
|
||||
(void) result;
|
||||
if (result == -1)
|
||||
{
|
||||
os_sockWaitsetFreeCtx (&ws->ctx);
|
||||
os_sockWaitsetFreeSet (&ws->set);
|
||||
ddsrt_free (ws);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if !defined(LWIP_SOCKET)
|
||||
ws->set.fds[0] = ws->pipe[0];
|
||||
|
|
@ -685,8 +672,8 @@ os_sockWaitset os_sockWaitsetNew (void)
|
|||
ws->set.conns[0] = NULL;
|
||||
|
||||
#if !defined(__VXWORKS__) && !defined(_WIN32) && !defined(LWIP_SOCKET)
|
||||
fcntl (ws->pipe[0], F_SETFD, fcntl (ws->pipe[0], F_GETFD) | FD_CLOEXEC);
|
||||
fcntl (ws->pipe[1], F_SETFD, fcntl (ws->pipe[1], F_GETFD) | FD_CLOEXEC);
|
||||
(void) fcntl (ws->pipe[0], F_SETFD, fcntl (ws->pipe[0], F_GETFD) | FD_CLOEXEC);
|
||||
(void) fcntl (ws->pipe[1], F_SETFD, fcntl (ws->pipe[1], F_GETFD) | FD_CLOEXEC);
|
||||
#endif
|
||||
#if !defined(LWIP_SOCKET)
|
||||
FD_SET (ws->set.fds[0], &ws->ctx.rdset);
|
||||
|
|
@ -707,17 +694,6 @@ static void os_sockWaitsetGrow (os_sockWaitsetSet * set)
|
|||
set->fds = ddsrt_realloc (set->fds, set->sz * sizeof (*set->fds));
|
||||
}
|
||||
|
||||
static void os_sockWaitsetFreeSet (os_sockWaitsetSet * set)
|
||||
{
|
||||
ddsrt_free (set->fds);
|
||||
ddsrt_free (set->conns);
|
||||
}
|
||||
|
||||
static void os_sockWaitsetFreeCtx (os_sockWaitsetCtx ctx)
|
||||
{
|
||||
os_sockWaitsetFreeSet (&ctx->set);
|
||||
}
|
||||
|
||||
void os_sockWaitsetFree (os_sockWaitset ws)
|
||||
{
|
||||
#if defined(__VXWORKS__) && defined(__RTP__)
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@
|
|||
#include "dds/ddsi/q_globals.h"
|
||||
#include "dds/ddsi/sysdeps.h"
|
||||
|
||||
static char main_thread_name[] = "main";
|
||||
|
||||
struct thread_states thread_states;
|
||||
ddsrt_thread_local struct thread_state1 *tsd_thread_state;
|
||||
|
||||
|
|
@ -47,6 +45,7 @@ extern inline void thread_state_awake_fixed_domain (struct thread_state1 *ts1);
|
|||
extern inline void thread_state_awake_to_awake_no_nest (struct thread_state1 *ts1);
|
||||
|
||||
static struct thread_state1 *init_thread_state (const char *tname, const struct q_globals *gv, enum thread_state state);
|
||||
static void reap_thread_state (struct thread_state1 *ts1);
|
||||
|
||||
static void *ddsrt_malloc_aligned_cacheline (size_t size)
|
||||
{
|
||||
|
|
@ -74,45 +73,74 @@ static void ddsrt_free_aligned (void *ptr)
|
|||
}
|
||||
}
|
||||
|
||||
void thread_states_init_static (void)
|
||||
{
|
||||
static struct thread_state1 ts = {
|
||||
.state = THREAD_STATE_ALIVE, .vtime = DDSRT_ATOMIC_UINT32_INIT (0), .name = "(anon)"
|
||||
};
|
||||
tsd_thread_state = &ts;
|
||||
}
|
||||
|
||||
void thread_states_init (unsigned maxthreads)
|
||||
{
|
||||
ddsrt_mutex_init (&thread_states.lock);
|
||||
thread_states.nthreads = maxthreads;
|
||||
thread_states.ts =
|
||||
ddsrt_malloc_aligned_cacheline (maxthreads * sizeof (*thread_states.ts));
|
||||
memset (thread_states.ts, 0, maxthreads * sizeof (*thread_states.ts));
|
||||
/* The compiler doesn't realize that ts is large enough. */
|
||||
DDSRT_WARNING_MSVC_OFF(6386);
|
||||
for (uint32_t i = 0; i < thread_states.nthreads; i++)
|
||||
/* Called with ddsrt's singleton mutex held (see dds_init/fini). Application threads
|
||||
remaining alive can result in thread_states remaining alive, and as those thread
|
||||
cache the address, we must then re-use the old array. */
|
||||
if (thread_states.ts == NULL)
|
||||
{
|
||||
thread_states.ts[i].state = THREAD_STATE_ZERO;
|
||||
ddsrt_atomic_st32 (&thread_states.ts[i].vtime, 0);
|
||||
memset (thread_states.ts[i].name, 0, sizeof (thread_states.ts[i].name));
|
||||
ddsrt_mutex_init (&thread_states.lock);
|
||||
thread_states.nthreads = maxthreads;
|
||||
thread_states.ts = ddsrt_malloc_aligned_cacheline (maxthreads * sizeof (*thread_states.ts));
|
||||
memset (thread_states.ts, 0, maxthreads * sizeof (*thread_states.ts));
|
||||
/* The compiler doesn't realize that ts is large enough. */
|
||||
DDSRT_WARNING_MSVC_OFF(6386);
|
||||
for (uint32_t i = 0; i < thread_states.nthreads; i++)
|
||||
{
|
||||
thread_states.ts[i].state = THREAD_STATE_ZERO;
|
||||
ddsrt_atomic_st32 (&thread_states.ts[i].vtime, 0);
|
||||
memset (thread_states.ts[i].name, 0, sizeof (thread_states.ts[i].name));
|
||||
}
|
||||
DDSRT_WARNING_MSVC_ON(6386);
|
||||
}
|
||||
DDSRT_WARNING_MSVC_ON(6386);
|
||||
|
||||
/* This thread should be at the same address as before, or never have had a slot
|
||||
in the past. Also, allocate a slot for this thread if it didn't have one yet
|
||||
(not strictly required, but it'll get one eventually anyway, and this makes
|
||||
it rather more clear). */
|
||||
#ifndef NDEBUG
|
||||
struct thread_state1 * const ts0 = tsd_thread_state;
|
||||
#endif
|
||||
struct thread_state1 * const ts1 = lookup_thread_state_real ();
|
||||
assert (ts0 == NULL || ts0 == ts1);
|
||||
(void) ts1;
|
||||
}
|
||||
|
||||
void thread_states_fini (void)
|
||||
bool thread_states_fini (void)
|
||||
{
|
||||
for (uint32_t i = 0; i < thread_states.nthreads; i++)
|
||||
assert (thread_states.ts[i].state != THREAD_STATE_ALIVE);
|
||||
ddsrt_mutex_destroy (&thread_states.lock);
|
||||
ddsrt_free_aligned (thread_states.ts);
|
||||
/* Calling thread is the one shutting everything down, so it certainly won't (well, shouldn't)
|
||||
need its slot anymore. Clean it up so that if all other threads happen to have been stopped
|
||||
already, we can release all resources. */
|
||||
struct thread_state1 *ts1 = lookup_thread_state ();
|
||||
assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts1->vtime)));
|
||||
reap_thread_state (ts1);
|
||||
tsd_thread_state = NULL;
|
||||
|
||||
/* All spawned threads are gone, but the main thread is still alive,
|
||||
downgraded to an ordinary thread (we're on it right now). We
|
||||
don't want to lose the ability to log messages, so set ts to a
|
||||
NULL pointer and rely on lookup_thread_state()'s checks
|
||||
thread_states.ts. */
|
||||
thread_states.ts = NULL;
|
||||
/* Some applications threads that, at some point, required a thread state, may still be around.
|
||||
Of those, the cleanup routine is invoked when the thread terminates. This should be rewritten
|
||||
to not rely on this global thing and with each thread owning its own bit state, e.g., linked
|
||||
together in a list to give the GC access to it. Until then, we can't release these resources
|
||||
if there are still users. */
|
||||
uint32_t others = 0;
|
||||
ddsrt_mutex_lock (&thread_states.lock);
|
||||
for (uint32_t i = 0; i < thread_states.nthreads; i++)
|
||||
{
|
||||
assert (thread_states.ts[i].state != THREAD_STATE_ALIVE);
|
||||
others += (thread_states.ts[i].state == THREAD_STATE_LAZILY_CREATED);
|
||||
}
|
||||
ddsrt_mutex_unlock (&thread_states.lock);
|
||||
if (others == 0)
|
||||
{
|
||||
ddsrt_mutex_destroy (&thread_states.lock);
|
||||
ddsrt_free_aligned (thread_states.ts);
|
||||
thread_states.ts = NULL;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
|
|
@ -121,7 +149,7 @@ static struct thread_state1 *find_thread_state (ddsrt_thread_t tid)
|
|||
if (thread_states.ts) {
|
||||
for (uint32_t i = 0; i < thread_states.nthreads; i++)
|
||||
{
|
||||
if (ddsrt_thread_equal (thread_states.ts[i].tid, tid))
|
||||
if (ddsrt_thread_equal (thread_states.ts[i].tid, tid) && thread_states.ts[i].state != THREAD_STATE_ZERO)
|
||||
return &thread_states.ts[i];
|
||||
}
|
||||
}
|
||||
|
|
@ -203,26 +231,6 @@ static int find_free_slot (const char *name)
|
|||
return -1;
|
||||
}
|
||||
|
||||
void upgrade_main_thread (void)
|
||||
{
|
||||
int cand;
|
||||
struct thread_state1 *ts1;
|
||||
ddsrt_mutex_lock (&thread_states.lock);
|
||||
if ((cand = find_free_slot ("name")) < 0)
|
||||
abort ();
|
||||
ts1 = &thread_states.ts[cand];
|
||||
if (ts1->state == THREAD_STATE_ZERO)
|
||||
assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts1->vtime)));
|
||||
ts1->state = THREAD_STATE_LAZILY_CREATED;
|
||||
ts1->tid = ddsrt_thread_self ();
|
||||
DDSRT_WARNING_MSVC_OFF(4996);
|
||||
strncpy (ts1->name, main_thread_name, sizeof (ts1->name));
|
||||
DDSRT_WARNING_MSVC_ON(4996);
|
||||
ts1->name[sizeof (ts1->name) - 1] = 0;
|
||||
ddsrt_mutex_unlock (&thread_states.lock);
|
||||
tsd_thread_state = ts1;
|
||||
}
|
||||
|
||||
const struct config_thread_properties_listelem *lookup_thread_properties (const struct config *config, const char *name)
|
||||
{
|
||||
const struct config_thread_properties_listelem *e;
|
||||
|
|
@ -332,15 +340,6 @@ void reset_thread_state (struct thread_state1 *ts1)
|
|||
reap_thread_state (ts1);
|
||||
}
|
||||
|
||||
void downgrade_main_thread (void)
|
||||
{
|
||||
struct thread_state1 *ts1 = lookup_thread_state ();
|
||||
assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts1->vtime)));
|
||||
/* no need to sync with service lease: already stopped */
|
||||
reap_thread_state (ts1);
|
||||
thread_states_init_static ();
|
||||
}
|
||||
|
||||
void log_stack_traces (const struct ddsrt_log_cfg *logcfg, const struct q_globals *gv)
|
||||
{
|
||||
for (uint32_t i = 0; i < thread_states.nthreads; i++)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue