From a6dc93ac03c83b57a317945cfc3ef165d4c7fb16 Mon Sep 17 00:00:00 2001 From: Dan Rose Date: Fri, 6 Dec 2019 21:31:06 -0600 Subject: [PATCH 01/28] Define NOMINMAX to suppress windows min/max macros Signed-off-by: Dan Rose --- src/ddsrt/include/dds/ddsrt/types/windows.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ddsrt/include/dds/ddsrt/types/windows.h b/src/ddsrt/include/dds/ddsrt/types/windows.h index 7e81bf8..1171cc7 100644 --- a/src/ddsrt/include/dds/ddsrt/types/windows.h +++ b/src/ddsrt/include/dds/ddsrt/types/windows.h @@ -16,6 +16,10 @@ #define WIN32_LEAN_AND_MEAN #endif +#ifndef NOMINMAX +#define NOMINMAX +#endif + #include #include #include From a41a6159991ace9581d7409444c2b0950032e561 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 7 Jan 2020 15:58:52 +0100 Subject: [PATCH 02/28] Remove non-standard "CM" discovery topics These topics are non-standard and not actually used anywhere in Cyclone, so it is rather silly to keep them. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_domain.c | 15 +- src/core/ddsc/tests/lifespan.c | 2 +- .../ddsi/include/dds/ddsi/q_ddsi_discovery.h | 1 - src/core/ddsi/include/dds/ddsi/q_entity.h | 13 +- src/core/ddsi/include/dds/ddsi/q_plist.h | 22 +-- src/core/ddsi/include/dds/ddsi/q_rtps.h | 6 - src/core/ddsi/src/q_ddsi_discovery.c | 139 +------------- src/core/ddsi/src/q_entity.c | 170 +++--------------- src/core/ddsi/src/q_plist.c | 12 +- src/core/ddsi/tests/plist.c | 8 +- 10 files changed, 49 insertions(+), 339 deletions(-) diff --git a/src/core/ddsc/src/dds_domain.c b/src/core/ddsc/src/dds_domain.c index 1769250..01d8085 100644 --- a/src/core/ddsc/src/dds_domain.c +++ b/src/core/ddsc/src/dds_domain.c @@ -138,20 +138,9 @@ static dds_entity_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i /* Set additional default participant properties */ char progname[50] = "UNKNOWN"; /* FIXME: once retrieving process names is back in */ - char hostname[64]; - domain->gv.default_local_plist_pp.process_id = (unsigned) ddsrt_getpid(); - domain->gv.default_local_plist_pp.present |= PP_PRISMTECH_PROCESS_ID; - domain->gv.default_local_plist_pp.exec_name = dds_string_alloc(32); - (void) snprintf (domain->gv.default_local_plist_pp.exec_name, 32, "CycloneDDS: %u", domain->gv.default_local_plist_pp.process_id); - len = (uint32_t) (13 + strlen (domain->gv.default_local_plist_pp.exec_name)); - domain->gv.default_local_plist_pp.present |= PP_PRISMTECH_EXEC_NAME; - if (ddsrt_gethostname (hostname, sizeof (hostname)) == DDS_RETCODE_OK) - { - domain->gv.default_local_plist_pp.node_name = dds_string_dup (hostname); - domain->gv.default_local_plist_pp.present |= PP_PRISMTECH_NODE_NAME; - } + len = (uint32_t) (strlen (progname) + 13); domain->gv.default_local_plist_pp.entity_name = dds_alloc (len); - (void) snprintf (domain->gv.default_local_plist_pp.entity_name, len, "%s<%u>", progname, domain->gv.default_local_plist_pp.process_id); + (void) snprintf (domain->gv.default_local_plist_pp.entity_name, len, "%s<%u>", progname, (unsigned) ddsrt_getpid ()); domain->gv.default_local_plist_pp.present |= PP_ENTITY_NAME; if (rtps_start (&domain->gv) < 0) diff --git a/src/core/ddsc/tests/lifespan.c b/src/core/ddsc/tests/lifespan.c index 7190a71..fea4079 100644 --- a/src/core/ddsc/tests/lifespan.c +++ b/src/core/ddsc/tests/lifespan.c @@ -161,4 +161,4 @@ CU_Test(ddsc_lifespan, basic, .init=lifespan_init, .fini=lifespan_fini) check_whc_state(g_writer, -1, -1); dds_delete_qos(qos); -} \ No newline at end of file +} diff --git a/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h b/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h index 9077d98..3146c89 100644 --- a/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h +++ b/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h @@ -34,7 +34,6 @@ int sedp_dispose_unregister_writer (struct writer *wr); int sedp_dispose_unregister_reader (struct reader *rd); int sedp_write_topic (struct participant *pp, const struct nn_plist *datap); -int sedp_write_cm_participant (struct participant *pp, int alive); int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const ddsi_guid_t *rdguid, void *qarg); diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index cae655a..778d5c0 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -196,7 +196,6 @@ struct participant struct entity_common e; dds_duration_t lease_duration; /* constant */ uint32_t bes; /* built-in endpoint set */ - uint32_t prismtech_bes; /* prismtech-specific extension of built-in endpoints set */ unsigned is_ddsi2_pp: 1; /* true for the "federation leader", the ddsi2 participant itself in OSPL; FIXME: probably should use this for broker mode as well ... */ struct nn_plist *plist; /* settings/QoS for this participant */ struct xevent *spdp_xevent; /* timed event for periodically publishing SPDP */ @@ -347,7 +346,6 @@ struct proxy_participant unsigned lease_expired: 1; unsigned deleting: 1; unsigned proxypp_have_spdp: 1; - unsigned proxypp_have_cm: 1; unsigned owns_lease: 1; }; @@ -645,16 +643,11 @@ void delete_local_orphan_writer (struct local_orphan_writer *wr); /* Set when this proxy participant is not to be announced on the built-in topics yet */ #define CF_PROXYPP_NO_SPDP (1 << 3) -void new_proxy_participant (struct q_globals *gv, const struct ddsi_guid *guid, unsigned bes, unsigned prismtech_bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct nn_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq); +void new_proxy_participant (struct q_globals *gv, const struct ddsi_guid *guid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct nn_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq); int delete_proxy_participant_by_guid (struct q_globals *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit); -enum update_proxy_participant_source { - UPD_PROXYPP_SPDP, - UPD_PROXYPP_CM -}; - -int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, enum update_proxy_participant_source source, nn_wctime_t timestamp); -int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, enum update_proxy_participant_source source, nn_wctime_t timestamp); +int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, nn_wctime_t timestamp); +int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, nn_wctime_t timestamp); void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct lease *newlease); void purge_proxy_participants (struct q_globals *gv, const nn_locator_t *loc, bool delete_from_as_disc); diff --git a/src/core/ddsi/include/dds/ddsi/q_plist.h b/src/core/ddsi/include/dds/ddsi/q_plist.h index 3a0c20c..930dc44 100644 --- a/src/core/ddsi/include/dds/ddsi/q_plist.h +++ b/src/core/ddsi/include/dds/ddsi/q_plist.h @@ -47,20 +47,16 @@ extern "C" { #define PP_ORIGINAL_WRITER_INFO ((uint64_t)1 << 23) #define PP_ENDPOINT_GUID ((uint64_t)1 << 24) #define PP_PRISMTECH_PARTICIPANT_VERSION_INFO ((uint64_t)1 << 26) -#define PP_PRISMTECH_NODE_NAME ((uint64_t)1 << 27) -#define PP_PRISMTECH_EXEC_NAME ((uint64_t)1 << 28) -#define PP_PRISMTECH_PROCESS_ID ((uint64_t)1 << 29) -#define PP_PRISMTECH_BUILTIN_ENDPOINT_SET ((uint64_t)1 << 33) -#define PP_PRISMTECH_TYPE_DESCRIPTION ((uint64_t)1 << 34) -#define PP_COHERENT_SET ((uint64_t)1 << 37) +#define PP_PRISMTECH_TYPE_DESCRIPTION ((uint64_t)1 << 27) +#define PP_COHERENT_SET ((uint64_t)1 << 28) #ifdef DDSI_INCLUDE_SSM -#define PP_READER_FAVOURS_SSM ((uint64_t)1 << 39) +#define PP_READER_FAVOURS_SSM ((uint64_t)1 << 29) #endif /* Security extensions. */ -#define PP_IDENTITY_TOKEN ((uint64_t)1 << 41) -#define PP_PERMISSIONS_TOKEN ((uint64_t)1 << 42) -#define PP_DOMAIN_ID ((uint64_t)1 << 43) -#define PP_DOMAIN_TAG ((uint64_t)1 << 44) +#define PP_IDENTITY_TOKEN ((uint64_t)1 << 30) +#define PP_PERMISSIONS_TOKEN ((uint64_t)1 << 31) +#define PP_DOMAIN_ID ((uint64_t)1 << 32) +#define PP_DOMAIN_TAG ((uint64_t)1 << 33) /* 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) */ @@ -150,15 +146,11 @@ typedef struct nn_plist { nn_entityid_t group_entityid; #endif uint32_t builtin_endpoint_set; - uint32_t prismtech_builtin_endpoint_set; /* int type_max_size_serialized; */ char *entity_name; nn_keyhash_t keyhash; uint32_t statusinfo; nn_prismtech_participant_version_info_t prismtech_participant_version_info; - char *node_name; - char *exec_name; - uint32_t process_id; char *type_description; nn_sequence_number_t coherent_set_seqno; #ifdef DDSI_INCLUDE_SSM diff --git a/src/core/ddsi/include/dds/ddsi/q_rtps.h b/src/core/ddsi/include/dds/ddsi/q_rtps.h index 9359e5b..544c971 100644 --- a/src/core/ddsi/include/dds/ddsi/q_rtps.h +++ b/src/core/ddsi/include/dds/ddsi/q_rtps.h @@ -44,12 +44,6 @@ typedef int64_t seqno_t; #define NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER 0x100c7 #define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER 0x200c2 #define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER 0x200c7 -#define NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER 0x142 -#define NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_READER 0x147 -#define NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER 0x242 -#define NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_READER 0x247 -#define NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER 0x342 -#define NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_READER 0x347 #define NN_ENTITYID_SOURCE_MASK 0xc0 #define NN_ENTITYID_SOURCE_USER 0x00 #define NN_ENTITYID_SOURCE_BUILTIN 0xc0 diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index e135e74..33699d6 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -236,11 +236,6 @@ int spdp_write (struct participant *pp) ps.aliased |= PP_DOMAIN_TAG; ps.domain_tag = pp->e.gv->config.domainTag; } - if (pp->prismtech_bes) - { - ps.present |= PP_PRISMTECH_BUILTIN_ENDPOINT_SET; - ps.prismtech_builtin_endpoint_set = pp->prismtech_bes; - } ps.default_unicast_locators.n = 1; ps.default_unicast_locators.first = ps.default_unicast_locators.last = &def_uni_loc_one; @@ -526,8 +521,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_ NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER | NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER; struct addrset *as_meta, *as_default; - unsigned builtin_endpoint_set; - unsigned prismtech_builtin_endpoint_set; + uint32_t builtin_endpoint_set; ddsi_guid_t privileged_pp_guid; dds_duration_t lease_duration; unsigned custom_flags = 0; @@ -555,7 +549,6 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_ so it seemed; and yet they are necessary for correct operation, so add them. */ builtin_endpoint_set = datap->builtin_endpoint_set; - prismtech_builtin_endpoint_set = (datap->present & PP_PRISMTECH_BUILTIN_ENDPOINT_SET) ? datap->prismtech_builtin_endpoint_set : 0; if (vendor_is_rti (rst->vendor) && ((builtin_endpoint_set & (NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER | @@ -570,21 +563,6 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_ NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER | NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER; } - if ((datap->present & PP_PRISMTECH_PARTICIPANT_VERSION_INFO) && - (datap->present & PP_PRISMTECH_BUILTIN_ENDPOINT_SET) && - !(datap->prismtech_participant_version_info.flags & NN_PRISMTECH_FL_PTBES_FIXED_0)) - { - /* FIXED_0 (bug 0) indicates that this is an updated version that advertises - CM readers/writers correctly (without it, we could make a reasonable guess, - but it would cause problems with cases where we would be happy with only - (say) CM participant. Have to do a backwards-compatible fix because it has - already been released with the flags all aliased to bits 0 and 1 ... */ - GVLOGDISC (" (ptbes_fixed_0 %x)", prismtech_builtin_endpoint_set); - if (prismtech_builtin_endpoint_set & NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_READER) - prismtech_builtin_endpoint_set |= NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_READER | NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_READER; - if (prismtech_builtin_endpoint_set & NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_WRITER) - prismtech_builtin_endpoint_set |= NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER | NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER; - } /* Do we know this GUID already? */ { @@ -627,7 +605,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_ GVLOGDISC ("SPDP ST0 "PGUIDFMT, PGUID (datap->participant_guid)); GVLOGDISC (proxypp->implicitly_created ? " (NEW was-implicitly-created)" : " (update)"); proxypp->implicitly_created = 0; - update_proxy_participant_plist_locked (proxypp, seq, datap, UPD_PROXYPP_SPDP, timestamp); + update_proxy_participant_plist_locked (proxypp, seq, datap, timestamp); } ddsrt_mutex_unlock (&proxypp->e.lock); return interesting; @@ -641,7 +619,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_ } } - GVLOGDISC ("SPDP ST0 "PGUIDFMT" bes %x ptbes %x NEW", PGUID (datap->participant_guid), builtin_endpoint_set, prismtech_builtin_endpoint_set); + GVLOGDISC ("SPDP ST0 "PGUIDFMT" bes %x NEW", PGUID (datap->participant_guid), builtin_endpoint_set); if (datap->present & PP_PARTICIPANT_LEASE_DURATION) { @@ -770,7 +748,6 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_ gv, &datap->participant_guid, builtin_endpoint_set, - prismtech_builtin_endpoint_set, &privileged_pp_guid, as_default, as_meta, @@ -1109,7 +1086,7 @@ static struct proxy_participant *implicitly_create_proxypp (struct q_globals *gv doing anything about (1). That means we fall back to the legacy mode of locally generating GIDs but leaving the system id unchanged if the remote is OSPL. */ actual_vendorid = (datap->present & PP_VENDORID) ? datap->vendorid : vendorid; - new_proxy_participant(gv, ppguid, 0, 0, &privguid, new_addrset(), new_addrset(), &pp_plist, T_NEVER, actual_vendorid, CF_IMPLICITLY_CREATED_PROXYPP, timestamp, seq); + new_proxy_participant(gv, ppguid, 0, &privguid, new_addrset(), new_addrset(), &pp_plist, T_NEVER, actual_vendorid, CF_IMPLICITLY_CREATED_PROXYPP, timestamp, seq); } else if (ppguid->prefix.u[0] == src_guid_prefix->u[0] && vendor_is_eclipse_or_opensplice (vendorid)) { @@ -1143,7 +1120,7 @@ static struct proxy_participant *implicitly_create_proxypp (struct q_globals *gv ddsrt_mutex_unlock (&privpp->e.lock); pp_plist.prismtech_participant_version_info.flags &= ~NN_PRISMTECH_FL_PARTICIPANT_IS_DDSI2; - new_proxy_participant (gv, ppguid, 0, 0, &privguid, as_default, as_meta, &pp_plist, T_NEVER, vendorid, CF_IMPLICITLY_CREATED_PROXYPP | CF_PROXYPP_NO_SPDP, timestamp, seq); + new_proxy_participant (gv, ppguid, 0, &privguid, as_default, as_meta, &pp_plist, T_NEVER, vendorid, CF_IMPLICITLY_CREATED_PROXYPP | CF_PROXYPP_NO_SPDP, timestamp, seq); } } @@ -1447,104 +1424,6 @@ int sedp_write_topic (struct participant *pp, const struct nn_plist *datap) } -/****************************************************************************** - *** - *** PrismTech CM data - *** - *****************************************************************************/ - -int sedp_write_cm_participant (struct participant *pp, int alive) -{ - struct writer * sedp_wr; - struct nn_xmsg *mpayload; - nn_plist_t ps; - int ret; - - if (pp->e.onlylocal) { - /* This topic is only locally available. */ - return 0; - } - - sedp_wr = get_sedp_writer (pp, NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER); - - /* The message is only a temporary thing, used only for encoding - the QoS and other settings. So the header fields aren't really - important, except that they need to be set to reasonable things - or it'll crash */ - mpayload = nn_xmsg_new (sedp_wr->e.gv->xmsgpool, &sedp_wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA); - nn_plist_init_empty (&ps); - ps.present = PP_PARTICIPANT_GUID; - ps.participant_guid = pp->e.guid; - nn_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0); - nn_plist_fini (&ps); - if (alive) - { - nn_plist_addtomsg (mpayload, pp->plist, - PP_PRISMTECH_NODE_NAME | PP_PRISMTECH_EXEC_NAME | PP_PRISMTECH_PROCESS_ID | - PP_ENTITY_NAME, - QP_PRISMTECH_ENTITY_FACTORY); - } - nn_xmsg_addpar_sentinel (mpayload); - - ETRACE (pp, "sedp: write CMParticipant ST%x for "PGUIDFMT" via "PGUIDFMT"\n", - alive ? 0 : NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER, PGUID (pp->e.guid), PGUID (sedp_wr->e.guid)); - ret = write_mpayload (sedp_wr, alive, PID_PARTICIPANT_GUID, mpayload); - nn_xmsg_free (mpayload); - return ret; -} - -static void handle_SEDP_CM (const struct receiver_state *rst, ddsi_entityid_t wr_entity_id, nn_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len) -{ - struct q_globals * const gv = rst->gv; - const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ - GVLOGDISC ("SEDP_CM ST%x", statusinfo); - assert (wr_entity_id.u == NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER); - (void) wr_entity_id; - if (data == NULL) - { - GVLOGDISC (" no payload?\n"); - return; - } - else - { - nn_plist_t decoded_data; - nn_plist_src_t src; - dds_return_t plist_ret; - src.protocol_version = rst->protocol_version; - src.vendorid = rst->vendor; - src.encoding = data->identifier; - src.buf = (unsigned char *) data + 4; - src.bufsz = len - 4; - src.strict = NN_STRICT_P (gv->config); - src.factory = gv->m_factory; - src.logconfig = &gv->logconfig; - if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) - { - if (plist_ret != DDS_RETCODE_UNSUPPORTED) - GVWARNING ("SEDP_CM (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); - return; - } - - /* ignore: dispose/unregister is tied to deleting the participant, which will take care of the dispose/unregister for us */; - if ((statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER)) == 0) - { - struct proxy_participant *proxypp; - if (!(decoded_data.present & PP_PARTICIPANT_GUID)) - GVWARNING ("SEDP_CM (vendor %u.%u): missing participant GUID\n", src.vendorid.id[0], src.vendorid.id[1]); - else - { - if ((proxypp = entidx_lookup_proxy_participant_guid (gv->entity_index, &decoded_data.participant_guid)) == NULL) - proxypp = implicitly_create_proxypp (gv, &decoded_data.participant_guid, &decoded_data, &rst->src_guid_prefix, rst->vendor, timestamp, 0); - if (proxypp != NULL) - update_proxy_participant_plist (proxypp, 0, &decoded_data, UPD_PROXYPP_CM, timestamp); - } - } - - nn_plist_fini (&decoded_data); - } - GVLOGDISC ("\n"); -} - /****************************************************************************** *****************************************************************************/ @@ -1711,13 +1590,8 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str switch (srcguid.entityid.u) { case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER: pid = PID_PARTICIPANT_GUID; break; - case NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER: - pid = PID_GROUP_GUID; - break; case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER: case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER: pid = PID_ENDPOINT_GUID; @@ -1767,9 +1641,6 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER: 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); - break; default: GVLOGDISC ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": not handled\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index f69e5b7..e887e35 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -94,10 +94,6 @@ static const unsigned builtin_writers_besmask = NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER | NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER | NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER; -static const unsigned prismtech_builtin_writers_besmask = - NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_WRITER | - NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER | - NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER; static dds_return_t new_writer_guid (struct writer **wr_out, const struct ddsi_guid *guid, const struct ddsi_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc, status_cb_t status_cb, void *status_cbarg); static dds_return_t new_reader_guid (struct reader **rd_out, const struct ddsi_guid *guid, const struct ddsi_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct ddsi_rhc *rhc, status_cb_t status_cb, void *status_cbarg); @@ -570,18 +566,16 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * /* Create built-in endpoints (note: these have no GID, and no group GUID). */ pp->bes = 0; - pp->prismtech_bes = 0; subguid.prefix = pp->e.guid.prefix; memset (&group_guid, 0, sizeof (group_guid)); - /* SPDP writer */ -#define LAST_WR_PARAMS NULL, NULL + /* SPDP writer */ /* Note: skip SEDP <=> skip SPDP because of the way ddsi_discovery.c does things currently. */ if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) { subguid.entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->spdp_endpoint_xqos, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->spdp_endpoint_xqos, whc_new(gv, 1, 1, 1), NULL, NULL); /* But we need the as_disc address set for SPDP, because we need to send it to everyone regardless of the existence of readers. */ { @@ -604,31 +598,19 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) { subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER; - - subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS); - pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_WRITER; - - subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS); - pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER; - - subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS); - pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER; } if (gv->config.do_topic_discovery) { /* TODO: make this one configurable, we don't want all participants to publish all topics (or even just those that they use themselves) */ subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER; } @@ -636,7 +618,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) { subguid.entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER; } @@ -658,21 +640,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * subguid.entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER); new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER; - - subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_READER); - new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); - pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_READER; - - subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_READER); - new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); - pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_READER; - - subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_READER); - new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); - pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_READER; - } -#undef LAST_WR_PARAMS /* If the participant doesn't have the full set of builtin writers it depends on the privileged participant, which must exist, hence @@ -682,8 +650,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * Except when the participant is only locally available. */ if (!(flags & RTPS_PF_ONLY_LOCAL)) { ddsrt_mutex_lock (&gv->privileged_pp_lock); - if ((pp->bes & builtin_writers_besmask) != builtin_writers_besmask || - (pp->prismtech_bes & prismtech_builtin_writers_besmask) != prismtech_builtin_writers_besmask) + if ((pp->bes & builtin_writers_besmask) != builtin_writers_besmask) { /* Simply crash when the privileged participant doesn't exist when it is needed. Its existence is a precondition, and this is not @@ -731,10 +698,6 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * pp->spdp_xevent = qxev_spdp (gv->xevents, add_duration_to_mtime (now_mt (), 100 * T_MILLISECOND), &pp->e.guid, NULL); } - /* Also write the CM data - this one being transient local, we only - need to write it once (or when it changes, I suppose) */ - sedp_write_cm_participant (pp, 1); - { nn_mtime_t tsched; tsched.v = (pp->lease_duration == T_NEVER) ? T_NEVER : 0; @@ -808,13 +771,6 @@ static void unref_participant (struct participant *pp, const struct ddsi_guid *g NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER, NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER, NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER, - /* PrismTech ones: */ - NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER, - NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_READER, - NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER, - NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_READER, - NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER, - NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_READER }; ddsi_guid_t stguid; @@ -833,7 +789,7 @@ static void unref_participant (struct participant *pp, const struct ddsi_guid *g ELOGDISC (pp, "unref_participant("PGUIDFMT" @ %p <- "PGUIDFMT" @ %p) user %"PRId32" builtin %"PRId32"\n", PGUID (pp->e.guid), (void*)pp, PGUID (stguid), (void*)guid_of_refing_entity, pp->user_refc, pp->builtin_refc); - if (pp->user_refc == 0 && (pp->bes != 0 || pp->prismtech_bes != 0) && !pp->builtins_deleted) + if (pp->user_refc == 0 && pp->bes != 0 && !pp->builtins_deleted) { int i; @@ -869,9 +825,6 @@ static void unref_participant (struct participant *pp, const struct ddsi_guid *g scheduled for deletion when it runs into an empty WHC */ spdp_dispose_unregister (pp); - /* We don't care, but other implementations might: */ - sedp_write_cm_participant (pp, 0); - /* If this happens to be the privileged_pp, clear it */ ddsrt_mutex_lock (&pp->e.gv->privileged_pp_lock); if (pp == pp->e.gv->privileged_pp) @@ -887,8 +840,7 @@ static void unref_participant (struct participant *pp, const struct ddsi_guid *g if (!(pp->e.onlylocal)) { - if ((pp->bes & builtin_writers_besmask) != builtin_writers_besmask || - (pp->prismtech_bes & prismtech_builtin_writers_besmask) != prismtech_builtin_writers_besmask) + if ((pp->bes & builtin_writers_besmask) != builtin_writers_besmask) { /* Participant doesn't have a full complement of built-in writers, therefore, it relies on gv.privileged_pp, and @@ -963,7 +915,7 @@ dds_return_t delete_participant (struct q_globals *gv, const struct ddsi_guid *p struct writer *get_builtin_writer (const struct participant *pp, unsigned entityid) { ddsi_guid_t bwr_guid; - unsigned bes_mask = 0, prismtech_bes_mask = 0; + uint32_t bes_mask = 0; if (pp->e.onlylocal) { return NULL; @@ -986,15 +938,6 @@ struct writer *get_builtin_writer (const struct participant *pp, unsigned entity case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER: bes_mask = NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER; break; - case NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER: - prismtech_bes_mask = NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_WRITER; - break; - case NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER: - prismtech_bes_mask = NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER; - break; - case NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER: - prismtech_bes_mask = NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER; - break; case NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER: bes_mask = NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER; break; @@ -1003,7 +946,7 @@ struct writer *get_builtin_writer (const struct participant *pp, unsigned entity return NULL; } - if ((pp->bes & bes_mask) || (pp->prismtech_bes & prismtech_bes_mask)) + if (pp->bes & bes_mask) { /* Participant has this SEDP writer => use it. */ bwr_guid.prefix = pp->e.guid.prefix; @@ -2165,25 +2108,6 @@ static ddsi_entityid_t builtin_entityid_match (ddsi_entityid_t x) res.u = NN_ENTITYID_UNKNOWN; break; - case NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_READER: - res.u = NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER; - break; - case NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER: - res.u = NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_READER; - break; - case NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_READER: - res.u = NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER; - break; - case NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER: - res.u = NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_READER; - break; - case NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_READER: - res.u = NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER; - break; - case NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER: - res.u = NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_READER; - break; - default: assert (0); } @@ -3732,22 +3656,7 @@ static void proxy_participant_remove_pwr_lease_locked (struct proxy_participant } } -void new_proxy_participant -( - struct q_globals *gv, - const struct ddsi_guid *ppguid, - unsigned bes, - unsigned prismtech_bes, - const struct ddsi_guid *privileged_pp_guid, - struct addrset *as_default, - struct addrset *as_meta, - const nn_plist_t *plist, - dds_duration_t tlease_dur, - nn_vendorid_t vendor, - unsigned custom_flags, - nn_wctime_t timestamp, - seqno_t seq -) +void new_proxy_participant (struct q_globals *gv, const struct ddsi_guid *ppguid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const nn_plist_t *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq) { /* No locking => iff all participants use unique guids, and sedp runs on a single thread, it can't go wrong. FIXME, maybe? The @@ -3768,7 +3677,6 @@ void new_proxy_participant proxypp->deleting = 0; proxypp->vendor = vendor; proxypp->bes = bes; - proxypp->prismtech_bes = prismtech_bes; proxypp->seq = seq; if (privileged_pp_guid) { proxypp->privileged_pp_guid = *privileged_pp_guid; @@ -3850,14 +3758,6 @@ void new_proxy_participant proxypp->proxypp_have_spdp = 0; else proxypp->proxypp_have_spdp = 1; - /* Non-PrismTech doesn't implement the PT extensions and therefore won't generate - a CMParticipant; if a PT peer does not implement a CMParticipant writer, then it - presumably also is a handicapped implementation (perhaps simply an old one) */ - if (!vendor_is_eclipse_or_prismtech(proxypp->vendor) || - (proxypp->bes != 0 && !(proxypp->prismtech_bes & NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_WRITER))) - proxypp->proxypp_have_cm = 1; - else - proxypp->proxypp_have_cm = 0; /* Proxy participant must be in the hash tables for new_proxy_{writer,reader} to work */ @@ -3887,13 +3787,7 @@ void new_proxy_participant LTE (PARTICIPANT_MESSAGE_DATA_WRITER, P2P, PARTICIPANT_MESSAGE_WRITER), LTE (PARTICIPANT_MESSAGE_DATA_READER, P2P, PARTICIPANT_MESSAGE_READER), TE (DISC_, TOPIC_ANNOUNCER, SEDP, TOPIC_WRITER), - TE (DISC_, TOPIC_DETECTOR, SEDP, TOPIC_READER), - PT_TE (DISC_, CM_PARTICIPANT_READER, SEDP, CM_PARTICIPANT_READER), - PT_TE (DISC_, CM_PARTICIPANT_WRITER, SEDP, CM_PARTICIPANT_WRITER), - PT_TE (DISC_, CM_PUBLISHER_READER, SEDP, CM_PUBLISHER_READER), - PT_TE (DISC_, CM_PUBLISHER_WRITER, SEDP, CM_PUBLISHER_WRITER), - PT_TE (DISC_, CM_SUBSCRIBER_READER, SEDP, CM_SUBSCRIBER_READER), - PT_TE (DISC_, CM_SUBSCRIBER_WRITER, SEDP, CM_SUBSCRIBER_WRITER) + TE (DISC_, TOPIC_DETECTOR, SEDP, TOPIC_READER) }; #undef PT_TE #undef TE @@ -3945,39 +3839,31 @@ void new_proxy_participant ddsrt_mutex_unlock (&proxypp->e.lock); } -int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, enum update_proxy_participant_source source, nn_wctime_t timestamp) +int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, nn_wctime_t timestamp) { - nn_plist_t *new_plist = ddsrt_malloc (sizeof (*new_plist)); - nn_plist_init_empty (new_plist); - nn_plist_mergein_missing (new_plist, datap, PP_PRISMTECH_NODE_NAME | PP_PRISMTECH_EXEC_NAME | PP_PRISMTECH_PROCESS_ID | PP_ENTITY_NAME, QP_USER_DATA); - nn_plist_mergein_missing (new_plist, &proxypp->e.gv->default_plist_pp, ~(uint64_t)0, ~(uint64_t)0); - if (seq > proxypp->seq) + { proxypp->seq = seq; - switch (source) - { - case UPD_PROXYPP_SPDP: - (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; - break; - - case UPD_PROXYPP_CM: - nn_plist_fini (proxypp->plist); - ddsrt_free (proxypp->plist); - proxypp->plist = new_plist; - proxypp->proxypp_have_cm = 1; - break; + struct q_globals * const gv = proxypp->e.gv; + const uint64_t pmask = PP_ENTITY_NAME; + const uint64_t qmask = QP_USER_DATA; + nn_plist_t *new_plist = ddsrt_malloc (sizeof (*new_plist)); + nn_plist_init_empty (new_plist); + nn_plist_mergein_missing (new_plist, datap, pmask, qmask); + nn_plist_mergein_missing (new_plist, &gv->default_plist_pp, ~(uint64_t)0, ~(uint64_t)0); + (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; } return 0; } -int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, enum update_proxy_participant_source source, nn_wctime_t timestamp) +int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, nn_wctime_t timestamp) { ddsrt_mutex_lock (&proxypp->e.lock); - update_proxy_participant_plist_locked (proxypp, seq, datap, source, timestamp); + update_proxy_participant_plist_locked (proxypp, seq, datap, timestamp); ddsrt_mutex_unlock (&proxypp->e.lock); return 0; } diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 6571c3f..dc2c9f0 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -1221,11 +1221,7 @@ static const struct piddesc piddesc_eclipse[] = { { PID_PAD, PDF_QOS, QP_CYCLONE_IGNORELOCAL, "CYCLONE_IGNORELOCAL", offsetof (struct nn_plist, qos.ignorelocal), membersize (struct nn_plist, qos.ignorelocal), { .desc = { XE2, XSTOP } }, 0 }, - PP (PRISMTECH_BUILTIN_ENDPOINT_SET, prismtech_builtin_endpoint_set, Xu), PP (PRISMTECH_PARTICIPANT_VERSION_INFO, prismtech_participant_version_info, Xux5, XS), - PP (PRISMTECH_EXEC_NAME, exec_name, XS), - PP (PRISMTECH_PROCESS_ID, process_id, Xu), - PP (PRISMTECH_NODE_NAME, node_name, XS), PP (PRISMTECH_TYPE_DESCRIPTION, type_description, XS), { PID_SENTINEL, 0, 0, NULL, 0, 0, { .desc = { XSTOP } }, 0 } }; @@ -1237,11 +1233,7 @@ static const struct piddesc piddesc_prismtech[] = { QP (PRISMTECH_WRITER_DATA_LIFECYCLE, writer_data_lifecycle, Xb), QP (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle, XDx2), QP (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys, XbCOND, XQ, XS, XSTOP), - PP (PRISMTECH_BUILTIN_ENDPOINT_SET, prismtech_builtin_endpoint_set, Xu), PP (PRISMTECH_PARTICIPANT_VERSION_INFO, prismtech_participant_version_info, Xux5, XS), - PP (PRISMTECH_EXEC_NAME, exec_name, XS), - PP (PRISMTECH_PROCESS_ID, process_id, Xu), - PP (PRISMTECH_NODE_NAME, node_name, XS), PP (PRISMTECH_TYPE_DESCRIPTION, type_description, XS), { PID_SENTINEL, 0, 0, NULL, 0, 0, { .desc = { XSTOP } }, 0 } }; @@ -1320,8 +1312,8 @@ static const struct piddesc_index piddesc_vendor_index[] = { /* List of entries that require unalias, fini processing; initialized by nn_plist_init_tables; will assert when table too small or too large */ -static const struct piddesc *piddesc_unalias[20]; -static const struct piddesc *piddesc_fini[20]; +static const struct piddesc *piddesc_unalias[18]; +static const struct piddesc *piddesc_fini[18]; static ddsrt_once_t table_init_control = DDSRT_ONCE_INIT; static nn_parameterid_t pid_without_flags (nn_parameterid_t pid) diff --git a/src/core/ddsi/tests/plist.c b/src/core/ddsi/tests/plist.c index 603d07a..b8e4e44 100644 --- a/src/core/ddsi/tests/plist.c +++ b/src/core/ddsi/tests/plist.c @@ -23,9 +23,8 @@ CU_Test (ddsi_plist, unalias_copy_merge) nn_plist_t p0, p0memcpy; char *p0strs[3]; nn_plist_init_empty (&p0); - p0.present = PP_PRISMTECH_PROCESS_ID | PP_ENTITY_NAME; + p0.present = PP_ENTITY_NAME; p0.aliased = PP_ENTITY_NAME; - p0.process_id = 0x12345678; p0.entity_name = "nemo"; p0.qos.present = QP_PARTITION; p0.qos.aliased = QP_PARTITION; @@ -56,7 +55,6 @@ CU_Test (ddsi_plist, unalias_copy_merge) CU_ASSERT (p1.aliased == 0); CU_ASSERT (p1.qos.present == p0.qos.present); CU_ASSERT (p1.qos.aliased == 0); - CU_ASSERT (p1.process_id == p0.process_id); CU_ASSERT (p1.entity_name != p0.entity_name); CU_ASSERT_STRING_EQUAL (p1.entity_name, p0.entity_name); CU_ASSERT (p1.qos.partition.n == p0.qos.partition.n); @@ -83,7 +81,6 @@ CU_Test (ddsi_plist, unalias_copy_merge) CU_ASSERT (p2.aliased == p2memcpy.aliased); CU_ASSERT (p2.qos.present == p0.qos.present); CU_ASSERT (p2.qos.aliased == p2memcpy.qos.aliased); - CU_ASSERT (p2.process_id == p0.process_id); CU_ASSERT (p2.entity_name == p2memcpy.entity_name); CU_ASSERT_STRING_EQUAL (p2.entity_name, "omen"); CU_ASSERT (p2.qos.partition.n == p0.qos.partition.n); @@ -101,7 +98,6 @@ CU_Test (ddsi_plist, unalias_copy_merge) CU_ASSERT (p0.aliased == 0); CU_ASSERT (p0.qos.present == p0memcpy.qos.present); CU_ASSERT (p0.qos.aliased == 0); - CU_ASSERT (p0.process_id == p0memcpy.process_id); CU_ASSERT (p0.entity_name != p0memcpy.entity_name); CU_ASSERT_STRING_EQUAL (p0.entity_name, p0memcpy.entity_name); CU_ASSERT (p0.qos.partition.n == p0memcpy.qos.partition.n); @@ -123,7 +119,6 @@ CU_Test (ddsi_plist, unalias_copy_merge) CU_ASSERT (p3.aliased == 0); CU_ASSERT (p3.qos.present == p0.qos.present); CU_ASSERT (p3.qos.aliased == 0); - CU_ASSERT (p3.process_id == p0.process_id); CU_ASSERT (p3.entity_name != p0.entity_name); CU_ASSERT_STRING_EQUAL (p3.entity_name, p0.entity_name); CU_ASSERT (p3.qos.partition.n == p0.qos.partition.n); @@ -150,7 +145,6 @@ CU_Test (ddsi_plist, unalias_copy_merge) CU_ASSERT (p4.aliased == p4memcpy.aliased); CU_ASSERT (p4.qos.present == p0.qos.present); CU_ASSERT (p4.qos.aliased == p4memcpy.qos.aliased); - CU_ASSERT (p4.process_id == p0.process_id); CU_ASSERT (p4.entity_name == p4memcpy.entity_name); CU_ASSERT_STRING_EQUAL (p4.entity_name, "omen"); CU_ASSERT (p4.qos.partition.n == p0.qos.partition.n); From 219cb6cf4fc01688f2b02013a7ccd14a08b2bf12 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 18 Dec 2019 16:19:59 +0100 Subject: [PATCH 03/28] Refactored linked list administration in rhc so that it becomes reusable Signed-off-by: Dennis Potman --- src/core/ddsc/src/dds_rhc_default.c | 115 ++++++++++--------------- src/ddsrt/CMakeLists.txt | 20 ++--- src/ddsrt/include/dds/ddsrt/circlist.h | 43 +++++++++ src/ddsrt/src/circlist.c | 84 ++++++++++++++++++ 4 files changed, 182 insertions(+), 80 deletions(-) create mode 100644 src/ddsrt/include/dds/ddsrt/circlist.h create mode 100644 src/ddsrt/src/circlist.c diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index a3922cb..15bf67d 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -30,6 +30,7 @@ #include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsrt/hopscotch.h" #include "dds/ddsrt/avl.h" +#include "dds/ddsrt/circlist.h" #include "dds/ddsi/ddsi_rhc.h" #include "dds/ddsi/q_xqos.h" #include "dds/ddsi/q_unused.h" @@ -271,8 +272,7 @@ struct rhc_instance { int32_t strength; /* "current" ownership strength */ ddsi_guid_t wr_guid; /* guid of last writer (if wr_iid != 0 then wr_guid is the corresponding guid, else undef) */ nn_wctime_t tstamp; /* source time stamp of last update */ - struct rhc_instance *next; /* next non-empty instance in arbitrary ordering */ - struct rhc_instance *prev; + struct ddsrt_circlist_elem nonempty_list; /* links non-empty instances in arbitrary ordering */ struct ddsi_tkmap_instance *tk; /* backref into TK for unref'ing */ struct rhc_sample a_sample; /* pre-allocated storage for 1 sample */ }; @@ -286,7 +286,7 @@ typedef enum rhc_store_result { struct dds_rhc_default { struct dds_rhc common; struct ddsrt_hh *instances; - struct rhc_instance *nonempty_instances; /* circular, points to most recently added one, NULL if none */ + struct ddsrt_circlist nonempty_instances; /* circular, points to most recently added one, NULL if none */ struct lwregs registrations; /* should be a global one (with lock-free lookups) */ /* Instance/Sample maximums from resource limits QoS */ @@ -494,57 +494,33 @@ static int instance_iid_eq (const void *va, const void *vb) static void add_inst_to_nonempty_list (struct dds_rhc_default *rhc, struct rhc_instance *inst) { - if (rhc->nonempty_instances == NULL) - { - inst->next = inst->prev = inst; - } - else - { - struct rhc_instance * const hd = rhc->nonempty_instances; -#ifndef NDEBUG - { - const struct rhc_instance *x = hd; - do { assert (x != inst); x = x->next; } while (x != hd); - } -#endif - inst->next = hd->next; - inst->prev = hd; - hd->next = inst; - inst->next->prev = inst; - } - rhc->nonempty_instances = inst; + ddsrt_circlist_append (&rhc->nonempty_instances, &inst->nonempty_list); rhc->n_nonempty_instances++; } static void remove_inst_from_nonempty_list (struct dds_rhc_default *rhc, struct rhc_instance *inst) { assert (inst_is_empty (inst)); -#ifndef NDEBUG - { - const struct rhc_instance *x = rhc->nonempty_instances; - assert (x); - do { if (x == inst) break; x = x->next; } while (x != rhc->nonempty_instances); - assert (x == inst); - } -#endif - - if (inst->next == inst) - { - rhc->nonempty_instances = NULL; - } - else - { - struct rhc_instance * const inst_prev = inst->prev; - struct rhc_instance * const inst_next = inst->next; - inst_prev->next = inst_next; - inst_next->prev = inst_prev; - if (rhc->nonempty_instances == inst) - rhc->nonempty_instances = inst_prev; - } + ddsrt_circlist_remove (&rhc->nonempty_instances, &inst->nonempty_list); assert (rhc->n_nonempty_instances > 0); rhc->n_nonempty_instances--; } +static struct rhc_instance *oldest_nonempty_instance (const struct dds_rhc_default *rhc) +{ + return DDSRT_FROM_CIRCLIST (struct rhc_instance, nonempty_list, ddsrt_circlist_oldest (&rhc->nonempty_instances)); +} + +static struct rhc_instance *latest_nonempty_instance (const struct dds_rhc_default *rhc) +{ + return DDSRT_FROM_CIRCLIST (struct rhc_instance, nonempty_list, ddsrt_circlist_latest (&rhc->nonempty_instances)); +} + +static struct rhc_instance *next_nonempty_instance (const struct rhc_instance *inst) +{ + return DDSRT_FROM_CIRCLIST (struct rhc_instance, nonempty_list, inst->nonempty_list.next); +} + #ifdef DDSI_INCLUDE_LIFESPAN static void drop_expired_samples (struct dds_rhc_default *rhc, struct rhc_sample *sample) { @@ -631,6 +607,7 @@ struct dds_rhc *dds_rhc_default_new_xchecks (dds_reader *reader, struct q_global lwregs_init (&rhc->registrations); ddsrt_mutex_init (&rhc->lock); rhc->instances = ddsrt_hh_new (1, instance_iid_hash, instance_iid_eq); + ddsrt_circlist_init (&rhc->nonempty_instances); rhc->topic = topic; rhc->reader = reader; rhc->tkmap = gv->m_tkmap; @@ -814,7 +791,7 @@ static void dds_rhc_default_free (struct dds_rhc_default *rhc) lifespan_fini (&rhc->lifespan); #endif ddsrt_hh_enum (rhc->instances, free_instance_rhc_free_wrap, rhc); - assert (rhc->nonempty_instances == NULL); + assert (ddsrt_circlist_isempty (&rhc->nonempty_instances)); ddsrt_hh_free (rhc->instances); lwregs_fini (&rhc->registrations); if (rhc->qcond_eval_samplebuf != NULL) @@ -1966,10 +1943,10 @@ static int dds_rhc_read_w_qminv (struct dds_rhc_default *rhc, bool lock, void ** rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, rhc->n_invsamples, rhc->n_vread, rhc->n_invread); - if (rhc->nonempty_instances) + if (!ddsrt_circlist_isempty (&rhc->nonempty_instances)) { const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0; - struct rhc_instance * inst = rhc->nonempty_instances->next; + struct rhc_instance * inst = oldest_nonempty_instance (rhc); struct rhc_instance * const end = inst; do { @@ -2055,7 +2032,7 @@ static int dds_rhc_read_w_qminv (struct dds_rhc_default *rhc, bool lock, void ** break; } } - inst = inst->next; + inst = next_nonempty_instance (inst); } while (inst != end && n < max_samples); } @@ -2083,14 +2060,14 @@ static int dds_rhc_take_w_qminv (struct dds_rhc_default *rhc, bool lock, void ** rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, rhc->n_invsamples, rhc->n_vread, rhc->n_invread); - if (rhc->nonempty_instances) + if (!ddsrt_circlist_isempty (&rhc->nonempty_instances)) { const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0; - struct rhc_instance *inst = rhc->nonempty_instances->next; + struct rhc_instance *inst = oldest_nonempty_instance (rhc); unsigned n_insts = rhc->n_nonempty_instances; while (n_insts-- > 0 && n < max_samples) { - struct rhc_instance * const inst1 = inst->next; + struct rhc_instance * const inst1 = next_nonempty_instance (inst); iid = inst->iid; if (handle == DDS_HANDLE_NIL || iid == handle) { @@ -2238,14 +2215,14 @@ static int dds_rhc_takecdr_w_qminv (struct dds_rhc_default *rhc, bool lock, stru rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, rhc->n_invsamples, rhc->n_vread, rhc->n_invread); - if (rhc->nonempty_instances) + if (!ddsrt_circlist_isempty (&rhc->nonempty_instances)) { const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0; - struct rhc_instance *inst = rhc->nonempty_instances->next; + struct rhc_instance *inst = oldest_nonempty_instance (rhc); unsigned n_insts = rhc->n_nonempty_instances; while (n_insts-- > 0 && n < max_samples) { - struct rhc_instance * const inst1 = inst->next; + struct rhc_instance * const inst1 = next_nonempty_instance (inst); iid = inst->iid; if (handle == DDS_HANDLE_NIL || iid == handle) { @@ -2454,13 +2431,14 @@ static bool dds_rhc_default_add_readcondition (struct dds_rhc_default *rhc, dds_ { /* Read condition is not cached inside the instances and samples, so it only needs to be evaluated on the non-empty instances */ - if (rhc->nonempty_instances) + if (!ddsrt_circlist_isempty (&rhc->nonempty_instances)) { - struct rhc_instance *inst = rhc->nonempty_instances; + struct rhc_instance *inst = latest_nonempty_instance (rhc); + struct rhc_instance const * const end = inst; do { trigger += rhc_get_cond_trigger (inst, cond); - inst = inst->next; - } while (inst != rhc->nonempty_instances); + inst = next_nonempty_instance (inst); + } while (inst != end); } } else @@ -2904,26 +2882,25 @@ static int rhc_check_counts_locked (struct dds_rhc_default *rhc, bool check_cond { for (i = 0, rciter = rhc->conds; i < ncheck; i++, rciter = rciter->m_next) assert (cond_match_count[i] == ddsrt_atomic_ld32 (&rciter->m_entity.m_status.m_trigger)); - } + } if (rhc->n_nonempty_instances == 0) { - assert (rhc->nonempty_instances == NULL); + assert (ddsrt_circlist_isempty (&rhc->nonempty_instances)); } else { - struct rhc_instance *prev, *end; - assert (rhc->nonempty_instances != NULL); - prev = rhc->nonempty_instances->prev; - end = rhc->nonempty_instances; - inst = rhc->nonempty_instances; + assert (!ddsrt_circlist_isempty (&rhc->nonempty_instances)); + struct ddsrt_circlist_elem const *prev = rhc->nonempty_instances.latest->prev; + inst = latest_nonempty_instance (rhc); + struct rhc_instance const * const end = inst; n_nonempty_instances = 0; do { assert (!inst_is_empty (inst)); - assert (prev->next == inst); - assert (inst->prev == prev); - prev = inst; - inst = inst->next; + assert (prev->next == &inst->nonempty_list); + assert (inst->nonempty_list.prev == prev); + prev = &inst->nonempty_list; + inst = next_nonempty_instance (inst); n_nonempty_instances++; } while (inst != end); assert (rhc->n_nonempty_instances == n_nonempty_instances); diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index b750b0c..8525a94 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -101,6 +101,10 @@ set(include_path "${CMAKE_CURRENT_SOURCE_DIR}/include") set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/src") list(APPEND headers + "${include_path}/dds/ddsrt/avl.h" + "${include_path}/dds/ddsrt/fibheap.h" + "${include_path}/dds/ddsrt/hopscotch.h" + "${include_path}/dds/ddsrt/thread_pool.h" "${include_path}/dds/ddsrt/log.h" "${include_path}/dds/ddsrt/retcode.h" "${include_path}/dds/ddsrt/attributes.h" @@ -113,7 +117,8 @@ list(APPEND headers "${include_path}/dds/ddsrt/strtol.h" "${include_path}/dds/ddsrt/types.h" "${include_path}/dds/ddsrt/countargs.h" - "${include_path}/dds/ddsrt/static_assert.h") + "${include_path}/dds/ddsrt/static_assert.h" + "${include_path}/dds/ddsrt/circlist.h") list(APPEND sources "${source_path}/bswap.c" @@ -121,21 +126,14 @@ list(APPEND sources "${source_path}/log.c" "${source_path}/retcode.c" "${source_path}/strtod.c" - "${source_path}/strtol.c") - -list(APPEND headers - "${include_path}/dds/ddsrt/avl.h" - "${include_path}/dds/ddsrt/fibheap.h" - "${include_path}/dds/ddsrt/hopscotch.h" - "${include_path}/dds/ddsrt/thread_pool.h") - -list(APPEND sources + "${source_path}/strtol.c" "${source_path}/avl.c" "${source_path}/expand_envvars.c" "${source_path}/fibheap.c" "${source_path}/hopscotch.c" "${source_path}/thread_pool.c" - "${source_path}/xmlparser.c") + "${source_path}/xmlparser.c" + "${source_path}/circlist.c") # Not every target offers the same set of features. For embedded targets the # set of features may even be different between builds. e.g. a FreeRTOS build diff --git a/src/ddsrt/include/dds/ddsrt/circlist.h b/src/ddsrt/include/dds/ddsrt/circlist.h new file mode 100644 index 0000000..3c4ca56 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/circlist.h @@ -0,0 +1,43 @@ +/* + * 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 DDSRT_CIRCLIST_H +#define DDSRT_CIRCLIST_H + +/* Circular doubly linked list implementation */ + +#include +#include +#include "dds/export.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +#define DDSRT_FROM_CIRCLIST(typ_, member_, cle_) ((typ_ *) ((char *) (cle_) - offsetof (typ_, member_))) + +struct ddsrt_circlist { + struct ddsrt_circlist_elem *latest; /* pointer to latest inserted element */ +}; + +struct ddsrt_circlist_elem { + struct ddsrt_circlist_elem *next; + struct ddsrt_circlist_elem *prev; +}; + +DDS_EXPORT void ddsrt_circlist_init (struct ddsrt_circlist *list); +DDS_EXPORT bool ddsrt_circlist_isempty (const struct ddsrt_circlist *list); +DDS_EXPORT void ddsrt_circlist_append (struct ddsrt_circlist *list, struct ddsrt_circlist_elem *elem); +DDS_EXPORT void ddsrt_circlist_remove (struct ddsrt_circlist *list, struct ddsrt_circlist_elem *elem); +DDS_EXPORT struct ddsrt_circlist_elem *ddsrt_circlist_oldest (const struct ddsrt_circlist *list); +DDS_EXPORT struct ddsrt_circlist_elem *ddsrt_circlist_latest (const struct ddsrt_circlist *list); + +#endif /* DDSRT_CIRCLIST_H */ \ No newline at end of file diff --git a/src/ddsrt/src/circlist.c b/src/ddsrt/src/circlist.c new file mode 100644 index 0000000..51159bd --- /dev/null +++ b/src/ddsrt/src/circlist.c @@ -0,0 +1,84 @@ +/* + * 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 +#include +#include +#include +#include "dds/ddsrt/circlist.h" + +void ddsrt_circlist_init (struct ddsrt_circlist *list) +{ + list->latest = NULL; +} + +bool ddsrt_circlist_isempty (const struct ddsrt_circlist *list) +{ + return list->latest == NULL; +} + +void ddsrt_circlist_append (struct ddsrt_circlist *list, struct ddsrt_circlist_elem *elem) +{ + if (list->latest == NULL) + elem->next = elem->prev = elem; + else + { + struct ddsrt_circlist_elem * const hd = list->latest; +#ifndef NDEBUG + { + const struct ddsrt_circlist_elem *x = hd; + do { assert (x != elem); x = x->next; } while (x != hd); + } +#endif + elem->next = hd->next; + elem->prev = hd; + hd->next = elem; + elem->next->prev = elem; + } + list->latest = elem; +} + +void ddsrt_circlist_remove (struct ddsrt_circlist *list, struct ddsrt_circlist_elem *elem) +{ +#ifndef NDEBUG + { + const struct ddsrt_circlist_elem *x = list->latest; + assert (x); + do { if (x == elem) break; x = x->next; } while (x != list->latest); + assert (x == elem); + } +#endif + if (elem->next == elem) + list->latest = NULL; + else + { + struct ddsrt_circlist_elem * const elem_prev = elem->prev; + struct ddsrt_circlist_elem * const elem_next = elem->next; + elem_prev->next = elem_next; + elem_next->prev = elem_prev; + if (list->latest == elem) + list->latest = elem_prev; + } +} + +struct ddsrt_circlist_elem *ddsrt_circlist_oldest (const struct ddsrt_circlist *list) +{ + assert (!ddsrt_circlist_isempty (list)); + return list->latest->next; +} + +struct ddsrt_circlist_elem *ddsrt_circlist_latest (const struct ddsrt_circlist *list) +{ + assert (!ddsrt_circlist_isempty (list)); + return list->latest; +} + + From 231cb8c9f786343cc237c792f5d8f4a8eff7d365 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 18 Dec 2019 16:22:31 +0100 Subject: [PATCH 04/28] Deadline Missed QoS implementation This commit contains the implementation of the deadline QoS for readers and writers. The description of this QoS in the DDS specification (section 2.2.3.7): "This policy is useful for cases where a Topic is expected to have each instance updated periodically. On the publishing side this setting establishes a contract that the application must meet. On the subscribing side the setting establishes a minimum requirement for the remote publishers that are expected to supply the data values." On the writer side, the deadline missed event also needs to trigger in case only local readers exist. The implementation for this inserts the sample in the writer history cache temporary, so that an instance is created in the whc. Immediately after inserting the sample, it is removed again. With the creation of the instance, the deadline missed event is created, which will take care of triggering the deadline missed callback if required. In case the instance already existed, the timer of the event is renewed. To verify the changes to the writer history cache, add an additional test to check the write history cache state. This test checks the state of the whc after writing samples by a writer with specific combinations of qos settings. The state of the whc is checked for stored samples (min/max sequence number) and the absence of unacked data, after writing samples and wait for acks by the local and/or remote readers (which is also a parameter for this test). This test is introduced as part of the deadline implementation, but its scope is wider than only the changes that were made in the whc implementation for the deadline qos. This test showed that even before the deadline support was added, whc_default_remove_acked_messages_full data was not marked as acked in case of transient-local keep-all. This resulted in data in whc that never gets in acked state. This has been fixed as well. Signed-off-by: Dennis Potman --- .travis.yml | 27 +- src/core/CMakeLists.txt | 5 + src/core/ddsc/src/dds__rhc_default.h | 5 + src/core/ddsc/src/dds__whc.h | 7 +- src/core/ddsc/src/dds__writer.h | 4 + src/core/ddsc/src/dds_reader.c | 17 +- src/core/ddsc/src/dds_rhc_default.c | 102 +++- src/core/ddsc/src/dds_whc.c | 303 +++++++---- src/core/ddsc/src/dds_writer.c | 40 +- src/core/ddsc/tests/CMakeLists.txt | 5 + src/core/ddsc/tests/Space.idl | 6 + src/core/ddsc/tests/deadline.c | 484 ++++++++++++++++++ src/core/ddsc/tests/whc.c | 279 ++++++++++ src/core/ddsi/CMakeLists.txt | 9 + .../ddsi/include/dds/ddsi/ddsi_deadline.h | 84 +++ src/core/ddsi/src/ddsi_deadline.c | 112 ++++ src/core/ddsi/src/q_entity.c | 24 +- src/core/ddsi/src/q_transmit.c | 35 +- src/core/ddsi/src/q_xevent.c | 18 +- src/core/xtests/rhc_torture/rhc_torture.c | 34 +- src/mpt/tests/qos/procs/rw.c | 4 + 21 files changed, 1417 insertions(+), 187 deletions(-) create mode 100644 src/core/ddsc/tests/deadline.c create mode 100644 src/core/ddsc/tests/whc.c create mode 100644 src/core/ddsi/include/dds/ddsi/ddsi_deadline.h create mode 100644 src/core/ddsi/src/ddsi_deadline.c diff --git a/.travis.yml b/.travis.yml index d4d10aa..f2f8ef3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -142,33 +142,33 @@ windows_vs2017: &windows_vs2017 jobs: include: - <<: *linux_gcc8 - env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, GENERATOR="Unix Makefiles", COVERITY_SCAN=true ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles", COVERITY_SCAN=true ] if: type = cron - <<: *linux_gcc8 - env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, GENERATOR="Unix Makefiles" ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ] - <<: *linux_gcc8 - env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, LIFESPAN=YES, GENERATOR="Unix Makefiles" ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ] - <<: *linux_gcc8 - env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=NO, LIFESPAN=NO, GENERATOR="Unix Makefiles" ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=NO, LIFESPAN=NO, DEADLINE=NO, GENERATOR="Unix Makefiles" ] - <<: *linux_clang - env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, GENERATOR="Unix Makefiles" ] + env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ] - <<: *linux_clang - env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, LIFESPAN=YES, GENERATOR="Unix Makefiles" ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ] - <<: *osx_xcode9 - env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=NO, LIFESPAN=YES, GENERATOR="Unix Makefiles" ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=NO, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ] if: type = cron - <<: *osx_xcode - env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=NO, LIFESPAN=YES, GENERATOR="Unix Makefiles", MACOSX_DEPLOYMENT_TARGET=10.12 ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=NO, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles", MACOSX_DEPLOYMENT_TARGET=10.12 ] - <<: *osx_xcode - env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, GENERATOR="Unix Makefiles" ] + env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ] - <<: *osx_xcode - env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, LIFESPAN=YES, GENERATOR="Unix Makefiles" ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ] - <<: *windows_vs2017 - env: [ ARCH=x86, ASAN=none, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, GENERATOR="Visual Studio 15 2017" ] + env: [ ARCH=x86, ASAN=none, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Visual Studio 15 2017" ] - <<: *windows_vs2017 - env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, GENERATOR="Visual Studio 15 2017 Win64" ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Visual Studio 15 2017 Win64" ] - <<: *windows_vs2017 - env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, LIFESPAN=YES, GENERATOR="Visual Studio 15 2017 Win64" ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Visual Studio 15 2017 Win64" ] before_script: - conan profile new default --detect @@ -200,6 +200,7 @@ script: -DUSE_SANITIZER=${ASAN} -DENABLE_SSL=${SSL} -DENABLE_LIFESPAN=${LIFESPAN} + -DENABLE_DEADLINE_MISSED=${DEADLINE} -DBUILD_TESTING=on -DWERROR=on -G "${GENERATOR}" .. diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index aba5f20..ab95de9 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -32,6 +32,11 @@ if(ENABLE_LIFESPAN) add_definitions(-DDDSI_INCLUDE_LIFESPAN) endif() +option(ENABLE_DEADLINE_MISSED "Enable Deadline Missed QoS support" ON) +if(ENABLE_DEADLINE_MISSED) + add_definitions(-DDDSI_INCLUDE_DEADLINE_MISSED) +endif() + # OpenSSL is huge, raising the RSS by 1MB or so, and moreover find_package(OpenSSL) causes # trouble on some older CMake versions that otherwise work fine, so provide an option to avoid # all OpenSSL related things. diff --git a/src/core/ddsc/src/dds__rhc_default.h b/src/core/ddsc/src/dds__rhc_default.h index 7a8a8e1..f6b2413 100644 --- a/src/core/ddsc/src/dds__rhc_default.h +++ b/src/core/ddsc/src/dds__rhc_default.h @@ -25,7 +25,12 @@ struct rhc_sample; DDS_EXPORT struct dds_rhc *dds_rhc_default_new_xchecks (dds_reader *reader, struct q_globals *gv, const struct ddsi_sertopic *topic, bool xchecks); DDS_EXPORT struct dds_rhc *dds_rhc_default_new (struct dds_reader *reader, const struct ddsi_sertopic *topic); +#ifdef DDSI_INCLUDE_LIFESPAN DDS_EXPORT nn_mtime_t dds_rhc_default_sample_expired_cb(void *hc, nn_mtime_t tnow); +#endif +#ifdef DDSI_INCLUDE_DEADLINE_MISSED +DDS_EXPORT nn_mtime_t dds_rhc_default_deadline_missed_cb(void *hc, nn_mtime_t tnow); +#endif #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds__whc.h b/src/core/ddsc/src/dds__whc.h index dcaeb42..a252ba0 100644 --- a/src/core/ddsc/src/dds__whc.h +++ b/src/core/ddsc/src/dds__whc.h @@ -19,7 +19,12 @@ extern "C" { #endif struct q_globals; -struct whc *whc_new (struct q_globals *gv, int is_transient_local, uint32_t hdepth, uint32_t tldepth); +struct whc_writer_info; +struct dds_writer; + +struct whc *whc_new (struct q_globals *gv, const struct whc_writer_info *wrinfo); +struct whc_writer_info *whc_make_wrinfo (struct dds_writer *wr, const dds_qos_t *qos); +void whc_free_wrinfo (struct whc_writer_info *); #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds__writer.h b/src/core/ddsc/src/dds__writer.h index c2c9336..0f1b7ef 100644 --- a/src/core/ddsc/src/dds__writer.h +++ b/src/core/ddsc/src/dds__writer.h @@ -20,6 +20,10 @@ extern "C" { DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_writer, DDS_KIND_WRITER) +struct status_cb_data; + +void dds_writer_status_cb (void *entity, const struct status_cb_data * data); + #if defined (__cplusplus) } #endif diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 28964f9..ff0b8cc 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -71,9 +71,23 @@ static dds_return_t dds_reader_delete (dds_entity *e) return DDS_RETCODE_OK; } +static dds_return_t validate_reader_qos (const dds_qos_t *rqos) +{ +#ifndef DDSI_INCLUDE_DEADLINE_MISSED + if (rqos != NULL && (rqos->present & QP_DEADLINE) && rqos->deadline.deadline != DDS_INFINITY) + return DDS_RETCODE_BAD_PARAMETER; +#else + DDSRT_UNUSED_ARG (rqos); +#endif + return DDS_RETCODE_OK; +} + static dds_return_t dds_reader_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) { /* note: e->m_qos is still the old one to allow for failure here */ + dds_return_t ret; + if ((ret = validate_reader_qos(qos)) != DDS_RETCODE_OK) + return ret; if (enabled) { struct reader *rd; @@ -420,7 +434,8 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe nn_xqos_mergein_missing (rqos, tp->m_entity.m_qos, ~(uint64_t)0); nn_xqos_mergein_missing (rqos, &sub->m_entity.m_domain->gv.default_xqos_rd, ~(uint64_t)0); - if ((ret = nn_xqos_valid (&sub->m_entity.m_domain->gv.logconfig, rqos)) != DDS_RETCODE_OK) + if ((ret = nn_xqos_valid (&sub->m_entity.m_domain->gv.logconfig, rqos)) < 0 || + (ret = validate_reader_qos(rqos)) != DDS_RETCODE_OK) { dds_delete_qos (rqos); reader = ret; diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index 15bf67d..cdce42e 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -43,6 +43,9 @@ #ifdef DDSI_INCLUDE_LIFESPAN #include "dds/ddsi/ddsi_lifespan.h" #endif +#ifdef DDSI_INCLUDE_DEADLINE_MISSED +#include "dds/ddsi/ddsi_deadline.h" +#endif #include "dds/ddsi/sysdeps.h" /* INSTANCE MANAGEMENT @@ -273,6 +276,9 @@ struct rhc_instance { ddsi_guid_t wr_guid; /* guid of last writer (if wr_iid != 0 then wr_guid is the corresponding guid, else undef) */ nn_wctime_t tstamp; /* source time stamp of last update */ struct ddsrt_circlist_elem nonempty_list; /* links non-empty instances in arbitrary ordering */ +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + struct deadline_elem deadline; /* element in deadline missed administration */ +#endif struct ddsi_tkmap_instance *tk; /* backref into TK for unref'ing */ struct rhc_sample a_sample; /* pre-allocated storage for 1 sample */ }; @@ -325,6 +331,9 @@ struct dds_rhc_default { #ifdef DDSI_INCLUDE_LIFESPAN struct lifespan_adm lifespan; /* Lifespan administration */ #endif +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + struct deadline_adm deadline; /* Deadline missed administration */ +#endif }; struct trigger_info_cmn { @@ -598,6 +607,36 @@ nn_mtime_t dds_rhc_default_sample_expired_cb(void *hc, nn_mtime_t tnow) } #endif /* DDSI_INCLUDE_LIFESPAN */ +#ifdef DDSI_INCLUDE_DEADLINE_MISSED +nn_mtime_t dds_rhc_default_deadline_missed_cb(void *hc, nn_mtime_t tnow) +{ + struct dds_rhc_default *rhc = hc; + void *vinst; + nn_mtime_t tnext; + ddsrt_mutex_lock (&rhc->lock); + while ((tnext = deadline_next_missed_locked (&rhc->deadline, tnow, &vinst)).v == 0) + { + struct rhc_instance *inst = vinst; + deadline_reregister_instance_locked (&rhc->deadline, &inst->deadline, tnow); + + inst->wr_iid_islive = 0; + + status_cb_data_t cb_data; + cb_data.raw_status_id = (int) DDS_REQUESTED_DEADLINE_MISSED_STATUS_ID; + cb_data.extra = 0; + cb_data.handle = inst->iid; + cb_data.add = true; + ddsrt_mutex_unlock (&rhc->lock); + dds_reader_status_cb (&rhc->reader->m_entity, &cb_data); + ddsrt_mutex_lock (&rhc->lock); + + tnow = now_mt (); + } + ddsrt_mutex_unlock (&rhc->lock); + return tnext; +} +#endif /* DDSI_INCLUDE_DEADLINE_MISSED */ + struct dds_rhc *dds_rhc_default_new_xchecks (dds_reader *reader, struct q_globals *gv, const struct ddsi_sertopic *topic, bool xchecks) { struct dds_rhc_default *rhc = ddsrt_malloc (sizeof (*rhc)); @@ -618,6 +657,11 @@ struct dds_rhc *dds_rhc_default_new_xchecks (dds_reader *reader, struct q_global lifespan_init (gv, &rhc->lifespan, offsetof(struct dds_rhc_default, lifespan), offsetof(struct rhc_sample, lifespan), dds_rhc_default_sample_expired_cb); #endif +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + rhc->deadline.dur = (reader != NULL) ? reader->m_entity.m_qos->deadline.deadline : DDS_INFINITY; + deadline_init (gv, &rhc->deadline, offsetof(struct dds_rhc_default, deadline), offsetof(struct rhc_instance, deadline), dds_rhc_default_deadline_missed_cb); +#endif + return &rhc->common; } @@ -638,6 +682,8 @@ static void dds_rhc_default_set_qos (struct dds_rhc_default * rhc, const dds_qos rhc->reliable = (qos->reliability.kind == DDS_RELIABILITY_RELIABLE); assert(qos->history.kind != DDS_HISTORY_KEEP_LAST || qos->history.depth > 0); rhc->history_depth = (qos->history.kind == DDS_HISTORY_KEEP_LAST) ? (uint32_t)qos->history.depth : ~0u; + /* FIXME: updating deadline duration not yet supported + rhc->deadline.dur = qos->deadline.deadline; */ } static bool eval_predicate_sample (const struct dds_rhc_default *rhc, const struct ddsi_serdata *sample, bool (*pred) (const void *sample)) @@ -735,6 +781,10 @@ static void free_empty_instance (struct rhc_instance *inst, struct dds_rhc_defau { assert (inst_is_empty (inst)); ddsi_tkmap_instance_unref (rhc->tkmap, inst->tk); +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + if (!inst->isdisposed) + deadline_unregister_instance_locked (&rhc->deadline, &inst->deadline); +#endif ddsrt_free (inst); } @@ -789,9 +839,15 @@ static void dds_rhc_default_free (struct dds_rhc_default *rhc) #ifdef DDSI_INCLUDE_LIFESPAN dds_rhc_default_sample_expired_cb (rhc, NN_MTIME_NEVER); lifespan_fini (&rhc->lifespan); +#endif +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + deadline_stop (&rhc->deadline); #endif ddsrt_hh_enum (rhc->instances, free_instance_rhc_free_wrap, rhc); assert (ddsrt_circlist_isempty (&rhc->nonempty_instances)); +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + deadline_fini (&rhc->deadline); +#endif ddsrt_hh_free (rhc->instances); lwregs_fini (&rhc->registrations); if (rhc->qcond_eval_samplebuf != NULL) @@ -863,7 +919,6 @@ static bool add_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst, { /* replace oldest sample; latest points to the latest one, the list is circular from old -> new, so latest->next is the oldest */ - inst_clear_invsample_if_exists (rhc, inst, trig_qc); assert (inst->latest != NULL); s = inst->latest->next; @@ -885,7 +940,6 @@ static bool add_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst, else { /* Check if resource max_samples QoS exceeded */ - if (rhc->reader && rhc->max_samples != DDS_LENGTH_UNLIMITED && rhc->n_vsamples >= (uint32_t) rhc->max_samples) { cb_data->raw_status_id = (int) DDS_SAMPLE_REJECTED_STATUS_ID; @@ -896,7 +950,6 @@ static bool add_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst, } /* Check if resource max_samples_per_instance QoS exceeded */ - if (rhc->reader && rhc->max_samples_per_instance != DDS_LENGTH_UNLIMITED && inst->nvsamples >= (uint32_t) rhc->max_samples_per_instance) { cb_data->raw_status_id = (int) DDS_SAMPLE_REJECTED_STATUS_ID; @@ -907,7 +960,6 @@ static bool add_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst, } /* add new latest sample */ - s = alloc_sample (inst); inst_clear_invsample_if_exists (rhc, inst, trig_qc); if (inst->latest == NULL) @@ -933,6 +985,11 @@ static bool add_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst, s->lifespan.t_expire = wrinfo->lifespan_exp; lifespan_register_sample_locked (&rhc->lifespan, &s->lifespan); #endif +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + /* Only renew the deadline missed counter in case the sample is actually stored in the rhc */ + if (!inst->isdisposed) + deadline_renew_instance_locked (&rhc->deadline, &inst->deadline); +#endif s->conds = 0; if (rhc->nqconds != 0) @@ -1294,7 +1351,7 @@ static bool dds_rhc_unregister (struct dds_rhc_default *rhc, struct rhc_instance return notify_data_available; } -static struct rhc_instance *alloc_new_instance (const struct dds_rhc_default *rhc, const struct ddsi_writer_info *wrinfo, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) +static struct rhc_instance *alloc_new_instance (struct dds_rhc_default *rhc, const struct ddsi_writer_info *wrinfo, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) { struct rhc_instance *inst; @@ -1325,6 +1382,11 @@ static struct rhc_instance *alloc_new_instance (const struct dds_rhc_default *rh } } +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + if (!inst->isdisposed) + deadline_register_instance_locked (&rhc->deadline, &inst->deadline, now_mt ()); +#endif + return inst; } @@ -1485,8 +1547,6 @@ static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, cons cb_data.handle = 0; cb_data.add = true; goto error_or_nochange; - - /* FIXME: deadline (and other) QoS? */ } else { @@ -1536,11 +1596,19 @@ static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, cons TRACE (" disposed->notdisposed"); inst->isdisposed = 0; inst->disposed_gen++; +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + if (!is_dispose) + deadline_register_instance_locked (&rhc->deadline, &inst->deadline, now_mt ()); +#endif } if (is_dispose) { inst->isdisposed = 1; inst_became_disposed = !old_isdisposed; +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + if (inst_became_disposed) + deadline_unregister_instance_locked (&rhc->deadline, &inst->deadline); +#endif TRACE (" dispose(%d)", inst_became_disposed); } @@ -1556,9 +1624,24 @@ static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, cons /* FIXME: fix the bad rejection handling, probably put back in a proper rollback, until then a band-aid like this will have to do: */ inst->isnew = old_isnew; - inst->isdisposed = old_isdisposed; if (old_isdisposed) + { inst->disposed_gen--; + if (!inst->isdisposed) + { + inst->isdisposed = 1; +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + deadline_unregister_instance_locked (&rhc->deadline, &inst->deadline); +#endif + } + } + else if (inst->isdisposed) + { + inst->isdisposed = 0; +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + deadline_register_instance_locked (&rhc->deadline, &inst->deadline, now_mt ()); +#endif + } goto error_or_nochange; } notify_data_available = true; @@ -1695,6 +1778,9 @@ static void dds_rhc_default_unregister_wr (struct dds_rhc_default * __restrict r if (auto_dispose && !inst->isdisposed) { inst->isdisposed = 1; +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + deadline_unregister_instance_locked (&rhc->deadline, &inst->deadline); +#endif /* Set invalid sample for disposing it (unregister may also set it for unregistering) */ if (inst->latest) diff --git a/src/core/ddsc/src/dds_whc.c b/src/core/ddsc/src/dds_whc.c index 5197a30..8c071ec 100644 --- a/src/core/ddsc/src/dds_whc.c +++ b/src/core/ddsc/src/dds_whc.c @@ -22,6 +22,9 @@ #ifdef DDSI_INCLUDE_LIFESPAN #include "dds/ddsi/ddsi_lifespan.h" #endif +#ifdef DDSI_INCLUDE_DEADLINE_MISSED +#include "dds/ddsi/ddsi_deadline.h" +#endif #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_tkmap.h" @@ -29,7 +32,10 @@ #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_freelist.h" #include "dds/ddsi/q_globals.h" +#include "dds/ddsi/q_entity.h" #include "dds__whc.h" +#include "dds__entity.h" +#include "dds__writer.h" #define USE_EHH 0 @@ -66,6 +72,9 @@ struct whc_idxnode { seqno_t prune_seq; struct ddsi_tkmap_instance *tk; uint32_t headidx; +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + struct deadline_elem deadline; /* list element for deadline missed */ +#endif struct whc_node *hist[]; }; @@ -76,6 +85,15 @@ struct whc_seq_entry { }; #endif +struct whc_writer_info { + dds_writer * writer; /* can be NULL, eg in case of whc for built-in writers */ + unsigned is_transient_local: 1; + unsigned has_deadline: 1; + uint32_t hdepth; /* 0 = unlimited */ + uint32_t tldepth; /* 0 = disabled/unlimited (no need to maintain an index if KEEP_ALL <=> is_transient_local + tldepth=0) */ + uint32_t idxdepth; /* = max (hdepth, tldepth) */ +}; + struct whc_impl { struct whc common; ddsrt_mutex_t lock; @@ -84,13 +102,10 @@ struct whc_impl { size_t sample_overhead; uint32_t fragment_size; uint64_t total_bytes; /* total number of bytes pushed in */ - unsigned is_transient_local: 1; unsigned xchecks: 1; struct q_globals *gv; struct ddsi_tkmap *tkmap; - uint32_t hdepth; /* 0 = unlimited */ - uint32_t tldepth; /* 0 = disabled/unlimited (no need to maintain an index if KEEP_ALL <=> is_transient_local + tldepth=0) */ - uint32_t idxdepth; /* = max (hdepth, tldepth) */ + struct whc_writer_info wrinfo; seqno_t max_drop_seq; /* samples in whc with seq <= max_drop_seq => transient-local */ struct whc_intvnode *open_intv; /* interval where next sample will go (usually) */ struct whc_node *maxseq_node; /* NULL if empty; if not in open_intv, open_intv is empty */ @@ -104,6 +119,9 @@ struct whc_impl { #ifdef DDSI_INCLUDE_LIFESPAN struct lifespan_adm lifespan; /* Lifespan administration */ #endif +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + struct deadline_adm deadline; /* Deadline missed administration */ +#endif }; struct whc_sample_iter_impl { @@ -373,45 +391,91 @@ static nn_mtime_t whc_sample_expired_cb(void *hc, nn_mtime_t tnow) } #endif -struct whc *whc_new (struct q_globals *gv, int is_transient_local, uint32_t hdepth, uint32_t tldepth) +#ifdef DDSI_INCLUDE_DEADLINE_MISSED +static nn_mtime_t whc_deadline_missed_cb(void *hc, nn_mtime_t tnow) +{ + struct whc_impl *whc = hc; + void *vidxnode; + nn_mtime_t tnext; + ddsrt_mutex_lock (&whc->lock); + while ((tnext = deadline_next_missed_locked (&whc->deadline, tnow, &vidxnode)).v == 0) + { + struct whc_idxnode *idxnode = vidxnode; + deadline_reregister_instance_locked (&whc->deadline, &idxnode->deadline, tnow); + + status_cb_data_t cb_data; + cb_data.raw_status_id = (int) DDS_OFFERED_DEADLINE_MISSED_STATUS_ID; + cb_data.extra = 0; + cb_data.handle = 0; + cb_data.add = true; + ddsrt_mutex_unlock (&whc->lock); + dds_writer_status_cb (&whc->wrinfo.writer->m_entity, &cb_data); + ddsrt_mutex_lock (&whc->lock); + + tnow = now_mt (); + } + ddsrt_mutex_unlock (&whc->lock); + return tnext; +} +#endif + +struct whc_writer_info *whc_make_wrinfo (struct dds_writer *wr, const dds_qos_t *qos) +{ + struct whc_writer_info *wrinfo = ddsrt_malloc (sizeof (*wrinfo)); + wrinfo->writer = wr; + wrinfo->is_transient_local = (qos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL); + wrinfo->has_deadline = (qos->deadline.deadline != DDS_INFINITY); + wrinfo->hdepth = (qos->history.kind == DDS_HISTORY_KEEP_ALL) ? 0 : (unsigned) qos->history.depth; + if (!wrinfo->is_transient_local) + wrinfo->tldepth = 0; + else + wrinfo->tldepth = (qos->durability_service.history.kind == DDS_HISTORY_KEEP_ALL) ? 0 : (unsigned) qos->durability_service.history.depth; + wrinfo->idxdepth = wrinfo->hdepth > wrinfo->tldepth ? wrinfo->hdepth : wrinfo->tldepth; + return wrinfo; +} + +void whc_free_wrinfo (struct whc_writer_info *wrinfo) +{ + ddsrt_free (wrinfo); +} + +struct whc *whc_new (struct q_globals *gv, const struct whc_writer_info *wrinfo) { size_t sample_overhead = 80; /* INFO_TS, DATA (estimate), inline QoS */ struct whc_impl *whc; struct whc_intvnode *intv; - assert ((hdepth == 0 || tldepth <= hdepth) || is_transient_local); + assert ((wrinfo->hdepth == 0 || wrinfo->tldepth <= wrinfo->hdepth) || wrinfo->is_transient_local); whc = ddsrt_malloc (sizeof (*whc)); whc->common.ops = &whc_ops; ddsrt_mutex_init (&whc->lock); - whc->is_transient_local = is_transient_local ? 1 : 0; whc->xchecks = (gv->config.enabled_xchecks & DDS_XCHECK_WHC) != 0; whc->gv = gv; whc->tkmap = gv->m_tkmap; - whc->hdepth = hdepth; - whc->tldepth = tldepth; - whc->idxdepth = hdepth > tldepth ? hdepth : tldepth; + memcpy (&whc->wrinfo, wrinfo, sizeof (*wrinfo)); whc->seq_size = 0; whc->max_drop_seq = 0; whc->unacked_bytes = 0; whc->total_bytes = 0; whc->sample_overhead = sample_overhead; whc->fragment_size = gv->config.fragment_size; + whc->idx_hash = ddsrt_hh_new (1, whc_idxnode_hash_key, whc_idxnode_eq_key); #if USE_EHH whc->seq_hash = ddsrt_ehh_new (sizeof (struct whc_seq_entry), 32, whc_seq_entry_hash, whc_seq_entry_eq); #else whc->seq_hash = ddsrt_hh_new (1, whc_node_hash, whc_node_eq); #endif - if (whc->idxdepth > 0) - whc->idx_hash = ddsrt_hh_new (1, whc_idxnode_hash_key, whc_idxnode_eq_key); - else - whc->idx_hash = NULL; - #ifdef DDSI_INCLUDE_LIFESPAN lifespan_init (gv, &whc->lifespan, offsetof(struct whc_impl, lifespan), offsetof(struct whc_node, lifespan), whc_sample_expired_cb); #endif +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + whc->deadline.dur = (wrinfo->writer != NULL) ? wrinfo->writer->m_entity.m_qos->deadline.deadline : DDS_INFINITY; + deadline_init (gv, &whc->deadline, offsetof(struct whc_impl, deadline), offsetof(struct whc_idxnode, deadline), whc_deadline_missed_cb); +#endif + /* seq interval tree: always has an "open" node */ ddsrt_avl_init (&whc_seq_treedef, &whc->seq); intv = ddsrt_malloc (sizeof (*intv)); @@ -450,14 +514,19 @@ void whc_default_free (struct whc *whc_generic) lifespan_fini (&whc->lifespan); #endif - if (whc->idx_hash) - { - struct ddsrt_hh_iter it; - struct whc_idxnode *n; - for (n = ddsrt_hh_iter_first (whc->idx_hash, &it); n != NULL; n = ddsrt_hh_iter_next (&it)) - ddsrt_free (n); - ddsrt_hh_free (whc->idx_hash); - } +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + deadline_stop (&whc->deadline); + ddsrt_mutex_lock (&whc->lock); + deadline_clear (&whc->deadline); + ddsrt_mutex_unlock (&whc->lock); + deadline_fini (&whc->deadline); +#endif + + struct ddsrt_hh_iter it; + struct whc_idxnode *idxn; + for (idxn = ddsrt_hh_iter_first (whc->idx_hash, &it); idxn != NULL; idxn = ddsrt_hh_iter_next (&it)) + ddsrt_free (idxn); + ddsrt_hh_free (whc->idx_hash); { struct whc_node *whcn = whc->maxseq_node; @@ -577,31 +646,19 @@ static seqno_t whc_default_next_seq (const struct whc *whc_generic, seqno_t seq) return nseq; } -static void delete_one_sample_from_idx (struct whc_impl *whc, struct whc_node *whcn) +static void delete_one_sample_from_idx (struct whc_node *whcn) { struct whc_idxnode * const idxn = whcn->idxnode; assert (idxn != NULL); assert (idxn->hist[idxn->headidx] != NULL); assert (idxn->hist[whcn->idxnode_pos] == whcn); - if (whcn->idxnode_pos != idxn->headidx) - idxn->hist[whcn->idxnode_pos] = NULL; - else - { -#ifndef NDEBUG - for (uint32_t i = 0; i < whc->idxdepth; i++) - assert (i == idxn->headidx || idxn->hist[i] == NULL); -#endif - if (!ddsrt_hh_remove (whc->idx_hash, idxn)) - assert (0); - ddsi_tkmap_instance_unref (whc->tkmap, idxn->tk); - ddsrt_free (idxn); - } + idxn->hist[whcn->idxnode_pos] = NULL; whcn->idxnode = NULL; } static void free_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_idxnode *idxn) { - for (uint32_t i = 0; i < whc->idxdepth; i++) + for (uint32_t i = 0; i < whc->wrinfo.idxdepth; i++) { if (idxn->hist[i]) { @@ -622,6 +679,9 @@ static void delete_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop { if (!ddsrt_hh_remove (whc->idx_hash, idxn)) assert (0); +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + deadline_unregister_instance_locked (&whc->deadline, &idxn->deadline); +#endif free_one_instance_from_idx (whc, max_drop_seq, idxn); } @@ -631,9 +691,9 @@ static int whcn_in_tlidx (const struct whc_impl *whc, const struct whc_idxnode * return 0; else { - uint32_t d = (idxn->headidx + (pos > idxn->headidx ? whc->idxdepth : 0)) - pos; - assert (d < whc->idxdepth); - return d < whc->tldepth; + uint32_t d = (idxn->headidx + (pos > idxn->headidx ? whc->wrinfo.idxdepth : 0)) - pos; + assert (d < whc->wrinfo.idxdepth); + return d < whc->wrinfo.tldepth; } } @@ -649,7 +709,7 @@ static uint32_t whc_default_downgrade_to_volatile (struct whc *whc_generic, stru ddsrt_mutex_lock (&whc->lock); check_whc (whc); - if (whc->idxdepth == 0) + if (whc->wrinfo.idxdepth == 0) { /* if not maintaining an index at all, this is nonsense */ get_state_locked (whc, st); @@ -657,19 +717,24 @@ static uint32_t whc_default_downgrade_to_volatile (struct whc *whc_generic, stru return 0; } - assert (!whc->is_transient_local); - if (whc->tldepth > 0) + assert (!whc->wrinfo.is_transient_local); + if (whc->wrinfo.tldepth > 0) { - assert (whc->hdepth == 0 || whc->tldepth <= whc->hdepth); - whc->tldepth = 0; - if (whc->hdepth == 0) + assert (whc->wrinfo.hdepth == 0 || whc->wrinfo.tldepth <= whc->wrinfo.hdepth); + whc->wrinfo.tldepth = 0; + if (whc->wrinfo.hdepth == 0) { struct ddsrt_hh_iter it; - struct whc_idxnode *n; - for (n = ddsrt_hh_iter_first (whc->idx_hash, &it); n != NULL; n = ddsrt_hh_iter_next (&it)) - free_one_instance_from_idx (whc, 0, n); + struct whc_idxnode *idxn; + for (idxn = ddsrt_hh_iter_first (whc->idx_hash, &it); idxn != NULL; idxn = ddsrt_hh_iter_next (&it)) + { +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + deadline_unregister_instance_locked (&whc->deadline, &idxn->deadline); +#endif + free_one_instance_from_idx (whc, 0, idxn); + } ddsrt_hh_free (whc->idx_hash); - whc->idxdepth = 0; + whc->wrinfo.idxdepth = 0; whc->idx_hash = NULL; } } @@ -711,7 +776,7 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i /* If it is in the tlidx, take it out. Transient-local data never gets here */ if (whcn->idxnode) - delete_one_sample_from_idx (whc, whcn); + delete_one_sample_from_idx (whcn); if (whcn->unacked) { assert (whc->unacked_bytes >= whcn->size); @@ -927,15 +992,27 @@ static uint32_t whc_default_remove_acked_messages_full (struct whc_impl *whc, se struct whc_node deferred_list_head, *last_to_free = &deferred_list_head; uint32_t ndropped = 0; - if (whc->is_transient_local && whc->tldepth == 0) + whcn = find_nextseq_intv (&intv, whc, whc->max_drop_seq); + if (whc->wrinfo.is_transient_local && whc->wrinfo.tldepth == 0) { - /* KEEP_ALL on transient local, so we can never ever delete anything */ - TRACE (" KEEP_ALL transient-local: do nothing\n"); + /* KEEP_ALL on transient local, so we can never ever delete anything, but + we have to ack the data in whc */ + TRACE (" KEEP_ALL transient-local: ack data\n"); + while (whcn && whcn->seq <= max_drop_seq) + { + if (whcn->unacked) + { + assert (whc->unacked_bytes >= whcn->size); + whc->unacked_bytes -= whcn->size; + whcn->unacked = 0; + } + whcn = whcn->next_seq; + } + whc->max_drop_seq = max_drop_seq; *deferred_free_list = NULL; return 0; } - whcn = find_nextseq_intv (&intv, whc, whc->max_drop_seq); deferred_list_head.next_seq = NULL; prev_seq = whcn ? whcn->prev_seq : NULL; while (whcn && whcn->seq <= max_drop_seq) @@ -982,10 +1059,10 @@ static uint32_t whc_default_remove_acked_messages_full (struct whc_impl *whc, se the T-L history but that are not anymore. Writing new samples will eventually push these out, but if the difference is large and the update rate low, it may take a long time. Thus, we had better prune them. */ - if (whc->tldepth > 0 && whc->idxdepth > whc->tldepth) + if (whc->wrinfo.tldepth > 0 && whc->wrinfo.idxdepth > whc->wrinfo.tldepth) { - assert (whc->hdepth == whc->idxdepth); - TRACE (" idxdepth %"PRIu32" > tldepth %"PRIu32" > 0 -- must prune\n", whc->idxdepth, whc->tldepth); + assert (whc->wrinfo.hdepth == whc->wrinfo.idxdepth); + TRACE (" idxdepth %"PRIu32" > tldepth %"PRIu32" > 0 -- must prune\n", whc->wrinfo.idxdepth, whc->wrinfo.tldepth); /* Do a second pass over the sequence number range we just processed: this time we only encounter samples that were retained because of the transient-local durability setting @@ -1010,11 +1087,11 @@ static uint32_t whc_default_remove_acked_messages_full (struct whc_impl *whc, se idxn->prune_seq = max_drop_seq; idx = idxn->headidx; - cnt = whc->idxdepth - whc->tldepth; + cnt = whc->wrinfo.idxdepth - whc->wrinfo.tldepth; while (cnt--) { struct whc_node *oldn; - if (++idx == whc->idxdepth) + if (++idx == whc->wrinfo.idxdepth) idx = 0; if ((oldn = idxn->hist[idx]) != NULL) { @@ -1061,12 +1138,16 @@ static uint32_t whc_default_remove_acked_messages (struct whc *whc_generic, seqn get_state_locked (whc, &tmp); TRACE ("whc_default_remove_acked_messages(%p max_drop_seq %"PRId64")\n", (void *)whc, max_drop_seq); TRACE (" whc: [%"PRId64",%"PRId64"] max_drop_seq %"PRId64" h %"PRIu32" tl %"PRIu32"\n", - tmp.min_seq, tmp.max_seq, whc->max_drop_seq, whc->hdepth, whc->tldepth); + tmp.min_seq, tmp.max_seq, whc->max_drop_seq, whc->wrinfo.hdepth, whc->wrinfo.tldepth); } check_whc (whc); - if (whc->idxdepth == 0) + /* In case a deadline is set, a sample may be added to whc temporarily, which could be + stored in acked state. The _noidx variant of removing messages assumes that unacked + data exists in whc. So in case of a deadline, the _full variant is used instead, + even when index depth is 0 */ + if (whc->wrinfo.idxdepth == 0 && !whc->wrinfo.has_deadline && !whc->wrinfo.is_transient_local) cnt = whc_default_remove_acked_messages_noidx (whc, max_drop_seq, deferred_free_list); else cnt = whc_default_remove_acked_messages_full (whc, max_drop_seq, deferred_free_list); @@ -1080,8 +1161,6 @@ static struct whc_node *whc_default_insert_seq (struct whc_impl *whc, seqno_t ma struct whc_node *newn = NULL; #ifndef DDSI_INCLUDE_LIFESPAN - /* FIXME: the 'exp' arg is used for lifespan, refactor this parameter to a struct 'writer info' - that contains both lifespan and deadline info of the writer */ DDSRT_UNUSED_ARG (exp); #endif @@ -1172,7 +1251,7 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se TRACE ("whc_default_insert(%p max_drop_seq %"PRId64" seq %"PRId64" exp %"PRId64" plist %p serdata %p:%"PRIx32")\n", (void *) whc, max_drop_seq, seq, exp.v, (void *) plist, (void *) serdata, serdata->hash); TRACE (" whc: [%"PRId64",%"PRId64"] max_drop_seq %"PRId64" h %"PRIu32" tl %"PRIu32"\n", - whcst.min_seq, whcst.max_seq, whc->max_drop_seq, whc->hdepth, whc->tldepth); + whcst.min_seq, whcst.max_seq, whc->max_drop_seq, whc->wrinfo.hdepth, whc->wrinfo.tldepth); } assert (max_drop_seq < MAX_SEQ_NUMBER); @@ -1189,7 +1268,7 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se TRACE (" whcn %p:", (void*)newn); /* Special case of empty data (such as commit messages) can't go into index, and if we're not maintaining an index, we're done, too */ - if (serdata->kind == SDK_EMPTY || whc->idxdepth == 0) + if (serdata->kind == SDK_EMPTY) { TRACE (" empty or no hist\n"); ddsrt_mutex_unlock (&whc->lock); @@ -1215,42 +1294,50 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se } else { - struct whc_node *oldn; - if (++idxn->headidx == whc->idxdepth) - idxn->headidx = 0; - if ((oldn = idxn->hist[idxn->headidx]) != NULL) +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + deadline_renew_instance_locked (&whc->deadline, &idxn->deadline); +#endif + if (whc->wrinfo.idxdepth > 0) { - TRACE (" overwrite whcn %p", (void *)oldn); - oldn->idxnode = NULL; - } - idxn->hist[idxn->headidx] = newn; - newn->idxnode = idxn; - newn->idxnode_pos = idxn->headidx; - - if (oldn && (whc->hdepth > 0 || oldn->seq <= max_drop_seq)) - { - TRACE (" prune whcn %p", (void *)oldn); - assert (oldn != whc->maxseq_node); - whc_delete_one (whc, oldn); - } - - /* Special case for dropping everything beyond T-L history when the new sample is being - auto-acknowledged (for lack of reliable readers), and the keep-last T-L history is - shallower than the keep-last regular history (normal path handles this via pruning in - whc_default_remove_acked_messages, but that never happens when there are no readers). */ - if (seq <= max_drop_seq && whc->tldepth > 0 && whc->idxdepth > whc->tldepth) - { - uint32_t pos = idxn->headidx + whc->idxdepth - whc->tldepth; - if (pos >= whc->idxdepth) - pos -= whc->idxdepth; - if ((oldn = idxn->hist[pos]) != NULL) + struct whc_node *oldn; + if (++idxn->headidx == whc->wrinfo.idxdepth) + idxn->headidx = 0; + if ((oldn = idxn->hist[idxn->headidx]) != NULL) { - TRACE (" prune tl whcn %p", (void *)oldn); - assert (oldn != whc->maxseq_node); - whc_delete_one (whc, oldn); + TRACE (" overwrite whcn %p", (void *)oldn); + oldn->idxnode = NULL; } + idxn->hist[idxn->headidx] = newn; + newn->idxnode = idxn; + newn->idxnode_pos = idxn->headidx; + + if (oldn && (whc->wrinfo.hdepth > 0 || oldn->seq <= max_drop_seq) && whc->wrinfo.tldepth > 0) + { + TRACE (" prune whcn %p", (void *)oldn); + assert (oldn != whc->maxseq_node || whc->wrinfo.has_deadline); + whc_delete_one (whc, oldn); + if (oldn == whc->maxseq_node) + whc->maxseq_node = whc_findmax_procedurally (whc); + } + + /* Special case for dropping everything beyond T-L history when the new sample is being + auto-acknowledged (for lack of reliable readers), and the keep-last T-L history is + shallower than the keep-last regular history (normal path handles this via pruning in + whc_default_remove_acked_messages, but that never happens when there are no readers). */ + if (seq <= max_drop_seq && whc->wrinfo.tldepth > 0 && whc->wrinfo.idxdepth > whc->wrinfo.tldepth) + { + uint32_t pos = idxn->headidx + whc->wrinfo.idxdepth - whc->wrinfo.tldepth; + if (pos >= whc->wrinfo.idxdepth) + pos -= whc->wrinfo.idxdepth; + if ((oldn = idxn->hist[pos]) != NULL) + { + TRACE (" prune tl whcn %p", (void *)oldn); + assert (oldn != whc->maxseq_node); + whc_delete_one (whc, oldn); + } + } + TRACE ("\n"); } - TRACE ("\n"); } } else @@ -1259,20 +1346,26 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se /* Ignore unregisters, but insert everything else */ if (!(serdata->statusinfo & NN_STATUSINFO_UNREGISTER)) { - idxn = ddsrt_malloc (sizeof (*idxn) + whc->idxdepth * sizeof (idxn->hist[0])); + idxn = ddsrt_malloc (sizeof (*idxn) + whc->wrinfo.idxdepth * sizeof (idxn->hist[0])); TRACE (" idxn %p", (void *)idxn); ddsi_tkmap_instance_ref (tk); idxn->iid = tk->m_iid; idxn->tk = tk; idxn->prune_seq = 0; idxn->headidx = 0; - idxn->hist[0] = newn; - for (uint32_t i = 1; i < whc->idxdepth; i++) - idxn->hist[i] = NULL; - newn->idxnode = idxn; - newn->idxnode_pos = 0; + if (whc->wrinfo.idxdepth > 0) + { + idxn->hist[0] = newn; + for (uint32_t i = 1; i < whc->wrinfo.idxdepth; i++) + idxn->hist[i] = NULL; + newn->idxnode = idxn; + newn->idxnode_pos = 0; + } if (!ddsrt_hh_add (whc->idx_hash, idxn)) assert (0); +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + deadline_register_instance_locked (&whc->deadline, &idxn->deadline, now_mt ()); +#endif } else { diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 0dbe254..1e023c1 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -50,9 +50,9 @@ static dds_return_t dds_writer_status_validate (uint32_t mask) then status conditions is not triggered. */ -static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) +void dds_writer_status_cb (void *entity, const struct status_cb_data *data) { - dds_writer * const wr = ventity; + dds_writer * const wr = entity; /* When data is NULL, it means that the DDSI reader is deleted. */ if (data == NULL) @@ -223,7 +223,12 @@ static dds_return_t validate_writer_qos (const dds_qos_t *wqos) #ifndef DDSI_INCLUDE_LIFESPAN if (wqos != NULL && (wqos->present & QP_LIFESPAN) && wqos->lifespan.duration != DDS_INFINITY) return DDS_RETCODE_BAD_PARAMETER; -#else +#endif +#ifndef DDSI_INCLUDE_DEADLINE_MISSED + if (wqos != NULL && (wqos->present & QP_DEADLINE) && wqos->deadline.deadline != DDS_INFINITY) + return DDS_RETCODE_BAD_PARAMETER; +#endif +#if defined(DDSI_INCLUDE_LIFESPAN) && defined(DDSI_INCLUDE_DEADLINE_MISSED) DDSRT_UNUSED_ARG (wqos); #endif return DDS_RETCODE_OK; @@ -246,30 +251,6 @@ static dds_return_t dds_writer_qos_set (dds_entity *e, const dds_qos_t *qos, boo return DDS_RETCODE_OK; } -static struct whc *make_whc (struct dds_domain *dom, const dds_qos_t *qos) -{ - bool handle_as_transient_local; - uint32_t hdepth, tldepth; - /* Construct WHC -- if aggressive_keep_last1 is set, the WHC will - drop all samples for which a later update is available. This - forces it to maintain a tlidx. */ - handle_as_transient_local = (qos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL); - if (qos->history.kind == DDS_HISTORY_KEEP_ALL) - hdepth = 0; - else - hdepth = (unsigned) qos->history.depth; - if (!handle_as_transient_local) - tldepth = 0; - else - { - if (qos->durability_service.history.kind == DDS_HISTORY_KEEP_ALL) - tldepth = 0; - else - tldepth = (unsigned) qos->durability_service.history.depth; - } - return whc_new (&dom->gv, handle_as_transient_local, hdepth, tldepth); -} - const struct dds_entity_deriver dds_entity_deriver_writer = { .interrupt = dds_writer_interrupt, .close = dds_writer_close, @@ -288,6 +269,7 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit dds_participant *pp; dds_topic *tp; dds_entity_t publisher; + struct whc_writer_info *wrinfo; { dds_entity *p_or_p; @@ -348,7 +330,9 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit wr->m_topic = tp; dds_entity_add_ref_locked (&tp->m_entity); wr->m_xp = nn_xpack_new (conn, get_bandwidth_limit (wqos->transport_priority), pub->m_entity.m_domain->gv.config.xpack_send_async); - wr->m_whc = make_whc (pub->m_entity.m_domain, wqos); + wrinfo = whc_make_wrinfo (wr, wqos); + wr->m_whc = whc_new (&pub->m_entity.m_domain->gv, wrinfo); + whc_free_wrinfo (wrinfo); wr->whc_batch = pub->m_entity.m_domain->gv.config.whc_batch; thread_state_awake (lookup_thread_state (), &pub->m_entity.m_domain->gv); diff --git a/src/core/ddsc/tests/CMakeLists.txt b/src/core/ddsc/tests/CMakeLists.txt index bb6dbe7..3f902dd 100644 --- a/src/core/ddsc/tests/CMakeLists.txt +++ b/src/core/ddsc/tests/CMakeLists.txt @@ -51,6 +51,7 @@ set(ddsc_test_sources "unsupported.c" "waitset.c" "waitset_torture.c" + "whc.c" "write.c" "write_various_types.c" "writer.c") @@ -59,6 +60,10 @@ if(ENABLE_LIFESPAN) list(APPEND ddsc_test_sources "lifespan.c") endif() +if(ENABLE_DEADLINE_MISSED) + list(APPEND ddsc_test_sources "deadline.c") +endif() + add_cunit_executable(cunit_ddsc ${ddsc_test_sources}) target_include_directories( cunit_ddsc PRIVATE diff --git a/src/core/ddsc/tests/Space.idl b/src/core/ddsc/tests/Space.idl index 3ebbc48..d4d0149 100644 --- a/src/core/ddsc/tests/Space.idl +++ b/src/core/ddsc/tests/Space.idl @@ -22,6 +22,12 @@ module Space { long long_3; }; #pragma keylist Type2 long_1 + struct Type3 { + long long_1; + long long_2; + long long_3; + }; +#pragma keylist Type3 struct simpletypes { long l; diff --git a/src/core/ddsc/tests/deadline.c b/src/core/ddsc/tests/deadline.c new file mode 100644 index 0000000..818847a --- /dev/null +++ b/src/core/ddsc/tests/deadline.c @@ -0,0 +1,484 @@ +/* + * 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 +#include + +#include "dds/dds.h" +#include "CUnit/Theory.h" +#include "Space.h" + +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/threads.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsi/ddsi_entity_index.h" +#include "dds/ddsi/q_entity.h" +#include "dds/ddsi/q_whc.h" +#include "dds__entity.h" + +#define MAX_RUNS 4 +#define WRITER_DEADLINE DDS_MSECS(50) + +#define DDS_DOMAINID_PUB 0 +#define DDS_DOMAINID_SUB 1 +#define DDS_CONFIG_NO_PORT_GAIN "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}0" + +static dds_entity_t g_domain = 0; +static dds_entity_t g_participant = 0; +static dds_entity_t g_subscriber = 0; +static dds_entity_t g_publisher = 0; +static dds_entity_t g_topic = 0; +static dds_qos_t *g_qos; +static dds_entity_t g_remote_domain = 0; +static dds_entity_t g_remote_participant = 0; +static dds_entity_t g_remote_subscriber = 0; +static dds_entity_t g_remote_topic = 0; + + +static char * create_topic_name(const char *prefix, char *name, size_t size) +{ + ddsrt_pid_t pid = ddsrt_getpid(); + ddsrt_tid_t tid = ddsrt_gettid(); + (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); + return name; +} + +static void sync_reader_writer(dds_entity_t participant, dds_entity_t reader, dds_entity_t writer) +{ + dds_attach_t triggered; + dds_return_t ret; + dds_entity_t waitset_rd = dds_create_waitset(participant); + CU_ASSERT_FATAL(waitset_rd > 0); + dds_entity_t waitset_wr = dds_create_waitset(g_participant); + CU_ASSERT_FATAL(waitset_wr > 0); + + /* Sync reader to writer. */ + ret = dds_set_status_mask(reader, DDS_SUBSCRIPTION_MATCHED_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + ret = dds_waitset_attach(waitset_rd, reader, reader); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + ret = dds_waitset_wait(waitset_rd, &triggered, 1, DDS_SECS(1)); + CU_ASSERT_EQUAL_FATAL(ret, 1); + CU_ASSERT_EQUAL_FATAL(reader, (dds_entity_t)(intptr_t)triggered); + ret = dds_waitset_detach(waitset_rd, reader); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + dds_delete(waitset_rd); + + /* Sync writer to reader. */ + ret = dds_set_status_mask(writer, DDS_PUBLICATION_MATCHED_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + ret = dds_waitset_attach(waitset_wr, writer, writer); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + ret = dds_waitset_wait(waitset_wr, &triggered, 1, DDS_SECS(1)); + CU_ASSERT_EQUAL_FATAL(ret, 1); + CU_ASSERT_EQUAL_FATAL(writer, (dds_entity_t)(intptr_t)triggered); + ret = dds_waitset_detach(waitset_wr, writer); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + dds_delete(waitset_wr); +} + +static dds_entity_t create_and_sync_reader(dds_entity_t participant, dds_entity_t subscriber, dds_entity_t topic, dds_qos_t *qos, dds_entity_t writer) +{ + dds_entity_t reader = dds_create_reader(subscriber, topic, qos, NULL); + CU_ASSERT_FATAL(reader > 0); + sync_reader_writer (participant, reader, writer); + dds_return_t ret = dds_set_status_mask(reader, DDS_REQUESTED_DEADLINE_MISSED_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + return reader; +} + +static void deadline_init(void) +{ + char name[100]; + + /* 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_domain = dds_create_domain(DDS_DOMAINID_PUB, conf_pub); + g_remote_domain = dds_create_domain(DDS_DOMAINID_SUB, conf_sub); + dds_free(conf_pub); + dds_free(conf_sub); + + g_qos = dds_create_qos(); + CU_ASSERT_PTR_NOT_NULL_FATAL(g_qos); + + g_participant = dds_create_participant(DDS_DOMAINID_PUB, NULL, NULL); + CU_ASSERT_FATAL(g_participant > 0); + g_remote_participant = dds_create_participant(DDS_DOMAINID_SUB, NULL, NULL); + CU_ASSERT_FATAL(g_remote_participant > 0); + + g_subscriber = dds_create_subscriber(g_participant, NULL, NULL); + CU_ASSERT_FATAL(g_subscriber > 0); + + g_remote_subscriber = dds_create_subscriber(g_remote_participant, NULL, NULL); + CU_ASSERT_FATAL(g_remote_subscriber > 0); + + g_publisher = dds_create_publisher(g_participant, NULL, NULL); + CU_ASSERT_FATAL(g_publisher > 0); + + create_topic_name("ddsc_qos_deadline_test", name, sizeof name); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, name, NULL, NULL); + CU_ASSERT_FATAL(g_topic > 0); + g_remote_topic = dds_create_topic(g_remote_participant, &Space_Type1_desc, name, NULL, NULL); + CU_ASSERT_FATAL(g_remote_topic > 0); + + dds_qset_history(g_qos, DDS_HISTORY_KEEP_ALL, DDS_LENGTH_UNLIMITED); + dds_qset_durability(g_qos, DDS_DURABILITY_TRANSIENT_LOCAL); + dds_qset_reliability(g_qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); +} + +static void deadline_fini(void) +{ + dds_delete_qos(g_qos); + dds_delete(g_subscriber); + dds_delete(g_remote_subscriber); + dds_delete(g_publisher); + dds_delete(g_topic); + dds_delete(g_participant); + dds_delete(g_remote_participant); + dds_delete(g_domain); + dds_delete(g_remote_domain); +} + +static void msg(const char *msg, ...) +{ + va_list args; + dds_time_t t; + t = dds_time(); + printf("%d.%06d ", (int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000); + va_start(args, msg); + vprintf(msg, args); + va_end(args); + printf("\n"); +} + +static void sleepfor(dds_duration_t sleep_dur) +{ + dds_sleepfor (sleep_dur); + msg("after sleeping %"PRId64, sleep_dur); +} + +static bool check_missed_deadline_reader(dds_entity_t reader, uint32_t exp_missed_total, int32_t exp_missed_change) +{ + struct dds_requested_deadline_missed_status dstatus; + dds_return_t ret = dds_get_requested_deadline_missed_status(reader, &dstatus); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + msg("- check reader total actual %u == expected %u / change actual %d == expected %d", dstatus.total_count, exp_missed_total, dstatus.total_count_change, exp_missed_change); + return dstatus.total_count == exp_missed_total && dstatus.total_count_change == exp_missed_change; +} + +static bool check_missed_deadline_writer(dds_entity_t writer, uint32_t exp_missed_total, int32_t exp_missed_change) +{ + struct dds_offered_deadline_missed_status dstatus; + dds_return_t ret = dds_get_offered_deadline_missed_status(writer, &dstatus); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + msg("- check writer total actual %u == expected %u / change actual %d == expected %d", dstatus.total_count, exp_missed_total, dstatus.total_count_change, exp_missed_change); + return dstatus.total_count == exp_missed_total && dstatus.total_count_change == exp_missed_change; +} + +CU_Test(ddsc_deadline, basic, .init=deadline_init, .fini=deadline_fini) +{ + Space_Type1 sample = { 0, 0, 0 }; + dds_entity_t reader, reader_remote, reader_dl, reader_dl_remote, writer; + dds_return_t ret; + dds_duration_t deadline_dur = WRITER_DEADLINE; + uint32_t run = 1; + bool test_finished = false; + + do + { + msg("deadline test: duration %"PRId64, deadline_dur); + + dds_qset_deadline(g_qos, deadline_dur); + writer = dds_create_writer(g_publisher, g_topic, g_qos, NULL); + CU_ASSERT_FATAL(writer > 0); + + reader_dl = create_and_sync_reader(g_participant, g_subscriber, g_topic, g_qos, writer); + reader_dl_remote = create_and_sync_reader(g_remote_participant, g_remote_subscriber, g_remote_topic, g_qos, writer); + + dds_qset_deadline(g_qos, DDS_INFINITY); + reader = create_and_sync_reader(g_participant, g_subscriber, g_topic, g_qos, writer); + reader_remote = create_and_sync_reader(g_remote_participant, g_remote_subscriber, g_remote_topic, g_qos, writer); + + ret = dds_set_status_mask(writer, DDS_OFFERED_DEADLINE_MISSED_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + /* Write first sample */ + msg("write sample 1"); + ret = dds_write (writer, &sample); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + + /* Sleep 0.5 * deadline_dur: expect no missed deadlines for reader and writer */ + sleepfor(deadline_dur / 2); + if (!check_missed_deadline_reader(reader, 0, 0) || + !check_missed_deadline_reader(reader_remote, 0, 0) || + !check_missed_deadline_reader(reader_dl, 0, 0) || + !check_missed_deadline_reader(reader_dl_remote, 0, 0) || + !check_missed_deadline_writer(writer, 0, 0)) + deadline_dur *= 10 / (run + 1); + else + { + /* Write another sample */ + msg("write sample 2"); + ret = dds_write (writer, &sample); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + + /* Sleep 0.5 * deadline_dur: expect no missed deadlines for reader and writer */ + sleepfor(deadline_dur / 2); + if (!check_missed_deadline_reader(reader, 0, 0) || + !check_missed_deadline_reader(reader_remote, 0, 0) || + !check_missed_deadline_reader(reader_dl, 0, 0) || + !check_missed_deadline_reader(reader_dl_remote, 0, 0) || + !check_missed_deadline_writer(writer, 0, 0)) + deadline_dur *= 10 / (run + 1); + else + { + /* Sleep deadline_dur: expect deadline reader to have 1 missed deadline */ + sleepfor(deadline_dur); + if (!check_missed_deadline_reader(reader, 0, 0) || + !check_missed_deadline_reader(reader_remote, 0, 0) || + !check_missed_deadline_reader(reader_dl, 1, 1) || + !check_missed_deadline_reader(reader_dl_remote, 1, 1) || + !check_missed_deadline_writer(writer, 1, 1)) + deadline_dur *= 10 / (run + 1); + else + { + /* Sleep another 2 * deadline_duration: expect 2 new triggers for missed deadline for both reader and writer */ + sleepfor(2 * deadline_dur); + if (!check_missed_deadline_reader(reader, 0, 0) || + !check_missed_deadline_reader(reader_remote, 0, 0) || + !check_missed_deadline_reader(reader_dl, 3, 2) || + !check_missed_deadline_reader(reader_dl_remote, 3, 2) || + !check_missed_deadline_writer(writer, 3, 2)) + deadline_dur *= 10 / (run + 1); + else + test_finished = true; + } + } + } + + dds_delete(reader); + dds_delete(writer); + + if (!test_finished) + { + if (++run > MAX_RUNS) + { + msg("run limit reached, test failed"); + CU_FAIL_FATAL("Run limit reached"); + test_finished = true; + } + else + { + msg("restarting test with deadline duration %"PRId64, deadline_dur); + sleepfor(deadline_dur); + } + } + } while (!test_finished); +} + +#define V DDS_DURABILITY_VOLATILE +#define TL DDS_DURABILITY_TRANSIENT_LOCAL +#define R DDS_RELIABILITY_RELIABLE +#define BE DDS_RELIABILITY_BEST_EFFORT +#define KA DDS_HISTORY_KEEP_ALL +#define KL DDS_HISTORY_KEEP_LAST +CU_TheoryDataPoints(ddsc_deadline, writer_types) = { + CU_DataPoints(dds_durability_kind_t, V, V, V, V, TL, TL, TL, TL), + CU_DataPoints(dds_reliability_kind_t, BE, BE, R, R, BE, BE, R, R), + CU_DataPoints(dds_history_kind_t, KA, KL, KA, KL, KA, KL, KA, KL) +}; +#undef V +#undef TL +#undef R +#undef BE +#undef KA +#undef KL +CU_Theory((dds_durability_kind_t dur_kind, dds_reliability_kind_t rel_kind, dds_history_kind_t hist_kind), ddsc_deadline, writer_types, .init = deadline_init, .fini = deadline_fini) +{ + Space_Type1 sample = { 0, 0, 0 }; + dds_entity_t reader, writer; + dds_qos_t *qos; + dds_return_t ret; + void * samples[1]; + dds_sample_info_t info; + Space_Type1 rd_sample; + samples[0] = &rd_sample; + struct dds_offered_deadline_missed_status dstatus; + uint32_t run = 1; + dds_duration_t deadline_dur = WRITER_DEADLINE; + bool test_finished = false; + + do + { + msg("deadline test: duration %"PRId64", writer type %d %d %s", deadline_dur, dur_kind, rel_kind, hist_kind == DDS_HISTORY_KEEP_ALL ? "all" : "1"); + + qos = dds_create_qos(); + CU_ASSERT_PTR_NOT_NULL_FATAL(qos); + dds_qset_durability(qos, dur_kind); + dds_qset_reliability(qos, rel_kind, DDS_INFINITY); + dds_qset_history(qos, hist_kind, (hist_kind == DDS_HISTORY_KEEP_ALL) ? 0 : 1); + dds_qset_deadline(qos, deadline_dur); + writer = dds_create_writer(g_publisher, g_topic, qos, NULL); + CU_ASSERT_FATAL(writer > 0); + reader = create_and_sync_reader(g_participant, g_subscriber, g_topic, qos, writer); + + /* Set status mask on writer to get offered deadline missed status */ + ret = dds_set_status_mask(writer, DDS_OFFERED_DEADLINE_MISSED_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + /* Write sample */ + ret = dds_write (writer, &sample); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + + /* Take sample */ + ret = dds_take (reader, samples, &info, 1, 1); + CU_ASSERT_EQUAL_FATAL (ret, 1); + + /* Sleep 2 * deadline_dur: expect missed deadlines for writer */ + sleepfor(2 * deadline_dur); + ret = dds_get_offered_deadline_missed_status(writer, &dstatus); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + msg("- check writer total actual %u > 0 / change actual %d > 0", dstatus.total_count, dstatus.total_count_change); + if (dstatus.total_count == 0 || dstatus.total_count_change == 0) + deadline_dur *= 10 / (run + 1); + else + { + uint32_t prev_cnt = dstatus.total_count; + + /* Sleep 3 * deadline_dur: expect more missed deadlines for writer */ + sleepfor(3 * deadline_dur); + ret = dds_get_offered_deadline_missed_status(writer, &dstatus); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + msg("- check reader total actual %u > expected %u / change actual %d > 0", dstatus.total_count, prev_cnt, dstatus.total_count_change); + if (dstatus.total_count <= prev_cnt || dstatus.total_count_change == 0) + deadline_dur *= 10 / (run + 1); + else + test_finished = true; + } + + dds_delete_qos(qos); + dds_delete(reader); + dds_delete(writer); + + if (!test_finished) + { + if (++run > MAX_RUNS) + { + msg("run limit reached, test failed"); + CU_FAIL_FATAL("Run limit reached"); + test_finished = true; + } + else + { + msg("restarting test with deadline duration %"PRId64, deadline_dur); + sleepfor(deadline_dur); + } + } + } while (!test_finished); +} + +CU_TheoryDataPoints(ddsc_deadline, instances) = { + CU_DataPoints(int32_t, 1, 10, 10, 100), /* instance count */ + CU_DataPoints(uint8_t, 0, 0, 4, 10), /* unregister every n-th instance */ + CU_DataPoints(uint8_t, 0, 0, 5, 20), /* dispose every n-th instance */ +}; +CU_Theory((int32_t n_inst, uint8_t unreg_nth, uint8_t dispose_nth), ddsc_deadline, instances, .init = deadline_init, .fini = deadline_fini, .timeout = 60) +{ + Space_Type1 sample = { 0, 0, 0 }; + dds_entity_t reader_dl, writer; + dds_return_t ret; + int32_t n, n_unreg, n_dispose, n_alive, run = 1; + bool test_finished = false; + dds_duration_t deadline_dur = WRITER_DEADLINE; + + do + { + msg("deadline test: duration %"PRId64", instance count %d, unreg %dth, dispose %dth", deadline_dur, n_inst, unreg_nth, dispose_nth); + dds_qset_deadline(g_qos, deadline_dur); + CU_ASSERT_PTR_NOT_NULL_FATAL(g_qos); + + writer = dds_create_writer(g_publisher, g_topic, g_qos, NULL); + CU_ASSERT_FATAL(writer > 0); + reader_dl = create_and_sync_reader(g_participant, g_subscriber, g_topic, g_qos, writer); + + /* Write first sample for each instance */ + n_unreg = n_dispose = 0; + for (n = 1; n <= n_inst; n++) + { + sample.long_1 = n; + ret = dds_write (writer, &sample); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + if (unreg_nth && n % unreg_nth == 0) + { + ret = dds_unregister_instance (writer, &sample); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + n_unreg++; + } + else if (dispose_nth && n % dispose_nth == 0) + { + ret = dds_dispose (writer, &sample); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + n_dispose++; + } + } + n_alive = n_inst - n_dispose - n_unreg; + + /* Sleep deadline_dur + 50% and check missed deadline count */ + sleepfor(3 * deadline_dur / 2); + if (!check_missed_deadline_reader(reader_dl, (uint32_t)n_alive, n_alive)) + deadline_dur *= 10 / (run + 1); + else + { + /* Sleep another deadline_dur: expect new trigger for missed deadline for all non-disposed instances */ + sleepfor(deadline_dur); + if (!check_missed_deadline_reader(reader_dl, 2 * (uint32_t)n_alive, n_alive)) + deadline_dur *= 10 / (run + 1); + else + { + /* Write second sample for all (including disposed) instances */ + for (n = 1; n <= n_inst; n++) + { + sample.long_1 = n; + ret = dds_write (writer, &sample); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + } + + /* Sleep deadline_dur + 25%: expect new trigger for missed deadline for non-disposed instances */ + sleepfor(5 * deadline_dur / 4); + if (!check_missed_deadline_reader(reader_dl, 2 * (uint32_t)n_alive + (uint32_t)n_inst, n_inst)) + deadline_dur *= 10 / (run + 1); + else + test_finished = true; + } + } + + dds_delete(reader_dl); + dds_delete(writer); + + if (!test_finished) + { + if (++run > MAX_RUNS) + { + msg("run limit reached, test failed"); + CU_FAIL_FATAL("Run limit reached"); + test_finished = true; + } + else + { + msg("restarting test with deadline duration %"PRId64, deadline_dur); + sleepfor(deadline_dur); + } + } + } while (!test_finished); +} diff --git a/src/core/ddsc/tests/whc.c b/src/core/ddsc/tests/whc.c new file mode 100644 index 0000000..212c51a --- /dev/null +++ b/src/core/ddsc/tests/whc.c @@ -0,0 +1,279 @@ +/* + * 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 +#include + +#include "dds/dds.h" +#include "CUnit/Theory.h" +#include "Space.h" + +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/threads.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsi/ddsi_entity_index.h" +#include "dds/ddsi/q_entity.h" +#include "dds/ddsi/q_whc.h" +#include "dds__entity.h" + +#define DDS_DOMAINID_PUB 0 +#define DDS_DOMAINID_SUB 1 +#define DDS_CONFIG_NO_PORT_GAIN "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}0" +#define DDS_CONFIG_NO_PORT_GAIN_LOG "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}cyclonedds_whc_test.${CYCLONEDDS_DOMAIN_ID}.${CYCLONEDDS_PID}.logfinest0" + +#define SAMPLE_COUNT 5 +#define DEADLINE_DURATION DDS_MSECS(1) + +static uint32_t g_topic_nr = 0; +static dds_entity_t g_domain = 0; +static dds_entity_t g_participant = 0; +static dds_entity_t g_subscriber = 0; +static dds_entity_t g_publisher = 0; +static dds_qos_t *g_qos; +static dds_entity_t g_remote_domain = 0; +static dds_entity_t g_remote_participant = 0; +static dds_entity_t g_remote_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 whc_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_domain = dds_create_domain(DDS_DOMAINID_PUB, conf_pub); + g_remote_domain = dds_create_domain(DDS_DOMAINID_SUB, conf_sub); + dds_free(conf_pub); + dds_free(conf_sub); + + g_qos = dds_create_qos(); + CU_ASSERT_PTR_NOT_NULL_FATAL(g_qos); + + g_participant = dds_create_participant(DDS_DOMAINID_PUB, NULL, NULL); + CU_ASSERT_FATAL(g_participant > 0); + g_remote_participant = dds_create_participant(DDS_DOMAINID_SUB, NULL, NULL); + CU_ASSERT_FATAL(g_remote_participant > 0); + + g_subscriber = dds_create_subscriber(g_participant, NULL, NULL); + CU_ASSERT_FATAL(g_subscriber > 0); + + g_remote_subscriber = dds_create_subscriber(g_remote_participant, NULL, NULL); + CU_ASSERT_FATAL(g_remote_subscriber > 0); + + g_publisher = dds_create_publisher(g_participant, NULL, NULL); + CU_ASSERT_FATAL(g_publisher > 0); +} + +static void whc_fini (void) +{ + dds_delete_qos(g_qos); + dds_delete(g_subscriber); + dds_delete(g_remote_subscriber); + dds_delete(g_publisher); + dds_delete(g_participant); + dds_delete(g_remote_participant); + dds_delete(g_domain); + dds_delete(g_remote_domain); +} + +static dds_entity_t create_and_sync_reader(dds_entity_t subscriber, dds_entity_t topic, dds_qos_t *qos, dds_entity_t writer) +{ + dds_return_t ret; + dds_entity_t reader = dds_create_reader(subscriber, topic, qos, NULL); + CU_ASSERT_FATAL(reader > 0); + while (1) + { + dds_publication_matched_status_t st; + ret = dds_get_publication_matched_status (writer, &st); + CU_ASSERT_FATAL (ret == DDS_RETCODE_OK); + if (st.current_count_change == 1) + break; + dds_sleepfor (DDS_MSECS (1)); + } + return reader; +} + +static void check_whc_state(dds_entity_t writer, seqno_t exp_min, seqno_t exp_max) +{ + struct dds_entity *wr_entity; + struct writer *wr; + struct whc_state whcst; + CU_ASSERT_EQUAL_FATAL(dds_entity_pin(writer, &wr_entity), 0); + thread_state_awake(lookup_thread_state(), &wr_entity->m_domain->gv); + wr = entidx_lookup_writer_guid(wr_entity->m_domain->gv.entity_index, &wr_entity->m_guid); + CU_ASSERT_FATAL(wr != NULL); + assert(wr != NULL); /* for Clang's static analyzer */ + whc_get_state(wr->whc, &whcst); + thread_state_asleep(lookup_thread_state()); + dds_entity_unpin(wr_entity); + + printf(" -- final state: unacked: %zu; min %"PRId64" (exp %"PRId64"); max %"PRId64" (exp %"PRId64")\n", whcst.unacked_bytes, whcst.min_seq, exp_min, whcst.max_seq, exp_max); + CU_ASSERT_EQUAL_FATAL (whcst.unacked_bytes, 0); + CU_ASSERT_EQUAL_FATAL (whcst.min_seq, exp_min); + CU_ASSERT_EQUAL_FATAL (whcst.max_seq, exp_max); +} + + +#define V DDS_DURABILITY_VOLATILE +#define TL DDS_DURABILITY_TRANSIENT_LOCAL +#define R DDS_RELIABILITY_RELIABLE +#define BE DDS_RELIABILITY_BEST_EFFORT +#define KA DDS_HISTORY_KEEP_ALL +#define KL DDS_HISTORY_KEEP_LAST +static void test_whc_end_state(dds_durability_kind_t d, dds_reliability_kind_t r, dds_history_kind_t h, int32_t hd, dds_history_kind_t dh, + int32_t dhd, bool lrd, bool rrd, int32_t ni, bool k, bool dl) +{ + char name[100]; + Space_Type1 sample = { 0, 0, 0 }; + Space_Type3 sample_keyless = { 0, 0, 0 }; + dds_entity_t reader, reader_remote, writer; + dds_entity_t topic; + dds_entity_t remote_topic; + dds_return_t ret; + int32_t s, i; + + printf ("test_whc_end_state: %s, %s, %s(%d), durability %s(%d), readers: %u local, %u remote, instances: %u, key %u, deadline %"PRId64"\n", + d == V ? "volatile" : "TL", + r == BE ? "best-effort" : "reliable", + h == KA ? "keep-all" : "keep-last", h == KA ? 0 : hd, + dh == KA ? "keep-all" : "keep-last", dh == KA ? 0 : dhd, + lrd, rrd, ni, k, + dl ? DEADLINE_DURATION : INT64_C(-1)); + + dds_qset_durability (g_qos, d); + dds_qset_reliability (g_qos, r, DDS_INFINITY); + dds_qset_history (g_qos, h, h == KA ? 0 : hd); + dds_qset_deadline (g_qos, dl ? DEADLINE_DURATION : DDS_INFINITY); + dds_qset_durability_service (g_qos, 0, dh, dh == KA ? 0 : dhd, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED); + + create_topic_name ("ddsc_whc_end_state_test", g_topic_nr++, name, sizeof name); + topic = dds_create_topic (g_participant, k ? &Space_Type1_desc : &Space_Type3_desc, name, NULL, NULL); + CU_ASSERT_FATAL(topic > 0); + remote_topic = dds_create_topic (g_remote_participant, k ? &Space_Type1_desc : &Space_Type3_desc, name, NULL, NULL); + CU_ASSERT_FATAL(remote_topic > 0); + + writer = dds_create_writer (g_publisher, topic, g_qos, NULL); + CU_ASSERT_FATAL(writer > 0); + ret = dds_set_status_mask(writer, DDS_PUBLICATION_MATCHED_STATUS); + CU_ASSERT_FATAL (ret == DDS_RETCODE_OK) + + reader = lrd ? create_and_sync_reader (g_subscriber, topic, g_qos, writer) : 0; + reader_remote = rrd ? create_and_sync_reader (g_remote_subscriber, remote_topic, g_qos, writer) : 0; + + for (s = 0; s < SAMPLE_COUNT; s++) + { + if (k) + for (i = 0; i < ni; i++) + { + sample.long_1 = (int32_t)i; + ret = dds_write (writer, &sample); + CU_ASSERT_FATAL (ret == DDS_RETCODE_OK); + } + else + { + ret = dds_write (writer, &sample_keyless); + CU_ASSERT_FATAL (ret == DDS_RETCODE_OK); + } + } + + /* delete readers, wait until no matching reader */ + if (rrd) + { + ret = dds_delete (reader_remote); + CU_ASSERT_FATAL (ret == DDS_RETCODE_OK); + } + if (lrd) + { + ret = dds_delete (reader); + CU_ASSERT_FATAL (ret == DDS_RETCODE_OK); + } + while (1) + { + dds_publication_matched_status_t st; + ret = dds_get_publication_matched_status (writer, &st); + CU_ASSERT_FATAL (ret == DDS_RETCODE_OK); + if (st.current_count == 0) + break; + dds_sleepfor (DDS_MSECS (1)); + } + + /* check whc state */ + int32_t exp_max = (d == TL) ? ni * SAMPLE_COUNT : -1; + int32_t exp_min = (d == TL) ? ((dh == KA) ? 1 : exp_max - dhd * ni + 1) : -1; + check_whc_state (writer, exp_min, exp_max); + + dds_delete (writer); + dds_delete (remote_topic); + dds_delete (topic); +} + +#define ARRAY_LEN(A) ((int32_t)(sizeof(A) / sizeof(A[0]))) +CU_Test(ddsc_whc, check_end_state, .init=whc_init, .fini=whc_fini, .timeout=30) +{ + dds_durability_kind_t dur[] = {V, TL}; + dds_reliability_kind_t rel[] = {BE, R}; + dds_history_kind_t hist[] = {KA, KL}; + dds_history_kind_t dhist[] = {KA, KL}; + int32_t hist_depth[] = {1, 3}; + int32_t dhist_depth[] = {1, 3}; + bool loc_rd[] = {false, true}; + bool rem_rd[] = {false, true}; + int32_t n_inst[] = {1, 3}; + bool keyed[] = {false, true}; +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + bool deadline[] = {false, true}; +#else + bool deadline[] = {false}; +#endif + int32_t i_d, i_r, i_h, i_hd, i_dh, i_dhd, i_lrd, i_rrd, i_ni, i_k, i_dl; + + for (i_d = 0; i_d < ARRAY_LEN(dur); i_d++) + for (i_r = 0; i_r < ARRAY_LEN(rel); i_r++) + for (i_h = 0; i_h < ARRAY_LEN(hist); i_h++) + for (i_hd = 0; i_hd < ARRAY_LEN(hist_depth); i_hd++) + for (i_dh = 0; i_dh < ARRAY_LEN(dhist); i_dh++) + for (i_dhd = 0; i_dhd < ARRAY_LEN(dhist_depth); i_dhd++) + for (i_lrd = 0; i_lrd < ARRAY_LEN(loc_rd); i_lrd++) + for (i_rrd = 0; i_rrd < ARRAY_LEN(rem_rd); i_rrd++) + for (i_ni = 0; i_ni < ARRAY_LEN(n_inst); i_ni++) + for (i_k = 0; i_k < ARRAY_LEN(keyed); i_k++) + for (i_dl = 0; i_dl < ARRAY_LEN(deadline); i_dl++) + { + if (rel[i_r] == BE && dur[i_d] == TL) + continue; + else if (hist[i_h] == KA && i_hd > 0) + continue; + else if (dhist[i_dh] == KA && i_dhd > 0) + continue; + else + { + test_whc_end_state (dur[i_d], rel[i_r], hist[i_h], hist_depth[i_hd], dhist[i_dh], dhist_depth[i_dhd], + loc_rd[i_lrd], rem_rd[i_rrd], keyed[i_k] ? n_inst[i_ni] : 1, keyed[i_k], deadline[i_dl]); + } + } +} + +#undef ARRAY_LEN +#undef V +#undef TL +#undef R +#undef BE +#undef KA +#undef KL diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 9f85d8e..464f39b 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -30,6 +30,7 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" ddsi_rhc.c ddsi_pmd.c ddsi_entity_index.c + ddsi_deadline.c q_addrset.c q_bitset_inlines.c q_bswap.c @@ -63,6 +64,10 @@ if(ENABLE_LIFESPAN) list(APPEND srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src/ddsi_lifespan.c") endif() +if(ENABLE_DEADLINE_MISSED) + list(APPEND srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src/ddsi_deadline.c") +endif() + # The includes should reside close to the code. As long as that's not the case, # pull them in from this CMakeLists.txt. PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" @@ -86,6 +91,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" ddsi_rhc.h ddsi_guid.h ddsi_entity_index.h + ddsi_deadline.h q_addrset.h q_bitset.h q_bswap.h @@ -125,6 +131,9 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" if(ENABLE_LIFESPAN) list(APPEND hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi/ddsi_lifespan.h") endif() +if(ENABLE_DEADLINE_MISSED) + list(APPEND hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi/ddsi_deadline.h") +endif() target_sources(ddsc PRIVATE ${srcs_ddsi} ${hdrs_private_ddsi}) diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_deadline.h b/src/core/ddsi/include/dds/ddsi/ddsi_deadline.h new file mode 100644 index 0000000..53c250d --- /dev/null +++ b/src/core/ddsi/include/dds/ddsi/ddsi_deadline.h @@ -0,0 +1,84 @@ +/* + * 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_DEADLINE_H +#define DDSI_DEADLINE_H + +#include "dds/ddsrt/circlist.h" +#include "dds/ddsi/q_time.h" +#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/q_xevent.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +typedef nn_mtime_t (*deadline_missed_cb_t)(void *hc, nn_mtime_t tnow); + +struct deadline_adm { + struct ddsrt_circlist list; /* linked list for deadline missed */ + struct xevent *evt; /* xevent that triggers when deadline expires for an instance */ + deadline_missed_cb_t deadline_missed_cb; /* callback for deadline missed; this cb can use deadline_next_missed_locked to get next instance that has a missed deadline */ + size_t list_offset; /* offset of deadline_adm element in whc or rhc */ + size_t elem_offset; /* offset of deadline_elem element in whc or rhc instance */ + dds_duration_t dur; /* deadline duration */ +}; + +struct deadline_elem { + struct ddsrt_circlist_elem e; + nn_mtime_t t_deadline; +}; + +DDS_EXPORT void deadline_init (const struct q_globals *gv, struct deadline_adm *deadline_adm, size_t list_offset, size_t elem_offset, deadline_missed_cb_t deadline_missed_cb); +DDS_EXPORT void deadline_stop (const struct deadline_adm *deadline_adm); +DDS_EXPORT void deadline_clear (struct deadline_adm *deadline_adm); +DDS_EXPORT void deadline_fini (const struct deadline_adm *deadline_adm); +DDS_EXPORT nn_mtime_t deadline_next_missed_locked (struct deadline_adm *deadline_adm, nn_mtime_t tnow, void **instance); +DDS_EXPORT void deadline_register_instance_real (struct deadline_adm *deadline_adm, struct deadline_elem *elem, nn_mtime_t tprev, nn_mtime_t tnow); +DDS_EXPORT void deadline_unregister_instance_real (struct deadline_adm *deadline_adm, struct deadline_elem *elem); +DDS_EXPORT void deadline_renew_instance_real (struct deadline_adm *deadline_adm, struct deadline_elem *elem); + +inline void deadline_register_instance_locked (struct deadline_adm *deadline_adm, struct deadline_elem *elem, nn_mtime_t tnow) +{ + if (deadline_adm->dur != T_NEVER) + deadline_register_instance_real (deadline_adm, elem, tnow, tnow); +} + +inline void deadline_reregister_instance_locked (struct deadline_adm *deadline_adm, struct deadline_elem *elem, nn_mtime_t tnow) +{ + if (deadline_adm->dur != T_NEVER) + deadline_register_instance_real (deadline_adm, elem, elem->t_deadline, tnow); +} + +inline void deadline_unregister_instance_locked (struct deadline_adm *deadline_adm, struct deadline_elem *elem) +{ + if (deadline_adm->dur != T_NEVER) + { + assert (elem->t_deadline.v != T_NEVER); + deadline_unregister_instance_real (deadline_adm, elem); + } +} + +inline void deadline_renew_instance_locked (struct deadline_adm *deadline_adm, struct deadline_elem *elem) +{ + if (deadline_adm->dur != T_NEVER) + { + assert (elem->t_deadline.v != T_NEVER); + deadline_renew_instance_real (deadline_adm, elem); + } +} + +#if defined (__cplusplus) +} +#endif + +#endif /* DDSI_DEADLINE_H */ + diff --git a/src/core/ddsi/src/ddsi_deadline.c b/src/core/ddsi/src/ddsi_deadline.c new file mode 100644 index 0000000..a4775c8 --- /dev/null +++ b/src/core/ddsi/src/ddsi_deadline.c @@ -0,0 +1,112 @@ +/* + * 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 +#include +#include "dds/ddsrt/circlist.h" +#include "dds/ddsi/ddsi_deadline.h" +#include "dds/ddsi/q_time.h" +#include "dds/ddsi/q_xevent.h" + +static void instance_deadline_missed_cb (struct xevent *xev, void *varg, nn_mtime_t tnow) +{ + struct deadline_adm * const deadline_adm = varg; + nn_mtime_t next_valid = deadline_adm->deadline_missed_cb((char *)deadline_adm - deadline_adm->list_offset, tnow); + resched_xevent_if_earlier (xev, next_valid); +} + +/* Gets the instance from the list in deadline admin that has the earliest missed deadline and + * removes the instance element from the list. If no more instances with missed deadline exist + * in the list, the deadline (nn_mtime_t) for the first instance to 'expire' is returned. If the + * list is empty, NN_MTIME_NEVER is returned */ +nn_mtime_t deadline_next_missed_locked (struct deadline_adm *deadline_adm, nn_mtime_t tnow, void **instance) +{ + struct deadline_elem *elem = NULL; + if (!ddsrt_circlist_isempty (&deadline_adm->list)) + { + struct ddsrt_circlist_elem *list_elem = ddsrt_circlist_oldest (&deadline_adm->list); + elem = DDSRT_FROM_CIRCLIST (struct deadline_elem, e, list_elem); + if (elem->t_deadline.v <= tnow.v) + { + ddsrt_circlist_remove (&deadline_adm->list, &elem->e); + if (instance != NULL) + *instance = (char *)elem - deadline_adm->elem_offset; + return (nn_mtime_t) { 0 }; + } + } + if (instance != NULL) + *instance = NULL; + return (elem != NULL) ? elem->t_deadline : NN_MTIME_NEVER; +} + +void deadline_init (const struct q_globals *gv, struct deadline_adm *deadline_adm, size_t list_offset, size_t elem_offset, deadline_missed_cb_t deadline_missed_cb) +{ + ddsrt_circlist_init (&deadline_adm->list); + deadline_adm->evt = qxev_callback (gv->xevents, NN_MTIME_NEVER, instance_deadline_missed_cb, deadline_adm); + deadline_adm->deadline_missed_cb = deadline_missed_cb; + deadline_adm->list_offset = list_offset; + deadline_adm->elem_offset = elem_offset; +} + +void deadline_stop (const struct deadline_adm *deadline_adm) +{ + delete_xevent_callback (deadline_adm->evt); +} + +void deadline_clear (struct deadline_adm *deadline_adm) +{ + while ((deadline_next_missed_locked (deadline_adm, NN_MTIME_NEVER, NULL)).v == 0); +} + +void deadline_fini (const struct deadline_adm *deadline_adm) +{ + assert (ddsrt_circlist_isempty (&deadline_adm->list)); + (void) deadline_adm; +} + +extern inline void deadline_register_instance_locked (struct deadline_adm *deadline_adm, struct deadline_elem *elem, nn_mtime_t tnow); +extern inline void deadline_reregister_instance_locked (struct deadline_adm *deadline_adm, struct deadline_elem *elem, nn_mtime_t tnow); + +void deadline_register_instance_real (struct deadline_adm *deadline_adm, struct deadline_elem *elem, nn_mtime_t tprev, nn_mtime_t tnow) +{ + ddsrt_circlist_append(&deadline_adm->list, &elem->e); + elem->t_deadline = (tprev.v + deadline_adm->dur >= tnow.v) ? tprev : tnow; + elem->t_deadline.v += deadline_adm->dur; + resched_xevent_if_earlier (deadline_adm->evt, elem->t_deadline); +} + +extern inline void deadline_unregister_instance_locked (struct deadline_adm *deadline_adm, struct deadline_elem *elem); + +void deadline_unregister_instance_real (struct deadline_adm *deadline_adm, struct deadline_elem *elem) +{ + /* Updating the scheduled event with the new shortest expiry + * is not required, because the event will be rescheduled when + * this removed element expires. Only remove the element from the + * deadline list */ + + elem->t_deadline = NN_MTIME_NEVER; + ddsrt_circlist_remove(&deadline_adm->list, &elem->e); +} + +extern inline void deadline_renew_instance_locked (struct deadline_adm *deadline_adm, struct deadline_elem *elem); + +void deadline_renew_instance_real (struct deadline_adm *deadline_adm, struct deadline_elem *elem) +{ + /* move element to end of the list (list->latest) and update deadline + according to current deadline duration in rhc (event with old deadline + will still be triggered, but has no effect on this instance because in + the callback the deadline (which will be the updated value) will be + checked for expiry */ + ddsrt_circlist_remove(&deadline_adm->list, &elem->e); + elem->t_deadline = now_mt(); + elem->t_deadline.v += deadline_adm->dur; + ddsrt_circlist_append(&deadline_adm->list, &elem->e); +} diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index e887e35..a4380c8 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -486,6 +486,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * { struct participant *pp; ddsi_guid_t subguid, group_guid; + struct whc_writer_info *wrinfo; /* no reserved bits may be set */ assert ((flags & ~(RTPS_PF_NO_BUILTIN_READERS | RTPS_PF_NO_BUILTIN_WRITERS | RTPS_PF_PRIVILEGED_PP | RTPS_PF_IS_DDSI2_PP | RTPS_PF_ONLY_LOCAL)) == 0); @@ -575,7 +576,9 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) { subguid.entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->spdp_endpoint_xqos, whc_new(gv, 1, 1, 1), NULL, NULL); + wrinfo = whc_make_wrinfo (NULL, &gv->spdp_endpoint_xqos); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->spdp_endpoint_xqos, whc_new(gv, wrinfo), NULL, NULL); + whc_free_wrinfo (wrinfo); /* But we need the as_disc address set for SPDP, because we need to send it to everyone regardless of the existence of readers. */ { @@ -595,14 +598,15 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * entidx_insert_participant_guid (gv->entity_index, pp); /* SEDP writers: */ + wrinfo = whc_make_wrinfo (NULL, &gv->builtin_endpoint_xqos_wr); if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) { subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), NULL, NULL); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), NULL, NULL); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER; } @@ -610,7 +614,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * { /* TODO: make this one configurable, we don't want all participants to publish all topics (or even just those that they use themselves) */ subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), NULL, NULL); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER; } @@ -618,10 +622,12 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) { subguid.entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), NULL, NULL); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER; } + whc_free_wrinfo (wrinfo); + /* SPDP, SEDP, PMD readers: */ if (!(flags & RTPS_PF_NO_BUILTIN_READERS)) { @@ -3020,12 +3026,10 @@ static void gc_delete_writer (struct gcreq *gcreq) /* Do last gasp on SEDP and free writer. */ if (!is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE)) sedp_dispose_unregister_writer (wr); - if (wr->status_cb) - { - (wr->status_cb) (wr->status_cb_entity, NULL); - } - whc_free (wr->whc); + if (wr->status_cb) + (wr->status_cb) (wr->status_cb_entity, NULL); + #ifdef DDSI_INCLUDE_SSM if (wr->ssm_as) unref_addrset (wr->ssm_as); diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 0edf47f..14587a1 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -879,7 +879,8 @@ int enqueue_sample_wrlock_held (struct writer *wr, seqno_t seq, const struct nn_ static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) { /* returns: < 0 on error, 0 if no need to insert in whc, > 0 if inserted */ - int do_insert, insres, res; + int insres, res = 0; + bool wr_deadline = false; ASSERT_MUTEX_HELD (&wr->e.lock); @@ -900,17 +901,15 @@ static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist } assert (wr->reliable || have_reliable_subs (wr) == 0); +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + /* If deadline missed duration is not infinite, the sample is inserted in + the whc so that the instance is created (or renewed) in the whc and the deadline + missed event is registered. The sample is removed immediately after inserting it + as we don't want to store it. */ + wr_deadline = wr->xqos->deadline.deadline != DDS_INFINITY; +#endif - if (wr->reliable && have_reliable_subs (wr)) - do_insert = 1; - else if (wr->handle_as_transient_local) - do_insert = 1; - else - do_insert = 0; - - if (!do_insert) - res = 0; - else + if ((wr->reliable && have_reliable_subs (wr)) || wr_deadline || wr->handle_as_transient_local) { nn_mtime_t exp = NN_MTIME_NEVER; #ifdef DDSI_INCLUDE_LIFESPAN @@ -921,6 +920,20 @@ static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist exp = add_duration_to_mtime(serdata->twrite, wr->xqos->lifespan.duration); #endif res = ((insres = whc_insert (wr->whc, writer_max_drop_seq (wr), seq, exp, plist, serdata, tk)) < 0) ? insres : 1; + +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + if (!(wr->reliable && have_reliable_subs (wr)) && !wr->handle_as_transient_local) + { + /* Sample was inserted only because writer has deadline, so we'll remove the sample from whc */ + struct whc_node *deferred_free_list = NULL; + struct whc_state whcst; + uint32_t n = whc_remove_acked_messages (wr->whc, seq, &whcst, &deferred_free_list); + (void)n; + assert (n <= 1); + assert (whcst.min_seq == -1 && whcst.max_seq == -1); + whc_free_deferred_free_list (wr->whc, deferred_free_list); + } +#endif } #ifndef NDEBUG diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index 69826a2..fc178d1 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -342,14 +342,20 @@ void delete_xevent_callback (struct xevent *ev) struct xeventq *evq = ev->evq; assert (ev->kind == XEVK_CALLBACK); ddsrt_mutex_lock (&evq->lock); - if (ev->tsched.v != T_NEVER) + /* wait until neither scheduled nor executing; loop in case the callback reschedules the event */ + while (ev->tsched.v != T_NEVER || ev->u.callback.executing) { - assert (ev->tsched.v != TSCHED_DELETE); - ddsrt_fibheap_delete (&evq_xevents_fhdef, &evq->xevents, ev); - ev->tsched.v = TSCHED_DELETE; + if (ev->tsched.v != T_NEVER) + { + assert (ev->tsched.v != TSCHED_DELETE); + ddsrt_fibheap_delete (&evq_xevents_fhdef, &evq->xevents, ev); + ev->tsched.v = T_NEVER; + } + if (ev->u.callback.executing) + { + ddsrt_cond_wait (&evq->cond, &evq->lock); + } } - while (ev->u.callback.executing) - ddsrt_cond_wait (&evq->cond, &evq->lock); ddsrt_mutex_unlock (&evq->lock); free_xevent (evq, ev); } diff --git a/src/core/xtests/rhc_torture/rhc_torture.c b/src/core/xtests/rhc_torture/rhc_torture.c index 080f993..8568eeb 100644 --- a/src/core/xtests/rhc_torture/rhc_torture.c +++ b/src/core/xtests/rhc_torture/rhc_torture.c @@ -107,7 +107,7 @@ static struct ddsi_serdata *mkkeysample (int32_t keyval, unsigned statusinfo) return sd; } -#ifdef DDSI_INCLUDE_LIFESPAN +#if defined(DDSI_INCLUDE_LIFESPAN) || defined (DDSI_INCLUDE_DEADLINE_MISSED) static nn_mtime_t rand_texp () { nn_mtime_t ret = now_mt(); @@ -116,6 +116,13 @@ static nn_mtime_t rand_texp () } #endif +#ifdef DDSI_INCLUDE_DEADLINE_MISSED +static dds_duration_t rand_deadline () +{ + return (dds_duration_t) (ddsrt_prng_random (&prng) % DDS_MSECS(500)); +} +#endif + static uint64_t store (struct ddsi_tkmap *tkmap, struct dds_rhc *rhc, struct proxy_writer *wr, struct ddsi_serdata *sd, bool print, bool lifespan_expiry) { #ifndef DDSI_INCLUDE_LIFESPAN @@ -569,6 +576,9 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, dds_qos_t *qos = dds_create_qos (); dds_qset_history (qos, DDS_HISTORY_KEEP_LAST, MAX_HIST_DEPTH); dds_qset_destination_order (qos, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP); +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + dds_qset_deadline (qos, rand_deadline()); +#endif /* two identical readers because we need 63 conditions while we can currently only attach 32 a single reader */ dds_entity_t rd[] = { dds_create_reader (pp, tp, qos, NULL), dds_create_reader (pp, tp, qos, NULL) }; const size_t nrd = sizeof (rd) / sizeof (rd[0]); @@ -673,7 +683,8 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, [9] = "tkc", [10] = "tkc1", [11] = "delwr", - [12] = "drpxp" + [12] = "drpxp", + [13] = "dlmis" }; static const uint32_t opfreqs[] = { [0] = 500, /* write */ @@ -689,9 +700,14 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, [10] = 100, /* take cond, max 1 */ [11] = 1, /* unreg writer */ #ifdef DDSI_INCLUDE_LIFESPAN - [12] = 100 /* drop expired sample */ + [12] = 100, /* drop expired sample */ #else - [12] = 0 /* drop expired sample */ + [12] = 0, /* drop expired sample */ +#endif +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + [13] = 100 /* deadline missed */ +#else + [13] = 0 /* drop expired sample */ #endif }; uint32_t opthres[sizeof (opfreqs) / sizeof (opfreqs[0])]; @@ -829,6 +845,16 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, for (size_t k = 0; k < nrd; k++) (void) dds_rhc_default_sample_expired_cb (rhc[k], rand_texp()); thread_state_asleep (lookup_thread_state ()); +#endif + break; + } + case 13: { +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + thread_state_awake_domain_ok (lookup_thread_state ()); + /* We can assume that rhc[k] is a dds_rhc_default at this point */ + for (size_t k = 0; k < nrd; k++) + (void) dds_rhc_default_deadline_missed_cb (rhc[k], rand_texp()); + thread_state_asleep (lookup_thread_state ()); #endif break; } diff --git a/src/mpt/tests/qos/procs/rw.c b/src/mpt/tests/qos/procs/rw.c index 10cceee..6f7ad0b 100644 --- a/src/mpt/tests/qos/procs/rw.c +++ b/src/mpt/tests/qos/procs/rw.c @@ -98,7 +98,11 @@ static void setqos (dds_qos_t *q, size_t i, bool isrd, bool create) #else dds_qset_lifespan (q, DDS_INFINITY); #endif +#ifdef DDSI_INCLUDE_DEADLINE_MISSED dds_qset_deadline (q, INT64_C (67890123456789012) + (int32_t) i); +#else + dds_qset_deadline (q, DDS_INFINITY); +#endif dds_qset_latency_budget (q, INT64_C (45678901234567890) + (int32_t) i); dds_qset_ownership (q, (dds_ownership_kind_t) ((i + 1) % 2)); dds_qset_ownership_strength (q, 0x12345670 + (int32_t) i); From 60e51479c1109e00666075f1c3c0579e336ead36 Mon Sep 17 00:00:00 2001 From: Thijs Sassen Date: Tue, 14 Jan 2020 17:02:10 +0100 Subject: [PATCH 05/28] Added extra header file needed to work around an issue(see issue #74) when reading samples in c++ And updated dds_read_instance_mask and dds_take_instance_mask to work with DDS_READ_WITHOUT_LOCK Signed-off-by: Thijs Sassen --- src/core/ddsc/CMakeLists.txt | 1 + .../ddsc/include/dds/ddsc/dds_internal_api.h | 44 +++++++++++++++++++ src/core/ddsc/src/dds_read.c | 4 +- 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 src/core/ddsc/include/dds/ddsc/dds_internal_api.h diff --git a/src/core/ddsc/CMakeLists.txt b/src/core/ddsc/CMakeLists.txt index b32a4b5..65c6c34 100644 --- a/src/core/ddsc/CMakeLists.txt +++ b/src/core/ddsc/CMakeLists.txt @@ -51,6 +51,7 @@ PREPEND(hdrs_public_ddsc "$ Date: Wed, 15 Jan 2020 12:42:08 +0100 Subject: [PATCH 06/28] Implement dds_wait_for_acks (writer only) Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds__writer.h | 1 + src/core/ddsc/src/dds_publisher.c | 28 +++++++++++++++++++++-- src/core/ddsc/src/dds_writer.c | 10 ++++++++ src/core/ddsc/tests/unsupported.c | 15 ------------ src/core/ddsi/include/dds/ddsi/q_entity.h | 3 ++- src/core/ddsi/src/q_entity.c | 20 ++++++++++++---- 6 files changed, 55 insertions(+), 22 deletions(-) diff --git a/src/core/ddsc/src/dds__writer.h b/src/core/ddsc/src/dds__writer.h index 0f1b7ef..69ff7e1 100644 --- a/src/core/ddsc/src/dds__writer.h +++ b/src/core/ddsc/src/dds__writer.h @@ -23,6 +23,7 @@ DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_writer, DDS_KIND_WRITER) struct status_cb_data; void dds_writer_status_cb (void *entity, const struct status_cb_data * data); +dds_return_t dds__writer_wait_for_acks (struct dds_writer *wr, dds_time_t abstimeout); #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds_publisher.c b/src/core/ddsc/src/dds_publisher.c index ae20658..b6f0792 100644 --- a/src/core/ddsc/src/dds_publisher.c +++ b/src/core/ddsc/src/dds_publisher.c @@ -15,6 +15,7 @@ #include "dds__listener.h" #include "dds__participant.h" #include "dds__publisher.h" +#include "dds__writer.h" #include "dds__qos.h" #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/q_entity.h" @@ -94,10 +95,33 @@ dds_return_t dds_resume (dds_entity_t publisher) dds_return_t dds_wait_for_acks (dds_entity_t publisher_or_writer, dds_duration_t timeout) { + dds_return_t ret; + dds_entity *p_or_w_ent; + if (timeout < 0) return DDS_RETCODE_BAD_PARAMETER; - static const dds_entity_kind_t kinds[] = { DDS_KIND_WRITER, DDS_KIND_PUBLISHER }; - return dds_generic_unimplemented_operation_manykinds (publisher_or_writer, sizeof (kinds) / sizeof (kinds[0]), kinds); + + if ((ret = dds_entity_pin (publisher_or_writer, &p_or_w_ent)) < 0) + return ret; + + const dds_time_t tnow = dds_time (); + const dds_time_t abstimeout = (DDS_INFINITY - timeout <= tnow) ? DDS_NEVER : (tnow + timeout); + switch (dds_entity_kind (p_or_w_ent)) + { + case DDS_KIND_PUBLISHER: + /* FIXME: wait_for_acks on all writers of the same publisher */ + dds_entity_unpin (p_or_w_ent); + return DDS_RETCODE_UNSUPPORTED; + + case DDS_KIND_WRITER: + ret = dds__writer_wait_for_acks ((struct dds_writer *) p_or_w_ent, abstimeout); + dds_entity_unpin (p_or_w_ent); + return ret; + + default: + dds_entity_unpin (p_or_w_ent); + return DDS_RETCODE_ILLEGAL_OPERATION; + } } dds_return_t dds_publisher_begin_coherent (dds_entity_t publisher) diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 1e023c1..163d4e1 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -379,6 +379,16 @@ dds_entity_t dds_get_publisher (dds_entity_t writer) } } +dds_return_t dds__writer_wait_for_acks (struct dds_writer *wr, dds_time_t abstimeout) +{ + /* during lifetime of the writer m_wr is constant, it is only during deletion that it + gets erased at some point */ + if (wr->m_wr == NULL) + return DDS_RETCODE_OK; + else + return writer_wait_for_acks (wr->m_wr, abstimeout); +} + DDS_GET_STATUS(writer, publication_matched, PUBLICATION_MATCHED, total_count_change, current_count_change) DDS_GET_STATUS(writer, liveliness_lost, LIVELINESS_LOST, total_count_change) DDS_GET_STATUS(writer, offered_deadline_missed, OFFERED_DEADLINE_MISSED, total_count_change) diff --git a/src/core/ddsc/tests/unsupported.c b/src/core/ddsc/tests/unsupported.c index b7e63cb..9c538ce 100644 --- a/src/core/ddsc/tests/unsupported.c +++ b/src/core/ddsc/tests/unsupported.c @@ -84,21 +84,6 @@ CU_Test(ddsc_unsupported, dds_begin_end_coherent, .init = setup, .fini = teardow } } -CU_Test(ddsc_unsupported, dds_wait_for_acks, .init = setup, .fini = teardown) -{ - dds_return_t result; - static struct index_result pars[] = { - {PUB, DDS_RETCODE_UNSUPPORTED}, - {WRI, DDS_RETCODE_UNSUPPORTED}, - {BAD, DDS_RETCODE_BAD_PARAMETER} - }; - - for (size_t i=0; i < sizeof (pars) / sizeof (pars[0]);i++) { - result = dds_wait_for_acks(e[pars[i].index], 0); - CU_ASSERT_EQUAL(result, pars[i].exp_res); - } -} - CU_Test(ddsc_unsupported, dds_suspend_resume, .init = setup, .fini = teardown) { dds_return_t result; diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 778d5c0..f177a83 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -240,7 +240,7 @@ struct writer struct endpoint_common c; status_cb_t status_cb; void * status_cb_entity; - ddsrt_cond_t throttle_cond; /* used to trigger a transmit thread blocked in throttle_writer() */ + ddsrt_cond_t throttle_cond; /* used to trigger a transmit thread blocked in throttle_writer() or wait_for_acks() */ seqno_t seq; /* last sequence number (transmitted seqs are 1 ... seq) */ seqno_t cs_seq; /* 1st seq in coherent set (or 0) */ seq_xmit_t seq_xmit; /* last sequence number actually transmitted */ @@ -605,6 +605,7 @@ seqno_t writer_max_drop_seq (const struct writer *wr); int writer_must_have_hb_scheduled (const struct writer *wr, const struct whc_state *whcst); void writer_set_retransmitting (struct writer *wr); void writer_clear_retransmitting (struct writer *wr); +dds_return_t writer_wait_for_acks (struct writer *wr, dds_time_t abstimeout); dds_return_t unblock_throttled_writer (struct q_globals *gv, const struct ddsi_guid *guid); dds_return_t delete_writer (struct q_globals *gv, const struct ddsi_guid *guid); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index a4380c8..1bed076 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -2690,10 +2690,8 @@ unsigned remove_acked_messages (struct writer *wr, struct whc_state *whcst, stru assert (wr->e.guid.entityid.u != NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER); ASSERT_MUTEX_HELD (&wr->e.lock); n = whc_remove_acked_messages (wr->whc, writer_max_drop_seq (wr), whcst, deferred_free_list); - /* when transitioning from >= low-water to < low-water, signal - anyone waiting in throttle_writer() */ - if (wr->throttling && whcst->unacked_bytes <= wr->whc_low) - ddsrt_cond_broadcast (&wr->throttle_cond); + /* trigger anyone waiting in throttle_writer() or wait_for_acks() */ + ddsrt_cond_broadcast (&wr->throttle_cond); if (wr->retransmitting && whcst->unacked_bytes == 0) writer_clear_retransmitting (wr); if (wr->state == WRST_LINGERING && whcst->unacked_bytes == 0) @@ -3092,6 +3090,20 @@ dds_return_t unblock_throttled_writer (struct q_globals *gv, const struct ddsi_g return 0; } +dds_return_t writer_wait_for_acks (struct writer *wr, dds_time_t abstimeout) +{ + dds_return_t rc; + seqno_t ref_seq; + ddsrt_mutex_lock (&wr->e.lock); + ref_seq = wr->seq; + while (wr->state == WRST_OPERATIONAL && ref_seq > writer_max_drop_seq (wr)) + if (!ddsrt_cond_waituntil (&wr->throttle_cond, &wr->e.lock, abstimeout)) + break; + rc = (ref_seq <= writer_max_drop_seq (wr)) ? DDS_RETCODE_OK : DDS_RETCODE_TIMEOUT; + ddsrt_mutex_unlock (&wr->e.lock); + return rc; +} + dds_return_t delete_writer_nolinger_locked (struct writer *wr) { ELOGDISC (wr, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (wr->e.guid)); From 1ed7a65b4fed0c3218271b010e8c9386d4880061 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 15 Jan 2020 12:42:48 +0100 Subject: [PATCH 07/28] Give interface name when warning about multicast Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 5365f4d..11abfa4 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -957,7 +957,7 @@ int rtps_init (struct q_globals *gv) { if (!gv->interfaces[gv->selected_interface].mc_capable) { - GVWARNING ("selected interface is not multicast-capable: disabling multicast\n"); + GVWARNING ("selected interface \"%s\" is not multicast-capable: disabling multicast\n", gv->interfaces[gv->selected_interface].name); gv->config.allowMulticast = AMC_FALSE; /* ensure discovery can work: firstly, that the process will be reachable on a "well-known" port number, and secondly, that the local interface's IP address gets added to the discovery From 0f527135fc8f7b1e1d4fc43443e008518500fc2a Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 15 Jan 2020 12:43:59 +0100 Subject: [PATCH 08/28] Fix pwr lease expiry during pwr creation The transition to not-alive can occur between registering the lease and making the proxy writer visible in the GUID hash table, so handling lease expiry for proxy writer must not depend on it being visible there. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_entity.h | 1 - src/core/ddsi/src/q_entity.c | 14 -------------- src/core/ddsi/src/q_lease.c | 2 +- 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index f177a83..62dabfe 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -676,7 +676,6 @@ void update_proxy_writer (struct proxy_writer *pwr, seqno_t seq, struct addrset 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); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 1bed076..5510835 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -4510,20 +4510,6 @@ int proxy_writer_set_notalive (struct proxy_writer *pwr, bool notify) 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 = entidx_lookup_proxy_writer_guid (gv->entity_index, 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 ----------------------------------------------------- */ int new_proxy_reader (struct q_globals *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const nn_plist_t *plist, nn_wctime_t timestamp, seqno_t seq diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index a903ab2..6a2d33a 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -281,7 +281,7 @@ int64_t check_and_handle_lease_expiration (struct q_globals *gv, nn_etime_t tnow delete_proxy_participant_by_guid (gv, &g, now(), 1); break; case EK_PROXY_WRITER: - proxy_writer_set_notalive_guid (gv, &g, true); + proxy_writer_set_notalive ((struct proxy_writer *) l->entity, true); break; case EK_PARTICIPANT: case EK_READER: From 5632ed46b53be920ed5c7d27872612368c7e6e10 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 15 Jan 2020 12:47:44 +0100 Subject: [PATCH 09/28] Register manual-by-topic lease in transition to alive Lease handling removes expired leases from the heap, and so a proxy writer that transitions from not-alive to alive needs to re-schedule expiry again or it will remain alive forever after having regained liveliness once. This was missing for a manual-by-topic lease. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_entity.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 5510835..abc9976 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -4478,8 +4478,13 @@ void proxy_writer_set_alive_may_unlock (struct proxy_writer *pwr, bool notify) 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); + if (pwr->c.xqos->liveliness.lease_duration != T_NEVER) + { + if (pwr->c.xqos->liveliness.kind != DDS_LIVELINESS_MANUAL_BY_TOPIC) + proxy_participant_add_pwr_lease_locked (pwr->c.proxypp, pwr); + else + lease_set_expiry (pwr->lease, add_duration_to_etime (now_et (), pwr->lease->tdur)); + } ddsrt_mutex_unlock (&pwr->c.proxypp->e.lock); if (notify) From 4af531a1c3e66acc8f3db4b73064bbcef0e0cb75 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 15 Jan 2020 12:50:01 +0100 Subject: [PATCH 10/28] Add a test for duration 0ns and 1ns manual lease Signed-off-by: Erik Boasson --- .travis.yml | 2 +- src/core/ddsc/tests/liveliness.c | 269 +++++++++++++++++++++++++++++++ 2 files changed, 270 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f2f8ef3..1be51fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -215,7 +215,7 @@ script: ${SCAN_BUILD} cmake --build . --config ${BUILD_TYPE} --target install ;; esac - - CYCLONEDDS_URI='allconfigstderr' ctest -j 4 --output-on-failure -T test -E '^CUnit_ddsrt_random_default_random$' -C ${BUILD_TYPE} + - CYCLONEDDS_URI='alltrueconfigstderr' ctest -j 4 --output-on-failure -T test -E '^CUnit_ddsrt_random_default_random$' -C ${BUILD_TYPE} - if [ "${ASAN}" != "none" ]; then CMAKE_LINKER_FLAGS="-DCMAKE_LINKER_FLAGS=-fsanitize=${USE_SANITIZER}"; CMAKE_C_FLAGS="-DCMAKE_C_FLAGS=-fsanitize=${USE_SANITIZER}"; diff --git a/src/core/ddsc/tests/liveliness.c b/src/core/ddsc/tests/liveliness.c index 0976c5f..856e897 100644 --- a/src/core/ddsc/tests/liveliness.c +++ b/src/core/ddsc/tests/liveliness.c @@ -814,3 +814,272 @@ CU_Theory((uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp) } while (!test_finished); } #undef MAX_WRITERS + +/** + * Check that manual-by-participant/topic writers with lease duration 0ns and 1ns work. + */ +struct liveliness_changed_state { + ddsrt_mutex_t lock; + dds_instance_handle_t w0_handle; + bool weirdness; + uint32_t w0_alive, w0_not_alive; +}; + +static void liveliness_changed_listener (dds_entity_t rd, const dds_liveliness_changed_status_t status, void *arg) +{ + struct liveliness_changed_state *st = arg; + (void) rd; + + ddsrt_mutex_lock (&st->lock); + if (status.last_publication_handle != st->w0_handle) + { + if (st->w0_handle == 0) + { + printf ("liveliness_changed_listener: w0 = %"PRIx64"\n", status.last_publication_handle); + st->w0_handle = status.last_publication_handle; + } + else + { + printf ("liveliness_changed_listener: too many writer handles\n"); + st->weirdness = true; + } + } + + if (status.alive_count_change != 0 || status.not_alive_count_change != 0) + { + switch (status.alive_count_change) + { + case -1: + break; + case 1: + if (status.last_publication_handle == st->w0_handle) + st->w0_alive++; + else + { + printf ("liveliness_changed_listener: alive_count_change = %d: unrecognized writer\n", status.alive_count_change); + st->weirdness = true; + } + break; + default: + printf ("liveliness_changed_listener: alive_count_change = %d\n", status.alive_count_change); + st->weirdness = true; + } + + switch (status.not_alive_count_change) + { + case -1: + break; + case 1: + if (status.last_publication_handle == st->w0_handle) + st->w0_not_alive++; + else + { + printf ("liveliness_changed_listener: not_alive_count_change = %d: unrecognized writer\n", status.not_alive_count_change); + st->weirdness = true; + } + break; + default: + printf ("liveliness_changed_listener: not_alive_count_change = %d\n", status.not_alive_count_change); + st->weirdness = true; + } + } + ddsrt_mutex_unlock (&st->lock); +} + +static bool get_and_check_status (dds_entity_t reader, dds_entity_t writer_active) +{ + struct dds_liveliness_changed_status lstatus; + struct dds_subscription_matched_status sstatus; + struct dds_publication_matched_status pstatus; + dds_return_t rc; + rc = dds_get_subscription_matched_status(reader, &sstatus); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + rc = dds_get_liveliness_changed_status(reader, &lstatus); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + rc = dds_get_publication_matched_status(writer_active, &pstatus); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + CU_ASSERT_FATAL(lstatus.alive_count + lstatus.not_alive_count <= 2); + printf ("%d %d %d %d\n", (int)sstatus.current_count, (int)lstatus.alive_count, (int)lstatus.not_alive_count, (int)pstatus.current_count); + return (sstatus.current_count == 2 && lstatus.not_alive_count == 2 && pstatus.current_count == 1); +} + +static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_liveliness_kind_t lkind, dds_duration_t ldur) +{ + const uint32_t nsamples = (sleep <= DDS_MSECS(10)) ? 100 : 10; + dds_entity_t pub_topic; + dds_entity_t sub_topic; + dds_entity_t reader; + dds_entity_t writer_active; /* writing */ + dds_entity_t writer_inactive; /* not writing, liveliness should still toggle */ + dds_entity_t waitset; + dds_listener_t *listener; + dds_qos_t *qos; + dds_return_t rc; + struct dds_liveliness_changed_status lstatus; + char name[100]; + Space_Type1 sample = {1, 0, 0}; + struct liveliness_changed_state listener_state = { + .weirdness = false, + .w0_handle = 0, + .w0_alive = 0, + .w0_not_alive = 0, + }; + ddsrt_mutex_init (&listener_state.lock); + + waitset = dds_create_waitset(DDS_CYCLONEDDS_HANDLE); + CU_ASSERT_FATAL(waitset > 0); + + qos = dds_create_qos(); + CU_ASSERT_FATAL(qos != NULL); + dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); + dds_qset_history(qos, DDS_HISTORY_KEEP_ALL, 0); + + create_topic_name("ddsc_liveliness_lease_duration_zero", g_topic_nr++, name, sizeof name); + pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, qos, NULL); + CU_ASSERT_FATAL(pub_topic > 0); + sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, qos, NULL); + CU_ASSERT_FATAL(sub_topic > 0); + + /* reader liveliness is always automatic/infinity */ + dds_qset_liveliness(qos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY); + reader = dds_create_reader(g_sub_participant, sub_topic, qos, NULL); + CU_ASSERT_FATAL(reader > 0); + rc = dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS | DDS_SUBSCRIPTION_MATCHED_STATUS); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + rc = dds_waitset_attach(waitset, reader, reader); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + + /* writer liveliness varies */ + dds_qset_liveliness(qos, lkind, ldur); + writer_active = dds_create_writer(g_pub_participant, pub_topic, qos, NULL); + CU_ASSERT_FATAL(writer_active > 0); + writer_inactive = dds_create_writer(g_pub_participant, pub_topic, qos, NULL); + CU_ASSERT_FATAL(writer_inactive > 0); + rc = dds_set_status_mask(writer_active, DDS_PUBLICATION_MATCHED_STATUS); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + rc = dds_waitset_attach(waitset, writer_active, writer_active); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + + dds_delete_qos(qos); + + /* wait for writers to be discovered and to have lost their liveliness, and for + writer_active to have discovered the reader */ + while (!get_and_check_status (reader, writer_active)) + { + rc = dds_waitset_wait(waitset, NULL, 0, DDS_SECS(5)); + if (rc < 1) + { + get_and_check_status (reader, writer_active); + CU_ASSERT_FATAL(rc >= 1); + } + } + + /* switch to using a listener: those allow us to observe all events */ + listener = dds_create_listener (&listener_state); + dds_lset_liveliness_changed(listener, liveliness_changed_listener); + rc = dds_set_listener (reader, listener); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + dds_delete_listener (listener); + + /* write as fast as possible - we don't expect this to cause the writers + to gain and lose liveliness once for each sample, but it should have + become alive at least once and fall back to not alive afterward */ + for (uint32_t i = 0; i < nsamples; i++) + { + rc = dds_write(writer_active, &sample); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + if (sleep && i < nsamples - 1) + dds_sleepfor(sleep); + } + + rc = dds_wait_for_acks(writer_active, DDS_SECS(5)); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + + /* verify the reader received all samples */ + { + void *raw[] = { &sample }; + dds_sample_info_t si; + uint32_t cnt = 0; + while (dds_take(reader, raw, &si, 1, 1) == 1) + cnt++; + CU_ASSERT(cnt == nsamples); + } + + /* transition to not alive is not necessarily immediate */ + { + int retries = 100; + rc = dds_get_liveliness_changed_status(reader, &lstatus); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + printf("early liveliness changed status: alive %"PRId32" not-alive %"PRId32"\n", lstatus.alive_count, lstatus.not_alive_count); + + ddsrt_mutex_lock (&listener_state.lock); + printf("early w0 %"PRIx64" alive %"PRId32" not-alive %"PRId32"\n", listener_state.w0_handle, listener_state.w0_alive, listener_state.w0_not_alive); + CU_ASSERT(!listener_state.weirdness); + CU_ASSERT(listener_state.w0_handle != 0); + while (listener_state.w0_not_alive < listener_state.w0_alive && retries-- > 0) + { + ddsrt_mutex_unlock(&listener_state.lock); + dds_sleepfor(DDS_MSECS(10)); + rc = dds_get_liveliness_changed_status(reader, &lstatus); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + ddsrt_mutex_lock(&listener_state.lock); + } + + printf("late liveliness changed status: alive %"PRId32" not-alive %"PRId32"\n", lstatus.alive_count, lstatus.not_alive_count); + printf("final w0 %"PRIx64" alive %"PRId32" not-alive %"PRId32"\n", listener_state.w0_handle, listener_state.w0_alive, listener_state.w0_not_alive); + CU_ASSERT(listener_state.w0_alive == listener_state.w0_not_alive); + if (sleep == 0) + { + /* if not sleeping, it's ok if the transition happens only once */ + CU_ASSERT(listener_state.w0_alive > 0); + } + else if (sleep <= DDS_MSECS(10)) + { + /* if sleeping briefly, expect the a good number of writes to toggle liveliness */ + CU_ASSERT(listener_state.w0_alive >= nsamples / 3); + } + else + { + /* if sleeping, expect the vast majority (90%) of the writes to toggle liveliness */ + CU_ASSERT(listener_state.w0_alive >= nsamples - nsamples / 10); + } + ddsrt_mutex_unlock(&listener_state.lock); + } + + /* cleanup */ + rc = dds_delete(waitset); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + rc = dds_delete(reader); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + rc = dds_delete(writer_active); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + rc = dds_delete(writer_inactive); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + rc = dds_delete(sub_topic); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + rc = dds_delete(pub_topic); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + + ddsrt_mutex_destroy(&listener_state.lock); +} + +CU_Test(ddsc_liveliness, lease_duration_zero_or_one, .init = liveliness_init, .fini = liveliness_fini, .timeout = 30) +{ + static const dds_duration_t sleep[] = { 0, DDS_MSECS(10), DDS_MSECS(100) }; + static const dds_liveliness_kind_t lkind[] = { DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_LIVELINESS_MANUAL_BY_TOPIC }; + static const dds_duration_t ldur[] = { 0, 1 }; + for (size_t sleep_idx = 0; sleep_idx < sizeof (sleep) / sizeof (sleep[0]); sleep_idx++) + { + for (size_t lkind_idx = 0; lkind_idx < sizeof (lkind) / sizeof (lkind[0]); lkind_idx++) + { + for (size_t ldur_idx = 0; ldur_idx < sizeof (ldur) / sizeof (ldur[0]); ldur_idx++) + { + dds_duration_t s = sleep[sleep_idx]; + dds_liveliness_kind_t k = lkind[lkind_idx]; + dds_duration_t d = ldur[ldur_idx]; + printf ("lease_duration_zero_or_one: sleep = %"PRId64" lkind = %d ldur = %"PRId64"\n", s, (int) k, d); + lease_duration_zero_or_one_impl (s, k, d); + } + } + } +} From be327f5e56ac597438f37c0b1cbf2ca48d8c6116 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 16 Jan 2020 16:30:24 +0100 Subject: [PATCH 11/28] Fix race between DCPSParticipant write and lease expiry Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_entity.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index abc9976..5f91343 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -3845,13 +3845,15 @@ void new_proxy_participant (struct q_globals *gv, const struct ddsi_guid *ppguid nn_plist_fini (&plist_rd); } + /* write DCPSParticipant topic before the lease can expire */ + builtintopic_write (gv->builtin_topic_interface, &proxypp->e, timestamp, true); + /* 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 entidx_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->minl_auto)); - builtintopic_write (gv->builtin_topic_interface, &proxypp->e, timestamp, true); ddsrt_mutex_unlock (&proxypp->e.lock); } From 263d8016b84487cf34b5a3ab6de3bf9b5226057a Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 20 Jan 2020 16:14:01 +0100 Subject: [PATCH 12/28] Fix macros for testing presence of atomic LIFO Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_freelist.h | 12 ++++++------ src/core/ddsi/src/q_freelist.c | 6 +++--- src/ddsrt/include/dds/ddsrt/circlist.h | 2 +- src/ddsrt/src/atomics.c | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_freelist.h b/src/core/ddsi/include/dds/ddsi/q_freelist.h index 75b4fc0..84cc3e5 100644 --- a/src/core/ddsi/include/dds/ddsi/q_freelist.h +++ b/src/core/ddsi/include/dds/ddsi/q_freelist.h @@ -25,11 +25,11 @@ extern "C" { #define FREELIST_TYPE FREELIST_DOUBLE -#if 0 -#if HAVE_ATOMIC_LIFO +#ifndef FREELIST_TYPE +#if DDSRT_HAVE_ATOMIC_LIFO #define FREELIST_TYPE FREELIST_ATOMIC_LIFO #else -#define FREELIST_TYPE FREELIST_SIMPLE +#define FREELIST_TYPE FREELIST_DOUBLE #endif #endif @@ -45,7 +45,7 @@ struct nn_freelist { ddsrt_atomic_lifo_t x; ddsrt_atomic_uint32_t count; uint32_t max; - off_t linkoff; + size_t linkoff; }; #elif FREELIST_TYPE == FREELIST_DOUBLE @@ -73,12 +73,12 @@ struct nn_freelist { struct nn_freelistM *emlist; uint32_t count; uint32_t max; - off_t linkoff; + size_t linkoff; }; #endif -void nn_freelist_init (struct nn_freelist *fl, uint32_t max, off_t linkoff); +void nn_freelist_init (struct nn_freelist *fl, uint32_t max, size_t linkoff); void nn_freelist_fini (struct nn_freelist *fl, void (*free) (void *elem)); bool nn_freelist_push (struct nn_freelist *fl, void *elem); void *nn_freelist_pushmany (struct nn_freelist *fl, void *first, void *last, uint32_t n); diff --git a/src/core/ddsi/src/q_freelist.c b/src/core/ddsi/src/q_freelist.c index 9d1a1bc..28ed6ea 100644 --- a/src/core/ddsi/src/q_freelist.c +++ b/src/core/ddsi/src/q_freelist.c @@ -20,7 +20,7 @@ #if FREELIST_TYPE == FREELIST_NONE -void nn_freelist_init (struct nn_freelist *fl, uint32_t max, off_t linkoff) +void nn_freelist_init (struct nn_freelist *fl, uint32_t max, size_t linkoff) { (void) fl; (void) max; (void) linkoff; } @@ -50,7 +50,7 @@ void *nn_freelist_pop (struct nn_freelist *fl) #elif FREELIST_TYPE == FREELIST_ATOMIC_LIFO -void nn_freelist_init (struct nn_freelist *fl, uint32_t max, off_t linkoff) +void nn_freelist_init (struct nn_freelist *fl, uint32_t max, size_t linkoff) { ddsrt_atomic_lifo_init (&fl->x); ddsrt_atomic_st32(&fl->count, 0); @@ -104,7 +104,7 @@ void *nn_freelist_pop (struct nn_freelist *fl) static ddsrt_thread_local int freelist_inner_idx = -1; -void nn_freelist_init (struct nn_freelist *fl, uint32_t max, off_t linkoff) +void nn_freelist_init (struct nn_freelist *fl, uint32_t max, size_t linkoff) { int i; ddsrt_mutex_init (&fl->lock); diff --git a/src/ddsrt/include/dds/ddsrt/circlist.h b/src/ddsrt/include/dds/ddsrt/circlist.h index 3c4ca56..767b582 100644 --- a/src/ddsrt/include/dds/ddsrt/circlist.h +++ b/src/ddsrt/include/dds/ddsrt/circlist.h @@ -40,4 +40,4 @@ DDS_EXPORT void ddsrt_circlist_remove (struct ddsrt_circlist *list, struct ddsrt DDS_EXPORT struct ddsrt_circlist_elem *ddsrt_circlist_oldest (const struct ddsrt_circlist *list); DDS_EXPORT struct ddsrt_circlist_elem *ddsrt_circlist_latest (const struct ddsrt_circlist *list); -#endif /* DDSRT_CIRCLIST_H */ \ No newline at end of file +#endif /* DDSRT_CIRCLIST_H */ diff --git a/src/ddsrt/src/atomics.c b/src/ddsrt/src/atomics.c index 829be41..88512da 100644 --- a/src/ddsrt/src/atomics.c +++ b/src/ddsrt/src/atomics.c @@ -119,7 +119,7 @@ extern inline int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_ #endif extern inline int ddsrt_atomic_casptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t exp, uintptr_t des); extern inline int ddsrt_atomic_casvoidp (volatile ddsrt_atomic_voidp_t *x, void *exp, void *des); -#if DDSRT_ATOMIC_LIFO_SUPPORT +#if DDSRT_HAVE_ATOMIC_LIFO extern inline int ddsrt_atomic_casvoidp2 (volatile ddsrt_atomic_uintptr2_t *x, uintptr_t a0, uintptr_t b0, uintptr_t a1, uintptr_t b1); #endif /* FENCES */ @@ -129,7 +129,7 @@ extern inline void ddsrt_atomic_fence_stst (void); extern inline void ddsrt_atomic_fence_acq (void); extern inline void ddsrt_atomic_fence_rel (void); -#if DDSRT_ATOMIC_LIFO_SUPPORT +#if DDSRT_HAVE_ATOMIC_LIFO void ddsrt_atomic_lifo_init (ddsrt_atomic_lifo_t *head) { head->aba_head.s.a = head->aba_head.s.b = 0; From bb7679849299f3314e00b605f8ec2e90bea33de4 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 22 Jan 2020 10:41:02 +0100 Subject: [PATCH 13/28] Default to a single receive thread on Windows This works around a termination issue on Windows caused by the process sometimes being unable to send a packet to itself to wake up a thread stuck in a blocking read on a socket. Signed-off-by: Erik Boasson --- docs/makernc.pl | 2 +- docs/manual/options.md | 14 +++++----- etc/cyclonedds.rnc | 31 +++++++++++++---------- etc/cyclonedds.xsd | 22 +++++++++++----- src/core/ddsi/include/dds/ddsi/q_config.h | 2 +- src/core/ddsi/src/q_config.c | 8 +++--- src/core/ddsi/src/q_init.c | 30 +++++++++++++++++++++- 7 files changed, 75 insertions(+), 34 deletions(-) diff --git a/docs/makernc.pl b/docs/makernc.pl index 07a67db..2daaa57 100644 --- a/docs/makernc.pl +++ b/docs/makernc.pl @@ -344,7 +344,7 @@ sub conv_to_rnc { } elsif ($fs->{kstr} eq "Enum") { die unless exists $enum_values{$fs->{typehint}}; my @vs = split /;/, $enum_values{$fs->{typehint}}; - printf $fh "${indent} ${sep}%s\n", (join '|', map { "\"$_\"" } @vs); + printf $fh "${indent} ${sep}(%s)\n", (join '|', map { "\"$_\"" } @vs); } elsif ($fs->{kstr} eq "Int") { printf $fh "${indent} ${sep}xsd:integer\n"; #if (exists $range{$lctn} || exists $range{$fs->{typehint}}) { diff --git a/docs/manual/options.md b/docs/manual/options.md index eab7449..4cef963 100644 --- a/docs/manual/options.md +++ b/docs/manual/options.md @@ -903,15 +903,17 @@ The default value is: "-1". #### //CycloneDDS/Domain/Internal/MultipleReceiveThreads Attributes: [maxretries](#cycloneddsdomaininternalmultiplereceivethreadsmaxretries) -Boolean +One of: false, true, default This element controls whether all traffic is handled by a single receive -thread or whether multiple receive threads may be used to improve -latency. Currently multiple receive threads are only used for -connectionless transport (e.g., UDP) and ManySocketsMode not set to -single (the default). +thread (false) or whether multiple receive threads may be used to improve +latency (true). By default it is disabled on Windows because it appears +that one cannot count on being able to send packets to oneself, which is +necessary to stop the thread during shutdown. Currently multiple receive +threads are only used for connectionless transport (e.g., UDP) and +ManySocketsMode not set to single (the default). -The default value is: "true". +The default value is: "default". #### //CycloneDDS/Domain/Internal/MultipleReceiveThreads[@maxretries] diff --git a/etc/cyclonedds.rnc b/etc/cyclonedds.rnc index 19e6dcb..22f13bb 100644 --- a/etc/cyclonedds.rnc +++ b/etc/cyclonedds.rnc @@ -51,7 +51,7 @@ somewhat. It also causes the set of port numbers needed by Cyclone DDS to become predictable, which may be useful for firewall and NAT configuration.

The default value is: "single".

""" ] ] element ManySocketsMode { - "false"|"true"|"single"|"none"|"many" + ("false"|"true"|"single"|"none"|"many") }? & [ a:documentation [ xml:lang="en" """

This element sets the level of standards conformance of this instance @@ -78,7 +78,7 @@ though there is no good reason not to.

The default setting is "lax".

The default value is: "lax".

""" ] ] element StandardsConformance { - "lax"|"strict"|"pedantic" + ("lax"|"strict"|"pedantic") }? }? & [ a:documentation [ xml:lang="en" """ @@ -444,13 +444,13 @@ is available.

The default value is: "false".

""" ] ]

This element allows selecting the transport to be used (udp, udp6, tcp, tcp6, raweth)

The default value is: "default".

""" ] ] element Transport { - "default"|"udp"|"udp6"|"tcp"|"tcp6"|"raweth" + ("default"|"udp"|"udp6"|"tcp"|"tcp6"|"raweth") }? & [ a:documentation [ xml:lang="en" """

Deprecated (use Transport instead)

The default value is: "default".

""" ] ] element UseIPv6 { - "false"|"true"|"default" + ("false"|"true"|"default") }? }? & [ a:documentation [ xml:lang="en" """ @@ -509,7 +509,7 @@ most efficient, and full is inefficient but certain to be compliant. See also Internal/ConservativeBuiltinReaderStartup.

The default value is: "writers".

""" ] ] element BuiltinEndpointSet { - "full"|"writers"|"minimal" + ("full"|"writers"|"minimal") }? & [ a:documentation [ xml:lang="en" """

The ControlTopic element allows configured whether Cyclone DDS @@ -735,10 +735,13 @@ is: "-1".

""" ] ] }? & [ a:documentation [ xml:lang="en" """

This element controls whether all traffic is handled by a single -receive thread or whether multiple receive threads may be used to improve -latency. Currently multiple receive threads are only used for -connectionless transport (e.g., UDP) and ManySocketsMode not set to -single (the default).

The default value is: "true".

""" ] ] +receive thread (false) or whether multiple receive threads may be used to +improve latency (true). By default it is disabled on Windows because it +appears that one cannot count on being able to send packets to oneself, +which is necessary to stop the thread during shutdown. Currently multiple +receive threads are only used for connectionless transport (e.g., UDP) +and ManySocketsMode not set to single (the default).

The default +value is: "default".

""" ] ] element MultipleReceiveThreads { [ a:documentation [ xml:lang="en" """

Receive threads dedicated to a single socket can only be triggered for @@ -750,7 +753,7 @@ attribute before aborting.

The default value is: attribute maxretries { xsd:integer }? - & xsd:boolean + & ("false"|"true"|"default") }? & [ a:documentation [ xml:lang="en" """

This setting controls the delay between receipt of a HEARTBEAT @@ -835,7 +838,7 @@ try to merge. Internal/RetransmitMergingPeriod.

The default value is: "never".

""" ] ] element RetransmitMerging { - "never"|"adaptive"|"always" + ("never"|"adaptive"|"always") }? & [ a:documentation [ xml:lang="en" """

This setting determines the size of the time window in which a NACK of @@ -1220,7 +1223,7 @@ using TCP.

The default value is: "false".

""" ] ] General/Transport instead.

The default value is: "default".

""" ] ] element Enable { - "false"|"true"|"default" + ("false"|"true"|"default") }? & [ a:documentation [ xml:lang="en" """

This element enables the TCP_NODELAY socket option, preventing @@ -1326,7 +1329,7 @@ from the underlying operating system to be able to assign some of the privileged scheduling classes.

The default value is: "default".

""" ] ] element Class { - "realtime"|"timeshare"|"default" + ("realtime"|"timeshare"|"default") }? & [ a:documentation [ xml:lang="en" """

This element specifies the thread priority (decimal integer or @@ -1467,7 +1470,7 @@ situation rather than the current situation. Currently, the most useful verbosity levels are config, fine and finest.

The default value is: "none".

""" ] ] element Verbosity { - "finest"|"finer"|"fine"|"config"|"info"|"warning"|"severe"|"none" + ("finest"|"finer"|"fine"|"config"|"info"|"warning"|"severe"|"none") }? }? }? diff --git a/etc/cyclonedds.xsd b/etc/cyclonedds.xsd index 867f95b..894742d 100644 --- a/etc/cyclonedds.xsd +++ b/etc/cyclonedds.xsd @@ -1013,14 +1013,24 @@ is: &quot;-1&quot;.</p> <p>This element controls whether all traffic is handled by a single -receive thread or whether multiple receive threads may be used to improve -latency. Currently multiple receive threads are only used for -connectionless transport (e.g., UDP) and ManySocketsMode not set to -single (the default).</p><p>The default value is: &quot;true&quot;.</p> +receive thread (false) or whether multiple receive threads may be used to +improve latency (true). By default it is disabled on Windows because it +appears that one cannot count on being able to send packets to oneself, +which is necessary to stop the thread during shutdown. Currently multiple +receive threads are only used for connectionless transport (e.g., UDP) +and ManySocketsMode not set to single (the default).</p><p>The default +value is: &quot;default&quot;.</p> - + + + + + + + + @@ -1032,7 +1042,7 @@ attribute before aborting.</p><p>The default value is: &quot;4294967295&quot;.</p> - + diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index c20f2a4..7417c3b 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -218,7 +218,7 @@ struct config int64_t liveliness_monitoring_interval; int prioritize_retransmit; int xpack_send_async; - int multiple_recv_threads; + enum boolean_default multiple_recv_threads; unsigned recv_thread_stop_maxretries; unsigned primary_reorder_maxsamples; diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 8818134..63e937b 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -149,9 +149,7 @@ DU(ipv4); DUPF(allow_multicast); DUPF(boolean); DU(boolean_default); -#if 0 PF(boolean_default); -#endif DUPF(string); DU(tracingOutputFileName); DU(verbosity); @@ -584,8 +582,8 @@ static const struct cfgelem unsupp_cfgelems[] = { BLURB("

This element controls whether the actual sending of packets occurs on the same thread that prepares them, or is done asynchronously by another thread.

") }, { LEAF_W_ATTRS("RediscoveryBlacklistDuration", rediscovery_blacklist_duration_attrs), 1, "10s", ABSOFF(prune_deleted_ppant.delay), 0, uf_duration_inf, 0, pf_duration, BLURB("

This element controls for how long a remote participant that was previously deleted will remain on a blacklist to prevent rediscovery, giving the software on a node time to perform any cleanup actions it needs to do. To some extent this delay is required internally by DDSI2E, but in the default configuration with the 'enforce' attribute set to false, DDSI2E will reallow rediscovery as soon as it has cleared its internal administration. Setting it to too small a value may result in the entry being pruned from the blacklist before DDSI2E is ready, it is therefore recommended to set it to at least several seconds.

") }, - { LEAF_W_ATTRS("MultipleReceiveThreads", multiple_recv_threads_attrs), 1, "true", ABSOFF(multiple_recv_threads), 0, uf_boolean, 0, pf_boolean, - BLURB("

This element controls whether all traffic is handled by a single receive thread or whether multiple receive threads may be used to improve latency. Currently multiple receive threads are only used for connectionless transport (e.g., UDP) and ManySocketsMode not set to single (the default).

") }, + { LEAF_W_ATTRS("MultipleReceiveThreads", multiple_recv_threads_attrs), 1, "default", ABSOFF(multiple_recv_threads), 0, uf_boolean_default, 0, pf_boolean_default, + BLURB("

This element controls whether all traffic is handled by a single receive thread (false) or whether multiple receive threads may be used to improve latency (true). By default it is disabled on Windows because it appears that one cannot count on being able to send packets to oneself, which is necessary to stop the thread during shutdown. Currently multiple receive threads are only used for connectionless transport (e.g., UDP) and ManySocketsMode not set to single (the default).

") }, { MGROUP("ControlTopic", control_topic_cfgelems, control_topic_cfgattrs), 1, 0, 0, 0, 0, 0, 0, 0, BLURB("

The ControlTopic element allows configured whether DDSI2E provides a special control interface via a predefined topic or not.

") }, { GROUP("Test", unsupp_test_cfgelems), @@ -1456,7 +1454,7 @@ GENERIC_ENUM_CTYPE (boolean, int) static const char *en_boolean_default_vs[] = { "default", "false", "true", NULL }; static const enum boolean_default en_boolean_default_ms[] = { BOOLDEF_DEFAULT, BOOLDEF_FALSE, BOOLDEF_TRUE, 0 }; -GENERIC_ENUM_UF (boolean_default) +GENERIC_ENUM (boolean_default) static const char *en_besmode_vs[] = { "full", "writers", "minimal", NULL }; static const enum besmode en_besmode_ms[] = { BESMODE_FULL, BESMODE_WRITERS, BESMODE_MINIMAL, 0 }; diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 11abfa4..4d36783 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -796,8 +796,36 @@ static void free_special_topics (struct q_globals *gv) ddsi_sertopic_unref (gv->rawcdr_topic); } +static bool use_multiple_receive_threads (const struct config *cfg) +{ + /* Under some unknown circumstances Windows (at least Windows 10) exhibits + the interesting behaviour of losing its ability to let us send packets + to our own sockets. When that happens, dedicated receive threads can no + longer be stopped and Cyclone hangs in shutdown. So until someone + figures out why this happens, it is probably best have a different + default on Windows. */ +#if _WIN32 + const bool def = false; +#else + const bool def = true; +#endif + switch (cfg->multiple_recv_threads) + { + case BOOLDEF_FALSE: + return false; + case BOOLDEF_TRUE: + return true; + case BOOLDEF_DEFAULT: + return def; + } + assert (0); + return false; +} + static int setup_and_start_recv_threads (struct q_globals *gv) { + const bool multi_recv_thr = use_multiple_receive_threads (&gv->config); + for (uint32_t i = 0; i < MAX_RECV_THREADS; i++) { gv->recv_threads[i].ts = NULL; @@ -812,7 +840,7 @@ static int setup_and_start_recv_threads (struct q_globals *gv) gv->n_recv_threads = 1; gv->recv_threads[0].name = "recv"; gv->recv_threads[0].arg.mode = RTM_MANY; - if (gv->m_factory->m_connless && gv->config.many_sockets_mode != MSM_NO_UNICAST && gv->config.multiple_recv_threads) + if (gv->m_factory->m_connless && gv->config.many_sockets_mode != MSM_NO_UNICAST && multi_recv_thr) { if (ddsi_is_mcaddr (gv, &gv->loc_default_mc) && !ddsi_is_ssm_mcaddr (gv, &gv->loc_default_mc) && (gv->config.allowMulticast & AMC_ASM)) { From 9410753076c311d77e4e54994d05c96a025090d9 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 13 Jan 2020 13:43:11 +0100 Subject: [PATCH 14/28] Liveliness local readers This commit adds support for liveliness QoS when using local readers. The implementation for (liveliness) expiration of writers used here is similar to that used with proxy writers, and it also supports the three liveliness kinds (1) automatic, which is trivial when using a local reader and writer, (2) manual-by-participant and (3) manual-by-topic. In addition, these changes and fixes are included in this commit: - Fixed a bug in heartbeat handling in the reader: for manual-by- participant writers the lease was not updated on reception of a heartbeat message with liveliness flag set. This is fixed and a test-case is added. - Include the liveliness flag in a heartbeat message to the trace - Trace all lease renewals, including liveliness leases - Replaced liveliness changed state 'twitch' by 2 subsequent calls to the status callback - Added a test for liveliness duration 0 and 1ns (for both local and remote readers) Signed-off-by: Dennis Potman --- src/core/ddsc/src/dds_reader.c | 7 +- src/core/ddsc/tests/liveliness.c | 304 ++++++++++------ src/core/ddsi/include/dds/ddsi/q_entity.h | 13 +- src/core/ddsi/src/ddsi_pmd.c | 5 + src/core/ddsi/src/q_entity.c | 415 ++++++++++++++++++---- src/core/ddsi/src/q_lease.c | 35 +- src/core/ddsi/src/q_receive.c | 5 +- src/core/ddsi/src/q_transmit.c | 18 + src/tools/decode-trace | 11 +- 9 files changed, 610 insertions(+), 203 deletions(-) diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index ff0b8cc..71bfd3d 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -254,9 +254,8 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) 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); + (uint32_t) LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE < UINT32_MAX); + assert (data->extra <= (uint32_t) LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE); switch ((enum liveliness_changed_data_extra) data->extra) { case LIVELINESS_CHANGED_ADD_ALIVE: @@ -287,8 +286,6 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) 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); diff --git a/src/core/ddsc/tests/liveliness.c b/src/core/ddsc/tests/liveliness.c index 856e897..25ccac1 100644 --- a/src/core/ddsc/tests/liveliness.c +++ b/src/core/ddsc/tests/liveliness.c @@ -153,10 +153,11 @@ CU_TheoryDataPoints(ddsc_liveliness, pmd_count) = { #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) + +static void test_pmd_count(dds_liveliness_kind_t kind, uint32_t ldur, double mult, bool remote_reader) { dds_entity_t pub_topic; - dds_entity_t sub_topic; + dds_entity_t sub_topic = 0; dds_entity_t reader; dds_entity_t writer; seqno_t start_seqno, end_seqno; @@ -169,9 +170,9 @@ CU_Theory((dds_liveliness_kind_t kind, uint32_t ldur, double mult), ddsc_livelin dds_time_t t; t = dds_time(); - printf("%d.%06d running test: kind %s, lease duration %d, delay %d\n", + printf("%d.%06d running test: kind %s, lease duration %d, delay %d, %s reader\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)); + kind == 0 ? "A" : "MP", ldur, (int32_t)(mult * ldur), remote_reader ? "remote" : "local"); /* wait for initial PMD to be sent by the participant */ while (get_pmd_seqno(g_pub_participant) < 1) @@ -180,17 +181,18 @@ CU_Theory((dds_liveliness_kind_t kind, uint32_t ldur, double mult), ddsc_livelin /* 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); + if (remote_reader) + 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); + CU_ASSERT_FATAL((reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_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_FATAL((waitset = dds_create_waitset(remote_reader ? g_sub_participant : g_pub_participant)) > 0); CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK); /* writer */ @@ -221,12 +223,19 @@ CU_Theory((dds_liveliness_kind_t kind, uint32_t ldur, double mult), ddsc_livelin CU_ASSERT(get_pmd_seqno(g_pub_participant) - start_seqno < mult) /* cleanup */ - CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK); + if (remote_reader) + 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); } +CU_Theory((dds_liveliness_kind_t kind, uint32_t ldur, double mult), ddsc_liveliness, pmd_count, .init = liveliness_init, .fini = liveliness_fini, .timeout = 30) +{ + test_pmd_count(kind, ldur, mult, false); + test_pmd_count(kind, ldur, mult, true); +} + /** * Test that the expected number of proxy writers expires (set to not-alive) * after a certain delay for various combinations of writers with different @@ -239,10 +248,11 @@ CU_TheoryDataPoints(ddsc_liveliness, expire_liveliness_kinds) = { 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) + +static void test_expire_liveliness_kinds(uint32_t ldur, double mult, uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp, bool remote_reader) { dds_entity_t pub_topic; - dds_entity_t sub_topic; + dds_entity_t sub_topic = 0; dds_entity_t reader; dds_entity_t *writers; dds_qos_t *rqos, *wqos_auto, *wqos_man_pp, *wqos_man_tp; @@ -257,19 +267,20 @@ CU_Theory((uint32_t ldur, double mult, uint32_t wr_cnt_auto, uint32_t wr_cnt_man 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", + printf("%d.%06d running test: lease duration %d, delay %f, auto/man-by-part/man-by-topic %u/%u/%u\n, %s reader", (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); + ldur, mult, wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, remote_reader ? "remote" : "local"); /* 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); + if (remote_reader) + 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); + CU_ASSERT_FATAL((reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_topic, rqos, NULL)) > 0); dds_delete_qos(rqos); CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK); @@ -281,7 +292,7 @@ CU_Theory((uint32_t ldur, double mult, uint32_t wr_cnt_auto, uint32_t wr_cnt_man 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_FATAL((waitset = dds_create_waitset(remote_reader ? g_sub_participant : g_pub_participant)) > 0); CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK); writers = dds_alloc(wr_cnt * sizeof(dds_entity_t)); @@ -347,7 +358,8 @@ CU_Theory((uint32_t ldur, double mult, uint32_t wr_cnt_auto, uint32_t wr_cnt_man 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); + if (remote_reader) + 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); @@ -369,14 +381,21 @@ CU_Theory((uint32_t ldur, double mult, uint32_t wr_cnt_auto, uint32_t wr_cnt_man } 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) +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) +{ + test_expire_liveliness_kinds (ldur, mult, wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, false); + test_expire_liveliness_kinds (ldur, mult, wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, true); +} + + +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, bool remote_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_FATAL((waitset = dds_create_waitset(remote_reader ? g_sub_participant : g_pub_participant)) > 0); CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK); CU_ASSERT_FATAL((wqos = dds_create_qos()) != NULL); @@ -424,22 +443,22 @@ CU_Test(ddsc_liveliness, lease_duration, .init = liveliness_init, .fini = liveli 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); + add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(1000), &writers[wr_cnt++], pub_topic, reader, true); 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); + add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(2000), &writers[wr_cnt++], pub_topic, reader, true); 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); + add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(2000), &writers[wr_cnt++], pub_topic, reader, true); 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); + add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(500), &writers[wr_cnt++], pub_topic, reader, true); 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); + add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(100), &writers[wr_cnt++], pub_topic, reader, true); 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); + add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_TOPIC, DDS_MSECS(100), &writers[wr_cnt++], pub_topic, reader, true); CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(500)); /* cleanup */ @@ -454,10 +473,10 @@ CU_Test(ddsc_liveliness, lease_duration, .init = liveliness_init, .fini = liveli /** * 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) +static void test_lease_duration_pwr(bool remote_reader) { dds_entity_t pub_topic; - dds_entity_t sub_topic; + dds_entity_t sub_topic = 0; dds_entity_t reader; dds_entity_t writer; char name[100]; @@ -467,15 +486,18 @@ CU_Test(ddsc_liveliness, lease_duration_pwr, .init = liveliness_init, .fini = li uint32_t status; dds_duration_t ldur; + printf("running test lease_duration_pwr: %s reader\n", remote_reader ? "remote" : "local"); + /* 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); + if (remote_reader) + 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); + CU_ASSERT_FATAL((reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_topic, rqos, NULL)) > 0); dds_delete_qos(rqos); CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK); @@ -486,7 +508,7 @@ CU_Test(ddsc_liveliness, lease_duration_pwr, .init = liveliness_init, .fini = li 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_FATAL((waitset = dds_create_waitset(remote_reader ? g_sub_participant : g_pub_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); @@ -509,11 +531,18 @@ CU_Test(ddsc_liveliness, lease_duration_pwr, .init = liveliness_init, .fini = li 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); + if (remote_reader) + 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); } +CU_Test(ddsc_liveliness, lease_duration_pwr, .init = liveliness_init, .fini = liveliness_fini) +{ + test_lease_duration_pwr(false); + test_lease_duration_pwr(true); +} + /** * Create a relative large number of writers with liveliness kinds automatic and * manual-by-participant and with decreasing lease duration, and check that all @@ -521,10 +550,11 @@ CU_Test(ddsc_liveliness, lease_duration_pwr, .init = liveliness_init, .fini = li * 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) + +static void test_create_delete_writer_stress(bool remote_reader) { dds_entity_t pub_topic; - dds_entity_t sub_topic; + dds_entity_t sub_topic = 0; dds_entity_t reader; dds_entity_t writers[MAX_WRITERS]; dds_entity_t waitset; @@ -538,18 +568,21 @@ CU_Test(ddsc_liveliness, create_delete_writer_stress, .init = liveliness_init, . Space_Type1 sample = {0, 0, 0}; int64_t ldur = 1000; + printf("running test create_delete_writer_stress: %s reader\n", remote_reader ? "remote" : "local"); + /* 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); + if (remote_reader) + 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); + CU_ASSERT_FATAL((reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_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_FATAL((waitset = dds_create_waitset(remote_reader ? g_sub_participant : g_pub_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 */ @@ -604,42 +637,53 @@ CU_Test(ddsc_liveliness, create_delete_writer_stress, .init = liveliness_init, . 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); + if (remote_reader) + CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK); } + +CU_Test(ddsc_liveliness, create_delete_writer_stress, .init = liveliness_init, .fini = liveliness_fini, .timeout = 15) +{ + test_create_delete_writer_stress(false); + test_create_delete_writer_stress(true); +} #undef MAX_WRITERS /** * Check the counts in liveliness_changed_status result. */ -CU_Test(ddsc_liveliness, status_counts, .init = liveliness_init, .fini = liveliness_fini) +static void test_status_counts(bool remote_reader) { dds_entity_t pub_topic; - dds_entity_t sub_topic; + dds_entity_t sub_topic = 0; 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_liveliness_changed_status lcstatus; + struct dds_liveliness_lost_status llstatus; struct dds_subscription_matched_status sstatus; char name[100]; dds_duration_t ldur = DDS_MSECS(500); Space_Type1 sample = {1, 0, 0}; + printf("running test status_counts: %s reader\n", remote_reader ? "remote" : "local"); + /* 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); + if (remote_reader) + 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); + CU_ASSERT_FATAL((reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_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_FATAL((waitset = dds_create_waitset(remote_reader ? g_sub_participant : g_pub_participant)) > 0); CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK); /* writer */ @@ -647,56 +691,72 @@ CU_Test(ddsc_liveliness, status_counts, .init = liveliness_init, .fini = livelin 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); + CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(writer, DDS_LIVELINESS_LOST_STATUS), DDS_RETCODE_OK); /* 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_liveliness_changed_status(reader, &lcstatus); + CU_ASSERT_EQUAL_FATAL(lcstatus.alive_count, 1); dds_get_subscription_matched_status(reader, &sstatus); CU_ASSERT_EQUAL_FATAL(sstatus.current_count, 1); + dds_get_liveliness_lost_status(writer, &llstatus); + CU_ASSERT_EQUAL_FATAL(llstatus.total_count, 0); /* 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_liveliness_changed_status(reader, &lcstatus); + CU_ASSERT_EQUAL_FATAL(lcstatus.alive_count, 0); dds_get_subscription_matched_status(reader, &sstatus); CU_ASSERT_EQUAL_FATAL(sstatus.current_count, 1); + dds_get_liveliness_lost_status(writer, &llstatus); + CU_ASSERT_EQUAL_FATAL(llstatus.total_count, 1); + CU_ASSERT_EQUAL_FATAL(llstatus.total_count_change, 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_liveliness_changed_status(reader, &lcstatus); + CU_ASSERT_EQUAL_FATAL(lcstatus.alive_count, 1); dds_get_subscription_matched_status(reader, &sstatus); CU_ASSERT_EQUAL_FATAL(sstatus.current_count, 1); + dds_get_liveliness_lost_status(writer, &llstatus); + CU_ASSERT_EQUAL_FATAL(llstatus.total_count_change, 0); /* 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); + if (remote_reader) + CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK); } +CU_Test(ddsc_liveliness, status_counts, .init = liveliness_init, .fini = liveliness_fini) +{ + test_status_counts(false); + test_status_counts(true); +} + /** * 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_DataPoints(uint32_t, 1, 0, 0, 1, 0, 1, 2), /* number of writers with automatic liveliness */ + CU_DataPoints(uint32_t, 0, 1, 0, 1, 1, 0, 2), /* number of writers with manual-by-participant liveliness */ + CU_DataPoints(uint32_t, 0, 0, 1, 1, 2, 2, 0), /* 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) + +static void test_assert_liveliness(uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp, bool remote_reader) { - dds_entity_t pub_topic, sub_topic, reader, writers[MAX_WRITERS]; + dds_entity_t pub_topic, sub_topic = 0, reader, writers[MAX_WRITERS]; dds_qos_t *rqos; struct dds_liveliness_changed_status lstatus; char name[100]; @@ -708,29 +768,30 @@ CU_Theory((uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp) { 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); + printf("running test assert_liveliness: auto/man-by-part/man-by-topic %u/%u/%u with ldur %d, %s reader\n", + wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, ldur, remote_reader ? "remote" : "local"); /* 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); + if (remote_reader) + 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); + CU_ASSERT_FATAL((reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_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); + add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(ldur), &writers[wr_cnt++], pub_topic, reader, remote_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); + add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(ldur), &writers[wr_cnt++], pub_topic, reader, remote_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); + add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_TOPIC, DDS_MSECS(ldur), &writers[wr_cnt++], pub_topic, reader, remote_reader); t = dds_time(); if (t - tstart > DDS_MSECS(0.5 * ldur)) { @@ -750,13 +811,13 @@ CU_Theory((uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp) stopped = 0; do { - for (size_t n = wr_cnt - wr_cnt_man_tp; n < wr_cnt; n++) - dds_assert_liveliness(writers[n]); + for (size_t n = wr_cnt_auto; n < wr_cnt; n++) + CU_ASSERT_EQUAL_FATAL(dds_assert_liveliness(writers[n]), DDS_RETCODE_OK); 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); + CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK); 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) { @@ -795,7 +856,8 @@ CU_Theory((uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp) 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); + if (remote_reader) + 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) @@ -813,6 +875,12 @@ CU_Theory((uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp) } } while (!test_finished); } + +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) +{ + test_assert_liveliness(wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, false); + test_assert_liveliness(wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, true); +} #undef MAX_WRITERS /** @@ -883,31 +951,47 @@ static void liveliness_changed_listener (dds_entity_t rd, const dds_liveliness_c st->weirdness = true; } } + else + { + printf ("liveliness_changed_listener: alive_count_change = 0 && not_alive_count_change = 0\n"); + st->weirdness = true; + } ddsrt_mutex_unlock (&st->lock); } -static bool get_and_check_status (dds_entity_t reader, dds_entity_t writer_active) +#define STATUS_UNSYNCED 0 +#define STATUS_SYNCED 1 +#define STATUS_DATA 2 +static unsigned get_and_check_status (dds_entity_t reader, dds_entity_t writer_active) { struct dds_liveliness_changed_status lstatus; struct dds_subscription_matched_status sstatus; struct dds_publication_matched_status pstatus; + uint32_t dstatus; + uint32_t result = STATUS_UNSYNCED; dds_return_t rc; rc = dds_get_subscription_matched_status(reader, &sstatus); CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); rc = dds_get_liveliness_changed_status(reader, &lstatus); CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + rc = dds_take_status(reader, &dstatus, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); rc = dds_get_publication_matched_status(writer_active, &pstatus); CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); CU_ASSERT_FATAL(lstatus.alive_count + lstatus.not_alive_count <= 2); - printf ("%d %d %d %d\n", (int)sstatus.current_count, (int)lstatus.alive_count, (int)lstatus.not_alive_count, (int)pstatus.current_count); - return (sstatus.current_count == 2 && lstatus.not_alive_count == 2 && pstatus.current_count == 1); + printf ("sub %d | alive %d | not-alive %d | pub %d | data %d\n", (int)sstatus.current_count, (int)lstatus.alive_count, (int)lstatus.not_alive_count, (int)pstatus.current_count, dstatus != 0); + if (dstatus) + result |= STATUS_DATA; + if (sstatus.current_count == 2 && lstatus.not_alive_count == 2 && pstatus.current_count == 1) + result |= STATUS_SYNCED; + return result; } -static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_liveliness_kind_t lkind, dds_duration_t ldur) +static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_liveliness_kind_t lkind, dds_duration_t ldur, bool remote_reader) { - const uint32_t nsamples = (sleep <= DDS_MSECS(10)) ? 100 : 10; + const uint32_t nsamples = (sleep <= DDS_MSECS(10)) ? 50 : 5; dds_entity_t pub_topic; - dds_entity_t sub_topic; + dds_entity_t sub_topic = 0; dds_entity_t reader; dds_entity_t writer_active; /* writing */ dds_entity_t writer_inactive; /* not writing, liveliness should still toggle */ @@ -937,14 +1021,17 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines create_topic_name("ddsc_liveliness_lease_duration_zero", g_topic_nr++, name, sizeof name); pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, qos, NULL); CU_ASSERT_FATAL(pub_topic > 0); - sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, qos, NULL); - CU_ASSERT_FATAL(sub_topic > 0); + if (remote_reader) + { + sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, qos, NULL); + CU_ASSERT_FATAL(sub_topic > 0); + } /* reader liveliness is always automatic/infinity */ dds_qset_liveliness(qos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY); - reader = dds_create_reader(g_sub_participant, sub_topic, qos, NULL); + reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_topic, qos, NULL); CU_ASSERT_FATAL(reader > 0); - rc = dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS | DDS_SUBSCRIPTION_MATCHED_STATUS); + rc = dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS | DDS_SUBSCRIPTION_MATCHED_STATUS | DDS_DATA_AVAILABLE_STATUS); CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); rc = dds_waitset_attach(waitset, reader, reader); CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); @@ -964,15 +1051,29 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines /* wait for writers to be discovered and to have lost their liveliness, and for writer_active to have discovered the reader */ - while (!get_and_check_status (reader, writer_active)) + unsigned status = STATUS_UNSYNCED; + bool initial_sample_written = false, initial_sample_received = false; + do { + status = get_and_check_status (reader, writer_active); + if (status & STATUS_DATA) + initial_sample_received = true; + if (status & STATUS_SYNCED && !initial_sample_written) + { + rc = dds_write(writer_active, &sample); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + initial_sample_written = true; + } + if (status & STATUS_SYNCED && initial_sample_received) + break; + rc = dds_waitset_wait(waitset, NULL, 0, DDS_SECS(5)); if (rc < 1) { get_and_check_status (reader, writer_active); CU_ASSERT_FATAL(rc >= 1); } - } + } while (1); /* switch to using a listener: those allow us to observe all events */ listener = dds_create_listener (&listener_state); @@ -1002,7 +1103,7 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines uint32_t cnt = 0; while (dds_take(reader, raw, &si, 1, 1) == 1) cnt++; - CU_ASSERT(cnt == nsamples); + CU_ASSERT(cnt == nsamples + 1); } /* transition to not alive is not necessarily immediate */ @@ -1028,21 +1129,15 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines printf("late liveliness changed status: alive %"PRId32" not-alive %"PRId32"\n", lstatus.alive_count, lstatus.not_alive_count); printf("final w0 %"PRIx64" alive %"PRId32" not-alive %"PRId32"\n", listener_state.w0_handle, listener_state.w0_alive, listener_state.w0_not_alive); CU_ASSERT(listener_state.w0_alive == listener_state.w0_not_alive); + uint32_t exp_alive; if (sleep == 0) - { - /* if not sleeping, it's ok if the transition happens only once */ - CU_ASSERT(listener_state.w0_alive > 0); - } + exp_alive = 1; /* if not sleeping, it's ok if the transition happens only once */ else if (sleep <= DDS_MSECS(10)) - { - /* if sleeping briefly, expect the a good number of writes to toggle liveliness */ - CU_ASSERT(listener_state.w0_alive >= nsamples / 3); - } + exp_alive = nsamples / 3; /* if sleeping briefly, expect the a good number of writes to toggle liveliness */ else - { - /* if sleeping, expect the vast majority (90%) of the writes to toggle liveliness */ - CU_ASSERT(listener_state.w0_alive >= nsamples - nsamples / 10); - } + exp_alive = nsamples - nsamples / 5; /* if sleeping, expect the vast majority (80%) of the writes to toggle liveliness */ + printf("check w0_alive %d >= %d\n", listener_state.w0_alive, exp_alive); + CU_ASSERT(listener_state.w0_alive >= exp_alive); ddsrt_mutex_unlock(&listener_state.lock); } @@ -1055,8 +1150,11 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); rc = dds_delete(writer_inactive); CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); - rc = dds_delete(sub_topic); - CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + if (remote_reader) + { + rc = dds_delete(sub_topic); + CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); + } rc = dds_delete(pub_topic); CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); @@ -1065,20 +1163,26 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines CU_Test(ddsc_liveliness, lease_duration_zero_or_one, .init = liveliness_init, .fini = liveliness_fini, .timeout = 30) { + static const bool remote_rd[] = { false, true }; static const dds_duration_t sleep[] = { 0, DDS_MSECS(10), DDS_MSECS(100) }; static const dds_liveliness_kind_t lkind[] = { DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_LIVELINESS_MANUAL_BY_TOPIC }; static const dds_duration_t ldur[] = { 0, 1 }; - for (size_t sleep_idx = 0; sleep_idx < sizeof (sleep) / sizeof (sleep[0]); sleep_idx++) + for (size_t remote_rd_idx = 0; remote_rd_idx < sizeof (remote_rd) / sizeof (remote_rd[0]); remote_rd_idx++) { - for (size_t lkind_idx = 0; lkind_idx < sizeof (lkind) / sizeof (lkind[0]); lkind_idx++) + for (size_t sleep_idx = 0; sleep_idx < sizeof (sleep) / sizeof (sleep[0]); sleep_idx++) { - for (size_t ldur_idx = 0; ldur_idx < sizeof (ldur) / sizeof (ldur[0]); ldur_idx++) + for (size_t lkind_idx = 0; lkind_idx < sizeof (lkind) / sizeof (lkind[0]); lkind_idx++) { - dds_duration_t s = sleep[sleep_idx]; - dds_liveliness_kind_t k = lkind[lkind_idx]; - dds_duration_t d = ldur[ldur_idx]; - printf ("lease_duration_zero_or_one: sleep = %"PRId64" lkind = %d ldur = %"PRId64"\n", s, (int) k, d); - lease_duration_zero_or_one_impl (s, k, d); + for (size_t ldur_idx = 0; ldur_idx < sizeof (ldur) / sizeof (ldur[0]); ldur_idx++) + { + bool rrd = remote_rd[remote_rd_idx]; + dds_duration_t s = sleep[sleep_idx]; + dds_liveliness_kind_t k = lkind[lkind_idx]; + dds_duration_t d = ldur[ldur_idx]; + printf ("### lease_duration_zero_or_one: sleep = %"PRId64" lkind = %d ldur = %"PRId64" reader = %s\n", s, (int) k, d, rrd ? "remote" : "local"); + lease_duration_zero_or_one_impl (s, k, d, rrd); + printf ("\n"); + } } } } diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 62dabfe..34ab9f8 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -64,8 +64,7 @@ enum liveliness_changed_data_extra { LIVELINESS_CHANGED_REMOVE_NOT_ALIVE, LIVELINESS_CHANGED_REMOVE_ALIVE, LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE, - LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE, - LIVELINESS_CHANGED_TWITCH + LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE }; typedef struct status_cb_data @@ -102,6 +101,8 @@ struct wr_rd_match { struct rd_wr_match { ddsrt_avl_node_t avlnode; ddsi_guid_t wr_guid; + unsigned wr_alive: 1; /* tracks wr's alive state */ + uint32_t wr_alive_vclock; /* used to ensure progress */ }; struct wr_prd_match { @@ -208,6 +209,8 @@ struct participant 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 */ + ddsrt_atomic_voidp_t minl_man; /* lease object for shortest manual-by-participant liveliness writer's lease */ + ddsrt_fibheap_t leaseheap_man; /* keeps leases for this participant's writers (with liveliness manual-by-participant) */ }; struct endpoint_common { @@ -255,10 +258,12 @@ struct writer unsigned handle_as_transient_local: 1; /* controls whether data is retained in WHC */ unsigned include_keyhash: 1; /* iff 1, this writer includes a keyhash; keyless topics => include_keyhash = 0 */ unsigned retransmitting: 1; /* iff 1, this writer is currently retransmitting */ + unsigned alive: 1; /* iff 1, the writer is alive (lease for this writer is not expired); field may be modified only when holding both wr->e.lock and wr->c.pp->e.lock */ #ifdef DDSI_INCLUDE_SSM unsigned supports_ssm: 1; struct addrset *ssm_as; #endif + uint32_t alive_vclock; /* virtual clock counting transitions between alive/not-alive */ const struct ddsi_sertopic * topic; /* topic, but may be NULL for built-ins */ 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 */ @@ -282,6 +287,7 @@ struct writer uint32_t rexmit_lost_count; /* cum samples lost but retransmit requested (also counting events) */ struct xeventq *evq; /* timed event queue to be used by this writer */ struct local_reader_ary rdary; /* LOCAL readers for fast-pathing; if not fast-pathed, fall back to scanning local_readers */ + struct lease *lease; /* for liveliness administration (writer can only become inactive when using manual liveliness) */ }; inline seqno_t writer_read_seq_xmit (const struct writer *wr) { @@ -620,6 +626,9 @@ struct local_orphan_writer { struct local_orphan_writer *new_local_orphan_writer (struct q_globals *gv, ddsi_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc); void delete_local_orphan_writer (struct local_orphan_writer *wr); +void writer_set_alive_may_unlock (struct writer *wr, bool notify); +int writer_set_notalive (struct writer *wr, bool notify); + /* To create or delete a new proxy participant: "guid" MUST have the pre-defined participant entity id. Unlike delete_participant(), deleting a proxy participant will automatically delete all its diff --git a/src/core/ddsi/src/ddsi_pmd.c b/src/core/ddsi/src/ddsi_pmd.c index 198bc27..3136e91 100644 --- a/src/core/ddsi/src/ddsi_pmd.c +++ b/src/core/ddsi/src/ddsi_pmd.c @@ -49,12 +49,17 @@ static void debug_print_rawdata (const struct q_globals *gv, const char *msg, co 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 (); + struct lease *lease; thread_state_awake (ts1, gv); struct participant *pp = entidx_lookup_participant_guid (gv->entity_index, pp_guid); if (pp == NULL) GVTRACE ("write_pmd_message("PGUIDFMT") - builtin pmd writer not found\n", PGUID (*pp_guid)); else + { + if ((lease = ddsrt_atomic_ldvoidp (&pp->minl_man)) != NULL) + lease_renew (lease, now_et()); write_pmd_message (ts1, NULL, pp, pmd_kind); + } thread_state_asleep (ts1); } diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 5f91343..63bbb6d 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -64,7 +64,7 @@ struct deleted_participants_admin { int64_t delay; }; -struct proxy_writer_alive_state { +struct alive_state { bool alive; uint32_t vclock; }; @@ -197,6 +197,18 @@ bool is_local_orphan_endpoint (const struct entity_common *e) is_builtin_endpoint (e->guid.entityid, NN_VENDORID_ECLIPSE)); } +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); +/* used in (proxy)participant for writer liveliness monitoring */ +const ddsrt_fibheap_def_t lease_fhdef_pp = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct lease, pp_heapnode), compare_lease_tdur); + static void entity_common_init (struct entity_common *e, struct q_globals *gv, const struct ddsi_guid *guid, const char *name, enum entity_kind kind, nn_wctime_t tcreate, nn_vendorid_t vendorid, bool onlylocal) { e->guid = *guid; @@ -413,17 +425,6 @@ 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; @@ -482,6 +483,81 @@ static void pp_release_entityid(struct participant *pp, ddsi_entityid_t id) ddsrt_mutex_unlock (&pp->e.lock); } +static void gc_participant_lease (struct gcreq *gcreq) +{ + lease_free (gcreq->arg); + gcreq_free (gcreq); +} + +static void participant_replace_minl (struct participant *pp, 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 (pp->e.gv->gcreq_queue, gc_participant_lease); + struct lease *lease_old = ddsrt_atomic_ldvoidp (&pp->minl_man); + assert (lease_old != NULL); + lease_unregister (lease_old); /* ensures lease will not expire while it is replaced */ + gcreq->arg = lease_old; + gcreq_enqueue (gcreq); + ddsrt_atomic_stvoidp (&pp->minl_man, lnew); +} + +static void participant_add_wr_lease_locked (struct participant * pp, const struct writer * wr) +{ + struct lease *minl_prev; + struct lease *minl_new; + + assert (wr->lease != NULL); + minl_prev = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man); + ddsrt_fibheap_insert (&lease_fhdef_pp, &pp->leaseheap_man, wr->lease); + minl_new = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man); + /* if inserted lease is new shortest lease */ + if (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 (ddsrt_atomic_ldvoidp (&pp->minl_man) == NULL); + ddsrt_atomic_stvoidp (&pp->minl_man, lnew); + } + else + { + participant_replace_minl (pp, lnew); + } + lease_register (lnew); + } +} + +static void participant_remove_wr_lease_locked (struct participant * pp, struct writer * wr) +{ + struct lease *minl; + + assert (wr->lease != NULL); + assert (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT); + minl = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man); + ddsrt_fibheap_delete (&lease_fhdef_pp, &pp->leaseheap_man, wr->lease); + /* if writer with min lease is removed: update participant lease to use new minimal duration */ + if (wr->lease == minl) + { + if ((minl = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man)) != NULL) + { + dds_duration_t trem = minl->tdur - wr->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); + participant_replace_minl (pp, lnew); + lease_register (lnew); + } + else + { + participant_replace_minl (pp, NULL); + } + } +} + dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist) { struct participant *pp; @@ -559,6 +635,9 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * pp->m_conn = NULL; } + ddsrt_fibheap_init (&lease_fhdef_pp, &pp->leaseheap_man); + ddsrt_atomic_stvoidp (&pp->minl_man, NULL); + /* Before we create endpoints -- and may call unref_participant if things go wrong -- we must initialize all that unref_participant depends on. */ @@ -1394,13 +1473,26 @@ 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) +static void writer_get_alive_state_locked (struct writer *wr, struct alive_state *st) +{ + st->alive = wr->alive; + st->vclock = wr->alive_vclock; +} + +static void writer_get_alive_state (struct writer *wr, struct alive_state *st) +{ + ddsrt_mutex_lock (&wr->e.lock); + writer_get_alive_state_locked (wr, st); + ddsrt_mutex_unlock (&wr->e.lock); +} + +static void proxy_writer_get_alive_state_locked (struct proxy_writer *pwr, struct 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) +static void proxy_writer_get_alive_state (struct proxy_writer *pwr, struct alive_state *st) { ddsrt_mutex_lock (&pwr->e.lock); proxy_writer_get_alive_state_locked (pwr, st); @@ -1464,7 +1556,73 @@ 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) +static void reader_update_notify_alive_state_invoke_cb (struct reader *rd, uint64_t iid, bool notify, int delta, const struct alive_state *alive_state) +{ + /* 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 = iid; + data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID; + if (delta < 0) { + data.extra = (uint32_t) LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE; + (rd->status_cb) (rd->status_cb_entity, &data); + } else if (delta > 0) { + data.extra = (uint32_t) LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE; + (rd->status_cb) (rd->status_cb_entity, &data); + } else { + /* Twitch: the resulting (proxy)writer state is unchanged, but there has been + a transition to another state and back to the current state. So we'll call + the callback twice in this case. */ + static const enum liveliness_changed_data_extra x[] = { + LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE, + LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE + }; + data.extra = (uint32_t) x[alive_state->alive]; + (rd->status_cb) (rd->status_cb_entity, &data); + data.extra = (uint32_t) x[!alive_state->alive]; + (rd->status_cb) (rd->status_cb_entity, &data); + } + } +} + +static void reader_update_notify_wr_alive_state (struct reader *rd, const struct writer *wr, const struct alive_state *alive_state) +{ + struct rd_wr_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_local_writers_treedef, &rd->local_writers, &wr->e.guid)) != NULL) + { + if ((int32_t) (alive_state->vclock - m->wr_alive_vclock) > 0) + { + delta = (int) alive_state->alive - (int) m->wr_alive; + notify = true; + m->wr_alive = alive_state->alive; + m->wr_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, &wr->e, wr->xqos, NN_STATUSINFO_UNREGISTER); + ddsi_rhc_unregister_wr (rd->rhc, &wrinfo); + } + + reader_update_notify_alive_state_invoke_cb (rd, wr->e.iid, notify, delta, alive_state); +} + +static void reader_update_notify_wr_alive_state_guid (const struct ddsi_guid *rd_guid, const struct writer *wr, const struct alive_state *alive_state) +{ + struct reader *rd; + if ((rd = entidx_lookup_reader_guid (wr->e.gv->entity_index, rd_guid)) != NULL) + reader_update_notify_wr_alive_state (rd, wr, alive_state); +} + +static void reader_update_notify_pwr_alive_state (struct reader *rd, const struct proxy_writer *pwr, const struct alive_state *alive_state) { struct rd_pwr_match *m; bool notify = false; @@ -1489,24 +1647,10 @@ static void reader_update_notify_pwr_alive_state (struct reader *rd, const struc 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); - } + reader_update_notify_alive_state_invoke_cb (rd, pwr->e.iid, notify, delta, alive_state); } -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) +static void reader_update_notify_pwr_alive_state_guid (const struct ddsi_guid *rd_guid, const struct proxy_writer *pwr, const struct alive_state *alive_state) { struct reader *rd; if ((rd = entidx_lookup_reader_guid (pwr->e.gv->entity_index, rd_guid)) != NULL) @@ -1573,7 +1717,7 @@ static void reader_drop_local_connection (const struct ddsi_guid *rd_guid, const status_cb_data_t data; data.handle = wr->e.iid; data.add = false; - data.extra = (uint32_t) LIVELINESS_CHANGED_REMOVE_ALIVE; + data.extra = (uint32_t) (m->wr_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); @@ -1812,7 +1956,7 @@ 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, const struct proxy_writer_alive_state *alive_state) +static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, nn_count_t *init_count, const struct alive_state *alive_state) { struct rd_pwr_match *m = ddsrt_malloc (sizeof (*m)); ddsrt_avl_ipath_t path; @@ -1886,12 +2030,14 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, } } -static void reader_add_local_connection (struct reader *rd, struct writer *wr) +static void reader_add_local_connection (struct reader *rd, struct writer *wr, const struct alive_state *alive_state) { struct rd_wr_match *m = ddsrt_malloc (sizeof (*m)); ddsrt_avl_ipath_t path; m->wr_guid = wr->e.guid; + m->wr_alive = alive_state->alive; + m->wr_alive_vclock = alive_state->vclock; ddsrt_mutex_lock (&rd->e.lock); @@ -1914,7 +2060,7 @@ static void reader_add_local_connection (struct reader *rd, struct writer *wr) status_cb_data_t data; data.handle = wr->e.iid; data.add = true; - data.extra = (uint32_t) LIVELINESS_CHANGED_ADD_ALIVE; + 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); @@ -2190,7 +2336,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; + struct alive_state alive_state; if (isb0 != isb1) return; if (rd->e.onlylocal) @@ -2242,6 +2388,7 @@ static bool ignore_local_p (const ddsi_guid_t *guid1, const ddsi_guid_t *guid2, static void connect_writer_with_reader (struct writer *wr, struct reader *rd, nn_mtime_t tnow) { dds_qos_policy_id_t reason; + struct alive_state alive_state; (void)tnow; if (!is_local_orphan_endpoint (&wr->e) && (is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE) || is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE))) return; @@ -2253,8 +2400,17 @@ static void connect_writer_with_reader (struct writer *wr, struct reader *rd, nn reader_qos_mismatch (rd, reason); return; } - reader_add_local_connection (rd, wr); + /* 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. */ + writer_get_alive_state (wr, &alive_state); + reader_add_local_connection (rd, wr, &alive_state); writer_add_local_connection (wr, rd); + + /* 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. */ + writer_get_alive_state (wr, &alive_state); + reader_update_notify_wr_alive_state (rd, wr, &alive_state); } static void connect_writer_with_proxy_reader_wrapper (struct entity_common *vwr, struct entity_common *vprd, nn_mtime_t tnow) @@ -2702,6 +2858,91 @@ unsigned remove_acked_messages (struct writer *wr, struct whc_state *whcst, stru return n; } +static void writer_notify_liveliness_change_may_unlock (struct writer *wr) +{ + struct alive_state alive_state; + writer_get_alive_state_locked (wr, &alive_state); + + struct ddsi_guid rdguid; + struct pwr_rd_match *m; + memset (&rdguid, 0, sizeof (rdguid)); + while (wr->alive_vclock == alive_state.vclock && + (m = ddsrt_avl_lookup_succ (&wr_local_readers_treedef, &wr->local_readers, &rdguid)) != NULL) + { + rdguid = m->rd_guid; + ddsrt_mutex_unlock (&wr->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_wr_alive_state_guid (&rdguid, wr, &alive_state); + ddsrt_mutex_lock (&wr->e.lock); + } +} + +void writer_set_alive_may_unlock (struct writer *wr, bool notify) +{ + /* Caller has wr->e.lock, so we can safely read wr->alive. Updating wr->alive requires + also taking wr->c.pp->e.lock because wr->alive <=> (wr->lease in pp's lease heap). */ + assert (!wr->alive); + + /* check that writer still exists (when deleting it is removed from guid hash) */ + if (entidx_lookup_writer_guid (wr->e.gv->entity_index, &wr->e.guid) == NULL) + { + ELOGDISC (wr, "writer_set_alive_may_unlock("PGUIDFMT") - not in entity index, wr deleting\n", PGUID (wr->e.guid)); + return; + } + + ddsrt_mutex_lock (&wr->c.pp->e.lock); + wr->alive = true; + wr->alive_vclock++; + if (wr->xqos->liveliness.lease_duration != T_NEVER) + { + if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT) + participant_add_wr_lease_locked (wr->c.pp, wr); + else if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_TOPIC) + lease_set_expiry (wr->lease, add_duration_to_etime (now_et (), wr->lease->tdur)); + } + ddsrt_mutex_unlock (&wr->c.pp->e.lock); + + if (notify) + writer_notify_liveliness_change_may_unlock (wr); +} + +static int writer_set_notalive_locked (struct writer *wr, bool notify) +{ + if (!wr->alive) + return DDS_RETCODE_PRECONDITION_NOT_MET; + + /* To update wr->alive, both wr->e.lock and wr->c.pp->e.lock + should be taken */ + ddsrt_mutex_lock (&wr->c.pp->e.lock); + wr->alive = false; + wr->alive_vclock++; + if (wr->xqos->liveliness.lease_duration != T_NEVER && wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT) + participant_remove_wr_lease_locked (wr->c.pp, wr); + ddsrt_mutex_unlock (&wr->c.pp->e.lock); + + if (notify) + { + if (wr->status_cb) + { + status_cb_data_t data; + data.handle = wr->e.iid; + data.raw_status_id = (int) DDS_LIVELINESS_LOST_STATUS_ID; + (wr->status_cb) (wr->status_cb_entity, &data); + } + writer_notify_liveliness_change_may_unlock (wr); + } + return DDS_RETCODE_OK; +} + +int writer_set_notalive (struct writer *wr, bool notify) +{ + ddsrt_mutex_lock (&wr->e.lock); + int ret = writer_set_notalive_locked(wr, notify); + ddsrt_mutex_unlock (&wr->e.lock); + return ret; +} + static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc, status_cb_t status_cb, void * status_entity) { ddsrt_cond_init (&wr->throttle_cond); @@ -2723,6 +2964,8 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se wr->throttle_tracing = 0; wr->rexmit_count = 0; wr->rexmit_lost_count = 0; + wr->alive = 1; + wr->alive_vclock = 0; wr->status_cb = status_cb; wr->status_cb_entity = status_entity; @@ -2835,7 +3078,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se } 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.lease_duration != T_NEVER) { wr->lease_duration = ddsrt_malloc (sizeof(*wr->lease_duration)); wr->lease_duration->ldur = wr->xqos->liveliness.lease_duration; @@ -2913,16 +3156,32 @@ static dds_return_t new_writer_guid (struct writer **wr_out, const struct ddsi_g if (wr->lease_duration != NULL) { 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)); + if (wr->xqos->liveliness.kind == DDS_LIVELINESS_AUTOMATIC) + { + /* 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); - /* 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 ()); + /* Trigger pmd update */ + (void) resched_xevent_if_earlier (pp->pmd_update_xevent, now_mt ()); + } + else + { + nn_etime_t texpire = add_duration_to_etime (now_et (), wr->lease_duration->ldur); + wr->lease = lease_new (texpire, wr->lease_duration->ldur, &wr->e); + if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT) + { + ddsrt_mutex_lock (&pp->e.lock); + participant_add_wr_lease_locked (pp, wr); + ddsrt_mutex_unlock (&pp->e.lock); + } + else + { + lease_register (wr->lease); + } + } } return 0; @@ -3019,6 +3278,8 @@ static void gc_delete_writer (struct gcreq *gcreq) { assert (wr->lease_duration->ldur == DDS_DURATION_INVALID); ddsrt_free (wr->lease_duration); + if (wr->xqos->liveliness.kind != DDS_LIVELINESS_AUTOMATIC) + lease_free (wr->lease); } /* Do last gasp on SEDP and free writer. */ @@ -3113,11 +3374,21 @@ dds_return_t delete_writer_nolinger_locked (struct writer *wr) entidx_remove_writer_guid (wr->e.gv->entity_index, 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 ()); + if (wr->xqos->liveliness.kind == DDS_LIVELINESS_AUTOMATIC) + { + 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); + resched_xevent_if_earlier (wr->c.pp->pmd_update_xevent, now_mt ()); + } + else + { + if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_TOPIC) + lease_unregister (wr->lease); + if (writer_set_notalive_locked (wr, false) != DDS_RETCODE_OK) + ELOGDISC (wr, "writer_set_notalive failed for "PGUIDFMT"\n", PGUID (wr->e.guid)); + } } gcreq_writer (wr); return 0; @@ -3541,21 +3812,13 @@ 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 gcreq *gcreq = gcreq_new (proxypp->e.gv->gcreq_queue, gc_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; @@ -3568,11 +3831,11 @@ void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct ddsrt_mutex_lock (&proxypp->e.lock); if (proxypp->owns_lease) { - struct lease *minl = ddsrt_fibheap_min (&lease_fhdef_proxypp, &proxypp->leaseheap_auto); - ddsrt_fibheap_delete (&lease_fhdef_proxypp, &proxypp->leaseheap_auto, proxypp->lease); + struct lease *minl = ddsrt_fibheap_min (&lease_fhdef_pp, &proxypp->leaseheap_auto); + ddsrt_fibheap_delete (&lease_fhdef_pp, &proxypp->leaseheap_auto, proxypp->lease); if (minl == proxypp->lease) { - if ((minl = ddsrt_fibheap_min (&lease_fhdef_proxypp, &proxypp->leaseheap_auto)) != NULL) + if ((minl = ddsrt_fibheap_min (&lease_fhdef_pp, &proxypp->leaseheap_auto)) != NULL) { dds_duration_t trem = minl->tdur - proxypp->lease->tdur; assert (trem >= 0); @@ -3599,7 +3862,7 @@ void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct 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 gcreq *gcreq = gcreq_new (proxypp->e.gv->gcreq_queue, gc_participant_lease); lease_unregister (proxypp->lease); gcreq->arg = proxypp->lease; gcreq_enqueue (gcreq); @@ -3620,9 +3883,9 @@ static void proxy_participant_add_pwr_lease_locked (struct proxy_participant * p 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); + minl_prev = ddsrt_fibheap_min (&lease_fhdef_pp, lh); + ddsrt_fibheap_insert (&lease_fhdef_pp, lh, pwr->lease); + minl_new = ddsrt_fibheap_min (&lease_fhdef_pp, lh); /* if inserted lease is new shortest lease */ if (proxypp->owns_lease && minl_prev != minl_new) { @@ -3651,12 +3914,12 @@ static void proxy_participant_remove_pwr_lease_locked (struct proxy_participant 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); + minl = ddsrt_fibheap_min (&lease_fhdef_pp, lh); + ddsrt_fibheap_delete (&lease_fhdef_pp, 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) + if ((minl = ddsrt_fibheap_min (&lease_fhdef_pp, lh)) != NULL) { dds_duration_t trem = minl->tdur - pwr->lease->tdur; assert (trem >= 0); @@ -3716,8 +3979,8 @@ void new_proxy_participant (struct q_globals *gv, const struct ddsi_guid *ppguid struct proxy_participant *privpp; privpp = entidx_lookup_proxy_participant_guid (gv->entity_index, &proxypp->privileged_pp_guid); - ddsrt_fibheap_init (&lease_fhdef_proxypp, &proxypp->leaseheap_auto); - ddsrt_fibheap_init (&lease_fhdef_proxypp, &proxypp->leaseheap_man); + ddsrt_fibheap_init (&lease_fhdef_pp, &proxypp->leaseheap_auto); + ddsrt_fibheap_init (&lease_fhdef_pp, &proxypp->leaseheap_man); ddsrt_atomic_stvoidp (&proxypp->minl_man, NULL); if (privpp != NULL && privpp->is_ddsi2_pp) @@ -3743,7 +4006,7 @@ void new_proxy_participant (struct q_globals *gv, const struct ddsi_guid *ppguid /* 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); + ddsrt_fibheap_insert (&lease_fhdef_pp, &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 @@ -3933,9 +4196,9 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p 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); + ddsrt_fibheap_delete (&lease_fhdef_pp, &proxypp->leaseheap_auto, proxypp->lease); + assert (ddsrt_fibheap_min (&lease_fhdef_pp, &proxypp->leaseheap_auto) == NULL); + assert (ddsrt_fibheap_min (&lease_fhdef_pp, &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); @@ -4445,7 +4708,7 @@ int delete_proxy_writer (struct q_globals *gv, const struct ddsi_guid *guid, nn_ static void proxy_writer_notify_liveliness_change_may_unlock (struct proxy_writer *pwr) { - struct proxy_writer_alive_state alive_state; + struct alive_state alive_state; proxy_writer_get_alive_state_locked (pwr, &alive_state); struct ddsi_guid rdguid; diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index 6a2d33a..bc974b1 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -144,6 +144,22 @@ void lease_free (struct lease *l) ddsrt_free (l); } +static void trace_lease_renew (const struct lease *l, const char *tag, nn_etime_t tend_new) +{ + struct q_globals const * gv = l->entity->gv; + if (gv->logconfig.c.mask & DDS_LC_TRACE) + { + int32_t tsec, tusec; + GVTRACE (" L(%s", tag); + if (l->entity->guid.entityid.u == NN_ENTITYID_PARTICIPANT) + GVTRACE (":%"PRIx32, l->entity->guid.entityid.u); + else + GVTRACE (""PGUIDFMT"", PGUID (l->entity->guid)); + etime_to_sec_usec (&tsec, &tusec, tend_new); + GVTRACE (" %"PRId32".%06"PRId32")", tsec, tusec); + } +} + void lease_renew (struct lease *l, nn_etime_t tnowE) { nn_etime_t tend_new = add_duration_to_etime (tnowE, l->tdur); @@ -160,18 +176,7 @@ void lease_renew (struct lease *l, nn_etime_t tnowE) * 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; - GVTRACE (" L("); - if (l->entity->guid.entityid.u == NN_ENTITYID_PARTICIPANT) - GVTRACE (":%"PRIx32, l->entity->guid.entityid.u); - else - GVTRACE (""PGUIDFMT"", PGUID (l->entity->guid)); - etime_to_sec_usec (&tsec, &tusec, tend_new); - GVTRACE (" %"PRId32".%06"PRId32")", tsec, tusec); - } + trace_lease_renew (l, "", tend_new); } void lease_set_expiry (struct lease *l, nn_etime_t when) @@ -189,6 +194,7 @@ void lease_set_expiry (struct lease *l, nn_etime_t when) TSCHED_NOT_ON_HEAP == INT64_MIN) */ l->tsched = when; ddsrt_fibheap_decrease_key (&lease_fhdef, &gv->leaseheap, l); + trace_lease_renew (l, "earlier ", when); trigger = true; } else if (l->tsched.v == TSCHED_NOT_ON_HEAP && when.v < T_NEVER) @@ -196,6 +202,7 @@ void lease_set_expiry (struct lease *l, nn_etime_t when) /* not currently scheduled, with a finite new expiry time */ l->tsched = when; ddsrt_fibheap_insert (&lease_fhdef, &gv->leaseheap, l); + trace_lease_renew (l, "insert ", when); trigger = true; } ddsrt_mutex_unlock (&gv->leaseheap_lock); @@ -283,9 +290,11 @@ int64_t check_and_handle_lease_expiration (struct q_globals *gv, nn_etime_t tnow case EK_PROXY_WRITER: proxy_writer_set_notalive ((struct proxy_writer *) l->entity, true); break; + case EK_WRITER: + writer_set_notalive ((struct writer *) l->entity, true); + break; case EK_PARTICIPANT: case EK_READER: - case EK_WRITER: case EK_PROXY_READER: assert (false); break; diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 24b4bab..9d35df5 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -1121,7 +1121,8 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct dst.prefix = rst->dst_guid_prefix; dst.entityid = msg->readerId; - RSTTRACE ("HEARTBEAT(%s#%"PRId32":%"PRId64"..%"PRId64" ", msg->smhdr.flags & HEARTBEAT_FLAG_FINAL ? "F" : "", msg->count, firstseq, lastseq); + RSTTRACE ("HEARTBEAT(%s%s#%"PRId32":%"PRId64"..%"PRId64" ", msg->smhdr.flags & HEARTBEAT_FLAG_FINAL ? "F" : "", + msg->smhdr.flags & HEARTBEAT_FLAG_LIVELINESS ? "L" : "", msg->count, firstseq, lastseq); if (!rst->forme) { @@ -1139,7 +1140,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct 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.kind != DDS_LIVELINESS_AUTOMATIC && pwr->c.xqos->liveliness.lease_duration != T_NEVER) { if ((lease = ddsrt_atomic_ldvoidp (&pwr->c.proxypp->minl_man)) != NULL) diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 14587a1..e967c73 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -32,6 +32,7 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_hbcontrol.h" +#include "dds/ddsi/q_lease.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_sertopic.h" @@ -675,6 +676,8 @@ dds_return_t write_hb_liveliness (struct q_globals * const gv, struct ddsi_guid struct nn_xmsg *msg = NULL; struct whc_state whcst; struct thread_state1 * const ts1 = lookup_thread_state (); + struct lease *lease; + thread_state_awake (ts1, gv); struct writer *wr = entidx_lookup_writer_guid (gv->entity_index, wr_guid); if (wr == NULL) @@ -682,6 +685,12 @@ dds_return_t write_hb_liveliness (struct q_globals * const gv, struct ddsi_guid GVTRACE ("write_hb_liveliness("PGUIDFMT") - writer not found\n", PGUID (*wr_guid)); return DDS_RETCODE_PRECONDITION_NOT_MET; } + + if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT && ((lease = ddsrt_atomic_ldvoidp (&wr->c.pp->minl_man)) != NULL)) + lease_renew (lease, now_et()); + else if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_TOPIC && wr->lease != NULL) + lease_renew (wr->lease, now_et()); + if ((msg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, sizeof (InfoTS_t) + sizeof (Heartbeat_t), NN_XMSG_KIND_CONTROL)) == NULL) return DDS_RETCODE_OUT_OF_RESOURCES; ddsrt_mutex_lock (&wr->e.lock); @@ -1081,6 +1090,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * int r; seqno_t seq; nn_mtime_t tnow; + struct lease *lease; /* If GC not allowed, we must be sure to never block when writing. That is only the case for (true, aggressive) KEEP_LAST writers, and also only if there is no limit to how much unacknowledged data the WHC may contain. */ assert (gc_allowed || (wr->xqos->history.kind == DDS_HISTORY_KEEP_LAST && wr->whc_low == INT32_MAX)); @@ -1102,8 +1112,16 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * goto drop; } + if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT && ((lease = ddsrt_atomic_ldvoidp (&wr->c.pp->minl_man)) != NULL)) + lease_renew (lease, now_et()); + else if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_TOPIC && wr->lease != NULL) + lease_renew (wr->lease, now_et()); + ddsrt_mutex_lock (&wr->e.lock); + if (!wr->alive) + writer_set_alive_may_unlock (wr, true); + if (end_of_txn) { wr->cs_seq = 0; diff --git a/src/tools/decode-trace b/src/tools/decode-trace index eedeee5..3f19c4d 100755 --- a/src/tools/decode-trace +++ b/src/tools/decode-trace @@ -36,6 +36,7 @@ for (@showopts) { my $topfmt = "%${topcolwidth}.${topcolwidth}s"; my $guidre = "[0-9a-f]+(?::[0-9a-f]+){3}"; my $gidre = "[0-9a-f]+(?::[0-9a-f]+){2}"; +my $leasere = "(?:L\\((?:[a-z]+ )?[0-9a-f:]+\\s+[0-9.]+\\)\\s*)+"; my %opstr = ("00" => "R ", "01" => "W ", # index by $stinfo.$dflag "10" => " D ", "11" => "WD ", "20" => " U", "21" => "W U", @@ -258,7 +259,7 @@ while(<>) { # decent proxy for that. # # FIXME: find a way of dealing with decimal representation ... - if (/: ACKNACK\(F?#\d+:(\d+)\/(\d+):[01]* (?:L\([0-9a-f:]+\s+[0-9.]+\)\s*)?([0-9a-f]+(?::[0-9a-f]+){2}:[234]c7) -\> ([0-9a-f]+(?::[0-9a-f]+){2}:[234]c2) .*?(happy-now)?/) { + if (/: ACKNACK\(F?#\d+:(\d+)\/(\d+):[01]* (?:$leasere)?([0-9a-f]+(?::[0-9a-f]+){2}:[234]c7) -\> ([0-9a-f]+(?::[0-9a-f]+){2}:[234]c2) .*?(happy-now)?/) { if (defined $5 || ($1 > 1 && $2 == 0 && version_at_least(6,6,4))) { # happy-now should be enough, but historically DDSI2 advertised only data present in the WHC, # which caused happy-now to not show up if the historical data ended on an unregister, because @@ -266,7 +267,7 @@ while(<>) { # last one written (that is, unregistered) (fixed in 6.6.4) check_disccomplete("A", $3); } - } elsif (/: HEARTBEAT\(F?#\d+:(\d+)\.\.(\d+)\s+(?:L\([0-9a-f:]+\s+[0-9.]+\)\s*)?([0-9a-f]+(?::[0-9a-f]+){2}:[234]c2)/) { + } elsif (/: HEARTBEAT\(F?L?#\d+:(\d+)\.\.(\d+)\s+(?:$leasere)?([0-9a-f]+(?::[0-9a-f]+){2}:[234]c2)/) { check_disccomplete("H", $3); # if there is no data and final is set there might be no ACK check_disccomplete("B", $3) if $2 < $1; @@ -745,7 +746,7 @@ while(<>) { if $nlost > 0 && $shows{rematch}; delete $prd->{matches}->{$wrguid}->{seqp1del}; } - } elsif (/ACKNACK\(F?#\d+:(\d+)\/\d+:([01]*) (?:L\(:1c1 [0-9.]+\) )?($guidre) -> ($guidre)(\??)/o) { + } elsif (/ACKNACK\(F?#\d+:(\d+)\/\d+:([01]*) (?:$leasere)?($guidre) -> ($guidre)(\??)/o) { my $seqp1 = $1; my $nackset = $2; my $prdguid = hexify($3); my $wrguid = hexify($4); my $wrknown = ($5 eq ""); my $wr = $wr{$wrguid}; my $cnt = ($nackset =~ y/1//); @@ -904,7 +905,7 @@ while(<>) { } } } - } elsif (/HEARTBEAT\(F?#\d+:(\d+)\.\.(\d+) ($guidre)/o) { + } elsif (/HEARTBEAT\(F?L?#\d+:(\d+)\.\.(\d+) ($guidre)/o) { my $prdguid = hexify($3); (my $ppguid = $prdguid) =~ s/:[0-9a-f]+$/:1c1/; $proxypp{$ppguid}->{non_spdp_seen} = 1 if exists $proxypp{$ppguid} && !defined $proxypp{$ppguid}->{tdel}; @@ -1475,7 +1476,7 @@ not necessarily the 4th field in, say, AWK): EOT ; exit 1; - return; + return; } sub fmtblurb { From 02c2753bd7c985146fe0a84fbfc580cb6e4cf343 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 28 Jan 2020 12:36:30 +0100 Subject: [PATCH 15/28] Fixes in liveliness test lease_duration_zero_or_one Signed-off-by: Dennis Potman --- src/core/ddsc/tests/liveliness.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/core/ddsc/tests/liveliness.c b/src/core/ddsc/tests/liveliness.c index 25ccac1..497b131 100644 --- a/src/core/ddsc/tests/liveliness.c +++ b/src/core/ddsc/tests/liveliness.c @@ -218,9 +218,9 @@ static void test_pmd_count(dds_liveliness_kind_t kind, uint32_t ldur, double mul /* 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)) + CU_ASSERT_FATAL(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) + CU_ASSERT_FATAL(get_pmd_seqno(g_pub_participant) - start_seqno < mult) /* cleanup */ if (remote_reader) @@ -1097,14 +1097,18 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines CU_ASSERT_FATAL(rc == DDS_RETCODE_OK); /* verify the reader received all samples */ + void *raw[] = { &sample }; + dds_sample_info_t si; + uint32_t cnt = 0; + do { - void *raw[] = { &sample }; - dds_sample_info_t si; - uint32_t cnt = 0; - while (dds_take(reader, raw, &si, 1, 1) == 1) + rc = dds_waitset_wait(waitset, NULL, 0, DDS_SECS(5)); + CU_ASSERT_FATAL(rc >= 1); + while (dds_take(reader, raw, &si, 1, 1) == 1 && si.valid_data) cnt++; - CU_ASSERT(cnt == nsamples + 1); } + while (cnt < nsamples + 1); + CU_ASSERT_FATAL(cnt == nsamples + 1); /* transition to not alive is not necessarily immediate */ { @@ -1115,8 +1119,8 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines ddsrt_mutex_lock (&listener_state.lock); printf("early w0 %"PRIx64" alive %"PRId32" not-alive %"PRId32"\n", listener_state.w0_handle, listener_state.w0_alive, listener_state.w0_not_alive); - CU_ASSERT(!listener_state.weirdness); - CU_ASSERT(listener_state.w0_handle != 0); + CU_ASSERT_FATAL(!listener_state.weirdness); + CU_ASSERT_FATAL(listener_state.w0_handle != 0); while (listener_state.w0_not_alive < listener_state.w0_alive && retries-- > 0) { ddsrt_mutex_unlock(&listener_state.lock); @@ -1128,7 +1132,7 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines printf("late liveliness changed status: alive %"PRId32" not-alive %"PRId32"\n", lstatus.alive_count, lstatus.not_alive_count); printf("final w0 %"PRIx64" alive %"PRId32" not-alive %"PRId32"\n", listener_state.w0_handle, listener_state.w0_alive, listener_state.w0_not_alive); - CU_ASSERT(listener_state.w0_alive == listener_state.w0_not_alive); + CU_ASSERT_FATAL(listener_state.w0_alive == listener_state.w0_not_alive); uint32_t exp_alive; if (sleep == 0) exp_alive = 1; /* if not sleeping, it's ok if the transition happens only once */ @@ -1137,7 +1141,7 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines else exp_alive = nsamples - nsamples / 5; /* if sleeping, expect the vast majority (80%) of the writes to toggle liveliness */ printf("check w0_alive %d >= %d\n", listener_state.w0_alive, exp_alive); - CU_ASSERT(listener_state.w0_alive >= exp_alive); + CU_ASSERT_FATAL(listener_state.w0_alive >= exp_alive); ddsrt_mutex_unlock(&listener_state.lock); } From 150f20d10c36adfb1b4def6d558238214b77157d Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 4 Feb 2020 11:45:04 +0100 Subject: [PATCH 16/28] Bugfix in liveliness tests Some of the liveliness qos tests were not using unique topic names for the tests for local and remote readers. Re-using the participant for these 2 tests results in unexpected reader-proxywriter matches in the latter test. Fixed by adding a sequence number in the topic name. Signed-off-by: Dennis Potman --- src/core/ddsc/tests/liveliness.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/ddsc/tests/liveliness.c b/src/core/ddsc/tests/liveliness.c index 497b131..a11e5ea 100644 --- a/src/core/ddsc/tests/liveliness.c +++ b/src/core/ddsc/tests/liveliness.c @@ -428,7 +428,7 @@ CU_Test(ddsc_liveliness, lease_duration, .init = liveliness_init, .fini = liveli uint32_t n; /* topics */ - create_topic_name("ddsc_liveliness_ldur", 1, name, sizeof name); + create_topic_name("ddsc_liveliness_ldur", 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); @@ -489,7 +489,7 @@ static void test_lease_duration_pwr(bool remote_reader) printf("running test lease_duration_pwr: %s reader\n", remote_reader ? "remote" : "local"); /* topics */ - create_topic_name("ddsc_liveliness_ldurpwr", 1, name, sizeof name); + create_topic_name("ddsc_liveliness_ldurpwr", g_topic_nr++, name, sizeof name); CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); if (remote_reader) CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); @@ -571,7 +571,7 @@ static void test_create_delete_writer_stress(bool remote_reader) printf("running test create_delete_writer_stress: %s reader\n", remote_reader ? "remote" : "local"); /* topics */ - create_topic_name("ddsc_liveliness_wr_stress", 1, name, sizeof name); + create_topic_name("ddsc_liveliness_wr_stress", g_topic_nr++, name, sizeof name); CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); if (remote_reader) CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); From e4069d79ca6910c3f3c91ff5db67bdd3ae53f04d Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Thu, 6 Feb 2020 12:00:43 +0100 Subject: [PATCH 17/28] Update readme file with info on adding Bintray repository to conan remotes list Signed-off-by: Dennis Potman --- README.md | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index c0c5def..7742ed5 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ current [ROS2 RMW layer](https://github.com/ros2/rmw_cyclonedds), that is suffic To obtain Eclipse Cyclone DDS, do - $ git clone https://github.com/eclipse-cyclonedds/cyclonedds.git + $ git clone https://github.com/eclipse-cyclonedds/cyclonedds.git $ cd cyclonedds $ mkdir build @@ -66,7 +66,7 @@ generating build files. For example, "Visual Studio 15 2017 Win64" would target using Visual Studio 2017. To install it after a successful build, do: - + $ cmake --build . --target install which will copy everything to: @@ -102,12 +102,21 @@ Such a build requires the presence of [CUnit](http://cunit.sourceforge.net/). Y yourself, or you can choose to instead rely on the [Conan](https://conan.io) packaging system that the CI build infrastructure also uses. In that case, install Conan and do: - $ conan install .. + $ conan install .. --build missing -in the build directory prior to running cmake. For Windows, depending on the generator, you might -also need to add switches to select the architecture and build type, e.g., ``conan install -s -arch=x86_64 -s build_type=Debug ..`` This will automatically download and/or build CUnit (and, at -the moment, OpenSSL). +in the build directory prior to running cmake. + +The CUnit Conan package is hosted in the [Bintray repository](https://bintray.com/bincrafters/public-conan). +In case this repository was not added to your Conan remotes list yet (and the above mentioned install +command failed because it could not find the CUnit package), you can add the Bintray repository by: + + $ conan remote add https://api.bintray.com/conan/bincrafters/public-conan + +Replace ```` with a name that identifies the repository (e.g. my-conan-bintray). + +For Windows, depending on the generator, you might also need to add switches to select the architecture +and build type, e.g., ``conan install -s arch=x86_64 -s build_type=Debug ..`` This will automatically +download and/or build CUnit (and, at the moment, OpenSSL). ## Documentation @@ -128,14 +137,14 @@ to run the program, it is merely to illustrate the process. $ cd roundtrip $ cmake /share/CycloneDDS/examples/roundtrip $ cmake --build . - + On one terminal start the application that will be responding to pings: $ ./RoundtripPong On another terminal, start the application that will be sending the pings: - - $ ./RoundtripPing 0 0 0 + + $ ./RoundtripPing 0 0 0 # payloadSize: 0 | numSamples: 0 | timeOut: 0 # Waiting for startup jitter to stabilise # Warm up complete. From 59d4d1eb5739ab5a436bbbe04df5ed263baf0a09 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Thu, 6 Feb 2020 12:36:14 +0100 Subject: [PATCH 18/28] Processed review comments: fixed Bincrafters repo name in readme and changed suggested local name for repo Signed-off-by: Dennis Potman --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7742ed5..6a85ddb 100644 --- a/README.md +++ b/README.md @@ -106,13 +106,14 @@ the CI build infrastructure also uses. In that case, install Conan and do: in the build directory prior to running cmake. -The CUnit Conan package is hosted in the [Bintray repository](https://bintray.com/bincrafters/public-conan). -In case this repository was not added to your Conan remotes list yet (and the above mentioned install -command failed because it could not find the CUnit package), you can add the Bintray repository by: +The CUnit Conan package is hosted in the +[Bincrafters Bintray repository](https://bintray.com/bincrafters/public-conan). In case this repository +was not added to your Conan remotes list yet (and the above mentioned install command failed because it +could not find the CUnit package), you can add the Bintray repository by: $ conan remote add https://api.bintray.com/conan/bincrafters/public-conan -Replace ```` with a name that identifies the repository (e.g. my-conan-bintray). +Replace ```` with a name that identifies the repository (e.g. ``bincrafters``). For Windows, depending on the generator, you might also need to add switches to select the architecture and build type, e.g., ``conan install -s arch=x86_64 -s build_type=Debug ..`` This will automatically From 3de040d21ad7bac1e6d55779219b2f50675236bd Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Wed, 5 Feb 2020 23:23:04 +0100 Subject: [PATCH 19/28] Add support for musl libc Based on patch by mauropasse (issue #383). Signed-off-by: Jeroen Koekkoek --- src/core/ddsi/src/sysdeps.c | 2 +- src/ddsrt/src/threads/posix/threads.c | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/core/ddsi/src/sysdeps.c b/src/core/ddsi/src/sysdeps.c index e7b2915..b1ce8c3 100644 --- a/src/core/ddsi/src/sysdeps.c +++ b/src/core/ddsi/src/sysdeps.c @@ -18,7 +18,7 @@ #include "dds/ddsi/q_log.h" #include "dds/ddsi/sysdeps.h" -#if DDSRT_WITH_FREERTOS || !(defined __APPLE__ || defined __linux) || (__GNUC__ > 0 && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40100) +#if DDSRT_WITH_FREERTOS || !(defined __APPLE__ || (defined __linux && (defined __GLIBC__ || defined __UCLIBC__))) || (__GNUC__ > 0 && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40100) void log_stacktrace (const struct ddsrt_log_cfg *logcfg, const char *name, ddsrt_thread_t tid) { DDSRT_UNUSED_ARG (name); diff --git a/src/ddsrt/src/threads/posix/threads.c b/src/ddsrt/src/threads/posix/threads.c index 0d2c387..14d09fd 100644 --- a/src/ddsrt/src/threads/posix/threads.c +++ b/src/ddsrt/src/threads/posix/threads.c @@ -39,6 +39,7 @@ typedef struct { } thread_context_t; #if defined(__linux) +#include #include #include #define MAXTHREADNAMESIZE (15) /* 16 bytes including null-terminating byte. */ @@ -72,9 +73,10 @@ ddsrt_thread_getname(char *str, size_t size) assert(size > 0); #if defined(__linux) - /* Thread names are limited to 16 bytes on Linux. ERANGE is returned if the - buffer is smaller than 16 bytes. Use an intermediate buffer. */ - (void)pthread_getname_np(pthread_self(), buf, sizeof(buf)); + /* Thread names are limited to 16 bytes on Linux, which the buffer should + allow space for. prctl is favored over pthread_getname_np for + portability. e.g. musl libc. */ + (void)prctl(PR_GET_NAME, (unsigned long)buf, 0UL, 0UL, 0UL); cnt = ddsrt_strlcpy(str, buf, size); #elif defined(__APPLE__) /* pthread_getname_np on APPLE uses strlcpy to copy the thread name, but From 2d252ad1f6a37dd63e12d0cf81015b4d210aced8 Mon Sep 17 00:00:00 2001 From: Michel Date: Mon, 10 Feb 2020 10:10:42 +0100 Subject: [PATCH 20/28] Description corrections. Signed-off-by: Michel --- src/core/ddsc/include/dds/dds.h | 6 +++--- src/core/ddsc/include/dds/ddsc/dds_public_qos.h | 4 +++- src/ddsrt/include/dds/ddsrt/time.h | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index 85d015f..089eea8 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -1324,7 +1324,7 @@ dds_create_writer( * * This operation registers an instance with a key value to the data writer and * returns an instance handle that could be used for successive write & dispose - * operations. When the handle is not allocated, the function will return and + * operations. When the handle is not allocated, the function will return an * error and the handle will be un-touched. * * @param[in] writer The writer to which instance has be associated. @@ -2035,7 +2035,7 @@ dds_waitset_attach( * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK - * Entity attached. + * Entity detached. * @retval DDS_RETCODE_ERROR * An internal error has occurred. * @retval DDS_RETCODE_BAD_PARAMETER @@ -2072,7 +2072,7 @@ dds_waitset_detach( * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK - * Entity attached. + * Trigger value set. * @retval DDS_RETCODE_ERROR * An internal error has occurred. * @retval DDS_RETCODE_BAD_PARAMETER diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h index 503a567..eb0a670 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h @@ -149,6 +149,8 @@ dds_qset_durability (dds_qos_t * __restrict qos, dds_durability_kind_t kind); /** * @brief Set the history policy of a qos structure. + * + * Note that depth is only relevant for keep last. If you want limited history for keep all, use dds_qset_resource_limits(). * * @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy * @param[in] kind - History kind value \ref DCPS_QoS_History @@ -297,7 +299,7 @@ dds_qset_partition1 ( * * @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy * @param[in] kind - Reliability kind - * @param[in] max_blocking_time - Max blocking duration applied when kind is reliable. + * @param[in] max_blocking_time - Max blocking duration applied when kind is reliable. This is how long the writer will block when its history is full. */ DDS_EXPORT void dds_qset_reliability ( diff --git a/src/ddsrt/include/dds/ddsrt/time.h b/src/ddsrt/include/dds/ddsrt/time.h index 3570801..a604a5e 100644 --- a/src/ddsrt/include/dds/ddsrt/time.h +++ b/src/ddsrt/include/dds/ddsrt/time.h @@ -43,7 +43,7 @@ extern "C" { /** Absolute Time definition */ typedef int64_t dds_time_t; -/** Relative Time definition */ +/** Relative Time definition in nanoseconds */ typedef int64_t dds_duration_t; /** @name Macro definition for time units in nanoseconds. From 6bd28fb4b1b627f00f2892bb6a0e46ca29416d74 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 7 Jan 2020 15:59:17 +0100 Subject: [PATCH 21/28] Add plist diff and partial fini functions To bring them in line with the QoS support. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_plist.h | 2 ++ src/core/ddsi/src/q_plist.c | 44 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/core/ddsi/include/dds/ddsi/q_plist.h b/src/core/ddsi/include/dds/ddsi/q_plist.h index 930dc44..cf9dd2e 100644 --- a/src/core/ddsi/include/dds/ddsi/q_plist.h +++ b/src/core/ddsi/include/dds/ddsi/q_plist.h @@ -228,9 +228,11 @@ DDS_EXPORT nn_plist_t *nn_plist_dup (const nn_plist_t *src); */ DDS_EXPORT dds_return_t nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uint64_t pwanted, uint64_t qwanted, const nn_plist_src_t *src); DDS_EXPORT void nn_plist_fini (nn_plist_t *ps); +DDS_EXPORT void nn_plist_fini_mask (nn_plist_t *plist, uint64_t pmask, uint64_t qmask); DDS_EXPORT void nn_plist_unalias (nn_plist_t *plist); DDS_EXPORT void nn_plist_addtomsg (struct nn_xmsg *m, const nn_plist_t *ps, uint64_t pwanted, uint64_t qwanted); DDS_EXPORT void nn_plist_init_default_participant (nn_plist_t *plist); +DDS_EXPORT void nn_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const nn_plist_t *x, const nn_plist_t *y, uint64_t pmask, uint64_t qmask); struct nn_rmsg; struct nn_rsample_info; diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index dc2c9f0..3ed9ff0 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -1625,6 +1625,11 @@ void nn_plist_fini (nn_plist_t *plist) plist_or_xqos_fini (plist, 0, ~(uint64_t)0, ~(uint64_t)0); } +void nn_plist_fini_mask (nn_plist_t *plist, uint64_t pmask, uint64_t qmask) +{ + plist_or_xqos_fini (plist, 0, pmask, qmask); +} + void nn_plist_unalias (nn_plist_t *plist) { plist_or_xqos_unalias (plist, 0); @@ -1708,6 +1713,45 @@ uint64_t nn_xqos_delta (const dds_qos_t *x, const dds_qos_t *y, uint64_t mask) return delta; } +void nn_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const nn_plist_t *x, const nn_plist_t *y, uint64_t pmask, uint64_t qmask) +{ + if (piddesc_unalias[0] == NULL) + nn_plist_init_tables (); + *pdelta = (x->present ^ y->present) & pmask; + const uint64_t pcheck = (x->present & y->present) & pmask; + *qdelta = (x->qos.present ^ y->qos.present) & qmask; + const uint64_t qcheck = (x->qos.present & y->qos.present) & qmask; + for (size_t k = 0; k < sizeof (piddesc_tables_all) / sizeof (piddesc_tables_all[0]); k++) + { + struct piddesc const * const table = piddesc_tables_all[k]; + for (uint32_t i = 0; table[i].pid != PID_SENTINEL; i++) + { + struct piddesc const * const entry = &table[i]; + const uint64_t check = (entry->flags & PDF_QOS) ? qcheck : pcheck; + uint64_t * const delta = (entry->flags & PDF_QOS) ? qdelta : pdelta; + /* QoS come first in the table, but for those we use nn_xqos_delta */ + if (entry->flags & PDF_QOS) + continue; + if (check & entry->present_flag) + { + const size_t srcoff = entry->plist_offset; + bool equal; + /* Partition is special-cased because it is a set (with a special rules + for empty sets and empty strings to boot), and normal string sequence + comparison requires the ordering to be the same */ + if (entry->pid == PID_PARTITION) + equal = partitions_equal (&x->qos.partition, &y->qos.partition); + else if (!(entry->flags & PDF_FUNCTION)) + equal = equal_generic (x, y, srcoff, entry->op.desc); + else + equal = entry->op.f.equal (x, y, srcoff); + if (!equal) + *delta |= entry->present_flag; + } + } + } +} + static dds_return_t validate_external_duration (const ddsi_duration_t *d) { /* Accepted are zero, positive, infinite or invalid as defined in From 08c9db09347c11e270466d713c2c1cee007eb46c Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 8 Jan 2020 12:26:21 +0100 Subject: [PATCH 22/28] Rework plist/qos printing, diffing and logging * Use the parameter tables to pretty-print QoS and plist, rather than a hard-coded function supporting only the QoS. * Support diffing two plists: a single table-driven function can handle both nn_plist_t and ddsi_qos_t, and it removes the discrepancy between the two types. * Log content of discovery samples in trace rather than merely printing "(plist)" Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_topic.c | 1 + src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h | 6 +- .../include/dds/ddsi/ddsi_serdata_default.h | 1 + src/core/ddsi/include/dds/ddsi/ddsi_tran.h | 10 +- src/core/ddsi/include/dds/ddsi/q_plist.h | 2 + src/core/ddsi/include/dds/ddsi/q_protocol.h | 4 +- src/core/ddsi/include/dds/ddsi/q_xqos.h | 3 +- src/core/ddsi/src/ddsi_ipaddr.c | 13 +- src/core/ddsi/src/ddsi_mcgroup.c | 6 +- src/core/ddsi/src/ddsi_raweth.c | 8 +- src/core/ddsi/src/ddsi_serdata_default.c | 25 +- src/core/ddsi/src/ddsi_tcp.c | 44 +- src/core/ddsi/src/ddsi_tran.c | 75 ++- src/core/ddsi/src/ddsi_udp.c | 10 +- src/core/ddsi/src/q_addrset.c | 9 +- src/core/ddsi/src/q_ddsi_discovery.c | 6 +- src/core/ddsi/src/q_debmon.c | 4 +- src/core/ddsi/src/q_entity.c | 14 +- src/core/ddsi/src/q_init.c | 21 +- src/core/ddsi/src/q_nwif.c | 8 +- src/core/ddsi/src/q_plist.c | 588 ++++++++++++------ src/core/ddsi/src/q_receive.c | 4 +- src/core/ddsi/src/q_xmsg.c | 2 +- src/mpt/tests/qos/procs/rw.c | 20 +- src/tools/decode-trace | 11 +- 25 files changed, 575 insertions(+), 320 deletions(-) diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 7d9df7d..9c4c724 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -482,6 +482,7 @@ dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descrip st = dds_alloc (sizeof (*st)); ddsi_sertopic_init (&st->c, name, desc->m_typename, &ddsi_sertopic_ops_default, desc->m_nkeys ? &ddsi_serdata_ops_cdr : &ddsi_serdata_ops_cdr_nokey, (desc->m_nkeys == 0)); + st->gv = &ppent->m_domain->gv; st->native_encoding_identifier = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE); st->serpool = ppent->m_domain->gv.serpool; st->type = (void*) desc; diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h b/src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h index 96257fa..392c41b 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h @@ -18,11 +18,11 @@ extern "C" { #endif -enum ddsi_nearby_address_result ddsi_ipaddr_is_nearby_address (ddsi_tran_factory_t tran, const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface *interf); +enum ddsi_nearby_address_result ddsi_ipaddr_is_nearby_address (const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface *interf); enum ddsi_locator_from_string_result ddsi_ipaddr_from_string (ddsi_tran_factory_t tran, nn_locator_t *loc, const char *str, int32_t kind); int ddsi_ipaddr_compare (const struct sockaddr *const sa1, const struct sockaddr *const sa2); -char *ddsi_ipaddr_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port); -void ddsi_ipaddr_to_loc (nn_locator_t *dst, const struct sockaddr *src, int32_t kind); +char *ddsi_ipaddr_to_string (char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port); +void ddsi_ipaddr_to_loc (const struct ddsi_tran_factory *tran, nn_locator_t *dst, const struct sockaddr *src, int32_t kind); void ddsi_ipaddr_from_loc (struct sockaddr_storage *dst, const nn_locator_t *src); #if defined (__cplusplus) diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h index ae582ff..4aa7f7b 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -107,6 +107,7 @@ struct ddsi_sertopic_default { struct ddsi_sertopic c; uint16_t native_encoding_identifier; /* (PL_)?CDR_(LE|BE) */ struct serdatapool *serpool; + struct q_globals *gv; struct dds_topic_descriptor * type; unsigned nkeys; diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_tran.h b/src/core/ddsi/include/dds/ddsi/ddsi_tran.h index 488b401..6d5f25f 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_tran.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_tran.h @@ -78,7 +78,7 @@ enum ddsi_nearby_address_result { DNAR_SAME }; -typedef enum ddsi_nearby_address_result (*ddsi_is_nearby_address_fn_t) (ddsi_tran_factory_t tran, const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface *interf); +typedef enum ddsi_nearby_address_result (*ddsi_is_nearby_address_fn_t) (const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface *interf); enum ddsi_locator_from_string_result { AFSR_OK, /* conversion succeeded */ @@ -89,7 +89,7 @@ enum ddsi_locator_from_string_result { typedef enum ddsi_locator_from_string_result (*ddsi_locator_from_string_fn_t) (ddsi_tran_factory_t tran, nn_locator_t *loc, const char *str); -typedef char * (*ddsi_locator_to_string_fn_t) (ddsi_tran_factory_t tran, char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port); +typedef char * (*ddsi_locator_to_string_fn_t) (char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port); typedef int (*ddsi_enumerate_interfaces_fn_t) (ddsi_tran_factory_t tran, enum transport_selector transport_selector, ddsrt_ifaddrs_t **interfs); @@ -255,7 +255,7 @@ void ddsi_conn_transfer_group_membership (ddsi_tran_conn_t conn, ddsi_tran_conn_ int ddsi_conn_rejoin_transferred_mcgroups (ddsi_tran_conn_t conn); int ddsi_is_mcaddr (const struct q_globals *gv, const nn_locator_t *loc); int ddsi_is_ssm_mcaddr (const struct q_globals *gv, const nn_locator_t *loc); -enum ddsi_nearby_address_result ddsi_is_nearby_address (const struct q_globals *gv, const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface *interf); +enum ddsi_nearby_address_result ddsi_is_nearby_address (const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface *interf); enum ddsi_locator_from_string_result ddsi_locator_from_string (const struct q_globals *gv, nn_locator_t *loc, const char *str, ddsi_tran_factory_t default_factory); @@ -270,8 +270,8 @@ enum ddsi_locator_from_string_result ddsi_locator_from_string (const struct q_gl */ #define DDSI_LOCSTRLEN 70 -char *ddsi_locator_to_string (const struct q_globals *gv, char *dst, size_t sizeof_dst, const nn_locator_t *loc); -char *ddsi_locator_to_string_no_port (const struct q_globals *gv, char *dst, size_t sizeof_dst, const nn_locator_t *loc); +char *ddsi_locator_to_string (char *dst, size_t sizeof_dst, const nn_locator_t *loc); +char *ddsi_locator_to_string_no_port (char *dst, size_t sizeof_dst, const nn_locator_t *loc); int ddsi_enumerate_interfaces (ddsi_tran_factory_t factory, enum transport_selector transport_selector, ddsrt_ifaddrs_t **interfs); diff --git a/src/core/ddsi/include/dds/ddsi/q_plist.h b/src/core/ddsi/include/dds/ddsi/q_plist.h index cf9dd2e..346e70e 100644 --- a/src/core/ddsi/include/dds/ddsi/q_plist.h +++ b/src/core/ddsi/include/dds/ddsi/q_plist.h @@ -233,6 +233,8 @@ DDS_EXPORT void nn_plist_unalias (nn_plist_t *plist); DDS_EXPORT void nn_plist_addtomsg (struct nn_xmsg *m, const nn_plist_t *ps, uint64_t pwanted, uint64_t qwanted); DDS_EXPORT void nn_plist_init_default_participant (nn_plist_t *plist); DDS_EXPORT void nn_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const nn_plist_t *x, const nn_plist_t *y, uint64_t pmask, uint64_t qmask); +DDS_EXPORT void nn_plist_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const nn_plist_t *plist); +DDS_EXPORT size_t nn_plist_print (char * __restrict buf, size_t bufsize, const nn_plist_t *plist); struct nn_rmsg; struct nn_rsample_info; diff --git a/src/core/ddsi/include/dds/ddsi/q_protocol.h b/src/core/ddsi/include/dds/ddsi/q_protocol.h index 54844f9..e158df9 100644 --- a/src/core/ddsi/include/dds/ddsi/q_protocol.h +++ b/src/core/ddsi/include/dds/ddsi/q_protocol.h @@ -58,9 +58,9 @@ typedef struct nn_fragment_number_set_header { typedef int32_t nn_count_t; #define DDSI_COUNT_MIN (-2147483647 - 1) #define DDSI_COUNT_MAX (2147483647) -/* address field in locator maintained in network byte order, the rest - in host (yes: that's a FIXME) */ +/* address field in locator maintained in network byte order, the rest in host */ typedef struct { + const struct ddsi_tran_factory *tran; int32_t kind; uint32_t port; unsigned char address[16]; diff --git a/src/core/ddsi/include/dds/ddsi/q_xqos.h b/src/core/ddsi/include/dds/ddsi/q_xqos.h index cecd24b..d591da2 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xqos.h +++ b/src/core/ddsi/include/dds/ddsi/q_xqos.h @@ -319,7 +319,8 @@ DDS_EXPORT dds_return_t nn_xqos_valid (const struct ddsrt_log_cfg *logcfg, const DDS_EXPORT void nn_xqos_mergein_missing (dds_qos_t *a, const dds_qos_t *b, uint64_t mask); DDS_EXPORT uint64_t nn_xqos_delta (const dds_qos_t *a, const dds_qos_t *b, uint64_t mask); DDS_EXPORT void nn_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, uint64_t wanted); -DDS_EXPORT void nn_log_xqos (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos); +DDS_EXPORT void nn_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos); +DDS_EXPORT size_t nn_xqos_print (char * __restrict buf, size_t bufsize, const dds_qos_t *xqos); DDS_EXPORT dds_qos_t *nn_xqos_dup (const dds_qos_t *src); #if defined (__cplusplus) diff --git a/src/core/ddsi/src/ddsi_ipaddr.c b/src/core/ddsi/src/ddsi_ipaddr.c index f939816..1172201 100644 --- a/src/core/ddsi/src/ddsi_ipaddr.c +++ b/src/core/ddsi/src/ddsi_ipaddr.c @@ -54,11 +54,10 @@ int ddsi_ipaddr_compare (const struct sockaddr *const sa1, const struct sockaddr return eq; } -enum ddsi_nearby_address_result ddsi_ipaddr_is_nearby_address (ddsi_tran_factory_t tran, const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface interf[]) +enum ddsi_nearby_address_result ddsi_ipaddr_is_nearby_address (const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface interf[]) { struct sockaddr_storage tmp, iftmp, nmtmp, ownip; size_t i; - (void)tran; ddsi_ipaddr_from_loc(&tmp, loc); for (i = 0; i < ninterf; i++) { @@ -111,16 +110,15 @@ enum ddsi_locator_from_string_result ddsi_ipaddr_from_string (ddsi_tran_factory_ if (tmpaddr.ss_family != af) { return AFSR_MISMATCH; } - ddsi_ipaddr_to_loc (loc, (struct sockaddr *)&tmpaddr, kind); + ddsi_ipaddr_to_loc (tran, loc, (struct sockaddr *)&tmpaddr, kind); /* This is just an address, so there is no valid value for port, other than INVALID. Without a guarantee that tmpaddr has port 0, best is to set it explicitly here */ loc->port = NN_LOCATOR_PORT_INVALID; return AFSR_OK; } -char *ddsi_ipaddr_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port) +char *ddsi_ipaddr_to_string (char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port) { - (void)tran; assert (sizeof_dst > 1); if (loc->kind == NN_LOCATOR_KIND_INVALID) (void) snprintf (dst, sizeof_dst, "(invalid)"); @@ -161,8 +159,9 @@ char *ddsi_ipaddr_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_ return dst; } -void ddsi_ipaddr_to_loc (nn_locator_t *dst, const struct sockaddr *src, int32_t kind) +void ddsi_ipaddr_to_loc (const struct ddsi_tran_factory *tran, nn_locator_t *dst, const struct sockaddr *src, int32_t kind) { + dst->tran = (struct ddsi_tran_factory *) tran; dst->kind = kind; switch (src->sa_family) { @@ -172,6 +171,7 @@ void ddsi_ipaddr_to_loc (nn_locator_t *dst, const struct sockaddr *src, int32_t assert (kind == NN_LOCATOR_KIND_UDPv4 || kind == NN_LOCATOR_KIND_TCPv4); if (x->sin_addr.s_addr == htonl (INADDR_ANY)) { + dst->tran = NULL; dst->kind = NN_LOCATOR_KIND_INVALID; dst->port = NN_LOCATOR_PORT_INVALID; memset (dst->address, 0, sizeof (dst->address)); @@ -191,6 +191,7 @@ void ddsi_ipaddr_to_loc (nn_locator_t *dst, const struct sockaddr *src, int32_t assert (kind == NN_LOCATOR_KIND_UDPv6 || kind == NN_LOCATOR_KIND_TCPv6); if (IN6_IS_ADDR_UNSPECIFIED (&x->sin6_addr)) { + dst->tran = NULL; dst->kind = NN_LOCATOR_KIND_INVALID; dst->port = NN_LOCATOR_PORT_INVALID; memset (dst->address, 0, sizeof (dst->address)); diff --git a/src/core/ddsi/src/ddsi_mcgroup.c b/src/core/ddsi/src/ddsi_mcgroup.c index a956ce1..96b204e 100644 --- a/src/core/ddsi/src/ddsi_mcgroup.c +++ b/src/core/ddsi/src/ddsi_mcgroup.c @@ -136,14 +136,14 @@ static char *make_joinleave_msg (char *buf, size_t bufsz, ddsi_tran_conn_t conn, int n; #ifdef DDSI_INCLUDE_SSM if (srcloc) { - ddsi_locator_to_string_no_port(conn->m_base.gv, srcstr, sizeof(srcstr), srcloc); + ddsi_locator_to_string_no_port(srcstr, sizeof(srcstr), srcloc); } #else DDSRT_UNUSED_ARG (srcloc); #endif - ddsi_locator_to_string_no_port (conn->m_base.gv, mcstr, sizeof(mcstr), mcloc); + ddsi_locator_to_string_no_port (mcstr, sizeof(mcstr), mcloc); if (interf) - ddsi_locator_to_string_no_port(conn->m_base.gv, interfstr, sizeof(interfstr), &interf->loc); + ddsi_locator_to_string_no_port(interfstr, sizeof(interfstr), &interf->loc); else (void) snprintf (interfstr, sizeof (interfstr), "(default)"); n = err ? snprintf (buf, bufsz, "error %d in ", err) : 0; diff --git a/src/core/ddsi/src/ddsi_raweth.c b/src/core/ddsi/src/ddsi_raweth.c index e3454f9..b5a0d07 100644 --- a/src/core/ddsi/src/ddsi_raweth.c +++ b/src/core/ddsi/src/ddsi_raweth.c @@ -38,9 +38,8 @@ typedef struct ddsi_raweth_conn { int m_ifindex; } *ddsi_raweth_conn_t; -static char *ddsi_raweth_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port) +static char *ddsi_raweth_to_string (char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port) { - (void)tran; if (with_port) (void) snprintf(dst, sizeof_dst, "[%02x:%02x:%02x:%02x:%02x:%02x]:%u", loc->address[10], loc->address[11], loc->address[12], @@ -80,6 +79,7 @@ static ssize_t ddsi_raweth_conn_read (ddsi_tran_conn_t conn, unsigned char * buf { if (srcloc) { + srcloc->tran = conn->m_factory; srcloc->kind = NN_LOCATOR_KIND_RAWETH; srcloc->port = ntohs (src.sll_protocol); memset(srcloc->address, 0, 10); @@ -305,9 +305,8 @@ static int ddsi_raweth_is_ssm_mcaddr (const ddsi_tran_factory_t tran, const nn_l return 0; } -static enum ddsi_nearby_address_result ddsi_raweth_is_nearby_address (ddsi_tran_factory_t tran, const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface interf[]) +static enum ddsi_nearby_address_result ddsi_raweth_is_nearby_address (const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface interf[]) { - (void) tran; (void) loc; (void) ownloc; (void) ninterf; @@ -319,6 +318,7 @@ static enum ddsi_locator_from_string_result ddsi_raweth_address_from_string (dds { int i = 0; (void)tran; + loc->tran = tran; loc->kind = NN_LOCATOR_KIND_RAWETH; loc->port = NN_LOCATOR_PORT_INVALID; memset (loc->address, 0, sizeof (loc->address)); diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 666e0d3..a2f842e 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -644,10 +644,27 @@ static size_t serdata_default_print_cdr (const struct ddsi_sertopic *sertopic_co static size_t serdata_default_print_plist (const struct ddsi_sertopic *sertopic_common, const struct ddsi_serdata *serdata_common, char *buf, size_t size) { - /* FIXME: should change q_plist.c to print to a string instead of a log, and then drop the - logging of QoS in the rest of code, instead relying on this */ - (void)sertopic_common; (void)serdata_common; - return (size_t) snprintf (buf, size, "(plist)"); + const struct ddsi_serdata_default *d = (const struct ddsi_serdata_default *)serdata_common; + const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)sertopic_common; + nn_plist_src_t src; + nn_plist_t tmp; + src.buf = (const unsigned char *) d->data; + src.bufsz = d->pos; + src.encoding = d->hdr.identifier; + src.factory = tp->gv->m_factory; + src.logconfig = &tp->gv->logconfig; + src.protocol_version.major = RTPS_MAJOR; + src.protocol_version.minor = RTPS_MINOR; + src.strict = false; + src.vendorid = NN_VENDORID_ECLIPSE; + if (nn_plist_init_frommsg (&tmp, NULL, ~(uint64_t)0, ~(uint64_t)0, &src) < 0) + return (size_t) snprintf (buf, size, "(unparseable-plist)"); + else + { + size_t ret = nn_plist_print (buf, size, &tmp); + nn_plist_fini (&tmp); + return ret; + } } static size_t serdata_default_print_raw (const struct ddsi_sertopic *sertopic_common, const struct ddsi_serdata *serdata_common, char *buf, size_t size) diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 47ff028..70f6ccb 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -100,11 +100,11 @@ static const ddsrt_avl_treedef_t ddsi_tcp_treedef = DDSRT_AVL_TREEDEF_INITIALIZE static ddsi_tcp_conn_t ddsi_tcp_new_conn (struct ddsi_tran_factory_tcp *fact, ddsrt_socket_t, bool, struct sockaddr *); -static char *sockaddr_to_string_with_port (const struct q_globals *gv, char *dst, size_t sizeof_dst, const struct sockaddr *src) +static char *sockaddr_to_string_with_port (struct ddsi_tran_factory_tcp *fact, char *dst, size_t sizeof_dst, const struct sockaddr *src) { nn_locator_t loc; - ddsi_ipaddr_to_loc(&loc, src, src->sa_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); - ddsi_locator_to_string(gv, dst, sizeof_dst, &loc); + ddsi_ipaddr_to_loc(&fact->fact, &loc, src, src->sa_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); + ddsi_locator_to_string(dst, sizeof_dst, &loc); return dst; } @@ -182,9 +182,7 @@ static void ddsi_tcp_node_free (void * ptr) static void ddsi_tcp_conn_connect (ddsi_tcp_conn_t conn, const ddsrt_msghdr_t * msg) { -#ifdef DDSI_INCLUDE_SSL struct ddsi_tran_factory_tcp * const fact = (struct ddsi_tran_factory_tcp *) conn->m_base.m_factory; -#endif char buff[DDSI_LOCSTRLEN]; ddsrt_socket_t sock; dds_return_t ret; @@ -219,7 +217,7 @@ static void ddsi_tcp_conn_connect (ddsi_tcp_conn_t conn, const ddsrt_msghdr_t * } #endif - sockaddr_to_string_with_port(conn->m_base.m_base.gv, buff, sizeof(buff), (struct sockaddr *) msg->msg_name); + sockaddr_to_string_with_port(fact, buff, sizeof(buff), (struct sockaddr *) msg->msg_name); DDS_CLOG (DDS_LC_TCP, &conn->m_base.m_base.gv->logconfig, "tcp connect socket %"PRIdSOCK" port %u to %s\n", sock, get_socket_port (&conn->m_base.m_base.gv->logconfig, sock), buff); /* Also may need to receive on connection so add to waitset */ @@ -267,7 +265,7 @@ static void ddsi_tcp_cache_add (struct ddsi_tran_factory_tcp *fact, ddsi_tcp_con } } - sockaddr_to_string_with_port(fact->fact.gv, buff, sizeof(buff), (struct sockaddr *)&conn->m_peer_addr); + sockaddr_to_string_with_port(fact, buff, sizeof(buff), (struct sockaddr *)&conn->m_peer_addr); DDS_CLOG (DDS_LC_TCP, &fact->fact.gv->logconfig, "tcp cache %s %s socket %"PRIdSOCK" to %s\n", action, conn->m_base.m_server ? "server" : "client", conn->m_sock, buff); } @@ -282,7 +280,7 @@ static void ddsi_tcp_cache_remove (ddsi_tcp_conn_t conn) node = ddsrt_avl_lookup_dpath (&ddsi_tcp_treedef, &fact->ddsi_tcp_cache_g, conn, &path); if (node) { - sockaddr_to_string_with_port(fact->fact.gv, buff, sizeof(buff), (struct sockaddr *)&conn->m_peer_addr); + sockaddr_to_string_with_port(fact, buff, sizeof(buff), (struct sockaddr *)&conn->m_peer_addr); DDS_CLOG (DDS_LC_TCP, &conn->m_base.m_base.gv->logconfig, "tcp cache removed socket %"PRIdSOCK" to %s\n", conn->m_sock, buff); ddsrt_avl_delete_dpath (&ddsi_tcp_treedef, &fact->ddsi_tcp_cache_g, node, &path); ddsi_tcp_node_free (node); @@ -383,9 +381,7 @@ static bool ddsi_tcp_select (const struct ddsrt_log_cfg *logcfg, ddsrt_socket_t static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char *buf, size_t len, bool allow_spurious, nn_locator_t *srcloc) { -#ifdef DDSI_INCLUDE_SSL struct ddsi_tran_factory_tcp * const fact = (struct ddsi_tran_factory_tcp *) conn->m_factory; -#endif dds_return_t rc; ddsi_tcp_conn_t tcp = (ddsi_tcp_conn_t) conn; ssize_t (*rd) (ddsi_tcp_conn_t, void *, size_t, dds_return_t * err) = ddsi_tcp_conn_read_plain; @@ -409,7 +405,7 @@ static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char *buf, si { if (srcloc) { - ddsi_ipaddr_to_loc(srcloc, (struct sockaddr *)&tcp->m_peer_addr, tcp->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); + ddsi_ipaddr_to_loc(&fact->fact, srcloc, (struct sockaddr *)&tcp->m_peer_addr, tcp->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); } return (ssize_t) pos; } @@ -775,7 +771,7 @@ static ddsi_tran_conn_t ddsi_tcp_accept (ddsi_tran_listener_t listener) if (sock == DDSRT_INVALID_SOCKET) { (void)ddsrt_getsockname (tl->m_sock, (struct sockaddr *) &addr, &addrlen); - sockaddr_to_string_with_port(fact->fact.gv, buff, sizeof(buff), (struct sockaddr *)&addr); + sockaddr_to_string_with_port(fact, buff, sizeof(buff), (struct sockaddr *)&addr); DDS_CLOG ((rc == DDS_RETCODE_OK) ? DDS_LC_ERROR : DDS_LC_FATAL, &listener->m_base.gv->logconfig, "tcp accept failed on socket %"PRIdSOCK" at %s retcode %"PRId32"\n", tl->m_sock, buff, rc); } else if (getpeername (sock, (struct sockaddr *) &addr, &addrlen) == -1) @@ -785,7 +781,7 @@ static ddsi_tran_conn_t ddsi_tcp_accept (ddsi_tran_listener_t listener) } else { - sockaddr_to_string_with_port(fact->fact.gv, buff, sizeof(buff), (struct sockaddr *)&addr); + sockaddr_to_string_with_port(fact, buff, sizeof(buff), (struct sockaddr *)&addr); DDS_CLOG (DDS_LC_TCP, &listener->m_base.gv->logconfig, "tcp accept new socket %"PRIdSOCK" on socket %"PRIdSOCK" from %s\n", sock, tl->m_sock, buff); (void)ddsrt_setsocknonblocking (sock, true); @@ -822,8 +818,8 @@ static void ddsi_tcp_conn_peer_locator (ddsi_tran_conn_t conn, nn_locator_t * lo char buff[DDSI_LOCSTRLEN]; ddsi_tcp_conn_t tc = (ddsi_tcp_conn_t) conn; assert (tc->m_sock != DDSRT_INVALID_SOCKET); - ddsi_ipaddr_to_loc (loc, (struct sockaddr *)&tc->m_peer_addr, tc->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); - ddsi_locator_to_string(conn->m_base.gv, buff, sizeof(buff), loc); + ddsi_ipaddr_to_loc (conn->m_factory, loc, (struct sockaddr *)&tc->m_peer_addr, tc->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); + ddsi_locator_to_string(buff, sizeof(buff), loc); DDS_CLOG (DDS_LC_TCP, &conn->m_base.gv->logconfig, "(tcp EP:%s)", buff); } @@ -863,6 +859,7 @@ static ddsi_tran_listener_t ddsi_tcp_create_listener (ddsi_tran_factory_t fact, struct sockaddr_storage addr; socklen_t addrlen = sizeof (addr); ddsi_tcp_listener_t tl = NULL; + struct ddsi_tran_factory_tcp * const fact_tcp = (struct ddsi_tran_factory_tcp *) fact; (void) qos; @@ -894,7 +891,7 @@ static ddsi_tran_listener_t ddsi_tcp_create_listener (ddsi_tran_factory_t fact, return NULL; } - sockaddr_to_string_with_port(fact->gv, buff, sizeof(buff), (struct sockaddr *)&addr); + sockaddr_to_string_with_port(fact_tcp, buff, sizeof(buff), (struct sockaddr *)&addr); DDS_CLOG (DDS_LC_TCP, &fact->gv->logconfig, "tcp create listener socket %"PRIdSOCK" on %s\n", sock, buff); } @@ -903,11 +900,9 @@ static ddsi_tran_listener_t ddsi_tcp_create_listener (ddsi_tran_factory_t fact, static void ddsi_tcp_conn_delete (ddsi_tcp_conn_t conn) { -#ifdef DDSI_INCLUDE_SSL struct ddsi_tran_factory_tcp * const fact = (struct ddsi_tran_factory_tcp *) conn->m_base.m_factory; -#endif char buff[DDSI_LOCSTRLEN]; - sockaddr_to_string_with_port(conn->m_base.m_base.gv, buff, sizeof(buff), (struct sockaddr *)&conn->m_peer_addr); + sockaddr_to_string_with_port(fact, buff, sizeof(buff), (struct sockaddr *)&conn->m_peer_addr); DDS_CLOG (DDS_LC_TCP, &conn->m_base.m_base.gv->logconfig, "tcp free %s connnection on socket %"PRIdSOCK" to %s\n", conn->m_base.m_server ? "server" : "client", conn->m_sock, buff); #ifdef DDSI_INCLUDE_SSL @@ -932,10 +927,10 @@ static void ddsi_tcp_close_conn (ddsi_tran_conn_t tc) char buff[DDSI_LOCSTRLEN]; nn_locator_t loc; ddsi_tcp_conn_t conn = (ddsi_tcp_conn_t) tc; - sockaddr_to_string_with_port(tc->m_base.gv, buff, sizeof(buff), (struct sockaddr *)&conn->m_peer_addr); + sockaddr_to_string_with_port(fact_tcp, buff, sizeof(buff), (struct sockaddr *)&conn->m_peer_addr); DDS_CLOG (DDS_LC_TCP, &tc->m_base.gv->logconfig, "tcp close %s connnection on socket %"PRIdSOCK" to %s\n", conn->m_base.m_server ? "server" : "client", conn->m_sock, buff); (void) shutdown (conn->m_sock, 2); - ddsi_ipaddr_to_loc(&loc, (struct sockaddr *)&conn->m_peer_addr, conn->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); + ddsi_ipaddr_to_loc(&fact_tcp->fact, &loc, (struct sockaddr *)&conn->m_peer_addr, conn->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); loc.port = conn->m_peer_port; purge_proxy_participants (conn->m_base.m_base.gv, &loc, conn->m_base.m_server); } @@ -993,8 +988,9 @@ static void ddsi_tcp_unblock_listener (ddsi_tran_listener_t listener) } while (ret == DDS_RETCODE_INTERRUPTED); if (ret != DDS_RETCODE_OK) { + struct ddsi_tran_factory_tcp * const fact = (struct ddsi_tran_factory_tcp *) listener->m_factory; char buff[DDSI_LOCSTRLEN]; - sockaddr_to_string_with_port(listener->m_base.gv, buff, sizeof(buff), (struct sockaddr *)&addr); + sockaddr_to_string_with_port(fact, buff, sizeof(buff), (struct sockaddr *)&addr); DDS_CWARNING (&listener->m_base.gv->logconfig, "tcp failed to connect to own listener (%s) error %"PRId32"\n", buff, ret); } } @@ -1050,9 +1046,9 @@ static int ddsi_tcp_is_ssm_mcaddr (const ddsi_tran_factory_t tran, const nn_loca return 0; } -static enum ddsi_nearby_address_result ddsi_tcp_is_nearby_address (ddsi_tran_factory_t tran, const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface interf[]) +static enum ddsi_nearby_address_result ddsi_tcp_is_nearby_address (const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface interf[]) { - return ddsi_ipaddr_is_nearby_address(tran, loc, ownloc, ninterf, interf); + return ddsi_ipaddr_is_nearby_address(loc, ownloc, ninterf, interf); } static int ddsi_tcp_is_valid_port (ddsi_tran_factory_t fact, uint32_t port) diff --git a/src/core/ddsi/src/ddsi_tran.c b/src/core/ddsi/src/ddsi_tran.c index 5350d58..94ffc89 100644 --- a/src/core/ddsi/src/ddsi_tran.c +++ b/src/core/ddsi/src/ddsi_tran.c @@ -17,6 +17,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/ifaddrs.h" #include "dds/ddsi/ddsi_tran.h" +#include "dds/ddsi/ddsi_ipaddr.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_globals.h" @@ -250,10 +251,12 @@ int ddsi_is_ssm_mcaddr (const struct q_globals *gv, const nn_locator_t *loc) return 0; } -enum ddsi_nearby_address_result ddsi_is_nearby_address (const struct q_globals *gv, const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface interf[]) +enum ddsi_nearby_address_result ddsi_is_nearby_address (const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface interf[]) { - ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind(gv, loc->kind); - return tran ? tran->m_is_nearby_address_fn (tran, loc, ownloc, ninterf, interf) : DNAR_DISTANT; + if (loc->tran != ownloc->tran || loc->kind != ownloc->kind) + return DNAR_DISTANT; + else + return ownloc->tran->m_is_nearby_address_fn (loc, ownloc, ninterf, interf); } enum ddsi_locator_from_string_result ddsi_locator_from_string (const struct q_globals *gv, nn_locator_t *loc, const char *str, ddsi_tran_factory_t default_factory) @@ -277,29 +280,67 @@ enum ddsi_locator_from_string_result ddsi_locator_from_string (const struct q_gl return tran->m_locator_from_string_fn (tran, loc, sep ? sep + 1 : str); } -char *ddsi_locator_to_string (const struct q_globals *gv, char *dst, size_t sizeof_dst, const nn_locator_t *loc) +char *ddsi_locator_to_string (char *dst, size_t sizeof_dst, const nn_locator_t *loc) { /* FIXME: should add a "factory" for INVALID locators */ - if (loc->kind != NN_LOCATOR_KIND_INVALID) { - ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind(gv, loc->kind); - int pos = snprintf (dst, sizeof_dst, "%s/", tran->m_typename); - 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 { + if (loc->kind == NN_LOCATOR_KIND_INVALID) { (void) snprintf (dst, sizeof_dst, "invalid/0:0"); + } else if (loc->tran != NULL) { + int pos = snprintf (dst, sizeof_dst, "%s/", loc->tran->m_typename); + if (0 < pos && (size_t)pos < sizeof_dst) + (void) loc->tran->m_locator_to_string_fn (dst + (size_t)pos, sizeof_dst - (size_t)pos, loc, 1); + } else { + /* Because IPv4 and IPv6 addresses are so common we special-case and print them in the usual form + even if they didn't get mapped to a transport. To indicate that this mapping never took place + the kind is still printed as a number, not as (udp|tcp)6? */ + switch (loc->kind) + { + case NN_LOCATOR_KIND_TCPv4: + case NN_LOCATOR_KIND_TCPv6: + case NN_LOCATOR_KIND_UDPv4: + case NN_LOCATOR_KIND_UDPv6: { + int pos = snprintf (dst, sizeof_dst, "%"PRId32"/", loc->kind); + if (0 < pos && (size_t)pos < sizeof_dst) + (void) ddsi_ipaddr_to_string (dst + (size_t)pos, sizeof_dst - (size_t)pos, loc, 1); + break; + } + default: { + const unsigned char * const x = loc->address; + (void) snprintf (dst, sizeof_dst, "%"PRId32"/[%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]:%"PRIu32, + loc->kind, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15], loc->port); + break; + } + } } return dst; } -char *ddsi_locator_to_string_no_port (const struct q_globals *gv, char *dst, size_t sizeof_dst, const nn_locator_t *loc) +char *ddsi_locator_to_string_no_port (char *dst, size_t sizeof_dst, const nn_locator_t *loc) { - if (loc->kind != NN_LOCATOR_KIND_INVALID) { - ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind(gv, loc->kind); - int pos = snprintf (dst, sizeof_dst, "%s/", tran->m_typename); - 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 { + if (loc->kind == NN_LOCATOR_KIND_INVALID) { (void) snprintf (dst, sizeof_dst, "invalid/0"); + } else if (loc->tran != NULL) { + int pos = snprintf (dst, sizeof_dst, "%s/", loc->tran->m_typename); + if (0 < pos && (size_t)pos < sizeof_dst) + (void) loc->tran->m_locator_to_string_fn (dst + (size_t)pos, sizeof_dst - (size_t)pos, loc, 0); + } else { + switch (loc->kind) + { + case NN_LOCATOR_KIND_TCPv4: + case NN_LOCATOR_KIND_TCPv6: + case NN_LOCATOR_KIND_UDPv4: + case NN_LOCATOR_KIND_UDPv6: { + int pos = snprintf (dst, sizeof_dst, "%"PRId32"/", loc->kind); + if (0 < pos && (size_t)pos < sizeof_dst) + (void) ddsi_ipaddr_to_string (dst + (size_t)pos, sizeof_dst - (size_t)pos, loc, 0); + break; + } + default: { + const unsigned char * const x = loc->address; + (void) snprintf (dst, sizeof_dst, "%"PRId32"/[%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]", + loc->kind, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15]); + } + } } return dst; } diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 5addd41..8ebfcf1 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -68,7 +68,7 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s if (ret > 0) { if (srcloc) - ddsi_ipaddr_to_loc(srcloc, (struct sockaddr *)&src, src.ss_family == AF_INET ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_UDPv6); + ddsi_ipaddr_to_loc(conn->m_factory, srcloc, (struct sockaddr *)&src, src.ss_family == AF_INET ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_UDPv6); if(conn->m_base.gv->pcap_fp) { @@ -88,8 +88,8 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s { char addrbuf[DDSI_LOCSTRLEN]; nn_locator_t tmp; - ddsi_ipaddr_to_loc(&tmp, (struct sockaddr *)&src, src.ss_family == AF_INET ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_UDPv6); - ddsi_locator_to_string(conn->m_base.gv, addrbuf, sizeof(addrbuf), &tmp); + ddsi_ipaddr_to_loc(conn->m_factory, &tmp, (struct sockaddr *)&src, src.ss_family == AF_INET ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_UDPv6); + ddsi_locator_to_string(addrbuf, sizeof(addrbuf), &tmp); DDS_CWARNING(&conn->m_base.gv->logconfig, "%s => %d truncated to %d\n", addrbuf, (int)ret, (int)len); } } @@ -432,10 +432,10 @@ static enum ddsi_locator_from_string_result ddsi_udp_address_from_string (ddsi_t return ddsi_ipaddr_from_string (tran, loc, str, tran->m_kind); } -static char *ddsi_udp_locator_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port) +static char *ddsi_udp_locator_to_string (char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port) { if (loc->kind != NN_LOCATOR_KIND_UDPv4MCGEN) { - return ddsi_ipaddr_to_string(tran, dst, sizeof_dst, loc, with_port); + return ddsi_ipaddr_to_string(dst, sizeof_dst, loc, with_port); } else { struct sockaddr_in src; nn_udpv4mcgen_address_t mcgen; diff --git a/src/core/ddsi/src/q_addrset.c b/src/core/ddsi/src/q_addrset.c index 0d557e7..0c6d69d 100644 --- a/src/core/ddsi/src/q_addrset.c +++ b/src/core/ddsi/src/q_addrset.c @@ -94,7 +94,7 @@ static int add_addresses_to_addrset_1 (const struct q_globals *gv, struct addrse if (port_mode >= 0) { loc.port = (unsigned) port_mode; - GVLOG (DDS_LC_CONFIG, "%s: add %s", msgtag, ddsi_locator_to_string(gv, buf, sizeof(buf), &loc)); + GVLOG (DDS_LC_CONFIG, "%s: add %s", msgtag, ddsi_locator_to_string(buf, sizeof(buf), &loc)); add_to_addrset (gv, as, &loc); } else @@ -107,7 +107,7 @@ static int add_addresses_to_addrset_1 (const struct q_globals *gv, struct addrse { 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)); + GVLOG (DDS_LC_CONFIG, "%s", ddsi_locator_to_string(buf, sizeof(buf), &loc)); else GVLOG (DDS_LC_CONFIG, ", :%"PRIu32, loc.port); add_to_addrset (gv, as, &loc); @@ -119,7 +119,7 @@ static int add_addresses_to_addrset_1 (const struct q_globals *gv, struct addrse loc.port = ddsi_get_port (&gv->config, DDSI_PORT_MULTI_DISC, 0); else loc.port = (uint32_t) port_mode; - GVLOG (DDS_LC_CONFIG, "%s", ddsi_locator_to_string(gv, buf, sizeof(buf), &loc)); + GVLOG (DDS_LC_CONFIG, "%s", ddsi_locator_to_string(buf, sizeof(buf), &loc)); add_to_addrset (gv, as, &loc); } } @@ -231,6 +231,7 @@ void unref_addrset (struct addrset *as) void set_unspec_locator (nn_locator_t *loc) { + loc->tran = NULL; loc->kind = NN_LOCATOR_KIND_INVALID; loc->port = NN_LOCATOR_PORT_INVALID; memset (loc->address, 0, sizeof (loc->address)); @@ -557,7 +558,7 @@ static void log_addrset_helper (const nn_locator_t *n, void *varg) const struct q_globals *gv = arg->gv; char buf[DDSI_LOCSTRLEN]; if (gv->logconfig.c.mask & arg->tf) - GVLOG (arg->tf, " %s", ddsi_locator_to_string (gv, buf, sizeof(buf), n)); + GVLOG (arg->tf, " %s", ddsi_locator_to_string (buf, sizeof(buf), n)); } void nn_log_addrset (struct q_globals *gv, uint32_t tf, const char *prefix, const struct addrset *as) diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 33699d6..5a9b1ec 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -117,7 +117,7 @@ static int get_locator (const struct q_globals *gv, nn_locator_t *loc, const nn_ first_set = 1; } - switch (ddsi_is_nearby_address(gv, &l->loc, &gv->ownloc, (size_t) gv->n_interfaces, gv->interfaces)) + switch (ddsi_is_nearby_address(&l->loc, &gv->ownloc, (size_t) gv->n_interfaces, gv->interfaces)) { case DNAR_DISTANT: break; @@ -738,7 +738,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_ } GVLOGDISC (" QOS={"); - nn_log_xqos (DDS_LC_DISCOVERY, &gv->logconfig, &datap->qos); + nn_xqos_log (DDS_LC_DISCOVERY, &gv->logconfig, &datap->qos); GVLOGDISC ("}\n"); maybe_add_pp_as_meta_to_as_disc (gv, as_meta); @@ -1270,7 +1270,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, seqno_t seq, nn GVLOGDISC (" ssm=%u", ssm); #endif GVLOGDISC (") QOS={"); - nn_log_xqos (DDS_LC_DISCOVERY, &gv->logconfig, xqos); + nn_xqos_log (DDS_LC_DISCOVERY, &gv->logconfig, xqos); GVLOGDISC ("}\n"); if ((datap->endpoint_guid.entityid.u & NN_ENTITYID_SOURCE_MASK) == NN_ENTITYID_SOURCE_VENDOR && !vendor_is_eclipse_or_prismtech (vendorid)) diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index 6f6bf69..7586ea0 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -88,7 +88,7 @@ static void print_address (const nn_locator_t *n, void *varg) { struct print_address_arg *arg = varg; char buf[DDSI_LOCSTRLEN]; - arg->count += cpf (arg->conn, " %s", ddsi_locator_to_string (arg->conn->m_base.gv, buf, sizeof(buf), n)); + arg->count += cpf (arg->conn, " %s", ddsi_locator_to_string (buf, sizeof(buf), n)); } static int print_addrset (ddsi_tran_conn_t conn, const char *prefix, struct addrset *as, const char *suffix) @@ -381,7 +381,7 @@ struct debug_monitor *new_debug_monitor (struct q_globals *gv, int32_t port) nn_locator_t loc; char buf[DDSI_LOCSTRLEN]; (void) ddsi_listener_locator(dm->servsock, &loc); - GVLOG (DDS_LC_CONFIG, "debmon at %s\n", ddsi_locator_to_string (gv, buf, sizeof(buf), &loc)); + GVLOG (DDS_LC_CONFIG, "debmon at %s\n", ddsi_locator_to_string (buf, sizeof(buf), &loc)); } ddsrt_mutex_init (&dm->lock); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 63bbb6d..ee58f1e 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -442,7 +442,7 @@ static bool update_qos_locked (struct entity_common *e, dds_qos_t *ent_qos, cons !!(mask & QP_TOPIC_DATA)); #endif EELOGDISC (e, "update_qos_locked "PGUIDFMT" delta=%"PRIu64" QOS={", PGUID(e->guid), mask); - nn_log_xqos (DDS_LC_DISCOVERY, &e->gv->logconfig, xqos); + nn_xqos_log (DDS_LC_DISCOVERY, &e->gv->logconfig, xqos); EELOGDISC (e, "}\n"); if (mask == 0) @@ -621,7 +621,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * if (gv->logconfig.c.mask & DDS_LC_DISCOVERY) { GVLOGDISC ("PARTICIPANT "PGUIDFMT" QOS={", PGUID (pp->e.guid)); - nn_log_xqos (DDS_LC_DISCOVERY, &gv->logconfig, &pp->plist->qos); + nn_xqos_log (DDS_LC_DISCOVERY, &gv->logconfig, &pp->plist->qos); GVLOGDISC ("}\n"); } @@ -1247,7 +1247,7 @@ static void rebuild_trace_covered(const struct q_globals *gv, int nreaders, int for (i = 0; i < nlocs; i++) { char buf[DDSI_LOCATORSTRLEN]; - ddsi_locator_to_string(gv, buf, sizeof(buf), &locs[i]); + ddsi_locator_to_string(buf, sizeof(buf), &locs[i]); GVLOGDISC (" loc %2d = %-30s %2d {", i, buf, locs_nrds[i]); for (j = 0; j < nreaders; j++) if (covered[j * nlocs + i] >= 0) @@ -1286,7 +1286,7 @@ static void rebuild_add(const struct q_globals *gv, struct addrset *newas, int l char str[DDSI_LOCATORSTRLEN]; if (locs[locidx].kind != NN_LOCATOR_KIND_UDPv4MCGEN) { - ddsi_locator_to_string(gv, str, sizeof(str), &locs[locidx]); + ddsi_locator_to_string(str, sizeof(str), &locs[locidx]); GVLOGDISC (" simple %s\n", str); add_to_addrset(gv, newas, &locs[locidx]); } @@ -1305,7 +1305,7 @@ static void rebuild_add(const struct q_globals *gv, struct addrset *newas, int l iph |= 1u << covered[i * nlocs + locidx]; ipn = htonl(iph); memcpy(l.address + 12, &ipn, 4); - ddsi_locator_to_string(gv, str, sizeof(str), &l); + ddsi_locator_to_string(str, sizeof(str), &l); GVLOGDISC (" mcgen %s\n", str); add_to_addrset(gv, newas, &l); } @@ -2979,7 +2979,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se set_topic_type_name (wr->xqos, topic); ELOGDISC (wr, "WRITER "PGUIDFMT" QOS={", PGUID (wr->e.guid)); - nn_log_xqos (DDS_LC_DISCOVERY, &wr->e.gv->logconfig, wr->xqos); + nn_xqos_log (DDS_LC_DISCOVERY, &wr->e.gv->logconfig, wr->xqos); ELOGDISC (wr, "}\n"); assert (wr->xqos->present & QP_RELIABILITY); @@ -3609,7 +3609,7 @@ static dds_return_t new_reader_guid if (rd->e.gv->logconfig.c.mask & DDS_LC_DISCOVERY) { ELOGDISC (rd, "READER "PGUIDFMT" QOS={", PGUID (rd->e.guid)); - nn_log_xqos (DDS_LC_DISCOVERY, &rd->e.gv->logconfig, rd->xqos); + nn_xqos_log (DDS_LC_DISCOVERY, &rd->e.gv->logconfig, rd->xqos); ELOGDISC (rd, "}\n"); } assert (rd->xqos->present & QP_RELIABILITY); diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 4d36783..8e62b22 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -282,6 +282,7 @@ static int set_spdp_address (struct q_globals *gv) const uint32_t port = ddsi_get_port (&gv->config, DDSI_PORT_MULTI_DISC, 0); int rc = 0; /* FIXME: FIXME: FIXME: */ + gv->loc_spdp_mc.tran = NULL; gv->loc_spdp_mc.kind = NN_LOCATOR_KIND_INVALID; if (strcmp (gv->config.spdpMulticastAddressString, "239.255.0.1") != 0) { @@ -342,6 +343,7 @@ static int set_ext_address_and_mask (struct q_globals *gv) if (!gv->config.externalMaskString || strcmp (gv->config.externalMaskString, "0.0.0.0") == 0) { memset(&gv->extmask.address, 0, sizeof(gv->extmask.address)); + gv->extmask.tran = NULL; gv->extmask.kind = NN_LOCATOR_KIND_INVALID; gv->extmask.port = NN_LOCATOR_PORT_INVALID; } @@ -765,7 +767,7 @@ static void wait_for_receive_threads (struct q_globals *gv) } } -static struct ddsi_sertopic *make_special_topic (struct serdatapool *serpool, uint16_t enc_id, const struct ddsi_serdata_ops *ops) +static struct ddsi_sertopic *make_special_topic (struct q_globals *gv, struct serdatapool *serpool, uint16_t enc_id, const struct ddsi_serdata_ops *ops) { /* FIXME: two things (at least) - it claims there is a key, but the underlying type description is missing @@ -778,6 +780,7 @@ static struct ddsi_sertopic *make_special_topic (struct serdatapool *serpool, ui struct ddsi_sertopic_default *st = ddsrt_malloc (sizeof (*st)); memset (st, 0, sizeof (*st)); ddsi_sertopic_init_anon (&st->c, &ddsi_sertopic_ops_default, ops, false); + st->gv = gv; st->native_encoding_identifier = enc_id; st->serpool = serpool; st->nkeys = 1; @@ -786,8 +789,8 @@ static struct ddsi_sertopic *make_special_topic (struct serdatapool *serpool, ui static void make_special_topics (struct q_globals *gv) { - gv->plist_topic = make_special_topic (gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? PL_CDR_LE : PL_CDR_BE, &ddsi_serdata_ops_plist); - gv->rawcdr_topic = make_special_topic (gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE, &ddsi_serdata_ops_rawcdr); + gv->plist_topic = make_special_topic (gv, gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? PL_CDR_LE : PL_CDR_BE, &ddsi_serdata_ops_plist); + gv->rawcdr_topic = make_special_topic (gv, gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE, &ddsi_serdata_ops_rawcdr); } static void free_special_topics (struct q_globals *gv) @@ -1024,12 +1027,12 @@ int rtps_init (struct q_globals *gv) { char buf[DDSI_LOCSTRLEN]; /* the "ownip", "extip" labels in the trace have been there for so long, that it seems worthwhile to retain them even though they need not be IP any longer */ - GVLOG (DDS_LC_CONFIG, "ownip: %s\n", ddsi_locator_to_string_no_port (gv, buf, sizeof(buf), &gv->ownloc)); - GVLOG (DDS_LC_CONFIG, "extip: %s\n", ddsi_locator_to_string_no_port (gv, buf, sizeof(buf), &gv->extloc)); - GVLOG (DDS_LC_CONFIG, "extmask: %s%s\n", ddsi_locator_to_string_no_port (gv, buf, sizeof(buf), &gv->extmask), gv->m_factory->m_kind != NN_LOCATOR_KIND_UDPv4 ? " (not applicable)" : ""); + GVLOG (DDS_LC_CONFIG, "ownip: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv->ownloc)); + GVLOG (DDS_LC_CONFIG, "extip: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv->extloc)); + GVLOG (DDS_LC_CONFIG, "extmask: %s%s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv->extmask), gv->m_factory->m_kind != NN_LOCATOR_KIND_UDPv4 ? " (not applicable)" : ""); GVLOG (DDS_LC_CONFIG, "networkid: 0x%lx\n", (unsigned long) gv->myNetworkId); - GVLOG (DDS_LC_CONFIG, "SPDP MC: %s\n", ddsi_locator_to_string_no_port (gv, buf, sizeof(buf), &gv->loc_spdp_mc)); - GVLOG (DDS_LC_CONFIG, "default MC: %s\n", ddsi_locator_to_string_no_port (gv, buf, sizeof(buf), &gv->loc_default_mc)); + GVLOG (DDS_LC_CONFIG, "SPDP MC: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv->loc_spdp_mc)); + GVLOG (DDS_LC_CONFIG, "default MC: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv->loc_default_mc)); #ifdef DDSI_INCLUDE_SSM GVLOG (DDS_LC_CONFIG, "SSM support included\n"); #endif @@ -1342,7 +1345,7 @@ int rtps_init (struct q_globals *gv) { struct config_peer_listelem peer_local; char local_addr[DDSI_LOCSTRLEN]; - ddsi_locator_to_string_no_port (gv, local_addr, sizeof (local_addr), &gv->interfaces[gv->selected_interface].loc); + ddsi_locator_to_string_no_port (local_addr, sizeof (local_addr), &gv->interfaces[gv->selected_interface].loc); peer_local.next = NULL; peer_local.peer = local_addr; add_peer_addresses (gv, gv->as_disc, &peer_local); diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index c5c4c85..79edd74 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -504,9 +504,9 @@ int find_own_ip (struct q_globals *gv, const char *requested_address) else #endif { - ddsi_ipaddr_to_loc(&gv->interfaces[gv->n_interfaces].loc, ifa->addr, gv->m_factory->m_kind); + ddsi_ipaddr_to_loc(gv->m_factory, &gv->interfaces[gv->n_interfaces].loc, ifa->addr, gv->m_factory->m_kind); } - ddsi_locator_to_string_no_port(gv, addrbuf, sizeof(addrbuf), &gv->interfaces[gv->n_interfaces].loc); + ddsi_locator_to_string_no_port(addrbuf, sizeof(addrbuf), &gv->interfaces[gv->n_interfaces].loc); GVLOG (DDS_LC_CONFIG, " %s(", addrbuf); if (!(ifa->flags & IFF_MULTICAST) && multicast_override (if_name, &gv->config)) @@ -568,7 +568,7 @@ int find_own_ip (struct q_globals *gv, const char *requested_address) if (ifa->addr->sa_family == AF_INET && ifa->netmask) { - ddsi_ipaddr_to_loc(&gv->interfaces[gv->n_interfaces].netmask, ifa->netmask, gv->m_factory->m_kind); + ddsi_ipaddr_to_loc(gv->m_factory, &gv->interfaces[gv->n_interfaces].netmask, ifa->netmask, gv->m_factory->m_kind); } else { @@ -593,7 +593,7 @@ int find_own_ip (struct q_globals *gv, const char *requested_address) const int idx = maxq_list[0]; char *names; int p; - ddsi_locator_to_string_no_port (gv, addrbuf, sizeof(addrbuf), &gv->interfaces[idx].loc); + ddsi_locator_to_string_no_port (addrbuf, sizeof(addrbuf), &gv->interfaces[idx].loc); names = ddsrt_malloc (maxq_strlen + 1); p = 0; for (i = 0; i < maxq_count && (size_t) p < maxq_strlen; i++) diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 3ed9ff0..8cc371e 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -109,6 +109,7 @@ struct piddesc { dds_return_t (*fini) (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag); dds_return_t (*valid) (const void *src, size_t srcoff); bool (*equal) (const void *srcx, const void *srcy, size_t srcoff); + bool (*print) (char * __restrict *buf, size_t * __restrict bufsize, const void *src, size_t srcoff); } f; } op; dds_return_t (*deser_validate_xform) (void * __restrict dst, const struct dd * __restrict dd); @@ -116,7 +117,6 @@ struct piddesc { extern inline bool pserop_seralign_is_1 (enum pserop op); -static void log_octetseq (uint32_t cat, const struct ddsrt_log_cfg *logcfg, uint32_t n, const unsigned char *xs); static dds_return_t validate_history_qospolicy (const dds_history_qospolicy_t *q); static dds_return_t validate_resource_limits_qospolicy (const dds_resource_limits_qospolicy_t *q); static dds_return_t validate_history_and_resource_limits (const dds_history_qospolicy_t *qh, const dds_resource_limits_qospolicy_t *qr); @@ -124,7 +124,7 @@ static dds_return_t validate_external_duration (const ddsi_duration_t *d); static dds_return_t validate_durability_service_qospolicy_acceptzero (const dds_durability_service_qospolicy_t *q, bool acceptzero); static dds_return_t do_locator (nn_locators_t *ls, uint64_t *present, uint64_t wanted, uint64_t fl, const struct dd *dd, const struct ddsi_tran_factory *factory); static dds_return_t final_validation_qos (const dds_qos_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid, bool *dursvc_accepted_allzero, bool strict); -static int partitions_equal (const dds_partition_qospolicy_t *a, const dds_partition_qospolicy_t *b); +static int partitions_equal (const void *srca, const void *srcb, size_t off); static dds_return_t nn_xqos_valid_strictness (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos, bool strict); static size_t align4size (size_t x) @@ -169,6 +169,34 @@ static dds_return_t deser_uint32 (uint32_t *dst, const struct dd * __restrict dd return 0; } +/* Returns true if buffer not yet exhausted, false otherwise */ +static bool prtf (char * __restrict *buf, size_t * __restrict bufsize, const char *fmt, ...) +{ + va_list ap; + if (*bufsize == 0) + return false; + va_start (ap, fmt); + int n = vsnprintf (*buf, *bufsize, fmt, ap); + va_end (ap); + if (n < 0) + { + **buf = 0; + return false; + } + else if ((size_t) n <= *bufsize) + { + *buf += (size_t) n; + *bufsize -= (size_t) n; + return (*bufsize > 0); + } + else + { + *buf += *bufsize; + *bufsize = 0; + return false; + } +} + #define alignof(type_) offsetof (struct { char c; type_ d; }, d) static dds_return_t deser_reliability (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff) @@ -222,6 +250,12 @@ static bool equal_reliability (const void *srcx, const void *srcy, size_t srcoff return x->kind == y->kind && x->max_blocking_time == y->max_blocking_time; } +static bool print_reliability (char * __restrict *buf, size_t * __restrict bufsize, const void *src, size_t srcoff) +{ + dds_reliability_qospolicy_t const * const x = deser_generic_src (src, &srcoff, alignof (dds_reliability_qospolicy_t)); + return prtf (buf, bufsize, "%d:%"PRId64, (int) x->kind, x->max_blocking_time); +} + static dds_return_t deser_statusinfo (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff) { uint32_t * const x = deser_generic_dst (dst, dstoff, alignof (dds_reliability_qospolicy_t)); @@ -246,6 +280,12 @@ static dds_return_t ser_statusinfo (struct nn_xmsg *xmsg, nn_parameterid_t pid, return 0; } +static bool print_statusinfo (char * __restrict *buf, size_t * __restrict bufsize, const void *src, size_t srcoff) +{ + uint32_t const * const x = deser_generic_src (src, &srcoff, alignof (uint32_t)); + return prtf (buf, bufsize, "%"PRIx32, *x); +} + static dds_return_t deser_locator (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff) { nn_locators_t * const x = deser_generic_dst (dst, dstoff, alignof (nn_locators_t)); @@ -271,8 +311,10 @@ static dds_return_t ser_locator (struct nn_xmsg *xmsg, nn_parameterid_t pid, con nn_locators_t const * const x = deser_generic_src (src, &srcoff, alignof (nn_locators_t)); for (const struct nn_locators_one *l = x->first; l != NULL; l = l->next) { - char * const p = nn_xmsg_addpar (xmsg, pid, sizeof (nn_locator_t)); - memcpy (p, &l->loc, sizeof (nn_locator_t)); + char * const p = nn_xmsg_addpar (xmsg, pid, 24); + memcpy (p, &l->loc.kind, 4); + memcpy (p + 4, &l->loc.port, 4); + memcpy (p + 8, l->loc.address, 16); } return 0; } @@ -310,6 +352,21 @@ static dds_return_t fini_locator (void * __restrict dst, size_t * __restrict dst return 0; } +static bool print_locator (char * __restrict *buf, size_t * __restrict bufsize, const void *src, size_t srcoff) +{ + nn_locators_t const * const x = deser_generic_src (src, &srcoff, alignof (nn_locators_t)); + const char *sep = ""; + prtf (buf, bufsize, "{"); + for (const struct nn_locators_one *l = x->first; l != NULL; l = l->next) + { + char tmp[DDSI_LOCATORSTRLEN]; + ddsi_locator_to_string (tmp, sizeof (tmp), &l->loc); + prtf (buf, bufsize, "%s%s", sep, tmp); + sep = ","; + } + return prtf (buf, bufsize, "}"); +} + static size_t ser_generic_srcsize (const enum pserop * __restrict desc) { size_t srcoff = 0, srcalign = 0; @@ -1040,6 +1097,186 @@ bool plist_equal_generic (const void *srcx, const void *srcy, const enum pserop return equal_generic (srcx, srcy, 0, desc); } +static uint32_t isprint_runlen (uint32_t n, const unsigned char *xs) +{ + uint32_t m; + for (m = 0; m < n && xs[m] != '"' && isprint (xs[m]) && xs[m] < 127; m++) + ; + return m; +} + +static bool prtf_octetseq (char * __restrict *buf, size_t * __restrict bufsize, uint32_t n, const unsigned char *xs) +{ + uint32_t i = 0; + while (i < n) + { + uint32_t m = isprint_runlen (n - i, xs); + if (m >= 4 || (i == 0 && m == n)) + { + if (!prtf (buf, bufsize, "%s\"%*.*s\"", i == 0 ? "" : ",", m, m, xs)) + return false; + xs += m; + i += m; + } + else + { + if (m == 0) + m = 1; + while (m--) + { + if (!prtf (buf, bufsize, "%s%u", i == 0 ? "" : ",", *xs++)) + return false; + i++; + } + } + } + return true; +} + +static bool print_generic1 (char * __restrict *buf, size_t * __restrict bufsize, const void *src, size_t srcoff, const enum pserop * __restrict desc, const char *sep) +{ + while (true) + { + switch (*desc) + { + case XSTOP: + return true; + case XO: { /* octet sequence */ + ddsi_octetseq_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_octetseq_t)); + prtf (buf, bufsize, "%s%"PRIu32"<", sep, x->length); + (void) prtf_octetseq (buf, bufsize, x->length, x->value); + if (!prtf (buf, bufsize, ">")) + return false; + srcoff += sizeof (*x); + break; + } + case XS: { /* string */ + char const * const * const x = deser_generic_src (src, &srcoff, alignof (char *)); + if (!prtf (buf, bufsize, "%s\"%s\"", sep, *x)) + return false; + srcoff += sizeof (*x); + break; + } + case XE1: case XE2: case XE3: { /* enum */ + unsigned const * const x = deser_generic_src (src, &srcoff, alignof (unsigned)); + if (!prtf (buf, bufsize, "%s%u", sep, *x)) + return false; + srcoff += sizeof (*x); + break; + } + case Xi: case Xix2: case Xix3: case Xix4: { /* int32_t(s) */ + int32_t const * const x = deser_generic_src (src, &srcoff, alignof (int32_t)); + const uint32_t cnt = 1 + (uint32_t) (*desc - Xi); + for (uint32_t i = 0; i < cnt; i++) + { + if (!prtf (buf, bufsize, "%s%"PRId32, sep, x[i])) + return false; + sep = ":"; + } + srcoff += cnt * sizeof (*x); + break; + } + case Xu: case Xux2: case Xux3: case Xux4: case Xux5: { /* uint32_t(s) */ + uint32_t const * const x = deser_generic_src (src, &srcoff, alignof (uint32_t)); + const uint32_t cnt = 1 + (uint32_t) (*desc - Xu); + for (uint32_t i = 0; i < cnt; i++) + { + if (!prtf (buf, bufsize, "%s%"PRIu32, sep, x[i])) + return false; + sep = ":"; + } + srcoff += cnt * sizeof (*x); + break; + } + case XD: case XDx2: { /* duration(s): int64_t <=> int32_t.uint32_t (seconds.fraction) */ + dds_duration_t const * const x = deser_generic_src (src, &srcoff, alignof (dds_duration_t)); + const uint32_t cnt = 1 + (uint32_t) (*desc - XD); + for (uint32_t i = 0; i < cnt; i++) + { + if (!prtf (buf, bufsize, "%s%"PRId64, sep, x[i])) + return false; + sep = ":"; + } + srcoff += cnt * sizeof (*x); + break; + } + case Xo: case Xox2: { /* octet(s) */ + unsigned char const * const x = deser_generic_src (src, &srcoff, alignof (unsigned char)); + const uint32_t cnt = 1 + (uint32_t) (*desc - Xo); + for (uint32_t i = 0; i < cnt; i++) + { + if (!prtf (buf, bufsize, "%s%d", sep, x[i])) + return false; + sep = ":"; + } + srcoff += cnt * sizeof (*x); + break; + } + case Xb: case Xbx2: case XbCOND: { /* boolean(s) */ + unsigned char const * const x = deser_generic_src (src, &srcoff, alignof (unsigned char)); + const uint32_t cnt = (*desc == Xbx2) ? 2 : 1; /* <<<< beware! */ + for (uint32_t i = 0; i < cnt; i++) + { + if (!prtf (buf, bufsize, "%s%d", sep, x[i])) + return false; + sep = ":"; + } + srcoff += cnt * sizeof (*x); + break; + } + case XbPROP: { /* "propagate" boolean: don't serialize, skip it and everything that follows if false */ + unsigned char const * const x = deser_generic_src (src, &srcoff, alignof (unsigned char)); + if (!prtf (buf, bufsize, "%s%d", sep, *x)) + return false; + srcoff++; + break; + } + case XG: { /* GUID */ + ddsi_guid_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_guid_t)); + if (!prtf (buf, bufsize, "%s"PGUIDFMT, sep, PGUID (*x))) + return false; + srcoff += sizeof (*x); + break; + } + case XK: { /* keyhash */ + nn_keyhash_t const * const x = deser_generic_src (src, &srcoff, alignof (nn_keyhash_t)); + if (!prtf (buf, bufsize, "%s{%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x}", sep, + x->value[0], x->value[1], x->value[2], x->value[3], x->value[4], x->value[5], x->value[6], x->value[7], + x->value[8], x->value[9], x->value[10], x->value[11], x->value[12], x->value[13], x->value[14], x->value[15])) + return false; + srcoff += sizeof (*x); + break; + } + case XQ: { + ddsi_octetseq_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_octetseq_t)); + if (!prtf (buf, bufsize, "%s{", sep)) + return false; + if (x->length > 0) + { + const size_t elem_size = ser_generic_srcsize (desc + 1); + for (uint32_t i = 0; i < x->length; i++) + if (!print_generic1 (buf, bufsize, x->value, i * elem_size, desc + 1, (i == 0) ? "" : ",")) + return false; + } + if (!prtf (buf, bufsize, "}")) + return false; + srcoff += sizeof (*x); + while (*++desc != XSTOP) { } + break; + } + case Xopt: + break; + } + sep = ":"; + desc++; + } +} + +static bool print_generic (char * __restrict *buf, size_t * __restrict bufsize, const void *src, size_t srcoff, const enum pserop * __restrict desc) +{ + return print_generic1 (buf, bufsize, src, srcoff, desc, ""); +} + #define membersize(type, member) sizeof (((type *) 0)->member) #define ENTRY(PFX_, NAME_, member_, flag_, validate_, ...) \ { PID_##NAME_, flag_, PFX_##_##NAME_, #NAME_, offsetof (struct nn_plist, member_), \ @@ -1124,7 +1361,6 @@ static dds_return_t dvx_reader_favours_ssm (void * __restrict dst, const struct } #endif - /* Standardized parameters -- QoS _MUST_ come first (nn_plist_init_tables verifies this) because it allows early-out when processing a dds_qos_t instead of an nn_plist_t */ static const struct piddesc piddesc_omg[] = { @@ -1146,7 +1382,7 @@ static const struct piddesc piddesc_omg[] = { /* Reliability encoding does not follow the rules (best-effort/reliable map to 1/2 instead of 0/1 */ { PID_RELIABILITY, PDF_QOS | PDF_FUNCTION, QP_RELIABILITY, "RELIABILITY", offsetof (struct nn_plist, qos.reliability), membersize (struct nn_plist, qos.reliability), - { .f = { .deser = deser_reliability, .ser = ser_reliability, .valid = valid_reliability, .equal = equal_reliability } }, 0 }, + { .f = { .deser = deser_reliability, .ser = ser_reliability, .valid = valid_reliability, .equal = equal_reliability, .print = print_reliability } }, 0 }, QP (LIFESPAN, lifespan, XD), QP (DESTINATION_ORDER, destination_order, XE1), /* History depth is ignored when kind = KEEP_ALL, and must be >= 1 when KEEP_LAST, so can't use "l" */ @@ -1177,34 +1413,34 @@ static const struct piddesc piddesc_omg[] = { 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 }, + { .f = { .deser = deser_statusinfo, .ser = ser_statusinfo, .print = print_statusinfo } }, 0 }, /* Locators are difficult to deal with because they can occur multi times to represent a set; that is manageable for deser, unalias and fini, but it breaks ser because that one only generates a single parameter header */ { PID_UNICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI, PP_UNICAST_LOCATOR, "UNICAST_LOCATOR", offsetof (struct nn_plist, unicast_locators), membersize (struct nn_plist, unicast_locators), - { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator } }, 0 }, + { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator, .print = print_locator } }, 0 }, { PID_MULTICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI, PP_MULTICAST_LOCATOR, "MULTICAST_LOCATOR", offsetof (struct nn_plist, multicast_locators), membersize (struct nn_plist, multicast_locators), - { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator } }, 0 }, + { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator, .print = print_locator } }, 0 }, { PID_DEFAULT_UNICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI, PP_DEFAULT_UNICAST_LOCATOR, "DEFAULT_UNICAST_LOCATOR", offsetof (struct nn_plist, default_unicast_locators), membersize (struct nn_plist, default_unicast_locators), - { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator } }, 0 }, + { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator, .print = print_locator } }, 0 }, { PID_DEFAULT_MULTICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI, PP_DEFAULT_MULTICAST_LOCATOR, "DEFAULT_MULTICAST_LOCATOR", offsetof (struct nn_plist, default_multicast_locators), membersize (struct nn_plist, default_multicast_locators), - { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator } }, 0 }, + { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator, .print = print_locator } }, 0 }, { PID_METATRAFFIC_UNICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI, PP_METATRAFFIC_UNICAST_LOCATOR, "METATRAFFIC_UNICAST_LOCATOR", offsetof (struct nn_plist, metatraffic_unicast_locators), membersize (struct nn_plist, metatraffic_unicast_locators), - { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator } }, 0 }, + { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator, .print = print_locator } }, 0 }, { PID_METATRAFFIC_MULTICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI, PP_METATRAFFIC_MULTICAST_LOCATOR, "METATRAFFIC_MULTICAST_LOCATOR", offsetof (struct nn_plist, metatraffic_multicast_locators), membersize (struct nn_plist, metatraffic_multicast_locators), - { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator } }, 0 }, + { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator, .print = print_locator } }, 0 }, /* PID_..._{IPADDRESS,PORT} is impossible to deal with and are never generated, only accepted. The problem is that there one needs additional state (and even then there is no clear interpretation) ... So they'll have to be special-cased */ @@ -1675,76 +1911,55 @@ dds_return_t nn_xqos_valid (const struct ddsrt_log_cfg *logcfg, const dds_qos_t return nn_xqos_valid_strictness (logcfg, xqos, true); } -uint64_t nn_xqos_delta (const dds_qos_t *x, const dds_qos_t *y, uint64_t mask) +static void plist_or_xqos_delta (uint64_t *pdelta, uint64_t *qdelta, const void *srcx, const void *srcy, size_t shift, uint64_t pmask, uint64_t qmask) { - if (piddesc_unalias[0] == NULL) - nn_plist_init_tables (); - /* Returns QP_... set for settings where x differs from y; if - present in x but not in y (or in y but not in x) it counts as a - difference. */ - uint64_t delta = (x->present ^ y->present) & mask; - const uint64_t check = (x->present & y->present) & mask; - for (size_t k = 0; k < sizeof (piddesc_tables_all) / sizeof (piddesc_tables_all[0]); k++) - { - struct piddesc const * const table = piddesc_tables_all[k]; - for (uint32_t i = 0; table[i].pid != PID_SENTINEL; i++) - { - struct piddesc const * const entry = &table[i]; - if (!(entry->flags & PDF_QOS)) - break; - if (check & entry->present_flag) - { - const size_t srcoff = entry->plist_offset - offsetof (nn_plist_t, qos); - bool equal; - /* Partition is special-cased because it is a set (with a special rules - for empty sets and empty strings to boot), and normal string sequence - comparison requires the ordering to be the same */ - if (entry->pid == PID_PARTITION) - equal = partitions_equal (&x->partition, &y->partition); - else if (!(entry->flags & PDF_FUNCTION)) - equal = equal_generic (x, y, srcoff, entry->op.desc); - else - equal = entry->op.f.equal (x, y, srcoff); - if (!equal) - delta |= entry->present_flag; - } - } - } - return delta; -} + uint64_t pcheck, qcheck; -void nn_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const nn_plist_t *x, const nn_plist_t *y, uint64_t pmask, uint64_t qmask) -{ if (piddesc_unalias[0] == NULL) nn_plist_init_tables (); - *pdelta = (x->present ^ y->present) & pmask; - const uint64_t pcheck = (x->present & y->present) & pmask; - *qdelta = (x->qos.present ^ y->qos.present) & qmask; - const uint64_t qcheck = (x->qos.present & y->qos.present) & qmask; + if (shift > 0) + { + const dds_qos_t *x = srcx; + const dds_qos_t *y = srcy; + *pdelta = 0; + pcheck = 0; + *qdelta = (x->present ^ y->present) & qmask; + qcheck = (x->present & y->present) & qmask; + } + else + { + const nn_plist_t *x = srcx; + const nn_plist_t *y = srcy; + *pdelta = (x->present ^ y->present) & pmask; + pcheck = (x->present & y->present) & pmask; + *qdelta = (x->qos.present ^ y->qos.present) & qmask; + qcheck = (x->qos.present & y->qos.present) & qmask; + } for (size_t k = 0; k < sizeof (piddesc_tables_all) / sizeof (piddesc_tables_all[0]); k++) { struct piddesc const * const table = piddesc_tables_all[k]; for (uint32_t i = 0; table[i].pid != PID_SENTINEL; i++) { struct piddesc const * const entry = &table[i]; + if (shift > 0 && !(entry->flags & PDF_QOS)) + break; + assert (entry->plist_offset >= shift); + assert (shift == 0 || entry->plist_offset - shift < sizeof (dds_qos_t)); const uint64_t check = (entry->flags & PDF_QOS) ? qcheck : pcheck; uint64_t * const delta = (entry->flags & PDF_QOS) ? qdelta : pdelta; - /* QoS come first in the table, but for those we use nn_xqos_delta */ - if (entry->flags & PDF_QOS) - continue; if (check & entry->present_flag) { - const size_t srcoff = entry->plist_offset; + const size_t off = entry->plist_offset - shift; bool equal; /* Partition is special-cased because it is a set (with a special rules for empty sets and empty strings to boot), and normal string sequence comparison requires the ordering to be the same */ if (entry->pid == PID_PARTITION) - equal = partitions_equal (&x->qos.partition, &y->qos.partition); + equal = partitions_equal (srcx, srcy, off); else if (!(entry->flags & PDF_FUNCTION)) - equal = equal_generic (x, y, srcoff, entry->op.desc); + equal = equal_generic (srcx, srcy, off, entry->op.desc); else - equal = entry->op.f.equal (x, y, srcoff); + equal = entry->op.f.equal (srcx, srcy, off); if (!equal) *delta |= entry->present_flag; } @@ -1752,6 +1967,18 @@ void nn_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const nn_plist_t *x, co } } +uint64_t nn_xqos_delta (const dds_qos_t *x, const dds_qos_t *y, uint64_t mask) +{ + uint64_t pdelta, qdelta; + plist_or_xqos_delta (&pdelta, &qdelta, x, y, offsetof (nn_plist_t, qos), 0, mask); + return qdelta; +} + +void nn_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const nn_plist_t *x, const nn_plist_t *y, uint64_t pmask, uint64_t qmask) +{ + plist_or_xqos_delta (pdelta, qdelta, x, y, 0, pmask, qmask); +} + static dds_return_t validate_external_duration (const ddsi_duration_t *d) { /* Accepted are zero, positive, infinite or invalid as defined in @@ -1908,10 +2135,12 @@ static dds_return_t do_locator (nn_locators_t *ls, uint64_t *present, uint64_t w { nn_locator_t loc; - if (dd->bufsz < sizeof (loc)) + if (dd->bufsz < 24) return DDS_RETCODE_BAD_PARAMETER; - memcpy (&loc, dd->buf, sizeof (loc)); + memcpy (&loc.kind, dd->buf, 4); + memcpy (&loc.port, dd->buf + 4, 4); + memcpy (loc.address, dd->buf + 8, 16); if (dd->bswap) { loc.kind = ddsrt_bswap4 (loc.kind); @@ -1946,19 +2175,22 @@ static dds_return_t do_locator (nn_locators_t *ls, uint64_t *present, uint64_t w return DDS_RETCODE_BAD_PARAMETER; if (loc.port != 0) return DDS_RETCODE_BAD_PARAMETER; - /* silently dropped correctly formatted "invalid" locators. */ + /* silently drop correctly formatted "invalid" locators. */ return 0; case NN_LOCATOR_KIND_RESERVED: - /* silently dropped "reserved" locators. */ + /* silently drop "reserved" locators. */ return 0; default: return 0; } + + loc.tran = ddsi_factory_supports (factory, loc.kind) ? factory : NULL; return add_locator (ls, present, wanted, fl, &loc); } static void locator_from_ipv4address_port (nn_locator_t *loc, const nn_ipv4address_t *a, const nn_port_t *p, ddsi_tran_factory_t factory) { + loc->tran = factory; loc->kind = factory->m_connless ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_TCPv4; loc->port = *p; memset (loc->address, 0, 12); @@ -2186,12 +2418,13 @@ static dds_return_t init_one_parameter (nn_plist_t *plist, nn_ipaddress_params_t ret = entry->deser_validate_xform (dst, dd); if (ret < 0) { - DDS_CWARNING (logcfg, "invalid parameter list (vendor %u.%u, version %u.%u): pid %"PRIx16" (%s) invalid, input = ", + char tmp[256], *ptmp = tmp; + size_t tmpsize = sizeof (tmp); + (void) prtf_octetseq (&ptmp, &tmpsize, (uint32_t) dd->bufsz, dd->buf); + DDS_CWARNING (logcfg, "invalid parameter list (vendor %u.%u, version %u.%u): pid %"PRIx16" (%s) invalid, input = %s\n", dd->vendorid.id[0], dd->vendorid.id[1], dd->protocol_version.major, dd->protocol_version.minor, - pid, entry->name); - log_octetseq (DDS_LC_WARNING, logcfg, (uint32_t) dd->bufsz, dd->buf); - DDS_CWARNING (logcfg, "\n"); + pid, entry->name, tmp); } return ret; } @@ -2404,9 +2637,10 @@ dds_return_t nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uin if (src->logconfig->c.mask & DDS_LC_PLIST) { - DDS_CLOG (DDS_LC_PLIST, src->logconfig, "%4"PRIx32" PID %"PRIx16" len %"PRIu16" ", (uint32_t) (pl - src->buf), pid, length); - log_octetseq (DDS_LC_PLIST, src->logconfig, length, (const unsigned char *) (par + 1)); - DDS_CLOG (DDS_LC_PLIST, src->logconfig, "\n"); + char tmp[256], *ptmp = tmp; + size_t tmpsize = sizeof (tmp); + (void) prtf_octetseq (&ptmp, &tmpsize, length, (const unsigned char *) (par + 1)); + DDS_CLOG (DDS_LC_PLIST, src->logconfig, "%4"PRIx32" PID %"PRIx16" len %"PRIu16" %s\n", (uint32_t) (pl - src->buf), pid, length, tmp); } dd.buf = (const unsigned char *) (par + 1); @@ -2818,8 +3052,10 @@ static int partitions_equal_nlogn (const dds_partition_qospolicy_t *a, const dds return equal; } -static int partitions_equal (const dds_partition_qospolicy_t *a, const dds_partition_qospolicy_t *b) +static int partitions_equal (const void *srca, const void *srcb, size_t off) { + const dds_partition_qospolicy_t *a = (const dds_partition_qospolicy_t *) ((const char *) srca + off); + const dds_partition_qospolicy_t *b = (const dds_partition_qospolicy_t *) ((const char *) srcb + off); /* Return true iff (the set a->strs) equals (the set b->strs); that is, order doesn't matter. One could argue that "**" and "*" are equal, but we're not that precise here. */ @@ -2870,139 +3106,93 @@ void nn_plist_addtomsg (struct nn_xmsg *m, const nn_plist_t *ps, uint64_t pwante /*************************/ -static uint32_t isprint_runlen (uint32_t n, const unsigned char *xs) +static void plist_or_xqos_print (char * __restrict *buf, size_t * __restrict bufsize, const void * __restrict src, size_t shift, uint64_t pwanted, uint64_t qwanted) { - uint32_t m; - for (m = 0; m < n && xs[m] != '"' && isprint (xs[m]) && xs[m] < 127; m++) - ; - return m; -} - - -static void log_octetseq (uint32_t cat, const struct ddsrt_log_cfg *logcfg, uint32_t n, const unsigned char *xs) -{ - uint32_t i = 0; - while (i < n) + /* shift == 0: plist, shift > 0: just qos */ + const char *sep = ""; + uint64_t pw, qw; + if (shift > 0) { - uint32_t m = isprint_runlen (n - i, xs); - if (m >= 4 || (i == 0 && m == n)) + const dds_qos_t *qos = src; + pw = 0; + qw = qos->present & qwanted; + } + else + { + const nn_plist_t *plist = src; + pw = plist->present & pwanted; + qw = plist->qos.present & qwanted; + } + for (size_t k = 0; k < sizeof (piddesc_tables_output) / sizeof (piddesc_tables_output[0]); k++) + { + struct piddesc const * const table = piddesc_tables_output[k]; + for (uint32_t i = 0; table[i].pid != PID_SENTINEL; i++) { - DDS_CLOG (cat, logcfg, "%s\"%*.*s\"", i == 0 ? "" : ",", m, m, xs); - xs += m; - i += m; - } - else - { - if (m == 0) - m = 1; - while (m--) + struct piddesc const * const entry = &table[i]; + if (entry->pid == PID_PAD) + continue; + if (((entry->flags & PDF_QOS) ? qw : pw) & entry->present_flag) { - DDS_CLOG (cat, logcfg, "%s%u", i == 0 ? "" : ",", *xs++); - i++; + assert (entry->plist_offset >= shift); + assert (shift == 0 || entry->plist_offset - shift < sizeof (dds_qos_t)); + size_t srcoff = entry->plist_offset - shift; + /* convert name to lower case for making the trace easier on the eyes */ + char lcname[64]; + const size_t namelen = strlen (entry->name); + assert (namelen < sizeof (lcname)); + for (size_t p = 0; p < namelen; p++) + lcname[p] = (char) tolower (entry->name[p]); + lcname[namelen] = 0; + if (!prtf (buf, bufsize, "%s%s=", sep, lcname)) + return; + sep = ","; + bool cont; + if (!(entry->flags & PDF_FUNCTION)) + cont = print_generic (buf, bufsize, src, srcoff, entry->op.desc); + else + cont = entry->op.f.print (buf, bufsize, src, srcoff); + if (!cont) + return; } } } } -void nn_log_xqos (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos) +static void plist_or_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const void * __restrict src, size_t shift, uint64_t pwanted, uint64_t qwanted) { - uint64_t p = xqos->present; - const char *prefix = ""; -#define LOGB0(fmt_) DDS_CLOG (cat, logcfg, "%s" fmt_, prefix) -#define LOGB1(fmt_, ...) DDS_CLOG (cat, logcfg, "%s" fmt_, prefix, __VA_ARGS__) -#define DO(name_, body_) do { if (p & QP_##name_) { { body_ } prefix = ","; } } while (0) - -#define FMT_DUR "%"PRId64".%09"PRId32 -#define PRINTARG_DUR(d) ((int64_t) ((d) / 1000000000)), ((int32_t) ((d) % 1000000000)) - - DO (TOPIC_NAME, { LOGB1 ("topic=%s", xqos->topic_name); }); - DO (TYPE_NAME, { LOGB1 ("type=%s", xqos->type_name); }); - DO (PRESENTATION, { LOGB1 ("presentation=%d:%u:%u", xqos->presentation.access_scope, xqos->presentation.coherent_access, xqos->presentation.ordered_access); }); - DO (PARTITION, { - LOGB0 ("partition={"); - for (uint32_t i = 0; i < xqos->partition.n; i++) { - DDS_CLOG (cat, logcfg, "%s%s", (i == 0) ? "" : ",", xqos->partition.strs[i]); - } - DDS_CLOG (cat, logcfg, "}"); - }); - DO (GROUP_DATA, { - LOGB1 ("group_data=%"PRIu32"<", xqos->group_data.length); - log_octetseq (cat, logcfg, xqos->group_data.length, xqos->group_data.value); - DDS_CLOG (cat, logcfg, ">"); - }); - DO (TOPIC_DATA, { - LOGB1 ("topic_data=%"PRIu32"<", xqos->topic_data.length); - log_octetseq (cat, logcfg, xqos->topic_data.length, xqos->topic_data.value); - DDS_CLOG(cat, logcfg, ">"); - }); - DO (DURABILITY, { LOGB1 ("durability=%d", xqos->durability.kind); }); - DO (DURABILITY_SERVICE, { - LOGB0 ("durability_service="); - DDS_CLOG(cat, logcfg, FMT_DUR, PRINTARG_DUR (xqos->durability_service.service_cleanup_delay)); - DDS_CLOG(cat, logcfg, ":{%u:%"PRId32"}", xqos->durability_service.history.kind, xqos->durability_service.history.depth); - DDS_CLOG(cat, logcfg, ":{%"PRId32":%"PRId32":%"PRId32"}", xqos->durability_service.resource_limits.max_samples, xqos->durability_service.resource_limits.max_instances, xqos->durability_service.resource_limits.max_samples_per_instance); - }); - DO (DEADLINE, { LOGB1 ("deadline="FMT_DUR, PRINTARG_DUR (xqos->deadline.deadline)); }); - DO (LATENCY_BUDGET, { LOGB1 ("latency_budget="FMT_DUR, PRINTARG_DUR (xqos->latency_budget.duration)); }); - DO (LIVELINESS, { LOGB1 ("liveliness=%d:"FMT_DUR, xqos->liveliness.kind, PRINTARG_DUR (xqos->liveliness.lease_duration)); }); - DO (RELIABILITY, { LOGB1 ("reliability=%d:"FMT_DUR, xqos->reliability.kind, PRINTARG_DUR (xqos->reliability.max_blocking_time)); }); - DO (DESTINATION_ORDER, { LOGB1 ("destination_order=%d", xqos->destination_order.kind); }); - DO (HISTORY, { LOGB1 ("history=%d:%"PRId32, xqos->history.kind, xqos->history.depth); }); - DO (RESOURCE_LIMITS, { LOGB1 ("resource_limits=%"PRId32":%"PRId32":%"PRId32, xqos->resource_limits.max_samples, xqos->resource_limits.max_instances, xqos->resource_limits.max_samples_per_instance); }); - DO (TRANSPORT_PRIORITY, { LOGB1 ("transport_priority=%"PRId32, xqos->transport_priority.value); }); - DO (LIFESPAN, { LOGB1 ("lifespan="FMT_DUR, PRINTARG_DUR (xqos->lifespan.duration)); }); - DO (USER_DATA, { - LOGB1 ("user_data=%"PRIu32"<", xqos->user_data.length); - log_octetseq (cat, logcfg, xqos->user_data.length, xqos->user_data.value); - DDS_CLOG (cat, logcfg, ">"); - }); - DO (OWNERSHIP, { LOGB1 ("ownership=%d", xqos->ownership.kind); }); - DO (OWNERSHIP_STRENGTH, { LOGB1 ("ownership_strength=%"PRId32, xqos->ownership_strength.value); }); - DO (TIME_BASED_FILTER, { LOGB1 ("time_based_filter="FMT_DUR, PRINTARG_DUR (xqos->time_based_filter.minimum_separation)); }); - DO (PRISMTECH_READER_DATA_LIFECYCLE, { LOGB1 ("reader_data_lifecycle="FMT_DUR":"FMT_DUR, PRINTARG_DUR (xqos->reader_data_lifecycle.autopurge_nowriter_samples_delay), PRINTARG_DUR (xqos->reader_data_lifecycle.autopurge_disposed_samples_delay)); }); - DO (PRISMTECH_WRITER_DATA_LIFECYCLE, { - LOGB1 ("writer_data_lifecycle={%u}", xqos->writer_data_lifecycle.autodispose_unregistered_instances); }); - DO (PRISMTECH_READER_LIFESPAN, { LOGB1 ("reader_lifespan={%u,"FMT_DUR"}", xqos->reader_lifespan.use_lifespan, PRINTARG_DUR (xqos->reader_lifespan.duration)); }); - DO (PRISMTECH_SUBSCRIPTION_KEYS, { - LOGB1 ("subscription_keys={%u,{", xqos->subscription_keys.use_key_list); - for (uint32_t i = 0; i < xqos->subscription_keys.key_list.n; i++) { - DDS_CLOG (cat, logcfg, "%s%s", (i == 0) ? "" : ",", xqos->subscription_keys.key_list.strs[i]); - } - DDS_CLOG (cat, logcfg, "}}"); - }); - DO (PRISMTECH_ENTITY_FACTORY, { LOGB1 ("entity_factory=%u", xqos->entity_factory.autoenable_created_entities); }); - DO (CYCLONE_IGNORELOCAL, { LOGB1 ("ignorelocal=%u", xqos->ignorelocal.value); }); - DO (PROPERTY_LIST, { - LOGB0 ("property_list={"); - DDS_CLOG (cat, logcfg, "value={"); - for (uint32_t i = 0; i < xqos->property.value.n; i++) { - DDS_CLOG (cat, logcfg, "%s{%s,%s,%u}", - (i == 0) ? "" : ",", - xqos->property.value.props[i].name, - xqos->property.value.props[i].value, - xqos->property.value.props[i].propagate); - } - DDS_CLOG (cat, logcfg, "}"); - DDS_CLOG (cat, logcfg, "binary_value={"); - for (uint32_t i = 0; i < xqos->property.binary_value.n; i++) { - DDS_CLOG (cat, logcfg, "%s{%s,(%u,%p),%u}", - (i == 0) ? "" : ",", - xqos->property.binary_value.props[i].name, - xqos->property.binary_value.props[i].value.length, - xqos->property.binary_value.props[i].value.value, - xqos->property.binary_value.props[i].propagate); - } - DDS_CLOG (cat, logcfg, "}"); - DDS_CLOG (cat, logcfg, "}"); - }); - -#undef PRINTARG_DUR -#undef FMT_DUR -#undef DO -#undef LOGB5 -#undef LOGB4 -#undef LOGB3 -#undef LOGB2 -#undef LOGB1 -#undef LOGB0 + if (logcfg->c.mask & cat) + { + char tmp[1024], *ptmp = tmp; + size_t tmpsize = sizeof (tmp); + plist_or_xqos_print (&ptmp, &tmpsize, src, shift, pwanted, qwanted); + DDS_CLOG (cat, logcfg, "%s", tmp); + } +} + +size_t nn_xqos_print (char * __restrict buf, size_t bufsize, const dds_qos_t *xqos) +{ + const size_t bufsize_in = bufsize; + (void) prtf (&buf, &bufsize, "{"); + plist_or_xqos_print (&buf, &bufsize, xqos, offsetof (nn_plist_t, qos), 0, ~(uint64_t)0); + (void) prtf (&buf, &bufsize, "}"); + return bufsize_in - bufsize; +} + +size_t nn_plist_print (char * __restrict buf, size_t bufsize, const nn_plist_t *plist) +{ + const size_t bufsize_in = bufsize; + (void) prtf (&buf, &bufsize, "{"); + plist_or_xqos_print (&buf, &bufsize, plist, 0, ~(uint64_t)0, ~(uint64_t)0); + (void) prtf (&buf, &bufsize, "}"); + return bufsize_in - bufsize; +} + +void nn_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos) +{ + plist_or_xqos_log (cat, logcfg, xqos, offsetof (nn_plist_t, qos), 0, ~(uint64_t)0); +} + +void nn_plist_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const nn_plist_t *plist) +{ + plist_or_xqos_log (cat, logcfg, plist, 0, ~(uint64_t)0, ~(uint64_t)0); } diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 9d35df5..b0d14b1 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -3021,7 +3021,7 @@ static bool do_packet (struct thread_state1 * const ts1, struct q_globals *gv, d if (gv->logconfig.c.mask & DDS_LC_TRACE) { char addrstr[DDSI_LOCSTRLEN]; - ddsi_locator_to_string(gv, addrstr, sizeof(addrstr), &srcloc); + ddsi_locator_to_string(addrstr, sizeof(addrstr), &srcloc); GVTRACE ("HDR(%"PRIx32":%"PRIx32":%"PRIx32" vendor %d.%d) len %lu from %s\n", PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, addrstr); } @@ -3296,7 +3296,7 @@ void trigger_recv_threads (const struct q_globals *gv) ddsrt_iovec_t iov; iov.iov_base = &dummy; iov.iov_len = 1; - GVTRACE ("trigger_recv_threads: %d single %s\n", i, ddsi_locator_to_string (gv, buf, sizeof (buf), dst)); + GVTRACE ("trigger_recv_threads: %d single %s\n", i, ddsi_locator_to_string (buf, sizeof (buf), dst)); ddsi_conn_write (gv->data_conn_uc, dst, 1, &iov, 0); break; } diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 2336364..154d82c 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -1021,7 +1021,7 @@ static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg) if (gv->logconfig.c.mask & DDS_LC_TRACE) { char buf[DDSI_LOCSTRLEN]; - GVTRACE (" %s", ddsi_locator_to_string (gv, buf, sizeof(buf), loc)); + GVTRACE (" %s", ddsi_locator_to_string (buf, sizeof(buf), loc)); } if (gv->config.xmit_lossiness > 0) diff --git a/src/mpt/tests/qos/procs/rw.c b/src/mpt/tests/qos/procs/rw.c index 6f7ad0b..d1e6e26 100644 --- a/src/mpt/tests/qos/procs/rw.c +++ b/src/mpt/tests/qos/procs/rw.c @@ -146,8 +146,8 @@ static bool pubsub_qos_eq_h (const dds_qos_t *a, dds_entity_t ent) struct ddsrt_log_cfg logcfg; dds_log_cfg_init (&logcfg, 0, DDS_LC_ERROR, stderr, stderr); DDS_CLOG (DDS_LC_ERROR, &logcfg, "pub/sub: delta = %"PRIx64"\n", delta); - nn_log_xqos (DDS_LC_ERROR, &logcfg, a); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); - nn_log_xqos (DDS_LC_ERROR, &logcfg, b); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + nn_xqos_log (DDS_LC_ERROR, &logcfg, a); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + nn_xqos_log (DDS_LC_ERROR, &logcfg, b); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); } dds_delete_qos (b); return delta == 0; @@ -168,8 +168,8 @@ static bool reader_qos_eq_h (const dds_qos_t *a, dds_entity_t ent) struct ddsrt_log_cfg logcfg; dds_log_cfg_init (&logcfg, 0, DDS_LC_ERROR, stderr, stderr); DDS_CLOG (DDS_LC_ERROR, &logcfg, "reader: delta = %"PRIx64"\n", delta); - nn_log_xqos (DDS_LC_ERROR, &logcfg, a); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); - nn_log_xqos (DDS_LC_ERROR, &logcfg, b); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + nn_xqos_log (DDS_LC_ERROR, &logcfg, a); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + nn_xqos_log (DDS_LC_ERROR, &logcfg, b); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); } dds_delete_qos (b); return delta == 0; @@ -190,8 +190,8 @@ static bool writer_qos_eq_h (const dds_qos_t *a, dds_entity_t ent) struct ddsrt_log_cfg logcfg; dds_log_cfg_init (&logcfg, 0, DDS_LC_ERROR, stderr, stderr); DDS_CLOG (DDS_LC_ERROR, &logcfg, "writer: delta = %"PRIx64"\n", delta); - nn_log_xqos (DDS_LC_ERROR, &logcfg, a); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); - nn_log_xqos (DDS_LC_ERROR, &logcfg, b); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + nn_xqos_log (DDS_LC_ERROR, &logcfg, a); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + nn_xqos_log (DDS_LC_ERROR, &logcfg, b); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); } dds_delete_qos (b); return delta == 0; @@ -275,8 +275,8 @@ MPT_ProcessEntry (rw_publisher, struct ddsrt_log_cfg logcfg; dds_log_cfg_init (&logcfg, 0, DDS_LC_ERROR, stderr, stderr); DDS_CLOG (DDS_LC_ERROR, &logcfg, "matched reader: delta = %"PRIx64"\n", delta); - nn_log_xqos (DDS_LC_ERROR, &logcfg, qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); - nn_log_xqos (DDS_LC_ERROR, &logcfg, ep->qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + nn_xqos_log (DDS_LC_ERROR, &logcfg, qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + nn_xqos_log (DDS_LC_ERROR, &logcfg, ep->qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); } MPT_ASSERT (delta == 0, "writer %zu %zu matched reader QoS mismatch\n", i, j); dds_delete_qos (ep->qos); @@ -427,8 +427,8 @@ MPT_ProcessEntry (rw_subscriber, struct ddsrt_log_cfg logcfg; dds_log_cfg_init (&logcfg, 0, DDS_LC_ERROR, stderr, stderr); DDS_CLOG (DDS_LC_ERROR, &logcfg, "matched writer: delta = %"PRIx64"\n", delta); - nn_log_xqos (DDS_LC_ERROR, &logcfg, qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); - nn_log_xqos (DDS_LC_ERROR, &logcfg, ep->qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + nn_xqos_log (DDS_LC_ERROR, &logcfg, qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + nn_xqos_log (DDS_LC_ERROR, &logcfg, ep->qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); } MPT_ASSERT (delta == 0, "reader %zu %zu matched writer QoS mismatch\n", i, j); dds_delete_qos (ep->qos); diff --git a/src/tools/decode-trace b/src/tools/decode-trace index 3f19c4d..e534669 100755 --- a/src/tools/decode-trace +++ b/src/tools/decode-trace @@ -352,8 +352,10 @@ while(<>) { $rwguid{$tid} = $guid; # if $is_cyclone; die "$guid $rwguid{$tid}" unless $guid eq $rwguid{$tid}; my $topic; my $type; my $groupcoh; my $partitions; my $keepall; - if ($3 =~ /topic=([^,]+?),type=([^,]+?).*?,presentation=(\d:\d):\d,partition=\{([^}]*?)\}.*?,history=([01]):/) { - $topic = $1; $type = $2; $groupcoh = ($3 eq "2:1"); $partitions = $4; $keepall = $5; + if ($qos =~ /topic(?:_name)?=([^,]+?),type(?:_name)=([^,]+?).*?,partition=\{([^}]*?)\}/) { + $topic = $1; $type = $2; $partitions = $3; + die unless $qos =~ /,history=([01]):/; $keepall = $1; + die unless $qos =~ /,presentation=(\d:\d):\d/; $groupcoh = ($1 eq "2:1"); unless (defined $rwguid{$tid} && ($ftrflag{$tid} || (defined $psgid{$tid} && defined $psguid{$tid} && defined $rwgid{$tid})) || 1) { # $is_cyclone die; } @@ -623,15 +625,14 @@ while(<>) { my $h = ($kind eq "READER") ? \%prd : \%pwr; my $hk = ($kind eq "READER") ? "prd" : "pwr"; my $qos = $3; - unless ($3 =~ /topic=([^,]+?),type=([^,]+?),presentation=(\d+):\d+:\d+,partition=\{([^}]*?)\}.*?,durability=(\d+)/) { + unless ($3 =~ /topic(?:_name)?=([^,]+?),type(?:_name)?=([^,]+?),(?:.+?,)?partition=\{([^}]*?)\}/) { die unless $prwguid =~ /[4c][27]$/; } - my $topic = $1; my $type = $2; my $access_scope = $3; my $partitions = $4; my $durkind = $5; + my $topic = $1; my $type = $2; my $partitions = $3; (my $ppguid = $prwguid) =~ s/:[0-9a-f]+$/:1c1/; die unless exists $proxypp{$ppguid} && !defined $proxypp{$ppguid}->{tdel}; my @ps = split ',', $partitions; my $stopic = make_stopic($partitions, $topic); - #print "$kind $topic\n" if $durkind >= 2 && ($kind eq "READER" || $access_scope >= 2); my $prw = { guid => $prwguid, ppguid => $ppguid, topic => $topic, stopic => $stopic, type => $type, partition => \@ps, matches => {}, checklost => 0, suppressbegin => 0, tcreate => $ts, tstamps => {} }; From 27d7c726266931fa3e4d60bda78358b50be83640 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 28 Jan 2020 21:29:14 +0100 Subject: [PATCH 23/28] Relax constraints on topic entities This commit changes the implementation of topics so that multiple topic entities can exist in a single participant for the same topic. Different entities may refer to different topic implementations (sertopics, akin to a type support in the DDS specification). All entities (for the same participant) always have the same QoS, via the new "ktopic" table in the participant. Readers and writers are bound to a topic entity and inherit its properties. If a topic comes in two definitions, say one for C and one for C++, one can have a single participant with a reader delivering the data in C representation and another reader delivering it in C++ representation. This changes the behaviour of create_topic and find_topic: these now (on successful return) always return a new entity (and thus with a unique handle), where previously these would simply return a existing one when possible. This also requires some small additions to the sertopic/serdata interface. Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/dds.h | 45 +- .../ddsc/include/dds/ddsc/dds_public_impl.h | 1 + src/core/ddsc/src/dds__entity.h | 3 +- src/core/ddsc/src/dds__participant.h | 2 + src/core/ddsc/src/dds__serdata_builtintopic.h | 3 +- src/core/ddsc/src/dds__topic.h | 6 +- src/core/ddsc/src/dds__types.h | 26 +- src/core/ddsc/src/dds_builtin.c | 29 +- src/core/ddsc/src/dds_domain.c | 2 +- src/core/ddsc/src/dds_entity.c | 261 +++++++-- src/core/ddsc/src/dds_participant.c | 12 + src/core/ddsc/src/dds_reader.c | 93 +-- src/core/ddsc/src/dds_serdata_builtintopic.c | 2 +- src/core/ddsc/src/dds_sertopic_builtintopic.c | 18 +- src/core/ddsc/src/dds_topic.c | 549 ++++++++---------- src/core/ddsc/src/dds_writer.c | 45 +- src/core/ddsc/tests/topic.c | 6 +- src/core/ddsi/include/dds/ddsi/ddsi_serdata.h | 2 + .../include/dds/ddsi/ddsi_serdata_default.h | 1 - .../ddsi/include/dds/ddsi/ddsi_sertopic.h | 35 +- src/core/ddsi/include/dds/ddsi/q_globals.h | 3 + src/core/ddsi/src/ddsi_serdata_default.c | 56 +- src/core/ddsi/src/ddsi_sertopic.c | 86 ++- src/core/ddsi/src/ddsi_sertopic_default.c | 22 + src/core/ddsi/src/q_init.c | 55 +- src/core/xtests/rhc_torture/rhc_torture.c | 8 +- src/ddsrt/CMakeLists.txt | 2 + src/ddsrt/include/dds/ddsrt/mh3.h | 34 ++ src/ddsrt/src/mh3.c | 69 +++ 29 files changed, 946 insertions(+), 530 deletions(-) create mode 100644 src/ddsrt/include/dds/ddsrt/mh3.h create mode 100644 src/ddsrt/src/mh3.c diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index 089eea8..75f0f44 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -555,7 +555,9 @@ dds_set_enabled_status(dds_entity_t entity, uint32_t mask); * @param[in] entity Entity on which to get qos. * @param[out] qos Pointer to the qos structure that returns the set policies. * - * @returns A dds_return_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. The QoS object will have + * at least all QoS relevant for the entity present and the corresponding dds_qget_... + * will return true. * * @retval DDS_RETCODE_OK * The existing set of QoS policy values applied to the entity @@ -962,7 +964,9 @@ dds_lookup_participant( * @brief Creates a new topic with default type handling. * * The type name for the topic is taken from the generated descriptor. Topic - * matching is done on a combination of topic name and type name. + * matching is done on a combination of topic name and type name. Each successful + * call to dds_create_topic creates a new topic entity sharing the same QoS + * settings with all other topics of the same name. * * @param[in] participant Participant on which to create the topic. * @param[in] descriptor An IDL generated topic descriptor. @@ -970,14 +974,20 @@ dds_lookup_participant( * @param[in] qos QoS to set on the new topic (can be NULL). * @param[in] listener Any listener functions associated with the new topic (can be NULL). * - * @returns A valid topic handle or an error code. + * @returns A valid, unique topic handle or an error code. * * @retval >=0 - * A valid topic handle. + * A valid unique topic handle. * @retval DDS_RETCODE_BAD_PARAMETER * Either participant, descriptor, name or qos is invalid. + * @retval DDS_RETCODE_BAD_PARAMETER + * Either participant, descriptor, name or qos is invalid. + * @retval DDS_RETCODE_INCONSISTENT_POLICY + * QoS mismatch between qos and an existing topic's QoS. + * @retval DDS_RETCODE_PRECONDITION_NOT_MET + * Mismatch between type name in descriptor and pre-existing + * topic's type name. */ -/* TODO: Check list of retcodes is complete. */ DDS_EXPORT dds_entity_t dds_create_topic( dds_entity_t participant, @@ -992,7 +1002,13 @@ struct nn_plist; * @brief Creates a new topic with arbitrary type handling. * * The type name for the topic is taken from the provided "sertopic" object. Topic - * matching is done on a combination of topic name and type name. + * matching is done on a combination of topic name and type name. Each successful + * call to dds_create_topic creates a new topic entity sharing the same QoS + * settings with all other topics of the same name. + * + * If sertopic is not yet known in the domain, it is added and its refcount + * incremented; if an equivalent sertopic object is already known, then the known + * one is used instead. * * @param[in] participant Participant on which to create the topic. * @param[in] sertopic Internal description of the topic type (includes name). @@ -1000,14 +1016,20 @@ struct nn_plist; * @param[in] listener Any listener functions associated with the new topic (can be NULL). * @param[in] sedp_plist Topic description to be published as part of discovery (if NULL, not published). * - * @returns A valid topic handle or an error code. + * @returns A valid, unique topic handle or an error code. * * @retval >=0 - * A valid topic handle. + * A valid unique topic handle. * @retval DDS_RETCODE_BAD_PARAMETER * Either participant, descriptor, name or qos is invalid. + * @retval DDS_RETCODE_BAD_PARAMETER + * Either participant, descriptor, name or qos is invalid. + * @retval DDS_RETCODE_INCONSISTENT_POLICY + * QoS mismatch between qos and an existing topic's QoS. + * @retval DDS_RETCODE_PRECONDITION_NOT_MET + * Mismatch between type name in sertopic and pre-existing + * topic's type name. */ -/* TODO: Check list of retcodes is complete. */ DDS_EXPORT dds_entity_t dds_create_topic_arbitrary ( dds_entity_t participant, @@ -1030,8 +1052,9 @@ dds_create_topic_arbitrary ( * A valid topic handle. * @retval DDS_RETCODE_BAD_PARAMETER * Participant was invalid. + * @retval DDS_RETCODE_PRECONDITION_NOT_MET + * No topic of this name existed yet in the participant */ -/* TODO: Check list of retcodes is complete. */ DDS_EXPORT dds_entity_t dds_find_topic(dds_entity_t participant, const char *name); @@ -1047,8 +1070,6 @@ dds_find_topic(dds_entity_t participant, const char *name); * @retval DDS_RETCODE_OK * Success. */ -/* TODO: do we need a convenience version as well that allocates and add a _s suffix to this one? */ -/* TODO: Check annotation. Could be _Out_writes_to_(size, return + 1) as well. */ DDS_EXPORT dds_return_t dds_get_name(dds_entity_t topic, char *name, size_t size); diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_impl.h b/src/core/ddsc/include/dds/ddsc/dds_public_impl.h index 0b0d99d..730020c 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_impl.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_impl.h @@ -112,6 +112,7 @@ typedef enum dds_entity_kind DDS_KIND_DOMAIN, DDS_KIND_CYCLONEDDS } dds_entity_kind_t; +#define DDS_KIND_MAX DDS_KIND_CYCLONEDDS /* Handles are opaque pointers to implementation types */ typedef uint64_t dds_instance_handle_t; diff --git a/src/core/ddsc/src/dds__entity.h b/src/core/ddsc/src/dds__entity.h index 3725d83..23025c3 100644 --- a/src/core/ddsc/src/dds__entity.h +++ b/src/core/ddsc/src/dds__entity.h @@ -86,7 +86,8 @@ DDS_EXPORT void dds_entity_status_signal (dds_entity *e, uint32_t status); DDS_EXPORT void dds_entity_invoke_listener (const dds_entity *entity, enum dds_status_id which, const void *vst); -DDS_EXPORT dds_participant *dds_entity_participant (dds_entity *e); +DDS_EXPORT dds_participant *dds_entity_participant (const dds_entity *e); +DDS_EXPORT const ddsi_guid_t *dds_entity_participant_guid (const dds_entity *e); DDS_EXPORT void dds_entity_final_deinit_before_free (dds_entity *e); DDS_EXPORT bool dds_entity_in_scope (const dds_entity *e, const dds_entity *root); diff --git a/src/core/ddsc/src/dds__participant.h b/src/core/ddsc/src/dds__participant.h index ef52d86..feac58c 100644 --- a/src/core/ddsc/src/dds__participant.h +++ b/src/core/ddsc/src/dds__participant.h @@ -20,6 +20,8 @@ extern "C" { DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_participant, DDS_KIND_PARTICIPANT) +extern const ddsrt_avl_treedef_t participant_ktopics_treedef; + #if defined (__cplusplus) } #endif diff --git a/src/core/ddsc/src/dds__serdata_builtintopic.h b/src/core/ddsc/src/dds__serdata_builtintopic.h index 803f7e3..e95aa36 100644 --- a/src/core/ddsc/src/dds__serdata_builtintopic.h +++ b/src/core/ddsc/src/dds__serdata_builtintopic.h @@ -37,13 +37,12 @@ struct q_globals; struct ddsi_sertopic_builtintopic { struct ddsi_sertopic c; enum ddsi_sertopic_builtintopic_type type; - struct q_globals *gv; }; extern const struct ddsi_sertopic_ops ddsi_sertopic_ops_builtintopic; extern const struct ddsi_serdata_ops ddsi_serdata_ops_builtintopic; -struct ddsi_sertopic *new_sertopic_builtintopic (enum ddsi_sertopic_builtintopic_type type, const char *name, const char *typename, struct q_globals *gv); +struct ddsi_sertopic *new_sertopic_builtintopic (enum ddsi_sertopic_builtintopic_type type, const char *name, const char *typename); #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds__topic.h b/src/core/ddsc/src/dds__topic.h index d59dc1f..c1c794d 100644 --- a/src/core/ddsc/src/dds__topic.h +++ b/src/core/ddsc/src/dds__topic.h @@ -21,9 +21,13 @@ extern "C" { DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_topic, DDS_KIND_TOPIC) -DDS_EXPORT struct ddsi_sertopic * dds_topic_lookup (dds_domain * domain, const char * name) ddsrt_nonnull_all; DDS_EXPORT void dds_topic_free (dds_domainid_t domainid, struct ddsi_sertopic * st) ddsrt_nonnull_all; +DDS_EXPORT dds_return_t dds_topic_pin (dds_entity_t handle, struct dds_topic **tp) ddsrt_nonnull_all; +DDS_EXPORT void dds_topic_unpin (struct dds_topic *tp) ddsrt_nonnull_all; +DDS_EXPORT void dds_topic_defer_set_qos (struct dds_topic *tp) ddsrt_nonnull_all; +DDS_EXPORT void dds_topic_allow_set_qos (struct dds_topic *tp) ddsrt_nonnull_all; + #ifndef DDS_TOPIC_INTERN_FILTER_FN_DEFINED #define DDS_TOPIC_INTERN_FILTER_FN_DEFINED typedef bool (*dds_topic_intern_filter_fn) (const void * sample, void *ctx); diff --git a/src/core/ddsc/src/dds__types.h b/src/core/ddsc/src/dds__types.h index 4b9eec5..362a65c 100644 --- a/src/core/ddsc/src/dds__types.h +++ b/src/core/ddsc/src/dds__types.h @@ -34,6 +34,7 @@ struct dds_writer; struct dds_publisher; struct dds_subscriber; struct dds_topic; +struct dds_ktopic; struct dds_readcond; struct dds_guardcond; struct dds_statuscond; @@ -127,7 +128,7 @@ typedef struct dds_entity { ddsrt_avl_node_t m_avlnode_child; /* [m_mutex of m_parent] */ ddsrt_avl_tree_t m_children; /* [m_mutex] tree on m_iid using m_avlnode_child */ struct dds_domain *m_domain; /* constant */ - dds_qos_t *m_qos; /* [m_mutex] */ + dds_qos_t *m_qos; /* [m_mutex]; null for topics (they rely on correpsonding "ktopic") (+waitset,domain,&c.) */ ddsi_guid_t m_guid; /* unique (if not 0) and constant; FIXME: set during creation, but possibly after becoming visible */ dds_instance_handle_t m_iid; /* unique for all time, constant; FIXME: like GUID */ uint32_t m_flags; /* [m_mutex] */ @@ -215,7 +216,6 @@ typedef struct dds_domain { ddsrt_avl_node_t m_node; /* for dds_global.m_domains */ dds_domainid_t m_id; - ddsrt_avl_tree_t m_topics; struct cfgst *cfgst; struct ddsi_sertopic *builtin_participant_topic; @@ -238,14 +238,31 @@ typedef struct dds_publisher { struct dds_entity m_entity; } dds_publisher; +typedef struct dds_ktopic { + /* name -> mapping for topics, part of the participant + and protected by the participant's lock (including the actual QoS + setting) + + defer_set_qos is used to implement an intentionally unfair single-writer/ + multiple-reader lock using the participant's lock & cond var: set_qos + "write-locks" it, create_reader and create_writer "read-lock" it. */ + ddsrt_avl_node_t pp_ktopics_avlnode; + uint32_t refc; + uint32_t defer_set_qos; /* set_qos must wait for this to be 0 */ + dds_qos_t *qos; + char *name; /* [constant] */ + char *type_name; /* [constant] */ +} dds_ktopic; + typedef struct dds_participant { struct dds_entity m_entity; dds_entity_t m_builtin_subscriber; + ddsrt_avl_tree_t m_ktopics; /* [m_entity.m_mutex] */ } dds_participant; typedef struct dds_reader { struct dds_entity m_entity; - struct dds_topic *m_topic; + struct dds_topic *m_topic; /* refc'd, constant, lock(rd) -> lock(tp) allowed */ 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 +282,7 @@ typedef struct dds_reader { typedef struct dds_writer { struct dds_entity m_entity; - struct dds_topic *m_topic; + struct dds_topic *m_topic; /* refc'd, constant, lock(wr) -> lock(tp) allowed */ 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 )*/ @@ -287,6 +304,7 @@ typedef bool (*dds_topic_intern_filter_fn) (const void * sample, void *ctx); typedef struct dds_topic { struct dds_entity m_entity; struct ddsi_sertopic *m_stopic; + struct dds_ktopic *m_ktopic; /* refc'd, constant */ dds_topic_intern_filter_fn filter_fn; void *filter_ctx; diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index 8dd026f..cae0eb3 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -242,6 +242,13 @@ static void dds__builtin_write (const struct entity_common *e, nn_wctime_t times } } +static void unref_builtin_topics (struct dds_domain *dom) +{ + ddsi_sertopic_unref (dom->builtin_participant_topic); + ddsi_sertopic_unref (dom->builtin_reader_topic); + ddsi_sertopic_unref (dom->builtin_writer_topic); +} + void dds__builtin_init (struct dds_domain *dom) { dds_qos_t *qos = dds__create_builtin_qos (); @@ -253,9 +260,15 @@ void dds__builtin_init (struct dds_domain *dom) dom->btif.builtintopic_write = dds__builtin_write; dom->gv.builtin_topic_interface = &dom->btif; - dom->builtin_participant_topic = new_sertopic_builtintopic (DSBT_PARTICIPANT, "DCPSParticipant", "org::eclipse::cyclonedds::builtin::DCPSParticipant", &dom->gv); - dom->builtin_reader_topic = new_sertopic_builtintopic (DSBT_READER, "DCPSSubscription", "org::eclipse::cyclonedds::builtin::DCPSSubscription", &dom->gv); - dom->builtin_writer_topic = new_sertopic_builtintopic (DSBT_WRITER, "DCPSPublication", "org::eclipse::cyclonedds::builtin::DCPSPublication", &dom->gv); + dom->builtin_participant_topic = new_sertopic_builtintopic (DSBT_PARTICIPANT, "DCPSParticipant", "org::eclipse::cyclonedds::builtin::DCPSParticipant"); + dom->builtin_reader_topic = new_sertopic_builtintopic (DSBT_READER, "DCPSSubscription", "org::eclipse::cyclonedds::builtin::DCPSSubscription"); + dom->builtin_writer_topic = new_sertopic_builtintopic (DSBT_WRITER, "DCPSPublication", "org::eclipse::cyclonedds::builtin::DCPSPublication"); + + ddsrt_mutex_lock (&dom->gv.sertopics_lock); + ddsi_sertopic_register_locked (&dom->gv, dom->builtin_participant_topic); + ddsi_sertopic_register_locked (&dom->gv, dom->builtin_reader_topic); + ddsi_sertopic_register_locked (&dom->gv, dom->builtin_writer_topic); + ddsrt_mutex_unlock (&dom->gv.sertopics_lock); thread_state_awake (lookup_thread_state (), &dom->gv); const struct entity_index *gh = dom->gv.entity_index; @@ -265,6 +278,11 @@ void dds__builtin_init (struct dds_domain *dom) thread_state_asleep (lookup_thread_state ()); dds_delete_qos (qos); + + /* ddsi_sertopic_init initializes the refcount to 1 and dds_sertopic_register_locked increments + it. All "real" references (such as readers and writers) are also accounted for in the + reference count, so we have an excess reference here. */ + unref_builtin_topics (dom); } void dds__builtin_fini (struct dds_domain *dom) @@ -275,8 +293,5 @@ void dds__builtin_fini (struct dds_domain *dom) delete_local_orphan_writer (dom->builtintopic_writer_publications); delete_local_orphan_writer (dom->builtintopic_writer_subscriptions); thread_state_asleep (lookup_thread_state ()); - - ddsi_sertopic_unref (dom->builtin_participant_topic); - ddsi_sertopic_unref (dom->builtin_reader_topic); - ddsi_sertopic_unref (dom->builtin_writer_topic); + unref_builtin_topics (dom); } diff --git a/src/core/ddsc/src/dds_domain.c b/src/core/ddsc/src/dds_domain.c index 01d8085..0a1ffe1 100644 --- a/src/core/ddsc/src/dds_domain.c +++ b/src/core/ddsc/src/dds_domain.c @@ -13,6 +13,7 @@ #include "dds/ddsrt/process.h" #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/hopscotch.h" #include "dds__init.h" #include "dds/ddsc/dds_rhc.h" #include "dds__domain.h" @@ -59,7 +60,6 @@ static dds_entity_t dds_domain_init (dds_domain *domain, dds_domainid_t domain_i domain->m_entity.m_iid = ddsi_iid_gen (); domain->gv.tstart = now (); - ddsrt_avl_init (&dds_topictree_def, &domain->m_topics); /* | domain_id | domain id in config | result +-----------+---------------------+---------- diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index 4e6a225..7a80ddb 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -135,11 +135,65 @@ static bool entity_has_status (const dds_entity *e) return false; } +static bool entity_may_have_children (const dds_entity *e) +{ + switch (e->m_kind) + { + case DDS_KIND_TOPIC: + return false; + case DDS_KIND_READER: + case DDS_KIND_WRITER: + case DDS_KIND_PUBLISHER: + case DDS_KIND_SUBSCRIBER: + case DDS_KIND_PARTICIPANT: + case DDS_KIND_COND_READ: + case DDS_KIND_COND_QUERY: + case DDS_KIND_COND_GUARD: + case DDS_KIND_WAITSET: + case DDS_KIND_DOMAIN: + case DDS_KIND_CYCLONEDDS: + break; + case DDS_KIND_DONTCARE: + abort (); + break; + } + return true; +} + +#ifndef NDEBUG +static bool entity_kind_has_qos (dds_entity_kind_t kind) +{ + switch (kind) + { + case DDS_KIND_READER: + case DDS_KIND_WRITER: + case DDS_KIND_PUBLISHER: + case DDS_KIND_SUBSCRIBER: + case DDS_KIND_PARTICIPANT: + return true; + case DDS_KIND_TOPIC: + case DDS_KIND_COND_READ: + case DDS_KIND_COND_QUERY: + case DDS_KIND_COND_GUARD: + case DDS_KIND_WAITSET: + case DDS_KIND_DOMAIN: + case DDS_KIND_CYCLONEDDS: + break; + case DDS_KIND_DONTCARE: + abort (); + break; + } + return false; +} +#endif + 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; + /* CycloneDDS is at the root of the hierarchy */ assert ((kind == DDS_KIND_CYCLONEDDS) == (parent == NULL)); + assert (entity_kind_has_qos (kind) == (qos != NULL)); assert (e); e->m_kind = kind; @@ -196,7 +250,7 @@ dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind { /* 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) + if ((handle = dds_handle_create (&e->m_hdllink, implicit, entity_may_have_children (e))) <= 0) return (dds_entity_t) handle; } @@ -219,41 +273,40 @@ void dds_entity_register_child (dds_entity *parent, dds_entity *child) dds_entity_add_ref_locked (parent); } -static dds_entity *get_first_child (ddsrt_avl_tree_t *remaining_children, bool ignore_topics) +static dds_entity *get_next_child (ddsrt_avl_tree_t *remaining_children, uint32_t allowed_kinds, uint64_t *cursor) { 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)) + for (dds_entity *e = ddsrt_avl_iter_succ (&dds_entity_children_td, remaining_children, &it, cursor); e != NULL; e = ddsrt_avl_iter_next (&it)) { - if ((!ignore_topics) || (dds_entity_kind(e) != DDS_KIND_TOPIC)) + dds_entity_kind_t kind = dds_entity_kind (e); + if ((1u << (uint32_t) kind) & allowed_kinds) return e; } return NULL; } -static void delete_children(struct dds_entity *parent, bool ignore_topics) +static void delete_children (struct dds_entity *parent, uint32_t allowed_kinds) { dds_entity *child; dds_return_t ret; + uint64_t cursor = 0; ddsrt_mutex_lock (&parent->m_mutex); - while ((child = get_first_child(&parent->m_children, ignore_topics)) != NULL) + while ((child = get_next_child (&parent->m_children, allowed_kinds, &cursor)) != NULL) { dds_entity_t child_handle = child->m_hdllink.hdl; + cursor = child->m_iid; /* 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); + (void) ret; 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)) - { + /* The dds_delete can fail if the child is being deleted in parallel, in which case: + wait until it is has gone. */ + if (ddsrt_avl_lookup (&dds_entity_children_td, &parent->m_children, &cursor) != NULL) ddsrt_cond_wait (&parent->m_cond, &parent->m_mutex); - } } ddsrt_mutex_unlock (&parent->m_mutex); } @@ -283,12 +336,20 @@ static const char *entity_kindstr (dds_entity_kind_t kind) static void print_delete (const dds_entity *e, enum delete_impl_state delstate , dds_instance_handle_t iid) { - unsigned cm = ddsrt_atomic_ld32 (&e->m_hdllink.cnt_flags); - printf ("delete(%p, delstate %s, iid %"PRIx64"): %s%s %d pin %u refc %u %s %s\n", - (void *) e, (delstate == DIS_IMPLICIT) ? "implicit" : (delstate == DIS_EXPLICIT) ? "explicit" : "from_parent", iid, - entity_kindstr (e->m_kind), (e->m_flags & DDS_ENTITY_IMPLICIT) ? " [implicit]" : "", - e->m_hdllink.hdl, cm & 0xfff, (cm >> 12) & 0x7fff, (cm & 0x80000000) ? "closed" : "open", - ddsrt_avl_is_empty (&e->m_children) ? "childless" : "has-children"); + if (e) + { + unsigned cm = ddsrt_atomic_ld32 (&e->m_hdllink.cnt_flags); + printf ("delete(%p, delstate %s, iid %"PRIx64"): %s%s %d pin %u refc %u %s %s\n", + (void *) e, (delstate == DIS_IMPLICIT) ? "implicit" : (delstate == DIS_EXPLICIT) ? "explicit" : "from_parent", iid, + entity_kindstr (e->m_kind), (e->m_flags & DDS_ENTITY_IMPLICIT) ? " [implicit]" : "", + e->m_hdllink.hdl, cm & 0xfff, (cm >> 12) & 0x7fff, (cm & 0x80000000) ? "closed" : "open", + ddsrt_avl_is_empty (&e->m_children) ? "childless" : "has-children"); + } + else + { + printf ("delete(%p, delstate %s, handle %"PRId64"): pin failed\n", + (void *) e, (delstate == DIS_IMPLICIT) ? "implicit" : (delstate == DIS_EXPLICIT) ? "explicit" : "from_parent", iid); + } } #endif @@ -315,7 +376,12 @@ static dds_return_t dds_delete_impl (dds_entity_t entity, enum delete_impl_state else if (ret == DDS_RETCODE_TRY_AGAIN) /* non-child refs exist */ return DDS_RETCODE_OK; else + { +#if TRACE_DELETE + print_delete (NULL, delstate, (uint64_t) entity); +#endif return ret; + } } dds_return_t dds_delete_impl_pinned (dds_entity *e, enum delete_impl_state delstate) @@ -392,8 +458,15 @@ static dds_return_t really_delete_pinned_closed_locked (struct dds_entity *e, en * * To circumvent the problem. We ignore topics in the first loop. */ - delete_children(e, true /* ignore topics */); - delete_children(e, false /* delete topics */); + DDSRT_STATIC_ASSERT ((uint32_t) DDS_KIND_MAX < 32); + static const uint32_t disallowed_kinds[] = { + 1u << (uint32_t) DDS_KIND_TOPIC, + (uint32_t) 0 + }; + for (size_t i = 0; i < sizeof (disallowed_kinds) / sizeof (disallowed_kinds[0]); i++) + { + delete_children (e, ~disallowed_kinds[i]); + } /* 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 @@ -476,13 +549,20 @@ dds_entity_t dds_get_parent (dds_entity_t entity) } } -dds_participant *dds_entity_participant (dds_entity *e) +dds_participant *dds_entity_participant (const dds_entity *e) { while (e && dds_entity_kind (e) != DDS_KIND_PARTICIPANT) e = e->m_parent; return (dds_participant *) e; } +const ddsi_guid_t *dds_entity_participant_guid (const dds_entity *e) +{ + struct dds_participant const * const pp = dds_entity_participant (e); + assert (pp != NULL); + return &pp->m_entity.m_guid; +} + dds_entity_t dds_get_participant (dds_entity_t entity) { dds_entity *e; @@ -577,51 +657,124 @@ dds_return_t dds_get_qos (dds_entity_t entity, dds_qos_t *qos) ret = DDS_RETCODE_ILLEGAL_OPERATION; else { + dds_qos_t *entity_qos; + if (dds_entity_kind (e) != DDS_KIND_TOPIC) + entity_qos = e->m_qos; + else + { + struct dds_topic * const tp = (dds_topic *) e; + struct dds_participant * const pp = dds_entity_participant (e); + ddsrt_mutex_lock (&pp->m_entity.m_mutex); + entity_qos = tp->m_ktopic->qos; + ddsrt_mutex_unlock (&pp->m_entity.m_mutex); + } + dds_reset_qos (qos); - nn_xqos_mergein_missing (qos, e->m_qos, ~(QP_TOPIC_NAME | QP_TYPE_NAME)); + nn_xqos_mergein_missing (qos, entity_qos, ~(QP_TOPIC_NAME | QP_TYPE_NAME)); ret = DDS_RETCODE_OK; } dds_entity_unlock(e); return ret; } -static dds_return_t dds_set_qos_locked_impl (dds_entity *e, const dds_qos_t *qos, uint64_t mask) +static dds_return_t dds_set_qos_locked_raw (dds_entity *e, dds_qos_t **e_qos_ptr, bool e_enabled, const dds_qos_t *qos, uint64_t mask, const struct ddsrt_log_cfg *logcfg, dds_return_t (*set_qos) (struct dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all) { dds_return_t ret; + + /* Any attempt to do this on a topic ends up doing it on the ktopic instead, so that there is + but a single QoS for a topic in a participant while there can be multiple definitions of it, + and hence, multiple sertopics. Those are needed for multi-language support. */ dds_qos_t *newqos = dds_create_qos (); nn_xqos_mergein_missing (newqos, qos, mask); - nn_xqos_mergein_missing (newqos, e->m_qos, ~(uint64_t)0); - if ((ret = nn_xqos_valid (&e->m_domain->gv.logconfig, newqos)) != DDS_RETCODE_OK) - ; /* oops ... invalid or inconsistent */ - else if (!(e->m_flags & DDS_ENTITY_ENABLED)) - ; /* do as you please while the entity is not enabled (perhaps we should even allow invalid ones?) */ + nn_xqos_mergein_missing (newqos, *e_qos_ptr, ~(uint64_t)0); + if ((ret = nn_xqos_valid (logcfg, newqos)) != DDS_RETCODE_OK) + { + /* invalid or inconsistent QoS settings */ + goto error_or_nochange; + } + else if (!e_enabled) + { + /* do as you please while the entity is not enabled */ + } else { - const uint64_t delta = nn_xqos_delta (e->m_qos, newqos, ~(uint64_t)0); - if (delta == 0) /* no change */ - ret = DDS_RETCODE_OK; - else if (delta & ~QP_CHANGEABLE_MASK) - ret = DDS_RETCODE_IMMUTABLE_POLICY; - else if (delta & (QP_RXO_MASK | QP_PARTITION)) - ret = DDS_RETCODE_UNSUPPORTED; /* not yet supporting things that affect matching */ - else + const uint64_t delta = nn_xqos_delta (*e_qos_ptr, newqos, ~(uint64_t)0); + if (delta == 0) { - /* yay! */ + /* new settings are identical to the old */ + goto error_or_nochange; + } + else if (delta & ~QP_CHANGEABLE_MASK) + { + /* not all QoS may be changed according to the spec */ + ret = DDS_RETCODE_IMMUTABLE_POLICY; + goto error_or_nochange; + } + else if (delta & (QP_RXO_MASK | QP_PARTITION)) + { + /* Cyclone doesn't (yet) support changing QoS that affect matching. Simply re-doing the + matching is easy enough, but the consequences are very weird. E.g., what is the + expectation if a transient-local writer has published data while its partition QoS is set + to A, and then changes its partition to B? Should a reader in B get the data originally + published in A? + + One can do the same thing with other RxO QoS settings, e.g., the latency budget setting. + I find that weird, and I'd rather have sane answers to these questions than set up these + traps and pitfalls for people to walk into ... + */ + ret = DDS_RETCODE_UNSUPPORTED; + goto error_or_nochange; } } - if (ret != DDS_RETCODE_OK) - dds_delete_qos (newqos); - else if ((ret = dds_entity_deriver_set_qos (e, newqos, e->m_flags & DDS_ENTITY_ENABLED)) != DDS_RETCODE_OK) - dds_delete_qos (newqos); + assert (ret == DDS_RETCODE_OK); + if ((ret = set_qos (e, newqos, e_enabled)) != DDS_RETCODE_OK) + goto error_or_nochange; else { - dds_delete_qos (e->m_qos); - e->m_qos = newqos; + dds_delete_qos (*e_qos_ptr); + *e_qos_ptr = newqos; } + return DDS_RETCODE_OK; + +error_or_nochange: + dds_delete_qos (newqos); return ret; } +static dds_return_t dds_set_qos_locked_impl (dds_entity *e, const dds_qos_t *qos, uint64_t mask) +{ + const struct ddsrt_log_cfg *logcfg = &e->m_domain->gv.logconfig; + dds_entity_kind_t kind = dds_entity_kind (e); + if (kind != DDS_KIND_TOPIC) + { + return dds_set_qos_locked_raw (e, &e->m_qos, (e->m_flags & DDS_ENTITY_ENABLED) != 0, qos, mask, logcfg, dds_entity_deriver_table[kind]->set_qos); + } + else + { + /* Topics must be enabled for now (all are currently, so for now it is not a meaningful limitation): + there can only be a single QoS (or different versions with the same name can have different QoS - + in particular a different value for TOPIC_DATA - and therefore the idea that it is a free-for-all + on the QoS for a disabled entity falls apart for topics. + + FIXME: topic should have a QoS object while still disabled */ + assert (e->m_flags & DDS_ENTITY_ENABLED); + struct dds_topic * const tp = (struct dds_topic *) e; + struct dds_participant * const pp = dds_entity_participant (e); + struct dds_ktopic * const ktp = tp->m_ktopic; + dds_return_t rc; + ddsrt_mutex_lock (&pp->m_entity.m_mutex); + while (ktp->defer_set_qos != 0) + ddsrt_cond_wait (&pp->m_entity.m_cond, &pp->m_entity.m_mutex); + + /* dds_entity_deriver_table[kind]->set_qos had better avoid looking at the entity! */ + rc = dds_set_qos_locked_raw (NULL, &ktp->qos, (e->m_flags & DDS_ENTITY_ENABLED) != 0, qos, mask, logcfg, dds_entity_deriver_table[kind]->set_qos); + + ddsrt_mutex_unlock (&pp->m_entity.m_mutex); + return rc; + } +} + static void pushdown_pubsub_qos (dds_entity *e) { /* e claimed but no mutex held */ @@ -650,7 +803,7 @@ static void pushdown_pubsub_qos (dds_entity *e) ddsrt_mutex_unlock (&e->m_mutex); } -static void pushdown_topic_qos (dds_entity *e, struct dds_entity *tp) +static void pushdown_topic_qos (dds_entity *e, struct dds_ktopic *ktp) { /* on input: both entities claimed but no mutexes held */ enum { NOP, PROP, CHANGE } todo; @@ -658,12 +811,12 @@ static void pushdown_topic_qos (dds_entity *e, struct dds_entity *tp) { case DDS_KIND_READER: { dds_reader *rd = (dds_reader *) e; - todo = (&rd->m_topic->m_entity == tp) ? CHANGE : NOP; + todo = (rd->m_topic->m_ktopic == ktp) ? CHANGE : NOP; break; } case DDS_KIND_WRITER: { dds_writer *wr = (dds_writer *) e; - todo = (&wr->m_topic->m_entity == tp) ? CHANGE : NOP; + todo = (wr->m_topic->m_ktopic == ktp) ? CHANGE : NOP; break; } default: { @@ -677,10 +830,11 @@ static void pushdown_topic_qos (dds_entity *e, struct dds_entity *tp) break; case CHANGE: { /* may lock topic while holding reader/writer lock */ + struct dds_participant * const pp = dds_entity_participant (e); ddsrt_mutex_lock (&e->m_mutex); - ddsrt_mutex_lock (&tp->m_mutex); - dds_set_qos_locked_impl (e, tp->m_qos, QP_TOPIC_DATA); - ddsrt_mutex_unlock (&tp->m_mutex); + ddsrt_mutex_lock (&pp->m_entity.m_mutex); + dds_set_qos_locked_impl (e, ktp->qos, QP_TOPIC_DATA); + ddsrt_mutex_unlock (&pp->m_entity.m_mutex); ddsrt_mutex_unlock (&e->m_mutex); break; } @@ -697,7 +851,7 @@ static void pushdown_topic_qos (dds_entity *e, struct dds_entity *tp) assert (x == c); /* see dds_get_children for why "c" remains valid despite unlocking m_mutex */ ddsrt_mutex_unlock (&e->m_mutex); - pushdown_topic_qos (c, tp); + pushdown_topic_qos (c, ktp); ddsrt_mutex_lock (&e->m_mutex); dds_entity_unpin (c); } @@ -740,7 +894,8 @@ dds_return_t dds_set_qos (dds_entity_t entity, const dds_qos_t *qos) assert (dds_entity_kind (e->m_parent) == DDS_KIND_PARTICIPANT); if (dds_entity_pin (e->m_parent->m_hdllink.hdl, &pp) == DDS_RETCODE_OK) { - pushdown_topic_qos (pp, e); + struct dds_topic *tp = (struct dds_topic *) e; + pushdown_topic_qos (pp, tp->m_ktopic); dds_entity_unpin (pp); } break; diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index e9cdacb..47ee768 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -10,6 +10,7 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include +#include #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/environ.h" @@ -30,6 +31,13 @@ DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_participant) #define DDS_PARTICIPANT_STATUS_MASK (0u) +static int cmp_ktopic_name (const void *a, const void *b) +{ + return strcmp (a, b); +} + +const ddsrt_avl_treedef_t participant_ktopics_treedef = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY(offsetof (struct dds_ktopic, pp_ktopics_avlnode), offsetof (struct dds_ktopic, name), cmp_ktopic_name, 0); + static dds_return_t dds_participant_status_validate (uint32_t mask) { return (mask & ~DDS_PARTICIPANT_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK; @@ -42,6 +50,9 @@ static dds_return_t dds_participant_delete (dds_entity *e) dds_return_t ret; assert (dds_entity_kind (e) == DDS_KIND_PARTICIPANT); + /* ktopics & topics are children and therefore must all have been deleted by the time we get here */ + assert (ddsrt_avl_is_empty (&((struct dds_participant *) e)->m_ktopics)); + thread_state_awake (lookup_thread_state (), &e->m_domain->gv); if ((ret = delete_participant (&e->m_domain->gv, &e->m_guid)) < 0) DDS_CERROR (&e->m_domain->gv.logconfig, "dds_participant_delete: internal error %"PRId32"\n", ret); @@ -125,6 +136,7 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_ pp->m_entity.m_iid = get_entity_instance_id (&dom->gv, &guid); pp->m_entity.m_domain = dom; pp->m_builtin_subscriber = 0; + ddsrt_avl_init (&participant_ktopics_treedef, &pp->m_ktopics); /* Add participant to extent */ ddsrt_mutex_lock (&dom->m_entity.m_mutex); diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 71bfd3d..3a6b385 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -14,6 +14,7 @@ #include "dds/dds.h" #include "dds/version.h" #include "dds/ddsrt/static_assert.h" +#include "dds__participant.h" #include "dds__subscriber.h" #include "dds__reader.h" #include "dds__listener.h" @@ -359,32 +360,34 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe { dds_qos_t *rqos; dds_subscriber *sub = NULL; - dds_participant *pp; dds_entity_t subscriber; - dds_reader *rd; dds_topic *tp; - dds_entity_t reader; - dds_entity_t t; - dds_return_t ret = DDS_RETCODE_OK; - bool internal_topic; + dds_return_t rc; + dds_entity_t pseudo_topic = 0; + bool created_implicit_sub = false; switch (topic) { - case DDS_BUILTIN_TOPIC_DCPSPARTICIPANT: case DDS_BUILTIN_TOPIC_DCPSTOPIC: + /* not implemented yet */ + return DDS_RETCODE_BAD_PARAMETER; + + case DDS_BUILTIN_TOPIC_DCPSPARTICIPANT: case DDS_BUILTIN_TOPIC_DCPSPUBLICATION: 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); + /* translate provided pseudo-topic to a real one */ + pseudo_topic = topic; + if ((subscriber = dds__get_builtin_subscriber (participant_or_subscriber)) < 0) + return subscriber; + if ((rc = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK) + return rc; + topic = dds__get_builtin_topic (subscriber, topic); break; default: { dds_entity *p_or_s; - if ((ret = dds_entity_lock (participant_or_subscriber, DDS_KIND_DONTCARE, &p_or_s)) != DDS_RETCODE_OK) - return ret; + if ((rc = dds_entity_lock (participant_or_subscriber, DDS_KIND_DONTCARE, &p_or_s)) != DDS_RETCODE_OK) + return rc; switch (dds_entity_kind (p_or_s)) { case DDS_KIND_SUBSCRIBER: @@ -392,34 +395,39 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe sub = (dds_subscriber *) p_or_s; break; case DDS_KIND_PARTICIPANT: + created_implicit_sub = true; 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; + if ((rc = dds_subscriber_lock (subscriber, &sub)) < 0) + return rc; break; default: dds_entity_unlock (p_or_s); return DDS_RETCODE_ILLEGAL_OPERATION; } - internal_topic = false; - t = topic; break; } } - if ((ret = dds_topic_lock (t, &tp)) != DDS_RETCODE_OK) - { - reader = ret; - goto err_tp_lock; - } + if ((rc = dds_topic_pin (topic, &tp)) < 0) + goto err_pin_topic; assert (tp->m_stopic); - pp = dds_entity_participant (&sub->m_entity); - if (pp != dds_entity_participant (&tp->m_entity)) + if (dds_entity_participant (&sub->m_entity) != dds_entity_participant (&tp->m_entity)) { - reader = DDS_RETCODE_BAD_PARAMETER; + rc = DDS_RETCODE_BAD_PARAMETER; goto err_pp_mismatch; } + /* Prevent set_qos on the topic until reader has been created and registered: we can't + allow a TOPIC_DATA change to ccur before the reader has been created because that + change would then not be published in the discovery/built-in topics. + + Don't keep the participant (which protects the topic's QoS) locked because that + can cause deadlocks for applications creating a reader/writer from within a + subscription matched listener (whether the restrictions on what one can do in + listeners are reasonable or not, it used to work so it can be broken arbitrarily). */ + dds_topic_defer_set_qos (tp); + /* Merge qos from topic and subscriber, dds_copy_qos only fails when it is passed a null argument, but that isn't the case here */ rqos = dds_create_qos (); @@ -427,31 +435,30 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe nn_xqos_mergein_missing (rqos, qos, DDS_READER_QOS_MASK); if (sub->m_entity.m_qos) nn_xqos_mergein_missing (rqos, sub->m_entity.m_qos, ~(uint64_t)0); - if (tp->m_entity.m_qos) - nn_xqos_mergein_missing (rqos, tp->m_entity.m_qos, ~(uint64_t)0); + if (tp->m_ktopic->qos) + nn_xqos_mergein_missing (rqos, tp->m_ktopic->qos, ~(uint64_t)0); nn_xqos_mergein_missing (rqos, &sub->m_entity.m_domain->gv.default_xqos_rd, ~(uint64_t)0); - if ((ret = nn_xqos_valid (&sub->m_entity.m_domain->gv.logconfig, rqos)) < 0 || - (ret = validate_reader_qos(rqos)) != DDS_RETCODE_OK) + if ((rc = nn_xqos_valid (&sub->m_entity.m_domain->gv.logconfig, rqos)) < 0 || + (rc = validate_reader_qos(rqos)) != DDS_RETCODE_OK) { dds_delete_qos (rqos); - reader = ret; goto err_bad_qos; } /* Additional checks required for built-in topics: we don't want to run into a resource limit on a built-in topic, it is a needless complication */ - if (internal_topic && !dds__validate_builtin_reader_qos (tp->m_entity.m_domain, topic, rqos)) + if (pseudo_topic && !dds__validate_builtin_reader_qos (tp->m_entity.m_domain, pseudo_topic, rqos)) { dds_delete_qos (rqos); - reader = DDS_RETCODE_INCONSISTENT_POLICY; + rc = DDS_RETCODE_INCONSISTENT_POLICY; goto err_bad_qos; } /* 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, false, rqos, listener, DDS_READER_STATUS_MASK); + struct dds_reader * const rd = dds_alloc (sizeof (*rd)); + const dds_entity_t 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); @@ -468,25 +475,27 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe dds_entity_init_complete (&rd->m_entity); thread_state_awake (lookup_thread_state (), &sub->m_entity.m_domain->gv); - ret = new_reader (&rd->m_rd, &rd->m_entity.m_domain->gv, &rd->m_entity.m_guid, NULL, &pp->m_entity.m_guid, tp->m_stopic, rqos, &rd->m_rhc->common.rhc, dds_reader_status_cb, rd); - assert (ret == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */ + rc = new_reader (&rd->m_rd, &rd->m_entity.m_domain->gv, &rd->m_entity.m_guid, NULL, dds_entity_participant_guid (&sub->m_entity), tp->m_stopic, rqos, &rd->m_rhc->common.rhc, dds_reader_status_cb, rd); + assert (rc == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */ thread_state_asleep (lookup_thread_state ()); rd->m_entity.m_iid = get_entity_instance_id (&rd->m_entity.m_domain->gv, &rd->m_entity.m_guid); dds_entity_register_child (&sub->m_entity, &rd->m_entity); - dds_topic_unlock (tp); + dds_topic_allow_set_qos (tp); + dds_topic_unpin (tp); dds_subscriber_unlock (sub); return reader; err_bad_qos: + dds_topic_allow_set_qos (tp); err_pp_mismatch: - dds_topic_unlock (tp); -err_tp_lock: + dds_topic_unpin (tp); +err_pin_topic: dds_subscriber_unlock (sub); - if ((sub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0) + if (created_implicit_sub) (void) dds_delete (subscriber); - return reader; + return rc; } void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb, void *cbarg) diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index 1425c60..f9d3122 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -132,7 +132,7 @@ static struct ddsi_serdata *ddsi_serdata_builtin_from_keyhash (const struct ddsi /* FIXME: not quite elegant to manage the creation of a serdata for a built-in topic via this function, but I also find it quite unelegant to let from_sample read straight from the underlying internal entity, and to_sample convert to the external format ... I could claim the internal entity is the "serialised form", but that forces wrapping it in a fragchain in one way or another, which, though possible, is also a bit lacking in elegance. */ const struct ddsi_sertopic_builtintopic *tp = (const struct ddsi_sertopic_builtintopic *)tpcmn; /* keyhash must in host format (which the GUIDs always are internally) */ - struct entity_common *entity = entidx_lookup_guid_untyped (tp->gv->entity_index, (const ddsi_guid_t *) keyhash->value); + struct entity_common *entity = entidx_lookup_guid_untyped (tp->c.gv->entity_index, (const ddsi_guid_t *) keyhash->value); struct ddsi_serdata_builtintopic *d = serdata_builtin_new(tp, entity ? SDK_DATA : SDK_KEY); memcpy (&d->key, keyhash->value, sizeof (d->key)); if (entity) diff --git a/src/core/ddsc/src/dds_sertopic_builtintopic.c b/src/core/ddsc/src/dds_sertopic_builtintopic.c index 07f730c..c5ace24 100644 --- a/src/core/ddsc/src/dds_sertopic_builtintopic.c +++ b/src/core/ddsc/src/dds_sertopic_builtintopic.c @@ -25,12 +25,11 @@ /* FIXME: sertopic /= ddstopic so a lot of stuff needs to be moved here from dds_topic.c and the free function needs to be implemented properly */ -struct ddsi_sertopic *new_sertopic_builtintopic (enum ddsi_sertopic_builtintopic_type type, const char *name, const char *typename, struct q_globals *gv) +struct ddsi_sertopic *new_sertopic_builtintopic (enum ddsi_sertopic_builtintopic_type type, const char *name, const char *typename) { struct ddsi_sertopic_builtintopic *tp = ddsrt_malloc (sizeof (*tp)); ddsi_sertopic_init (&tp->c, name, typename, &ddsi_sertopic_ops_builtintopic, &ddsi_serdata_ops_builtintopic, false); tp->type = type; - tp->gv = gv; return &tp->c; } @@ -40,6 +39,19 @@ static void sertopic_builtin_free (struct ddsi_sertopic *tp) ddsrt_free (tp); } +static bool sertopic_builtin_equal (const struct ddsi_sertopic *acmn, const struct ddsi_sertopic *bcmn) +{ + const struct ddsi_sertopic_builtintopic *a = (struct ddsi_sertopic_builtintopic *) acmn; + const struct ddsi_sertopic_builtintopic *b = (struct ddsi_sertopic_builtintopic *) bcmn; + return a->type == b->type; +} + +static uint32_t sertopic_builtin_hash (const struct ddsi_sertopic *tpcmn) +{ + const struct ddsi_sertopic_builtintopic *tp = (struct ddsi_sertopic_builtintopic *) tpcmn; + return tp->type; +} + static void free_pp (void *vsample) { dds_builtintopic_participant_t *sample = vsample; @@ -131,6 +143,8 @@ static void sertopic_builtin_free_samples (const struct ddsi_sertopic *sertopic_ } const struct ddsi_sertopic_ops ddsi_sertopic_ops_builtintopic = { + .equal = sertopic_builtin_equal, + .hash = sertopic_builtin_hash, .free = sertopic_builtin_free, .zero_samples = sertopic_builtin_zero_samples, .realloc_samples = sertopic_builtin_realloc_samples, diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 9c4c724..7b40f9b 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -45,15 +45,6 @@ struct topic_sertopic_node { const struct ddsi_sertopic *st; }; -static int topic_sertopic_node_cmp (const void *va, const void *vb) -{ - const struct ddsi_sertopic *a = va; - const struct ddsi_sertopic *b = vb; - return strcmp (a->name, b->name); -} - -const ddsrt_avl_treedef_t dds_topictree_def = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct topic_sertopic_node, avlnode), offsetof (struct topic_sertopic_node, st), topic_sertopic_node_cmp, 0); - static bool is_valid_name (const char *name) ddsrt_nonnull_all; static bool is_valid_name (const char *name) @@ -112,164 +103,88 @@ static void dds_topic_status_cb (struct dds_topic *tp) } #endif -struct ddsi_sertopic *dds_topic_lookup (dds_domain *domain, const char *name) +dds_return_t dds_topic_pin (dds_entity_t handle, struct dds_topic **tp) { - const struct ddsi_sertopic key = { .name = (char *) name }; - struct ddsi_sertopic *st; - struct topic_sertopic_node *nst; - ddsrt_mutex_lock (&dds_global.m_mutex); - if ((nst = ddsrt_avl_lookup (&dds_topictree_def, &domain->m_topics, &key)) == NULL) - st = NULL; - else - st = ddsi_sertopic_ref (nst->st); - ddsrt_mutex_unlock (&dds_global.m_mutex); - return st; -} - -static bool dds_find_topic_check_and_add_ref (dds_entity_t participant, dds_entity_t topic, const char *name) -{ - dds_topic *tp; - if (dds_topic_lock (topic, &tp) != DDS_RETCODE_OK) - return false; - - bool ret; - if (dds_entity_participant (&tp->m_entity)->m_entity.m_hdllink.hdl != participant || strcmp (tp->m_stopic->name, name) != 0) - ret = false; - else - { - /* 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); - return ret; -} - -dds_entity_t dds_find_topic (dds_entity_t participant, const char *name) -{ - dds_entity *pe; + struct dds_entity *e; dds_return_t ret; - dds_entity_t topic; - - if (name == NULL) - return DDS_RETCODE_BAD_PARAMETER; - - /* claim participant handle to guarantee the handle remains valid after - unlocking the participant prior to verifying the found topic still - exists */ - if ((ret = dds_entity_pin (participant, &pe)) < 0) + if ((ret = dds_entity_pin (handle, &e)) < 0) return ret; - if (dds_entity_kind (pe) != DDS_KIND_PARTICIPANT) + if (dds_entity_kind (e) != DDS_KIND_TOPIC) { - dds_entity_unpin (pe); + dds_entity_unpin (e); return DDS_RETCODE_ILLEGAL_OPERATION; } + *tp = (struct dds_topic *) e; + return DDS_RETCODE_OK; +} - do { - dds_participant *p; - topic = DDS_RETCODE_PRECONDITION_NOT_MET; - if ((ret = dds_participant_lock (participant, &p)) == DDS_RETCODE_OK) - { - ddsrt_avl_iter_t it; - for (dds_entity *e = ddsrt_avl_iter_first (&dds_entity_children_td, &p->m_entity.m_children, &it); e != NULL; e = ddsrt_avl_iter_next (&it)) - { - if (dds_entity_kind (e) == DDS_KIND_TOPIC && strcmp (((dds_topic *) e)->m_stopic->name, name) == 0) - { - topic = e->m_hdllink.hdl; - break; - } - } - dds_participant_unlock (p); - } - } while (topic > 0 && !dds_find_topic_check_and_add_ref (participant, topic, name)); +void dds_topic_unpin (struct dds_topic *tp) +{ + dds_entity_unpin (&tp->m_entity); +} - dds_entity_unpin (pe); - return topic; +void dds_topic_defer_set_qos (struct dds_topic *tp) +{ + struct dds_ktopic * const ktp = tp->m_ktopic; + struct dds_participant * const pp = dds_entity_participant (&tp->m_entity); + ddsrt_mutex_lock (&pp->m_entity.m_mutex); + ++ktp->defer_set_qos; + ddsrt_mutex_unlock (&pp->m_entity.m_mutex); +} + +void dds_topic_allow_set_qos (struct dds_topic *tp) +{ + struct dds_ktopic * const ktp = tp->m_ktopic; + struct dds_participant * const pp = dds_entity_participant (&tp->m_entity); + ddsrt_mutex_lock (&pp->m_entity.m_mutex); + assert (ktp->defer_set_qos > 0); + if (--ktp->defer_set_qos == 0) + ddsrt_cond_broadcast (&pp->m_entity.m_cond); + ddsrt_mutex_unlock (&pp->m_entity.m_mutex); } static dds_return_t dds_topic_delete (dds_entity *e) ddsrt_nonnull_all; static dds_return_t dds_topic_delete (dds_entity *e) { - dds_topic *tp = (dds_topic *) e; - dds_domain *domain = tp->m_entity.m_domain; - ddsrt_avl_dpath_t dp; - struct topic_sertopic_node *stn; - - ddsrt_mutex_lock (&dds_global.m_mutex); - - stn = ddsrt_avl_lookup_dpath (&dds_topictree_def, &domain->m_topics, tp->m_stopic, &dp); - assert (stn != NULL); - if (--stn->refc == 0) - { - ddsrt_avl_delete_dpath (&dds_topictree_def, &domain->m_topics, stn, &dp); - ddsrt_free (stn); - } - + struct dds_topic * const tp = (dds_topic *) e; + struct dds_ktopic * const ktp = tp->m_ktopic; + assert (dds_entity_kind (e->m_parent) == DDS_KIND_PARTICIPANT); + dds_participant * const pp = (dds_participant *) e->m_parent; ddsi_sertopic_unref (tp->m_stopic); - ddsrt_mutex_unlock (&dds_global.m_mutex); + + ddsrt_mutex_lock (&pp->m_entity.m_mutex); + if (--ktp->refc == 0) + { + ddsrt_avl_delete (&participant_ktopics_treedef, &pp->m_ktopics, ktp); + dds_delete_qos (ktp->qos); + ddsrt_free (ktp->name); + ddsrt_free (ktp->type_name); + dds_free (ktp); + } + ddsrt_mutex_unlock (&pp->m_entity.m_mutex); return DDS_RETCODE_OK; } static dds_return_t dds_topic_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) { - /* note: e->m_qos is still the old one to allow for failure here */ + /* We never actually set the qos of a struct dds_topic and really shouldn't be here, + but the code to check whether set_qos is supported uses the entity's qos_set + function as a proxy. One of the weird things about the topic's set_qos is that + this is called with e == NULL. */ (void) e; (void) qos; (void) enabled; + assert (e == NULL); return DDS_RETCODE_OK; } -static bool dupdef_qos_ok (const dds_qos_t *qos, const dds_topic *tp) +static bool dupdef_qos_ok (const dds_qos_t *qos, const dds_ktopic *ktp) { - if ((qos == NULL) != (tp->m_entity.m_qos == NULL)) + if ((qos == NULL) != (ktp->qos == NULL)) return false; else if (qos == NULL) return true; else - return dds_qos_equal (tp->m_entity.m_qos, qos); -} - -static bool sertopic_equivalent (const struct ddsi_sertopic *a, const struct ddsi_sertopic *b) -{ - if (strcmp (a->name_type_name, b->name_type_name) != 0) - return false; - if (a->serdata_basehash != b->serdata_basehash) - return false; - if (a->ops != b->ops) - return false; - if (a->serdata_ops != b->serdata_ops) - return false; - return true; -} - -static dds_return_t create_topic_topic_arbitrary_check_sertopic (dds_entity_t participant, dds_entity_t topic, struct ddsi_sertopic *sertopic, const dds_qos_t *qos) -{ - dds_topic *tp; - dds_return_t ret; - - if (dds_topic_lock (topic, &tp) < 0) - return DDS_RETCODE_NOT_FOUND; - - if (dds_entity_participant (&tp->m_entity)->m_entity.m_hdllink.hdl != participant) - ret = DDS_RETCODE_NOT_FOUND; - else if (!sertopic_equivalent (tp->m_stopic, sertopic)) - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - else if (!dupdef_qos_ok (qos, tp)) - ret = DDS_RETCODE_INCONSISTENT_POLICY; - else - { - /* See dds_find_topic_check_and_add_ref */ - ret = DDS_RETCODE_OK; - } - dds_topic_unlock (tp); - return ret; + return dds_qos_equal (ktp->qos, qos); } const struct dds_entity_deriver dds_entity_deriver_topic = { @@ -280,31 +195,110 @@ const struct dds_entity_deriver dds_entity_deriver_topic = { .validate_status = dds_topic_status_validate }; +/** +* @brief Checks whether a ktopic with the same name exists in the participant, +* and if so, whether it's QoS matches or not. +* +* The set of ktopics is stored in the participant, protected by the participant's +* mutex and the internal state of these ktopics (including the QoS) is also +* protected by that mutex. +* +* @param[out] ktp_out matching ktopic if call was successful, or NULL if no +* ktopic with this name exists +* @param[in] pp pinned & locked participant +* @param[in] name topic name to look for +* @param[in] type_name type name the topic must have +* @param[in] new_qos QoS for the new topic (can be NULL) +* +* @returns success + ktopic, success + NULL or error. +* +* @retval DDS_RETCODE_OK +* ktp_out is either NULL (first attempt at creating this topic), or +* the matching ktopic entity +* @retval DDS_RETCODE_INCONSISTENT_POLICY +* a ktopic exists with differing QoS +* @retval DDS_RETCODE_PRECONDITION_NOT_MET +* a ktopic exists with a different type name +*/ +static dds_return_t lookup_and_check_ktopic (struct dds_ktopic **ktp_out, dds_participant *pp, const char *name, const char *type_name, const dds_qos_t *new_qos) +{ + struct q_globals * const gv = &pp->m_entity.m_domain->gv; + struct dds_ktopic *ktp; + if ((ktp = *ktp_out = ddsrt_avl_lookup (&participant_ktopics_treedef, &pp->m_ktopics, name)) == NULL) + { + GVTRACE ("lookup_and_check_ktopic_may_unlock_pp: no such ktopic\n"); + return DDS_RETCODE_OK; + } + else if (strcmp (ktp->type_name, type_name) != 0) + { + GVTRACE ("lookup_and_check_ktopic_may_unlock_pp: ktp %p typename %s mismatch\n", (void *) ktp, ktp->type_name); + return DDS_RETCODE_PRECONDITION_NOT_MET; + } + else if (!dupdef_qos_ok (new_qos, ktp)) + { + GVTRACE ("lookup_and_check_ktopic_may_unlock_pp: ktp %p qos mismatch\n", (void *) ktp); + return DDS_RETCODE_INCONSISTENT_POLICY; + } + else + { + GVTRACE ("lookup_and_check_ktopic_may_unlock_pp: ktp %p reuse\n", (void *) ktp); + return DDS_RETCODE_OK; + } +} + +static dds_entity_t create_topic_pp_locked (struct dds_participant *pp, struct dds_ktopic *ktp, bool implicit, struct ddsi_sertopic *sertopic_registered, const dds_listener_t *listener, const nn_plist_t *sedp_plist) +{ + dds_entity_t hdl; + dds_topic *tp = dds_alloc (sizeof (*tp)); + hdl = dds_entity_init (&tp->m_entity, &pp->m_entity, DDS_KIND_TOPIC, implicit, NULL, listener, DDS_TOPIC_STATUS_MASK); + tp->m_entity.m_iid = ddsi_iid_gen (); + dds_entity_register_child (&pp->m_entity, &tp->m_entity); + tp->m_ktopic = ktp; + tp->m_stopic = sertopic_registered; + + /* Publish Topic */ + if (sedp_plist) + { + struct participant *ddsi_pp; + nn_plist_t plist; + + thread_state_awake (lookup_thread_state (), &pp->m_entity.m_domain->gv); + ddsi_pp = entidx_lookup_participant_guid (pp->m_entity.m_domain->gv.entity_index, &pp->m_entity.m_guid); + assert (ddsi_pp); + + nn_plist_init_empty (&plist); + nn_plist_mergein_missing (&plist, sedp_plist, ~(uint64_t)0, ~(uint64_t)0); + nn_xqos_mergein_missing (&plist.qos, ktp->qos, ~(uint64_t)0); + sedp_write_topic (ddsi_pp, &plist); + nn_plist_fini (&plist); + thread_state_asleep (lookup_thread_state ()); + } + + dds_entity_init_complete (&tp->m_entity); + return hdl; +} + dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_sertopic *sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const nn_plist_t *sedp_plist) { dds_return_t rc; - dds_participant *par; - dds_entity *par_ent; - dds_topic *top; + dds_participant *pp; dds_qos_t *new_qos = NULL; dds_entity_t hdl; - struct participant *ddsi_pp; + struct ddsi_sertopic *sertopic_registered; if (sertopic == NULL) return DDS_RETCODE_BAD_PARAMETER; - /* Claim participant handle so we can be sure the handle will not be - reused if we temporarily unlock the participant to check the an - existing topic's compatibility */ - if ((rc = dds_entity_pin (participant, &par_ent)) < 0) - return rc; - /* Verify that we've been given a participant, not strictly necessary - because dds_participant_lock below checks it, but this is more - obvious */ - if (dds_entity_kind (par_ent) != DDS_KIND_PARTICIPANT) { - dds_entity_unpin (par_ent); - return DDS_RETCODE_ILLEGAL_OPERATION; + dds_entity *par_ent; + if ((rc = dds_entity_pin (participant, &par_ent)) < 0) + return rc; + if (dds_entity_kind (par_ent) != DDS_KIND_PARTICIPANT) + { + dds_entity_unpin (par_ent); + return DDS_RETCODE_ILLEGAL_OPERATION; + } + pp = (struct dds_participant *) par_ent; } new_qos = dds_create_qos (); @@ -314,155 +308,76 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s * * nn_xqos_mergein_missing (new_qos, &gv.default_xqos_tp, ~(uint64_t)0); * - * but the crazy defaults of the DDS specification has a default settings - * for reliability that are dependent on the entity type: readers and + * but the crazy defaults of the DDS specification has a default setting + * for reliability that is dependent on the entity type: readers and * topics default to best-effort, but writers to reliable. * * Leaving the topic QoS sparse means a default-default topic QoS of * best-effort will do "the right thing" and let a writer still default to * reliable ... (and keep behaviour unchanged) */ - if ((rc = nn_xqos_valid (&par_ent->m_domain->gv.logconfig, new_qos)) != DDS_RETCODE_OK) - goto err_invalid_qos; - - /* FIXME: just mutex_lock ought to be good enough, but there is the - pesky "closed" check still ... */ - if ((rc = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK) - goto err_lock_participant; - - bool retry_lookup; - do { - dds_entity_t topic; - - /* claim participant handle to guarantee the handle remains valid after - unlocking the participant prior to verifying the found topic still - exists */ - topic = DDS_RETCODE_PRECONDITION_NOT_MET; - ddsrt_avl_iter_t it; - for (dds_entity *e = ddsrt_avl_iter_first (&dds_entity_children_td, &par->m_entity.m_children, &it); e != NULL; e = ddsrt_avl_iter_next (&it)) - { - if (dds_entity_kind (e) == DDS_KIND_TOPIC && strcmp (((dds_topic *) e)->m_stopic->name, sertopic->name) == 0) - { - topic = e->m_hdllink.hdl; - break; - } - } - if (topic < 0) - { - /* no topic with the name exists; we have locked the participant, and - so we can proceed with creating the topic */ - retry_lookup = false; - } - else - { - /* some topic with the same name exists; need to lock the topic to - perform the checks, but locking the topic while holding the - participant lock violates the lock order (child -> parent). So - unlock that participant and check the topic while accounting - for the various scary cases. */ - dds_participant_unlock (par); - - rc = create_topic_topic_arbitrary_check_sertopic (participant, topic, sertopic, new_qos); - switch (rc) - { - case DDS_RETCODE_OK: /* duplicate definition */ - dds_entity_unpin (par_ent); - dds_delete_qos (new_qos); - return topic; - - case DDS_RETCODE_NOT_FOUND: - /* either participant is now being deleted, topic was deleted, or - topic was deleted & the handle reused for something else -- so */ - retry_lookup = true; - break; - - case DDS_RETCODE_PRECONDITION_NOT_MET: /* incompatible sertopic */ - case DDS_RETCODE_INCONSISTENT_POLICY: /* different QoS */ - /* inconsistent definition */ - dds_entity_unpin (par_ent); - dds_delete_qos (new_qos); - return rc; - - default: - abort (); - } - - if ((rc = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK) - goto err_lock_participant; - } - } while (retry_lookup); - - /* FIXME: make this a function - Add sertopic to domain -- but note that it may have been created by another thread - on another participant that is attached to the same domain */ + struct q_globals * const gv = &pp->m_entity.m_domain->gv; + if ((rc = nn_xqos_valid (&gv->logconfig, new_qos)) != DDS_RETCODE_OK) { - struct dds_domain *domain = par->m_entity.m_domain; - - ddsrt_avl_ipath_t ip; - struct topic_sertopic_node *stn; - - ddsrt_mutex_lock (&dds_global.m_mutex); - - stn = ddsrt_avl_lookup_ipath (&dds_topictree_def, &domain->m_topics, sertopic, &ip); - if (stn == NULL) - { - /* no existing definition: use new */ - stn = ddsrt_malloc (sizeof (*stn)); - stn->refc = 1; - stn->st = ddsi_sertopic_ref (sertopic); - ddsrt_avl_insert (&dds_topictree_def, &domain->m_topics, stn); - ddsrt_mutex_unlock (&dds_global.m_mutex); - } - else if (sertopic_equivalent (stn->st, sertopic)) - { - /* ok -- same definition, so use existing one instead */ - sertopic = ddsi_sertopic_ref (stn->st); - stn->refc++; - ddsrt_mutex_unlock (&dds_global.m_mutex); - } - else - { - /* bummer, delete */ - ddsrt_mutex_unlock (&dds_global.m_mutex); - rc = DDS_RETCODE_PRECONDITION_NOT_MET; - goto err_sertopic_reuse; - } + dds_delete_qos (new_qos); + dds_entity_unpin (&pp->m_entity); + return rc; } - /* Create topic */ - top = dds_alloc (sizeof (*top)); + /* See if we're allowed to create the topic; ktp is returned pinned & locked + so we can be sure it doesn't disappear and its QoS can't change */ + GVTRACE ("dds_create_topic_arbitrary (pp %p "PGUIDFMT" sertopic %p reg?%s refc %"PRIu32" %s/%s)\n", + (void *) pp, PGUID (pp->m_entity.m_guid), (void *) sertopic, sertopic->gv ? "yes" : "no", + ddsrt_atomic_ld32 (&sertopic->refc), sertopic->name, sertopic->type_name); + ddsrt_mutex_lock (&pp->m_entity.m_mutex); + struct dds_ktopic *ktp; + if ((rc = lookup_and_check_ktopic (&ktp, pp, sertopic->name, sertopic->type_name, new_qos)) != DDS_RETCODE_OK) + { + GVTRACE ("dds_create_topic_arbitrary: failed after compatibility check: %s\n", dds_strretcode (rc)); + dds_participant_unlock (pp); + dds_delete_qos (new_qos); + return rc; + } + + /* Create a ktopic if it doesn't exist yet, else reference existing one and delete the + unneeded "new_qos". */ + if (ktp == NULL) + { + ktp = dds_alloc (sizeof (*ktp)); + ktp->refc = 1; + ktp->defer_set_qos = 0; + ktp->qos = new_qos; + /* have to copy these because the ktopic can outlast any specific sertopic */ + ktp->name = ddsrt_strdup (sertopic->name); + ktp->type_name = ddsrt_strdup (sertopic->type_name); + ddsrt_avl_insert (&participant_ktopics_treedef, &pp->m_ktopics, ktp); + GVTRACE ("create_and_lock_ktopic: ktp %p\n", (void *) ktp); + } + else + { + ktp->refc++; + dds_delete_qos (new_qos); + } + + /* Sertopic: re-use a previously registered one if possible, else register this one */ + { + ddsrt_mutex_lock (&gv->sertopics_lock); + if ((sertopic_registered = ddsi_sertopic_lookup_locked (gv, sertopic)) != NULL) + GVTRACE ("dds_create_topic_arbitrary: reuse sertopic %p\n", (void *) sertopic_registered); + else + { + GVTRACE ("dds_create_topic_arbitrary: register new sertopic %p\n", (void *) sertopic); + ddsi_sertopic_register_locked (gv, sertopic); + sertopic_registered = sertopic; + } + ddsrt_mutex_unlock (&gv->sertopics_lock); + } + + /* Create topic referencing ktopic & sertopic_registered */ /* 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; - - /* Publish Topic */ - thread_state_awake (lookup_thread_state (), &par->m_entity.m_domain->gv); - ddsi_pp = entidx_lookup_participant_guid (par->m_entity.m_domain->gv.entity_index, &par->m_entity.m_guid); - assert (ddsi_pp); - if (sedp_plist) - { - nn_plist_t plist; - nn_plist_init_empty (&plist); - nn_plist_mergein_missing (&plist, sedp_plist, ~(uint64_t)0, ~(uint64_t)0); - nn_xqos_mergein_missing (&plist.qos, new_qos, ~(uint64_t)0); - sedp_write_topic (ddsi_pp, &plist); - nn_plist_fini (&plist); - } - thread_state_asleep (lookup_thread_state ()); - - dds_entity_init_complete (&top->m_entity); - dds_participant_unlock (par); - dds_entity_unpin (par_ent); + hdl = create_topic_pp_locked (pp, ktp, (sertopic_registered->ops == &ddsi_sertopic_ops_builtintopic), sertopic_registered, listener, sedp_plist); + dds_participant_unlock (pp); + GVTRACE ("dds_create_topic_arbitrary: new topic %"PRId32"\n", hdl); return hdl; - -err_sertopic_reuse: - dds_participant_unlock (par); -err_lock_participant: -err_invalid_qos: - dds_delete_qos (new_qos); - dds_entity_unpin (par_ent); - return rc; } dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descriptor_t *desc, const char *name, const dds_qos_t *qos, const dds_listener_t *listener) @@ -482,7 +397,6 @@ dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descrip st = dds_alloc (sizeof (*st)); ddsi_sertopic_init (&st->c, name, desc->m_typename, &ddsi_sertopic_ops_default, desc->m_nkeys ? &ddsi_serdata_ops_cdr : &ddsi_serdata_ops_cdr_nokey, (desc->m_nkeys == 0)); - st->gv = &ppent->m_domain->gv; st->native_encoding_identifier = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE); st->serpool = ppent->m_domain->gv.serpool; st->type = (void*) desc; @@ -522,6 +436,47 @@ dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descrip return hdl; } +dds_entity_t dds_find_topic (dds_entity_t participant, const char *name) +{ + dds_participant *pp; + dds_return_t rc; + + if (name == NULL) + return DDS_RETCODE_BAD_PARAMETER; + + if ((rc = dds_participant_lock (participant, &pp)) < 0) + return rc; + + ddsrt_avl_iter_t it; + for (dds_entity *e = ddsrt_avl_iter_first (&dds_entity_children_td, &pp->m_entity.m_children, &it); e != NULL; e = ddsrt_avl_iter_next (&it)) + { + if (dds_entity_kind (e) != DDS_KIND_TOPIC) + continue; + + struct dds_entity *x; + if (dds_entity_pin (e->m_hdllink.hdl, &x) != DDS_RETCODE_OK) + continue; + + struct dds_topic * const tp = (struct dds_topic *) e; + if (x != e || strcmp (tp->m_ktopic->name, name) != 0) + { + dds_entity_unpin (x); + continue; + } + + struct ddsi_sertopic * const sertopic = ddsi_sertopic_ref (tp->m_stopic); + struct dds_ktopic * const ktp = tp->m_ktopic; + ktp->refc++; + dds_entity_unpin (x); + + dds_entity_t hdl = create_topic_pp_locked (pp, ktp, false, sertopic, NULL, NULL); + dds_participant_unlock (pp); + return hdl; + } + dds_participant_unlock (pp); + return DDS_RETCODE_PRECONDITION_NOT_MET; +} + static bool dds_topic_chaining_filter (const void *sample, void *ctx) { dds_topic_filter_fn realf = (dds_topic_filter_fn) ctx; @@ -594,10 +549,10 @@ dds_return_t dds_get_name (dds_entity_t topic, char *name, size_t size) if (size <= 0 || name == NULL) return DDS_RETCODE_BAD_PARAMETER; name[0] = '\0'; - if ((ret = dds_topic_lock (topic, &t)) != DDS_RETCODE_OK) + if ((ret = dds_topic_pin (topic, &t)) != DDS_RETCODE_OK) return ret; (void) snprintf (name, size, "%s", t->m_stopic->name); - dds_topic_unlock (t); + dds_topic_unpin (t); return DDS_RETCODE_OK; } @@ -608,10 +563,10 @@ dds_return_t dds_get_type_name (dds_entity_t topic, char *name, size_t size) if (size <= 0 || name == NULL) return DDS_RETCODE_BAD_PARAMETER; name[0] = '\0'; - if ((ret = dds_topic_lock (topic, &t)) != DDS_RETCODE_OK) + if ((ret = dds_topic_pin (topic, &t)) != DDS_RETCODE_OK) return ret; (void) snprintf (name, size, "%s", t->m_stopic->type_name); - dds_topic_unlock (t); + dds_topic_unpin (t); return DDS_RETCODE_OK; } diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 163d4e1..7c5040b 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -263,13 +263,11 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit { dds_return_t rc; dds_qos_t *wqos; - dds_writer *wr; - dds_entity_t writer; dds_publisher *pub = NULL; - dds_participant *pp; dds_topic *tp; dds_entity_t publisher; struct whc_writer_info *wrinfo; + bool created_implicit_pub = false; { dds_entity *p_or_p; @@ -286,6 +284,7 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit dds_entity_unlock (p_or_p); if ((rc = dds_publisher_lock (publisher, &pub)) < 0) return rc; + created_implicit_pub = true; break; default: dds_entity_unlock (p_or_p); @@ -295,25 +294,33 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit ddsi_tran_conn_t conn = pub->m_entity.m_domain->gv.data_conn_uc; - if ((rc = dds_topic_lock (topic, &tp)) != DDS_RETCODE_OK) - goto err_tp_lock; + if ((rc = dds_topic_pin (topic, &tp)) != DDS_RETCODE_OK) + goto err_pin_topic; assert (tp->m_stopic); - - pp = dds_entity_participant (&pub->m_entity); - if (pp != dds_entity_participant (&tp->m_entity)) + if (dds_entity_participant (&pub->m_entity) != dds_entity_participant (&tp->m_entity)) { rc = DDS_RETCODE_BAD_PARAMETER; goto err_pp_mismatch; } + /* Prevent set_qos on the topic until writer has been created and registered: we can't + allow a TOPIC_DATA change to ccur before the writer has been created because that + change would then not be published in the discovery/built-in topics. + + Don't keep the participant (which protects the topic's QoS) locked because that + can cause deadlocks for applications creating a reader/writer from within a + publication matched listener (whether the restrictions on what one can do in + listeners are reasonable or not, it used to work so it can be broken arbitrarily). */ + dds_topic_defer_set_qos (tp); + /* Merge Topic & Publisher qos */ wqos = dds_create_qos (); if (qos) nn_xqos_mergein_missing (wqos, qos, DDS_WRITER_QOS_MASK); if (pub->m_entity.m_qos) nn_xqos_mergein_missing (wqos, pub->m_entity.m_qos, ~(uint64_t)0); - if (tp->m_entity.m_qos) - nn_xqos_mergein_missing (wqos, tp->m_entity.m_qos, ~(uint64_t)0); + if (tp->m_ktopic->qos) + nn_xqos_mergein_missing (wqos, tp->m_ktopic->qos, ~(uint64_t)0); nn_xqos_mergein_missing (wqos, &pub->m_entity.m_domain->gv.default_xqos_wr, ~(uint64_t)0); if ((rc = nn_xqos_valid (&pub->m_entity.m_domain->gv.logconfig, wqos)) < 0 || @@ -324,9 +331,8 @@ 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, false, wqos, listener, DDS_WRITER_STATUS_MASK); - + struct dds_writer * const wr = dds_alloc (sizeof (*wr)); + const dds_entity_t 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); wr->m_xp = nn_xpack_new (conn, get_bandwidth_limit (wqos->transport_priority), pub->m_entity.m_domain->gv.config.xpack_send_async); @@ -336,7 +342,7 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit wr->whc_batch = pub->m_entity.m_domain->gv.config.whc_batch; thread_state_awake (lookup_thread_state (), &pub->m_entity.m_domain->gv); - rc = new_writer (&wr->m_wr, &wr->m_entity.m_domain->gv, &wr->m_entity.m_guid, NULL, &pp->m_entity.m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); + rc = new_writer (&wr->m_wr, &wr->m_entity.m_domain->gv, &wr->m_entity.m_guid, NULL, dds_entity_participant_guid (&pub->m_entity), tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); assert(rc == DDS_RETCODE_OK); thread_state_asleep (lookup_thread_state ()); @@ -344,16 +350,19 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit dds_entity_register_child (&pub->m_entity, &wr->m_entity); dds_entity_init_complete (&wr->m_entity); - dds_topic_unlock (tp); + + dds_topic_allow_set_qos (tp); + dds_topic_unpin (tp); dds_publisher_unlock (pub); return writer; err_bad_qos: + dds_topic_allow_set_qos (tp); err_pp_mismatch: - dds_topic_unlock (tp); -err_tp_lock: + dds_topic_unpin (tp); +err_pin_topic: dds_publisher_unlock (pub); - if ((pub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0) + if (created_implicit_pub) (void) dds_delete (publisher); return rc; } diff --git a/src/core/ddsc/tests/topic.c b/src/core/ddsc/tests/topic.c index d71c8d5..0142a4d 100644 --- a/src/core/ddsc/tests/topic.c +++ b/src/core/ddsc/tests/topic.c @@ -130,8 +130,12 @@ CU_Test(ddsc_topic_create, duplicate, .init=ddsc_topic_init, .fini=ddsc_topic_fi /* Creating the same topic should succeed. */ topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, g_topicRtmDataTypeName, NULL, NULL); CU_ASSERT_FATAL(topic > 0); + CU_ASSERT_FATAL(topic != g_topicRtmDataType); ret = dds_delete(topic); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + /* Old topic entity should remain in existence */ + ret = dds_get_parent(g_topicRtmDataType); + CU_ASSERT(ret > 0); } /*************************************************************************************************/ @@ -201,7 +205,7 @@ CU_Test(ddsc_topic_find, valid, .init=ddsc_topic_init, .fini=ddsc_topic_fini) dds_return_t ret; topic = dds_find_topic(g_participant, g_topicRtmDataTypeName); - CU_ASSERT_EQUAL_FATAL(topic, g_topicRtmDataType); + CU_ASSERT_NOT_EQUAL_FATAL(topic, g_topicRtmDataType); ret = dds_delete(topic); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h index 4d9b64b..0074141 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h @@ -132,6 +132,8 @@ typedef bool (*ddsi_serdata_eqkey_t) (const struct ddsi_serdata *a, const struct returning bufsize-1) if it had to truncate) */ typedef size_t (*ddsi_serdata_print_t) (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, char *buf, size_t size); +#define DDSI_SERDATA_HAS_FROM_SER_IOV 1 + struct ddsi_serdata_ops { ddsi_serdata_eqkey_t eqkey; ddsi_serdata_size_t get_size; diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h index 4aa7f7b..ae582ff 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -107,7 +107,6 @@ struct ddsi_sertopic_default { struct ddsi_sertopic c; uint16_t native_encoding_identifier; /* (PL_)?CDR_(LE|BE) */ struct serdatapool *serpool; - struct q_globals *gv; struct dds_topic_descriptor * type; unsigned nkeys; diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h index e23333c..1085ddd 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h @@ -23,17 +23,18 @@ extern "C" { struct ddsi_serdata; struct ddsi_serdata_ops; struct ddsi_sertopic_ops; +struct q_globals; struct ddsi_sertopic { const struct ddsi_sertopic_ops *ops; const struct ddsi_serdata_ops *serdata_ops; uint32_t serdata_basehash; bool topickind_no_key; - char *name_type_name; char *name; char *type_name; uint64_t iid; - ddsrt_atomic_uint32_t refc; /* counts refs from entities, not from data */ + struct q_globals *gv; + ddsrt_atomic_uint32_t refc; /* counts refs from entities (topic, reader, writer), not from data */ }; /* The old and the new happen to have the same memory layout on a 64-bit machine @@ -48,6 +49,27 @@ struct ddsi_sertopic { binary compatible. */ #define DDSI_SERTOPIC_HAS_TOPICKIND_NO_KEY 1 +/* Type changed: name_type_name and ii removed and gv added; and the set of + operations got extended by the a predicate for testing to sertopics (with the + same "ops") for equality ("equal") as well as a function for hashing the + non-generic part of the sertopic definition (via "hash"). These two operations + make it possible to intern sertopics without duplicates, which has become + relevant now that multiple ddsi_sertopics can be associated with a single topic + name. + + Testing for DDSI_SERTOPIC_HAS_EQUAL_AND_HASH allows one to have a single source + that can handle both variants, but there's no binary compatbility. */ +#define DDSI_SERTOPIC_HAS_EQUAL_AND_HASH 1 + +/* Called to compare two sertopics for equality, if it is already known that name, + type name, topickind_no_Key, and operations are all the same. (serdata_basehash + is computed from the set of operations.) */ +typedef bool (*ddsi_sertopic_equal_t) (const struct ddsi_sertopic *a, const struct ddsi_sertopic *b); + +/* Hash the custom components of a sertopic (this XOR'd with a hash computed from + the fields that are defined in struct ddsi_sertopic) */ +typedef uint32_t (*ddsi_sertopic_hash_t) (const struct ddsi_sertopic *tp); + /* Called when the refcount dropped to zero */ typedef void (*ddsi_sertopic_free_t) (struct ddsi_sertopic *tp); @@ -66,15 +88,22 @@ struct ddsi_sertopic_ops { ddsi_sertopic_zero_samples_t zero_samples; ddsi_sertopic_realloc_samples_t realloc_samples; ddsi_sertopic_free_samples_t free_samples; + ddsi_sertopic_equal_t equal; + ddsi_sertopic_hash_t hash; }; +struct ddsi_sertopic *ddsi_sertopic_lookup_locked (struct q_globals *gv, const struct ddsi_sertopic *sertopic_template); +void ddsi_sertopic_register_locked (struct q_globals *gv, struct ddsi_sertopic *sertopic); + DDS_EXPORT void ddsi_sertopic_init (struct ddsi_sertopic *tp, const char *name, const char *type_name, const struct ddsi_sertopic_ops *sertopic_ops, const struct ddsi_serdata_ops *serdata_ops, bool topickind_no_key); -DDS_EXPORT void ddsi_sertopic_init_anon (struct ddsi_sertopic *tp, const struct ddsi_sertopic_ops *sertopic_ops, const struct ddsi_serdata_ops *serdata_ops, bool topickind_no_key); DDS_EXPORT void ddsi_sertopic_fini (struct ddsi_sertopic *tp); DDS_EXPORT struct ddsi_sertopic *ddsi_sertopic_ref (const struct ddsi_sertopic *tp); DDS_EXPORT void ddsi_sertopic_unref (struct ddsi_sertopic *tp); DDS_EXPORT uint32_t ddsi_sertopic_compute_serdata_basehash (const struct ddsi_serdata_ops *ops); +DDS_EXPORT bool ddsi_sertopic_equal (const struct ddsi_sertopic *a, const struct ddsi_sertopic *b); +DDS_EXPORT uint32_t ddsi_sertopic_hash (const struct ddsi_sertopic *tp); + DDS_EXPORT inline void ddsi_sertopic_free (struct ddsi_sertopic *tp) { tp->ops->free (tp); } diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/q_globals.h index 12f5bb0..954867e 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/q_globals.h @@ -290,6 +290,9 @@ struct q_globals { struct ddsi_builtin_topic_interface *builtin_topic_interface; struct nn_group_membership *mship; + + ddsrt_mutex_t sertopics_lock; + struct ddsrt_hh *sertopics; }; #if defined (__cplusplus) diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index a2f842e..a33d3c1 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -17,6 +17,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" #include "dds/ddsrt/md5.h" +#include "dds/ddsrt/mh3.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" @@ -117,59 +118,10 @@ static void serdata_default_append_blob (struct ddsi_serdata_default **d, size_t memcpy (p, data, sz); } -/* Fixed seed and length */ - -#define DDS_MH3_LEN 16 -#define DDS_MH3_SEED 0 - -#define DDS_MH3_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) - -/* Really - http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp, - MurmurHash3_x86_32 - */ - -static uint32_t dds_mh3 (const void * key) -{ - const uint8_t *data = (const uint8_t *) key; - const intptr_t nblocks = (intptr_t) (DDS_MH3_LEN / 4); - const uint32_t c1 = 0xcc9e2d51; - const uint32_t c2 = 0x1b873593; - - uint32_t h1 = DDS_MH3_SEED; - - const uint32_t *blocks = (const uint32_t *) (data + nblocks * 4); - register intptr_t i; - - for (i = -nblocks; i; i++) - { - uint32_t k1 = blocks[i]; - - k1 *= c1; - k1 = DDS_MH3_ROTL32 (k1, 15); - k1 *= c2; - - h1 ^= k1; - h1 = DDS_MH3_ROTL32 (h1, 13); - h1 = h1 * 5+0xe6546b64; - } - - /* finalization */ - - h1 ^= DDS_MH3_LEN; - h1 ^= h1 >> 16; - h1 *= 0x85ebca6b; - h1 ^= h1 >> 13; - h1 *= 0xc2b2ae35; - h1 ^= h1 >> 16; - - return h1; -} - static struct ddsi_serdata *fix_serdata_default(struct ddsi_serdata_default *d, uint32_t basehash) { if (d->keyhash.m_iskey) - d->c.hash = dds_mh3 (d->keyhash.m_hash) ^ basehash; + d->c.hash = ddsrt_mh3 (d->keyhash.m_hash, 16, 0) ^ basehash; else d->c.hash = *((uint32_t *)d->keyhash.m_hash) ^ basehash; return &d->c; @@ -651,8 +603,8 @@ static size_t serdata_default_print_plist (const struct ddsi_sertopic *sertopic_ src.buf = (const unsigned char *) d->data; src.bufsz = d->pos; src.encoding = d->hdr.identifier; - src.factory = tp->gv->m_factory; - src.logconfig = &tp->gv->logconfig; + src.factory = tp->c.gv->m_factory; + src.logconfig = &tp->c.gv->logconfig; src.protocol_version.major = RTPS_MAJOR; src.protocol_version.minor = RTPS_MINOR; src.strict = false; diff --git a/src/core/ddsi/src/ddsi_sertopic.c b/src/core/ddsi/src/ddsi_sertopic.c index 968a1de..4dda872 100644 --- a/src/core/ddsi/src/ddsi_sertopic.c +++ b/src/core/ddsi/src/ddsi_sertopic.c @@ -16,6 +16,8 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/md5.h" +#include "dds/ddsrt/mh3.h" +#include "dds/ddsrt/hopscotch.h" #include "dds/ddsrt/string.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" @@ -23,21 +25,82 @@ #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/ddsi_serdata.h" +#include "dds/ddsi/q_globals.h" + +bool ddsi_sertopic_equal (const struct ddsi_sertopic *a, const struct ddsi_sertopic *b) +{ + if (strcmp (a->name, b->name) != 0) + return false; + if (strcmp (a->type_name, b->type_name) != 0) + return false; + if (a->serdata_basehash != b->serdata_basehash) + return false; + if (a->ops != b->ops) + return false; + if (a->serdata_ops != b->serdata_ops) + return false; + return a->ops->equal (a, b); +} + +uint32_t ddsi_sertopic_hash (const struct ddsi_sertopic *a) +{ + uint32_t h; + h = ddsrt_mh3 (a->name, strlen (a->name), a->serdata_basehash); + h = ddsrt_mh3 (a->type_name, strlen (a->type_name), h); + return h ^ a->ops->hash (a); +} struct ddsi_sertopic *ddsi_sertopic_ref (const struct ddsi_sertopic *sertopic_const) { - struct ddsi_sertopic *sertopic = (struct ddsi_sertopic *)sertopic_const; + struct ddsi_sertopic *sertopic = (struct ddsi_sertopic *) sertopic_const; if (sertopic) ddsrt_atomic_inc32 (&sertopic->refc); return sertopic; } +struct ddsi_sertopic *ddsi_sertopic_lookup_locked (struct q_globals *gv, const struct ddsi_sertopic *sertopic_template) +{ + struct ddsi_sertopic *sertopic = ddsrt_hh_lookup (gv->sertopics, sertopic_template); +#ifndef NDEBUG + if (sertopic != NULL) + { + assert (sertopic->gv != NULL); + assert (sertopic->iid != 0); + } +#endif + return ddsi_sertopic_ref (sertopic); +} + +void ddsi_sertopic_register_locked (struct q_globals *gv, struct ddsi_sertopic *sertopic) +{ + assert (sertopic->gv == NULL); + assert (sertopic->iid == 0); + assert (ddsrt_atomic_ld32 (&sertopic->refc) == 1); + + (void) ddsi_sertopic_ref (sertopic); + sertopic->gv = gv; + sertopic->iid = ddsi_iid_gen (); + int x = ddsrt_hh_add (gv->sertopics, sertopic); + assert (x); + (void) x; +} + void ddsi_sertopic_unref (struct ddsi_sertopic *sertopic) { if (sertopic) { if (ddsrt_atomic_dec32_ov (&sertopic->refc) == 1) { + /* if registered, drop from set of registered sertopics */ + if (sertopic->gv) + { + ddsrt_mutex_lock (&sertopic->gv->sertopics_lock); + (void) ddsrt_hh_remove (sertopic->gv->sertopics, sertopic); + ddsrt_mutex_unlock (&sertopic->gv->sertopics_lock); + sertopic->gv = NULL; + sertopic->iid = 0; + } + ddsi_sertopic_free (sertopic); } } @@ -46,36 +109,21 @@ void ddsi_sertopic_unref (struct ddsi_sertopic *sertopic) void ddsi_sertopic_init (struct ddsi_sertopic *tp, const char *name, const char *type_name, const struct ddsi_sertopic_ops *sertopic_ops, const struct ddsi_serdata_ops *serdata_ops, bool topickind_no_key) { ddsrt_atomic_st32 (&tp->refc, 1); - tp->iid = ddsi_iid_gen (); tp->name = ddsrt_strdup (name); tp->type_name = ddsrt_strdup (type_name); - size_t ntn_sz = strlen (tp->name) + 1 + strlen (tp->type_name) + 1; - tp->name_type_name = ddsrt_malloc (ntn_sz); - (void) snprintf (tp->name_type_name, ntn_sz, "%s/%s", tp->name, tp->type_name); - tp->ops = sertopic_ops; - tp->serdata_ops = serdata_ops; - tp->serdata_basehash = ddsi_sertopic_compute_serdata_basehash (tp->serdata_ops); - tp->topickind_no_key = topickind_no_key; -} - -void ddsi_sertopic_init_anon (struct ddsi_sertopic *tp, const struct ddsi_sertopic_ops *sertopic_ops, const struct ddsi_serdata_ops *serdata_ops, bool topickind_no_key) -{ - ddsrt_atomic_st32 (&tp->refc, 1); - tp->iid = ddsi_iid_gen (); - tp->name = NULL; - tp->type_name = NULL; - tp->name_type_name = NULL; tp->ops = sertopic_ops; tp->serdata_ops = serdata_ops; tp->serdata_basehash = ddsi_sertopic_compute_serdata_basehash (tp->serdata_ops); tp->topickind_no_key = topickind_no_key; + /* set later, on registration */ + tp->iid = 0; + tp->gv = NULL; } void ddsi_sertopic_fini (struct ddsi_sertopic *tp) { ddsrt_free (tp->name); ddsrt_free (tp->type_name); - ddsrt_free (tp->name_type_name); } uint32_t ddsi_sertopic_compute_serdata_basehash (const struct ddsi_serdata_ops *ops) diff --git a/src/core/ddsi/src/ddsi_sertopic_default.c b/src/core/ddsi/src/ddsi_sertopic_default.c index 0fbfec6..0da5c5c 100644 --- a/src/core/ddsi/src/ddsi_sertopic_default.c +++ b/src/core/ddsi/src/ddsi_sertopic_default.c @@ -15,6 +15,7 @@ #include #include "dds/ddsrt/md5.h" +#include "dds/ddsrt/mh3.h" #include "dds/ddsrt/heap.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" @@ -22,6 +23,25 @@ #include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/ddsi_serdata_default.h" +static bool sertopic_default_equal (const struct ddsi_sertopic *acmn, const struct ddsi_sertopic *bcmn) +{ + const struct ddsi_sertopic_default *a = (struct ddsi_sertopic_default *) acmn; + const struct ddsi_sertopic_default *b = (struct ddsi_sertopic_default *) bcmn; + return a->type == b->type; +} + +static uint32_t sertopic_default_hash (const struct ddsi_sertopic *tpcmn) +{ + const struct ddsi_sertopic_default *tp = (struct ddsi_sertopic_default *) tpcmn; + if (tp->type == NULL) + return 0; + else + { + return ddsrt_mh3 (tp->type->m_keys, tp->type->m_nkeys * sizeof (*tp->type->m_keys), + ddsrt_mh3 (tp->type->m_ops, tp->type->m_nops * sizeof (*tp->type->m_ops), 0)); + } +} + static void sertopic_default_free (struct ddsi_sertopic *tp) { ddsi_sertopic_fini (tp); @@ -76,6 +96,8 @@ static void sertopic_default_free_samples (const struct ddsi_sertopic *sertopic_ } const struct ddsi_sertopic_ops ddsi_sertopic_ops_default = { + .equal = sertopic_default_equal, + .hash = sertopic_default_hash, .free = sertopic_default_free, .zero_samples = sertopic_default_zero_samples, .realloc_samples = sertopic_default_realloc_samples, diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 8e62b22..1deb503 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -767,7 +767,7 @@ static void wait_for_receive_threads (struct q_globals *gv) } } -static struct ddsi_sertopic *make_special_topic (struct q_globals *gv, struct serdatapool *serpool, uint16_t enc_id, const struct ddsi_serdata_ops *ops) +static struct ddsi_sertopic *make_special_topic (const char *name, struct serdatapool *serpool, uint16_t enc_id, const struct ddsi_serdata_ops *ops) { /* FIXME: two things (at least) - it claims there is a key, but the underlying type description is missing @@ -779,26 +779,34 @@ static struct ddsi_sertopic *make_special_topic (struct q_globals *gv, struct se (kinda natural if they stop being "default" ones) */ struct ddsi_sertopic_default *st = ddsrt_malloc (sizeof (*st)); memset (st, 0, sizeof (*st)); - ddsi_sertopic_init_anon (&st->c, &ddsi_sertopic_ops_default, ops, false); - st->gv = gv; + ddsi_sertopic_init (&st->c, name, name, &ddsi_sertopic_ops_default, ops, false); st->native_encoding_identifier = enc_id; st->serpool = serpool; st->nkeys = 1; return (struct ddsi_sertopic *) st; } -static void make_special_topics (struct q_globals *gv) -{ - gv->plist_topic = make_special_topic (gv, gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? PL_CDR_LE : PL_CDR_BE, &ddsi_serdata_ops_plist); - gv->rawcdr_topic = make_special_topic (gv, gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE, &ddsi_serdata_ops_rawcdr); -} - static void free_special_topics (struct q_globals *gv) { ddsi_sertopic_unref (gv->plist_topic); ddsi_sertopic_unref (gv->rawcdr_topic); } +static void make_special_topics (struct q_globals *gv) +{ + gv->plist_topic = make_special_topic ("plist", gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? PL_CDR_LE : PL_CDR_BE, &ddsi_serdata_ops_plist); + gv->rawcdr_topic = make_special_topic ("rawcdr", gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE, &ddsi_serdata_ops_rawcdr); + + ddsrt_mutex_lock (&gv->sertopics_lock); + ddsi_sertopic_register_locked (gv, gv->plist_topic); + ddsi_sertopic_register_locked (gv, gv->rawcdr_topic); + ddsrt_mutex_unlock (&gv->sertopics_lock); + + /* register increments refcount (which is reasonable), but at some point + one needs to get rid of that reference */ + free_special_topics (gv); +} + static bool use_multiple_receive_threads (const struct config *cfg) { /* Under some unknown circumstances Windows (at least Windows 10) exhibits @@ -909,6 +917,16 @@ fail: return -1; } +static int ddsi_sertopic_equal_wrap (const void *a, const void *b) +{ + return ddsi_sertopic_equal (a, b); +} + +static uint32_t ddsi_sertopic_hash_wrap (const void *tp) +{ + return ddsi_sertopic_hash (tp); +} + int rtps_init (struct q_globals *gv) { uint32_t port_disc_uc = 0; @@ -1078,6 +1096,8 @@ int rtps_init (struct q_globals *gv) make_builtin_endpoint_xqos (&gv->builtin_endpoint_xqos_rd, &gv->default_xqos_rd); make_builtin_endpoint_xqos (&gv->builtin_endpoint_xqos_wr, &gv->default_xqos_wr); + ddsrt_mutex_init (&gv->sertopics_lock); + gv->sertopics = ddsrt_hh_new (1, ddsi_sertopic_hash_wrap, ddsi_sertopic_equal_wrap); make_special_topics (gv); ddsrt_mutex_init (&gv->participant_set_lock); @@ -1410,6 +1430,14 @@ err_unicast_sockets: ddsrt_cond_destroy (&gv->participant_set_cond); ddsrt_mutex_destroy (&gv->participant_set_lock); free_special_topics (gv); +#ifndef NDEBUG + { + struct ddsrt_hh_iter it; + assert (ddsrt_hh_iter_first (gv->sertopics, &it) == NULL); + } +#endif + ddsrt_hh_free (gv->sertopics); + ddsrt_mutex_destroy (&gv->sertopics_lock); nn_xqos_fini (&gv->builtin_endpoint_xqos_wr); nn_xqos_fini (&gv->builtin_endpoint_xqos_rd); nn_xqos_fini (&gv->spdp_endpoint_xqos); @@ -1748,6 +1776,15 @@ void rtps_fini (struct q_globals *gv) ddsrt_cond_destroy (&gv->participant_set_cond); free_special_topics (gv); +#ifndef NDEBUG + { + struct ddsrt_hh_iter it; + assert (ddsrt_hh_iter_first (gv->sertopics, &it) == NULL); + } +#endif + ddsrt_hh_free (gv->sertopics); + ddsrt_mutex_destroy (&gv->sertopics_lock); + nn_xqos_fini (&gv->builtin_endpoint_xqos_wr); nn_xqos_fini (&gv->builtin_endpoint_xqos_rd); nn_xqos_fini (&gv->spdp_endpoint_xqos); diff --git a/src/core/xtests/rhc_torture/rhc_torture.c b/src/core/xtests/rhc_torture/rhc_torture.c index 8568eeb..757cb03 100644 --- a/src/core/xtests/rhc_torture/rhc_torture.c +++ b/src/core/xtests/rhc_torture/rhc_torture.c @@ -921,10 +921,10 @@ int main (int argc, char **argv) mainthread = lookup_thread_state (); assert (ddsrt_atomic_ldvoidp (&mainthread->gv) != NULL); { - struct dds_entity *x; - if (dds_entity_lock(tp, DDS_KIND_TOPIC, &x) < 0) abort(); - mdtopic = dds_topic_lookup(x->m_domain, "RhcTypes_T"); - dds_entity_unlock(x); + struct dds_topic *x; + if (dds_topic_pin (tp, &x) < 0) abort(); + mdtopic = ddsi_sertopic_ref (x->m_stopic); + dds_topic_unpin (x); } if (0 >= first) diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 8525a94..db0deaa 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -111,6 +111,7 @@ list(APPEND headers "${include_path}/dds/ddsrt/endian.h" "${include_path}/dds/ddsrt/arch.h" "${include_path}/dds/ddsrt/misc.h" + "${include_path}/dds/ddsrt/mh3.h" "${include_path}/dds/ddsrt/io.h" "${include_path}/dds/ddsrt/process.h" "${include_path}/dds/ddsrt/strtod.h" @@ -127,6 +128,7 @@ list(APPEND sources "${source_path}/retcode.c" "${source_path}/strtod.c" "${source_path}/strtol.c" + "${source_path}/mh3.c" "${source_path}/avl.c" "${source_path}/expand_envvars.c" "${source_path}/fibheap.c" diff --git a/src/ddsrt/include/dds/ddsrt/mh3.h b/src/ddsrt/include/dds/ddsrt/mh3.h new file mode 100644 index 0000000..d22e387 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/mh3.h @@ -0,0 +1,34 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSRT_MH3_H +#define DDSRT_MH3_H + +#include +#include + +#include "dds/export.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +DDS_EXPORT uint32_t +ddsrt_mh3( + const void *key, + size_t len, + uint32_t seed); + +#if defined(__cplusplus) +} +#endif + +#endif /* DDSRT_MH3_H */ diff --git a/src/ddsrt/src/mh3.c b/src/ddsrt/src/mh3.c new file mode 100644 index 0000000..f186e95 --- /dev/null +++ b/src/ddsrt/src/mh3.c @@ -0,0 +1,69 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include "dds/ddsrt/mh3.h" + +#define DDSRT_MH3_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) + +/* Really + http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp, + MurmurHash3_x86_32 +*/ +uint32_t ddsrt_mh3 (const void *key, size_t len, uint32_t seed) +{ + const uint8_t *data = (const uint8_t *) key; + const intptr_t nblocks = (intptr_t) (len / 4); + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; + + uint32_t h1 = seed; + const uint32_t *blocks = (const uint32_t *) (data + nblocks * 4); + for (intptr_t i = -nblocks; i; i++) + { + uint32_t k1 = blocks[i]; + + k1 *= c1; + k1 = DDSRT_MH3_ROTL32 (k1, 15); + k1 *= c2; + + h1 ^= k1; + h1 = DDSRT_MH3_ROTL32 (h1, 13); + h1 = h1 * 5 + 0xe6546b64; + } + + const uint8_t *tail = data + nblocks * 4; + uint32_t k1 = 0; + switch (len & 3) + { + case 3: + k1 ^= (uint32_t) tail[2] << 16; + /* FALLS THROUGH */ + case 2: + k1 ^= (uint32_t) tail[1] << 8; + /* FALLS THROUGH */ + case 1: + k1 ^= (uint32_t) tail[0]; + k1 *= c1; + k1 = DDSRT_MH3_ROTL32 (k1, 15); + k1 *= c2; + h1 ^= k1; + /* FALLS THROUGH */ + }; + + /* finalization */ + h1 ^= (uint32_t) len; + h1 ^= h1 >> 16; + h1 *= 0x85ebca6b; + h1 ^= h1 >> 13; + h1 *= 0xc2b2ae35; + h1 ^= h1 >> 16; + return h1; +} From d92d491b8381cfea37faec31eb6eb02222d48127 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 30 Jan 2020 16:11:14 +0100 Subject: [PATCH 24/28] Update local delivery code for multiple sertopics This also removes the code duplication for the handling delivery from local vs remote writers. (And it adds a test.) Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_serdata_builtintopic.c | 1 + src/core/ddsc/src/dds_write.c | 146 +++-- src/core/ddsc/tests/CMakeLists.txt | 1 + src/core/ddsc/tests/multi_sertopic.c | 609 ++++++++++++++++++ src/core/ddsi/CMakeLists.txt | 2 + .../include/dds/ddsi/ddsi_deliver_locally.h | 62 ++ src/core/ddsi/include/dds/ddsi/ddsi_serdata.h | 8 + src/core/ddsi/include/dds/ddsi/q_entity.h | 14 +- src/core/ddsi/src/ddsi_deliver_locally.c | 269 ++++++++ src/core/ddsi/src/ddsi_serdata.c | 1 + src/core/ddsi/src/ddsi_serdata_default.c | 65 ++ src/core/ddsi/src/q_entity.c | 40 +- src/core/ddsi/src/q_receive.c | 176 ++--- 13 files changed, 1205 insertions(+), 189 deletions(-) create mode 100644 src/core/ddsc/tests/multi_sertopic.c create mode 100644 src/core/ddsi/include/dds/ddsi/ddsi_deliver_locally.h create mode 100644 src/core/ddsi/src/ddsi_deliver_locally.c diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index f9d3122..7bdb481 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -288,6 +288,7 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_builtintopic = { .eqkey = serdata_builtin_eqkey, .free = serdata_builtin_free, .from_ser = 0, + .from_ser_iov = 0, .from_keyhash = ddsi_serdata_builtin_from_keyhash, .from_sample = 0, .to_ser = serdata_builtin_to_ser, diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 0f65cc6..29fc12c 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -25,6 +25,7 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_radmin.h" #include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_deliver_locally.h" dds_return_t dds_write (dds_entity_t writer, const void *data) { @@ -71,80 +72,103 @@ dds_return_t dds_write_ts (dds_entity_t writer, const void *data, dds_time_t tim return ret; } -static dds_return_t try_store (struct ddsi_rhc *rhc, const struct ddsi_writer_info *pwr_info, struct ddsi_serdata *payload, struct ddsi_tkmap_instance *tk, dds_duration_t *max_block_ms) +static struct reader *writer_first_in_sync_reader (struct entity_index *entity_index, struct entity_common *wrcmn, ddsrt_avl_iter_t *it) { - while (! ddsi_rhc_store (rhc, pwr_info, payload, tk)) + assert (wrcmn->kind == EK_WRITER); + struct writer *wr = (struct writer *) wrcmn; + struct wr_rd_match *m = ddsrt_avl_iter_first (&wr_local_readers_treedef, &wr->local_readers, it); + return m ? entidx_lookup_reader_guid (entity_index, &m->rd_guid) : NULL; +} + +static struct reader *writer_next_in_sync_reader (struct entity_index *entity_index, ddsrt_avl_iter_t *it) +{ + struct wr_rd_match *m = ddsrt_avl_iter_next (it); + return m ? entidx_lookup_reader_guid (entity_index, &m->rd_guid) : NULL; +} + +struct local_sourceinfo { + const struct ddsi_sertopic *src_topic; + struct ddsi_serdata *src_payload; + struct ddsi_tkmap_instance *src_tk; + nn_mtime_t timeout; +}; + +static struct ddsi_serdata *local_make_sample (struct ddsi_tkmap_instance **tk, struct q_globals *gv, struct ddsi_sertopic const * const topic, void *vsourceinfo) +{ + struct local_sourceinfo *si = vsourceinfo; + if (topic == si->src_topic) { - if (*max_block_ms > 0) + *tk = si->src_tk; + /* FIXME: see if this pair of refc increments can't be avoided + They're needed because free_sample_after_delivery will always be called, but + in the common case of a local writer and a single sertopic, make_sample doesn't + actually create a sample, and so free_sample_after_delivery doesn't actually + have to free anything */ + ddsi_tkmap_instance_ref (si->src_tk); + return ddsi_serdata_ref (si->src_payload); + } + else + { + /* ouch ... convert a serdata from one sertopic to another ... */ + ddsrt_iovec_t iov; + uint32_t size = ddsi_serdata_size (si->src_payload); + (void) ddsi_serdata_to_ser_ref (si->src_payload, 0, size, &iov); + struct ddsi_serdata *d = ddsi_serdata_from_ser_iov (topic, si->src_payload->kind, 1, &iov, size); + ddsi_serdata_to_ser_unref (si->src_payload, &iov); + if (d) { - dds_sleepfor (DDS_HEADBANG_TIMEOUT); - *max_block_ms -= DDS_HEADBANG_TIMEOUT; + d->statusinfo = si->src_payload->statusinfo; + d->timestamp = si->src_payload->timestamp; + *tk = ddsi_tkmap_lookup_instance_ref (gv->m_tkmap, d); } else { - return DDS_RETCODE_TIMEOUT; + DDS_CWARNING (&gv->logconfig, "local: deserialization %s/%s failed in topic type conversion\n", topic->name, topic->type_name); } + return d; + } +} + +static dds_return_t local_on_delivery_failure_fastpath (struct entity_common *source_entity, bool source_entity_locked, struct local_reader_ary *fastpath_rdary, void *vsourceinfo) +{ + (void) fastpath_rdary; + (void) source_entity_locked; + assert (source_entity->kind == EK_WRITER); + struct writer *wr = (struct writer *) source_entity; + struct local_sourceinfo *si = vsourceinfo; + nn_mtime_t tnow = now_mt (); + if (si->timeout.v == 0) + si->timeout = add_duration_to_mtime (tnow, wr->xqos->reliability.max_blocking_time); + if (tnow.v >= si->timeout.v) + return DDS_RETCODE_TIMEOUT; + else + { + dds_sleepfor (DDS_HEADBANG_TIMEOUT); + return DDS_RETCODE_OK; } - return DDS_RETCODE_OK; } static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *payload, struct ddsi_tkmap_instance *tk) { - dds_return_t ret = DDS_RETCODE_OK; - ddsrt_mutex_lock (&wr->rdary.rdary_lock); - if (wr->rdary.fastpath_ok) - { - struct reader ** const rdary = wr->rdary.rdary; - if (rdary[0]) - { - dds_duration_t max_block_ms = wr->xqos->reliability.max_blocking_time; - struct ddsi_writer_info pwr_info; - ddsi_make_writer_info (&pwr_info, &wr->e, wr->xqos, payload->statusinfo); - for (uint32_t i = 0; rdary[i]; i++) { - DDS_CTRACE (&wr->e.gv->logconfig, "reader "PGUIDFMT"\n", PGUID (rdary[i]->e.guid)); - if ((ret = try_store (rdary[i]->rhc, &pwr_info, payload, tk, &max_block_ms)) != DDS_RETCODE_OK) - break; - } - } - ddsrt_mutex_unlock (&wr->rdary.rdary_lock); - } - else - { - /* When deleting, pwr is no longer accessible via the hash - tables, and consequently, a reader may be deleted without - it being possible to remove it from rdary. The primary - reason rdary exists is to avoid locking the proxy writer - but this is less of an issue when we are deleting it, so - we fall back to using the GUIDs so that we can deliver all - samples we received from it. As writer being deleted any - reliable samples that are rejected are simply discarded. */ - ddsrt_avl_iter_t it; - struct pwr_rd_match *m; - struct ddsi_writer_info wrinfo; - const struct entity_index *gh = wr->e.gv->entity_index; - dds_duration_t max_block_ms = wr->xqos->reliability.max_blocking_time; - ddsrt_mutex_unlock (&wr->rdary.rdary_lock); - ddsi_make_writer_info (&wrinfo, &wr->e, wr->xqos, payload->statusinfo); - ddsrt_mutex_lock (&wr->e.lock); - for (m = ddsrt_avl_iter_first (&wr_local_readers_treedef, &wr->local_readers, &it); m != NULL; m = ddsrt_avl_iter_next (&it)) - { - struct reader *rd; - if ((rd = entidx_lookup_reader_guid (gh, &m->rd_guid)) != NULL) - { - DDS_CTRACE (&wr->e.gv->logconfig, "reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid)); - /* Copied the return value ignore from DDSI deliver_user_data () function. */ - if ((ret = try_store (rd->rhc, &wrinfo, payload, tk, &max_block_ms)) != DDS_RETCODE_OK) - break; - } - } - ddsrt_mutex_unlock (&wr->e.lock); - } - - if (ret == DDS_RETCODE_TIMEOUT) - { + static const struct deliver_locally_ops deliver_locally_ops = { + .makesample = local_make_sample, + .first_reader = writer_first_in_sync_reader, + .next_reader = writer_next_in_sync_reader, + .on_failure_fastpath = local_on_delivery_failure_fastpath + }; + struct local_sourceinfo sourceinfo = { + .src_topic = wr->topic, + .src_payload = payload, + .src_tk = tk, + .timeout = { 0 }, + }; + dds_return_t rc; + struct ddsi_writer_info wrinfo; + ddsi_make_writer_info (&wrinfo, &wr->e, wr->xqos, payload->statusinfo); + rc = deliver_locally_allinsync (wr->e.gv, &wr->e, false, &wr->rdary, &wrinfo, &deliver_locally_ops, &sourceinfo); + if (rc == DDS_RETCODE_TIMEOUT) DDS_CERROR (&wr->e.gv->logconfig, "The writer could not deliver data on time, probably due to a local reader resources being full\n"); - } - return ret; + return rc; } dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstamp, dds_write_action action) diff --git a/src/core/ddsc/tests/CMakeLists.txt b/src/core/ddsc/tests/CMakeLists.txt index 3f902dd..bdd239e 100644 --- a/src/core/ddsc/tests/CMakeLists.txt +++ b/src/core/ddsc/tests/CMakeLists.txt @@ -30,6 +30,7 @@ set(ddsc_test_sources "instance_get_key.c" "listener.c" "liveliness.c" + "multi_sertopic.c" "participant.c" "publisher.c" "qos.c" diff --git a/src/core/ddsc/tests/multi_sertopic.c b/src/core/ddsc/tests/multi_sertopic.c new file mode 100644 index 0000000..9501b27 --- /dev/null +++ b/src/core/ddsc/tests/multi_sertopic.c @@ -0,0 +1,609 @@ +/* + * 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 +#include + +#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/ddsi/ddsi_serdata.h" +#include "dds/ddsi/ddsi_entity_index.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:+,}0" +#define DDS_CONFIG_NO_PORT_GAIN_LOG "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}cyclonedds_multi_sertopic_tests.${CYCLONEDDS_DOMAIN_ID}.${CYCLONEDDS_PID}.logfinest0" + +/* IDL preprocessing is not really friendly towards creating multiple descriptors + for the same type name with different definitions, so we do it by hand. */ +struct uint32_seq { + uint32_t _maximum; + uint32_t _length; + uint32_t *_buffer; + bool _release; +}; + +struct two_uint32 { + uint32_t v[2]; +}; + +struct two_uint32_seq { + uint32_t _maximum; + uint32_t _length; + struct two_uint32 *_buffer; + bool _release; +}; + +struct type_seq { + struct uint32_seq x; +}; + +struct type_ary { + uint32_t x[4]; +}; + +struct type_uni { + uint32_t _d; + union + { + struct two_uint32_seq a; + uint32_t b[4]; + } _u; +}; + +static const dds_topic_descriptor_t type_seq_desc = +{ + .m_size = sizeof (struct type_seq), + .m_align = sizeof (void *), + .m_flagset = DDS_TOPIC_NO_OPTIMIZE, + .m_nkeys = 0, + .m_typename = "multi_sertopic_type", + .m_keys = NULL, + .m_nops = 2, + .m_ops = (const uint32_t[]) { + DDS_OP_ADR | DDS_OP_TYPE_SEQ | DDS_OP_SUBTYPE_4BY, offsetof (struct type_seq, x), + DDS_OP_RTS + }, + .m_meta = "" /* this is on its way out anyway */ +}; + +static const dds_topic_descriptor_t type_ary_desc = +{ + .m_size = sizeof (struct type_ary), + .m_align = 4u, + .m_flagset = DDS_TOPIC_NO_OPTIMIZE, + .m_nkeys = 0, + .m_typename = "multi_sertopic_type", + .m_keys = NULL, + .m_nops = 2, + .m_ops = (const uint32_t[]) { + DDS_OP_ADR | DDS_OP_TYPE_ARR | DDS_OP_SUBTYPE_4BY, offsetof (struct type_ary, x), 4, + DDS_OP_RTS + }, + .m_meta = "" /* this is on its way out anyway */ +}; + +static const dds_topic_descriptor_t type_uni_desc = +{ + .m_size = sizeof (struct type_uni), + .m_align = sizeof (void *), + .m_flagset = DDS_TOPIC_NO_OPTIMIZE | DDS_TOPIC_CONTAINS_UNION, + .m_nkeys = 0, + .m_typename = "multi_sertopic_type", + .m_keys = NULL, + .m_nops = 8, + .m_ops = (const uint32_t[]) { + DDS_OP_ADR | DDS_OP_TYPE_UNI | DDS_OP_SUBTYPE_4BY | DDS_OP_FLAG_DEF, offsetof (struct type_uni, _d), 2u, (23u << 16) + 4u, + DDS_OP_JEQ | DDS_OP_TYPE_SEQ | 6, 3, offsetof (struct type_uni, _u.a), + DDS_OP_JEQ | DDS_OP_TYPE_ARR | 12, 0, offsetof (struct type_uni, _u.b), + DDS_OP_ADR | DDS_OP_TYPE_SEQ | DDS_OP_SUBTYPE_STU, 0u, + sizeof (struct two_uint32), (8u << 16u) + 4u, + DDS_OP_ADR | DDS_OP_TYPE_ARR | DDS_OP_SUBTYPE_4BY, offsetof (struct two_uint32, v), 2, + DDS_OP_RTS, + DDS_OP_RTS, + DDS_OP_ADR | DDS_OP_TYPE_ARR | DDS_OP_SUBTYPE_4BY, 0u, 4, + DDS_OP_RTS, + DDS_OP_RTS + + }, + .m_meta = "" /* this is on its way out anyway */ +}; + +/* The slow delivery path has a switchover at 4 sertopics (well, today it has ...) so it is better to + to test with > 4 different sertopics. That path (again, today) iterates over GUIDs in increasing + order, and as all readers are created in the participant and the entity ids are strictly + monotonically increasing for the first ~ 16M entities (again, today), creating additional + readers for these topics at the end means that "ary2" is the one that ends up in > 4 case. + Calling takecdr */ +static const dds_topic_descriptor_t type_ary1_desc = +{ + .m_size = sizeof (struct type_ary), + .m_align = 1u, + .m_flagset = DDS_TOPIC_NO_OPTIMIZE, + .m_nkeys = 0, + .m_typename = "multi_sertopic_type", + .m_keys = NULL, + .m_nops = 2, + .m_ops = (const uint32_t[]) { + DDS_OP_ADR | DDS_OP_TYPE_ARR | DDS_OP_SUBTYPE_1BY, offsetof (struct type_ary, x), 16, + DDS_OP_RTS + }, + .m_meta = "" /* this is on its way out anyway */ +}; + +static const dds_topic_descriptor_t type_ary2_desc = +{ + .m_size = sizeof (struct type_ary), + .m_align = 2u, + .m_flagset = DDS_TOPIC_NO_OPTIMIZE, + .m_nkeys = 0, + .m_typename = "multi_sertopic_type", + .m_keys = NULL, + .m_nops = 2, + .m_ops = (const uint32_t[]) { + DDS_OP_ADR | DDS_OP_TYPE_ARR | DDS_OP_SUBTYPE_2BY, offsetof (struct type_ary, x), 8, + DDS_OP_RTS + }, + .m_meta = "" /* this is on its way out anyway */ +}; + +static 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 multi_sertopic_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 multi_sertopic_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); +} + +static bool get_and_check_writer_status (size_t nwr, const dds_entity_t *wrs, size_t nrd) +{ + dds_return_t rc; + struct dds_publication_matched_status x; + for (size_t i = 0; i < nwr; i++) + { + rc = dds_get_publication_matched_status (wrs[i], &x); + CU_ASSERT_FATAL (rc == DDS_RETCODE_OK); + if (x.current_count != nrd) + return false; + } + return true; +} + +static bool get_and_check_reader_status (size_t nrd, const dds_entity_t *rds, size_t nwr) +{ + dds_return_t rc; + struct dds_subscription_matched_status x; + for (size_t i = 0; i < nrd; i++) + { + rc = dds_get_subscription_matched_status (rds[i], &x); + CU_ASSERT_FATAL (rc == DDS_RETCODE_OK); + if (x.current_count != nwr) + return false; + } + return true; +} + +static void waitfor_or_reset_fastpath (dds_entity_t rdhandle, bool fastpath, size_t nwr) +{ + dds_return_t rc; + struct dds_entity *x; + + rc = dds_entity_pin (rdhandle, &x); + CU_ASSERT_FATAL (rc == DDS_RETCODE_OK); + CU_ASSERT_FATAL (dds_entity_kind (x) == DDS_KIND_READER); + + struct reader * const rd = ((struct dds_reader *) x)->m_rd; + struct rd_pwr_match *m; + ddsi_guid_t cursor; + size_t wrcount = 0; + thread_state_awake (lookup_thread_state (), rd->e.gv); + ddsrt_mutex_lock (&rd->e.lock); + + memset (&cursor, 0, sizeof (cursor)); + while ((m = ddsrt_avl_lookup_succ (&rd_writers_treedef, &rd->writers, &cursor)) != NULL) + { + cursor = m->pwr_guid; + ddsrt_mutex_unlock (&rd->e.lock); + struct proxy_writer * const pwr = entidx_lookup_proxy_writer_guid (rd->e.gv->entity_index, &cursor); + ddsrt_mutex_lock (&pwr->rdary.rdary_lock); + if (!fastpath) + pwr->rdary.fastpath_ok = false; + else + { + while (!pwr->rdary.fastpath_ok) + { + ddsrt_mutex_unlock (&pwr->rdary.rdary_lock); + dds_sleepfor (DDS_MSECS (10)); + ddsrt_mutex_lock (&pwr->rdary.rdary_lock); + } + } + wrcount++; + ddsrt_mutex_unlock (&pwr->rdary.rdary_lock); + ddsrt_mutex_lock (&rd->e.lock); + } + + memset (&cursor, 0, sizeof (cursor)); + while ((m = ddsrt_avl_lookup_succ (&rd_local_writers_treedef, &rd->local_writers, &cursor)) != NULL) + { + cursor = m->pwr_guid; + ddsrt_mutex_unlock (&rd->e.lock); + struct writer * const wr = entidx_lookup_writer_guid (rd->e.gv->entity_index, &cursor); + ddsrt_mutex_lock (&wr->rdary.rdary_lock); + if (!fastpath) + wr->rdary.fastpath_ok = fastpath; + else + { + while (!wr->rdary.fastpath_ok) + { + ddsrt_mutex_unlock (&wr->rdary.rdary_lock); + dds_sleepfor (DDS_MSECS (10)); + ddsrt_mutex_lock (&wr->rdary.rdary_lock); + } + } + wrcount++; + ddsrt_mutex_unlock (&wr->rdary.rdary_lock); + ddsrt_mutex_lock (&rd->e.lock); + } + ddsrt_mutex_unlock (&rd->e.lock); + thread_state_asleep (lookup_thread_state ()); + dds_entity_unpin (x); + + CU_ASSERT_FATAL (wrcount == nwr); +} + +static struct ddsi_sertopic *get_sertopic_from_reader (dds_entity_t reader) +{ + /* not refcounting the sertopic: so this presumes it is kept alive for other reasons */ + dds_return_t rc; + struct dds_entity *x; + struct dds_reader *rd; + struct ddsi_sertopic *sertopic; + rc = dds_entity_pin (reader, &x); + CU_ASSERT_FATAL (rc == DDS_RETCODE_OK); + CU_ASSERT_FATAL (dds_entity_kind (x) == DDS_KIND_READER); + rd = (struct dds_reader *) x; + sertopic = rd->m_topic->m_stopic; + dds_entity_unpin (x); + return sertopic; +} + +static void logsink (void *arg, const dds_log_data_t *msg) +{ + ddsrt_atomic_uint32_t *deser_fail = arg; + fputs (msg->message - msg->hdrsize, stderr); + if (strstr (msg->message, "deserialization") && strstr (msg->message, "failed")) + ddsrt_atomic_inc32 (deser_fail); +} + +static void ddsc_multi_sertopic_impl (dds_entity_t pp_pub, dds_entity_t pp_sub, bool fastpath) +{ +#define SEQ_IDX 0 +#define ARY_IDX 1 +#define UNI_IDX 2 + char name[100]; + static const dds_topic_descriptor_t *descs[] = { + &type_seq_desc, &type_ary_desc, &type_uni_desc, + &type_ary1_desc, &type_ary2_desc + }; + dds_entity_t pub_topics[3], writers[3]; + dds_entity_t sub_topics[5]; + dds_entity_t readers[15]; + dds_entity_t waitset; + dds_qos_t *qos; + dds_return_t rc; + + printf ("multi_sertopic: %s %s\n", (pp_pub == pp_sub) ? "local" : "remote", fastpath ? "fastpath" : "slowpath"); + + waitset = dds_create_waitset (DDS_CYCLONEDDS_HANDLE); + CU_ASSERT_FATAL (waitset > 0); + + qos = dds_create_qos (); + CU_ASSERT_FATAL (qos != NULL); + dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); + dds_qset_destination_order (qos, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0); + + create_topic_name ("ddsc_multi_sertopic_lease_duration_zero", g_topic_nr++, name, sizeof name); + + for (size_t i = 0; i < sizeof (pub_topics) / sizeof (pub_topics[0]); i++) + { + pub_topics[i] = dds_create_topic (pp_pub, descs[i], name, qos, NULL); + CU_ASSERT_FATAL (pub_topics[i] > 0); + } + for (size_t i = 0; i < sizeof (writers) / sizeof (writers[0]); i++) + { + writers[i] = dds_create_writer (pp_pub, pub_topics[i], qos, NULL); + CU_ASSERT_FATAL (writers[i] > 0); + } + for (size_t i = 0; i < sizeof (sub_topics) / sizeof (sub_topics[0]); i++) + { + sub_topics[i] = dds_create_topic (pp_sub, descs[i], name, qos, NULL); + CU_ASSERT_FATAL (sub_topics[i] > 0); + } + DDSRT_STATIC_ASSERT (sizeof (readers) >= sizeof (sub_topics)); + DDSRT_STATIC_ASSERT ((sizeof (readers) % sizeof (sub_topics)) == 0); + for (size_t i = 0; i < sizeof (sub_topics) / sizeof (sub_topics[0]); i++) + { + readers[i] = dds_create_reader (pp_sub, sub_topics[i], qos, NULL); + CU_ASSERT_FATAL (readers[i] > 0); + } + for (size_t i = sizeof (sub_topics) / sizeof (sub_topics[0]); i < sizeof (readers) / sizeof (readers[0]); i++) + { + const size_t nrd = sizeof (readers) / sizeof (readers[0]); + const size_t ntp = sizeof (sub_topics) / sizeof (sub_topics[0]); + readers[i] = dds_create_reader (pp_sub, sub_topics[(i - ntp) / (nrd / ntp - 1)], qos, NULL); + CU_ASSERT_FATAL (readers[i] > 0); + } + + dds_delete_qos (qos); + + /* wait for discovery to complete */ + for (size_t i = 0; i < sizeof (writers) / sizeof (writers[0]); i++) + { + rc = dds_set_status_mask (writers[i], DDS_PUBLICATION_MATCHED_STATUS); + CU_ASSERT_FATAL (rc == DDS_RETCODE_OK); + rc = dds_waitset_attach (waitset, writers[i], -(dds_attach_t)i - 1); + CU_ASSERT_FATAL (rc == DDS_RETCODE_OK); + } + for (size_t i = 0; i < sizeof (readers) / sizeof (readers[0]); i++) + { + rc = dds_set_status_mask (readers[i], DDS_SUBSCRIPTION_MATCHED_STATUS | DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_FATAL (rc == DDS_RETCODE_OK); + rc = dds_waitset_attach (waitset, readers[i], (dds_attach_t)i); + CU_ASSERT_FATAL (rc == DDS_RETCODE_OK); + } + + printf ("wait for discovery, fastpath_ok; delete & recreate readers\n"); + while (!(get_and_check_writer_status (sizeof (writers) / sizeof (writers[0]), writers, sizeof (readers) / sizeof (readers[0])) && + get_and_check_reader_status (sizeof (readers) / sizeof (readers[0]), readers, sizeof (writers) / sizeof (writers[0])))) + { + rc = dds_waitset_wait (waitset, NULL, 0, DDS_SECS(5)); + CU_ASSERT_FATAL (rc >= 1); + } + + /* we want to check both the fast path and the slow path ... so first wait + for it to be set on all (proxy) writers, then possibly reset it */ + for (size_t i = 0; i < sizeof (readers) / sizeof (readers[0]); i++) + waitfor_or_reset_fastpath (readers[i], true, sizeof (writers) / sizeof (writers[0])); + if (!fastpath) + { + printf ("clear fastpath_ok\n"); + for (size_t i = 0; i < sizeof (readers) / sizeof (readers[0]); i++) + waitfor_or_reset_fastpath (readers[i], false, sizeof (writers) / sizeof (writers[0])); + } + + /* check the log output for deserialization failures */ + ddsrt_atomic_uint32_t deser_fail = DDSRT_ATOMIC_UINT32_INIT (0); + dds_set_log_sink (logsink, &deser_fail); + + /* Write one of each type: all of these samples result in the same serialised + form but interpreting the memory layout for type X as-if it were of type Y + wreaks havoc. */ + { + struct type_seq s = { + .x = { + ._length = 3, ._maximum = 3, ._release = false, ._buffer = (uint32_t[]) { 1, 4, 2 } + } + }; + struct type_ary a = { + .x = { 3, 1, 4, 2 } + }; + struct type_uni u = { + ._d = 3, + ._u = { .a = { + ._length = 1, ._maximum = 1, ._release = false, ._buffer = (struct two_uint32[]) { { { 4, 2 } } } + } } + }; + printf ("writing ...\n"); + rc = dds_write_ts (writers[SEQ_IDX], &s, 1); + CU_ASSERT_FATAL (rc == DDS_RETCODE_OK); + rc = dds_write_ts (writers[ARY_IDX], &a, 2); + CU_ASSERT_FATAL (rc == DDS_RETCODE_OK); + rc = dds_write_ts (writers[UNI_IDX], &u, 3); + CU_ASSERT_FATAL (rc == DDS_RETCODE_OK); + + /* Also write a sample that can't be deserialised by the other types */ + struct type_seq s1 = { + .x = { + ._length = 1, ._maximum = 1, ._release = false, ._buffer = (uint32_t[]) { 1 } + } + }; + rc = dds_write_ts (writers[SEQ_IDX], &s1, 4); + CU_ASSERT_FATAL (rc == DDS_RETCODE_OK); + } + + /* All readers should have received three samples, and those that are of type seq + should have received one extra (whereas the others should cause deserialization + failure warnings) */ + printf ("reading\n"); + const size_t nexp = ((sizeof (writers) / sizeof (writers[0])) * + (sizeof (readers) / sizeof (readers[0])) + + ((sizeof (readers) / sizeof (readers[0])) / (sizeof (sub_topics) / sizeof (sub_topics[0])))); + /* expecting exactly as many deserialization failures as there are topics other than seq */ + const size_t nexp_fail = sizeof (sub_topics) / sizeof (sub_topics[0]) - 1; + uint32_t nseen = 0; + while (nseen < nexp) + { + dds_sample_info_t si; + + rc = dds_waitset_wait (waitset, NULL, 0, DDS_SECS (5)); + CU_ASSERT_FATAL (rc >= 1); + + { + struct type_seq s = { .x = { 0 } }; + void *raws[] = { &s }; + while (dds_take (readers[SEQ_IDX], raws, &si, 1, 1) == 1) + { + if (!si.valid_data) + continue; + printf ("recv: seq %"PRId64"\n", si.source_timestamp); + if (si.source_timestamp == 4) + { + CU_ASSERT_FATAL (s.x._length == 1); + CU_ASSERT_FATAL (s.x._buffer[0] == 1); + } + else + { + CU_ASSERT_FATAL (si.source_timestamp >= 1 && si.source_timestamp <= 3); + CU_ASSERT_FATAL (s.x._length == 3); + CU_ASSERT_FATAL (s.x._buffer[0] == 1); + CU_ASSERT_FATAL (s.x._buffer[1] == 4); + CU_ASSERT_FATAL (s.x._buffer[2] == 2); + } + nseen++; + } + dds_free (s.x._buffer); + } + + { + struct type_ary a; + void *rawa[] = { &a }; + while (dds_take (readers[ARY_IDX], rawa, &si, 1, 1) == 1) + { + if (!si.valid_data) + continue; + printf ("recv: ary %"PRId64"\n", si.source_timestamp); + CU_ASSERT_FATAL (si.source_timestamp >= 1 && si.source_timestamp <= 3); + CU_ASSERT_FATAL (a.x[0] == 3); + CU_ASSERT_FATAL (a.x[1] == 1); + CU_ASSERT_FATAL (a.x[2] == 4); + CU_ASSERT_FATAL (a.x[3] == 2); + nseen++; + } + } + + { + struct type_uni u = { ._u.a = { 0 } }; + void *rawu[] = { &u }; + while (dds_take (readers[UNI_IDX], rawu, &si, 1, 1) == 1) + { + if (!si.valid_data) + continue; + printf ("recv: uni %"PRId64"\n", si.source_timestamp); + CU_ASSERT_FATAL (si.source_timestamp >= 1 && si.source_timestamp <= 3); + CU_ASSERT_FATAL (u._d == 3); + CU_ASSERT_FATAL (u._u.a._length == 1); + assert (u._u.a._buffer != NULL); /* for Clang static analyzer */ + CU_ASSERT_FATAL (u._u.a._buffer[0].v[0] == 4); + CU_ASSERT_FATAL (u._u.a._buffer[0].v[1] == 2); + dds_free (u._u.a._buffer); + u._u.a._buffer = NULL; + nseen++; + } + } + + DDSRT_STATIC_ASSERT (((1u << SEQ_IDX) | (1u << ARY_IDX) | (1u << UNI_IDX)) == 7); + for (size_t i = 3; i < sizeof (readers) / sizeof (readers[0]); i++) + { + struct ddsi_serdata *sample; + while (dds_takecdr (readers[i], &sample, 1, &si, DDS_ANY_STATE) == 1) + { + if (!si.valid_data) + continue; + printf ("recv: reader %zu %"PRId64"\n", i, si.source_timestamp); + CU_ASSERT_FATAL (sample->topic == get_sertopic_from_reader (readers[i])); + ddsi_serdata_unref (sample); + nseen++; + } + } + } + CU_ASSERT_FATAL (nseen == nexp); + + /* data from remote writers can cause a deserialization failure after all + expected samples have been seen (becasue it is written last); so wait + for them */ + while (ddsrt_atomic_ld32 (&deser_fail) < nexp_fail) + dds_sleepfor (DDS_MSECS (10)); + CU_ASSERT_FATAL (ddsrt_atomic_ld32 (&deser_fail) == nexp_fail); + + /* deleting the waitset is important: it is bound to the library rather than to + a domain and consequently won't be deleted simply because all domains are */ + rc = dds_delete (waitset); + + CU_ASSERT_FATAL (rc == DDS_RETCODE_OK); + dds_set_log_sink (0, NULL); +} + +CU_Test(ddsc_multi_sertopic, local, .init = multi_sertopic_init, .fini = multi_sertopic_fini) +{ + ddsc_multi_sertopic_impl (g_pub_participant, g_pub_participant, true); +} + +CU_Test(ddsc_multi_sertopic, remote, .init = multi_sertopic_init, .fini = multi_sertopic_fini) +{ + ddsc_multi_sertopic_impl (g_pub_participant, g_sub_participant, true); +} + +CU_Test(ddsc_multi_sertopic, local_slowpath, .init = multi_sertopic_init, .fini = multi_sertopic_fini) +{ + ddsc_multi_sertopic_impl (g_pub_participant, g_pub_participant, false); +} + +CU_Test(ddsc_multi_sertopic, remote_slowpath, .init = multi_sertopic_init, .fini = multi_sertopic_fini) +{ + ddsc_multi_sertopic_impl (g_pub_participant, g_sub_participant, false); +} diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 464f39b..01c566d 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -31,6 +31,7 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" ddsi_pmd.c ddsi_entity_index.c ddsi_deadline.c + ddsi_deliver_locally.c q_addrset.c q_bitset_inlines.c q_bswap.c @@ -92,6 +93,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" ddsi_guid.h ddsi_entity_index.h ddsi_deadline.h + ddsi_deliver_locally.h q_addrset.h q_bitset.h q_bswap.h diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_deliver_locally.h b/src/core/ddsi/include/dds/ddsi/ddsi_deliver_locally.h new file mode 100644 index 0000000..5ecec40 --- /dev/null +++ b/src/core/ddsi/include/dds/ddsi/ddsi_deliver_locally.h @@ -0,0 +1,62 @@ +/* + * Copyright(c) 2020 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_DELIVER_LOCALLY_H +#define DDSI_DELIVER_LOCALLY_H + +#include +#include + +#include "dds/export.h" +#include "dds/ddsrt/retcode.h" +#include "dds/ddsrt/avl.h" +#include "dds/ddsi/ddsi_guid.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +struct q_globals; +struct ddsi_tkmap_instance; +struct ddsi_sertopic; +struct ddsi_serdata; +struct entity_index; +struct reader; +struct entity_common; +struct ddsi_writer_info; +struct local_reader_ary; + +typedef struct ddsi_serdata * (*deliver_locally_makesample_t) (struct ddsi_tkmap_instance **tk, struct q_globals *gv, struct ddsi_sertopic const * const topic, void *vsourceinfo); +typedef struct reader * (*deliver_locally_first_reader_t) (struct entity_index *entity_index, struct entity_common *source_entity, ddsrt_avl_iter_t *it); +typedef struct reader * (*deliver_locally_next_reader_t) (struct entity_index *entity_index, ddsrt_avl_iter_t *it); + +/** return: + - DDS_RETCODE_OK to try again immediately + - DDS_RETCODE_TRY_AGAIN to complete restart the operation later + - anything else: error to be returned from deliver_locally_xxx */ +typedef dds_return_t (*deliver_locally_on_failure_fastpath_t) (struct entity_common *source_entity, bool source_entity_locked, struct local_reader_ary *fastpath_rdary, void *vsourceinfo); + +struct deliver_locally_ops { + deliver_locally_makesample_t makesample; + deliver_locally_first_reader_t first_reader; + deliver_locally_next_reader_t next_reader; + deliver_locally_on_failure_fastpath_t on_failure_fastpath; +}; + +dds_return_t deliver_locally_one (struct q_globals *gv, struct entity_common *source_entity, bool source_entity_locked, const ddsi_guid_t *rdguid, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo); + +dds_return_t deliver_locally_allinsync (struct q_globals *gv, struct entity_common *source_entity, bool source_entity_locked, struct local_reader_ary *fastpath_rdary, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo); + +#if defined (__cplusplus) +} +#endif + +#endif /* DDSI_DELIVER_LOCALLY_H */ diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h index 0074141..ceb5112 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h @@ -61,6 +61,9 @@ typedef void (*ddsi_serdata_free_t) (struct ddsi_serdata *d); - FIXME: get the encoding header out of the serialised data */ typedef struct ddsi_serdata * (*ddsi_serdata_from_ser_t) (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, const struct nn_rdata *fragchain, size_t size); +/* Exactly like ddsi_serdata_from_ser_t, but with the data in an iovec and guaranteed absence of overlap */ +typedef struct ddsi_serdata * (*ddsi_serdata_from_ser_iov_t) (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size); + /* Construct a serdata from a keyhash (an SDK_KEY by definition) */ typedef struct ddsi_serdata * (*ddsi_serdata_from_keyhash_t) (const struct ddsi_sertopic *topic, const struct nn_keyhash *keyhash); @@ -138,6 +141,7 @@ struct ddsi_serdata_ops { ddsi_serdata_eqkey_t eqkey; ddsi_serdata_size_t get_size; ddsi_serdata_from_ser_t from_ser; + ddsi_serdata_from_ser_iov_t from_ser_iov; ddsi_serdata_from_keyhash_t from_keyhash; ddsi_serdata_from_sample_t from_sample; ddsi_serdata_to_ser_t to_ser; @@ -173,6 +177,10 @@ DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_ser (const struct ddsi_ return topic->serdata_ops->from_ser (topic, kind, fragchain, size); } +DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_ser_iov (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size) { + return topic->serdata_ops->from_ser_iov (topic, kind, niov, iov, size); +} + DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_keyhash (const struct ddsi_sertopic *topic, const struct nn_keyhash *keyhash) { return topic->serdata_ops->from_keyhash (topic, keyhash); } diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 34ab9f8..f5d6dde 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -185,7 +185,7 @@ struct local_reader_ary { unsigned valid: 1; /* always true until (proxy-)writer is being deleted; !valid => !fastpath_ok */ unsigned fastpath_ok: 1; /* if not ok, fall back to using GUIDs (gives access to the reader-writer match data for handling readers that bumped into resource limits, hence can flip-flop, unlike "valid") */ uint32_t n_readers; - struct reader **rdary; /* for efficient delivery, null-pointer terminated */ + struct reader **rdary; /* for efficient delivery, null-pointer terminated, grouped by topic */ }; struct avail_entityid_set { @@ -427,12 +427,12 @@ struct proxy_reader { ddsrt_avl_tree_t writers; /* matching LOCAL writers */ }; -extern const ddsrt_avl_treedef_t wr_readers_treedef; -extern const ddsrt_avl_treedef_t wr_local_readers_treedef; -extern const ddsrt_avl_treedef_t rd_writers_treedef; -extern const ddsrt_avl_treedef_t rd_local_writers_treedef; -extern const ddsrt_avl_treedef_t pwr_readers_treedef; -extern const ddsrt_avl_treedef_t prd_writers_treedef; +DDS_EXPORT extern const ddsrt_avl_treedef_t wr_readers_treedef; +DDS_EXPORT extern const ddsrt_avl_treedef_t wr_local_readers_treedef; +DDS_EXPORT extern const ddsrt_avl_treedef_t rd_writers_treedef; +DDS_EXPORT extern const ddsrt_avl_treedef_t rd_local_writers_treedef; +DDS_EXPORT extern const ddsrt_avl_treedef_t pwr_readers_treedef; +DDS_EXPORT extern const ddsrt_avl_treedef_t prd_writers_treedef; extern const ddsrt_avl_treedef_t deleted_participants_treedef; #define DPG_LOCAL 1 diff --git a/src/core/ddsi/src/ddsi_deliver_locally.c b/src/core/ddsi/src/ddsi_deliver_locally.c new file mode 100644 index 0000000..bea4270 --- /dev/null +++ b/src/core/ddsi/src/ddsi_deliver_locally.c @@ -0,0 +1,269 @@ +/* + * 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 +#include + +#include "dds/ddsrt/log.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/avl.h" + +#include "dds/ddsi/ddsi_deliver_locally.h" +#include "dds/ddsi/ddsi_sertopic.h" +#include "dds/ddsi/ddsi_serdata.h" +#include "dds/ddsi/ddsi_tkmap.h" +#include "dds/ddsi/ddsi_rhc.h" +#include "dds/ddsi/ddsi_entity_index.h" +#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/q_entity.h" + +#define TOPIC_SAMPLE_CACHE_SIZE 4 + +struct ddsi_sertopic; +struct ddsi_serdata; +struct ddsi_tkmap_instance; + +struct topic_sample_cache_entry { + struct ddsi_serdata *sample; + struct ddsi_tkmap_instance *tk; +}; + +struct topic_sample_cache_large_entry { + ddsrt_avl_node_t avlnode; + const struct ddsi_sertopic *topic; + struct ddsi_serdata *sample; + struct ddsi_tkmap_instance *tk; +}; + +struct topic_sample_cache { + uint32_t n; + const struct ddsi_sertopic *topics[TOPIC_SAMPLE_CACHE_SIZE]; + struct topic_sample_cache_entry samples[TOPIC_SAMPLE_CACHE_SIZE]; + ddsrt_avl_tree_t overflow; +}; + +static int cmp_topic_ptrs (const void *va, const void *vb) +{ + uintptr_t a = (uintptr_t) va; + uintptr_t b = (uintptr_t) vb; + return (a == b) ? 0 : (a < b) ? -1 : 1; +} + +static const ddsrt_avl_treedef_t tsc_large_td = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct topic_sample_cache_large_entry, avlnode), offsetof (struct topic_sample_cache_large_entry, topic), cmp_topic_ptrs, 0); + +static void free_sample_after_store (struct q_globals *gv, struct ddsi_serdata *sample, struct ddsi_tkmap_instance *tk) +{ + if (sample) + { + ddsi_tkmap_instance_unref (gv->m_tkmap, tk); + ddsi_serdata_unref (sample); + } +} + +static void topic_sample_cache_init (struct topic_sample_cache * __restrict tsc) +{ + tsc->n = 0; + ddsrt_avl_init (&tsc_large_td, &tsc->overflow); +} + +static void free_large_entry (void *vnode, void *varg) +{ + struct topic_sample_cache_large_entry *e = vnode; + struct q_globals *gv = varg; + free_sample_after_store (gv, e->sample, e->tk); + ddsrt_free (e); +} + +static void topic_sample_cache_fini (struct topic_sample_cache * __restrict tsc, struct q_globals *gv) +{ + for (uint32_t i = 0; i < tsc->n && i < TOPIC_SAMPLE_CACHE_SIZE; i++) + if (tsc->topics[i] && tsc->samples[i].tk) + free_sample_after_store (gv, tsc->samples[i].sample, tsc->samples[i].tk); + + ddsrt_avl_free_arg (&tsc_large_td, &tsc->overflow, free_large_entry, gv); +} + +static bool topic_sample_cache_lookup (struct ddsi_serdata ** __restrict sample, struct ddsi_tkmap_instance ** __restrict tk, struct topic_sample_cache * __restrict tsc, const struct ddsi_sertopic *topic) +{ + /* linear scan of an array of pointers should be pretty fast */ + for (uint32_t i = 0; i < tsc->n && i < TOPIC_SAMPLE_CACHE_SIZE; i++) + { + if (tsc->topics[i] == topic) + { + *tk = tsc->samples[i].tk; + *sample = tsc->samples[i].sample; + return true; + } + } + + struct topic_sample_cache_large_entry *e; + if ((e = ddsrt_avl_lookup (&tsc_large_td, &tsc->overflow, topic)) != NULL) + { + *tk = e->tk; + *sample = e->sample; + return true; + } + return false; +} + +static void topic_sample_cache_store (struct topic_sample_cache * __restrict tsc, const struct ddsi_sertopic *topic, struct ddsi_serdata *sample, struct ddsi_tkmap_instance *tk) +{ + if (tsc->n < TOPIC_SAMPLE_CACHE_SIZE) + { + tsc->topics[tsc->n] = topic; + tsc->samples[tsc->n].tk = tk; + tsc->samples[tsc->n].sample = sample; + } + else + { + struct topic_sample_cache_large_entry *e = ddsrt_malloc (sizeof (*e)); + e->topic = topic; + e->tk = tk; + e->sample = sample; + ddsrt_avl_insert (&tsc_large_td, &tsc->overflow, e); + } + tsc->n++; +} + +dds_return_t deliver_locally_one (struct q_globals *gv, struct entity_common *source_entity, bool source_entity_locked, const ddsi_guid_t *rdguid, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo) +{ + struct reader *rd = entidx_lookup_reader_guid (gv->entity_index, rdguid); + if (rd == NULL) + return DDS_RETCODE_OK; + + struct ddsi_serdata *payload; + struct ddsi_tkmap_instance *tk; + if ((payload = ops->makesample (&tk, gv, rd->topic, vsourceinfo)) != NULL) + { + EETRACE (source_entity, " =>"PGUIDFMT"\n", PGUID (*rdguid)); + /* FIXME: why look up rd,pwr again? Their states remains valid while the thread stays + "awake" (although a delete can be initiated), and blocking like this is a stopgap + anyway -- quite possibly to abort once either is deleted */ + while (!ddsi_rhc_store (rd->rhc, wrinfo, payload, tk)) + { + if (source_entity_locked) + ddsrt_mutex_unlock (&source_entity->lock); + dds_sleepfor (DDS_MSECS (1)); + if (source_entity_locked) + ddsrt_mutex_lock (&source_entity->lock); + if (entidx_lookup_reader_guid (gv->entity_index, rdguid) == NULL || + entidx_lookup_guid_untyped (gv->entity_index, &source_entity->guid) == NULL) + { + /* give up when reader or proxy writer no longer accessible */ + break; + } + } + free_sample_after_store (gv, payload, tk); + } + return DDS_RETCODE_OK; +} + +static dds_return_t deliver_locally_slowpath (struct q_globals *gv, struct entity_common *source_entity, bool source_entity_locked, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo) +{ + /* When deleting, pwr is no longer accessible via the hash + tables, and consequently, a reader may be deleted without + it being possible to remove it from rdary. The primary + reason rdary exists is to avoid locking the proxy writer + but this is less of an issue when we are deleting it, so + we fall back to using the GUIDs so that we can deliver all + samples we received from it. As writer being deleted any + reliable samples that are rejected are simply discarded. */ + struct topic_sample_cache tsc; + ddsrt_avl_iter_t it; + struct reader *rd; + topic_sample_cache_init (&tsc); + if (!source_entity_locked) + ddsrt_mutex_lock (&source_entity->lock); + rd = ops->first_reader (gv->entity_index, source_entity, &it); + if (rd != NULL) + EETRACE (source_entity, " =>"); + while (rd != NULL) + { + struct ddsi_serdata *payload; + struct ddsi_tkmap_instance *tk; + if (!topic_sample_cache_lookup (&payload, &tk, &tsc, rd->topic)) + { + payload = ops->makesample (&tk, gv, rd->topic, vsourceinfo); + topic_sample_cache_store (&tsc, rd->topic, payload, tk); + } + /* check payload to allow for deserialisation failures */ + if (payload) + { + EETRACE (source_entity, " "PGUIDFMT, PGUID (rd->e.guid)); + (void) ddsi_rhc_store (rd->rhc, wrinfo, payload, tk); + } + rd = ops->next_reader (gv->entity_index, &it); + } + EETRACE (source_entity, "\n"); + if (!source_entity_locked) + ddsrt_mutex_unlock (&source_entity->lock); + topic_sample_cache_fini (&tsc, gv); + return DDS_RETCODE_OK; +} + +static dds_return_t deliver_locally_fastpath (struct q_globals *gv, struct entity_common *source_entity, bool source_entity_locked, struct local_reader_ary *fastpath_rdary, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo) +{ + struct reader ** const rdary = fastpath_rdary->rdary; + uint32_t i = 0; + while (rdary[i]) + { + struct ddsi_sertopic const * const topic = rdary[i]->topic; + struct ddsi_serdata *payload; + struct ddsi_tkmap_instance *tk; + if ((payload = ops->makesample (&tk, gv, topic, vsourceinfo)) == NULL) + { + /* malformed payload: skip all readers with the same topic */ + while (rdary[++i] && rdary[i]->topic == topic) + ; /* do nothing */ + } + else + { + do { + dds_return_t rc; + while (!ddsi_rhc_store (rdary[i]->rhc, wrinfo, payload, tk)) + { + if ((rc = ops->on_failure_fastpath (source_entity, source_entity_locked, fastpath_rdary, vsourceinfo)) != DDS_RETCODE_OK) + { + free_sample_after_store (gv, payload, tk); + return rc; + } + } + } while (rdary[++i] && rdary[i]->topic == topic); + free_sample_after_store (gv, payload, tk); + } + } + return DDS_RETCODE_OK; +} + +dds_return_t deliver_locally_allinsync (struct q_globals *gv, struct entity_common *source_entity, bool source_entity_locked, struct local_reader_ary *fastpath_rdary, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo) +{ + dds_return_t rc; + /* FIXME: Retry loop for re-delivery of rejected reliable samples is a bad hack + should instead throttle back the writer by skipping acknowledgement and retry */ + do { + ddsrt_mutex_lock (&fastpath_rdary->rdary_lock); + if (fastpath_rdary->fastpath_ok) + { + EETRACE (source_entity, " => EVERYONE\n"); + if (fastpath_rdary->rdary[0]) + rc = deliver_locally_fastpath (gv, source_entity, source_entity_locked, fastpath_rdary, wrinfo, ops, vsourceinfo); + else + rc = DDS_RETCODE_OK; + ddsrt_mutex_unlock (&fastpath_rdary->rdary_lock); + } + else + { + ddsrt_mutex_unlock (&fastpath_rdary->rdary_lock); + rc = deliver_locally_slowpath (gv, source_entity, source_entity_locked, wrinfo, ops, vsourceinfo); + } + } while (rc == DDS_RETCODE_TRY_AGAIN); + return rc; +} diff --git a/src/core/ddsi/src/ddsi_serdata.c b/src/core/ddsi/src/ddsi_serdata.c index 68caae0..5cd816e 100644 --- a/src/core/ddsi/src/ddsi_serdata.c +++ b/src/core/ddsi/src/ddsi_serdata.c @@ -36,6 +36,7 @@ extern inline struct ddsi_serdata *ddsi_serdata_ref (const struct ddsi_serdata * extern inline void ddsi_serdata_unref (struct ddsi_serdata *serdata); extern inline uint32_t ddsi_serdata_size (const struct ddsi_serdata *d); extern inline struct ddsi_serdata *ddsi_serdata_from_ser (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, const struct nn_rdata *fragchain, size_t size); +extern inline struct ddsi_serdata *ddsi_serdata_from_ser_iov (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size); extern inline struct ddsi_serdata *ddsi_serdata_from_keyhash (const struct ddsi_sertopic *topic, const struct nn_keyhash *keyhash); extern inline struct ddsi_serdata *ddsi_serdata_from_sample (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, const void *sample); extern inline struct ddsi_serdata *ddsi_serdata_to_topicless (const struct ddsi_serdata *d); diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index a33d3c1..9344253 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -268,6 +268,51 @@ static struct ddsi_serdata_default *serdata_default_from_ser_common (const struc } } +static struct ddsi_serdata_default *serdata_default_from_ser_iov_common (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size) +{ + const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn; + + /* FIXME: check whether this really is the correct maximum: offsets are relative + to the CDR header, but there are also some places that use a serdata as-if it + were a stream, and those use offsets (m_index) relative to the start of the + serdata */ + if (size > UINT32_MAX - offsetof (struct ddsi_serdata_default, hdr)) + return NULL; + assert (niov >= 1); + if (iov[0].iov_len < 4) /* CDR header */ + return NULL; + struct ddsi_serdata_default *d = serdata_default_new_size (tp, kind, (uint32_t) size); + if (d == NULL) + return NULL; + + memcpy (&d->hdr, iov[0].iov_base, sizeof (d->hdr)); + assert (d->hdr.identifier == CDR_LE || d->hdr.identifier == CDR_BE); + serdata_default_append_blob (&d, 1, iov[0].iov_len - 4, (const char *) iov[0].iov_base + 4); + for (ddsrt_msg_iovlen_t i = 1; i < niov; i++) + serdata_default_append_blob (&d, 1, iov[i].iov_len, iov[i].iov_base); + + const bool needs_bswap = (d->hdr.identifier != NATIVE_ENCODING); + d->hdr.identifier = NATIVE_ENCODING; + const uint32_t pad = ddsrt_fromBE2u (d->hdr.options) & 2; + if (d->pos < pad) + { + ddsi_serdata_unref (&d->c); + return NULL; + } + else if (!dds_stream_normalize (d->data, d->pos - pad, needs_bswap, tp, kind == SDK_KEY)) + { + ddsi_serdata_unref (&d->c); + return NULL; + } + else + { + dds_istream_t is; + dds_istream_from_serdata_default (&is, d); + dds_stream_extract_keyhash (&is, &d->keyhash, tp, kind == SDK_KEY); + return d; + } +} + static struct ddsi_serdata *serdata_default_from_ser (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const struct nn_rdata *fragchain, size_t size) { struct ddsi_serdata_default *d; @@ -276,6 +321,14 @@ static struct ddsi_serdata *serdata_default_from_ser (const struct ddsi_sertopic return fix_serdata_default (d, tpcmn->serdata_basehash); } +static struct ddsi_serdata *serdata_default_from_ser_iov (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size) +{ + struct ddsi_serdata_default *d; + if ((d = serdata_default_from_ser_iov_common (tpcmn, kind, niov, iov, size)) == NULL) + return NULL; + return fix_serdata_default (d, tpcmn->serdata_basehash); +} + static struct ddsi_serdata *serdata_default_from_ser_nokey (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const struct nn_rdata *fragchain, size_t size) { struct ddsi_serdata_default *d; @@ -284,6 +337,14 @@ static struct ddsi_serdata *serdata_default_from_ser_nokey (const struct ddsi_se return fix_serdata_default_nokey (d, tpcmn->serdata_basehash); } +static struct ddsi_serdata *serdata_default_from_ser_iov_nokey (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size) +{ + struct ddsi_serdata_default *d; + if ((d = serdata_default_from_ser_iov_common (tpcmn, kind, niov, iov, size)) == NULL) + return NULL; + return fix_serdata_default_nokey (d, tpcmn->serdata_basehash); +} + static struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash) { /* FIXME: not quite sure this is correct, though a check against a specially hacked OpenSplice suggests it is */ @@ -630,6 +691,7 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_cdr = { .eqkey = serdata_default_eqkey, .free = serdata_default_free, .from_ser = serdata_default_from_ser, + .from_ser_iov = serdata_default_from_ser_iov, .from_keyhash = ddsi_serdata_from_keyhash_cdr, .from_sample = serdata_default_from_sample_cdr, .to_ser = serdata_default_to_ser, @@ -646,6 +708,7 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_cdr_nokey = { .eqkey = serdata_default_eqkey_nokey, .free = serdata_default_free, .from_ser = serdata_default_from_ser_nokey, + .from_ser_iov = serdata_default_from_ser_iov_nokey, .from_keyhash = ddsi_serdata_from_keyhash_cdr_nokey, .from_sample = serdata_default_from_sample_cdr_nokey, .to_ser = serdata_default_to_ser, @@ -662,6 +725,7 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_plist = { .eqkey = serdata_default_eqkey, .free = serdata_default_free, .from_ser = serdata_default_from_ser, + .from_ser_iov = serdata_default_from_ser_iov, .from_keyhash = 0, .from_sample = serdata_default_from_sample_plist, .to_ser = serdata_default_to_ser, @@ -678,6 +742,7 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_rawcdr = { .eqkey = serdata_default_eqkey, .free = serdata_default_free, .from_ser = serdata_default_from_ser, + .from_ser_iov = serdata_default_from_ser_iov, .from_keyhash = 0, .from_sample = serdata_default_from_sample_rawcdr, .to_ser = serdata_default_to_ser, diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index ee58f1e..456a98e 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -259,10 +259,28 @@ static void local_reader_ary_fini (struct local_reader_ary *x) static void local_reader_ary_insert (struct local_reader_ary *x, struct reader *rd) { ddsrt_mutex_lock (&x->rdary_lock); + x->rdary = ddsrt_realloc (x->rdary, (x->n_readers + 2) * sizeof (*x->rdary)); + if (x->n_readers <= 1 || rd->topic == x->rdary[x->n_readers - 1]->topic) + { + /* if the first or second reader, or if the topic is the same as that of + the last one in the list simply appending the new will maintain order */ + x->rdary[x->n_readers] = rd; + } + else + { + uint32_t i; + for (i = 0; i < x->n_readers; i++) + if (x->rdary[i]->topic == rd->topic) + break; + if (i < x->n_readers) + { + /* shift any with the same topic plus whichever follow to make room */ + memmove (&x->rdary[i + 1], &x->rdary[i], (x->n_readers - i) * sizeof (x->rdary[i])); + } + x->rdary[i] = rd; + } + x->rdary[x->n_readers + 1] = NULL; x->n_readers++; - x->rdary = ddsrt_realloc (x->rdary, (x->n_readers + 1) * sizeof (*x->rdary)); - x->rdary[x->n_readers - 1] = rd; - x->rdary[x->n_readers] = NULL; ddsrt_mutex_unlock (&x->rdary_lock); } @@ -271,13 +289,20 @@ static void local_reader_ary_remove (struct local_reader_ary *x, struct reader * uint32_t i; ddsrt_mutex_lock (&x->rdary_lock); for (i = 0; i < x->n_readers; i++) - { if (x->rdary[i] == rd) break; - } assert (i < x->n_readers); - /* if i == N-1 copy is a no-op */ - x->rdary[i] = x->rdary[x->n_readers-1]; + if (i + 1 < x->n_readers) + { + /* dropping the final one never requires any fixups; dropping one that has + the same topic as the last is as simple as moving the last one in the + removed one's location; else shift all following readers to keep it + grouped by topic */ + if (rd->topic == x->rdary[x->n_readers - 1]->topic) + x->rdary[i] = x->rdary[x->n_readers - 1]; + else + memmove (&x->rdary[i], &x->rdary[i + 1], (x->n_readers - i - 1) * sizeof (x->rdary[i])); + } x->n_readers--; x->rdary[x->n_readers] = NULL; x->rdary = ddsrt_realloc (x->rdary, (x->n_readers + 1) * sizeof (*x->rdary)); @@ -4537,7 +4562,6 @@ int new_proxy_writer (struct q_globals *gv, const struct ddsi_guid *ppguid, cons pwr->evq = evq; pwr->ddsi2direct_cb = 0; pwr->ddsi2direct_cbarg = 0; - local_reader_ary_init (&pwr->rdary); /* locking the entity prevents matching while the built-in topic hasn't been published yet */ diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index b0d14b1..0b8e118 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -45,6 +45,7 @@ #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/q_receive.h" #include "dds/ddsi/ddsi_rhc.h" +#include "dds/ddsi/ddsi_deliver_locally.h" #include "dds/ddsi/q_transmit.h" #include "dds/ddsi/q_globals.h" @@ -1733,12 +1734,30 @@ static struct ddsi_serdata *get_serdata (struct ddsi_sertopic const * const topi return sd; } -static struct ddsi_serdata *new_sample_from_data (struct ddsi_tkmap_instance **tk1, struct q_globals *gv, const struct nn_rsample_info *sampleinfo, unsigned char data_smhdr_flags, const nn_plist_t *qos, const struct nn_rdata *fragchain, unsigned statusinfo, nn_wctime_t tstamp, struct ddsi_sertopic const * const topic) +struct remote_sourceinfo { + const struct nn_rsample_info *sampleinfo; + unsigned char data_smhdr_flags; + const nn_plist_t *qos; + const struct nn_rdata *fragchain; + unsigned statusinfo; + nn_wctime_t tstamp; +}; + +static struct ddsi_serdata *remote_make_sample (struct ddsi_tkmap_instance **tk, struct q_globals *gv, struct ddsi_sertopic const * const topic, void *vsourceinfo) { + /* hopefully the compiler figures out that these are just aliases and doesn't reload them + unnecessarily from memory */ + const struct remote_sourceinfo * __restrict si = vsourceinfo; + const struct nn_rsample_info * __restrict sampleinfo = si->sampleinfo; + const struct nn_rdata * __restrict fragchain = si->fragchain; + const uint32_t statusinfo = si->statusinfo; + const unsigned char data_smhdr_flags = si->data_smhdr_flags; + const nn_wctime_t tstamp = si->tstamp; + const nn_plist_t * __restrict qos = si->qos; const char *failmsg = NULL; struct ddsi_serdata *sample = NULL; - if (statusinfo == 0) + if (si->statusinfo == 0) { /* normal write */ if (!(data_smhdr_flags & DATA_FLAG_DATAFLAG) || sampleinfo->size == 0) @@ -1752,7 +1771,7 @@ static struct ddsi_serdata *new_sample_from_data (struct ddsi_tkmap_instance **t "data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": write without proper payload (data_smhdr_flags 0x%x size %"PRIu32")\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (guid), sampleinfo->seq, - data_smhdr_flags, sampleinfo->size); + si->data_smhdr_flags, sampleinfo->size); return NULL; } sample = get_serdata (topic, fragchain, sampleinfo->size, 0, statusinfo, tstamp); @@ -1807,7 +1826,7 @@ static struct ddsi_serdata *new_sample_from_data (struct ddsi_tkmap_instance **t } else { - if ((*tk1 = ddsi_tkmap_lookup_instance_ref (gv->m_tkmap, sample)) == NULL) + if ((*tk = ddsi_tkmap_lookup_instance_ref (gv->m_tkmap, sample)) == NULL) { ddsi_serdata_unref (sample); sample = NULL; @@ -1831,12 +1850,6 @@ static struct ddsi_serdata *new_sample_from_data (struct ddsi_tkmap_instance **t return sample; } -static void free_sample_after_store (struct q_globals *gv, struct ddsi_serdata *sample, struct ddsi_tkmap_instance *tk) -{ - ddsi_tkmap_instance_unref (gv->m_tkmap, tk); - ddsi_serdata_unref (sample); -} - unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr) { switch ((SubmessageKind_t) smhdr->submessageId) @@ -1858,28 +1871,51 @@ unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr) } } -static struct reader *proxy_writer_first_in_sync_reader (struct proxy_writer *pwr, ddsrt_avl_iter_t *it) +static struct reader *proxy_writer_first_in_sync_reader (struct entity_index *entity_index, struct entity_common *pwrcmn, ddsrt_avl_iter_t *it) { + assert (pwrcmn->kind == EK_PROXY_WRITER); + struct proxy_writer *pwr = (struct proxy_writer *) pwrcmn; struct pwr_rd_match *m; struct reader *rd; for (m = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, it); m != NULL; m = ddsrt_avl_iter_next (it)) - if (m->in_sync == PRMSS_SYNC && (rd = entidx_lookup_reader_guid (pwr->e.gv->entity_index, &m->rd_guid)) != NULL) + if (m->in_sync == PRMSS_SYNC && (rd = entidx_lookup_reader_guid (entity_index, &m->rd_guid)) != NULL) return rd; return NULL; } -static struct reader *proxy_writer_next_in_sync_reader (struct proxy_writer *pwr, ddsrt_avl_iter_t *it) +static struct reader *proxy_writer_next_in_sync_reader (struct entity_index *entity_index, ddsrt_avl_iter_t *it) { struct pwr_rd_match *m; struct reader *rd; for (m = ddsrt_avl_iter_next (it); m != NULL; m = ddsrt_avl_iter_next (it)) - if (m->in_sync == PRMSS_SYNC && (rd = entidx_lookup_reader_guid (pwr->e.gv->entity_index, &m->rd_guid)) != NULL) + if (m->in_sync == PRMSS_SYNC && (rd = entidx_lookup_reader_guid (entity_index, &m->rd_guid)) != NULL) return rd; return NULL; } +static dds_return_t remote_on_delivery_failure_fastpath (struct entity_common *source_entity, bool source_entity_locked, struct local_reader_ary *fastpath_rdary, void *vsourceinfo) +{ + (void) vsourceinfo; + ddsrt_mutex_unlock (&fastpath_rdary->rdary_lock); + if (source_entity_locked) + ddsrt_mutex_unlock (&source_entity->lock); + + dds_sleepfor (DDS_MSECS (10)); + + if (source_entity_locked) + ddsrt_mutex_lock (&source_entity->lock); + ddsrt_mutex_lock (&fastpath_rdary->rdary_lock); + return DDS_RETCODE_TRY_AGAIN; +} + static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const ddsi_guid_t *rdguid, int pwr_locked) { + static const struct deliver_locally_ops deliver_locally_ops = { + .makesample = remote_make_sample, + .first_reader = proxy_writer_first_in_sync_reader, + .next_reader = proxy_writer_next_in_sync_reader, + .on_failure_fastpath = remote_on_delivery_failure_fastpath + }; struct receiver_state const * const rst = sampleinfo->rst; struct q_globals * const gv = rst->gv; struct proxy_writer * const pwr = sampleinfo->pwr; @@ -1953,108 +1989,22 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st struct ddsi_writer_info wrinfo; ddsi_make_writer_info (&wrinfo, &pwr->e, pwr->c.xqos, statusinfo); - if (rdguid == NULL) - { - /* FIXME: Retry loop, for re-delivery of rejected reliable samples. Is a - temporary hack till throttling back of writer is implemented (with late - acknowledgement of sample and nack). */ - retry: - ddsrt_mutex_lock (&pwr->rdary.rdary_lock); - if (pwr->rdary.fastpath_ok) - { - struct reader ** const rdary = pwr->rdary.rdary; - if (rdary[0]) - { - struct ddsi_serdata *payload; - struct ddsi_tkmap_instance *tk; - if ((payload = new_sample_from_data (&tk, gv, sampleinfo, data_smhdr_flags, &qos, fragchain, statusinfo, tstamp, rdary[0]->topic)) != NULL) - { - ETRACE (pwr, " => EVERYONE\n"); - uint32_t i = 0; - do { - if (!ddsi_rhc_store (rdary[i]->rhc, &wrinfo, payload, tk)) - { - if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock); - ddsrt_mutex_unlock (&pwr->rdary.rdary_lock); - /* It is painful to drop the sample, but there is no guarantee that the readers - will still be there after unlocking; indeed, it is even possible that the - topic definition got replaced in the meantime. Fortunately, this is in - the midst of a FIXME for many other reasons. */ - free_sample_after_store (gv, payload, tk); - dds_sleepfor (DDS_MSECS (10)); - if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock); - goto retry; - } - } while (rdary[++i]); - free_sample_after_store (gv, payload, tk); - } - } - ddsrt_mutex_unlock (&pwr->rdary.rdary_lock); - } - else - { - /* When deleting, pwr is no longer accessible via the hash - tables, and consequently, a reader may be deleted without - it being possible to remove it from rdary. The primary - reason rdary exists is to avoid locking the proxy writer - but this is less of an issue when we are deleting it, so - we fall back to using the GUIDs so that we can deliver all - samples we received from it. As writer being deleted any - reliable samples that are rejected are simply discarded. */ - ddsrt_avl_iter_t it; - struct reader *rd; - ddsrt_mutex_unlock (&pwr->rdary.rdary_lock); - if (!pwr_locked) ddsrt_mutex_lock (&pwr->e.lock); - if ((rd = proxy_writer_first_in_sync_reader (pwr, &it)) != NULL) - { - struct ddsi_serdata *payload; - struct ddsi_tkmap_instance *tk; - if ((payload = new_sample_from_data (&tk, gv, sampleinfo, data_smhdr_flags, &qos, fragchain, statusinfo, tstamp, rd->topic)) != NULL) - { - ETRACE (pwr, " =>"); - do { - ETRACE (pwr, " "PGUIDFMT, PGUID (rd->e.guid)); - (void) ddsi_rhc_store (rd->rhc, &wrinfo, payload, tk); - rd = proxy_writer_next_in_sync_reader (pwr, &it); - } while (rd != NULL); - free_sample_after_store (gv, payload, tk); - ETRACE (pwr, "\n"); - } - } - if (!pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock); - } - - ddsrt_atomic_st32 (&pwr->next_deliv_seq_lowword, (uint32_t) (sampleinfo->seq + 1)); - } + struct remote_sourceinfo sourceinfo = { + .sampleinfo = sampleinfo, + .data_smhdr_flags = data_smhdr_flags, + .qos = &qos, + .fragchain = fragchain, + .statusinfo = statusinfo, + .tstamp = tstamp + }; + if (rdguid) + (void) deliver_locally_one (gv, &pwr->e, pwr_locked != 0, rdguid, &wrinfo, &deliver_locally_ops, &sourceinfo); else { - struct reader *rd = entidx_lookup_reader_guid (gv->entity_index, rdguid); - if (rd != NULL) - { - struct ddsi_serdata *payload; - struct ddsi_tkmap_instance *tk; - if ((payload = new_sample_from_data (&tk, gv, sampleinfo, data_smhdr_flags, &qos, fragchain, statusinfo, tstamp, rd->topic)) != NULL) - { - ETRACE (pwr, " =>"PGUIDFMT"\n", PGUID (*rdguid)); - /* FIXME: why look up rd,pwr again? Their states remains valid while the thread stays - "awake" (although a delete can be initiated), and blocking like this is a stopgap - anyway -- quite possibly to abort once either is deleted */ - while (!ddsi_rhc_store (rd->rhc, &wrinfo, payload, tk)) - { - if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock); - dds_sleepfor (DDS_MSECS (1)); - if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock); - if (entidx_lookup_reader_guid (gv->entity_index, rdguid) == NULL || - entidx_lookup_proxy_writer_guid (gv->entity_index, &pwr->e.guid) == NULL) - { - /* give up when reader or proxy writer no longer accessible */ - break; - } - } - free_sample_after_store (gv, payload, tk); - } - } + (void) deliver_locally_allinsync (gv, &pwr->e, pwr_locked != 0, &pwr->rdary, &wrinfo, &deliver_locally_ops, &sourceinfo); + ddsrt_atomic_st32 (&pwr->next_deliv_seq_lowword, (uint32_t) (sampleinfo->seq + 1)); } + nn_plist_fini (&qos); return 0; } From 551dae69a4da4c5564d91c4d6ee55df496bda22b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 3 Feb 2020 10:20:34 +0100 Subject: [PATCH 25/28] Rename q_globals to ddsi_domaingv The name (not its definition) now leaks out in ddsi_sertopic, and the messy old names really shouldn't pollute the interface any more than necessary. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds__rhc_default.h | 4 +- src/core/ddsc/src/dds__serdata_builtintopic.h | 2 +- src/core/ddsc/src/dds__types.h | 4 +- src/core/ddsc/src/dds__whc.h | 4 +- src/core/ddsc/src/dds_builtin.c | 2 +- src/core/ddsc/src/dds_domain.c | 2 +- src/core/ddsc/src/dds_init.c | 2 +- src/core/ddsc/src/dds_instance.c | 2 +- src/core/ddsc/src/dds_matched.c | 2 +- src/core/ddsc/src/dds_participant.c | 2 +- src/core/ddsc/src/dds_publisher.c | 2 +- src/core/ddsc/src/dds_read.c | 2 +- src/core/ddsc/src/dds_reader.c | 2 +- src/core/ddsc/src/dds_rhc_default.c | 10 +-- src/core/ddsc/src/dds_subscriber.c | 2 +- src/core/ddsc/src/dds_topic.c | 6 +- src/core/ddsc/src/dds_whc.c | 6 +- src/core/ddsc/src/dds_whc_builtintopic.c | 2 +- src/core/ddsc/src/dds_write.c | 4 +- src/core/ddsc/src/dds_writer.c | 6 +- src/core/ddsi/CMakeLists.txt | 2 +- .../ddsi/include/dds/ddsi/ddsi_deadline.h | 4 +- .../include/dds/ddsi/ddsi_deliver_locally.h | 8 +-- .../dds/ddsi/{q_globals.h => ddsi_domaingv.h} | 15 ++--- .../ddsi/include/dds/ddsi/ddsi_entity_index.h | 4 +- .../ddsi/include/dds/ddsi/ddsi_lifespan.h | 4 +- src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h | 6 +- src/core/ddsi/include/dds/ddsi/ddsi_pmd.h | 4 +- src/core/ddsi/include/dds/ddsi/ddsi_raweth.h | 2 +- .../ddsi/include/dds/ddsi/ddsi_sertopic.h | 8 +-- src/core/ddsi/include/dds/ddsi/ddsi_tcp.h | 8 +-- .../ddsi/include/dds/ddsi/ddsi_threadmon.h | 6 +- src/core/ddsi/include/dds/ddsi/ddsi_tkmap.h | 4 +- src/core/ddsi/include/dds/ddsi/ddsi_tran.h | 20 +++--- src/core/ddsi/include/dds/ddsi/ddsi_udp.h | 2 +- src/core/ddsi/include/dds/ddsi/q_addrset.h | 26 ++++---- src/core/ddsi/include/dds/ddsi/q_debmon.h | 2 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 40 ++++++------ src/core/ddsi/include/dds/ddsi/q_gc.h | 4 +- src/core/ddsi/include/dds/ddsi/q_init.h | 4 +- src/core/ddsi/include/dds/ddsi/q_lease.h | 8 +-- src/core/ddsi/include/dds/ddsi/q_nwif.h | 6 +- src/core/ddsi/include/dds/ddsi/q_pcap.h | 4 +- src/core/ddsi/include/dds/ddsi/q_radmin.h | 4 +- src/core/ddsi/include/dds/ddsi/q_receive.h | 2 +- src/core/ddsi/include/dds/ddsi/q_rtps.h | 14 ++-- src/core/ddsi/include/dds/ddsi/q_thread.h | 10 +-- src/core/ddsi/include/dds/ddsi/q_transmit.h | 2 +- src/core/ddsi/include/dds/ddsi/q_xmsg.h | 10 +-- src/core/ddsi/src/ddsi_deadline.c | 2 +- src/core/ddsi/src/ddsi_deliver_locally.c | 16 ++--- src/core/ddsi/src/ddsi_entity_index.c | 6 +- src/core/ddsi/src/ddsi_ipaddr.c | 2 +- src/core/ddsi/src/ddsi_lifespan.c | 2 +- src/core/ddsi/src/ddsi_mcgroup.c | 10 +-- src/core/ddsi/src/ddsi_pmd.c | 8 +-- src/core/ddsi/src/ddsi_raweth.c | 6 +- src/core/ddsi/src/ddsi_serdata_default.c | 2 +- src/core/ddsi/src/ddsi_sertopic.c | 6 +- src/core/ddsi/src/ddsi_ssl.c | 16 ++--- src/core/ddsi/src/ddsi_tcp.c | 6 +- src/core/ddsi/src/ddsi_threadmon.c | 12 ++-- src/core/ddsi/src/ddsi_tkmap.c | 6 +- src/core/ddsi/src/ddsi_tran.c | 18 +++--- src/core/ddsi/src/ddsi_udp.c | 4 +- src/core/ddsi/src/q_addrset.c | 32 +++++----- src/core/ddsi/src/q_ddsi_discovery.c | 32 +++++----- src/core/ddsi/src/q_debmon.c | 10 +-- src/core/ddsi/src/q_entity.c | 64 +++++++++---------- src/core/ddsi/src/q_gc.c | 8 +-- src/core/ddsi/src/q_init.c | 51 ++++++++------- src/core/ddsi/src/q_lease.c | 18 +++--- src/core/ddsi/src/q_nwif.c | 14 ++-- src/core/ddsi/src/q_pcap.c | 6 +- src/core/ddsi/src/q_plist.c | 2 +- src/core/ddsi/src/q_radmin.c | 6 +- src/core/ddsi/src/q_receive.c | 30 ++++----- src/core/ddsi/src/q_thread.c | 18 +++--- src/core/ddsi/src/q_transmit.c | 30 ++++----- src/core/ddsi/src/q_xevent.c | 22 +++---- src/core/ddsi/src/q_xmsg.c | 28 ++++---- src/core/xtests/rhc_torture/rhc_torture.c | 16 ++--- 82 files changed, 402 insertions(+), 408 deletions(-) rename src/core/ddsi/include/dds/ddsi/{q_globals.h => ddsi_domaingv.h} (96%) diff --git a/src/core/ddsc/src/dds__rhc_default.h b/src/core/ddsc/src/dds__rhc_default.h index f6b2413..cf8fab3 100644 --- a/src/core/ddsc/src/dds__rhc_default.h +++ b/src/core/ddsc/src/dds__rhc_default.h @@ -19,11 +19,11 @@ extern "C" { struct dds_rhc; struct dds_reader; struct ddsi_sertopic; -struct q_globals; +struct ddsi_domaingv; struct dds_rhc_default; struct rhc_sample; -DDS_EXPORT struct dds_rhc *dds_rhc_default_new_xchecks (dds_reader *reader, struct q_globals *gv, const struct ddsi_sertopic *topic, bool xchecks); +DDS_EXPORT struct dds_rhc *dds_rhc_default_new_xchecks (dds_reader *reader, struct ddsi_domaingv *gv, const struct ddsi_sertopic *topic, bool xchecks); DDS_EXPORT struct dds_rhc *dds_rhc_default_new (struct dds_reader *reader, const struct ddsi_sertopic *topic); #ifdef DDSI_INCLUDE_LIFESPAN DDS_EXPORT nn_mtime_t dds_rhc_default_sample_expired_cb(void *hc, nn_mtime_t tnow); diff --git a/src/core/ddsc/src/dds__serdata_builtintopic.h b/src/core/ddsc/src/dds__serdata_builtintopic.h index e95aa36..825e7cf 100644 --- a/src/core/ddsc/src/dds__serdata_builtintopic.h +++ b/src/core/ddsc/src/dds__serdata_builtintopic.h @@ -33,7 +33,7 @@ enum ddsi_sertopic_builtintopic_type { DSBT_WRITER }; -struct q_globals; +struct ddsi_domaingv; struct ddsi_sertopic_builtintopic { struct ddsi_sertopic c; enum ddsi_sertopic_builtintopic_type type; diff --git a/src/core/ddsc/src/dds__types.h b/src/core/ddsc/src/dds__types.h index 362a65c..8abc9cc 100644 --- a/src/core/ddsc/src/dds__types.h +++ b/src/core/ddsc/src/dds__types.h @@ -17,7 +17,7 @@ #include "dds/dds.h" #include "dds/ddsrt/sync.h" #include "dds/ddsi/q_rtps.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsrt/avl.h" #include "dds/ddsi/ddsi_builtin_topic_if.h" #include "dds__handles.h" @@ -227,7 +227,7 @@ typedef struct dds_domain { struct local_orphan_writer *builtintopic_writer_subscriptions; struct ddsi_builtin_topic_interface btif; - struct q_globals gv; + struct ddsi_domaingv gv; } dds_domain; typedef struct dds_subscriber { diff --git a/src/core/ddsc/src/dds__whc.h b/src/core/ddsc/src/dds__whc.h index a252ba0..5f3c7a9 100644 --- a/src/core/ddsc/src/dds__whc.h +++ b/src/core/ddsc/src/dds__whc.h @@ -18,11 +18,11 @@ extern "C" { #endif -struct q_globals; +struct ddsi_domaingv; struct whc_writer_info; struct dds_writer; -struct whc *whc_new (struct q_globals *gv, const struct whc_writer_info *wrinfo); +struct whc *whc_new (struct ddsi_domaingv *gv, const struct whc_writer_info *wrinfo); struct whc_writer_info *whc_make_wrinfo (struct dds_writer *wr, const dds_qos_t *qos); void whc_free_wrinfo (struct whc_writer_info *); diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index cae0eb3..1d95e91 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -15,7 +15,7 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_config.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_plist.h" /* for nn_keyhash */ #include "dds__init.h" #include "dds__domain.h" diff --git a/src/core/ddsc/src/dds_domain.c b/src/core/ddsc/src/dds_domain.c index 0a1ffe1..489b49c 100644 --- a/src/core/ddsc/src/dds_domain.c +++ b/src/core/ddsc/src/dds_domain.c @@ -27,7 +27,7 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_gc.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" static dds_return_t dds_domain_free (dds_entity *vdomain); diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 7444a26..05f0d2c 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -30,7 +30,7 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_gc.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/version.h" static void dds_close (struct dds_entity *e); diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index 74c2089..cf82de8 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -21,7 +21,7 @@ #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" dds_return_t dds_writedispose (dds_entity_t writer, const void *data) { diff --git a/src/core/ddsc/src/dds_matched.c b/src/core/ddsc/src/dds_matched.c index 4ca9cc2..c46f2b9 100644 --- a/src/core/ddsc/src/dds_matched.c +++ b/src/core/ddsc/src/dds_matched.c @@ -15,7 +15,7 @@ #include "dds/dds.h" #include "dds/version.h" #include "dds/ddsi/q_config.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/q_thread.h" diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 47ee768..6dbebf1 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -18,7 +18,7 @@ #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_plist.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/ddsi_entity_index.h" #include "dds/version.h" #include "dds__init.h" diff --git a/src/core/ddsc/src/dds_publisher.c b/src/core/ddsc/src/dds_publisher.c index b6f0792..f319956 100644 --- a/src/core/ddsc/src/dds_publisher.c +++ b/src/core/ddsc/src/dds_publisher.c @@ -19,7 +19,7 @@ #include "dds__qos.h" #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/q_entity.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/version.h" DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_publisher) diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 3901cb0..394b7e4 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -18,7 +18,7 @@ #include "dds/ddsi/q_thread.h" #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/q_entity.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/ddsi_sertopic.h" /* diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 3a6b385..c44c0af 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -26,7 +26,7 @@ #include "dds__qos.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds__builtin.h" #include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/ddsi_entity_index.h" diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index cdce42e..e664e0a 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -35,7 +35,7 @@ #include "dds/ddsi/q_xqos.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_config.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_radmin.h" /* sampleinfo */ #include "dds/ddsi/q_entity.h" /* proxy_writer_info */ #include "dds/ddsi/ddsi_serdata.h" @@ -273,13 +273,13 @@ struct rhc_instance { uint32_t disposed_gen; /* bloody generation counters - worst invention of mankind */ uint32_t no_writers_gen; /* __/ */ int32_t strength; /* "current" ownership strength */ - ddsi_guid_t wr_guid; /* guid of last writer (if wr_iid != 0 then wr_guid is the corresponding guid, else undef) */ + ddsi_guid_t wr_guid; /* guid of last writer (if wr_iid != 0 then wr_guid is the corresponding guid, else undef) */ nn_wctime_t tstamp; /* source time stamp of last update */ struct ddsrt_circlist_elem nonempty_list; /* links non-empty instances in arbitrary ordering */ #ifdef DDSI_INCLUDE_DEADLINE_MISSED struct deadline_elem deadline; /* element in deadline missed administration */ #endif - struct ddsi_tkmap_instance *tk; /* backref into TK for unref'ing */ + struct ddsi_tkmap_instance *tk;/* backref into TK for unref'ing */ struct rhc_sample a_sample; /* pre-allocated storage for 1 sample */ }; @@ -318,7 +318,7 @@ struct dds_rhc_default { dds_reader *reader; /* reader -- may be NULL (used by rhc_torture) */ struct ddsi_tkmap *tkmap; /* back pointer to tkmap */ - struct q_globals *gv; /* globals -- so far only for log config */ + struct ddsi_domaingv *gv; /* globals -- so far only for log config */ const struct ddsi_sertopic *topic; /* topic description */ uint32_t history_depth; /* depth, 1 for KEEP_LAST_1, 2**32-1 for KEEP_ALL */ @@ -637,7 +637,7 @@ nn_mtime_t dds_rhc_default_deadline_missed_cb(void *hc, nn_mtime_t tnow) } #endif /* DDSI_INCLUDE_DEADLINE_MISSED */ -struct dds_rhc *dds_rhc_default_new_xchecks (dds_reader *reader, struct q_globals *gv, const struct ddsi_sertopic *topic, bool xchecks) +struct dds_rhc *dds_rhc_default_new_xchecks (dds_reader *reader, struct ddsi_domaingv *gv, const struct ddsi_sertopic *topic, bool xchecks) { struct dds_rhc_default *rhc = ddsrt_malloc (sizeof (*rhc)); memset (rhc, 0, sizeof (*rhc)); diff --git a/src/core/ddsc/src/dds_subscriber.c b/src/core/ddsc/src/dds_subscriber.c index 0729064..19c923c 100644 --- a/src/core/ddsc/src/dds_subscriber.c +++ b/src/core/ddsc/src/dds_subscriber.c @@ -16,7 +16,7 @@ #include "dds__qos.h" #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/q_entity.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsrt/heap.h" #include "dds/version.h" diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 7b40f9b..815abed 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -31,7 +31,7 @@ #include "dds/ddsi/q_ddsi_discovery.h" #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/q_plist.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds__serdata_builtintopic.h" DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_topic) @@ -222,7 +222,7 @@ const struct dds_entity_deriver dds_entity_deriver_topic = { */ static dds_return_t lookup_and_check_ktopic (struct dds_ktopic **ktp_out, dds_participant *pp, const char *name, const char *type_name, const dds_qos_t *new_qos) { - struct q_globals * const gv = &pp->m_entity.m_domain->gv; + struct ddsi_domaingv * const gv = &pp->m_entity.m_domain->gv; struct dds_ktopic *ktp; if ((ktp = *ktp_out = ddsrt_avl_lookup (&participant_ktopics_treedef, &pp->m_ktopics, name)) == NULL) { @@ -315,7 +315,7 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s * Leaving the topic QoS sparse means a default-default topic QoS of * best-effort will do "the right thing" and let a writer still default to * reliable ... (and keep behaviour unchanged) */ - struct q_globals * const gv = &pp->m_entity.m_domain->gv; + struct ddsi_domaingv * const gv = &pp->m_entity.m_domain->gv; if ((rc = nn_xqos_valid (&gv->logconfig, new_qos)) != DDS_RETCODE_OK) { dds_delete_qos (new_qos); diff --git a/src/core/ddsc/src/dds_whc.c b/src/core/ddsc/src/dds_whc.c index 8c071ec..b553cc5 100644 --- a/src/core/ddsc/src/dds_whc.c +++ b/src/core/ddsc/src/dds_whc.c @@ -31,7 +31,7 @@ #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_freelist.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_entity.h" #include "dds__whc.h" #include "dds__entity.h" @@ -103,7 +103,7 @@ struct whc_impl { uint32_t fragment_size; uint64_t total_bytes; /* total number of bytes pushed in */ unsigned xchecks: 1; - struct q_globals *gv; + struct ddsi_domaingv *gv; struct ddsi_tkmap *tkmap; struct whc_writer_info wrinfo; seqno_t max_drop_seq; /* samples in whc with seq <= max_drop_seq => transient-local */ @@ -439,7 +439,7 @@ void whc_free_wrinfo (struct whc_writer_info *wrinfo) ddsrt_free (wrinfo); } -struct whc *whc_new (struct q_globals *gv, const struct whc_writer_info *wrinfo) +struct whc *whc_new (struct ddsi_domaingv *gv, const struct whc_writer_info *wrinfo) { size_t sample_overhead = 80; /* INFO_TS, DATA (estimate), inline QoS */ struct whc_impl *whc; diff --git a/src/core/ddsc/src/dds_whc_builtintopic.c b/src/core/ddsc/src/dds_whc_builtintopic.c index 36a27f0..cf48167 100644 --- a/src/core/ddsc/src/dds_whc_builtintopic.c +++ b/src/core/ddsc/src/dds_whc_builtintopic.c @@ -19,7 +19,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/q_entity.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds__serdata_builtintopic.h" #include "dds__whc_builtintopic.h" diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 29fc12c..3ef2f74 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -24,7 +24,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_radmin.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/ddsi_deliver_locally.h" dds_return_t dds_write (dds_entity_t writer, const void *data) @@ -93,7 +93,7 @@ struct local_sourceinfo { nn_mtime_t timeout; }; -static struct ddsi_serdata *local_make_sample (struct ddsi_tkmap_instance **tk, struct q_globals *gv, struct ddsi_sertopic const * const topic, void *vsourceinfo) +static struct ddsi_serdata *local_make_sample (struct ddsi_tkmap_instance **tk, struct ddsi_domaingv *gv, struct ddsi_sertopic const * const topic, void *vsourceinfo) { struct local_sourceinfo *si = vsourceinfo; if (topic == si->src_topic) diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 7c5040b..382b084 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -15,7 +15,7 @@ #include "dds/version.h" #include "dds/ddsrt/static_assert.h" #include "dds/ddsi/q_config.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_xmsg.h" @@ -181,7 +181,7 @@ static void dds_writer_interrupt (dds_entity *e) ddsrt_nonnull_all; static void dds_writer_interrupt (dds_entity *e) { - struct q_globals * const gv = &e->m_domain->gv; + struct ddsi_domaingv * const gv = &e->m_domain->gv; thread_state_awake (lookup_thread_state (), gv); unblock_throttled_writer (gv, &e->m_guid); thread_state_asleep (lookup_thread_state ()); @@ -192,7 +192,7 @@ static void dds_writer_close (dds_entity *e) ddsrt_nonnull_all; static void dds_writer_close (dds_entity *e) { struct dds_writer * const wr = (struct dds_writer *) e; - struct q_globals * const gv = &e->m_domain->gv; + struct ddsi_domaingv * const gv = &e->m_domain->gv; struct thread_state1 * const ts1 = lookup_thread_state (); thread_state_awake (ts1, gv); nn_xpack_send (wr->m_xp, false); diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 01c566d..74b0fda 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -94,6 +94,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" ddsi_entity_index.h ddsi_deadline.h ddsi_deliver_locally.h + ddsi_domaingv.h q_addrset.h q_bitset.h q_bswap.h @@ -104,7 +105,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" q_feature_check.h q_freelist.h q_gc.h - q_globals.h q_hbcontrol.h q_lat_estim.h q_lease.h diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_deadline.h b/src/core/ddsi/include/dds/ddsi/ddsi_deadline.h index 53c250d..4903eca 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_deadline.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_deadline.h @@ -14,7 +14,7 @@ #include "dds/ddsrt/circlist.h" #include "dds/ddsi/q_time.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_xevent.h" #if defined (__cplusplus) @@ -37,7 +37,7 @@ struct deadline_elem { nn_mtime_t t_deadline; }; -DDS_EXPORT void deadline_init (const struct q_globals *gv, struct deadline_adm *deadline_adm, size_t list_offset, size_t elem_offset, deadline_missed_cb_t deadline_missed_cb); +DDS_EXPORT void deadline_init (const struct ddsi_domaingv *gv, struct deadline_adm *deadline_adm, size_t list_offset, size_t elem_offset, deadline_missed_cb_t deadline_missed_cb); DDS_EXPORT void deadline_stop (const struct deadline_adm *deadline_adm); DDS_EXPORT void deadline_clear (struct deadline_adm *deadline_adm); DDS_EXPORT void deadline_fini (const struct deadline_adm *deadline_adm); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_deliver_locally.h b/src/core/ddsi/include/dds/ddsi/ddsi_deliver_locally.h index 5ecec40..53d584e 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_deliver_locally.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_deliver_locally.h @@ -24,7 +24,7 @@ extern "C" { #endif -struct q_globals; +struct ddsi_domaingv; struct ddsi_tkmap_instance; struct ddsi_sertopic; struct ddsi_serdata; @@ -34,7 +34,7 @@ struct entity_common; struct ddsi_writer_info; struct local_reader_ary; -typedef struct ddsi_serdata * (*deliver_locally_makesample_t) (struct ddsi_tkmap_instance **tk, struct q_globals *gv, struct ddsi_sertopic const * const topic, void *vsourceinfo); +typedef struct ddsi_serdata * (*deliver_locally_makesample_t) (struct ddsi_tkmap_instance **tk, struct ddsi_domaingv *gv, struct ddsi_sertopic const * const topic, void *vsourceinfo); typedef struct reader * (*deliver_locally_first_reader_t) (struct entity_index *entity_index, struct entity_common *source_entity, ddsrt_avl_iter_t *it); typedef struct reader * (*deliver_locally_next_reader_t) (struct entity_index *entity_index, ddsrt_avl_iter_t *it); @@ -51,9 +51,9 @@ struct deliver_locally_ops { deliver_locally_on_failure_fastpath_t on_failure_fastpath; }; -dds_return_t deliver_locally_one (struct q_globals *gv, struct entity_common *source_entity, bool source_entity_locked, const ddsi_guid_t *rdguid, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo); +dds_return_t deliver_locally_one (struct ddsi_domaingv *gv, struct entity_common *source_entity, bool source_entity_locked, const ddsi_guid_t *rdguid, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo); -dds_return_t deliver_locally_allinsync (struct q_globals *gv, struct entity_common *source_entity, bool source_entity_locked, struct local_reader_ary *fastpath_rdary, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo); +dds_return_t deliver_locally_allinsync (struct ddsi_domaingv *gv, struct entity_common *source_entity, bool source_entity_locked, struct local_reader_ary *fastpath_rdary, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h similarity index 96% rename from src/core/ddsi/include/dds/ddsi/q_globals.h rename to src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h index 954867e..542ccfd 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h @@ -9,8 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef Q_GLOBALS_H -#define Q_GLOBALS_H +#ifndef DDSI_DOMAINGV_H +#define DDSI_DOMAINGV_H #include @@ -68,7 +68,7 @@ enum recv_thread_mode { struct recv_thread_arg { enum recv_thread_mode mode; struct nn_rbufpool *rbpool; - struct q_globals *gv; + struct ddsi_domaingv *gv; union { struct { const nn_locator_t *loc; @@ -82,7 +82,7 @@ struct recv_thread_arg { struct deleted_participants_admin; -struct q_globals { +struct ddsi_domaingv { volatile int terminate; volatile int deaf; volatile int mute; @@ -270,11 +270,6 @@ struct q_globals { struct ddsi_sertopic *plist_topic; /* used for all discovery data */ struct ddsi_sertopic *rawcdr_topic; /* used for participant message data */ - /* Network ID needed by v_groupWrite -- FIXME: might as well pass it - to the receive thread instead of making it global (and that would - remove the need to include kernelModule.h) */ - uint32_t myNetworkId; - ddsrt_mutex_t sendq_lock; ddsrt_cond_t sendq_cond; unsigned sendq_length; @@ -299,4 +294,4 @@ struct q_globals { } #endif -#endif /* Q_GLOBALS_H */ +#endif /* DDSI_DOMAINGV_H */ diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_entity_index.h b/src/core/ddsi/include/dds/ddsi/ddsi_entity_index.h index 78a353e..54b6d59 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_entity_index.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_entity_index.h @@ -21,7 +21,7 @@ extern "C" { struct entity_index; struct ddsi_guid; -struct q_globals; +struct ddsi_domaingv; struct match_entities_range_key { union { @@ -63,7 +63,7 @@ struct entidx_enum at the protocol level slightly before the network reader can use it to transmit data. */ -struct entity_index *entity_index_new (struct q_globals *gv) ddsrt_nonnull_all; +struct entity_index *entity_index_new (struct ddsi_domaingv *gv) ddsrt_nonnull_all; void entity_index_free (struct entity_index *ei) ddsrt_nonnull_all; void entidx_insert_participant_guid (struct entity_index *ei, struct participant *pp) ddsrt_nonnull_all; diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_lifespan.h b/src/core/ddsi/include/dds/ddsi/ddsi_lifespan.h index 8ce3fee..7c1843c 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_lifespan.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_lifespan.h @@ -14,7 +14,7 @@ #include "dds/ddsrt/fibheap.h" #include "dds/ddsi/q_time.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #if defined (__cplusplus) extern "C" { @@ -35,7 +35,7 @@ struct lifespan_fhnode { nn_mtime_t t_expire; }; -DDS_EXPORT void lifespan_init (const struct q_globals *gv, struct lifespan_adm *lifespan_adm, size_t fh_offset, size_t fh_node_offset, sample_expired_cb_t sample_expired_cb); +DDS_EXPORT void lifespan_init (const struct ddsi_domaingv *gv, struct lifespan_adm *lifespan_adm, size_t fh_offset, size_t fh_node_offset, sample_expired_cb_t sample_expired_cb); DDS_EXPORT void lifespan_fini (const struct lifespan_adm *lifespan_adm); DDS_EXPORT nn_mtime_t lifespan_next_expired_locked (const struct lifespan_adm *lifespan_adm, nn_mtime_t tnow, void **sample); DDS_EXPORT void lifespan_register_sample_real (struct lifespan_adm *lifespan_adm, struct lifespan_fhnode *node); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h b/src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h index 37b403c..8a865ef 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h @@ -22,10 +22,10 @@ struct nn_group_membership; struct nn_group_membership *new_group_membership (void); void free_group_membership (struct nn_group_membership *mship); -int ddsi_join_mc (const struct q_globals *gv, struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_locator_t *mcip); -int ddsi_leave_mc (const struct q_globals *gv, struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_locator_t *mcip); +int ddsi_join_mc (const struct ddsi_domaingv *gv, struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_locator_t *mcip); +int ddsi_leave_mc (const struct ddsi_domaingv *gv, struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_locator_t *mcip); void ddsi_transfer_group_membership (struct nn_group_membership *mship, ddsi_tran_conn_t conn, ddsi_tran_conn_t newconn); -int ddsi_rejoin_transferred_mcgroups (const struct q_globals *gv, struct nn_group_membership *mship, ddsi_tran_conn_t conn); +int ddsi_rejoin_transferred_mcgroups (const struct ddsi_domaingv *gv, struct nn_group_membership *mship, ddsi_tran_conn_t conn); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_pmd.h b/src/core/ddsi/include/dds/ddsi/ddsi_pmd.h index c2638f2..a2b1daf 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_pmd.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_pmd.h @@ -18,14 +18,14 @@ extern "C" { #endif -struct q_globals; +struct ddsi_domaingv; 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_guid (struct ddsi_domaingv * 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); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_raweth.h b/src/core/ddsi/include/dds/ddsi/ddsi_raweth.h index 54b4479..abd2857 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_raweth.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_raweth.h @@ -16,7 +16,7 @@ extern "C" { #endif -int ddsi_raweth_init (struct q_globals *gv); +int ddsi_raweth_init (struct ddsi_domaingv *gv); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h index 1085ddd..7713af3 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h @@ -23,7 +23,7 @@ extern "C" { struct ddsi_serdata; struct ddsi_serdata_ops; struct ddsi_sertopic_ops; -struct q_globals; +struct ddsi_domaingv; struct ddsi_sertopic { const struct ddsi_sertopic_ops *ops; @@ -33,7 +33,7 @@ struct ddsi_sertopic { char *name; char *type_name; uint64_t iid; - struct q_globals *gv; + struct ddsi_domaingv *gv; ddsrt_atomic_uint32_t refc; /* counts refs from entities (topic, reader, writer), not from data */ }; @@ -92,8 +92,8 @@ struct ddsi_sertopic_ops { ddsi_sertopic_hash_t hash; }; -struct ddsi_sertopic *ddsi_sertopic_lookup_locked (struct q_globals *gv, const struct ddsi_sertopic *sertopic_template); -void ddsi_sertopic_register_locked (struct q_globals *gv, struct ddsi_sertopic *sertopic); +struct ddsi_sertopic *ddsi_sertopic_lookup_locked (struct ddsi_domaingv *gv, const struct ddsi_sertopic *sertopic_template); +void ddsi_sertopic_register_locked (struct ddsi_domaingv *gv, struct ddsi_sertopic *sertopic); DDS_EXPORT void ddsi_sertopic_init (struct ddsi_sertopic *tp, const char *name, const char *type_name, const struct ddsi_sertopic_ops *sertopic_ops, const struct ddsi_serdata_ops *serdata_ops, bool topickind_no_key); DDS_EXPORT void ddsi_sertopic_fini (struct ddsi_sertopic *tp); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h b/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h index d6d5eb7..cf92a45 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h @@ -24,15 +24,15 @@ extern "C" { struct ddsi_ssl_plugins { - bool (*init) (struct q_globals *gv); + bool (*init) (struct ddsi_domaingv *gv); void (*fini) (void); void (*ssl_free) (SSL *ssl); void (*bio_vfree) (BIO *bio); ssize_t (*read) (SSL *ssl, void *buf, size_t len, dds_return_t *err); ssize_t (*write) (SSL *ssl, const void *msg, size_t len, dds_return_t *err); - SSL * (*connect) (const struct q_globals *gv, ddsrt_socket_t sock); + SSL * (*connect) (const struct ddsi_domaingv *gv, ddsrt_socket_t sock); BIO * (*listen) (ddsrt_socket_t sock); - SSL * (*accept) (const struct q_globals *gv, BIO *bio, ddsrt_socket_t *sock); + SSL * (*accept) (const struct ddsi_domaingv *gv, BIO *bio, ddsrt_socket_t *sock); }; #if defined (__cplusplus) @@ -45,7 +45,7 @@ struct ddsi_ssl_plugins extern "C" { #endif -int ddsi_tcp_init (struct q_globals *gv); +int ddsi_tcp_init (struct ddsi_domaingv *gv); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h b/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h index 18d5bc7..6014051 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h @@ -17,12 +17,12 @@ extern "C" { #endif struct ddsi_threadmon; -struct q_globals; +struct ddsi_domaingv; struct ddsi_threadmon *ddsi_threadmon_new (int64_t liveliness_monitoring_interval, bool noprogress_log_stacktraces); dds_return_t ddsi_threadmon_start (struct ddsi_threadmon *sl, const char *name); -void ddsi_threadmon_register_domain (struct ddsi_threadmon *sl, const struct q_globals *gv); -void ddsi_threadmon_unregister_domain (struct ddsi_threadmon *sl, const struct q_globals *gv); +void ddsi_threadmon_register_domain (struct ddsi_threadmon *sl, const struct ddsi_domaingv *gv); +void ddsi_threadmon_unregister_domain (struct ddsi_threadmon *sl, const struct ddsi_domaingv *gv); void ddsi_threadmon_stop (struct ddsi_threadmon *sl); void ddsi_threadmon_free (struct ddsi_threadmon *sl); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_tkmap.h b/src/core/ddsi/include/dds/ddsi/ddsi_tkmap.h index 3461d63..e29460b 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_tkmap.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_tkmap.h @@ -22,7 +22,7 @@ extern "C" { struct ddsi_tkmap; struct ddsi_serdata; struct dds_topic; -struct q_globals; +struct ddsi_domaingv; struct ddsi_tkmap_instance { @@ -31,7 +31,7 @@ struct ddsi_tkmap_instance ddsrt_atomic_uint32_t m_refc; }; -DDS_EXPORT struct ddsi_tkmap *ddsi_tkmap_new (struct q_globals *gv); +DDS_EXPORT struct ddsi_tkmap *ddsi_tkmap_new (struct ddsi_domaingv *gv); DDS_EXPORT void ddsi_tkmap_free (struct ddsi_tkmap *tkmap); DDS_EXPORT void ddsi_tkmap_instance_ref (struct ddsi_tkmap_instance *tk); DDS_EXPORT uint64_t ddsi_tkmap_lookup (struct ddsi_tkmap *tkmap, const struct ddsi_serdata *serdata); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_tran.h b/src/core/ddsi/include/dds/ddsi/ddsi_tran.h index 6d5f25f..4d7d0e4 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_tran.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_tran.h @@ -94,7 +94,7 @@ typedef char * (*ddsi_locator_to_string_fn_t) (char *dst, size_t sizeof_dst, con typedef int (*ddsi_enumerate_interfaces_fn_t) (ddsi_tran_factory_t tran, enum transport_selector transport_selector, ddsrt_ifaddrs_t **interfs); /* Data types */ -struct q_globals; +struct ddsi_domaingv; struct ddsi_tran_base { /* Data */ @@ -102,7 +102,7 @@ struct ddsi_tran_base uint32_t m_port; uint32_t m_trantype; bool m_multicast; - struct q_globals *gv; + struct ddsi_domaingv *gv; /* Functions */ @@ -182,7 +182,7 @@ struct ddsi_tran_factory const char *m_default_spdp_address; bool m_connless; bool m_stream; - struct q_globals *gv; + struct ddsi_domaingv *gv; /* Relationships */ @@ -197,11 +197,11 @@ struct ddsi_tran_qos int m_diffserv; }; -void ddsi_tran_factories_fini (struct q_globals *gv); -void ddsi_factory_add (struct q_globals *gv, ddsi_tran_factory_t factory); +void ddsi_tran_factories_fini (struct ddsi_domaingv *gv); +void ddsi_factory_add (struct ddsi_domaingv *gv, ddsi_tran_factory_t factory); void ddsi_factory_free (ddsi_tran_factory_t factory); -ddsi_tran_factory_t ddsi_factory_find (const struct q_globals *gv, const char * type); -ddsi_tran_factory_t ddsi_factory_find_supported_kind (const struct q_globals *gv, int32_t kind); +ddsi_tran_factory_t ddsi_factory_find (const struct ddsi_domaingv *gv, const char * type); +ddsi_tran_factory_t ddsi_factory_find_supported_kind (const struct ddsi_domaingv *gv, int32_t kind); void ddsi_factory_conn_init (const struct ddsi_tran_factory *factory, ddsi_tran_conn_t conn); inline bool ddsi_factory_supports (const struct ddsi_tran_factory *factory, int32_t kind) { @@ -253,11 +253,11 @@ int ddsi_conn_join_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcip, const n int ddsi_conn_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_locator_t *mcip, const struct nn_interface *interf); void ddsi_conn_transfer_group_membership (ddsi_tran_conn_t conn, ddsi_tran_conn_t newconn); int ddsi_conn_rejoin_transferred_mcgroups (ddsi_tran_conn_t conn); -int ddsi_is_mcaddr (const struct q_globals *gv, const nn_locator_t *loc); -int ddsi_is_ssm_mcaddr (const struct q_globals *gv, const nn_locator_t *loc); +int ddsi_is_mcaddr (const struct ddsi_domaingv *gv, const nn_locator_t *loc); +int ddsi_is_ssm_mcaddr (const struct ddsi_domaingv *gv, const nn_locator_t *loc); enum ddsi_nearby_address_result ddsi_is_nearby_address (const nn_locator_t *loc, const nn_locator_t *ownloc, size_t ninterf, const struct nn_interface *interf); -enum ddsi_locator_from_string_result ddsi_locator_from_string (const struct q_globals *gv, nn_locator_t *loc, const char *str, ddsi_tran_factory_t default_factory); +enum ddsi_locator_from_string_result ddsi_locator_from_string (const struct ddsi_domaingv *gv, nn_locator_t *loc, const char *str, ddsi_tran_factory_t default_factory); /* 8 for transport/ 1 for [ diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_udp.h b/src/core/ddsi/include/dds/ddsi/ddsi_udp.h index 888452c..4b58a19 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_udp.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_udp.h @@ -24,7 +24,7 @@ typedef struct nn_udpv4mcgen_address { uint8_t idx; /* must be last: then sorting will put them consecutively */ } nn_udpv4mcgen_address_t; -int ddsi_udp_init (struct q_globals *gv); +int ddsi_udp_init (struct ddsi_domaingv *gv); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/q_addrset.h b/src/core/ddsi/include/dds/ddsi/q_addrset.h index 669061f..2ded8b9 100644 --- a/src/core/ddsi/include/dds/ddsi/q_addrset.h +++ b/src/core/ddsi/include/dds/ddsi/q_addrset.h @@ -39,16 +39,16 @@ typedef ssize_t (*addrset_forone_fun_t) (const nn_locator_t *loc, void *arg); struct addrset *new_addrset (void); struct addrset *ref_addrset (struct addrset *as); void unref_addrset (struct addrset *as); -void add_to_addrset (const struct q_globals *gv, struct addrset *as, const nn_locator_t *loc); -void remove_from_addrset (const struct q_globals *gv, struct addrset *as, const nn_locator_t *loc); +void add_to_addrset (const struct ddsi_domaingv *gv, struct addrset *as, const nn_locator_t *loc); +void remove_from_addrset (const struct ddsi_domaingv *gv, struct addrset *as, const nn_locator_t *loc); int addrset_purge (struct addrset *as); int compare_locators (const nn_locator_t *a, const nn_locator_t *b); /* These lock ASADD, then lock/unlock AS any number of times, then unlock ASADD */ -void copy_addrset_into_addrset_uc (const struct q_globals *gv, struct addrset *as, const struct addrset *asadd); -void copy_addrset_into_addrset_mc (const struct q_globals *gv, struct addrset *as, const struct addrset *asadd); -void copy_addrset_into_addrset (const struct q_globals *gv, struct addrset *as, const struct addrset *asadd); +void copy_addrset_into_addrset_uc (const struct ddsi_domaingv *gv, struct addrset *as, const struct addrset *asadd); +void copy_addrset_into_addrset_mc (const struct ddsi_domaingv *gv, struct addrset *as, const struct addrset *asadd); +void copy_addrset_into_addrset (const struct ddsi_domaingv *gv, struct addrset *as, const struct addrset *asadd); size_t addrset_count (const struct addrset *as); size_t addrset_count_uc (const struct addrset *as); @@ -63,7 +63,7 @@ int addrset_any_mc (const struct addrset *as, nn_locator_t *dst); int addrset_forone (struct addrset *as, addrset_forone_fun_t f, void *arg); void addrset_forall (struct addrset *as, addrset_forall_fun_t f, void *arg); size_t addrset_forall_count (struct addrset *as, addrset_forall_fun_t f, void *arg); -void nn_log_addrset (struct q_globals *gv, uint32_t tf, const char *prefix, const struct addrset *as); +void nn_log_addrset (struct ddsi_domaingv *gv, uint32_t tf, const char *prefix, const struct addrset *as); /* Tries to lock A then B for a decent check, returning false if trylock B fails */ @@ -72,15 +72,15 @@ int addrset_eq_onesidederr (const struct addrset *a, const struct addrset *b); int is_unspec_locator (const nn_locator_t *loc); void set_unspec_locator (nn_locator_t *loc); -struct q_globals; -int add_addresses_to_addrset (const struct q_globals *gv, struct addrset *as, const char *addrs, int port_mode, const char *msgtag, int req_mc); +struct ddsi_domaingv; +int add_addresses_to_addrset (const struct ddsi_domaingv *gv, struct addrset *as, const char *addrs, int port_mode, const char *msgtag, int req_mc); #ifdef DDSI_INCLUDE_SSM -int addrset_contains_ssm (const struct q_globals *gv, const struct addrset *as); -int addrset_any_ssm (const struct q_globals *gv, const struct addrset *as, nn_locator_t *dst); -int addrset_any_non_ssm_mc (const struct q_globals *gv, const struct addrset *as, nn_locator_t *dst); -void copy_addrset_into_addrset_no_ssm_mc (const struct q_globals *gv, struct addrset *as, const struct addrset *asadd); -void copy_addrset_into_addrset_no_ssm (const struct q_globals *gv, struct addrset *as, const struct addrset *asadd); +int addrset_contains_ssm (const struct ddsi_domaingv *gv, const struct addrset *as); +int addrset_any_ssm (const struct ddsi_domaingv *gv, const struct addrset *as, nn_locator_t *dst); +int addrset_any_non_ssm_mc (const struct ddsi_domaingv *gv, const struct addrset *as, nn_locator_t *dst); +void copy_addrset_into_addrset_no_ssm_mc (const struct ddsi_domaingv *gv, struct addrset *as, const struct addrset *asadd); +void copy_addrset_into_addrset_no_ssm (const struct ddsi_domaingv *gv, struct addrset *as, const struct addrset *asadd); #endif #if defined (__cplusplus) diff --git a/src/core/ddsi/include/dds/ddsi/q_debmon.h b/src/core/ddsi/include/dds/ddsi/q_debmon.h index 5f5ac06..3596f77 100644 --- a/src/core/ddsi/include/dds/ddsi/q_debmon.h +++ b/src/core/ddsi/include/dds/ddsi/q_debmon.h @@ -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, int32_t port); +struct debug_monitor *new_debug_monitor (struct ddsi_domaingv *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); diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index f5d6dde..3105512 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -165,7 +165,7 @@ struct entity_common { struct ddsi_tkmap_instance *tk; ddsrt_mutex_t lock; bool onlylocal; - struct q_globals *gv; + struct ddsi_domaingv *gv; ddsrt_avl_node_t all_entities_avlnode; /* QoS changes always lock the entity itself, and additionally @@ -530,7 +530,7 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e); * @retval DDS_RETCODE_OUT_OF_RESOURCES * The configured maximum number of participants has been reached. */ -dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals *gv, unsigned flags, const struct nn_plist *plist); +dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const struct nn_plist *plist); /** * @brief Create a new participant in the domain. See also new_participant_guid. @@ -554,7 +554,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * * @retval DDS_RETCODE_OUT_OF_RESOURCES * The configured maximum number of participants has been reached. */ -dds_return_t new_participant (struct ddsi_guid *ppguid, struct q_globals *gv, unsigned flags, const struct nn_plist *plist); +dds_return_t new_participant (struct ddsi_guid *ppguid, struct ddsi_domaingv *gv, unsigned flags, const struct nn_plist *plist); /** * @brief Initiate the deletion of the participant: @@ -580,9 +580,9 @@ dds_return_t new_participant (struct ddsi_guid *ppguid, struct q_globals *gv, un * @retval DDS_RETCODE_BAD_PARAMETER * ppguid lookup failed. */ -dds_return_t delete_participant (struct q_globals *gv, const struct ddsi_guid *ppguid); +dds_return_t delete_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid); void update_participant_plist (struct participant *pp, const struct nn_plist *plist); -uint64_t get_entity_instance_id (const struct q_globals *gv, const struct ddsi_guid *guid); +uint64_t get_entity_instance_id (const struct ddsi_domaingv *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 */ @@ -597,9 +597,9 @@ DDS_EXPORT struct writer *get_builtin_writer (const struct participant *pp, unsi GUID "ppguid". May return NULL if participant unknown or writer/reader already known. */ -dds_return_t new_writer (struct writer **wr_out, struct q_globals *gv, struct ddsi_guid *wrguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg); +dds_return_t new_writer (struct writer **wr_out, struct ddsi_domaingv *gv, struct ddsi_guid *wrguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg); -dds_return_t new_reader (struct reader **rd_out, struct q_globals *gv, struct ddsi_guid *rdguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct ddsi_rhc * rhc, status_cb_t status_cb, void *status_cb_arg); +dds_return_t new_reader (struct reader **rd_out, struct ddsi_domaingv *gv, struct ddsi_guid *rdguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct ddsi_rhc * rhc, status_cb_t status_cb, void *status_cb_arg); void update_reader_qos (struct reader *rd, const struct dds_qos *xqos); void update_writer_qos (struct writer *wr, const struct dds_qos *xqos); @@ -613,17 +613,17 @@ void writer_set_retransmitting (struct writer *wr); void writer_clear_retransmitting (struct writer *wr); dds_return_t writer_wait_for_acks (struct writer *wr, dds_time_t abstimeout); -dds_return_t unblock_throttled_writer (struct q_globals *gv, const struct ddsi_guid *guid); -dds_return_t delete_writer (struct q_globals *gv, const struct ddsi_guid *guid); -dds_return_t delete_writer_nolinger (struct q_globals *gv, const struct ddsi_guid *guid); +dds_return_t unblock_throttled_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *guid); +dds_return_t delete_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *guid); +dds_return_t delete_writer_nolinger (struct ddsi_domaingv *gv, const struct ddsi_guid *guid); dds_return_t delete_writer_nolinger_locked (struct writer *wr); -dds_return_t delete_reader (struct q_globals *gv, const struct ddsi_guid *guid); +dds_return_t delete_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *guid); struct local_orphan_writer { struct writer wr; }; -struct local_orphan_writer *new_local_orphan_writer (struct q_globals *gv, ddsi_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc); +struct local_orphan_writer *new_local_orphan_writer (struct ddsi_domaingv *gv, ddsi_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc); void delete_local_orphan_writer (struct local_orphan_writer *wr); void writer_set_alive_may_unlock (struct writer *wr, bool notify); @@ -653,20 +653,20 @@ int writer_set_notalive (struct writer *wr, bool notify); /* Set when this proxy participant is not to be announced on the built-in topics yet */ #define CF_PROXYPP_NO_SPDP (1 << 3) -void new_proxy_participant (struct q_globals *gv, const struct ddsi_guid *guid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct nn_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq); -int delete_proxy_participant_by_guid (struct q_globals *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit); +void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct nn_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq); +int delete_proxy_participant_by_guid (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit); int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, nn_wctime_t timestamp); int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, nn_wctime_t timestamp); void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct lease *newlease); -void purge_proxy_participants (struct q_globals *gv, const nn_locator_t *loc, bool delete_from_as_disc); +void purge_proxy_participants (struct ddsi_domaingv *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); -int new_proxy_reader (struct q_globals *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const struct nn_plist *plist, nn_wctime_t timestamp, seqno_t seq + int new_proxy_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const struct nn_plist *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp, seqno_t seq); +int new_proxy_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const struct nn_plist *plist, nn_wctime_t timestamp, seqno_t seq #ifdef DDSI_INCLUDE_SSM , int favours_ssm #endif @@ -677,8 +677,8 @@ int new_proxy_reader (struct q_globals *gv, const struct ddsi_guid *ppguid, cons reader or writer. Actual deletion is scheduled in the future, when no outstanding references may still exist (determined by checking thread progress, &c.). */ -int delete_proxy_writer (struct q_globals *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit); -int delete_proxy_reader (struct q_globals *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit); +int delete_proxy_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit); +int delete_proxy_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit); void update_proxy_reader (struct proxy_reader *prd, seqno_t seq, struct addrset *as, const struct dds_qos *xqos, nn_wctime_t timestamp); void update_proxy_writer (struct proxy_writer *pwr, seqno_t seq, struct addrset *as, const struct dds_qos *xqos, nn_wctime_t timestamp); @@ -693,7 +693,7 @@ void delete_proxy_group (struct entity_index *entidx, const struct ddsi_guid *gu /* Call this to empty all address sets of all writers to stop all outgoing traffic, or to rebuild them all (which only makes sense after previously having emptied them all). */ -void rebuild_or_clear_writer_addrsets(struct q_globals *gv, int rebuild); +void rebuild_or_clear_writer_addrsets(struct ddsi_domaingv *gv, int rebuild); void local_reader_ary_setfastpath_ok (struct local_reader_ary *x, bool fastpath_ok); diff --git a/src/core/ddsi/include/dds/ddsi/q_gc.h b/src/core/ddsi/include/dds/ddsi/q_gc.h index 2b02bd3..ffb2e11 100644 --- a/src/core/ddsi/include/dds/ddsi/q_gc.h +++ b/src/core/ddsi/include/dds/ddsi/q_gc.h @@ -21,7 +21,7 @@ extern "C" { struct gcreq; struct gcreq_queue; -struct q_globals; +struct ddsi_domaingv; struct writer; struct reader; @@ -44,7 +44,7 @@ struct gcreq { struct idx_vtime vtimes[]; }; -DDS_EXPORT struct gcreq_queue *gcreq_queue_new (struct q_globals *gv); +DDS_EXPORT struct gcreq_queue *gcreq_queue_new (struct ddsi_domaingv *gv); DDS_EXPORT void gcreq_queue_drain (struct gcreq_queue *q); DDS_EXPORT void gcreq_queue_free (struct gcreq_queue *q); diff --git a/src/core/ddsi/include/dds/ddsi/q_init.h b/src/core/ddsi/include/dds/ddsi/q_init.h index 73f3548..32010f9 100644 --- a/src/core/ddsi/include/dds/ddsi/q_init.h +++ b/src/core/ddsi/include/dds/ddsi/q_init.h @@ -16,8 +16,8 @@ extern "C" { #endif -int create_multicast_sockets (struct q_globals *gv); -int joinleave_spdp_defmcip (struct q_globals *gv, int dojoin); +int create_multicast_sockets (struct ddsi_domaingv *gv); +int joinleave_spdp_defmcip (struct ddsi_domaingv *gv, int dojoin); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/q_lease.h b/src/core/ddsi/include/dds/ddsi/q_lease.h index 51a00cb..b6c5f5c 100644 --- a/src/core/ddsi/include/dds/ddsi/q_lease.h +++ b/src/core/ddsi/include/dds/ddsi/q_lease.h @@ -24,7 +24,7 @@ extern "C" { struct receiver_state; struct participant; struct entity_common; -struct q_globals; /* FIXME: make a special for the lease admin */ +struct ddsi_domaingv; /* FIXME: make a special for the lease admin */ struct lease { ddsrt_fibheap_node_t heapnode; @@ -37,8 +37,8 @@ struct lease { 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); +void lease_management_init (struct ddsi_domaingv *gv); +void lease_management_term (struct ddsi_domaingv *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); @@ -46,7 +46,7 @@ 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); +int64_t check_and_handle_lease_expiration (struct ddsi_domaingv *gv, nn_etime_t tnow); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/q_nwif.h b/src/core/ddsi/include/dds/ddsi/q_nwif.h index e69a5a7..7e4688c 100644 --- a/src/core/ddsi/include/dds/ddsi/q_nwif.h +++ b/src/core/ddsi/include/dds/ddsi/q_nwif.h @@ -22,7 +22,7 @@ extern "C" { #endif -struct q_globals; +struct ddsi_domaingv; #define MAX_INTERFACES 128 struct nn_interface { @@ -35,8 +35,8 @@ struct nn_interface { char *name; }; -int make_socket (ddsrt_socket_t *socket, uint16_t port, bool stream, bool reuse, const struct q_globals *gv); -int find_own_ip (struct q_globals *gv, const char *requested_address); +int make_socket (ddsrt_socket_t *socket, uint16_t port, bool stream, bool reuse, const struct ddsi_domaingv *gv); +int find_own_ip (struct ddsi_domaingv *gv, const char *requested_address); uint32_t locator_to_hopefully_unique_uint32 (const nn_locator_t *src); #if defined (__cplusplus) diff --git a/src/core/ddsi/include/dds/ddsi/q_pcap.h b/src/core/ddsi/include/dds/ddsi/q_pcap.h index 09836c8..94f7d22 100644 --- a/src/core/ddsi/include/dds/ddsi/q_pcap.h +++ b/src/core/ddsi/include/dds/ddsi/q_pcap.h @@ -23,8 +23,8 @@ struct msghdr; FILE * new_pcap_file (const struct ddsrt_log_cfg *logcfg, const char *name); -void write_pcap_received (struct q_globals *gv, nn_wctime_t tstamp, const struct sockaddr_storage *src, const struct sockaddr_storage *dst, unsigned char *buf, size_t sz); -void write_pcap_sent (struct q_globals *gv, nn_wctime_t tstamp, const struct sockaddr_storage *src, +void write_pcap_received (struct ddsi_domaingv *gv, nn_wctime_t tstamp, const struct sockaddr_storage *src, const struct sockaddr_storage *dst, unsigned char *buf, size_t sz); +void write_pcap_sent (struct ddsi_domaingv *gv, nn_wctime_t tstamp, const struct sockaddr_storage *src, const ddsrt_msghdr_t *hdr, size_t sz); #if defined (__cplusplus) diff --git a/src/core/ddsi/include/dds/ddsi/q_radmin.h b/src/core/ddsi/include/dds/ddsi/q_radmin.h index 3dde1be..9ded3d4 100644 --- a/src/core/ddsi/include/dds/ddsi/q_radmin.h +++ b/src/core/ddsi/include/dds/ddsi/q_radmin.h @@ -111,7 +111,7 @@ struct receiver_state { nn_protocol_version_t protocol_version; /* 2 => 44/48 */ ddsi_tran_conn_t conn; /* Connection for request */ nn_locator_t srcloc; - struct q_globals *gv; + struct ddsi_domaingv *gv; }; struct nn_rsample_info { @@ -230,7 +230,7 @@ int nn_reorder_wantsample (struct nn_reorder *reorder, seqno_t seq); unsigned nn_reorder_nackmap (struct nn_reorder *reorder, seqno_t base, seqno_t maxseq, struct nn_sequence_number_set_header *map, uint32_t *mapbits, uint32_t maxsz, int notail); seqno_t nn_reorder_next_seq (const struct nn_reorder *reorder); -struct nn_dqueue *nn_dqueue_new (const char *name, const struct q_globals *gv, uint32_t max_samples, nn_dqueue_handler_t handler, void *arg); +struct nn_dqueue *nn_dqueue_new (const char *name, const struct ddsi_domaingv *gv, uint32_t max_samples, nn_dqueue_handler_t handler, void *arg); void nn_dqueue_free (struct nn_dqueue *q); bool nn_dqueue_enqueue_deferred_wakeup (struct nn_dqueue *q, struct nn_rsample_chain *sc, nn_reorder_result_t rres); void dd_dqueue_enqueue_trigger (struct nn_dqueue *q); diff --git a/src/core/ddsi/include/dds/ddsi/q_receive.h b/src/core/ddsi/include/dds/ddsi/q_receive.h index e165bea..617b563 100644 --- a/src/core/ddsi/include/dds/ddsi/q_receive.h +++ b/src/core/ddsi/include/dds/ddsi/q_receive.h @@ -22,7 +22,7 @@ struct nn_rdata; struct ddsi_tran_listener; struct recv_thread_arg; -void trigger_recv_threads (const struct q_globals *gv); +void trigger_recv_threads (const struct ddsi_domaingv *gv); uint32_t recv_thread (void *vrecv_thread_arg); uint32_t listen_thread (struct ddsi_tran_listener * listener); int user_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const ddsi_guid_t *rdguid, void *qarg); diff --git a/src/core/ddsi/include/dds/ddsi/q_rtps.h b/src/core/ddsi/include/dds/ddsi/q_rtps.h index 544c971..a822d4e 100644 --- a/src/core/ddsi/include/dds/ddsi/q_rtps.h +++ b/src/core/ddsi/include/dds/ddsi/q_rtps.h @@ -58,13 +58,13 @@ typedef int64_t seqno_t; #define NN_ENTITYID_ALLOCSTEP 0x100 struct cfgst; -struct q_globals; -int rtps_config_prep (struct q_globals *config, struct cfgst *cfgst); -int rtps_config_open_trace (struct q_globals *config); -int rtps_init (struct q_globals *config); -int rtps_start (struct q_globals *config); -void rtps_stop (struct q_globals *config); -void rtps_fini (struct q_globals *config); +struct ddsi_domaingv; +int rtps_config_prep (struct ddsi_domaingv *config, struct cfgst *cfgst); +int rtps_config_open_trace (struct ddsi_domaingv *config); +int rtps_init (struct ddsi_domaingv *config); +int rtps_start (struct ddsi_domaingv *config); +void rtps_stop (struct ddsi_domaingv *config); +void rtps_fini (struct ddsi_domaingv *config); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/q_thread.h b/src/core/ddsi/include/dds/ddsi/q_thread.h index e1703f9..c899ee1 100644 --- a/src/core/ddsi/include/dds/ddsi/q_thread.h +++ b/src/core/ddsi/include/dds/ddsi/q_thread.h @@ -54,7 +54,7 @@ enum thread_state { THREAD_STATE_ALIVE /* known to be alive - for Cyclone internal threads */ }; -struct q_globals; +struct ddsi_domaingv; struct config; struct ddsrt_log_cfg; @@ -103,10 +103,10 @@ DDS_EXPORT bool thread_states_fini (void); DDS_EXPORT const struct config_thread_properties_listelem *lookup_thread_properties (const struct config *config, const char *name); DDS_EXPORT dds_return_t create_thread_with_properties (struct thread_state1 **ts1, struct config_thread_properties_listelem const * const tprops, const char *name, uint32_t (*f) (void *arg), void *arg); -DDS_EXPORT dds_return_t create_thread (struct thread_state1 **ts, const struct q_globals *gv, const char *name, uint32_t (*f) (void *arg), void *arg); +DDS_EXPORT dds_return_t create_thread (struct thread_state1 **ts, const struct ddsi_domaingv *gv, const char *name, uint32_t (*f) (void *arg), void *arg); DDS_EXPORT struct thread_state1 *lookup_thread_state_real (void); DDS_EXPORT dds_return_t join_thread (struct thread_state1 *ts1); -DDS_EXPORT void log_stack_traces (const struct ddsrt_log_cfg *logcfg, const struct q_globals *gv); +DDS_EXPORT void log_stack_traces (const struct ddsrt_log_cfg *logcfg, const struct ddsi_domaingv *gv); DDS_EXPORT void reset_thread_state (struct thread_state1 *ts1); DDS_EXPORT int thread_exists (const char *name); @@ -161,13 +161,13 @@ DDS_EXPORT inline void thread_state_asleep (struct thread_state1 *ts1) ddsrt_atomic_st32 (&ts1->vtime, vt); } -DDS_EXPORT inline void thread_state_awake (struct thread_state1 *ts1, const struct q_globals *gv) +DDS_EXPORT inline void thread_state_awake (struct thread_state1 *ts1, const struct ddsi_domaingv *gv) { vtime_t vt = ddsrt_atomic_ld32 (&ts1->vtime); assert ((vt & VTIME_NEST_MASK) < VTIME_NEST_MASK); assert (gv != NULL); assert (ts1->state != THREAD_STATE_ALIVE || gv == ddsrt_atomic_ldvoidp (&ts1->gv)); - ddsrt_atomic_stvoidp (&ts1->gv, (struct q_globals *) gv); + ddsrt_atomic_stvoidp (&ts1->gv, (struct ddsi_domaingv *) gv); ddsrt_atomic_fence_stst (); ddsrt_atomic_st32 (&ts1->vtime, vt + 1u); /* nested calls a rare and an extra fence doesn't break things */ diff --git a/src/core/ddsi/include/dds/ddsi/q_transmit.h b/src/core/ddsi/include/dds/ddsi/q_transmit.h index b88b999..c654052 100644 --- a/src/core/ddsi/include/dds/ddsi/q_transmit.h +++ b/src/core/ddsi/include/dds/ddsi/q_transmit.h @@ -43,7 +43,7 @@ int write_sample_nogc_notk (struct thread_state1 * const ts1, struct nn_xpack *x 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, 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); +dds_return_t write_hb_liveliness (struct ddsi_domaingv * const gv, struct ddsi_guid *wr_guid, struct nn_xpack *xp); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/q_xmsg.h b/src/core/ddsi/include/dds/ddsi/q_xmsg.h index 78463a7..32941c2 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xmsg.h +++ b/src/core/ddsi/include/dds/ddsi/q_xmsg.h @@ -92,7 +92,7 @@ void nn_xmsg_set_data_readerId (struct nn_xmsg *m, ddsi_entityid_t *readerId); Returns 1 if merge was successful, else 0. On failure, neither message will have been changed and both should be sent as if there had been no merging. */ -int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct q_globals *gv, struct nn_xmsg *m, const struct nn_xmsg *madd); +int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct ddsi_domaingv *gv, struct nn_xmsg *m, const struct nn_xmsg *madd); /* To set writer ids for updating last transmitted sequence number; wrfragid is 0 based, unlike DDSI but like other places where @@ -135,10 +135,10 @@ int64_t nn_xpack_maxdelay (const struct nn_xpack *xp); unsigned nn_xpack_packetid (const struct nn_xpack *xp); /* SENDQ */ -void nn_xpack_sendq_init (struct q_globals *gv); -void nn_xpack_sendq_start (struct q_globals *gv); -void nn_xpack_sendq_stop (struct q_globals *gv); -void nn_xpack_sendq_fini (struct q_globals *gv); +void nn_xpack_sendq_init (struct ddsi_domaingv *gv); +void nn_xpack_sendq_start (struct ddsi_domaingv *gv); +void nn_xpack_sendq_stop (struct ddsi_domaingv *gv); +void nn_xpack_sendq_fini (struct ddsi_domaingv *gv); #if defined (__cplusplus) } diff --git a/src/core/ddsi/src/ddsi_deadline.c b/src/core/ddsi/src/ddsi_deadline.c index a4775c8..56ab8e4 100644 --- a/src/core/ddsi/src/ddsi_deadline.c +++ b/src/core/ddsi/src/ddsi_deadline.c @@ -47,7 +47,7 @@ nn_mtime_t deadline_next_missed_locked (struct deadline_adm *deadline_adm, nn_mt return (elem != NULL) ? elem->t_deadline : NN_MTIME_NEVER; } -void deadline_init (const struct q_globals *gv, struct deadline_adm *deadline_adm, size_t list_offset, size_t elem_offset, deadline_missed_cb_t deadline_missed_cb) +void deadline_init (const struct ddsi_domaingv *gv, struct deadline_adm *deadline_adm, size_t list_offset, size_t elem_offset, deadline_missed_cb_t deadline_missed_cb) { ddsrt_circlist_init (&deadline_adm->list); deadline_adm->evt = qxev_callback (gv->xevents, NN_MTIME_NEVER, instance_deadline_missed_cb, deadline_adm); diff --git a/src/core/ddsi/src/ddsi_deliver_locally.c b/src/core/ddsi/src/ddsi_deliver_locally.c index bea4270..b04d2fe 100644 --- a/src/core/ddsi/src/ddsi_deliver_locally.c +++ b/src/core/ddsi/src/ddsi_deliver_locally.c @@ -22,7 +22,7 @@ #include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_rhc.h" #include "dds/ddsi/ddsi_entity_index.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_entity.h" #define TOPIC_SAMPLE_CACHE_SIZE 4 @@ -59,7 +59,7 @@ static int cmp_topic_ptrs (const void *va, const void *vb) static const ddsrt_avl_treedef_t tsc_large_td = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct topic_sample_cache_large_entry, avlnode), offsetof (struct topic_sample_cache_large_entry, topic), cmp_topic_ptrs, 0); -static void free_sample_after_store (struct q_globals *gv, struct ddsi_serdata *sample, struct ddsi_tkmap_instance *tk) +static void free_sample_after_store (struct ddsi_domaingv *gv, struct ddsi_serdata *sample, struct ddsi_tkmap_instance *tk) { if (sample) { @@ -77,12 +77,12 @@ static void topic_sample_cache_init (struct topic_sample_cache * __restrict tsc) static void free_large_entry (void *vnode, void *varg) { struct topic_sample_cache_large_entry *e = vnode; - struct q_globals *gv = varg; + struct ddsi_domaingv *gv = varg; free_sample_after_store (gv, e->sample, e->tk); ddsrt_free (e); } -static void topic_sample_cache_fini (struct topic_sample_cache * __restrict tsc, struct q_globals *gv) +static void topic_sample_cache_fini (struct topic_sample_cache * __restrict tsc, struct ddsi_domaingv *gv) { for (uint32_t i = 0; i < tsc->n && i < TOPIC_SAMPLE_CACHE_SIZE; i++) if (tsc->topics[i] && tsc->samples[i].tk) @@ -133,7 +133,7 @@ static void topic_sample_cache_store (struct topic_sample_cache * __restrict tsc tsc->n++; } -dds_return_t deliver_locally_one (struct q_globals *gv, struct entity_common *source_entity, bool source_entity_locked, const ddsi_guid_t *rdguid, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo) +dds_return_t deliver_locally_one (struct ddsi_domaingv *gv, struct entity_common *source_entity, bool source_entity_locked, const ddsi_guid_t *rdguid, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo) { struct reader *rd = entidx_lookup_reader_guid (gv->entity_index, rdguid); if (rd == NULL) @@ -166,7 +166,7 @@ dds_return_t deliver_locally_one (struct q_globals *gv, struct entity_common *so return DDS_RETCODE_OK; } -static dds_return_t deliver_locally_slowpath (struct q_globals *gv, struct entity_common *source_entity, bool source_entity_locked, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo) +static dds_return_t deliver_locally_slowpath (struct ddsi_domaingv *gv, struct entity_common *source_entity, bool source_entity_locked, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo) { /* When deleting, pwr is no longer accessible via the hash tables, and consequently, a reader may be deleted without @@ -209,7 +209,7 @@ static dds_return_t deliver_locally_slowpath (struct q_globals *gv, struct entit return DDS_RETCODE_OK; } -static dds_return_t deliver_locally_fastpath (struct q_globals *gv, struct entity_common *source_entity, bool source_entity_locked, struct local_reader_ary *fastpath_rdary, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo) +static dds_return_t deliver_locally_fastpath (struct ddsi_domaingv *gv, struct entity_common *source_entity, bool source_entity_locked, struct local_reader_ary *fastpath_rdary, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo) { struct reader ** const rdary = fastpath_rdary->rdary; uint32_t i = 0; @@ -243,7 +243,7 @@ static dds_return_t deliver_locally_fastpath (struct q_globals *gv, struct entit return DDS_RETCODE_OK; } -dds_return_t deliver_locally_allinsync (struct q_globals *gv, struct entity_common *source_entity, bool source_entity_locked, struct local_reader_ary *fastpath_rdary, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo) +dds_return_t deliver_locally_allinsync (struct ddsi_domaingv *gv, struct entity_common *source_entity, bool source_entity_locked, struct local_reader_ary *fastpath_rdary, const struct ddsi_writer_info *wrinfo, const struct deliver_locally_ops * __restrict ops, void *vsourceinfo) { dds_return_t rc; /* FIXME: Retry loop for re-delivery of rejected reliable samples is a bad hack diff --git a/src/core/ddsi/src/ddsi_entity_index.c b/src/core/ddsi/src/ddsi_entity_index.c index c7b09b9..7183a30 100644 --- a/src/core/ddsi/src/ddsi_entity_index.c +++ b/src/core/ddsi/src/ddsi_entity_index.c @@ -20,7 +20,7 @@ #include "dds/ddsrt/avl.h" #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/q_config.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_gc.h" #include "dds/ddsi/q_rtps.h" /* guid_t */ @@ -220,13 +220,13 @@ static void gc_buckets_cb (struct gcreq *gcreq) static void gc_buckets (void *bs, void *varg) { - struct q_globals *gv = varg; + struct ddsi_domaingv *gv = varg; struct gcreq *gcreq = gcreq_new (gv->gcreq_queue, gc_buckets_cb); gcreq->arg = bs; gcreq_enqueue (gcreq); } -struct entity_index *entity_index_new (struct q_globals *gv) +struct entity_index *entity_index_new (struct ddsi_domaingv *gv) { struct entity_index *entidx; entidx = ddsrt_malloc (sizeof (*entidx)); diff --git a/src/core/ddsi/src/ddsi_ipaddr.c b/src/core/ddsi/src/ddsi_ipaddr.c index 1172201..d9f89ae 100644 --- a/src/core/ddsi/src/ddsi_ipaddr.c +++ b/src/core/ddsi/src/ddsi_ipaddr.c @@ -18,7 +18,7 @@ #include "dds/ddsi/ddsi_ipaddr.h" #include "dds/ddsi/q_nwif.h" #include "dds/ddsi/q_config.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" int ddsi_ipaddr_compare (const struct sockaddr *const sa1, const struct sockaddr *const sa2) { diff --git a/src/core/ddsi/src/ddsi_lifespan.c b/src/core/ddsi/src/ddsi_lifespan.c index 1ed3a3c..3ad8737 100644 --- a/src/core/ddsi/src/ddsi_lifespan.c +++ b/src/core/ddsi/src/ddsi_lifespan.c @@ -49,7 +49,7 @@ nn_mtime_t lifespan_next_expired_locked (const struct lifespan_adm *lifespan_adm return (node != NULL) ? node->t_expire : NN_MTIME_NEVER; } -void lifespan_init (const struct q_globals *gv, struct lifespan_adm *lifespan_adm, size_t fh_offset, size_t fh_node_offset, sample_expired_cb_t sample_expired_cb) +void lifespan_init (const struct ddsi_domaingv *gv, struct lifespan_adm *lifespan_adm, size_t fh_offset, size_t fh_node_offset, sample_expired_cb_t sample_expired_cb) { ddsrt_fibheap_init (&lifespan_fhdef, &lifespan_adm->ls_exp_heap); lifespan_adm->evt = qxev_callback (gv->xevents, NN_MTIME_NEVER, lifespan_rhc_node_exp, lifespan_adm); diff --git a/src/core/ddsi/src/ddsi_mcgroup.c b/src/core/ddsi/src/ddsi_mcgroup.c index 96b204e..cd49444 100644 --- a/src/core/ddsi/src/ddsi_mcgroup.c +++ b/src/core/ddsi/src/ddsi_mcgroup.c @@ -20,7 +20,7 @@ #include "dds/ddsi/ddsi_mcgroup.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsrt/avl.h" struct nn_group_membership_node { @@ -177,7 +177,7 @@ static int interface_in_recvips_p (const struct config_in_addr_node *recvips, co return 0; } -static int joinleave_mcgroups (const struct q_globals *gv, ddsi_tran_conn_t conn, int join, const nn_locator_t *srcloc, const nn_locator_t *mcloc) +static int joinleave_mcgroups (const struct ddsi_domaingv *gv, ddsi_tran_conn_t conn, int join, const nn_locator_t *srcloc, const nn_locator_t *mcloc) { int rc; switch (gv->recvips_mode) @@ -223,7 +223,7 @@ static int joinleave_mcgroups (const struct q_globals *gv, ddsi_tran_conn_t conn return 0; } -int ddsi_join_mc (const struct q_globals *gv, struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc) +int ddsi_join_mc (const struct ddsi_domaingv *gv, struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc) { /* FIXME: gv to be reduced; perhaps mship, recvips, interfaces, ownloc should be combined into a single struct */ int ret; @@ -242,7 +242,7 @@ int ddsi_join_mc (const struct q_globals *gv, struct nn_group_membership *mship, return ret; } -int ddsi_leave_mc (const struct q_globals *gv, struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc) +int ddsi_leave_mc (const struct ddsi_domaingv *gv, struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc) { int ret; ddsrt_mutex_lock (&mship->lock); @@ -282,7 +282,7 @@ void ddsi_transfer_group_membership (struct nn_group_membership *mship, ddsi_tra ddsrt_mutex_unlock (&mship->lock); } -int ddsi_rejoin_transferred_mcgroups (const struct q_globals *gv, struct nn_group_membership *mship, ddsi_tran_conn_t conn) +int ddsi_rejoin_transferred_mcgroups (const struct ddsi_domaingv *gv, struct nn_group_membership *mship, ddsi_tran_conn_t conn) { /* FIXME: see gv should be reduced; perhaps recvips, ownloc, mship, interfaces should be a single struct */ struct nn_group_membership_node *n, min, max; diff --git a/src/core/ddsi/src/ddsi_pmd.c b/src/core/ddsi/src/ddsi_pmd.c index 3136e91..9a6df62 100644 --- a/src/core/ddsi/src/ddsi_pmd.c +++ b/src/core/ddsi/src/ddsi_pmd.c @@ -18,7 +18,7 @@ #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/ddsi_entity_index.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_lease.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_misc.h" @@ -31,7 +31,7 @@ #include "dds/ddsi/sysdeps.h" -static void debug_print_rawdata (const struct q_globals *gv, const char *msg, const void *data, size_t len) +static void debug_print_rawdata (const struct ddsi_domaingv *gv, const char *msg, const void *data, size_t len) { const unsigned char *c = data; size_t i; @@ -46,7 +46,7 @@ static void debug_print_rawdata (const struct q_globals *gv, const char *msg, co GVTRACE (">"); } -void write_pmd_message_guid (struct q_globals * const gv, struct ddsi_guid *pp_guid, unsigned pmd_kind) +void write_pmd_message_guid (struct ddsi_domaingv * const gv, struct ddsi_guid *pp_guid, unsigned pmd_kind) { struct thread_state1 * const ts1 = lookup_thread_state (); struct lease *lease; @@ -66,7 +66,7 @@ void write_pmd_message_guid (struct q_globals * const gv, struct ddsi_guid *pp_g 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 ddsi_domaingv * const gv = pp->e.gv; struct writer *wr; union { ParticipantMessageData_t pmd; diff --git a/src/core/ddsi/src/ddsi_raweth.c b/src/core/ddsi/src/ddsi_raweth.c index b5a0d07..1f7ed6a 100644 --- a/src/core/ddsi/src/ddsi_raweth.c +++ b/src/core/ddsi/src/ddsi_raweth.c @@ -17,7 +17,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_pcap.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" @@ -362,7 +362,7 @@ static int ddsi_raweth_is_valid_port (ddsi_tran_factory_t fact, uint32_t port) return (port >= 1 && port <= 65535); } -int ddsi_raweth_init (struct q_globals *gv) +int ddsi_raweth_init (struct ddsi_domaingv *gv) { struct ddsi_tran_factory *fact = ddsrt_malloc (sizeof (*fact)); memset (fact, 0, sizeof (*fact)); @@ -391,6 +391,6 @@ int ddsi_raweth_init (struct q_globals *gv) #else -int ddsi_raweth_init (struct q_globals *gv) { (void) gv; return 0; } +int ddsi_raweth_init (struct ddsi_domaingv *gv) { (void) gv; return 0; } #endif /* defined __linux */ diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 9344253..ad60528 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -24,7 +24,7 @@ #include "dds/ddsi/ddsi_tkmap.h" #include "dds__stream.h" #include "dds/ddsi/q_radmin.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/ddsi_serdata_default.h" #if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN diff --git a/src/core/ddsi/src/ddsi_sertopic.c b/src/core/ddsi/src/ddsi_sertopic.c index 4dda872..278bd7e 100644 --- a/src/core/ddsi/src/ddsi_sertopic.c +++ b/src/core/ddsi/src/ddsi_sertopic.c @@ -25,7 +25,7 @@ #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/ddsi_serdata.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" bool ddsi_sertopic_equal (const struct ddsi_sertopic *a, const struct ddsi_sertopic *b) { @@ -58,7 +58,7 @@ struct ddsi_sertopic *ddsi_sertopic_ref (const struct ddsi_sertopic *sertopic_co return sertopic; } -struct ddsi_sertopic *ddsi_sertopic_lookup_locked (struct q_globals *gv, const struct ddsi_sertopic *sertopic_template) +struct ddsi_sertopic *ddsi_sertopic_lookup_locked (struct ddsi_domaingv *gv, const struct ddsi_sertopic *sertopic_template) { struct ddsi_sertopic *sertopic = ddsrt_hh_lookup (gv->sertopics, sertopic_template); #ifndef NDEBUG @@ -71,7 +71,7 @@ struct ddsi_sertopic *ddsi_sertopic_lookup_locked (struct q_globals *gv, const s return ddsi_sertopic_ref (sertopic); } -void ddsi_sertopic_register_locked (struct q_globals *gv, struct ddsi_sertopic *sertopic) +void ddsi_sertopic_register_locked (struct ddsi_domaingv *gv, struct ddsi_sertopic *sertopic) { assert (sertopic->gv == NULL); assert (sertopic->iid == 0); diff --git a/src/core/ddsi/src/ddsi_ssl.c b/src/core/ddsi/src/ddsi_ssl.c index e8abd98..bbbf19b 100644 --- a/src/core/ddsi/src/ddsi_ssl.c +++ b/src/core/ddsi/src/ddsi_ssl.c @@ -28,7 +28,7 @@ #include "dds/ddsrt/sockets.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/threads.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" static SSL_CTX *ddsi_ssl_ctx = NULL; static bool ddsi_ssl_allow_self_signed_hack = false; @@ -38,7 +38,7 @@ static SSL *ddsi_ssl_new (void) return SSL_new (ddsi_ssl_ctx); } -static void ddsi_ssl_error (const struct q_globals *gv, SSL *ssl, const char *str, int err) +static void ddsi_ssl_error (const struct ddsi_domaingv *gv, SSL *ssl, const char *str, int err) { char buff[128]; ERR_error_string ((unsigned) SSL_get_error (ssl, err), buff); @@ -178,7 +178,7 @@ static void ddsi_ssl_dynlock_destroy (CRYPTO_dynlock_value *lock, const char *fi static int ddsi_ssl_password (char *buf, int num, int rwflag, void *udata) { - struct q_globals *gv = udata; + struct ddsi_domaingv *gv = udata; (void) rwflag; if (num < 0 || (size_t) num < strlen (gv->config.ssl_key_pass) + 1) return 0; @@ -188,7 +188,7 @@ static int ddsi_ssl_password (char *buf, int num, int rwflag, void *udata) return (int) strlen (gv->config.ssl_key_pass); } -static SSL_CTX *ddsi_ssl_ctx_init (struct q_globals *gv) +static SSL_CTX *ddsi_ssl_ctx_init (struct ddsi_domaingv *gv) { SSL_CTX *ctx = SSL_CTX_new (SSLv23_method ()); unsigned disallow_TLSv1_2; @@ -281,7 +281,7 @@ fail: return NULL; } -static void dds_report_tls_version (const struct q_globals *gv, const SSL *ssl, const char *oper) +static void dds_report_tls_version (const struct ddsi_domaingv *gv, const SSL *ssl, const char *oper) { if (ssl) { @@ -292,7 +292,7 @@ static void dds_report_tls_version (const struct q_globals *gv, const SSL *ssl, } } -static SSL *ddsi_ssl_connect (const struct q_globals *gv, ddsrt_socket_t sock) +static SSL *ddsi_ssl_connect (const struct ddsi_domaingv *gv, ddsrt_socket_t sock) { SSL *ssl; int err; @@ -326,7 +326,7 @@ static BIO *ddsi_ssl_listen (ddsrt_socket_t sock) return bio; } -static SSL *ddsi_ssl_accept (const struct q_globals *gv, BIO *bio, ddsrt_socket_t *sock) +static SSL *ddsi_ssl_accept (const struct ddsi_domaingv *gv, BIO *bio, ddsrt_socket_t *sock) { SSL *ssl = NULL; BIO *nbio; @@ -350,7 +350,7 @@ static SSL *ddsi_ssl_accept (const struct q_globals *gv, BIO *bio, ddsrt_socket_ return ssl; } -static bool ddsi_ssl_init (struct q_globals *gv) +static bool ddsi_ssl_init (struct ddsi_domaingv *gv) { /* FIXME: allocate this stuff ... don't copy gv into a global variable ... */ ERR_load_BIO_strings (); diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 70f6ccb..e46bfc9 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -25,7 +25,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_entity.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #define INVALID_PORT (~0u) @@ -165,7 +165,7 @@ static void ddsi_tcp_sock_free (const struct ddsrt_log_cfg *logcfg, ddsrt_socket } } -static void ddsi_tcp_sock_new (ddsrt_socket_t *sock, unsigned short port, const struct q_globals *gv) +static void ddsi_tcp_sock_new (ddsrt_socket_t *sock, unsigned short port, const struct ddsi_domaingv *gv) { if (make_socket (sock, port, true, true, gv) != 0) { @@ -1057,7 +1057,7 @@ static int ddsi_tcp_is_valid_port (ddsi_tran_factory_t fact, uint32_t port) return (port <= 65535); } -int ddsi_tcp_init (struct q_globals *gv) +int ddsi_tcp_init (struct ddsi_domaingv *gv) { struct ddsi_tran_factory_tcp *fact = ddsrt_malloc (sizeof (*fact)); diff --git a/src/core/ddsi/src/ddsi_threadmon.c b/src/core/ddsi/src/ddsi_threadmon.c index 53139e9..2d1a453 100644 --- a/src/core/ddsi/src/ddsi_threadmon.c +++ b/src/core/ddsi/src/ddsi_threadmon.c @@ -22,7 +22,7 @@ #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_unused.h" -#include "dds/ddsi/q_globals.h" /* for mattr, cattr */ +#include "dds/ddsi/ddsi_domaingv.h" /* for mattr, cattr */ #include "dds/ddsi/q_receive.h" struct alive_vt { @@ -31,7 +31,7 @@ struct alive_vt { }; struct threadmon_domain { - const struct q_globals *gv; + const struct ddsi_domaingv *gv; unsigned n_not_alive; size_t msgpos; char msg[2048]; @@ -51,7 +51,7 @@ struct ddsi_threadmon { struct ddsrt_hh *domains; }; -static struct threadmon_domain *find_domain (struct ddsi_threadmon *sl, const struct q_globals *gv) +static struct threadmon_domain *find_domain (struct ddsi_threadmon *sl, const struct ddsi_domaingv *gv) { struct threadmon_domain dummy; dummy.gv = gv; @@ -101,7 +101,7 @@ static uint32_t threadmon_thread (struct ddsi_threadmon *sl) vtime_t vt = ddsrt_atomic_ld32 (&thread_states.ts[i].vtime); ddsrt_atomic_fence_ldld (); - struct q_globals const * const gv = ddsrt_atomic_ldvoidp (&thread_states.ts[i].gv); + struct ddsi_domaingv const * const gv = ddsrt_atomic_ldvoidp (&thread_states.ts[i].gv); struct threadmon_domain *tmdom = find_domain (sl, gv); if (tmdom == NULL) continue; @@ -238,7 +238,7 @@ dds_return_t ddsi_threadmon_start (struct ddsi_threadmon *sl, const char *name) return DDS_RETCODE_ERROR; } -void ddsi_threadmon_register_domain (struct ddsi_threadmon *sl, const struct q_globals *gv) +void ddsi_threadmon_register_domain (struct ddsi_threadmon *sl, const struct ddsi_domaingv *gv) { if (gv->config.liveliness_monitoring) { @@ -256,7 +256,7 @@ void ddsi_threadmon_register_domain (struct ddsi_threadmon *sl, const struct q_g } } -void ddsi_threadmon_unregister_domain (struct ddsi_threadmon *sl, const struct q_globals *gv) +void ddsi_threadmon_unregister_domain (struct ddsi_threadmon *sl, const struct ddsi_domaingv *gv) { if (gv->config.liveliness_monitoring) { diff --git a/src/core/ddsi/src/ddsi_tkmap.c b/src/core/ddsi/src/ddsi_tkmap.c index c00d4aa..7f281cd 100644 --- a/src/core/ddsi/src/ddsi_tkmap.c +++ b/src/core/ddsi/src/ddsi_tkmap.c @@ -18,7 +18,7 @@ #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_gc.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/ddsi_tkmap.h" @@ -32,7 +32,7 @@ struct ddsi_tkmap { struct ddsrt_chh *m_hh; - struct q_globals *gv; + struct ddsi_domaingv *gv; ddsrt_mutex_t m_lock; ddsrt_cond_t m_cond; }; @@ -86,7 +86,7 @@ static int dds_tk_equals_void (const void *a, const void *b) return dds_tk_equals (a, b); } -struct ddsi_tkmap *ddsi_tkmap_new (struct q_globals *gv) +struct ddsi_tkmap *ddsi_tkmap_new (struct ddsi_domaingv *gv) { struct ddsi_tkmap *tkmap = dds_alloc (sizeof (*tkmap)); tkmap->m_hh = ddsrt_chh_new (1, dds_tk_hash_void, dds_tk_equals_void, gc_buckets, tkmap); diff --git a/src/core/ddsi/src/ddsi_tran.c b/src/core/ddsi/src/ddsi_tran.c index 94ffc89..2bdda5d 100644 --- a/src/core/ddsi/src/ddsi_tran.c +++ b/src/core/ddsi/src/ddsi_tran.c @@ -20,7 +20,7 @@ #include "dds/ddsi/ddsi_ipaddr.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" extern inline uint32_t ddsi_conn_type (ddsi_tran_conn_t conn); extern inline uint32_t ddsi_conn_port (ddsi_tran_conn_t conn); @@ -37,13 +37,13 @@ extern inline ddsi_tran_conn_t ddsi_listener_accept (ddsi_tran_listener_t listen extern inline ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, bool allow_spurious, nn_locator_t *srcloc); extern inline ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const ddsrt_iovec_t *iov, uint32_t flags); -void ddsi_factory_add (struct q_globals *gv, ddsi_tran_factory_t factory) +void ddsi_factory_add (struct ddsi_domaingv *gv, ddsi_tran_factory_t factory) { factory->m_factory = gv->ddsi_tran_factories; gv->ddsi_tran_factories = factory; } -ddsi_tran_factory_t ddsi_factory_find (const struct q_globals *gv, const char *type) +ddsi_tran_factory_t ddsi_factory_find (const struct ddsi_domaingv *gv, const char *type) { /* FIXME: should speed up */ ddsi_tran_factory_t factory = gv->ddsi_tran_factories; @@ -60,7 +60,7 @@ ddsi_tran_factory_t ddsi_factory_find (const struct q_globals *gv, const char *t return factory; } -void ddsi_tran_factories_fini (struct q_globals *gv) +void ddsi_tran_factories_fini (struct ddsi_domaingv *gv) { ddsi_tran_factory_t factory; while ((factory = gv->ddsi_tran_factories) != NULL) @@ -73,7 +73,7 @@ void ddsi_tran_factories_fini (struct q_globals *gv) } } -static ddsi_tran_factory_t ddsi_factory_find_with_len (const struct q_globals *gv, const char *type, size_t len) +static ddsi_tran_factory_t ddsi_factory_find_with_len (const struct ddsi_domaingv *gv, const char *type, size_t len) { /* FIXME: should speed up */ ddsi_tran_factory_t factory = gv->ddsi_tran_factories; @@ -91,7 +91,7 @@ static ddsi_tran_factory_t ddsi_factory_find_with_len (const struct q_globals *g } ddsrt_attribute_no_sanitize (("thread")) -ddsi_tran_factory_t ddsi_factory_find_supported_kind (const struct q_globals *gv, int32_t kind) +ddsi_tran_factory_t ddsi_factory_find_supported_kind (const struct ddsi_domaingv *gv, int32_t kind) { /* FIXME: MUST speed up */ ddsi_tran_factory_t factory; @@ -237,13 +237,13 @@ void ddsi_listener_free (ddsi_tran_listener_t listener) } } -int ddsi_is_mcaddr (const struct q_globals *gv, const nn_locator_t *loc) +int ddsi_is_mcaddr (const struct ddsi_domaingv *gv, const nn_locator_t *loc) { ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind (gv, loc->kind); return tran ? tran->m_is_mcaddr_fn (tran, loc) : 0; } -int ddsi_is_ssm_mcaddr (const struct q_globals *gv, const nn_locator_t *loc) +int ddsi_is_ssm_mcaddr (const struct ddsi_domaingv *gv, const nn_locator_t *loc) { ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind(gv, loc->kind); if (tran && tran->m_is_ssm_mcaddr_fn != 0) @@ -259,7 +259,7 @@ enum ddsi_nearby_address_result ddsi_is_nearby_address (const nn_locator_t *loc, return ownloc->tran->m_is_nearby_address_fn (loc, ownloc, ninterf, interf); } -enum ddsi_locator_from_string_result ddsi_locator_from_string (const struct q_globals *gv, nn_locator_t *loc, const char *str, ddsi_tran_factory_t default_factory) +enum ddsi_locator_from_string_result ddsi_locator_from_string (const struct ddsi_domaingv *gv, nn_locator_t *loc, const char *str, ddsi_tran_factory_t default_factory) { const char *sep = strchr(str, '/'); ddsi_tran_factory_t tran; diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 8ebfcf1..8720468 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -25,7 +25,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_pcap.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" typedef struct ddsi_udp_conn { struct ddsi_tran_conn m_base; @@ -472,7 +472,7 @@ static int ddsi_udp_is_valid_port (ddsi_tran_factory_t fact, uint32_t port) return (port <= 65535); } -int ddsi_udp_init (struct q_globals *gv) +int ddsi_udp_init (struct ddsi_domaingv *gv) { struct ddsi_tran_factory *fact = ddsrt_malloc (sizeof (*fact)); memset (fact, 0, sizeof (*fact)); diff --git a/src/core/ddsi/src/q_addrset.c b/src/core/ddsi/src/q_addrset.c index 0c6d69d..98e5406 100644 --- a/src/core/ddsi/src/q_addrset.c +++ b/src/core/ddsi/src/q_addrset.c @@ -23,7 +23,7 @@ #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_addrset.h" -#include "dds/ddsi/q_globals.h" /* gv.mattr */ +#include "dds/ddsi/ddsi_domaingv.h" /* gv.mattr */ #include "dds/ddsi/ddsi_udp.h" /* nn_mc4gen_address_t */ /* So what does one do with const & mutexes? I need to take lock in a @@ -44,7 +44,7 @@ static int compare_locators_vwrap (const void *va, const void *vb); static const ddsrt_avl_ctreedef_t addrset_treedef = DDSRT_AVL_CTREEDEF_INITIALIZER (offsetof (struct addrset_node, avlnode), offsetof (struct addrset_node, loc), compare_locators_vwrap, 0); -static int add_addresses_to_addrset_1 (const struct q_globals *gv, struct addrset *as, const char *ip, int port_mode, const char *msgtag, int req_mc, int mcgen_base, int mcgen_count, int mcgen_idx) +static int add_addresses_to_addrset_1 (const struct ddsi_domaingv *gv, struct addrset *as, const char *ip, int port_mode, const char *msgtag, int req_mc, int mcgen_base, int mcgen_count, int mcgen_idx) { char buf[DDSI_LOCSTRLEN]; nn_locator_t loc; @@ -128,7 +128,7 @@ static int add_addresses_to_addrset_1 (const struct q_globals *gv, struct addrse return 0; } -int add_addresses_to_addrset (const struct q_globals *gv, struct addrset *as, const char *addrs, int port_mode, const char *msgtag, int req_mc) +int add_addresses_to_addrset (const struct ddsi_domaingv *gv, struct addrset *as, const char *addrs, int port_mode, const char *msgtag, int req_mc) { /* port_mode: -1 => take from string, if 0 & unicast, add for a range of participant indices; port_mode >= 0 => always set port to port_mode @@ -246,7 +246,7 @@ int is_unspec_locator (const nn_locator_t *loc) } #ifdef DDSI_INCLUDE_SSM -int addrset_contains_ssm (const struct q_globals *gv, const struct addrset *as) +int addrset_contains_ssm (const struct ddsi_domaingv *gv, const struct addrset *as) { struct addrset_node *n; ddsrt_avl_citer_t it; @@ -263,7 +263,7 @@ int addrset_contains_ssm (const struct q_globals *gv, const struct addrset *as) return 0; } -int addrset_any_ssm (const struct q_globals *gv, const struct addrset *as, nn_locator_t *dst) +int addrset_any_ssm (const struct ddsi_domaingv *gv, const struct addrset *as, nn_locator_t *dst) { struct addrset_node *n; ddsrt_avl_citer_t it; @@ -281,7 +281,7 @@ int addrset_any_ssm (const struct q_globals *gv, const struct addrset *as, nn_lo return 0; } -int addrset_any_non_ssm_mc (const struct q_globals *gv, const struct addrset *as, nn_locator_t *dst) +int addrset_any_non_ssm_mc (const struct ddsi_domaingv *gv, const struct addrset *as, nn_locator_t *dst) { struct addrset_node *n; ddsrt_avl_citer_t it; @@ -309,7 +309,7 @@ int addrset_purge (struct addrset *as) return 0; } -void add_to_addrset (const struct q_globals *gv, struct addrset *as, const nn_locator_t *loc) +void add_to_addrset (const struct ddsi_domaingv *gv, struct addrset *as, const nn_locator_t *loc) { if (!is_unspec_locator (loc)) { @@ -326,7 +326,7 @@ void add_to_addrset (const struct q_globals *gv, struct addrset *as, const nn_lo } } -void remove_from_addrset (const struct q_globals *gv, struct addrset *as, const nn_locator_t *loc) +void remove_from_addrset (const struct ddsi_domaingv *gv, struct addrset *as, const nn_locator_t *loc) { ddsrt_avl_dpath_t path; ddsrt_avl_ctree_t *tree = ddsi_is_mcaddr (gv, loc) ? &as->mcaddrs : &as->ucaddrs; @@ -340,7 +340,7 @@ void remove_from_addrset (const struct q_globals *gv, struct addrset *as, const UNLOCK (as); } -void copy_addrset_into_addrset_uc (const struct q_globals *gv, struct addrset *as, const struct addrset *asadd) +void copy_addrset_into_addrset_uc (const struct ddsi_domaingv *gv, struct addrset *as, const struct addrset *asadd) { struct addrset_node *n; ddsrt_avl_citer_t it; @@ -350,7 +350,7 @@ void copy_addrset_into_addrset_uc (const struct q_globals *gv, struct addrset *a UNLOCK (asadd); } -void copy_addrset_into_addrset_mc (const struct q_globals *gv, struct addrset *as, const struct addrset *asadd) +void copy_addrset_into_addrset_mc (const struct ddsi_domaingv *gv, struct addrset *as, const struct addrset *asadd) { struct addrset_node *n; ddsrt_avl_citer_t it; @@ -360,14 +360,14 @@ void copy_addrset_into_addrset_mc (const struct q_globals *gv, struct addrset *a UNLOCK (asadd); } -void copy_addrset_into_addrset (const struct q_globals *gv, struct addrset *as, const struct addrset *asadd) +void copy_addrset_into_addrset (const struct ddsi_domaingv *gv, struct addrset *as, const struct addrset *asadd) { copy_addrset_into_addrset_uc (gv, as, asadd); copy_addrset_into_addrset_mc (gv, as, asadd); } #ifdef DDSI_INCLUDE_SSM -void copy_addrset_into_addrset_no_ssm_mc (const struct q_globals *gv, struct addrset *as, const struct addrset *asadd) +void copy_addrset_into_addrset_no_ssm_mc (const struct ddsi_domaingv *gv, struct addrset *as, const struct addrset *asadd) { struct addrset_node *n; ddsrt_avl_citer_t it; @@ -381,7 +381,7 @@ void copy_addrset_into_addrset_no_ssm_mc (const struct q_globals *gv, struct add } -void copy_addrset_into_addrset_no_ssm (const struct q_globals *gv, struct addrset *as, const struct addrset *asadd) +void copy_addrset_into_addrset_no_ssm (const struct ddsi_domaingv *gv, struct addrset *as, const struct addrset *asadd) { copy_addrset_into_addrset_uc (gv, as, asadd); copy_addrset_into_addrset_no_ssm_mc (gv, as, asadd); @@ -549,19 +549,19 @@ int addrset_forone (struct addrset *as, addrset_forone_fun_t f, void *arg) struct log_addrset_helper_arg { uint32_t tf; - struct q_globals *gv; + struct ddsi_domaingv *gv; }; static void log_addrset_helper (const nn_locator_t *n, void *varg) { const struct log_addrset_helper_arg *arg = varg; - const struct q_globals *gv = arg->gv; + const struct ddsi_domaingv *gv = arg->gv; char buf[DDSI_LOCSTRLEN]; if (gv->logconfig.c.mask & arg->tf) GVLOG (arg->tf, " %s", ddsi_locator_to_string (buf, sizeof(buf), n)); } -void nn_log_addrset (struct q_globals *gv, uint32_t tf, const char *prefix, const struct addrset *as) +void nn_log_addrset (struct ddsi_domaingv *gv, uint32_t tf, const char *prefix, const struct addrset *as) { if (gv->logconfig.c.mask & tf) { diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 5a9b1ec..452f0e1 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -36,7 +36,7 @@ #include "dds/ddsi/q_radmin.h" #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/q_entity.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_transmit.h" @@ -45,7 +45,7 @@ #include "dds/ddsi/q_feature_check.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) +static int get_locator (const struct ddsi_domaingv *gv, nn_locator_t *loc, const nn_locators_t *locs, int uc_same_subnet) { struct nn_locators_one *l; nn_locator_t first, samenet; @@ -159,7 +159,7 @@ static int get_locator (const struct q_globals *gv, nn_locator_t *loc, const nn_ *** *****************************************************************************/ -static void maybe_add_pp_as_meta_to_as_disc (struct q_globals *gv, const struct addrset *as_meta) +static void maybe_add_pp_as_meta_to_as_disc (struct ddsi_domaingv *gv, const struct addrset *as_meta) { if (addrset_empty_mc (as_meta) || !(gv->config.allowMulticast & AMC_SPDP)) { @@ -391,7 +391,7 @@ static unsigned pseudo_random_delay (const ddsi_guid_t *x, const ddsi_guid_t *y, return (unsigned) (m >> 32); } -static void respond_to_spdp (const struct q_globals *gv, const ddsi_guid_t *dest_proxypp_guid) +static void respond_to_spdp (const struct ddsi_domaingv *gv, const ddsi_guid_t *dest_proxypp_guid) { struct entidx_enum_participant est; struct participant *pp; @@ -418,7 +418,7 @@ static void respond_to_spdp (const struct q_globals *gv, const ddsi_guid_t *dest static int handle_SPDP_dead (const struct receiver_state *rst, nn_wctime_t timestamp, const nn_plist_t *datap, unsigned statusinfo) { - struct q_globals * const gv = rst->gv; + struct ddsi_domaingv * const gv = rst->gv; ddsi_guid_t guid; GVLOGDISC ("SPDP ST%x", statusinfo); @@ -444,7 +444,7 @@ static int handle_SPDP_dead (const struct receiver_state *rst, nn_wctime_t times return 1; } -static void allowmulticast_aware_add_to_addrset (const struct q_globals *gv, uint32_t allow_multicast, struct addrset *as, const nn_locator_t *loc) +static void allowmulticast_aware_add_to_addrset (const struct ddsi_domaingv *gv, uint32_t allow_multicast, struct addrset *as, const nn_locator_t *loc) { #if DDSI_INCLUDE_SSM if (ddsi_is_ssm_mcaddr (gv, loc)) @@ -478,7 +478,7 @@ static struct proxy_participant *find_ddsi2_proxy_participant (const struct enti return pp; } -static void make_participants_dependent_on_ddsi2 (struct q_globals *gv, const ddsi_guid_t *ddsi2guid, nn_wctime_t timestamp) +static void make_participants_dependent_on_ddsi2 (struct ddsi_domaingv *gv, const ddsi_guid_t *ddsi2guid, nn_wctime_t timestamp) { struct entidx_enum_proxy_participant it; struct proxy_participant *pp, *d2pp; @@ -516,7 +516,7 @@ static void make_participants_dependent_on_ddsi2 (struct q_globals *gv, const dd static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_wctime_t timestamp, const nn_plist_t *datap) { - struct q_globals * const gv = rst->gv; + struct ddsi_domaingv * const gv = rst->gv; const unsigned bes_sedp_announcer_mask = NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER | NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER; @@ -799,7 +799,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_ static void handle_SPDP (const struct receiver_state *rst, seqno_t seq, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len) { - struct q_globals * const gv = rst->gv; + struct ddsi_domaingv * const gv = rst->gv; const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ if (data == NULL) { @@ -846,7 +846,7 @@ static void handle_SPDP (const struct receiver_state *rst, seqno_t seq, nn_wctim } struct add_locator_to_ps_arg { - struct q_globals *gv; + struct ddsi_domaingv *gv; nn_plist_t *ps; }; @@ -894,7 +894,7 @@ static int sedp_write_endpoint const struct entity_common *common, const struct endpoint_common *epcommon, const dds_qos_t *xqos, struct addrset *as) { - struct q_globals * const gv = wr->e.gv; + struct ddsi_domaingv * const gv = wr->e.gv; const dds_qos_t *defqos = is_writer_entityid (epguid->entityid) ? &gv->default_xqos_wr : &gv->default_xqos_rd; struct nn_xmsg *mpayload; uint64_t qosdiff; @@ -1049,7 +1049,7 @@ static const char *durability_to_string (dds_durability_kind_t k) return "undefined-durability"; } -static struct proxy_participant *implicitly_create_proxypp (struct q_globals *gv, const ddsi_guid_t *ppguid, nn_plist_t *datap /* note: potentially modifies datap */, const ddsi_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp, seqno_t seq) +static struct proxy_participant *implicitly_create_proxypp (struct ddsi_domaingv *gv, const ddsi_guid_t *ppguid, nn_plist_t *datap /* note: potentially modifies datap */, const ddsi_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp, seqno_t seq) { ddsi_guid_t privguid; nn_plist_t pp_plist; @@ -1132,7 +1132,7 @@ static struct proxy_participant *implicitly_create_proxypp (struct q_globals *gv static void handle_SEDP_alive (const struct receiver_state *rst, seqno_t seq, nn_plist_t *datap /* note: potentially modifies datap */, const ddsi_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp) { #define E(msg, lbl) do { GVLOGDISC (msg); goto lbl; } while (0) - struct q_globals * const gv = rst->gv; + struct ddsi_domaingv * const gv = rst->gv; struct proxy_participant *pp; struct proxy_writer * pwr = NULL; struct proxy_reader * prd = NULL; @@ -1326,7 +1326,7 @@ err: static void handle_SEDP_dead (const struct receiver_state *rst, nn_plist_t *datap, nn_wctime_t timestamp) { - struct q_globals * const gv = rst->gv; + struct ddsi_domaingv * const gv = rst->gv; int res; if (!(datap->present & PP_ENDPOINT_GUID)) { @@ -1343,7 +1343,7 @@ static void handle_SEDP_dead (const struct receiver_state *rst, nn_plist_t *data static void handle_SEDP (const struct receiver_state *rst, seqno_t seq, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len) { - struct q_globals * const gv = rst->gv; + struct ddsi_domaingv * const gv = rst->gv; const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ GVLOGDISC ("SEDP ST%x", statusinfo); if (data == NULL) @@ -1460,7 +1460,7 @@ static int defragment (unsigned char **datap, const struct nn_rdata *fragchain, int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, UNUSED_ARG (const ddsi_guid_t *rdguid), UNUSED_ARG (void *qarg)) { - struct q_globals * const gv = sampleinfo->rst->gv; + struct ddsi_domaingv * const gv = sampleinfo->rst->gv; struct proxy_writer *pwr; struct { struct CDRHeader cdr; diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index 7586ea0..e42168d 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -27,7 +27,7 @@ #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_plist.h" #include "dds/ddsi/ddsi_entity_index.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_addrset.h" #include "dds/ddsi/q_radmin.h" #include "dds/ddsi/q_ddsi_discovery.h" @@ -52,7 +52,7 @@ struct debug_monitor { ddsi_tran_listener_t servsock; ddsrt_mutex_t lock; ddsrt_cond_t cond; - struct q_globals *gv; + struct ddsi_domaingv *gv; struct plugin *plugins; int stop; }; @@ -142,7 +142,7 @@ static int print_proxy_endpoint_common (ddsi_tran_conn_t conn, const char *label } -static int print_participants (struct thread_state1 * const ts1, struct q_globals *gv, ddsi_tran_conn_t conn) +static int print_participants (struct thread_state1 * const ts1, struct ddsi_domaingv *gv, ddsi_tran_conn_t conn) { struct entidx_enum_participant e; struct participant *p; @@ -227,7 +227,7 @@ static int print_participants (struct thread_state1 * const ts1, struct q_global return x; } -static int print_proxy_participants (struct thread_state1 * const ts1, struct q_globals *gv, ddsi_tran_conn_t conn) +static int print_proxy_participants (struct thread_state1 * const ts1, struct ddsi_domaingv *gv, ddsi_tran_conn_t conn) { struct entidx_enum_proxy_participant e; struct proxy_participant *p; @@ -346,7 +346,7 @@ static uint32_t debmon_main (void *vdm) return 0; } -struct debug_monitor *new_debug_monitor (struct q_globals *gv, int32_t port) +struct debug_monitor *new_debug_monitor (struct ddsi_domaingv *gv, int32_t port) { struct debug_monitor *dm; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 456a98e..1f873d4 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -31,7 +31,7 @@ #include "dds/ddsi/q_lease.h" #include "dds/ddsi/q_qosmatch.h" #include "dds/ddsi/ddsi_entity_index.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_addrset.h" #include "dds/ddsi/q_xevent.h" /* qxev_spdp, &c. */ #include "dds/ddsi/q_ddsi_discovery.h" /* spdp_write, &c. */ @@ -209,7 +209,7 @@ const ddsrt_fibheap_def_t ldur_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (st /* used in (proxy)participant for writer liveliness monitoring */ const ddsrt_fibheap_def_t lease_fhdef_pp = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct lease, pp_heapnode), compare_lease_tdur); -static void entity_common_init (struct entity_common *e, struct q_globals *gv, const struct ddsi_guid *guid, const char *name, enum entity_kind kind, nn_wctime_t tcreate, nn_vendorid_t vendorid, bool onlylocal) +static void entity_common_init (struct entity_common *e, struct ddsi_domaingv *gv, const struct ddsi_guid *guid, const char *name, enum entity_kind kind, nn_wctime_t tcreate, nn_vendorid_t vendorid, bool onlylocal) { e->guid = *guid; e->kind = kind; @@ -583,7 +583,7 @@ static void participant_remove_wr_lease_locked (struct participant * pp, struct } } -dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist) +dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const nn_plist_t *plist) { struct participant *pp; ddsi_guid_t subguid, group_guid; @@ -816,7 +816,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * return 0; } -dds_return_t new_participant (ddsi_guid_t *p_ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist) +dds_return_t new_participant (ddsi_guid_t *p_ppguid, struct ddsi_domaingv *gv, unsigned flags, const nn_plist_t *plist) { union { uint64_t u64; uint32_t u32[2]; } u; u.u32[0] = gv->ppguid_base.prefix.u[1]; @@ -837,7 +837,7 @@ void update_participant_plist (struct participant *pp, const nn_plist_t *plist) ddsrt_mutex_unlock (&pp->e.lock); } -static void delete_builtin_endpoint (struct q_globals *gv, const struct ddsi_guid *ppguid, unsigned entityid) +static void delete_builtin_endpoint (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, unsigned entityid) { ddsi_guid_t guid; guid.prefix = ppguid->prefix; @@ -1009,7 +1009,7 @@ static void gc_delete_participant (struct gcreq *gcreq) unref_participant (pp, NULL); } -dds_return_t delete_participant (struct q_globals *gv, const struct ddsi_guid *ppguid) +dds_return_t delete_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid) { struct participant *pp; GVLOGDISC ("delete_participant("PGUIDFMT")\n", PGUID (*ppguid)); @@ -1266,7 +1266,7 @@ static void rebuild_make_locs_nrds(int **locs_nrds, int nreaders, int nlocs, con *locs_nrds = ln; } -static void rebuild_trace_covered(const struct q_globals *gv, int nreaders, int nlocs, const nn_locator_t *locs, const int *locs_nrds, const int8_t *covered) +static void rebuild_trace_covered(const struct ddsi_domaingv *gv, int nreaders, int nlocs, const nn_locator_t *locs, const int *locs_nrds, const int8_t *covered) { int i, j; for (i = 0; i < nlocs; i++) @@ -1283,7 +1283,7 @@ static void rebuild_trace_covered(const struct q_globals *gv, int nreaders, int } } -static int rebuild_select(const struct q_globals *gv, int nlocs, const nn_locator_t *locs, const int *locs_nrds, bool prefer_multicast) +static int rebuild_select(const struct ddsi_domaingv *gv, int nlocs, const nn_locator_t *locs, const int *locs_nrds, bool prefer_multicast) { int i, j; if (nlocs == 0) @@ -1306,7 +1306,7 @@ static int rebuild_select(const struct q_globals *gv, int nlocs, const nn_locato return (locs_nrds[j] > 0) ? j : -1; } -static void rebuild_add(const struct q_globals *gv, struct addrset *newas, int locidx, int nreaders, int nlocs, const nn_locator_t *locs, const int8_t *covered) +static void rebuild_add(const struct ddsi_domaingv *gv, struct addrset *newas, int locidx, int nreaders, int nlocs, const nn_locator_t *locs, const int8_t *covered) { char str[DDSI_LOCATORSTRLEN]; if (locs[locidx].kind != NN_LOCATOR_KIND_UDPv4MCGEN) @@ -1409,7 +1409,7 @@ static void rebuild_writer_addrset (struct writer *wr) ELOGDISC (wr, "\n"); } -void rebuild_or_clear_writer_addrsets (struct q_globals *gv, int rebuild) +void rebuild_or_clear_writer_addrsets (struct ddsi_domaingv *gv, int rebuild) { struct entidx_enum_writer est; struct writer *wr; @@ -1453,7 +1453,7 @@ static void free_wr_prd_match (struct wr_prd_match *m) } } -static void free_rd_pwr_match (struct q_globals *gv, struct rd_pwr_match *m) +static void free_rd_pwr_match (struct ddsi_domaingv *gv, struct rd_pwr_match *m) { if (m) { @@ -2658,7 +2658,7 @@ static void new_reader_writer_common (const struct ddsrt_log_cfg *logcfg, const topic ? topic->type_name : "(null)"); } -static void endpoint_common_init (struct entity_common *e, struct endpoint_common *c, struct q_globals *gv, enum entity_kind kind, const struct ddsi_guid *guid, const struct ddsi_guid *group_guid, struct participant *pp, bool onlylocal) +static void endpoint_common_init (struct entity_common *e, struct endpoint_common *c, struct ddsi_domaingv *gv, enum entity_kind kind, const struct ddsi_guid *guid, const struct ddsi_guid *group_guid, struct participant *pp, bool onlylocal) { entity_common_init (e, gv, guid, NULL, kind, now (), NN_VENDORID_ECLIPSE, pp->e.onlylocal || onlylocal); c->pp = ref_participant (pp, &e->guid); @@ -3212,7 +3212,7 @@ static dds_return_t new_writer_guid (struct writer **wr_out, const struct ddsi_g return 0; } -dds_return_t new_writer (struct writer **wr_out, struct q_globals *gv, struct ddsi_guid *wrguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg) +dds_return_t new_writer (struct writer **wr_out, struct ddsi_domaingv *gv, struct ddsi_guid *wrguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg) { struct participant *pp; dds_return_t rc; @@ -3234,7 +3234,7 @@ dds_return_t new_writer (struct writer **wr_out, struct q_globals *gv, struct dd return new_writer_guid (wr_out, wrguid, group_guid, pp, topic, xqos, whc, status_cb, status_cb_arg); } -struct local_orphan_writer *new_local_orphan_writer (struct q_globals *gv, ddsi_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc) +struct local_orphan_writer *new_local_orphan_writer (struct ddsi_domaingv *gv, ddsi_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc) { ddsi_guid_t guid; struct local_orphan_writer *lowr; @@ -3360,7 +3360,7 @@ static void writer_set_state (struct writer *wr, enum writer_state newstate) wr->state = newstate; } -dds_return_t unblock_throttled_writer (struct q_globals *gv, const struct ddsi_guid *guid) +dds_return_t unblock_throttled_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *guid) { struct writer *wr; assert (is_writer_entityid (guid->entityid)); @@ -3419,7 +3419,7 @@ dds_return_t delete_writer_nolinger_locked (struct writer *wr) return 0; } -dds_return_t delete_writer_nolinger (struct q_globals *gv, const struct ddsi_guid *guid) +dds_return_t delete_writer_nolinger (struct ddsi_domaingv *gv, const struct ddsi_guid *guid) { struct writer *wr; /* We take no care to ensure application writers are not deleted @@ -3449,7 +3449,7 @@ void delete_local_orphan_writer (struct local_orphan_writer *lowr) ddsrt_mutex_unlock (&lowr->wr.e.lock); } -dds_return_t delete_writer (struct q_globals *gv, const struct ddsi_guid *guid) +dds_return_t delete_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *guid) { struct writer *wr; struct whc_state whcst; @@ -3490,7 +3490,7 @@ dds_return_t delete_writer (struct q_globals *gv, const struct ddsi_guid *guid) /* READER ----------------------------------------------------------- */ #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS -static struct addrset *get_as_from_mapping (const struct q_globals *gv, const char *partition, const char *topic) +static struct addrset *get_as_from_mapping (const struct ddsi_domaingv *gv, const char *partition, const char *topic) { struct config_partitionmapping_listelem *pm; struct addrset *as = new_addrset (); @@ -3506,13 +3506,13 @@ static struct addrset *get_as_from_mapping (const struct q_globals *gv, const ch struct join_leave_mcast_helper_arg { ddsi_tran_conn_t conn; - struct q_globals *gv; + struct ddsi_domaingv *gv; }; static void join_mcast_helper (const nn_locator_t *n, void *varg) { struct join_leave_mcast_helper_arg *arg = varg; - struct q_globals *gv = arg->gv; + struct ddsi_domaingv *gv = arg->gv; if (ddsi_is_mcaddr (gv, n)) { if (n->kind != NN_LOCATOR_KIND_UDPv4MCGEN) @@ -3554,7 +3554,7 @@ static void join_mcast_helper (const nn_locator_t *n, void *varg) static void leave_mcast_helper (const nn_locator_t *n, void *varg) { struct join_leave_mcast_helper_arg *arg = varg; - struct q_globals *gv = arg->gv; + struct ddsi_domaingv *gv = arg->gv; if (ddsi_is_mcaddr (gv, n)) { if (n->kind != NN_LOCATOR_KIND_UDPv4MCGEN) @@ -3733,7 +3733,7 @@ static dds_return_t new_reader_guid dds_return_t new_reader ( struct reader **rd_out, - struct q_globals *gv, + struct ddsi_domaingv *gv, struct ddsi_guid *rdguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, @@ -3812,7 +3812,7 @@ static void gc_delete_reader (struct gcreq *gcreq) ddsrt_free (rd); } -dds_return_t delete_reader (struct q_globals *gv, const struct ddsi_guid *guid) +dds_return_t delete_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *guid) { struct reader *rd; assert (!is_writer_entityid (guid->entityid)); @@ -3960,7 +3960,7 @@ static void proxy_participant_remove_pwr_lease_locked (struct proxy_participant } } -void new_proxy_participant (struct q_globals *gv, const struct ddsi_guid *ppguid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const nn_plist_t *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq) +void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const nn_plist_t *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq) { /* No locking => iff all participants use unique guids, and sedp runs on a single thread, it can't go wrong. FIXME, maybe? The @@ -4151,7 +4151,7 @@ int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, se { proxypp->seq = seq; - struct q_globals * const gv = proxypp->e.gv; + struct ddsi_domaingv * const gv = proxypp->e.gv; const uint64_t pmask = PP_ENTITY_NAME; const uint64_t qmask = QP_USER_DATA; nn_plist_t *new_plist = ddsrt_malloc (sizeof (*new_plist)); @@ -4367,7 +4367,7 @@ static void purge_helper (const nn_locator_t *n, void * varg) delete_proxy_participant_by_guid (data->proxypp->e.gv, &data->proxypp->e.guid, data->timestamp, 1); } -void purge_proxy_participants (struct q_globals *gv, const nn_locator_t *loc, bool delete_from_as_disc) +void purge_proxy_participants (struct ddsi_domaingv *gv, const nn_locator_t *loc, bool delete_from_as_disc) { /* FIXME: check whether addr:port can't be reused for a new connection by the time we get here. */ /* NOTE: This function exists for the sole purpose of cleaning up after closing a TCP connection in ddsi_tcp_close_conn and the state of the calling thread could be anything at this point. Because of that we do the unspeakable and toggle the thread state conditionally. We can't afford to have it in "asleep", as that causes a race with the garbage collector. */ @@ -4390,7 +4390,7 @@ void purge_proxy_participants (struct q_globals *gv, const nn_locator_t *loc, bo thread_state_asleep (ts1); } -int delete_proxy_participant_by_guid (struct q_globals *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit) +int delete_proxy_participant_by_guid (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit) { struct proxy_participant *ppt; @@ -4413,7 +4413,7 @@ int delete_proxy_participant_by_guid (struct q_globals *gv, const struct ddsi_gu return 0; } -uint64_t get_entity_instance_id (const struct q_globals *gv, const struct ddsi_guid *guid) +uint64_t get_entity_instance_id (const struct ddsi_domaingv *gv, const struct ddsi_guid *guid) { struct thread_state1 *ts1 = lookup_thread_state (); struct entity_common *e; @@ -4472,7 +4472,7 @@ static void proxy_endpoint_common_fini (struct entity_common *e, struct proxy_en /* PROXY-WRITER ----------------------------------------------------- */ -int new_proxy_writer (struct q_globals *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const nn_plist_t *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp, seqno_t seq) +int new_proxy_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const nn_plist_t *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp, seqno_t seq) { struct proxy_participant *proxypp; struct proxy_writer *pwr; @@ -4698,7 +4698,7 @@ static void gc_delete_proxy_writer (struct gcreq *gcreq) /* 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) +int delete_proxy_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit) { struct proxy_writer *pwr; DDSRT_UNUSED_ARG (isimplicit); @@ -4806,7 +4806,7 @@ int proxy_writer_set_notalive (struct proxy_writer *pwr, bool notify) /* PROXY-READER ----------------------------------------------------- */ -int new_proxy_reader (struct q_globals *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const nn_plist_t *plist, nn_wctime_t timestamp, seqno_t seq +int new_proxy_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const nn_plist_t *plist, nn_wctime_t timestamp, seqno_t seq #ifdef DDSI_INCLUDE_SSM , int favours_ssm #endif @@ -4917,7 +4917,7 @@ static void gc_delete_proxy_reader (struct gcreq *gcreq) ddsrt_free (prd); } -int delete_proxy_reader (struct q_globals *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit) +int delete_proxy_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit) { struct proxy_reader *prd; (void)isimplicit; diff --git a/src/core/ddsi/src/q_gc.c b/src/core/ddsi/src/q_gc.c index 948510d..4444112 100644 --- a/src/core/ddsi/src/q_gc.c +++ b/src/core/ddsi/src/q_gc.c @@ -24,7 +24,7 @@ #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_lease.h" -#include "dds/ddsi/q_globals.h" /* for mattr, cattr */ +#include "dds/ddsi/ddsi_domaingv.h" /* for mattr, cattr */ #include "dds/ddsi/q_receive.h" /* for trigger_receive_threads */ struct gcreq_queue { @@ -34,11 +34,11 @@ struct gcreq_queue { ddsrt_cond_t cond; int terminate; int32_t count; - struct q_globals *gv; + struct ddsi_domaingv *gv; struct thread_state1 *ts; }; -static void threads_vtime_gather_for_wait (const struct q_globals *gv, unsigned *nivs, struct idx_vtime *ivs) +static void threads_vtime_gather_for_wait (const struct ddsi_domaingv *gv, unsigned *nivs, struct idx_vtime *ivs) { /* copy vtimes of threads, skipping those that are sleeping */ uint32_t i, j; @@ -189,7 +189,7 @@ static uint32_t gcreq_queue_thread (struct gcreq_queue *q) return 0; } -struct gcreq_queue *gcreq_queue_new (struct q_globals *gv) +struct gcreq_queue *gcreq_queue_new (struct ddsi_domaingv *gv) { struct gcreq_queue *q = ddsrt_malloc (sizeof (*q)); diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 1deb503..7727384 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -42,7 +42,7 @@ #include "dds/ddsi/q_gc.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_nwif.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/q_receive.h" #include "dds/ddsi/q_pcap.h" @@ -62,7 +62,7 @@ #include "dds__whc.h" #include "dds/ddsi/ddsi_iid.h" -static void add_peer_addresses (const struct q_globals *gv, struct addrset *as, const struct config_peer_listelem *list) +static void add_peer_addresses (const struct ddsi_domaingv *gv, struct addrset *as, const struct config_peer_listelem *list) { while (list) { @@ -77,7 +77,7 @@ enum make_uc_sockets_ret { MUSRET_NOSOCKET }; -static enum make_uc_sockets_ret make_uc_sockets (struct q_globals *gv, uint32_t * pdisc, uint32_t * pdata, int ppid) +static enum make_uc_sockets_ret make_uc_sockets (struct ddsi_domaingv *gv, uint32_t * pdisc, uint32_t * pdata, int ppid) { if (gv->config.many_sockets_mode == MSM_NO_UNICAST) { @@ -133,7 +133,7 @@ static void make_builtin_endpoint_xqos (dds_qos_t *q, const dds_qos_t *template) q->durability.kind = DDS_DURABILITY_TRANSIENT_LOCAL; } -static int set_recvips (struct q_globals *gv) +static int set_recvips (struct ddsi_domaingv *gv) { gv->recvips = NULL; @@ -238,7 +238,7 @@ static int set_recvips (struct q_globals *gv) * return -1 : ddsi is unicast, but 'mc' indicates it expects multicast * return 0 : ddsi is multicast, but 'mc' indicates it expects unicast * The return 0 means that the possible changes in 'loc' can be ignored. */ -static int string_to_default_locator (const struct q_globals *gv, nn_locator_t *loc, const char *string, uint32_t port, int mc, const char *tag) +static int string_to_default_locator (const struct ddsi_domaingv *gv, nn_locator_t *loc, const char *string, uint32_t port, int mc, const char *tag) { if (strspn (string, " \t") == strlen (string)) { @@ -277,7 +277,7 @@ static int string_to_default_locator (const struct q_globals *gv, nn_locator_t * return 1; } -static int set_spdp_address (struct q_globals *gv) +static int set_spdp_address (struct ddsi_domaingv *gv) { const uint32_t port = ddsi_get_port (&gv->config, DDSI_PORT_MULTI_DISC, 0); int rc = 0; @@ -310,7 +310,7 @@ static int set_spdp_address (struct q_globals *gv) return 0; } -static int set_default_mc_address (struct q_globals *gv) +static int set_default_mc_address (struct ddsi_domaingv *gv) { const uint32_t port = ddsi_get_port (&gv->config, DDSI_PORT_MULTI_DATA, 0); int rc; @@ -324,7 +324,7 @@ static int set_default_mc_address (struct q_globals *gv) return 0; } -static int set_ext_address_and_mask (struct q_globals *gv) +static int set_ext_address_and_mask (struct ddsi_domaingv *gv) { nn_locator_t loc; int rc; @@ -361,7 +361,7 @@ static int set_ext_address_and_mask (struct q_globals *gv) } #ifdef DDSI_INCLUDE_NETWORK_CHANNELS -static int known_channel_p (const struct q_globals *gv, const char *name) +static int known_channel_p (const struct ddsi_domaingv *gv, const char *name) { const struct config_channel_listelem *c; for (c = gv->config.channels; c; c = c->next) @@ -371,7 +371,7 @@ static int known_channel_p (const struct q_globals *gv, const char *name) } #endif -static int check_thread_properties (const struct q_globals *gv) +static int check_thread_properties (const struct ddsi_domaingv *gv) { #ifdef DDSI_INCLUDE_NETWORK_CHANNELS static const char *fixed[] = { "recv", "tev", "gc", "lease", "dq.builtins", "debmon", NULL }; @@ -411,7 +411,7 @@ static int check_thread_properties (const struct q_globals *gv) return ok; } -int rtps_config_open_trace (struct q_globals *gv) +int rtps_config_open_trace (struct ddsi_domaingv *gv) { DDSRT_WARNING_MSVC_OFF(4996); int status; @@ -447,7 +447,7 @@ int rtps_config_open_trace (struct q_globals *gv) DDSRT_WARNING_MSVC_ON(4996); } -int rtps_config_prep (struct q_globals *gv, struct cfgst *cfgst) +int rtps_config_prep (struct ddsi_domaingv *gv, struct cfgst *cfgst) { #ifdef DDSI_INCLUDE_NETWORK_CHANNELS unsigned num_channels = 0; @@ -613,7 +613,7 @@ err_config_late_error: } struct joinleave_spdp_defmcip_helper_arg { - struct q_globals *gv; + struct ddsi_domaingv *gv; int errcount; int dojoin; }; @@ -639,7 +639,7 @@ static void joinleave_spdp_defmcip_helper (const nn_locator_t *loc, void *varg) } } -int joinleave_spdp_defmcip (struct q_globals *gv, int dojoin) +int joinleave_spdp_defmcip (struct ddsi_domaingv *gv, int dojoin) { /* Addrset provides an easy way to filter out duplicates */ struct joinleave_spdp_defmcip_helper_arg arg; @@ -661,7 +661,7 @@ int joinleave_spdp_defmcip (struct q_globals *gv, int dojoin) return 0; } -int create_multicast_sockets (struct q_globals *gv) +int create_multicast_sockets (struct ddsi_domaingv *gv) { ddsi_tran_qos_t qos = ddsi_tran_create_qos (); ddsi_tran_conn_t disc, data; @@ -711,7 +711,7 @@ err_disc: return 0; } -static void rtps_term_prep (struct q_globals *gv) +static void rtps_term_prep (struct ddsi_domaingv *gv) { /* Stop all I/O */ ddsrt_mutex_lock (&gv->lock); @@ -726,7 +726,7 @@ static void rtps_term_prep (struct q_globals *gv) } struct wait_for_receive_threads_helper_arg { - struct q_globals *gv; + struct ddsi_domaingv *gv; unsigned count; }; @@ -739,7 +739,7 @@ static void wait_for_receive_threads_helper (struct xevent *xev, void *varg, nn_ (void) resched_xevent_if_earlier (xev, add_duration_to_mtime (tnow, T_SECOND)); } -static void wait_for_receive_threads (struct q_globals *gv) +static void wait_for_receive_threads (struct ddsi_domaingv *gv) { struct xevent *trigev; struct wait_for_receive_threads_helper_arg cbarg; @@ -786,13 +786,13 @@ static struct ddsi_sertopic *make_special_topic (const char *name, struct serdat return (struct ddsi_sertopic *) st; } -static void free_special_topics (struct q_globals *gv) +static void free_special_topics (struct ddsi_domaingv *gv) { ddsi_sertopic_unref (gv->plist_topic); ddsi_sertopic_unref (gv->rawcdr_topic); } -static void make_special_topics (struct q_globals *gv) +static void make_special_topics (struct ddsi_domaingv *gv) { gv->plist_topic = make_special_topic ("plist", gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? PL_CDR_LE : PL_CDR_BE, &ddsi_serdata_ops_plist); gv->rawcdr_topic = make_special_topic ("rawcdr", gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE, &ddsi_serdata_ops_rawcdr); @@ -833,7 +833,7 @@ static bool use_multiple_receive_threads (const struct config *cfg) return false; } -static int setup_and_start_recv_threads (struct q_globals *gv) +static int setup_and_start_recv_threads (struct ddsi_domaingv *gv) { const bool multi_recv_thr = use_multiple_receive_threads (&gv->config); @@ -927,7 +927,7 @@ static uint32_t ddsi_sertopic_hash_wrap (const void *tp) return ddsi_sertopic_hash (tp); } -int rtps_init (struct q_globals *gv) +int rtps_init (struct ddsi_domaingv *gv) { uint32_t port_disc_uc = 0; uint32_t port_data_uc = 0; @@ -1048,7 +1048,6 @@ int rtps_init (struct q_globals *gv) GVLOG (DDS_LC_CONFIG, "ownip: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv->ownloc)); GVLOG (DDS_LC_CONFIG, "extip: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv->extloc)); GVLOG (DDS_LC_CONFIG, "extmask: %s%s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv->extmask), gv->m_factory->m_kind != NN_LOCATOR_KIND_UDPv4 ? " (not applicable)" : ""); - GVLOG (DDS_LC_CONFIG, "networkid: 0x%lx\n", (unsigned long) gv->myNetworkId); GVLOG (DDS_LC_CONFIG, "SPDP MC: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv->loc_spdp_mc)); GVLOG (DDS_LC_CONFIG, "default MC: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv->loc_default_mc)); #ifdef DDSI_INCLUDE_SSM @@ -1483,7 +1482,7 @@ static void stop_all_xeventq_upto (struct config_channel_listelem *chptr) } #endif -int rtps_start (struct q_globals *gv) +int rtps_start (struct ddsi_domaingv *gv) { if (xeventq_start (gv->xevents, NULL) < 0) return -1; @@ -1549,7 +1548,7 @@ static void builtins_dqueue_ready_cb (void *varg) ddsrt_mutex_unlock (&arg->lock); } -void rtps_stop (struct q_globals *gv) +void rtps_stop (struct ddsi_domaingv *gv) { struct thread_state1 * const ts1 = lookup_thread_state (); @@ -1680,7 +1679,7 @@ void rtps_stop (struct q_globals *gv) ddsrt_mutex_destroy (&gv->privileged_pp_lock); } -void rtps_fini (struct q_globals *gv) +void rtps_fini (struct ddsi_domaingv *gv) { /* Shut down the GC system -- no new requests will be added */ gcreq_queue_free (gv->gcreq_queue); diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index bc974b1..7a0b598 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -32,7 +32,7 @@ #include "dds/ddsi/q_radmin.h" #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/q_entity.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_transmit.h" @@ -64,13 +64,13 @@ int compare_lease_tdur (const void *va, const void *vb) return (a->tdur == b->tdur) ? 0 : (a->tdur < b->tdur) ? -1 : 1; } -void lease_management_init (struct q_globals *gv) +void lease_management_init (struct ddsi_domaingv *gv) { ddsrt_mutex_init (&gv->leaseheap_lock); ddsrt_fibheap_init (&lease_fhdef, &gv->leaseheap); } -void lease_management_term (struct q_globals *gv) +void lease_management_term (struct ddsi_domaingv *gv) { assert (ddsrt_fibheap_min (&lease_fhdef, &gv->leaseheap) == NULL); ddsrt_mutex_destroy (&gv->leaseheap_lock); @@ -105,7 +105,7 @@ struct lease *lease_clone (const struct lease *l) void lease_register (struct lease *l) /* FIXME: make lease admin struct */ { - struct q_globals * const gv = l->entity->gv; + struct ddsi_domaingv * const gv = l->entity->gv; GVTRACE ("lease_register(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid)); ddsrt_mutex_lock (&gv->leaseheap_lock); assert (l->tsched.v == TSCHED_NOT_ON_HEAP); @@ -123,7 +123,7 @@ void lease_register (struct lease *l) /* FIXME: make lease admin struct */ void lease_unregister (struct lease *l) { - struct q_globals * const gv = l->entity->gv; + struct ddsi_domaingv * const gv = l->entity->gv; 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) @@ -139,14 +139,14 @@ void lease_unregister (struct lease *l) void lease_free (struct lease *l) { - struct q_globals * const gv = l->entity->gv; + struct ddsi_domaingv * const gv = l->entity->gv; GVTRACE ("lease_free(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid)); ddsrt_free (l); } static void trace_lease_renew (const struct lease *l, const char *tag, nn_etime_t tend_new) { - struct q_globals const * gv = l->entity->gv; + struct ddsi_domaingv const * gv = l->entity->gv; if (gv->logconfig.c.mask & DDS_LC_TRACE) { int32_t tsec, tusec; @@ -181,7 +181,7 @@ void lease_renew (struct lease *l, nn_etime_t tnowE) void lease_set_expiry (struct lease *l, nn_etime_t when) { - struct q_globals * const gv = l->entity->gv; + struct ddsi_domaingv * const gv = l->entity->gv; bool trigger = false; assert (when.v >= 0); ddsrt_mutex_lock (&gv->leaseheap_lock); @@ -212,7 +212,7 @@ void lease_set_expiry (struct lease *l, nn_etime_t when) force_lease_check (gv->gcreq_queue); } -int64_t check_and_handle_lease_expiration (struct q_globals *gv, nn_etime_t tnowE) +int64_t check_and_handle_lease_expiration (struct ddsi_domaingv *gv, nn_etime_t tnowE) { struct lease *l; int64_t delay; diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index 79edd74..7b96a2f 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -24,7 +24,7 @@ #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_nwif.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_misc.h" @@ -214,7 +214,7 @@ static int set_reuse_options (const struct ddsrt_log_cfg *logcfg, ddsrt_socket_t return 0; } -static int bind_socket (ddsrt_socket_t socket, unsigned short port, const struct q_globals *gv) +static int bind_socket (ddsrt_socket_t socket, unsigned short port, const struct ddsi_domaingv *gv) { dds_return_t rc = DDS_RETCODE_ERROR; @@ -249,7 +249,7 @@ static int bind_socket (ddsrt_socket_t socket, unsigned short port, const struct } #if DDSRT_HAVE_IPV6 -static int set_mc_options_transmit_ipv6 (ddsrt_socket_t socket, const struct q_globals *gv) +static int set_mc_options_transmit_ipv6 (ddsrt_socket_t socket, const struct ddsi_domaingv *gv) { unsigned interfaceNo = gv->interfaceNo; unsigned ttl = (unsigned) gv->config.multicast_ttl; @@ -274,7 +274,7 @@ static int set_mc_options_transmit_ipv6 (ddsrt_socket_t socket, const struct q_g } #endif -static int set_mc_options_transmit_ipv4 (ddsrt_socket_t socket, const struct q_globals *gv) +static int set_mc_options_transmit_ipv4 (ddsrt_socket_t socket, const struct ddsi_domaingv *gv) { unsigned char ttl = (unsigned char) gv->config.multicast_ttl; unsigned char loop; @@ -319,7 +319,7 @@ static int set_mc_options_transmit_ipv4 (ddsrt_socket_t socket, const struct q_g return 0; } -static int set_mc_options_transmit (ddsrt_socket_t socket, const struct q_globals *gv) +static int set_mc_options_transmit (ddsrt_socket_t socket, const struct ddsi_domaingv *gv) { #if DDSRT_HAVE_IPV6 if (gv->config.transport_selector == TRANS_TCP6 || gv->config.transport_selector == TRANS_UDP6) @@ -338,7 +338,7 @@ static int set_mc_options_transmit (ddsrt_socket_t socket, const struct q_global } } -int make_socket (ddsrt_socket_t *sock, uint16_t port, bool stream, bool reuse, const struct q_globals *gv) +int make_socket (ddsrt_socket_t *sock, uint16_t port, bool stream, bool reuse, const struct ddsi_domaingv *gv) { /* FIXME: this stuff has to move to the transports */ int rc = -2; @@ -433,7 +433,7 @@ static int multicast_override(const char *ifname, const struct config *config) #include #endif -int find_own_ip (struct q_globals *gv, const char *requested_address) +int find_own_ip (struct ddsi_domaingv *gv, const char *requested_address) { const char *sep = " "; char last_if_name[80] = ""; diff --git a/src/core/ddsi/src/q_pcap.c b/src/core/ddsi/src/q_pcap.c index 1ac6117..42b2824 100644 --- a/src/core/ddsi/src/q_pcap.c +++ b/src/core/ddsi/src/q_pcap.c @@ -16,7 +16,7 @@ #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_config.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_pcap.h" @@ -127,7 +127,7 @@ static uint16_t calc_ipv4_checksum (const uint16_t *x) return (uint16_t) ~s; } -void write_pcap_received (struct q_globals *gv, nn_wctime_t tstamp, const struct sockaddr_storage *src, const struct sockaddr_storage *dst, unsigned char *buf, size_t sz) +void write_pcap_received (struct ddsi_domaingv *gv, nn_wctime_t tstamp, const struct sockaddr_storage *src, const struct sockaddr_storage *dst, unsigned char *buf, size_t sz) { if (gv->config.transport_selector == TRANS_UDP) { @@ -160,7 +160,7 @@ void write_pcap_received (struct q_globals *gv, nn_wctime_t tstamp, const struct } } -void write_pcap_sent (struct q_globals *gv, nn_wctime_t tstamp, const struct sockaddr_storage *src, const ddsrt_msghdr_t *hdr, size_t sz) +void write_pcap_sent (struct ddsi_domaingv *gv, nn_wctime_t tstamp, const struct sockaddr_storage *src, const ddsrt_msghdr_t *hdr, size_t sz) { if (gv->config.transport_selector == TRANS_UDP) { diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 8cc371e..1405b13 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -31,7 +31,7 @@ #include "dds/ddsi/ddsi_udp.h" /* nn_mc4gen_address_t */ #include "dds/ddsi/q_config.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_protocol.h" /* for NN_STATUSINFO_... */ #include "dds/ddsi/q_radmin.h" /* for nn_plist_quickscan */ diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index e6a8252..2f5694f 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -41,7 +41,7 @@ #include "dds/ddsi/q_radmin.h" #include "dds/ddsi/q_bitset.h" #include "dds/ddsi/q_thread.h" -#include "dds/ddsi/q_globals.h" /* for mattr, cattr */ +#include "dds/ddsi/ddsi_domaingv.h" /* for mattr, cattr */ /* OVERVIEW ------------------------------------------------------------ @@ -2426,7 +2426,7 @@ static enum dqueue_elem_kind dqueue_elem_kind (const struct nn_rsample_chain_ele static uint32_t dqueue_thread (struct nn_dqueue *q) { struct thread_state1 * const ts1 = lookup_thread_state (); - struct q_globals const * const gv = ddsrt_atomic_ldvoidp (&ts1->gv); + struct ddsi_domaingv const * const gv = ddsrt_atomic_ldvoidp (&ts1->gv); nn_mtime_t next_thread_cputime = { 0 }; int keepgoing = 1; ddsi_guid_t rdguid, *prdguid = NULL; @@ -2513,7 +2513,7 @@ static uint32_t dqueue_thread (struct nn_dqueue *q) return 0; } -struct nn_dqueue *nn_dqueue_new (const char *name, const struct q_globals *gv, uint32_t max_samples, nn_dqueue_handler_t handler, void *arg) +struct nn_dqueue *nn_dqueue_new (const char *name, const struct ddsi_domaingv *gv, uint32_t max_samples, nn_dqueue_handler_t handler, void *arg) { struct nn_dqueue *q; char *thrname; diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 0b8e118..614aba4 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -48,7 +48,7 @@ #include "dds/ddsi/ddsi_deliver_locally.h" #include "dds/ddsi/q_transmit.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_init.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_mcgroup.h" @@ -1743,7 +1743,7 @@ struct remote_sourceinfo { nn_wctime_t tstamp; }; -static struct ddsi_serdata *remote_make_sample (struct ddsi_tkmap_instance **tk, struct q_globals *gv, struct ddsi_sertopic const * const topic, void *vsourceinfo) +static struct ddsi_serdata *remote_make_sample (struct ddsi_tkmap_instance **tk, struct ddsi_domaingv *gv, struct ddsi_sertopic const * const topic, void *vsourceinfo) { /* hopefully the compiler figures out that these are just aliases and doesn't reload them unnecessarily from memory */ @@ -1917,7 +1917,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st .on_failure_fastpath = remote_on_delivery_failure_fastpath }; struct receiver_state const * const rst = sampleinfo->rst; - struct q_globals * const gv = rst->gv; + struct ddsi_domaingv * const gv = rst->gv; struct proxy_writer * const pwr = sampleinfo->pwr; unsigned statusinfo; Data_DataFrag_common_t *msg; @@ -2257,7 +2257,7 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct static int handle_SPDP (const struct nn_rsample_info *sampleinfo, struct nn_rdata *rdata) { - struct q_globals * const gv = sampleinfo->rst->gv; + struct ddsi_domaingv * const gv = sampleinfo->rst->gv; struct nn_rsample *rsample; struct nn_rsample_chain sc; struct nn_rdata *fragchain; @@ -2452,7 +2452,7 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct return 1; } -static void malformed_packet_received_nosubmsg (const struct q_globals *gv, const unsigned char * msg, ssize_t len, const char *state, nn_vendorid_t vendorid +static void malformed_packet_received_nosubmsg (const struct ddsi_domaingv *gv, const unsigned char * msg, ssize_t len, const char *state, nn_vendorid_t vendorid ) { char tmp[1024]; @@ -2469,7 +2469,7 @@ static void malformed_packet_received_nosubmsg (const struct q_globals *gv, cons GVWARNING ("%s\n", tmp); } -static void malformed_packet_received (const struct q_globals *gv, const unsigned char *msg, const unsigned char *submsg, size_t len, const char *state, SubmessageKind_t smkind, nn_vendorid_t vendorid) +static void malformed_packet_received (const struct ddsi_domaingv *gv, const unsigned char *msg, const unsigned char *submsg, size_t len, const char *state, SubmessageKind_t smkind, nn_vendorid_t vendorid) { char tmp[1024]; size_t i, pos, smsize; @@ -2584,7 +2584,7 @@ static struct receiver_state *rst_cow_if_needed (int *rst_live, struct nn_rmsg * static int handle_submsg_sequence ( struct thread_state1 * const ts1, - struct q_globals *gv, + struct ddsi_domaingv *gv, ddsi_tran_conn_t conn, const nn_locator_t *srcloc, nn_wctime_t tnowWC, @@ -2864,7 +2864,7 @@ malformed_asleep: return -1; } -static bool do_packet (struct thread_state1 * const ts1, struct q_globals *gv, ddsi_tran_conn_t conn, const ddsi_guid_prefix_t *guidprefix, struct nn_rbufpool *rbpool) +static bool do_packet (struct thread_state1 * const ts1, struct ddsi_domaingv *gv, ddsi_tran_conn_t conn, const ddsi_guid_prefix_t *guidprefix, struct nn_rbufpool *rbpool) { /* UDP max packet size is 64kB */ @@ -3041,7 +3041,7 @@ static void local_participant_set_fini (struct local_participant_set *lps) ddsrt_free (lps->ps); } -static void rebuild_local_participant_set (struct thread_state1 * const ts1, struct q_globals *gv, struct local_participant_set *lps) +static void rebuild_local_participant_set (struct thread_state1 * const ts1, struct ddsi_domaingv *gv, struct local_participant_set *lps) { struct entidx_enum_participant est; struct participant *pp; @@ -3109,7 +3109,7 @@ static void rebuild_local_participant_set (struct thread_state1 * const ts1, str uint32_t listen_thread (struct ddsi_tran_listener *listener) { - struct q_globals *gv = listener->m_base.gv; + struct ddsi_domaingv *gv = listener->m_base.gv; ddsi_tran_conn_t conn; while (ddsrt_atomic_ld32 (&gv->rtps_keepgoing)) @@ -3132,7 +3132,7 @@ static int recv_thread_waitset_add_conn (os_sockWaitset ws, ddsi_tran_conn_t con return 0; else { - struct q_globals *gv = conn->m_base.gv; + struct ddsi_domaingv *gv = conn->m_base.gv; for (uint32_t i = 0; i < gv->n_recv_threads; i++) if (gv->recv_threads[i].arg.mode == RTM_SINGLE && gv->recv_threads[i].arg.u.single.conn == conn) return 0; @@ -3151,7 +3151,7 @@ struct local_deaf_state { nn_mtime_t tnext; }; -static int check_and_handle_deafness_recover (struct q_globals *gv, struct local_deaf_state *st, unsigned num_fixed_uc) +static int check_and_handle_deafness_recover (struct ddsi_domaingv *gv, struct local_deaf_state *st, unsigned num_fixed_uc) { int rebuildws = 0; if (now_mt().v < st->tnext.v) @@ -3206,7 +3206,7 @@ error: return rebuildws; } -static int check_and_handle_deafness (struct q_globals *gv, struct local_deaf_state *st, unsigned num_fixed_uc) +static int check_and_handle_deafness (struct ddsi_domaingv *gv, struct local_deaf_state *st, unsigned num_fixed_uc) { const int gv_deaf = gv->deaf; assert (gv_deaf == 0 || gv_deaf == 1); @@ -3231,7 +3231,7 @@ static int check_and_handle_deafness (struct q_globals *gv, struct local_deaf_st } } -void trigger_recv_threads (const struct q_globals *gv) +void trigger_recv_threads (const struct ddsi_domaingv *gv) { for (uint32_t i = 0; i < gv->n_recv_threads; i++) { @@ -3263,7 +3263,7 @@ uint32_t recv_thread (void *vrecv_thread_arg) { struct thread_state1 * const ts1 = lookup_thread_state (); struct recv_thread_arg *recv_thread_arg = vrecv_thread_arg; - struct q_globals * const gv = recv_thread_arg->gv; + struct ddsi_domaingv * const gv = recv_thread_arg->gv; struct nn_rbufpool *rbpool = recv_thread_arg->rbpool; os_sockWaitset waitset = recv_thread_arg->mode == RTM_MANY ? recv_thread_arg->u.many.ws : NULL; nn_mtime_t next_thread_cputime = { 0 }; diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index 1c0c144..a8190fa 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -25,7 +25,7 @@ #include "dds/ddsi/ddsi_threadmon.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_config.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/sysdeps.h" struct thread_states thread_states; @@ -39,12 +39,12 @@ extern inline struct thread_state1 *lookup_thread_state (void); extern inline bool thread_is_asleep (void); extern inline bool thread_is_awake (void); extern inline void thread_state_asleep (struct thread_state1 *ts1); -extern inline void thread_state_awake (struct thread_state1 *ts1, const struct q_globals *gv); +extern inline void thread_state_awake (struct thread_state1 *ts1, const struct ddsi_domaingv *gv); extern inline void thread_state_awake_domain_ok (struct thread_state1 *ts1); extern inline void thread_state_awake_fixed_domain (struct thread_state1 *ts1); extern inline void thread_state_awake_to_awake_no_nest (struct thread_state1 *ts1); -static struct thread_state1 *init_thread_state (const char *tname, const struct q_globals *gv, enum thread_state state); +static struct thread_state1 *init_thread_state (const char *tname, const struct ddsi_domaingv *gv, enum thread_state state); static void reap_thread_state (struct thread_state1 *ts1); static void *ddsrt_malloc_aligned_cacheline (size_t size) @@ -213,7 +213,7 @@ static uint32_t create_thread_wrapper (void *ptr) { uint32_t ret; struct thread_context *ctx = ptr; - struct q_globals const * const gv = ddsrt_atomic_ldvoidp (&ctx->self->gv); + struct ddsi_domaingv const * const gv = ddsrt_atomic_ldvoidp (&ctx->self->gv); if (gv) GVTRACE ("started new thread %"PRIdTID": %s\n", ddsrt_gettid (), ctx->self->name); ctx->self->tid = ddsrt_thread_self (); @@ -240,7 +240,7 @@ const struct config_thread_properties_listelem *lookup_thread_properties (const return e; } -static struct thread_state1 *init_thread_state (const char *tname, const struct q_globals *gv, enum thread_state state) +static struct thread_state1 *init_thread_state (const char *tname, const struct ddsi_domaingv *gv, enum thread_state state) { int cand; struct thread_state1 *ts; @@ -249,7 +249,7 @@ static struct thread_state1 *init_thread_state (const char *tname, const struct return NULL; ts = &thread_states.ts[cand]; - ddsrt_atomic_stvoidp (&ts->gv, (struct q_globals *) gv); + ddsrt_atomic_stvoidp (&ts->gv, (struct ddsi_domaingv *) gv); assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts->vtime))); (void) ddsrt_strlcpy (ts->name, tname, sizeof (ts->name)); ts->state = state; @@ -257,7 +257,7 @@ static struct thread_state1 *init_thread_state (const char *tname, const struct return ts; } -static dds_return_t create_thread_int (struct thread_state1 **ts1, const struct q_globals *gv, struct config_thread_properties_listelem const * const tprops, const char *name, uint32_t (*f) (void *arg), void *arg) +static dds_return_t create_thread_int (struct thread_state1 **ts1, const struct ddsi_domaingv *gv, struct config_thread_properties_listelem const * const tprops, const char *name, uint32_t (*f) (void *arg), void *arg) { ddsrt_threadattr_t tattr; ddsrt_thread_t tid; @@ -308,7 +308,7 @@ dds_return_t create_thread_with_properties (struct thread_state1 **ts1, struct c return create_thread_int (ts1, NULL, tprops, name, f, arg); } -dds_return_t create_thread (struct thread_state1 **ts1, const struct q_globals *gv, const char *name, uint32_t (*f) (void *arg), void *arg) +dds_return_t create_thread (struct thread_state1 **ts1, const struct ddsi_domaingv *gv, const char *name, uint32_t (*f) (void *arg), void *arg) { struct config_thread_properties_listelem const * const tprops = lookup_thread_properties (&gv->config, name); return create_thread_int (ts1, gv, tprops, name, f, arg); @@ -337,7 +337,7 @@ void reset_thread_state (struct thread_state1 *ts1) reap_thread_state (ts1); } -void log_stack_traces (const struct ddsrt_log_cfg *logcfg, const struct q_globals *gv) +void log_stack_traces (const struct ddsrt_log_cfg *logcfg, const struct ddsi_domaingv *gv) { for (uint32_t i = 0; i < thread_states.nthreads; i++) { diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index e967c73..1b6180a 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -27,7 +27,7 @@ #include "dds/ddsi/q_xevent.h" #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_config.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_transmit.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_unused.h" @@ -79,7 +79,7 @@ static void writer_hbcontrol_note_hb (struct writer *wr, nn_mtime_t tnow, int an int64_t writer_hbcontrol_intv (const struct writer *wr, const struct whc_state *whcst, UNUSED_ARG (nn_mtime_t tnow)) { - struct q_globals const * const gv = wr->e.gv; + struct ddsi_domaingv const * const gv = wr->e.gv; struct hbcontrol const * const hbc = &wr->hbcontrol; int64_t ret = gv->config.const_hb_intv_sched; size_t n_unacked; @@ -105,7 +105,7 @@ int64_t writer_hbcontrol_intv (const struct writer *wr, const struct whc_state * void writer_hbcontrol_note_asyncwrite (struct writer *wr, nn_mtime_t tnow) { - struct q_globals const * const gv = wr->e.gv; + struct ddsi_domaingv const * const gv = wr->e.gv; struct hbcontrol * const hbc = &wr->hbcontrol; nn_mtime_t tnext; @@ -134,7 +134,7 @@ int writer_hbcontrol_must_send (const struct writer *wr, const struct whc_state struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const struct whc_state *whcst, nn_mtime_t tnow, int hbansreq, int issync) { - struct q_globals const * const gv = wr->e.gv; + struct ddsi_domaingv const * const gv = wr->e.gv; struct nn_xmsg *msg; const ddsi_guid_t *prd_guid; @@ -226,7 +226,7 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru static int writer_hbcontrol_ack_required_generic (const struct writer *wr, const struct whc_state *whcst, nn_mtime_t tlast, nn_mtime_t tnow, int piggyback) { - struct q_globals const * const gv = wr->e.gv; + struct ddsi_domaingv const * const gv = wr->e.gv; struct hbcontrol const * const hbc = &wr->hbcontrol; const int64_t hb_intv_ack = gv->config.const_hb_intv_sched; assert(wr->heartbeat_xevent != NULL && whcst != NULL); @@ -317,7 +317,7 @@ struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_ 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 ddsi_domaingv const * const gv = wr->e.gv; struct nn_xmsg_marker sm_marker; Heartbeat_t * hb; seqno_t max = 0, min = 1; @@ -392,7 +392,7 @@ static dds_return_t create_fragment_message_simple (struct writer *wr, seqno_t s /* actual expected_inline_qos_size is typically 0, but always claiming 32 bytes won't make a difference, so no point in being precise */ const size_t expected_inline_qos_size = /* statusinfo */ 8 + /* keyhash */ 20 + /* sentinel */ 4; - struct q_globals const * const gv = wr->e.gv; + struct ddsi_domaingv const * const gv = wr->e.gv; struct nn_xmsg_marker sm_marker; unsigned char contentflag = 0; Data_t *data; @@ -477,7 +477,7 @@ dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const stru actual expected_inline_qos_size is typically 0, but always claiming 32 bytes won't make a difference, so no point in being precise */ const size_t expected_inline_qos_size = /* statusinfo */ 8 + /* keyhash */ 20 + /* sentinel */ 4; - struct q_globals const * const gv = wr->e.gv; + struct ddsi_domaingv const * const gv = wr->e.gv; struct nn_xmsg_marker sm_marker; void *sm; Data_DataFrag_common_t *ddcmn; @@ -636,7 +636,7 @@ dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const stru static void create_HeartbeatFrag (struct writer *wr, seqno_t seq, unsigned fragnum, struct proxy_reader *prd, struct nn_xmsg **pmsg) { - struct q_globals const * const gv = wr->e.gv; + struct ddsi_domaingv const * const gv = wr->e.gv; struct nn_xmsg_marker sm_marker; HeartbeatFrag_t *hbf; ASSERT_MUTEX_HELD (&wr->e.lock); @@ -671,7 +671,7 @@ static void create_HeartbeatFrag (struct writer *wr, seqno_t seq, unsigned fragn nn_xmsg_submsg_setnext (*pmsg, sm_marker); } -dds_return_t write_hb_liveliness (struct q_globals * const gv, struct ddsi_guid *wr_guid, struct nn_xpack *xp) +dds_return_t write_hb_liveliness (struct ddsi_domaingv * const gv, struct ddsi_guid *wr_guid, struct nn_xpack *xp) { struct nn_xmsg *msg = NULL; struct whc_state whcst; @@ -790,7 +790,7 @@ static void transmit_sample_lgmsg_unlocked (struct nn_xpack *xp, struct writer * static void transmit_sample_unlocks_wr (struct nn_xpack *xp, struct writer *wr, const struct whc_state *whcst, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew) { /* on entry: &wr->e.lock held; on exit: lock no longer held */ - struct q_globals const * const gv = wr->e.gv; + struct ddsi_domaingv const * const gv = wr->e.gv; struct nn_xmsg *fmsg; uint32_t sz; assert(xp); @@ -832,7 +832,7 @@ static void transmit_sample_unlocks_wr (struct nn_xpack *xp, struct writer *wr, 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) { - struct q_globals const * const gv = wr->e.gv; + struct ddsi_domaingv const * const gv = wr->e.gv; uint32_t i, sz, nfrags; int enqueued = 1; @@ -997,7 +997,7 @@ static dds_return_t throttle_writer (struct thread_state1 * const ts1, struct nn resent to them, until a ACKNACK is received from that reader. This implicitly clears the whc and unblocks the writer. */ - struct q_globals const * const gv = wr->e.gv; + struct ddsi_domaingv const * const gv = wr->e.gv; dds_return_t result = DDS_RETCODE_OK; nn_mtime_t tnow = now_mt (); const nn_mtime_t abstimeout = add_duration_to_mtime (tnow, wr->xqos->reliability.max_blocking_time); @@ -1068,7 +1068,7 @@ static dds_return_t throttle_writer (struct thread_state1 * const ts1, struct nn static int maybe_grow_whc (struct writer *wr) { - struct q_globals const * const gv = wr->e.gv; + struct ddsi_domaingv const * const gv = wr->e.gv; if (!wr->retransmitting && gv->config.whc_adaptive && wr->whc_high < gv->config.whc_highwater_mark) { nn_etime_t tnow = now_et(); @@ -1086,7 +1086,7 @@ static int maybe_grow_whc (struct writer *wr) static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk, int end_of_txn, int gc_allowed) { - struct q_globals const * const gv = wr->e.gv; + struct ddsi_domaingv const * const gv = wr->e.gv; int r; seqno_t seq; nn_mtime_t tnow; diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index fc178d1..9a839aa 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -27,7 +27,7 @@ #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_unused.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/q_transmit.h" #include "dds/ddsi/q_bswap.h" @@ -144,7 +144,7 @@ struct xeventq { size_t max_queued_rexmit_msgs; int terminate; struct thread_state1 *ts; - struct q_globals *gv; + struct ddsi_domaingv *gv; ddsrt_mutex_t lock; ddsrt_cond_t cond; ddsi_tran_conn_t tev_conn; @@ -586,7 +586,7 @@ static void handle_xevk_entityid (struct nn_xpack *xp, struct xevent_nt *ev) static void handle_xevk_heartbeat (struct nn_xpack *xp, struct xevent *ev, nn_mtime_t tnow /* monotonic */) { - struct q_globals const * const gv = ev->evq->gv; + struct ddsi_domaingv const * const gv = ev->evq->gv; struct nn_xmsg *msg; struct writer *wr; nn_mtime_t t_next; @@ -857,7 +857,7 @@ static void handle_xevk_acknack (UNUSED_ARG (struct nn_xpack *xp), struct xevent A little snag is that the defragmenter can throw out partial samples in favour of others, so MUST ensure that the defragmenter won't start threshing and fail to make progress! */ - struct q_globals *gv = ev->evq->gv; + struct ddsi_domaingv *gv = ev->evq->gv; struct proxy_writer *pwr; struct nn_xmsg *msg; struct pwr_rd_match *rwn; @@ -948,7 +948,7 @@ static bool resend_spdp_sample_by_guid_key (struct writer *wr, const ddsi_guid_t /* Look up data in (transient-local) WHC by key value -- FIXME: clearly a slightly more efficient and elegant way of looking up the key value is to be preferred */ - struct q_globals *gv = wr->e.gv; + struct ddsi_domaingv *gv = wr->e.gv; bool sample_found; nn_plist_t ps; nn_plist_init_empty (&ps); @@ -984,7 +984,7 @@ static bool resend_spdp_sample_by_guid_key (struct writer *wr, const ddsi_guid_t static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *ev, nn_mtime_t tnow) { /* Like the writer pointer in the heartbeat event, the participant pointer in the spdp event is assumed valid. */ - struct q_globals *gv = ev->evq->gv; + struct ddsi_domaingv *gv = ev->evq->gv; struct participant *pp; struct proxy_reader *prd; struct writer *spdp_wr; @@ -1098,7 +1098,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e 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; + struct ddsi_domaingv * const gv = ev->evq->gv; struct participant *pp; dds_duration_t intv; nn_mtime_t tnext; @@ -1133,7 +1133,7 @@ static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_ static void handle_xevk_delete_writer (UNUSED_ARG (struct nn_xpack *xp), struct xevent *ev, UNUSED_ARG (nn_mtime_t tnow)) { /* don't worry if the writer is already gone by the time we get here. */ - struct q_globals * const gv = ev->evq->gv; + struct ddsi_domaingv * const gv = ev->evq->gv; GVTRACE ("handle_xevk_delete_writer: "PGUIDFMT"\n", PGUID (ev->u.delete_writer.guid)); delete_writer_nolinger (gv, &ev->u.delete_writer.guid); delete_xevent (ev); @@ -1354,7 +1354,7 @@ void qxev_msg (struct xeventq *evq, struct nn_xmsg *msg) void qxev_prd_entityid (struct proxy_reader *prd, ddsi_guid_prefix_t *id) { - struct q_globals * const gv = prd->e.gv; + struct ddsi_domaingv * const gv = prd->e.gv; struct nn_xmsg *msg; struct xevent_nt *ev; @@ -1382,7 +1382,7 @@ void qxev_prd_entityid (struct proxy_reader *prd, ddsi_guid_prefix_t *id) void qxev_pwr_entityid (struct proxy_writer *pwr, ddsi_guid_prefix_t *id) { - struct q_globals * const gv = pwr->e.gv; + struct ddsi_domaingv * const gv = pwr->e.gv; struct nn_xmsg *msg; struct xevent_nt *ev; @@ -1410,7 +1410,7 @@ void qxev_pwr_entityid (struct proxy_writer *pwr, ddsi_guid_prefix_t *id) int qxev_msg_rexmit_wrlock_held (struct xeventq *evq, struct nn_xmsg *msg, int force) { - struct q_globals * const gv = evq->gv; + struct ddsi_domaingv * const gv = evq->gv; size_t msg_size = nn_xmsg_size (msg); struct xevent_nt *ev; diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 154d82c..7c7ae22 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -37,7 +37,7 @@ #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_entity.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/q_freelist.h" #include "dds/ddsi/ddsi_serdata_default.h" @@ -202,7 +202,7 @@ struct nn_xpack size_t niov; ddsrt_iovec_t *iov; enum nn_xmsg_dstmode dstmode; - struct q_globals *gv; + struct ddsi_domaingv *gv; union { @@ -644,7 +644,7 @@ static int readerId_compatible (const struct nn_xmsg *m, const struct nn_xmsg *m return e.u == NN_ENTITYID_UNKNOWN || e.u == eadd.u; } -int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct q_globals *gv, struct nn_xmsg *m, const struct nn_xmsg *madd) +int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct ddsi_domaingv *gv, struct nn_xmsg *m, const struct nn_xmsg *madd) { assert (m->kindspecific.data.wrseq >= 1); assert (m->kindspecific.data.wrguid.prefix.u[0] != 0); @@ -829,7 +829,7 @@ int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg * m) pointer we compute the address of the xmsg from the address of the chain element, &c. */ -static void nn_xmsg_chain_release (struct q_globals *gv, struct nn_xmsg_chain *chain) +static void nn_xmsg_chain_release (struct ddsi_domaingv *gv, struct nn_xmsg_chain *chain) { ddsi_guid_t wrguid; memset (&wrguid, 0, sizeof (wrguid)); @@ -887,7 +887,7 @@ static void nn_xmsg_chain_add (struct nn_xmsg_chain *chain, struct nn_xmsg *m) #define NN_BW_LIMIT_MAX_BUFFER (-30 * T_MILLISECOND) #define NN_BW_LIMIT_MIN_SLEEP (2 * T_MILLISECOND) -static void nn_bw_limit_sleep_if_needed (struct q_globals const * const gv, struct nn_bw_limiter *this, ssize_t size) +static void nn_bw_limit_sleep_if_needed (struct ddsi_domaingv const * const gv, struct nn_bw_limiter *this, ssize_t size) { if ( this->bandwidth > 0 ) { nn_mtime_t tnow = now_mt(); @@ -1015,7 +1015,7 @@ void nn_xpack_free (struct nn_xpack *xp) static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg) { struct nn_xpack *xp = varg; - struct q_globals const * const gv = xp->gv; + struct ddsi_domaingv const * const gv = xp->gv; ssize_t nbytes = 0; if (gv->logconfig.c.mask & DDS_LC_TRACE) @@ -1101,7 +1101,7 @@ static void nn_xpack_send1_threaded (const nn_locator_t *loc, void * varg) static void nn_xpack_send_real (struct nn_xpack *xp) { - struct q_globals const * const gv = xp->gv; + struct ddsi_domaingv const * const gv = xp->gv; size_t calls; assert (xp->niov <= NN_XMSG_MAX_MESSAGE_IOVECS); @@ -1181,7 +1181,7 @@ static void nn_xpack_send_real (struct nn_xpack *xp) static uint32_t nn_xpack_sendq_thread (void *vgv) { - struct q_globals *gv = vgv; + struct ddsi_domaingv *gv = vgv; ddsrt_mutex_lock (&gv->sendq_lock); while (!(gv->sendq_stop && gv->sendq_head == NULL)) { @@ -1205,7 +1205,7 @@ static uint32_t nn_xpack_sendq_thread (void *vgv) return 0; } -void nn_xpack_sendq_init (struct q_globals *gv) +void nn_xpack_sendq_init (struct ddsi_domaingv *gv) { gv->sendq_stop = 0; gv->sendq_head = NULL; @@ -1215,13 +1215,13 @@ void nn_xpack_sendq_init (struct q_globals *gv) ddsrt_cond_init (&gv->sendq_cond); } -void nn_xpack_sendq_start (struct q_globals *gv) +void nn_xpack_sendq_start (struct ddsi_domaingv *gv) { 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) +void nn_xpack_sendq_stop (struct ddsi_domaingv *gv) { ddsrt_mutex_lock (&gv->sendq_lock); gv->sendq_stop = 1; @@ -1229,7 +1229,7 @@ void nn_xpack_sendq_stop (struct q_globals *gv) ddsrt_mutex_unlock (&gv->sendq_lock); } -void nn_xpack_sendq_fini (struct q_globals *gv) +void nn_xpack_sendq_fini (struct ddsi_domaingv *gv) { assert (gv->sendq_head == NULL); join_thread (gv->sendq_ts); @@ -1245,7 +1245,7 @@ void nn_xpack_send (struct nn_xpack *xp, bool immediately) } else { - struct q_globals * const gv = xp->gv; + struct ddsi_domaingv * const gv = xp->gv; struct nn_xpack *xp1 = ddsrt_malloc (sizeof (*xp)); memcpy (xp1, xp, sizeof (*xp1)); nn_xpack_reinit (xp); @@ -1350,7 +1350,7 @@ static int guid_prefix_eq (const ddsi_guid_prefix_t *a, const ddsi_guid_prefix_t int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flags) { /* Returns > 0 if pack got sent out before adding m */ - struct q_globals const * const gv = xp->gv; + struct ddsi_domaingv const * const gv = xp->gv; static InfoDST_t static_zero_dst = { { SMID_INFO_DST, (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? SMFLAG_ENDIANNESS : 0), sizeof (ddsi_guid_prefix_t) }, { { 0,0,0,0, 0,0,0,0, 0,0,0,0 } } diff --git a/src/core/xtests/rhc_torture/rhc_torture.c b/src/core/xtests/rhc_torture/rhc_torture.c index 757cb03..5741f5f 100644 --- a/src/core/xtests/rhc_torture/rhc_torture.c +++ b/src/core/xtests/rhc_torture/rhc_torture.c @@ -24,7 +24,7 @@ #include "dds__entity.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_bswap.h" -#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_radmin.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_gc.h" @@ -167,7 +167,7 @@ static uint64_t store (struct ddsi_tkmap *tkmap, struct dds_rhc *rhc, struct pro return iid; } -static struct proxy_writer *mkwr (const struct q_globals *gv, bool auto_dispose) +static struct proxy_writer *mkwr (const struct ddsi_domaingv *gv, bool auto_dispose) { struct proxy_writer *pwr; struct dds_qos *xqos; @@ -191,7 +191,7 @@ static void fwr (struct proxy_writer *wr) free (wr); } -static struct dds_rhc *mkrhc (struct q_globals *gv, dds_reader *rd, dds_history_kind_t hk, int32_t hdepth, dds_destination_order_kind_t dok) +static struct dds_rhc *mkrhc (struct ddsi_domaingv *gv, dds_reader *rd, dds_history_kind_t hk, int32_t hdepth, dds_destination_order_kind_t dok) { struct dds_rhc *rhc; dds_qos_t rqos; @@ -560,9 +560,9 @@ static dds_entity_t readcond_wrapper (dds_entity_t reader, uint32_t mask, dds_qu return dds_create_readcondition (reader, mask); } -static struct q_globals *get_gv (dds_entity_t e) +static struct ddsi_domaingv *get_gv (dds_entity_t e) { - struct q_globals *gv; + struct ddsi_domaingv *gv; dds_entity *x; if (dds_entity_pin (e, &x) < 0) abort (); @@ -594,7 +594,7 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, dds_entity_unlock (x); } - const struct q_globals *gv = get_gv (pp); + const struct ddsi_domaingv *gv = get_gv (pp); struct ddsi_tkmap *tkmap = gv->m_tkmap; struct proxy_writer *wr[] = { mkwr (gv, 0), mkwr (gv, 1), mkwr (gv, 1) }; @@ -929,7 +929,7 @@ int main (int argc, char **argv) if (0 >= first) { - struct q_globals *gv = get_gv (pp); + struct ddsi_domaingv *gv = get_gv (pp); struct ddsi_tkmap *tkmap = gv->m_tkmap; if (print) printf ("************* 0 *************\n"); @@ -980,7 +980,7 @@ int main (int argc, char **argv) if (1 >= first) { - struct q_globals *gv = get_gv (pp); + struct ddsi_domaingv *gv = get_gv (pp); struct ddsi_tkmap *tkmap = gv->m_tkmap; if (print) printf ("************* 1 *************\n"); From ad19f571aee177890ee2663bcc7938ef0e57f7f0 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 3 Feb 2020 10:35:31 +0100 Subject: [PATCH 26/28] Rename nn_plist, xqos to ddsi_plist, xqos This already was leaking out in the interface, so this name change was needed too. The relationship between plist and xqos being so intimate, doing the one but not the other made no sense. Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/dds.h | 6 +- src/core/ddsc/src/dds__qos.h | 2 +- src/core/ddsc/src/dds__serdata_builtintopic.h | 2 +- src/core/ddsc/src/dds_builtin.c | 2 +- src/core/ddsc/src/dds_entity.c | 12 +- src/core/ddsc/src/dds_matched.c | 2 +- src/core/ddsc/src/dds_participant.c | 18 +- src/core/ddsc/src/dds_publisher.c | 6 +- src/core/ddsc/src/dds_qos.c | 16 +- src/core/ddsc/src/dds_reader.c | 10 +- src/core/ddsc/src/dds_rhc_default.c | 2 +- src/core/ddsc/src/dds_serdata_builtintopic.c | 22 +- src/core/ddsc/src/dds_subscriber.c | 6 +- src/core/ddsc/src/dds_topic.c | 28 +-- src/core/ddsc/src/dds_whc.c | 12 +- src/core/ddsc/src/dds_whc_builtintopic.c | 2 +- src/core/ddsc/src/dds_writer.c | 10 +- src/core/ddsi/CMakeLists.txt | 6 +- .../ddsi/include/dds/ddsi/ddsi_domaingv.h | 6 +- .../dds/ddsi/{q_plist.h => ddsi_plist.h} | 55 ++--- .../dds/ddsi/{q_xqos.h => ddsi_xqos.h} | 42 ++-- src/core/ddsi/include/dds/ddsi/q_config.h | 2 +- .../ddsi/include/dds/ddsi/q_ddsi_discovery.h | 4 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 22 +- src/core/ddsi/include/dds/ddsi/q_transmit.h | 4 +- src/core/ddsi/include/dds/ddsi/q_whc.h | 8 +- src/core/ddsi/include/dds/ddsi/q_xmsg.h | 2 +- src/core/ddsi/src/{q_plist.c => ddsi_plist.c} | 232 +++++++++--------- src/core/ddsi/src/ddsi_serdata_default.c | 12 +- src/core/ddsi/src/q_ddsi_discovery.c | 98 ++++---- src/core/ddsi/src/q_debmon.c | 2 +- src/core/ddsi/src/q_entity.c | 88 +++---- src/core/ddsi/src/q_init.c | 68 ++--- src/core/ddsi/src/q_lease.c | 2 +- src/core/ddsi/src/q_qosmatch.c | 2 +- src/core/ddsi/src/q_radmin.c | 2 +- src/core/ddsi/src/q_receive.c | 24 +- src/core/ddsi/src/q_transmit.c | 26 +- src/core/ddsi/src/q_whc.c | 2 +- src/core/ddsi/src/q_xevent.c | 8 +- src/core/ddsi/src/q_xmsg.c | 2 +- src/core/ddsi/tests/plist.c | 48 ++-- src/core/ddsi/tests/plist_generic.c | 2 +- src/core/xtests/rhc_torture/rhc_torture.c | 8 +- src/mpt/tests/qos/procs/rw.c | 28 +-- 45 files changed, 481 insertions(+), 482 deletions(-) rename src/core/ddsi/include/dds/ddsi/{q_plist.h => ddsi_plist.h} (81%) rename src/core/ddsi/include/dds/ddsi/{q_xqos.h => ddsi_xqos.h} (88%) rename src/core/ddsi/src/{q_plist.c => ddsi_plist.c} (93%) diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index 75f0f44..dddd300 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -50,6 +50,8 @@ extern "C" { #endif struct dds_rhc; +struct ddsi_plist; +struct ddsi_sertopic; struct ddsi_serdata; #define DDS_MIN_PSEUDO_HANDLE ((dds_entity_t) 0x7fff0000) @@ -996,8 +998,6 @@ dds_create_topic( const dds_qos_t *qos, const dds_listener_t *listener); -struct ddsi_sertopic; -struct nn_plist; /** * @brief Creates a new topic with arbitrary type handling. * @@ -1036,7 +1036,7 @@ dds_create_topic_arbitrary ( struct ddsi_sertopic *sertopic, const dds_qos_t *qos, const dds_listener_t *listener, - const struct nn_plist *sedp_plist); + const struct ddsi_plist *sedp_plist); /** * @brief Finds a named topic. diff --git a/src/core/ddsc/src/dds__qos.h b/src/core/ddsc/src/dds__qos.h index be21eb9..99a26a6 100644 --- a/src/core/ddsc/src/dds__qos.h +++ b/src/core/ddsc/src/dds__qos.h @@ -12,7 +12,7 @@ #ifndef _DDS_QOS_H_ #define _DDS_QOS_H_ -#include "dds/ddsi/q_xqos.h" +#include "dds/ddsi/ddsi_xqos.h" #if defined (__cplusplus) extern "C" { diff --git a/src/core/ddsc/src/dds__serdata_builtintopic.h b/src/core/ddsc/src/dds__serdata_builtintopic.h index 825e7cf..60fdec0 100644 --- a/src/core/ddsc/src/dds__serdata_builtintopic.h +++ b/src/core/ddsc/src/dds__serdata_builtintopic.h @@ -12,7 +12,7 @@ #ifndef DDSI_SERDATA_BUILTINTOPIC_H #define DDSI_SERDATA_BUILTINTOPIC_H -#include "dds/ddsi/q_xqos.h" +#include "dds/ddsi/ddsi_xqos.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_sertopic.h" diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index 1d95e91..7956672 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -16,7 +16,7 @@ #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_domaingv.h" -#include "dds/ddsi/q_plist.h" /* for nn_keyhash */ +#include "dds/ddsi/ddsi_plist.h" #include "dds__init.h" #include "dds__domain.h" #include "dds__participant.h" diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index 7a80ddb..2b842af 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -23,7 +23,7 @@ #include "dds__topic.h" #include "dds/version.h" #include "dds/ddsi/ddsi_pmd.h" -#include "dds/ddsi/q_xqos.h" +#include "dds/ddsi/ddsi_xqos.h" #include "dds/ddsi/q_transmit.h" extern inline dds_entity *dds_entity_from_handle_link (struct dds_handle_link *hdllink); @@ -670,7 +670,7 @@ dds_return_t dds_get_qos (dds_entity_t entity, dds_qos_t *qos) } dds_reset_qos (qos); - nn_xqos_mergein_missing (qos, entity_qos, ~(QP_TOPIC_NAME | QP_TYPE_NAME)); + ddsi_xqos_mergein_missing (qos, entity_qos, ~(QP_TOPIC_NAME | QP_TYPE_NAME)); ret = DDS_RETCODE_OK; } dds_entity_unlock(e); @@ -685,9 +685,9 @@ static dds_return_t dds_set_qos_locked_raw (dds_entity *e, dds_qos_t **e_qos_ptr but a single QoS for a topic in a participant while there can be multiple definitions of it, and hence, multiple sertopics. Those are needed for multi-language support. */ dds_qos_t *newqos = dds_create_qos (); - nn_xqos_mergein_missing (newqos, qos, mask); - nn_xqos_mergein_missing (newqos, *e_qos_ptr, ~(uint64_t)0); - if ((ret = nn_xqos_valid (logcfg, newqos)) != DDS_RETCODE_OK) + ddsi_xqos_mergein_missing (newqos, qos, mask); + ddsi_xqos_mergein_missing (newqos, *e_qos_ptr, ~(uint64_t)0); + if ((ret = ddsi_xqos_valid (logcfg, newqos)) != DDS_RETCODE_OK) { /* invalid or inconsistent QoS settings */ goto error_or_nochange; @@ -698,7 +698,7 @@ static dds_return_t dds_set_qos_locked_raw (dds_entity *e, dds_qos_t **e_qos_ptr } else { - const uint64_t delta = nn_xqos_delta (*e_qos_ptr, newqos, ~(uint64_t)0); + const uint64_t delta = ddsi_xqos_delta (*e_qos_ptr, newqos, ~(uint64_t)0); if (delta == 0) { /* new settings are identical to the old */ diff --git a/src/core/ddsc/src/dds_matched.c b/src/core/ddsc/src/dds_matched.c index c46f2b9..d2cc6a9 100644 --- a/src/core/ddsc/src/dds_matched.c +++ b/src/core/ddsc/src/dds_matched.c @@ -135,7 +135,7 @@ static dds_builtintopic_endpoint_t *make_builtintopic_endpoint (const ddsi_guid_ tmp = nn_hton_guid (*ppguid); memcpy (&ep->participant_key, &tmp, sizeof (ep->participant_key)); ep->qos = dds_create_qos (); - nn_xqos_mergein_missing (ep->qos, qos, ~(QP_TOPIC_NAME | QP_TYPE_NAME)); + ddsi_xqos_mergein_missing (ep->qos, qos, ~(QP_TOPIC_NAME | QP_TYPE_NAME)); ep->topic_name = dds_string_dup (qos->topic_name); ep->type_name = dds_string_dup (qos->type_name); return ep; diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 6dbebf1..3cbb48d 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -17,7 +17,7 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_config.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/ddsi_entity_index.h" #include "dds/version.h" @@ -69,8 +69,8 @@ static dds_return_t dds_participant_qos_set (dds_entity *e, const dds_qos_t *qos thread_state_awake (lookup_thread_state (), &e->m_domain->gv); if ((pp = entidx_lookup_participant_guid (e->m_domain->gv.entity_index, &e->m_guid)) != NULL) { - nn_plist_t plist; - nn_plist_init_empty (&plist); + ddsi_plist_t plist; + ddsi_plist_init_empty (&plist); plist.qos.present = plist.qos.aliased = qos->present; plist.qos = *qos; update_participant_plist (pp, &plist); @@ -94,7 +94,7 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_ dds_entity_t ret; ddsi_guid_t guid; dds_participant * pp; - nn_plist_t plist; + ddsi_plist_t plist; dds_qos_t *new_qos = NULL; char *config = ""; @@ -109,19 +109,19 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_ new_qos = dds_create_qos (); if (qos != NULL) - nn_xqos_mergein_missing (new_qos, qos, DDS_PARTICIPANT_QOS_MASK); - nn_xqos_mergein_missing (new_qos, &dom->gv.default_local_plist_pp.qos, ~(uint64_t)0); - if ((ret = nn_xqos_valid (&dom->gv.logconfig, new_qos)) < 0) + ddsi_xqos_mergein_missing (new_qos, qos, DDS_PARTICIPANT_QOS_MASK); + ddsi_xqos_mergein_missing (new_qos, &dom->gv.default_local_plist_pp.qos, ~(uint64_t)0); + if ((ret = ddsi_xqos_valid (&dom->gv.logconfig, new_qos)) < 0) goto err_qos_validation; /* Translate qos */ - nn_plist_init_empty (&plist); + ddsi_plist_init_empty (&plist); dds_merge_qos (&plist.qos, new_qos); thread_state_awake (lookup_thread_state (), &dom->gv); ret = new_participant (&guid, &dom->gv, 0, &plist); thread_state_asleep (lookup_thread_state ()); - nn_plist_fini (&plist); + ddsi_plist_fini (&plist); if (ret < 0) { ret = DDS_RETCODE_ERROR; diff --git a/src/core/ddsc/src/dds_publisher.c b/src/core/ddsc/src/dds_publisher.c index f319956..00ea520 100644 --- a/src/core/ddsc/src/dds_publisher.c +++ b/src/core/ddsc/src/dds_publisher.c @@ -55,9 +55,9 @@ dds_entity_t dds__create_publisher_l (dds_participant *par, bool implicit, const new_qos = dds_create_qos (); if (qos) - nn_xqos_mergein_missing (new_qos, qos, DDS_PUBLISHER_QOS_MASK); - nn_xqos_mergein_missing (new_qos, &par->m_entity.m_domain->gv.default_xqos_pub, ~(uint64_t)0); - if ((ret = nn_xqos_valid (&par->m_entity.m_domain->gv.logconfig, new_qos)) != DDS_RETCODE_OK) + ddsi_xqos_mergein_missing (new_qos, qos, DDS_PUBLISHER_QOS_MASK); + ddsi_xqos_mergein_missing (new_qos, &par->m_entity.m_domain->gv.default_xqos_pub, ~(uint64_t)0); + if ((ret = ddsi_xqos_valid (&par->m_entity.m_domain->gv.logconfig, new_qos)) != DDS_RETCODE_OK) { dds_participant_unlock (par); return ret; diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index 68f12e6..f3fb576 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -15,7 +15,7 @@ #include "dds/dds.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_plist.h" static void dds_qos_data_copy_in (ddsi_octetseq_t *data, const void * __restrict value, size_t sz, bool overwrite) { @@ -51,7 +51,7 @@ static bool dds_qos_data_copy_out (const ddsi_octetseq_t *data, void **value, si dds_qos_t *dds_create_qos (void) { dds_qos_t *qos = ddsrt_malloc (sizeof (dds_qos_t)); - nn_xqos_init_empty (qos); + ddsi_xqos_init_empty (qos); return qos; } @@ -64,8 +64,8 @@ void dds_reset_qos (dds_qos_t * __restrict qos) { if (qos) { - nn_xqos_fini (qos); - nn_xqos_init_empty (qos); + ddsi_xqos_fini (qos); + ddsi_xqos_init_empty (qos); } } @@ -78,7 +78,7 @@ void dds_delete_qos (dds_qos_t * __restrict qos) { if (qos) { - nn_xqos_fini (qos); + ddsi_xqos_fini (qos); ddsrt_free (qos); } } @@ -92,7 +92,7 @@ dds_return_t dds_copy_qos (dds_qos_t * __restrict dst, const dds_qos_t * __restr { if (src == NULL || dst == NULL) return DDS_RETCODE_BAD_PARAMETER; - nn_xqos_copy (dst, src); + ddsi_xqos_copy (dst, src); return DDS_RETCODE_OK; } @@ -105,7 +105,7 @@ void dds_merge_qos (dds_qos_t * __restrict dst, const dds_qos_t * __restrict src { /* Copy qos from source to destination unless already set */ if (src != NULL && dst != NULL) - nn_xqos_mergein_missing (dst, src, ~(uint64_t)0); + ddsi_xqos_mergein_missing (dst, src, ~(uint64_t)0); } void dds_qos_merge (dds_qos_t * __restrict dst, const dds_qos_t * __restrict src) @@ -121,7 +121,7 @@ bool dds_qos_equal (const dds_qos_t * __restrict a, const dds_qos_t * __restrict else if (a == NULL || b == NULL) return false; else - return nn_xqos_delta (a, b, ~(uint64_t)0) == 0; + return ddsi_xqos_delta (a, b, ~(uint64_t)0) == 0; } void dds_qset_userdata (dds_qos_t * __restrict qos, const void * __restrict value, size_t sz) diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index c44c0af..3af861b 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -432,14 +432,14 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe argument, but that isn't the case here */ rqos = dds_create_qos (); if (qos) - nn_xqos_mergein_missing (rqos, qos, DDS_READER_QOS_MASK); + ddsi_xqos_mergein_missing (rqos, qos, DDS_READER_QOS_MASK); if (sub->m_entity.m_qos) - nn_xqos_mergein_missing (rqos, sub->m_entity.m_qos, ~(uint64_t)0); + ddsi_xqos_mergein_missing (rqos, sub->m_entity.m_qos, ~(uint64_t)0); if (tp->m_ktopic->qos) - nn_xqos_mergein_missing (rqos, tp->m_ktopic->qos, ~(uint64_t)0); - nn_xqos_mergein_missing (rqos, &sub->m_entity.m_domain->gv.default_xqos_rd, ~(uint64_t)0); + ddsi_xqos_mergein_missing (rqos, tp->m_ktopic->qos, ~(uint64_t)0); + ddsi_xqos_mergein_missing (rqos, &sub->m_entity.m_domain->gv.default_xqos_rd, ~(uint64_t)0); - if ((rc = nn_xqos_valid (&sub->m_entity.m_domain->gv.logconfig, rqos)) < 0 || + if ((rc = ddsi_xqos_valid (&sub->m_entity.m_domain->gv.logconfig, rqos)) < 0 || (rc = validate_reader_qos(rqos)) != DDS_RETCODE_OK) { dds_delete_qos (rqos); diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index e664e0a..7c68b68 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -32,7 +32,7 @@ #include "dds/ddsrt/avl.h" #include "dds/ddsrt/circlist.h" #include "dds/ddsi/ddsi_rhc.h" -#include "dds/ddsi/q_xqos.h" +#include "dds/ddsi/ddsi_xqos.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_domaingv.h" diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index 7bdb481..4e19675 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -19,7 +19,7 @@ #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_plist.h" #include "dds__stream.h" #include "dds__serdata_builtintopic.h" #include "dds/ddsi/ddsi_tkmap.h" @@ -60,7 +60,7 @@ static void serdata_builtin_free(struct ddsi_serdata *dcmn) { struct ddsi_serdata_builtintopic *d = (struct ddsi_serdata_builtintopic *)dcmn; if (d->c.kind == SDK_DATA) - nn_xqos_fini (&d->xqos); + ddsi_xqos_fini (&d->xqos); ddsrt_free (d); } @@ -73,13 +73,13 @@ static struct ddsi_serdata_builtintopic *serdata_builtin_new(const struct ddsi_s static void from_entity_pp (struct ddsi_serdata_builtintopic *d, const struct participant *pp) { - nn_xqos_copy(&d->xqos, &pp->plist->qos); + ddsi_xqos_copy(&d->xqos, &pp->plist->qos); d->pphandle = pp->e.iid; } static void from_entity_proxypp (struct ddsi_serdata_builtintopic *d, const struct proxy_participant *proxypp) { - nn_xqos_copy(&d->xqos, &proxypp->plist->qos); + ddsi_xqos_copy(&d->xqos, &proxypp->plist->qos); d->pphandle = proxypp->e.iid; } @@ -100,14 +100,14 @@ static void set_topic_type_from_sertopic (struct ddsi_serdata_builtintopic *d, c static void from_entity_rd (struct ddsi_serdata_builtintopic *d, const struct reader *rd) { d->pphandle = rd->c.pp->e.iid; - nn_xqos_copy(&d->xqos, rd->xqos); + ddsi_xqos_copy(&d->xqos, rd->xqos); set_topic_type_from_sertopic(d, rd->topic); } static void from_entity_prd (struct ddsi_serdata_builtintopic *d, const struct proxy_reader *prd) { d->pphandle = prd->c.proxypp->e.iid; - nn_xqos_copy(&d->xqos, prd->c.xqos); + ddsi_xqos_copy(&d->xqos, prd->c.xqos); assert (d->xqos.present & QP_TOPIC_NAME); assert (d->xqos.present & QP_TYPE_NAME); } @@ -115,14 +115,14 @@ static void from_entity_prd (struct ddsi_serdata_builtintopic *d, const struct p static void from_entity_wr (struct ddsi_serdata_builtintopic *d, const struct writer *wr) { d->pphandle = wr->c.pp->e.iid; - nn_xqos_copy(&d->xqos, wr->xqos); + ddsi_xqos_copy(&d->xqos, wr->xqos); set_topic_type_from_sertopic(d, wr->topic); } static void from_entity_pwr (struct ddsi_serdata_builtintopic *d, const struct proxy_writer *pwr) { d->pphandle = pwr->c.proxypp->e.iid; - nn_xqos_copy(&d->xqos, pwr->c.xqos); + ddsi_xqos_copy(&d->xqos, pwr->c.xqos); assert (d->xqos.present & QP_TOPIC_NAME); assert (d->xqos.present & QP_TYPE_NAME); } @@ -196,10 +196,10 @@ static dds_qos_t *dds_qos_from_xqos_reuse (dds_qos_t *old, const dds_qos_t *src) old = ddsrt_malloc (sizeof (*old)); else { - nn_xqos_fini (old); + ddsi_xqos_fini (old); } - nn_xqos_init_empty (old); - nn_xqos_mergein_missing (old, src, ~(QP_TOPIC_NAME | QP_TYPE_NAME)); + ddsi_xqos_init_empty (old); + ddsi_xqos_mergein_missing (old, src, ~(QP_TOPIC_NAME | QP_TYPE_NAME)); return old; } diff --git a/src/core/ddsc/src/dds_subscriber.c b/src/core/ddsc/src/dds_subscriber.c index 19c923c..e501f5b 100644 --- a/src/core/ddsc/src/dds_subscriber.c +++ b/src/core/ddsc/src/dds_subscriber.c @@ -55,9 +55,9 @@ dds_entity_t dds__create_subscriber_l (dds_participant *participant, bool implic new_qos = dds_create_qos (); if (qos) - nn_xqos_mergein_missing (new_qos, qos, DDS_SUBSCRIBER_QOS_MASK); - nn_xqos_mergein_missing (new_qos, &participant->m_entity.m_domain->gv.default_xqos_sub, ~(uint64_t)0); - if ((ret = nn_xqos_valid (&participant->m_entity.m_domain->gv.logconfig, new_qos)) != DDS_RETCODE_OK) + ddsi_xqos_mergein_missing (new_qos, qos, DDS_SUBSCRIBER_QOS_MASK); + ddsi_xqos_mergein_missing (new_qos, &participant->m_entity.m_domain->gv.default_xqos_sub, ~(uint64_t)0); + if ((ret = ddsi_xqos_valid (&participant->m_entity.m_domain->gv.logconfig, new_qos)) != DDS_RETCODE_OK) { dds_delete_qos (new_qos); return ret; diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 815abed..13a2f45 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -30,7 +30,7 @@ #include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/q_ddsi_discovery.h" #include "dds/ddsi/ddsi_iid.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/ddsi_domaingv.h" #include "dds__serdata_builtintopic.h" @@ -246,7 +246,7 @@ static dds_return_t lookup_and_check_ktopic (struct dds_ktopic **ktp_out, dds_pa } } -static dds_entity_t create_topic_pp_locked (struct dds_participant *pp, struct dds_ktopic *ktp, bool implicit, struct ddsi_sertopic *sertopic_registered, const dds_listener_t *listener, const nn_plist_t *sedp_plist) +static dds_entity_t create_topic_pp_locked (struct dds_participant *pp, struct dds_ktopic *ktp, bool implicit, struct ddsi_sertopic *sertopic_registered, const dds_listener_t *listener, const ddsi_plist_t *sedp_plist) { dds_entity_t hdl; dds_topic *tp = dds_alloc (sizeof (*tp)); @@ -260,17 +260,17 @@ static dds_entity_t create_topic_pp_locked (struct dds_participant *pp, struct d if (sedp_plist) { struct participant *ddsi_pp; - nn_plist_t plist; + ddsi_plist_t plist; thread_state_awake (lookup_thread_state (), &pp->m_entity.m_domain->gv); ddsi_pp = entidx_lookup_participant_guid (pp->m_entity.m_domain->gv.entity_index, &pp->m_entity.m_guid); assert (ddsi_pp); - nn_plist_init_empty (&plist); - nn_plist_mergein_missing (&plist, sedp_plist, ~(uint64_t)0, ~(uint64_t)0); - nn_xqos_mergein_missing (&plist.qos, ktp->qos, ~(uint64_t)0); + ddsi_plist_init_empty (&plist); + ddsi_plist_mergein_missing (&plist, sedp_plist, ~(uint64_t)0, ~(uint64_t)0); + ddsi_xqos_mergein_missing (&plist.qos, ktp->qos, ~(uint64_t)0); sedp_write_topic (ddsi_pp, &plist); - nn_plist_fini (&plist); + ddsi_plist_fini (&plist); thread_state_asleep (lookup_thread_state ()); } @@ -278,7 +278,7 @@ static dds_entity_t create_topic_pp_locked (struct dds_participant *pp, struct d return hdl; } -dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_sertopic *sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const nn_plist_t *sedp_plist) +dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_sertopic *sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const ddsi_plist_t *sedp_plist) { dds_return_t rc; dds_participant *pp; @@ -303,10 +303,10 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s new_qos = dds_create_qos (); if (qos) - nn_xqos_mergein_missing (new_qos, qos, DDS_TOPIC_QOS_MASK); + ddsi_xqos_mergein_missing (new_qos, qos, DDS_TOPIC_QOS_MASK); /* One would expect this: * - * nn_xqos_mergein_missing (new_qos, &gv.default_xqos_tp, ~(uint64_t)0); + * ddsi_xqos_mergein_missing (new_qos, &gv.default_xqos_tp, ~(uint64_t)0); * * but the crazy defaults of the DDS specification has a default setting * for reliability that is dependent on the entity type: readers and @@ -316,7 +316,7 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s * best-effort will do "the right thing" and let a writer still default to * reliable ... (and keep behaviour unchanged) */ struct ddsi_domaingv * const gv = &pp->m_entity.m_domain->gv; - if ((rc = nn_xqos_valid (&gv->logconfig, new_qos)) != DDS_RETCODE_OK) + if ((rc = ddsi_xqos_valid (&gv->logconfig, new_qos)) != DDS_RETCODE_OK) { dds_delete_qos (new_qos); dds_entity_unpin (&pp->m_entity); @@ -383,7 +383,7 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descriptor_t *desc, const char *name, const dds_qos_t *qos, const dds_listener_t *listener) { struct ddsi_sertopic_default *st; - nn_plist_t plist; + ddsi_plist_t plist; dds_entity_t hdl; struct dds_entity *ppent; dds_return_t ret; @@ -409,7 +409,7 @@ dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descrip DDS_CTRACE (&ppent->m_domain->gv.logconfig, "Marshalling for type: %s is %soptimised\n", desc->m_typename, st->opt_size ? "" : "not "); } - nn_plist_init_empty (&plist); + ddsi_plist_init_empty (&plist); /* Set Topic meta data (for SEDP publication) */ plist.qos.topic_name = ddsrt_strdup (st->c.name); plist.qos.type_name = ddsrt_strdup (st->c.type_name); @@ -432,7 +432,7 @@ dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descrip hdl = dds_create_topic_arbitrary (participant, &st->c, qos, listener, &plist); ddsi_sertopic_unref (&st->c); dds_entity_unpin (ppent); - nn_plist_fini (&plist); + ddsi_plist_fini (&plist); return hdl; } diff --git a/src/core/ddsc/src/dds_whc.c b/src/core/ddsc/src/dds_whc.c index b553cc5..de50ba4 100644 --- a/src/core/ddsc/src/dds_whc.c +++ b/src/core/ddsc/src/dds_whc.c @@ -48,7 +48,7 @@ struct whc_node { seqno_t seq; uint64_t total_bytes; /* cumulative number of bytes up to and including this node */ size_t size; - struct nn_plist *plist; /* 0 if nothing special */ + struct ddsi_plist *plist; /* 0 if nothing special */ unsigned unacked: 1; /* counted in whc::unacked_bytes iff 1 */ unsigned borrowed: 1; /* at most one can borrow it at any time */ nn_mtime_t last_rexmit_ts; @@ -155,7 +155,7 @@ static uint32_t whc_default_remove_acked_messages_full (struct whc_impl *whc, se static uint32_t whc_default_remove_acked_messages (struct whc *whc, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list); static void whc_default_free_deferred_free_list (struct whc *whc, struct whc_node *deferred_free_list); static void whc_default_get_state (const struct whc *whc, struct whc_state *st); -static int whc_default_insert (struct whc *whc, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); +static int whc_default_insert (struct whc *whc, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); static seqno_t whc_default_next_seq (const struct whc *whc, seqno_t seq); static bool whc_default_borrow_sample (const struct whc *whc, seqno_t seq, struct whc_borrowed_sample *sample); static bool whc_default_borrow_sample_key (const struct whc *whc, const struct ddsi_serdata *serdata_key, struct whc_borrowed_sample *sample); @@ -498,7 +498,7 @@ static void free_whc_node_contents (struct whc_node *whcn) { ddsi_serdata_unref (whcn->serdata); if (whcn->plist) { - nn_plist_fini (whcn->plist); + ddsi_plist_fini (whcn->plist); ddsrt_free (whcn->plist); } } @@ -1156,7 +1156,7 @@ static uint32_t whc_default_remove_acked_messages (struct whc *whc_generic, seqn return cnt; } -static struct whc_node *whc_default_insert_seq (struct whc_impl *whc, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct nn_plist *plist, struct ddsi_serdata *serdata) +static struct whc_node *whc_default_insert_seq (struct whc_impl *whc, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct ddsi_plist *plist, struct ddsi_serdata *serdata) { struct whc_node *newn = NULL; @@ -1228,7 +1228,7 @@ static struct whc_node *whc_default_insert_seq (struct whc_impl *whc, seqno_t ma return newn; } -static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) +static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) { struct whc_impl * const whc = (struct whc_impl *)whc_generic; struct whc_node *newn = NULL; @@ -1439,7 +1439,7 @@ static void return_sample_locked (struct whc_impl *whc, struct whc_borrowed_samp ddsi_serdata_unref (sample->serdata); if (sample->plist) { - nn_plist_fini (sample->plist); + ddsi_plist_fini (sample->plist); ddsrt_free (sample->plist); } } diff --git a/src/core/ddsc/src/dds_whc_builtintopic.c b/src/core/ddsc/src/dds_whc_builtintopic.c index cf48167..361f515 100644 --- a/src/core/ddsc/src/dds_whc_builtintopic.c +++ b/src/core/ddsc/src/dds_whc_builtintopic.c @@ -143,7 +143,7 @@ static void bwhc_get_state (const struct whc *whc, struct whc_state *st) st->unacked_bytes = 0; } -static int bwhc_insert (struct whc *whc, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) +static int bwhc_insert (struct whc *whc, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) { (void)whc; (void)max_drop_seq; diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 382b084..a2e341f 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -316,14 +316,14 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit /* Merge Topic & Publisher qos */ wqos = dds_create_qos (); if (qos) - nn_xqos_mergein_missing (wqos, qos, DDS_WRITER_QOS_MASK); + ddsi_xqos_mergein_missing (wqos, qos, DDS_WRITER_QOS_MASK); if (pub->m_entity.m_qos) - nn_xqos_mergein_missing (wqos, pub->m_entity.m_qos, ~(uint64_t)0); + ddsi_xqos_mergein_missing (wqos, pub->m_entity.m_qos, ~(uint64_t)0); if (tp->m_ktopic->qos) - nn_xqos_mergein_missing (wqos, tp->m_ktopic->qos, ~(uint64_t)0); - nn_xqos_mergein_missing (wqos, &pub->m_entity.m_domain->gv.default_xqos_wr, ~(uint64_t)0); + ddsi_xqos_mergein_missing (wqos, tp->m_ktopic->qos, ~(uint64_t)0); + ddsi_xqos_mergein_missing (wqos, &pub->m_entity.m_domain->gv.default_xqos_wr, ~(uint64_t)0); - if ((rc = nn_xqos_valid (&pub->m_entity.m_domain->gv.logconfig, wqos)) < 0 || + if ((rc = ddsi_xqos_valid (&pub->m_entity.m_domain->gv.logconfig, wqos)) < 0 || (rc = validate_writer_qos(wqos)) != DDS_RETCODE_OK) { dds_delete_qos(wqos); diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 74b0fda..0fe18ef 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -32,6 +32,7 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" ddsi_entity_index.c ddsi_deadline.c ddsi_deliver_locally.c + ddsi_plist.c q_addrset.c q_bitset_inlines.c q_bswap.c @@ -46,7 +47,6 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" q_misc.c q_nwif.c q_pcap.c - q_plist.c q_qosmatch.c q_radmin.c q_receive.c @@ -95,6 +95,8 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" ddsi_deadline.h ddsi_deliver_locally.h ddsi_domaingv.h + ddsi_plist.h + ddsi_xqos.h q_addrset.h q_bitset.h q_bswap.h @@ -112,7 +114,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" q_misc.h q_nwif.h q_pcap.h - q_plist.h q_protocol.h q_qosmatch.h q_radmin.h @@ -127,7 +128,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" q_whc.h q_xevent.h q_xmsg.h - q_xqos.h sysdeps.h ) if(ENABLE_LIFESPAN) diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h b/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h index 542ccfd..caadcb1 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h @@ -20,7 +20,7 @@ #include "dds/ddsrt/sync.h" #include "dds/ddsrt/fibheap.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_nwif.h" #include "dds/ddsi/q_sockwaitset.h" @@ -225,8 +225,8 @@ struct ddsi_domaingv { supplying values for missing QoS settings in incoming discovery packets); plus the actual QoSs needed for the builtin endpoints. */ - nn_plist_t default_plist_pp; - nn_plist_t default_local_plist_pp; + ddsi_plist_t default_plist_pp; + ddsi_plist_t default_local_plist_pp; dds_qos_t default_xqos_rd; dds_qos_t default_xqos_wr; dds_qos_t default_xqos_wr_nad; diff --git a/src/core/ddsi/include/dds/ddsi/q_plist.h b/src/core/ddsi/include/dds/ddsi/ddsi_plist.h similarity index 81% rename from src/core/ddsi/include/dds/ddsi/q_plist.h rename to src/core/ddsi/include/dds/ddsi/ddsi_plist.h index 346e70e..2db8914 100644 --- a/src/core/ddsi/include/dds/ddsi/q_plist.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_plist.h @@ -9,18 +9,17 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef NN_PLIST_H -#define NN_PLIST_H +#ifndef DDSI_PLIST_H +#define DDSI_PLIST_H #include "dds/ddsi/q_feature_check.h" -#include "dds/ddsi/q_xqos.h" +#include "dds/ddsi/ddsi_xqos.h" #include "dds/ddsi/ddsi_tran.h" /* FIXME: eliminate */ #if defined (__cplusplus) extern "C" { #endif - #define PP_PROTOCOL_VERSION ((uint64_t)1 << 0) #define PP_VENDORID ((uint64_t)1 << 1) #define PP_UNICAST_LOCATOR ((uint64_t)1 << 2) @@ -118,7 +117,7 @@ typedef struct nn_prismtech_eotgroup_tid { uint32_t transactionId; } nn_prismtech_eotgroup_tid_t; -typedef struct nn_plist { +typedef struct ddsi_plist { uint64_t present; uint64_t aliased; @@ -158,12 +157,12 @@ typedef struct nn_plist { #endif uint32_t domain_id; char *domain_tag; -} nn_plist_t; +} ddsi_plist_t; /***/ -typedef struct nn_plist_src { +typedef struct ddsi_plist_src { nn_protocol_version_t protocol_version; nn_vendorid_t vendorid; int encoding; @@ -172,16 +171,16 @@ typedef struct nn_plist_src { bool strict; ddsi_tran_factory_t factory; /* eliminate this */ struct ddsrt_log_cfg *logconfig; -} nn_plist_src_t; +} ddsi_plist_src_t; -void nn_plist_init_tables (void); -DDS_EXPORT void nn_plist_init_empty (nn_plist_t *dest); -DDS_EXPORT void nn_plist_mergein_missing (nn_plist_t *a, const nn_plist_t *b, uint64_t pmask, uint64_t qmask); -DDS_EXPORT void nn_plist_copy (nn_plist_t *dst, const nn_plist_t *src); -DDS_EXPORT nn_plist_t *nn_plist_dup (const nn_plist_t *src); +void ddsi_plist_init_tables (void); +DDS_EXPORT void ddsi_plist_init_empty (ddsi_plist_t *dest); +DDS_EXPORT void ddsi_plist_mergein_missing (ddsi_plist_t *a, const ddsi_plist_t *b, uint64_t pmask, uint64_t qmask); +DDS_EXPORT void ddsi_plist_copy (ddsi_plist_t *dst, const ddsi_plist_t *src); +DDS_EXPORT ddsi_plist_t *ddsi_plist_dup (const ddsi_plist_t *src); /** - * @brief Initialize an nn_plist_t from a PL_CDR_{LE,BE} paylaod. + * @brief Initialize an ddsi_plist_t from a PL_CDR_{LE,BE} paylaod. * * @param[in] pwanted * PP_... flags indicating which non-QoS parameters are of interest, treated as @@ -206,8 +205,8 @@ DDS_EXPORT nn_plist_t *nn_plist_dup (const nn_plist_t *src); * input (indicated by the "aliased" bits in the plist/xqos structures), but * some things cannot be aliased (e.g., the array of pointers to strings for a * sequence of strings). - * Generally, nn_plist_fini should be called when done with the parameter list, - * even when nn_plist_unlias or nn_xqos_unlias hasn't been called. + * Generally, ddsi_plist_fini should be called when done with the parameter list, + * even when ddsi_plist_unlias or ddsi_xqos_unlias hasn't been called. * @param[out] nextafterplist * If non-NULL, *nextafterplist is set to the first byte following the parameter * list sentinel on successful parse, or to NULL on failure @@ -226,25 +225,25 @@ DDS_EXPORT nn_plist_t *nn_plist_dup (const nn_plist_t *src); * Input contained an unrecognized parameter with the "incompatible-if-unknown" * flag set; dest is cleared, *nextafterplist is NULL. */ -DDS_EXPORT dds_return_t nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uint64_t pwanted, uint64_t qwanted, const nn_plist_src_t *src); -DDS_EXPORT void nn_plist_fini (nn_plist_t *ps); -DDS_EXPORT void nn_plist_fini_mask (nn_plist_t *plist, uint64_t pmask, uint64_t qmask); -DDS_EXPORT void nn_plist_unalias (nn_plist_t *plist); -DDS_EXPORT void nn_plist_addtomsg (struct nn_xmsg *m, const nn_plist_t *ps, uint64_t pwanted, uint64_t qwanted); -DDS_EXPORT void nn_plist_init_default_participant (nn_plist_t *plist); -DDS_EXPORT void nn_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const nn_plist_t *x, const nn_plist_t *y, uint64_t pmask, uint64_t qmask); -DDS_EXPORT void nn_plist_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const nn_plist_t *plist); -DDS_EXPORT size_t nn_plist_print (char * __restrict buf, size_t bufsize, const nn_plist_t *plist); +DDS_EXPORT dds_return_t ddsi_plist_init_frommsg (ddsi_plist_t *dest, char **nextafterplist, uint64_t pwanted, uint64_t qwanted, const ddsi_plist_src_t *src); +DDS_EXPORT void ddsi_plist_fini (ddsi_plist_t *ps); +DDS_EXPORT void ddsi_plist_fini_mask (ddsi_plist_t *plist, uint64_t pmask, uint64_t qmask); +DDS_EXPORT void ddsi_plist_unalias (ddsi_plist_t *plist); +DDS_EXPORT void ddsi_plist_addtomsg (struct nn_xmsg *m, const ddsi_plist_t *ps, uint64_t pwanted, uint64_t qwanted); +DDS_EXPORT void ddsi_plist_init_default_participant (ddsi_plist_t *plist); +DDS_EXPORT void ddsi_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const ddsi_plist_t *x, const ddsi_plist_t *y, uint64_t pmask, uint64_t qmask); +DDS_EXPORT void ddsi_plist_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const ddsi_plist_t *plist); +DDS_EXPORT size_t ddsi_plist_print (char * __restrict buf, size_t bufsize, const ddsi_plist_t *plist); struct nn_rmsg; struct nn_rsample_info; struct nn_rdata; -DDS_EXPORT unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn_rmsg *rmsg, const nn_plist_src_t *src); -DDS_EXPORT const unsigned char *nn_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid); +DDS_EXPORT unsigned char *ddsi_plist_quickscan (struct nn_rsample_info *dest, const struct nn_rmsg *rmsg, const ddsi_plist_src_t *src); +DDS_EXPORT const unsigned char *ddsi_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid); #if defined (__cplusplus) } #endif -#endif /* NN_PLIST_H */ +#endif /* DDSI_PLIST_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_xqos.h b/src/core/ddsi/include/dds/ddsi/ddsi_xqos.h similarity index 88% rename from src/core/ddsi/include/dds/ddsi/q_xqos.h rename to src/core/ddsi/include/dds/ddsi/ddsi_xqos.h index d591da2..039f5c7 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xqos.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_xqos.h @@ -9,8 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef NN_XQOS_H -#define NN_XQOS_H +#ifndef DDSI_XQOS_H +#define DDSI_XQOS_H #include "dds/ddsc/dds_public_qosdefs.h" /*XXX*/ @@ -304,27 +304,27 @@ struct dds_qos { struct nn_xmsg; -DDS_EXPORT void nn_xqos_init_empty (dds_qos_t *xqos); -DDS_EXPORT void nn_xqos_init_default_reader (dds_qos_t *xqos); -DDS_EXPORT void nn_xqos_init_default_writer (dds_qos_t *xqos); -DDS_EXPORT void nn_xqos_init_default_writer_noautodispose (dds_qos_t *xqos); -DDS_EXPORT void nn_xqos_init_default_subscriber (dds_qos_t *xqos); -DDS_EXPORT void nn_xqos_init_default_publisher (dds_qos_t *xqos); -DDS_EXPORT void nn_xqos_init_default_topic (dds_qos_t *xqos); -DDS_EXPORT void nn_xqos_copy (dds_qos_t *dst, const dds_qos_t *src); -DDS_EXPORT void nn_xqos_unalias (dds_qos_t *xqos); -DDS_EXPORT void nn_xqos_fini (dds_qos_t *xqos); -DDS_EXPORT void nn_xqos_fini_mask (dds_qos_t *xqos, uint64_t mask); -DDS_EXPORT dds_return_t nn_xqos_valid (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos); -DDS_EXPORT void nn_xqos_mergein_missing (dds_qos_t *a, const dds_qos_t *b, uint64_t mask); -DDS_EXPORT uint64_t nn_xqos_delta (const dds_qos_t *a, const dds_qos_t *b, uint64_t mask); -DDS_EXPORT void nn_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, uint64_t wanted); -DDS_EXPORT void nn_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos); -DDS_EXPORT size_t nn_xqos_print (char * __restrict buf, size_t bufsize, const dds_qos_t *xqos); -DDS_EXPORT dds_qos_t *nn_xqos_dup (const dds_qos_t *src); +DDS_EXPORT void ddsi_xqos_init_empty (dds_qos_t *xqos); +DDS_EXPORT void ddsi_xqos_init_default_reader (dds_qos_t *xqos); +DDS_EXPORT void ddsi_xqos_init_default_writer (dds_qos_t *xqos); +DDS_EXPORT void ddsi_xqos_init_default_writer_noautodispose (dds_qos_t *xqos); +DDS_EXPORT void ddsi_xqos_init_default_subscriber (dds_qos_t *xqos); +DDS_EXPORT void ddsi_xqos_init_default_publisher (dds_qos_t *xqos); +DDS_EXPORT void ddsi_xqos_init_default_topic (dds_qos_t *xqos); +DDS_EXPORT void ddsi_xqos_copy (dds_qos_t *dst, const dds_qos_t *src); +DDS_EXPORT void ddsi_xqos_unalias (dds_qos_t *xqos); +DDS_EXPORT void ddsi_xqos_fini (dds_qos_t *xqos); +DDS_EXPORT void ddsi_xqos_fini_mask (dds_qos_t *xqos, uint64_t mask); +DDS_EXPORT dds_return_t ddsi_xqos_valid (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos); +DDS_EXPORT void ddsi_xqos_mergein_missing (dds_qos_t *a, const dds_qos_t *b, uint64_t mask); +DDS_EXPORT uint64_t ddsi_xqos_delta (const dds_qos_t *a, const dds_qos_t *b, uint64_t mask); +DDS_EXPORT void ddsi_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, uint64_t wanted); +DDS_EXPORT void ddsi_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos); +DDS_EXPORT size_t ddsi_xqos_print (char * __restrict buf, size_t bufsize, const dds_qos_t *xqos); +DDS_EXPORT dds_qos_t *ddsi_xqos_dup (const dds_qos_t *src); #if defined (__cplusplus) } #endif -#endif /* NN_XQOS_H */ +#endif /* DDSI_XQOS_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index 7417c3b..fd66ad2 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -14,7 +14,7 @@ #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_thread.h" -#include "dds/ddsi/q_xqos.h" +#include "dds/ddsi/ddsi_xqos.h" #include "dds/ddsi/q_feature_check.h" #include "dds/ddsi/ddsi_portmapping.h" diff --git a/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h b/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h index 3146c89..c5c801e 100644 --- a/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h +++ b/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h @@ -23,7 +23,7 @@ struct writer; struct reader; struct nn_rsample_info; struct nn_rdata; -struct nn_plist; +struct ddsi_plist; int spdp_write (struct participant *pp); int spdp_dispose_unregister (struct participant *pp); @@ -33,7 +33,7 @@ int sedp_write_reader (struct reader *rd); int sedp_dispose_unregister_writer (struct writer *wr); int sedp_dispose_unregister_reader (struct reader *rd); -int sedp_write_topic (struct participant *pp, const struct nn_plist *datap); +int sedp_write_topic (struct participant *pp, const struct ddsi_plist *datap); int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const ddsi_guid_t *rdguid, void *qarg); diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 3105512..c90e2bc 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -40,7 +40,7 @@ struct addrset; struct ddsi_sertopic; struct whc; struct dds_qos; -struct nn_plist; +struct ddsi_plist; struct lease; struct proxy_group; @@ -198,7 +198,7 @@ struct participant dds_duration_t lease_duration; /* constant */ uint32_t bes; /* built-in endpoint set */ unsigned is_ddsi2_pp: 1; /* true for the "federation leader", the ddsi2 participant itself in OSPL; FIXME: probably should use this for broker mode as well ... */ - struct nn_plist *plist; /* settings/QoS for this participant */ + struct ddsi_plist *plist; /* settings/QoS for this participant */ struct xevent *spdp_xevent; /* timed event for periodically publishing SPDP */ struct xevent *pmd_update_xevent; /* timed event for periodically publishing ParticipantMessageData */ nn_locator_t m_locator; @@ -334,7 +334,7 @@ struct proxy_participant unsigned bes; /* built-in endpoint set */ 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 */ + struct ddsi_plist *plist; /* settings/QoS for this participant */ 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 */ @@ -530,7 +530,7 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e); * @retval DDS_RETCODE_OUT_OF_RESOURCES * The configured maximum number of participants has been reached. */ -dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const struct nn_plist *plist); +dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const struct ddsi_plist *plist); /** * @brief Create a new participant in the domain. See also new_participant_guid. @@ -554,7 +554,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domain * @retval DDS_RETCODE_OUT_OF_RESOURCES * The configured maximum number of participants has been reached. */ -dds_return_t new_participant (struct ddsi_guid *ppguid, struct ddsi_domaingv *gv, unsigned flags, const struct nn_plist *plist); +dds_return_t new_participant (struct ddsi_guid *ppguid, struct ddsi_domaingv *gv, unsigned flags, const struct ddsi_plist *plist); /** * @brief Initiate the deletion of the participant: @@ -581,7 +581,7 @@ dds_return_t new_participant (struct ddsi_guid *ppguid, struct ddsi_domaingv *gv * ppguid lookup failed. */ dds_return_t delete_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid); -void update_participant_plist (struct participant *pp, const struct nn_plist *plist); +void update_participant_plist (struct participant *pp, const struct ddsi_plist *plist); uint64_t get_entity_instance_id (const struct ddsi_domaingv *gv, const struct ddsi_guid *guid); /* Gets the interval for PMD messages, which is the minimal lease duration for writers @@ -653,11 +653,11 @@ int writer_set_notalive (struct writer *wr, bool notify); /* Set when this proxy participant is not to be announced on the built-in topics yet */ #define CF_PROXYPP_NO_SPDP (1 << 3) -void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct nn_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq); +void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct ddsi_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq); int delete_proxy_participant_by_guid (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit); -int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, nn_wctime_t timestamp); -int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, nn_wctime_t timestamp); +int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct ddsi_plist *datap, nn_wctime_t timestamp); +int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t seq, const struct ddsi_plist *datap, nn_wctime_t timestamp); void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct lease *newlease); void purge_proxy_participants (struct ddsi_domaingv *gv, const nn_locator_t *loc, bool delete_from_as_disc); @@ -665,8 +665,8 @@ void purge_proxy_participants (struct ddsi_domaingv *gv, const nn_locator_t *loc /* To create a new proxy writer or reader; the proxy participant is determined from the GUID and must exist. */ - int new_proxy_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const struct nn_plist *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp, seqno_t seq); -int new_proxy_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const struct nn_plist *plist, nn_wctime_t timestamp, seqno_t seq + int new_proxy_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const struct ddsi_plist *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp, seqno_t seq); +int new_proxy_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const struct ddsi_plist *plist, nn_wctime_t timestamp, seqno_t seq #ifdef DDSI_INCLUDE_SSM , int favours_ssm #endif diff --git a/src/core/ddsi/include/dds/ddsi/q_transmit.h b/src/core/ddsi/include/dds/ddsi/q_transmit.h index c654052..d2610a5 100644 --- a/src/core/ddsi/include/dds/ddsi/q_transmit.h +++ b/src/core/ddsi/include/dds/ddsi/q_transmit.h @@ -40,8 +40,8 @@ int write_sample_gc_notk (struct thread_state1 * const ts1, struct nn_xpack *xp, int write_sample_nogc_notk (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata); /* 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); +dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const struct ddsi_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 ddsi_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, int hbliveliness, ddsi_entityid_t dst, int issync); dds_return_t write_hb_liveliness (struct ddsi_domaingv * const gv, struct ddsi_guid *wr_guid, struct nn_xpack *xp); diff --git a/src/core/ddsi/include/dds/ddsi/q_whc.h b/src/core/ddsi/include/dds/ddsi/q_whc.h index b726f52..40622a8 100644 --- a/src/core/ddsi/include/dds/ddsi/q_whc.h +++ b/src/core/ddsi/include/dds/ddsi/q_whc.h @@ -20,7 +20,7 @@ extern "C" { #endif struct ddsi_serdata; -struct nn_plist; +struct ddsi_plist; struct ddsi_tkmap_instance; struct whc_node; /* opaque, but currently used for deferred free lists */ struct whc; @@ -28,7 +28,7 @@ struct whc; struct whc_borrowed_sample { seqno_t seq; struct ddsi_serdata *serdata; - struct nn_plist *plist; + struct ddsi_plist *plist; bool unacked; nn_mtime_t last_rexmit_ts; unsigned rexmit_count; @@ -73,7 +73,7 @@ typedef void (*whc_free_t)(struct whc *whc); reliable readers that have not acknowledged all data */ /* max_drop_seq must go soon, it's way too ugly. */ /* plist may be NULL or ddsrt_malloc'd, WHC takes ownership of plist */ -typedef int (*whc_insert_t)(struct whc *whc, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); +typedef int (*whc_insert_t)(struct whc *whc, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); typedef uint32_t (*whc_downgrade_to_volatile_t)(struct whc *whc, struct whc_state *st); typedef uint32_t (*whc_remove_acked_messages_t)(struct whc *whc, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list); typedef void (*whc_free_deferred_free_list_t)(struct whc *whc, struct whc_node *deferred_free_list); @@ -121,7 +121,7 @@ inline bool whc_sample_iter_borrow_next (struct whc_sample_iter *it, struct whc_ inline void whc_free (struct whc *whc) { whc->ops->free (whc); } -inline int whc_insert (struct whc *whc, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) { +inline int whc_insert (struct whc *whc, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) { return whc->ops->insert (whc, max_drop_seq, seq, exp, plist, serdata, tk); } inline unsigned whc_downgrade_to_volatile (struct whc *whc, struct whc_state *st) { diff --git a/src/core/ddsi/include/dds/ddsi/q_xmsg.h b/src/core/ddsi/include/dds/ddsi/q_xmsg.h index 32941c2..ed717b7 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xmsg.h +++ b/src/core/ddsi/include/dds/ddsi/q_xmsg.h @@ -15,7 +15,7 @@ #include #include "dds/ddsi/q_protocol.h" /* for, e.g., SubmessageKind_t */ -#include "dds/ddsi/q_xqos.h" /* for, e.g., octetseq, stringseq */ +#include "dds/ddsi/ddsi_xqos.h" /* for, e.g., octetseq, stringseq */ #include "dds/ddsi/ddsi_tran.h" #if defined (__cplusplus) diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/ddsi_plist.c similarity index 93% rename from src/core/ddsi/src/q_plist.c rename to src/core/ddsi/src/ddsi_plist.c index 1405b13..1ccac80 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/ddsi_plist.c @@ -24,7 +24,7 @@ #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_unused.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/ddsi_vendor.h" @@ -33,7 +33,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_protocol.h" /* for NN_STATUSINFO_... */ -#include "dds/ddsi/q_radmin.h" /* for nn_plist_quickscan */ +#include "dds/ddsi/q_radmin.h" /* for ddsi_plist_quickscan */ #include "dds/ddsrt/avl.h" #include "dds/ddsi/q_misc.h" /* for vendor_is_... */ @@ -48,7 +48,7 @@ DDSRT_STATIC_ASSERT(DDS_LENGTH_UNLIMITED == -1); /* These are internal to the parameter list processing. We never generate them, and we never want to do see them anywhere outside the actual parsing of an incoming parameter list. (There are - entries in nn_plist, but they are never to be inspected and + entries in ddsi_plist, but they are never to be inspected and the bits corresponding to them must be 0 except while processing an incoming parameter list.) */ #define PPTMP_MULTICAST_IPADDRESS (1 << 0) @@ -95,7 +95,7 @@ struct piddesc { uint16_t flags; /* see PDF_xxx flags */ uint64_t present_flag; /* flag in plist.present / plist.qos.present */ const char *name; /* name for reporting invalid input */ - size_t plist_offset; /* offset from start of nn_plist_t */ + size_t plist_offset; /* offset from start of ddsi_plist_t */ size_t size; /* in-memory size for copying */ union { /* descriptor for generic code: 12 is enough for the current set of @@ -125,7 +125,7 @@ static dds_return_t validate_durability_service_qospolicy_acceptzero (const dds_ static dds_return_t do_locator (nn_locators_t *ls, uint64_t *present, uint64_t wanted, uint64_t fl, const struct dd *dd, const struct ddsi_tran_factory *factory); static dds_return_t final_validation_qos (const dds_qos_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid, bool *dursvc_accepted_allzero, bool strict); static int partitions_equal (const void *srca, const void *srcb, size_t off); -static dds_return_t nn_xqos_valid_strictness (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos, bool strict); +static dds_return_t ddsi_xqos_valid_strictness (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos, bool strict); static size_t align4size (size_t x) { @@ -1278,9 +1278,9 @@ static bool print_generic (char * __restrict *buf, size_t * __restrict bufsize, } #define membersize(type, member) sizeof (((type *) 0)->member) -#define ENTRY(PFX_, NAME_, member_, flag_, validate_, ...) \ - { PID_##NAME_, flag_, PFX_##_##NAME_, #NAME_, offsetof (struct nn_plist, member_), \ - membersize (struct nn_plist, member_), { .desc = { __VA_ARGS__, XSTOP } }, validate_ \ +#define ENTRY(PFX_, NAME_, member_, flag_, validate_, ...) \ + { PID_##NAME_, flag_, PFX_##_##NAME_, #NAME_, offsetof (struct ddsi_plist, member_), \ + membersize (struct ddsi_plist, member_), { .desc = { __VA_ARGS__, XSTOP } }, validate_ \ } #define QPV(NAME_, name_, ...) ENTRY(QP, NAME_, qos.name_, PDF_QOS, dvx_##name_, __VA_ARGS__) #define PPV(NAME_, name_, ...) ENTRY(PP, NAME_, name_, 0, dvx_##name_, __VA_ARGS__) @@ -1361,8 +1361,8 @@ static dds_return_t dvx_reader_favours_ssm (void * __restrict dst, const struct } #endif -/* Standardized parameters -- QoS _MUST_ come first (nn_plist_init_tables verifies this) because - it allows early-out when processing a dds_qos_t instead of an nn_plist_t */ +/* Standardized parameters -- QoS _MUST_ come first (ddsi_plist_init_tables verifies this) because + it allows early-out when processing a dds_qos_t instead of an ddsi_plist_t */ static const struct piddesc piddesc_omg[] = { QP (USER_DATA, user_data, XO), QP (TOPIC_NAME, topic_name, XS), @@ -1381,7 +1381,7 @@ static const struct piddesc piddesc_omg[] = { QP (PROPERTY_LIST, property, XQ, XbPROP, XS, XS, XSTOP, Xopt, XQ, XbPROP, XS, XO, XSTOP), /* Reliability encoding does not follow the rules (best-effort/reliable map to 1/2 instead of 0/1 */ { PID_RELIABILITY, PDF_QOS | PDF_FUNCTION, QP_RELIABILITY, "RELIABILITY", - offsetof (struct nn_plist, qos.reliability), membersize (struct nn_plist, qos.reliability), + offsetof (struct ddsi_plist, qos.reliability), membersize (struct ddsi_plist, qos.reliability), { .f = { .deser = deser_reliability, .ser = ser_reliability, .valid = valid_reliability, .equal = equal_reliability, .print = print_reliability } }, 0 }, QP (LIFESPAN, lifespan, XD), QP (DESTINATION_ORDER, destination_order, XE1), @@ -1412,34 +1412,34 @@ static const struct piddesc piddesc_omg[] = { 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), + offsetof (struct ddsi_plist, statusinfo), membersize (struct ddsi_plist, statusinfo), { .f = { .deser = deser_statusinfo, .ser = ser_statusinfo, .print = print_statusinfo } }, 0 }, /* Locators are difficult to deal with because they can occur multi times to represent a set; that is manageable for deser, unalias and fini, but it breaks ser because that one only generates a single parameter header */ { PID_UNICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI, PP_UNICAST_LOCATOR, "UNICAST_LOCATOR", - offsetof (struct nn_plist, unicast_locators), membersize (struct nn_plist, unicast_locators), + offsetof (struct ddsi_plist, unicast_locators), membersize (struct ddsi_plist, unicast_locators), { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator, .print = print_locator } }, 0 }, { PID_MULTICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI, PP_MULTICAST_LOCATOR, "MULTICAST_LOCATOR", - offsetof (struct nn_plist, multicast_locators), membersize (struct nn_plist, multicast_locators), + offsetof (struct ddsi_plist, multicast_locators), membersize (struct ddsi_plist, multicast_locators), { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator, .print = print_locator } }, 0 }, { PID_DEFAULT_UNICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI, PP_DEFAULT_UNICAST_LOCATOR, "DEFAULT_UNICAST_LOCATOR", - offsetof (struct nn_plist, default_unicast_locators), membersize (struct nn_plist, default_unicast_locators), + offsetof (struct ddsi_plist, default_unicast_locators), membersize (struct ddsi_plist, default_unicast_locators), { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator, .print = print_locator } }, 0 }, { PID_DEFAULT_MULTICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI, PP_DEFAULT_MULTICAST_LOCATOR, "DEFAULT_MULTICAST_LOCATOR", - offsetof (struct nn_plist, default_multicast_locators), membersize (struct nn_plist, default_multicast_locators), + offsetof (struct ddsi_plist, default_multicast_locators), membersize (struct ddsi_plist, default_multicast_locators), { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator, .print = print_locator } }, 0 }, { PID_METATRAFFIC_UNICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI, PP_METATRAFFIC_UNICAST_LOCATOR, "METATRAFFIC_UNICAST_LOCATOR", - offsetof (struct nn_plist, metatraffic_unicast_locators), membersize (struct nn_plist, metatraffic_unicast_locators), + offsetof (struct ddsi_plist, metatraffic_unicast_locators), membersize (struct ddsi_plist, metatraffic_unicast_locators), { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator, .print = print_locator } }, 0 }, { PID_METATRAFFIC_MULTICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI, PP_METATRAFFIC_MULTICAST_LOCATOR, "METATRAFFIC_MULTICAST_LOCATOR", - offsetof (struct nn_plist, metatraffic_multicast_locators), membersize (struct nn_plist, metatraffic_multicast_locators), + offsetof (struct ddsi_plist, metatraffic_multicast_locators), membersize (struct ddsi_plist, metatraffic_multicast_locators), { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator, .print = print_locator } }, 0 }, /* PID_..._{IPADDRESS,PORT} is impossible to deal with and are never generated, only accepted. The problem is that there one needs additional state (and even then there is no clear @@ -1455,7 +1455,7 @@ static const struct piddesc piddesc_eclipse[] = { QP (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle, XDx2), QP (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys, XbCOND, XQ, XS, XSTOP), { PID_PAD, PDF_QOS, QP_CYCLONE_IGNORELOCAL, "CYCLONE_IGNORELOCAL", - offsetof (struct nn_plist, qos.ignorelocal), membersize (struct nn_plist, qos.ignorelocal), + offsetof (struct ddsi_plist, qos.ignorelocal), membersize (struct ddsi_plist, qos.ignorelocal), { .desc = { XE2, XSTOP } }, 0 }, PP (PRISMTECH_PARTICIPANT_VERSION_INFO, prismtech_participant_version_info, Xux5, XS), PP (PRISMTECH_TYPE_DESCRIPTION, type_description, XS), @@ -1515,7 +1515,7 @@ struct piddesc_index { Sizes are such that the highest PID (without flags) in table are the last entry in the array. Checked by - nn_plist_init_tables. + ddsi_plist_init_tables. FIXME: should compute them at build-time */ #ifdef DDSI_INCLUDE_SSM @@ -1546,7 +1546,7 @@ static const struct piddesc_index piddesc_vendor_index[] = { #undef INDEX_ANY /* List of entries that require unalias, fini processing; - initialized by nn_plist_init_tables; will assert when + initialized by ddsi_plist_init_tables; will assert when table too small or too large */ static const struct piddesc *piddesc_unalias[18]; static const struct piddesc *piddesc_fini[18]; @@ -1568,7 +1568,7 @@ static int piddesc_cmp_qos_addr (const void *va, const void *vb) return ((uintptr_t) *a == (uintptr_t) *b) ? 0 : ((uintptr_t) *a < (uintptr_t) *b) ? -1 : 1; } -static void nn_plist_init_tables_real (void) +static void ddsi_plist_init_tables_real (void) { /* make index of pid -> entry */ for (size_t i = 0; i < sizeof (piddesc_vendor_index) / sizeof (piddesc_vendor_index[0]); i++) @@ -1659,9 +1659,9 @@ static void nn_plist_init_tables_real (void) #endif } -void nn_plist_init_tables (void) +void ddsi_plist_init_tables (void) { - ddsrt_once (&table_init_control, nn_plist_init_tables_real); + ddsrt_once (&table_init_control, ddsi_plist_init_tables_real); } static void plist_or_xqos_fini (void * __restrict dst, size_t shift, uint64_t pmask, uint64_t qmask) @@ -1671,7 +1671,7 @@ static void plist_or_xqos_fini (void * __restrict dst, size_t shift, uint64_t pm /* DDS manipulation can be done without creating a participant, so we may have to initialize tables just-in-time */ if (piddesc_fini[0] == NULL) - nn_plist_init_tables (); + ddsi_plist_init_tables (); if (shift > 0) { dds_qos_t *qos = dst; @@ -1680,7 +1680,7 @@ static void plist_or_xqos_fini (void * __restrict dst, size_t shift, uint64_t pm } else { - nn_plist_t *plist = dst; + ddsi_plist_t *plist = dst; pfs = (struct flagset) { .present = &plist->present, .aliased = &plist->aliased }; qfs = (struct flagset) { .present = &plist->qos.present, .aliased = &plist->qos.aliased }; } @@ -1713,7 +1713,7 @@ static void plist_or_xqos_unalias (void * __restrict dst, size_t shift) /* DDS manipulation can be done without creating a participant, so we may have to initialize tables just-in-time */ if (piddesc_unalias[0] == NULL) - nn_plist_init_tables (); + ddsi_plist_init_tables (); if (shift > 0) { dds_qos_t *qos = dst; @@ -1722,7 +1722,7 @@ static void plist_or_xqos_unalias (void * __restrict dst, size_t shift) } else { - nn_plist_t *plist = dst; + ddsi_plist_t *plist = dst; pfs = (struct flagset) { .present = &plist->present, .aliased = &plist->aliased }; qfs = (struct flagset) { .present = &plist->qos.present, .aliased = &plist->qos.aliased }; } @@ -1754,8 +1754,8 @@ static void plist_or_xqos_mergein_missing (void * __restrict dst, const void * _ struct flagset pfs_src, qfs_src; struct flagset pfs_dst, qfs_dst; #ifndef NDEBUG - const uint64_t aliased_dst_inp = (shift == 0) ? ((nn_plist_t *) dst)->aliased : 0; - const uint64_t aliased_dst_inq = (shift == 0) ? ((nn_plist_t *) dst)->qos.aliased : ((dds_qos_t *) dst)->aliased; + const uint64_t aliased_dst_inp = (shift == 0) ? ((ddsi_plist_t *) dst)->aliased : 0; + const uint64_t aliased_dst_inq = (shift == 0) ? ((ddsi_plist_t *) dst)->qos.aliased : ((dds_qos_t *) dst)->aliased; #endif if (shift > 0) { @@ -1768,8 +1768,8 @@ static void plist_or_xqos_mergein_missing (void * __restrict dst, const void * _ } else { - nn_plist_t *plist_dst = dst; - const nn_plist_t *plist_src = src; + ddsi_plist_t *plist_dst = dst; + const ddsi_plist_t *plist_src = src; pfs_dst = (struct flagset) { .present = &plist_dst->present, .aliased = &plist_dst->aliased }; qfs_dst = (struct flagset) { .present = &plist_dst->qos.present, .aliased = &plist_dst->qos.aliased }; pfs_src = (struct flagset) { .present = (uint64_t *) &plist_src->present, .aliased = (uint64_t *) &plist_src->aliased }; @@ -1830,7 +1830,7 @@ static void plist_or_xqos_addtomsg (struct nn_xmsg *xmsg, const void * __restric } else { - const nn_plist_t *plist = src; + const ddsi_plist_t *plist = src; pw = plist->present & pwanted; qw = plist->qos.present & qwanted; } @@ -1856,26 +1856,26 @@ static void plist_or_xqos_addtomsg (struct nn_xmsg *xmsg, const void * __restric } } -void nn_plist_fini (nn_plist_t *plist) +void ddsi_plist_fini (ddsi_plist_t *plist) { plist_or_xqos_fini (plist, 0, ~(uint64_t)0, ~(uint64_t)0); } -void nn_plist_fini_mask (nn_plist_t *plist, uint64_t pmask, uint64_t qmask) +void ddsi_plist_fini_mask (ddsi_plist_t *plist, uint64_t pmask, uint64_t qmask) { plist_or_xqos_fini (plist, 0, pmask, qmask); } -void nn_plist_unalias (nn_plist_t *plist) +void ddsi_plist_unalias (ddsi_plist_t *plist) { plist_or_xqos_unalias (plist, 0); } -static dds_return_t nn_xqos_valid_strictness (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos, bool strict) +static dds_return_t ddsi_xqos_valid_strictness (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos, bool strict) { dds_return_t ret; if (piddesc_unalias[0] == NULL) - nn_plist_init_tables (); + ddsi_plist_init_tables (); for (size_t k = 0; k < sizeof (piddesc_tables_all) / sizeof (piddesc_tables_all[0]); k++) { struct piddesc const * const table = piddesc_tables_all[k]; @@ -1886,14 +1886,14 @@ static dds_return_t nn_xqos_valid_strictness (const struct ddsrt_log_cfg *logcfg break; if (xqos->present & entry->present_flag) { - const size_t srcoff = entry->plist_offset - offsetof (nn_plist_t, qos); + const size_t srcoff = entry->plist_offset - offsetof (ddsi_plist_t, qos); if (!(entry->flags & PDF_FUNCTION)) ret = valid_generic (xqos, srcoff, entry->op.desc); else ret = entry->op.f.valid (xqos, srcoff); if (ret < 0) { - DDS_CLOG (DDS_LC_PLIST, logcfg, "nn_xqos_valid: %s invalid\n", entry->name); + DDS_CLOG (DDS_LC_PLIST, logcfg, "ddsi_xqos_valid: %s invalid\n", entry->name); return ret; } } @@ -1901,14 +1901,14 @@ static dds_return_t nn_xqos_valid_strictness (const struct ddsrt_log_cfg *logcfg } if ((ret = final_validation_qos (xqos, (nn_protocol_version_t) { RTPS_MAJOR, RTPS_MINOR }, NN_VENDORID_ECLIPSE, NULL, strict)) < 0) { - DDS_CLOG (DDS_LC_PLIST, logcfg, "nn_xqos_valid: final validation failed\n"); + DDS_CLOG (DDS_LC_PLIST, logcfg, "ddsi_xqos_valid: final validation failed\n"); } return ret; } -dds_return_t nn_xqos_valid (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos) +dds_return_t ddsi_xqos_valid (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos) { - return nn_xqos_valid_strictness (logcfg, xqos, true); + return ddsi_xqos_valid_strictness (logcfg, xqos, true); } static void plist_or_xqos_delta (uint64_t *pdelta, uint64_t *qdelta, const void *srcx, const void *srcy, size_t shift, uint64_t pmask, uint64_t qmask) @@ -1916,7 +1916,7 @@ static void plist_or_xqos_delta (uint64_t *pdelta, uint64_t *qdelta, const void uint64_t pcheck, qcheck; if (piddesc_unalias[0] == NULL) - nn_plist_init_tables (); + ddsi_plist_init_tables (); if (shift > 0) { const dds_qos_t *x = srcx; @@ -1928,8 +1928,8 @@ static void plist_or_xqos_delta (uint64_t *pdelta, uint64_t *qdelta, const void } else { - const nn_plist_t *x = srcx; - const nn_plist_t *y = srcy; + const ddsi_plist_t *x = srcx; + const ddsi_plist_t *y = srcy; *pdelta = (x->present ^ y->present) & pmask; pcheck = (x->present & y->present) & pmask; *qdelta = (x->qos.present ^ y->qos.present) & qmask; @@ -1967,14 +1967,14 @@ static void plist_or_xqos_delta (uint64_t *pdelta, uint64_t *qdelta, const void } } -uint64_t nn_xqos_delta (const dds_qos_t *x, const dds_qos_t *y, uint64_t mask) +uint64_t ddsi_xqos_delta (const dds_qos_t *x, const dds_qos_t *y, uint64_t mask) { uint64_t pdelta, qdelta; - plist_or_xqos_delta (&pdelta, &qdelta, x, y, offsetof (nn_plist_t, qos), 0, mask); + plist_or_xqos_delta (&pdelta, &qdelta, x, y, offsetof (ddsi_plist_t, qos), 0, mask); return qdelta; } -void nn_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const nn_plist_t *x, const nn_plist_t *y, uint64_t pmask, uint64_t qmask) +void ddsi_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const ddsi_plist_t *x, const ddsi_plist_t *y, uint64_t pmask, uint64_t qmask) { plist_or_xqos_delta (pdelta, qdelta, x, y, 0, pmask, qmask); } @@ -2197,7 +2197,7 @@ static void locator_from_ipv4address_port (nn_locator_t *loc, const nn_ipv4addre memcpy (loc->address + 12, a, 4); } -static dds_return_t do_ipv4address (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t wanted, uint32_t fl_tmp, const struct dd *dd, ddsi_tran_factory_t factory) +static dds_return_t do_ipv4address (ddsi_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t wanted, uint32_t fl_tmp, const struct dd *dd, ddsi_tran_factory_t factory) { nn_ipv4address_t *a; nn_port_t *p; @@ -2264,7 +2264,7 @@ static dds_return_t do_ipv4address (nn_plist_t *dest, nn_ipaddress_params_tmp_t } } -static dds_return_t do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t wanted, uint32_t fl_tmp, const struct dd *dd, ddsi_tran_factory_t factory) +static dds_return_t do_port (ddsi_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t wanted, uint32_t fl_tmp, const struct dd *dd, ddsi_tran_factory_t factory) { nn_ipv4address_t *a; nn_port_t *p; @@ -2321,7 +2321,7 @@ static dds_return_t do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_t } } -static dds_return_t return_unrecognized_pid (nn_plist_t *plist, nn_parameterid_t pid) +static dds_return_t return_unrecognized_pid (ddsi_plist_t *plist, nn_parameterid_t pid) { if (!(pid & PID_UNRECOGNIZED_INCOMPATIBLE_FLAG)) return 0; @@ -2332,7 +2332,7 @@ static dds_return_t return_unrecognized_pid (nn_plist_t *plist, nn_parameterid_t } } -static dds_return_t init_one_parameter (nn_plist_t *plist, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t pwanted, uint64_t qwanted, uint16_t pid, const struct dd *dd, ddsi_tran_factory_t factory, const ddsrt_log_cfg_t *logcfg) +static dds_return_t init_one_parameter (ddsi_plist_t *plist, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t pwanted, uint64_t qwanted, uint16_t pid, const struct dd *dd, ddsi_tran_factory_t factory, const ddsrt_log_cfg_t *logcfg) { /* special-cased ipv4address and port, because they have state beyond that what gets passed into the generic code */ @@ -2429,38 +2429,38 @@ static dds_return_t init_one_parameter (nn_plist_t *plist, nn_ipaddress_params_t return ret; } -void nn_plist_mergein_missing (nn_plist_t *a, const nn_plist_t *b, uint64_t pmask, uint64_t qmask) +void ddsi_plist_mergein_missing (ddsi_plist_t *a, const ddsi_plist_t *b, uint64_t pmask, uint64_t qmask) { plist_or_xqos_mergein_missing (a, b, 0, pmask, qmask); } -void nn_xqos_mergein_missing (dds_qos_t *a, const dds_qos_t *b, uint64_t mask) +void ddsi_xqos_mergein_missing (dds_qos_t *a, const dds_qos_t *b, uint64_t mask) { - plist_or_xqos_mergein_missing (a, b, offsetof (nn_plist_t, qos), 0, mask); + plist_or_xqos_mergein_missing (a, b, offsetof (ddsi_plist_t, qos), 0, mask); } -void nn_plist_copy (nn_plist_t *dst, const nn_plist_t *src) +void ddsi_plist_copy (ddsi_plist_t *dst, const ddsi_plist_t *src) { - nn_plist_init_empty (dst); - nn_plist_mergein_missing (dst, src, ~(uint64_t)0, ~(uint64_t)0); + ddsi_plist_init_empty (dst); + ddsi_plist_mergein_missing (dst, src, ~(uint64_t)0, ~(uint64_t)0); } -nn_plist_t *nn_plist_dup (const nn_plist_t *src) +ddsi_plist_t *ddsi_plist_dup (const ddsi_plist_t *src) { - nn_plist_t *dst; + ddsi_plist_t *dst; dst = ddsrt_malloc (sizeof (*dst)); - nn_plist_copy (dst, src); + ddsi_plist_copy (dst, src); assert (dst->aliased == 0); return dst; } -void nn_plist_init_empty (nn_plist_t *dest) +void ddsi_plist_init_empty (ddsi_plist_t *dest) { #ifndef NDEBUG memset (dest, 0, sizeof (*dest)); #endif dest->present = dest->aliased = 0; - nn_xqos_init_empty (&dest->qos); + ddsi_xqos_init_empty (&dest->qos); } static dds_return_t final_validation_qos (const dds_qos_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid, bool *dursvc_accepted_allzero, bool strict) @@ -2540,12 +2540,12 @@ static dds_return_t final_validation_qos (const dds_qos_t *dest, nn_protocol_ver return 0; } -static dds_return_t final_validation (nn_plist_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid, bool *dursvc_accepted_allzero, bool strict) +static dds_return_t final_validation (ddsi_plist_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid, bool *dursvc_accepted_allzero, bool strict) { return final_validation_qos (&dest->qos, protocol_version, vendorid, dursvc_accepted_allzero, strict); } -dds_return_t nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uint64_t pwanted, uint64_t qwanted, const nn_plist_src_t *src) +dds_return_t ddsi_plist_init_frommsg (ddsi_plist_t *dest, char **nextafterplist, uint64_t pwanted, uint64_t qwanted, const ddsi_plist_src_t *src) { const unsigned char *pl; struct dd dd; @@ -2581,10 +2581,10 @@ dds_return_t nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uin src->vendorid.id[0], src->vendorid.id[1], src->encoding); return DDS_RETCODE_BAD_PARAMETER; } - nn_plist_init_empty (dest); + ddsi_plist_init_empty (dest); dest_tmp.present = 0; - DDS_CLOG (DDS_LC_PLIST, src->logconfig, "NN_PLIST_INIT (bswap %d)\n", dd.bswap); + DDS_CLOG (DDS_LC_PLIST, src->logconfig, "DDSI_PLIST_INIT (bswap %d)\n", dd.bswap); pl = src->buf; while (pl + sizeof (nn_parameter_t) <= src->buf + src->bufsz) @@ -2605,7 +2605,7 @@ dds_return_t nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uin DDS_CLOG (DDS_LC_PLIST, src->logconfig, "%4"PRIx32" PID %"PRIx16"\n", (uint32_t) (pl - src->buf), pid); if ((res = final_validation (dest, src->protocol_version, src->vendorid, &dursvc_accepted_allzero, src->strict)) < 0) { - nn_plist_fini (dest); + ddsi_plist_fini (dest); return res; } else @@ -2624,14 +2624,14 @@ dds_return_t nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uin { DDS_CWARNING (src->logconfig, "plist(vendor %u.%u): parameter length %"PRIu16" out of bounds\n", src->vendorid.id[0], src->vendorid.id[1], length); - nn_plist_fini (dest); + ddsi_plist_fini (dest); return DDS_RETCODE_BAD_PARAMETER; } if ((length % 4) != 0) /* DDSI 9.4.2.11 */ { DDS_CWARNING (src->logconfig, "plist(vendor %u.%u): parameter length %"PRIu16" mod 4 != 0\n", src->vendorid.id[0], src->vendorid.id[1], length); - nn_plist_fini (dest); + ddsi_plist_fini (dest); return DDS_RETCODE_BAD_PARAMETER; } @@ -2649,7 +2649,7 @@ dds_return_t nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uin { /* make sure we print a trace message on error */ DDS_CTRACE (src->logconfig, "plist(vendor %u.%u): failed at pid=%"PRIx16"\n", src->vendorid.id[0], src->vendorid.id[1], pid); - nn_plist_fini (dest); + ddsi_plist_fini (dest); return res; } pl += sizeof (*par) + length; @@ -2658,11 +2658,11 @@ dds_return_t nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uin without encountering a sentinel. That is an error */ DDS_CWARNING (src->logconfig, "plist(vendor %u.%u): invalid parameter list: sentinel missing\n", src->vendorid.id[0], src->vendorid.id[1]); - nn_plist_fini (dest); + ddsi_plist_fini (dest); return DDS_RETCODE_BAD_PARAMETER; } -const unsigned char *nn_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid) +const unsigned char *ddsi_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid) { /* Scans the parameter list starting at src looking just for pid, returning NULL if not found; no further checking is done and the input is assumed to valid and in native format. Clearly @@ -2678,11 +2678,11 @@ const unsigned char *nn_plist_findparam_native_unchecked (const void *src, nn_pa return (unsigned char *) (par + 1); } -unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn_rmsg *rmsg, const nn_plist_src_t *src) +unsigned char *ddsi_plist_quickscan (struct nn_rsample_info *dest, const struct nn_rmsg *rmsg, const ddsi_plist_src_t *src) { /* Sets a few fields in dest, returns address of first byte following parameter list, or NULL on error. Most errors will go - undetected, unlike nn_plist_init_frommsg(). */ + undetected, unlike ddsi_plist_init_frommsg(). */ const unsigned char *pl; (void)rmsg; dest->statusinfo = 0; @@ -2709,7 +2709,7 @@ unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn src->vendorid.id[0], src->vendorid.id[1], src->encoding); return NULL; } - DDS_CLOG (DDS_LC_PLIST, src->logconfig, "NN_PLIST_QUICKSCAN (bswap %d)\n", dest->bswap); + DDS_CLOG (DDS_LC_PLIST, src->logconfig, "DDSI_PLIST_QUICKSCAN (bswap %d)\n", dest->bswap); pl = src->buf; while (pl + sizeof (nn_parameter_t) <= src->buf + src->bufsz) { @@ -2770,7 +2770,7 @@ unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn return NULL; } -void nn_xqos_init_empty (dds_qos_t *dest) +void ddsi_xqos_init_empty (dds_qos_t *dest) { #ifndef NDEBUG memset (dest, 0, sizeof (*dest)); @@ -2778,9 +2778,9 @@ void nn_xqos_init_empty (dds_qos_t *dest) dest->present = dest->aliased = 0; } -void nn_plist_init_default_participant (nn_plist_t *plist) +void ddsi_plist_init_default_participant (ddsi_plist_t *plist) { - nn_plist_init_empty (plist); + ddsi_plist_init_empty (plist); plist->qos.present |= QP_PRISMTECH_ENTITY_FACTORY; plist->qos.entity_factory.autoenable_created_entities = 0; @@ -2792,7 +2792,7 @@ void nn_plist_init_default_participant (nn_plist_t *plist) static void xqos_init_default_common (dds_qos_t *xqos) { - nn_xqos_init_empty (xqos); + ddsi_xqos_init_empty (xqos); xqos->present |= QP_PRESENTATION; xqos->presentation.access_scope = DDS_PRESENTATION_INSTANCE; @@ -2834,7 +2834,7 @@ static void xqos_init_default_common (dds_qos_t *xqos) xqos->ignorelocal.value = DDS_IGNORELOCAL_NONE; } -static void nn_xqos_init_default_endpoint (dds_qos_t *xqos) +static void ddsi_xqos_init_default_endpoint (dds_qos_t *xqos) { xqos_init_default_common (xqos); @@ -2855,9 +2855,9 @@ static void nn_xqos_init_default_endpoint (dds_qos_t *xqos) xqos->partition.strs = NULL; } -void nn_xqos_init_default_reader (dds_qos_t *xqos) +void ddsi_xqos_init_default_reader (dds_qos_t *xqos) { - nn_xqos_init_default_endpoint (xqos); + ddsi_xqos_init_default_endpoint (xqos); xqos->present |= QP_RELIABILITY; xqos->reliability.kind = DDS_RELIABILITY_BEST_EFFORT; @@ -2879,9 +2879,9 @@ void nn_xqos_init_default_reader (dds_qos_t *xqos) xqos->subscription_keys.key_list.strs = NULL; } -void nn_xqos_init_default_writer (dds_qos_t *xqos) +void ddsi_xqos_init_default_writer (dds_qos_t *xqos) { - nn_xqos_init_default_endpoint (xqos); + ddsi_xqos_init_default_endpoint (xqos); xqos->present |= QP_DURABILITY_SERVICE; xqos->durability_service.service_cleanup_delay = 0; @@ -2908,13 +2908,13 @@ void nn_xqos_init_default_writer (dds_qos_t *xqos) xqos->writer_data_lifecycle.autodispose_unregistered_instances = 1; } -void nn_xqos_init_default_writer_noautodispose (dds_qos_t *xqos) +void ddsi_xqos_init_default_writer_noautodispose (dds_qos_t *xqos) { - nn_xqos_init_default_writer (xqos); + ddsi_xqos_init_default_writer (xqos); xqos->writer_data_lifecycle.autodispose_unregistered_instances = 0; } -void nn_xqos_init_default_topic (dds_qos_t *xqos) +void ddsi_xqos_init_default_topic (dds_qos_t *xqos) { xqos_init_default_common (xqos); @@ -2942,9 +2942,9 @@ void nn_xqos_init_default_topic (dds_qos_t *xqos) xqos->subscription_keys.key_list.strs = NULL; } -static void nn_xqos_init_default_publisher_subscriber (dds_qos_t *xqos) +static void ddsi_xqos_init_default_publisher_subscriber (dds_qos_t *xqos) { - nn_xqos_init_empty (xqos); + ddsi_xqos_init_empty (xqos); xqos->present |= QP_GROUP_DATA; xqos->group_data.length = 0; @@ -2958,41 +2958,41 @@ static void nn_xqos_init_default_publisher_subscriber (dds_qos_t *xqos) xqos->partition.strs = NULL; } -void nn_xqos_init_default_subscriber (dds_qos_t *xqos) +void ddsi_xqos_init_default_subscriber (dds_qos_t *xqos) { - nn_xqos_init_default_publisher_subscriber (xqos); + ddsi_xqos_init_default_publisher_subscriber (xqos); } -void nn_xqos_init_default_publisher (dds_qos_t *xqos) +void ddsi_xqos_init_default_publisher (dds_qos_t *xqos) { - nn_xqos_init_default_publisher_subscriber (xqos); + ddsi_xqos_init_default_publisher_subscriber (xqos); } -void nn_xqos_copy (dds_qos_t *dst, const dds_qos_t *src) +void ddsi_xqos_copy (dds_qos_t *dst, const dds_qos_t *src) { - nn_xqos_init_empty (dst); - nn_xqos_mergein_missing (dst, src, ~(uint64_t)0); + ddsi_xqos_init_empty (dst); + ddsi_xqos_mergein_missing (dst, src, ~(uint64_t)0); } -void nn_xqos_fini (dds_qos_t *xqos) +void ddsi_xqos_fini (dds_qos_t *xqos) { - plist_or_xqos_fini (xqos, offsetof (nn_plist_t, qos), ~(uint64_t)0, ~(uint64_t)0); + plist_or_xqos_fini (xqos, offsetof (ddsi_plist_t, qos), ~(uint64_t)0, ~(uint64_t)0); } -void nn_xqos_fini_mask (dds_qos_t *xqos, uint64_t mask) +void ddsi_xqos_fini_mask (dds_qos_t *xqos, uint64_t mask) { - plist_or_xqos_fini (xqos, offsetof (nn_plist_t, qos), ~(uint64_t)0, mask); + plist_or_xqos_fini (xqos, offsetof (ddsi_plist_t, qos), ~(uint64_t)0, mask); } -void nn_xqos_unalias (dds_qos_t *xqos) +void ddsi_xqos_unalias (dds_qos_t *xqos) { - plist_or_xqos_unalias (xqos, offsetof (nn_plist_t, qos)); + plist_or_xqos_unalias (xqos, offsetof (ddsi_plist_t, qos)); } -dds_qos_t * nn_xqos_dup (const dds_qos_t *src) +dds_qos_t * ddsi_xqos_dup (const dds_qos_t *src) { dds_qos_t *dst = ddsrt_malloc (sizeof (*dst)); - nn_xqos_copy (dst, src); + ddsi_xqos_copy (dst, src); assert (dst->aliased == 0); return dst; } @@ -3094,12 +3094,12 @@ static int partitions_equal (const void *srca, const void *srcb, size_t off) /*************************/ -void nn_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, uint64_t wanted) +void ddsi_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, uint64_t wanted) { - plist_or_xqos_addtomsg (m, xqos, offsetof (struct nn_plist, qos), 0, wanted); + plist_or_xqos_addtomsg (m, xqos, offsetof (struct ddsi_plist, qos), 0, wanted); } -void nn_plist_addtomsg (struct nn_xmsg *m, const nn_plist_t *ps, uint64_t pwanted, uint64_t qwanted) +void ddsi_plist_addtomsg (struct nn_xmsg *m, const ddsi_plist_t *ps, uint64_t pwanted, uint64_t qwanted) { plist_or_xqos_addtomsg (m, ps, 0, pwanted, qwanted); } @@ -3119,7 +3119,7 @@ static void plist_or_xqos_print (char * __restrict *buf, size_t * __restrict buf } else { - const nn_plist_t *plist = src; + const ddsi_plist_t *plist = src; pw = plist->present & pwanted; qw = plist->qos.present & qwanted; } @@ -3169,16 +3169,16 @@ static void plist_or_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, } } -size_t nn_xqos_print (char * __restrict buf, size_t bufsize, const dds_qos_t *xqos) +size_t ddsi_xqos_print (char * __restrict buf, size_t bufsize, const dds_qos_t *xqos) { const size_t bufsize_in = bufsize; (void) prtf (&buf, &bufsize, "{"); - plist_or_xqos_print (&buf, &bufsize, xqos, offsetof (nn_plist_t, qos), 0, ~(uint64_t)0); + plist_or_xqos_print (&buf, &bufsize, xqos, offsetof (ddsi_plist_t, qos), 0, ~(uint64_t)0); (void) prtf (&buf, &bufsize, "}"); return bufsize_in - bufsize; } -size_t nn_plist_print (char * __restrict buf, size_t bufsize, const nn_plist_t *plist) +size_t ddsi_plist_print (char * __restrict buf, size_t bufsize, const ddsi_plist_t *plist) { const size_t bufsize_in = bufsize; (void) prtf (&buf, &bufsize, "{"); @@ -3187,12 +3187,12 @@ size_t nn_plist_print (char * __restrict buf, size_t bufsize, const nn_plist_t * return bufsize_in - bufsize; } -void nn_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos) +void ddsi_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos) { - plist_or_xqos_log (cat, logcfg, xqos, offsetof (nn_plist_t, qos), 0, ~(uint64_t)0); + plist_or_xqos_log (cat, logcfg, xqos, offsetof (ddsi_plist_t, qos), 0, ~(uint64_t)0); } -void nn_plist_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const nn_plist_t *plist) +void ddsi_plist_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const ddsi_plist_t *plist) { plist_or_xqos_log (cat, logcfg, plist, 0, ~(uint64_t)0, ~(uint64_t)0); } diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index ad60528..a5502ac 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -462,7 +462,7 @@ static struct ddsi_serdata *serdata_default_from_sample_plist (const struct ddsi if (d == NULL) return NULL; serdata_default_append_blob (&d, 1, sample->size, sample->blob); - const unsigned char *rawkey = nn_plist_findparam_native_unchecked (sample->blob, sample->keyparam); + const unsigned char *rawkey = ddsi_plist_findparam_native_unchecked (sample->blob, sample->keyparam); #ifndef NDEBUG size_t keysize; #endif @@ -659,8 +659,8 @@ static size_t serdata_default_print_plist (const struct ddsi_sertopic *sertopic_ { const struct ddsi_serdata_default *d = (const struct ddsi_serdata_default *)serdata_common; const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)sertopic_common; - nn_plist_src_t src; - nn_plist_t tmp; + ddsi_plist_src_t src; + ddsi_plist_t tmp; src.buf = (const unsigned char *) d->data; src.bufsz = d->pos; src.encoding = d->hdr.identifier; @@ -670,12 +670,12 @@ static size_t serdata_default_print_plist (const struct ddsi_sertopic *sertopic_ src.protocol_version.minor = RTPS_MINOR; src.strict = false; src.vendorid = NN_VENDORID_ECLIPSE; - if (nn_plist_init_frommsg (&tmp, NULL, ~(uint64_t)0, ~(uint64_t)0, &src) < 0) + if (ddsi_plist_init_frommsg (&tmp, NULL, ~(uint64_t)0, ~(uint64_t)0, &src) < 0) return (size_t) snprintf (buf, size, "(unparseable-plist)"); else { - size_t ret = nn_plist_print (buf, size, &tmp); - nn_plist_fini (&tmp); + size_t ret = ddsi_plist_print (buf, size, &tmp); + ddsi_plist_fini (&tmp); return ret; } } diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 452f0e1..0d3484d 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -27,7 +27,7 @@ #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_xevent.h" #include "dds/ddsi/q_addrset.h" @@ -187,7 +187,7 @@ int spdp_write (struct participant *pp) { struct nn_xmsg *mpayload; struct nn_locators_one def_uni_loc_one, def_multi_loc_one, meta_uni_loc_one, meta_multi_loc_one; - nn_plist_t ps; + ddsi_plist_t ps; struct writer *wr; size_t size; char node[64]; @@ -215,7 +215,7 @@ int spdp_write (struct participant *pp) construct the payload. */ mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid.prefix, 0, NN_XMSG_KIND_DATA); - nn_plist_init_empty (&ps); + ddsi_plist_init_empty (&ps); ps.present |= PP_PARTICIPANT_GUID | PP_BUILTIN_ENDPOINT_SET | PP_PROTOCOL_VERSION | PP_VENDORID | PP_PARTICIPANT_LEASE_DURATION | PP_DOMAIN_ID; @@ -321,15 +321,15 @@ int spdp_write (struct participant *pp) } /* Participant QoS's insofar as they are set, different from the default, and mapped to the SPDP data, rather than to the PrismTech-specific CMParticipant endpoint. Currently, that means just USER_DATA. */ - qosdiff = nn_xqos_delta (&pp->plist->qos, &pp->e.gv->default_plist_pp.qos, QP_USER_DATA); + qosdiff = ddsi_xqos_delta (&pp->plist->qos, &pp->e.gv->default_plist_pp.qos, QP_USER_DATA); if (pp->e.gv->config.explicitly_publish_qos_set_to_default) qosdiff |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK; assert (ps.qos.present == 0); - nn_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, 0); - nn_plist_addtomsg (mpayload, pp->plist, 0, qosdiff); + ddsi_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, 0); + ddsi_plist_addtomsg (mpayload, pp->plist, 0, qosdiff); nn_xmsg_addpar_sentinel (mpayload); - nn_plist_fini (&ps); + ddsi_plist_fini (&ps); ret = write_mpayload (wr, 1, PID_PARTICIPANT_GUID, mpayload); nn_xmsg_free (mpayload); @@ -339,7 +339,7 @@ int spdp_write (struct participant *pp) int spdp_dispose_unregister (struct participant *pp) { struct nn_xmsg *mpayload; - nn_plist_t ps; + ddsi_plist_t ps; struct writer *wr; int ret; @@ -350,12 +350,12 @@ int spdp_dispose_unregister (struct participant *pp) } mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid.prefix, 0, NN_XMSG_KIND_DATA); - nn_plist_init_empty (&ps); + ddsi_plist_init_empty (&ps); ps.present |= PP_PARTICIPANT_GUID; ps.participant_guid = pp->e.guid; - nn_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0); + ddsi_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0); nn_xmsg_addpar_sentinel (mpayload); - nn_plist_fini (&ps); + ddsi_plist_fini (&ps); ret = write_mpayload (wr, 0, PID_PARTICIPANT_GUID, mpayload); nn_xmsg_free (mpayload); @@ -416,7 +416,7 @@ static void respond_to_spdp (const struct ddsi_domaingv *gv, const ddsi_guid_t * entidx_enum_participant_fini (&est); } -static int handle_SPDP_dead (const struct receiver_state *rst, nn_wctime_t timestamp, const nn_plist_t *datap, unsigned statusinfo) +static int handle_SPDP_dead (const struct receiver_state *rst, nn_wctime_t timestamp, const ddsi_plist_t *datap, unsigned statusinfo) { struct ddsi_domaingv * const gv = rst->gv; ddsi_guid_t guid; @@ -514,7 +514,7 @@ static void make_participants_dependent_on_ddsi2 (struct ddsi_domaingv *gv, cons } } -static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_wctime_t timestamp, const nn_plist_t *datap) +static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_wctime_t timestamp, const ddsi_plist_t *datap) { struct ddsi_domaingv * const gv = rst->gv; const unsigned bes_sedp_announcer_mask = @@ -738,7 +738,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_ } GVLOGDISC (" QOS={"); - nn_xqos_log (DDS_LC_DISCOVERY, &gv->logconfig, &datap->qos); + ddsi_xqos_log (DDS_LC_DISCOVERY, &gv->logconfig, &datap->qos); GVLOGDISC ("}\n"); maybe_add_pp_as_meta_to_as_disc (gv, as_meta); @@ -808,8 +808,8 @@ static void handle_SPDP (const struct receiver_state *rst, seqno_t seq, nn_wctim } else { - nn_plist_t decoded_data; - nn_plist_src_t src; + ddsi_plist_t decoded_data; + ddsi_plist_src_t src; int interesting = 0; dds_return_t plist_ret; src.protocol_version = rst->protocol_version; @@ -820,7 +820,7 @@ static void handle_SPDP (const struct receiver_state *rst, seqno_t seq, nn_wctim src.strict = NN_STRICT_P (gv->config); src.factory = gv->m_factory; src.logconfig = &gv->logconfig; - if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) + if ((plist_ret = ddsi_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { if (plist_ret != DDS_RETCODE_UNSUPPORTED) GVWARNING ("SPDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); @@ -840,14 +840,14 @@ static void handle_SPDP (const struct receiver_state *rst, seqno_t seq, nn_wctim break; } - nn_plist_fini (&decoded_data); + ddsi_plist_fini (&decoded_data); GVLOG (interesting ? DDS_LC_DISCOVERY : DDS_LC_TRACE, "\n"); } } struct add_locator_to_ps_arg { struct ddsi_domaingv *gv; - nn_plist_t *ps; + ddsi_plist_t *ps; }; static void add_locator_to_ps (const nn_locator_t *loc, void *varg) @@ -898,10 +898,10 @@ static int sedp_write_endpoint const dds_qos_t *defqos = is_writer_entityid (epguid->entityid) ? &gv->default_xqos_wr : &gv->default_xqos_rd; struct nn_xmsg *mpayload; uint64_t qosdiff; - nn_plist_t ps; + ddsi_plist_t ps; int ret; - nn_plist_init_empty (&ps); + ddsi_plist_init_empty (&ps); ps.present |= PP_ENDPOINT_GUID; ps.endpoint_guid = *epguid; @@ -950,7 +950,7 @@ static int sedp_write_endpoint } #endif - qosdiff = nn_xqos_delta (xqos, defqos, ~(uint64_t)0); + qosdiff = ddsi_xqos_delta (xqos, defqos, ~(uint64_t)0); if (gv->config.explicitly_publish_qos_set_to_default) qosdiff |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK; @@ -968,10 +968,10 @@ static int sedp_write_endpoint important, except that they need to be set to reasonable things or it'll crash */ mpayload = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA); - nn_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0); - if (xqos) nn_xqos_addtomsg (mpayload, xqos, qosdiff); + ddsi_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0); + if (xqos) ddsi_xqos_addtomsg (mpayload, xqos, qosdiff); nn_xmsg_addpar_sentinel (mpayload); - nn_plist_fini (&ps); + ddsi_plist_fini (&ps); GVLOGDISC ("sedp: write for "PGUIDFMT" via "PGUIDFMT"\n", PGUID (*epguid), PGUID (wr->e.guid)); ret = write_mpayload (wr, alive, PID_ENDPOINT_GUID, mpayload); @@ -1049,10 +1049,10 @@ static const char *durability_to_string (dds_durability_kind_t k) return "undefined-durability"; } -static struct proxy_participant *implicitly_create_proxypp (struct ddsi_domaingv *gv, const ddsi_guid_t *ppguid, nn_plist_t *datap /* note: potentially modifies datap */, const ddsi_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp, seqno_t seq) +static struct proxy_participant *implicitly_create_proxypp (struct ddsi_domaingv *gv, const ddsi_guid_t *ppguid, ddsi_plist_t *datap /* note: potentially modifies datap */, const ddsi_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp, seqno_t seq) { ddsi_guid_t privguid; - nn_plist_t pp_plist; + ddsi_plist_t pp_plist; if (memcmp (&ppguid->prefix, src_guid_prefix, sizeof (ppguid->prefix)) == 0) /* if the writer is owned by the participant itself, we're not interested */ @@ -1060,7 +1060,7 @@ static struct proxy_participant *implicitly_create_proxypp (struct ddsi_domaingv privguid.prefix = *src_guid_prefix; privguid.entityid = to_entityid (NN_ENTITYID_PARTICIPANT); - nn_plist_init_empty(&pp_plist); + ddsi_plist_init_empty(&pp_plist); if (vendor_is_cloud (vendorid)) { @@ -1105,9 +1105,9 @@ static struct proxy_participant *implicitly_create_proxypp (struct ddsi_domaingv goto err; } else { struct addrset *as_default, *as_meta; - nn_plist_t tmp_plist; + ddsi_plist_t tmp_plist; GVTRACE (" from-ddsi2 "PGUIDFMT, PGUID (privguid)); - nn_plist_init_empty (&pp_plist); + ddsi_plist_init_empty (&pp_plist); ddsrt_mutex_lock (&privpp->e.lock); as_default = ref_addrset(privpp->as_default); @@ -1116,7 +1116,7 @@ static struct proxy_participant *implicitly_create_proxypp (struct ddsi_domaingv tmp_plist = *privpp->plist; tmp_plist.present = PP_PARTICIPANT_GUID | PP_PRISMTECH_PARTICIPANT_VERSION_INFO; tmp_plist.participant_guid = *ppguid; - nn_plist_mergein_missing (&pp_plist, &tmp_plist, ~(uint64_t)0, ~(uint64_t)0); + ddsi_plist_mergein_missing (&pp_plist, &tmp_plist, ~(uint64_t)0, ~(uint64_t)0); ddsrt_mutex_unlock (&privpp->e.lock); pp_plist.prismtech_participant_version_info.flags &= ~NN_PRISMTECH_FL_PARTICIPANT_IS_DDSI2; @@ -1125,11 +1125,11 @@ static struct proxy_participant *implicitly_create_proxypp (struct ddsi_domaingv } err: - nn_plist_fini (&pp_plist); + ddsi_plist_fini (&pp_plist); return entidx_lookup_proxy_participant_guid (gv->entity_index, ppguid); } -static void handle_SEDP_alive (const struct receiver_state *rst, seqno_t seq, nn_plist_t *datap /* note: potentially modifies datap */, const ddsi_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp) +static void handle_SEDP_alive (const struct receiver_state *rst, seqno_t seq, ddsi_plist_t *datap /* note: potentially modifies datap */, const ddsi_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp) { #define E(msg, lbl) do { GVLOGDISC (msg); goto lbl; } while (0) struct ddsi_domaingv * const gv = rst->gv; @@ -1178,11 +1178,11 @@ static void handle_SEDP_alive (const struct receiver_state *rst, seqno_t seq, nn xqos = &datap->qos; is_writer = is_writer_entityid (datap->endpoint_guid.entityid); if (!is_writer) - nn_xqos_mergein_missing (xqos, &gv->default_xqos_rd, ~(uint64_t)0); + ddsi_xqos_mergein_missing (xqos, &gv->default_xqos_rd, ~(uint64_t)0); else if (vendor_is_eclipse_or_prismtech(vendorid)) - nn_xqos_mergein_missing (xqos, &gv->default_xqos_wr, ~(uint64_t)0); + ddsi_xqos_mergein_missing (xqos, &gv->default_xqos_wr, ~(uint64_t)0); else - nn_xqos_mergein_missing (xqos, &gv->default_xqos_wr_nad, ~(uint64_t)0); + ddsi_xqos_mergein_missing (xqos, &gv->default_xqos_wr_nad, ~(uint64_t)0); /* After copy + merge, should have at least the ones present in the input. Also verify reliability and durability are present, @@ -1270,7 +1270,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, seqno_t seq, nn GVLOGDISC (" ssm=%u", ssm); #endif GVLOGDISC (") QOS={"); - nn_xqos_log (DDS_LC_DISCOVERY, &gv->logconfig, xqos); + ddsi_xqos_log (DDS_LC_DISCOVERY, &gv->logconfig, xqos); GVLOGDISC ("}\n"); if ((datap->endpoint_guid.entityid.u & NN_ENTITYID_SOURCE_MASK) == NN_ENTITYID_SOURCE_VENDOR && !vendor_is_eclipse_or_prismtech (vendorid)) @@ -1324,7 +1324,7 @@ err: #undef E } -static void handle_SEDP_dead (const struct receiver_state *rst, nn_plist_t *datap, nn_wctime_t timestamp) +static void handle_SEDP_dead (const struct receiver_state *rst, ddsi_plist_t *datap, nn_wctime_t timestamp) { struct ddsi_domaingv * const gv = rst->gv; int res; @@ -1353,8 +1353,8 @@ static void handle_SEDP (const struct receiver_state *rst, seqno_t seq, nn_wctim } else { - nn_plist_t decoded_data; - nn_plist_src_t src; + ddsi_plist_t decoded_data; + ddsi_plist_src_t src; dds_return_t plist_ret; src.protocol_version = rst->protocol_version; src.vendorid = rst->vendor; @@ -1364,7 +1364,7 @@ static void handle_SEDP (const struct receiver_state *rst, seqno_t seq, nn_wctim src.strict = NN_STRICT_P (gv->config); src.factory = gv->m_factory; src.logconfig = &gv->logconfig; - if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) + if ((plist_ret = ddsi_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { if (plist_ret != DDS_RETCODE_UNSUPPORTED) GVWARNING ("SEDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); @@ -1384,7 +1384,7 @@ static void handle_SEDP (const struct receiver_state *rst, seqno_t seq, nn_wctim break; } - nn_plist_fini (&decoded_data); + ddsi_plist_fini (&decoded_data); } } @@ -1394,7 +1394,7 @@ static void handle_SEDP (const struct receiver_state *rst, seqno_t seq, nn_wctim *** *****************************************************************************/ -int sedp_write_topic (struct participant *pp, const struct nn_plist *datap) +int sedp_write_topic (struct participant *pp, const struct ddsi_plist *datap) { struct writer *sedp_wr; struct nn_xmsg *mpayload; @@ -1411,10 +1411,10 @@ int sedp_write_topic (struct participant *pp, const struct nn_plist *datap) sedp_wr = get_sedp_writer (pp, NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER); mpayload = nn_xmsg_new (sedp_wr->e.gv->xmsgpool, &sedp_wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA); - delta = nn_xqos_delta (&datap->qos, &sedp_wr->e.gv->default_xqos_tp, ~(uint64_t)0); + delta = ddsi_xqos_delta (&datap->qos, &sedp_wr->e.gv->default_xqos_tp, ~(uint64_t)0); if (sedp_wr->e.gv->config.explicitly_publish_qos_set_to_default) delta |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK; - nn_plist_addtomsg (mpayload, datap, ~(uint64_t)0, delta); + ddsi_plist_addtomsg (mpayload, datap, ~(uint64_t)0, delta); nn_xmsg_addpar_sentinel (mpayload); ETRACE (pp, "sedp: write topic %s via "PGUIDFMT"\n", datap->qos.topic_name, PGUID (sedp_wr->e.guid)); @@ -1473,7 +1473,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str ddsi_guid_t srcguid; Data_DataFrag_common_t *msg; unsigned char data_smhdr_flags; - nn_plist_t qos; + ddsi_plist_t qos; unsigned char *datap; int needs_free; uint32_t datasz = sampleinfo->size; @@ -1511,12 +1511,12 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str need_keyhash = (datasz == 0 || (data_smhdr_flags & (DATA_FLAG_KEYFLAG | DATA_FLAG_DATAFLAG)) == 0); if (!(sampleinfo->complex_qos || need_keyhash)) { - nn_plist_init_empty (&qos); + ddsi_plist_init_empty (&qos); statusinfo = sampleinfo->statusinfo; } else { - nn_plist_src_t src; + ddsi_plist_src_t src; size_t qos_offset = NN_RDATA_SUBMSG_OFF (fragchain) + offsetof (Data_DataFrag_common_t, octetsToInlineQos) + sizeof (msg->octetsToInlineQos) + msg->octetsToInlineQos; dds_return_t plist_ret; src.protocol_version = sampleinfo->rst->protocol_version; @@ -1527,7 +1527,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str src.strict = NN_STRICT_P (gv->config); src.factory = gv->m_factory; src.logconfig = &gv->logconfig; - if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH, 0, &src)) < 0) + if ((plist_ret = ddsi_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH, 0, &src)) < 0) { if (plist_ret != DDS_RETCODE_UNSUPPORTED) GVWARNING ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n", diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index e42168d..fbf33a0 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -25,7 +25,7 @@ #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_log.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_addrset.h" diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 1f873d4..f52cddb 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -27,7 +27,7 @@ #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_log.h" #include "dds/ddsrt/avl.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/q_lease.h" #include "dds/ddsi/q_qosmatch.h" #include "dds/ddsi/ddsi_entity_index.h" @@ -454,7 +454,7 @@ static bool update_qos_locked (struct entity_common *e, dds_qos_t *ent_qos, cons { uint64_t mask; - mask = nn_xqos_delta (ent_qos, xqos, QP_CHANGEABLE_MASK & ~(QP_RXO_MASK | QP_PARTITION)) & xqos->present; + mask = ddsi_xqos_delta (ent_qos, xqos, QP_CHANGEABLE_MASK & ~(QP_RXO_MASK | QP_PARTITION)) & xqos->present; #if 0 int a = (ent_qos->present & QP_TOPIC_DATA) ? (int) ent_qos->topic_data.length : 6; int b = (xqos->present & QP_TOPIC_DATA) ? (int) xqos->topic_data.length : 6; @@ -467,7 +467,7 @@ static bool update_qos_locked (struct entity_common *e, dds_qos_t *ent_qos, cons !!(mask & QP_TOPIC_DATA)); #endif EELOGDISC (e, "update_qos_locked "PGUIDFMT" delta=%"PRIu64" QOS={", PGUID(e->guid), mask); - nn_xqos_log (DDS_LC_DISCOVERY, &e->gv->logconfig, xqos); + ddsi_xqos_log (DDS_LC_DISCOVERY, &e->gv->logconfig, xqos); EELOGDISC (e, "}\n"); if (mask == 0) @@ -475,8 +475,8 @@ static bool update_qos_locked (struct entity_common *e, dds_qos_t *ent_qos, cons return false; ddsrt_mutex_lock (&e->qos_lock); - nn_xqos_fini_mask (ent_qos, mask); - nn_xqos_mergein_missing (ent_qos, xqos, mask); + ddsi_xqos_fini_mask (ent_qos, mask); + ddsi_xqos_mergein_missing (ent_qos, xqos, mask); ddsrt_mutex_unlock (&e->qos_lock); builtintopic_write (e->gv->builtin_topic_interface, e, timestamp, true); return true; @@ -583,7 +583,7 @@ static void participant_remove_wr_lease_locked (struct participant * pp, struct } } -dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const nn_plist_t *plist) +dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const ddsi_plist_t *plist) { struct participant *pp; ddsi_guid_t subguid, group_guid; @@ -640,13 +640,13 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domain 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); + ddsi_plist_copy (pp->plist, plist); + ddsi_plist_mergein_missing (pp->plist, &gv->default_local_plist_pp, ~(uint64_t)0, ~(uint64_t)0); if (gv->logconfig.c.mask & DDS_LC_DISCOVERY) { GVLOGDISC ("PARTICIPANT "PGUIDFMT" QOS={", PGUID (pp->e.guid)); - nn_xqos_log (DDS_LC_DISCOVERY, &gv->logconfig, &pp->plist->qos); + ddsi_xqos_log (DDS_LC_DISCOVERY, &gv->logconfig, &pp->plist->qos); GVLOGDISC ("}\n"); } @@ -816,7 +816,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domain return 0; } -dds_return_t new_participant (ddsi_guid_t *p_ppguid, struct ddsi_domaingv *gv, unsigned flags, const nn_plist_t *plist) +dds_return_t new_participant (ddsi_guid_t *p_ppguid, struct ddsi_domaingv *gv, unsigned flags, const ddsi_plist_t *plist) { union { uint64_t u64; uint32_t u32[2]; } u; u.u32[0] = gv->ppguid_base.prefix.u[1]; @@ -829,7 +829,7 @@ dds_return_t new_participant (ddsi_guid_t *p_ppguid, struct ddsi_domaingv *gv, u return new_participant_guid (p_ppguid, gv, flags, plist); } -void update_participant_plist (struct participant *pp, const nn_plist_t *plist) +void update_participant_plist (struct participant *pp, const ddsi_plist_t *plist) { ddsrt_mutex_lock (&pp->e.lock); if (update_qos_locked (&pp->e, &pp->plist->qos, &plist->qos, now ())) @@ -987,7 +987,7 @@ static void unref_participant (struct participant *pp, const struct ddsi_guid *g while longer for it to wakeup. */ ddsi_conn_free (pp->m_conn); } - nn_plist_fini (pp->plist); + ddsi_plist_fini (pp->plist); ddsrt_free (pp->plist); ddsrt_mutex_destroy (&pp->refc_lock); entity_common_fini (&pp->e); @@ -2998,13 +2998,13 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se /* Copy QoS, merging in defaults */ wr->xqos = ddsrt_malloc (sizeof (*wr->xqos)); - nn_xqos_copy (wr->xqos, xqos); - nn_xqos_mergein_missing (wr->xqos, &wr->e.gv->default_xqos_wr, ~(uint64_t)0); + ddsi_xqos_copy (wr->xqos, xqos); + ddsi_xqos_mergein_missing (wr->xqos, &wr->e.gv->default_xqos_wr, ~(uint64_t)0); assert (wr->xqos->aliased == 0); set_topic_type_name (wr->xqos, topic); ELOGDISC (wr, "WRITER "PGUIDFMT" QOS={", PGUID (wr->e.guid)); - nn_xqos_log (DDS_LC_DISCOVERY, &wr->e.gv->logconfig, wr->xqos); + ddsi_xqos_log (DDS_LC_DISCOVERY, &wr->e.gv->logconfig, wr->xqos); ELOGDISC (wr, "}\n"); assert (wr->xqos->present & QP_RELIABILITY); @@ -3319,7 +3319,7 @@ static void gc_delete_writer (struct gcreq *gcreq) unref_addrset (wr->ssm_as); #endif unref_addrset (wr->as); /* must remain until readers gone (rebuilding of addrset) */ - nn_xqos_fini (wr->xqos); + ddsi_xqos_fini (wr->xqos); ddsrt_free (wr->xqos); local_reader_ary_fini (&wr->rdary); ddsrt_cond_destroy (&wr->throttle_cond); @@ -3626,15 +3626,15 @@ static dds_return_t new_reader_guid /* Copy QoS, merging in defaults */ rd->xqos = ddsrt_malloc (sizeof (*rd->xqos)); - nn_xqos_copy (rd->xqos, xqos); - nn_xqos_mergein_missing (rd->xqos, &pp->e.gv->default_xqos_rd, ~(uint64_t)0); + ddsi_xqos_copy (rd->xqos, xqos); + ddsi_xqos_mergein_missing (rd->xqos, &pp->e.gv->default_xqos_rd, ~(uint64_t)0); assert (rd->xqos->aliased == 0); set_topic_type_name (rd->xqos, topic); if (rd->e.gv->logconfig.c.mask & DDS_LC_DISCOVERY) { ELOGDISC (rd, "READER "PGUIDFMT" QOS={", PGUID (rd->e.guid)); - nn_xqos_log (DDS_LC_DISCOVERY, &rd->e.gv->logconfig, rd->xqos); + ddsi_xqos_log (DDS_LC_DISCOVERY, &rd->e.gv->logconfig, rd->xqos); ELOGDISC (rd, "}\n"); } assert (rd->xqos->present & QP_RELIABILITY); @@ -3802,7 +3802,7 @@ static void gc_delete_reader (struct gcreq *gcreq) } ddsi_sertopic_unref ((struct ddsi_sertopic *) rd->topic); - nn_xqos_fini (rd->xqos); + ddsi_xqos_fini (rd->xqos); ddsrt_free (rd->xqos); #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS unref_addrset (rd->as); @@ -3960,7 +3960,7 @@ static void proxy_participant_remove_pwr_lease_locked (struct proxy_participant } } -void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const nn_plist_t *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq) +void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const ddsi_plist_t *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq) { /* No locking => iff all participants use unique guids, and sedp runs on a single thread, it can't go wrong. FIXME, maybe? The @@ -4045,8 +4045,8 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp proxypp->as_default = as_default; proxypp->as_meta = as_meta; proxypp->endpoints = NULL; - proxypp->plist = nn_plist_dup (plist); - nn_xqos_mergein_missing (&proxypp->plist->qos, &gv->default_plist_pp.qos, ~(uint64_t)0); + proxypp->plist = ddsi_plist_dup (plist); + ddsi_xqos_mergein_missing (&proxypp->plist->qos, &gv->default_plist_pp.qos, ~(uint64_t)0); ddsrt_avl_init (&proxypp_groups_treedef, &proxypp->groups); if (custom_flags & CF_INC_KERNEL_SEQUENCE_NUMBERS) @@ -4096,15 +4096,15 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp #undef PT_TE #undef TE #undef LTE - nn_plist_t plist_rd, plist_wr; + ddsi_plist_t plist_rd, plist_wr; int i; /* Note: no entity name or group GUID supplied, but that shouldn't matter, as these are internal to DDSI and don't use group coherency */ - nn_plist_init_empty (&plist_wr); - nn_plist_init_empty (&plist_rd); - nn_xqos_copy (&plist_wr.qos, &gv->builtin_endpoint_xqos_wr); - nn_xqos_copy (&plist_rd.qos, &gv->builtin_endpoint_xqos_rd); + ddsi_plist_init_empty (&plist_wr); + ddsi_plist_init_empty (&plist_rd); + ddsi_xqos_copy (&plist_wr.qos, &gv->builtin_endpoint_xqos_wr); + ddsi_xqos_copy (&plist_rd.qos, &gv->builtin_endpoint_xqos_rd); for (i = 0; i < (int) (sizeof (bestab) / sizeof (*bestab)); i++) { const struct bestab *te = &bestab[i]; @@ -4129,8 +4129,8 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp } } } - nn_plist_fini (&plist_wr); - nn_plist_fini (&plist_rd); + ddsi_plist_fini (&plist_wr); + ddsi_plist_fini (&plist_rd); } /* write DCPSParticipant topic before the lease can expire */ @@ -4145,7 +4145,7 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp ddsrt_mutex_unlock (&proxypp->e.lock); } -int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, nn_wctime_t timestamp) +int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct ddsi_plist *datap, nn_wctime_t timestamp) { if (seq > proxypp->seq) { @@ -4154,19 +4154,19 @@ int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, se struct ddsi_domaingv * const gv = proxypp->e.gv; const uint64_t pmask = PP_ENTITY_NAME; const uint64_t qmask = QP_USER_DATA; - nn_plist_t *new_plist = ddsrt_malloc (sizeof (*new_plist)); - nn_plist_init_empty (new_plist); - nn_plist_mergein_missing (new_plist, datap, pmask, qmask); - nn_plist_mergein_missing (new_plist, &gv->default_plist_pp, ~(uint64_t)0, ~(uint64_t)0); + ddsi_plist_t *new_plist = ddsrt_malloc (sizeof (*new_plist)); + ddsi_plist_init_empty (new_plist); + ddsi_plist_mergein_missing (new_plist, datap, pmask, qmask); + ddsi_plist_mergein_missing (new_plist, &gv->default_plist_pp, ~(uint64_t)0, ~(uint64_t)0); (void) update_qos_locked (&proxypp->e, &proxypp->plist->qos, &new_plist->qos, timestamp); - nn_plist_fini (new_plist); + ddsi_plist_fini (new_plist); ddsrt_free (new_plist); proxypp->proxypp_have_spdp = 1; } return 0; } -int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, nn_wctime_t timestamp) +int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t seq, const struct ddsi_plist *datap, nn_wctime_t timestamp) { ddsrt_mutex_lock (&proxypp->e.lock); update_proxy_participant_plist_locked (proxypp, seq, datap, timestamp); @@ -4234,7 +4234,7 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p 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); + ddsi_plist_fini (proxypp->plist); ddsrt_free (proxypp->plist); entity_common_fini (&proxypp->e); remove_deleted_participant_guid (proxypp->e.gv->deleted_participants, &proxypp->e.guid, DPG_LOCAL | DPG_REMOTE); @@ -4427,7 +4427,7 @@ uint64_t get_entity_instance_id (const struct ddsi_domaingv *gv, const struct dd /* PROXY-ENDPOINT --------------------------------------------------- */ -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) +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 ddsi_plist_t *plist) { const char *name; int ret; @@ -4439,7 +4439,7 @@ static int proxy_endpoint_common_init (struct entity_common *e, struct proxy_end name = (plist->present & PP_ENTITY_NAME) ? plist->entity_name : ""; entity_common_init (e, proxypp->e.gv, guid, name, kind, tcreate, proxypp->vendor, false); - c->xqos = nn_xqos_dup (&plist->qos); + c->xqos = ddsi_xqos_dup (&plist->qos); c->as = ref_addrset (as); c->vendor = proxypp->vendor; c->seq = seq; @@ -4451,7 +4451,7 @@ static int proxy_endpoint_common_init (struct entity_common *e, struct proxy_end if ((ret = ref_proxy_participant (proxypp, c)) != DDS_RETCODE_OK) { - nn_xqos_fini (c->xqos); + ddsi_xqos_fini (c->xqos); ddsrt_free (c->xqos); unref_addrset (c->as); entity_common_fini (e); @@ -4464,7 +4464,7 @@ static int proxy_endpoint_common_init (struct entity_common *e, struct proxy_end static void proxy_endpoint_common_fini (struct entity_common *e, struct proxy_endpoint_common *c) { unref_proxy_participant (c->proxypp, c); - nn_xqos_fini (c->xqos); + ddsi_xqos_fini (c->xqos); ddsrt_free (c->xqos); unref_addrset (c->as); entity_common_fini (e); @@ -4472,7 +4472,7 @@ static void proxy_endpoint_common_fini (struct entity_common *e, struct proxy_en /* PROXY-WRITER ----------------------------------------------------- */ -int new_proxy_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const nn_plist_t *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp, seqno_t seq) +int new_proxy_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const ddsi_plist_t *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp, seqno_t seq) { struct proxy_participant *proxypp; struct proxy_writer *pwr; @@ -4806,7 +4806,7 @@ int proxy_writer_set_notalive (struct proxy_writer *pwr, bool notify) /* PROXY-READER ----------------------------------------------------- */ -int new_proxy_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const nn_plist_t *plist, nn_wctime_t timestamp, seqno_t seq +int new_proxy_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const ddsi_plist_t *plist, nn_wctime_t timestamp, seqno_t seq #ifdef DDSI_INCLUDE_SSM , int favours_ssm #endif diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 7727384..af5e849 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -27,7 +27,7 @@ #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_lat_estim.h" @@ -127,7 +127,7 @@ static enum make_uc_sockets_ret make_uc_sockets (struct ddsi_domaingv *gv, uint3 static void make_builtin_endpoint_xqos (dds_qos_t *q, const dds_qos_t *template) { - nn_xqos_copy (q, template); + ddsi_xqos_copy (q, template); q->reliability.kind = DDS_RELIABILITY_RELIABLE; q->reliability.max_blocking_time = 100 * T_MILLISECOND; q->durability.kind = DDS_DURABILITY_TRANSIENT_LOCAL; @@ -935,7 +935,7 @@ int rtps_init (struct ddsi_domaingv *gv) gv->tstart = now (); /* wall clock time, used in logs */ - nn_plist_init_tables (); + ddsi_plist_init_tables (); gv->disc_conn_uc = NULL; gv->data_conn_uc = NULL; @@ -1082,15 +1082,15 @@ int rtps_init (struct ddsi_domaingv *gv) gv->xmsgpool = nn_xmsgpool_new (); gv->serpool = ddsi_serdatapool_new (); - nn_plist_init_default_participant (&gv->default_plist_pp); - nn_plist_init_default_participant (&gv->default_local_plist_pp); - nn_xqos_init_default_reader (&gv->default_xqos_rd); - nn_xqos_init_default_writer (&gv->default_xqos_wr); - nn_xqos_init_default_writer_noautodispose (&gv->default_xqos_wr_nad); - nn_xqos_init_default_topic (&gv->default_xqos_tp); - nn_xqos_init_default_subscriber (&gv->default_xqos_sub); - nn_xqos_init_default_publisher (&gv->default_xqos_pub); - nn_xqos_copy (&gv->spdp_endpoint_xqos, &gv->default_xqos_rd); + ddsi_plist_init_default_participant (&gv->default_plist_pp); + ddsi_plist_init_default_participant (&gv->default_local_plist_pp); + ddsi_xqos_init_default_reader (&gv->default_xqos_rd); + ddsi_xqos_init_default_writer (&gv->default_xqos_wr); + ddsi_xqos_init_default_writer_noautodispose (&gv->default_xqos_wr_nad); + ddsi_xqos_init_default_topic (&gv->default_xqos_tp); + ddsi_xqos_init_default_subscriber (&gv->default_xqos_sub); + ddsi_xqos_init_default_publisher (&gv->default_xqos_pub); + ddsi_xqos_copy (&gv->spdp_endpoint_xqos, &gv->default_xqos_rd); gv->spdp_endpoint_xqos.durability.kind = DDS_DURABILITY_TRANSIENT_LOCAL; make_builtin_endpoint_xqos (&gv->builtin_endpoint_xqos_rd, &gv->default_xqos_rd); make_builtin_endpoint_xqos (&gv->builtin_endpoint_xqos_wr, &gv->default_xqos_wr); @@ -1437,17 +1437,17 @@ err_unicast_sockets: #endif ddsrt_hh_free (gv->sertopics); ddsrt_mutex_destroy (&gv->sertopics_lock); - nn_xqos_fini (&gv->builtin_endpoint_xqos_wr); - nn_xqos_fini (&gv->builtin_endpoint_xqos_rd); - nn_xqos_fini (&gv->spdp_endpoint_xqos); - nn_xqos_fini (&gv->default_xqos_pub); - nn_xqos_fini (&gv->default_xqos_sub); - nn_xqos_fini (&gv->default_xqos_tp); - nn_xqos_fini (&gv->default_xqos_wr_nad); - nn_xqos_fini (&gv->default_xqos_wr); - nn_xqos_fini (&gv->default_xqos_rd); - nn_plist_fini (&gv->default_local_plist_pp); - nn_plist_fini (&gv->default_plist_pp); + ddsi_xqos_fini (&gv->builtin_endpoint_xqos_wr); + ddsi_xqos_fini (&gv->builtin_endpoint_xqos_rd); + ddsi_xqos_fini (&gv->spdp_endpoint_xqos); + ddsi_xqos_fini (&gv->default_xqos_pub); + ddsi_xqos_fini (&gv->default_xqos_sub); + ddsi_xqos_fini (&gv->default_xqos_tp); + ddsi_xqos_fini (&gv->default_xqos_wr_nad); + ddsi_xqos_fini (&gv->default_xqos_wr); + ddsi_xqos_fini (&gv->default_xqos_rd); + ddsi_plist_fini (&gv->default_local_plist_pp); + ddsi_plist_fini (&gv->default_plist_pp); ddsi_serdatapool_free (gv->serpool); nn_xmsgpool_free (gv->xmsgpool); #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS @@ -1784,17 +1784,17 @@ void rtps_fini (struct ddsi_domaingv *gv) ddsrt_hh_free (gv->sertopics); ddsrt_mutex_destroy (&gv->sertopics_lock); - nn_xqos_fini (&gv->builtin_endpoint_xqos_wr); - nn_xqos_fini (&gv->builtin_endpoint_xqos_rd); - nn_xqos_fini (&gv->spdp_endpoint_xqos); - nn_xqos_fini (&gv->default_xqos_pub); - nn_xqos_fini (&gv->default_xqos_sub); - nn_xqos_fini (&gv->default_xqos_tp); - nn_xqos_fini (&gv->default_xqos_wr_nad); - nn_xqos_fini (&gv->default_xqos_wr); - nn_xqos_fini (&gv->default_xqos_rd); - nn_plist_fini (&gv->default_local_plist_pp); - nn_plist_fini (&gv->default_plist_pp); + ddsi_xqos_fini (&gv->builtin_endpoint_xqos_wr); + ddsi_xqos_fini (&gv->builtin_endpoint_xqos_rd); + ddsi_xqos_fini (&gv->spdp_endpoint_xqos); + ddsi_xqos_fini (&gv->default_xqos_pub); + ddsi_xqos_fini (&gv->default_xqos_sub); + ddsi_xqos_fini (&gv->default_xqos_tp); + ddsi_xqos_fini (&gv->default_xqos_wr_nad); + ddsi_xqos_fini (&gv->default_xqos_wr); + ddsi_xqos_fini (&gv->default_xqos_rd); + ddsi_plist_fini (&gv->default_local_plist_pp); + ddsi_plist_fini (&gv->default_plist_pp); ddsrt_mutex_destroy (&gv->lock); diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index 7a0b598..7e8f9f3 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -24,7 +24,7 @@ #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_xevent.h" #include "dds/ddsi/q_addrset.h" diff --git a/src/core/ddsi/src/q_qosmatch.c b/src/core/ddsi/src/q_qosmatch.c index 721a010..7c951e1 100644 --- a/src/core/ddsi/src/q_qosmatch.c +++ b/src/core/ddsi/src/q_qosmatch.c @@ -13,7 +13,7 @@ #include #include "dds/ddsi/q_time.h" -#include "dds/ddsi/q_xqos.h" +#include "dds/ddsi/ddsi_xqos.h" #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_qosmatch.h" diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index 2f5694f..e269b35 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -36,7 +36,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_radmin.h" #include "dds/ddsi/q_bitset.h" diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 614aba4..c01e730 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -28,7 +28,7 @@ #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_lat_estim.h" @@ -334,7 +334,7 @@ static int valid_Data (const struct receiver_state *rst, struct nn_rmsg *rmsg, D ptr = (unsigned char *) msg + offsetof (Data_DataFrag_common_t, octetsToInlineQos) + sizeof (msg->x.octetsToInlineQos) + msg->x.octetsToInlineQos; if (msg->x.smhdr.flags & DATA_FLAG_INLINE_QOS) { - nn_plist_src_t src; + ddsi_plist_src_t src; src.protocol_version = rst->protocol_version; src.vendorid = rst->vendor; src.encoding = (msg->x.smhdr.flags & SMFLAG_ENDIANNESS) ? PL_CDR_LE : PL_CDR_BE; @@ -343,7 +343,7 @@ static int valid_Data (const struct receiver_state *rst, struct nn_rmsg *rmsg, D src.factory = NULL; src.logconfig = &rst->gv->logconfig; /* just a quick scan, gathering only what we _really_ need */ - if ((ptr = nn_plist_quickscan (sampleinfo, rmsg, &src)) == NULL) + if ((ptr = ddsi_plist_quickscan (sampleinfo, rmsg, &src)) == NULL) return 0; } else @@ -456,7 +456,7 @@ static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rms ptr = (unsigned char *) msg + offsetof (Data_DataFrag_common_t, octetsToInlineQos) + sizeof (msg->x.octetsToInlineQos) + msg->x.octetsToInlineQos; if (msg->x.smhdr.flags & DATAFRAG_FLAG_INLINE_QOS) { - nn_plist_src_t src; + ddsi_plist_src_t src; src.protocol_version = rst->protocol_version; src.vendorid = rst->vendor; src.encoding = (msg->x.smhdr.flags & SMFLAG_ENDIANNESS) ? PL_CDR_LE : PL_CDR_BE; @@ -465,7 +465,7 @@ static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rms src.factory = NULL; src.logconfig = &rst->gv->logconfig; /* just a quick scan, gathering only what we _really_ need */ - if ((ptr = nn_plist_quickscan (sampleinfo, rmsg, &src)) == NULL) + if ((ptr = ddsi_plist_quickscan (sampleinfo, rmsg, &src)) == NULL) return 0; } else @@ -1737,7 +1737,7 @@ static struct ddsi_serdata *get_serdata (struct ddsi_sertopic const * const topi struct remote_sourceinfo { const struct nn_rsample_info *sampleinfo; unsigned char data_smhdr_flags; - const nn_plist_t *qos; + const ddsi_plist_t *qos; const struct nn_rdata *fragchain; unsigned statusinfo; nn_wctime_t tstamp; @@ -1753,7 +1753,7 @@ static struct ddsi_serdata *remote_make_sample (struct ddsi_tkmap_instance **tk, const uint32_t statusinfo = si->statusinfo; const unsigned char data_smhdr_flags = si->data_smhdr_flags; const nn_wctime_t tstamp = si->tstamp; - const nn_plist_t * __restrict qos = si->qos; + const ddsi_plist_t * __restrict qos = si->qos; const char *failmsg = NULL; struct ddsi_serdata *sample = NULL; @@ -1922,7 +1922,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st unsigned statusinfo; Data_DataFrag_common_t *msg; unsigned char data_smhdr_flags; - nn_plist_t qos; + ddsi_plist_t qos; int need_keyhash; if (pwr->ddsi2direct_cb) @@ -1958,12 +1958,12 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st need_keyhash = (sampleinfo->size == 0 || (data_smhdr_flags & (DATA_FLAG_KEYFLAG | DATA_FLAG_DATAFLAG)) == 0); if (!(sampleinfo->complex_qos || need_keyhash) || !(data_smhdr_flags & DATA_FLAG_INLINE_QOS)) { - nn_plist_init_empty (&qos); + ddsi_plist_init_empty (&qos); statusinfo = sampleinfo->statusinfo; } else { - nn_plist_src_t src; + ddsi_plist_src_t src; size_t qos_offset = NN_RDATA_SUBMSG_OFF (fragchain) + offsetof (Data_DataFrag_common_t, octetsToInlineQos) + sizeof (msg->octetsToInlineQos) + msg->octetsToInlineQos; dds_return_t plist_ret; src.protocol_version = rst->protocol_version; @@ -1974,7 +1974,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st src.strict = NN_STRICT_P (gv->config); src.factory = gv->m_factory; src.logconfig = &gv->logconfig; - if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH | PP_COHERENT_SET, 0, &src)) < 0) + if ((plist_ret = ddsi_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH | PP_COHERENT_SET, 0, &src)) < 0) { if (plist_ret != DDS_RETCODE_UNSUPPORTED) GVWARNING ("data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n", @@ -2005,7 +2005,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st ddsrt_atomic_st32 (&pwr->next_deliv_seq_lowword, (uint32_t) (sampleinfo->seq + 1)); } - nn_plist_fini (&qos); + ddsi_plist_fini (&qos); return 0; } diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 1b6180a..d412613 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -461,7 +461,7 @@ static dds_return_t create_fragment_message_simple (struct writer *wr, seqno_t s return 0; } -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 **pmsg, int isnew) +dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const struct ddsi_plist *plist, struct ddsi_serdata *serdata, unsigned fragnum, struct proxy_reader *prd, struct nn_xmsg **pmsg, int isnew) { /* We always fragment into FRAGMENT_SIZEd fragments, which are near the smallest allowed fragment size & can't be bothered (yet) to @@ -730,7 +730,7 @@ static int must_skip_frag (const char *frags_to_skip, unsigned frag) } #endif -static void transmit_sample_lgmsg_unlocked (struct nn_xpack *xp, struct writer *wr, const struct whc_state *whcst, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew, uint32_t nfrags) +static void transmit_sample_lgmsg_unlocked (struct nn_xpack *xp, struct writer *wr, const struct whc_state *whcst, seqno_t seq, const struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew, uint32_t nfrags) { #if 0 const char *frags_to_skip = getenv ("SKIPFRAGS"); @@ -787,7 +787,7 @@ static void transmit_sample_lgmsg_unlocked (struct nn_xpack *xp, struct writer * } } -static void transmit_sample_unlocks_wr (struct nn_xpack *xp, struct writer *wr, const struct whc_state *whcst, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew) +static void transmit_sample_unlocks_wr (struct nn_xpack *xp, struct writer *wr, const struct whc_state *whcst, seqno_t seq, const struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew) { /* on entry: &wr->e.lock held; on exit: lock no longer held */ struct ddsi_domaingv const * const gv = wr->e.gv; @@ -830,7 +830,7 @@ static void transmit_sample_unlocks_wr (struct nn_xpack *xp, struct writer *wr, } } -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) +int enqueue_sample_wrlock_held (struct writer *wr, seqno_t seq, const struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew) { struct ddsi_domaingv const * const gv = wr->e.gv; uint32_t i, sz, nfrags; @@ -885,7 +885,7 @@ int enqueue_sample_wrlock_held (struct writer *wr, seqno_t seq, const struct nn_ return enqueued ? 0 : -1; } -static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) +static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) { /* returns: < 0 on error, 0 if no need to insert in whc, > 0 if inserted */ int insres, res = 0; @@ -1084,7 +1084,7 @@ static int maybe_grow_whc (struct writer *wr) return 0; } -static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk, int end_of_txn, int gc_allowed) +static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk, int end_of_txn, int gc_allowed) { struct ddsi_domaingv const * const gv = wr->e.gv; int r; @@ -1171,7 +1171,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * if (plist == NULL) { plist = ddsrt_malloc (sizeof (*plist)); - nn_plist_init_empty (plist); + ddsi_plist_init_empty (plist); } assert (!(plist->present & PP_COHERENT_SET)); plist->present |= PP_COHERENT_SET; @@ -1184,7 +1184,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * ddsrt_mutex_unlock (&wr->e.lock); if (plist != NULL) { - nn_plist_fini (plist); + ddsi_plist_fini (plist); ddsrt_free (plist); } } @@ -1200,7 +1200,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * ddsrt_mutex_unlock (&wr->e.lock); if (plist != NULL) { - nn_plist_fini (plist); + ddsi_plist_fini (plist); ddsrt_free (plist); } } @@ -1215,14 +1215,14 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * * creating the message, the WHC will free the plist (if any). Currently, * plist's are only used for coherent sets, which is assumed to be rare, * which in turn means that an extra copy doesn't hurt too badly ... */ - nn_plist_t plist_stk, *plist_copy; + ddsi_plist_t plist_stk, *plist_copy; struct whc_state whcst, *whcstptr; if (plist == NULL) plist_copy = NULL; else { plist_copy = &plist_stk; - nn_plist_copy (plist_copy, plist); + ddsi_plist_copy (plist_copy, plist); } if (wr->heartbeat_xevent == NULL) whcstptr = NULL; @@ -1233,7 +1233,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * } transmit_sample_unlocks_wr (xp, wr, whcstptr, seq, plist_copy, serdata, NULL, 1); if (plist_copy) - nn_plist_fini (plist_copy); + ddsi_plist_fini (plist_copy); } else { @@ -1246,7 +1246,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * /* If not actually inserted, WHC didn't take ownership of plist */ if (r == 0 && plist != NULL) { - nn_plist_fini (plist); + ddsi_plist_fini (plist); ddsrt_free (plist); } } diff --git a/src/core/ddsi/src/q_whc.c b/src/core/ddsi/src/q_whc.c index 0a7d1c8..457045d 100644 --- a/src/core/ddsi/src/q_whc.c +++ b/src/core/ddsi/src/q_whc.c @@ -21,7 +21,7 @@ extern inline void whc_return_sample (struct whc *whc, struct whc_borrowed_sampl extern inline void whc_sample_iter_init (const struct whc *whc, struct whc_sample_iter *it); extern inline bool whc_sample_iter_borrow_next (struct whc_sample_iter *it, struct whc_borrowed_sample *sample); extern inline void whc_free (struct whc *whc); -extern int whc_insert (struct whc *whc, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); +extern int whc_insert (struct whc *whc, seqno_t max_drop_seq, seqno_t seq, nn_mtime_t exp, struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); extern unsigned whc_downgrade_to_volatile (struct whc *whc, struct whc_state *st); extern unsigned whc_remove_acked_messages (struct whc *whc, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list); extern void whc_free_deferred_free_list (struct whc *whc, struct whc_node *deferred_free_list); diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index 9a839aa..7c3b777 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -950,14 +950,14 @@ static bool resend_spdp_sample_by_guid_key (struct writer *wr, const ddsi_guid_t is to be preferred */ struct ddsi_domaingv *gv = wr->e.gv; bool sample_found; - nn_plist_t ps; - nn_plist_init_empty (&ps); + ddsi_plist_t ps; + ddsi_plist_init_empty (&ps); ps.present |= PP_PARTICIPANT_GUID; ps.participant_guid = *guid; struct nn_xmsg *mpayload = nn_xmsg_new (gv->xmsgpool, &guid->prefix, 0, NN_XMSG_KIND_DATA); - nn_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0); + ddsi_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0); nn_xmsg_addpar_sentinel (mpayload); - nn_plist_fini (&ps); + ddsi_plist_fini (&ps); struct ddsi_plist_sample plist_sample; nn_xmsg_payload_to_plistsample (&plist_sample, PID_PARTICIPANT_GUID, mpayload); struct ddsi_serdata *sd = ddsi_serdata_from_sample (gv->plist_topic, SDK_KEY, &plist_sample); diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 7c7ae22..6a3de18 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -27,7 +27,7 @@ #include "dds/ddsrt/thread_pool.h" #include "dds/ddsi/q_protocol.h" -#include "dds/ddsi/q_xqos.h" +#include "dds/ddsi/ddsi_xqos.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_addrset.h" diff --git a/src/core/ddsi/tests/plist.c b/src/core/ddsi/tests/plist.c index b8e4e44..a26d932 100644 --- a/src/core/ddsi/tests/plist.c +++ b/src/core/ddsi/tests/plist.c @@ -14,15 +14,15 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/endian.h" -#include "dds/ddsi/q_xqos.h" -#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/ddsi_xqos.h" +#include "dds/ddsi/ddsi_plist.h" CU_Test (ddsi_plist, unalias_copy_merge) { /* one int, one string and one string sequence covers most cases */ - nn_plist_t p0, p0memcpy; + ddsi_plist_t p0, p0memcpy; char *p0strs[3]; - nn_plist_init_empty (&p0); + ddsi_plist_init_empty (&p0); p0.present = PP_ENTITY_NAME; p0.aliased = PP_ENTITY_NAME; p0.entity_name = "nemo"; @@ -36,10 +36,10 @@ CU_Test (ddsi_plist, unalias_copy_merge) memcpy (&p0memcpy, &p0, sizeof (p0)); /* manually alias one, so we can free it*/ - nn_plist_t p0alias; + ddsi_plist_t p0alias; memcpy (&p0alias, &p0, sizeof (p0)); p0alias.qos.partition.strs = ddsrt_memdup (p0alias.qos.partition.strs, p0.qos.partition.n * sizeof (*p0.qos.partition.strs)); - nn_plist_fini (&p0alias); + ddsi_plist_fini (&p0alias); CU_ASSERT (memcmp (&p0, &p0memcpy, sizeof (p0)) == 0); CU_ASSERT_STRING_EQUAL (p0.entity_name, "nemo"); CU_ASSERT_STRING_EQUAL (p0.qos.partition.strs[0], p0strs[0]); @@ -47,9 +47,9 @@ CU_Test (ddsi_plist, unalias_copy_merge) CU_ASSERT_STRING_EQUAL (p0.qos.partition.strs[2], p0strs[2]); /* copy an aliased one; the original must be unchanged, the copy unaliased */ - nn_plist_t p1; - nn_plist_init_empty (&p1); - nn_plist_copy (&p1, &p0); + ddsi_plist_t p1; + ddsi_plist_init_empty (&p1); + ddsi_plist_copy (&p1, &p0); CU_ASSERT (memcmp (&p0, &p0memcpy, sizeof (p0)) == 0); CU_ASSERT (p1.present == p0.present); CU_ASSERT (p1.aliased == 0); @@ -69,13 +69,13 @@ CU_Test (ddsi_plist, unalias_copy_merge) /* merge-in missing ones from an aliased copy: original must remain unchanged; existing ones should stay without touching "aliased" only new ones are added as unaliased ones */ - nn_plist_t p2, p2memcpy; - nn_plist_init_empty (&p2); + ddsi_plist_t p2, p2memcpy; + ddsi_plist_init_empty (&p2); p2.present = PP_ENTITY_NAME; p2.aliased = PP_ENTITY_NAME; p2.entity_name = "omen"; memcpy (&p2memcpy, &p2, sizeof (p2)); - nn_plist_mergein_missing (&p2, &p0, p0.present, p0.qos.present); + ddsi_plist_mergein_missing (&p2, &p0, p0.present, p0.qos.present); CU_ASSERT (memcmp (&p0, &p0memcpy, sizeof (p0)) == 0); CU_ASSERT (p2.present == p0.present); CU_ASSERT (p2.aliased == p2memcpy.aliased); @@ -93,7 +93,7 @@ CU_Test (ddsi_plist, unalias_copy_merge) CU_ASSERT_STRING_EQUAL (p2.qos.partition.strs[2], p0.qos.partition.strs[2]); /* unalias of p0, partition.strs mustn't change, because it, unlike its elements, wasn't aliased */ - nn_plist_unalias (&p0); + ddsi_plist_unalias (&p0); CU_ASSERT (p0.present == p0memcpy.present); CU_ASSERT (p0.aliased == 0); CU_ASSERT (p0.qos.present == p0memcpy.qos.present); @@ -111,9 +111,9 @@ CU_Test (ddsi_plist, unalias_copy_merge) memcpy (&p0memcpy, &p0, sizeof (p0)); /* copy an aliased one; the original must be unchanged, the copy unaliased */ - nn_plist_t p3; - nn_plist_init_empty (&p3); - nn_plist_copy (&p3, &p0); + ddsi_plist_t p3; + ddsi_plist_init_empty (&p3); + ddsi_plist_copy (&p3, &p0); CU_ASSERT (memcmp (&p0, &p0memcpy, sizeof (p0)) == 0); CU_ASSERT (p3.present == p0.present); CU_ASSERT (p3.aliased == 0); @@ -133,13 +133,13 @@ CU_Test (ddsi_plist, unalias_copy_merge) /* merge-in missing ones from an aliased copy: original must remain unchanged; existing ones should stay without touching "aliased" only new ones are added as unaliased ones */ - nn_plist_t p4, p4memcpy; - nn_plist_init_empty (&p4); + ddsi_plist_t p4, p4memcpy; + ddsi_plist_init_empty (&p4); p4.present = PP_ENTITY_NAME; p4.aliased = PP_ENTITY_NAME; p4.entity_name = "omen"; memcpy (&p4memcpy, &p4, sizeof (p4)); - nn_plist_mergein_missing (&p4, &p0, p0.present, p0.qos.present); + ddsi_plist_mergein_missing (&p4, &p0, p0.present, p0.qos.present); CU_ASSERT (memcmp (&p0, &p0memcpy, sizeof (p0)) == 0); CU_ASSERT (p4.present == p0.present); CU_ASSERT (p4.aliased == p4memcpy.aliased); @@ -156,9 +156,9 @@ CU_Test (ddsi_plist, unalias_copy_merge) CU_ASSERT_STRING_EQUAL (p4.qos.partition.strs[1], p0.qos.partition.strs[1]); CU_ASSERT_STRING_EQUAL (p4.qos.partition.strs[2], p0.qos.partition.strs[2]); - nn_plist_fini (&p0); - nn_plist_fini (&p1); - nn_plist_fini (&p2); - nn_plist_fini (&p3); - nn_plist_fini (&p4); + ddsi_plist_fini (&p0); + ddsi_plist_fini (&p1); + ddsi_plist_fini (&p2); + ddsi_plist_fini (&p3); + ddsi_plist_fini (&p4); } diff --git a/src/core/ddsi/tests/plist_generic.c b/src/core/ddsi/tests/plist_generic.c index 04c91d1..7c97b74 100644 --- a/src/core/ddsi/tests/plist_generic.c +++ b/src/core/ddsi/tests/plist_generic.c @@ -13,7 +13,7 @@ #include "CUnit/Theory.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/endian.h" -#include "dds/ddsi/q_xqos.h" +#include "dds/ddsi/ddsi_xqos.h" #include "dds/ddsi/ddsi_plist_generic.h" struct desc { diff --git a/src/core/xtests/rhc_torture/rhc_torture.c b/src/core/xtests/rhc_torture/rhc_torture.c index 5741f5f..b662b7a 100644 --- a/src/core/xtests/rhc_torture/rhc_torture.c +++ b/src/core/xtests/rhc_torture/rhc_torture.c @@ -176,8 +176,8 @@ static struct proxy_writer *mkwr (const struct ddsi_domaingv *gv, bool auto_disp xqos = ddsrt_malloc (sizeof (*xqos)); wr_iid = ddsi_iid_gen (); memset (pwr, 0, sizeof (*pwr)); - nn_xqos_init_empty (xqos); - nn_xqos_mergein_missing (xqos, &gv->default_xqos_wr, ~(uint64_t)0); + ddsi_xqos_init_empty (xqos); + ddsi_xqos_mergein_missing (xqos, &gv->default_xqos_wr, ~(uint64_t)0); xqos->ownership_strength.value = 0; xqos->writer_data_lifecycle.autodispose_unregistered_instances = auto_dispose; pwr->e.iid = wr_iid; @@ -195,12 +195,12 @@ static struct dds_rhc *mkrhc (struct ddsi_domaingv *gv, dds_reader *rd, dds_hist { struct dds_rhc *rhc; dds_qos_t rqos; - nn_xqos_init_empty (&rqos); + ddsi_xqos_init_empty (&rqos); rqos.present |= QP_HISTORY | QP_DESTINATION_ORDER; rqos.history.kind = hk; rqos.history.depth = hdepth; rqos.destination_order.kind = dok; - nn_xqos_mergein_missing (&rqos, &gv->default_xqos_rd, ~(uint64_t)0); + ddsi_xqos_mergein_missing (&rqos, &gv->default_xqos_rd, ~(uint64_t)0); thread_state_awake_domain_ok (lookup_thread_state ()); rhc = dds_rhc_default_new_xchecks (rd, gv, mdtopic, true); dds_rhc_set_qos(rhc, &rqos); diff --git a/src/mpt/tests/qos/procs/rw.c b/src/mpt/tests/qos/procs/rw.c index d1e6e26..14889cf 100644 --- a/src/mpt/tests/qos/procs/rw.c +++ b/src/mpt/tests/qos/procs/rw.c @@ -23,7 +23,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" -#include "dds/ddsi/q_xqos.h" +#include "dds/ddsi/ddsi_xqos.h" #include "rwdata.h" #include "rw.h" @@ -140,14 +140,14 @@ static bool pubsub_qos_eq_h (const dds_qos_t *a, dds_entity_t ent) dds_get_qos (ent, b); /* internal interface is more luxurious that a simple compare for equality, and using that here saves us a ton of code */ - uint64_t delta = nn_xqos_delta (a, b, QP_GROUP_DATA | QP_PRESENTATION | QP_PARTITION); + uint64_t delta = ddsi_xqos_delta (a, b, QP_GROUP_DATA | QP_PRESENTATION | QP_PARTITION); if (delta) { struct ddsrt_log_cfg logcfg; dds_log_cfg_init (&logcfg, 0, DDS_LC_ERROR, stderr, stderr); DDS_CLOG (DDS_LC_ERROR, &logcfg, "pub/sub: delta = %"PRIx64"\n", delta); - nn_xqos_log (DDS_LC_ERROR, &logcfg, a); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); - nn_xqos_log (DDS_LC_ERROR, &logcfg, b); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + ddsi_xqos_log (DDS_LC_ERROR, &logcfg, a); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + ddsi_xqos_log (DDS_LC_ERROR, &logcfg, b); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); } dds_delete_qos (b); return delta == 0; @@ -155,7 +155,7 @@ static bool pubsub_qos_eq_h (const dds_qos_t *a, dds_entity_t ent) static uint64_t reader_qos_delta (const dds_qos_t *a, const dds_qos_t *b) { - return nn_xqos_delta (a, b, QP_USER_DATA | QP_TOPIC_DATA | QP_GROUP_DATA | QP_DURABILITY | QP_HISTORY | QP_RESOURCE_LIMITS | QP_PRESENTATION | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_LIVELINESS | QP_TIME_BASED_FILTER | QP_PARTITION | QP_RELIABILITY | QP_DESTINATION_ORDER | QP_PRISMTECH_READER_DATA_LIFECYCLE); + return ddsi_xqos_delta (a, b, QP_USER_DATA | QP_TOPIC_DATA | QP_GROUP_DATA | QP_DURABILITY | QP_HISTORY | QP_RESOURCE_LIMITS | QP_PRESENTATION | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_LIVELINESS | QP_TIME_BASED_FILTER | QP_PARTITION | QP_RELIABILITY | QP_DESTINATION_ORDER | QP_PRISMTECH_READER_DATA_LIFECYCLE); } static bool reader_qos_eq_h (const dds_qos_t *a, dds_entity_t ent) @@ -168,8 +168,8 @@ static bool reader_qos_eq_h (const dds_qos_t *a, dds_entity_t ent) struct ddsrt_log_cfg logcfg; dds_log_cfg_init (&logcfg, 0, DDS_LC_ERROR, stderr, stderr); DDS_CLOG (DDS_LC_ERROR, &logcfg, "reader: delta = %"PRIx64"\n", delta); - nn_xqos_log (DDS_LC_ERROR, &logcfg, a); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); - nn_xqos_log (DDS_LC_ERROR, &logcfg, b); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + ddsi_xqos_log (DDS_LC_ERROR, &logcfg, a); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + ddsi_xqos_log (DDS_LC_ERROR, &logcfg, b); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); } dds_delete_qos (b); return delta == 0; @@ -177,7 +177,7 @@ static bool reader_qos_eq_h (const dds_qos_t *a, dds_entity_t ent) static uint64_t writer_qos_delta (const dds_qos_t *a, const dds_qos_t *b) { - return nn_xqos_delta (a, b, QP_USER_DATA | QP_TOPIC_DATA | QP_GROUP_DATA | QP_DURABILITY | QP_HISTORY | QP_RESOURCE_LIMITS | QP_PRESENTATION | QP_LIFESPAN | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_OWNERSHIP_STRENGTH | QP_LIVELINESS | QP_PARTITION | QP_RELIABILITY | QP_DESTINATION_ORDER | QP_PRISMTECH_WRITER_DATA_LIFECYCLE); + return ddsi_xqos_delta (a, b, QP_USER_DATA | QP_TOPIC_DATA | QP_GROUP_DATA | QP_DURABILITY | QP_HISTORY | QP_RESOURCE_LIMITS | QP_PRESENTATION | QP_LIFESPAN | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_OWNERSHIP_STRENGTH | QP_LIVELINESS | QP_PARTITION | QP_RELIABILITY | QP_DESTINATION_ORDER | QP_PRISMTECH_WRITER_DATA_LIFECYCLE); } static bool writer_qos_eq_h (const dds_qos_t *a, dds_entity_t ent) @@ -190,8 +190,8 @@ static bool writer_qos_eq_h (const dds_qos_t *a, dds_entity_t ent) struct ddsrt_log_cfg logcfg; dds_log_cfg_init (&logcfg, 0, DDS_LC_ERROR, stderr, stderr); DDS_CLOG (DDS_LC_ERROR, &logcfg, "writer: delta = %"PRIx64"\n", delta); - nn_xqos_log (DDS_LC_ERROR, &logcfg, a); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); - nn_xqos_log (DDS_LC_ERROR, &logcfg, b); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + ddsi_xqos_log (DDS_LC_ERROR, &logcfg, a); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + ddsi_xqos_log (DDS_LC_ERROR, &logcfg, b); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); } dds_delete_qos (b); return delta == 0; @@ -275,8 +275,8 @@ MPT_ProcessEntry (rw_publisher, struct ddsrt_log_cfg logcfg; dds_log_cfg_init (&logcfg, 0, DDS_LC_ERROR, stderr, stderr); DDS_CLOG (DDS_LC_ERROR, &logcfg, "matched reader: delta = %"PRIx64"\n", delta); - nn_xqos_log (DDS_LC_ERROR, &logcfg, qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); - nn_xqos_log (DDS_LC_ERROR, &logcfg, ep->qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + ddsi_xqos_log (DDS_LC_ERROR, &logcfg, qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + ddsi_xqos_log (DDS_LC_ERROR, &logcfg, ep->qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); } MPT_ASSERT (delta == 0, "writer %zu %zu matched reader QoS mismatch\n", i, j); dds_delete_qos (ep->qos); @@ -427,8 +427,8 @@ MPT_ProcessEntry (rw_subscriber, struct ddsrt_log_cfg logcfg; dds_log_cfg_init (&logcfg, 0, DDS_LC_ERROR, stderr, stderr); DDS_CLOG (DDS_LC_ERROR, &logcfg, "matched writer: delta = %"PRIx64"\n", delta); - nn_xqos_log (DDS_LC_ERROR, &logcfg, qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); - nn_xqos_log (DDS_LC_ERROR, &logcfg, ep->qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + ddsi_xqos_log (DDS_LC_ERROR, &logcfg, qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); + ddsi_xqos_log (DDS_LC_ERROR, &logcfg, ep->qos); DDS_CLOG (DDS_LC_ERROR, &logcfg, "\n"); } MPT_ASSERT (delta == 0, "reader %zu %zu matched writer QoS mismatch\n", i, j); dds_delete_qos (ep->qos); From ab7c95e02f686667914bf802876be23676778c02 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 4 Feb 2020 15:34:34 +0100 Subject: [PATCH 27/28] Clean up sertopic_default definition Signed-off-by: Erik Boasson --- src/core/ddsc/CMakeLists.txt | 2 - src/core/ddsc/src/dds__alloc.h | 2 - src/core/ddsc/src/dds__serdata_builtintopic.h | 6 +- src/core/ddsc/src/dds_alloc.c | 289 +------------- src/core/ddsc/src/dds_serdata_builtintopic.c | 1 - src/core/ddsc/src/dds_sertopic_builtintopic.c | 2 +- src/core/ddsc/src/dds_topic.c | 18 +- src/core/ddsc/src/dds_write.c | 2 +- src/core/ddsc/tests/multi_sertopic.c | 1 - src/core/ddsi/CMakeLists.txt | 2 + .../include/dds/ddsi/ddsi_cdrstream.h} | 8 +- .../include/dds/ddsi/ddsi_serdata_default.h | 38 +- .../ddsi/include/dds/ddsi/ddsi_sertopic.h | 1 - .../src/ddsi_cdrstream.c} | 375 ++++++++++++++++-- src/core/ddsi/src/ddsi_serdata_default.c | 6 +- src/core/ddsi/src/ddsi_sertopic.c | 10 +- src/core/ddsi/src/ddsi_sertopic_default.c | 50 ++- src/core/ddsi/src/ddsi_tkmap.c | 4 +- src/core/ddsi/src/q_init.c | 1 - src/core/ddsi/src/q_receive.c | 2 +- src/core/xtests/cdrtest/CMakeLists.txt | 2 + src/core/xtests/cdrtest/cdrtest.pl | 12 +- 22 files changed, 454 insertions(+), 380 deletions(-) rename src/core/{ddsc/src/dds__stream.h => ddsi/include/dds/ddsi/ddsi_cdrstream.h} (94%) rename src/core/{ddsc/src/dds_stream.c => ddsi/src/ddsi_cdrstream.c} (85%) diff --git a/src/core/ddsc/CMakeLists.txt b/src/core/ddsc/CMakeLists.txt index 65c6c34..d5bae0c 100644 --- a/src/core/ddsc/CMakeLists.txt +++ b/src/core/ddsc/CMakeLists.txt @@ -30,7 +30,6 @@ PREPEND(srcs_ddsc "${CMAKE_CURRENT_LIST_DIR}/src" dds_topic.c dds_listener.c dds_read.c - dds_stream.c dds_waitset.c dds_readcond.c dds_guardcond.c @@ -70,7 +69,6 @@ PREPEND(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src" dds__guardcond.h dds__reader.h dds__rhc_default.h - dds__stream.h dds__subscriber.h dds__topic.h dds__types.h diff --git a/src/core/ddsc/src/dds__alloc.h b/src/core/ddsc/src/dds__alloc.h index a8f09db..10eadcf 100644 --- a/src/core/ddsc/src/dds__alloc.h +++ b/src/core/ddsc/src/dds__alloc.h @@ -18,8 +18,6 @@ extern "C" { #endif -void dds_sample_free_contents (char * data, const uint32_t * ops); - #if defined (__cplusplus) } #endif diff --git a/src/core/ddsc/src/dds__serdata_builtintopic.h b/src/core/ddsc/src/dds__serdata_builtintopic.h index 60fdec0..52509f2 100644 --- a/src/core/ddsc/src/dds__serdata_builtintopic.h +++ b/src/core/ddsc/src/dds__serdata_builtintopic.h @@ -9,9 +9,10 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef DDSI_SERDATA_BUILTINTOPIC_H -#define DDSI_SERDATA_BUILTINTOPIC_H +#ifndef DDS__SERDATA_BUILTINTOPIC_H +#define DDS__SERDATA_BUILTINTOPIC_H +#include "dds/dds.h" #include "dds/ddsi/ddsi_xqos.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_sertopic.h" @@ -33,7 +34,6 @@ enum ddsi_sertopic_builtintopic_type { DSBT_WRITER }; -struct ddsi_domaingv; struct ddsi_sertopic_builtintopic { struct ddsi_sertopic c; enum ddsi_sertopic_builtintopic_type type; diff --git a/src/core/ddsc/src/dds_alloc.c b/src/core/ddsc/src/dds_alloc.c index 7ff7779..662719d 100644 --- a/src/core/ddsc/src/dds_alloc.c +++ b/src/core/ddsc/src/dds_alloc.c @@ -13,21 +13,9 @@ #include #include "dds__alloc.h" -#include "dds__stream.h" #include "dds/ddsrt/heap.h" #include "dds/ddsi/q_config.h" - -/* -#define OP_DEBUG_FREE 1 -*/ - -#if defined OP_DEBUG_FREE -static const char * stream_op_type[11] = -{ - NULL, "1Byte", "2Byte", "4Byte", "8Byte", "String", - "BString", "Sequence", "Array", "Union", "Struct" -}; -#endif +#include "dds/ddsi/ddsi_cdrstream.h" static dds_allocator_t dds_allocator_fns = { ddsrt_malloc, ddsrt_realloc, ddsrt_free }; @@ -87,287 +75,30 @@ void dds_string_free (char * str) dds_free (str); } -void dds_sample_free_contents (char *data, const uint32_t * ops) +static void dds_sample_free_key (void *vsample, const struct dds_topic_descriptor * desc) { - uint32_t op; - uint32_t type; - uint32_t num; - uint32_t subtype; - char * addr; - - while ((op = *ops) != DDS_OP_RTS) + char *sample = vsample; + for (uint32_t i = 0; i < desc->m_nkeys; i++) { - switch (DDS_OP_MASK & op) - { - case DDS_OP_ADR: - { - type = DDS_OP_TYPE (op); -#ifdef OP_DEBUG_FREE - DDS_TRACE("F-ADR: %s offset %d\n", stream_op_type[type], ops[1]); -#endif - addr = data + ops[1]; - ops += 2; - switch (type) - { - case DDS_OP_VAL_1BY: - case DDS_OP_VAL_2BY: - case DDS_OP_VAL_4BY: - case DDS_OP_VAL_8BY: - { - break; - } - case DDS_OP_VAL_STR: - { -#ifdef OP_DEBUG_FREE - DDS_TRACE("F-STR: @ %p %s\n", addr, *((char**) addr)); -#endif - dds_free (*((char**) addr)); - *((char**) addr) = NULL; - break; - } - case DDS_OP_VAL_SEQ: - { - dds_sequence_t * seq = (dds_sequence_t*) addr; - subtype = DDS_OP_SUBTYPE (op); - num = (seq->_maximum > seq->_length) ? seq->_maximum : seq->_length; - -#ifdef OP_DEBUG_FREE - DDS_TRACE("F-SEQ: of %s\n", stream_op_type[subtype]); -#endif - if ((seq->_release && num) || (subtype > DDS_OP_VAL_STR)) - { - switch (subtype) - { - case DDS_OP_VAL_1BY: - case DDS_OP_VAL_2BY: - case DDS_OP_VAL_4BY: - case DDS_OP_VAL_8BY: - { - break; - } - case DDS_OP_VAL_BST: - { - ops++; - break; - } - case DDS_OP_VAL_STR: - { - char ** ptr = (char**) seq->_buffer; - while (num--) - { - dds_free (*ptr++); - } - break; - } - default: - { - const uint32_t elem_size = *ops++; - const uint32_t * jsr_ops = ops + DDS_OP_ADR_JSR (*ops) - 3; - const uint32_t jmp = DDS_OP_ADR_JMP (*ops); - char * ptr = (char*) seq->_buffer; - - while (num--) - { - dds_sample_free_contents (ptr, jsr_ops); - ptr += elem_size; - } - ops += jmp ? (jmp - 3) : 1; - break; - } - } - } - if (seq->_release) - { - dds_free (seq->_buffer); - seq->_maximum = 0; - seq->_length = 0; - seq->_buffer = NULL; - } - break; - } - case DDS_OP_VAL_ARR: - { - subtype = DDS_OP_SUBTYPE (op); - num = *ops++; - -#ifdef OP_DEBUG_FREE - DDS_TRACE("F-ARR: of %s size %d\n", stream_op_type[subtype], num); -#endif - switch (subtype) - { - case DDS_OP_VAL_1BY: - case DDS_OP_VAL_2BY: - case DDS_OP_VAL_4BY: - case DDS_OP_VAL_8BY: - { - break; - } - case DDS_OP_VAL_STR: - { - char ** ptr = (char**) addr; - while (num--) - { - dds_free (*ptr++); - } - break; - } - case DDS_OP_VAL_BST: - { - ops += 2; - break; - } - default: - { - const uint32_t * jsr_ops = ops + DDS_OP_ADR_JSR (*ops) - 3; - const uint32_t jmp = DDS_OP_ADR_JMP (*ops); - const uint32_t elem_size = ops[1]; - - while (num--) - { - dds_sample_free_contents (addr, jsr_ops); - addr += elem_size; - } - ops += jmp ? (jmp - 3) : 2; - break; - } - } - break; - } - case DDS_OP_VAL_UNI: - { - const bool has_default = op & DDS_OP_FLAG_DEF; - subtype = DDS_OP_SUBTYPE (op); - num = ops[0]; - const uint32_t * jeq_op = ops + DDS_OP_ADR_JSR (ops[1]) - 2; - uint32_t disc = 0; - - assert (subtype <= DDS_OP_VAL_4BY); - -#ifdef OP_DEBUG_FREE - DDS_TRACE("F-UNI: switch %s cases %d\n", stream_op_type[subtype], num); -#endif - /* Get discriminant */ - - switch (subtype) - { - case DDS_OP_VAL_1BY: - { - disc = *((uint8_t*) addr); - break; - } - case DDS_OP_VAL_2BY: - { - disc = *((uint16_t*) addr); - break; - } - case DDS_OP_VAL_4BY: - { - disc = *((uint32_t*) addr); - break; - } - default: assert (0); - } - - /* Free case matching discriminant */ - - while (num--) - { - assert ((DDS_OP_MASK & jeq_op[0]) == DDS_OP_JEQ); - if ((jeq_op[1] == disc) || (has_default && (num == 0))) - { - subtype = DDS_JEQ_TYPE (jeq_op[0]); - addr = data + jeq_op[2]; - - switch (subtype) - { - case DDS_OP_VAL_1BY: - case DDS_OP_VAL_2BY: - case DDS_OP_VAL_4BY: - case DDS_OP_VAL_8BY: - case DDS_OP_VAL_BST: - { - break; - } - case DDS_OP_VAL_STR: - { - dds_free (*((char**) addr)); - *((char**) addr) = NULL; - break; - } - default: - { - dds_sample_free_contents (addr, jeq_op + DDS_OP_ADR_JSR (jeq_op[0])); - break; - } - } - break; - } - jeq_op += 3; - } - - /* Jump to next instruction */ - - ops += DDS_OP_ADR_JMP (ops[1]) - 2; - break; - } - case DDS_OP_VAL_BST: - { - ops++; - break; - } - default: assert (0); - } - break; - } - case DDS_OP_JSR: /* Implies nested type */ - { -#ifdef OP_DEBUG_FREE - DDS_TRACE("F-JSR: %d\n", DDS_OP_JUMP (op)); -#endif - dds_sample_free_contents (data, ops + DDS_OP_JUMP (op)); - ops++; - break; - } - default: assert (0); - } - } -#ifdef OP_DEBUG_FREE - DDS_TRACE("F-RTS:\n"); -#endif -} - -static void dds_sample_free_key (char * sample, const struct dds_topic_descriptor * desc) -{ - uint32_t i; - const uint32_t * op; - - for (i = 0; i < desc->m_nkeys; i++) - { - op = desc->m_ops + desc->m_keys[i].m_index; + const uint32_t *op = desc->m_ops + desc->m_keys[i].m_index; if (DDS_OP_TYPE (*op) == DDS_OP_VAL_STR) - { - dds_free (*(char**)(sample + op[1])); - } + dds_free (*(char **) (sample + op[1])); } } void dds_sample_free (void * sample, const struct dds_topic_descriptor * desc, dds_free_op_t op) { + /* external API, so can't replace the dds_topic_decsriptor type ... */ assert (desc); if (sample) { if (op & DDS_FREE_CONTENTS_BIT) - { - dds_sample_free_contents ((char*) sample, desc->m_ops); - } + dds_stream_free_sample (sample, desc->m_ops); else if (op & DDS_FREE_KEY_BIT) - { - dds_sample_free_key ((char*) sample, desc); - } + dds_sample_free_key (sample, desc); + if (op & DDS_FREE_ALL_BIT) - { dds_free (sample); - } } } diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index 4e19675..042d542 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -20,7 +20,6 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" #include "dds/ddsi/ddsi_plist.h" -#include "dds__stream.h" #include "dds__serdata_builtintopic.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/q_entity.h" diff --git a/src/core/ddsc/src/dds_sertopic_builtintopic.c b/src/core/ddsc/src/dds_sertopic_builtintopic.c index c5ace24..6c9b843 100644 --- a/src/core/ddsc/src/dds_sertopic_builtintopic.c +++ b/src/core/ddsc/src/dds_sertopic_builtintopic.c @@ -49,7 +49,7 @@ static bool sertopic_builtin_equal (const struct ddsi_sertopic *acmn, const stru static uint32_t sertopic_builtin_hash (const struct ddsi_sertopic *tpcmn) { const struct ddsi_sertopic_builtintopic *tp = (struct ddsi_sertopic_builtintopic *) tpcmn; - return tp->type; + return (uint32_t) tp->type; } static void free_pp (void *vsample) diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 13a2f45..93db04a 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -19,7 +19,6 @@ #include "dds__topic.h" #include "dds__listener.h" #include "dds__participant.h" -#include "dds__stream.h" #include "dds__init.h" #include "dds__domain.h" #include "dds__get_status.h" @@ -32,6 +31,7 @@ #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/ddsi_domaingv.h" +#include "dds/ddsi/ddsi_cdrstream.h" #include "dds__serdata_builtintopic.h" DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_topic) @@ -399,13 +399,19 @@ dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descrip ddsi_sertopic_init (&st->c, name, desc->m_typename, &ddsi_sertopic_ops_default, desc->m_nkeys ? &ddsi_serdata_ops_cdr : &ddsi_serdata_ops_cdr_nokey, (desc->m_nkeys == 0)); st->native_encoding_identifier = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE); st->serpool = ppent->m_domain->gv.serpool; - st->type = (void*) desc; - st->nkeys = desc->m_nkeys; - st->keys = desc->m_keys; + st->type.m_size = desc->m_size; + st->type.m_align = desc->m_align; + st->type.m_flagset = desc->m_flagset; + st->type.m_nkeys = desc->m_nkeys; + st->type.m_keys = ddsrt_malloc (st->type.m_nkeys * sizeof (*st->type.m_keys)); + for (uint32_t i = 0; i < st->type.m_nkeys; i++) + st->type.m_keys[i] = desc->m_keys[i].m_index; + st->type.m_nops = dds_stream_countops (desc->m_ops); + st->type.m_ops = ddsrt_memdup (desc->m_ops, st->type.m_nops * sizeof (*st->type.m_ops)); /* Check if topic cannot be optimised (memcpy marshal) */ - if (!(desc->m_flagset & DDS_TOPIC_NO_OPTIMIZE)) { - st->opt_size = dds_stream_check_optimize (desc); + if (!(st->type.m_flagset & DDS_TOPIC_NO_OPTIMIZE)) { + st->opt_size = dds_stream_check_optimize (&st->type); DDS_CTRACE (&ppent->m_domain->gv.logconfig, "Marshalling for type: %s is %soptimised\n", desc->m_typename, st->opt_size ? "" : "not "); } diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 3ef2f74..7519548 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -18,7 +18,7 @@ #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/ddsi_rhc.h" #include "dds/ddsi/ddsi_serdata.h" -#include "dds__stream.h" +#include "dds/ddsi/ddsi_cdrstream.h" #include "dds/ddsi/q_transmit.h" #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/q_config.h" diff --git a/src/core/ddsc/tests/multi_sertopic.c b/src/core/ddsc/tests/multi_sertopic.c index 9501b27..1bbdfbf 100644 --- a/src/core/ddsc/tests/multi_sertopic.c +++ b/src/core/ddsc/tests/multi_sertopic.c @@ -125,7 +125,6 @@ static const dds_topic_descriptor_t type_uni_desc = DDS_OP_ADR | DDS_OP_TYPE_ARR | DDS_OP_SUBTYPE_4BY, 0u, 4, DDS_OP_RTS, DDS_OP_RTS - }, .m_meta = "" /* this is on its way out anyway */ }; diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 0fe18ef..87b9c47 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -33,6 +33,7 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" ddsi_deadline.c ddsi_deliver_locally.c ddsi_plist.c + ddsi_cdrstream.c q_addrset.c q_bitset_inlines.c q_bswap.c @@ -97,6 +98,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" ddsi_domaingv.h ddsi_plist.h ddsi_xqos.h + ddsi_cdrstream.h q_addrset.h q_bitset.h q_bswap.h diff --git a/src/core/ddsc/src/dds__stream.h b/src/core/ddsi/include/dds/ddsi/ddsi_cdrstream.h similarity index 94% rename from src/core/ddsc/src/dds__stream.h rename to src/core/ddsi/include/dds/ddsi/ddsi_cdrstream.h index 7facf45..56ad225 100644 --- a/src/core/ddsc/src/dds__stream.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_cdrstream.h @@ -9,8 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef _DDS_STREAM_H_ -#define _DDS_STREAM_H_ +#ifndef DDSI_CDRSTREAM_H +#define DDSI_CDRSTREAM_H #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_serdata_default.h" @@ -44,8 +44,10 @@ bool dds_stream_normalize (void * __restrict data, uint32_t size, bool bswap, co void dds_stream_write_sample (dds_ostream_t * __restrict os, const void * __restrict data, const struct ddsi_sertopic_default * __restrict topic); void dds_stream_read_sample (dds_istream_t * __restrict is, void * __restrict data, const struct ddsi_sertopic_default * __restrict topic); +void dds_stream_free_sample (void *data, const uint32_t * ops); -size_t dds_stream_check_optimize (const dds_topic_descriptor_t * __restrict desc); +uint32_t dds_stream_countops (const uint32_t * __restrict ops); +size_t dds_stream_check_optimize (const struct ddsi_sertopic_default_desc * __restrict desc); void dds_istream_from_serdata_default (dds_istream_t * __restrict s, const struct ddsi_serdata_default * __restrict d); void dds_ostream_from_serdata_default (dds_ostream_t * __restrict s, struct ddsi_serdata_default * __restrict d); void dds_ostream_add_to_serdata_default (dds_ostream_t * __restrict s, struct ddsi_serdata_default ** __restrict d); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h index ae582ff..27a155b 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -20,7 +20,6 @@ #include "dds/ddsi/ddsi_sertopic.h" #include "dds/dds.h" -#include "dds__topic.h" #if defined (__cplusplus) extern "C" { @@ -95,41 +94,28 @@ struct ddsi_serdata_default { #undef DDSI_SERDATA_DEFAULT_PREPAD #undef DDSI_SERDATA_DEFAULT_FIXED_FIELD -struct dds_key_descriptor; -struct dds_topic_descriptor; - #ifndef DDS_TOPIC_INTERN_FILTER_FN_DEFINED #define DDS_TOPIC_INTERN_FILTER_FN_DEFINED typedef bool (*dds_topic_intern_filter_fn) (const void * sample, void *ctx); #endif +/* Reduced version of dds_topic_descriptor_t */ +struct ddsi_sertopic_default_desc { + uint32_t m_size; /* Size of topic type */ + uint32_t m_align; /* Alignment of topic type */ + uint32_t m_flagset; /* Flags */ + uint32_t m_nkeys; /* Number of keys (can be 0) */ + uint32_t *m_keys; /* Key descriptors (NULL iff m_nkeys 0) */ + uint32_t m_nops; /* Number of words in m_ops (which >= number of ops stored in preproc output) */ + uint32_t *m_ops; /* Marshalling meta data */ +}; + struct ddsi_sertopic_default { struct ddsi_sertopic c; uint16_t native_encoding_identifier; /* (PL_)?CDR_(LE|BE) */ struct serdatapool *serpool; - - struct dds_topic_descriptor * type; - unsigned nkeys; - - uint32_t flags; + struct ddsi_sertopic_default_desc type; size_t opt_size; - dds_topic_intern_filter_fn filter_fn; - void * filter_sample; - void * filter_ctx; - const struct dds_key_descriptor * keys; - - /* - Array of keys, represented as offset in the OpenSplice internal - format data blob. Keys must be stored in the order visited by - serializer (so that the serializer can simply compare the current - offset with the next key offset). Also: keys[nkeys].off =def= - ~0u, which won't equal any real offset so that there is no need - to test for the end of the array. - - Offsets work 'cos only primitive types, enums and strings are - accepted as keys. So there is no ambiguity if a key happens to - be inside a nested struct. - */ }; struct ddsi_plist_sample { diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h index 7713af3..f259c02 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h @@ -32,7 +32,6 @@ struct ddsi_sertopic { bool topickind_no_key; char *name; char *type_name; - uint64_t iid; struct ddsi_domaingv *gv; ddsrt_atomic_uint32_t refc; /* counts refs from entities (topic, reader, writer), not from data */ }; diff --git a/src/core/ddsc/src/dds_stream.c b/src/core/ddsi/src/ddsi_cdrstream.c similarity index 85% rename from src/core/ddsc/src/dds_stream.c rename to src/core/ddsi/src/ddsi_cdrstream.c index a6a9218..9fffea9 100644 --- a/src/core/ddsc/src/dds_stream.c +++ b/src/core/ddsi/src/ddsi_cdrstream.c @@ -18,7 +18,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" -#include "dds__stream.h" +#include "dds/ddsi/ddsi_cdrstream.h" #include "dds__alloc.h" #if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN @@ -210,7 +210,7 @@ static uint32_t get_type_size (enum dds_stream_typecode type) return (uint32_t)1 << ((uint32_t) type - 1); } -static size_t dds_stream_check_optimize1 (const dds_topic_descriptor_t * __restrict desc) +static size_t dds_stream_check_optimize1 (const struct ddsi_sertopic_default_desc * __restrict desc) { const uint32_t *ops = desc->m_ops; uint32_t insn; @@ -251,11 +251,141 @@ static size_t dds_stream_check_optimize1 (const dds_topic_descriptor_t * __restr return desc->m_size; } -size_t dds_stream_check_optimize (const dds_topic_descriptor_t * __restrict desc) +size_t dds_stream_check_optimize (const struct ddsi_sertopic_default_desc * __restrict desc) { return dds_stream_check_optimize1 (desc); } +static void dds_stream_countops1 (const uint32_t * __restrict ops, const uint32_t **ops_end); + +static const uint32_t *dds_stream_countops_seq (const uint32_t * __restrict ops, uint32_t insn, const uint32_t **ops_end) +{ + const enum dds_stream_typecode subtype = DDS_OP_SUBTYPE (insn); + switch (subtype) + { + 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: + ops += 2; + break; + case DDS_OP_VAL_BST: + ops += 3; + break; + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { + const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]); + uint32_t const * const jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]); + if (ops + 4 > *ops_end) + *ops_end = ops + 4; + dds_stream_countops1 (jsr_ops, ops_end); + ops += (jmp ? jmp : 4); /* FIXME: why would jmp be 0? */ + } + } + if (ops > *ops_end) + *ops_end = ops; + return ops; +} + +static const uint32_t *dds_stream_countops_arr (const uint32_t * __restrict ops, uint32_t insn, const uint32_t **ops_end) +{ + const enum dds_stream_typecode subtype = DDS_OP_SUBTYPE (insn); + switch (subtype) + { + 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: + ops += 3; + break; + case DDS_OP_VAL_BST: + ops += 5; + break; + 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]); + const uint32_t *jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]); + if (ops + 5 > *ops_end) + *ops_end = ops + 5; + dds_stream_countops1 (jsr_ops, ops_end); + ops += (jmp ? jmp : 5); + break; + } + } + if (ops > *ops_end) + *ops_end = ops; + return ops; +} + +static const uint32_t *dds_stream_countops_uni (const uint32_t * __restrict ops, const uint32_t **ops_end) +{ + const uint32_t numcases = ops[2]; + const uint32_t *jeq_op = ops + DDS_OP_ADR_JSR (ops[3]); + for (uint32_t i = 0; i < numcases; i++) + { + const enum dds_stream_typecode valtype = DDS_JEQ_TYPE (jeq_op[0]); + switch (valtype) + { + case DDS_OP_VAL_1BY: + case DDS_OP_VAL_2BY: + case DDS_OP_VAL_4BY: + case DDS_OP_VAL_8BY: + case DDS_OP_VAL_STR: + 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_countops1 (jeq_op + DDS_OP_ADR_JSR (jeq_op[0]), ops_end); + break; + } + jeq_op += 3; + } + if (jeq_op > *ops_end) + *ops_end = jeq_op; + ops += DDS_OP_ADR_JMP (ops[3]); + if (ops > *ops_end) + *ops_end = ops; + return ops; +} + +static void dds_stream_countops1 (const uint32_t * __restrict ops, const uint32_t **ops_end) +{ + uint32_t insn; + while ((insn = *ops) != DDS_OP_RTS) + { + switch (DDS_OP (insn)) + { + case DDS_OP_ADR: { + switch (DDS_OP_TYPE (insn)) + { + case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_STR: + ops += 2; + break; + case DDS_OP_VAL_BST: + ops += 3; + break; + case DDS_OP_VAL_SEQ: ops = dds_stream_countops_seq (ops, insn, ops_end); break; + case DDS_OP_VAL_ARR: ops = dds_stream_countops_arr (ops, insn, ops_end); break; + case DDS_OP_VAL_UNI: ops = dds_stream_countops_uni (ops, ops_end); break; + case DDS_OP_VAL_STU: abort (); break; + } + break; + } + case DDS_OP_JSR: { + dds_stream_countops1 (ops + DDS_OP_JUMP (insn), ops_end); + ops++; + break; + } + case DDS_OP_RTS: case DDS_OP_JEQ: { + abort (); + break; + } + } + } + ++ops; /* skip RTS op */ + if (ops > *ops_end) + *ops_end = ops; +} + +uint32_t dds_stream_countops (const uint32_t * __restrict ops) +{ + const uint32_t *ops_end = ops; + dds_stream_countops1 (ops, &ops_end); + return (uint32_t) (ops_end - ops); +} + 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); @@ -1039,12 +1169,12 @@ static bool stream_normalize (char * __restrict data, uint32_t * __restrict off, return true; } -static bool stream_normalize_key (void * __restrict data, uint32_t size, bool bswap, const struct dds_topic_descriptor * __restrict desc) +static bool stream_normalize_key (void * __restrict data, uint32_t size, bool bswap, const struct ddsi_sertopic_default_desc * __restrict desc) { uint32_t off = 0; for (uint32_t i = 0; i < desc->m_nkeys; i++) { - const uint32_t *op = desc->m_ops + desc->m_keys[i].m_index; + const uint32_t *op = desc->m_ops + desc->m_keys[i]; assert (insn_key_ok_p (*op)); switch (DDS_OP_TYPE (*op)) { @@ -1068,14 +1198,211 @@ bool dds_stream_normalize (void * __restrict data, uint32_t size, bool bswap, co if (size > CDR_SIZE_MAX) return false; if (just_key) - return stream_normalize_key (data, size, bswap, topic->type); + return stream_normalize_key (data, size, bswap, &topic->type); else { uint32_t off = 0; - return stream_normalize (data, &off, size, bswap, topic->type->m_ops); + return stream_normalize (data, &off, size, bswap, topic->type.m_ops); } } +/******************************************************************************************* + ** + ** Freeing samples + ** + *******************************************************************************************/ + +//#define OP_DEBUG_FREE 1 +void dds_stream_free_sample (void *vdata, const uint32_t * ops) +{ +#if defined OP_DEBUG_FREE + static const char *stream_op_type[11] = { + NULL, "1Byte", "2Byte", "4Byte", "8Byte", "String", "BString", "Sequence", "Array", "Union", "Struct" + }; +#endif + char *data = vdata; + uint32_t op; + uint32_t type; + uint32_t num; + uint32_t subtype; + char *addr; + while ((op = *ops) != DDS_OP_RTS) + { + switch (DDS_OP_MASK & op) + { + case DDS_OP_ADR: + { + type = DDS_OP_TYPE (op); +#ifdef OP_DEBUG_FREE + DDS_TRACE("F-ADR: %s offset %d\n", stream_op_type[type], ops[1]); +#endif + addr = data + ops[1]; + switch (type) + { + case DDS_OP_VAL_1BY: + case DDS_OP_VAL_2BY: + case DDS_OP_VAL_4BY: + case DDS_OP_VAL_8BY: + ops += 2; + break; + case DDS_OP_VAL_STR: +#ifdef OP_DEBUG_FREE + DDS_TRACE("F-STR: @ %p %s\n", addr, *((char **) addr)); +#endif + ops += 2; + dds_free (*((char **) addr)); + *((char **) addr) = NULL; + break; + case DDS_OP_VAL_SEQ: { + dds_sequence_t * seq = (dds_sequence_t *) addr; + ops += 2; + subtype = DDS_OP_SUBTYPE (op); + num = (seq->_maximum > seq->_length) ? seq->_maximum : seq->_length; +#ifdef OP_DEBUG_FREE + DDS_TRACE("F-SEQ: of %s\n", stream_op_type[subtype]); +#endif + if ((seq->_release && num) || (subtype > DDS_OP_VAL_STR)) + { + switch (subtype) + { + case DDS_OP_VAL_1BY: + case DDS_OP_VAL_2BY: + case DDS_OP_VAL_4BY: + case DDS_OP_VAL_8BY: + break; + case DDS_OP_VAL_BST: + ops++; + break; + case DDS_OP_VAL_STR: { + char **ptr = (char **) seq->_buffer; + while (num--) + dds_free (*ptr++); + break; + } + default: { + const uint32_t elem_size = *ops++; + const uint32_t *jsr_ops = ops + DDS_OP_ADR_JSR (*ops) - 3; + const uint32_t jmp = DDS_OP_ADR_JMP (*ops); + char *ptr = (char *) seq->_buffer; + while (num--) + { + dds_stream_free_sample (ptr, jsr_ops); + ptr += elem_size; + } + ops += jmp ? (jmp - 3) : 1; + break; + } + } + } + if (seq->_release) + { + dds_free (seq->_buffer); + seq->_maximum = 0; + seq->_length = 0; + seq->_buffer = NULL; + } + break; + } + case DDS_OP_VAL_ARR: { + ops += 2; + subtype = DDS_OP_SUBTYPE (op); + num = *ops++; +#ifdef OP_DEBUG_FREE + DDS_TRACE("F-ARR: of %s size %d\n", stream_op_type[subtype], num); +#endif + switch (subtype) + { + case DDS_OP_VAL_1BY: + case DDS_OP_VAL_2BY: + case DDS_OP_VAL_4BY: + case DDS_OP_VAL_8BY: + break; + case DDS_OP_VAL_STR: { + char **ptr = (char **) addr; + while (num--) + dds_free (*ptr++); + break; + } + case DDS_OP_VAL_BST: + ops += 2; + break; + default: { + const uint32_t *jsr_ops = ops + DDS_OP_ADR_JSR (*ops) - 3; + const uint32_t jmp = DDS_OP_ADR_JMP (*ops); + const uint32_t elem_size = ops[1]; + while (num--) + { + dds_stream_free_sample (addr, jsr_ops); + addr += elem_size; + } + ops += jmp ? (jmp - 3) : 2; + break; + } + } + break; + } + case DDS_OP_VAL_UNI: { +#ifdef OP_DEBUG_FREE + DDS_TRACE("F-UNI: switch %s\n", stream_op_type[subtype]); +#endif + /* Get discriminant */ + uint32_t disc = 0; + switch (DDS_OP_SUBTYPE (op)) + { + case DDS_OP_VAL_1BY: disc = *((uint8_t *) addr); break; + case DDS_OP_VAL_2BY: disc = *((uint16_t *) addr); break; + case DDS_OP_VAL_4BY: disc = *((uint32_t *) addr); break; + default: assert (0); + } + uint32_t const * const jeq_op = find_union_case (ops, disc); + ops += DDS_OP_ADR_JMP (ops[3]); + if (jeq_op) + { + subtype = DDS_JEQ_TYPE (jeq_op[0]); + addr = data + jeq_op[2]; + switch (subtype) + { + case DDS_OP_VAL_1BY: + case DDS_OP_VAL_2BY: + case DDS_OP_VAL_4BY: + case DDS_OP_VAL_8BY: + case DDS_OP_VAL_BST: + break; + case DDS_OP_VAL_STR: + dds_free (*((char **) addr)); + *((char **) addr) = NULL; + break; + default: + dds_stream_free_sample (addr, jeq_op + DDS_OP_ADR_JSR (jeq_op[0])); + break; + } + } + break; + } + case DDS_OP_VAL_BST: + ops += 3; + break; + default: + assert (0); + } + break; + } + case DDS_OP_JSR: /* Implies nested type */ +#ifdef OP_DEBUG_FREE + DDS_TRACE("F-JSR: %d\n", DDS_OP_JUMP (op)); +#endif + dds_stream_free_sample (data, ops + DDS_OP_JUMP (op)); + ops++; + break; + default: + assert (0); + } + } +#ifdef OP_DEBUG_FREE + DDS_TRACE("F-RTS:\n"); +#endif +} + /******************************************************************************************* ** ** Read/write of samples and keys -- i.e., DDSI payloads. @@ -1084,7 +1411,7 @@ bool dds_stream_normalize (void * __restrict data, uint32_t size, bool bswap, co void dds_stream_read_sample (dds_istream_t * __restrict is, void * __restrict data, const struct ddsi_sertopic_default * __restrict topic) { - const struct dds_topic_descriptor *desc = topic->type; + const struct ddsi_sertopic_default_desc *desc = &topic->type; if (topic->opt_size) dds_is_get_bytes (is, data, desc->m_size, 1); else @@ -1097,7 +1424,7 @@ void dds_stream_read_sample (dds_istream_t * __restrict is, void * __restrict da make any preallocated buffers go to waste, but it does allow reusing the message from read-to-read, at the somewhat reasonable price of a slower deserialization and not being able to use preallocated sequences in topics containing unions. */ - dds_sample_free_contents (data, desc->m_ops); + dds_stream_free_sample (data, desc->m_ops); memset (data, 0, desc->m_size); } dds_stream_read (is, data, desc->m_ops); @@ -1106,7 +1433,7 @@ void dds_stream_read_sample (dds_istream_t * __restrict is, void * __restrict da void dds_stream_write_sample (dds_ostream_t * __restrict os, const void * __restrict data, const struct ddsi_sertopic_default * __restrict topic) { - const struct dds_topic_descriptor *desc = topic->type; + const struct ddsi_sertopic_default_desc *desc = &topic->type; if (topic->opt_size && desc->m_align && (os->m_index % desc->m_align) == 0) dds_os_put_bytes (os, data, desc->m_size); else @@ -1115,10 +1442,10 @@ void dds_stream_write_sample (dds_ostream_t * __restrict os, const void * __rest void dds_stream_read_key (dds_istream_t * __restrict is, char * __restrict sample, const struct ddsi_sertopic_default * __restrict topic) { - const dds_topic_descriptor_t *desc = topic->type; + const struct ddsi_sertopic_default_desc *desc = &topic->type; for (uint32_t i = 0; i < desc->m_nkeys; i++) { - const uint32_t *op = desc->m_ops + desc->m_keys[i].m_index; + const uint32_t *op = desc->m_ops + desc->m_keys[i]; char *dst = sample + op[1]; assert (insn_key_ok_p (*op)); switch (DDS_OP_TYPE (*op)) @@ -1141,10 +1468,10 @@ void dds_stream_read_key (dds_istream_t * __restrict is, char * __restrict sampl void dds_stream_write_key (dds_ostream_t * __restrict os, const char * __restrict sample, const struct ddsi_sertopic_default * __restrict topic) { - const struct dds_topic_descriptor *desc = (const struct dds_topic_descriptor *) topic->type; + const struct ddsi_sertopic_default_desc *desc = &topic->type; for (uint32_t i = 0; i < desc->m_nkeys; i++) { - const uint32_t *insnp = desc->m_ops + desc->m_keys[i].m_index; + const uint32_t *insnp = desc->m_ops + desc->m_keys[i]; const void *src = sample + insnp[1]; assert (insn_key_ok_p (*insnp)); switch (DDS_OP_TYPE (*insnp)) @@ -1201,10 +1528,10 @@ static void dds_stream_swap_insitu (void * __restrict vbuf, uint32_t size, uint3 void dds_stream_write_keyBE (dds_ostreamBE_t * __restrict os, const char * __restrict sample, const struct ddsi_sertopic_default * __restrict topic) { - const struct dds_topic_descriptor *desc = (const struct dds_topic_descriptor *) topic->type; + const struct ddsi_sertopic_default_desc *desc = &topic->type; for (uint32_t i = 0; i < desc->m_nkeys; i++) { - const uint32_t *insnp = desc->m_ops + desc->m_keys[i].m_index; + const uint32_t *insnp = desc->m_ops + desc->m_keys[i]; const void *src = sample + insnp[1]; assert (insn_key_ok_p (*insnp)); switch (DDS_OP_TYPE (*insnp)) @@ -1362,10 +1689,10 @@ static void dds_stream_extract_keyBE_from_key_prim_op (dds_istream_t * __restric static void dds_stream_extract_keyBE_from_key (dds_istream_t * __restrict is, dds_ostreamBE_t * __restrict os, const struct ddsi_sertopic_default * __restrict topic) { - const dds_topic_descriptor_t *desc = topic->type; + const struct ddsi_sertopic_default_desc *desc = &topic->type; for (uint32_t i = 0; i < desc->m_nkeys; i++) { - uint32_t const * const op = desc->m_ops + desc->m_keys[i].m_index; + uint32_t const * const op = desc->m_ops + desc->m_keys[i]; dds_stream_extract_keyBE_from_key_prim_op (is, os, op); } } @@ -1565,21 +1892,21 @@ static void dds_stream_extract_keyBE_from_data1 (dds_istream_t * __restrict is, void dds_stream_extract_key_from_data (dds_istream_t * __restrict is, dds_ostream_t * __restrict os, const struct ddsi_sertopic_default * __restrict topic) { - const dds_topic_descriptor_t *desc = topic->type; + const struct ddsi_sertopic_default_desc *desc = &topic->type; uint32_t keys_remaining = desc->m_nkeys; dds_stream_extract_key_from_data1 (is, os, desc->m_ops, &keys_remaining); } void dds_stream_extract_keyBE_from_data (dds_istream_t * __restrict is, dds_ostreamBE_t * __restrict os, const struct ddsi_sertopic_default * __restrict topic) { - const dds_topic_descriptor_t *desc = topic->type; + const struct ddsi_sertopic_default_desc *desc = &topic->type; uint32_t keys_remaining = desc->m_nkeys; dds_stream_extract_keyBE_from_data1 (is, os, desc->m_ops, &keys_remaining); } void dds_stream_extract_keyhash (dds_istream_t * __restrict is, dds_keyhash_t * __restrict kh, const struct ddsi_sertopic_default * __restrict topic, const bool just_key) { - const dds_topic_descriptor_t *desc = topic->type; + const struct ddsi_sertopic_default_desc *desc = &topic->type; kh->m_set = 1; if (desc->m_nkeys == 0) kh->m_iskey = 1; @@ -1869,17 +2196,17 @@ static bool dds_stream_print_sample1 (char * __restrict *buf, size_t * __restric size_t dds_stream_print_sample (dds_istream_t * __restrict is, const struct ddsi_sertopic_default * __restrict topic, char * __restrict buf, size_t bufsize) { - (void) 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; } size_t dds_stream_print_key (dds_istream_t * __restrict is, const struct ddsi_sertopic_default * __restrict topic, char * __restrict buf, size_t bufsize) { - const dds_topic_descriptor_t *desc = topic->type; + const struct ddsi_sertopic_default_desc *desc = &topic->type; bool cont = prtf (&buf, &bufsize, ":k:{"); for (uint32_t i = 0; cont && i < desc->m_nkeys; i++) { - const uint32_t *op = desc->m_ops + desc->m_keys[i].m_index; + const uint32_t *op = desc->m_ops + desc->m_keys[i]; assert (insn_key_ok_p (*op)); switch (DDS_OP_TYPE (*op)) { diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index a5502ac..2889ba6 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -22,7 +22,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" #include "dds/ddsi/ddsi_tkmap.h" -#include "dds__stream.h" +#include "dds/ddsi/ddsi_cdrstream.h" #include "dds/ddsi/q_radmin.h" #include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/ddsi_serdata_default.h" @@ -349,7 +349,7 @@ static struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr (const struct ddsi_ser { /* FIXME: not quite sure this is correct, though a check against a specially hacked OpenSplice suggests it is */ const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn; - if (!(tp->type->m_flagset & DDS_TOPIC_FIXED_KEY)) + if (!(tp->type.m_flagset & DDS_TOPIC_FIXED_KEY)) { /* keyhash is MD5 of a key value, so impossible to turn into a key value */ return NULL; @@ -386,7 +386,7 @@ static struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr_nokey (const struct dd static void gen_keyhash_from_sample (const struct ddsi_sertopic_default *topic, dds_keyhash_t *kh, const char *sample) { - const struct dds_topic_descriptor *desc = (const struct dds_topic_descriptor *) topic->type; + const struct ddsi_sertopic_default_desc *desc = &topic->type; kh->m_set = 1; if (desc->m_nkeys == 0) kh->m_iskey = 1; diff --git a/src/core/ddsi/src/ddsi_sertopic.c b/src/core/ddsi/src/ddsi_sertopic.c index 278bd7e..8776ede 100644 --- a/src/core/ddsi/src/ddsi_sertopic.c +++ b/src/core/ddsi/src/ddsi_sertopic.c @@ -39,6 +39,8 @@ bool ddsi_sertopic_equal (const struct ddsi_sertopic *a, const struct ddsi_serto return false; if (a->serdata_ops != b->serdata_ops) return false; + if (a->topickind_no_key != b->topickind_no_key) + return false; return a->ops->equal (a, b); } @@ -47,6 +49,7 @@ uint32_t ddsi_sertopic_hash (const struct ddsi_sertopic *a) uint32_t h; h = ddsrt_mh3 (a->name, strlen (a->name), a->serdata_basehash); h = ddsrt_mh3 (a->type_name, strlen (a->type_name), h); + h ^= a->serdata_basehash ^ (uint32_t) a->topickind_no_key; return h ^ a->ops->hash (a); } @@ -63,10 +66,7 @@ struct ddsi_sertopic *ddsi_sertopic_lookup_locked (struct ddsi_domaingv *gv, con struct ddsi_sertopic *sertopic = ddsrt_hh_lookup (gv->sertopics, sertopic_template); #ifndef NDEBUG if (sertopic != NULL) - { assert (sertopic->gv != NULL); - assert (sertopic->iid != 0); - } #endif return ddsi_sertopic_ref (sertopic); } @@ -74,12 +74,10 @@ struct ddsi_sertopic *ddsi_sertopic_lookup_locked (struct ddsi_domaingv *gv, con void ddsi_sertopic_register_locked (struct ddsi_domaingv *gv, struct ddsi_sertopic *sertopic) { assert (sertopic->gv == NULL); - assert (sertopic->iid == 0); assert (ddsrt_atomic_ld32 (&sertopic->refc) == 1); (void) ddsi_sertopic_ref (sertopic); sertopic->gv = gv; - sertopic->iid = ddsi_iid_gen (); int x = ddsrt_hh_add (gv->sertopics, sertopic); assert (x); (void) x; @@ -98,7 +96,6 @@ void ddsi_sertopic_unref (struct ddsi_sertopic *sertopic) (void) ddsrt_hh_remove (sertopic->gv->sertopics, sertopic); ddsrt_mutex_unlock (&sertopic->gv->sertopics_lock); sertopic->gv = NULL; - sertopic->iid = 0; } ddsi_sertopic_free (sertopic); @@ -116,7 +113,6 @@ void ddsi_sertopic_init (struct ddsi_sertopic *tp, const char *name, const char tp->serdata_basehash = ddsi_sertopic_compute_serdata_basehash (tp->serdata_ops); tp->topickind_no_key = topickind_no_key; /* set later, on registration */ - tp->iid = 0; tp->gv = NULL; } diff --git a/src/core/ddsi/src/ddsi_sertopic_default.c b/src/core/ddsi/src/ddsi_sertopic_default.c index 0da5c5c..a10cb96 100644 --- a/src/core/ddsi/src/ddsi_sertopic_default.c +++ b/src/core/ddsi/src/ddsi_sertopic_default.c @@ -20,6 +20,7 @@ #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" +#include "dds/ddsi/ddsi_cdrstream.h" #include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/ddsi_serdata_default.h" @@ -27,37 +28,58 @@ static bool sertopic_default_equal (const struct ddsi_sertopic *acmn, const stru { const struct ddsi_sertopic_default *a = (struct ddsi_sertopic_default *) acmn; const struct ddsi_sertopic_default *b = (struct ddsi_sertopic_default *) bcmn; - return a->type == b->type; + if (a->native_encoding_identifier != b->native_encoding_identifier) + return false; + if (a->type.m_size != b->type.m_size) + return false; + if (a->type.m_align != b->type.m_align) + return false; + if (a->type.m_flagset != b->type.m_flagset) + return false; + if (a->type.m_nkeys != b->type.m_nkeys) + return false; + if (memcmp (a->type.m_keys, b->type.m_keys, a->type.m_nkeys * sizeof (*a->type.m_keys)) != 0) + return false; + if (a->type.m_nops != b->type.m_nops) + return false; + if (memcmp (a->type.m_ops, b->type.m_ops, a->type.m_nops * sizeof (*a->type.m_ops)) != 0) + return false; + assert (a->opt_size == b->opt_size); + return true; } static uint32_t sertopic_default_hash (const struct ddsi_sertopic *tpcmn) { const struct ddsi_sertopic_default *tp = (struct ddsi_sertopic_default *) tpcmn; - if (tp->type == NULL) - return 0; - else - { - return ddsrt_mh3 (tp->type->m_keys, tp->type->m_nkeys * sizeof (*tp->type->m_keys), - ddsrt_mh3 (tp->type->m_ops, tp->type->m_nops * sizeof (*tp->type->m_ops), 0)); - } + uint32_t h = 0; + h = ddsrt_mh3 (&tp->native_encoding_identifier, sizeof (tp->native_encoding_identifier), 0); + h = ddsrt_mh3 (&tp->type.m_size, sizeof (tp->type.m_size), h); + h = ddsrt_mh3 (&tp->type.m_align, sizeof (tp->type.m_align), h); + h = ddsrt_mh3 (&tp->type.m_flagset, sizeof (tp->type.m_flagset), h); + h = ddsrt_mh3 (tp->type.m_keys, tp->type.m_nkeys * sizeof (*tp->type.m_keys), h); + h = ddsrt_mh3 (tp->type.m_ops, tp->type.m_nops * sizeof (*tp->type.m_ops), h); + return h; } -static void sertopic_default_free (struct ddsi_sertopic *tp) +static void sertopic_default_free (struct ddsi_sertopic *tpcmn) { - ddsi_sertopic_fini (tp); + struct ddsi_sertopic_default *tp = (struct ddsi_sertopic_default *) tpcmn; + ddsrt_free (tp->type.m_keys); + ddsrt_free (tp->type.m_ops); + ddsi_sertopic_fini (&tp->c); ddsrt_free (tp); } static void sertopic_default_zero_samples (const struct ddsi_sertopic *sertopic_common, void *sample, size_t count) { const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)sertopic_common; - memset (sample, 0, tp->type->m_size * count); + memset (sample, 0, tp->type.m_size * count); } static void sertopic_default_realloc_samples (void **ptrs, const struct ddsi_sertopic *sertopic_common, void *old, size_t oldcount, size_t count) { const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)sertopic_common; - const size_t size = tp->type->m_size; + const size_t size = tp->type.m_size; char *new = (oldcount == count) ? old : dds_realloc (old, size * count); if (new && count > oldcount) memset (new + size * oldcount, 0, size * (count - oldcount)); @@ -73,7 +95,7 @@ static void sertopic_default_free_samples (const struct ddsi_sertopic *sertopic_ if (count > 0) { const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)sertopic_common; - const struct dds_topic_descriptor *type = tp->type; + const struct ddsi_sertopic_default_desc *type = &tp->type; const size_t size = type->m_size; #ifndef NDEBUG for (size_t i = 0, off = 0; i < count; i++, off += size) @@ -84,7 +106,7 @@ static void sertopic_default_free_samples (const struct ddsi_sertopic *sertopic_ char *ptr = ptrs[0]; for (size_t i = 0; i < count; i++) { - dds_sample_free (ptr, type, DDS_FREE_CONTENTS); + dds_stream_free_sample (ptr, type->m_ops); ptr += size; } } diff --git a/src/core/ddsi/src/ddsi_tkmap.c b/src/core/ddsi/src/ddsi_tkmap.c index 7f281cd..9b6324b 100644 --- a/src/core/ddsi/src/ddsi_tkmap.c +++ b/src/core/ddsi/src/ddsi_tkmap.c @@ -22,9 +22,9 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/ddsi_tkmap.h" -#include "dds/ddsrt/hopscotch.h" -#include "dds__stream.h" +#include "dds/ddsi/ddsi_cdrstream.h" #include "dds/ddsi/ddsi_serdata.h" +#include "dds/ddsrt/hopscotch.h" #define REFC_DELETE 0x80000000 #define REFC_MASK 0x0fffffff diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index af5e849..3d48219 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -782,7 +782,6 @@ static struct ddsi_sertopic *make_special_topic (const char *name, struct serdat ddsi_sertopic_init (&st->c, name, name, &ddsi_sertopic_ops_default, ops, false); st->native_encoding_identifier = enc_id; st->serpool = serpool; - st->nkeys = 1; return (struct ddsi_sertopic *) st; } diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index c01e730..7f0bf28 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -22,7 +22,7 @@ #include "dds/ddsrt/static_assert.h" #include "dds/ddsrt/avl.h" -#include "dds__stream.h" +#include "dds/ddsi/ddsi_cdrstream.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_misc.h" diff --git a/src/core/xtests/cdrtest/CMakeLists.txt b/src/core/xtests/cdrtest/CMakeLists.txt index 1535a9c..2021e0b 100644 --- a/src/core/xtests/cdrtest/CMakeLists.txt +++ b/src/core/xtests/cdrtest/CMakeLists.txt @@ -11,6 +11,8 @@ # cmake_minimum_required(VERSION 3.5) +find_package(CycloneDDS COMPONENTS idlc) + add_compile_options("-I${PROJECT_SOURCE_DIR}/src/ddsrt/include") add_compile_options("-I${PROJECT_SOURCE_DIR}/src/core/ddsc/include") add_compile_options("-I${PROJECT_SOURCE_DIR}/src/core/ddsc/src") diff --git a/src/core/xtests/cdrtest/cdrtest.pl b/src/core/xtests/cdrtest/cdrtest.pl index e850927..f42a7c2 100644 --- a/src/core/xtests/cdrtest/cdrtest.pl +++ b/src/core/xtests/cdrtest/cdrtest.pl @@ -54,7 +54,7 @@ print CYC <[1]_desc; + ddd.type = (struct ddsi_sertopic_default_desc) { + .m_size = $t->[1]_desc.m_size, + .m_align = $t->[1]_desc.m_align, + .m_flagset = $t->[1]_desc.m_flagset, + .m_nkeys = 0, + .m_keys = NULL, + .m_nops = dds_stream_countops ($t->[1]_desc.m_ops), + .m_ops = (uint32_t *) $t->[1]_desc.m_ops + }; for (uint32_t i = 0; i < 1000; i++) { for (size_t j = 0; j < sizeof (garbage); j++) garbage[j] = (unsigned char) ddsrt_random (); From b84eee5abbd4e935d3e47186e07ed93e4730b5f1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 11 Feb 2020 11:59:26 +0100 Subject: [PATCH 28/28] Fix detecting remote ping/pong writers in ddsperf The status mask on some readers got reduced to just "data available" when used in conjunction with a waitset, but the consequence is that the "subscription matched" listener would be suppressed. Signed-off-by: Erik Boasson --- src/tools/ddsperf/ddsperf.c | 72 +++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index 8fe6eae..628778b 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -969,18 +969,24 @@ static void maybe_send_new_ping (dds_time_t tnow, dds_time_t *tnextping) } } -static uint32_t subthread_waitset (void *varg) +static dds_entity_t make_reader_waitset (dds_entity_t rd) { - struct subthread_arg * const arg = varg; dds_entity_t ws; int32_t rc; ws = dds_create_waitset (dp); if ((rc = dds_waitset_attach (ws, termcond, 0)) < 0) error2 ("dds_waitset_attach (termcond, 0): %d\n", (int) rc); - if ((rc = dds_set_status_mask (rd_data, DDS_DATA_AVAILABLE_STATUS)) < 0) - error2 ("dds_set_status_mask (rd_data, DDS_DATA_AVAILABLE_STATUS): %d\n", (int) rc); - if ((rc = dds_waitset_attach (ws, rd_data, 1)) < 0) - error2 ("dds_waitset_attach (ws, rd_data, 1): %d\n", (int) rc); + if ((rc = dds_set_status_mask (rd, DDS_DATA_AVAILABLE_STATUS | DDS_SUBSCRIPTION_MATCHED_STATUS)) < 0) + error2 ("dds_set_status_mask (rd, DDS_DATA_AVAILABLE_STATUS | DDS_SUBSCRIPTION_MATCHED_STATUS): %d\n", (int) rc); + if ((rc = dds_waitset_attach (ws, rd, 1)) < 0) + error2 ("dds_waitset_attach (ws, rd, 1): %d\n", (int) rc); + return ws; +} + +static uint32_t subthread_waitset (void *varg) +{ + struct subthread_arg * const arg = varg; + dds_entity_t ws = make_reader_waitset (rd_data); while (!ddsrt_atomic_ld32 (&termflag)) { if (!process_data (rd_data, arg)) @@ -998,15 +1004,7 @@ static uint32_t subthread_waitset (void *varg) static uint32_t subpingthread_waitset (void *varg) { struct subthread_arg * const arg = varg; - dds_entity_t ws; - int32_t rc; - ws = dds_create_waitset (dp); - if ((rc = dds_waitset_attach (ws, termcond, 0)) < 0) - error2 ("dds_waitset_attach (termcond, 0): %d\n", (int) rc); - if ((rc = dds_set_status_mask (rd_ping, DDS_DATA_AVAILABLE_STATUS)) < 0) - error2 ("dds_set_status_mask (rd_ping, DDS_DATA_AVAILABLE_STATUS): %d\n", (int) rc); - if ((rc = dds_waitset_attach (ws, rd_ping, 1)) < 0) - error2 ("dds_waitset_attach (ws, rd_ping, 1): %d\n", (int) rc); + dds_entity_t ws = make_reader_waitset (rd_ping); while (!ddsrt_atomic_ld32 (&termflag)) { int32_t nxs; @@ -1020,15 +1018,7 @@ static uint32_t subpingthread_waitset (void *varg) static uint32_t subpongthread_waitset (void *varg) { struct subthread_arg * const arg = varg; - dds_entity_t ws; - int32_t rc; - ws = dds_create_waitset (dp); - if ((rc = dds_waitset_attach (ws, termcond, 0)) < 0) - error2 ("dds_waitset_attach (termcond, 0): %d\n", (int) rc); - if ((rc = dds_set_status_mask (rd_pong, DDS_DATA_AVAILABLE_STATUS)) < 0) - error2 ("dds_set_status_mask (rd_pong, DDS_DATA_AVAILABLE_STATUS): %d\n", (int) rc); - if ((rc = dds_waitset_attach (ws, rd_pong, 1)) < 0) - error2 ("dds_waitset_attach (ws, rd_pong, 1): %d\n", (int) rc); + dds_entity_t ws = make_reader_waitset (rd_pong); while (!ddsrt_atomic_ld32 (&termflag)) { int32_t nxs; @@ -1101,7 +1091,7 @@ static dds_entity_t create_pong_writer (dds_instance_handle_t pphandle, const st return wr_pong; } -static void delete_pong_writer (dds_instance_handle_t pphandle) +static dds_entity_t delete_pong_writer (dds_instance_handle_t pphandle) { uint32_t i = 0; dds_entity_t wr_pong = 0; @@ -1118,8 +1108,7 @@ static void delete_pong_writer (dds_instance_handle_t pphandle) } } ddsrt_mutex_unlock (&pongwr_lock); - if (wr_pong) - dds_delete (wr_pong); + return wr_pong; } static void free_ppant (void *vpp) @@ -1143,6 +1132,7 @@ static void participant_data_listener (dds_entity_t rd, void *arg) if (info.instance_state != DDS_ALIVE_INSTANCE_STATE) { ddsrt_avl_dpath_t dpath; + dds_entity_t pong_wr_to_del = 0; ddsrt_mutex_lock (&disc_lock); if ((pp = ddsrt_avl_lookup_dpath (&ppants_td, &ppants, &info.instance_handle, &dpath)) != NULL) { @@ -1151,7 +1141,7 @@ static void participant_data_listener (dds_entity_t rd, void *arg) if (pp->handle != dp_handle || ignorelocal == DDS_IGNORELOCAL_NONE) { - delete_pong_writer (pp->handle); + pong_wr_to_del = delete_pong_writer (pp->handle); n_pong_expected_delta--; } @@ -1161,6 +1151,7 @@ static void participant_data_listener (dds_entity_t rd, void *arg) free_ppant (pp); } ddsrt_mutex_unlock (&disc_lock); + dds_delete (pong_wr_to_del); } else { @@ -1171,6 +1162,7 @@ static void participant_data_listener (dds_entity_t rd, void *arg) /* only add unknown participants with the magic user_data value: DDSPerf:X:HOSTNAME, where X is decimal */ if (dds_qget_userdata (sample->qos, &vudata, &usz) && usz > 0) { + bool make_pongwr = false; const char *udata = vudata; int has_reader, pos; long pid; @@ -1199,15 +1191,17 @@ static void participant_data_listener (dds_entity_t rd, void *arg) ddsrt_fibheap_insert (&ppants_to_match_fhd, &ppants_to_match, pp); ddsrt_avl_insert_ipath (&ppants_td, &ppants, pp, &ipath); - if (pp->handle != dp_handle || ignorelocal == DDS_IGNORELOCAL_NONE) - { - struct guidstr guidstr; - make_guidstr (&guidstr, &sample->key); - create_pong_writer (pp->handle, &guidstr); - n_pong_expected_delta++; - } + make_pongwr = (pp->handle != dp_handle || ignorelocal == DDS_IGNORELOCAL_NONE); } ddsrt_mutex_unlock (&disc_lock); + + if (make_pongwr) + { + struct guidstr guidstr; + make_guidstr (&guidstr, &sample->key); + create_pong_writer (pp->handle, &guidstr); + n_pong_expected_delta++; + } } dds_free (vudata); } @@ -1312,8 +1306,8 @@ static void subscription_matched_listener (dds_entity_t rd, const dds_subscripti static void publication_matched_listener (dds_entity_t wr, const dds_publication_matched_status_t status, void *arg) { /* this only works because the listener is called for every match; but I don't think that is something the - spec guarantees, and I don't think Cyclone should guarantee that either -- and if it isn't guaranteed - _really_ needs the get_matched_... interfaces to not have to implement the matching logic ... */ + spec guarantees, and I don't think Cyclone should guarantee that either -- and if it isn't guaranteed + _really_ needs the get_matched_... interfaces to not have to implement the matching logic ... */ (void) wr; if (status.current_count_change > 0) { @@ -1326,8 +1320,8 @@ static void publication_matched_listener (dds_entity_t wr, const dds_publication static void set_data_available_listener (dds_entity_t rd, const char *rd_name, dds_on_data_available_fn fn, void *arg) { /* This convoluted code is so that we leave all listeners unchanged, except the - data_available one. There is no real need for these complications, but it is - a nice exercise. */ + data_available one. There is no real need for these complications, but it is + a nice exercise. */ dds_listener_t *listener = dds_create_listener (arg); dds_return_t rc; dds_lset_data_available (listener, fn);