Merge branch 'master' into merge6
Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com>
This commit is contained in:
commit
660d495746
124 changed files with 5049 additions and 1672 deletions
|
@ -103,7 +103,8 @@ if(BUILD_DOCS)
|
|||
"__attribute__="
|
||||
"__declspec(x)="
|
||||
"DDS_EXPORT="
|
||||
"DDS_DEPRECATED_EXPORT=")
|
||||
"DDS_DEPRECATED_EXPORT="
|
||||
"DDSRT_STATIC_ASSERT(x)=")
|
||||
find_package(Doxygen REQUIRED)
|
||||
doxygen_add_docs(ddsc_api_docs "ddsc/include")
|
||||
endif()
|
||||
|
|
|
@ -747,27 +747,50 @@ dds_create_participant(
|
|||
* @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.
|
||||
*
|
||||
* It will not be created if a domain with the given domain id already exists.
|
||||
* This could have been created implicitly by a dds_create_participant().
|
||||
*
|
||||
* Please be aware that the given domain_id always takes precedence over the
|
||||
* configuration.
|
||||
*
|
||||
* | domain_id | domain id in config | result
|
||||
* +-----------+---------------------+----------
|
||||
* | n | any (or absent) | n, config is used
|
||||
* | n | m == n | n, config is used
|
||||
* | n | m != n | n, config is ignored: default
|
||||
*
|
||||
* Config models:
|
||||
* 1: <CycloneDDS>
|
||||
* <Domain id="X">...</Domain>
|
||||
* <Domain .../>
|
||||
* </CycloneDDS>
|
||||
* where ... is all that can today be set in children of CycloneDDS
|
||||
* with the exception of the id
|
||||
* 2: <CycloneDDS>
|
||||
* <Domain><Id>X</Id></Domain>
|
||||
* ...
|
||||
* </CycloneDDS>
|
||||
* legacy form, domain id must be the first element in the file with
|
||||
* a value (if nothing has been set previously, it a warning is good
|
||||
* enough)
|
||||
*
|
||||
* Using NULL or "" as config will create a domain with default settings.
|
||||
*
|
||||
*
|
||||
* @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
|
||||
* @returns A valid entity handle or an error 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
|
||||
* @retval DDS_RETCODE_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_EXPORT dds_entity_t
|
||||
dds_create_domain(const dds_domainid_t domain, const char *config);
|
||||
|
||||
/**
|
||||
|
@ -777,15 +800,10 @@ dds_create_domain(const dds_domainid_t domain, const char *config);
|
|||
* For instance, it will return the Participant that was used when
|
||||
* creating a Publisher (when that Publisher was provided here).
|
||||
*
|
||||
* When a reader or a writer are created with a partition, then a
|
||||
* subscriber or publisher respectively are created implicitly. These
|
||||
* implicit subscribers or publishers will be deleted automatically
|
||||
* when the reader or writer is deleted. However, when this function
|
||||
* returns such an implicit entity, it is from there on out considered
|
||||
* 'explicit'. This means that it isn't deleted automatically anymore.
|
||||
* The application should explicitly call dds_delete on those entities
|
||||
* now (or delete the parent participant which will delete all entities
|
||||
* within its hierarchy).
|
||||
* When a reader or a writer are created with a participant, then a
|
||||
* subscriber or publisher are created implicitly.
|
||||
* This function will return the implicit parent and not the used
|
||||
* participant.
|
||||
*
|
||||
* @param[in] entity Entity from which to get its parent.
|
||||
*
|
||||
|
@ -852,15 +870,10 @@ dds_get_participant(dds_entity_t entity);
|
|||
* When supplying NULL as list and 0 as size, you can use this to acquire
|
||||
* the number of children without having to pre-allocate a list.
|
||||
*
|
||||
* When a reader or a writer are created with a partition, then a
|
||||
* subscriber or publisher respectively are created implicitly. These
|
||||
* implicit subscribers or publishers will be deleted automatically
|
||||
* when the reader or writer is deleted. However, when this function
|
||||
* returns such an implicit entity, it is from there on out considered
|
||||
* 'explicit'. This means that it isn't deleted automatically anymore.
|
||||
* The application should explicitly call dds_delete on those entities
|
||||
* now (or delete the parent participant which will delete all entities
|
||||
* within its hierarchy).
|
||||
* When a reader or a writer are created with a participant, then a
|
||||
* subscriber or publisher are created implicitly.
|
||||
* When used on the participant, this function will return the implicit
|
||||
* subscriber and/or publisher and not the related reader/writer.
|
||||
*
|
||||
* @param[in] entity Entity from which to get its children.
|
||||
* @param[out] children Pre-allocated array to contain the found children.
|
||||
|
@ -869,7 +882,7 @@ dds_get_participant(dds_entity_t entity);
|
|||
* @returns Number of children or an error code.
|
||||
*
|
||||
* @retval >=0
|
||||
* Number of childer found children (can be larger than 'size').
|
||||
* Number of found children (can be larger than 'size').
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* An internal error has occurred.
|
||||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
|
@ -1200,6 +1213,7 @@ dds_wait_for_acks(dds_entity_t publisher_or_writer, dds_duration_t timeout);
|
|||
/**
|
||||
* @brief Creates a new instance of a DDS reader.
|
||||
*
|
||||
* When a participant is used to create a reader, an implicit subscriber is created.
|
||||
* This implicit subscriber will be deleted automatically when the created reader
|
||||
* is deleted.
|
||||
*
|
||||
|
@ -1226,6 +1240,7 @@ dds_create_reader(
|
|||
/**
|
||||
* @brief Creates a new instance of a DDS reader with a custom history cache.
|
||||
*
|
||||
* When a participant is used to create a reader, an implicit subscriber is created.
|
||||
* This implicit subscriber will be deleted automatically when the created reader
|
||||
* is deleted.
|
||||
*
|
||||
|
@ -1273,6 +1288,7 @@ dds_reader_wait_for_historical_data(
|
|||
/**
|
||||
* @brief Creates a new instance of a DDS writer.
|
||||
*
|
||||
* When a participant is used to create a writer, an implicit publisher is created.
|
||||
* This implicit publisher will be deleted automatically when the created writer
|
||||
* is deleted.
|
||||
*
|
||||
|
@ -1696,12 +1712,28 @@ DDS_EXPORT void
|
|||
dds_write_flush(dds_entity_t writer);
|
||||
|
||||
/**
|
||||
* @brief Write a CDR serialized value of a data instance
|
||||
* @brief Write a serialized value of a data instance
|
||||
*
|
||||
* This call causes the writer to write the serialized value that is provided
|
||||
* in the serdata argument.
|
||||
*
|
||||
* @param[in] writer The writer entity.
|
||||
* @param[in] serdata CDR serialized value to be written.
|
||||
* @param[in] serdata Serialized value to be written.
|
||||
*
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* The writer successfully wrote the serialized value.
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* An internal error has occurred.
|
||||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
* One of the given arguments is not valid.
|
||||
* @retval DDS_RETCODE_ILLEGAL_OPERATION
|
||||
* The operation is invoked on an inappropriate object.
|
||||
* @retval DDS_RETCODE_ALREADY_DELETED
|
||||
* The entity has already been deleted.
|
||||
* @retval DDS_RETCODE_TIMEOUT
|
||||
* The writer failed to write the serialized value reliably within the specified max_blocking_time.
|
||||
*/
|
||||
DDS_EXPORT dds_return_t
|
||||
dds_writecdr(dds_entity_t writer, struct ddsi_serdata *serdata);
|
||||
|
@ -2652,6 +2684,44 @@ dds_take_mask_wl(
|
|||
uint32_t maxs,
|
||||
uint32_t mask);
|
||||
|
||||
/**
|
||||
* @brief Access the collection of serialized data values (of same type) and
|
||||
* sample info from the data reader, readcondition or querycondition.
|
||||
*
|
||||
* This call accesses the serialized data from the data reader, readcondition or
|
||||
* querycondition and makes it available to the application. The serialized data
|
||||
* is made available through \ref ddsi_serdata structures. Once read the data is
|
||||
* removed from the reader and cannot be 'read' or 'taken' again.
|
||||
*
|
||||
* Return value provides information about the number of samples read, which will
|
||||
* be <= maxs. Based on the count, the buffer will contain serialized data to be
|
||||
* read only when valid_data bit in sample info structure is set.
|
||||
* The buffer required for data values, could be allocated explicitly or can
|
||||
* use the memory from data reader to prevent copy. In the latter case, buffer and
|
||||
* sample_info should be returned back, once it is no longer using the data.
|
||||
*
|
||||
* @param[in] reader_or_condition Reader, readcondition or querycondition entity.
|
||||
* @param[out] buf An array of pointers to \ref ddsi_serdata structures that contain
|
||||
* the serialized data. The pointers can be NULL.
|
||||
* @param[in] maxs Maximum number of samples to read.
|
||||
* @param[out] si Pointer to an array of \ref dds_sample_info_t returned for each data value.
|
||||
* @param[in] mask Filter the data based on dds_sample_state_t|dds_view_state_t|dds_instance_state_t.
|
||||
*
|
||||
* @returns A dds_return_t with the number of samples read or an error code.
|
||||
*
|
||||
* @retval >=0
|
||||
* Number of samples read.
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* An internal error has occurred.
|
||||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
* One of the given arguments is not valid.
|
||||
* @retval DDS_RETCODE_ILLEGAL_OPERATION
|
||||
* The operation is invoked on an inappropriate object.
|
||||
* @retval DDS_RETCODE_ALREADY_DELETED
|
||||
* The entity has already been deleted.
|
||||
* @retval DDS_RETCODE_PRECONDITION_NOT_MET
|
||||
* The precondition for this operation is not met.
|
||||
*/
|
||||
DDS_EXPORT dds_return_t
|
||||
dds_takecdr(
|
||||
dds_entity_t reader_or_condition,
|
||||
|
@ -3244,6 +3314,29 @@ dds_get_matched_publication_data (
|
|||
dds_entity_t reader,
|
||||
dds_instance_handle_t ih);
|
||||
|
||||
/**
|
||||
* @brief This operation manually asserts the liveliness of a writer
|
||||
* or domain participant.
|
||||
*
|
||||
* This operation manually asserts the liveliness of a writer
|
||||
* or domain participant. This is used in combination with the Liveliness
|
||||
* QoS policy to indicate that the entity remains active. This operation need
|
||||
* only be used if the liveliness kind in the QoS is either
|
||||
* DDS_LIVELINESS_MANUAL_BY_PARTICIPANT or DDS_LIVELINESS_MANUAL_BY_TOPIC.
|
||||
*
|
||||
* @param[in] entity A domain participant or writer
|
||||
*
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* The operation was successful.
|
||||
* @retval DDS_RETCODE_ILLEGAL_OPERATION
|
||||
* The operation is invoked on an inappropriate object.
|
||||
*/
|
||||
DDS_EXPORT dds_return_t
|
||||
dds_assert_liveliness (
|
||||
dds_entity_t entity);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
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_entity_t dds_domain_create_internal (dds_domain **domain_out, dds_domainid_t id, bool implicit, const char *config) ddsrt_nonnull((1,4));
|
||||
DDS_EXPORT dds_domain *dds_domain_find_locked (dds_domainid_t id);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
|
|
|
@ -24,6 +24,7 @@ dds_entity_init(
|
|||
dds_entity * e,
|
||||
dds_entity * parent,
|
||||
dds_entity_kind_t kind,
|
||||
bool implicit,
|
||||
dds_qos_t * qos,
|
||||
const dds_listener_t *listener,
|
||||
status_mask_t mask);
|
||||
|
@ -38,6 +39,12 @@ dds_entity_register_child (
|
|||
DDS_EXPORT void
|
||||
dds_entity_add_ref_locked(dds_entity *e);
|
||||
|
||||
DDS_EXPORT void
|
||||
dds_entity_drop_ref(dds_entity *e);
|
||||
|
||||
DDS_EXPORT void
|
||||
dds_entity_unpin_and_drop_ref (dds_entity *e);
|
||||
|
||||
#define DEFINE_ENTITY_LOCK_UNLOCK(qualifier_, type_, kind_) \
|
||||
qualifier_ dds_return_t type_##_lock (dds_entity_t hdl, type_ **x) \
|
||||
{ \
|
||||
|
@ -96,6 +103,8 @@ dds_entity_pin (
|
|||
dds_entity_t hdl,
|
||||
dds_entity **eptr);
|
||||
|
||||
DDS_EXPORT dds_return_t dds_entity_pin_for_delete (dds_entity_t hdl, bool explicit, dds_entity **eptr);
|
||||
|
||||
DDS_EXPORT void dds_entity_unpin (
|
||||
dds_entity *e);
|
||||
|
||||
|
|
|
@ -72,9 +72,11 @@ typedef int32_t dds_handle_t;
|
|||
|
||||
/* 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)
|
||||
#define HDL_FLAG_CLOSING (0x80000000u)
|
||||
#define HDL_FLAG_DELETE_DEFERRED (0x40000000u)
|
||||
#define HDL_FLAG_PENDING (0x20000000u)
|
||||
#define HDL_FLAG_IMPLICIT (0x10000000u)
|
||||
#define HDL_FLAG_ALLOW_CHILDREN (0x08000000u) /* refc counts children */
|
||||
|
||||
struct dds_handle_link {
|
||||
dds_handle_t hdl;
|
||||
|
@ -116,7 +118,9 @@ dds_handle_server_fini(void);
|
|||
*/
|
||||
DDS_EXPORT dds_handle_t
|
||||
dds_handle_create(
|
||||
struct dds_handle_link *link);
|
||||
struct dds_handle_link *link,
|
||||
bool implicit,
|
||||
bool allow_children);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -124,7 +128,7 @@ dds_handle_create(
|
|||
*/
|
||||
DDS_EXPORT dds_return_t
|
||||
dds_handle_register_special (
|
||||
struct dds_handle_link *link, dds_handle_t handle);
|
||||
struct dds_handle_link *link, bool implicit, bool allow_children, dds_handle_t handle);
|
||||
|
||||
DDS_EXPORT void dds_handle_unpend (struct dds_handle_link *link);
|
||||
|
||||
|
@ -181,6 +185,8 @@ DDS_EXPORT void
|
|||
dds_handle_unpin(
|
||||
struct dds_handle_link *link);
|
||||
|
||||
int32_t dds_handle_pin_for_delete (dds_handle_t hdl, bool explicit, struct dds_handle_link **link);
|
||||
bool dds_handle_drop_childref_and_pin (struct dds_handle_link *link, bool may_delete_parent);
|
||||
|
||||
/*
|
||||
* Check if the handle is closed.
|
||||
|
@ -195,11 +201,15 @@ dds_handle_unpin(
|
|||
|
||||
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 bool dds_handle_close (struct dds_handle_link *link);
|
||||
DDS_EXPORT bool dds_handle_unpin_and_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;
|
||||
return (ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_FLAG_CLOSING) != 0;
|
||||
}
|
||||
|
||||
DDS_EXPORT bool dds_handle_is_not_refd (struct dds_handle_link *link);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,13 @@ extern "C" {
|
|||
|
||||
DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_publisher, DDS_KIND_PUBLISHER)
|
||||
|
||||
dds_entity_t
|
||||
dds__create_publisher_l(
|
||||
struct dds_participant *participant, /* entity-lock must be held */
|
||||
bool implicit,
|
||||
const dds_qos_t *qos,
|
||||
const dds_listener_t *listener);
|
||||
|
||||
dds_return_t dds_publisher_begin_coherent (dds_entity_t e);
|
||||
dds_return_t dds_publisher_end_coherent (dds_entity_t e);
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_subscriber, DDS_KIND_SUBSCRIBER)
|
|||
dds_entity_t
|
||||
dds__create_subscriber_l(
|
||||
struct dds_participant *participant, /* entity-lock must be held */
|
||||
bool implicit,
|
||||
const dds_qos_t *qos,
|
||||
const dds_listener_t *listener);
|
||||
|
||||
|
|
|
@ -245,7 +245,7 @@ typedef struct dds_participant {
|
|||
|
||||
typedef struct dds_reader {
|
||||
struct dds_entity m_entity;
|
||||
const struct dds_topic *m_topic;
|
||||
struct dds_topic *m_topic;
|
||||
struct dds_rhc *m_rhc; /* aliases m_rd->rhc with a wider interface, FIXME: but m_rd owns it for resource management */
|
||||
struct reader *m_rd;
|
||||
bool m_data_on_readers;
|
||||
|
@ -265,7 +265,7 @@ typedef struct dds_reader {
|
|||
|
||||
typedef struct dds_writer {
|
||||
struct dds_entity m_entity;
|
||||
const struct dds_topic *m_topic;
|
||||
struct dds_topic *m_topic;
|
||||
struct nn_xpack *m_xp;
|
||||
struct writer *m_wr;
|
||||
struct whc *m_whc; /* FIXME: ownership still with underlying DDSI writer (cos of DDSI built-in writers )*/
|
||||
|
|
|
@ -131,7 +131,7 @@ bool dds__validate_builtin_reader_qos (const dds_domain *dom, dds_entity_t topic
|
|||
static dds_entity_t dds__create_builtin_subscriber (dds_participant *participant)
|
||||
{
|
||||
dds_qos_t *qos = dds__create_builtin_qos ();
|
||||
dds_entity_t sub = dds__create_subscriber_l (participant, qos, NULL);
|
||||
dds_entity_t sub = dds__create_subscriber_l (participant, false, qos, NULL);
|
||||
dds_delete_qos (qos);
|
||||
return sub;
|
||||
}
|
||||
|
|
|
@ -48,16 +48,14 @@ 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, const char *config)
|
||||
static dds_entity_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_id, const char *config, bool implicit)
|
||||
{
|
||||
dds_return_t ret = DDS_RETCODE_OK;
|
||||
dds_entity_t domh;
|
||||
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;
|
||||
if ((domh = dds_entity_init (&domain->m_entity, &dds_global.m_entity, DDS_KIND_DOMAIN, implicit, NULL, NULL, 0)) < 0)
|
||||
return domh;
|
||||
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 ();
|
||||
|
@ -90,7 +88,7 @@ static dds_return_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i
|
|||
if (domain->cfgst == NULL)
|
||||
{
|
||||
DDS_ILOG (DDS_LC_CONFIG, domain_id, "Failed to parse configuration\n");
|
||||
ret = DDS_RETCODE_ERROR;
|
||||
domh = DDS_RETCODE_ERROR;
|
||||
goto fail_config;
|
||||
}
|
||||
|
||||
|
@ -100,14 +98,14 @@ static dds_return_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i
|
|||
if (rtps_config_prep (&domain->gv, domain->cfgst) != 0)
|
||||
{
|
||||
DDS_ILOG (DDS_LC_CONFIG, domain->m_id, "Failed to configure RTPS\n");
|
||||
ret = DDS_RETCODE_ERROR;
|
||||
domh = DDS_RETCODE_ERROR;
|
||||
goto fail_rtps_config;
|
||||
}
|
||||
|
||||
if (rtps_init (&domain->gv) < 0)
|
||||
{
|
||||
DDS_ILOG (DDS_LC_CONFIG, domain->m_id, "Failed to initialize RTPS\n");
|
||||
ret = DDS_RETCODE_ERROR;
|
||||
domh = DDS_RETCODE_ERROR;
|
||||
goto fail_rtps_init;
|
||||
}
|
||||
|
||||
|
@ -122,14 +120,14 @@ static dds_return_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i
|
|||
if (dds_global.threadmon == NULL)
|
||||
{
|
||||
DDS_ILOG (DDS_LC_CONFIG, domain->m_id, "Failed to create a thread liveliness monitor\n");
|
||||
ret = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
domh = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
goto fail_threadmon_new;
|
||||
}
|
||||
/* FIXME: thread properties */
|
||||
if (ddsi_threadmon_start (dds_global.threadmon, "threadmon") < 0)
|
||||
{
|
||||
DDS_ILOG (DDS_LC_ERROR, domain->m_id, "Failed to start the thread liveliness monitor\n");
|
||||
ret = DDS_RETCODE_ERROR;
|
||||
domh = DDS_RETCODE_ERROR;
|
||||
goto fail_threadmon_start;
|
||||
}
|
||||
}
|
||||
|
@ -159,16 +157,17 @@ static dds_return_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i
|
|||
if (rtps_start (&domain->gv) < 0)
|
||||
{
|
||||
DDS_ILOG (DDS_LC_CONFIG, domain->m_id, "Failed to start RTPS\n");
|
||||
ret = DDS_RETCODE_ERROR;
|
||||
domh = DDS_RETCODE_ERROR;
|
||||
goto fail_rtps_start;
|
||||
}
|
||||
|
||||
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;
|
||||
return domh;
|
||||
|
||||
fail_rtps_start:
|
||||
dds__builtin_fini (domain);
|
||||
if (domain->gv.config.liveliness_monitoring && dds_global.threadmon_count == 1)
|
||||
ddsi_threadmon_stop (dds_global.threadmon);
|
||||
fail_threadmon_start:
|
||||
|
@ -184,7 +183,7 @@ fail_rtps_config:
|
|||
config_fini (domain->cfgst);
|
||||
fail_config:
|
||||
dds_handle_delete (&domain->m_entity.m_hdllink);
|
||||
return ret;
|
||||
return domh;
|
||||
}
|
||||
|
||||
dds_domain *dds_domain_find_locked (dds_domainid_t id)
|
||||
|
@ -192,37 +191,25 @@ 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_internal (dds_domain **domain_out, dds_domainid_t id, bool use_existing, const char *config)
|
||||
dds_entity_t dds_domain_create_internal (dds_domain **domain_out, dds_domainid_t id, bool implicit, const char *config)
|
||||
{
|
||||
struct dds_domain *dom;
|
||||
dds_return_t ret;
|
||||
dds_entity_t domh = DDS_RETCODE_ERROR;
|
||||
|
||||
/* FIXME: should perhaps lock parent object just like everywhere */
|
||||
ddsrt_mutex_lock (&dds_global.m_mutex);
|
||||
retry:
|
||||
if (id != DDS_DOMAIN_DEFAULT)
|
||||
{
|
||||
if ((dom = dds_domain_find_locked (id)) == NULL)
|
||||
ret = DDS_RETCODE_NOT_FOUND;
|
||||
else
|
||||
ret = DDS_RETCODE_OK;
|
||||
}
|
||||
dom = dds_domain_find_locked (id);
|
||||
else
|
||||
{
|
||||
if ((dom = ddsrt_avl_find_min (&dds_domaintree_def, &dds_global.m_domains)) != NULL)
|
||||
ret = DDS_RETCODE_OK;
|
||||
else
|
||||
ret = DDS_RETCODE_NOT_FOUND;
|
||||
}
|
||||
dom = ddsrt_avl_find_min (&dds_domaintree_def, &dds_global.m_domains);
|
||||
|
||||
switch (ret)
|
||||
if (dom)
|
||||
{
|
||||
case DDS_RETCODE_OK:
|
||||
if (!use_existing)
|
||||
{
|
||||
ret = DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
break;
|
||||
}
|
||||
if (!implicit)
|
||||
domh = DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
else
|
||||
{
|
||||
ddsrt_mutex_lock (&dom->m_entity.m_mutex);
|
||||
if (dds_handle_is_closed (&dom->m_entity.m_hdllink))
|
||||
{
|
||||
|
@ -230,52 +217,54 @@ dds_return_t dds_domain_create_internal (dds_domain **domain_out, dds_domainid_t
|
|||
ddsrt_cond_wait (&dds_global.m_cond, &dds_global.m_mutex);
|
||||
goto retry;
|
||||
}
|
||||
else
|
||||
dds_entity_add_ref_locked (&dom->m_entity);
|
||||
dds_handle_repin (&dom->m_entity.m_hdllink);
|
||||
domh = dom->m_entity.m_hdllink.hdl;
|
||||
ddsrt_mutex_unlock (&dom->m_entity.m_mutex);
|
||||
*domain_out = dom;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dom = dds_alloc (sizeof (*dom));
|
||||
if ((domh = dds_domain_init (dom, id, config, implicit)) < 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);
|
||||
if (implicit)
|
||||
{
|
||||
dds_entity_add_ref_locked (&dom->m_entity);
|
||||
ddsrt_mutex_unlock (&dom->m_entity.m_mutex);
|
||||
*domain_out = dom;
|
||||
dds_handle_repin (&dom->m_entity.m_hdllink);
|
||||
}
|
||||
break;
|
||||
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;
|
||||
domh = dom->m_entity.m_hdllink.hdl;
|
||||
ddsrt_mutex_unlock (&dom->m_entity.m_mutex);
|
||||
*domain_out = dom;
|
||||
}
|
||||
}
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
return ret;
|
||||
return domh;
|
||||
}
|
||||
|
||||
dds_return_t dds_create_domain(const dds_domainid_t domain, const char *config)
|
||||
dds_entity_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)
|
||||
if (domain == DDS_DOMAIN_DEFAULT)
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
|
||||
if (config == NULL)
|
||||
config = "";
|
||||
|
||||
/* Make sure DDS instance is initialized. */
|
||||
if ((ret = dds_init ()) < 0)
|
||||
goto err_dds_init;
|
||||
return ret;
|
||||
|
||||
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:
|
||||
ret = dds_domain_create_internal (&dom, domain, false, config);
|
||||
dds_entity_unpin_and_drop_ref (&dds_global.m_entity);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -368,5 +357,5 @@ void dds_write_set_batch (bool enable)
|
|||
}
|
||||
}
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
dds_entity_unpin_and_drop_ref (&dds_global.m_entity);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
#include "dds__qos.h"
|
||||
#include "dds__topic.h"
|
||||
#include "dds/version.h"
|
||||
#include "dds/ddsi/ddsi_pmd.h"
|
||||
#include "dds/ddsi/q_xqos.h"
|
||||
#include "dds/ddsi/q_transmit.h"
|
||||
|
||||
extern inline dds_entity *dds_entity_from_handle_link (struct dds_handle_link *hdllink);
|
||||
extern inline bool dds_entity_is_enabled (const dds_entity *e);
|
||||
|
@ -80,11 +82,34 @@ 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 dds_return_t dds_delete_impl (dds_entity_t entity, enum delete_impl_state delstate);
|
||||
static dds_return_t really_delete_pinned_closed_locked (struct dds_entity *e, enum delete_impl_state delstate);
|
||||
|
||||
void dds_entity_add_ref_locked (dds_entity *e)
|
||||
{
|
||||
dds_handle_add_ref (&e->m_hdllink);
|
||||
}
|
||||
|
||||
void dds_entity_drop_ref (dds_entity *e)
|
||||
{
|
||||
if (dds_handle_drop_ref (&e->m_hdllink))
|
||||
{
|
||||
dds_return_t ret = dds_delete_impl(e->m_hdllink.hdl, DIS_EXPLICIT);
|
||||
assert (ret == DDS_RETCODE_OK);
|
||||
(void) ret;
|
||||
}
|
||||
}
|
||||
|
||||
void dds_entity_unpin_and_drop_ref (dds_entity *e)
|
||||
{
|
||||
if (dds_handle_unpin_and_drop_ref (&e->m_hdllink))
|
||||
{
|
||||
dds_return_t ret = dds_delete_impl(e->m_hdllink.hdl, DIS_EXPLICIT);
|
||||
assert (ret == DDS_RETCODE_OK);
|
||||
(void) ret;
|
||||
}
|
||||
}
|
||||
|
||||
static bool entity_has_status (const dds_entity *e)
|
||||
{
|
||||
switch (e->m_kind)
|
||||
|
@ -110,7 +135,7 @@ static bool entity_has_status (const dds_entity *e)
|
|||
return false;
|
||||
}
|
||||
|
||||
dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind_t kind, dds_qos_t *qos, const dds_listener_t *listener, status_mask_t mask)
|
||||
dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind_t kind, bool implicit, dds_qos_t *qos, const dds_listener_t *listener, status_mask_t mask)
|
||||
{
|
||||
dds_handle_t handle;
|
||||
|
||||
|
@ -125,6 +150,8 @@ dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind
|
|||
|
||||
/* TODO: CHAM-96: Implement dynamic enabling of entity. */
|
||||
e->m_flags |= DDS_ENTITY_ENABLED;
|
||||
if (implicit)
|
||||
e->m_flags |= DDS_ENTITY_IMPLICIT;
|
||||
|
||||
/* set the status enable based on kind */
|
||||
if (entity_has_status (e))
|
||||
|
@ -162,12 +189,14 @@ dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind
|
|||
|
||||
if (kind == DDS_KIND_CYCLONEDDS)
|
||||
{
|
||||
if ((handle = dds_handle_register_special (&e->m_hdllink, DDS_CYCLONEDDS_HANDLE)) <= 0)
|
||||
if ((handle = dds_handle_register_special (&e->m_hdllink, implicit, true, DDS_CYCLONEDDS_HANDLE)) <= 0)
|
||||
return (dds_entity_t) handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((handle = dds_handle_create (&e->m_hdllink)) <= 0)
|
||||
/* for topics, refc counts readers/writers, for all others, it counts children (this we can get away with
|
||||
as long as topics can't have children) */
|
||||
if ((handle = dds_handle_create (&e->m_hdllink, implicit, (kind != DDS_KIND_TOPIC))) <= 0)
|
||||
return (dds_entity_t) handle;
|
||||
}
|
||||
|
||||
|
@ -182,22 +211,53 @@ void dds_entity_init_complete (dds_entity *entity)
|
|||
|
||||
void dds_entity_register_child (dds_entity *parent, dds_entity *child)
|
||||
{
|
||||
/* parent must be tracking children in its refc, or children can't be added */
|
||||
assert (ddsrt_atomic_ld32 (&parent->m_hdllink.cnt_flags) & HDL_FLAG_ALLOW_CHILDREN);
|
||||
assert (child->m_iid != 0);
|
||||
assert (ddsrt_avl_lookup (&dds_entity_children_td, &parent->m_children, &child->m_iid) == NULL);
|
||||
ddsrt_avl_insert (&dds_entity_children_td, &parent->m_children, child);
|
||||
dds_entity_add_ref_locked (parent);
|
||||
}
|
||||
|
||||
static dds_entity *next_non_topic_child (ddsrt_avl_tree_t *remaining_children)
|
||||
static dds_entity *get_first_child (ddsrt_avl_tree_t *remaining_children, bool ignore_topics)
|
||||
{
|
||||
ddsrt_avl_iter_t it;
|
||||
for (dds_entity *e = ddsrt_avl_iter_first (&dds_entity_children_td, remaining_children, &it); e != NULL; e = ddsrt_avl_iter_next (&it))
|
||||
{
|
||||
if (dds_entity_kind (e) != DDS_KIND_TOPIC)
|
||||
if ((!ignore_topics) || (dds_entity_kind(e) != DDS_KIND_TOPIC))
|
||||
return e;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void delete_children(struct dds_entity *parent, bool ignore_topics)
|
||||
{
|
||||
dds_entity *child;
|
||||
dds_return_t ret;
|
||||
ddsrt_mutex_lock (&parent->m_mutex);
|
||||
while ((child = get_first_child(&parent->m_children, ignore_topics)) != NULL)
|
||||
{
|
||||
dds_entity_t child_handle = child->m_hdllink.hdl;
|
||||
|
||||
/* The child will remove itself from the parent->m_children list. */
|
||||
ddsrt_mutex_unlock (&parent->m_mutex);
|
||||
ret = dds_delete_impl (child_handle, DIS_FROM_PARENT);
|
||||
assert (ret == DDS_RETCODE_OK || ret == DDS_RETCODE_BAD_PARAMETER);
|
||||
ddsrt_mutex_lock (&parent->m_mutex);
|
||||
|
||||
/* The dds_delete can fail if the child is being deleted in parallel,
|
||||
* in which case: wait when its not deleted yet.
|
||||
* The child will trigger the condition after it removed itself from
|
||||
* the childrens list. */
|
||||
if ((ret == DDS_RETCODE_BAD_PARAMETER) &&
|
||||
(get_first_child(&parent->m_children, ignore_topics) == child))
|
||||
{
|
||||
ddsrt_cond_wait (&parent->m_cond, &parent->m_mutex);
|
||||
}
|
||||
}
|
||||
ddsrt_mutex_unlock (&parent->m_mutex);
|
||||
}
|
||||
|
||||
#define TRACE_DELETE 0 /* FIXME: use DDS_LOG for this */
|
||||
#if TRACE_DELETE
|
||||
static const char *entity_kindstr (dds_entity_kind_t kind)
|
||||
|
@ -227,13 +287,11 @@ static void print_delete (const dds_entity *e, enum delete_impl_state delstate ,
|
|||
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",
|
||||
e->m_hdllink.hdl, cm & 0xfff, (cm >> 12) & 0x7fff, (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);
|
||||
|
@ -252,53 +310,33 @@ static dds_return_t dds_delete_impl (dds_entity_t entity, enum delete_impl_state
|
|||
{
|
||||
dds_entity *e;
|
||||
dds_return_t ret;
|
||||
if ((ret = dds_entity_pin (entity, &e)) < 0)
|
||||
return ret;
|
||||
else
|
||||
if ((ret = dds_entity_pin_for_delete (entity, (delstate != DIS_IMPLICIT), &e)) == DDS_RETCODE_OK)
|
||||
return dds_delete_impl_pinned (e, delstate);
|
||||
else if (ret == DDS_RETCODE_TRY_AGAIN) /* non-child refs exist */
|
||||
return DDS_RETCODE_OK;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
dds_return_t dds_delete_impl_pinned (dds_entity *e, enum delete_impl_state delstate)
|
||||
{
|
||||
dds_entity *child;
|
||||
dds_return_t ret;
|
||||
|
||||
/* 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 TRACE_DELETE
|
||||
print_delete (e, delstate, iid);
|
||||
print_delete (e, delstate, e->m_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))
|
||||
{
|
||||
dds_entity_unlock (e);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
assert (dds_handle_is_closed (&e->m_hdllink));
|
||||
return really_delete_pinned_closed_locked (e, delstate);
|
||||
}
|
||||
|
||||
/* 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))
|
||||
{
|
||||
dds_entity_unlock (e);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
static dds_return_t really_delete_pinned_closed_locked (struct dds_entity *e, enum delete_impl_state delstate)
|
||||
{
|
||||
dds_return_t ret;
|
||||
|
||||
/* 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
|
||||
|
@ -354,24 +392,8 @@ dds_return_t dds_delete_impl_pinned (dds_entity *e, enum delete_impl_state delst
|
|||
*
|
||||
* To circumvent the problem. We ignore topics in the first loop.
|
||||
*/
|
||||
ddsrt_mutex_lock (&e->m_mutex);
|
||||
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);
|
||||
(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)
|
||||
{
|
||||
assert (dds_entity_kind (child) == DDS_KIND_TOPIC);
|
||||
dds_entity_t child_handle = child->m_hdllink.hdl;
|
||||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
(void) dds_delete_impl (child_handle, DIS_FROM_PARENT);
|
||||
ddsrt_mutex_lock (&e->m_mutex);
|
||||
}
|
||||
ddsrt_mutex_unlock (&e->m_mutex);
|
||||
delete_children(e, true /* ignore topics */);
|
||||
delete_children(e, false /* delete topics */);
|
||||
|
||||
/* 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
|
||||
|
@ -391,15 +413,16 @@ dds_return_t dds_delete_impl_pinned (dds_entity *e, enum delete_impl_state delst
|
|||
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);
|
||||
if (dds_handle_drop_childref_and_pin (&p->m_hdllink, delstate != DIS_FROM_PARENT))
|
||||
{
|
||||
dds_handle_close(&p->m_hdllink);
|
||||
assert (dds_handle_is_closed (&p->m_hdllink));
|
||||
assert (dds_handle_is_not_refd (&p->m_hdllink));
|
||||
assert (ddsrt_avl_is_empty (&p->m_children));
|
||||
parent_to_delete = p;
|
||||
}
|
||||
/* trigger parent in case it is waiting in delete */
|
||||
ddsrt_cond_broadcast (&p->m_cond);
|
||||
|
||||
if (delstate != DIS_FROM_PARENT && (p->m_flags & DDS_ENTITY_IMPLICIT) && ddsrt_avl_is_empty (&p->m_children))
|
||||
{
|
||||
if ((ret = dds_entity_pin (p->m_hdllink.hdl, &parent_to_delete)) < 0)
|
||||
parent_to_delete = NULL;
|
||||
}
|
||||
|
||||
ddsrt_mutex_unlock (&p->m_mutex);
|
||||
}
|
||||
|
||||
|
@ -1121,6 +1144,19 @@ dds_return_t dds_entity_pin (dds_entity_t hdl, dds_entity **eptr)
|
|||
}
|
||||
}
|
||||
|
||||
dds_return_t dds_entity_pin_for_delete (dds_entity_t hdl, bool explicit, dds_entity **eptr)
|
||||
{
|
||||
dds_return_t hres;
|
||||
struct dds_handle_link *hdllink;
|
||||
if ((hres = dds_handle_pin_for_delete (hdl, explicit, &hdllink)) < 0)
|
||||
return hres;
|
||||
else
|
||||
{
|
||||
*eptr = dds_entity_from_handle_link (hdllink);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void dds_entity_unpin (dds_entity *e)
|
||||
{
|
||||
dds_handle_unpin (&e->m_hdllink);
|
||||
|
@ -1349,3 +1385,32 @@ dds_return_t dds_generic_unimplemented_operation (dds_entity_t handle, dds_entit
|
|||
return dds_generic_unimplemented_operation_manykinds (handle, 1, &kind);
|
||||
}
|
||||
|
||||
dds_return_t dds_assert_liveliness (dds_entity_t entity)
|
||||
{
|
||||
dds_return_t rc;
|
||||
dds_entity *e, *ewr;
|
||||
|
||||
if ((rc = dds_entity_pin (entity, &e)) != DDS_RETCODE_OK)
|
||||
return rc;
|
||||
switch (dds_entity_kind (e))
|
||||
{
|
||||
case DDS_KIND_PARTICIPANT: {
|
||||
write_pmd_message_guid (&e->m_domain->gv, &e->m_guid, PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE);
|
||||
break;
|
||||
}
|
||||
case DDS_KIND_WRITER: {
|
||||
if ((rc = dds_entity_lock (entity, DDS_KIND_WRITER, &ewr)) != DDS_RETCODE_OK)
|
||||
return rc;
|
||||
if ((rc = write_hb_liveliness (&e->m_domain->gv, &e->m_guid, ((struct dds_writer *)ewr)->m_xp)) != DDS_RETCODE_OK)
|
||||
return rc;
|
||||
dds_entity_unlock (e);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
rc = DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dds_entity_unpin (e);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -57,18 +57,18 @@ dds_entity_t dds_create_guardcondition (dds_entity_t owner)
|
|||
}
|
||||
|
||||
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);
|
||||
dds_entity_t hdl = dds_entity_init (&gcond->m_entity, e, DDS_KIND_COND_GUARD, false, 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);
|
||||
dds_entity_unpin_and_drop_ref (&dds_global.m_entity);
|
||||
return hdl;
|
||||
|
||||
err_entity_kind:
|
||||
dds_entity_unlock (e);
|
||||
err_entity_lock:
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
dds_entity_unpin_and_drop_ref (&dds_global.m_entity);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,11 +20,36 @@
|
|||
#include "dds__handles.h"
|
||||
#include "dds__types.h"
|
||||
|
||||
#define HDL_REFCOUNT_MASK (0x0ffff000u)
|
||||
#define HDL_REFCOUNT_MASK (0x07fff000u)
|
||||
#define HDL_REFCOUNT_UNIT (0x00001000u)
|
||||
#define HDL_REFCOUNT_SHIFT 12
|
||||
#define HDL_PINCOUNT_MASK (0x00000fffu)
|
||||
|
||||
/*
|
||||
"regular" entities other than topics:
|
||||
- create makes it
|
||||
- delete deletes it and its children immediately
|
||||
- explicit domain: additional protection for bootstrapping complications need extra care
|
||||
|
||||
implicit entities other than topics (pub, sub, domain, cyclonedds):
|
||||
- created "spontaneously" as a consequence of creating the writer/reader/participant
|
||||
- delete of last child causes it to disappear
|
||||
- explicit delete treated like a delete of a "regular" entity
|
||||
- domain, cyclonedds: bootstrapping complications require additional protection
|
||||
|
||||
topics:
|
||||
- create makes it
|
||||
- never has children (so the handle's cnt_flags can have a different meaning)
|
||||
- readers, writers keep it in existence
|
||||
- delete deferred until no readers/writers exist
|
||||
- an attempt at deleting it fails if in "deferred delete" state (or should it simply
|
||||
return ok while doing nothing?), other operations keep going so, e.g., listeners
|
||||
remain useful
|
||||
|
||||
built-in topics:
|
||||
- implicit variant of a topic
|
||||
*/
|
||||
|
||||
/* 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
|
||||
increases with an increasing number of handles. 16M handles seems likely to be
|
||||
|
@ -82,7 +107,7 @@ void dds_handle_server_fini (void)
|
|||
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" : "");
|
||||
cf & HDL_FLAG_DELETE_DEFERRED ? " delete-deferred" : "");
|
||||
}
|
||||
assert (ddsrt_hh_iter_first (handles.ht, &it) == NULL);
|
||||
#endif
|
||||
|
@ -94,9 +119,9 @@ void dds_handle_server_fini (void)
|
|||
}
|
||||
|
||||
static bool hhadd (struct ddsrt_hh *ht, void *elem) { return ddsrt_hh_add (ht, elem); }
|
||||
static dds_handle_t dds_handle_create_int (struct dds_handle_link *link)
|
||||
static dds_handle_t dds_handle_create_int (struct dds_handle_link *link, bool implicit, bool refc_counts_children)
|
||||
{
|
||||
ddsrt_atomic_st32 (&link->cnt_flags, HDL_FLAG_PENDING | HDL_REFCOUNT_UNIT | 1u);
|
||||
ddsrt_atomic_st32 (&link->cnt_flags, HDL_FLAG_PENDING | (implicit ? HDL_FLAG_IMPLICIT : HDL_REFCOUNT_UNIT) | (refc_counts_children ? HDL_FLAG_ALLOW_CHILDREN : 0) | 1u);
|
||||
do {
|
||||
do {
|
||||
link->hdl = (int32_t) (ddsrt_random () & INT32_MAX);
|
||||
|
@ -105,7 +130,7 @@ static dds_handle_t dds_handle_create_int (struct dds_handle_link *link)
|
|||
return link->hdl;
|
||||
}
|
||||
|
||||
dds_handle_t dds_handle_create (struct dds_handle_link *link)
|
||||
dds_handle_t dds_handle_create (struct dds_handle_link *link, bool implicit, bool allow_children)
|
||||
{
|
||||
dds_handle_t ret;
|
||||
ddsrt_mutex_lock (&handles.lock);
|
||||
|
@ -117,14 +142,14 @@ dds_handle_t dds_handle_create (struct dds_handle_link *link)
|
|||
else
|
||||
{
|
||||
handles.count++;
|
||||
ret = dds_handle_create_int (link);
|
||||
ret = dds_handle_create_int (link, implicit, allow_children);
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
assert (ret > 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
dds_return_t dds_handle_register_special (struct dds_handle_link *link, dds_handle_t handle)
|
||||
dds_return_t dds_handle_register_special (struct dds_handle_link *link, bool implicit, bool allow_children, dds_handle_t handle)
|
||||
{
|
||||
dds_return_t ret;
|
||||
if (handle <= 0)
|
||||
|
@ -138,7 +163,7 @@ dds_return_t dds_handle_register_special (struct dds_handle_link *link, dds_hand
|
|||
else
|
||||
{
|
||||
handles.count++;
|
||||
ddsrt_atomic_st32 (&link->cnt_flags, HDL_FLAG_PENDING | HDL_REFCOUNT_UNIT | 1u);
|
||||
ddsrt_atomic_st32 (&link->cnt_flags, HDL_FLAG_PENDING | (implicit ? HDL_FLAG_IMPLICIT : HDL_REFCOUNT_UNIT) | (allow_children ? HDL_FLAG_ALLOW_CHILDREN : 0) | 1u);
|
||||
link->hdl = handle;
|
||||
if (hhadd (handles.ht, link))
|
||||
ret = handle;
|
||||
|
@ -155,9 +180,9 @@ void dds_handle_unpend (struct dds_handle_link *link)
|
|||
#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_DELETE_DEFERRED));
|
||||
assert (!(cf & HDL_FLAG_CLOSING));
|
||||
assert ((cf & HDL_REFCOUNT_MASK) >= HDL_REFCOUNT_UNIT);
|
||||
assert ((cf & HDL_REFCOUNT_MASK) >= HDL_REFCOUNT_UNIT || (cf & HDL_FLAG_IMPLICIT));
|
||||
assert ((cf & HDL_PINCOUNT_MASK) >= 1u);
|
||||
#endif
|
||||
ddsrt_atomic_and32 (&link->cnt_flags, ~HDL_FLAG_PENDING);
|
||||
|
@ -171,7 +196,6 @@ int32_t dds_handle_delete (struct dds_handle_link *link)
|
|||
if (!(cf & HDL_FLAG_PENDING))
|
||||
{
|
||||
assert (cf & HDL_FLAG_CLOSING);
|
||||
assert (cf & HDL_FLAG_CLOSED);
|
||||
assert ((cf & HDL_REFCOUNT_MASK) == 0u);
|
||||
}
|
||||
assert ((cf & HDL_PINCOUNT_MASK) == 1u);
|
||||
|
@ -213,7 +237,7 @@ static int32_t dds_handle_pin_int (dds_handle_t hdl, uint32_t delta, struct dds_
|
|||
rc = DDS_RETCODE_OK;
|
||||
do {
|
||||
cf = ddsrt_atomic_ld32 (&(*link)->cnt_flags);
|
||||
if (cf & (HDL_FLAG_CLOSED | HDL_FLAG_CLOSING | HDL_FLAG_PENDING))
|
||||
if (cf & (HDL_FLAG_CLOSING | HDL_FLAG_PENDING))
|
||||
{
|
||||
rc = DDS_RETCODE_BAD_PARAMETER;
|
||||
break;
|
||||
|
@ -229,6 +253,169 @@ 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_for_delete (dds_handle_t hdl, bool explicit, struct dds_handle_link **link)
|
||||
{
|
||||
struct dds_handle_link dummy = { .hdl = hdl };
|
||||
int32_t rc;
|
||||
/* it makes sense to check here for initialization: the first thing any operation
|
||||
(other than create_participant) does is to call dds_handle_pin on the supplied
|
||||
entity, so checking here whether the library has been initialised helps avoid
|
||||
crashes if someone forgets to create a participant (or allows a program to
|
||||
continue after failing to create one).
|
||||
|
||||
One could check that the handle is > 0, but that would catch fewer errors
|
||||
without any advantages. */
|
||||
if (handles.ht == NULL)
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
|
||||
ddsrt_mutex_lock (&handles.lock);
|
||||
*link = ddsrt_hh_lookup (handles.ht, &dummy);
|
||||
if (*link == NULL)
|
||||
rc = DDS_RETCODE_BAD_PARAMETER;
|
||||
else
|
||||
{
|
||||
uint32_t cf, cf1;
|
||||
/* Assume success; bail out if the object turns out to be in the process of
|
||||
being deleted */
|
||||
do {
|
||||
cf = ddsrt_atomic_ld32 (&(*link)->cnt_flags);
|
||||
|
||||
if (cf & (HDL_FLAG_CLOSING | HDL_FLAG_PENDING))
|
||||
{
|
||||
/* Only one can succeed (and if closing is already set, the handle's reference has
|
||||
already been dropped) */
|
||||
rc = DDS_RETCODE_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
else if (cf & HDL_FLAG_DELETE_DEFERRED)
|
||||
{
|
||||
/* Someone already called delete, but the operation was deferred becauses there are still
|
||||
outstanding references. This implies that there are no children, because then the
|
||||
entire hierarchy would simply have been deleted. */
|
||||
assert (!(cf & HDL_FLAG_ALLOW_CHILDREN));
|
||||
if (cf & HDL_REFCOUNT_MASK)
|
||||
{
|
||||
rc = DDS_RETCODE_ALREADY_DELETED;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Refcount reached zero. Pin to allow deletion. */
|
||||
cf1 = (cf + 1u) | HDL_FLAG_CLOSING;
|
||||
}
|
||||
}
|
||||
else if (explicit)
|
||||
{
|
||||
/* Explicit call to dds_delete (either by application or by parent deleting its children) */
|
||||
if (cf & HDL_FLAG_IMPLICIT)
|
||||
{
|
||||
/* Entity is implicit, so handle doesn't hold a reference */
|
||||
cf1 = (cf + 1u) | HDL_FLAG_CLOSING;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert ((cf & HDL_REFCOUNT_MASK) > 0);
|
||||
if ((cf & HDL_REFCOUNT_MASK) == HDL_REFCOUNT_UNIT)
|
||||
{
|
||||
/* Last reference is closing. Pin entity and indicate that it is closing. */
|
||||
cf1 = (cf - HDL_REFCOUNT_UNIT + 1u) | HDL_FLAG_CLOSING;
|
||||
}
|
||||
else if (!(cf & HDL_FLAG_ALLOW_CHILDREN))
|
||||
{
|
||||
/* The refcnt does not contain children.
|
||||
* Indicate that the closing of the entity is deferred. */
|
||||
cf1 = (cf - HDL_REFCOUNT_UNIT) | HDL_FLAG_DELETE_DEFERRED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Entity is explicit, so handle held a reference, refc only counts children as so is not our concern */
|
||||
cf1 = (cf - HDL_REFCOUNT_UNIT + 1u) | HDL_FLAG_CLOSING;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Implicit call to dds_delete (child invoking delete on its parent) */
|
||||
if (cf & HDL_FLAG_IMPLICIT)
|
||||
{
|
||||
assert ((cf & HDL_REFCOUNT_MASK) > 0);
|
||||
if ((cf & HDL_REFCOUNT_MASK) == HDL_REFCOUNT_UNIT)
|
||||
{
|
||||
/* Last reference is closing. Pin entity and indicate that it is closing. */
|
||||
cf1 = (cf - HDL_REFCOUNT_UNIT + 1u) | HDL_FLAG_CLOSING;
|
||||
}
|
||||
else if (!(cf & HDL_FLAG_ALLOW_CHILDREN))
|
||||
{
|
||||
/* The refcnt does not contain children.
|
||||
* Indicate that the closing of the entity is deferred. */
|
||||
cf1 = (cf - HDL_REFCOUNT_UNIT) | HDL_FLAG_DELETE_DEFERRED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just reduce the children refcount by one. */
|
||||
cf1 = (cf - HDL_REFCOUNT_UNIT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Child can't delete an explicit parent */
|
||||
rc = DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ((cf1 & HDL_REFCOUNT_MASK) == 0 || (cf1 & HDL_FLAG_ALLOW_CHILDREN)) ? DDS_RETCODE_OK : DDS_RETCODE_TRY_AGAIN;
|
||||
} while (!ddsrt_atomic_cas32 (&(*link)->cnt_flags, cf, cf1));
|
||||
}
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool dds_handle_drop_childref_and_pin (struct dds_handle_link *link, bool may_delete_parent)
|
||||
{
|
||||
bool del_parent = false;
|
||||
ddsrt_mutex_lock (&handles.lock);
|
||||
uint32_t cf, cf1;
|
||||
do {
|
||||
cf = ddsrt_atomic_ld32 (&link->cnt_flags);
|
||||
|
||||
if (cf & (HDL_FLAG_CLOSING | HDL_FLAG_PENDING))
|
||||
{
|
||||
/* Only one can succeed; child ref still to be removed */
|
||||
assert ((cf & HDL_REFCOUNT_MASK) > 0);
|
||||
cf1 = (cf - HDL_REFCOUNT_UNIT);
|
||||
del_parent = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cf & HDL_FLAG_IMPLICIT)
|
||||
{
|
||||
/* Implicit parent: delete if last ref */
|
||||
if ((cf & HDL_REFCOUNT_MASK) == HDL_REFCOUNT_UNIT && may_delete_parent)
|
||||
{
|
||||
cf1 = (cf - HDL_REFCOUNT_UNIT + 1u);
|
||||
del_parent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert ((cf & HDL_REFCOUNT_MASK) > 0);
|
||||
cf1 = (cf - HDL_REFCOUNT_UNIT);
|
||||
del_parent = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Child can't delete an explicit parent; child ref still to be removed */
|
||||
assert ((cf & HDL_REFCOUNT_MASK) > 0);
|
||||
cf1 = (cf - HDL_REFCOUNT_UNIT);
|
||||
del_parent = false;
|
||||
}
|
||||
}
|
||||
} while (!ddsrt_atomic_cas32 (&link->cnt_flags, cf, cf1));
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
return del_parent;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -237,7 +424,6 @@ int32_t dds_handle_pin_and_ref (dds_handle_t hdl, struct dds_handle_link **link)
|
|||
void dds_handle_repin (struct dds_handle_link *link)
|
||||
{
|
||||
uint32_t x = ddsrt_atomic_inc32_nv (&link->cnt_flags);
|
||||
assert (!(x & HDL_FLAG_CLOSED));
|
||||
(void) x;
|
||||
}
|
||||
|
||||
|
@ -245,7 +431,6 @@ void dds_handle_unpin (struct dds_handle_link *link)
|
|||
{
|
||||
#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
|
||||
|
@ -266,16 +451,43 @@ void dds_handle_add_ref (struct dds_handle_link *link)
|
|||
|
||||
bool dds_handle_drop_ref (struct dds_handle_link *link)
|
||||
{
|
||||
assert ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_REFCOUNT_MASK) != 0);
|
||||
uint32_t old, new;
|
||||
do {
|
||||
old = ddsrt_atomic_ld32 (&link->cnt_flags);
|
||||
if ((old & HDL_REFCOUNT_MASK) != HDL_REFCOUNT_UNIT)
|
||||
new = old - HDL_REFCOUNT_UNIT;
|
||||
else
|
||||
new = (old - HDL_REFCOUNT_UNIT) | HDL_FLAG_CLOSING;
|
||||
assert ((old & HDL_REFCOUNT_MASK) > 0);
|
||||
new = old - HDL_REFCOUNT_UNIT;
|
||||
} while (!ddsrt_atomic_cas32 (&link->cnt_flags, old, new));
|
||||
return (new & HDL_REFCOUNT_MASK) == 0;
|
||||
ddsrt_mutex_lock (&handles.lock);
|
||||
if ((new & (HDL_FLAG_CLOSING | HDL_PINCOUNT_MASK)) == (HDL_FLAG_CLOSING | 1u))
|
||||
{
|
||||
ddsrt_cond_broadcast (&handles.cond);
|
||||
}
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
return ((new & HDL_REFCOUNT_MASK) == 0);
|
||||
}
|
||||
|
||||
bool dds_handle_unpin_and_drop_ref (struct dds_handle_link *link)
|
||||
{
|
||||
uint32_t old, new;
|
||||
do {
|
||||
old = ddsrt_atomic_ld32 (&link->cnt_flags);
|
||||
assert ((old & HDL_REFCOUNT_MASK) > 0);
|
||||
assert ((old & HDL_PINCOUNT_MASK) > 0);
|
||||
new = old - HDL_REFCOUNT_UNIT - 1u;
|
||||
} while (!ddsrt_atomic_cas32 (&link->cnt_flags, old, new));
|
||||
ddsrt_mutex_lock (&handles.lock);
|
||||
if ((new & (HDL_FLAG_CLOSING | HDL_PINCOUNT_MASK)) == (HDL_FLAG_CLOSING | 1u))
|
||||
{
|
||||
ddsrt_cond_broadcast (&handles.cond);
|
||||
}
|
||||
ddsrt_mutex_unlock (&handles.lock);
|
||||
return ((new & HDL_REFCOUNT_MASK) == 0);
|
||||
}
|
||||
|
||||
bool dds_handle_close (struct dds_handle_link *link)
|
||||
{
|
||||
uint32_t old = ddsrt_atomic_or32_ov (&link->cnt_flags, HDL_FLAG_CLOSING);
|
||||
return (old & HDL_REFCOUNT_MASK) == 0;
|
||||
}
|
||||
|
||||
void dds_handle_close_wait (struct dds_handle_link *link)
|
||||
|
@ -283,17 +495,18 @@ void dds_handle_close_wait (struct dds_handle_link *link)
|
|||
#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);
|
||||
}
|
||||
|
||||
bool dds_handle_is_not_refd (struct dds_handle_link *link)
|
||||
{
|
||||
return ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_REFCOUNT_MASK) == 0);
|
||||
}
|
||||
|
||||
extern inline bool dds_handle_is_closed (struct dds_handle_link *link);
|
||||
|
|
|
@ -119,9 +119,8 @@ dds_return_t dds_init (void)
|
|||
goto fail_handleserver;
|
||||
}
|
||||
|
||||
dds_entity_init (&dds_global.m_entity, NULL, DDS_KIND_CYCLONEDDS, NULL, NULL, 0);
|
||||
dds_entity_init (&dds_global.m_entity, NULL, DDS_KIND_CYCLONEDDS, true, 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);
|
||||
|
|
|
@ -113,7 +113,7 @@ dds_return_t dds_unregister_instance_ts (dds_entity_t writer, const void *data,
|
|||
return ret;
|
||||
|
||||
if (wr->m_entity.m_qos)
|
||||
dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose);
|
||||
(void) dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose);
|
||||
|
||||
thread_state_awake (ts1, &wr->m_entity.m_domain->gv);
|
||||
if (autodispose)
|
||||
|
@ -140,7 +140,7 @@ dds_return_t dds_unregister_instance_ih_ts (dds_entity_t writer, dds_instance_ha
|
|||
return ret;
|
||||
|
||||
if (wr->m_entity.m_qos)
|
||||
dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose);
|
||||
(void) dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose);
|
||||
|
||||
thread_state_awake (ts1, &wr->m_entity.m_domain->gv);
|
||||
if (autodispose)
|
||||
|
|
|
@ -117,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, &dom->m_entity, 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, false, new_qos, listener, DDS_PARTICIPANT_STATUS_MASK)) < 0)
|
||||
goto err_entity_init;
|
||||
|
||||
pp->m_entity.m_guid = guid;
|
||||
|
@ -126,14 +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_entity.m_mutex);
|
||||
ddsrt_mutex_lock (&dom->m_entity.m_mutex);
|
||||
dds_entity_register_child (&dom->m_entity, &pp->m_entity);
|
||||
ddsrt_mutex_unlock (&dds_global.m_entity.m_mutex);
|
||||
ddsrt_mutex_unlock (&dom->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);
|
||||
dds_entity_unpin_and_drop_ref (&dom->m_entity);
|
||||
dds_entity_unpin_and_drop_ref (&dds_global.m_entity);
|
||||
return ret;
|
||||
|
||||
err_entity_init:
|
||||
|
@ -141,9 +141,9 @@ err_entity_init:
|
|||
err_new_participant:
|
||||
err_qos_validation:
|
||||
dds_delete_qos (new_qos);
|
||||
dds_delete (dom->m_entity.m_hdllink.hdl);
|
||||
dds_entity_unpin_and_drop_ref (&dom->m_entity);
|
||||
err_domain_create:
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
dds_entity_unpin_and_drop_ref (&dds_global.m_entity);
|
||||
err_dds_init:
|
||||
return ret;
|
||||
}
|
||||
|
@ -175,6 +175,6 @@ dds_return_t dds_lookup_participant (dds_domainid_t domain_id, dds_entity_t *par
|
|||
}
|
||||
}
|
||||
ddsrt_mutex_unlock (&dds_global.m_mutex);
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
dds_entity_unpin_and_drop_ref (&dds_global.m_entity);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -45,17 +45,13 @@ const struct dds_entity_deriver dds_entity_deriver_publisher = {
|
|||
.validate_status = dds_publisher_status_validate
|
||||
};
|
||||
|
||||
dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qos, const dds_listener_t *listener)
|
||||
dds_entity_t dds__create_publisher_l (dds_participant *par, bool implicit, const dds_qos_t *qos, const dds_listener_t *listener)
|
||||
{
|
||||
dds_participant *par;
|
||||
dds_publisher *pub;
|
||||
dds_entity_t hdl;
|
||||
dds_qos_t *new_qos;
|
||||
dds_return_t ret;
|
||||
|
||||
if ((ret = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK)
|
||||
return ret;
|
||||
|
||||
new_qos = dds_create_qos ();
|
||||
if (qos)
|
||||
nn_xqos_mergein_missing (new_qos, qos, DDS_PUBLISHER_QOS_MASK);
|
||||
|
@ -67,10 +63,21 @@ dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qo
|
|||
}
|
||||
|
||||
pub = dds_alloc (sizeof (*pub));
|
||||
hdl = dds_entity_init (&pub->m_entity, &par->m_entity, DDS_KIND_PUBLISHER, new_qos, listener, DDS_PUBLISHER_STATUS_MASK);
|
||||
hdl = dds_entity_init (&pub->m_entity, &par->m_entity, DDS_KIND_PUBLISHER, implicit, 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);
|
||||
return hdl;
|
||||
}
|
||||
|
||||
dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qos, const dds_listener_t *listener)
|
||||
{
|
||||
dds_participant *par;
|
||||
dds_entity_t hdl;
|
||||
dds_return_t ret;
|
||||
if ((ret = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK)
|
||||
return ret;
|
||||
hdl = dds__create_publisher_l (par, false, qos, listener);
|
||||
dds_participant_unlock (par);
|
||||
return hdl;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ dds_readcond *dds_create_readcond (dds_reader *rd, dds_entity_kind_t kind, uint3
|
|||
{
|
||||
dds_readcond *cond = dds_alloc (sizeof (*cond));
|
||||
assert ((kind == DDS_KIND_COND_READ && filter == 0) || (kind == DDS_KIND_COND_QUERY && filter != 0));
|
||||
(void) dds_entity_init (&cond->m_entity, &rd->m_entity, kind, NULL, NULL, 0);
|
||||
(void) dds_entity_init (&cond->m_entity, &rd->m_entity, kind, false, NULL, NULL, 0);
|
||||
cond->m_entity.m_iid = ddsi_iid_gen ();
|
||||
dds_entity_register_child (&rd->m_entity, &cond->m_entity);
|
||||
cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE;
|
||||
|
|
|
@ -62,11 +62,11 @@ 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;
|
||||
(void) dds_delete (rd->m_topic->m_entity.m_hdllink.hdl);
|
||||
dds_free (rd->m_loan);
|
||||
thread_state_awake (lookup_thread_state (), &e->m_domain->gv);
|
||||
dds_rhc_free (rd->m_rhc);
|
||||
thread_state_asleep (lookup_thread_state ());
|
||||
dds_entity_drop_ref (&rd->m_topic->m_entity);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
|
@ -150,6 +150,7 @@ 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);
|
||||
}
|
||||
|
@ -232,16 +233,47 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data)
|
|||
}
|
||||
case DDS_LIVELINESS_CHANGED_STATUS_ID: {
|
||||
struct dds_liveliness_changed_status * const st = vst = &rd->m_liveliness_changed_status;
|
||||
if (data->add) {
|
||||
st->alive_count++;
|
||||
st->alive_count_change++;
|
||||
if (st->not_alive_count > 0) {
|
||||
DDSRT_STATIC_ASSERT ((uint32_t) LIVELINESS_CHANGED_ADD_ALIVE == 0 &&
|
||||
LIVELINESS_CHANGED_ADD_ALIVE < LIVELINESS_CHANGED_ADD_NOT_ALIVE &&
|
||||
LIVELINESS_CHANGED_ADD_NOT_ALIVE < LIVELINESS_CHANGED_REMOVE_NOT_ALIVE &&
|
||||
LIVELINESS_CHANGED_REMOVE_NOT_ALIVE < LIVELINESS_CHANGED_REMOVE_ALIVE &&
|
||||
LIVELINESS_CHANGED_REMOVE_ALIVE < LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE &&
|
||||
LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE < LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE &&
|
||||
LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE < LIVELINESS_CHANGED_TWITCH &&
|
||||
(uint32_t) LIVELINESS_CHANGED_TWITCH < UINT32_MAX);
|
||||
assert (data->extra <= (uint32_t) LIVELINESS_CHANGED_TWITCH);
|
||||
switch ((enum liveliness_changed_data_extra) data->extra)
|
||||
{
|
||||
case LIVELINESS_CHANGED_ADD_ALIVE:
|
||||
st->alive_count++;
|
||||
st->alive_count_change++;
|
||||
break;
|
||||
case LIVELINESS_CHANGED_ADD_NOT_ALIVE:
|
||||
st->not_alive_count++;
|
||||
st->not_alive_count_change++;
|
||||
break;
|
||||
case LIVELINESS_CHANGED_REMOVE_NOT_ALIVE:
|
||||
st->not_alive_count--;
|
||||
}
|
||||
} else {
|
||||
st->alive_count--;
|
||||
st->not_alive_count++;
|
||||
st->not_alive_count_change++;
|
||||
st->not_alive_count_change--;
|
||||
break;
|
||||
case LIVELINESS_CHANGED_REMOVE_ALIVE:
|
||||
st->alive_count--;
|
||||
st->alive_count_change--;
|
||||
break;
|
||||
case LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE:
|
||||
st->alive_count--;
|
||||
st->alive_count_change--;
|
||||
st->not_alive_count++;
|
||||
st->not_alive_count_change++;
|
||||
break;
|
||||
case LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE:
|
||||
st->not_alive_count--;
|
||||
st->not_alive_count_change--;
|
||||
st->alive_count++;
|
||||
st->alive_count_change++;
|
||||
break;
|
||||
case LIVELINESS_CHANGED_TWITCH:
|
||||
break;
|
||||
}
|
||||
st->last_publication_handle = data->handle;
|
||||
invoke = (lst->on_liveliness_changed != 0);
|
||||
|
@ -332,36 +364,37 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe
|
|||
case DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION:
|
||||
internal_topic = true;
|
||||
subscriber = dds__get_builtin_subscriber (participant_or_subscriber);
|
||||
if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK)
|
||||
return ret;
|
||||
t = dds__get_builtin_topic (subscriber, topic);
|
||||
break;
|
||||
|
||||
default: {
|
||||
dds_entity *p_or_s;
|
||||
if ((ret = dds_entity_pin (participant_or_subscriber, &p_or_s)) != DDS_RETCODE_OK)
|
||||
if ((ret = dds_entity_lock (participant_or_subscriber, DDS_KIND_DONTCARE, &p_or_s)) != DDS_RETCODE_OK)
|
||||
return ret;
|
||||
if (dds_entity_kind (p_or_s) == DDS_KIND_PARTICIPANT)
|
||||
subscriber = dds_create_subscriber (participant_or_subscriber, qos, NULL);
|
||||
else
|
||||
subscriber = participant_or_subscriber;
|
||||
dds_entity_unpin (p_or_s);
|
||||
switch (dds_entity_kind (p_or_s))
|
||||
{
|
||||
case DDS_KIND_SUBSCRIBER:
|
||||
subscriber = participant_or_subscriber;
|
||||
sub = (dds_subscriber *) p_or_s;
|
||||
break;
|
||||
case DDS_KIND_PARTICIPANT:
|
||||
subscriber = dds__create_subscriber_l ((dds_participant *) p_or_s, true, qos, NULL);
|
||||
dds_entity_unlock (p_or_s);
|
||||
if ((ret = dds_subscriber_lock (subscriber, &sub)) < 0)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
dds_entity_unlock (p_or_s);
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
}
|
||||
internal_topic = false;
|
||||
t = topic;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK)
|
||||
{
|
||||
reader = ret;
|
||||
goto err_sub_lock;
|
||||
}
|
||||
|
||||
if (subscriber != participant_or_subscriber && !internal_topic)
|
||||
{
|
||||
/* Delete implicit subscriber if reader creation fails */
|
||||
sub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT;
|
||||
}
|
||||
|
||||
if ((ret = dds_topic_lock (t, &tp)) != DDS_RETCODE_OK)
|
||||
{
|
||||
reader = ret;
|
||||
|
@ -405,7 +438,7 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe
|
|||
|
||||
/* 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);
|
||||
reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, false, rqos, listener, DDS_READER_STATUS_MASK);
|
||||
rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED;
|
||||
rd->m_topic = tp;
|
||||
rd->m_rhc = rhc ? rhc : dds_rhc_default_new (rd, tp->m_stopic);
|
||||
|
@ -431,12 +464,6 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe
|
|||
|
||||
dds_topic_unlock (tp);
|
||||
dds_subscriber_unlock (sub);
|
||||
|
||||
if (internal_topic)
|
||||
{
|
||||
/* If topic is builtin, then the topic entity is local and should be deleted because the application won't. */
|
||||
dds_delete (t);
|
||||
}
|
||||
return reader;
|
||||
|
||||
err_bad_qos:
|
||||
|
@ -446,9 +473,6 @@ err_tp_lock:
|
|||
dds_subscriber_unlock (sub);
|
||||
if ((sub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0)
|
||||
(void) dds_delete (subscriber);
|
||||
err_sub_lock:
|
||||
if (internal_topic)
|
||||
dds_delete (t);
|
||||
return reader;
|
||||
}
|
||||
|
||||
|
|
|
@ -1110,7 +1110,7 @@ static int rhc_unregister_isreg_w_sideeffects (struct dds_rhc_default *rhc, cons
|
|||
if (inst->wrcount == 2 && inst->wr_iid_islive && inst->wr_iid != wr_iid)
|
||||
{
|
||||
TRACE (",delreg(remain)");
|
||||
lwregs_delete (&rhc->registrations, inst->iid, inst->wr_iid);
|
||||
(void) lwregs_delete (&rhc->registrations, inst->iid, inst->wr_iid);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -1627,7 +1627,7 @@ static void dds_rhc_default_unregister_wr (struct dds_rhc_default * __restrict r
|
|||
}
|
||||
}
|
||||
|
||||
dds_rhc_unregister (rhc, inst, wrinfo, inst->tstamp, &post, &trig_qc);
|
||||
(void) dds_rhc_unregister (rhc, inst, wrinfo, inst->tstamp, &post, &trig_qc);
|
||||
|
||||
TRACE ("\n");
|
||||
|
||||
|
@ -2394,7 +2394,7 @@ static bool dds_rhc_default_add_readcondition (struct dds_rhc_default *rhc, dds_
|
|||
ddsrt_atomic_st32 (&cond->m_entity.m_status.m_trigger, trigger);
|
||||
dds_entity_status_signal (&cond->m_entity, DDS_DATA_AVAILABLE_STATUS);
|
||||
}
|
||||
|
||||
|
||||
TRACE ("add_readcondition(%p, %"PRIx32", %"PRIx32", %"PRIx32") => %p qminv %"PRIx32" ; rhc %"PRIu32" conds\n",
|
||||
(void *) rhc, cond->m_sample_states, cond->m_view_states,
|
||||
cond->m_instance_states, (void *) cond, cond->m_qminv, rhc->nconds);
|
||||
|
|
|
@ -256,24 +256,25 @@ size_t dds_stream_check_optimize (const dds_topic_descriptor_t * __restrict desc
|
|||
return dds_stream_check_optimize1 (desc);
|
||||
}
|
||||
|
||||
static char *dds_stream_reuse_string (dds_istream_t * __restrict is, char * __restrict str, const uint32_t bound)
|
||||
static void dds_stream_reuse_string_bound (dds_istream_t * __restrict is, char * __restrict str, const uint32_t bound)
|
||||
{
|
||||
const uint32_t length = dds_is_get4 (is);
|
||||
const void *src = is->m_buffer + is->m_index;
|
||||
if (bound)
|
||||
{
|
||||
/* FIXME: validation now rejects data containing an oversize bounded string,
|
||||
so this check is superfluous, but perhaps rejecting such a sample is the
|
||||
wrong thing to do */
|
||||
assert (str != NULL);
|
||||
memcpy (str, src, length > bound ? bound : length);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (str == NULL || strlen (str) + 1 < length)
|
||||
str = dds_realloc (str, length);
|
||||
memcpy (str, src, length);
|
||||
}
|
||||
/* FIXME: validation now rejects data containing an oversize bounded string,
|
||||
so this check is superfluous, but perhaps rejecting such a sample is the
|
||||
wrong thing to do */
|
||||
assert (str != NULL);
|
||||
memcpy (str, src, length > bound ? bound : length);
|
||||
is->m_index += length;
|
||||
}
|
||||
|
||||
static char *dds_stream_reuse_string (dds_istream_t * __restrict is, char * __restrict str)
|
||||
{
|
||||
const uint32_t length = dds_is_get4 (is);
|
||||
const void *src = is->m_buffer + is->m_index;
|
||||
if (str == NULL || strlen (str) + 1 < length)
|
||||
str = dds_realloc (str, length);
|
||||
memcpy (str, src, length);
|
||||
is->m_index += length;
|
||||
return str;
|
||||
}
|
||||
|
@ -596,7 +597,7 @@ static const uint32_t *dds_stream_read_seq (dds_istream_t * __restrict is, char
|
|||
seq->_length = (num <= seq->_maximum) ? num : seq->_maximum;
|
||||
char **ptr = (char **) seq->_buffer;
|
||||
for (uint32_t i = 0; i < seq->_length; i++)
|
||||
ptr[i] = dds_stream_reuse_string (is, ptr[i], 0);
|
||||
ptr[i] = dds_stream_reuse_string (is, ptr[i]);
|
||||
for (uint32_t i = seq->_length; i < num; i++)
|
||||
dds_stream_skip_string (is);
|
||||
return ops + 2;
|
||||
|
@ -607,7 +608,7 @@ static const uint32_t *dds_stream_read_seq (dds_istream_t * __restrict is, char
|
|||
seq->_length = (num <= seq->_maximum) ? num : seq->_maximum;
|
||||
char *ptr = (char *) seq->_buffer;
|
||||
for (uint32_t i = 0; i < seq->_length; i++)
|
||||
(void) dds_stream_reuse_string (is, ptr + i * elem_size, elem_size);
|
||||
dds_stream_reuse_string_bound (is, ptr + i * elem_size, elem_size);
|
||||
for (uint32_t i = seq->_length; i < num; i++)
|
||||
dds_stream_skip_string (is);
|
||||
return ops + 3;
|
||||
|
@ -641,14 +642,14 @@ static const uint32_t *dds_stream_read_arr (dds_istream_t * __restrict is, char
|
|||
case DDS_OP_VAL_STR: {
|
||||
char **ptr = (char **) addr;
|
||||
for (uint32_t i = 0; i < num; i++)
|
||||
ptr[i] = dds_stream_reuse_string (is, ptr[i], 0);
|
||||
ptr[i] = dds_stream_reuse_string (is, ptr[i]);
|
||||
return ops + 3;
|
||||
}
|
||||
case DDS_OP_VAL_BST: {
|
||||
char *ptr = (char *) addr;
|
||||
const uint32_t elem_size = ops[4];
|
||||
for (uint32_t i = 0; i < num; i++)
|
||||
(void) dds_stream_reuse_string (is, ptr + i * elem_size, elem_size);
|
||||
dds_stream_reuse_string_bound (is, ptr + i * elem_size, elem_size);
|
||||
return ops + 5;
|
||||
}
|
||||
case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: {
|
||||
|
@ -685,7 +686,7 @@ static const uint32_t *dds_stream_read_uni (dds_istream_t * __restrict is, char
|
|||
case DDS_OP_VAL_2BY: *((uint16_t *) valaddr) = dds_is_get2 (is); break;
|
||||
case DDS_OP_VAL_4BY: *((uint32_t *) valaddr) = dds_is_get4 (is); break;
|
||||
case DDS_OP_VAL_8BY: *((uint64_t *) valaddr) = dds_is_get8 (is); break;
|
||||
case DDS_OP_VAL_STR: *(char **) valaddr = dds_stream_reuse_string (is, *((char **) valaddr), 0); break;
|
||||
case DDS_OP_VAL_STR: *(char **) valaddr = dds_stream_reuse_string (is, *((char **) valaddr)); break;
|
||||
case DDS_OP_VAL_BST: case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU:
|
||||
dds_stream_read (is, valaddr, jeq_op + DDS_OP_ADR_JSR (jeq_op[0]));
|
||||
break;
|
||||
|
@ -709,8 +710,8 @@ static void dds_stream_read (dds_istream_t * __restrict is, char * __restrict da
|
|||
case DDS_OP_VAL_2BY: *((uint16_t *) addr) = dds_is_get2 (is); ops += 2; break;
|
||||
case DDS_OP_VAL_4BY: *((uint32_t *) addr) = dds_is_get4 (is); ops += 2; break;
|
||||
case DDS_OP_VAL_8BY: *((uint64_t *) addr) = dds_is_get8 (is); ops += 2; break;
|
||||
case DDS_OP_VAL_STR: *((char **) addr) = dds_stream_reuse_string (is, *((char **) addr), 0); ops += 2; break;
|
||||
case DDS_OP_VAL_BST: dds_stream_reuse_string (is, (char *) addr, ops[2]); ops += 3; break;
|
||||
case DDS_OP_VAL_STR: *((char **) addr) = dds_stream_reuse_string (is, *((char **) addr)); ops += 2; break;
|
||||
case DDS_OP_VAL_BST: dds_stream_reuse_string_bound (is, (char *) addr, ops[2]); ops += 3; break;
|
||||
case DDS_OP_VAL_SEQ: ops = dds_stream_read_seq (is, addr, ops, insn); break;
|
||||
case DDS_OP_VAL_ARR: ops = dds_stream_read_arr (is, addr, ops, insn); break;
|
||||
case DDS_OP_VAL_UNI: ops = dds_stream_read_uni (is, addr, data, ops, insn); break;
|
||||
|
@ -1126,8 +1127,8 @@ void dds_stream_read_key (dds_istream_t * __restrict is, char * __restrict sampl
|
|||
case DDS_OP_VAL_2BY: *((uint16_t *) dst) = dds_is_get2 (is); break;
|
||||
case DDS_OP_VAL_4BY: *((uint32_t *) dst) = dds_is_get4 (is); break;
|
||||
case DDS_OP_VAL_8BY: *((uint64_t *) dst) = dds_is_get8 (is); break;
|
||||
case DDS_OP_VAL_STR: *((char **) dst) = dds_stream_reuse_string (is, *((char **) dst), 0); break;
|
||||
case DDS_OP_VAL_BST: dds_stream_reuse_string (is, dst, op[2]); break;
|
||||
case DDS_OP_VAL_STR: *((char **) dst) = dds_stream_reuse_string (is, *((char **) dst)); break;
|
||||
case DDS_OP_VAL_BST: dds_stream_reuse_string_bound (is, dst, op[2]); break;
|
||||
case DDS_OP_VAL_ARR:
|
||||
dds_is_get_bytes (is, dst, op[2], get_type_size (DDS_OP_SUBTYPE (*op)));
|
||||
break;
|
||||
|
@ -1728,16 +1729,16 @@ static const uint32_t *prtf_seq (char * __restrict *buf, size_t *bufsize, dds_is
|
|||
num = dds_is_get4 (is);
|
||||
if (num == 0)
|
||||
{
|
||||
prtf (buf, bufsize, "{}");
|
||||
(void) 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);
|
||||
(void) 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);
|
||||
(void) 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]);
|
||||
|
@ -1745,10 +1746,10 @@ static const uint32_t *prtf_seq (char * __restrict *buf, size_t *bufsize, dds_is
|
|||
bool cont = prtf (buf, bufsize, "{");
|
||||
for (uint32_t i = 0; cont && i < num; i++)
|
||||
{
|
||||
if (i > 0) prtf (buf, bufsize, ",");
|
||||
if (i > 0) (void) prtf (buf, bufsize, ",");
|
||||
cont = dds_stream_print_sample1 (buf, bufsize, is, jsr_ops, subtype == DDS_OP_VAL_STU);
|
||||
}
|
||||
prtf (buf, bufsize, "}");
|
||||
(void) prtf (buf, bufsize, "}");
|
||||
return ops + (jmp ? jmp : 4); /* FIXME: why would jmp be 0? */
|
||||
}
|
||||
}
|
||||
|
@ -1762,10 +1763,10 @@ static const uint32_t *prtf_arr (char * __restrict *buf, size_t *bufsize, dds_is
|
|||
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);
|
||||
(void) 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);
|
||||
(void) 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]);
|
||||
|
@ -1773,10 +1774,10 @@ static const uint32_t *prtf_arr (char * __restrict *buf, size_t *bufsize, dds_is
|
|||
bool cont = prtf (buf, bufsize, "{");
|
||||
for (uint32_t i = 0; cont && i < num; i++)
|
||||
{
|
||||
if (i > 0) prtf (buf, bufsize, ",");
|
||||
if (i > 0) (void) prtf (buf, bufsize, ",");
|
||||
cont = dds_stream_print_sample1 (buf, bufsize, is, jsr_ops, subtype == DDS_OP_VAL_STU);
|
||||
}
|
||||
prtf (buf, bufsize, "}");
|
||||
(void) prtf (buf, bufsize, "}");
|
||||
return ops + (jmp ? jmp : 5);
|
||||
}
|
||||
}
|
||||
|
@ -1787,7 +1788,7 @@ static const uint32_t *prtf_uni (char * __restrict *buf, size_t *bufsize, dds_is
|
|||
{
|
||||
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);
|
||||
(void) prtf (buf, bufsize, "%"PRIu32":", disc);
|
||||
ops += DDS_OP_ADR_JMP (ops[3]);
|
||||
if (jeq_op)
|
||||
{
|
||||
|
@ -1796,10 +1797,10 @@ static const uint32_t *prtf_uni (char * __restrict *buf, size_t *bufsize, dds_is
|
|||
{
|
||||
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);
|
||||
(void) 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);
|
||||
(void) dds_stream_print_sample1 (buf, bufsize, is, jeq_op + DDS_OP_ADR_JSR (jeq_op[0]), valtype == DDS_OP_VAL_STU);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1812,11 +1813,11 @@ static bool dds_stream_print_sample1 (char * __restrict *buf, size_t * __restric
|
|||
bool cont = true;
|
||||
bool needs_comma = false;
|
||||
if (add_braces)
|
||||
prtf (buf, bufsize, "{");
|
||||
(void) prtf (buf, bufsize, "{");
|
||||
while (cont && (insn = *ops) != DDS_OP_RTS)
|
||||
{
|
||||
if (needs_comma)
|
||||
prtf (buf, bufsize, ",");
|
||||
(void) prtf (buf, bufsize, ",");
|
||||
needs_comma = true;
|
||||
switch (DDS_OP (insn))
|
||||
{
|
||||
|
@ -1859,13 +1860,13 @@ static bool dds_stream_print_sample1 (char * __restrict *buf, size_t * __restric
|
|||
}
|
||||
}
|
||||
if (add_braces)
|
||||
prtf (buf, bufsize, "}");
|
||||
(void) 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);
|
||||
(void) dds_stream_print_sample1 (&buf, &bufsize, is, topic->type->m_ops, true);
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
|
@ -1891,7 +1892,7 @@ size_t dds_stream_print_key (dds_istream_t * __restrict is, const struct ddsi_se
|
|||
break;
|
||||
}
|
||||
}
|
||||
prtf (&buf, &bufsize, "}");
|
||||
(void) prtf (&buf, &bufsize, "}");
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ const struct dds_entity_deriver dds_entity_deriver_subscriber = {
|
|||
.validate_status = dds_subscriber_status_validate
|
||||
};
|
||||
|
||||
dds_entity_t dds__create_subscriber_l (dds_participant *participant, const dds_qos_t *qos, const dds_listener_t *listener)
|
||||
dds_entity_t dds__create_subscriber_l (dds_participant *participant, bool implicit, const dds_qos_t *qos, const dds_listener_t *listener)
|
||||
{
|
||||
/* participant entity lock must be held */
|
||||
dds_subscriber *sub;
|
||||
|
@ -64,7 +64,7 @@ dds_entity_t dds__create_subscriber_l (dds_participant *participant, const dds_q
|
|||
}
|
||||
|
||||
sub = dds_alloc (sizeof (*sub));
|
||||
subscriber = dds_entity_init (&sub->m_entity, &participant->m_entity, DDS_KIND_SUBSCRIBER, new_qos, listener, DDS_SUBSCRIBER_STATUS_MASK);
|
||||
subscriber = dds_entity_init (&sub->m_entity, &participant->m_entity, DDS_KIND_SUBSCRIBER, implicit, 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);
|
||||
|
@ -78,7 +78,7 @@ dds_entity_t dds_create_subscriber (dds_entity_t participant, const dds_qos_t *q
|
|||
dds_return_t ret;
|
||||
if ((ret = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK)
|
||||
return ret;
|
||||
hdl = dds__create_subscriber_l (par, qos, listener);
|
||||
hdl = dds__create_subscriber_l (par, false, qos, listener);
|
||||
dds_participant_unlock (par);
|
||||
return hdl;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "dds/ddsi/ddsi_iid.h"
|
||||
#include "dds/ddsi/q_plist.h"
|
||||
#include "dds/ddsi/q_globals.h"
|
||||
#include "dds__serdata_builtintopic.h"
|
||||
|
||||
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_topic)
|
||||
|
||||
|
@ -135,12 +136,16 @@ static bool dds_find_topic_check_and_add_ref (dds_entity_t participant, dds_enti
|
|||
ret = false;
|
||||
else
|
||||
{
|
||||
/* FIXME: calling addref is wrong because the Cyclone library has no
|
||||
knowledge of the reference and hence simply deleting the participant
|
||||
won't make the ref count drop to 0. On the other hand, the DDS spec
|
||||
says find_topic (and a second call to create_topic) return a new
|
||||
proxy that must separately be deleted. */
|
||||
dds_entity_add_ref_locked (&tp->m_entity);
|
||||
/* Simply return the same topic, though that is different to the spirit
|
||||
of the DDS specification, which gives you a unique copy. Giving that
|
||||
unique copy means there potentially many versions of exactly the same
|
||||
topic around, and that two entities can be dealing with the same data
|
||||
even though they have different topics objects (though with the same
|
||||
name). That I find a confusing model.
|
||||
|
||||
As far as I can tell, the only benefit is the ability to set different
|
||||
listeners on the various copies of the topic. And that seems to be a
|
||||
really small benefit. */
|
||||
ret = true;
|
||||
}
|
||||
dds_topic_unlock (tp);
|
||||
|
@ -259,12 +264,7 @@ static dds_return_t create_topic_topic_arbitrary_check_sertopic (dds_entity_t pa
|
|||
ret = DDS_RETCODE_INCONSISTENT_POLICY;
|
||||
else
|
||||
{
|
||||
/* FIXME: calling addref is wrong because the Cyclone library has no
|
||||
knowledge of the reference and hence simply deleting the participant
|
||||
won't make the ref count drop to 0. On the other hand, the DDS spec
|
||||
says find_topic (and a second call to create_topic) return a new
|
||||
proxy that must separately be deleted. */
|
||||
dds_entity_add_ref_locked (&tp->m_entity);
|
||||
/* See dds_find_topic_check_and_add_ref */
|
||||
ret = DDS_RETCODE_OK;
|
||||
}
|
||||
dds_topic_unlock (tp);
|
||||
|
@ -429,7 +429,8 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s
|
|||
|
||||
/* Create topic */
|
||||
top = dds_alloc (sizeof (*top));
|
||||
hdl = dds_entity_init (&top->m_entity, &par->m_entity, DDS_KIND_TOPIC, new_qos, listener, DDS_TOPIC_STATUS_MASK);
|
||||
/* FIXME: setting "implicit" based on sertopic->ops is a hack */
|
||||
hdl = dds_entity_init (&top->m_entity, &par->m_entity, DDS_KIND_TOPIC, (sertopic->ops == &ddsi_sertopic_ops_builtintopic), new_qos, listener, DDS_TOPIC_STATUS_MASK);
|
||||
top->m_entity.m_iid = ddsi_iid_gen ();
|
||||
dds_entity_register_child (&par->m_entity, &top->m_entity);
|
||||
top->m_stopic = sertopic;
|
||||
|
|
|
@ -166,7 +166,7 @@ dds_entity_t dds_create_waitset (dds_entity_t owner)
|
|||
}
|
||||
|
||||
dds_waitset *waitset = dds_alloc (sizeof (*waitset));
|
||||
dds_entity_t hdl = dds_entity_init (&waitset->m_entity, e, DDS_KIND_WAITSET, NULL, NULL, 0);
|
||||
dds_entity_t hdl = dds_entity_init (&waitset->m_entity, e, DDS_KIND_WAITSET, false, NULL, NULL, 0);
|
||||
ddsrt_mutex_init (&waitset->wait_lock);
|
||||
ddsrt_cond_init (&waitset->wait_cond);
|
||||
waitset->m_entity.m_iid = ddsi_iid_gen ();
|
||||
|
@ -176,13 +176,13 @@ dds_entity_t dds_create_waitset (dds_entity_t owner)
|
|||
waitset->entities = NULL;
|
||||
dds_entity_init_complete (&waitset->m_entity);
|
||||
dds_entity_unlock (e);
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
dds_entity_unpin_and_drop_ref (&dds_global.m_entity);
|
||||
return hdl;
|
||||
|
||||
err_entity_kind:
|
||||
dds_entity_unlock (e);
|
||||
err_entity_lock:
|
||||
dds_delete_impl_pinned (&dds_global.m_entity, DIS_EXPLICIT);
|
||||
dds_entity_unpin_and_drop_ref (&dds_global.m_entity);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -209,13 +209,12 @@ static dds_return_t dds_writer_delete (dds_entity *e) ddsrt_nonnull_all;
|
|||
static dds_return_t dds_writer_delete (dds_entity *e)
|
||||
{
|
||||
dds_writer * const wr = (dds_writer *) e;
|
||||
dds_return_t ret;
|
||||
/* FIXME: not freeing WHC here because it is owned by the DDSI entity */
|
||||
thread_state_awake (lookup_thread_state (), &e->m_domain->gv);
|
||||
nn_xpack_free (wr->m_xp);
|
||||
thread_state_asleep (lookup_thread_state ());
|
||||
ret = dds_delete (wr->m_topic->m_entity.m_hdllink.hdl);
|
||||
return ret;
|
||||
dds_entity_drop_ref (&wr->m_topic->m_entity);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
static dds_return_t dds_writer_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
|
||||
|
@ -277,21 +276,27 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
|
|||
|
||||
{
|
||||
dds_entity *p_or_p;
|
||||
if ((rc = dds_entity_pin (participant_or_publisher, &p_or_p)) != DDS_RETCODE_OK)
|
||||
if ((rc = dds_entity_lock (participant_or_publisher, DDS_KIND_DONTCARE, &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);
|
||||
else
|
||||
publisher = participant_or_publisher;
|
||||
dds_entity_unpin (p_or_p);
|
||||
switch (dds_entity_kind (p_or_p))
|
||||
{
|
||||
case DDS_KIND_PUBLISHER:
|
||||
publisher = participant_or_publisher;
|
||||
pub = (dds_publisher *) p_or_p;
|
||||
break;
|
||||
case DDS_KIND_PARTICIPANT:
|
||||
publisher = dds__create_publisher_l ((dds_participant *) p_or_p, true, qos, NULL);
|
||||
dds_entity_unlock (p_or_p);
|
||||
if ((rc = dds_publisher_lock (publisher, &pub)) < 0)
|
||||
return rc;
|
||||
break;
|
||||
default:
|
||||
dds_entity_unlock (p_or_p);
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rc = dds_publisher_lock (publisher, &pub)) != DDS_RETCODE_OK)
|
||||
return rc;
|
||||
|
||||
ddsi_tran_conn_t conn = pub->m_entity.m_domain->gv.data_conn_uc;
|
||||
if (publisher != participant_or_publisher)
|
||||
pub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT;
|
||||
|
||||
if ((rc = dds_topic_lock (topic, &tp)) != DDS_RETCODE_OK)
|
||||
goto err_tp_lock;
|
||||
|
@ -322,7 +327,7 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
|
|||
|
||||
/* Create writer */
|
||||
wr = dds_alloc (sizeof (*wr));
|
||||
writer = dds_entity_init (&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK);
|
||||
writer = dds_entity_init (&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, false, wqos, listener, DDS_WRITER_STATUS_MASK);
|
||||
|
||||
wr->m_topic = tp;
|
||||
dds_entity_add_ref_locked (&tp->m_entity);
|
||||
|
|
|
@ -21,12 +21,14 @@ set(ddsc_test_sources
|
|||
"config.c"
|
||||
"dispose.c"
|
||||
"domain.c"
|
||||
"domain_torture.c"
|
||||
"entity_api.c"
|
||||
"entity_hierarchy.c"
|
||||
"entity_status.c"
|
||||
"err.c"
|
||||
"instance_get_key.c"
|
||||
"listener.c"
|
||||
"liveliness.c"
|
||||
"participant.c"
|
||||
"publisher.c"
|
||||
"qos.c"
|
||||
|
@ -55,7 +57,8 @@ add_cunit_executable(cunit_ddsc ${ddsc_test_sources})
|
|||
target_include_directories(
|
||||
cunit_ddsc PRIVATE
|
||||
"$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/src/include/>"
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../ddsi/include/>")
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../ddsc/src>"
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../ddsi/include>")
|
||||
target_link_libraries(cunit_ddsc PRIVATE RoundTrip Space TypesArrayKey ddsc)
|
||||
|
||||
# Setup environment for config-tests
|
||||
|
|
|
@ -27,98 +27,62 @@
|
|||
#define URI_VARIABLE DDS_PROJECT_NAME_NOSPACE_CAPS"_URI"
|
||||
#define MAX_PARTICIPANTS_VARIABLE "MAX_PARTICIPANTS"
|
||||
|
||||
static void config__check_env(
|
||||
const char * env_variable,
|
||||
const char * expected_value)
|
||||
static void config__check_env (const char *env_variable, const char *expected_value)
|
||||
{
|
||||
char * env_uri = NULL;
|
||||
ddsrt_getenv(env_variable, &env_uri);
|
||||
#if 0
|
||||
const char * const env_not_set = "Environment variable '%s' isn't set. This needs to be set to '%s' for this test to run.";
|
||||
const char * const env_not_as_expected = "Environment variable '%s' has an unexpected value: '%s' (expected: '%s')";
|
||||
#endif
|
||||
|
||||
char *env_uri = NULL;
|
||||
ddsrt_getenv (env_variable, &env_uri);
|
||||
#ifdef FORCE_ENV
|
||||
{
|
||||
bool env_ok;
|
||||
|
||||
if (env_uri == NULL)
|
||||
env_ok = false;
|
||||
else if (strncmp (env_uri, expected_value, strlen (expected_value)) != 0)
|
||||
env_ok = false;
|
||||
else
|
||||
env_ok = true;
|
||||
|
||||
if (!env_ok)
|
||||
{
|
||||
bool env_ok;
|
||||
|
||||
if ( env_uri == NULL ) {
|
||||
env_ok = false;
|
||||
} else if ( strncmp(env_uri, expected_value, strlen(expected_value)) != 0 ) {
|
||||
env_ok = false;
|
||||
} else {
|
||||
env_ok = true;
|
||||
}
|
||||
|
||||
if ( !env_ok ) {
|
||||
dds_return_t r;
|
||||
|
||||
r = ddsrt_setenv(env_variable, expected_value);
|
||||
CU_ASSERT_EQUAL_FATAL(r, DDS_RETCODE_OK);
|
||||
}
|
||||
dds_return_t r = ddsrt_setenv (env_variable, expected_value);
|
||||
CU_ASSERT_EQUAL_FATAL (r, DDS_RETCODE_OK);
|
||||
}
|
||||
}
|
||||
#else
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(env_uri);
|
||||
CU_ASSERT_STRING_EQUAL_FATAL(env_uri, expected_value);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL (env_uri);
|
||||
CU_ASSERT_STRING_EQUAL_FATAL (env_uri, expected_value);
|
||||
#endif /* FORCE_ENV */
|
||||
|
||||
}
|
||||
|
||||
CU_Test(ddsc_config, simple_udp, .init = ddsrt_init, .fini = ddsrt_fini) {
|
||||
|
||||
dds_entity_t participant;
|
||||
|
||||
config__check_env(URI_VARIABLE, CONFIG_ENV_SIMPLE_UDP);
|
||||
config__check_env(MAX_PARTICIPANTS_VARIABLE, CONFIG_ENV_MAX_PARTICIPANTS);
|
||||
|
||||
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
|
||||
|
||||
CU_ASSERT_FATAL(participant> 0);
|
||||
|
||||
dds_delete(participant);
|
||||
CU_Test (ddsc_config, simple_udp, .init = ddsrt_init, .fini = ddsrt_fini)
|
||||
{
|
||||
dds_entity_t participant;
|
||||
config__check_env (URI_VARIABLE, CONFIG_ENV_SIMPLE_UDP);
|
||||
config__check_env (MAX_PARTICIPANTS_VARIABLE, CONFIG_ENV_MAX_PARTICIPANTS);
|
||||
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
|
||||
CU_ASSERT_FATAL (participant> 0);
|
||||
dds_delete (participant);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_config, user_config, .init = ddsrt_init, .fini = ddsrt_fini) {
|
||||
CU_Test (ddsc_config, user_config, .init = ddsrt_init, .fini = ddsrt_fini)
|
||||
{
|
||||
dds_entity_t domain;
|
||||
domain = dds_create_domain (1,
|
||||
"<"DDS_PROJECT_NAME"><Domain><Id>any</Id></Domain>"
|
||||
"<DDSI2E><Internal><MaxParticipants>2</MaxParticipants></Internal></DDSI2E>"
|
||||
"</"DDS_PROJECT_NAME">");
|
||||
CU_ASSERT_FATAL (domain > 0);
|
||||
|
||||
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_create_participant (1, NULL, NULL);
|
||||
CU_ASSERT_FATAL(participant_1 > 0);
|
||||
|
||||
dds_entity_t participant_1;
|
||||
dds_entity_t participant_2;
|
||||
dds_entity_t participant_3;
|
||||
dds_entity_t participant_2 = dds_create_participant (1, NULL, NULL);
|
||||
CU_ASSERT_FATAL(participant_2 > 0);
|
||||
|
||||
participant_1 = dds_create_participant(1, NULL, NULL);
|
||||
dds_entity_t participant_3 = dds_create_participant (1, NULL, NULL);
|
||||
CU_ASSERT(participant_3 < 0);
|
||||
|
||||
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);
|
||||
dds_delete (domain);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -823,4 +787,5 @@ CU_Test(ddsc_config, security_qos_invalid, .init = ddsrt_init, .fini = ddsrt_fin
|
|||
#endif
|
||||
dds_set_log_sink(NULL, NULL);
|
||||
dds_set_trace_sink(NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xml-model href="https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd"
|
||||
schematypens="http://www.w3.org/2001/XMLSchema" ?>
|
||||
<!--
|
||||
Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
|
||||
|
@ -10,10 +12,10 @@
|
|||
|
||||
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
-->
|
||||
<CycloneDDS>
|
||||
<CycloneDDS xmlns="https://cdds.io/config">
|
||||
<!-- Simple config-file for testing whether a config-file can be picked up
|
||||
correctly. -->
|
||||
<Domain id="3">
|
||||
<Domain Id="3">
|
||||
<General>
|
||||
<NetworkInterfaceAddress>127.0.0.1</NetworkInterfaceAddress>
|
||||
<AllowMulticast>true</AllowMulticast>
|
||||
|
@ -28,8 +30,8 @@
|
|||
</Tracing>
|
||||
<Internal>
|
||||
<MaxParticipants>${MAX_PARTICIPANTS}</MaxParticipants>
|
||||
<HeartbeatInterval max="10 s"> 100 ms </HeartbeatInterval>
|
||||
<RediscoveryBlacklistDuration></RediscoveryBlacklistDuration>
|
||||
<HeartbeatInterval>100 ms</HeartbeatInterval>
|
||||
<RediscoveryBlacklistDuration>10s</RediscoveryBlacklistDuration>
|
||||
</Internal>
|
||||
</Domain>
|
||||
</CycloneDDS>
|
||||
|
|
|
@ -140,3 +140,150 @@ CU_Test(ddsc_domain, delete_cyclonedds)
|
|||
rc = dds_get_domainid (pp[0], &did);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_domain_create, valid)
|
||||
{
|
||||
dds_return_t ret;
|
||||
dds_domainid_t did;
|
||||
dds_entity_t domain;
|
||||
|
||||
domain = dds_create_domain(1, "<"DDS_PROJECT_NAME"><Domain><Id>1</Id></Domain></"DDS_PROJECT_NAME">");
|
||||
CU_ASSERT_FATAL(domain > 0);
|
||||
|
||||
ret = dds_get_domainid (domain, &did);
|
||||
CU_ASSERT_FATAL(ret == DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL(did == 1);
|
||||
|
||||
ret = dds_delete(domain);
|
||||
CU_ASSERT_FATAL(ret == DDS_RETCODE_OK);
|
||||
ret = dds_delete(domain);
|
||||
CU_ASSERT_FATAL(ret != DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_domain_create, mismatch)
|
||||
{
|
||||
dds_return_t ret;
|
||||
dds_domainid_t did;
|
||||
dds_entity_t domain;
|
||||
|
||||
/* The config should have been ignored. */
|
||||
domain = dds_create_domain(2, "<"DDS_PROJECT_NAME"><Domain><Id>3</Id></Domain></"DDS_PROJECT_NAME">");
|
||||
CU_ASSERT_FATAL(domain > 0);
|
||||
|
||||
ret = dds_get_domainid (domain, &did);
|
||||
CU_ASSERT_FATAL(ret == DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL(did == 2);
|
||||
|
||||
ret = dds_delete(domain);
|
||||
CU_ASSERT_FATAL(ret == DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_domain_create, empty)
|
||||
{
|
||||
dds_return_t ret;
|
||||
dds_domainid_t did;
|
||||
dds_entity_t domain;
|
||||
|
||||
/* This should create a domain with default settings. */
|
||||
domain = dds_create_domain(3, "");
|
||||
CU_ASSERT_FATAL(domain > 0);
|
||||
|
||||
ret = dds_get_domainid (domain, &did);
|
||||
CU_ASSERT_FATAL(ret == DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL(did == 3);
|
||||
|
||||
ret = dds_delete(domain);
|
||||
CU_ASSERT_FATAL(ret == DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_domain_create, null)
|
||||
{
|
||||
dds_return_t ret;
|
||||
dds_domainid_t did;
|
||||
dds_entity_t domain;
|
||||
|
||||
/* This should start create a domain with default settings. */
|
||||
domain = dds_create_domain(5, NULL);
|
||||
CU_ASSERT_FATAL(domain > 0);
|
||||
|
||||
ret = dds_get_domainid (domain, &did);
|
||||
CU_ASSERT_FATAL(ret == DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL(did == 5);
|
||||
|
||||
ret = dds_delete(domain);
|
||||
CU_ASSERT_FATAL(ret == DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_domain_create, after_domain)
|
||||
{
|
||||
dds_entity_t domain1;
|
||||
dds_entity_t domain2;
|
||||
|
||||
domain1 = dds_create_domain(4, "<"DDS_PROJECT_NAME"><Domain><Id>any</Id></Domain></"DDS_PROJECT_NAME">");
|
||||
CU_ASSERT_FATAL(domain1 > 0);
|
||||
|
||||
domain2 = dds_create_domain(4, "<"DDS_PROJECT_NAME"><Domain><Id>any</Id></Domain></"DDS_PROJECT_NAME">");
|
||||
CU_ASSERT_FATAL(domain2 == DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
|
||||
dds_delete(domain1);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_domain_create, after_participant)
|
||||
{
|
||||
dds_entity_t domain;
|
||||
dds_entity_t participant;
|
||||
|
||||
participant = dds_create_participant (5, NULL, NULL);
|
||||
CU_ASSERT_FATAL(participant > 0);
|
||||
|
||||
domain = dds_create_domain(5, "<"DDS_PROJECT_NAME"><Domain><Id>any</Id></Domain></"DDS_PROJECT_NAME">");
|
||||
CU_ASSERT_FATAL(domain == DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
|
||||
dds_delete(participant);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_domain_create, diff)
|
||||
{
|
||||
dds_return_t ret;
|
||||
dds_domainid_t did;
|
||||
dds_entity_t domain1;
|
||||
dds_entity_t domain2;
|
||||
|
||||
domain1 = dds_create_domain(1, "<"DDS_PROJECT_NAME"><Domain><Id>any</Id></Domain></"DDS_PROJECT_NAME">");
|
||||
CU_ASSERT_FATAL(domain1 > 0);
|
||||
|
||||
domain2 = dds_create_domain(2, "<"DDS_PROJECT_NAME"><Domain><Id>any</Id></Domain></"DDS_PROJECT_NAME">");
|
||||
CU_ASSERT_FATAL(domain2 > 0);
|
||||
|
||||
ret = dds_get_domainid (domain1, &did);
|
||||
CU_ASSERT_FATAL(ret == DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL(did == 1);
|
||||
|
||||
ret = dds_get_domainid (domain2, &did);
|
||||
CU_ASSERT_FATAL(ret == DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL(did == 2);
|
||||
|
||||
ret = dds_delete(domain1);
|
||||
CU_ASSERT_FATAL(ret == DDS_RETCODE_OK);
|
||||
ret = dds_delete(domain2);
|
||||
CU_ASSERT_FATAL(ret == DDS_RETCODE_OK);
|
||||
|
||||
ret = dds_delete(domain1);
|
||||
CU_ASSERT_FATAL(ret != DDS_RETCODE_OK);
|
||||
ret = dds_delete(domain2);
|
||||
CU_ASSERT_FATAL(ret != DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_domain_create, domain_default)
|
||||
{
|
||||
dds_entity_t domain;
|
||||
domain = dds_create_domain(DDS_DOMAIN_DEFAULT, "<"DDS_PROJECT_NAME"><Domain><Id>any</Id></Domain></"DDS_PROJECT_NAME">");
|
||||
CU_ASSERT_FATAL(domain == DDS_RETCODE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
CU_Test(ddsc_domain_create, invalid_xml)
|
||||
{
|
||||
dds_entity_t domain;
|
||||
domain = dds_create_domain(1, "<CycloneDDS incorrect XML");
|
||||
CU_ASSERT_FATAL(domain == DDS_RETCODE_ERROR);
|
||||
}
|
||||
|
|
118
src/core/ddsc/tests/domain_torture.c
Normal file
118
src/core/ddsc/tests/domain_torture.c
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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/threads.h"
|
||||
#include "dds/ddsrt/atomics.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
|
||||
|
||||
#define N_THREADS (10)
|
||||
|
||||
static const dds_duration_t TEST_DURATION = DDS_SECS(3);
|
||||
|
||||
static ddsrt_atomic_uint32_t terminate;
|
||||
|
||||
|
||||
static uint32_t create_participants_thread (void *varg)
|
||||
{
|
||||
(void) varg;
|
||||
while (!ddsrt_atomic_ld32 (&terminate))
|
||||
{
|
||||
dds_entity_t par = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
|
||||
if (par < 0)
|
||||
{
|
||||
fprintf (stderr, "dds_create_participant failed: %s\n", dds_strretcode (par));
|
||||
ddsrt_atomic_st32 (&terminate, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dds_return_t ret = dds_delete(par);
|
||||
if (ret != DDS_RETCODE_OK)
|
||||
{
|
||||
fprintf (stderr, "dds_delete failed: %s\n", dds_strretcode (ret));
|
||||
ddsrt_atomic_st32 (&terminate, 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void participant_creation_torture()
|
||||
{
|
||||
dds_return_t rc;
|
||||
ddsrt_thread_t tids[N_THREADS];
|
||||
ddsrt_threadattr_t tattr;
|
||||
ddsrt_threadattr_init (&tattr);
|
||||
|
||||
/* Start threads. */
|
||||
for (size_t i = 0; i < sizeof(tids) / sizeof(*tids); i++)
|
||||
{
|
||||
rc = ddsrt_thread_create (&tids[i], "domain_torture_explicit", &tattr, create_participants_thread, 0);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
/* Let the threads do the torturing for a while. */
|
||||
dds_sleepfor(TEST_DURATION);
|
||||
|
||||
/* Stop and check threads results. */
|
||||
ddsrt_atomic_st32 (&terminate, 1);
|
||||
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 == DDS_RETCODE_OK);
|
||||
CU_ASSERT (retval == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* There are some issues when completely init/deinit the
|
||||
* library in a torturing way. We really just want to
|
||||
* check the domain creation/deletion. So, disable this
|
||||
* test for now.
|
||||
*/
|
||||
CU_Test (ddsc_domain, torture_implicit, .disabled=true)
|
||||
{
|
||||
/* No explicit domain creation, just start creating and
|
||||
* deleting participants (that'll create and delete the
|
||||
* domain implicitly) in a torturing manner. */
|
||||
participant_creation_torture();
|
||||
}
|
||||
|
||||
|
||||
CU_Test (ddsc_domain, torture_explicit)
|
||||
{
|
||||
dds_return_t rc;
|
||||
dds_entity_t domain;
|
||||
|
||||
/* Create domain explicitly. */
|
||||
domain = dds_create_domain(1, "");
|
||||
CU_ASSERT_FATAL (domain > 0);
|
||||
|
||||
/* Start creating and deleting participants on the
|
||||
* explicit domain in a torturing manner. */
|
||||
participant_creation_torture();
|
||||
|
||||
/* Delete domain. */
|
||||
rc = dds_delete(domain);
|
||||
CU_ASSERT_FATAL (rc == DDS_RETCODE_OK);
|
||||
rc = dds_delete(domain);
|
||||
CU_ASSERT_FATAL (rc != DDS_RETCODE_OK);
|
||||
}
|
|
@ -192,6 +192,10 @@ CU_Test(ddsc_entity_delete, recursive_with_deleted_topic)
|
|||
ret = dds_delete(g_topic);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
|
||||
/* Second call to delete a topic must fail */
|
||||
ret = dds_delete(g_topic);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ALREADY_DELETED);
|
||||
|
||||
/* Third, deleting the participant should delete all children of which
|
||||
* the writer with the last topic reference is one. */
|
||||
ret = dds_delete(g_participant);
|
||||
|
@ -988,6 +992,70 @@ CU_Test(ddsc_entity_get_parent, implicit_subscriber)
|
|||
}
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
CU_Test(ddsc_entity_implicit, delete_publisher)
|
||||
{
|
||||
dds_entity_t participant;
|
||||
dds_entity_t writer;
|
||||
dds_entity_t parent;
|
||||
dds_entity_t topic;
|
||||
dds_return_t ret;
|
||||
char name[100];
|
||||
|
||||
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
|
||||
CU_ASSERT_FATAL(participant > 0);
|
||||
|
||||
topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_delete_publisher", name, 100), NULL, NULL);
|
||||
CU_ASSERT_FATAL(topic > 0);
|
||||
|
||||
writer = dds_create_writer(participant, topic, NULL, NULL);
|
||||
CU_ASSERT_FATAL(writer > 0);
|
||||
|
||||
parent = dds_get_parent(writer);
|
||||
CU_ASSERT_FATAL(parent > 0);
|
||||
|
||||
ret = dds_delete(parent);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
|
||||
ret = dds_delete(writer);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER);
|
||||
|
||||
dds_delete(participant);
|
||||
}
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
CU_Test(ddsc_entity_implicit, delete_subscriber)
|
||||
{
|
||||
dds_entity_t participant;
|
||||
dds_entity_t reader;
|
||||
dds_entity_t parent;
|
||||
dds_entity_t topic;
|
||||
dds_return_t ret;
|
||||
char name[100];
|
||||
|
||||
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
|
||||
CU_ASSERT_FATAL(participant > 0);
|
||||
|
||||
topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_delete_subscriber", name, 100), NULL, NULL);
|
||||
CU_ASSERT_FATAL(topic > 0);
|
||||
|
||||
reader = dds_create_reader(participant, topic, NULL, NULL);
|
||||
CU_ASSERT_FATAL(reader > 0);
|
||||
|
||||
parent = dds_get_parent(reader);
|
||||
CU_ASSERT_FATAL(parent > 0);
|
||||
|
||||
ret = dds_delete(parent);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
|
||||
ret = dds_delete(reader);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER);
|
||||
|
||||
dds_delete(participant);
|
||||
}
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#endif
|
||||
|
|
|
@ -360,9 +360,9 @@ CU_Test(ddsc_entity, liveliness_changed, .init=init_entity_status, .fini=fini_en
|
|||
ret = dds_get_liveliness_changed_status (rea, &liveliness_changed);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count_change, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count, 1);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count_change,1);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count_change, -1);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count_change,0);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.last_publication_handle, writer_i_hdl);
|
||||
|
||||
/* Second call should reset the changed count. */
|
||||
|
@ -370,7 +370,7 @@ CU_Test(ddsc_entity, liveliness_changed, .init=init_entity_status, .fini=fini_en
|
|||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count_change, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count, 1);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count_change,0);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.last_publication_handle, writer_i_hdl);
|
||||
}
|
||||
|
|
|
@ -1196,9 +1196,9 @@ CU_Test(ddsc_listener, liveliness_changed, .init=init_triggering_test, .fini=fin
|
|||
CU_ASSERT_EQUAL_FATAL(triggered & DDS_LIVELINESS_CHANGED_STATUS, DDS_LIVELINESS_CHANGED_STATUS);
|
||||
CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader);
|
||||
CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.alive_count, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.alive_count_change, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.not_alive_count, 1);
|
||||
CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.not_alive_count_change, 1);
|
||||
CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.alive_count_change, -1);
|
||||
CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.not_alive_count, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.not_alive_count_change, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.last_publication_handle, writer_hdl);
|
||||
|
||||
/* The listener should have reset the count_change. */
|
||||
|
@ -1206,7 +1206,7 @@ CU_Test(ddsc_listener, liveliness_changed, .init=init_triggering_test, .fini=fin
|
|||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count_change, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count, 1);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count_change, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(liveliness_changed.last_publication_handle, writer_hdl);
|
||||
}
|
||||
|
|
815
src/core/ddsc/tests/liveliness.c
Normal file
815
src/core/ddsc/tests/liveliness.c
Normal file
|
@ -0,0 +1,815 @@
|
|||
/*
|
||||
* 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 "Space.h"
|
||||
#include "config_env.h"
|
||||
|
||||
#include "dds/version.h"
|
||||
#include "dds__entity.h"
|
||||
#include "dds/ddsi/q_entity.h"
|
||||
#include "dds/ddsrt/cdtors.h"
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/process.h"
|
||||
#include "dds/ddsrt/threads.h"
|
||||
#include "dds/ddsrt/environ.h"
|
||||
#include "dds/ddsrt/atomics.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
|
||||
#define DDS_DOMAINID_PUB 0
|
||||
#define DDS_DOMAINID_SUB 1
|
||||
#define DDS_CONFIG_NO_PORT_GAIN "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}<Discovery><ExternalDomainId>0</ExternalDomainId></Discovery>"
|
||||
#define DDS_CONFIG_NO_PORT_GAIN_LOG "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}<Tracing><OutputFile>cyclonedds_liveliness_tests.${CYCLONEDDS_DOMAIN_ID}.${CYCLONEDDS_PID}.log</OutputFile><Verbosity>finest</Verbosity></Tracing><Discovery><ExternalDomainId>0</ExternalDomainId></Discovery>"
|
||||
|
||||
uint32_t g_topic_nr = 0;
|
||||
static dds_entity_t g_pub_domain = 0;
|
||||
static dds_entity_t g_pub_participant = 0;
|
||||
static dds_entity_t g_pub_publisher = 0;
|
||||
|
||||
static dds_entity_t g_sub_domain = 0;
|
||||
static dds_entity_t g_sub_participant = 0;
|
||||
static dds_entity_t g_sub_subscriber = 0;
|
||||
|
||||
static char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size)
|
||||
{
|
||||
/* Get unique g_topic name. */
|
||||
ddsrt_pid_t pid = ddsrt_getpid();
|
||||
ddsrt_tid_t tid = ddsrt_gettid();
|
||||
(void)snprintf(name, size, "%s%d_pid%" PRIdPID "_tid%" PRIdTID "", prefix, nr, pid, tid);
|
||||
return name;
|
||||
}
|
||||
|
||||
static void liveliness_init(void)
|
||||
{
|
||||
/* Domains for pub and sub use a different domain id, but the portgain setting
|
||||
* in configuration is 0, so that both domains will map to the same port number.
|
||||
* This allows to create two domains in a single test process. */
|
||||
char *conf_pub = ddsrt_expand_envvars(DDS_CONFIG_NO_PORT_GAIN, DDS_DOMAINID_PUB);
|
||||
char *conf_sub = ddsrt_expand_envvars(DDS_CONFIG_NO_PORT_GAIN, DDS_DOMAINID_SUB);
|
||||
g_pub_domain = dds_create_domain(DDS_DOMAINID_PUB, conf_pub);
|
||||
g_sub_domain = dds_create_domain(DDS_DOMAINID_SUB, conf_sub);
|
||||
dds_free(conf_pub);
|
||||
dds_free(conf_sub);
|
||||
|
||||
g_pub_participant = dds_create_participant(DDS_DOMAINID_PUB, NULL, NULL);
|
||||
CU_ASSERT_FATAL(g_pub_participant > 0);
|
||||
g_sub_participant = dds_create_participant(DDS_DOMAINID_SUB, NULL, NULL);
|
||||
CU_ASSERT_FATAL(g_sub_participant > 0);
|
||||
|
||||
g_pub_publisher = dds_create_publisher(g_pub_participant, NULL, NULL);
|
||||
CU_ASSERT_FATAL(g_pub_publisher > 0);
|
||||
g_sub_subscriber = dds_create_subscriber(g_sub_participant, NULL, NULL);
|
||||
CU_ASSERT_FATAL(g_sub_subscriber > 0);
|
||||
}
|
||||
|
||||
static void liveliness_fini(void)
|
||||
{
|
||||
dds_delete(g_sub_subscriber);
|
||||
dds_delete(g_pub_publisher);
|
||||
dds_delete(g_sub_participant);
|
||||
dds_delete(g_pub_participant);
|
||||
dds_delete(g_sub_domain);
|
||||
dds_delete(g_pub_domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current PMD sequence number for the participant. This
|
||||
* can be used to count the number of PMD messages that is sent by
|
||||
* the participant.
|
||||
*/
|
||||
static seqno_t get_pmd_seqno(dds_entity_t participant)
|
||||
{
|
||||
seqno_t seqno;
|
||||
struct dds_entity *pp_entity;
|
||||
struct participant *pp;
|
||||
struct writer *wr;
|
||||
CU_ASSERT_EQUAL_FATAL(dds_entity_pin(participant, &pp_entity), 0);
|
||||
thread_state_awake(lookup_thread_state(), &pp_entity->m_domain->gv);
|
||||
pp = ephash_lookup_participant_guid(pp_entity->m_domain->gv.guid_hash, &pp_entity->m_guid);
|
||||
wr = get_builtin_writer(pp, NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER);
|
||||
CU_ASSERT_FATAL(wr != NULL);
|
||||
assert(wr != NULL); /* for Clang's static analyzer */
|
||||
seqno = wr->seq;
|
||||
thread_state_asleep(lookup_thread_state());
|
||||
dds_entity_unpin(pp_entity);
|
||||
return seqno;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current PMD interval for the participant
|
||||
*/
|
||||
static dds_duration_t get_pmd_interval(dds_entity_t participant)
|
||||
{
|
||||
dds_duration_t intv;
|
||||
struct dds_entity *pp_entity;
|
||||
struct participant *pp;
|
||||
CU_ASSERT_EQUAL_FATAL(dds_entity_pin(participant, &pp_entity), 0);
|
||||
thread_state_awake(lookup_thread_state(), &pp_entity->m_domain->gv);
|
||||
pp = ephash_lookup_participant_guid(pp_entity->m_domain->gv.guid_hash, &pp_entity->m_guid);
|
||||
intv = pp_get_pmd_interval(pp);
|
||||
thread_state_asleep(lookup_thread_state());
|
||||
dds_entity_unpin(pp_entity);
|
||||
return intv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current lease duration for the participant
|
||||
*/
|
||||
static dds_duration_t get_ldur_config(dds_entity_t participant)
|
||||
{
|
||||
struct dds_entity *pp_entity;
|
||||
dds_duration_t ldur;
|
||||
CU_ASSERT_EQUAL_FATAL(dds_entity_pin(participant, &pp_entity), 0);
|
||||
ldur = (dds_duration_t)pp_entity->m_domain->gv.config.lease_duration;
|
||||
dds_entity_unpin(pp_entity);
|
||||
return ldur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the correct number of PMD messages is sent for
|
||||
* the various liveliness kinds.
|
||||
*/
|
||||
#define A DDS_LIVELINESS_AUTOMATIC
|
||||
#define MP DDS_LIVELINESS_MANUAL_BY_PARTICIPANT
|
||||
#define MT DDS_LIVELINESS_MANUAL_BY_TOPIC
|
||||
CU_TheoryDataPoints(ddsc_liveliness, pmd_count) = {
|
||||
CU_DataPoints(dds_liveliness_kind_t, A, A, MP, MT), /* liveliness kind */
|
||||
CU_DataPoints(uint32_t, 200, 500, 100, 100), /* lease duration */
|
||||
CU_DataPoints(double, 10, 5, 5, 5), /* delay (n times lease duration) */
|
||||
};
|
||||
#undef MT
|
||||
#undef MP
|
||||
#undef A
|
||||
CU_Theory((dds_liveliness_kind_t kind, uint32_t ldur, double mult), ddsc_liveliness, pmd_count, .init = liveliness_init, .fini = liveliness_fini, .timeout = 30)
|
||||
{
|
||||
dds_entity_t pub_topic;
|
||||
dds_entity_t sub_topic;
|
||||
dds_entity_t reader;
|
||||
dds_entity_t writer;
|
||||
seqno_t start_seqno, end_seqno;
|
||||
dds_qos_t *rqos;
|
||||
dds_qos_t *wqos;
|
||||
dds_entity_t waitset;
|
||||
dds_attach_t triggered;
|
||||
uint32_t status;
|
||||
char name[100];
|
||||
dds_time_t t;
|
||||
|
||||
t = dds_time();
|
||||
printf("%d.%06d running test: kind %s, lease duration %d, delay %d\n",
|
||||
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000,
|
||||
kind == 0 ? "A" : "MP", ldur, (int32_t)(mult * ldur));
|
||||
|
||||
/* wait for initial PMD to be sent by the participant */
|
||||
while (get_pmd_seqno(g_pub_participant) < 1)
|
||||
dds_sleepfor(DDS_MSECS(50));
|
||||
|
||||
/* topics */
|
||||
create_topic_name("ddsc_liveliness_pmd_count", g_topic_nr++, name, sizeof name);
|
||||
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
|
||||
/* reader */
|
||||
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
|
||||
dds_delete_qos(rqos);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||
|
||||
/* waitset on reader */
|
||||
CU_ASSERT_FATAL((waitset = dds_create_waitset(g_sub_participant)) > 0);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
||||
|
||||
/* writer */
|
||||
CU_ASSERT_FATAL((wqos = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(wqos, kind, DDS_MSECS(ldur));
|
||||
CU_ASSERT_FATAL((writer = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
|
||||
dds_delete_qos(wqos);
|
||||
|
||||
/* wait for writer to be alive */
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(1)), 1);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_take_status(reader, &status, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||
|
||||
/* check no of PMD messages sent */
|
||||
start_seqno = get_pmd_seqno(g_pub_participant);
|
||||
dds_sleepfor(DDS_MSECS((dds_duration_t)(mult * ldur)));
|
||||
end_seqno = get_pmd_seqno(g_pub_participant);
|
||||
|
||||
t = dds_time();
|
||||
printf("%d.%06d PMD sequence no: start %" PRId64 " -> end %" PRId64 "\n",
|
||||
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000,
|
||||
start_seqno, end_seqno);
|
||||
|
||||
/* End-start should be mult - 1 under ideal circumstances, but consider the test successful
|
||||
when at least 50% of the expected PMD's was sent. This checks that the frequency for sending
|
||||
PMDs was increased when the writer was added. */
|
||||
CU_ASSERT(end_seqno - start_seqno >= (kind == DDS_LIVELINESS_AUTOMATIC ? (50 * (mult - 1)) / 100 : 0))
|
||||
if (kind != DDS_LIVELINESS_AUTOMATIC)
|
||||
CU_ASSERT(get_pmd_seqno(g_pub_participant) - start_seqno < mult)
|
||||
|
||||
/* cleanup */
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(writer), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the expected number of proxy writers expires (set to not-alive)
|
||||
* after a certain delay for various combinations of writers with different
|
||||
* liveliness kinds.
|
||||
*/
|
||||
CU_TheoryDataPoints(ddsc_liveliness, expire_liveliness_kinds) = {
|
||||
CU_DataPoints(uint32_t, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200), /* lease duration for initial test run (increased for each retry when test fails) */
|
||||
CU_DataPoints(double, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 2, 2, 2, 2, 2, 2, 2, 2, 2), /* delay (n times lease duration) */
|
||||
CU_DataPoints(uint32_t, 1, 0, 2, 0, 1, 0, 0, 1, 1, 2, 0, 5, 0, 15, 15), /* number of writers with automatic liveliness */
|
||||
CU_DataPoints(uint32_t, 1, 1, 2, 2, 0, 0, 0, 1, 0, 2, 2, 5, 10, 0, 15), /* number of writers with manual-by-participant liveliness */
|
||||
CU_DataPoints(uint32_t, 1, 1, 2, 2, 1, 1, 1, 1, 0, 1, 1, 2, 5, 0, 10), /* number of writers with manual-by-topic liveliness */
|
||||
};
|
||||
CU_Theory((uint32_t ldur, double mult, uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp), ddsc_liveliness, expire_liveliness_kinds, .init = liveliness_init, .fini = liveliness_fini, .timeout = 120)
|
||||
{
|
||||
dds_entity_t pub_topic;
|
||||
dds_entity_t sub_topic;
|
||||
dds_entity_t reader;
|
||||
dds_entity_t *writers;
|
||||
dds_qos_t *rqos, *wqos_auto, *wqos_man_pp, *wqos_man_tp;
|
||||
dds_entity_t waitset;
|
||||
dds_attach_t triggered;
|
||||
struct dds_liveliness_changed_status lstatus;
|
||||
uint32_t status, n, run = 1, wr_cnt = wr_cnt_auto + wr_cnt_man_pp + wr_cnt_man_tp;
|
||||
char name[100];
|
||||
dds_time_t tstart, t;
|
||||
bool test_finished = false;
|
||||
|
||||
do
|
||||
{
|
||||
tstart = dds_time();
|
||||
printf("%d.%06d running test: lease duration %d, delay %f, auto/man-by-part/man-by-topic %u/%u/%u\n",
|
||||
(int32_t)(tstart / DDS_NSECS_IN_SEC), (int32_t)(tstart % DDS_NSECS_IN_SEC) / 1000,
|
||||
ldur, mult, wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp);
|
||||
|
||||
/* topics */
|
||||
create_topic_name("ddsc_liveliness_expire_kinds", g_topic_nr++, name, sizeof name);
|
||||
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
|
||||
/* reader */
|
||||
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
|
||||
dds_delete_qos(rqos);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||
|
||||
/* writers */
|
||||
CU_ASSERT_FATAL((wqos_auto = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(wqos_auto, DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(ldur));
|
||||
CU_ASSERT_FATAL((wqos_man_pp = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(wqos_man_pp, DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(ldur));
|
||||
CU_ASSERT_FATAL((wqos_man_tp = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(wqos_man_tp, DDS_LIVELINESS_MANUAL_BY_TOPIC, DDS_MSECS(ldur));
|
||||
|
||||
CU_ASSERT_FATAL((waitset = dds_create_waitset(g_sub_participant)) > 0);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
||||
|
||||
writers = dds_alloc(wr_cnt * sizeof(dds_entity_t));
|
||||
for (n = 0; n < wr_cnt; n++)
|
||||
{
|
||||
dds_qos_t *wqos;
|
||||
wqos = n < wr_cnt_auto ? wqos_auto : (n < (wr_cnt_auto + wr_cnt_man_pp) ? wqos_man_pp : wqos_man_tp);
|
||||
CU_ASSERT_FATAL((writers[n] = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_take_status(reader, &status, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||
}
|
||||
dds_delete_qos(wqos_auto);
|
||||
dds_delete_qos(wqos_man_pp);
|
||||
dds_delete_qos(wqos_man_tp);
|
||||
|
||||
t = dds_time();
|
||||
if (t - tstart > DDS_MSECS(0.5 * ldur))
|
||||
{
|
||||
ldur *= 10 / (run + 1);
|
||||
printf("%d.%06d failed to create writers in time\n",
|
||||
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* check alive count before proxy writers are expired */
|
||||
dds_get_liveliness_changed_status(reader, &lstatus);
|
||||
printf("%d.%06d writers alive: %d\n", (int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000, lstatus.alive_count);
|
||||
CU_ASSERT_EQUAL_FATAL(lstatus.alive_count, wr_cnt);
|
||||
|
||||
dds_time_t tstop = tstart + DDS_MSECS((dds_duration_t)(mult * ldur));
|
||||
uint32_t stopped = 0;
|
||||
do
|
||||
{
|
||||
dds_duration_t w = tstop - dds_time();
|
||||
CU_ASSERT_FATAL((dds_waitset_wait(waitset, &triggered, 1, w > 0 ? w : 0)) >= 0);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
|
||||
stopped += (uint32_t)lstatus.not_alive_count_change;
|
||||
} while (dds_time() < tstop);
|
||||
t = dds_time();
|
||||
printf("%d.%06d writers stopped: %u\n",
|
||||
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000, stopped);
|
||||
|
||||
size_t exp_stopped = mult < 1 ? 0 : (wr_cnt_man_pp + wr_cnt_man_tp);
|
||||
if (stopped != exp_stopped)
|
||||
{
|
||||
ldur *= 10 / (run + 1);
|
||||
printf("%d.%06d incorrect number of stopped writers\n",
|
||||
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* check alive count */
|
||||
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL(lstatus.alive_count, mult < 1 ? wr_cnt : wr_cnt_auto);
|
||||
test_finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_detach(waitset, reader), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(waitset), DDS_RETCODE_OK);
|
||||
|
||||
for (n = 0; n < wr_cnt; n++)
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(writers[n]), DDS_RETCODE_OK);
|
||||
dds_free(writers);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
||||
|
||||
if (!test_finished)
|
||||
{
|
||||
if (++run > 3)
|
||||
{
|
||||
printf("%d.%06d run limit reached, test failed\n", (int32_t)(tstart / DDS_NSECS_IN_SEC), (int32_t)(tstart % DDS_NSECS_IN_SEC) / 1000);
|
||||
CU_FAIL_FATAL("Run limit reached");
|
||||
test_finished = true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%d.%06d restarting test with ldur %d\n",
|
||||
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000, ldur);
|
||||
}
|
||||
}
|
||||
} while (!test_finished);
|
||||
}
|
||||
|
||||
static void add_and_check_writer(dds_liveliness_kind_t kind, dds_duration_t ldur, dds_entity_t *writer, dds_entity_t topic, dds_entity_t reader)
|
||||
{
|
||||
dds_entity_t waitset;
|
||||
dds_qos_t *wqos;
|
||||
dds_attach_t triggered;
|
||||
uint32_t status;
|
||||
|
||||
CU_ASSERT_FATAL((waitset = dds_create_waitset(g_sub_participant)) > 0);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
||||
|
||||
CU_ASSERT_FATAL((wqos = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(wqos, kind, ldur);
|
||||
CU_ASSERT_FATAL((*writer = dds_create_writer(g_pub_participant, topic, wqos, NULL)) > 0);
|
||||
dds_delete_qos(wqos);
|
||||
|
||||
/* wait for writer to be alive */
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_MSECS(1000)), 1);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_take_status(reader, &status, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_detach(waitset, reader), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(waitset), DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the correct PMD interval is set for the participant
|
||||
* based on the lease duration of the writers.
|
||||
*/
|
||||
#define MAX_WRITERS 10
|
||||
CU_Test(ddsc_liveliness, lease_duration, .init = liveliness_init, .fini = liveliness_fini)
|
||||
{
|
||||
dds_entity_t pub_topic;
|
||||
dds_entity_t sub_topic;
|
||||
dds_entity_t reader;
|
||||
dds_entity_t writers[MAX_WRITERS];
|
||||
uint32_t wr_cnt = 0;
|
||||
char name[100];
|
||||
dds_qos_t *rqos;
|
||||
uint32_t n;
|
||||
|
||||
/* topics */
|
||||
create_topic_name("ddsc_liveliness_ldur", 1, name, sizeof name);
|
||||
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
|
||||
/* reader and waitset */
|
||||
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
|
||||
dds_delete_qos(rqos);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||
|
||||
/* check if pmd defaults to configured duration */
|
||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), get_ldur_config(g_pub_participant));
|
||||
|
||||
/* create writers and check pmd interval in publishing participant */
|
||||
add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(1000), &writers[wr_cnt++], pub_topic, reader);
|
||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(1000));
|
||||
|
||||
add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(2000), &writers[wr_cnt++], pub_topic, reader);
|
||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(1000));
|
||||
|
||||
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(2000), &writers[wr_cnt++], pub_topic, reader);
|
||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(1000));
|
||||
|
||||
add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(500), &writers[wr_cnt++], pub_topic, reader);
|
||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(500));
|
||||
|
||||
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(100), &writers[wr_cnt++], pub_topic, reader);
|
||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(500));
|
||||
|
||||
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_TOPIC, DDS_MSECS(100), &writers[wr_cnt++], pub_topic, reader);
|
||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(500));
|
||||
|
||||
/* cleanup */
|
||||
for (n = 0; n < wr_cnt; n++)
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(writers[n]), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
||||
}
|
||||
#undef MAX_WRITERS
|
||||
|
||||
/**
|
||||
* Check that the correct lease duration is set in the matched
|
||||
* publications in the readers. */
|
||||
CU_Test(ddsc_liveliness, lease_duration_pwr, .init = liveliness_init, .fini = liveliness_fini)
|
||||
{
|
||||
dds_entity_t pub_topic;
|
||||
dds_entity_t sub_topic;
|
||||
dds_entity_t reader;
|
||||
dds_entity_t writer;
|
||||
char name[100];
|
||||
dds_qos_t *rqos, *wqos;
|
||||
dds_entity_t waitset;
|
||||
dds_attach_t triggered;
|
||||
uint32_t status;
|
||||
dds_duration_t ldur;
|
||||
|
||||
/* topics */
|
||||
create_topic_name("ddsc_liveliness_ldurpwr", 1, name, sizeof name);
|
||||
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
|
||||
/* reader */
|
||||
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
|
||||
dds_delete_qos(rqos);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||
|
||||
/* writer */
|
||||
ldur = 1000;
|
||||
CU_ASSERT_FATAL((wqos = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(wqos, DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(ldur));
|
||||
CU_ASSERT_FATAL((writer = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
|
||||
|
||||
/* wait for writer to be alive */
|
||||
CU_ASSERT_FATAL((waitset = dds_create_waitset(g_sub_participant)) > 0);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_MSECS(1000)), 1);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_take_status(reader, &status, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||
|
||||
/* check pwr lease duration in matched publication */
|
||||
dds_instance_handle_t wrs[1];
|
||||
CU_ASSERT_EQUAL_FATAL(dds_get_matched_publications(reader, wrs, 1), 1);
|
||||
dds_builtintopic_endpoint_t *ep;
|
||||
ep = dds_get_matched_publication_data(reader, wrs[0]);
|
||||
CU_ASSERT_FATAL(ep != NULL);
|
||||
assert(ep != NULL); /* for Clang's static analyzer */
|
||||
CU_ASSERT_EQUAL_FATAL(ep->qos->liveliness.lease_duration, DDS_MSECS(ldur));
|
||||
dds_delete_qos(ep->qos);
|
||||
dds_free(ep->topic_name);
|
||||
dds_free(ep->type_name);
|
||||
dds_free(ep);
|
||||
|
||||
/* cleanup */
|
||||
dds_delete_qos(wqos);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_detach(waitset, reader), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(waitset), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(writer), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a relative large number of writers with liveliness kinds automatic and
|
||||
* manual-by-participant and with decreasing lease duration, and check that all
|
||||
* writers become alive. During the writer creation loop, every third writer
|
||||
* is deleted immediately after creating.
|
||||
*/
|
||||
#define MAX_WRITERS 100
|
||||
CU_Test(ddsc_liveliness, create_delete_writer_stress, .init = liveliness_init, .fini = liveliness_fini, .timeout = 15)
|
||||
{
|
||||
dds_entity_t pub_topic;
|
||||
dds_entity_t sub_topic;
|
||||
dds_entity_t reader;
|
||||
dds_entity_t writers[MAX_WRITERS];
|
||||
dds_entity_t waitset;
|
||||
dds_qos_t *wqos;
|
||||
struct dds_liveliness_changed_status lstatus;
|
||||
uint32_t alive_writers_auto = 0, alive_writers_man = 0;
|
||||
char name[100];
|
||||
dds_qos_t *rqos;
|
||||
dds_attach_t triggered;
|
||||
uint32_t n;
|
||||
Space_Type1 sample = {0, 0, 0};
|
||||
int64_t ldur = 1000;
|
||||
|
||||
/* topics */
|
||||
create_topic_name("ddsc_liveliness_wr_stress", 1, name, sizeof name);
|
||||
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
|
||||
/* reader and waitset */
|
||||
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
|
||||
dds_delete_qos(rqos);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL((waitset = dds_create_waitset(g_sub_participant)) > 0);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
||||
|
||||
/* create 1st writer and wait for it to become alive */
|
||||
CU_ASSERT_FATAL((wqos = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(wqos, DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(ldur));
|
||||
CU_ASSERT_FATAL((writers[0] = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_MSECS(1000)), 1);
|
||||
alive_writers_man++;
|
||||
|
||||
/* create writers */
|
||||
for (n = 1; n < MAX_WRITERS; n++)
|
||||
{
|
||||
dds_qset_liveliness(wqos, n % 2 ? DDS_LIVELINESS_AUTOMATIC : DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(n % 3 ? ldur + n : ldur - n) + ((n % 3) == 2 ? 1 : 0));
|
||||
CU_ASSERT_FATAL((writers[n] = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
|
||||
dds_write(writers[n], &sample);
|
||||
if (n % 3 == 2)
|
||||
dds_delete(writers[n]);
|
||||
else if (n % 2)
|
||||
alive_writers_auto++;
|
||||
else
|
||||
alive_writers_man++;
|
||||
}
|
||||
dds_delete_qos(wqos);
|
||||
printf("alive_writers_auto: %d, alive_writers_man: %d\n", alive_writers_auto, alive_writers_man);
|
||||
|
||||
/* wait for auto liveliness writers to become alive and manual-by-pp writers to become not-alive */
|
||||
do
|
||||
{
|
||||
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
|
||||
printf("alive: %d, not-alive: %d\n", lstatus.alive_count, lstatus.not_alive_count);
|
||||
dds_sleepfor(DDS_MSECS(50));
|
||||
} while (lstatus.alive_count != alive_writers_auto || lstatus.not_alive_count != alive_writers_man);
|
||||
|
||||
/* check that counts are stable after a delay */
|
||||
dds_sleepfor(DDS_MSECS(ldur / 2));
|
||||
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL(lstatus.alive_count == alive_writers_auto && lstatus.not_alive_count == alive_writers_man);
|
||||
|
||||
/* cleanup remaining writers */
|
||||
for (n = 0; n < MAX_WRITERS; n++)
|
||||
{
|
||||
if (n % 3 != 2)
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(writers[n]), DDS_RETCODE_OK);
|
||||
}
|
||||
/* wait for alive_count and not_alive_count to become 0 */
|
||||
do
|
||||
{
|
||||
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
|
||||
printf("alive: %d, not: %d\n", lstatus.alive_count, lstatus.not_alive_count);
|
||||
dds_sleepfor(DDS_MSECS(ldur / 10));
|
||||
} while (lstatus.alive_count > 0 || lstatus.not_alive_count > 0);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_detach(waitset, reader), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(waitset), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
||||
}
|
||||
#undef MAX_WRITERS
|
||||
|
||||
/**
|
||||
* Check the counts in liveliness_changed_status result.
|
||||
*/
|
||||
CU_Test(ddsc_liveliness, status_counts, .init = liveliness_init, .fini = liveliness_fini)
|
||||
{
|
||||
dds_entity_t pub_topic;
|
||||
dds_entity_t sub_topic;
|
||||
dds_entity_t reader;
|
||||
dds_entity_t writer;
|
||||
dds_entity_t waitset;
|
||||
dds_qos_t *rqos;
|
||||
dds_qos_t *wqos;
|
||||
dds_attach_t triggered;
|
||||
struct dds_liveliness_changed_status lstatus;
|
||||
struct dds_subscription_matched_status sstatus;
|
||||
char name[100];
|
||||
dds_duration_t ldur = DDS_MSECS(500);
|
||||
Space_Type1 sample = {1, 0, 0};
|
||||
|
||||
/* topics */
|
||||
create_topic_name("ddsc_liveliness_status_counts", g_topic_nr++, name, sizeof name);
|
||||
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
|
||||
/* reader */
|
||||
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
|
||||
dds_delete_qos(rqos);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||
CU_ASSERT_FATAL((waitset = dds_create_waitset(g_sub_participant)) > 0);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
||||
|
||||
/* writer */
|
||||
CU_ASSERT_FATAL((wqos = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(wqos, DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, ldur);
|
||||
CU_ASSERT_FATAL((writer = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
|
||||
dds_delete_qos(wqos);
|
||||
|
||||
/* wait for writer to be alive */
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
|
||||
|
||||
/* check status counts before proxy writer is expired */
|
||||
dds_get_liveliness_changed_status(reader, &lstatus);
|
||||
CU_ASSERT_EQUAL_FATAL(lstatus.alive_count, 1);
|
||||
dds_get_subscription_matched_status(reader, &sstatus);
|
||||
CU_ASSERT_EQUAL_FATAL(sstatus.current_count, 1);
|
||||
|
||||
/* sleep for more than lease duration, writer should be set not-alive but subscription still matched */
|
||||
dds_sleepfor(ldur + DDS_MSECS(100));
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
|
||||
|
||||
dds_get_liveliness_changed_status(reader, &lstatus);
|
||||
CU_ASSERT_EQUAL_FATAL(lstatus.alive_count, 0);
|
||||
dds_get_subscription_matched_status(reader, &sstatus);
|
||||
CU_ASSERT_EQUAL_FATAL(sstatus.current_count, 1);
|
||||
|
||||
/* write sample and re-check status counts */
|
||||
dds_write(writer, &sample);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
|
||||
|
||||
dds_get_liveliness_changed_status(reader, &lstatus);
|
||||
CU_ASSERT_EQUAL_FATAL(lstatus.alive_count, 1);
|
||||
dds_get_subscription_matched_status(reader, &sstatus);
|
||||
CU_ASSERT_EQUAL_FATAL(sstatus.current_count, 1);
|
||||
|
||||
/* cleanup */
|
||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_detach(waitset, reader), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(waitset), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(writer), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that dds_assert_liveliness works as expected for liveliness
|
||||
* kinds manual-by-participant and manual-by-topic.
|
||||
*/
|
||||
#define MAX_WRITERS 100
|
||||
CU_TheoryDataPoints(ddsc_liveliness, assert_liveliness) = {
|
||||
CU_DataPoints(uint32_t, 1, 0, 0, 1), /* number of writers with automatic liveliness */
|
||||
CU_DataPoints(uint32_t, 1, 1, 0, 0), /* number of writers with manual-by-participant liveliness */
|
||||
CU_DataPoints(uint32_t, 1, 1, 1, 2), /* number of writers with manual-by-topic liveliness */
|
||||
};
|
||||
CU_Theory((uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp), ddsc_liveliness, assert_liveliness, .init = liveliness_init, .fini = liveliness_fini, .timeout = 60)
|
||||
{
|
||||
dds_entity_t pub_topic, sub_topic, reader, writers[MAX_WRITERS];
|
||||
dds_qos_t *rqos;
|
||||
struct dds_liveliness_changed_status lstatus;
|
||||
char name[100];
|
||||
uint32_t ldur = 100, wr_cnt, run = 1, stopped;
|
||||
dds_time_t tstart, tstop, t;
|
||||
bool test_finished = false;
|
||||
|
||||
do
|
||||
{
|
||||
wr_cnt = 0;
|
||||
assert(wr_cnt_auto + wr_cnt_man_pp + wr_cnt_man_tp < MAX_WRITERS);
|
||||
printf("running test assert_liveliness: auto/man-by-part/man-by-topic %u/%u/%u with ldur %d\n",
|
||||
wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, ldur);
|
||||
|
||||
/* topics */
|
||||
create_topic_name("ddsc_liveliness_assert", g_topic_nr++, name, sizeof name);
|
||||
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||
|
||||
/* reader */
|
||||
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
||||
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
|
||||
dds_delete_qos(rqos);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||
|
||||
/* writers */
|
||||
for (size_t n = 0; n < wr_cnt_auto; n++)
|
||||
add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(ldur), &writers[wr_cnt++], pub_topic, reader);
|
||||
tstart = dds_time();
|
||||
for (size_t n = 0; n < wr_cnt_man_pp; n++)
|
||||
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(ldur), &writers[wr_cnt++], pub_topic, reader);
|
||||
for (size_t n = 0; n < wr_cnt_man_tp; n++)
|
||||
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_TOPIC, DDS_MSECS(ldur), &writers[wr_cnt++], pub_topic, reader);
|
||||
t = dds_time();
|
||||
if (t - tstart > DDS_MSECS(0.5 * ldur))
|
||||
{
|
||||
ldur *= 10 / (run + 1);
|
||||
printf("%d.%06d failed to create writers with non-automatic liveliness kind in time\n",
|
||||
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* check status counts before proxy writer is expired */
|
||||
dds_get_liveliness_changed_status(reader, &lstatus);
|
||||
CU_ASSERT_EQUAL_FATAL(lstatus.alive_count, wr_cnt_auto + wr_cnt_man_pp + wr_cnt_man_tp);
|
||||
|
||||
/* delay for more than lease duration and assert liveliness on writers:
|
||||
all writers (including man-by-pp) should be kept alive */
|
||||
tstop = dds_time() + 4 * DDS_MSECS(ldur) / 3;
|
||||
stopped = 0;
|
||||
do
|
||||
{
|
||||
for (size_t n = wr_cnt - wr_cnt_man_tp; n < wr_cnt; n++)
|
||||
dds_assert_liveliness(writers[n]);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
|
||||
stopped += (uint32_t)lstatus.not_alive_count_change;
|
||||
dds_sleepfor(DDS_MSECS(50));
|
||||
} while (dds_time() < tstop);
|
||||
dds_get_liveliness_changed_status(reader, &lstatus);
|
||||
printf("writers alive with dds_assert_liveliness on all writers: %d, writers stopped: %d\n", lstatus.alive_count, stopped);
|
||||
if (lstatus.alive_count != wr_cnt_auto + wr_cnt_man_pp + wr_cnt_man_tp || stopped != 0)
|
||||
{
|
||||
ldur *= 10 / (run + 1);
|
||||
printf("incorrect number of writers alive or stopped writers\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* delay for more than lease duration and assert liveliness on participant:
|
||||
writers with liveliness man-by-pp should be kept alive, man-by-topic writers
|
||||
should stop */
|
||||
tstop = dds_time() + 4 * DDS_MSECS(ldur) / 3;
|
||||
stopped = 0;
|
||||
do
|
||||
{
|
||||
dds_assert_liveliness(g_pub_participant);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
|
||||
stopped += (uint32_t)lstatus.not_alive_count_change;
|
||||
dds_sleepfor(DDS_MSECS(50));
|
||||
} while (dds_time() < tstop);
|
||||
dds_get_liveliness_changed_status(reader, &lstatus);
|
||||
printf("writers alive with dds_assert_liveliness on participant: %d, writers stopped: %d\n", lstatus.alive_count, stopped);
|
||||
if (lstatus.alive_count != wr_cnt_auto + wr_cnt_man_pp || stopped != wr_cnt_man_tp)
|
||||
{
|
||||
ldur *= 10 / (run + 1);
|
||||
printf("incorrect number of writers alive or stopped writers\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
test_finished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
||||
for (size_t n = 0; n < wr_cnt; n++)
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(writers[n]), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
||||
|
||||
if (!test_finished)
|
||||
{
|
||||
if (++run > 3)
|
||||
{
|
||||
CU_FAIL_FATAL("Run limit reached");
|
||||
test_finished = true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("restarting test with ldur %d\n", ldur);
|
||||
}
|
||||
}
|
||||
} while (!test_finished);
|
||||
}
|
||||
#undef MAX_WRITERS
|
|
@ -19,6 +19,7 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src"
|
|||
ddsi_ipaddr.c
|
||||
ddsi_mcgroup.c
|
||||
ddsi_security_omg.c
|
||||
ddsi_portmapping.c
|
||||
ddsi_serdata.c
|
||||
ddsi_serdata_default.c
|
||||
ddsi_sertopic.c
|
||||
|
@ -28,6 +29,7 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src"
|
|||
ddsi_vendor.c
|
||||
ddsi_threadmon.c
|
||||
ddsi_rhc.c
|
||||
ddsi_pmd.c
|
||||
q_addrset.c
|
||||
q_bitset_inlines.c
|
||||
q_bswap.c
|
||||
|
@ -71,6 +73,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi"
|
|||
ddsi_mcgroup.h
|
||||
ddsi_plist_generic.h
|
||||
ddsi_security_omg.h
|
||||
ddsi_portmapping.h
|
||||
ddsi_serdata.h
|
||||
ddsi_sertopic.h
|
||||
ddsi_serdata_default.h
|
||||
|
|
35
src/core/ddsi/include/dds/ddsi/ddsi_pmd.h
Normal file
35
src/core/ddsi/include/dds/ddsi/ddsi_pmd.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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
|
||||
* 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_PMD_H
|
||||
#define DDSI_PMD_H
|
||||
|
||||
#include "dds/ddsi/q_time.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct q_globals;
|
||||
struct thread_state1;
|
||||
struct ddsi_guid;
|
||||
struct nn_xpack;
|
||||
struct participant;
|
||||
struct receiver_state;
|
||||
|
||||
void write_pmd_message_guid (struct q_globals * const gv, struct ddsi_guid *pp_guid, unsigned pmd_kind);
|
||||
void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack *xp, struct participant *pp, unsigned pmd_kind);
|
||||
void handle_pmd_message (const struct receiver_state *rst, nn_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* DDSI_PMD_H */
|
49
src/core/ddsi/include/dds/ddsi/ddsi_portmapping.h
Normal file
49
src/core/ddsi/include/dds/ddsi/ddsi_portmapping.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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_PORTMAPPING_H
|
||||
#define DDSI_PORTMAPPING_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum ddsi_port {
|
||||
DDSI_PORT_MULTI_DISC,
|
||||
DDSI_PORT_MULTI_DATA,
|
||||
DDSI_PORT_UNI_DISC,
|
||||
DDSI_PORT_UNI_DATA
|
||||
};
|
||||
|
||||
struct ddsi_portmapping {
|
||||
uint32_t base;
|
||||
uint32_t dg;
|
||||
uint32_t pg;
|
||||
uint32_t d0;
|
||||
uint32_t d1;
|
||||
uint32_t d2;
|
||||
uint32_t d3;
|
||||
};
|
||||
|
||||
struct config;
|
||||
|
||||
bool ddsi_valid_portmapping (const struct config *config, int32_t participant_index, char *msg, size_t msgsize);
|
||||
uint32_t ddsi_get_port (const struct config *config, enum ddsi_port which, int32_t participant_index);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSI_PORTMAPPING_H */
|
|
@ -61,7 +61,7 @@ typedef void (*ddsi_tran_peer_locator_fn_t) (ddsi_tran_conn_t, nn_locator_t *);
|
|||
typedef void (*ddsi_tran_disable_multiplexing_fn_t) (ddsi_tran_conn_t);
|
||||
typedef ddsi_tran_conn_t (*ddsi_tran_accept_fn_t) (ddsi_tran_listener_t);
|
||||
typedef ddsi_tran_conn_t (*ddsi_tran_create_conn_fn_t) (ddsi_tran_factory_t fact, uint32_t, ddsi_tran_qos_t);
|
||||
typedef ddsi_tran_listener_t (*ddsi_tran_create_listener_fn_t) (ddsi_tran_factory_t fact, int port, ddsi_tran_qos_t);
|
||||
typedef ddsi_tran_listener_t (*ddsi_tran_create_listener_fn_t) (ddsi_tran_factory_t fact, uint32_t port, ddsi_tran_qos_t);
|
||||
typedef void (*ddsi_tran_release_conn_fn_t) (ddsi_tran_conn_t);
|
||||
typedef void (*ddsi_tran_close_conn_fn_t) (ddsi_tran_conn_t);
|
||||
typedef void (*ddsi_tran_unblock_listener_fn_t) (ddsi_tran_listener_t);
|
||||
|
@ -70,6 +70,7 @@ typedef int (*ddsi_tran_join_mc_fn_t) (ddsi_tran_conn_t, const nn_locator_t *src
|
|||
typedef int (*ddsi_tran_leave_mc_fn_t) (ddsi_tran_conn_t, const nn_locator_t *srcip, const nn_locator_t *mcip, const struct nn_interface *interf);
|
||||
typedef int (*ddsi_is_mcaddr_fn_t) (ddsi_tran_factory_t tran, const nn_locator_t *loc);
|
||||
typedef int (*ddsi_is_ssm_mcaddr_fn_t) (ddsi_tran_factory_t tran, const nn_locator_t *loc);
|
||||
typedef int (*ddsi_is_valid_port_fn_t) (ddsi_tran_factory_t tran, uint32_t port);
|
||||
|
||||
enum ddsi_nearby_address_result {
|
||||
DNAR_DISTANT,
|
||||
|
@ -172,7 +173,8 @@ struct ddsi_tran_factory
|
|||
ddsi_locator_from_string_fn_t m_locator_from_string_fn;
|
||||
ddsi_locator_to_string_fn_t m_locator_to_string_fn;
|
||||
ddsi_enumerate_interfaces_fn_t m_enumerate_interfaces_fn;
|
||||
|
||||
ddsi_is_valid_port_fn_t m_is_valid_port_fn;
|
||||
|
||||
/* Data */
|
||||
|
||||
int32_t m_kind;
|
||||
|
@ -205,10 +207,17 @@ void ddsi_factory_conn_init (const struct ddsi_tran_factory *factory, ddsi_tran_
|
|||
inline bool ddsi_factory_supports (const struct ddsi_tran_factory *factory, int32_t kind) {
|
||||
return factory->m_supports_fn (factory, kind);
|
||||
}
|
||||
inline int ddsi_is_valid_port (ddsi_tran_factory_t factory, uint32_t port) {
|
||||
return factory->m_is_valid_port_fn (factory, port);
|
||||
}
|
||||
inline ddsi_tran_conn_t ddsi_factory_create_conn (ddsi_tran_factory_t factory, uint32_t port, ddsi_tran_qos_t qos) {
|
||||
if (!ddsi_is_valid_port (factory, port))
|
||||
return NULL;
|
||||
return factory->m_create_conn_fn (factory, port, qos);
|
||||
}
|
||||
inline ddsi_tran_listener_t ddsi_factory_create_listener (ddsi_tran_factory_t factory, int port, ddsi_tran_qos_t qos) {
|
||||
inline ddsi_tran_listener_t ddsi_factory_create_listener (ddsi_tran_factory_t factory, uint32_t port, ddsi_tran_qos_t qos) {
|
||||
if (!ddsi_is_valid_port (factory, port))
|
||||
return NULL;
|
||||
return factory->m_create_listener_fn (factory, port, qos);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,17 +16,12 @@
|
|||
#include "dds/ddsi/q_thread.h"
|
||||
#include "dds/ddsi/q_xqos.h"
|
||||
#include "dds/ddsi/q_feature_check.h"
|
||||
#include "dds/ddsi/ddsi_portmapping.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* FIXME: should eventually move to abstraction layer */
|
||||
typedef enum q__schedPrioClass {
|
||||
Q__SCHED_PRIO_RELATIVE,
|
||||
Q__SCHED_PRIO_ABSOLUTE
|
||||
} q__schedPrioClass;
|
||||
|
||||
enum nn_standards_conformance {
|
||||
NN_SC_PEDANTIC,
|
||||
NN_SC_STRICT,
|
||||
|
@ -54,14 +49,6 @@ enum boolean_default {
|
|||
BOOLDEF_TRUE
|
||||
};
|
||||
|
||||
enum durability_cdr
|
||||
{
|
||||
DUR_CDR_LE,
|
||||
DUR_CDR_BE,
|
||||
DUR_CDR_SERVER,
|
||||
DUR_CDR_CLIENT
|
||||
};
|
||||
|
||||
#define PARTICIPANT_INDEX_AUTO -1
|
||||
#define PARTICIPANT_INDEX_NONE -2
|
||||
|
||||
|
@ -77,7 +64,6 @@ struct config_networkpartition_listelem {
|
|||
char *address_string;
|
||||
struct addrset *as;
|
||||
int connected;
|
||||
uint32_t partitionHash;
|
||||
uint32_t partitionId;
|
||||
};
|
||||
|
||||
|
@ -245,9 +231,10 @@ struct config
|
|||
int dontRoute;
|
||||
int enableMulticastLoopback;
|
||||
uint32_t domainId;
|
||||
struct config_maybe_uint32 extDomainId; // domain id advertised in discovery
|
||||
char *domainTag;
|
||||
int participantIndex;
|
||||
int maxAutoParticipantIndex;
|
||||
uint32_t port_base;
|
||||
char *spdpMulticastAddressString;
|
||||
char *defaultMulticastAddressString;
|
||||
char *assumeMulticastCapable;
|
||||
|
@ -370,12 +357,7 @@ struct config
|
|||
enum many_sockets_mode many_sockets_mode;
|
||||
int assume_rti_has_pmd_endpoints;
|
||||
|
||||
uint32_t port_dg;
|
||||
uint32_t port_pg;
|
||||
uint32_t port_d0;
|
||||
uint32_t port_d1;
|
||||
uint32_t port_d2;
|
||||
uint32_t port_d3;
|
||||
struct ddsi_portmapping ports;
|
||||
|
||||
int monitor_port;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ struct debug_monitor;
|
|||
typedef int (*debug_monitor_cpf_t) (ddsi_tran_conn_t conn, const char *fmt, ...);
|
||||
typedef int (*debug_monitor_plugin_t) (ddsi_tran_conn_t conn, debug_monitor_cpf_t cpf, void *arg);
|
||||
|
||||
struct debug_monitor *new_debug_monitor (struct q_globals *gv, int port);
|
||||
struct debug_monitor *new_debug_monitor (struct q_globals *gv, int32_t port);
|
||||
void add_debug_monitor_plugin (struct debug_monitor *dm, debug_monitor_plugin_t fn, void *arg);
|
||||
void free_debug_monitor (struct debug_monitor *dm);
|
||||
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
#ifndef Q_ENTITY_H
|
||||
#define Q_ENTITY_H
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/atomics.h"
|
||||
#include "dds/ddsrt/avl.h"
|
||||
#include "dds/ddsrt/fibheap.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsi/q_rtps.h"
|
||||
#include "dds/ddsi/q_plist.h"
|
||||
|
@ -48,14 +50,25 @@ struct proxy_group;
|
|||
struct proxy_endpoint_common;
|
||||
typedef void (*ddsi2direct_directread_cb_t) (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, void *arg);
|
||||
|
||||
/* Liveliness changed is more complicated than just add/remove. Encode the event
|
||||
in status_cb_data_t::extra and ignore status_cb_data_t::add */
|
||||
enum liveliness_changed_data_extra {
|
||||
LIVELINESS_CHANGED_ADD_ALIVE,
|
||||
LIVELINESS_CHANGED_ADD_NOT_ALIVE,
|
||||
LIVELINESS_CHANGED_REMOVE_NOT_ALIVE,
|
||||
LIVELINESS_CHANGED_REMOVE_ALIVE,
|
||||
LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE,
|
||||
LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE,
|
||||
LIVELINESS_CHANGED_TWITCH
|
||||
};
|
||||
|
||||
typedef struct status_cb_data
|
||||
{
|
||||
int raw_status_id;
|
||||
uint32_t extra;
|
||||
uint64_t handle;
|
||||
bool add;
|
||||
}
|
||||
status_cb_data_t;
|
||||
} status_cb_data_t;
|
||||
|
||||
typedef void (*status_cb_t) (void *entity, const status_cb_data_t *data);
|
||||
|
||||
|
@ -67,6 +80,8 @@ struct prd_wr_match {
|
|||
struct rd_pwr_match {
|
||||
ddsrt_avl_node_t avlnode;
|
||||
ddsi_guid_t pwr_guid;
|
||||
unsigned pwr_alive: 1; /* tracks pwr's alive state */
|
||||
uint32_t pwr_alive_vclock; /* used to ensure progress */
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
nn_locator_t ssm_mc_loc;
|
||||
nn_locator_t ssm_src_loc;
|
||||
|
@ -189,6 +204,7 @@ struct participant
|
|||
int32_t user_refc; /* number of non-built-in endpoints in this participant [refc_lock] */
|
||||
int32_t builtin_refc; /* number of built-in endpoints in this participant [refc_lock] */
|
||||
int builtins_deleted; /* whether deletion of built-in endpoints has been initiated [refc_lock] */
|
||||
ddsrt_fibheap_t ldur_auto_wr; /* Heap that contains lease duration for writers with automatic liveliness in this participant */
|
||||
};
|
||||
|
||||
struct endpoint_common {
|
||||
|
@ -210,6 +226,11 @@ enum writer_state {
|
|||
|
||||
typedef ddsrt_atomic_uint64_t seq_xmit_t;
|
||||
|
||||
struct ldur_fhnode {
|
||||
ddsrt_fibheap_node_t heapnode;
|
||||
dds_duration_t ldur;
|
||||
};
|
||||
|
||||
struct writer
|
||||
{
|
||||
struct entity_common e;
|
||||
|
@ -239,7 +260,7 @@ struct writer
|
|||
struct addrset *as; /* set of addresses to publish to */
|
||||
struct addrset *as_group; /* alternate case, used for SPDP, when using Cloud with multiple bootstrap locators */
|
||||
struct xevent *heartbeat_xevent; /* timed event for "periodically" publishing heartbeats when unack'd data present, NULL <=> unreliable */
|
||||
dds_duration_t lease_duration;
|
||||
struct ldur_fhnode *lease_duration; /* fibheap node to keep lease duration for this writer, NULL in case of automatic liveliness with inifite duration */
|
||||
struct whc *whc; /* WHC tracking history, T-L durability service history + samples by sequence number for retransmit */
|
||||
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" */
|
||||
|
@ -305,7 +326,11 @@ struct proxy_participant
|
|||
unsigned prismtech_bes; /* prismtech-specific extension of built-in endpoints set */
|
||||
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 */
|
||||
ddsrt_atomic_voidp_t minl_auto; /* lease object for shortest automatic liveliness pwr's lease (includes this proxypp's lease) */
|
||||
ddsrt_fibheap_t leaseheap_auto; /* keeps leases for this proxypp and leases for pwrs (with liveliness automatic) */
|
||||
ddsrt_atomic_voidp_t minl_man; /* lease object for shortest manual-by-participant liveliness pwr's lease */
|
||||
ddsrt_fibheap_t leaseheap_man; /* keeps leases for this proxypp and leases for pwrs (with liveliness manual-by-participant) */
|
||||
struct lease *lease; /* lease for this proxypp */
|
||||
struct addrset *as_default; /* default address set to use for user data traffic */
|
||||
struct addrset *as_meta; /* default address set to use for discovery traffic */
|
||||
struct proxy_endpoint_common *endpoints; /* all proxy endpoints can be reached from here */
|
||||
|
@ -316,6 +341,7 @@ struct proxy_participant
|
|||
unsigned is_ddsi2_pp: 1; /* if this is the federation-leader on the remote node */
|
||||
unsigned minimal_bes_mode: 1;
|
||||
unsigned lease_expired: 1;
|
||||
unsigned deleting: 1;
|
||||
unsigned proxypp_have_spdp: 1;
|
||||
unsigned proxypp_have_cm: 1;
|
||||
unsigned owns_lease: 1;
|
||||
|
@ -368,10 +394,12 @@ struct proxy_writer {
|
|||
unsigned deliver_synchronously: 1; /* iff 1, delivery happens straight from receive thread for non-historical data; else through delivery queue "dqueue" */
|
||||
unsigned have_seen_heartbeat: 1; /* iff 1, we have received at least on heartbeat from this proxy writer */
|
||||
unsigned local_matching_inprogress: 1; /* iff 1, we are still busy matching local readers; this is so we don't deliver incoming data to some but not all readers initially */
|
||||
unsigned alive: 1; /* iff 1, the proxy writer is alive (lease for this proxy writer is not expired); field may be modified only when holding both pwr->e.lock and pwr->c.proxypp->e.lock */
|
||||
unsigned filtered: 1; /* iff 1, builtin proxy writer uses content filter, which affects heartbeats and gaps. */
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
unsigned supports_ssm: 1; /* iff 1, this proxy writer supports SSM */
|
||||
#endif
|
||||
uint32_t alive_vclock; /* virtual clock counting transitions between alive/not-alive */
|
||||
struct nn_defrag *defrag; /* defragmenter for this proxy writer; FIXME: perhaps shouldn't be for historical data */
|
||||
struct nn_reorder *reorder; /* message reordering for this proxy writer, out-of-sync readers can have their own, see pwr_rd_match */
|
||||
struct nn_dqueue *dqueue; /* delivery queue for asynchronous delivery (historical data is always delivered asynchronously) */
|
||||
|
@ -379,6 +407,7 @@ struct proxy_writer {
|
|||
struct local_reader_ary rdary; /* LOCAL readers for fast-pathing; if not fast-pathed, fall back to scanning local_readers */
|
||||
ddsi2direct_directread_cb_t ddsi2direct_cb;
|
||||
void *ddsi2direct_cbarg;
|
||||
struct lease *lease;
|
||||
};
|
||||
|
||||
|
||||
|
@ -553,10 +582,14 @@ dds_return_t delete_participant (struct q_globals *gv, const struct ddsi_guid *p
|
|||
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 ddsi_guid *guid);
|
||||
|
||||
/* Gets the interval for PMD messages, which is the minimal lease duration for writers
|
||||
with auto liveliness in this participant, or the participants lease duration if shorter */
|
||||
DDS_EXPORT dds_duration_t pp_get_pmd_interval(struct participant *pp);
|
||||
|
||||
/* 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
|
||||
its own writer, use it; else use the privileged participant. */
|
||||
struct writer *get_builtin_writer (const struct participant *pp, unsigned entityid);
|
||||
DDS_EXPORT struct writer *get_builtin_writer (const struct participant *pp, unsigned entityid);
|
||||
|
||||
/* To create a new DDSI writer or reader belonging to participant with
|
||||
GUID "ppguid". May return NULL if participant unknown or
|
||||
|
@ -628,6 +661,7 @@ void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct
|
|||
|
||||
void purge_proxy_participants (struct q_globals *gv, const nn_locator_t *loc, bool delete_from_as_disc);
|
||||
|
||||
|
||||
/* 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 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);
|
||||
|
@ -648,6 +682,10 @@ int delete_proxy_reader (struct q_globals *gv, const struct ddsi_guid *guid, nn_
|
|||
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);
|
||||
|
||||
void proxy_writer_set_alive_may_unlock (struct proxy_writer *pwr, bool notify);
|
||||
int proxy_writer_set_notalive (struct proxy_writer *pwr, bool notify);
|
||||
void proxy_writer_set_notalive_guid (struct q_globals *gv, const struct ddsi_guid *pwrguid, bool notify);
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ struct ddsi_guid;
|
|||
EK_PROXY_READER
|
||||
};
|
||||
#define EK_NKINDS ((int) EK_PROXY_READER + 1)
|
||||
|
||||
|
||||
struct ephash_enum
|
||||
{
|
||||
struct ddsrt_chh_iter it;
|
||||
|
@ -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 ddsi_guid *guid);
|
||||
void *ephash_lookup_guid (const struct ephash *eh, const struct ddsi_guid *guid, enum entity_kind kind);
|
||||
DDS_EXPORT void *ephash_lookup_guid_untyped (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
DDS_EXPORT 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 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);
|
||||
DDS_EXPORT struct participant *ephash_lookup_participant_guid (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
DDS_EXPORT struct proxy_participant *ephash_lookup_proxy_participant_guid (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
DDS_EXPORT struct writer *ephash_lookup_writer_guid (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
DDS_EXPORT struct reader *ephash_lookup_reader_guid (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
DDS_EXPORT struct proxy_writer *ephash_lookup_proxy_writer_guid (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
DDS_EXPORT struct proxy_reader *ephash_lookup_proxy_reader_guid (const struct ephash *eh, const struct ddsi_guid *guid);
|
||||
|
||||
|
||||
/* Enumeration of entries in the hash table:
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#ifndef Q_LEASE_H
|
||||
#define Q_LEASE_H
|
||||
|
||||
#include "dds/ddsrt/atomics.h"
|
||||
#include "dds/ddsrt/fibheap.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
#include "dds/ddsi/q_time.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
|
@ -20,21 +23,31 @@ extern "C" {
|
|||
|
||||
struct receiver_state;
|
||||
struct participant;
|
||||
struct lease;
|
||||
struct entity_common;
|
||||
struct q_globals; /* FIXME: make a special for the lease admin */
|
||||
|
||||
struct lease {
|
||||
ddsrt_fibheap_node_t heapnode;
|
||||
ddsrt_fibheap_node_t pp_heapnode;
|
||||
nn_etime_t tsched; /* access guarded by leaseheap_lock */
|
||||
ddsrt_atomic_uint64_t tend; /* really an nn_etime_t */
|
||||
dds_duration_t tdur; /* constant (renew depends on it) */
|
||||
struct entity_common *entity; /* constant */
|
||||
};
|
||||
|
||||
int compare_lease_tsched (const void *va, const void *vb);
|
||||
int compare_lease_tdur (const void *va, const void *vb);
|
||||
void lease_management_init (struct q_globals *gv);
|
||||
void lease_management_term (struct q_globals *gv);
|
||||
struct lease *lease_new (nn_etime_t texpire, int64_t tdur, struct entity_common *e);
|
||||
struct lease *lease_clone (const struct lease *l);
|
||||
void lease_register (struct lease *l);
|
||||
void lease_unregister (struct lease *l);
|
||||
void lease_free (struct lease *l);
|
||||
void lease_renew (struct lease *l, nn_etime_t tnow);
|
||||
void lease_set_expiry (struct lease *l, nn_etime_t when);
|
||||
int64_t check_and_handle_lease_expiration (struct q_globals *gv, nn_etime_t tnow);
|
||||
|
||||
void handle_PMD (const struct receiver_state *rst, nn_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -39,8 +39,6 @@ DDS_EXPORT int guid_prefix_eq (const ddsi_guid_prefix_t *a, const ddsi_guid_pref
|
|||
DDS_EXPORT int guid_eq (const struct ddsi_guid *a, const struct ddsi_guid *b);
|
||||
DDS_EXPORT int ddsi2_patmatch (const char *pat, const char *str);
|
||||
|
||||
uint32_t crc32_calc (const void *buf, size_t length);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -56,13 +56,15 @@ extern "C" {
|
|||
#ifdef DDSI_INCLUDE_SSM
|
||||
#define PP_READER_FAVOURS_SSM ((uint64_t)1 << 39)
|
||||
#endif
|
||||
#define PP_DOMAIN_ID ((uint64_t)1 << 40)
|
||||
#define PP_DOMAIN_TAG ((uint64_t)1 << 41)
|
||||
/* Security extensions. */
|
||||
#define PP_IDENTITY_TOKEN ((uint64_t)1 << 41)
|
||||
#define PP_PERMISSIONS_TOKEN ((uint64_t)1 << 42)
|
||||
#define PP_ENDPOINT_SECURITY_INFO ((uint64_t)1 << 43)
|
||||
#define PP_PARTICIPANT_SECURITY_INFO ((uint64_t)1 << 44)
|
||||
#define PP_IDENTITY_STATUS_TOKEN ((uint64_t)1 << 45)
|
||||
#define PP_DATA_TAGS ((uint64_t)1 << 46)
|
||||
#define PP_IDENTITY_TOKEN ((uint64_t)1 << 42)
|
||||
#define PP_PERMISSIONS_TOKEN ((uint64_t)1 << 43)
|
||||
#define PP_ENDPOINT_SECURITY_INFO ((uint64_t)1 << 44)
|
||||
#define PP_PARTICIPANT_SECURITY_INFO ((uint64_t)1 << 45)
|
||||
#define PP_IDENTITY_STATUS_TOKEN ((uint64_t)1 << 46)
|
||||
#define PP_DATA_TAGS ((uint64_t)1 << 47)
|
||||
/* Set for unrecognized parameters that are in the reserved space or
|
||||
in our own vendor-specific space that have the
|
||||
PID_UNRECOGNIZED_INCOMPATIBLE_FLAG set (see DDSI 2.1 9.6.2.2.1) */
|
||||
|
@ -241,6 +243,8 @@ typedef struct nn_plist {
|
|||
#ifdef DDSI_INCLUDE_SSM
|
||||
nn_reader_favours_ssm_t reader_favours_ssm;
|
||||
#endif
|
||||
uint32_t domain_id;
|
||||
char *domain_tag;
|
||||
} nn_plist_t;
|
||||
|
||||
|
||||
|
|
|
@ -350,6 +350,8 @@ DDSRT_WARNING_MSVC_ON(4200)
|
|||
|
||||
#define PID_PAD 0x0u
|
||||
#define PID_SENTINEL 0x1u
|
||||
#define PID_DOMAIN_ID 0xfu
|
||||
#define PID_DOMAIN_TAG (0x14u | PID_UNRECOGNIZED_INCOMPATIBLE_FLAG)
|
||||
#define PID_USER_DATA 0x2cu
|
||||
#define PID_TOPIC_NAME 0x5u
|
||||
#define PID_TYPE_NAME 0x7u
|
||||
|
|
|
@ -98,7 +98,8 @@ struct nn_rmsg {
|
|||
|
||||
struct nn_rmsg_chunk chunk;
|
||||
};
|
||||
#define NN_RMSG_PAYLOAD(m) ((unsigned char *) (&(m)->chunk + 1))
|
||||
DDSRT_STATIC_ASSERT (sizeof (struct nn_rmsg) == offsetof (struct nn_rmsg, chunk) + sizeof (struct nn_rmsg_chunk));
|
||||
#define NN_RMSG_PAYLOAD(m) ((unsigned char *) (m + 1))
|
||||
#define NN_RMSG_PAYLOADOFF(m, o) (NN_RMSG_PAYLOAD (m) + (o))
|
||||
|
||||
struct receiver_state {
|
||||
|
|
|
@ -27,7 +27,7 @@ typedef int64_t seqno_t;
|
|||
|
||||
#define PGUIDPREFIX(gp) (gp).u[0], (gp).u[1], (gp).u[2]
|
||||
#define PGUID(g) PGUIDPREFIX ((g).prefix), (g).entityid.u
|
||||
#define PGUIDFMT "%"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32
|
||||
#define PGUIDFMT "%" PRIx32 ":%" PRIx32 ":%" PRIx32 ":%" PRIx32
|
||||
|
||||
/* predefined entity ids; here viewed as an unsigned int, on the
|
||||
network as four bytes corresponding to the integer in network byte
|
||||
|
|
|
@ -42,7 +42,8 @@ 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, ddsi_entityid_t dst, int issync);
|
||||
void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_state *whcst, int hbansreq, int hbliveliness, ddsi_entityid_t dst, int issync);
|
||||
dds_return_t write_hb_liveliness (struct q_globals * const gv, struct ddsi_guid *wr_guid, struct nn_xpack *xp);
|
||||
int write_sample_p2p_wrlock_held(struct writer *wr, seqno_t seq, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk, struct proxy_reader *prd);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
|
|
|
@ -123,7 +123,7 @@ char *ddsi_ipaddr_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_
|
|||
(void)tran;
|
||||
assert (sizeof_dst > 1);
|
||||
if (loc->kind == NN_LOCATOR_KIND_INVALID)
|
||||
snprintf (dst, sizeof_dst, "(invalid)");
|
||||
(void) snprintf (dst, sizeof_dst, "(invalid)");
|
||||
else
|
||||
{
|
||||
struct sockaddr_storage src;
|
||||
|
|
|
@ -148,7 +148,7 @@ static char *make_joinleave_msg (char *buf, size_t bufsz, ddsi_tran_conn_t conn,
|
|||
(void) snprintf (interfstr, sizeof (interfstr), "(default)");
|
||||
n = err ? snprintf (buf, bufsz, "error %d in ", err) : 0;
|
||||
if ((size_t) n < bufsz)
|
||||
snprintf (buf + n, bufsz - (size_t) n, "%s conn %p for (%s, %s) interface %s", join ? "join" : "leave", (void *) conn, mcstr, srcstr, interfstr);
|
||||
(void) snprintf (buf + n, bufsz - (size_t) n, "%s conn %p for (%s, %s) interface %s", join ? "join" : "leave", (void *) conn, mcstr, srcstr, interfstr);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
|
160
src/core/ddsi/src/ddsi_pmd.c
Normal file
160
src/core/ddsi/src/ddsi_pmd.c
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* 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
|
||||
* 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 <string.h>
|
||||
#include "dds/ddsi/ddsi_pmd.h"
|
||||
#include "dds/ddsi/ddsi_serdata.h"
|
||||
#include "dds/ddsi/ddsi_serdata_default.h"
|
||||
#include "dds/ddsi/ddsi_tkmap.h"
|
||||
#include "dds/ddsi/q_bswap.h"
|
||||
#include "dds/ddsi/q_entity.h"
|
||||
#include "dds/ddsi/q_globals.h"
|
||||
#include "dds/ddsi/q_lease.h"
|
||||
#include "dds/ddsi/q_log.h"
|
||||
#include "dds/ddsi/q_misc.h"
|
||||
#include "dds/ddsi/q_protocol.h"
|
||||
#include "dds/ddsi/q_radmin.h"
|
||||
#include "dds/ddsi/q_rtps.h"
|
||||
#include "dds/ddsi/q_time.h"
|
||||
#include "dds/ddsi/q_transmit.h"
|
||||
#include "dds/ddsi/q_xmsg.h"
|
||||
|
||||
#include "dds/ddsi/sysdeps.h"
|
||||
|
||||
static void debug_print_rawdata (const struct q_globals *gv, const char *msg, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *c = data;
|
||||
size_t i;
|
||||
GVTRACE ("%s<", msg);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (32 < c[i] && c[i] <= 127)
|
||||
GVTRACE ("%s%c", (i > 0 && (i%4) == 0) ? " " : "", c[i]);
|
||||
else
|
||||
GVTRACE ("%s\\x%02x", (i > 0 && (i%4) == 0) ? " " : "", c[i]);
|
||||
}
|
||||
GVTRACE (">");
|
||||
}
|
||||
|
||||
void write_pmd_message_guid (struct q_globals * const gv, struct ddsi_guid *pp_guid, unsigned pmd_kind)
|
||||
{
|
||||
struct thread_state1 * const ts1 = lookup_thread_state ();
|
||||
thread_state_awake (ts1, gv);
|
||||
struct participant *pp = ephash_lookup_participant_guid (gv->guid_hash, pp_guid);
|
||||
if (pp == NULL)
|
||||
GVTRACE ("write_pmd_message("PGUIDFMT") - builtin pmd writer not found\n", PGUID (*pp_guid));
|
||||
else
|
||||
write_pmd_message (ts1, NULL, pp, pmd_kind);
|
||||
thread_state_asleep (ts1);
|
||||
}
|
||||
|
||||
void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack *xp, struct participant *pp, unsigned pmd_kind)
|
||||
{
|
||||
#define PMD_DATA_LENGTH 1
|
||||
struct q_globals * const gv = pp->e.gv;
|
||||
struct writer *wr;
|
||||
union {
|
||||
ParticipantMessageData_t pmd;
|
||||
char pad[offsetof (ParticipantMessageData_t, value) + PMD_DATA_LENGTH];
|
||||
} u;
|
||||
struct ddsi_serdata *serdata;
|
||||
struct ddsi_tkmap_instance *tk;
|
||||
|
||||
if ((wr = get_builtin_writer (pp, NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER)) == NULL)
|
||||
{
|
||||
GVTRACE ("write_pmd_message("PGUIDFMT") - builtin pmd writer not found\n", PGUID (pp->e.guid));
|
||||
return;
|
||||
}
|
||||
|
||||
u.pmd.participantGuidPrefix = nn_hton_guid_prefix (pp->e.guid.prefix);
|
||||
u.pmd.kind = ddsrt_toBE4u (pmd_kind);
|
||||
u.pmd.length = PMD_DATA_LENGTH;
|
||||
memset (u.pmd.value, 0, u.pmd.length);
|
||||
|
||||
struct ddsi_rawcdr_sample raw = {
|
||||
.blob = &u,
|
||||
.size = offsetof (ParticipantMessageData_t, value) + PMD_DATA_LENGTH,
|
||||
.key = &u.pmd,
|
||||
.keysize = 16
|
||||
};
|
||||
serdata = ddsi_serdata_from_sample (gv->rawcdr_topic, SDK_DATA, &raw);
|
||||
serdata->timestamp = now ();
|
||||
|
||||
tk = ddsi_tkmap_lookup_instance_ref (gv->m_tkmap, serdata);
|
||||
write_sample_nogc (ts1, xp, wr, serdata, tk);
|
||||
ddsi_tkmap_instance_unref (gv->m_tkmap, tk);
|
||||
#undef PMD_DATA_LENGTH
|
||||
}
|
||||
|
||||
void handle_pmd_message (const struct receiver_state *rst, nn_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len)
|
||||
{
|
||||
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 *proxypp;
|
||||
ddsi_guid_t ppguid;
|
||||
struct lease *l;
|
||||
RSTTRACE (" PMD ST%x", statusinfo);
|
||||
if (data->identifier != CDR_LE && data->identifier != CDR_BE)
|
||||
{
|
||||
RSTTRACE (" PMD data->identifier %u !?\n", ntohs (data->identifier));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER))
|
||||
{
|
||||
case 0:
|
||||
if (offsetof (ParticipantMessageData_t, value) > len - sizeof (struct CDRHeader))
|
||||
debug_print_rawdata (rst->gv, " SHORT1", data, len);
|
||||
else
|
||||
{
|
||||
const ParticipantMessageData_t *pmd = (ParticipantMessageData_t *) (data + 1);
|
||||
ddsi_guid_prefix_t p = nn_ntoh_guid_prefix (pmd->participantGuidPrefix);
|
||||
uint32_t kind = ntohl (pmd->kind);
|
||||
uint32_t length = bswap ? ddsrt_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);
|
||||
if (len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value) < length)
|
||||
debug_print_rawdata (rst->gv, " SHORT2", pmd->value, len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value));
|
||||
else
|
||||
debug_print_rawdata (rst->gv, "", pmd->value, length);
|
||||
ppguid.prefix = p;
|
||||
ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
|
||||
if ((proxypp = ephash_lookup_proxy_participant_guid (rst->gv->guid_hash, &ppguid)) == NULL)
|
||||
RSTTRACE (" PPunknown");
|
||||
else if (kind == PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE &&
|
||||
(l = ddsrt_atomic_ldvoidp (&proxypp->minl_man)) != NULL)
|
||||
{
|
||||
/* Renew lease for entity with shortest manual-by-participant lease */
|
||||
lease_renew (l, now_et ());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NN_STATUSINFO_DISPOSE:
|
||||
case NN_STATUSINFO_UNREGISTER:
|
||||
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 (ddsi_guid_prefix_t))
|
||||
debug_print_rawdata (rst->gv, " SHORT3", data, len);
|
||||
else
|
||||
{
|
||||
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");
|
||||
else
|
||||
RSTTRACE (" delete");
|
||||
}
|
||||
break;
|
||||
}
|
||||
RSTTRACE ("\n");
|
||||
}
|
126
src/core/ddsi/src/ddsi_portmapping.c
Normal file
126
src/core/ddsi/src/ddsi_portmapping.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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 "dds/ddsi/ddsi_portmapping.h"
|
||||
#include "dds/ddsi/q_config.h"
|
||||
|
||||
static bool get_port_int (uint32_t *port, const struct ddsi_portmapping *map, enum ddsi_port which, uint32_t domain_id, int32_t participant_index, char *str_if_overflow, size_t strsize)
|
||||
{
|
||||
uint32_t off = UINT32_MAX, ppidx = UINT32_MAX;
|
||||
|
||||
assert (domain_id != UINT32_MAX);
|
||||
assert (participant_index >= 0 || participant_index == PARTICIPANT_INDEX_NONE);
|
||||
|
||||
switch (which)
|
||||
{
|
||||
case DDSI_PORT_MULTI_DISC:
|
||||
off = map->d0;
|
||||
/* multicast port numbers are not affected by participant index */
|
||||
ppidx = 0;
|
||||
break;
|
||||
case DDSI_PORT_MULTI_DATA:
|
||||
off = map->d2;
|
||||
/* multicast port numbers are not affected by participant index */
|
||||
ppidx = 0;
|
||||
break;
|
||||
case DDSI_PORT_UNI_DISC:
|
||||
if (participant_index == PARTICIPANT_INDEX_NONE)
|
||||
{
|
||||
/* participant index "none" means unicast ports get chosen by the transport */
|
||||
*port = 0;
|
||||
return true;
|
||||
}
|
||||
off = map->d1;
|
||||
ppidx = (uint32_t) participant_index;
|
||||
break;
|
||||
case DDSI_PORT_UNI_DATA:
|
||||
if (participant_index == PARTICIPANT_INDEX_NONE)
|
||||
{
|
||||
/* participant index "none" means unicast ports get chosen by the transport */
|
||||
*port = 0;
|
||||
return true;
|
||||
}
|
||||
off = map->d3;
|
||||
ppidx = (uint32_t) participant_index;
|
||||
break;
|
||||
}
|
||||
|
||||
const uint64_t a = (uint64_t) map->dg * domain_id;
|
||||
const uint64_t b = map->base + (uint64_t) map->pg * ppidx + off;
|
||||
|
||||
/* For the mapping to be valid, the port number must be in range of an unsigned 32 bit integer and must
|
||||
not be 0 (as that is used for indicating a random port should be selected by the transport). The
|
||||
transports may limit this further, but at least we won't have to worry about overflow anymore. */
|
||||
*port = (uint32_t) (a + b);
|
||||
if (a <= UINT32_MAX && b <= UINT32_MAX - a && *port > 0)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
/* a, b < 2^64 ~ 18e18; 2^32 <= a + b < 2^65 ~ 36e18
|
||||
2^32 ~ 4e9, so it can easily be split into (a+b) `div` 1e9 and (a+b) `mod` 1e9
|
||||
and then the most-significant part is guaranteed to be > 0 */
|
||||
const uint32_t billion = 1000000000;
|
||||
const uint32_t y = (uint32_t) (a % billion) + (uint32_t) (b % billion);
|
||||
const uint64_t x = (a / billion) + (b / billion) + (y / billion);
|
||||
snprintf (str_if_overflow, strsize, "%"PRIu64"%09"PRIu32, x, y % billion);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *portname (enum ddsi_port which)
|
||||
{
|
||||
const char *n = "?";
|
||||
switch (which)
|
||||
{
|
||||
case DDSI_PORT_MULTI_DISC: n = "multicast discovery"; break;
|
||||
case DDSI_PORT_MULTI_DATA: n = "multicast data"; break;
|
||||
case DDSI_PORT_UNI_DISC: n = "unicast discovery"; break;
|
||||
case DDSI_PORT_UNI_DATA: n = "unicast data"; break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
bool ddsi_valid_portmapping (const struct config *config, int32_t participant_index, char *msg, size_t msgsize)
|
||||
{
|
||||
DDSRT_STATIC_ASSERT (DDSI_PORT_MULTI_DISC >= 0 &&
|
||||
DDSI_PORT_MULTI_DISC + 1 == DDSI_PORT_MULTI_DATA &&
|
||||
DDSI_PORT_MULTI_DATA + 1 == DDSI_PORT_UNI_DISC &&
|
||||
DDSI_PORT_UNI_DISC + 1 == DDSI_PORT_UNI_DATA &&
|
||||
DDSI_PORT_UNI_DATA >= 0);
|
||||
uint32_t dummy_port;
|
||||
char str[32];
|
||||
bool ok = true;
|
||||
enum ddsi_port which = DDSI_PORT_MULTI_DISC;
|
||||
int n = snprintf (msg, msgsize, "port number(s) of out range:");
|
||||
size_t pos = (n >= 0 && (size_t) n <= msgsize) ? (size_t) n : msgsize;
|
||||
do {
|
||||
if (!get_port_int (&dummy_port, &config->ports, which, config->extDomainId.value, participant_index, str, sizeof (str)))
|
||||
{
|
||||
n = snprintf (msg + pos, msgsize - pos, "%s %s %s", ok ? "" : ",", portname (which), str);
|
||||
if (n >= 0 && (size_t) n <= msgsize - pos)
|
||||
pos += (size_t) n;
|
||||
ok = false;
|
||||
}
|
||||
} while (which++ != DDSI_PORT_UNI_DATA);
|
||||
return ok;
|
||||
}
|
||||
|
||||
uint32_t ddsi_get_port (const struct config *config, enum ddsi_port which, int32_t participant_index)
|
||||
{
|
||||
/* Not supposed to come here if port mapping is invalid */
|
||||
uint32_t port;
|
||||
char str[32];
|
||||
bool ok = get_port_int (&port, &config->ports, which, config->extDomainId.value, participant_index, str, sizeof (str));
|
||||
assert (ok);
|
||||
(void) ok;
|
||||
return port;
|
||||
}
|
|
@ -42,13 +42,13 @@ static char *ddsi_raweth_to_string (ddsi_tran_factory_t tran, char *dst, size_t
|
|||
{
|
||||
(void)tran;
|
||||
if (with_port)
|
||||
snprintf(dst, sizeof_dst, "[%02x:%02x:%02x:%02x:%02x:%02x]:%u",
|
||||
loc->address[10], loc->address[11], loc->address[12],
|
||||
loc->address[13], loc->address[14], loc->address[15], loc->port);
|
||||
(void) snprintf(dst, sizeof_dst, "[%02x:%02x:%02x:%02x:%02x:%02x]:%u",
|
||||
loc->address[10], loc->address[11], loc->address[12],
|
||||
loc->address[13], loc->address[14], loc->address[15], loc->port);
|
||||
else
|
||||
snprintf(dst, sizeof_dst, "[%02x:%02x:%02x:%02x:%02x:%02x]",
|
||||
loc->address[10], loc->address[11], loc->address[12],
|
||||
loc->address[13], loc->address[14], loc->address[15]);
|
||||
(void) snprintf(dst, sizeof_dst, "[%02x:%02x:%02x:%02x:%02x:%02x]",
|
||||
loc->address[10], loc->address[11], loc->address[12],
|
||||
loc->address[13], loc->address[14], loc->address[15]);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
@ -94,9 +94,9 @@ static ssize_t ddsi_raweth_conn_read (ddsi_tran_conn_t conn, unsigned char * buf
|
|||
)
|
||||
{
|
||||
char addrbuf[DDSI_LOCSTRLEN];
|
||||
snprintf(addrbuf, sizeof(addrbuf), "[%02x:%02x:%02x:%02x:%02x:%02x]:%u",
|
||||
src.sll_addr[0], src.sll_addr[1], src.sll_addr[2],
|
||||
src.sll_addr[3], src.sll_addr[4], src.sll_addr[5], ntohs(src.sll_protocol));
|
||||
(void) snprintf(addrbuf, sizeof(addrbuf), "[%02x:%02x:%02x:%02x:%02x:%02x]:%u",
|
||||
src.sll_addr[0], src.sll_addr[1], src.sll_addr[2],
|
||||
src.sll_addr[3], src.sll_addr[4], src.sll_addr[5], ntohs(src.sll_protocol));
|
||||
DDS_CWARNING(&conn->m_base.gv->logconfig, "%s => %d truncated to %d\n", addrbuf, (int)ret, (int)len);
|
||||
}
|
||||
}
|
||||
|
@ -356,6 +356,12 @@ static int ddsi_raweth_enumerate_interfaces (ddsi_tran_factory_t fact, enum tran
|
|||
return ddsrt_getifaddrs(ifs, afs);
|
||||
}
|
||||
|
||||
static int ddsi_raweth_is_valid_port (ddsi_tran_factory_t fact, uint32_t port)
|
||||
{
|
||||
(void) fact;
|
||||
return (port >= 1 && port <= 65535);
|
||||
}
|
||||
|
||||
int ddsi_raweth_init (struct q_globals *gv)
|
||||
{
|
||||
struct ddsi_tran_factory *fact = ddsrt_malloc (sizeof (*fact));
|
||||
|
@ -377,6 +383,7 @@ int ddsi_raweth_init (struct q_globals *gv)
|
|||
fact->m_locator_from_string_fn = ddsi_raweth_address_from_string;
|
||||
fact->m_locator_to_string_fn = ddsi_raweth_to_string;
|
||||
fact->m_enumerate_interfaces_fn = ddsi_raweth_enumerate_interfaces;
|
||||
fact->m_is_valid_port_fn = ddsi_raweth_is_valid_port;
|
||||
ddsi_factory_add (gv, fact);
|
||||
GVLOG (DDS_LC_CONFIG, "raweth initialized\n");
|
||||
return 0;
|
||||
|
|
|
@ -856,7 +856,7 @@ static ddsi_tcp_conn_t ddsi_tcp_new_conn (struct ddsi_tran_factory_tcp *fact, dd
|
|||
return conn;
|
||||
}
|
||||
|
||||
static ddsi_tran_listener_t ddsi_tcp_create_listener (ddsi_tran_factory_t fact, int port, ddsi_tran_qos_t qos)
|
||||
static ddsi_tran_listener_t ddsi_tcp_create_listener (ddsi_tran_factory_t fact, uint32_t port, ddsi_tran_qos_t qos)
|
||||
{
|
||||
char buff[DDSI_LOCSTRLEN];
|
||||
ddsrt_socket_t sock;
|
||||
|
@ -1055,6 +1055,12 @@ static enum ddsi_nearby_address_result ddsi_tcp_is_nearby_address (ddsi_tran_fac
|
|||
return ddsi_ipaddr_is_nearby_address(tran, loc, ownloc, ninterf, interf);
|
||||
}
|
||||
|
||||
static int ddsi_tcp_is_valid_port (ddsi_tran_factory_t fact, uint32_t port)
|
||||
{
|
||||
(void) fact;
|
||||
return (port <= 65535);
|
||||
}
|
||||
|
||||
int ddsi_tcp_init (struct q_globals *gv)
|
||||
{
|
||||
struct ddsi_tran_factory_tcp *fact = ddsrt_malloc (sizeof (*fact));
|
||||
|
@ -1079,6 +1085,7 @@ int ddsi_tcp_init (struct q_globals *gv)
|
|||
fact->fact.m_is_mcaddr_fn = ddsi_tcp_is_mcaddr;
|
||||
fact->fact.m_is_ssm_mcaddr_fn = ddsi_tcp_is_ssm_mcaddr;
|
||||
fact->fact.m_is_nearby_address_fn = ddsi_tcp_is_nearby_address;
|
||||
fact->fact.m_is_valid_port_fn = ddsi_tcp_is_valid_port;
|
||||
ddsi_factory_add (gv, &fact->fact);
|
||||
|
||||
#if DDSRT_HAVE_IPV6
|
||||
|
|
|
@ -23,8 +23,9 @@
|
|||
|
||||
extern inline uint32_t ddsi_conn_type (ddsi_tran_conn_t conn);
|
||||
extern inline uint32_t ddsi_conn_port (ddsi_tran_conn_t conn);
|
||||
extern inline ddsi_tran_listener_t ddsi_factory_create_listener (ddsi_tran_factory_t factory, int port, ddsi_tran_qos_t qos);
|
||||
extern inline ddsi_tran_listener_t ddsi_factory_create_listener (ddsi_tran_factory_t factory, uint32_t port, ddsi_tran_qos_t qos);
|
||||
extern inline bool ddsi_factory_supports (const struct ddsi_tran_factory *factory, int32_t kind);
|
||||
extern inline int ddsi_is_valid_port (ddsi_tran_factory_t factory, uint32_t port);
|
||||
extern inline ddsrt_socket_t ddsi_conn_handle (ddsi_tran_conn_t conn);
|
||||
extern inline int ddsi_conn_locator (ddsi_tran_conn_t conn, nn_locator_t * loc);
|
||||
extern inline ddsrt_socket_t ddsi_tran_handle (ddsi_tran_base_t base);
|
||||
|
@ -285,7 +286,7 @@ char *ddsi_locator_to_string (const struct q_globals *gv, char *dst, size_t size
|
|||
if (0 < pos && (size_t)pos < sizeof_dst)
|
||||
(void) tran->m_locator_to_string_fn (tran, dst + (size_t)pos, sizeof_dst - (size_t)pos, loc, 1);
|
||||
} else {
|
||||
snprintf (dst, sizeof_dst, "invalid/0:0");
|
||||
(void) snprintf (dst, sizeof_dst, "invalid/0:0");
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
@ -298,7 +299,7 @@ char *ddsi_locator_to_string_no_port (const struct q_globals *gv, char *dst, siz
|
|||
if (0 < pos && (size_t)pos < sizeof_dst)
|
||||
(void) tran->m_locator_to_string_fn (tran, dst + (size_t)pos, sizeof_dst - (size_t)pos, loc, 0);
|
||||
} else {
|
||||
snprintf (dst, sizeof_dst, "invalid/0");
|
||||
(void) snprintf (dst, sizeof_dst, "invalid/0");
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
|
|
@ -454,7 +454,7 @@ static char *ddsi_udp_locator_to_string (ddsi_tran_factory_t tran, char *dst, si
|
|||
pos += (size_t)cnt;
|
||||
}
|
||||
if (with_port && pos < sizeof_dst) {
|
||||
snprintf (dst + pos, sizeof_dst - pos, ":%"PRIu32, loc->port);
|
||||
(void) snprintf (dst + pos, sizeof_dst - pos, ":%"PRIu32, loc->port);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
@ -466,6 +466,12 @@ static void ddsi_udp_fini (ddsi_tran_factory_t fact)
|
|||
ddsrt_free (fact);
|
||||
}
|
||||
|
||||
static int ddsi_udp_is_valid_port (ddsi_tran_factory_t fact, uint32_t port)
|
||||
{
|
||||
(void) fact;
|
||||
return (port <= 65535);
|
||||
}
|
||||
|
||||
int ddsi_udp_init (struct q_globals *gv)
|
||||
{
|
||||
struct ddsi_tran_factory *fact = ddsrt_malloc (sizeof (*fact));
|
||||
|
@ -489,6 +495,7 @@ int ddsi_udp_init (struct q_globals *gv)
|
|||
fact->m_locator_from_string_fn = ddsi_udp_address_from_string;
|
||||
fact->m_locator_to_string_fn = ddsi_udp_locator_to_string;
|
||||
fact->m_enumerate_interfaces_fn = ddsi_eth_enumerate_interfaces;
|
||||
fact->m_is_valid_port_fn = ddsi_udp_is_valid_port;
|
||||
#if DDSRT_HAVE_IPV6
|
||||
if (gv->config.transport_selector == TRANS_UDP6)
|
||||
{
|
||||
|
|
|
@ -103,25 +103,22 @@ static int add_addresses_to_addrset_1 (const struct q_globals *gv, struct addrse
|
|||
if (!ddsi_is_mcaddr (gv, &loc))
|
||||
{
|
||||
assert (gv->config.maxAutoParticipantIndex >= 0);
|
||||
for (uint32_t i = 0; i <= (uint32_t) gv->config.maxAutoParticipantIndex; i++)
|
||||
for (int32_t i = 0; i <= gv->config.maxAutoParticipantIndex; i++)
|
||||
{
|
||||
uint32_t port = gv->config.port_base + gv->config.port_dg * gv->config.domainId + i * gv->config.port_pg + gv->config.port_d1;
|
||||
loc.port = (unsigned) port;
|
||||
loc.port = ddsi_get_port (&gv->config, DDSI_PORT_UNI_DISC, i);
|
||||
if (i == 0)
|
||||
GVLOG (DDS_LC_CONFIG, "%s", ddsi_locator_to_string(gv, buf, sizeof(buf), &loc));
|
||||
else
|
||||
GVLOG (DDS_LC_CONFIG, ", :%"PRIu32, port);
|
||||
GVLOG (DDS_LC_CONFIG, ", :%"PRIu32, loc.port);
|
||||
add_to_addrset (gv, as, &loc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t port;
|
||||
if (port_mode == -1)
|
||||
port = gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d0;
|
||||
loc.port = ddsi_get_port (&gv->config, DDSI_PORT_MULTI_DISC, 0);
|
||||
else
|
||||
port = (uint32_t) port_mode;
|
||||
loc.port = (unsigned) port;
|
||||
loc.port = (uint32_t) port_mode;
|
||||
GVLOG (DDS_LC_CONFIG, "%s", ddsi_locator_to_string(gv, buf, sizeof(buf), &loc));
|
||||
add_to_addrset (gv, as, &loc);
|
||||
}
|
||||
|
|
|
@ -166,7 +166,6 @@ DUPF(uint32);
|
|||
DU(natint);
|
||||
DU(natint_255);
|
||||
DUPF(participantIndex);
|
||||
DU(port);
|
||||
DU(dyn_port);
|
||||
DUPF(memsize);
|
||||
DU(duration_inf);
|
||||
|
@ -756,20 +755,20 @@ static const struct cfgelem sizing_cfgelems[] = {
|
|||
};
|
||||
|
||||
static const struct cfgelem discovery_ports_cfgelems[] = {
|
||||
{ LEAF("Base"), 1, "7400", ABSOFF(port_base), 0, uf_port, 0, pf_uint,
|
||||
{ LEAF("Base"), 1, "7400", ABSOFF(ports.base), 0, uf_uint, 0, pf_uint,
|
||||
BLURB("<p>This element specifies the base port number (refer to the DDSI 2.1 specification, section 9.6.1, constant PB).</p>") },
|
||||
{ LEAF("DomainGain"), 1, "250", ABSOFF(port_dg), 0, uf_uint, 0, pf_uint,
|
||||
{ LEAF("DomainGain"), 1, "250", ABSOFF(ports.dg), 0, uf_uint, 0, pf_uint,
|
||||
BLURB("<p>This element specifies the domain gain, relating domain ids to sets of port numbers (refer to the DDSI 2.1 specification, section 9.6.1, constant DG).</p>") },
|
||||
{ LEAF("ParticipantGain"), 1, "2", ABSOFF(port_pg), 0, uf_uint, 0, pf_uint,
|
||||
{ LEAF("ParticipantGain"), 1, "2", ABSOFF(ports.pg), 0, uf_uint, 0, pf_uint,
|
||||
BLURB("<p>This element specifies the participant gain, relating p0, articipant index to sets of port numbers (refer to the DDSI 2.1 specification, section 9.6.1, constant PG).</p>") },
|
||||
{ LEAF("MulticastMetaOffset"), 1, "0", ABSOFF(port_d0), 0, uf_uint, 0, pf_uint,
|
||||
{ LEAF("MulticastMetaOffset"), 1, "0", ABSOFF(ports.d0), 0, uf_uint, 0, pf_uint,
|
||||
BLURB("<p>This element specifies the port number for multicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d0).</p>") },
|
||||
{ LEAF("UnicastMetaOffset"), 1, "10", ABSOFF(port_d1), 0, uf_uint, 0, pf_uint,
|
||||
{ LEAF("UnicastMetaOffset"), 1, "10", ABSOFF(ports.d1), 0, uf_uint, 0, pf_uint,
|
||||
BLURB("<p>This element specifies the port number for unicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d1).</p>") },
|
||||
{ LEAF("MulticastDataOffset"), 1, "1", ABSOFF(port_d2), 0, uf_uint, 0, pf_uint,
|
||||
BLURB("<p>This element specifies the port number for multicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d2).</p>") },
|
||||
{ LEAF("UnicastDataOffset"), 1, "11", ABSOFF(port_d3), 0, uf_uint, 0, pf_uint,
|
||||
BLURB("<p>This element specifies the port number for unicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d3).</p>") },
|
||||
{ LEAF("MulticastDataOffset"), 1, "1", ABSOFF(ports.d2), 0, uf_uint, 0, pf_uint,
|
||||
BLURB("<p>This element specifies the port number for multicast data traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d2).</p>") },
|
||||
{ LEAF("UnicastDataOffset"), 1, "11", ABSOFF(ports.d3), 0, uf_uint, 0, pf_uint,
|
||||
BLURB("<p>This element specifies the port number for unicast data traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d3).</p>") },
|
||||
END_MARKER
|
||||
};
|
||||
|
||||
|
@ -844,6 +843,10 @@ static const struct cfgelem discovery_peers_cfgelems[] = {
|
|||
};
|
||||
|
||||
static const struct cfgelem discovery_cfgelems[] = {
|
||||
{ LEAF("Tag"), 0, "", ABSOFF(domainTag), 0, uf_string, ff_free, pf_string,
|
||||
BLURB("<p>String extension for domain id that remote participants must match to be discovered.</p>") },
|
||||
{ LEAF ("ExternalDomainId"), 1, "default", ABSOFF (extDomainId), 0, uf_maybe_int32, 0, pf_maybe_int32,
|
||||
BLURB("<p>An override for the domain id, to be used in discovery and for determining the port number mapping. This allows creating multiple domains in a single process while making them appear as a single domain on the network. The value \"default\" disables the override.</p>") },
|
||||
{ LEAF("DSGracePeriod"), 1, "30 s", ABSOFF(ds_grace_period), 0, uf_duration_inf, 0, pf_duration,
|
||||
BLURB("<p>This setting controls for how long endpoints discovered via a Cloud discovery service will survive after the discovery service disappeared, allowing reconnect without loss of data when the discovery service restarts (or another instance takes over).</p>") },
|
||||
{ GROUP("Peers", discovery_peers_cfgelems),
|
||||
|
@ -983,7 +986,9 @@ static const struct cfgelem root_cfgelems[] = {
|
|||
};
|
||||
|
||||
static const struct cfgelem root_cfgattrs[] = {
|
||||
{ ATTR("xmlns"), 0, "", 0, 0, 0, uf_nop, 0, pf_nop, NULL },
|
||||
{ ATTR("xmlns:xsi"), 0, "", 0, 0, 0, uf_nop, 0, pf_nop, NULL },
|
||||
{ ATTR("xsi:schemaLocation"), 0, "", 0, 0, 0, uf_nop, 0, pf_nop, NULL },
|
||||
{ ATTR("xsi:noNamespaceSchemaLocation"), 0, "", 0, 0, 0, uf_nop, 0, pf_nop, NULL },
|
||||
END_MARKER
|
||||
};
|
||||
|
@ -1314,7 +1319,7 @@ static int64_t lookup_multiplier (struct cfgst *cfgst, const struct unit *unitta
|
|||
always allow 0 to be specified without a unit */
|
||||
return 1;
|
||||
} else if (def_mult == 0 && err_on_unrecognised) {
|
||||
cfg_error (cfgst, "%s: unit is required", value);
|
||||
(void) cfg_error (cfgst, "%s: unit is required", value);
|
||||
return 0;
|
||||
} else {
|
||||
cfg_warning (cfgst, "%s: use of default unit is deprecated", value);
|
||||
|
@ -1327,7 +1332,7 @@ static int64_t lookup_multiplier (struct cfgst *cfgst, const struct unit *unitta
|
|||
if (strcmp(unittab[i].name, value + unit_pos) == 0)
|
||||
return unittab[i].multiplier;
|
||||
if (err_on_unrecognised)
|
||||
cfg_error(cfgst, "%s: unrecognised unit", value + unit_pos);
|
||||
(void) cfg_error(cfgst, "%s: unrecognised unit", value + unit_pos);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -2045,34 +2050,23 @@ static enum update_result uf_natint_255(struct cfgst *cfgst, void *parent, struc
|
|||
|
||||
static enum update_result uf_uint (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
|
||||
{
|
||||
unsigned * const elem = cfg_address (cfgst, parent, cfgelem);
|
||||
uint32_t * const elem = cfg_address (cfgst, parent, cfgelem);
|
||||
char *endptr;
|
||||
unsigned long v = strtoul (value, &endptr, 10);
|
||||
if (*value == 0 || *endptr != 0)
|
||||
return cfg_error (cfgst, "%s: not a decimal integer", value);
|
||||
if (v != (unsigned) v)
|
||||
if (v != (uint32_t) v)
|
||||
return cfg_error (cfgst, "%s: value out of range", value);
|
||||
*elem = (unsigned) v;
|
||||
*elem = (uint32_t) v;
|
||||
return URES_SUCCESS;
|
||||
}
|
||||
|
||||
static void pf_uint (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
|
||||
{
|
||||
unsigned const * const p = cfg_address (cfgst, parent, cfgelem);
|
||||
uint32_t const * const p = cfg_address (cfgst, parent, cfgelem);
|
||||
cfg_logelem (cfgst, sources, "%u", *p);
|
||||
}
|
||||
|
||||
static enum update_result uf_port(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
|
||||
{
|
||||
int *elem = cfg_address (cfgst, parent, cfgelem);
|
||||
if (uf_uint (cfgst, parent, cfgelem, first, value) != URES_SUCCESS)
|
||||
return URES_ERROR;
|
||||
else if (*elem < 1 || *elem > 65535)
|
||||
return cfg_error (cfgst, "%s: out of range", value);
|
||||
else
|
||||
return URES_SUCCESS;
|
||||
}
|
||||
|
||||
static enum update_result uf_duration_gen (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, const char *value, int64_t def_mult, int64_t min_ns, int64_t max_ns)
|
||||
{
|
||||
return uf_natint64_unit (cfgst, cfg_address (cfgst, parent, cfgelem), value, unittab_duration, def_mult, min_ns, max_ns);
|
||||
|
@ -2242,7 +2236,7 @@ static int set_default (struct cfgst *cfgst, void *parent, struct cfgelem const
|
|||
enum update_result res;
|
||||
if (cfgelem->defvalue == NULL)
|
||||
{
|
||||
cfg_error (cfgst, "element missing in configuration");
|
||||
(void) cfg_error (cfgst, "element missing in configuration");
|
||||
return 0;
|
||||
}
|
||||
res = do_update (cfgst, cfgelem->update, parent, cfgelem, cfgelem->defvalue, 0);
|
||||
|
@ -2572,7 +2566,7 @@ static int proc_elem_open (void *varg, UNUSED_ARG (uintptr_t parentinfo), UNUSED
|
|||
cfg_subelem = partial_match;
|
||||
else
|
||||
{
|
||||
cfg_error (cfgst, "%s: unknown element", name);
|
||||
(void) cfg_error (cfgst, "%s: unknown element", name);
|
||||
cfgst_push (cfgst, 0, NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2686,7 +2680,7 @@ static int proc_attr (void *varg, UNUSED_ARG (uintptr_t eleminfo), const char *n
|
|||
return proc_update_cfgelem (cfgst, cfg_attr, value, true);
|
||||
else
|
||||
{
|
||||
cfg_error (cfgst, "%s: unknown attribute", name);
|
||||
(void) cfg_error (cfgst, "%s: unknown attribute", name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -2703,7 +2697,7 @@ static int proc_elem_data (void *varg, UNUSED_ARG (uintptr_t eleminfo), const ch
|
|||
return proc_update_cfgelem (cfgst, cfgelem, value, isattr);
|
||||
else
|
||||
{
|
||||
cfg_error (cfgst, "%s: no data expected", value);
|
||||
(void) cfg_error (cfgst, "%s: no data expected", value);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -2730,7 +2724,7 @@ static int proc_elem_close (void *varg, UNUSED_ARG (uintptr_t eleminfo), int lin
|
|||
static void proc_error (void *varg, const char *msg, int line)
|
||||
{
|
||||
struct cfgst * const cfgst = varg;
|
||||
cfg_error (cfgst, "parser error %s at line %d", msg, line);
|
||||
(void) cfg_error (cfgst, "parser error %s at line %d", msg, line);
|
||||
}
|
||||
|
||||
static int cfgst_node_cmp (const void *va, const void *vb)
|
||||
|
@ -2892,7 +2886,7 @@ struct cfgst *config_init (const char *config, struct config *cfg, uint32_t domi
|
|||
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));
|
||||
(void) snprintf (env_input, sizeof (env_input), "CYCLONEDDS_URI+%u", (unsigned) (tok - copy));
|
||||
cfgst->input = env_input;
|
||||
cfgst->line = 1;
|
||||
}
|
||||
|
@ -2996,12 +2990,7 @@ struct cfgst *config_init (const char *config, struct config *cfg, uint32_t domi
|
|||
while (p)
|
||||
{
|
||||
cfgst->cfg->nof_networkPartitions++;
|
||||
/* also use crc32 just like native nw and ordinary ddsi2e, only
|
||||
for interoperability because it is asking for trouble &
|
||||
forces us to include a crc32 routine when we have md5
|
||||
available anyway */
|
||||
p->partitionId = cfgst->cfg->nof_networkPartitions; /* starting at 1 */
|
||||
p->partitionHash = crc32_calc(p->name, strlen(p->name));
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
@ -3077,7 +3066,7 @@ static char *get_partition_search_pattern (const char *partition, const char *to
|
|||
{
|
||||
size_t sz = strlen (partition) + strlen (topic) + 2;
|
||||
char *pt = ddsrt_malloc (sz);
|
||||
snprintf (pt, sz, "%s.%s", partition, topic);
|
||||
(void) snprintf (pt, sz, "%s.%s", partition, topic);
|
||||
return pt;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "dds/ddsi/ddsi_serdata_default.h"
|
||||
#include "dds/ddsi/q_feature_check.h"
|
||||
#include "dds/ddsi/ddsi_security_omg.h"
|
||||
#include "dds/ddsi/ddsi_pmd.h"
|
||||
|
||||
static int get_locator (const struct q_globals *gv, nn_locator_t *loc, const nn_locators_t *locs, int uc_same_subnet)
|
||||
{
|
||||
|
@ -217,12 +218,25 @@ int spdp_write (struct participant *pp)
|
|||
|
||||
nn_plist_init_empty (&ps);
|
||||
ps.present |= PP_PARTICIPANT_GUID | PP_BUILTIN_ENDPOINT_SET |
|
||||
PP_PROTOCOL_VERSION | PP_VENDORID | PP_PARTICIPANT_LEASE_DURATION;
|
||||
PP_PROTOCOL_VERSION | PP_VENDORID | PP_PARTICIPANT_LEASE_DURATION |
|
||||
PP_DOMAIN_ID;
|
||||
ps.participant_guid = pp->e.guid;
|
||||
ps.builtin_endpoint_set = pp->bes;
|
||||
ps.protocol_version.major = RTPS_MAJOR;
|
||||
ps.protocol_version.minor = RTPS_MINOR;
|
||||
ps.vendorid = NN_VENDORID_ECLIPSE;
|
||||
ps.domain_id = pp->e.gv->config.extDomainId.value;
|
||||
/* Be sure not to send a DOMAIN_TAG when it is the default (an empty)
|
||||
string: it is an "incompatible-if-unrecognized" parameter, and so
|
||||
implementations that don't understand the parameter will refuse to
|
||||
discover us, and so sending the default would break backwards
|
||||
compatibility. */
|
||||
if (strcmp (pp->e.gv->config.domainTag, "") != 0)
|
||||
{
|
||||
ps.present |= PP_DOMAIN_TAG;
|
||||
ps.aliased |= PP_DOMAIN_TAG;
|
||||
ps.domain_tag = pp->e.gv->config.domainTag;
|
||||
}
|
||||
if (pp->prismtech_bes)
|
||||
{
|
||||
ps.present |= PP_PRISMTECH_BUILTIN_ENDPOINT_SET;
|
||||
|
@ -305,7 +319,7 @@ int spdp_write (struct participant *pp)
|
|||
ddsrt_mutex_unlock (&pp->e.gv->privileged_pp_lock);
|
||||
|
||||
if (ddsrt_gethostname(node, sizeof(node)-1) < 0)
|
||||
ddsrt_strlcpy (node, "unknown", sizeof (node));
|
||||
(void) 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);
|
||||
|
@ -418,7 +432,7 @@ static void respond_to_spdp (const struct q_globals *gv, const ddsi_guid_t *dest
|
|||
GVTRACE (" %"PRId64, delay);
|
||||
if (!pp->e.gv->config.unicast_response_to_spdp_messages)
|
||||
/* pp can't reach gc_delete_participant => can safely reschedule */
|
||||
resched_xevent_if_earlier (pp->spdp_xevent, tsched);
|
||||
(void) resched_xevent_if_earlier (pp->spdp_xevent, tsched);
|
||||
else
|
||||
qxev_spdp (gv->xevents, tsched, &pp->e.guid, dest_proxypp_guid);
|
||||
}
|
||||
|
@ -498,10 +512,8 @@ static void make_participants_dependent_on_ddsi2 (struct q_globals *gv, const dd
|
|||
{
|
||||
struct ephash_enum_proxy_participant it;
|
||||
struct proxy_participant *pp, *d2pp;
|
||||
struct lease *d2pp_lease;
|
||||
if ((d2pp = ephash_lookup_proxy_participant_guid (gv->guid_hash, ddsi2guid)) == NULL)
|
||||
return;
|
||||
d2pp_lease = ddsrt_atomic_ldvoidp (&d2pp->lease);
|
||||
ephash_enum_proxy_participant_init (&it, gv->guid_hash);
|
||||
while ((pp = ephash_enum_proxy_participant_next (&it)) != NULL)
|
||||
{
|
||||
|
@ -511,7 +523,7 @@ static void make_participants_dependent_on_ddsi2 (struct q_globals *gv, const dd
|
|||
ddsrt_mutex_lock (&pp->e.lock);
|
||||
pp->privileged_pp_guid = *ddsi2guid;
|
||||
ddsrt_mutex_unlock (&pp->e.lock);
|
||||
proxy_participant_reassign_lease (pp, d2pp_lease);
|
||||
proxy_participant_reassign_lease (pp, d2pp->lease);
|
||||
GVTRACE ("\n");
|
||||
|
||||
if (ephash_lookup_proxy_participant_guid (gv->guid_hash, ddsi2guid) == NULL)
|
||||
|
@ -545,6 +557,18 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_
|
|||
dds_duration_t lease_duration;
|
||||
unsigned custom_flags = 0;
|
||||
|
||||
/* If advertised domain id or domain tag doesn't match, ignore the message. Do this first to
|
||||
minimize the impact such messages have. */
|
||||
{
|
||||
const uint32_t domain_id = (datap->present & PP_DOMAIN_ID) ? datap->domain_id : gv->config.extDomainId.value;
|
||||
const char *domain_tag = (datap->present & PP_DOMAIN_TAG) ? datap->domain_tag : "";
|
||||
if (domain_id != gv->config.extDomainId.value || strcmp (domain_tag, gv->config.domainTag) != 0)
|
||||
{
|
||||
GVTRACE ("ignore remote participant in mismatching domain %"PRIu32" tag \"%s\"\n", domain_id, domain_tag);
|
||||
return 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]);
|
||||
|
@ -611,12 +635,15 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_
|
|||
else if (existing_entity->kind == EK_PROXY_PARTICIPANT)
|
||||
{
|
||||
struct proxy_participant *proxypp = (struct proxy_participant *) existing_entity;
|
||||
struct lease *lease;
|
||||
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 ());
|
||||
even skipping the automatic lease renewal. Note that proxy writers
|
||||
that are not alive are not set alive here. This is done only when
|
||||
data is received from a particular pwr (in handle_regular) */
|
||||
if ((lease = ddsrt_atomic_ldvoidp (&proxypp->minl_auto)) != NULL)
|
||||
lease_renew (lease, now_et ());
|
||||
ddsrt_mutex_lock (&proxypp->e.lock);
|
||||
if (proxypp->implicitly_created || seq > proxypp->seq)
|
||||
{
|
||||
|
@ -1278,7 +1305,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, seqno_t seq, nn
|
|||
GVLOGDISC (" "PGUIDFMT" attach-to-DS "PGUIDFMT, PGUID(pp->e.guid), PGUIDPREFIX(*src_guid_prefix), pp->privileged_pp_guid.entityid.u);
|
||||
ddsrt_mutex_lock (&pp->e.lock);
|
||||
pp->privileged_pp_guid.prefix = *src_guid_prefix;
|
||||
lease_set_expiry(ddsrt_atomic_ldvoidp(&pp->lease), never);
|
||||
lease_set_expiry(pp->lease, never);
|
||||
ddsrt_mutex_unlock (&pp->e.lock);
|
||||
}
|
||||
GVLOGDISC ("\n");
|
||||
|
@ -1388,13 +1415,9 @@ static void handle_SEDP_dead (const struct receiver_state *rst, nn_plist_t *data
|
|||
}
|
||||
GVLOGDISC (" "PGUIDFMT, PGUID (datap->endpoint_guid));
|
||||
if (is_writer_entityid (datap->endpoint_guid.entityid))
|
||||
{
|
||||
res = delete_proxy_writer (gv, &datap->endpoint_guid, timestamp, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = delete_proxy_reader (gv, &datap->endpoint_guid, timestamp, 0);
|
||||
}
|
||||
GVLOGDISC (" %s\n", (res < 0) ? " unknown" : " delete");
|
||||
}
|
||||
|
||||
|
@ -1812,7 +1835,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str
|
|||
break;
|
||||
case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER:
|
||||
case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER:
|
||||
handle_PMD (sampleinfo->rst, timestamp, statusinfo, datap, datasz);
|
||||
handle_pmd_message (sampleinfo->rst, timestamp, statusinfo, datap, datasz);
|
||||
break;
|
||||
case NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER:
|
||||
handle_SEDP_CM (sampleinfo->rst, srcguid.entityid, timestamp, statusinfo, datap, datasz);
|
||||
|
|
|
@ -346,10 +346,11 @@ static uint32_t debmon_main (void *vdm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct debug_monitor *new_debug_monitor (struct q_globals *gv, int port)
|
||||
struct debug_monitor *new_debug_monitor (struct q_globals *gv, int32_t port)
|
||||
{
|
||||
struct debug_monitor *dm;
|
||||
|
||||
/* negative port number means the feature is disabled */
|
||||
if (gv->config.monitor_port < 0)
|
||||
return NULL;
|
||||
|
||||
|
@ -362,7 +363,14 @@ struct debug_monitor *new_debug_monitor (struct q_globals *gv, int port)
|
|||
dm->plugins = NULL;
|
||||
if ((dm->tran_factory = ddsi_factory_find (gv, "tcp")) == NULL)
|
||||
dm->tran_factory = ddsi_factory_find (gv, "tcp6");
|
||||
dm->servsock = ddsi_factory_create_listener (dm->tran_factory, port, NULL);
|
||||
|
||||
if (!ddsi_is_valid_port (dm->tran_factory, (uint32_t) port))
|
||||
{
|
||||
GVERROR ("debug monitor port number %"PRId32" is invalid\n", port);
|
||||
goto err_invalid_port;
|
||||
}
|
||||
|
||||
dm->servsock = ddsi_factory_create_listener (dm->tran_factory, (uint32_t) port, NULL);
|
||||
if (dm->servsock == NULL)
|
||||
{
|
||||
GVWARNING ("debmon: can't create socket\n");
|
||||
|
@ -381,7 +389,8 @@ struct debug_monitor *new_debug_monitor (struct q_globals *gv, int port)
|
|||
if (ddsi_listener_listen (dm->servsock) < 0)
|
||||
goto err_listen;
|
||||
dm->stop = 0;
|
||||
create_thread (&dm->servts, gv, "debmon", debmon_main, dm);
|
||||
if (create_thread (&dm->servts, gv, "debmon", debmon_main, dm) != DDS_RETCODE_OK)
|
||||
goto err_listen;
|
||||
return dm;
|
||||
|
||||
err_listen:
|
||||
|
@ -389,6 +398,7 @@ err_listen:
|
|||
ddsrt_mutex_destroy(&dm->lock);
|
||||
ddsi_listener_free(dm->servsock);
|
||||
err_servsock:
|
||||
err_invalid_port:
|
||||
ddsrt_free(dm);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "dds/ddsrt/fibheap.h"
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/sockets.h"
|
||||
|
@ -69,6 +70,11 @@ struct deleted_participants_admin {
|
|||
int64_t delay;
|
||||
};
|
||||
|
||||
struct proxy_writer_alive_state {
|
||||
bool alive;
|
||||
uint32_t vclock;
|
||||
};
|
||||
|
||||
static int compare_guid (const void *va, const void *vb);
|
||||
static void augment_wr_prd_match (void *vnode, const void *vleft, const void *vright);
|
||||
|
||||
|
@ -409,6 +415,16 @@ static void remove_deleted_participant_guid (struct deleted_participants_admin *
|
|||
|
||||
/* PARTICIPANT ------------------------------------------------------ */
|
||||
|
||||
static int compare_ldur (const void *va, const void *vb)
|
||||
{
|
||||
const struct ldur_fhnode *a = va;
|
||||
const struct ldur_fhnode *b = vb;
|
||||
return (a->ldur == b->ldur) ? 0 : (a->ldur < b->ldur) ? -1 : 1;
|
||||
}
|
||||
|
||||
/* used in participant for keeping writer liveliness renewal */
|
||||
const ddsrt_fibheap_def_t ldur_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct ldur_fhnode, heapnode), compare_ldur);
|
||||
|
||||
static bool update_qos_locked (struct entity_common *e, dds_qos_t *ent_qos, const dds_qos_t *xqos, nn_wctime_t timestamp)
|
||||
{
|
||||
uint64_t mask;
|
||||
|
@ -601,6 +617,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals *
|
|||
ddsrt_mutex_init (&pp->refc_lock);
|
||||
inverse_uint32_set_init(&pp->avail_entityids.x, 1, UINT32_MAX / NN_ENTITYID_ALLOCSTEP);
|
||||
pp->lease_duration = gv->config.lease_duration;
|
||||
ddsrt_fibheap_init (&ldur_fhdef, &pp->ldur_auto_wr);
|
||||
pp->plist = ddsrt_malloc (sizeof (*pp->plist));
|
||||
nn_plist_copy (pp->plist, plist);
|
||||
nn_plist_mergein_missing (pp->plist, &gv->default_local_plist_pp, ~(uint64_t)0, ~(uint64_t)0);
|
||||
|
@ -1165,6 +1182,19 @@ struct writer *get_builtin_writer (const struct participant *pp, unsigned entity
|
|||
return ephash_lookup_writer_guid (pp->e.gv->guid_hash, &bwr_guid);
|
||||
}
|
||||
|
||||
dds_duration_t pp_get_pmd_interval (struct participant *pp)
|
||||
{
|
||||
struct ldur_fhnode *ldur_node;
|
||||
dds_duration_t intv;
|
||||
ddsrt_mutex_lock (&pp->e.lock);
|
||||
ldur_node = ddsrt_fibheap_min (&ldur_fhdef, &pp->ldur_auto_wr);
|
||||
intv = (ldur_node != NULL) ? ldur_node->ldur : T_NEVER;
|
||||
if (pp->lease_duration < intv)
|
||||
intv = pp->lease_duration;
|
||||
ddsrt_mutex_unlock (&pp->e.lock);
|
||||
return intv;
|
||||
}
|
||||
|
||||
/* WRITER/READER/PROXY-WRITER/PROXY-READER CONNECTION ---------------
|
||||
|
||||
These are all located in a separate section because they are so
|
||||
|
@ -1568,6 +1598,19 @@ static void free_wr_rd_match (struct wr_rd_match *m)
|
|||
if (m) ddsrt_free (m);
|
||||
}
|
||||
|
||||
static void proxy_writer_get_alive_state_locked (struct proxy_writer *pwr, struct proxy_writer_alive_state *st)
|
||||
{
|
||||
st->alive = pwr->alive;
|
||||
st->vclock = pwr->alive_vclock;
|
||||
}
|
||||
|
||||
static void proxy_writer_get_alive_state (struct proxy_writer *pwr, struct proxy_writer_alive_state *st)
|
||||
{
|
||||
ddsrt_mutex_lock (&pwr->e.lock);
|
||||
proxy_writer_get_alive_state_locked (pwr, st);
|
||||
ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
}
|
||||
|
||||
static void writer_drop_connection (const struct ddsi_guid *wr_guid, const struct proxy_reader *prd)
|
||||
{
|
||||
struct writer *wr;
|
||||
|
@ -1625,6 +1668,55 @@ static void writer_drop_local_connection (const struct ddsi_guid *wr_guid, struc
|
|||
}
|
||||
}
|
||||
|
||||
static void reader_update_notify_pwr_alive_state (struct reader *rd, const struct proxy_writer *pwr, const struct proxy_writer_alive_state *alive_state)
|
||||
{
|
||||
struct rd_pwr_match *m;
|
||||
bool notify = false;
|
||||
int delta = 0; /* -1: alive -> not_alive; 0: unchanged; 1: not_alive -> alive */
|
||||
ddsrt_mutex_lock (&rd->e.lock);
|
||||
if ((m = ddsrt_avl_lookup (&rd_writers_treedef, &rd->writers, &pwr->e.guid)) != NULL)
|
||||
{
|
||||
if ((int32_t) (alive_state->vclock - m->pwr_alive_vclock) > 0)
|
||||
{
|
||||
delta = (int) alive_state->alive - (int) m->pwr_alive;
|
||||
notify = true;
|
||||
m->pwr_alive = alive_state->alive;
|
||||
m->pwr_alive_vclock = alive_state->vclock;
|
||||
}
|
||||
}
|
||||
ddsrt_mutex_unlock (&rd->e.lock);
|
||||
|
||||
if (delta < 0 && rd->rhc)
|
||||
{
|
||||
struct ddsi_writer_info wrinfo;
|
||||
ddsi_make_writer_info (&wrinfo, &pwr->e, pwr->c.xqos);
|
||||
ddsi_rhc_unregister_wr (rd->rhc, &wrinfo);
|
||||
}
|
||||
|
||||
/* Liveliness changed events can race each other and can, potentially, be delivered
|
||||
in a different order. */
|
||||
if (notify && rd->status_cb)
|
||||
{
|
||||
status_cb_data_t data;
|
||||
data.handle = pwr->e.iid;
|
||||
if (delta == 0)
|
||||
data.extra = (uint32_t) LIVELINESS_CHANGED_TWITCH;
|
||||
else if (delta < 0)
|
||||
data.extra = (uint32_t) LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE;
|
||||
else
|
||||
data.extra = (uint32_t) LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE;
|
||||
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
}
|
||||
}
|
||||
|
||||
static void reader_update_notify_pwr_alive_state_guid (const struct ddsi_guid *rd_guid, const struct proxy_writer *pwr, const struct proxy_writer_alive_state *alive_state)
|
||||
{
|
||||
struct reader *rd;
|
||||
if ((rd = ephash_lookup_reader_guid (pwr->e.gv->guid_hash, rd_guid)) != NULL)
|
||||
reader_update_notify_pwr_alive_state (rd, pwr, alive_state);
|
||||
}
|
||||
|
||||
static void reader_drop_connection (const struct ddsi_guid *rd_guid, const struct proxy_writer *pwr)
|
||||
{
|
||||
struct reader *rd;
|
||||
|
@ -1646,9 +1738,9 @@ static void reader_drop_connection (const struct ddsi_guid *rd_guid, const struc
|
|||
if (rd->status_cb)
|
||||
{
|
||||
status_cb_data_t data;
|
||||
|
||||
data.add = false;
|
||||
data.handle = pwr->e.iid;
|
||||
data.add = false;
|
||||
data.extra = (uint32_t) (m->pwr_alive ? LIVELINESS_CHANGED_REMOVE_ALIVE : LIVELINESS_CHANGED_REMOVE_NOT_ALIVE);
|
||||
|
||||
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
|
@ -1683,9 +1775,9 @@ static void reader_drop_local_connection (const struct ddsi_guid *rd_guid, const
|
|||
if (rd->status_cb)
|
||||
{
|
||||
status_cb_data_t data;
|
||||
|
||||
data.add = false;
|
||||
data.handle = wr->e.iid;
|
||||
data.add = false;
|
||||
data.extra = (uint32_t) LIVELINESS_CHANGED_REMOVE_ALIVE;
|
||||
|
||||
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
|
@ -1864,7 +1956,7 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd)
|
|||
if (tnext.v < wr->hbcontrol.tsched.v)
|
||||
{
|
||||
wr->hbcontrol.tsched = tnext;
|
||||
resched_xevent_if_earlier (wr->heartbeat_xevent, tnext);
|
||||
(void) resched_xevent_if_earlier (wr->heartbeat_xevent, tnext);
|
||||
}
|
||||
ddsrt_mutex_unlock (&wr->e.lock);
|
||||
}
|
||||
|
@ -1928,12 +2020,14 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd)
|
|||
}
|
||||
}
|
||||
|
||||
static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, nn_count_t *init_count)
|
||||
static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, nn_count_t *init_count, const struct proxy_writer_alive_state *alive_state)
|
||||
{
|
||||
struct rd_pwr_match *m = ddsrt_malloc (sizeof (*m));
|
||||
ddsrt_avl_ipath_t path;
|
||||
|
||||
m->pwr_guid = pwr->e.guid;
|
||||
m->pwr_alive = alive_state->alive;
|
||||
m->pwr_alive_vclock = alive_state->vclock;
|
||||
|
||||
ddsrt_mutex_lock (&rd->e.lock);
|
||||
|
||||
|
@ -1973,7 +2067,9 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr,
|
|||
/* 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);
|
||||
int ret = ddsi_join_mc (rd->e.gv, rd->e.gv->mship, rd->e.gv->data_conn_mc, &m->ssm_src_loc, &m->ssm_mc_loc);
|
||||
if (ret < 0)
|
||||
ELOGDISC (rd, " unable to join\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1985,9 +2081,14 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr,
|
|||
if (rd->status_cb)
|
||||
{
|
||||
status_cb_data_t data;
|
||||
data.raw_status_id = (int) DDS_SUBSCRIPTION_MATCHED_STATUS_ID;
|
||||
data.add = true;
|
||||
data.handle = pwr->e.iid;
|
||||
data.add = true;
|
||||
data.extra = (uint32_t) (alive_state->alive ? LIVELINESS_CHANGED_ADD_ALIVE : LIVELINESS_CHANGED_ADD_NOT_ALIVE);
|
||||
|
||||
data.raw_status_id = (int) DDS_SUBSCRIPTION_MATCHED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
|
||||
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
}
|
||||
}
|
||||
|
@ -2019,14 +2120,15 @@ static void reader_add_local_connection (struct reader *rd, struct writer *wr)
|
|||
if (rd->status_cb)
|
||||
{
|
||||
status_cb_data_t data;
|
||||
data.add = true;
|
||||
data.handle = wr->e.iid;
|
||||
|
||||
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
data.add = true;
|
||||
data.extra = (uint32_t) LIVELINESS_CHANGED_ADD_ALIVE;
|
||||
|
||||
data.raw_status_id = (int) DDS_SUBSCRIPTION_MATCHED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
|
||||
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2153,16 +2255,6 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader
|
|||
qxev_pwr_entityid (pwr, &rd->e.guid);
|
||||
|
||||
ELOGDISC (pwr, "\n");
|
||||
|
||||
if (rd->status_cb)
|
||||
{
|
||||
status_cb_data_t data;
|
||||
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
||||
data.add = true;
|
||||
data.handle = pwr->e.iid;
|
||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
already_matched:
|
||||
|
@ -2374,6 +2466,7 @@ static void connect_proxy_writer_with_reader (struct proxy_writer *pwr, struct r
|
|||
const int isb1 = (is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) != 0);
|
||||
dds_qos_policy_id_t reason;
|
||||
nn_count_t init_count;
|
||||
struct proxy_writer_alive_state alive_state;
|
||||
if (isb0 != isb1)
|
||||
return;
|
||||
if (rd->e.onlylocal)
|
||||
|
@ -2383,8 +2476,18 @@ static void connect_proxy_writer_with_reader (struct proxy_writer *pwr, struct r
|
|||
reader_qos_mismatch (rd, reason);
|
||||
return;
|
||||
}
|
||||
reader_add_connection (rd, pwr, &init_count);
|
||||
|
||||
/* Initialze the reader's tracking information for the writer liveliness state to something
|
||||
sensible, but that may be outdated by the time the reader gets added to the writer's list
|
||||
of matching readers. */
|
||||
proxy_writer_get_alive_state (pwr, &alive_state);
|
||||
reader_add_connection (rd, pwr, &init_count, &alive_state);
|
||||
proxy_writer_add_connection (pwr, rd, tnow, init_count);
|
||||
|
||||
/* Once everything is set up: update with the latest state, any updates to the alive state
|
||||
happening in parallel will cause this to become a no-op. */
|
||||
proxy_writer_get_alive_state (pwr, &alive_state);
|
||||
reader_update_notify_pwr_alive_state (rd, pwr, &alive_state);
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -3072,13 +3175,17 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se
|
|||
{
|
||||
wr->heartbeat_xevent = NULL;
|
||||
}
|
||||
|
||||
assert (wr->xqos->present & QP_LIVELINESS);
|
||||
if (wr->xqos->liveliness.kind != DDS_LIVELINESS_AUTOMATIC || wr->xqos->liveliness.lease_duration != T_NEVER)
|
||||
if (wr->xqos->liveliness.kind == DDS_LIVELINESS_AUTOMATIC && wr->xqos->liveliness.lease_duration != T_NEVER)
|
||||
{
|
||||
ELOGDISC (wr, "writer "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n",
|
||||
PGUID (wr->e.guid), (int) wr->xqos->liveliness.kind, wr->xqos->liveliness.lease_duration);
|
||||
wr->lease_duration = ddsrt_malloc (sizeof(*wr->lease_duration));
|
||||
wr->lease_duration->ldur = wr->xqos->liveliness.lease_duration;
|
||||
}
|
||||
else
|
||||
{
|
||||
wr->lease_duration = NULL;
|
||||
}
|
||||
wr->lease_duration = T_NEVER; /* FIXME */
|
||||
|
||||
wr->whc = whc;
|
||||
if (wr->xqos->history.kind == DDS_HISTORY_KEEP_LAST)
|
||||
|
@ -3147,10 +3254,19 @@ static dds_return_t new_writer_guid (struct writer **wr_out, const struct ddsi_g
|
|||
match_writer_with_local_readers (wr, tnow);
|
||||
sedp_write_writer (wr);
|
||||
|
||||
if (wr->lease_duration != T_NEVER)
|
||||
if (wr->lease_duration != NULL)
|
||||
{
|
||||
nn_mtime_t tsched = { 0 };
|
||||
resched_xevent_if_earlier (pp->pmd_update_xevent, tsched);
|
||||
assert (wr->lease_duration->ldur != T_NEVER);
|
||||
assert (wr->xqos->liveliness.kind == DDS_LIVELINESS_AUTOMATIC);
|
||||
assert (!is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE));
|
||||
|
||||
/* Store writer lease duration in participant's heap in case of automatic liveliness */
|
||||
ddsrt_mutex_lock (&pp->e.lock);
|
||||
ddsrt_fibheap_insert (&ldur_fhdef, &pp->ldur_auto_wr, wr->lease_duration);
|
||||
ddsrt_mutex_unlock (&pp->e.lock);
|
||||
|
||||
/* Trigger pmd update */
|
||||
(void) resched_xevent_if_earlier (pp->pmd_update_xevent, now_mt ());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -3243,6 +3359,11 @@ static void gc_delete_writer (struct gcreq *gcreq)
|
|||
reader_drop_local_connection (&m->rd_guid, wr);
|
||||
free_wr_rd_match (m);
|
||||
}
|
||||
if (wr->lease_duration != NULL)
|
||||
{
|
||||
assert (wr->lease_duration->ldur == DDS_DURATION_INVALID);
|
||||
ddsrt_free (wr->lease_duration);
|
||||
}
|
||||
|
||||
/* Do last gasp on SEDP and free writer. */
|
||||
if (!is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE))
|
||||
|
@ -3323,6 +3444,13 @@ dds_return_t delete_writer_nolinger_locked (struct writer *wr)
|
|||
local_reader_ary_setinvalid (&wr->rdary);
|
||||
ephash_remove_writer_guid (wr->e.gv->guid_hash, wr);
|
||||
writer_set_state (wr, WRST_DELETING);
|
||||
if (wr->lease_duration != NULL) {
|
||||
ddsrt_mutex_lock (&wr->c.pp->e.lock);
|
||||
ddsrt_fibheap_delete (&ldur_fhdef, &wr->c.pp->ldur_auto_wr, wr->lease_duration);
|
||||
ddsrt_mutex_unlock (&wr->c.pp->e.lock);
|
||||
wr->lease_duration->ldur = DDS_DURATION_INVALID;
|
||||
resched_xevent_if_earlier (wr->c.pp->pmd_update_xevent, now_mt ());
|
||||
}
|
||||
gcreq_writer (wr);
|
||||
return 0;
|
||||
}
|
||||
|
@ -3577,11 +3705,6 @@ static dds_return_t new_reader_guid
|
|||
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)
|
||||
{
|
||||
ELOGDISC (rd, "reader "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n",
|
||||
PGUID (rd->e.guid), (int) rd->xqos->liveliness.kind, rd->xqos->liveliness.lease_duration);
|
||||
}
|
||||
|
||||
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
||||
rd->as = new_addrset ();
|
||||
|
@ -3758,38 +3881,72 @@ void update_reader_qos (struct reader *rd, const dds_qos_t *xqos)
|
|||
}
|
||||
|
||||
/* PROXY-PARTICIPANT ------------------------------------------------ */
|
||||
const ddsrt_fibheap_def_t lease_fhdef_proxypp = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct lease, pp_heapnode), compare_lease_tdur);
|
||||
|
||||
static void gc_proxy_participant_lease (struct gcreq *gcreq)
|
||||
{
|
||||
lease_free (gcreq->arg);
|
||||
gcreq_free (gcreq);
|
||||
}
|
||||
|
||||
static void proxy_participant_replace_minl (struct proxy_participant *proxypp, bool manbypp, struct lease *lnew)
|
||||
{
|
||||
/* By loading/storing the pointer atomically, we ensure we always
|
||||
read a valid (or once valid) lease. By delaying freeing the lease
|
||||
through the garbage collector, we ensure whatever lease update
|
||||
occurs in parallel completes before the memory is released. */
|
||||
struct gcreq *gcreq = gcreq_new (proxypp->e.gv->gcreq_queue, gc_proxy_participant_lease);
|
||||
struct lease *lease_old = ddsrt_atomic_ldvoidp (manbypp ? &proxypp->minl_man : &proxypp->minl_auto);
|
||||
lease_unregister (lease_old); /* ensures lease will not expire while it is replaced */
|
||||
gcreq->arg = lease_old;
|
||||
gcreq_enqueue (gcreq);
|
||||
ddsrt_atomic_stvoidp (manbypp ? &proxypp->minl_man : &proxypp->minl_auto, lnew);
|
||||
}
|
||||
|
||||
void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct lease *newlease)
|
||||
{
|
||||
/* Lease renewal is done by the receive thread without locking the
|
||||
proxy participant (and I'd like to keep it that way), but that
|
||||
means we must guarantee that the lease pointer remains valid once
|
||||
loaded.
|
||||
|
||||
By loading/storing the pointer atomically, we ensure we always
|
||||
read a valid (or once valid) value, by delaying the freeing
|
||||
through the garbage collector, we ensure whatever lease update
|
||||
occurs in parallel completes before the memory is released.
|
||||
|
||||
The lease_renew(never) call ensures the lease will never expire
|
||||
while we are messing with it. */
|
||||
ddsrt_mutex_lock (&proxypp->e.lock);
|
||||
if (proxypp->owns_lease)
|
||||
{
|
||||
const nn_etime_t never = { T_NEVER };
|
||||
struct lease *minl = ddsrt_fibheap_min (&lease_fhdef_proxypp, &proxypp->leaseheap_auto);
|
||||
ddsrt_fibheap_delete (&lease_fhdef_proxypp, &proxypp->leaseheap_auto, proxypp->lease);
|
||||
if (minl == proxypp->lease)
|
||||
{
|
||||
if ((minl = ddsrt_fibheap_min (&lease_fhdef_proxypp, &proxypp->leaseheap_auto)) != NULL)
|
||||
{
|
||||
dds_duration_t trem = minl->tdur - proxypp->lease->tdur;
|
||||
assert (trem >= 0);
|
||||
nn_etime_t texp = add_duration_to_etime (now_et(), trem);
|
||||
struct lease *lnew = lease_new (texp, minl->tdur, minl->entity);
|
||||
proxy_participant_replace_minl (proxypp, false, lnew);
|
||||
lease_register (lnew);
|
||||
}
|
||||
else
|
||||
{
|
||||
proxy_participant_replace_minl (proxypp, false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lease renewal is done by the receive thread without locking the
|
||||
proxy participant (and I'd like to keep it that way), but that
|
||||
means we must guarantee that the lease pointer remains valid once
|
||||
loaded.
|
||||
|
||||
By loading/storing the pointer atomically, we ensure we always
|
||||
read a valid (or once valid) value, by delaying the freeing
|
||||
through the garbage collector, we ensure whatever lease update
|
||||
occurs in parallel completes before the memory is released.
|
||||
|
||||
The lease_unregister call ensures the lease will never expire
|
||||
while we are messing with it. */
|
||||
struct gcreq *gcreq = gcreq_new (proxypp->e.gv->gcreq_queue, gc_proxy_participant_lease);
|
||||
struct lease *oldlease = ddsrt_atomic_ldvoidp (&proxypp->lease);
|
||||
lease_renew (oldlease, never);
|
||||
gcreq->arg = oldlease;
|
||||
lease_unregister (proxypp->lease);
|
||||
gcreq->arg = proxypp->lease;
|
||||
gcreq_enqueue (gcreq);
|
||||
proxypp->owns_lease = 0;
|
||||
}
|
||||
ddsrt_atomic_stvoidp (&proxypp->lease, newlease);
|
||||
proxypp->lease = newlease;
|
||||
|
||||
ddsrt_mutex_unlock (&proxypp->e.lock);
|
||||
}
|
||||
|
||||
|
@ -3942,14 +4099,13 @@ static void add_proxy_builtin_endpoints(
|
|||
&gv->builtin_stateless_xqos_rd);
|
||||
#endif
|
||||
|
||||
/* Register lease, but be careful not to accidentally re-register
|
||||
DDSI2's lease, as we may have become dependent on DDSI2 any time
|
||||
after ephash_insert_proxy_participant_guid even if
|
||||
privileged_pp_guid was NULL originally */
|
||||
/* Register lease for auto liveliness, but be careful not to accidentally re-register
|
||||
DDSI2's lease, as we may have become dependent on DDSI2 any time after
|
||||
ephash_insert_proxy_participant_guid even if privileged_pp_guid was NULL originally */
|
||||
ddsrt_mutex_lock (&proxypp->e.lock);
|
||||
|
||||
if (proxypp->owns_lease)
|
||||
lease_register (ddsrt_atomic_ldvoidp (&proxypp->lease));
|
||||
lease_register (ddsrt_atomic_ldvoidp (&proxypp->minl_auto));
|
||||
|
||||
builtintopic_write (gv->builtin_topic_interface, &proxypp->e, timestamp, true);
|
||||
ddsrt_mutex_unlock (&proxypp->e.lock);
|
||||
|
@ -3959,6 +4115,68 @@ static void add_proxy_builtin_endpoints(
|
|||
#undef LTE
|
||||
}
|
||||
|
||||
static void proxy_participant_add_pwr_lease_locked (struct proxy_participant * proxypp, const struct proxy_writer * pwr)
|
||||
{
|
||||
struct lease *minl_prev;
|
||||
struct lease *minl_new;
|
||||
ddsrt_fibheap_t *lh;
|
||||
bool manbypp;
|
||||
|
||||
assert (pwr->lease != NULL);
|
||||
manbypp = (pwr->c.xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT);
|
||||
lh = manbypp ? &proxypp->leaseheap_man : &proxypp->leaseheap_auto;
|
||||
minl_prev = ddsrt_fibheap_min (&lease_fhdef_proxypp, lh);
|
||||
ddsrt_fibheap_insert (&lease_fhdef_proxypp, lh, pwr->lease);
|
||||
minl_new = ddsrt_fibheap_min (&lease_fhdef_proxypp, lh);
|
||||
/* if inserted lease is new shortest lease */
|
||||
if (proxypp->owns_lease && minl_prev != minl_new)
|
||||
{
|
||||
nn_etime_t texp = add_duration_to_etime (now_et (), minl_new->tdur);
|
||||
struct lease *lnew = lease_new (texp, minl_new->tdur, minl_new->entity);
|
||||
if (minl_prev == NULL)
|
||||
{
|
||||
assert (manbypp);
|
||||
assert (ddsrt_atomic_ldvoidp (&proxypp->minl_man) == NULL);
|
||||
ddsrt_atomic_stvoidp (&proxypp->minl_man, lnew);
|
||||
}
|
||||
else
|
||||
{
|
||||
proxy_participant_replace_minl (proxypp, manbypp, lnew);
|
||||
}
|
||||
lease_register (lnew);
|
||||
}
|
||||
}
|
||||
|
||||
static void proxy_participant_remove_pwr_lease_locked (struct proxy_participant * proxypp, struct proxy_writer * pwr)
|
||||
{
|
||||
struct lease *minl;
|
||||
bool manbypp;
|
||||
ddsrt_fibheap_t *lh;
|
||||
|
||||
assert (pwr->lease != NULL);
|
||||
manbypp = (pwr->c.xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT);
|
||||
lh = manbypp ? &proxypp->leaseheap_man : &proxypp->leaseheap_auto;
|
||||
minl = ddsrt_fibheap_min (&lease_fhdef_proxypp, lh);
|
||||
ddsrt_fibheap_delete (&lease_fhdef_proxypp, lh, pwr->lease);
|
||||
/* if pwr with min lease is removed: update proxypp lease to use new minimal duration */
|
||||
if (proxypp->owns_lease && pwr->lease == minl)
|
||||
{
|
||||
if ((minl = ddsrt_fibheap_min (&lease_fhdef_proxypp, lh)) != NULL)
|
||||
{
|
||||
dds_duration_t trem = minl->tdur - pwr->lease->tdur;
|
||||
assert (trem >= 0);
|
||||
nn_etime_t texp = add_duration_to_etime (now_et(), trem);
|
||||
struct lease *lnew = lease_new (texp, minl->tdur, minl->entity);
|
||||
proxy_participant_replace_minl (proxypp, manbypp, lnew);
|
||||
lease_register (lnew);
|
||||
}
|
||||
else
|
||||
{
|
||||
proxy_participant_replace_minl (proxypp, manbypp, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void new_proxy_participant
|
||||
(
|
||||
struct q_globals *gv,
|
||||
|
@ -3992,6 +4210,7 @@ void new_proxy_participant
|
|||
entity_common_init (&proxypp->e, gv, ppguid, "", EK_PROXY_PARTICIPANT, timestamp, vendor, false);
|
||||
proxypp->refc = 1;
|
||||
proxypp->lease_expired = 0;
|
||||
proxypp->deleting = 0;
|
||||
proxypp->vendor = vendor;
|
||||
proxypp->bes = bes;
|
||||
proxypp->prismtech_bes = prismtech_bes;
|
||||
|
@ -4017,18 +4236,42 @@ void new_proxy_participant
|
|||
{
|
||||
struct proxy_participant *privpp;
|
||||
privpp = ephash_lookup_proxy_participant_guid (gv->guid_hash, &proxypp->privileged_pp_guid);
|
||||
|
||||
ddsrt_fibheap_init (&lease_fhdef_proxypp, &proxypp->leaseheap_auto);
|
||||
ddsrt_fibheap_init (&lease_fhdef_proxypp, &proxypp->leaseheap_man);
|
||||
ddsrt_atomic_stvoidp (&proxypp->minl_man, NULL);
|
||||
|
||||
if (privpp != NULL && privpp->is_ddsi2_pp)
|
||||
{
|
||||
ddsrt_atomic_stvoidp (&proxypp->lease, ddsrt_atomic_ldvoidp (&privpp->lease));
|
||||
proxypp->lease = privpp->lease;
|
||||
proxypp->owns_lease = 0;
|
||||
ddsrt_atomic_stvoidp (&proxypp->minl_auto, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Lease duration is meaningless when the lease never expires, but when proxy participants are created implicitly because of endpoint discovery from a cloud service, we do want the lease to expire eventually when the cloud discovery service disappears and never reappears. The normal data path renews the lease, so if the lease expiry is changed after the DS disappears but data continues to flow (even if it is only a single sample) the proxy participant would immediately go back to a non-expiring lease with no further triggers for deleting it. Instead, we take tlease_dur == NEVER as a special value meaning a lease that doesn't expire now and that has a "reasonable" lease duration. That way the lease renewal in the data path is fine, and we only need to do something special in SEDP handling. */
|
||||
/* Lease duration is meaningless when the lease never expires, but when proxy participants are
|
||||
created implicitly because of endpoint discovery from a cloud service, we do want the lease to expire
|
||||
eventually when the cloud discovery service disappears and never reappears. The normal data path renews
|
||||
the lease, so if the lease expiry is changed after the DS disappears but data continues to flow (even if
|
||||
it is only a single sample) the proxy participant would immediately go back to a non-expiring lease with
|
||||
no further triggers for deleting it. Instead, we take tlease_dur == NEVER as a special value meaning a
|
||||
lease that doesn't expire now and that has a "reasonable" lease duration. That way the lease renewal in
|
||||
the data path is fine, and we only need to do something special in SEDP handling. */
|
||||
nn_etime_t texp = add_duration_to_etime (now_et(), tlease_dur);
|
||||
dds_duration_t dur = (tlease_dur == T_NEVER) ? gv->config.lease_duration : tlease_dur;
|
||||
ddsrt_atomic_stvoidp (&proxypp->lease, lease_new (texp, dur, &proxypp->e));
|
||||
proxypp->lease = lease_new (texp, dur, &proxypp->e);
|
||||
proxypp->owns_lease = 1;
|
||||
|
||||
/* Add the proxypp lease to heap so that monitoring liveliness will include this lease
|
||||
and uses the shortest duration for proxypp and all its pwr's (with automatic liveliness) */
|
||||
ddsrt_fibheap_insert (&lease_fhdef_proxypp, &proxypp->leaseheap_auto, proxypp->lease);
|
||||
|
||||
/* Set the shortest lease for auto liveliness: clone proxypp's lease and store the clone in
|
||||
proxypp->minl_auto. As there are no pwr's at this point, the proxy pp's lease is the
|
||||
shortest lease. When a pwr with a shorter is added, the lease in minl_auto is replaced
|
||||
by the lease from the proxy writer in proxy_participant_add_pwr_lease_locked. This old shortest
|
||||
lease is freed, so that's why we need a clone and not the proxypp's lease in the heap. */
|
||||
ddsrt_atomic_stvoidp (&proxypp->minl_auto, (void *) lease_clone (proxypp->lease));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4084,7 +4327,7 @@ int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, se
|
|||
switch (source)
|
||||
{
|
||||
case UPD_PROXYPP_SPDP:
|
||||
update_qos_locked (&proxypp->e, &proxypp->plist->qos, &new_plist->qos, timestamp);
|
||||
(void) update_qos_locked (&proxypp->e, &proxypp->plist->qos, &new_plist->qos, timestamp);
|
||||
nn_plist_fini (new_plist);
|
||||
ddsrt_free (new_plist);
|
||||
proxypp->proxypp_have_spdp = 1;
|
||||
|
@ -4108,9 +4351,14 @@ int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t s
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ref_proxy_participant (struct proxy_participant *proxypp, struct proxy_endpoint_common *c)
|
||||
static int ref_proxy_participant (struct proxy_participant *proxypp, struct proxy_endpoint_common *c)
|
||||
{
|
||||
ddsrt_mutex_lock (&proxypp->e.lock);
|
||||
if (proxypp->deleting)
|
||||
{
|
||||
ddsrt_mutex_unlock (&proxypp->e.lock);
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
}
|
||||
c->proxypp = proxypp;
|
||||
proxypp->refc++;
|
||||
|
||||
|
@ -4122,6 +4370,8 @@ static void ref_proxy_participant (struct proxy_participant *proxypp, struct pro
|
|||
}
|
||||
proxypp->endpoints = c;
|
||||
ddsrt_mutex_unlock (&proxypp->e.lock);
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
static void unref_proxy_participant (struct proxy_participant *proxypp, struct proxy_endpoint_common *c)
|
||||
|
@ -4145,14 +4395,24 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p
|
|||
if (refc == 0)
|
||||
{
|
||||
assert (proxypp->endpoints == NULL);
|
||||
if (proxypp->owns_lease)
|
||||
{
|
||||
struct lease * minl_auto = ddsrt_atomic_ldvoidp (&proxypp->minl_auto);
|
||||
ddsrt_fibheap_delete (&lease_fhdef_proxypp, &proxypp->leaseheap_auto, proxypp->lease);
|
||||
assert (ddsrt_fibheap_min (&lease_fhdef_proxypp, &proxypp->leaseheap_auto) == NULL);
|
||||
assert (ddsrt_fibheap_min (&lease_fhdef_proxypp, &proxypp->leaseheap_man) == NULL);
|
||||
assert (ddsrt_atomic_ldvoidp (&proxypp->minl_man) == NULL);
|
||||
assert (!compare_guid (&minl_auto->entity->guid, &proxypp->e.guid));
|
||||
lease_unregister (minl_auto);
|
||||
lease_free (minl_auto);
|
||||
lease_free (proxypp->lease);
|
||||
}
|
||||
ddsrt_mutex_unlock (&proxypp->e.lock);
|
||||
ELOGDISC (proxypp, "unref_proxy_participant("PGUIDFMT"): refc=0, freeing\n", PGUID (proxypp->e.guid));
|
||||
unref_addrset (proxypp->as_default);
|
||||
unref_addrset (proxypp->as_meta);
|
||||
nn_plist_fini (proxypp->plist);
|
||||
ddsrt_free (proxypp->plist);
|
||||
if (proxypp->owns_lease)
|
||||
lease_free (ddsrt_atomic_ldvoidp (&proxypp->lease));
|
||||
entity_common_fini (&proxypp->e);
|
||||
remove_deleted_participant_guid (proxypp->e.gv->deleted_participants, &proxypp->e.guid, DPG_LOCAL | DPG_REMOTE);
|
||||
ddsrt_free (proxypp);
|
||||
|
@ -4213,15 +4473,17 @@ static void delete_or_detach_dependent_pp (struct proxy_participant *p, struct p
|
|||
/* Clear dependency (but don't touch entity id, which must be 0x1c1) and set the lease ticking */
|
||||
ELOGDISC (p, PGUIDFMT" detach-from-DS "PGUIDFMT"\n", PGUID(p->e.guid), PGUID(proxypp->e.guid));
|
||||
memset (&p->privileged_pp_guid.prefix, 0, sizeof (p->privileged_pp_guid.prefix));
|
||||
lease_set_expiry (ddsrt_atomic_ldvoidp (&p->lease), texp);
|
||||
lease_set_expiry (p->lease, texp);
|
||||
/* FIXME: replace in p->leaseheap_auto and get new minl_auto */
|
||||
ddsrt_mutex_unlock (&p->e.lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void delete_ppt (struct proxy_participant *proxypp, nn_wctime_t timestamp, int isimplicit)
|
||||
{
|
||||
struct proxy_endpoint_common * c;
|
||||
int ret;
|
||||
ddsi_entityid_t *eps;
|
||||
ddsi_guid_t ep_guid;
|
||||
uint32_t ep_count = 0;
|
||||
|
||||
/* if any proxy participants depend on this participant, delete them */
|
||||
ELOGDISC (proxypp, "delete_ppt("PGUIDFMT") - deleting dependent proxy participants\n", PGUID (proxypp->e.guid));
|
||||
|
@ -4234,31 +4496,38 @@ static void delete_ppt (struct proxy_participant *proxypp, nn_wctime_t timestamp
|
|||
ephash_enum_proxy_participant_fini (&est);
|
||||
}
|
||||
|
||||
/* delete_proxy_{reader,writer} merely schedules the actual delete
|
||||
operation, so we can hold the lock -- at least, for now. */
|
||||
|
||||
ddsrt_mutex_lock (&proxypp->e.lock);
|
||||
proxypp->deleting = 1;
|
||||
if (isimplicit)
|
||||
proxypp->lease_expired = 1;
|
||||
|
||||
ELOGDISC (proxypp, "delete_ppt("PGUIDFMT") - deleting endpoints\n", PGUID (proxypp->e.guid));
|
||||
c = proxypp->endpoints;
|
||||
while (c)
|
||||
/* Get snapshot of endpoints list so that we can release proxypp->e.lock
|
||||
Pwrs/prds may be deleted during the iteration over the entities,
|
||||
but resolving the guid will fail for these entities and the our
|
||||
call to delete_proxy_writer/reader returns. */
|
||||
{
|
||||
struct entity_common *e = entity_common_from_proxy_endpoint_common (c);
|
||||
if (is_writer_entityid (e->guid.entityid))
|
||||
eps = ddsrt_malloc (proxypp->refc * sizeof(ddsi_entityid_t));
|
||||
struct proxy_endpoint_common *cep = proxypp->endpoints;
|
||||
while (cep)
|
||||
{
|
||||
ret = delete_proxy_writer (proxypp->e.gv, &e->guid, timestamp, isimplicit);
|
||||
const struct entity_common *entc = entity_common_from_proxy_endpoint_common (cep);
|
||||
eps[ep_count++] = entc->guid.entityid;
|
||||
cep = cep->next_ep;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = delete_proxy_reader (proxypp->e.gv, &e->guid, timestamp, isimplicit);
|
||||
}
|
||||
(void) ret;
|
||||
c = c->next_ep;
|
||||
}
|
||||
ddsrt_mutex_unlock (&proxypp->e.lock);
|
||||
|
||||
ELOGDISC (proxypp, "delete_ppt("PGUIDFMT") - deleting endpoints\n", PGUID (proxypp->e.guid));
|
||||
ep_guid.prefix = proxypp->e.guid.prefix;
|
||||
for (uint32_t n = 0; n < ep_count; n++)
|
||||
{
|
||||
ep_guid.entityid = eps[n];
|
||||
if (is_writer_entityid (ep_guid.entityid))
|
||||
delete_proxy_writer (proxypp->e.gv, &ep_guid, timestamp, isimplicit);
|
||||
else
|
||||
delete_proxy_reader (proxypp->e.gv, &ep_guid, timestamp, isimplicit);
|
||||
}
|
||||
ddsrt_free (eps);
|
||||
gcreq_proxy_participant (proxypp);
|
||||
}
|
||||
|
||||
|
@ -4335,9 +4604,10 @@ uint64_t get_entity_instance_id (const struct q_globals *gv, const struct ddsi_g
|
|||
|
||||
/* PROXY-ENDPOINT --------------------------------------------------- */
|
||||
|
||||
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)
|
||||
static int 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;
|
||||
int ret;
|
||||
|
||||
if (is_builtin_entityid (guid->entityid, proxypp->vendor))
|
||||
assert ((plist->qos.present & (QP_TOPIC_NAME | QP_TYPE_NAME)) == 0);
|
||||
|
@ -4361,7 +4631,16 @@ static void proxy_endpoint_common_init (struct entity_common *e, struct proxy_en
|
|||
c->security_info.plugin_security_attributes = 0;
|
||||
#endif
|
||||
|
||||
ref_proxy_participant (proxypp, c);
|
||||
if ((ret = ref_proxy_participant (proxypp, c)) != DDS_RETCODE_OK)
|
||||
{
|
||||
nn_xqos_fini (c->xqos);
|
||||
ddsrt_free (c->xqos);
|
||||
unref_addrset (c->as);
|
||||
entity_common_fini (e);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
static void proxy_endpoint_common_fini (struct entity_common *e, struct proxy_endpoint_common *c)
|
||||
|
@ -4396,6 +4675,7 @@ int new_proxy_writer (struct q_globals *gv, const struct ddsi_guid *ppguid, cons
|
|||
int isreliable;
|
||||
nn_mtime_t tnow = now_mt ();
|
||||
enum nn_reorder_mode reorder_mode;
|
||||
int ret;
|
||||
|
||||
assert (is_writer_entityid (guid->entityid));
|
||||
assert (ephash_lookup_proxy_writer_guid (gv->guid_hash, guid) == NULL);
|
||||
|
@ -4407,7 +4687,11 @@ int new_proxy_writer (struct q_globals *gv, const struct ddsi_guid *ppguid, cons
|
|||
}
|
||||
|
||||
pwr = ddsrt_malloc (sizeof (*pwr));
|
||||
proxy_endpoint_common_init (&pwr->e, &pwr->c, EK_PROXY_WRITER, guid, timestamp, seq, proxypp, as, plist);
|
||||
if ((ret = proxy_endpoint_common_init (&pwr->e, &pwr->c, EK_PROXY_WRITER, guid, timestamp, seq, proxypp, as, plist)) != DDS_RETCODE_OK)
|
||||
{
|
||||
ddsrt_free (pwr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ddsrt_avl_init (&pwr_readers_treedef, &pwr->readers);
|
||||
pwr->n_reliable_readers = 0;
|
||||
|
@ -4416,6 +4700,8 @@ int new_proxy_writer (struct q_globals *gv, const struct ddsi_guid *ppguid, cons
|
|||
pwr->last_fragnum = ~0u;
|
||||
pwr->nackfragcount = 0;
|
||||
pwr->last_fragnum_reset = 0;
|
||||
pwr->alive = 1;
|
||||
pwr->alive_vclock = 0;
|
||||
pwr->filtered = 0;
|
||||
ddsrt_atomic_st32 (&pwr->next_deliv_seq_lowword, 1);
|
||||
if (is_builtin_entityid (pwr->e.guid.entityid, pwr->c.vendor)) {
|
||||
|
@ -4440,17 +4726,25 @@ int new_proxy_writer (struct q_globals *gv, const struct ddsi_guid *ppguid, cons
|
|||
#endif
|
||||
|
||||
assert (pwr->c.xqos->present & QP_LIVELINESS);
|
||||
if (pwr->c.xqos->liveliness.kind != DDS_LIVELINESS_AUTOMATIC)
|
||||
GVLOGDISC (" FIXME: only AUTOMATIC liveliness supported");
|
||||
#if 0
|
||||
pwr->tlease_dur = nn_from_ddsi_duration (pwr->c.xqos->liveliness.lease_duration);
|
||||
if (pwr->tlease_dur == 0)
|
||||
if (pwr->c.xqos->liveliness.lease_duration != T_NEVER)
|
||||
{
|
||||
GVLOGDISC (" FIXME: treating lease_duration=0 as inf");
|
||||
pwr->tlease_dur = T_NEVER;
|
||||
nn_etime_t texpire = add_duration_to_etime (now_et (), pwr->c.xqos->liveliness.lease_duration);
|
||||
pwr->lease = lease_new (texpire, pwr->c.xqos->liveliness.lease_duration, &pwr->e);
|
||||
if (pwr->c.xqos->liveliness.kind != DDS_LIVELINESS_MANUAL_BY_TOPIC)
|
||||
{
|
||||
ddsrt_mutex_lock (&proxypp->e.lock);
|
||||
proxy_participant_add_pwr_lease_locked (proxypp, pwr);
|
||||
ddsrt_mutex_unlock (&proxypp->e.lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
lease_register (pwr->lease);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pwr->lease = NULL;
|
||||
}
|
||||
pwr->tlease_end = add_duration_to_wctime (tnow, pwr->tlease_dur);
|
||||
#endif
|
||||
|
||||
if (isreliable)
|
||||
{
|
||||
|
@ -4531,7 +4825,7 @@ void update_proxy_writer (struct proxy_writer *pwr, seqno_t seq, struct addrset
|
|||
}
|
||||
}
|
||||
|
||||
update_qos_locked (&pwr->e, pwr->c.xqos, xqos, timestamp);
|
||||
(void) update_qos_locked (&pwr->e, pwr->c.xqos, xqos, timestamp);
|
||||
}
|
||||
ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
}
|
||||
|
@ -4589,7 +4883,7 @@ void update_proxy_reader (struct proxy_reader *prd, seqno_t seq, struct addrset
|
|||
}
|
||||
}
|
||||
|
||||
update_qos_locked (&prd->e, prd->c.xqos, xqos, timestamp);
|
||||
(void) update_qos_locked (&prd->e, prd->c.xqos, xqos, timestamp);
|
||||
}
|
||||
ddsrt_mutex_unlock (&prd->e.lock);
|
||||
}
|
||||
|
@ -4599,7 +4893,6 @@ static void gc_delete_proxy_writer (struct gcreq *gcreq)
|
|||
struct proxy_writer *pwr = gcreq->arg;
|
||||
ELOGDISC (pwr, "gc_delete_proxy_writer(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pwr->e.guid));
|
||||
gcreq_free (gcreq);
|
||||
|
||||
while (!ddsrt_avl_is_empty (&pwr->readers))
|
||||
{
|
||||
struct pwr_rd_match *m = ddsrt_avl_root_non_empty (&pwr_readers_treedef, &pwr->readers);
|
||||
|
@ -4609,17 +4902,22 @@ static void gc_delete_proxy_writer (struct gcreq *gcreq)
|
|||
free_pwr_rd_match (m);
|
||||
}
|
||||
local_reader_ary_fini (&pwr->rdary);
|
||||
if (pwr->c.xqos->liveliness.lease_duration != T_NEVER)
|
||||
lease_free (pwr->lease);
|
||||
proxy_endpoint_common_fini (&pwr->e, &pwr->c);
|
||||
nn_defrag_free (pwr->defrag);
|
||||
nn_reorder_free (pwr->reorder);
|
||||
ddsrt_free (pwr);
|
||||
}
|
||||
|
||||
/* First stage in deleting the proxy writer. In this function the pwr and its member pointers
|
||||
will remain valid. The real cleaning-up is done async in gc_delete_proxy_writer. */
|
||||
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;
|
||||
DDSRT_UNUSED_ARG (isimplicit);
|
||||
GVLOGDISC ("delete_proxy_writer ("PGUIDFMT") ", PGUID (*guid));
|
||||
|
||||
ddsrt_mutex_lock (&gv->lock);
|
||||
if ((pwr = ephash_lookup_proxy_writer_guid (gv->guid_hash, guid)) == NULL)
|
||||
{
|
||||
|
@ -4627,6 +4925,7 @@ int delete_proxy_writer (struct q_globals *gv, const struct ddsi_guid *guid, nn_
|
|||
GVLOGDISC ("- unknown\n");
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
/* Set "deleting" flag in particular for Lite, to signal to the receive path it can't
|
||||
trust rdary[] anymore, which is because removing the proxy writer from the hash
|
||||
table will prevent the readers from looking up the proxy writer, and consequently
|
||||
|
@ -4636,8 +4935,96 @@ int delete_proxy_writer (struct q_globals *gv, const struct ddsi_guid *guid, nn_
|
|||
builtintopic_write (gv->builtin_topic_interface, &pwr->e, timestamp, false);
|
||||
ephash_remove_proxy_writer_guid (gv->guid_hash, pwr);
|
||||
ddsrt_mutex_unlock (&gv->lock);
|
||||
if (pwr->c.xqos->liveliness.lease_duration != T_NEVER &&
|
||||
pwr->c.xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_TOPIC)
|
||||
lease_unregister (pwr->lease);
|
||||
if (proxy_writer_set_notalive (pwr, false) != DDS_RETCODE_OK)
|
||||
GVLOGDISC ("proxy_writer_set_notalive failed for "PGUIDFMT"\n", PGUID(*guid));
|
||||
gcreq_proxy_writer (pwr);
|
||||
return 0;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
static void proxy_writer_notify_liveliness_change_may_unlock (struct proxy_writer *pwr)
|
||||
{
|
||||
struct proxy_writer_alive_state alive_state;
|
||||
proxy_writer_get_alive_state_locked (pwr, &alive_state);
|
||||
|
||||
struct ddsi_guid rdguid;
|
||||
struct pwr_rd_match *m;
|
||||
memset (&rdguid, 0, sizeof (rdguid));
|
||||
while (pwr->alive_vclock == alive_state.vclock &&
|
||||
(m = ddsrt_avl_lookup_succ (&pwr_readers_treedef, &pwr->readers, &rdguid)) != NULL)
|
||||
{
|
||||
rdguid = m->rd_guid;
|
||||
ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
/* unlocking pwr means alive state may have changed already; we break out of the loop once we
|
||||
detect this but there for the reader in the current iteration, anything is possible */
|
||||
reader_update_notify_pwr_alive_state_guid (&rdguid, pwr, &alive_state);
|
||||
ddsrt_mutex_lock (&pwr->e.lock);
|
||||
}
|
||||
}
|
||||
|
||||
void proxy_writer_set_alive_may_unlock (struct proxy_writer *pwr, bool notify)
|
||||
{
|
||||
/* Caller has pwr->e.lock, so we can safely read pwr->alive. Updating pwr->alive requires
|
||||
also taking pwr->c.proxypp->e.lock because pwr->alive <=> (pwr->lease in proxypp's lease
|
||||
heap). */
|
||||
assert (!pwr->alive);
|
||||
|
||||
/* check that proxy writer still exists (when deleting it is removed from guid hash) */
|
||||
if (ephash_lookup_proxy_writer_guid (pwr->e.gv->guid_hash, &pwr->e.guid) == NULL)
|
||||
{
|
||||
ELOGDISC (pwr, "proxy_writer_set_alive_may_unlock("PGUIDFMT") - not in guid_hash, pwr deleting\n", PGUID (pwr->e.guid));
|
||||
return;
|
||||
}
|
||||
|
||||
ddsrt_mutex_lock (&pwr->c.proxypp->e.lock);
|
||||
pwr->alive = true;
|
||||
pwr->alive_vclock++;
|
||||
if (pwr->c.xqos->liveliness.lease_duration != T_NEVER && pwr->c.xqos->liveliness.kind != DDS_LIVELINESS_MANUAL_BY_TOPIC)
|
||||
proxy_participant_add_pwr_lease_locked (pwr->c.proxypp, pwr);
|
||||
ddsrt_mutex_unlock (&pwr->c.proxypp->e.lock);
|
||||
|
||||
if (notify)
|
||||
proxy_writer_notify_liveliness_change_may_unlock (pwr);
|
||||
}
|
||||
|
||||
int proxy_writer_set_notalive (struct proxy_writer *pwr, bool notify)
|
||||
{
|
||||
/* Caller should not have taken pwr->e.lock and pwr->c.proxypp->e.lock;
|
||||
* this function takes both locks to update pwr->alive value */
|
||||
ddsrt_mutex_lock (&pwr->e.lock);
|
||||
if (!pwr->alive)
|
||||
{
|
||||
ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
}
|
||||
|
||||
ddsrt_mutex_lock (&pwr->c.proxypp->e.lock);
|
||||
pwr->alive = false;
|
||||
pwr->alive_vclock++;
|
||||
if (pwr->c.xqos->liveliness.lease_duration != T_NEVER && pwr->c.xqos->liveliness.kind != DDS_LIVELINESS_MANUAL_BY_TOPIC)
|
||||
proxy_participant_remove_pwr_lease_locked (pwr->c.proxypp, pwr);
|
||||
ddsrt_mutex_unlock (&pwr->c.proxypp->e.lock);
|
||||
|
||||
if (notify)
|
||||
proxy_writer_notify_liveliness_change_may_unlock (pwr);
|
||||
ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
void proxy_writer_set_notalive_guid (struct q_globals *gv, const struct ddsi_guid *pwrguid, bool notify)
|
||||
{
|
||||
struct proxy_writer *pwr;
|
||||
if ((pwr = ephash_lookup_proxy_writer_guid (gv->guid_hash, pwrguid)) == NULL)
|
||||
GVLOGDISC (" "PGUIDFMT"?\n", PGUID (*pwrguid));
|
||||
else
|
||||
{
|
||||
GVLOGDISC ("proxy_writer_set_notalive_guid ("PGUIDFMT")", PGUID (*pwrguid));
|
||||
if (proxy_writer_set_notalive (pwr, notify) == DDS_RETCODE_PRECONDITION_NOT_MET)
|
||||
GVLOGDISC (" pwr was not alive");
|
||||
GVLOGDISC ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* PROXY-READER ----------------------------------------------------- */
|
||||
|
@ -4651,6 +5038,7 @@ int new_proxy_reader (struct q_globals *gv, const struct ddsi_guid *ppguid, cons
|
|||
struct proxy_participant *proxypp;
|
||||
struct proxy_reader *prd;
|
||||
nn_mtime_t tnow = now_mt ();
|
||||
int ret;
|
||||
|
||||
assert (!is_writer_entityid (guid->entityid));
|
||||
assert (ephash_lookup_proxy_reader_guid (gv->guid_hash, guid) == NULL);
|
||||
|
@ -4662,7 +5050,11 @@ int new_proxy_reader (struct q_globals *gv, const struct ddsi_guid *ppguid, cons
|
|||
}
|
||||
|
||||
prd = ddsrt_malloc (sizeof (*prd));
|
||||
proxy_endpoint_common_init (&prd->e, &prd->c, EK_PROXY_READER, guid, timestamp, seq, proxypp, as, plist);
|
||||
if ((ret = proxy_endpoint_common_init (&prd->e, &prd->c, EK_PROXY_READER, guid, timestamp, seq, proxypp, as, plist)) != DDS_RETCODE_OK)
|
||||
{
|
||||
ddsrt_free (prd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
prd->deleting = 0;
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
|
@ -4690,7 +5082,7 @@ int new_proxy_reader (struct q_globals *gv, const struct ddsi_guid *ppguid, cons
|
|||
ddsrt_mutex_unlock (&prd->e.lock);
|
||||
|
||||
match_proxy_reader_with_writers (prd, tnow);
|
||||
return 0;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
static void proxy_reader_set_delete_and_ack_all_messages (struct proxy_reader *prd)
|
||||
|
|
|
@ -133,7 +133,7 @@ static uint32_t gcreq_queue_thread (struct gcreq_queue *q)
|
|||
} else {
|
||||
to = delay;
|
||||
}
|
||||
ddsrt_cond_waitfor (&q->cond, &q->lock, to);
|
||||
(void) ddsrt_cond_waitfor (&q->cond, &q->lock, to);
|
||||
}
|
||||
if (q->first)
|
||||
{
|
||||
|
|
|
@ -71,36 +71,30 @@ static void add_peer_addresses (const struct q_globals *gv, struct addrset *as,
|
|||
}
|
||||
}
|
||||
|
||||
static int make_uc_sockets (struct q_globals *gv, uint32_t * pdisc, uint32_t * pdata, int ppid)
|
||||
enum make_uc_sockets_ret {
|
||||
MUSRET_SUCCESS,
|
||||
MUSRET_INVALID_PORTS,
|
||||
MUSRET_NOSOCKET
|
||||
};
|
||||
|
||||
static enum make_uc_sockets_ret make_uc_sockets (struct q_globals *gv, uint32_t * pdisc, uint32_t * pdata, int ppid)
|
||||
{
|
||||
if (gv->config.many_sockets_mode == MSM_NO_UNICAST)
|
||||
{
|
||||
assert (ppid == PARTICIPANT_INDEX_NONE);
|
||||
*pdata = *pdisc = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId);
|
||||
*pdata = *pdisc = ddsi_get_port (&gv->config, DDSI_PORT_MULTI_DISC, ppid);
|
||||
if (gv->config.allowMulticast)
|
||||
{
|
||||
/* FIXME: ugly hack - but we'll fix up after creating the multicast sockets */
|
||||
return 0;
|
||||
return MUSRET_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (ppid >= 0)
|
||||
{
|
||||
/* FIXME: verify port numbers are in range instead of truncating them like this */
|
||||
uint32_t base = gv->config.port_base + (gv->config.port_dg * gv->config.domainId) + ((uint32_t) ppid * gv->config.port_pg);
|
||||
*pdisc = base + gv->config.port_d1;
|
||||
*pdata = base + gv->config.port_d3;
|
||||
}
|
||||
else if (ppid == PARTICIPANT_INDEX_NONE)
|
||||
{
|
||||
*pdata = 0;
|
||||
*pdisc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
DDS_FATAL ("make_uc_sockets: invalid participant index %d\n", ppid);
|
||||
return -1;
|
||||
}
|
||||
*pdisc = ddsi_get_port (&gv->config, DDSI_PORT_UNI_DISC, ppid);
|
||||
*pdata = ddsi_get_port (&gv->config, DDSI_PORT_UNI_DATA, ppid);
|
||||
|
||||
if (!ddsi_is_valid_port (gv->m_factory, *pdisc) || !ddsi_is_valid_port (gv->m_factory, *pdata))
|
||||
return MUSRET_INVALID_PORTS;
|
||||
|
||||
gv->disc_conn_uc = ddsi_factory_create_conn (gv->m_factory, *pdisc, NULL);
|
||||
if (gv->disc_conn_uc)
|
||||
|
@ -123,13 +117,12 @@ static int make_uc_sockets (struct q_globals *gv, uint32_t * pdisc, uint32_t * p
|
|||
else
|
||||
{
|
||||
/* Set unicast locators */
|
||||
|
||||
ddsi_conn_locator (gv->disc_conn_uc, &gv->loc_meta_uc);
|
||||
ddsi_conn_locator (gv->data_conn_uc, &gv->loc_default_uc);
|
||||
}
|
||||
}
|
||||
|
||||
return gv->data_conn_uc ? 0 : -1;
|
||||
return gv->data_conn_uc ? MUSRET_SUCCESS : MUSRET_NOSOCKET;
|
||||
}
|
||||
|
||||
static void make_builtin_endpoint_xqos (dds_qos_t *q, const dds_qos_t *template)
|
||||
|
@ -309,7 +302,7 @@ static int string_to_default_locator (const struct q_globals *gv, nn_locator_t *
|
|||
|
||||
static int set_spdp_address (struct q_globals *gv)
|
||||
{
|
||||
const uint32_t port = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d0);
|
||||
const uint32_t port = ddsi_get_port (&gv->config, DDSI_PORT_MULTI_DISC, 0);
|
||||
int rc = 0;
|
||||
/* FIXME: FIXME: FIXME: */
|
||||
gv->loc_spdp_mc.kind = NN_LOCATOR_KIND_INVALID;
|
||||
|
@ -341,7 +334,7 @@ static int set_spdp_address (struct q_globals *gv)
|
|||
|
||||
static int set_default_mc_address (struct q_globals *gv)
|
||||
{
|
||||
const uint32_t port = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d2);
|
||||
const uint32_t port = ddsi_get_port (&gv->config, DDSI_PORT_MULTI_DATA, 0);
|
||||
int rc;
|
||||
if (!gv->config.defaultMulticastAddressString)
|
||||
gv->loc_default_mc = gv->loc_spdp_mc;
|
||||
|
@ -482,6 +475,33 @@ int rtps_config_prep (struct q_globals *gv, struct cfgst *cfgst)
|
|||
unsigned num_channel_threads = 0;
|
||||
#endif
|
||||
|
||||
/* advertised domain id defaults to the real domain id; clear "isdefault" so the config
|
||||
dump includes the actually used value rather than "default" */
|
||||
if (gv->config.extDomainId.isdefault)
|
||||
{
|
||||
gv->config.extDomainId.value = gv->config.domainId;
|
||||
gv->config.extDomainId.isdefault = 0;
|
||||
}
|
||||
|
||||
{
|
||||
char message[256];
|
||||
int32_t ppidx;
|
||||
if (gv->config.participantIndex >= 0 || gv->config.participantIndex == PARTICIPANT_INDEX_NONE)
|
||||
ppidx = gv->config.participantIndex;
|
||||
else if (gv->config.participantIndex == PARTICIPANT_INDEX_AUTO)
|
||||
ppidx = gv->config.maxAutoParticipantIndex;
|
||||
else
|
||||
{
|
||||
assert (0);
|
||||
ppidx = 0;
|
||||
}
|
||||
if (!ddsi_valid_portmapping (&gv->config, ppidx, message, sizeof (message)))
|
||||
{
|
||||
DDS_ILOG (DDS_LC_ERROR, gv->config.domainId, "Invalid port mapping: %s\n", message);
|
||||
goto err_config_late_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* retry_on_reject_duration default is dependent on late_ack_mode and responsiveness timeout, so fix up */
|
||||
if (gv->config.whc_init_highwater_mark.isdefault)
|
||||
gv->config.whc_init_highwater_mark.value = gv->config.whc_lowwater_mark;
|
||||
|
@ -669,8 +689,13 @@ int create_multicast_sockets (struct q_globals *gv)
|
|||
uint32_t port;
|
||||
qos->m_multicast = 1;
|
||||
|
||||
/* FIXME: should check for overflow */
|
||||
port = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d0);
|
||||
port = ddsi_get_port (&gv->config, DDSI_PORT_MULTI_DISC, 0);
|
||||
if (!ddsi_is_valid_port (gv->m_factory, port))
|
||||
{
|
||||
GVERROR ("Failed to create discovery multicast socket for domain %"PRIu32": resulting port number (%"PRIu32") is out of range\n",
|
||||
gv->config.extDomainId.value, port);
|
||||
goto err_disc;
|
||||
}
|
||||
if ((disc = ddsi_factory_create_conn (gv->m_factory, port, qos)) == NULL)
|
||||
goto err_disc;
|
||||
if (gv->config.many_sockets_mode == MSM_NO_UNICAST)
|
||||
|
@ -680,16 +705,24 @@ int create_multicast_sockets (struct q_globals *gv)
|
|||
}
|
||||
else
|
||||
{
|
||||
port = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d2);
|
||||
port = ddsi_get_port (&gv->config, DDSI_PORT_MULTI_DATA, 0);
|
||||
if (!ddsi_is_valid_port (gv->m_factory, port))
|
||||
{
|
||||
GVERROR ("Failed to create data multicast socket for domain %"PRIu32": resulting port number (%"PRIu32") is out of range\n",
|
||||
gv->config.extDomainId.value, port);
|
||||
goto err_disc;
|
||||
}
|
||||
if ((data = ddsi_factory_create_conn (gv->m_factory, port, qos)) == NULL)
|
||||
{
|
||||
goto err_data;
|
||||
}
|
||||
}
|
||||
ddsi_tran_free_qos (qos);
|
||||
|
||||
gv->disc_conn_mc = disc;
|
||||
gv->data_conn_mc = data;
|
||||
GVTRACE ("Multicast Ports: discovery %"PRIu32" data %"PRIu32" \n",
|
||||
ddsi_conn_port (gv->disc_conn_mc), ddsi_conn_port (gv->data_conn_mc));
|
||||
GVLOG (DDS_LC_CONFIG, "Multicast Ports: discovery %"PRIu32" data %"PRIu32" \n",
|
||||
ddsi_conn_port (gv->disc_conn_mc), ddsi_conn_port (gv->data_conn_mc));
|
||||
return 1;
|
||||
|
||||
err_data:
|
||||
|
@ -724,7 +757,7 @@ static void wait_for_receive_threads_helper (struct xevent *xev, void *varg, nn_
|
|||
if (arg->count++ == arg->gv->config.recv_thread_stop_maxretries)
|
||||
abort ();
|
||||
trigger_recv_threads (arg->gv);
|
||||
resched_xevent_if_earlier (xev, add_duration_to_mtime (tnow, T_SECOND));
|
||||
(void) resched_xevent_if_earlier (xev, add_duration_to_mtime (tnow, T_SECOND));
|
||||
}
|
||||
|
||||
static void wait_for_receive_threads (struct q_globals *gv)
|
||||
|
@ -1003,7 +1036,7 @@ int rtps_init (struct q_globals *gv)
|
|||
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
||||
/* Convert address sets in partition mappings from string to address sets */
|
||||
{
|
||||
const uint32_t port = gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d2;
|
||||
const uint32_t port = ddsi_get_port (&gv->config, DDSI_PORT_MULTI_DATA, 0);
|
||||
struct config_networkpartition_listelem *np;
|
||||
for (np = gv->config.networkPartitions; np; np = np->next)
|
||||
{
|
||||
|
@ -1106,33 +1139,44 @@ int rtps_init (struct q_globals *gv)
|
|||
{
|
||||
if (gv->config.participantIndex >= 0 || gv->config.participantIndex == PARTICIPANT_INDEX_NONE)
|
||||
{
|
||||
if (make_uc_sockets (gv, &port_disc_uc, &port_data_uc, gv->config.participantIndex) < 0)
|
||||
enum make_uc_sockets_ret musret = make_uc_sockets (gv, &port_disc_uc, &port_data_uc, gv->config.participantIndex);
|
||||
switch (musret)
|
||||
{
|
||||
GVERROR ("rtps_init: failed to create unicast sockets for domain %"PRId32" participant %d\n", gv->config.domainId, gv->config.participantIndex);
|
||||
goto err_unicast_sockets;
|
||||
case MUSRET_SUCCESS:
|
||||
break;
|
||||
case MUSRET_INVALID_PORTS:
|
||||
GVERROR ("Failed to create unicast sockets for domain %"PRIu32" participant index %d: resulting port numbers (%"PRIu32", %"PRIu32") are out of range\n",
|
||||
gv->config.extDomainId.value, gv->config.participantIndex, port_disc_uc, port_data_uc);
|
||||
goto err_unicast_sockets;
|
||||
case MUSRET_NOSOCKET:
|
||||
GVERROR ("rtps_init: failed to create unicast sockets for domain %"PRId32" participant index %d (ports %"PRIu32", %"PRIu32")\n", gv->config.extDomainId.value, gv->config.participantIndex, port_disc_uc, port_data_uc);
|
||||
goto err_unicast_sockets;
|
||||
}
|
||||
}
|
||||
else if (gv->config.participantIndex == PARTICIPANT_INDEX_AUTO)
|
||||
{
|
||||
/* try to find a free one, and update gv->config.participantIndex */
|
||||
enum make_uc_sockets_ret musret = MUSRET_NOSOCKET;
|
||||
int ppid;
|
||||
GVLOG (DDS_LC_CONFIG, "rtps_init: trying to find a free participant index\n");
|
||||
for (ppid = 0; ppid <= gv->config.maxAutoParticipantIndex; ppid++)
|
||||
for (ppid = 0; ppid <= gv->config.maxAutoParticipantIndex && musret == MUSRET_NOSOCKET; ppid++)
|
||||
{
|
||||
int r = make_uc_sockets (gv, &port_disc_uc, &port_data_uc, ppid);
|
||||
if (r == 0) /* Success! */
|
||||
break;
|
||||
else if (r == -1) /* Try next one */
|
||||
continue;
|
||||
else /* Oops! */
|
||||
musret = make_uc_sockets (gv, &port_disc_uc, &port_data_uc, ppid);
|
||||
switch (musret)
|
||||
{
|
||||
GVERROR ("rtps_init: failed to create unicast sockets for domain %"PRId32" participant %d\n", gv->config.domainId, ppid);
|
||||
goto err_unicast_sockets;
|
||||
case MUSRET_SUCCESS:
|
||||
break;
|
||||
case MUSRET_INVALID_PORTS:
|
||||
GVERROR ("Failed to create unicast sockets for domain %"PRIu32" participant index %d: resulting port numbers (%"PRIu32", %"PRIu32") are out of range\n",
|
||||
gv->config.extDomainId.value, ppid, port_disc_uc, port_data_uc);
|
||||
goto err_unicast_sockets;
|
||||
case MUSRET_NOSOCKET: /* Try next one */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ppid > gv->config.maxAutoParticipantIndex)
|
||||
{
|
||||
GVERROR ("rtps_init: failed to find a free participant index for domain %"PRId32"\n", gv->config.domainId);
|
||||
GVERROR ("Failed to find a free participant index for domain %"PRIu32"\n", gv->config.extDomainId.value);
|
||||
goto err_unicast_sockets;
|
||||
}
|
||||
gv->config.participantIndex = ppid;
|
||||
|
@ -1143,7 +1187,7 @@ int rtps_init (struct q_globals *gv)
|
|||
}
|
||||
GVLOG (DDS_LC_CONFIG, "rtps_init: uc ports: disc %"PRIu32" data %"PRIu32"\n", port_disc_uc, port_data_uc);
|
||||
}
|
||||
GVLOG (DDS_LC_CONFIG, "rtps_init: domainid %"PRId32" participantid %d\n", gv->config.domainId, gv->config.participantIndex);
|
||||
GVLOG (DDS_LC_CONFIG, "rtps_init: domainid %"PRIu32" participantid %d\n", gv->config.domainId, gv->config.participantIndex);
|
||||
|
||||
if (gv->config.pcap_file && *gv->config.pcap_file)
|
||||
{
|
||||
|
@ -1193,9 +1237,15 @@ int rtps_init (struct q_globals *gv)
|
|||
/* Must have a data_conn_uc/tev_conn/transmit_conn */
|
||||
gv->data_conn_uc = ddsi_factory_create_conn (gv->m_factory, 0, NULL);
|
||||
|
||||
if (gv->config.tcp_port != -1)
|
||||
if (gv->config.tcp_port == -1)
|
||||
; /* nop */
|
||||
else if (!ddsi_is_valid_port (gv->m_factory, (uint32_t) gv->config.tcp_port))
|
||||
{
|
||||
gv->listener = ddsi_factory_create_listener (gv->m_factory, gv->config.tcp_port, NULL);
|
||||
GVERROR ("Listener port %d is out of range for transport %s\n", gv->config.tcp_port, gv->m_factory->m_typename);
|
||||
}
|
||||
else
|
||||
{
|
||||
gv->listener = ddsi_factory_create_listener (gv->m_factory, (uint32_t) gv->config.tcp_port, NULL);
|
||||
if (gv->listener == NULL || ddsi_listener_listen (gv->listener) != 0)
|
||||
{
|
||||
GVERROR ("Failed to create %s listener\n", gv->m_factory->m_typename);
|
||||
|
@ -1445,13 +1495,23 @@ int rtps_start (struct q_globals *gv)
|
|||
}
|
||||
if (gv->listener)
|
||||
{
|
||||
create_thread (&gv->listen_ts, gv, "listen", (uint32_t (*) (void *)) listen_thread, gv->listener);
|
||||
/* FIXME: error handling */
|
||||
if (create_thread (&gv->listen_ts, gv, "listen", (uint32_t (*) (void *)) listen_thread, gv->listener) != DDS_RETCODE_OK)
|
||||
{
|
||||
GVERROR ("failed to create TCP listener thread\n");
|
||||
ddsi_listener_free (gv->listener);
|
||||
gv->listener = NULL;
|
||||
rtps_stop (gv);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (gv->config.monitor_port >= 0)
|
||||
{
|
||||
gv->debmon = new_debug_monitor (gv, gv->config.monitor_port);
|
||||
/* FIXME: clean up */
|
||||
if ((gv->debmon = new_debug_monitor (gv, gv->config.monitor_port)) == NULL)
|
||||
{
|
||||
GVERROR ("failed to create debug monitor thread\n");
|
||||
rtps_stop (gv);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -43,30 +43,27 @@
|
|||
!= 0 -- and note that it had better be 2's complement machine! */
|
||||
#define TSCHED_NOT_ON_HEAP INT64_MIN
|
||||
|
||||
struct lease {
|
||||
ddsrt_fibheap_node_t heapnode;
|
||||
nn_etime_t tsched; /* access guarded by leaseheap_lock */
|
||||
ddsrt_atomic_uint64_t tend; /* really an nn_etime_t */
|
||||
dds_duration_t tdur; /* constant (renew depends on it) */
|
||||
struct entity_common *entity; /* constant */
|
||||
};
|
||||
|
||||
static int compare_lease_tsched (const void *va, const void *vb);
|
||||
|
||||
static const ddsrt_fibheap_def_t lease_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct lease, heapnode), compare_lease_tsched);
|
||||
const ddsrt_fibheap_def_t lease_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER (offsetof (struct lease, heapnode), compare_lease_tsched);
|
||||
|
||||
static void force_lease_check (struct gcreq_queue *gcreq_queue)
|
||||
{
|
||||
gcreq_enqueue (gcreq_new (gcreq_queue, gcreq_free));
|
||||
}
|
||||
|
||||
static int compare_lease_tsched (const void *va, const void *vb)
|
||||
int compare_lease_tsched (const void *va, const void *vb)
|
||||
{
|
||||
const struct lease *a = va;
|
||||
const struct lease *b = vb;
|
||||
return (a->tsched.v == b->tsched.v) ? 0 : (a->tsched.v < b->tsched.v) ? -1 : 1;
|
||||
}
|
||||
|
||||
int compare_lease_tdur (const void *va, const void *vb)
|
||||
{
|
||||
const struct lease *a = va;
|
||||
const struct lease *b = vb;
|
||||
return (a->tdur == b->tdur) ? 0 : (a->tdur < b->tdur) ? -1 : 1;
|
||||
}
|
||||
|
||||
void lease_management_init (struct q_globals *gv)
|
||||
{
|
||||
ddsrt_mutex_init (&gv->leaseheap_lock);
|
||||
|
@ -92,6 +89,20 @@ struct lease *lease_new (nn_etime_t texpire, dds_duration_t tdur, struct entity_
|
|||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a clone of the provided lease. Note that this function does not use
|
||||
* locking and should therefore only be called from a context where lease 'l'
|
||||
* cannot be changed by another thread during the function call.
|
||||
*/
|
||||
struct lease *lease_clone (const struct lease *l)
|
||||
{
|
||||
nn_etime_t texp;
|
||||
dds_duration_t tdur;
|
||||
texp.v = (int64_t) ddsrt_atomic_ld64 (&l->tend);
|
||||
tdur = l->tdur;
|
||||
return lease_new (texp, tdur, l->entity);
|
||||
}
|
||||
|
||||
void lease_register (struct lease *l) /* FIXME: make lease admin struct */
|
||||
{
|
||||
struct q_globals * const gv = l->entity->gv;
|
||||
|
@ -110,23 +121,31 @@ void lease_register (struct lease *l) /* FIXME: make lease admin struct */
|
|||
force_lease_check (gv->gcreq_queue);
|
||||
}
|
||||
|
||||
void lease_free (struct lease *l)
|
||||
void lease_unregister (struct lease *l)
|
||||
{
|
||||
struct q_globals * const gv = l->entity->gv;
|
||||
GVTRACE ("lease_free(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid));
|
||||
GVTRACE ("lease_unregister(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid));
|
||||
ddsrt_mutex_lock (&gv->leaseheap_lock);
|
||||
if (l->tsched.v != TSCHED_NOT_ON_HEAP)
|
||||
{
|
||||
ddsrt_fibheap_delete (&lease_fhdef, &gv->leaseheap, l);
|
||||
l->tsched.v = TSCHED_NOT_ON_HEAP;
|
||||
}
|
||||
ddsrt_mutex_unlock (&gv->leaseheap_lock);
|
||||
ddsrt_free (l);
|
||||
|
||||
/* see lease_register() */
|
||||
force_lease_check (gv->gcreq_queue);
|
||||
}
|
||||
|
||||
void lease_free (struct lease *l)
|
||||
{
|
||||
struct q_globals * const gv = l->entity->gv;
|
||||
GVTRACE ("lease_free(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid));
|
||||
ddsrt_free (l);
|
||||
}
|
||||
|
||||
void lease_renew (struct lease *l, nn_etime_t tnowE)
|
||||
{
|
||||
struct q_globals const * const gv = l->entity->gv;
|
||||
nn_etime_t tend_new = add_duration_to_etime (tnowE, l->tdur);
|
||||
|
||||
/* do not touch tend if moving forward or if already expired */
|
||||
|
@ -137,6 +156,11 @@ void lease_renew (struct lease *l, nn_etime_t tnowE)
|
|||
return;
|
||||
} while (!ddsrt_atomic_cas64 (&l->tend, (uint64_t) tend, (uint64_t) tend_new.v));
|
||||
|
||||
/* Only at this point we can assume that gv can be recovered from the entity in the
|
||||
* lease (i.e. the entity still exists). In cases where dereferencing l->entity->gv
|
||||
* is not safe (e.g. the deletion of entities), the early out in the loop above
|
||||
* will be the case because tend is set to T_NEVER. */
|
||||
struct q_globals const * gv = l->entity->gv;
|
||||
if (gv->logconfig.c.mask & DDS_LC_TRACE)
|
||||
{
|
||||
int32_t tsec, tusec;
|
||||
|
@ -253,26 +277,19 @@ int64_t check_and_handle_lease_expiration (struct q_globals *gv, nn_etime_t tnow
|
|||
|
||||
switch (k)
|
||||
{
|
||||
case EK_PARTICIPANT:
|
||||
delete_participant (gv, &g);
|
||||
break;
|
||||
case EK_PROXY_PARTICIPANT:
|
||||
delete_proxy_participant_by_guid (gv, &g, now(), 1);
|
||||
break;
|
||||
case EK_WRITER:
|
||||
delete_writer_nolinger (gv, &g);
|
||||
break;
|
||||
case EK_PROXY_WRITER:
|
||||
delete_proxy_writer (gv, &g, now(), 1);
|
||||
proxy_writer_set_notalive_guid (gv, &g, true);
|
||||
break;
|
||||
case EK_PARTICIPANT:
|
||||
case EK_READER:
|
||||
delete_reader (gv, &g);
|
||||
break;
|
||||
case EK_WRITER:
|
||||
case EK_PROXY_READER:
|
||||
delete_proxy_reader (gv, &g, now(), 1);
|
||||
assert (false);
|
||||
break;
|
||||
}
|
||||
|
||||
ddsrt_mutex_lock (&gv->leaseheap_lock);
|
||||
}
|
||||
|
||||
|
@ -281,83 +298,3 @@ int64_t check_and_handle_lease_expiration (struct q_globals *gv, nn_etime_t tnow
|
|||
return delay;
|
||||
}
|
||||
|
||||
/******/
|
||||
|
||||
static void debug_print_rawdata (const struct q_globals *gv, const char *msg, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *c = data;
|
||||
size_t i;
|
||||
GVTRACE ("%s<", msg);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (32 < c[i] && c[i] <= 127)
|
||||
GVTRACE ("%s%c", (i > 0 && (i%4) == 0) ? " " : "", c[i]);
|
||||
else
|
||||
GVTRACE ("%s\\x%02x", (i > 0 && (i%4) == 0) ? " " : "", c[i]);
|
||||
}
|
||||
GVTRACE (">");
|
||||
}
|
||||
|
||||
void handle_PMD (const struct receiver_state *rst, nn_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len)
|
||||
{
|
||||
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;
|
||||
ddsi_guid_t ppguid;
|
||||
RSTTRACE (" PMD ST%x", statusinfo);
|
||||
if (data->identifier != CDR_LE && data->identifier != CDR_BE)
|
||||
{
|
||||
RSTTRACE (" PMD data->identifier %u !?\n", ntohs (data->identifier));
|
||||
return;
|
||||
}
|
||||
switch (statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER))
|
||||
{
|
||||
case 0:
|
||||
if (offsetof (ParticipantMessageData_t, value) > len - sizeof (struct CDRHeader))
|
||||
debug_print_rawdata (rst->gv, " SHORT1", data, len);
|
||||
else
|
||||
{
|
||||
const ParticipantMessageData_t *pmd = (ParticipantMessageData_t *) (data + 1);
|
||||
ddsi_guid_prefix_t p = nn_ntoh_guid_prefix (pmd->participantGuidPrefix);
|
||||
uint32_t kind = ntohl (pmd->kind);
|
||||
uint32_t length = bswap ? ddsrt_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);
|
||||
if (len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value) < length)
|
||||
debug_print_rawdata (rst->gv, " SHORT2", pmd->value, len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value));
|
||||
else
|
||||
debug_print_rawdata (rst->gv, "", pmd->value, length);
|
||||
ppguid.prefix = p;
|
||||
ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
|
||||
if ((pp = ephash_lookup_proxy_participant_guid (rst->gv->guid_hash, &ppguid)) == NULL)
|
||||
RSTTRACE (" PPunknown");
|
||||
else
|
||||
{
|
||||
/* Renew lease if arrival of this message didn't already do so, also renew the lease
|
||||
of the virtual participant used for DS-discovered endpoints */
|
||||
#if 0 // FIXME: superfluous ... receipt of the message already did it */
|
||||
lease_renew (ddsrt_atomic_ldvoidp (&pp->lease), now_et ());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NN_STATUSINFO_DISPOSE:
|
||||
case NN_STATUSINFO_UNREGISTER:
|
||||
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 (ddsi_guid_prefix_t))
|
||||
debug_print_rawdata (rst->gv, " SHORT3", data, len);
|
||||
else
|
||||
{
|
||||
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");
|
||||
else
|
||||
RSTTRACE (" delete");
|
||||
}
|
||||
break;
|
||||
}
|
||||
RSTTRACE ("\n");
|
||||
}
|
||||
|
|
|
@ -99,66 +99,3 @@ int ddsi2_patmatch (const char *pat, const char *str)
|
|||
}
|
||||
return *str == 0;
|
||||
}
|
||||
|
||||
|
||||
static const uint32_t crc32_table[] = {
|
||||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
|
||||
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
|
||||
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
|
||||
0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
|
||||
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
|
||||
0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
|
||||
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
|
||||
0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
|
||||
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
|
||||
0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
|
||||
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
|
||||
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
|
||||
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
|
||||
0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
|
||||
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
|
||||
0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
||||
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
|
||||
0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
|
||||
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
|
||||
0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
|
||||
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
|
||||
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
|
||||
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
|
||||
0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
|
||||
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
|
||||
0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
|
||||
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
|
||||
0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
|
||||
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
|
||||
0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
|
||||
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
|
||||
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
|
||||
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
|
||||
0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
|
||||
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
|
||||
0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
||||
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
|
||||
0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
|
||||
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
|
||||
0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
|
||||
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
|
||||
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
|
||||
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
|
||||
};
|
||||
|
||||
uint32_t crc32_calc (const void *buf, size_t length)
|
||||
{
|
||||
const uint8_t *vptr = buf;
|
||||
uint32_t reg = 0;
|
||||
uint8_t top;
|
||||
size_t i;
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
top = (uint8_t) (reg >> 24);
|
||||
top ^= *vptr;
|
||||
reg = (reg << 8) ^ crc32_table[top];
|
||||
vptr++;
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
|
|
@ -464,11 +464,11 @@ int find_own_ip (struct q_globals *gv, const char *requested_address)
|
|||
char if_name[sizeof (last_if_name)];
|
||||
int q = 0;
|
||||
|
||||
ddsrt_strlcpy(if_name, ifa->name, sizeof(if_name));
|
||||
(void) ddsrt_strlcpy(if_name, ifa->name, sizeof(if_name));
|
||||
|
||||
if (strcmp (if_name, last_if_name))
|
||||
GVLOG (DDS_LC_CONFIG, "%s%s", sep, if_name);
|
||||
ddsrt_strlcpy(last_if_name, if_name, sizeof(last_if_name));
|
||||
(void) ddsrt_strlcpy(last_if_name, if_name, sizeof(last_if_name));
|
||||
|
||||
/* interface must be up */
|
||||
if ((ifa->flags & IFF_UP) == 0) {
|
||||
|
|
|
@ -96,7 +96,7 @@ FILE *new_pcap_file (const struct ddsrt_log_cfg *logcfg, const char *name)
|
|||
hdr.sigfigs = 0;
|
||||
hdr.snaplen = 65535;
|
||||
hdr.network = LINKTYPE_RAW;
|
||||
fwrite (&hdr, sizeof (hdr), 1, fp);
|
||||
(void) fwrite (&hdr, sizeof (hdr), 1, fp);
|
||||
|
||||
return fp;
|
||||
DDSRT_WARNING_MSVC_ON(4996);
|
||||
|
@ -109,7 +109,7 @@ static void write_data (FILE *fp, const ddsrt_msghdr_t *msghdr, size_t sz)
|
|||
{
|
||||
size_t m1 = msghdr->msg_iov[i].iov_len;
|
||||
size_t m = (n + m1 <= sz) ? m1 : sz - n;
|
||||
fwrite (msghdr->msg_iov[i].iov_base, m, 1, fp);
|
||||
(void) fwrite (msghdr->msg_iov[i].iov_base, m, 1, fp);
|
||||
n += m;
|
||||
}
|
||||
assert (n == sz);
|
||||
|
@ -142,20 +142,20 @@ void write_pcap_received (struct q_globals *gv, nn_wctime_t tstamp, const struct
|
|||
ddsrt_mutex_lock (&gv->pcap_lock);
|
||||
wctime_to_sec_usec (&pcap_hdr.ts_sec, &pcap_hdr.ts_usec, tstamp);
|
||||
pcap_hdr.incl_len = pcap_hdr.orig_len = (uint32_t) sz_iud;
|
||||
fwrite (&pcap_hdr, sizeof (pcap_hdr), 1, gv->pcap_fp);
|
||||
(void) fwrite (&pcap_hdr, sizeof (pcap_hdr), 1, gv->pcap_fp);
|
||||
u.ipv4_hdr = ipv4_hdr_template;
|
||||
u.ipv4_hdr.totallength = ddsrt_toBE2u ((unsigned short) sz_iud);
|
||||
u.ipv4_hdr.ttl = 128;
|
||||
u.ipv4_hdr.srcip = ((struct sockaddr_in*) src)->sin_addr.s_addr;
|
||||
u.ipv4_hdr.dstip = ((struct sockaddr_in*) dst)->sin_addr.s_addr;
|
||||
u.ipv4_hdr.checksum = calc_ipv4_checksum (u.x);
|
||||
fwrite (&u.ipv4_hdr, sizeof (u.ipv4_hdr), 1, gv->pcap_fp);
|
||||
(void) fwrite (&u.ipv4_hdr, sizeof (u.ipv4_hdr), 1, gv->pcap_fp);
|
||||
udp_hdr.srcport = ((struct sockaddr_in*) src)->sin_port;
|
||||
udp_hdr.dstport = ((struct sockaddr_in*) dst)->sin_port;
|
||||
udp_hdr.length = ddsrt_toBE2u ((unsigned short) sz_ud);
|
||||
udp_hdr.checksum = 0; /* don't have to compute a checksum for UDPv4 */
|
||||
fwrite (&udp_hdr, sizeof (udp_hdr), 1, gv->pcap_fp);
|
||||
fwrite (buf, sz, 1, gv->pcap_fp);
|
||||
(void) fwrite (&udp_hdr, sizeof (udp_hdr), 1, gv->pcap_fp);
|
||||
(void) fwrite (buf, sz, 1, gv->pcap_fp);
|
||||
ddsrt_mutex_unlock (&gv->pcap_lock);
|
||||
}
|
||||
}
|
||||
|
@ -175,19 +175,19 @@ void write_pcap_sent (struct q_globals *gv, nn_wctime_t tstamp, const struct soc
|
|||
ddsrt_mutex_lock (&gv->pcap_lock);
|
||||
wctime_to_sec_usec (&pcap_hdr.ts_sec, &pcap_hdr.ts_usec, tstamp);
|
||||
pcap_hdr.incl_len = pcap_hdr.orig_len = (uint32_t) sz_iud;
|
||||
fwrite (&pcap_hdr, sizeof (pcap_hdr), 1, gv->pcap_fp);
|
||||
(void) fwrite (&pcap_hdr, sizeof (pcap_hdr), 1, gv->pcap_fp);
|
||||
u.ipv4_hdr = ipv4_hdr_template;
|
||||
u.ipv4_hdr.totallength = ddsrt_toBE2u ((unsigned short) sz_iud);
|
||||
u.ipv4_hdr.ttl = 255;
|
||||
u.ipv4_hdr.srcip = ((struct sockaddr_in*) src)->sin_addr.s_addr;
|
||||
u.ipv4_hdr.dstip = ((struct sockaddr_in*) hdr->msg_name)->sin_addr.s_addr;
|
||||
u.ipv4_hdr.checksum = calc_ipv4_checksum (u.x);
|
||||
fwrite (&u.ipv4_hdr, sizeof (u.ipv4_hdr), 1, gv->pcap_fp);
|
||||
(void) fwrite (&u.ipv4_hdr, sizeof (u.ipv4_hdr), 1, gv->pcap_fp);
|
||||
udp_hdr.srcport = ((struct sockaddr_in*) src)->sin_port;
|
||||
udp_hdr.dstport = ((struct sockaddr_in*) hdr->msg_name)->sin_port;
|
||||
udp_hdr.length = ddsrt_toBE2u ((unsigned short) sz_ud);
|
||||
udp_hdr.checksum = 0; /* don't have to compute a checksum for UDPv4 */
|
||||
fwrite (&udp_hdr, sizeof (udp_hdr), 1, gv->pcap_fp);
|
||||
(void) fwrite (&udp_hdr, sizeof (udp_hdr), 1, gv->pcap_fp);
|
||||
write_data (gv->pcap_fp, hdr, sz);
|
||||
ddsrt_mutex_unlock (&gv->pcap_lock);
|
||||
}
|
||||
|
|
|
@ -1309,6 +1309,8 @@ static const struct piddesc piddesc_omg[] = {
|
|||
PP (IDENTITY_STATUS_TOKEN, identity_status_token, XS, XQ, XbPROP, XS, XS, XSTOP, XQ, XbPROP, XS, XO, XSTOP),
|
||||
PP (DATA_TAGS, data_tags, XQ, XS, XS, XSTOP),
|
||||
#endif
|
||||
PP (DOMAIN_ID, domain_id, Xu),
|
||||
PP (DOMAIN_TAG, domain_tag, XS),
|
||||
{ PID_STATUSINFO, PDF_FUNCTION, PP_STATUSINFO, "STATUSINFO",
|
||||
offsetof (struct nn_plist, statusinfo), membersize (struct nn_plist, statusinfo),
|
||||
{ .f = { .deser = deser_statusinfo, .ser = ser_statusinfo } }, 0 },
|
||||
|
@ -1424,7 +1426,7 @@ struct piddesc_index {
|
|||
nn_plist_init_tables.
|
||||
|
||||
FIXME: should compute them at build-time */
|
||||
#define DEFAULT_PROC_ARRAY_SIZE 19
|
||||
#define DEFAULT_PROC_ARRAY_SIZE 20
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
#define DEFAULT_OMG_PIDS_ARRAY_SIZE (PID_READER_FAVOURS_SSM + 1)
|
||||
#else
|
||||
|
@ -2255,13 +2257,7 @@ static dds_return_t init_one_parameter (nn_plist_t *plist, nn_ipaddress_params_t
|
|||
return return_unrecognized_pid (plist, pid);
|
||||
assert (pid_to_index (pid) == pid_to_index (entry->pid));
|
||||
if (pid != entry->pid)
|
||||
{
|
||||
DDS_CERROR (logcfg, "error processing parameter list (vendor %u.%u, version %u.%u): pid %"PRIx16" mapped to pid %"PRIx16"\n",
|
||||
dd->vendorid.id[0], dd->vendorid.id[1],
|
||||
dd->protocol_version.major, dd->protocol_version.minor,
|
||||
pid, entry->pid);
|
||||
return return_unrecognized_pid (plist, pid);
|
||||
}
|
||||
assert (pid != PID_PAD);
|
||||
|
||||
struct flagset flagset;
|
||||
|
|
|
@ -2562,7 +2562,7 @@ struct nn_dqueue *nn_dqueue_new (const char *name, const struct q_globals *gv, u
|
|||
thrnamesz = 3 + strlen (name) + 1;
|
||||
if ((thrname = ddsrt_malloc (thrnamesz)) == NULL)
|
||||
goto fail_thrname;
|
||||
snprintf (thrname, thrnamesz, "dq.%s", name);
|
||||
(void) snprintf (thrname, thrnamesz, "dq.%s", name);
|
||||
if (create_thread (&q->ts, gv, thrname, (uint32_t (*) (void *)) dqueue_thread, q) != DDS_RETCODE_OK)
|
||||
goto fail_thread;
|
||||
ddsrt_free (thrname);
|
||||
|
@ -2675,7 +2675,7 @@ void nn_dqueue_enqueue1 (struct nn_dqueue *q, const ddsi_guid_t *rdguid, struct
|
|||
ddsrt_atomic_add32 (&q->nof_samples, 1 + (uint32_t) rres);
|
||||
if (nn_dqueue_enqueue_bubble_locked (q, b))
|
||||
ddsrt_cond_broadcast (&q->cond);
|
||||
nn_dqueue_enqueue_locked (q, sc);
|
||||
(void) nn_dqueue_enqueue_locked (q, sc);
|
||||
ddsrt_mutex_unlock (&q->lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -136,9 +136,11 @@ static int valid_AckNack (const struct receiver_state *rst, AckNack_t *msg, size
|
|||
/* Validation following 8.3.7.1.3 + 8.3.5.5 */
|
||||
if (!valid_sequence_number_set (&msg->readerSNState))
|
||||
{
|
||||
/* FastRTPS sends invalid pre-emptive ACKs -- patch the message so we can process it */
|
||||
if (! NN_STRICT_P (rst->gv->config) && vendor_is_eprosima (rst->vendor) &&
|
||||
fromSN (msg->readerSNState.bitmap_base) == 0 && msg->readerSNState.numbits == 0)
|
||||
/* FastRTPS, Connext send invalid pre-emptive ACKs -- patch the message to
|
||||
make it well-formed and process it as normal */
|
||||
if (! NN_STRICT_P (rst->gv->config) &&
|
||||
(fromSN (msg->readerSNState.bitmap_base) == 0 && msg->readerSNState.numbits == 0) &&
|
||||
(vendor_is_eprosima (rst->vendor) || vendor_is_rti (rst->vendor)))
|
||||
msg->readerSNState.bitmap_base = toSN (1);
|
||||
else
|
||||
return 0;
|
||||
|
@ -544,7 +546,7 @@ static void force_heartbeat_to_peer (struct writer *wr, const struct whc_state *
|
|||
}
|
||||
|
||||
/* Send a Heartbeat just to this peer */
|
||||
add_Heartbeat (m, wr, whcst, hbansreq, prd->e.guid.entityid, 0);
|
||||
add_Heartbeat (m, wr, whcst, hbansreq, 0, prd->e.guid.entityid, 0);
|
||||
ETRACE (wr, "force_heartbeat_to_peer: "PGUIDFMT" -> "PGUIDFMT" - queue for transmit\n",
|
||||
PGUID (wr->e.guid), PGUID (prd->e.guid));
|
||||
qxev_msg (wr->evq, m);
|
||||
|
@ -689,6 +691,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;
|
||||
struct lease *lease;
|
||||
ddsi_guid_t src, dst;
|
||||
seqno_t seqbase;
|
||||
seqno_t seq_xmit;
|
||||
|
@ -744,8 +747,8 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
|
||||
lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow);
|
||||
if ((lease = ddsrt_atomic_ldvoidp (&prd->c.proxypp->minl_auto)) != NULL)
|
||||
lease_renew (lease, tnow);
|
||||
|
||||
if (!wr->reliable) /* note: reliability can't be changed */
|
||||
{
|
||||
|
@ -1173,6 +1176,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;
|
||||
struct lease *lease;
|
||||
ddsi_guid_t src, dst;
|
||||
|
||||
src.prefix = rst->src_guid_prefix;
|
||||
|
@ -1200,14 +1204,19 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* liveliness is still only implemented partially (with all set to AUTOMATIC,
|
||||
BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
|
||||
lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
|
||||
if ((lease = ddsrt_atomic_ldvoidp (&pwr->c.proxypp->minl_auto)) != NULL)
|
||||
lease_renew (lease, tnow);
|
||||
|
||||
RSTTRACE (PGUIDFMT" -> "PGUIDFMT":", PGUID (src), PGUID (dst));
|
||||
|
||||
ddsrt_mutex_lock (&pwr->e.lock);
|
||||
|
||||
if (msg->smhdr.flags & HEARTBEAT_FLAG_LIVELINESS &&
|
||||
pwr->c.xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_TOPIC &&
|
||||
pwr->c.xqos->liveliness.lease_duration != T_NEVER)
|
||||
{
|
||||
if ((lease = ddsrt_atomic_ldvoidp (&pwr->c.proxypp->minl_man)) != NULL)
|
||||
lease_renew (lease, tnow);
|
||||
lease_renew (pwr->lease, tnow);
|
||||
}
|
||||
if (pwr->n_reliable_readers == 0)
|
||||
{
|
||||
RSTTRACE (PGUIDFMT" -> "PGUIDFMT" no-reliable-readers)", PGUID (src), PGUID (dst));
|
||||
|
@ -1347,6 +1356,7 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime
|
|||
const nn_fragment_number_t fragnum = msg->lastFragmentNum - 1; /* we do 0-based */
|
||||
ddsi_guid_t src, dst;
|
||||
struct proxy_writer *pwr;
|
||||
struct lease *lease;
|
||||
|
||||
src.prefix = rst->src_guid_prefix;
|
||||
src.entityid = msg->writerId;
|
||||
|
@ -1372,8 +1382,8 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
|
||||
lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
|
||||
if ((lease = ddsrt_atomic_ldvoidp (&pwr->c.proxypp->minl_auto)) != NULL)
|
||||
lease_renew (lease, tnow);
|
||||
|
||||
RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst));
|
||||
ddsrt_mutex_lock (&pwr->e.lock);
|
||||
|
@ -1449,7 +1459,7 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime
|
|||
samples we no longer care about) */
|
||||
int64_t delay = rst->gv->config.nack_delay;
|
||||
RSTTRACE ("/nackfrag");
|
||||
resched_xevent_if_earlier (m->acknack_xevent, add_duration_to_mtime (now_mt(), delay));
|
||||
(void) resched_xevent_if_earlier (m->acknack_xevent, add_duration_to_mtime (now_mt(), delay));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1463,6 +1473,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N
|
|||
struct proxy_reader *prd;
|
||||
struct wr_prd_match *rn;
|
||||
struct writer *wr;
|
||||
struct lease *lease;
|
||||
struct whc_borrowed_sample sample;
|
||||
ddsi_guid_t src, dst;
|
||||
nn_count_t *countp;
|
||||
|
@ -1505,8 +1516,8 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
|
||||
lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow);
|
||||
if ((lease = ddsrt_atomic_ldvoidp (&prd->c.proxypp->minl_auto)) != NULL)
|
||||
lease_renew (lease, tnow);
|
||||
|
||||
if (!wr->reliable) /* note: reliability can't be changed */
|
||||
{
|
||||
|
@ -1720,6 +1731,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;
|
||||
struct lease *lease;
|
||||
ddsi_guid_t src, dst;
|
||||
seqno_t gapstart, listbase;
|
||||
int32_t last_included_rel;
|
||||
|
@ -1759,8 +1771,8 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
|
||||
lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
|
||||
if ((lease = ddsrt_atomic_ldvoidp (&pwr->c.proxypp->minl_auto)) != NULL)
|
||||
lease_renew (lease, tnow);
|
||||
|
||||
ddsrt_mutex_lock (&pwr->e.lock);
|
||||
if ((wn = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, &dst)) == NULL)
|
||||
|
@ -2220,11 +2232,13 @@ static void clean_defrag (struct proxy_writer *pwr)
|
|||
nn_defrag_notegap (pwr->defrag, 1, seq);
|
||||
}
|
||||
|
||||
static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_DataFrag_common_t *msg, const struct nn_rsample_info *sampleinfo, uint32_t fragnum, struct nn_rdata *rdata, struct nn_dqueue **deferred_wakeup)
|
||||
static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_DataFrag_common_t *msg, const struct nn_rsample_info *sampleinfo,
|
||||
uint32_t fragnum, struct nn_rdata *rdata, struct nn_dqueue **deferred_wakeup, bool renew_manbypp_lease)
|
||||
{
|
||||
struct proxy_writer *pwr;
|
||||
struct nn_rsample *rsample;
|
||||
ddsi_guid_t dst;
|
||||
struct lease *lease;
|
||||
|
||||
dst.prefix = rst->dst_guid_prefix;
|
||||
dst.entityid = msg->readerId;
|
||||
|
@ -2239,14 +2253,28 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct
|
|||
return;
|
||||
}
|
||||
|
||||
/* liveliness is still only implemented partially (with all set to
|
||||
AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy
|
||||
participant's lease. */
|
||||
lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
|
||||
/* Proxy participant's "automatic" lease has to be renewed always, manual-by-participant one only
|
||||
for data published by the application. If pwr->lease exists, it is in some manual lease mode,
|
||||
so check whether it is actually in manual-by-topic mode before renewing it. As pwr->lease is
|
||||
set once (during entity creation) we can read it outside the lock, keeping all the lease
|
||||
renewals together. */
|
||||
if ((lease = ddsrt_atomic_ldvoidp (&pwr->c.proxypp->minl_auto)) != NULL)
|
||||
lease_renew (lease, tnow);
|
||||
if ((lease = ddsrt_atomic_ldvoidp (&pwr->c.proxypp->minl_man)) != NULL && renew_manbypp_lease)
|
||||
lease_renew (lease, tnow);
|
||||
if (pwr->lease && pwr->c.xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_TOPIC)
|
||||
lease_renew (pwr->lease, tnow);
|
||||
|
||||
/* Shouldn't lock the full writer, but will do so for now */
|
||||
ddsrt_mutex_lock (&pwr->e.lock);
|
||||
|
||||
/* A change in transition from not-alive to alive is relatively complicated
|
||||
and may involve temporarily unlocking the proxy writer during the process
|
||||
(to avoid unnecessarily holding pwr->e.lock while invoking listeners on
|
||||
the reader) */
|
||||
if (!pwr->alive)
|
||||
proxy_writer_set_alive_may_unlock (pwr, true);
|
||||
|
||||
/* Don't accept data when reliable readers exist and we haven't yet seen
|
||||
a heartbeat telling us what the "current" sequence number of the writer
|
||||
is. If no reliable readers are present, we can't request a heartbeat and
|
||||
|
@ -2347,7 +2375,10 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct
|
|||
/* Enqueue or deliver with pwr->e.lock held: to ensure no other
|
||||
receive thread's data gets interleaved -- arguably delivery
|
||||
needn't be exactly in-order, which would allow us to do this
|
||||
without pwr->e.lock held. */
|
||||
without pwr->e.lock held.
|
||||
Note that PMD is also handled here, but the pwr for PMD does not
|
||||
use no synchronous delivery, so deliver_user_data_synchronously
|
||||
(which asserts pwr is not built-in) is not used for PMD handling. */
|
||||
if (pwr->deliver_synchronously)
|
||||
{
|
||||
/* FIXME: just in case the synchronous delivery runs into a delay caused
|
||||
|
@ -2529,25 +2560,36 @@ static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_r
|
|||
unsigned submsg_offset, payload_offset;
|
||||
submsg_offset = (unsigned) ((unsigned char *) msg - NN_RMSG_PAYLOAD (rmsg));
|
||||
if (datap)
|
||||
{
|
||||
payload_offset = (unsigned) ((unsigned char *) datap - NN_RMSG_PAYLOAD (rmsg));
|
||||
}
|
||||
else
|
||||
{
|
||||
payload_offset = submsg_offset + (unsigned) size;
|
||||
}
|
||||
|
||||
rdata = nn_rdata_new (rmsg, 0, sampleinfo->size, submsg_offset, payload_offset);
|
||||
|
||||
if ((msg->x.writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) ||
|
||||
(msg->x.writerId.u == NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER))
|
||||
/* SPDP needs special treatment: there are no proxy writers for it
|
||||
and we accept data from unknown sources */
|
||||
if ((msg->x.writerId.u & NN_ENTITYID_SOURCE_MASK) == NN_ENTITYID_SOURCE_BUILTIN)
|
||||
{
|
||||
handle_SPDP (sampleinfo, rdata);
|
||||
bool renew_manbypp_lease = true;
|
||||
switch (msg->x.writerId.u)
|
||||
{
|
||||
case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER:
|
||||
/* fall through */
|
||||
case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER:
|
||||
/* SPDP needs special treatment: there are no proxy writers for it and we accept data from unknown sources */
|
||||
handle_SPDP (sampleinfo, rdata);
|
||||
break;
|
||||
case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER:
|
||||
/* fall through */
|
||||
case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER:
|
||||
/* Handle PMD as a regular message, but without renewing the leases on proxypp */
|
||||
renew_manbypp_lease = false;
|
||||
/* fall through */
|
||||
default:
|
||||
handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, ~0u, rdata, deferred_wakeup, renew_manbypp_lease);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, ~0u, rdata, deferred_wakeup);
|
||||
handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, ~0u, rdata, deferred_wakeup, true);
|
||||
}
|
||||
}
|
||||
RSTTRACE (")");
|
||||
|
@ -2583,13 +2625,23 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct
|
|||
struct nn_rdata *rdata;
|
||||
unsigned submsg_offset, payload_offset;
|
||||
uint32_t begin, endp1;
|
||||
if ((msg->x.writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) ||
|
||||
(msg->x.writerId.u == NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER))
|
||||
bool renew_manbypp_lease = true;
|
||||
if ((msg->x.writerId.u & NN_ENTITYID_SOURCE_MASK) == NN_ENTITYID_SOURCE_BUILTIN)
|
||||
{
|
||||
DDS_CWARNING (&rst->gv->logconfig, "DATAFRAG("PGUIDFMT" #%"PRId64" -> "PGUIDFMT") - fragmented builtin data not yet supported\n",
|
||||
PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, fromSN (msg->x.writerSN),
|
||||
PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u);
|
||||
return 1;
|
||||
switch (msg->x.writerId.u)
|
||||
{
|
||||
case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER:
|
||||
/* fall through */
|
||||
case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER:
|
||||
DDS_CWARNING (&rst->gv->logconfig, "DATAFRAG("PGUIDFMT" #%"PRId64" -> "PGUIDFMT") - fragmented builtin data not yet supported\n",
|
||||
PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, fromSN (msg->x.writerSN),
|
||||
PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u);
|
||||
return 1;
|
||||
case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER:
|
||||
/* fall through */
|
||||
case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER:
|
||||
renew_manbypp_lease = false;
|
||||
}
|
||||
}
|
||||
|
||||
submsg_offset = (unsigned) ((unsigned char *) msg - NN_RMSG_PAYLOAD (rmsg));
|
||||
|
@ -2630,7 +2682,7 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct
|
|||
wrong, it'll simply generate a request for retransmitting a
|
||||
non-existent fragment. The other side SHOULD be capable of
|
||||
dealing with that. */
|
||||
handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, msg->fragmentStartingNum + msg->fragmentsInSubmessage - 2, rdata, deferred_wakeup);
|
||||
handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, msg->fragmentStartingNum + msg->fragmentsInSubmessage - 2, rdata, deferred_wakeup, renew_manbypp_lease);
|
||||
}
|
||||
RSTTRACE (")");
|
||||
return 1;
|
||||
|
@ -3120,12 +3172,14 @@ static bool do_packet (struct thread_state1 * const ts1, struct q_globals *gv, d
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DDSRT_STATIC_ASSERT (sizeof (struct nn_rmsg) == offsetof (struct nn_rmsg, chunk) + sizeof (struct nn_rmsg_chunk));
|
||||
buff = (unsigned char *) NN_RMSG_PAYLOAD (rmsg);
|
||||
hdr = (Header_t*) buff;
|
||||
|
||||
if (conn->m_stream)
|
||||
{
|
||||
MsgLen_t * ml = (MsgLen_t*) (buff + RTPS_MESSAGE_HEADER_SIZE);
|
||||
MsgLen_t * ml = (MsgLen_t*) (hdr + 1);
|
||||
|
||||
/*
|
||||
Read in packet header to get size of packet in MsgLen_t, then read in
|
||||
|
|
|
@ -704,8 +704,8 @@ void os_sockWaitsetFree (os_sockWaitset ws)
|
|||
closesocket (ws->pipe[0]);
|
||||
closesocket (ws->pipe[1]);
|
||||
#elif !defined(LWIP_SOCKET)
|
||||
close (ws->pipe[0]);
|
||||
close (ws->pipe[1]);
|
||||
(void) close (ws->pipe[0]);
|
||||
(void) close (ws->pipe[1]);
|
||||
#endif
|
||||
#if defined(__VXWORKS__) && defined(__RTP__)
|
||||
pipeDevDelete ((char*) &nameBuf, 0);
|
||||
|
|
|
@ -251,7 +251,7 @@ static struct thread_state1 *init_thread_state (const char *tname, const struct
|
|||
ts = &thread_states.ts[cand];
|
||||
ddsrt_atomic_stvoidp (&ts->gv, (struct q_globals *) gv);
|
||||
assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts->vtime)));
|
||||
ddsrt_strlcpy (ts->name, tname, sizeof (ts->name));
|
||||
(void) ddsrt_strlcpy (ts->name, tname, sizeof (ts->name));
|
||||
ts->state = state;
|
||||
|
||||
return ts;
|
||||
|
|
|
@ -123,7 +123,7 @@ void writer_hbcontrol_note_asyncwrite (struct writer *wr, nn_mtime_t tnow)
|
|||
least one unacked msg if there are reliable readers, so must
|
||||
have a heartbeat scheduled. Do so now */
|
||||
hbc->tsched = tnext;
|
||||
resched_xevent_if_earlier (wr->heartbeat_xevent, tnext);
|
||||
(void) resched_xevent_if_earlier (wr->heartbeat_xevent, tnext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,7 +197,7 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru
|
|||
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
||||
nn_xmsg_setencoderid (msg, wr->partition_id);
|
||||
#endif
|
||||
add_Heartbeat (msg, wr, whcst, hbansreq, to_entityid (NN_ENTITYID_UNKNOWN), issync);
|
||||
add_Heartbeat (msg, wr, whcst, hbansreq, 0, to_entityid (NN_ENTITYID_UNKNOWN), issync);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -218,7 +218,7 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru
|
|||
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
||||
nn_xmsg_setencoderid (msg, wr->partition_id);
|
||||
#endif
|
||||
add_Heartbeat (msg, wr, whcst, hbansreq, prd_guid->entityid, issync);
|
||||
add_Heartbeat (msg, wr, whcst, hbansreq, 0, prd_guid->entityid, issync);
|
||||
}
|
||||
|
||||
/* It is possible that the encoding removed the submessage(s). */
|
||||
|
@ -352,7 +352,7 @@ struct nn_xmsg *writer_hbcontrol_p2p(struct writer *wr, const struct whc_state *
|
|||
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
||||
nn_xmsg_setencoderid (msg, wr->partition_id);
|
||||
#endif
|
||||
add_Heartbeat (msg, wr, whcst, hbansreq, prd->e.guid.entityid, 1);
|
||||
add_Heartbeat (msg, wr, whcst, hbansreq, 0, prd->e.guid.entityid, 1);
|
||||
|
||||
if (nn_xmsg_size(msg) == 0)
|
||||
{
|
||||
|
@ -364,7 +364,7 @@ struct nn_xmsg *writer_hbcontrol_p2p(struct writer *wr, const struct whc_state *
|
|||
}
|
||||
#endif
|
||||
|
||||
void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_state *whcst, int hbansreq, ddsi_entityid_t dst, int issync)
|
||||
void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_state *whcst, int hbansreq, int hbliveliness, ddsi_entityid_t dst, int issync)
|
||||
{
|
||||
struct q_globals const * const gv = wr->e.gv;
|
||||
struct nn_xmsg_marker sm_marker;
|
||||
|
@ -375,6 +375,7 @@ void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_sta
|
|||
|
||||
assert (wr->reliable);
|
||||
assert (hbansreq >= 0);
|
||||
assert (hbliveliness >= 0);
|
||||
|
||||
if (gv->config.meas_hb_to_ack_latency)
|
||||
{
|
||||
|
@ -388,6 +389,8 @@ void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_sta
|
|||
|
||||
if (!hbansreq)
|
||||
hb->smhdr.flags |= HEARTBEAT_FLAG_FINAL;
|
||||
if (hbliveliness)
|
||||
hb->smhdr.flags |= HEARTBEAT_FLAG_LIVELINESS;
|
||||
|
||||
hb->readerId = nn_hton_entityid (dst);
|
||||
hb->writerId = nn_hton_entityid (wr->e.guid.entityid);
|
||||
|
@ -736,6 +739,34 @@ static void create_HeartbeatFrag (struct writer *wr, seqno_t seq, unsigned fragn
|
|||
}
|
||||
}
|
||||
|
||||
dds_return_t write_hb_liveliness (struct q_globals * const gv, struct ddsi_guid *wr_guid, struct nn_xpack *xp)
|
||||
{
|
||||
struct nn_xmsg *msg = NULL;
|
||||
struct whc_state whcst;
|
||||
struct thread_state1 * const ts1 = lookup_thread_state ();
|
||||
thread_state_awake (ts1, gv);
|
||||
struct writer *wr = ephash_lookup_writer_guid (gv->guid_hash, wr_guid);
|
||||
if (wr == NULL)
|
||||
{
|
||||
GVTRACE ("write_hb_liveliness("PGUIDFMT") - writer not found\n", PGUID (*wr_guid));
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
}
|
||||
if ((msg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid, wr->c.pp, sizeof (InfoTS_t) + sizeof (Heartbeat_t), NN_XMSG_KIND_CONTROL)) == NULL)
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
ddsrt_mutex_lock (&wr->e.lock);
|
||||
nn_xmsg_setdstN (msg, wr->as, wr->as_group);
|
||||
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
||||
nn_xmsg_setencoderid (msg, wr->partition_id);
|
||||
#endif
|
||||
whc_get_state (wr->whc, &whcst);
|
||||
add_Heartbeat (msg, wr, &whcst, 0, 1, to_entityid (NN_ENTITYID_UNKNOWN), 1);
|
||||
ddsrt_mutex_unlock (&wr->e.lock);
|
||||
nn_xpack_addmsg (xp, msg, 0);
|
||||
nn_xpack_send (xp, true);
|
||||
thread_state_asleep (ts1);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int must_skip_frag (const char *frags_to_skip, unsigned frag)
|
||||
{
|
||||
|
|
|
@ -37,10 +37,12 @@
|
|||
#include "dds/ddsi/q_bitset.h"
|
||||
#include "dds/ddsi/q_lease.h"
|
||||
#include "dds/ddsi/q_xmsg.h"
|
||||
#include "dds/ddsi/q_entity.h"
|
||||
#include "dds/ddsi/ddsi_serdata.h"
|
||||
#include "dds/ddsi/ddsi_serdata_default.h"
|
||||
#include "dds/ddsi/ddsi_security_omg.h"
|
||||
#include "dds/ddsi/ddsi_tkmap.h"
|
||||
#include "dds/ddsi/ddsi_pmd.h"
|
||||
#include "dds__whc.h"
|
||||
|
||||
#include "dds/ddsi/sysdeps.h"
|
||||
|
@ -715,7 +717,7 @@ static void handle_xevk_heartbeat (struct nn_xpack *xp, struct xevent *ev, nn_mt
|
|||
ddsrt_avl_is_empty (&wr->readers) ? (seqno_t) -1 : ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->min_seq,
|
||||
ddsrt_avl_is_empty (&wr->readers) || ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->all_have_replied_to_hb ? "" : "!",
|
||||
whcst.max_seq, writer_read_seq_xmit (wr));
|
||||
resched_xevent_if_earlier (ev, t_next);
|
||||
(void) resched_xevent_if_earlier (ev, t_next);
|
||||
wr->hbcontrol.tsched = t_next;
|
||||
ddsrt_mutex_unlock (&wr->e.lock);
|
||||
|
||||
|
@ -1013,7 +1015,7 @@ static void handle_xevk_acknack (struct nn_xpack *xp, struct xevent *ev, nn_mtim
|
|||
HEARTBEAT, I've seen too many cases of not sending an NACK
|
||||
because the writing side got confused ... Better to recover
|
||||
eventually. */
|
||||
resched_xevent_if_earlier (ev, add_duration_to_mtime (tnow, gv->config.auto_resched_nack_delay));
|
||||
(void) resched_xevent_if_earlier (ev, add_duration_to_mtime (tnow, gv->config.auto_resched_nack_delay));
|
||||
}
|
||||
GVTRACE ("send acknack(rd "PGUIDFMT" -> pwr "PGUIDFMT")\n",
|
||||
PGUID (ev->u.acknack.rd_guid), PGUID (ev->u.acknack.pwr_guid));
|
||||
|
@ -1039,7 +1041,7 @@ static void handle_xevk_acknack (struct nn_xpack *xp, struct xevent *ev, nn_mtim
|
|||
intv = 5;
|
||||
else
|
||||
intv = 10;
|
||||
resched_xevent_if_earlier (ev, add_duration_to_mtime (tnow, intv * T_SECOND));
|
||||
(void) resched_xevent_if_earlier (ev, add_duration_to_mtime (tnow, intv * T_SECOND));
|
||||
}
|
||||
ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
|
||||
|
@ -1052,7 +1054,7 @@ static void handle_xevk_acknack (struct nn_xpack *xp, struct xevent *ev, nn_mtim
|
|||
outofmem:
|
||||
/* What to do if out of memory? Crash or burn? */
|
||||
ddsrt_mutex_unlock (&pwr->e.lock);
|
||||
resched_xevent_if_earlier (ev, add_duration_to_mtime (tnow, 100 * T_MILLISECOND));
|
||||
(void) resched_xevent_if_earlier (ev, add_duration_to_mtime (tnow, 100 * T_MILLISECOND));
|
||||
}
|
||||
|
||||
static bool resend_spdp_sample_by_guid_key (struct writer *wr, const ddsi_guid_t *guid, struct proxy_reader *prd)
|
||||
|
@ -1177,7 +1179,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e
|
|||
PGUID (pp->e.guid),
|
||||
PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER,
|
||||
(double)(tnext.v - tnow.v) / 1e9);
|
||||
resched_xevent_if_earlier (ev, tnext);
|
||||
(void) resched_xevent_if_earlier (ev, tnext);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1204,48 +1206,10 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e
|
|||
PGUID (pp->e.guid),
|
||||
PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER,
|
||||
(double)(tnext.v - tnow.v) / 1e9);
|
||||
resched_xevent_if_earlier (ev, tnext);
|
||||
(void) resched_xevent_if_earlier (ev, tnext);
|
||||
}
|
||||
}
|
||||
|
||||
static void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack *xp, struct participant *pp, unsigned pmd_kind)
|
||||
{
|
||||
#define PMD_DATA_LENGTH 1
|
||||
struct q_globals * const gv = pp->e.gv;
|
||||
struct writer *wr;
|
||||
union {
|
||||
ParticipantMessageData_t pmd;
|
||||
char pad[offsetof (ParticipantMessageData_t, value) + PMD_DATA_LENGTH];
|
||||
} u;
|
||||
struct ddsi_serdata *serdata;
|
||||
struct ddsi_tkmap_instance *tk;
|
||||
|
||||
if ((wr = get_builtin_writer (pp, NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER)) == NULL)
|
||||
{
|
||||
GVTRACE ("write_pmd_message("PGUIDFMT") - builtin pmd writer not found\n", PGUID (pp->e.guid));
|
||||
return;
|
||||
}
|
||||
|
||||
u.pmd.participantGuidPrefix = nn_hton_guid_prefix (pp->e.guid.prefix);
|
||||
u.pmd.kind = ddsrt_toBE4u (pmd_kind);
|
||||
u.pmd.length = PMD_DATA_LENGTH;
|
||||
memset (u.pmd.value, 0, u.pmd.length);
|
||||
|
||||
struct ddsi_rawcdr_sample raw = {
|
||||
.blob = &u,
|
||||
.size = offsetof (ParticipantMessageData_t, value) + PMD_DATA_LENGTH,
|
||||
.key = &u.pmd,
|
||||
.keysize = 16
|
||||
};
|
||||
serdata = ddsi_serdata_from_sample (gv->rawcdr_topic, SDK_DATA, &raw);
|
||||
serdata->timestamp = now ();
|
||||
|
||||
tk = ddsi_tkmap_lookup_instance_ref (gv->m_tkmap, serdata);
|
||||
write_sample_nogc (ts1, xp, wr, serdata, tk);
|
||||
ddsi_tkmap_instance_unref (gv->m_tkmap, tk);
|
||||
#undef PMD_DATA_LENGTH
|
||||
}
|
||||
|
||||
static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_xpack *xp, struct xevent *ev, nn_mtime_t tnow)
|
||||
{
|
||||
struct q_globals * const gv = ev->evq->gv;
|
||||
|
@ -1260,16 +1224,7 @@ static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_
|
|||
|
||||
write_pmd_message (ts1, xp, pp, PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE);
|
||||
|
||||
/* QoS changes can't change lease durations. So the only thing that
|
||||
could cause trouble here is that the addition or removal of a
|
||||
writer cause the interval to change for this participant. If we
|
||||
lock pp for reading out the lease duration we are guaranteed a
|
||||
consistent value (can't assume 64-bit atomic reads on all support
|
||||
platforms!) */
|
||||
ddsrt_mutex_lock (&pp->e.lock);
|
||||
intv = pp->lease_duration;
|
||||
|
||||
/* FIXME: need to use smallest liveliness duration of all automatic-liveliness writers */
|
||||
intv = pp_get_pmd_interval (pp);
|
||||
if (intv == T_NEVER)
|
||||
{
|
||||
tnext.v = T_NEVER;
|
||||
|
@ -1286,8 +1241,7 @@ static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_
|
|||
GVTRACE ("resched pmd("PGUIDFMT"): %gs\n", PGUID (pp->e.guid), (double)(tnext.v - tnow.v) / 1e9);
|
||||
}
|
||||
|
||||
resched_xevent_if_earlier (ev, tnext);
|
||||
ddsrt_mutex_unlock (&pp->e.lock);
|
||||
(void) resched_xevent_if_earlier (ev, tnext);
|
||||
}
|
||||
|
||||
static void handle_xevk_delete_writer (UNUSED_ARG (struct nn_xpack *xp), struct xevent *ev, UNUSED_ARG (nn_mtime_t tnow))
|
||||
|
|
|
@ -1387,7 +1387,7 @@ static uint32_t nn_xpack_sendq_thread (void *vgv)
|
|||
struct nn_xpack *xp;
|
||||
if ((xp = gv->sendq_head) == NULL)
|
||||
{
|
||||
ddsrt_cond_waitfor (&gv->sendq_cond, &gv->sendq_lock, 1000000);
|
||||
(void) ddsrt_cond_waitfor (&gv->sendq_cond, &gv->sendq_lock, 1000000);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1416,7 +1416,8 @@ void nn_xpack_sendq_init (struct q_globals *gv)
|
|||
|
||||
void nn_xpack_sendq_start (struct q_globals *gv)
|
||||
{
|
||||
create_thread (&gv->sendq_ts, gv, "sendq", nn_xpack_sendq_thread, NULL);
|
||||
if (create_thread (&gv->sendq_ts, gv, "sendq", nn_xpack_sendq_thread, NULL) != DDS_RETCODE_OK)
|
||||
GVERROR ("nn_xpack_sendq_start: can't create nn_xpack_sendq_thread\n");
|
||||
}
|
||||
|
||||
void nn_xpack_sendq_stop (struct q_globals *gv)
|
||||
|
|
|
@ -70,7 +70,7 @@ static char *print_tstamp (char *buf, size_t sz, dds_time_t t)
|
|||
if (d / 1000000000 != 0)
|
||||
pos += (size_t) snprintf (buf + pos, sz - pos, "%+ds", (int) (d / 1000000000));
|
||||
if (d % 1000000000 != 0)
|
||||
snprintf (buf + pos, sz - pos, "%+dns", (int) (d % 1000000000));
|
||||
(void) snprintf (buf + pos, sz - pos, "%+dns", (int) (d % 1000000000));
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -439,7 +439,7 @@ static void print_condmask (char *buf, size_t bufsz, const dds_readcond *cond)
|
|||
pos += (size_t) snprintf (buf + pos, bufsz - pos, "%sALIVE | DISPOSED", sep);
|
||||
break;
|
||||
}
|
||||
snprintf (buf + pos, bufsz - pos, "]");
|
||||
(void) snprintf (buf + pos, bufsz - pos, "]");
|
||||
}
|
||||
|
||||
static void rdcond (struct dds_rhc *rhc, dds_readcond *cond, const struct check *chk, int max, bool print, uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2])
|
||||
|
|
|
@ -184,6 +184,19 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage
|
|||
endif()
|
||||
set(system_exists FALSE)
|
||||
|
||||
# Headers that must remain private but are required by other runtime
|
||||
# source files must be located in src/<feature>/dds/ddsrt.
|
||||
if(IS_DIRECTORY "${source_path}/${feature}/include")
|
||||
file(GLOB_RECURSE
|
||||
files
|
||||
CONFIGURE_DEPENDS
|
||||
"${source_path}/${feature}/include/*.h")
|
||||
list(APPEND headers ${files})
|
||||
target_include_directories(
|
||||
ddsrt INTERFACE
|
||||
"$<BUILD_INTERFACE:${source_path}/${feature}/include/>")
|
||||
endif()
|
||||
|
||||
# Allow custom implementations for a feature. e.g. lwip as opposed to
|
||||
# windows or posix.
|
||||
set(_system_name "${system_name}")
|
||||
|
@ -192,18 +205,6 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage
|
|||
endif()
|
||||
|
||||
foreach(system ${_system_name} posix)
|
||||
# Headers that must remain private but are required by other runtime
|
||||
# source files must be located in src/<feature>/dds/ddsrt.
|
||||
if(IS_DIRECTORY "${source_path}/${feature}/include")
|
||||
file(GLOB_RECURSE
|
||||
files
|
||||
CONFIGURE_DEPENDS
|
||||
"${source_path}/${feature}/include/*.h")
|
||||
list(APPEND headers ${files})
|
||||
target_include_directories(
|
||||
ddsrt INTERFACE
|
||||
"$<BUILD_INTERFACE:${source_path}/${feature}/include/>")
|
||||
endif()
|
||||
if(IS_DIRECTORY "${source_path}/${feature}/${system}")
|
||||
file(GLOB_RECURSE
|
||||
files
|
||||
|
|
|
@ -84,4 +84,5 @@ inline int64_t ddsrt_bswap8 (int64_t x)
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_BSWAP_H */
|
||||
#endif /* DDSRT_BSWAP_H */
|
||||
|
||||
|
|
|
@ -62,6 +62,9 @@ typedef int64_t dds_duration_t;
|
|||
/** @name Invalid time value for assigning to time output when something goes wrong */
|
||||
#define DDS_TIME_INVALID ((dds_time_t) INT64_MIN)
|
||||
|
||||
/** @name Invalid duration value */
|
||||
#define DDS_DURATION_INVALID ((dds_duration_t) INT64_MIN)
|
||||
|
||||
/** @name Macro definition for time conversion to nanoseconds
|
||||
@{**/
|
||||
#define DDS_SECS(n) ((n) * DDS_NSECS_IN_SEC)
|
||||
|
|
|
@ -42,10 +42,10 @@ static char *expand_env (const char *name, char op, const char *alt, expand_fn e
|
|||
if ((ret = ddsrt_getenv (name, &env)) == DDS_RETCODE_OK) {
|
||||
/* ok */
|
||||
} else if (strcmp (name, "$") == 0 || strcmp (name, "CYCLONEDDS_PID") == 0) {
|
||||
snprintf (idstr, sizeof (idstr), "%"PRIdPID, ddsrt_getpid ());
|
||||
(void) snprintf (idstr, sizeof (idstr), "%"PRIdPID, ddsrt_getpid ());
|
||||
env = idstr;
|
||||
} else if (strcmp (name, "CYCLONEDDS_DOMAIN_ID") == 0 && domid != UINT32_MAX) {
|
||||
snprintf (idstr, sizeof (idstr), "%"PRIu32, domid);
|
||||
(void) snprintf (idstr, sizeof (idstr), "%"PRIu32, domid);
|
||||
env = idstr;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,10 +84,12 @@ static void *ddsrt_hh_lookup_internal (const struct ddsrt_hh *rt, const uint32_t
|
|||
uint32_t hopinfo = rt->buckets[bucket].hopinfo;
|
||||
uint32_t idx;
|
||||
for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) {
|
||||
const uint32_t bidx = (bucket + idx) & idxmask;
|
||||
void *data = rt->buckets[bidx].data;
|
||||
if (data && rt->equals (data, template))
|
||||
return data;
|
||||
if (hopinfo & 1) {
|
||||
const uint32_t bidx = (bucket + idx) & idxmask;
|
||||
void *data = rt->buckets[bidx].data;
|
||||
if (data && rt->equals (data, template))
|
||||
return data;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -453,10 +455,12 @@ static void *ddsrt_chh_lookup_internal (struct ddsrt_chh_bucket_array const * co
|
|||
ddsrt_atomic_fence_ldld ();
|
||||
hopinfo = ddsrt_atomic_ld32 (&bs[bucket].hopinfo);
|
||||
for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) {
|
||||
const uint32_t bidx = (bucket + idx) & idxmask;
|
||||
void *data = ddsrt_atomic_ldvoidp (&bs[bidx].data);
|
||||
if (ddsrt_chh_data_valid_p (data) && equals (data, template)) {
|
||||
return data;
|
||||
if (hopinfo & 1) {
|
||||
const uint32_t bidx = (bucket + idx) & idxmask;
|
||||
void *data = ddsrt_atomic_ldvoidp (&bs[bidx].data);
|
||||
if (ddsrt_chh_data_valid_p (data) && equals (data, template)) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
ddsrt_atomic_fence_ldld ();
|
||||
|
|
|
@ -94,7 +94,7 @@ static enum ddsrt_iftype guess_iftype (const struct ifaddrs *sys_ifa)
|
|||
struct ifmediareq ifmr;
|
||||
enum ddsrt_iftype type;
|
||||
memset (&ifmr, 0, sizeof (ifmr));
|
||||
ddsrt_strlcpy (ifmr.ifm_name, sys_ifa->ifa_name, sizeof (ifmr.ifm_name));
|
||||
(void) ddsrt_strlcpy (ifmr.ifm_name, sys_ifa->ifa_name, sizeof (ifmr.ifm_name));
|
||||
if (ioctl (sock, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0)
|
||||
{
|
||||
type = DDSRT_IFTYPE_UNKNOWN;
|
||||
|
|
|
@ -54,7 +54,7 @@ static void default_sink (void *ptr, const dds_log_data_t *data)
|
|||
{
|
||||
if (ptr)
|
||||
{
|
||||
fwrite (data->message - data->hdrsize, 1, data->hdrsize + data->size + 1, (FILE *) ptr);
|
||||
(void) fwrite (data->message - data->hdrsize, 1, data->hdrsize + data->size + 1, (FILE *) ptr);
|
||||
fflush ((FILE *) ptr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -203,8 +203,8 @@ ddsrt_proc_create(
|
|||
if (write(exec_fds[1], &exec_err, sizeof(int)) < (ssize_t)sizeof(int)) {
|
||||
DDS_ERROR("Could not write proc error pipe.\n");
|
||||
}
|
||||
close(exec_fds[1]);
|
||||
close(exec_fds[0]);
|
||||
(void) close(exec_fds[1]);
|
||||
(void) close(exec_fds[0]);
|
||||
ddsrt_free(exec_argv);
|
||||
_exit(1);
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ ddsrt_proc_create(
|
|||
|
||||
/* Get execv result. */
|
||||
rv = DDS_RETCODE_ERROR;
|
||||
close(exec_fds[1]);
|
||||
(void) close(exec_fds[1]);
|
||||
nr = read(exec_fds[0], &exec_err, sizeof(int));
|
||||
if (nr == 0) {
|
||||
/* Pipe closed by successful execv. */
|
||||
|
@ -228,14 +228,14 @@ ddsrt_proc_create(
|
|||
rv = DDS_RETCODE_NOT_ALLOWED;
|
||||
}
|
||||
}
|
||||
close(exec_fds[0]);
|
||||
(void) close(exec_fds[0]);
|
||||
|
||||
if (rv == DDS_RETCODE_OK) {
|
||||
/* Remember child pid. */
|
||||
*pid = spawn;
|
||||
} else {
|
||||
/* Remove the failed fork pid from the system list. */
|
||||
waitpid(spawn, NULL, 0);
|
||||
(void) waitpid(spawn, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,8 +244,8 @@ ddsrt_proc_create(
|
|||
|
||||
fail_fork:
|
||||
fail_fctl:
|
||||
close(exec_fds[0]);
|
||||
close(exec_fds[1]);
|
||||
(void) close(exec_fds[0]);
|
||||
(void) close(exec_fds[1]);
|
||||
fail_pipe:
|
||||
ddsrt_free(exec_argv);
|
||||
return rv;
|
||||
|
|
|
@ -109,7 +109,7 @@ ddsrt_getrusage_anythread (
|
|||
return DDS_RETCODE_ERROR;
|
||||
if ((fp = fopen (file, "r")) == NULL)
|
||||
return DDS_RETCODE_NOT_FOUND;
|
||||
enum { ERROR, READ_HEADING, SKIP_TO_EOL, READ_VCSW, READ_IVCSW } state = READ_HEADING;
|
||||
enum { ERROR = 1, READ_HEADING, SKIP_TO_EOL, READ_VCSW, READ_IVCSW } state = READ_HEADING;
|
||||
savepos = 0;
|
||||
while (state != ERROR && (c = fgetc (fp)) != EOF)
|
||||
{
|
||||
|
|
|
@ -126,7 +126,7 @@ ddsrt_thread_setname(const char *__restrict name)
|
|||
/* Thread names are limited to 16 bytes on Linux. ERANGE is returned if the
|
||||
name exceeds the limit, so silently truncate. */
|
||||
char buf[MAXTHREADNAMESIZE + 1] = "";
|
||||
ddsrt_strlcpy(buf, name, sizeof(buf));
|
||||
(void)ddsrt_strlcpy(buf, name, sizeof(buf));
|
||||
(void)pthread_setname_np(pthread_self(), name);
|
||||
#elif defined(__APPLE__)
|
||||
(void)pthread_setname_np(name);
|
||||
|
|
|
@ -313,7 +313,7 @@ ddsrt_thread_setname(
|
|||
}
|
||||
#pragma warning(pop)
|
||||
}
|
||||
ddsrt_strlcpy (thread_name, name, sizeof (thread_name));
|
||||
(void)ddsrt_strlcpy (thread_name, name, sizeof (thread_name));
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
|
|
|
@ -36,7 +36,7 @@ struct ddsrt_xmlp_state {
|
|||
size_t cbufmax; /* allocated size of cbuf (cbufn <= cbufmax) */
|
||||
size_t cbufmark; /* NORMARKER or marker position (cbufmark <= cbufp) for rewinding */
|
||||
int eof; /* fake EOF (for treating missing close tags as EOF) */
|
||||
char *cbuf; /* parser input buffer */
|
||||
unsigned char *cbuf; /* parser input buffer */
|
||||
FILE *fp; /* file to refill cbuf from, or NULL if parsing a string */
|
||||
int line; /* current line number */
|
||||
int prevline; /* line number at last token */
|
||||
|
@ -147,7 +147,7 @@ struct ddsrt_xmlp_state *ddsrt_xmlp_new_string (const char *string, void *varg,
|
|||
st = ddsrt_malloc (sizeof (*st));
|
||||
st->cbufn = strlen (string);
|
||||
st->cbufmax = st->cbufn;
|
||||
st->cbuf = (char *) string;
|
||||
st->cbuf = (unsigned char *) string;
|
||||
st->fp = NULL;
|
||||
ddsrt_xmlp_new_common (st);
|
||||
ddsrt_xmlp_new_setCB (st, varg, cb);
|
||||
|
@ -198,7 +198,7 @@ static int make_chars_available (struct ddsrt_xmlp_state *st, size_t nmin)
|
|||
}
|
||||
}
|
||||
/* buffer is owned by caller if fp = NULL, and by us if fp != NULL */
|
||||
if (st->cbufp + st->cbufmax < nmin) {
|
||||
if (st->cbufmax < st->cbufp + nmin) {
|
||||
st->cbufmax = st->cbufp + nmin;
|
||||
st->cbuf = ddsrt_realloc (st->cbuf, st->cbufmax);
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ static void rewind_to_input_marker (struct ddsrt_xmlp_state *st)
|
|||
|
||||
static int next_char (struct ddsrt_xmlp_state *st)
|
||||
{
|
||||
char c;
|
||||
unsigned char c;
|
||||
if (!make_chars_available (st, 1)) {
|
||||
return TOK_EOF;
|
||||
}
|
||||
|
@ -459,10 +459,10 @@ static int next_token_tag_withoutclose (struct ddsrt_xmlp_state *st, char **payl
|
|||
} else {
|
||||
int tok = TOK_OPEN_TAG;
|
||||
/* pre: peek_char(st) == '<' */
|
||||
next_char (st);
|
||||
(void) next_char (st);
|
||||
if (peek_char (st) == '/') {
|
||||
tok = TOK_CLOSE_TAG;
|
||||
next_char (st);
|
||||
(void) next_char (st);
|
||||
}
|
||||
/* we only do tag names that are identifiers */
|
||||
if (peek_char (st) == '>' && (st->options & DDSRT_XMLP_ANONYMOUS_CLOSE_TAG)) {
|
||||
|
@ -500,8 +500,8 @@ static int skip_comment (struct ddsrt_xmlp_state *st)
|
|||
if (!peek_chars (st, "<!--", 1)) {
|
||||
return 0;
|
||||
}
|
||||
while ((peek_char (st) != TOK_EOF && peek_char (st) != '-') || !peek_chars (st, "-->", 0)) {
|
||||
next_char (st);
|
||||
while (peek_char (st) != TOK_EOF && (peek_char (st) != '-' || !peek_chars (st, "-->", 0))) {
|
||||
(void) next_char (st);
|
||||
}
|
||||
if (peek_chars (st, "-->", 1)) {
|
||||
return 1;
|
||||
|
@ -514,7 +514,7 @@ static void processing_instruction (struct ddsrt_xmlp_state *st, const char *end
|
|||
{
|
||||
/* just after <?; skip everything up to and include ?> */
|
||||
while (peek_char (st) != TOK_EOF && !peek_chars (st, end, 1)) {
|
||||
next_char (st);
|
||||
(void) next_char (st);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -551,7 +551,7 @@ static int next_token (struct ddsrt_xmlp_state *st, char **payload)
|
|||
st->prevline = st->line;
|
||||
do {
|
||||
while (qq_isspace (peek_char (st))) {
|
||||
next_char (st);
|
||||
(void) next_char (st);
|
||||
}
|
||||
} while ((cmt = skip_comment (st)) > 0);
|
||||
if (cmt == TOK_ERROR) {
|
||||
|
|
|
@ -25,6 +25,7 @@ list(APPEND sources
|
|||
"thread_cleanup.c"
|
||||
"string.c"
|
||||
"log.c"
|
||||
"hopscotch.c"
|
||||
"random.c"
|
||||
"retcode.c"
|
||||
"strlcpy.c"
|
||||
|
|
209
src/ddsrt/tests/hopscotch.c
Normal file
209
src/ddsrt/tests/hopscotch.c
Normal file
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include "CUnit/Test.h"
|
||||
#include "CUnit/Theory.h"
|
||||
|
||||
#include "dds/ddsrt/random.h"
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
#include "dds/ddsrt/hopscotch.h"
|
||||
|
||||
#define MAX_NKEYS 10000
|
||||
#define MAX_ITERS 1000000
|
||||
|
||||
static int nkeys_hist[MAX_NKEYS+1];
|
||||
static uint32_t objs[MAX_NKEYS], keys[MAX_NKEYS];
|
||||
static uint32_t next_v;
|
||||
static ddsrt_prng_t prng;
|
||||
|
||||
static uint32_t hash_uint32 (const void *v)
|
||||
{
|
||||
const uint64_t m = UINT64_C (10242350189706880077);
|
||||
const uint32_t h = (uint32_t) ((*((uint32_t *) v) * m) >> 32);
|
||||
return h;
|
||||
}
|
||||
|
||||
static int equals_uint32 (const void *a, const void *b)
|
||||
{
|
||||
return *((uint32_t *) a) == *((uint32_t *) b);
|
||||
}
|
||||
|
||||
static int compare_uint32 (const void *va, const void *vb)
|
||||
{
|
||||
const uint32_t *a = va;
|
||||
const uint32_t *b = vb;
|
||||
return (*a == *b) ? 0 : (*a < *b) ? -1 : 1;
|
||||
}
|
||||
|
||||
static void swap (uint32_t *a, uint32_t *b)
|
||||
{
|
||||
uint32_t t = *a;
|
||||
*a = *b;
|
||||
*b = t;
|
||||
}
|
||||
|
||||
static void init (bool random)
|
||||
{
|
||||
uint32_t i;
|
||||
ddsrt_prng_init_simple (&prng, ddsrt_random ());
|
||||
next_v = MAX_NKEYS;
|
||||
for (i = 0; i < MAX_NKEYS; i++)
|
||||
{
|
||||
nkeys_hist[i] = 0;
|
||||
keys[i] = i;
|
||||
}
|
||||
if (random)
|
||||
{
|
||||
/* Generate MAX_NKEYS unique random ints by repeatedly replacing
|
||||
duplicates with other random numbers (this'll take more time the
|
||||
larger MAX_NKEYS is, but for practical values, it is nearly
|
||||
instantaneous) */
|
||||
for (i = 0; i < MAX_NKEYS - 1; i++)
|
||||
objs[i] = ddsrt_prng_random (&prng);
|
||||
do {
|
||||
objs[i] = ddsrt_prng_random (&prng);
|
||||
qsort (objs, MAX_NKEYS, sizeof (*objs), compare_uint32);
|
||||
for (i = 1; i < MAX_NKEYS && objs[i-1] != objs[i]; i++)
|
||||
;
|
||||
} while (i < MAX_NKEYS);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < MAX_NKEYS; i++)
|
||||
objs[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
struct ops {
|
||||
const char *name;
|
||||
void * (*new) (void);
|
||||
void (*free) (void *h);
|
||||
void * (*lookup) (void *h, const void *v);
|
||||
int (*add) (void *h, const void *v);
|
||||
int (*remove) (void *h, const void *v);
|
||||
};
|
||||
|
||||
#define WRAP(ret_, f_) static ret_ f_##_w (void *h, const void *v) { return f_ (h, v); }
|
||||
WRAP(void *, ddsrt_hh_lookup);
|
||||
WRAP(int, ddsrt_hh_add);
|
||||
WRAP(int, ddsrt_hh_remove);
|
||||
WRAP(void *, ddsrt_chh_lookup);
|
||||
WRAP(int, ddsrt_chh_add);
|
||||
WRAP(int, ddsrt_chh_remove);
|
||||
WRAP(void *, ddsrt_ehh_lookup);
|
||||
WRAP(int, ddsrt_ehh_add);
|
||||
WRAP(int, ddsrt_ehh_remove);
|
||||
#undef WRAP
|
||||
|
||||
static void free_buckets (void *bs, void *arg)
|
||||
{
|
||||
/* nothing to worry about because this is single threaded */
|
||||
(void) arg;
|
||||
ddsrt_free (bs);
|
||||
}
|
||||
|
||||
static void *hhnew (void) { return ddsrt_hh_new (1, hash_uint32, equals_uint32); }
|
||||
static void hhfree (void *h) { ddsrt_hh_free (h); }
|
||||
static void *chhnew (void) { return ddsrt_chh_new (1, hash_uint32, equals_uint32, free_buckets, NULL); }
|
||||
static void chhfree (void *h) { ddsrt_chh_free (h); }
|
||||
static void *ehhnew (void) { return ddsrt_ehh_new (sizeof (uint32_t), 1, hash_uint32, equals_uint32); }
|
||||
static void ehhfree (void *h) { ddsrt_ehh_free (h); }
|
||||
|
||||
static const struct ops hhops = {
|
||||
.name = "hh",
|
||||
.new = hhnew,
|
||||
.free = hhfree,
|
||||
.lookup = ddsrt_hh_lookup_w,
|
||||
.add = ddsrt_hh_add_w,
|
||||
.remove = ddsrt_hh_remove_w
|
||||
};
|
||||
static const struct ops chhops = {
|
||||
.name = "chh",
|
||||
.new = chhnew,
|
||||
.free = chhfree,
|
||||
.lookup = ddsrt_chh_lookup_w,
|
||||
.add = ddsrt_chh_add_w,
|
||||
.remove = ddsrt_chh_remove_w
|
||||
};
|
||||
static const struct ops ehhops = {
|
||||
.name = "ehh",
|
||||
.new = ehhnew,
|
||||
.free = ehhfree,
|
||||
.lookup = ddsrt_ehh_lookup_w,
|
||||
.add = ddsrt_ehh_add_w,
|
||||
.remove = ddsrt_ehh_remove_w
|
||||
};
|
||||
|
||||
static void adj_nop (uint32_t *v) { (void) v; }
|
||||
static void adj_seq (uint32_t *v) { *v = next_v++; }
|
||||
|
||||
typedef void (*adj_fun_t) (uint32_t *v);
|
||||
|
||||
CU_TheoryDataPoints (ddsrt_hopscotch, random) = {
|
||||
CU_DataPoints (const struct ops *, &hhops, &chhops, &ehhops, &hhops, &chhops, &ehhops),
|
||||
CU_DataPoints (bool, true, true, true, false, false, false),
|
||||
CU_DataPoints (adj_fun_t, adj_nop, adj_nop, adj_nop, adj_seq, adj_seq, adj_seq),
|
||||
CU_DataPoints (const char *, "nop", "nop", "nop", "seq", "seq", "seq")
|
||||
};
|
||||
|
||||
CU_Theory ((const struct ops *ops, bool random, adj_fun_t adj, const char *adjname), ddsrt_hopscotch, random)
|
||||
{
|
||||
printf ("%s random=%d adj=%s", ops->name, random, adjname);
|
||||
fflush (stdout);
|
||||
init (random);
|
||||
void *h = ops->new ();
|
||||
uint32_t i, nk = 0;
|
||||
uint64_t nn = 0;
|
||||
dds_time_t t0, t1;
|
||||
t0 = ddsrt_time_monotonic ();
|
||||
for (uint32_t iter = 0; iter < MAX_ITERS; iter++)
|
||||
{
|
||||
int r;
|
||||
assert (nk <= MAX_NKEYS);
|
||||
nkeys_hist[nk]++;
|
||||
if (nk == MAX_NKEYS || (nk > 0 && (ddsrt_prng_random (&prng) & 1)))
|
||||
{
|
||||
i = ddsrt_prng_random (&prng) % nk;
|
||||
if (!ops->lookup (h, &objs[keys[i]]))
|
||||
CU_FAIL_FATAL ("key not present\n");
|
||||
r = ops->remove (h, &objs[keys[i]]);
|
||||
if (!r)
|
||||
CU_FAIL_FATAL ("remove failed\n");
|
||||
if (ops->lookup (h, &objs[keys[i]]))
|
||||
CU_FAIL_FATAL ("key still present\n");
|
||||
adj (&objs[keys[i]]);
|
||||
swap (&keys[i], &keys[nk-1]);
|
||||
nk--;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = nk + (ddsrt_prng_random (&prng) % (MAX_NKEYS - nk));
|
||||
if (ops->lookup (h, &objs[keys[i]]))
|
||||
CU_FAIL_FATAL ("key already present\n");
|
||||
r = ops->add (h, &objs[keys[i]]);
|
||||
if (!r)
|
||||
CU_FAIL_FATAL ("add failed\n");
|
||||
if (!ops->lookup (h, &objs[keys[i]]))
|
||||
CU_FAIL_FATAL ("key still not present\n");
|
||||
swap (&keys[i], &keys[nk]);
|
||||
nk++;
|
||||
}
|
||||
nn++;
|
||||
}
|
||||
t1 = ddsrt_time_monotonic ();
|
||||
ops->free (h);
|
||||
printf (" %"PRIu64" %.0f ns/cycle\n", nn, (double) (t1 - t0) / (double) nn);
|
||||
}
|
|
@ -435,13 +435,13 @@ static void abort_handler (int sig)
|
|||
static void abort_log (void *arg, const dds_log_data_t *info)
|
||||
{
|
||||
(void) arg;
|
||||
ddsrt_strlcpy (abort_message, info->message, sizeof (abort_message));
|
||||
(void) ddsrt_strlcpy (abort_message, info->message, sizeof (abort_message));
|
||||
}
|
||||
|
||||
static void abort_trace (void *arg, const dds_log_data_t *info)
|
||||
{
|
||||
(void) arg;
|
||||
ddsrt_strlcpy (abort_message_trace, info->message, sizeof (abort_message_trace));
|
||||
(void) ddsrt_strlcpy (abort_message_trace, info->message, sizeof (abort_message_trace));
|
||||
}
|
||||
|
||||
CU_TheoryDataPoints(dds_log, fatal_aborts) = {
|
||||
|
@ -462,6 +462,7 @@ CU_Theory((bool local, int mode, bool expect_in_trace), dds_log, fatal_aborts)
|
|||
#if TEST_DDS_LC_FATAL
|
||||
struct sigaction action, oldaction;
|
||||
action.sa_flags = 0;
|
||||
sigemptyset (&action.sa_mask);
|
||||
action.sa_handler = abort_handler;
|
||||
|
||||
if (sigsetjmp (abort_jmpbuf, 0) != 0)
|
||||
|
|
|
@ -157,7 +157,7 @@ CU_Test(ddsrt_sockets, gethostname)
|
|||
|
||||
sysbuf[0] = '\0';
|
||||
#if LWIP_SOCKET
|
||||
ddsrt_strlcpy(sysbuf, "localhost", sizeof(sysbuf));
|
||||
(void) ddsrt_strlcpy(sysbuf, "localhost", sizeof(sysbuf));
|
||||
#else
|
||||
int ret = gethostname(sysbuf, sizeof(sysbuf));
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
|
|
@ -45,17 +45,17 @@ include(cmake/IdlcGenerate.cmake)
|
|||
|
||||
install(
|
||||
FILES "cmake/IdlcGenerate.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/idlc"
|
||||
COMPONENT dev)
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/idlc"
|
||||
COMPONENT idlc)
|
||||
|
||||
install(
|
||||
FILES "${IDLC_SCRIPT_IN}"
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/idlc"
|
||||
COMPONENT dev)
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/idlc"
|
||||
COMPONENT idlc)
|
||||
|
||||
install(
|
||||
FILES "${IDLC_JAR}"
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/idlc"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/idlc"
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
||||
COMPONENT dev)
|
||||
COMPONENT idlc)
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xml-model href="https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd"
|
||||
schematypens="http://www.w3.org/2001/XMLSchema" ?>
|
||||
<!--
|
||||
Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
|
||||
|
@ -9,10 +12,8 @@
|
|||
|
||||
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
-->
|
||||
<CycloneDDS>
|
||||
<Domain>
|
||||
<Id>any</Id>
|
||||
</Domain>
|
||||
<CycloneDDS xmlns="https://cdds.io/config">
|
||||
<Domain Id="any">
|
||||
<General>
|
||||
<AllowMulticast>true</AllowMulticast>
|
||||
<EnableMulticastLoopback>true</EnableMulticastLoopback>
|
||||
|
@ -24,4 +25,5 @@
|
|||
<Verbosity>finest</Verbosity>
|
||||
<OutputFile>ddsi_${MPT_PROCESS_NAME}.log</OutputFile>
|
||||
</Tracing-->
|
||||
</Domain>
|
||||
</CycloneDDS>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xml-model href="https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd"
|
||||
schematypens="http://www.w3.org/2001/XMLSchema" ?>
|
||||
<!--
|
||||
Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
|
||||
|
@ -9,10 +12,8 @@
|
|||
|
||||
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
-->
|
||||
<CycloneDDS>
|
||||
<Domain>
|
||||
<Id>${DOMAIN_ID}</Id>
|
||||
</Domain>
|
||||
<CycloneDDS xmlns="https://cdds.io/config">
|
||||
<Domain Id="${DOMAIN_ID}">
|
||||
<General>
|
||||
<AllowMulticast>true</AllowMulticast>
|
||||
<EnableMulticastLoopback>true</EnableMulticastLoopback>
|
||||
|
@ -24,4 +25,5 @@
|
|||
<Verbosity>finest</Verbosity>
|
||||
<OutputFile>ddsi_${MPT_PROCESS_NAME}.log</OutputFile>
|
||||
</Tracing-->
|
||||
</Domain>
|
||||
</CycloneDDS>
|
||||
|
|
|
@ -302,8 +302,6 @@ MPT_ProcessEntry (rw_publisher,
|
|||
i, j, dds_strretcode (rc));
|
||||
if (st.current_count)
|
||||
{
|
||||
printf ("%zu %zu: %d\n", i, j, (int) st.current_count);
|
||||
fflush (stdout);
|
||||
goto have_matches;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
static char *qp_duration_str (char *buf, size_t bufsz, dds_duration_t d)
|
||||
{
|
||||
if (d == DDS_INFINITY)
|
||||
snprintf (buf, bufsz, "infinite");
|
||||
(void) snprintf (buf, bufsz, "infinite");
|
||||
else
|
||||
snprintf (buf, bufsz, "%u.%09u", (unsigned)(d / DDS_NSECS_IN_SEC), (unsigned)(d % DDS_NSECS_IN_SEC));
|
||||
(void) snprintf (buf, bufsz, "%u.%09u", (unsigned)(d / DDS_NSECS_IN_SEC), (unsigned)(d % DDS_NSECS_IN_SEC));
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -443,9 +443,9 @@ static void print_dcps_participant (FILE *fp, dds_entity_t pp)
|
|||
qp_qos (data->qos, fp);
|
||||
}
|
||||
}
|
||||
dds_return_loan (rd, ptrs, n);
|
||||
(void) dds_return_loan (rd, ptrs, n);
|
||||
}
|
||||
dds_delete (rd);
|
||||
(void) dds_delete (rd);
|
||||
}
|
||||
|
||||
static void print_dcps_endpoint (FILE *fp, dds_entity_t pp, const char *type, dds_entity_t topic)
|
||||
|
@ -472,9 +472,9 @@ static void print_dcps_endpoint (FILE *fp, dds_entity_t pp, const char *type, dd
|
|||
qp_qos (data->qos,fp);
|
||||
}
|
||||
}
|
||||
dds_return_loan (rd, ptrs, n);
|
||||
(void) dds_return_loan (rd, ptrs, n);
|
||||
}
|
||||
dds_delete (rd);
|
||||
(void) dds_delete (rd);
|
||||
}
|
||||
|
||||
static void print_dcps_subscription (FILE *fp, dds_entity_t pp)
|
||||
|
|
|
@ -180,7 +180,7 @@ bool record_cputime (struct record_cputime_state *state, const char *prefix, dds
|
|||
}
|
||||
state->tprev = tnow;
|
||||
state->s.some_above = some_above;
|
||||
dds_write (state->wr, &state->s);
|
||||
(void) dds_write (state->wr, &state->s);
|
||||
return print_cputime (&state->s, prefix, false, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,9 @@ enum topicsel {
|
|||
KS, /* KeyedSeq type: seq#, key, sequence-of-octet */
|
||||
K32, /* Keyed32 type: seq#, key, array-of-24-octet (sizeof = 32) */
|
||||
K256, /* Keyed256 type: seq#, key, array-of-248-octet (sizeof = 256) */
|
||||
OU /* OneULong type: seq# */
|
||||
OU, /* OneULong type: seq# */
|
||||
UK16, /* Unkeyed16, type: seq#, array-of-12-octet (sizeof = 16) */
|
||||
UK1024/* Unkeyed1024, type: seq#, array-of-1020-octet (sizeof = 1024) */
|
||||
};
|
||||
|
||||
enum submode {
|
||||
|
@ -317,6 +319,8 @@ union data {
|
|||
Keyed32 k32;
|
||||
Keyed256 k256;
|
||||
OneULong ou;
|
||||
Unkeyed16 uk16;
|
||||
Unkeyed1024 uk1024;
|
||||
};
|
||||
|
||||
static void verrorx (int exitcode, const char *fmt, va_list ap)
|
||||
|
@ -529,6 +533,14 @@ static void *init_sample (union data *data, uint32_t seq)
|
|||
case OU:
|
||||
data->ou.seq = seq;
|
||||
break;
|
||||
case UK16:
|
||||
data->uk16.seq = seq;
|
||||
memset (data->uk16.baggage, 0xee, sizeof (data->uk16.baggage));
|
||||
break;
|
||||
case UK1024:
|
||||
data->uk1024.seq = seq;
|
||||
memset (data->uk1024.baggage, 0xee, sizeof (data->uk1024.baggage));
|
||||
break;
|
||||
}
|
||||
return baggage;
|
||||
}
|
||||
|
@ -791,10 +803,12 @@ static uint32_t topic_payload_size (enum topicsel tp, uint32_t bgsize)
|
|||
uint32_t size = 0;
|
||||
switch (tp)
|
||||
{
|
||||
case KS: size = 12 + bgsize; break;
|
||||
case K32: size = 32; break;
|
||||
case K256: size = 256; break;
|
||||
case OU: size = 4; break;
|
||||
case KS: size = 12 + bgsize; break;
|
||||
case K32: size = 32; break;
|
||||
case K256: size = 256; break;
|
||||
case OU: size = 4; break;
|
||||
case UK16: size = 16; break;
|
||||
case UK1024: size = 1024; break;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
@ -814,13 +828,15 @@ static bool process_data (dds_entity_t rd, struct subthread_arg *arg)
|
|||
uint32_t seq = 0, keyval = 0, size = 0;
|
||||
switch (topicsel)
|
||||
{
|
||||
case KS: {
|
||||
KeyedSeq *d = (KeyedSeq *) mseq[i]; keyval = d->keyval; seq = d->seq; size = topic_payload_size (topicsel, d->baggage._length);
|
||||
case KS: {
|
||||
KeyedSeq *d = mseq[i]; keyval = d->keyval; seq = d->seq; size = topic_payload_size (topicsel, d->baggage._length);
|
||||
break;
|
||||
}
|
||||
case K32: { Keyed32 *d = (Keyed32 *) mseq[i]; keyval = d->keyval; seq = d->seq; size = topic_payload_size (topicsel, 0); } break;
|
||||
case K256: { Keyed256 *d = (Keyed256 *) mseq[i]; keyval = d->keyval; seq = d->seq; size = topic_payload_size (topicsel, 0); } break;
|
||||
case OU: { OneULong *d = (OneULong *) mseq[i]; keyval = 0; seq = d->seq; size = topic_payload_size (topicsel, 0); } break;
|
||||
case K32: { Keyed32 *d = mseq[i]; keyval = d->keyval; seq = d->seq; size = topic_payload_size (topicsel, 0); } break;
|
||||
case K256: { Keyed256 *d = mseq[i]; keyval = d->keyval; seq = d->seq; size = topic_payload_size (topicsel, 0); } break;
|
||||
case OU: { OneULong *d = mseq[i]; keyval = 0; seq = d->seq; size = topic_payload_size (topicsel, 0); } break;
|
||||
case UK16: { Unkeyed16 *d = mseq[i]; keyval = 0; seq = d->seq; size = topic_payload_size (topicsel, 0); } break;
|
||||
case UK1024: { Unkeyed1024 *d = mseq[i]; keyval = 0; seq = d->seq; size = topic_payload_size (topicsel, 0); } break;
|
||||
}
|
||||
(void) check_eseq (&eseq_admin, seq, keyval, size, iseq[i].publication_handle);
|
||||
if (iseq[i].source_timestamp & 1)
|
||||
|
@ -1659,7 +1675,7 @@ struct multiplier {
|
|||
|
||||
static const struct multiplier frequency_units[] = {
|
||||
{ "Hz", 1 },
|
||||
{ "kHz", 1024 },
|
||||
{ "kHz", 1000 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -1865,7 +1881,7 @@ int main (int argc, char *argv[])
|
|||
case 'd': {
|
||||
char *col;
|
||||
int pos;
|
||||
ddsrt_strlcpy (netload_if, optarg, sizeof (netload_if));
|
||||
(void) ddsrt_strlcpy (netload_if, optarg, sizeof (netload_if));
|
||||
if ((col = strrchr (netload_if, ':')) == NULL || col == netload_if ||
|
||||
(sscanf (col+1, "%lf%n", &netload_bw, &pos) != 1 || (col+1)[pos] != 0))
|
||||
error3 ("-d%s: expected DEVICE:BANDWIDTH\n", optarg);
|
||||
|
@ -1883,6 +1899,8 @@ int main (int argc, char *argv[])
|
|||
else if (strcmp (optarg, "K32") == 0) topicsel = K32;
|
||||
else if (strcmp (optarg, "K256") == 0) topicsel = K256;
|
||||
else if (strcmp (optarg, "OU") == 0) topicsel = OU;
|
||||
else if (strcmp (optarg, "UK16") == 0) topicsel = UK16;
|
||||
else if (strcmp (optarg, "UK1024") == 0) topicsel = UK1024;
|
||||
else error3 ("%s: unknown topic\n", optarg);
|
||||
break;
|
||||
case 'M': maxwait = atof (optarg); if (maxwait <= 0) maxwait = HUGE_VAL; break;
|
||||
|
@ -1970,10 +1988,12 @@ int main (int argc, char *argv[])
|
|||
const dds_topic_descriptor_t *tp_desc = NULL;
|
||||
switch (topicsel)
|
||||
{
|
||||
case KS: tp_suf = "KS"; tp_desc = &KeyedSeq_desc; break;
|
||||
case K32: tp_suf = "K32"; tp_desc = &Keyed32_desc; break;
|
||||
case K256: tp_suf = "K256"; tp_desc = &Keyed256_desc; break;
|
||||
case OU: tp_suf = "OU"; tp_desc = &OneULong_desc; break;
|
||||
case KS: tp_suf = "KS"; tp_desc = &KeyedSeq_desc; break;
|
||||
case K32: tp_suf = "K32"; tp_desc = &Keyed32_desc; break;
|
||||
case K256: tp_suf = "K256"; tp_desc = &Keyed256_desc; break;
|
||||
case OU: tp_suf = "OU"; tp_desc = &OneULong_desc; break;
|
||||
case UK16: tp_suf = "UK16"; tp_desc = &Unkeyed16_desc; break;
|
||||
case UK1024: tp_suf = "UK1024"; tp_desc = &Unkeyed1024_desc; break;
|
||||
}
|
||||
snprintf (tpname_data, sizeof (tpname_data), "DDSPerf%cData%s", reliable ? 'R' : 'U', tp_suf);
|
||||
snprintf (tpname_ping, sizeof (tpname_ping), "DDSPerf%cPing%s", reliable ? 'R' : 'U', tp_suf);
|
||||
|
|
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