From f0f76454c7d261b2a515cfe9ad7a50392d6deb72 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 27 Mar 2019 09:15:41 +0100 Subject: [PATCH 001/178] timely initialization of builtin topics (#138) The rtps_init function used to initialize all data structures and start all threads used by the protocol stack, allowing discovery of remote entities before the built-in topic data structures were initialized. (Very) early discovery of a remote participant thus led to a crash. This commit splits the initialisation, providing a separate function for starting, in particular, the threads receiving data from the network. In terms of threads created, it matches exactly with the rtps_stop / rtps_fini split that already existed to address the exact same problem on termination. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_init.c | 15 +++- src/core/ddsi/include/dds/ddsi/q_rtps.h | 1 + src/core/ddsi/src/q_init.c | 98 ++++++++++++++----------- 3 files changed, 67 insertions(+), 47 deletions(-) diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 1a434b5..3aa8751 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -113,6 +113,7 @@ dds_init(dds_domainid_t domain) goto fail_rtps_config; } + upgrade_main_thread(); ut_avlInit(&dds_domaintree_def, &dds_global.m_domains); /* Start monitoring the liveliness of all threads. */ @@ -129,7 +130,7 @@ dds_init(dds_domainid_t domain) } } - if (rtps_init() < 0) + if (rtps_init () < 0) { DDS_LOG(DDS_LC_CONFIG, "Failed to initialize RTPS\n"); ret = DDS_ERRNO(DDS_RETCODE_ERROR); @@ -138,6 +139,13 @@ dds_init(dds_domainid_t domain) dds__builtin_init (); + if (rtps_start () < 0) + { + DDS_LOG(DDS_LC_CONFIG, "Failed to start RTPS\n"); + ret = DDS_ERRNO(DDS_RETCODE_ERROR); + goto fail_rtps_start; + } + if (gv.servicelease && nn_servicelease_start_renewing(gv.servicelease) < 0) { DDS_ERROR("Failed to start the servicelease\n"); @@ -145,8 +153,6 @@ dds_init(dds_domainid_t domain) goto fail_servicelease_start; } - upgrade_main_thread(); - /* Set additional default participant properties */ gv.default_plist_pp.process_id = (unsigned)ddsrt_getpid(); @@ -173,6 +179,8 @@ fail_servicelease_start: if (gv.servicelease) nn_servicelease_stop_renewing (gv.servicelease); rtps_stop (); +fail_rtps_start: + dds__builtin_fini (); rtps_fini (); fail_rtps_init: if (gv.servicelease) @@ -181,6 +189,7 @@ fail_rtps_init: gv.servicelease = NULL; } fail_servicelease_new: + downgrade_main_thread (); thread_states_fini(); fail_rtps_config: fail_config_domainid: diff --git a/src/core/ddsi/include/dds/ddsi/q_rtps.h b/src/core/ddsi/include/dds/ddsi/q_rtps.h index e9793d6..731fbd9 100644 --- a/src/core/ddsi/include/dds/ddsi/q_rtps.h +++ b/src/core/ddsi/include/dds/ddsi/q_rtps.h @@ -76,6 +76,7 @@ struct cfgst; int rtps_config_prep (struct cfgst *cfgst); int rtps_config_open (void); int rtps_init (void); +int rtps_start (void); void ddsi_plugin_init (void); void rtps_stop (void); void rtps_fini (void); diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index d5ca562..97ae856 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -1275,61 +1275,20 @@ int rtps_init (void) gv.rtps_keepgoing = 1; ddsrt_rwlock_init (&gv.qoslock); - { - int r; - gv.builtins_dqueue = nn_dqueue_new ("builtins", config.delivery_queue_maxsamples, builtins_dqueue_handler, NULL); - if ((r = xeventq_start (gv.xevents, NULL)) < 0) - { - DDS_FATAL("failed to start global event processing thread (%d)\n", r); - } - } - if (config.xpack_send_async) { nn_xpack_sendq_init(); nn_xpack_sendq_start(); } + gv.builtins_dqueue = nn_dqueue_new ("builtins", config.delivery_queue_maxsamples, builtins_dqueue_handler, NULL); #ifdef DDSI_INCLUDE_NETWORK_CHANNELS - /* Create a delivery queue and start tev for each channel */ - { - struct config_channel_listelem * chptr = config.channels; - while (chptr) - { - chptr->dqueue = nn_dqueue_new (chptr->name, config.delivery_queue_maxsamples, user_dqueue_handler, NULL); - if (chptr->evq) - { - int r; - if ((r = xeventq_start (chptr->evq, chptr->name)) < 0) - DDS_FATAL("failed to start event processing thread for channel '%s' (%d)\n", chptr->name, r); - } - chptr = chptr->next; - } - } + for (struct config_channel_listelem *chptr = config.channels; chptr; chptr = chptr->next) + chptr->dqueue = nn_dqueue_new (chptr->name, config.delivery_queue_maxsamples, user_dqueue_handler, NULL); #else gv.user_dqueue = nn_dqueue_new ("user", config.delivery_queue_maxsamples, user_dqueue_handler, NULL); #endif - if (setup_and_start_recv_threads () < 0) - { - DDS_FATAL("failed to start receive threads\n"); - } - - if (gv.listener) - { - gv.listen_ts = create_thread ("listen", (uint32_t (*) (void *)) listen_thread, gv.listener); - } - - if (gv.startup_mode) - { - qxev_end_startup_mode (add_duration_to_mtime (now_mt (), config.startup_mode_duration)); - } - - if (config.monitor_port >= 0) - { - gv.debmon = new_debug_monitor (config.monitor_port); - } - return 0; err_mc_conn: @@ -1402,6 +1361,57 @@ err_udp_tcp_init: return -1; } +#ifdef DDSI_INCLUDE_NETWORK_CHANNELS +static void stop_all_xeventq_upto (struct config_channel_listelem *chptr) +{ + for (struct config_channel_listelem *chptr1 = config.channels; chptr1 != chptr; chptr1 = chptr1->next) + if (chptr1->evq) + xeventq_stop (chptr1->evq); +} +#endif + +int rtps_start (void) +{ + if (xeventq_start (gv.xevents, NULL) < 0) + return -1; +#ifdef DDSI_INCLUDE_NETWORK_CHANNELS + for (struct config_channel_listelem *chptr = config.channels; chptr; chptr = chptr->next) + { + if (chptr->evq) + { + if (xeventq_start (chptr->evq, chptr->name) < 0) + { + stop_all_xeventq_upto (chptr); + xeventq_stop (gv.xevents); + return -1; + } + } + } +#endif + + if (setup_and_start_recv_threads () < 0) + { +#ifdef DDSI_INCLUDE_NETWORK_CHANNELS + stop_all_xeventq_upto (NULL); +#endif + xeventq_stop (gv.xevents); + return -1; + } + if (gv.listener) + { + gv.listen_ts = create_thread ("listen", (uint32_t (*) (void *)) listen_thread, gv.listener); + } + if (gv.startup_mode) + { + qxev_end_startup_mode (add_duration_to_mtime (now_mt (), config.startup_mode_duration)); + } + if (config.monitor_port >= 0) + { + gv.debmon = new_debug_monitor (config.monitor_port); + } + return 0; +} + struct dq_builtins_ready_arg { ddsrt_mutex_t lock; ddsrt_cond_t cond; From 774e52069daefce305ccd205a827cfc7e0bf383b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 27 Mar 2019 09:21:09 +0100 Subject: [PATCH 002/178] trace correct thread id during thread creation The rewrite of the abstraction layer changed some details in thread ids used in tracing and functions to get those ids, with a result of always printing the parent thread's id in create_thread rather than the newly create thread's id. As all supported platforms use thread names in the trace, it is a rather insignificant matter, and so this provides the trivial fix by letting the new thread log the message. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index cadbb6e..4d3fe45 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -172,6 +172,7 @@ static uint32_t create_thread_wrapper (void *ptr) { uint32_t ret; struct thread_context *ctx = ptr; + DDS_TRACE ("started new thread %"PRIdTID": %s\n", ddsrt_gettid (), ctx->self->name); ctx->self->tid = ddsrt_thread_self (); ret = ctx->f (ctx->arg); ddsrt_free (ctx); @@ -272,7 +273,6 @@ struct thread_state1 *create_thread (const char *name, uint32_t (*f) (void *arg) DDS_FATAL("create_thread: %s: ddsrt_thread_create failed\n", name); goto fatal; } - DDS_TRACE("started new thread %"PRIdTID" : %s\n", ddsrt_gettid(), name); ts1->extTid = tid; /* overwrite the temporary value with the correct external one */ ddsrt_mutex_unlock (&thread_states.lock); return ts1; From a15fc3594b91c55611bc7eaff9dfcce77ecb699e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 27 Mar 2019 09:25:09 +0100 Subject: [PATCH 003/178] avoid debmon thread shutdown logging write errors During shutdown, the optional "debmon" thread for getting some information about internal state of the DDSI stack had a tendency to run into errors from calling write on a connection that had already been closed immediately after connecting successfully to wake the thread. Instead of blindly writing into the connection, it now checks whether it is supposed to shutdown before doing anything, avoiding this particular problem. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_debmon.c | 49 +++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index eb83d81..beaa9bf 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -300,37 +300,46 @@ static int print_proxy_participants (struct thread_state1 *self, ddsi_tran_conn_ return x; } +static void debmon_handle_connection (struct debug_monitor *dm, ddsi_tran_conn_t conn) +{ + struct plugin *p; + int r = 0; + r += print_participants (dm->servts, conn); + if (r == 0) + r += print_proxy_participants (dm->servts, conn); + + /* Note: can only add plugins (at the tail) */ + ddsrt_mutex_lock (&dm->lock); + p = dm->plugins; + while (r == 0 && p != NULL) + { + ddsrt_mutex_unlock (&dm->lock); + r += p->fn (conn, cpf, p->arg); + ddsrt_mutex_lock (&dm->lock); + p = p->next; + } + ddsrt_mutex_unlock (&dm->lock); +} + static uint32_t debmon_main (void *vdm) { struct debug_monitor *dm = vdm; ddsrt_mutex_lock (&dm->lock); while (!dm->stop) { - ddsi_tran_conn_t conn; ddsrt_mutex_unlock (&dm->lock); - if ((conn = ddsi_listener_accept (dm->servsock)) != NULL) + ddsi_tran_conn_t conn = ddsi_listener_accept (dm->servsock); + ddsrt_mutex_lock (&dm->lock); + if (conn != NULL && !dm->stop) { - struct plugin *p; - int r = 0; - r += print_participants (dm->servts, conn); - if (r == 0) - r += print_proxy_participants (dm->servts, conn); - - /* Note: can only add plugins (at the tail) */ - ddsrt_mutex_lock (&dm->lock); - p = dm->plugins; - while (r == 0 && p != NULL) - { - ddsrt_mutex_unlock (&dm->lock); - r += p->fn (conn, cpf, p->arg); - ddsrt_mutex_lock (&dm->lock); - p = p->next; - } ddsrt_mutex_unlock (&dm->lock); - + debmon_handle_connection (dm, conn); + ddsrt_mutex_lock (&dm->lock); + } + if (conn != NULL) + { ddsi_conn_free (conn); } - ddsrt_mutex_lock (&dm->lock); } ddsrt_mutex_unlock (&dm->lock); return 0; From 8bc107b63517f1c94feed29f2c4c44ffbec4d956 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 27 Mar 2019 17:14:44 +0100 Subject: [PATCH 004/178] gracefully handle a too small ReceiveBufferSize Sizing/ReceiveBufferSize must be >= Sizing/ReceiveBufferChunkSize + N for some small N, and if it is not, Cyclone will crash reading beyond allocated memory in a nasty way. Ordinarily this should be handled by the configuration validation, but that would put the burden of knowing the details of computing N upon the user, an unreasonable requirement. The old state of an assertion presupposes a check, and brings us back that same requirement. Thus, a change to ensure that ReceiveBufferSize will be taken as the minimum of the configured value and the actual minimal value as determined by ChunkSize and whatever N happens to be. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_config.c | 2 +- src/core/ddsi/src/q_radmin.c | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index e318181..de2cceb 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -654,7 +654,7 @@ END_MARKER static const struct cfgelem sizing_cfgelems[] = { { LEAF("ReceiveBufferSize"), 1, "1 MiB", ABSOFF(rbuf_size), 0, uf_memsize, 0, pf_memsize, - "

This element sets the size of a single receive buffer. Many receive buffers may be needed. Their size must be greater than ReceiveBufferChunkSize by a modest amount.

" }, + "

This element sets the size of a single receive buffer. Many receive buffers may be needed. The minimum workable size a little bit larger than Sizing/ReceiveBufferChunkSize, and the value used is taken as the configured value and the actual minimum workable size.

" }, { LEAF("ReceiveBufferChunkSize"), 1, "128 KiB", ABSOFF(rmsg_chunk_size), 0, uf_memsize, 0, pf_memsize, "

This element specifies the size of one allocation unit in the receive buffer. Must be greater than the maximum packet size by a modest amount (too large packets are dropped). Each allocation is shrunk immediately after processing a message, or freed straightaway.

" }, END_MARKER diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index c6f4a22..41c6192 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -330,7 +330,13 @@ struct nn_rbufpool *nn_rbufpool_new (uint32_t rbuf_size, uint32_t max_rmsg_size) struct nn_rbufpool *rbp; assert (max_rmsg_size > 0); - assert (rbuf_size >= max_rmsg_size_w_hdr (max_rmsg_size)); + + /* raise rbuf_size to minimum possible considering max_rmsg_size, there is + no reason to bother the user with the small difference between the two + when he tries to configure things, and the crash is horrible when + rbuf_size is too small */ + if (rbuf_size < max_rmsg_size_w_hdr (max_rmsg_size)) + rbuf_size = max_rmsg_size_w_hdr (max_rmsg_size); if ((rbp = ddsrt_malloc (sizeof (*rbp))) == NULL) goto fail_rbp; From 44406ef6a72c4f5accdbf19cb156d2762fa56a1b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 27 Mar 2019 17:28:03 +0100 Subject: [PATCH 005/178] clarify "spdp" token in AllowMulticast option Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index de2cceb..596fb3e 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -248,7 +248,7 @@ static const struct cfgelem general_cfgelems[] = { "

This element controls whether DDSI2E uses multicasts for data traffic.

\n\

It is a comma-separated list of some of the following keywords: \"spdp\", \"asm\", \"ssm\", or either of \"false\" or \"true\".

\n\
    \n\ -
  • spdp: enables the use of ASM (any-source multicast) for participant discovery
  • \n\ +
  • spdp: enables the use of ASM (any-source multicast) for participant discovery, joining the multicast group on the discovery socket, transmitting SPDP messages to this group, but never advertising nor using any multicast address in any discovery message, thus forcing unicast communications for all endpoint discovery and user data.
  • \n\
  • asm: enables the use of ASM for all traffic (including SPDP)
  • \n\
  • ssm: enables the use of SSM (source-specific multicast) for all non-SPDP traffic (if supported)
  • \n\
\n\ From 30142d1812d43748a74aed7b2317a29d169e0b38 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 27 Mar 2019 17:29:26 +0100 Subject: [PATCH 006/178] remove rmbias_and_adjust assert on threadid (#121) The introduction of multiple receive threads could trigger the assertion because a set of samples ready for delivery may have been received by multiple threads (the problem manifests itself most easily with fragmented samples). This is actually a non-issue: * while synchronously processing a packet, there is a bias of 2**31 added to the refcount, to prevent any thread under any circumstance from ever freeing the data; * while data lives in the defragment buffers or reorder buffer of the proxy writer, a bias of 2**20 is added to it until this particular function is called, after delivery of the data to the readers, and (if needed) after inserting the samples in the reorder buffer of any readers that are out-of-sync with the proxy writer; * the relevant refcount is updated atomically in such a manner that this particular operation atomically removes the bias and performs the delayed increment of the refcount to account for the data being stored in any of the defragmenting or reorder buffers; * the only ordinary decrementing of the refcount happens either synchronously (if synchronous delivery is chosen), or asynchronously in a delivery queue thread, and so the entire mechanism exists to avoid premature freeing of the underlying data because the data is delivered very quickly (possibly synchronously); * as the biases are removed after all the delayed refcount increments are taken into account and there are no increments following the call to rmbias_and_adjust, the "ordinary" decrements can do no harm. * the case of data from multiple writers being combined in a single packet is dealt with by the 2**20 bias, and so there is potentially a problem if there are more than 2**20 out-of-sync readers attached to a single proxy writer, or data submessages from more than 2**11 writers in a single packet. The minimum possible data message is 32 bytes (headers, encoding, data, padding), so packets up to 64kB are safe. None of this is in any way related to which threads originally accepted the packets, and therefore I see no argument for the existence of the assertion. That said, it is a rather complicated mechanism of unknown benefit, and a major simplification is definitely something to be considered. In UDP mode I see no chance of abuse, but there may be network protocols (TCP, for sure) where there might be packets larger than 64kB and those could, under worst-case assumptions, cause trouble. That, too, is a reason to rethink it. The call to rmbias_and_adjust was sometimes called with the proxy writer locked, and sometimes after unlocking it. This commit changes it to consistently call it with the lock held. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_radmin.c | 46 +++++++---------------------------- src/core/ddsi/src/q_receive.c | 4 +-- 2 files changed, 11 insertions(+), 39 deletions(-) diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index 41c6192..20eaa66 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -639,11 +639,10 @@ static void nn_rmsg_addbias (struct nn_rmsg *rmsg) static void nn_rmsg_rmbias_and_adjust (struct nn_rmsg *rmsg, int adjust) { /* This can happen to any rmsg referenced by an sample still - progressing through the pipeline, but only by the receive + progressing through the pipeline, but only by a receive thread. Can't require it to be uncommitted. */ uint32_t sub; DDS_LOG(DDS_LC_RADMIN, "rmsg_rmbias_and_adjust(%p, %d)\n", (void *) rmsg, adjust); - ASSERT_RBUFPOOL_OWNER (rmsg->chunk.rbuf->rbufpool); assert (adjust >= 0); assert ((uint32_t) adjust < RMSG_REFCOUNT_RDATA_BIAS); sub = RMSG_REFCOUNT_RDATA_BIAS - (uint32_t) adjust; @@ -652,15 +651,6 @@ static void nn_rmsg_rmbias_and_adjust (struct nn_rmsg *rmsg, int adjust) nn_rmsg_free (rmsg); } -static void nn_rmsg_rmbias_anythread (struct nn_rmsg *rmsg) -{ - /* For removing garbage when freeing a nn_defrag. */ - uint32_t sub = RMSG_REFCOUNT_RDATA_BIAS; - DDS_LOG(DDS_LC_RADMIN, "rmsg_rmbias_anythread(%p)\n", (void *) rmsg); - assert (ddsrt_atomic_ld32 (&rmsg->refcount) >= sub); - if (ddsrt_atomic_sub32_nv (&rmsg->refcount, sub) == 0) - nn_rmsg_free (rmsg); -} static void nn_rmsg_unref (struct nn_rmsg *rmsg) { DDS_LOG(DDS_LC_RADMIN, "rmsg_unref(%p)\n", (void *) rmsg); @@ -752,16 +742,6 @@ static void nn_rdata_rmbias_and_adjust (struct nn_rdata *rdata, int adjust) nn_rmsg_rmbias_and_adjust (rdata->rmsg, adjust); } -static void nn_rdata_rmbias_anythread (struct nn_rdata *rdata) -{ - DDS_LOG(DDS_LC_RADMIN, "rdata_rmbias_anythread(%p)\n", (void *) rdata); -#ifndef NDEBUG - if (ddsrt_atomic_dec32_ov (&rdata->refcount_bias_added) != 1) - abort (); -#endif - nn_rmsg_rmbias_anythread (rdata->rmsg); -} - static void nn_rdata_unref (struct nn_rdata *rdata) { DDS_LOG(DDS_LC_RADMIN, "rdata_rdata_unref(%p)\n", (void *) rdata); @@ -900,29 +880,21 @@ struct nn_defrag *nn_defrag_new (enum nn_defrag_drop_mode drop_mode, uint32_t ma void nn_fragchain_adjust_refcount (struct nn_rdata *frag, int adjust) { - struct nn_rdata *frag1; DDS_LOG(DDS_LC_RADMIN, "fragchain_adjust_refcount(%p, %d)\n", (void *) frag, adjust); while (frag) { - frag1 = frag->nextfrag; + struct nn_rdata * const frag1 = frag->nextfrag; nn_rdata_rmbias_and_adjust (frag, adjust); frag = frag1; } } -static void nn_fragchain_rmbias_anythread (struct nn_rdata *frag, UNUSED_ARG (int adjust)) +static void nn_fragchain_rmbias (struct nn_rdata *frag) { - struct nn_rdata *frag1; - DDS_LOG(DDS_LC_RADMIN, "fragchain_rmbias_anythread(%p)\n", (void *) frag); - while (frag) - { - frag1 = frag->nextfrag; - nn_rdata_rmbias_anythread (frag); - frag = frag1; - } + nn_fragchain_adjust_refcount (frag, 0); } -static void defrag_rsample_drop (struct nn_defrag *defrag, struct nn_rsample *rsample, void (*fragchain_free) (struct nn_rdata *frag, int adjust)) +static void defrag_rsample_drop (struct nn_defrag *defrag, struct nn_rsample *rsample) { /* Can't reference rsample after the first fragchain_free, because we don't know which rdata/rmsg provides the storage for the @@ -938,7 +910,7 @@ static void defrag_rsample_drop (struct nn_defrag *defrag, struct nn_rsample *rs assert (defrag->n_samples > 0); defrag->n_samples--; for (iv = ut_avlIterFirst (&rsample_defrag_fragtree_treedef, &rsample->u.defrag.fragtree, &iter); iv; iv = ut_avlIterNext (&iter)) - fragchain_free (iv->first, 0); + nn_fragchain_rmbias (iv->first); } void nn_defrag_free (struct nn_defrag *defrag) @@ -948,7 +920,7 @@ void nn_defrag_free (struct nn_defrag *defrag) while (s) { DDS_LOG(DDS_LC_RADMIN, "defrag_free(%p, sample %p seq %"PRId64")\n", (void *) defrag, (void *) s, s->u.defrag.seq); - defrag_rsample_drop (defrag, s, nn_fragchain_rmbias_anythread); + defrag_rsample_drop (defrag, s); s = ut_avlFindMin (&defrag_sampletree_treedef, &defrag->sampletree); } assert (defrag->n_samples == 0); @@ -1312,7 +1284,7 @@ static int defrag_limit_samples (struct nn_defrag *defrag, seqno_t seq, seqno_t break; } assert (sample_to_drop != NULL); - defrag_rsample_drop (defrag, sample_to_drop, nn_fragchain_adjust_refcount); + defrag_rsample_drop (defrag, sample_to_drop); if (sample_to_drop == defrag->max_sample) { defrag->max_sample = ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree); @@ -1444,7 +1416,7 @@ void nn_defrag_notegap (struct nn_defrag *defrag, seqno_t min, seqno_t maxp1) while (s && s->u.defrag.seq < maxp1) { struct nn_rsample *s1 = ut_avlFindSucc (&defrag_sampletree_treedef, &defrag->sampletree, s); - defrag_rsample_drop (defrag, s, nn_fragchain_adjust_refcount); + defrag_rsample_drop (defrag, s); s = s1; } defrag->max_sample = ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 7de04a6..d09c89d 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -2304,8 +2304,8 @@ static int handle_SPDP (const struct nn_rsample_info *sampleinfo, struct nn_rdat fragchain = nn_rsample_fragchain (rsample); if ((rres = nn_reorder_rsample (&sc, gv.spdp_reorder, rsample, &refc_adjust, nn_dqueue_is_full (gv.builtins_dqueue))) > 0) nn_dqueue_enqueue (gv.builtins_dqueue, &sc, rres); - ddsrt_mutex_unlock (&gv.spdp_lock); nn_fragchain_adjust_refcount (fragchain, refc_adjust); + ddsrt_mutex_unlock (&gv.spdp_lock); return 0; } @@ -2342,8 +2342,8 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con ddsrt_mutex_lock (&pwr->e.lock); wn = ut_avlLookup (&pwr_readers_treedef, &pwr->readers, &dst); gap_was_valuable = handle_one_gap (pwr, wn, sampleinfo->seq, sampleinfo->seq+1, gap, &refc_adjust); - ddsrt_mutex_unlock (&pwr->e.lock); nn_fragchain_adjust_refcount (gap, refc_adjust); + ddsrt_mutex_unlock (&pwr->e.lock); if (gap_was_valuable) { From 20880016e319724764108b87c42d396411fcaab6 Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Thu, 28 Mar 2019 09:43:24 +0100 Subject: [PATCH 007/178] Cleanup log tests. Signed-off-by: Martin Bremmer --- src/ddsrt/tests/log.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/ddsrt/tests/log.c b/src/ddsrt/tests/log.c index ab5fcc6..2c619c9 100644 --- a/src/ddsrt/tests/log.c +++ b/src/ddsrt/tests/log.c @@ -115,6 +115,14 @@ static void copy(void *ptr, const dds_log_data_t *data) *(char **)ptr = ddsrt_strdup(data->message); } +static void reset(void) +{ + /* Reset log internals to default. */ + dds_set_log_mask(DDS_LC_ERROR | DDS_LC_WARNING); + dds_set_trace_sink(NULL, NULL); + dds_set_log_sink(NULL, NULL); +} + static void setup(void) { fh = fmemopen(NULL, 1024, "wb+"); @@ -123,6 +131,7 @@ static void setup(void) static void teardown(void) { + reset(); (void)fclose(fh); } @@ -178,7 +187,7 @@ CU_Test(dds_log, same_file, .init=setup, .fini=teardown) /* The sinks are considered to be the same only if the callback and userdata both are an exact match. If the userdata is different, the function should be called twice for log messages. */ -CU_Test(dds_log, same_sink_function) +CU_Test(dds_log, same_sink_function, .fini=reset) { int log_cnt = 0, trace_cnt = 0; @@ -190,7 +199,7 @@ CU_Test(dds_log, same_sink_function) CU_ASSERT_EQUAL(trace_cnt, 1); } -CU_Test(dds_log, exact_same_sink) +CU_Test(dds_log, exact_same_sink, .fini=reset) { int cnt = 0; @@ -266,7 +275,7 @@ CU_Test(dds_log, no_sink, .init=setup, .fini=teardown) /* A newline terminates the message. Until that a newline is encountered, the messages must be concatenated in the buffer. The newline is replaced by a NULL byte if it is flushed to a sink. */ -CU_Test(dds_log, newline_terminates) +CU_Test(dds_log, newline_terminates, .fini=reset) { char *msg = NULL; @@ -282,10 +291,9 @@ CU_Test(dds_log, newline_terminates) } /* Nothing must be written unless a category is enabled. */ -CU_Test(dds_log, disabled_categories_discarded) +CU_Test(dds_log, disabled_categories_discarded, .fini=reset) { char *msg = NULL; - dds_set_log_sink(©, &msg); DDS_INFO("foobar\n"); CU_ASSERT_PTR_NULL_FATAL(msg); @@ -336,7 +344,7 @@ static uint32_t run(void *ptr) /* Log and trace sinks can be changed at runtime. However, the operation must be synchronous! Verify the dds_set_log_sink blocks while other threads reside in the log or trace sinks. */ -CU_Test(dds_log, synchronous_sink_changes) +CU_Test(dds_log, synchronous_sink_changes, .fini=reset) { struct arg arg; dds_time_t diff, stamp; From 638cab92918ef79e67042bd85a8fd6c1e1c2c43c Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 2 Apr 2019 14:11:21 +0200 Subject: [PATCH 008/178] ignore all-zero durability service QoS in SEDP For compatibility with TwinOaks CoreDX, ignore an all-zero durability service QoS received over SEDP for volatile and transient-local endpoints. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_plist.c | 102 ++++++++++++++++++++++++++++++++---- src/docs/config.rst | 20 +++---- 2 files changed, 100 insertions(+), 22 deletions(-) diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 99c7f12..8ee2ccd 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -593,6 +593,11 @@ static void bswap_history_qospolicy (nn_history_qospolicy_t *q) q->depth = bswap4 (q->depth); } +static int history_qospolicy_allzero (const nn_history_qospolicy_t *q) +{ + return q->kind == NN_KEEP_LAST_HISTORY_QOS && q->depth == 0; +} + int validate_history_qospolicy (const nn_history_qospolicy_t *q) { /* Validity of history setting and of resource limits are dependent, @@ -630,6 +635,11 @@ static void bswap_resource_limits_qospolicy (nn_resource_limits_qospolicy_t *q) q->max_samples_per_instance = bswap4 (q->max_samples_per_instance); } +static int resource_limits_qospolicy_allzero (const nn_resource_limits_qospolicy_t *q) +{ + return q->max_samples == 0 && q->max_instances == 0 && q->max_samples_per_instance == 0; +} + int validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q) { const int unlimited = NN_DDS_LENGTH_UNLIMITED; @@ -707,9 +717,18 @@ static void bswap_durability_service_qospolicy (nn_durability_service_qospolicy_ bswap_resource_limits_qospolicy (&q->resource_limits); } -int validate_durability_service_qospolicy (const nn_durability_service_qospolicy_t *q) +static int durability_service_qospolicy_allzero (const nn_durability_service_qospolicy_t *q) +{ + return (history_qospolicy_allzero (&q->history) && + resource_limits_qospolicy_allzero (&q->resource_limits) && + q->service_cleanup_delay.seconds == 0 && q->service_cleanup_delay.fraction == 0); +} + +static int validate_durability_service_qospolicy_acceptzero (const nn_durability_service_qospolicy_t *q, bool acceptzero) { int res; + if (acceptzero && durability_service_qospolicy_allzero (q)) + return 0; if ((res = validate_duration (&q->service_cleanup_delay)) < 0) { DDS_TRACE("plist/validate_durability_service_qospolicy: duration invalid\n"); @@ -723,6 +742,11 @@ int validate_durability_service_qospolicy (const nn_durability_service_qospolicy return 0; } +int validate_durability_service_qospolicy (const nn_durability_service_qospolicy_t *q) +{ + return validate_durability_service_qospolicy_acceptzero (q, false); +} + static void bswap_liveliness_qospolicy (nn_liveliness_qospolicy_t *q) { q->kind = bswap4u (q->kind); @@ -1300,8 +1324,9 @@ static int do_guid (nn_guid_t *dst, uint64_t *present, uint64_t fl, int (*valid) *dst = nn_ntoh_guid (*dst); if (valid (dst, dd) < 0) { - if (fl == PP_PARTICIPANT_GUID && vendor_is_twinoaks (dd->vendorid) && - dst->entityid.u == 0 && ! NN_STRICT_P) + /* CoreDX once upon a time used to send out PARTICIPANT_GUID parameters with a 0 entity id, but it + that has long since changed (even if I don't know exactly when) */ + if (fl == PP_PARTICIPANT_GUID && vendor_is_twinoaks (dd->vendorid) && dst->entityid.u == 0 && ! NN_STRICT_P) { DDS_LOG(DDS_LC_DISCOVERY, "plist(vendor %u.%u): rewriting invalid participant guid %x:%x:%x:%x\n", dd->vendorid.id[0], dd->vendorid.id[1], PGUID (*dst)); @@ -1523,7 +1548,6 @@ static int init_one_parameter } \ return 0 Q (DURABILITY, durability); - Q (DURABILITY_SERVICE, durability_service); Q (LIVELINESS, liveliness); Q (DESTINATION_ORDER, destination_order); Q (HISTORY, history); @@ -1534,6 +1558,27 @@ static int init_one_parameter Q (TRANSPORT_PRIORITY, transport_priority); #undef Q + case PID_DURABILITY_SERVICE: + if (dd->bufsz < sizeof (nn_durability_service_qospolicy_t)) + { + DDS_TRACE("plist/init_one_parameter[pid=DURABILITY_SERVICE]: buffer too small\n"); + return ERR_INVALID; + } + else + { + nn_durability_service_qospolicy_t *q = &dest->qos.durability_service; + /* All-zero durability service is illegal, but at least CoreDX sometimes advertises + it in some harmless cases. So accept all-zero durability service, then handle it + in final_validation, where we can determine whether it really is harmless or not */ + memcpy (q, dd->buf, sizeof (*q)); + if (dd->bswap) + bswap_durability_service_qospolicy (q); + if ((res = validate_durability_service_qospolicy_acceptzero (q, true)) < 0) + return res; + dest->qos.present |= QP_DURABILITY_SERVICE; + } + return 0; + /* PID_RELIABILITY handled differently because it (formally, for static typing reasons) has a different type on the network than internally, with the transformation between the two @@ -2253,9 +2298,9 @@ nn_plist_t *nn_plist_dup (const nn_plist_t *src) return dst; } -static int final_validation (nn_plist_t *dest) +static int final_validation (nn_plist_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid) { - /* Resource limits & history are related, so if only one is given, + /* Resource limits & history are related, so if only one is given, set the other to the default, claim it has been provided & validate the combination. They can't be changed afterward, so this is a reasonable interpretation. */ @@ -2276,6 +2321,46 @@ static int final_validation (nn_plist_t *dest) if ((res = validate_history_and_resource_limits (&dest->qos.history, &dest->qos.resource_limits)) < 0) return res; } + + /* Durability service is sort-of accepted if all zeros, but only + for some protocol versions and vendors. We don't handle want + to deal with that case internally. Now that all QoS have been + parsed we know the setting of the durability QoS (the default + is always VOLATILE), and hence we can verify that the setting + is valid or delete it if irrelevant. */ + if (dest->qos.present & QP_DURABILITY_SERVICE) + { + const nn_durability_kind_t durkind = (dest->qos.present & QP_DURABILITY) ? dest->qos.durability.kind : NN_VOLATILE_DURABILITY_QOS; + bool acceptzero; + /* Use a somewhat convoluted rule to decide whether or not to + "accept" an all-zero durability service setting, to find a + reasonable mix of strictness and compatibility */ + if (protocol_version_is_newer (protocol_version)) + acceptzero = true; + else if (NN_STRICT_P) + acceptzero = vendor_is_twinoaks (vendorid); + else + acceptzero = !vendor_is_eclipse (vendorid); + switch (durkind) + { + case NN_VOLATILE_DURABILITY_QOS: + case NN_TRANSIENT_LOCAL_DURABILITY_QOS: + /* pretend we never saw it if it is all zero */ + if (acceptzero && durability_service_qospolicy_allzero (&dest->qos.durability_service)) + dest->qos.present &= ~QP_DURABILITY_SERVICE; + break; + case NN_TRANSIENT_DURABILITY_QOS: + case NN_PERSISTENT_DURABILITY_QOS: + break; + } + /* if it is still present, it must be valid */ + if (dest->qos.present & QP_DURABILITY_SERVICE) + { + int res; + if ((res = validate_durability_service_qospolicy (&dest->qos.durability_service)) < 0) + return res; + } + } return 0; } @@ -2341,10 +2426,9 @@ int nn_plist_init_frommsg length = (unsigned short) (dd.bswap ? bswap2u (par->length) : par->length); if (pid == PID_SENTINEL) { - /* Sentinel terminates list, the length is ignored, DDSI - 9.4.2.11. */ + /* Sentinel terminates list, the length is ignored, DDSI 9.4.2.11. */ DDS_LOG(DDS_LC_PLIST, "%4x PID %x\n", (unsigned) (pl - src->buf), pid); - if ((res = final_validation (dest)) < 0) + if ((res = final_validation (dest, src->protocol_version, src->vendorid)) < 0) { nn_plist_fini (dest); return ERR_INVALID; diff --git a/src/docs/config.rst b/src/docs/config.rst index 7223357..bd8b182 100644 --- a/src/docs/config.rst +++ b/src/docs/config.rst @@ -1117,20 +1117,14 @@ OpenSplice. Compatibility issues with TwinOaks ---------------------------------- -Interoperability with TwinOaks CoreDX require (or used to require at some point in the -past): +In the default configuration there should be no interoperability issues with TwinOaks CoreDX, +although there is the aforementioned difference in interpretation of the meaning of the +‘autodispose_unregistered_instances’ QoS on the writer. + +Interoperability with very old versions of CoreDX may require setting: + ``Compatibility/ManySocketsMode``: *true* -+ ``Compatibility/StandardsConformance``: *lax* -+ ``Compatibility/AckNackNumbitsEmptySet``: *0* + ``Compatibility/ExplicitlyPublishQosSetToDefault``: *true* -The ``ManySocketsMode`` option needed to be changed from the default, to ensure that -each domain participant has a unique locator; this was needed because TwinOaks CoreDX -DDS did not include the full GUID of a reader or writer if it needs to address just one, -but this is probably no longer the case. Note that the (old) behaviour of TwinOaks -CoreDX DDS has always been allowed by the specification. - -The ``Compatibility/ExplicitlyPublishQosSetToDefault`` settings work around TwinOaks -CoreDX DDS’ use of incorrect default values for some of the QoS settings if they are not -explicitly supplied during discovery. It may be that this is no longer the case. +The exact version number of CoreDX starting with which these settings are no longer needed is +unknown, but it has certainly not been needed for several years. From 63a5c87baf7dd6bb99f67c37fc659ce77dd4e23e Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Mon, 1 Apr 2019 12:03:09 +0200 Subject: [PATCH 009/178] Fix format strings and signatures for fixed size integers Signed-off-by: Jeroen Koekkoek --- src/core/CMakeLists.txt | 2 + src/core/ddsc/src/dds_write.c | 8 +- src/core/ddsi/include/dds/ddsi/ddsi_tran.h | 6 + src/core/ddsi/include/dds/ddsi/q_bitset.h | 23 +-- src/core/ddsi/include/dds/ddsi/q_error.h | 22 +-- src/core/ddsi/include/dds/ddsi/q_time.h | 6 +- src/core/ddsi/src/ddsi_ipaddr.c | 4 +- src/core/ddsi/src/ddsi_tcp.c | 6 +- src/core/ddsi/src/ddsi_udp.c | 2 +- src/core/ddsi/src/q_bitset_inlines.c | 10 +- src/core/ddsi/src/q_config.c | 6 +- src/core/ddsi/src/q_ddsi_discovery.c | 10 +- src/core/ddsi/src/q_entity.c | 36 ++-- src/core/ddsi/src/q_lease.c | 4 +- src/core/ddsi/src/q_nwif.c | 6 +- src/core/ddsi/src/q_plist.c | 206 ++++++++++----------- src/core/ddsi/src/q_receive.c | 24 +-- src/core/ddsi/src/q_security.c | 2 +- src/core/ddsi/src/q_servicelease.c | 2 +- src/core/ddsi/src/q_sockwaitset.c | 2 +- src/core/ddsi/src/q_thread.c | 2 +- src/core/ddsi/src/q_time.c | 12 +- src/core/ddsi/src/q_transmit.c | 12 +- src/core/ddsi/src/q_xevent.c | 2 +- src/core/ddsi/src/q_xmsg.c | 4 +- src/core/xtests/rhc_torture.c | 2 +- src/ddsrt/include/dds/ddsrt/misc.h | 2 +- src/ddsrt/include/dds/ddsrt/sockets.h | 8 +- src/examples/helloworld/publisher.c | 2 +- src/examples/helloworld/subscriber.c | 2 +- src/examples/throughput/publisher.c | 2 +- src/tools/ddsls/ddsls.c | 6 +- src/tools/pubsub/common.c | 4 +- src/tools/pubsub/pubsub.c | 24 +-- src/util/CMakeLists.txt | 4 + 35 files changed, 245 insertions(+), 230 deletions(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6eb4a82..2ef2fc3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -52,6 +52,8 @@ include(ddsc/CMakeLists.txt) target_link_libraries(ddsc PRIVATE util) target_link_libraries(ddsc PRIVATE ddsrt) +target_compile_definitions( + ddsc PUBLIC $>) target_include_directories( ddsc PUBLIC $>) diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 969c6f3..3f3bb5e 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -185,10 +185,10 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam if (!config.whc_batch) nn_xpack_send (wr->m_xp, false); ret = DDS_RETCODE_OK; - } else if (w_rc == ERR_TIMEOUT) { + } else if (w_rc == Q_ERR_TIMEOUT) { DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n"); ret = DDS_ERRNO (DDS_RETCODE_TIMEOUT); - } else if (w_rc == ERR_INVALID_DATA) { + } else if (w_rc == Q_ERR_INVALID_DATA) { DDS_ERROR ("Invalid data provided\n"); ret = DDS_ERRNO (DDS_RETCODE_ERROR); } else { @@ -224,10 +224,10 @@ dds_return_t dds_writecdr_impl_lowlevel (struct writer *ddsi_wr, struct nn_xpack if (!config.whc_batch && xp != NULL) nn_xpack_send (xp, false); ret = DDS_RETCODE_OK; - } else if (w_rc == ERR_TIMEOUT) { + } else if (w_rc == Q_ERR_TIMEOUT) { DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n"); ret = DDS_ERRNO(DDS_RETCODE_TIMEOUT); - } else if (w_rc == ERR_INVALID_DATA) { + } else if (w_rc == Q_ERR_INVALID_DATA) { DDS_ERROR ("Invalid data provided\n"); ret = DDS_ERRNO (DDS_RETCODE_ERROR); } else { diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_tran.h b/src/core/ddsi/include/dds/ddsi/ddsi_tran.h index 7946ca9..fa10474 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_tran.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_tran.h @@ -26,6 +26,12 @@ #define DDSI_TRAN_ON_CONNECT 0x0001 +#if DDSRT_HAVE_IPV6 == 1 +# define DDSI_LOCATORSTRLEN INET6_ADDRSTRLEN_EXTENDED +#else +# define DDSI_LOCATORSTRLEN INET_ADDRSTRLEN_EXTENDED +#endif + /* Core types */ typedef struct ddsi_tran_base * ddsi_tran_base_t; diff --git a/src/core/ddsi/include/dds/ddsi/q_bitset.h b/src/core/ddsi/include/dds/ddsi/q_bitset.h index efe9ba0..ec81027 100644 --- a/src/core/ddsi/include/dds/ddsi/q_bitset.h +++ b/src/core/ddsi/include/dds/ddsi/q_bitset.h @@ -13,41 +13,42 @@ #define NN_BITSET_H #include +#include #include #include "dds/ddsi/q_unused.h" -inline int nn_bitset_isset (unsigned numbits, const unsigned *bits, unsigned idx) +inline int nn_bitset_isset (uint32_t numbits, const uint32_t *bits, uint32_t idx) { - return idx < numbits && (bits[idx/32] & (1u << (31 - (idx%32)))); + return idx < numbits && (bits[idx/32] & (UINT32_C(1) << (31 - (idx%32)))); } -inline void nn_bitset_set (UNUSED_ARG_NDEBUG (unsigned numbits), unsigned *bits, unsigned idx) +inline void nn_bitset_set (UNUSED_ARG_NDEBUG (uint32_t numbits), uint32_t *bits, uint32_t idx) { assert (idx < numbits); - bits[idx/32] |= 1u << (31 - (idx%32)); + bits[idx/32] |= UINT32_C(1) << (31 - (idx%32)); } -inline void nn_bitset_clear (UNUSED_ARG_NDEBUG (unsigned numbits), unsigned *bits, unsigned idx) +inline void nn_bitset_clear (UNUSED_ARG_NDEBUG (uint32_t numbits), uint32_t *bits, uint32_t idx) { assert (idx < numbits); - bits[idx/32] &= ~(1u << (31 - (idx%32))); + bits[idx/32] &= ~(UINT32_C(1) << (31 - (idx%32))); } -inline void nn_bitset_zero (unsigned numbits, unsigned *bits) +inline void nn_bitset_zero (uint32_t numbits, uint32_t *bits) { memset (bits, 0, 4 * ((numbits + 31) / 32)); } -inline void nn_bitset_one (unsigned numbits, unsigned *bits) +inline void nn_bitset_one (uint32_t numbits, uint32_t *bits) { memset (bits, 0xff, 4 * ((numbits + 31) / 32)); /* clear bits "accidentally" set */ { - const unsigned k = numbits / 32; - const unsigned n = numbits % 32; - bits[k] &= ~(~0u >> n); + const uint32_t k = numbits / 32; + const uint32_t n = numbits % 32; + bits[k] &= ~(~UINT32_C(0) >> n); } } diff --git a/src/core/ddsi/include/dds/ddsi/q_error.h b/src/core/ddsi/include/dds/ddsi/q_error.h index c915b12..8c4f840 100644 --- a/src/core/ddsi/include/dds/ddsi/q_error.h +++ b/src/core/ddsi/include/dds/ddsi/q_error.h @@ -12,16 +12,16 @@ #ifndef NN_ERROR_H #define NN_ERROR_H -#define ERR_UNSPECIFIED -1 -#define ERR_INVALID -2 -#define ERR_OUT_OF_MEMORY -3 -#define ERR_ENTITY_EXISTS -4 -#define ERR_UNKNOWN_ENTITY -5 -#define ERR_OUT_OF_IDS -6 -#define ERR_INVALID_DATA -7 -#define ERR_BUSY -8 -#define ERR_NO_ADDRESS -9 -#define ERR_TIMEOUT -10 -#define ERR_INCOMPATIBLE -11 +#define Q_ERR_UNSPECIFIED -1 +#define Q_ERR_INVALID -2 +#define Q_ERR_OUT_OF_MEMORY -3 +#define Q_ERR_ENTITY_EXISTS -4 +#define Q_ERR_UNKNOWN_ENTITY -5 +#define Q_ERR_OUT_OF_IDS -6 +#define Q_ERR_INVALID_DATA -7 +#define Q_ERR_BUSY -8 +#define Q_ERR_NO_ADDRESS -9 +#define Q_ERR_TIMEOUT -10 +#define Q_ERR_INCOMPATIBLE -11 #endif /* NN_ERROR_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_time.h b/src/core/ddsi/include/dds/ddsi/q_time.h index 8048cfd..5c89cfa 100644 --- a/src/core/ddsi/include/dds/ddsi/q_time.h +++ b/src/core/ddsi/include/dds/ddsi/q_time.h @@ -53,9 +53,9 @@ int valid_ddsi_timestamp (nn_ddsi_time_t t); DDS_EXPORT nn_wctime_t now (void); /* wall clock time */ DDS_EXPORT nn_mtime_t now_mt (void); /* monotonic time */ DDS_EXPORT nn_etime_t now_et (void); /* elapsed time */ -DDS_EXPORT void mtime_to_sec_usec (int * __restrict sec, int * __restrict usec, nn_mtime_t t); -DDS_EXPORT void wctime_to_sec_usec (int * __restrict sec, int * __restrict usec, nn_wctime_t t); -DDS_EXPORT void etime_to_sec_usec (int * __restrict sec, int * __restrict usec, nn_etime_t t); +DDS_EXPORT void mtime_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, nn_mtime_t t); +DDS_EXPORT void wctime_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, nn_wctime_t t); +DDS_EXPORT void etime_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, nn_etime_t t); DDS_EXPORT nn_mtime_t mtime_round_up (nn_mtime_t t, int64_t round); DDS_EXPORT nn_mtime_t add_duration_to_mtime (nn_mtime_t t, int64_t d); DDS_EXPORT nn_wctime_t add_duration_to_wctime (nn_wctime_t t, int64_t d); diff --git a/src/core/ddsi/src/ddsi_ipaddr.c b/src/core/ddsi/src/ddsi_ipaddr.c index dc84dc7..c124b89 100644 --- a/src/core/ddsi/src/ddsi_ipaddr.c +++ b/src/core/ddsi/src/ddsi_ipaddr.c @@ -131,7 +131,7 @@ char *ddsi_ipaddr_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_ if (with_port) { pos = strlen (dst); assert(pos <= sizeof_dst); - snprintf (dst + pos, sizeof_dst - pos, ":%d", loc->port); + snprintf (dst + pos, sizeof_dst - pos, ":%"PRIu32, loc->port); } break; #if DDSRT_HAVE_IPV6 @@ -141,7 +141,7 @@ char *ddsi_ipaddr_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_ pos = strlen (dst); if (with_port) { assert(pos <= sizeof_dst); - snprintf (dst + pos, sizeof_dst - pos, "]:%u", loc->port); + snprintf (dst + pos, sizeof_dst - pos, "]:%"PRIu32, loc->port); } else { snprintf (dst + pos, sizeof_dst - pos, "]"); } diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 4309baf..2bb6576 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -390,7 +390,7 @@ static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s { dds_retcode_t rc; ddsi_tcp_conn_t tcp = (ddsi_tcp_conn_t) conn; - ssize_t (*rd) (ddsi_tcp_conn_t, void *, size_t, int * err) = ddsi_tcp_conn_read_plain; + ssize_t (*rd) (ddsi_tcp_conn_t, void *, size_t, dds_retcode_t * err) = ddsi_tcp_conn_read_plain; size_t pos = 0; ssize_t n; @@ -467,7 +467,7 @@ static ssize_t ddsi_tcp_conn_write_ssl (ddsi_tcp_conn_t conn, const void * buf, static ssize_t ddsi_tcp_block_write ( - ssize_t (*wr) (ddsi_tcp_conn_t, const void *, size_t, int *), + ssize_t (*wr) (ddsi_tcp_conn_t, const void *, size_t, dds_retcode_t *), ddsi_tcp_conn_t conn, const void * buf, size_t sz @@ -654,7 +654,7 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const nn_locator_t *d if (piecewise) { - ssize_t (*wr) (ddsi_tcp_conn_t, const void *, size_t, int *) = ddsi_tcp_conn_write_plain; + ssize_t (*wr) (ddsi_tcp_conn_t, const void *, size_t, dds_retcode_t *) = ddsi_tcp_conn_write_plain; int i = 0; #ifdef DDSI_INCLUDE_SSL if (ddsi_tcp_ssl_plugin.write) diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 0234c8f..a228097 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -490,7 +490,7 @@ static char *ddsi_udp_locator_to_string (ddsi_tran_factory_t tran, char *dst, si pos += (size_t)cnt; } if (with_port && pos < sizeof_dst) { - snprintf (dst + pos, sizeof_dst - pos, ":%d", loc->port); + snprintf (dst + pos, sizeof_dst - pos, ":%"PRIu32, loc->port); } return dst; } diff --git a/src/core/ddsi/src/q_bitset_inlines.c b/src/core/ddsi/src/q_bitset_inlines.c index 89d4b34..dbb9364 100644 --- a/src/core/ddsi/src/q_bitset_inlines.c +++ b/src/core/ddsi/src/q_bitset_inlines.c @@ -11,9 +11,9 @@ */ #include "dds/ddsi/q_bitset.h" -extern inline int nn_bitset_isset (unsigned numbits, const unsigned *bits, unsigned idx); -extern inline void nn_bitset_set (unsigned numbits, unsigned *bits, unsigned idx); -extern inline void nn_bitset_clear (unsigned numbits, unsigned *bits, unsigned idx); -extern inline void nn_bitset_zero (unsigned numbits, unsigned *bits); -extern inline void nn_bitset_one (unsigned numbits, unsigned *bits); +extern inline int nn_bitset_isset (uint32_t numbits, const uint32_t *bits, uint32_t idx); +extern inline void nn_bitset_set (uint32_t numbits, uint32_t *bits, uint32_t idx); +extern inline void nn_bitset_clear (uint32_t numbits, uint32_t *bits, uint32_t idx); +extern inline void nn_bitset_zero (uint32_t numbits, uint32_t *bits); +extern inline void nn_bitset_one (uint32_t numbits, uint32_t *bits); diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 596fb3e..07ddc4b 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -116,7 +116,7 @@ static const uint32_t xcheck_codes[] = { /* We want the tracing/verbosity settings to be fixed while parsing the configuration, so we update this variable instead. */ -static unsigned enabled_logcats; +static uint32_t enabled_logcats; static int cfgst_node_cmp(const void *va, const void *vb); static const ut_avlTreedef_t cfgst_found_treedef = @@ -1827,7 +1827,7 @@ static int uf_maybe_int32(struct cfgst *cfgst, void *parent, struct cfgelem cons elem->isdefault = 1; elem->value = 0; return 1; - } else if ( sscanf(value, "%d%n", &elem->value, &pos) == 1 && value[pos] == 0 ) { + } else if ( sscanf(value, "%"PRId32"%n", &elem->value, &pos) == 1 && value[pos] == 0 ) { elem->isdefault = 0; return 1; } else { @@ -1971,7 +1971,7 @@ static int uf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const * elem->isdefault = 1; elem->value = 0; return 1; - } else if (sscanf(value, "%d%n", &elem->value, &pos) == 1 && value[pos] == 0 && elem->value >= 0 && elem->value <= 230) { + } else if (sscanf(value, "%"PRId32"%n", &elem->value, &pos) == 1 && value[pos] == 0 && elem->value >= 0 && elem->value <= 230) { elem->isdefault = 0; return 1; } else { diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index ca34713..3f5a4b6 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -799,7 +799,7 @@ static void handle_SPDP (const struct receiver_state *rst, nn_wctime_t timestamp src.bufsz = len - 4; if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { - if (plist_ret != ERR_INCOMPATIBLE) + if (plist_ret != Q_ERR_INCOMPATIBLE) DDS_WARNING("SPDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); return; } @@ -1341,7 +1341,7 @@ static void handle_SEDP (const struct receiver_state *rst, nn_wctime_t timestamp src.bufsz = len - 4; if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { - if (plist_ret != ERR_INCOMPATIBLE) + if (plist_ret != Q_ERR_INCOMPATIBLE) DDS_WARNING("SEDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); return; } @@ -1469,7 +1469,7 @@ static void handle_SEDP_CM (const struct receiver_state *rst, nn_entityid_t wr_e src.bufsz = len - 4; if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { - if (plist_ret != ERR_INCOMPATIBLE) + if (plist_ret != Q_ERR_INCOMPATIBLE) DDS_WARNING("SEDP_CM (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); return; } @@ -1631,7 +1631,7 @@ static void handle_SEDP_GROUP (const struct receiver_state *rst, nn_wctime_t tim src.bufsz = len - 4; if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { - if (plist_ret != ERR_INCOMPATIBLE) + if (plist_ret != Q_ERR_INCOMPATIBLE) DDS_WARNING("SEDP_GROUP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); return; } @@ -1754,7 +1754,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str src.bufsz = NN_RDATA_PAYLOAD_OFF (fragchain) - qos_offset; if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH, 0, &src)) < 0) { - if (plist_ret != ERR_INCOMPATIBLE) + if (plist_ret != Q_ERR_INCOMPATIBLE) DDS_WARNING("data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": invalid inline qos\n", src.vendorid.id[0], src.vendorid.id[1], PGUID (srcguid), sampleinfo->seq); goto done_upd_deliv; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 39e15c2..d83f225 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -381,7 +381,7 @@ int pp_allocate_entityid(nn_entityid_t *id, unsigned kind, struct participant *p else { DDS_ERROR("pp_allocate_entityid(%x:%x:%x:%x): all ids in use\n", PGUID(pp->e.guid)); - ret = ERR_OUT_OF_IDS; + ret = Q_ERR_OUT_OF_IDS; } ddsrt_mutex_unlock (&pp->e.lock); return ret; @@ -412,7 +412,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis used to exist, but is currently being deleted and we're trying to recreate it. */ if (ephash_lookup_participant_guid (ppguid) != NULL) - return ERR_ENTITY_EXISTS; + return Q_ERR_ENTITY_EXISTS; if (config.max_participants == 0) { @@ -432,7 +432,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis { ddsrt_mutex_unlock (&gv.participant_set_lock); DDS_ERROR("new_participant(%x:%x:%x:%x, %x) failed: max participants reached\n", PGUID (*ppguid), flags); - return ERR_OUT_OF_IDS; + return Q_ERR_OUT_OF_IDS; } } @@ -659,7 +659,7 @@ int new_participant (nn_guid_t *p_ppguid, unsigned flags, const nn_plist_t *plis if (gv.next_ppguid.prefix.u[2]++ == ~0u) { ddsrt_mutex_unlock (&gv.privileged_pp_lock); - return ERR_OUT_OF_IDS; + return Q_ERR_OUT_OF_IDS; } ddsrt_mutex_unlock (&gv.privileged_pp_lock); *p_ppguid = ppguid; @@ -854,7 +854,7 @@ int delete_participant (const struct nn_guid *ppguid) { struct participant *pp; if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; ddsi_plugin.builtintopic_write (&pp->e, now(), false); remember_deleted_participant_guid (&pp->e.guid); ephash_remove_participant_guid (pp); @@ -1105,7 +1105,7 @@ static void rebuild_trace_covered(int nreaders, int nlocs, const nn_locator_t *l int i, j; for (i = 0; i < nlocs; i++) { - char buf[INET6_ADDRSTRLEN_EXTENDED]; + char buf[DDSI_LOCATORSTRLEN]; ddsi_locator_to_string(buf, sizeof(buf), &locs[i]); DDS_LOG(DDS_LC_DISCOVERY, " loc %2d = %-20s %2d {", i, buf, locs_nrds[i]); for (j = 0; j < nreaders; j++) @@ -1140,7 +1140,7 @@ static int rebuild_select(int nlocs, const nn_locator_t *locs, const int *locs_n static void rebuild_add(struct addrset *newas, int locidx, int nreaders, int nlocs, const nn_locator_t *locs, const int8_t *covered) { - char str[INET6_ADDRSTRLEN_EXTENDED]; + char str[DDSI_LOCATORSTRLEN]; if (locs[locidx].kind != NN_LOCATOR_KIND_UDPv4MCGEN) { ddsi_locator_to_string(str, sizeof(str), &locs[locidx]); @@ -2987,7 +2987,7 @@ int delete_writer_nolinger (const struct nn_guid *guid) if ((wr = ephash_lookup_writer_guid (guid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid %x:%x:%x:%x) ...\n", PGUID (*guid)); ddsrt_mutex_lock (&wr->e.lock); @@ -3010,7 +3010,7 @@ int delete_writer (const struct nn_guid *guid) if ((wr = ephash_lookup_writer_guid (guid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) ...\n", PGUID (*guid)); ddsrt_mutex_lock (&wr->e.lock); @@ -3029,12 +3029,12 @@ int delete_writer (const struct nn_guid *guid) else { nn_mtime_t tsched; - int tsec, tusec; + int32_t tsec, tusec; writer_set_state (wr, WRST_LINGERING); ddsrt_mutex_unlock (&wr->e.lock); tsched = add_duration_to_mtime (now_mt (), config.writer_linger_duration); mtime_to_sec_usec (&tsec, &tusec, tsched); - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) - unack'ed samples, will delete when ack'd or at t = %d.%06d\n", + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) - unack'ed samples, will delete when ack'd or at t = %"PRId32".%06"PRId32"\n", PGUID (*guid), tsec, tusec); qxev_delete_writer (tsched, &wr->e.guid); } @@ -3388,7 +3388,7 @@ int delete_reader (const struct nn_guid *guid) if ((rd = ephash_lookup_reader_guid (guid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } if (rd->rhc) { @@ -3900,7 +3900,7 @@ int delete_proxy_participant_by_guid (const struct nn_guid * guid, nn_wctime_t t { ddsrt_mutex_unlock (&gv.lock); DDS_LOG(DDS_LC_DISCOVERY, "- unknown\n"); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } DDS_LOG(DDS_LC_DISCOVERY, "- deleting\n"); ddsi_plugin.builtintopic_write (&ppt->e, timestamp, false); @@ -3955,7 +3955,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct break; default: DDS_WARNING("new_proxy_group: unrecognised entityid: %x\n", guid->entityid.u); - return ERR_INVALID_DATA; + return Q_ERR_INVALID_DATA; } ddsrt_mutex_lock (&proxypp->e.lock); if ((pgroup = ut_avlLookupIPath (&proxypp_groups_treedef, &proxypp->groups, guid, &ipath)) != NULL) @@ -4084,7 +4084,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, if ((proxypp = ephash_lookup_proxy_participant_guid (ppguid)) == NULL) { DDS_WARNING("new_proxy_writer(%x:%x:%x:%x): proxy participant unknown\n", PGUID (*guid)); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } pwr = ddsrt_malloc (sizeof (*pwr)); @@ -4277,7 +4277,7 @@ int delete_proxy_writer (const struct nn_guid *guid, nn_wctime_t timestamp, int { ddsrt_mutex_unlock (&gv.lock); DDS_LOG(DDS_LC_DISCOVERY, "- unknown\n"); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } /* Set "deleting" flag in particular for Lite, to signal to the receive path it can't trust rdary[] anymore, which is because removing the proxy writer from the hash @@ -4310,7 +4310,7 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, if ((proxypp = ephash_lookup_proxy_participant_guid (ppguid)) == NULL) { DDS_WARNING("new_proxy_reader(%x:%x:%x:%x): proxy participant unknown\n", PGUID (*guid)); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } prd = ddsrt_malloc (sizeof (*prd)); @@ -4408,7 +4408,7 @@ int delete_proxy_reader (const struct nn_guid *guid, nn_wctime_t timestamp, int { ddsrt_mutex_unlock (&gv.lock); DDS_LOG(DDS_LC_DISCOVERY, "- unknown\n"); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } ddsi_plugin.builtintopic_write (&prd->e, timestamp, false); ephash_remove_proxy_reader_guid (prd); diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index 438c0bf..1dac32c 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -164,14 +164,14 @@ void lease_renew (struct lease *l, nn_etime_t tnowE) if (did_update && (dds_get_log_mask() & DDS_LC_TRACE)) { - int tsec, tusec; + int32_t tsec, tusec; DDS_TRACE(" L("); if (l->entity->guid.entityid.u == NN_ENTITYID_PARTICIPANT) DDS_TRACE(":%x", l->entity->guid.entityid.u); else DDS_TRACE("%x:%x:%x:%x", PGUID (l->entity->guid)); etime_to_sec_usec (&tsec, &tusec, tend_new); - DDS_TRACE(" %d.%06d)", tsec, tusec); + DDS_TRACE(" %"PRId32".%06"PRId32")", tsec, tusec); } } diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index d6a7109..66c49bf 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -39,7 +39,7 @@ static void print_sockerror (const char *msg) unsigned locator_to_hopefully_unique_uint32 (const nn_locator_t *src) { - unsigned id; + unsigned id = 0; if (src->kind == NN_LOCATOR_KIND_UDPv4 || src->kind == NN_LOCATOR_KIND_TCPv4) memcpy (&id, src->address + 12, sizeof (id)); else @@ -93,7 +93,7 @@ static void set_socket_nodelay (ddsrt_socket_t sock) static int set_rcvbuf (ddsrt_socket_t socket) { uint32_t ReceiveBufferSize; - uint32_t optlen = (uint32_t) sizeof (ReceiveBufferSize); + socklen_t optlen = (socklen_t) sizeof (ReceiveBufferSize); uint32_t socket_min_rcvbuf_size; if (config.socket_min_rcvbuf_size.isdefault) socket_min_rcvbuf_size = 1048576; @@ -137,7 +137,7 @@ static int set_rcvbuf (ddsrt_socket_t socket) static int set_sndbuf (ddsrt_socket_t socket) { unsigned SendBufferSize; - uint32_t optlen = (uint32_t) sizeof(SendBufferSize); + socklen_t optlen = (socklen_t) sizeof(SendBufferSize); if (ddsrt_getsockopt(socket, SOL_SOCKET, SO_SNDBUF,(char *)&SendBufferSize, &optlen) != DDS_RETCODE_OK) { print_sockerror ("get SO_SNDBUF"); diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 8ee2ccd..ad97995 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -92,18 +92,18 @@ static int validate_string (const struct dd *dd, size_t *len) if (dd->bufsz < sizeof (struct cdrstring)) { DDS_TRACE("plist/validate_string: buffer too small (header)\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } *len = dd->bswap ? bswap4u (x->length) : x->length; if (*len < 1 || *len > dd->bufsz - offsetof (struct cdrstring, contents)) { DDS_TRACE("plist/validate_string: length %" PRIuSIZE " out of range\n", *len); - return ERR_INVALID; + return Q_ERR_INVALID; } if (x->contents[*len-1] != 0) { DDS_TRACE("plist/validate_string: terminator missing\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } return 0; } @@ -142,10 +142,10 @@ static int validate_octetseq (const struct dd *dd, size_t *len) { const struct cdroctetseq *x = (const struct cdroctetseq *) dd->buf; if (dd->bufsz < offsetof (struct cdroctetseq, value)) - return ERR_INVALID; + return Q_ERR_INVALID; *len = dd->bswap ? bswap4u (x->len) : x->len; if (*len > dd->bufsz - offsetof (struct cdroctetseq, value)) - return ERR_INVALID; + return Q_ERR_INVALID; return 0; } @@ -193,7 +193,7 @@ static int validate_stringseq (const struct dd *dd) if (dd->bufsz < sizeof (int)) { DDS_TRACE("plist/validate_stringseq: buffer too small (header)\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&n, seq, sizeof (n)); if (dd->bswap) @@ -202,7 +202,7 @@ static int validate_stringseq (const struct dd *dd) if (n < 0) { DDS_TRACE("plist/validate_stringseq: length %d out of range\n", n); - return ERR_INVALID; + return Q_ERR_INVALID; } else if (n == 0) { @@ -226,7 +226,7 @@ static int validate_stringseq (const struct dd *dd) if (i < n) { DDS_TRACE("plist/validate_stringseq: buffer too small (contents)\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } } /* Should I worry about junk between the last string & the end of @@ -248,7 +248,7 @@ static int alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) if (dd->bufsz < sizeof (int)) { DDS_TRACE("plist/alias_stringseq: buffer too small (header)\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&strseq->n, seq, sizeof (strseq->n)); if (dd->bswap) @@ -257,7 +257,7 @@ static int alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) if (strseq->n >= UINT_MAX / sizeof(*strs)) { DDS_TRACE("plist/alias_stringseq: length %u out of range\n", strseq->n); - return ERR_INVALID; + return Q_ERR_INVALID; } else if (strseq->n == 0) { @@ -284,7 +284,7 @@ static int alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) if (i != strseq->n) { DDS_TRACE("plist/validate_stringseq: buffer too small (contents)\n"); - result = ERR_INVALID; + result = Q_ERR_INVALID; goto fail; } strseq->strs = strs; @@ -535,7 +535,7 @@ static int validate_time (const nn_ddsi_time_t *t) else { DDS_TRACE("plist/validate_time: invalid timestamp (%08x.%08x)\n", t->seconds, t->fraction); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -555,7 +555,7 @@ static int do_duration (nn_duration_t *q, uint64_t *present, uint64_t fl, const if (dd->bufsz < sizeof (*q)) { DDS_TRACE("plist/do_duration: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (q, dd->buf, sizeof (*q)); if (dd->bswap) @@ -582,7 +582,7 @@ int validate_durability_qospolicy (const nn_durability_qospolicy_t *q) break; default: DDS_TRACE("plist/validate_durability_qospolicy: invalid kind (%d)\n", (int) q->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } return 0; } @@ -614,7 +614,7 @@ int validate_history_qospolicy (const nn_history_qospolicy_t *q) break; default: DDS_TRACE("plist/validate_history_qospolicy: invalid kind (%d)\n", (int) q->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } /* Accept all values for depth if kind = ALL */ if (q->kind == NN_KEEP_LAST_HISTORY_QOS) @@ -622,7 +622,7 @@ int validate_history_qospolicy (const nn_history_qospolicy_t *q) if (q->depth < 1) { DDS_TRACE("plist/validate_history_qospolicy: invalid depth (%d)\n", (int) q->depth); - return ERR_INVALID; + return Q_ERR_INVALID; } } return 0; @@ -649,17 +649,17 @@ int validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q) if (q->max_samples < 1 && q->max_samples != unlimited) { DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples invalid (%d)\n", (int) q->max_samples); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->max_instances < 1 && q->max_instances != unlimited) { DDS_TRACE("plist/validate_resource_limits_qospolicy: max_instances invalid (%d)\n", (int) q->max_instances); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->max_samples_per_instance < 1 && q->max_samples_per_instance != unlimited) { DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples_per_instance invalid (%d)\n", (int) q->max_samples_per_instance); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->max_samples != unlimited && q->max_samples_per_instance != unlimited) { @@ -668,7 +668,7 @@ int validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q) if (q->max_samples < q->max_samples_per_instance) { DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples (%d) and max_samples_per_instance (%d) incompatible\n", (int) q->max_samples, (int) q->max_samples_per_instance); - return ERR_INVALID; + return Q_ERR_INVALID; } } return 0; @@ -695,7 +695,7 @@ int validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, cons if (qr->max_samples_per_instance != unlimited) { DDS_TRACE("plist/validate_history_and_resource_limits: max_samples_per_instance (%d) incompatible with KEEP_ALL policy\n", (int) qr->max_samples_per_instance); - return ERR_INVALID; + return Q_ERR_INVALID; } #endif break; @@ -703,7 +703,7 @@ int validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, cons if (qr->max_samples_per_instance != unlimited && qh->depth > qr->max_samples_per_instance) { DDS_TRACE("plist/validate_history_and_resource_limits: depth (%d) and max_samples_per_instance (%d) incompatible with KEEP_LAST policy\n", (int) qh->depth, (int) qr->max_samples_per_instance); - return ERR_INVALID; + return Q_ERR_INVALID; } break; } @@ -766,7 +766,7 @@ int validate_liveliness_qospolicy (const nn_liveliness_qospolicy_t *q) return res; default: DDS_TRACE("plist/validate_liveliness_qospolicy: invalid kind (%d)\n", (int) q->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -794,7 +794,7 @@ static int validate_xform_reliability_qospolicy (nn_reliability_qospolicy_t *qds return res; default: DDS_TRACE("plist/validate_xform_reliability_qospolicy[pedantic]: invalid kind (%d)\n", (int) qext->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } } else @@ -811,7 +811,7 @@ static int validate_xform_reliability_qospolicy (nn_reliability_qospolicy_t *qds return res; default: DDS_TRACE("plist/validate_xform_reliability_qospolicy[!pedantic]: invalid kind (%d)\n", (int) qext->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } } } @@ -830,7 +830,7 @@ int validate_destination_order_qospolicy (const nn_destination_order_qospolicy_t return 0; default: DDS_TRACE("plist/validate_destination_order_qospolicy: invalid kind (%d)\n", (int) q->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -848,7 +848,7 @@ int validate_ownership_qospolicy (const nn_ownership_qospolicy_t *q) return 0; default: DDS_TRACE("plist/validate_ownership_qospolicy: invalid kind (%d)\n", (int) q->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -877,18 +877,18 @@ int validate_presentation_qospolicy (const nn_presentation_qospolicy_t *q) break; default: DDS_TRACE("plist/validate_presentation_qospolicy: invalid access_scope (%d)\n", (int) q->access_scope); - return ERR_INVALID; + return Q_ERR_INVALID; } /* Bools must be 0 or 1, i.e., only the lsb may be set */ if (q->coherent_access & ~1) { DDS_TRACE("plist/validate_presentation_qospolicy: coherent_access invalid (%d)\n", (int) q->coherent_access); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->ordered_access & ~1) { DDS_TRACE("plist/validate_presentation_qospolicy: ordered_access invalid (%d)\n", (int) q->ordered_access); - return ERR_INVALID; + return Q_ERR_INVALID; } /* coherent_access & ordered_access are a bit irrelevant for instance presentation qos, but it appears as if their values are @@ -964,7 +964,7 @@ static int do_locator if (dd->bufsz < sizeof (loc)) { DDS_TRACE("plist/do_locator: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&loc, dd->buf, sizeof (loc)); if (dd->bswap) @@ -979,12 +979,12 @@ static int do_locator if (loc.port <= 0 || loc.port > 65535) { DDS_TRACE("plist/do_locator[kind=IPv4]: invalid port (%d)\n", (int) loc.port); - return ERR_INVALID; + return Q_ERR_INVALID; } if (!locator_address_prefix12_zero (&loc)) { DDS_TRACE("plist/do_locator[kind=IPv4]: junk in address prefix\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } break; case NN_LOCATOR_KIND_UDPv6: @@ -992,7 +992,7 @@ static int do_locator if (loc.port <= 0 || loc.port > 65535) { DDS_TRACE("plist/do_locator[kind=IPv6]: invalid port (%d)\n", (int) loc.port); - return ERR_INVALID; + return Q_ERR_INVALID; } break; case NN_LOCATOR_KIND_UDPv4MCGEN: { @@ -1002,12 +1002,12 @@ static int do_locator if (loc.port <= 0 || loc.port > 65536) { DDS_TRACE("plist/do_locator[kind=IPv4MCGEN]: invalid port (%d)\n", (int) loc.port); - return ERR_INVALID; + return Q_ERR_INVALID; } if ((int)x->base + x->count >= 28 || x->count == 0 || x->idx >= x->count) { DDS_TRACE("plist/do_locator[kind=IPv4MCGEN]: invalid base/count/idx (%u,%u,%u)\n", x->base, x->count, x->idx); - return ERR_INVALID; + return Q_ERR_INVALID; } break; } @@ -1015,12 +1015,12 @@ static int do_locator if (!locator_address_zero (&loc)) { DDS_TRACE("plist/do_locator[kind=INVALID]: junk in address\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } if (loc.port != 0) { DDS_TRACE("plist/do_locator[kind=INVALID]: junk in port\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } /* silently dropped correctly formatted "invalid" locators. */ return 0; @@ -1029,7 +1029,7 @@ static int do_locator return 0; default: DDS_TRACE("plist/do_locator: invalid kind (%d)\n", (int) loc.kind); - return NN_PEDANTIC_P ? ERR_INVALID : 0; + return NN_PEDANTIC_P ? Q_ERR_INVALID : 0; } return add_locator (ls, present, wanted, fl, &loc); } @@ -1052,7 +1052,7 @@ static int do_ipv4address (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp if (dd->bufsz < sizeof (*a)) { DDS_TRACE("plist/do_ipv4address: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } switch (fl_tmp) { @@ -1122,7 +1122,7 @@ static int do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint6 if (dd->bufsz < sizeof (*p)) { DDS_TRACE("plist/do_port: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } switch (fl_tmp) { @@ -1156,7 +1156,7 @@ static int do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint6 if (*p <= 0 || *p > 65535) { DDS_TRACE("plist/do_port: invalid port (%d)\n", (int) *p); - return ERR_INVALID; + return Q_ERR_INVALID; } dest_tmp->present |= fl_tmp; if ((dest_tmp->present & (fl_tmp | fl1_tmp)) == (fl_tmp | fl1_tmp)) @@ -1185,7 +1185,7 @@ static int valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct else { DDS_TRACE("plist/valid_participant_guid: prefix is 0 but entityid is not (%u)\n", g->entityid.u); - return ERR_INVALID; + return Q_ERR_INVALID; } } else if (g->entityid.u == NN_ENTITYID_PARTICIPANT) @@ -1195,7 +1195,7 @@ static int valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct else { DDS_TRACE("plist/valid_participant_guid: entityid not a participant entityid (%u)\n", g->entityid.u); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -1209,7 +1209,7 @@ static int valid_group_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd else { DDS_TRACE("plist/valid_group_guid: prefix is 0 but entityid is not (%u)\n", g->entityid.u); - return ERR_INVALID; + return Q_ERR_INVALID; } } else if (g->entityid.u != 0) @@ -1220,7 +1220,7 @@ static int valid_group_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd else { DDS_TRACE("plist/valid_group_guid: entityid is 0\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -1234,7 +1234,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) else { DDS_TRACE("plist/valid_endpoint_guid: prefix is 0 but entityid is not (%x)\n", g->entityid.u); - return ERR_INVALID; + return Q_ERR_INVALID; } } switch (g->entityid.u & NN_ENTITYID_SOURCE_MASK) @@ -1255,7 +1255,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) DDS_TRACE("plist/valid_endpoint_guid[src=USER,proto=%u.%u]: invalid kind (%x)\n", dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u & NN_ENTITYID_KIND_MASK); - return ERR_INVALID; + return Q_ERR_INVALID; } } case NN_ENTITYID_SOURCE_BUILTIN: @@ -1279,7 +1279,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) { DDS_TRACE("plist/valid_endpoint_guid[src=BUILTIN,proto=%u.%u]: invalid entityid (%x)\n", dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u); - return ERR_INVALID; + return Q_ERR_INVALID; } } case NN_ENTITYID_SOURCE_VENDOR: @@ -1309,7 +1309,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) } default: DDS_TRACE("plist/valid_endpoint_guid: invalid source (%x)\n", g->entityid.u); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -1318,7 +1318,7 @@ static int do_guid (nn_guid_t *dst, uint64_t *present, uint64_t fl, int (*valid) if (dd->bufsz < sizeof (*dst)) { DDS_TRACE("plist/do_guid: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (dst, dd->buf, sizeof (*dst)); *dst = nn_ntoh_guid (*dst); @@ -1334,7 +1334,7 @@ static int do_guid (nn_guid_t *dst, uint64_t *present, uint64_t fl, int (*valid) } else { - return ERR_INVALID; + return Q_ERR_INVALID; } } *present |= fl; @@ -1358,7 +1358,7 @@ static int do_prismtech_participant_version_info (nn_prismtech_participant_versi else if (dd->bufsz < NN_PRISMTECH_PARTICIPANT_VERSION_INFO_FIXED_CDRSIZE) { DDS_TRACE("plist/do_prismtech_participant_version_info[pid=PRISMTECH_PARTICIPANT_VERSION_INFO]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1393,13 +1393,13 @@ static int do_subscription_keys_qospolicy (nn_subscription_keys_qospolicy_t *q, if (dd->bufsz < 4) { DDS_TRACE("plist/do_subscription_keys: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } q->use_key_list = (unsigned char) dd->buf[0]; if (q->use_key_list != 0 && q->use_key_list != 1) { DDS_TRACE("plist/do_subscription_keys: invalid use_key_list (%d)\n", (int) q->use_key_list); - return ERR_INVALID; + return Q_ERR_INVALID; } dd1 = *dd; dd1.buf += 4; @@ -1423,7 +1423,7 @@ static int do_reader_lifespan_qospolicy (nn_reader_lifespan_qospolicy_t *q, uint if (dd->bufsz < sizeof (*q)) { DDS_TRACE("plist/do_reader_lifespan: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } *q = *((nn_reader_lifespan_qospolicy_t *) dd->buf); if (dd->bswap) @@ -1431,7 +1431,7 @@ static int do_reader_lifespan_qospolicy (nn_reader_lifespan_qospolicy_t *q, uint if (q->use_lifespan != 0 && q->use_lifespan != 1) { DDS_TRACE("plist/do_reader_lifespan: invalid use_lifespan (%d)\n", (int) q->use_lifespan); - return ERR_INVALID; + return Q_ERR_INVALID; } if ((res = validate_duration (&q->duration)) >= 0) *present |= fl; @@ -1443,13 +1443,13 @@ static int do_entity_factory_qospolicy (nn_entity_factory_qospolicy_t *q, uint64 if (dd->bufsz < sizeof (*q)) { DDS_TRACE("plist/do_entity_factory: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } q->autoenable_created_entities = dd->buf[0]; if (q->autoenable_created_entities != 0 && q->autoenable_created_entities != 1) { DDS_TRACE("plist/do_entity_factory: invalid autoenable_created_entities (%d)\n", (int) q->autoenable_created_entities); - return ERR_INVALID; + return Q_ERR_INVALID; } *present |= fl; return 0; @@ -1461,17 +1461,17 @@ int validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t * validate_duration (&q->autopurge_disposed_samples_delay) < 0) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid autopurge_nowriter_sample_delay or autopurge_disposed_samples_delay\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->autopurge_dispose_all != 0 && q->autopurge_dispose_all != 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid autopurge_dispose_all\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->enable_invalid_samples != 0 && q->enable_invalid_samples != 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid enable_invalid_samples\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } /* Don't check consistency between enable_invalid_samples and invalid_samples_mode (yet) */ switch (q->invalid_sample_visibility) @@ -1482,7 +1482,7 @@ int validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t * break; default: DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid invalid_sample_visibility\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } return 0; } @@ -1535,7 +1535,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (nn_##name_##_qospolicy_t)) \ { \ DDS_TRACE("plist/init_one_parameter[pid=%s]: buffer too small\n", #NAME_); \ - return ERR_INVALID; \ + return Q_ERR_INVALID; \ } \ else \ { \ @@ -1562,7 +1562,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (nn_durability_service_qospolicy_t)) { DDS_TRACE("plist/init_one_parameter[pid=DURABILITY_SERVICE]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1589,7 +1589,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (nn_external_reliability_qospolicy_t)) { DDS_TRACE("plist/init_one_parameter[pid=RELIABILITY]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1640,7 +1640,7 @@ static int init_one_parameter else { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: buffer too small\n"); - ret = ERR_INVALID; + ret = Q_ERR_INVALID; } if (ret >= 0) dest->qos.present |= QP_PRISMTECH_READER_DATA_LIFECYCLE; @@ -1655,7 +1655,7 @@ static int init_one_parameter if (dd->bufsz < 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else if (dd->bufsz < sizeof (*q)) { @@ -1676,13 +1676,13 @@ static int init_one_parameter if (q->autodispose_unregistered_instances & ~1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: invalid autodispose_unregistered_instances (%d)\n", (int) q->autodispose_unregistered_instances); - return ERR_INVALID; + return Q_ERR_INVALID; } if (validate_duration (&q->autounregister_instance_delay) < 0 || validate_duration (&q->autopurge_suspended_samples_delay) < 0) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: invalid autounregister_instance_delay or autopurge_suspended_samples_delay\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->qos.present |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE; return 0; @@ -1694,7 +1694,7 @@ static int init_one_parameter else if (dd->bufsz < sizeof (dest->qos.relaxed_qos_matching)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_RELAXED_QOS_MATCHING]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1703,7 +1703,7 @@ static int init_one_parameter if (rqm->value != 0 && rqm->value != 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_RELAXED_QOS_MATCHING]: invalid\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->qos.present |= QP_PRISMTECH_RELAXED_QOS_MATCHING; return 0; @@ -1715,7 +1715,7 @@ static int init_one_parameter else if (dd->bufsz < sizeof (dest->qos.synchronous_endpoint)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SYNCHRONOUS_ENDPOINT]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1724,7 +1724,7 @@ static int init_one_parameter if (q->value != 0 && q->value != 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SYNCHRONOUS_ENDPOINT]: invalid value for synchronous flag\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->qos.present |= QP_PRISMTECH_SYNCHRONOUS_ENDPOINT; return 0; @@ -1735,7 +1735,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (nn_protocol_version_t)) { DDS_TRACE("plist/init_one_parameter[pid=PROTOCOL_VERSION]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->protocol_version, dd->buf, sizeof (dest->protocol_version)); if (NN_STRICT_P && @@ -1748,14 +1748,14 @@ static int init_one_parameter DDS_TRACE("plist/init_one_parameter[pid=PROTOCOL_VERSION,mode=STRICT]: version (%u.%u) mismatch with message (%u.%u)\n", dest->protocol_version.major, dest->protocol_version.minor, dd->protocol_version.major, dd->protocol_version.minor); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->present |= PP_PROTOCOL_VERSION; return 0; case PID_VENDORID: if (dd->bufsz < sizeof (nn_vendorid_t)) - return ERR_INVALID; + return Q_ERR_INVALID; memcpy (&dest->vendorid, dd->buf, sizeof (dest->vendorid)); if (NN_STRICT_P && (dest->vendorid.id[0] != dd->vendorid.id[0] || @@ -1764,7 +1764,7 @@ static int init_one_parameter /* see PROTOCOL_VERSION */ DDS_TRACE("plist/init_one_parameter[pid=VENDORID,mode=STRICT]: vendor (%u.%u) mismatch with message (%u.%u)\n", dest->vendorid.id[0], dest->vendorid.id[1], dd->vendorid.id[0], dd->vendorid.id[1]); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->present |= PP_VENDORID; return 0; @@ -1808,7 +1808,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->expects_inline_qos)) { DDS_TRACE("plist/init_one_parameter[pid=EXPECTS_INLINE_QOS]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->expects_inline_qos = dd->buf[0]; /* boolean: only lsb may be set */ @@ -1816,7 +1816,7 @@ static int init_one_parameter { DDS_TRACE("plist/init_one_parameter[pid=EXPECTS_INLINE_QOS]: invalid expects_inline_qos (%d)\n", (int) dest->expects_inline_qos); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->present |= PP_EXPECTS_INLINE_QOS; return 0; @@ -1828,7 +1828,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->participant_manual_liveliness_count)) { DDS_TRACE("plist/init_one_parameter[pid=PARTICIPANT_MANUAL_LIVELINESS_COUNT]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->participant_manual_liveliness_count, dd->buf, sizeof (dest->participant_manual_liveliness_count)); if (dd->bswap) @@ -1862,7 +1862,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->builtin_endpoint_set)) { DDS_TRACE("plist/init_one_parameter[pid=BUILTIN_ENDPOINT_SET(%u)]: buffer too small\n", pid); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->builtin_endpoint_set, dd->buf, sizeof (dest->builtin_endpoint_set)); if (dd->bswap) @@ -1887,7 +1887,7 @@ static int init_one_parameter { DDS_TRACE("plist/init_one_parameter[pid=BUILTIN_ENDPOINT_SET(%u),mode=STRICT,proto=%u.%u]: invalid set (0x%x)\n", pid, dd->protocol_version.major, dd->protocol_version.minor, dest->builtin_endpoint_set); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->present |= PP_BUILTIN_ENDPOINT_SET; return 0; @@ -1898,7 +1898,7 @@ static int init_one_parameter else if (dd->bufsz < sizeof (dest->prismtech_builtin_endpoint_set)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_BUILTIN_ENDPOINT_SET(%u)]: buffer too small\n", pid); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1921,7 +1921,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->keyhash)) { DDS_TRACE("plist/init_one_parameter[pid=KEYHASH]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->keyhash, dd->buf, sizeof (dest->keyhash)); dest->present |= PP_KEYHASH; @@ -1931,7 +1931,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->statusinfo)) { DDS_TRACE("plist/init_one_parameter[pid=STATUSINFO]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->statusinfo, dd->buf, sizeof (dest->statusinfo)); dest->statusinfo = fromBE4u (dest->statusinfo); @@ -1942,7 +1942,7 @@ static int init_one_parameter may use them in this version of the specification */ DDS_TRACE("plist/init_one_parameter[pid=STATUSINFO,mode=STRICT,proto=%u.%u]: invalid statusinfo (0x%x)\n", dd->protocol_version.major, dd->protocol_version.minor, dest->statusinfo); - return ERR_INVALID; + return Q_ERR_INVALID; } /* Clear all bits we don't understand, then add the extended bits if present */ dest->statusinfo &= NN_STATUSINFO_STANDARDIZED; @@ -1962,7 +1962,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->coherent_set_seqno)) { DDS_TRACE("plist/init_one_parameter[pid=COHERENT_SET]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1978,7 +1978,7 @@ static int init_one_parameter if (seqno <= 0 && seqno != NN_SEQUENCE_NUMBER_UNKNOWN) { DDS_TRACE("plist/init_one_parameter[pid=COHERENT_SET]: invalid sequence number (%" PRId64 ")\n", seqno); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->present |= PP_COHERENT_SET; return 0; @@ -1999,7 +1999,7 @@ static int init_one_parameter ignore it. */ DDS_TRACE("plist/init_one_parameter[pid=ENDPOINT_GUID,mode=PEDANTIC,proto=%u.%u]: undefined pid\n", dd->protocol_version.major, dd->protocol_version.minor); - return ERR_INVALID; + return Q_ERR_INVALID; } return do_guid (&dest->endpoint_guid, &dest->present, PP_ENDPOINT_GUID, valid_endpoint_guid, dd); @@ -2056,7 +2056,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->service_type)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SERVICE_TYPE]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->service_type, dd->buf, sizeof (dest->service_type)); if (dd->bswap) @@ -2070,7 +2070,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->process_id)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_PROCESS_ID]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->process_id, dd->buf, sizeof (dest->process_id)); if (dd->bswap) @@ -2089,7 +2089,7 @@ static int init_one_parameter else if (dd->bufsz < 2*sizeof (uint32_t)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_EOTINFO]: buffer too small (1)\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -2105,7 +2105,7 @@ static int init_one_parameter if (q->n > (dd->bufsz - 2*sizeof (uint32_t)) / sizeof (nn_prismtech_eotgroup_tid_t)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_EOTINFO]: buffer too small (2)\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->n == 0) q->tids = NULL; @@ -2134,7 +2134,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->reader_favours_ssm)) { DDS_TRACE("plist/init_one_parameter[pid=READER_FAVOURS_SSM]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -2174,13 +2174,13 @@ static int init_one_parameter bugs & the buffer overflows originate! */ if (pid & PID_UNRECOGNIZED_INCOMPATIBLE_FLAG) { dest->present |= PP_INCOMPATIBLE; - return ERR_INCOMPATIBLE; + return Q_ERR_INCOMPATIBLE; } else if (pid & PID_VENDORSPECIFIC_FLAG) { return 0; } else if (!protocol_version_is_newer (dd->protocol_version) && NN_STRICT_P) { DDS_TRACE("plist/init_one_parameter[pid=%u,mode=STRICT,proto=%u.%u]: undefined paramter id\n", pid, dd->protocol_version.major, dd->protocol_version.minor); - return ERR_INVALID; + return Q_ERR_INVALID; } else { return 0; } @@ -2188,7 +2188,7 @@ static int init_one_parameter assert (0); DDS_TRACE("plist/init_one_parameter: can't happen\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } static void default_resource_limits (nn_resource_limits_qospolicy_t *q) @@ -2404,7 +2404,7 @@ int nn_plist_init_frommsg default: DDS_WARNING ("plist(vendor %u.%u): unknown encoding (%d)\n", src->vendorid.id[0], src->vendorid.id[1], src->encoding); - return ERR_INVALID; + return Q_ERR_INVALID; } nn_plist_init_empty (dest); dest->unalias_needs_bswap = dd.bswap; @@ -2431,7 +2431,7 @@ int nn_plist_init_frommsg if ((res = final_validation (dest, src->protocol_version, src->vendorid)) < 0) { nn_plist_fini (dest); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -2446,14 +2446,14 @@ int nn_plist_init_frommsg DDS_WARNING("plist(vendor %u.%u): parameter length %u out of bounds\n", src->vendorid.id[0], src->vendorid.id[1], length); nn_plist_fini (dest); - return ERR_INVALID; + return Q_ERR_INVALID; } if ((length % 4) != 0) /* DDSI 9.4.2.11 */ { DDS_WARNING("plist(vendor %u.%u): parameter length %u mod 4 != 0\n", src->vendorid.id[0], src->vendorid.id[1], length); nn_plist_fini (dest); - return ERR_INVALID; + return Q_ERR_INVALID; } if (dds_get_log_mask() & DDS_LC_PLIST) @@ -2479,7 +2479,7 @@ int nn_plist_init_frommsg DDS_WARNING("plist(vendor %u.%u): invalid parameter list: sentinel missing\n", src->vendorid.id[0], src->vendorid.id[1]); nn_plist_fini (dest); - return ERR_INVALID; + return Q_ERR_INVALID; } const unsigned char *nn_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid) diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index d09c89d..bd628f8 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -573,7 +573,7 @@ static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rms return 1; } -static int add_Gap (struct nn_xmsg *msg, struct writer *wr, struct proxy_reader *prd, seqno_t start, seqno_t base, unsigned numbits, const unsigned *bits) +static int add_Gap (struct nn_xmsg *msg, struct writer *wr, struct proxy_reader *prd, seqno_t start, seqno_t base, uint32_t numbits, const uint32_t *bits) { struct nn_xmsg_marker sm_marker; Gap_t *gap; @@ -614,7 +614,7 @@ static void force_heartbeat_to_peer (struct writer *wr, const struct whc_state * it is as-if a Data submessage had once been sent with that sequence number and it now receives an unsollicited response to a NACK ... */ - unsigned bits = 0; + uint32_t bits = 0; seqno_t seq; if (wr->seq > 0) seq = wr->seq; @@ -708,7 +708,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac nn_count_t *countp; seqno_t gapstart = -1, gapend = -1; unsigned gapnumbits = 0; - unsigned gapbits[256 / 32]; + uint32_t gapbits[256 / 32]; int accelerate_rexmit = 0; int is_pure_ack; int is_pure_nonhist_ack; @@ -1531,7 +1531,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N } else { - static unsigned zero = 0; + static uint32_t zero = 0; struct nn_xmsg *m; DDS_TRACE(" msg not available: scheduling Gap\n"); m = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_CONTROL); @@ -1979,7 +1979,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st src.bufsz = NN_RDATA_PAYLOAD_OFF (fragchain) - qos_offset; if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH | PP_COHERENT_SET | PP_PRISMTECH_EOTINFO, 0, &src)) < 0) { - if (plist_ret != ERR_INCOMPATIBLE) + if (plist_ret != Q_ERR_INCOMPATIBLE) DDS_WARNING ("data(application, vendor %u.%u): %x:%x:%x:%x #%"PRId64": invalid inline qos\n", src.vendorid.id[0], src.vendorid.id[1], PGUID (pwr->e.guid), sampleinfo->seq); return 0; @@ -2545,7 +2545,7 @@ static void malformed_packet_received if (smsize >= sizeof (AckNack_t)) { const AckNack_t *x = (const AckNack_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%x,%"PRId64",%u}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%"PRIx32",%"PRIx32",%"PRId64",%"PRIu32"}", x->smhdr.submessageId, x->smhdr.flags, x->smhdr.octetsToNextHeader, x->readerId.u, x->writerId.u, fromSN (x->readerSNState.bitmap_base), x->readerSNState.numbits); @@ -2555,7 +2555,7 @@ static void malformed_packet_received if (smsize >= sizeof (Heartbeat_t)) { const Heartbeat_t *x = (const Heartbeat_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%x,%"PRId64",%"PRId64"}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%"PRIx32",%"PRIx32",%"PRId64",%"PRId64"}", x->smhdr.submessageId, x->smhdr.flags, x->smhdr.octetsToNextHeader, x->readerId.u, x->writerId.u, fromSN (x->firstSN), fromSN (x->lastSN)); } @@ -2564,7 +2564,7 @@ static void malformed_packet_received if (smsize >= sizeof (Gap_t)) { const Gap_t *x = (const Gap_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%x,%"PRId64",%"PRId64",%u}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%"PRIx32",%"PRIx32",%"PRId64",%"PRId64",%"PRIu32"}", x->smhdr.submessageId, x->smhdr.flags, x->smhdr.octetsToNextHeader, x->readerId.u, x->writerId.u, fromSN (x->gapStart), fromSN (x->gapList.bitmap_base), x->gapList.numbits); @@ -2574,7 +2574,7 @@ static void malformed_packet_received if (smsize >= sizeof (NackFrag_t)) { const NackFrag_t *x = (const NackFrag_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%x,%"PRId64",%u,%u}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%"PRIx32",%"PRIx32",%"PRId64",%u,%"PRIu32"}", x->smhdr.submessageId, x->smhdr.flags, x->smhdr.octetsToNextHeader, x->readerId.u, x->writerId.u, fromSN (x->writerSN), x->fragmentNumberState.bitmap_base, x->fragmentNumberState.numbits); @@ -2584,7 +2584,7 @@ static void malformed_packet_received if (smsize >= sizeof (HeartbeatFrag_t)) { const HeartbeatFrag_t *x = (const HeartbeatFrag_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%x,%"PRId64",%u}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%"PRIx32",%"PRIx32",%"PRId64",%u}", x->smhdr.submessageId, x->smhdr.flags, x->smhdr.octetsToNextHeader, x->readerId.u, x->writerId.u, fromSN (x->writerSN), x->lastFragmentNum); @@ -2594,7 +2594,7 @@ static void malformed_packet_received if (smsize >= sizeof (Data_t)) { const Data_t *x = (const Data_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%u,%x,%x,%"PRId64"}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%u,%"PRIx32",%"PRIx32",%"PRId64"}", x->x.smhdr.submessageId, x->x.smhdr.flags, x->x.smhdr.octetsToNextHeader, x->x.extraFlags, x->x.octetsToInlineQos, x->x.readerId.u, x->x.writerId.u, fromSN (x->x.writerSN)); @@ -2604,7 +2604,7 @@ static void malformed_packet_received if (smsize >= sizeof (DataFrag_t)) { const DataFrag_t *x = (const DataFrag_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%u,%x,%x,%"PRId64",%u,%u,%u,%u}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%u,%"PRIx32",%"PRIx32",%"PRId64",%u,%u,%u,%"PRIu32"}", x->x.smhdr.submessageId, x->x.smhdr.flags, x->x.smhdr.octetsToNextHeader, x->x.extraFlags, x->x.octetsToInlineQos, x->x.readerId.u, x->x.writerId.u, fromSN (x->x.writerSN), diff --git a/src/core/ddsi/src/q_security.c b/src/core/ddsi/src/q_security.c index b6ba901..408c077 100644 --- a/src/core/ddsi/src/q_security.c +++ b/src/core/ddsi/src/q_security.c @@ -1657,7 +1657,7 @@ static os_ssize_t q_security_sendmsg char stbuf[2048], *buf; size_t sz, data_size; uint32_t sz32, data_size32; - ssize_t ret = ERR_UNSPECIFIED; + ssize_t ret = Q_ERR_UNSPECIFIED; PT_InfoContainer_t * securityHeader; unsigned i; diff --git a/src/core/ddsi/src/q_servicelease.c b/src/core/ddsi/src/q_servicelease.c index 4c7fa87..2ab892a 100644 --- a/src/core/ddsi/src/q_servicelease.c +++ b/src/core/ddsi/src/q_servicelease.c @@ -217,7 +217,7 @@ int nn_servicelease_start_renewing (struct nn_servicelease *sl) fail_thread: sl->keepgoing = -1; - return ERR_UNSPECIFIED; + return Q_ERR_UNSPECIFIED; } void nn_servicelease_statechange_barrier (struct nn_servicelease *sl) diff --git a/src/core/ddsi/src/q_sockwaitset.c b/src/core/ddsi/src/q_sockwaitset.c index f0187b1..7d811e7 100644 --- a/src/core/ddsi/src/q_sockwaitset.c +++ b/src/core/ddsi/src/q_sockwaitset.c @@ -831,7 +831,7 @@ void os_sockWaitsetRemove (os_sockWaitset ws, ddsi_tran_conn_t conn) os_sockWaitsetCtx os_sockWaitsetWait (os_sockWaitset ws) { - int n = -1; + int32_t n = -1; unsigned u; int fdmax; fd_set * rdset = NULL; diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index 4d3fe45..6789407 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -301,7 +301,7 @@ int join_thread (struct thread_state1 *ts1) if (ddsrt_thread_join (ts1->extTid, NULL) == DDS_RETCODE_OK) ret = 0; else - ret = ERR_UNSPECIFIED; + ret = Q_ERR_UNSPECIFIED; assert (vtime_asleep_p (ts1->vtime)); reap_thread_state (ts1, 1); return ret; diff --git a/src/core/ddsi/src/q_time.c b/src/core/ddsi/src/q_time.c index add0d0b..05878b3 100644 --- a/src/core/ddsi/src/q_time.c +++ b/src/core/ddsi/src/q_time.c @@ -51,23 +51,23 @@ nn_etime_t now_et (void) return t; } -static void time_to_sec_usec (int * __restrict sec, int * __restrict usec, int64_t t) +static void time_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, int64_t t) { - *sec = (int) (t / T_SECOND); - *usec = (int) (t % T_SECOND) / 1000; + *sec = (int32_t) (t / T_SECOND); + *usec = (int32_t) (t % T_SECOND) / 1000; } -void mtime_to_sec_usec (int * __restrict sec, int * __restrict usec, nn_mtime_t t) +void mtime_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, nn_mtime_t t) { time_to_sec_usec (sec, usec, t.v); } -void wctime_to_sec_usec (int * __restrict sec, int * __restrict usec, nn_wctime_t t) +void wctime_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, nn_wctime_t t) { time_to_sec_usec (sec, usec, t.v); } -void etime_to_sec_usec (int * __restrict sec, int * __restrict usec, nn_etime_t t) +void etime_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, nn_etime_t t) { time_to_sec_usec (sec, usec, t.v); } diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 85d1874..27abfc7 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -424,7 +424,7 @@ static int create_fragment_message_simple (struct writer *wr, seqno_t seq, struc ASSERT_MUTEX_HELD (&wr->e.lock); if ((*pmsg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (Data_t) + expected_inline_qos_size, NN_XMSG_KIND_DATA)) == NULL) - return ERR_OUT_OF_MEMORY; + return Q_ERR_OUT_OF_MEMORY; #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS /* use the partition_id from the writer to select the proper encoder */ @@ -503,13 +503,13 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli an non-existent fragment, which a malicious (or buggy) remote reader can trigger. So we return an error instead of asserting as we used to. */ - return ERR_INVALID; + return Q_ERR_INVALID; } fragging = (config.fragment_size < size); if ((*pmsg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (DataFrag_t) + expected_inline_qos_size, xmsg_kind)) == NULL) - return ERR_OUT_OF_MEMORY; + return Q_ERR_OUT_OF_MEMORY; #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS /* use the partition_id from the writer to select the proper encoder */ @@ -522,7 +522,7 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli { nn_xmsg_free (*pmsg); *pmsg = NULL; - return ERR_NO_ADDRESS; + return Q_ERR_NO_ADDRESS; } /* retransmits: latency budget doesn't apply */ } @@ -1050,7 +1050,7 @@ static int write_sample_eot (struct nn_xpack *xp, struct writer *wr, struct nn_p ddsi_serdata_size (serdata), config.max_sample_size, PGUID (wr->e.guid), tname, ttname, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)"); - r = ERR_INVALID_DATA; + r = Q_ERR_INVALID_DATA; goto drop; } @@ -1082,7 +1082,7 @@ static int write_sample_eot (struct nn_xpack *xp, struct writer *wr, struct nn_p if (ores == DDS_RETCODE_TIMEOUT) { ddsrt_mutex_unlock (&wr->e.lock); - r = ERR_TIMEOUT; + r = Q_ERR_TIMEOUT; goto drop; } } diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index 8189c77..0e60a2a 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -521,7 +521,7 @@ int xeventq_start (struct xeventq *evq, const char *name) { ddsrt_free (evqname); } - return (evq->ts == NULL) ? ERR_UNSPECIFIED : 0; + return (evq->ts == NULL) ? Q_ERR_UNSPECIFIED : 0; } void xeventq_stop (struct xeventq *evq) diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 6f6d11d..ec1495d 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -591,7 +591,7 @@ int nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd) else { DDS_WARNING("nn_xmsg_setdstPRD: no address for %x:%x:%x:%x", PGUID (prd->e.guid)); - return ERR_NO_ADDRESS; + return Q_ERR_NO_ADDRESS; } } @@ -604,7 +604,7 @@ int nn_xmsg_setdstPWR (struct nn_xmsg *m, const struct proxy_writer *pwr) return 0; } DDS_WARNING("nn_xmsg_setdstPRD: no address for %x:%x:%x:%x", PGUID (pwr->e.guid)); - return ERR_NO_ADDRESS; + return Q_ERR_NO_ADDRESS; } void nn_xmsg_setdstN (struct nn_xmsg *m, struct addrset *as, struct addrset *as_group) diff --git a/src/core/xtests/rhc_torture.c b/src/core/xtests/rhc_torture.c index 9d66de1..827d04d 100644 --- a/src/core/xtests/rhc_torture.c +++ b/src/core/xtests/rhc_torture.c @@ -265,7 +265,7 @@ static void print_seq (int n, const dds_sample_info_t *iseq, const RhcTypes_T *m char buf[64]; assert(si->instance_handle); assert(si->publication_handle); - printf ("[%2d] %c%c%c %16"PRIx64" %16"PRIx64" %4d %4d %2d %2d %2d %2"PRId32, + printf ("[%2d] %c%c%c %16"PRIx64" %16"PRIx64" %4"PRIu32" %4"PRIu32" %2"PRIu32" %2"PRIu32" %2"PRIu32" %2"PRId32, i, si2ss(si), si2vs(si), si2is(si), si->instance_handle, si->publication_handle, si->disposed_generation_count, si->no_writers_generation_count, diff --git a/src/ddsrt/include/dds/ddsrt/misc.h b/src/ddsrt/include/dds/ddsrt/misc.h index f01b397..1d165b1 100644 --- a/src/ddsrt/include/dds/ddsrt/misc.h +++ b/src/ddsrt/include/dds/ddsrt/misc.h @@ -20,7 +20,7 @@ extern "C" { #if defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402 # define DDSRT_GNUC_STR(s) #s -# define DDSRT_GNUC_JOINSTR(x,y) DDSRT_GNUC_DIAG_STR(x ## y) +# define DDSRT_GNUC_JOINSTR(x,y) DDSRT_GNUC_STR(x ## y) # define DDSRT_GNUC_DO_PRAGMA(x) _Pragma (#x) # define DDSRT_GNUC_PRAGMA(x) DDSRT_GNUC_DO_PRAGMA(GCC diagnostic x) # if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406 diff --git a/src/ddsrt/include/dds/ddsrt/sockets.h b/src/ddsrt/include/dds/ddsrt/sockets.h index 4d25387..645af42 100644 --- a/src/ddsrt/include/dds/ddsrt/sockets.h +++ b/src/ddsrt/include/dds/ddsrt/sockets.h @@ -8,12 +8,14 @@ #include "dds/ddsrt/attributes.h" #include "dds/ddsrt/retcode.h" #include "dds/ddsrt/time.h" -#if !defined(_WIN32) -#include "dds/ddsrt/sockets/posix.h" -#else +#if _WIN32 #include "dds/ddsrt/sockets/windows.h" +#else +#include "dds/ddsrt/sockets/posix.h" #endif +#define INET_ADDRSTRLEN_EXTENDED (INET_ADDRSTRLEN + 6) /* ":12345" */ + #if DDSRT_HAVE_IPV6 #define INET6_ADDRSTRLEN_EXTENDED (INET6_ADDRSTRLEN + 8) /* "[]:12345" */ extern const struct in6_addr ddsrt_in6addr_any; diff --git a/src/examples/helloworld/publisher.c b/src/examples/helloworld/publisher.c index eeb2d54..2dec98e 100644 --- a/src/examples/helloworld/publisher.c +++ b/src/examples/helloworld/publisher.c @@ -52,7 +52,7 @@ int main (int argc, char ** argv) msg.message = "Hello World"; printf ("=== [Publisher] Writing : "); - printf ("Message (%d, %s)\n", msg.userID, msg.message); + printf ("Message (%"PRId32", %s)\n", msg.userID, msg.message); fflush (stdout); rc = dds_write (writer, &msg); diff --git a/src/examples/helloworld/subscriber.c b/src/examples/helloworld/subscriber.c index f35f80a..aee6208 100644 --- a/src/examples/helloworld/subscriber.c +++ b/src/examples/helloworld/subscriber.c @@ -61,7 +61,7 @@ int main (int argc, char ** argv) /* Print Message. */ msg = (HelloWorldData_Msg*) samples[0]; printf ("=== [Subscriber] Received : "); - printf ("Message (%d, %s)\n", msg->userID, msg->message); + printf ("Message (%"PRId32", %s)\n", msg->userID, msg->message); fflush (stdout); break; } diff --git a/src/examples/throughput/publisher.c b/src/examples/throughput/publisher.c index 8fd49d7..5109d6b 100644 --- a/src/examples/throughput/publisher.c +++ b/src/examples/throughput/publisher.c @@ -126,7 +126,7 @@ static int parse_args( *partitionName = argv[5]; /* The name of the partition */ } - printf ("payloadSize: %u bytes burstInterval: %u ms burstSize: %u timeOut: %u seconds partitionName: %s\n", + printf ("payloadSize: %"PRIu32" bytes burstInterval: %u ms burstSize: %"PRId32" timeOut: %u seconds partitionName: %s\n", *payloadSize, *burstInterval, *burstSize, *timeOut, *partitionName); fflush (stdout); diff --git a/src/tools/ddsls/ddsls.c b/src/tools/ddsls/ddsls.c index bd53700..fed04c4 100644 --- a/src/tools/ddsls/ddsls.c +++ b/src/tools/ddsls/ddsls.c @@ -150,17 +150,17 @@ void qp_resource_limits_1 (FILE *fp, int32_t max_samples, int32_t max_instances, if (max_samples == DDS_LENGTH_UNLIMITED) fprintf (fp, "unlimited"); else - fprintf (fp, "%d", max_samples); + fprintf (fp, "%"PRId32, max_samples); fprintf (fp, ", max_instances = "); if (max_instances == DDS_LENGTH_UNLIMITED) fprintf (fp, "unlimited"); else - fprintf (fp, "%d", max_instances); + fprintf (fp, "%"PRId32, max_instances); fprintf (fp, ", max_samples_per_instance = "); if (max_samples_per_instance == DDS_LENGTH_UNLIMITED) fprintf (fp, "unlimited\n"); else - fprintf (fp, "%d\n", max_samples_per_instance); + fprintf (fp, "%"PRId32"\n", max_samples_per_instance); } void qp_resource_limits (const dds_qos_t *q, FILE *fp) diff --git a/src/tools/pubsub/common.c b/src/tools/pubsub/common.c index a24abaf..43322f4 100644 --- a/src/tools/pubsub/common.c +++ b/src/tools/pubsub/common.c @@ -705,7 +705,7 @@ static int one_resource_limit(int32_t *val, const char **arg) { *val = DDS_LENGTH_UNLIMITED; (*arg) += 3; return 1; - } else if (sscanf(*arg, "%d%n", val, &pos) == 1) { + } else if (sscanf(*arg, "%"PRId32"%n", val, &pos) == 1) { (*arg) += pos; return 1; } else { @@ -957,7 +957,7 @@ bool dds_err_check (dds_return_t err, unsigned flags, const char * where) if (flags & (DDS_CHECK_REPORT | DDS_CHECK_FAIL)) { char msg[DDS_ERR_MSG_MAX]; - (void) snprintf (msg, DDS_ERR_MSG_MAX, "Error %d:M%d:%s", dds_err_file_id(err), dds_err_line(err), dds_err_str(err)); + (void) snprintf (msg, DDS_ERR_MSG_MAX, "Error %"PRId32":M%"PRId32":%s", dds_err_file_id(err), dds_err_line(err), dds_err_str(err)); if (flags & DDS_CHECK_REPORT) { printf ("%s: %s\n", where, msg); diff --git a/src/tools/pubsub/pubsub.c b/src/tools/pubsub/pubsub.c index cf7cde2..e775f10 100644 --- a/src/tools/pubsub/pubsub.c +++ b/src/tools/pubsub/pubsub.c @@ -45,7 +45,7 @@ //#define NUMSTR "0123456789" //#define HOSTNAMESTR "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-." NUMSTR -typedef int (*write_oper_t) (dds_entity_t wr, const void *d, const dds_time_t ts); +typedef dds_return_t (*write_oper_t) (dds_entity_t wr, const void *d, const dds_time_t ts); enum topicsel { UNSPEC, KS, K32, K64, K128, K256, OU, ARB }; enum readermode { MODE_PRINT, MODE_CHECK, MODE_ZEROLOAD, MODE_DUMP, MODE_NONE }; @@ -860,11 +860,11 @@ static void print_K(dds_time_t *tstart, dds_time_t tnow, dds_entity_t rd, const print_sampleinfo(tstart, tnow, si, tag); if (si->valid_data) { if(printmode == TGPM_MULTILINE) { - printf ("{\n%*.*s.seq = %u,\n%*.*s.keyval = %d }\n", 4, 4, "", seq, 4, 4, "", keyval); + printf ("{\n%*.*s.seq = %"PRIu32",\n%*.*s.keyval = %"PRId32" }\n", 4, 4, "", seq, 4, 4, "", keyval); } else if(printmode == TGPM_DENSE) { - printf ("{%u,%d}\n", seq, keyval); + printf ("{%"PRIu32",%"PRId32"}\n", seq, keyval); } else { - printf ("{ .seq = %u, .keyval = %d }\n", seq, keyval); + printf ("{ .seq = %"PRIu32", .keyval = %"PRId32" }\n", seq, keyval); } } else { /* May not look at mseq->_buffer[i] but want the key value @@ -877,11 +877,11 @@ static void print_K(dds_time_t *tstart, dds_time_t tnow, dds_entity_t rd, const int32_t d_key; if ((result = getkeyval(rd, &d_key, si->instance_handle)) == DDS_RETCODE_OK) { if(printmode == TGPM_MULTILINE) { - printf ("{\n%*.*s.seq = NA,\n%*.*s.keyval = %d }\n", 4, 4, "", 4, 4, "", keyval); + printf ("{\n%*.*s.seq = NA,\n%*.*s.keyval = %"PRId32" }\n", 4, 4, "", 4, 4, "", keyval); } else if(printmode == TGPM_DENSE) { - printf ("{NA,%d}\n", keyval); + printf ("{NA,%"PRId32"}\n", keyval); } else { - printf ("{ .seq = NA, .keyval = %d }\n", keyval); + printf ("{ .seq = NA, .keyval = %"PRId32" }\n", keyval); } } else printf ("get_key_value: error (%s)\n", dds_err_str(result)); @@ -930,11 +930,11 @@ static void print_seq_OU(dds_time_t *tstart, dds_time_t tnow, dds_entity_t rd __ print_sampleinfo(tstart, tnow, si, tag); if (si->valid_data) { if(printmode == TGPM_MULTILINE) { - printf ("{\n%*.*s.seq = %u }\n", 4, 4, "", mseq[i]->seq); + printf ("{\n%*.*s.seq = %"PRIu32" }\n", 4, 4, "", mseq[i]->seq); } else if(printmode == TGPM_DENSE) { - printf ("{%u}\n", mseq[i]->seq); + printf ("{%"PRIu32"}\n", mseq[i]->seq); } else { - printf ("{ .seq = %u }\n", mseq[i]->seq); + printf ("{ .seq = %"PRIu32" }\n", mseq[i]->seq); } } else { printf ("NA\n"); @@ -1109,7 +1109,7 @@ static void wr_on_publication_matched(dds_entity_t wr __attribute__((unused)), c } } -static int register_instance_wrapper(dds_entity_t wr, const void *d, const dds_time_t tstamp) { +static dds_return_t register_instance_wrapper(dds_entity_t wr, const void *d, const dds_time_t tstamp) { dds_instance_handle_t handle; (void)tstamp; return dds_register_instance(wr, &handle, d); @@ -1795,7 +1795,7 @@ static uint32_t subthread(void *vspec) { rc = dds_get_subscription_matched_status(rd, &status); error_report(rc, "dds_get_subscription_matched_status failed"); if (rc == DDS_RETCODE_OK) { - printf("[pre-read: subscription-matched: total=(%"PRIu32" change %d) current=(%"PRIu32" change %d) handle=%"PRIu64"]\n", + printf("[pre-read: subscription-matched: total=(%"PRIu32" change %"PRId32") current=(%"PRIu32" change %"PRId32") handle=%"PRIu64"]\n", status.total_count, status.total_count_change, status.current_count, status.current_count_change, diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 00bc5ac..4f44a70 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -25,6 +25,10 @@ generate_export_header( # util must NOT link with ddsrt to avoid duplicate symbols in ddsc! # ddsrt include directories are required though. +target_compile_definitions( + util + PUBLIC + $>) target_include_directories( util PUBLIC From 3bdd2a140d56b1533953b53f7565ab86bf4908c3 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Wed, 10 Apr 2019 14:23:33 +0200 Subject: [PATCH 010/178] Move md5 from ddsi to ddsrt Signed-off-by: Jeroen Koekkoek --- src/core/ddsc/src/dds_key.c | 11 +++-- src/core/ddsc/src/dds_serdata_builtintopic.c | 2 +- src/core/ddsc/src/dds_sertopic_builtintopic.c | 2 +- src/core/ddsc/src/dds_stream.c | 14 +++--- src/core/ddsi/CMakeLists.txt | 2 - src/core/ddsi/src/ddsi_serdata.c | 2 +- src/core/ddsi/src/ddsi_serdata_default.c | 14 +++--- src/core/ddsi/src/ddsi_sertopic.c | 15 +++--- src/core/ddsi/src/ddsi_sertopic_default.c | 2 +- src/core/ddsi/src/q_ddsi_discovery.c | 3 +- src/core/ddsi/src/q_init.c | 2 +- src/core/ddsi/src/q_misc.c | 3 +- src/core/ddsi/src/q_nwif.c | 13 ++--- src/core/ddsi/src/q_receive.c | 5 +- src/ddsrt/CMakeLists.txt | 2 +- .../q_md5.h => ddsrt/include/dds/ddsrt/md5.h} | 26 +++++----- .../ddsi/src/q_md5.c => ddsrt/src/md5.c} | 47 ++++++++++--------- 17 files changed, 84 insertions(+), 81 deletions(-) rename src/{core/ddsi/include/dds/ddsi/q_md5.h => ddsrt/include/dds/ddsrt/md5.h} (83%) rename src/{core/ddsi/src/q_md5.c => ddsrt/src/md5.c} (91%) diff --git a/src/core/ddsc/src/dds_key.c b/src/core/ddsc/src/dds_key.c index d0ab249..b919c85 100644 --- a/src/core/ddsc/src/dds_key.c +++ b/src/core/ddsc/src/dds_key.c @@ -11,11 +11,12 @@ */ #include #include + +#include "dds/ddsrt/md5.h" #include "dds__key.h" #include "dds__stream.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/q_bswap.h" -#include "dds/ddsi/q_md5.h" #ifndef NDEBUG static bool keyhash_is_reset(const dds_key_hash_t *kh) @@ -112,14 +113,14 @@ void dds_key_gen (const dds_topic_descriptor_t * const desc, dds_key_hash_t * kh else { dds_stream_t os; - md5_state_t md5st; + ddsrt_md5_state_t md5st; kh->m_iskey = 0; dds_stream_init(&os, 64); os.m_endian = 0; dds_key_gen_stream (desc, &os, sample); - md5_init (&md5st); - md5_append (&md5st, os.m_buffer.p8, os.m_index); - md5_finish (&md5st, (unsigned char *) kh->m_hash); + ddsrt_md5_init (&md5st); + ddsrt_md5_append (&md5st, os.m_buffer.p8, os.m_index); + ddsrt_md5_finish (&md5st, (unsigned char *) kh->m_hash); dds_stream_fini (&os); } } diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index 4d45df5..b62d405 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -15,7 +15,7 @@ #include #include "dds/ddsrt/heap.h" -#include "dds/ddsi/q_md5.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" diff --git a/src/core/ddsc/src/dds_sertopic_builtintopic.c b/src/core/ddsc/src/dds_sertopic_builtintopic.c index 87bfe0d..05c9544 100644 --- a/src/core/ddsc/src/dds_sertopic_builtintopic.c +++ b/src/core/ddsc/src/dds_sertopic_builtintopic.c @@ -16,7 +16,7 @@ #include "dds/dds.h" #include "dds/ddsrt/heap.h" -#include "dds/ddsi/q_md5.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" diff --git a/src/core/ddsc/src/dds_stream.c b/src/core/ddsc/src/dds_stream.c index 2fbee03..9d7505c 100644 --- a/src/core/ddsc/src/dds_stream.c +++ b/src/core/ddsc/src/dds_stream.c @@ -11,19 +11,19 @@ */ #include #include + +#include "dds/ddsrt/endian.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds__stream.h" #include "dds__key.h" #include "dds__alloc.h" -#include "dds/ddsi/q_md5.h" -#include "dds/ddsrt/endian.h" //#define OP_DEBUG_READ 1 //#define OP_DEBUG_WRITE 1 //#define OP_DEBUG_KEY 1 - #if defined OP_DEBUG_WRITE || defined OP_DEBUG_READ || defined OP_DEBUG_KEY static const char * stream_op_type[11] = { @@ -1612,14 +1612,14 @@ void dds_stream_read_keyhash else { dds_stream_t os; - md5_state_t md5st; + ddsrt_md5_state_t md5st; kh->m_iskey = 0; dds_stream_init (&os, 0); os.m_endian = 0; dds_stream_extract_key (is, &os, desc->m_ops, just_key); - md5_init (&md5st); - md5_append (&md5st, os.m_buffer.p8, os.m_index); - md5_finish (&md5st, (unsigned char *) kh->m_hash); + ddsrt_md5_init (&md5st); + ddsrt_md5_append (&md5st, os.m_buffer.p8, os.m_index); + ddsrt_md5_finish (&md5st, (unsigned char *) kh->m_hash); dds_stream_fini (&os); } } diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 29725a1..8821665 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -39,7 +39,6 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" q_init.c q_lat_estim.c q_lease.c - q_md5.c q_misc.c q_nwif.c q_pcap.c @@ -97,7 +96,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" q_lat_estim.h q_lease.h q_log.h - q_md5.h q_misc.h q_nwif.h q_pcap.h diff --git a/src/core/ddsi/src/ddsi_serdata.c b/src/core/ddsi/src/ddsi_serdata.c index 524241c..140c049 100644 --- a/src/core/ddsi/src/ddsi_serdata.c +++ b/src/core/ddsi/src/ddsi_serdata.c @@ -14,7 +14,7 @@ #include #include -#include "dds/ddsi/q_md5.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 9e938a8..c7c2cf9 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -16,7 +16,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" -#include "dds/ddsi/q_md5.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" @@ -377,16 +377,16 @@ static struct ddsi_serdata *serdata_default_from_sample_plist (const struct ddsi const char *topic_name = (const char *) (rawkey + sizeof(uint32_t)); uint32_t topic_name_sz; uint32_t topic_name_sz_BE; - md5_state_t md5st; - md5_byte_t digest[16]; + ddsrt_md5_state_t md5st; + ddsrt_md5_byte_t digest[16]; topic_name_sz = (uint32_t) strlen (topic_name) + 1; topic_name_sz_BE = toBE4u (topic_name_sz); d->keyhash.m_set = 1; d->keyhash.m_iskey = 0; - md5_init (&md5st); - md5_append (&md5st, (const md5_byte_t *) &topic_name_sz_BE, sizeof (topic_name_sz_BE)); - md5_append (&md5st, (const md5_byte_t *) topic_name, topic_name_sz); - md5_finish (&md5st, digest); + ddsrt_md5_init (&md5st); + ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *) &topic_name_sz_BE, sizeof (topic_name_sz_BE)); + ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *) topic_name, topic_name_sz); + ddsrt_md5_finish (&md5st, digest); memcpy (d->keyhash.m_hash, digest, 16); #ifndef NDEBUG keysize = sizeof (uint32_t) + topic_name_sz; diff --git a/src/core/ddsi/src/ddsi_sertopic.c b/src/core/ddsi/src/ddsi_sertopic.c index be68930..c4971b2 100644 --- a/src/core/ddsi/src/ddsi_sertopic.c +++ b/src/core/ddsi/src/ddsi_sertopic.c @@ -15,13 +15,12 @@ #include #include "dds/ddsrt/heap.h" -#include "dds/ddsi/q_md5.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" #include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/ddsi_serdata.h" -#include "dds/ddsi/q_md5.h" struct ddsi_sertopic *ddsi_sertopic_ref (const struct ddsi_sertopic *sertopic_const) { @@ -48,13 +47,13 @@ void ddsi_sertopic_unref (struct ddsi_sertopic *sertopic) uint32_t ddsi_sertopic_compute_serdata_basehash (const struct ddsi_serdata_ops *ops) { - md5_state_t md5st; - md5_byte_t digest[16]; + ddsrt_md5_state_t md5st; + ddsrt_md5_byte_t digest[16]; uint32_t res; - md5_init (&md5st); - md5_append (&md5st, (const md5_byte_t *) &ops, sizeof (ops)); - md5_append (&md5st, (const md5_byte_t *) ops, sizeof (*ops)); - md5_finish (&md5st, digest); + ddsrt_md5_init (&md5st); + ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *) &ops, sizeof (ops)); + ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *) ops, sizeof (*ops)); + ddsrt_md5_finish (&md5st, digest); memcpy (&res, digest, sizeof (res)); return res; } diff --git a/src/core/ddsi/src/ddsi_sertopic_default.c b/src/core/ddsi/src/ddsi_sertopic_default.c index be90044..3fff736 100644 --- a/src/core/ddsi/src/ddsi_sertopic_default.c +++ b/src/core/ddsi/src/ddsi_sertopic_default.c @@ -14,7 +14,7 @@ #include #include -#include "dds/ddsi/q_md5.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 3f5a4b6..be434dd 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -18,6 +18,7 @@ #include "dds/version.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsrt/sync.h" #include "dds/util/ut_avl.h" #include "dds/ddsi/q_protocol.h" @@ -30,6 +31,7 @@ #include "dds/ddsi/q_xevent.h" #include "dds/ddsi/q_addrset.h" #include "dds/ddsi/q_ddsi_discovery.h" + #include "dds/ddsi/q_radmin.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_entity.h" @@ -40,7 +42,6 @@ #include "dds/ddsi/q_lease.h" #include "dds/ddsi/q_error.h" #include "dds/ddsi/ddsi_serdata_default.h" -#include "dds/ddsi/q_md5.h" #include "dds/ddsi/q_feature_check.h" static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_same_subnet) diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 97ae856..9fddd09 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -13,6 +13,7 @@ #include #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/time.h" #include "dds/ddsrt/string.h" @@ -21,7 +22,6 @@ #include "dds/util/ut_avl.h" #include "dds/util/ut_thread_pool.h" -#include "dds/ddsi/q_md5.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_misc.h" diff --git a/src/core/ddsi/src/q_misc.c b/src/core/ddsi/src/q_misc.c index 3c97d19..8569c01 100644 --- a/src/core/ddsi/src/q_misc.c +++ b/src/core/ddsi/src/q_misc.c @@ -12,8 +12,9 @@ #include #include "dds/ddsi/q_misc.h" + +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" -#include "dds/ddsi/q_md5.h" extern inline seqno_t fromSN (const nn_sequence_number_t sn); extern inline nn_sequence_number_t toSN (seqno_t n); diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index 66c49bf..c013080 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -17,15 +17,16 @@ #include "dds/ddsrt/ifaddrs.h" #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/sockets.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_nwif.h" + #include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_unused.h" -#include "dds/ddsi/q_md5.h" #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_addrset.h" /* unspec locator */ #include "dds/ddsi/q_feature_check.h" @@ -45,11 +46,11 @@ unsigned locator_to_hopefully_unique_uint32 (const nn_locator_t *src) else { #if DDSRT_HAVE_IPV6 - md5_state_t st; - md5_byte_t digest[16]; - md5_init (&st); - md5_append (&st, (const md5_byte_t *) ((const struct sockaddr_in6 *) src)->sin6_addr.s6_addr, 16); - md5_finish (&st, digest); + ddsrt_md5_state_t st; + ddsrt_md5_byte_t digest[16]; + ddsrt_md5_init (&st); + ddsrt_md5_append (&st, (const ddsrt_md5_byte_t *) ((const struct sockaddr_in6 *) src)->sin6_addr.s6_addr, 16); + ddsrt_md5_finish (&st, digest); memcpy (&id, digest, sizeof (id)); #else DDS_FATAL("IPv6 unavailable\n"); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index bd628f8..f463392 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -15,11 +15,11 @@ #include #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/log.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/string.h" -#include "dds/ddsrt/log.h" -#include "dds/ddsi/q_md5.h" #include "dds/util/ut_avl.h" #include "dds__stream.h" #include "dds/ddsi/q_protocol.h" @@ -44,6 +44,7 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/q_receive.h" + #include "dds/ddsi/q_transmit.h" #include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_static_assert.h" diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index e8b62a6..5179742 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -89,7 +89,7 @@ list(APPEND sources # network stack. In order to mix-and-match various compilers, architectures, # operating systems, etc input from the build system is required. foreach(feature atomics cdtors environ heap ifaddrs random rusage - sockets string sync threads time) + sockets string sync threads time md5) if(EXISTS "${include_path}/dds/ddsrt/${feature}.h") list(APPEND headers "${include_path}/dds/ddsrt/${feature}.h") file(GLOB diff --git a/src/core/ddsi/include/dds/ddsi/q_md5.h b/src/ddsrt/include/dds/ddsrt/md5.h similarity index 83% rename from src/core/ddsi/include/dds/ddsi/q_md5.h rename to src/ddsrt/include/dds/ddsrt/md5.h index e040de0..4777d04 100644 --- a/src/core/ddsi/include/dds/ddsi/q_md5.h +++ b/src/ddsrt/include/dds/ddsrt/md5.h @@ -59,8 +59,8 @@ 1999-05-03 lpd Original version. */ -#ifndef md5_INCLUDED -# define md5_INCLUDED +#ifndef DDSRT_MD5_H +#define DDSRT_MD5_H #include @@ -74,15 +74,15 @@ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. */ -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ +typedef unsigned char ddsrt_md5_byte_t; /* 8-bit byte */ +typedef unsigned int ddsrt_md5_word_t; /* 32-bit word */ /* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ -} md5_state_t; +typedef struct ddsrt_md5_state_s { + ddsrt_md5_word_t count[2]; /* message length in bits, lsw first */ + ddsrt_md5_word_t abcd[4]; /* digest buffer */ + ddsrt_md5_byte_t buf[64]; /* accumulate block */ +} ddsrt_md5_state_t; #ifdef __cplusplus extern "C" @@ -90,16 +90,16 @@ extern "C" #endif /* Initialize the algorithm. */ -void md5_init(md5_state_t *pms); +void ddsrt_md5_init(ddsrt_md5_state_t *pms); /* Append a string to the message. */ -void md5_append(md5_state_t *pms, const md5_byte_t *data, unsigned nbytes); +void ddsrt_md5_append(ddsrt_md5_state_t *pms, const ddsrt_md5_byte_t *data, unsigned nbytes); /* Finish the message and return the digest. */ -void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +void ddsrt_md5_finish(ddsrt_md5_state_t *pms, ddsrt_md5_byte_t digest[16]); #ifdef __cplusplus } /* end extern "C" */ #endif -#endif /* md5_INCLUDED */ +#endif /* DDSRT_MD5_H */ diff --git a/src/core/ddsi/src/q_md5.c b/src/ddsrt/src/md5.c similarity index 91% rename from src/core/ddsi/src/q_md5.c rename to src/ddsrt/src/md5.c index 1a041c2..3116749 100644 --- a/src/core/ddsi/src/q_md5.c +++ b/src/ddsrt/src/md5.c @@ -63,9 +63,10 @@ 1999-05-03 lpd Original version. */ -#include "dds/ddsi/q_md5.h" #include + #include "dds/ddsrt/endian.h" /* big or little endianness */ +#include "dds/ddsrt/md5.h" /* Byte order stuff hacked to use OSPL's macros */ #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ @@ -77,7 +78,7 @@ # error "DDSRT_ENDIAN not defined" #endif -#define T_MASK ((md5_word_t)~0) +#define T_MASK ((ddsrt_md5_word_t)~0) #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) #define T3 0x242070db @@ -145,19 +146,19 @@ static void -md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +md5_process(ddsrt_md5_state_t *pms, const ddsrt_md5_byte_t *data /*[64]*/) { - md5_word_t + ddsrt_md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; + ddsrt_md5_word_t t; #if BYTE_ORDER > 0 /* Define storage only for big-endian CPUs. */ - md5_word_t X[16]; + ddsrt_md5_word_t X[16]; #else /* Define storage for little-endian or both types of CPUs. */ - md5_word_t xbuf[16]; - const md5_word_t *X; + ddsrt_md5_word_t xbuf[16]; + const ddsrt_md5_word_t *X; #endif { @@ -169,7 +170,7 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) */ static const int w = 1; - if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ + if (*((const ddsrt_md5_byte_t *)&w)) /* dynamic little-endian */ #endif #if BYTE_ORDER <= 0 /* little-endian */ { @@ -177,9 +178,9 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) * On little-endian machines, we can process properly aligned * data without copying it. */ - if (!((data - (const md5_byte_t *)0) & 3)) { + if (!((data - (const ddsrt_md5_byte_t *)0) & 3)) { /* data are properly aligned */ - X = (const md5_word_t *)data; + X = (const ddsrt_md5_word_t *)data; } else { /* not aligned */ memcpy(xbuf, data, 64); @@ -196,7 +197,7 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) * On big-endian machines, we must arrange the bytes in the * right order. */ - const md5_byte_t *xp = data; + const ddsrt_md5_byte_t *xp = data; int i; # if BYTE_ORDER == 0 @@ -326,7 +327,7 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) } void -md5_init(md5_state_t *pms) +ddsrt_md5_init(ddsrt_md5_state_t *pms) { pms->count[0] = pms->count[1] = 0; pms->abcd[0] = 0x67452301; @@ -336,12 +337,12 @@ md5_init(md5_state_t *pms) } void -md5_append(md5_state_t *pms, const md5_byte_t *data, unsigned nbytes) +ddsrt_md5_append(ddsrt_md5_state_t *pms, const ddsrt_md5_byte_t *data, unsigned nbytes) { - const md5_byte_t *p = data; + const ddsrt_md5_byte_t *p = data; unsigned left = nbytes; unsigned offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); + ddsrt_md5_word_t nbits = (ddsrt_md5_word_t)(nbytes << 3); if (nbytes == 0) return; @@ -374,24 +375,24 @@ md5_append(md5_state_t *pms, const md5_byte_t *data, unsigned nbytes) } void -md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +ddsrt_md5_finish(ddsrt_md5_state_t *pms, ddsrt_md5_byte_t digest[16]) { - static const md5_byte_t pad[64] = { + static const ddsrt_md5_byte_t pad[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - md5_byte_t data[8]; + ddsrt_md5_byte_t data[8]; int i; /* Save the length before padding. */ for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + data[i] = (ddsrt_md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + ddsrt_md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); /* Append the length. */ - md5_append(pms, data, 8); + ddsrt_md5_append(pms, data, 8); for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); + digest[i] = (ddsrt_md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); } From b14663c1735f4543cf9c1bf497c361f2f3d85f5c Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 9 Apr 2019 21:12:46 +0200 Subject: [PATCH 011/178] ignore data until a heartbeat is received (#146) When data arrives before a heartbeat has been received, it is impossible to know whether this is a new "live" sample or a retransmit, and for this reason the requesting of historical data is delayed until a heartbeat arrives that informs the readers of the range of sequence numbers to request as historical data. However, by this time, and without this new condition in place, the reader may have already received some data directly, and may consequently request some data twice. That's not right. Requiring a heartbeat to have been received before delivering the data avoids this problem, but potentially delays receiving data after a new writer/reader pair has been matched. The delay caused by a full handshake at that point seems less bad that the odd case of stuttering where that isn't expected. There are almost certainly some tricks possible to avoid that delay in the common cases, but there are more important things to do ... Best-effort readers on a reliable proxy writer are a bit special: if there are only best-effort readers, there is no guarantee that a heartbeat will be received, and so the condition does not apply. This commit attempts to deal with that by only requiring a heartbeat if some reliable readers exist, but that doesn't allow a smooth transition from "only best-effort readers" to "some reliable readers". One could moreover argue that this condition should not be imposed on volatile readers (at worst you get a little bit of data from before the match), but equally well that it should (there's no guarantee that no sample would be skipped in the case of a keep-all writer, if the first sample happened to be a retransmit). Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_entity.c | 5 +++-- src/core/ddsi/src/q_receive.c | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index d83f225..0b0c8fa 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -4111,12 +4111,13 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, } else { pwr->deliver_synchronously = 0; } - pwr->have_seen_heartbeat = 0; + /* Pretend we have seen a heartbeat if the proxy writer is a best-effort one */ + isreliable = (pwr->c.xqos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS); + pwr->have_seen_heartbeat = !isreliable; pwr->local_matching_inprogress = 1; #ifdef DDSI_INCLUDE_SSM pwr->supports_ssm = (addrset_contains_ssm (as) && config.allowMulticast & AMC_SSM) ? 1 : 0; #endif - isreliable = (pwr->c.xqos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS); /* Only assert PP lease on receipt of data if enabled (duh) and the proxy participant is a "real" participant, rather than the thing we use for endpoints discovered via the DS */ diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index f463392..8671a5b 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -1745,6 +1745,13 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm } DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x", PGUID (src), PGUID (dst)); + if (!pwr->have_seen_heartbeat && pwr->n_reliable_readers > 0) + { + DDS_TRACE(": no heartbeat seen yet", PGUID (pwr->e.guid), PGUID (dst)); + ddsrt_mutex_unlock (&pwr->e.lock); + return 1; + } + /* Notify reordering in proxy writer & and the addressed reader (if it is out-of-sync, &c.), while delivering samples that become available because preceding ones are now known to be missing. */ @@ -2173,6 +2180,25 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct /* Shouldn't lock the full writer, but will do so for now */ ddsrt_mutex_lock (&pwr->e.lock); + + /* Don't accept data when reliable readers exist and we haven't yet seen + a heartbeat telling us what the "current" sequence number of the writer + is. If no reliable readers are present, we can't request a heartbeat and + therefore must not require one. + + This should be fine except for the one case where one transitions from + having only best-effort readers to also having a reliable reader (in + the same process): in that case, the requirement that a heartbeat has + been seen could potentially result in a disruption of the data flow to + the best-effort readers. That state should last only for a very short + time, but it is rather inelegant. */ + if (!pwr->have_seen_heartbeat && pwr->n_reliable_readers > 0) + { + ddsrt_mutex_unlock (&pwr->e.lock); + DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x: no heartbeat seen yet", PGUID (pwr->e.guid), PGUID (dst)); + return; + } + if (ut_avlIsEmpty (&pwr->readers) || pwr->local_matching_inprogress) { ddsrt_mutex_unlock (&pwr->e.lock); From 671e73ec9818a527ef0479c56c028d35b138e3fd Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 10 Apr 2019 11:00:10 +0200 Subject: [PATCH 012/178] set DATA_AVAILABLE when deleting writer (#148) Deleting a writer causes unregisters (and possibly disposes) in the rest of the network, and these updates to the instances should trigger DATA_AVAILABLE. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_rhc.c | 17 ++++- src/core/ddsc/tests/listener.c | 110 ++++++++++++++++++++++++++++++++- 2 files changed, 124 insertions(+), 3 deletions(-) diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index b427df3..30dc4f3 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -1523,6 +1523,7 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ built-in topics and in get_instance_handle, and one used internally for tracking registrations and unregistrations. */ bool trigger_waitsets = false; + bool notify_data_available = false; struct rhc_instance *inst; struct ut_hhIter iter; const uint64_t wr_iid = pwr_info->iid; @@ -1568,16 +1569,28 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ TRACE ("\n"); + notify_data_available = true; if (trigger_info_differs (&pre, &post, &trig_qc) && update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst)) trigger_waitsets = true; assert (rhc_check_counts_locked (rhc, true, false)); } } TRACE (")\n"); + ddsrt_mutex_unlock (&rhc->lock); - if (trigger_waitsets) - dds_entity_status_signal (&rhc->reader->m_entity); + if (rhc->reader) + { + if (notify_data_available && (rhc->reader->m_entity.m_status_enable & DDS_DATA_AVAILABLE_STATUS)) + { + ddsrt_atomic_inc32 (&rhc->n_cbs); + dds_reader_data_available_cb (rhc->reader); + ddsrt_atomic_dec32 (&rhc->n_cbs); + } + + if (trigger_waitsets) + dds_entity_status_signal (&rhc->reader->m_entity); + } } void dds_rhc_relinquish_ownership (struct rhc * __restrict rhc, const uint64_t wr_iid) diff --git a/src/core/ddsc/tests/listener.c b/src/core/ddsc/tests/listener.c index e3f5c65..d049c85 100644 --- a/src/core/ddsc/tests/listener.c +++ b/src/core/ddsc/tests/listener.c @@ -400,7 +400,8 @@ static void fini_triggering_test(void) { dds_delete(g_reader); - dds_delete(g_writer); + if (g_writer) + dds_delete(g_writer); fini_triggering_base(); } @@ -847,6 +848,113 @@ CU_Test(ddsc_listener, data_available, .init=init_triggering_test, .fini=fini_tr ret = dds_read_status(g_reader, &status, DDS_DATA_AVAILABLE_STATUS); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(status, 0); + + /* Deleting the writer causes unregisters (or dispose+unregister), and those + should trigger DATA_AVAILABLE as well */ + cb_called = 0; + cb_reader = 0; + ret = dds_delete (g_writer); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + g_writer = 0; + triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); + + /* The listener should have swallowed the status. */ + ret = dds_read_status(g_subscriber, &status, DDS_DATA_ON_READERS_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, 0); + ret = dds_read_status(g_reader, &status, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, 0); +} + +CU_Test(ddsc_listener, data_available_delete_writer, .init=init_triggering_test, .fini=fini_triggering_test) +{ + dds_return_t ret; + uint32_t triggered; + uint32_t status; + RoundTripModule_DataType sample; + memset (&sample, 0, sizeof (sample)); + + /* We are interested in data available notifications. */ + dds_lset_data_available(g_listener, data_available_cb); + ret = dds_set_listener(g_reader, g_listener); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + /* Write sample, wait for the listener to swallow the status. */ + ret = dds_write(g_writer, &sample); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); + + /* Deleting the writer must trigger DATA_AVAILABLE as well */ + cb_called = 0; + cb_reader = 0; + ret = dds_delete (g_writer); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + g_writer = 0; + triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); + + /* The listener should have swallowed the status. */ + ret = dds_read_status(g_subscriber, &status, DDS_DATA_ON_READERS_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, 0); + ret = dds_read_status(g_reader, &status, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, 0); +} + +CU_Test(ddsc_listener, data_available_delete_writer_disposed, .init=init_triggering_test, .fini=fini_triggering_test) +{ + dds_return_t ret; + uint32_t triggered; + uint32_t status; + RoundTripModule_DataType sample; + memset (&sample, 0, sizeof (sample)); + + /* We are interested in data available notifications. */ + dds_lset_data_available(g_listener, data_available_cb); + ret = dds_set_listener(g_reader, g_listener); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + /* Write & dispose sample and take it so that the instance is empty & disposed. Then deleting + the writer should silently drop the instance. */ + ret = dds_write(g_writer, &sample); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + ret = dds_dispose(g_writer, &sample); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); + + /* Take all data so that the instance becomes empty & disposed */ + do { + void *sampleptr = &sample; + dds_sample_info_t info; + ret = dds_take (g_reader, &sampleptr, &info, 1, 1); + } while (ret > 0); + + /* Deleting the writer should not trigger DATA_AVAILABLE with all instances empty & disposed */ + cb_called = 0; + cb_reader = 0; + ret = dds_delete (g_writer); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + g_writer = 0; + triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); + + /* The listener should have swallowed the status. */ + ret = dds_read_status(g_subscriber, &status, DDS_DATA_ON_READERS_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, 0); + ret = dds_read_status(g_reader, &status, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, 0); } CU_Test(ddsc_listener, data_on_readers, .init=init_triggering_test, .fini=fini_triggering_test) From 4a60000e588f41fa3e032d8065d7baa889859c34 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Thu, 18 Apr 2019 17:34:14 +0200 Subject: [PATCH 013/178] Remove dependency on jdk8 Chocolatey package Signed-off-by: Jeroen Koekkoek --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1abb951..8274805 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,6 +64,9 @@ before_install: - if [ "${TRAVIS_OS_NAME}" = "windows" ]; then eval "unset CC"; eval "unset CXX"; + JAVA_HOME=$(find "/c/Program Files/Android/jdk/" -name "*openjdk*" | sort | head -n 1); + export JAVA_HOME; + export PATH="${PATH}:${JAVA_HOME}/bin"; else eval "export CC=${C_COMPILER}"; eval "export CXX=${CXX_COMPILER}"; @@ -83,13 +86,10 @@ before_install: # issue, JAVA_HOME is read from the registry and exported by this script. install: - if [ "${TRAVIS_OS_NAME}" = "windows" ]; then - choco install innoextract maven; + choco install innoextract; + choco install maven --ignore-dependencies; wget -q https://dl.bintray.com/conan/installers/conan-win-64_1_10_0.exe; innoextract conan-win-64_1_10_0.exe; - KEY='HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; - VALUE='JAVA_HOME'; - JAVA_HOME=$(REG QUERY "${KEY}" -v "${VALUE}" | sed -n 's/^.*JAVA_HOME \+[_A-Z]\+ \+//ip'); - eval "export JAVA_HOME=\"${JAVA_HOME}\""; eval "export PATH=\"$(pwd)/app/conan:${PATH}\""; elif [ "${TRAVIS_OS_NAME}" = "osx" ]; then eval "$(pyenv init -)"; From 0b106cc186c3e989b946e7e7ce5c1811c9c4616f Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Thu, 18 Apr 2019 18:45:10 +0200 Subject: [PATCH 014/178] Remove JAVA_HOME regarding registry from .travis.yml Signed-off-by: Jeroen Koekkoek --- .travis.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8274805..e619bf6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -77,13 +77,6 @@ before_install: # The real fix is to wait until Python and pip are both available on the # target. Until then download Conan from the official website and simply add # the extracted folder to the path. -# -# Maven requires JAVA_HOME to be set (at least on Windows), but Windows targets -# do not come with Java installed. For now it is installed through Chocolatey -# as a dependency of Maven, hence JAVA_HOME is only available after the -# package is installed. The problem is that the shell cannot be restarted and -# the path is not fixed as it contains the version number. To workaround this -# issue, JAVA_HOME is read from the registry and exported by this script. install: - if [ "${TRAVIS_OS_NAME}" = "windows" ]; then choco install innoextract; From 62a71a870f3e37669a301a727153c51929626ac1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 20 Apr 2019 10:28:33 +0200 Subject: [PATCH 015/178] fix race: delete reader & delete writer (#159) Adding and removing reader/writer matches can be done by multiple threads, and this can result in two threads simultaneously trying to do this on a single reader/writer pair. The code therefore always checks first whether the pair is (not) matched before proceeding. However, removing a reader from a proxy writer had part of the code outside this check. Therefore, if both entities are being deleted simultanously, there is a risk that local_reader_ary_remove is called twice for the same argument, and in that case, it asserts in one of them because the reader can no longer be found. The counting of the number of matched reliable readers suffers from the same race condition. This commit eliminates these race conditions by moving these operations into the block guarded by the aforementioned check. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_entity.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 0b0c8fa..c832a9b 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -1371,8 +1371,8 @@ static void writer_drop_local_connection (const struct nn_guid *wr_guid, struct if ((m = ut_avlLookup (&wr_local_readers_treedef, &wr->local_readers, &rd->e.guid)) != NULL) { ut_avlDelete (&wr_local_readers_treedef, &wr->local_readers, m); + local_reader_ary_remove (&wr->rdary, rd); } - local_reader_ary_remove (&wr->rdary, rd); ddsrt_mutex_unlock (&wr->e.lock); if (m != NULL && wr->status_cb) { @@ -1490,15 +1490,11 @@ static void proxy_writer_drop_connection (const struct nn_guid *pwr_guid, struct { ut_avlDelete (&pwr_readers_treedef, &pwr->readers, m); if (m->in_sync != PRMSS_SYNC) - { pwr->n_readers_out_of_sync--; - } + if (rd->reliable) + pwr->n_reliable_readers--; + local_reader_ary_remove (&pwr->rdary, rd); } - if (rd->reliable) - { - pwr->n_reliable_readers--; - } - local_reader_ary_remove (&pwr->rdary, rd); ddsrt_mutex_unlock (&pwr->e.lock); if (m != NULL) { From dd9aceb71313b6370710ce0896f5662346d8828d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 19 Feb 2019 10:53:09 +0100 Subject: [PATCH 016/178] small performance improvement in RHC The introduction of properly functioning query conditions adds some overhead, this commit removes some of that cost by avoiding some calls to update_conditions when there are no query conditions. It also removes the has_changed field from the instance, instead using a local boolean to track whether DATA_AVAILABLE should be raised or not. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_rhc.c | 76 ++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 30dc4f3..7f3029b 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -250,7 +250,6 @@ struct rhc_instance { unsigned isnew : 1; /* NEW or NOT_NEW view state */ unsigned a_sample_free : 1; /* whether or not a_sample is in use */ unsigned isdisposed : 1; /* DISPOSED or NOT_DISPOSED (if not disposed, wrcount determines ALIVE/NOT_ALIVE_NO_WRITERS) */ - unsigned has_changed : 1; /* To track changes in an instance - if number of samples are added or data is overwritten */ unsigned wr_iid_islive : 1; /* whether wr_iid is of a live writer */ unsigned inv_exists : 1; /* whether or not state change occurred since last sample (i.e., must return invalid sample) */ unsigned inv_isread : 1; /* whether or not that state change has been read before */ @@ -313,7 +312,6 @@ struct trigger_info_cmn { unsigned qminst; bool has_read; bool has_not_read; - bool has_changed; }; struct trigger_info_pre { @@ -552,7 +550,7 @@ static void inst_clear_invsample_if_exists (struct rhc *rhc, struct rhc_instance inst_clear_invsample (rhc, inst, trig_qc); } -static void inst_set_invsample (struct rhc *rhc, struct rhc_instance *inst, struct trigger_info_qcond *trig_qc) +static void inst_set_invsample (struct rhc *rhc, struct rhc_instance *inst, struct trigger_info_qcond *trig_qc, bool *nda) { if (!inst->inv_exists || inst->inv_isread) { @@ -563,6 +561,7 @@ static void inst_set_invsample (struct rhc *rhc, struct rhc_instance *inst, stru inst->inv_exists = 1; inst->inv_isread = 0; rhc->n_invsamples++; + *nda = true; } } @@ -651,7 +650,6 @@ static void init_trigger_info_cmn_nonmatch (struct trigger_info_cmn *info) info->qminst = ~0u; info->has_read = false; info->has_not_read = false; - info->has_changed = false; } static void get_trigger_info_cmn (struct trigger_info_cmn *info, struct rhc_instance *inst) @@ -659,12 +657,10 @@ static void get_trigger_info_cmn (struct trigger_info_cmn *info, struct rhc_inst info->qminst = qmask_of_inst (inst); info->has_read = inst_has_read (inst); info->has_not_read = inst_has_unread (inst); - info->has_changed = inst->has_changed; } static void get_trigger_info_pre (struct trigger_info_pre *info, struct rhc_instance *inst) { - inst->has_changed = 0; get_trigger_info_cmn (&info->c, inst); } @@ -680,15 +676,19 @@ static void init_trigger_info_qcond (struct trigger_info_qcond *qc) qc->inc_conds_sample = 0; } -static bool trigger_info_differs (const struct trigger_info_pre *pre, const struct trigger_info_post *post, const struct trigger_info_qcond *trig_qc) +static bool trigger_info_differs (const struct rhc *rhc, const struct trigger_info_pre *pre, const struct trigger_info_post *post, const struct trigger_info_qcond *trig_qc) { - return (pre->c.qminst != post->c.qminst || - pre->c.has_read != post->c.has_read || - pre->c.has_not_read != post->c.has_not_read || - pre->c.has_changed != post->c.has_changed || - trig_qc->dec_conds_invsample != trig_qc->inc_conds_invsample || - trig_qc->dec_conds_sample != trig_qc->inc_conds_sample || - trig_qc->dec_invsample_read != trig_qc->inc_invsample_read); + if (pre->c.qminst != post->c.qminst || + pre->c.has_read != post->c.has_read || + pre->c.has_not_read != post->c.has_not_read) + return true; + else if (rhc->nqconds == 0) + return false; + else + return (trig_qc->dec_conds_invsample != trig_qc->inc_conds_invsample || + trig_qc->dec_conds_sample != trig_qc->inc_conds_sample || + trig_qc->dec_invsample_read != trig_qc->inc_invsample_read || + trig_qc->dec_sample_read != trig_qc->inc_sample_read); } static bool add_sample (struct rhc *rhc, struct rhc_instance *inst, const struct proxy_writer_info *pwr_info, const struct ddsi_serdata *sample, status_cb_data_t *cb_data, struct trigger_info_qcond *trig_qc) @@ -722,9 +722,6 @@ static bool add_sample (struct rhc *rhc, struct rhc_instance *inst, const struct inst->nvread--; rhc->n_vread--; } - - /* set a flag to indicate instance has changed to notify data_available since the sample is overwritten */ - inst->has_changed = 1; } else { @@ -1042,7 +1039,7 @@ static int rhc_unregister_isreg_w_sideeffects (struct rhc *rhc, const struct rhc } } -static int rhc_unregister_updateinst (struct rhc *rhc, struct rhc_instance *inst, const struct proxy_writer_info * __restrict pwr_info, nn_wctime_t tstamp, struct trigger_info_qcond *trig_qc) +static int rhc_unregister_updateinst (struct rhc *rhc, struct rhc_instance *inst, const struct proxy_writer_info * __restrict pwr_info, nn_wctime_t tstamp, struct trigger_info_qcond *trig_qc, bool *nda) { assert (inst->wrcount > 0); @@ -1074,7 +1071,7 @@ static int rhc_unregister_updateinst (struct rhc *rhc, struct rhc_instance *inst care.) */ if (inst->latest == NULL || inst->latest->isread) { - inst_set_invsample (rhc, inst, trig_qc); + inst_set_invsample (rhc, inst, trig_qc, nda); update_inst (inst, pwr_info, false, tstamp); } if (!inst->isdisposed) @@ -1096,7 +1093,7 @@ static int rhc_unregister_updateinst (struct rhc *rhc, struct rhc_instance *inst /* Add invalid samples for transition to no-writers */ TRACE (",#0,empty,nowriters"); assert (inst_is_empty (inst)); - inst_set_invsample (rhc, inst, trig_qc); + inst_set_invsample (rhc, inst, trig_qc, nda); update_inst (inst, pwr_info, false, tstamp); account_for_empty_to_nonempty_transition (rhc, inst); inst->wr_iid_islive = 0; @@ -1105,8 +1102,10 @@ static int rhc_unregister_updateinst (struct rhc *rhc, struct rhc_instance *inst } } -static void dds_rhc_unregister (struct rhc *rhc, struct rhc_instance *inst, const struct proxy_writer_info * __restrict pwr_info, nn_wctime_t tstamp, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc) +static bool dds_rhc_unregister (struct rhc *rhc, struct rhc_instance *inst, const struct proxy_writer_info * __restrict pwr_info, nn_wctime_t tstamp, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc) { + bool notify_data_available = false; + /* 'post' always gets set; instance may have been freed upon return. */ TRACE (" unregister:"); if (!rhc_unregister_isreg_w_sideeffects (rhc, inst, pwr_info->iid)) @@ -1114,7 +1113,7 @@ static void dds_rhc_unregister (struct rhc *rhc, struct rhc_instance *inst, cons /* other registrations remain */ get_trigger_info_cmn (&post->c, inst); } - else if (rhc_unregister_updateinst (rhc, inst, pwr_info, tstamp, trig_qc)) + else if (rhc_unregister_updateinst (rhc, inst, pwr_info, tstamp, trig_qc, ¬ify_data_available)) { /* instance dropped */ init_trigger_info_cmn_nonmatch (&post->c); @@ -1124,6 +1123,7 @@ static void dds_rhc_unregister (struct rhc *rhc, struct rhc_instance *inst, cons /* no writers remain, but instance not empty */ get_trigger_info_cmn (&post->c, inst); } + return notify_data_available; } static struct rhc_instance *alloc_new_instance (const struct rhc *rhc, const struct proxy_writer_info *pwr_info, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) @@ -1207,7 +1207,8 @@ static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst else { if (inst->isdisposed) { - inst_set_invsample (rhc, inst, trig_qc); + bool nda_dummy = false; + inst_set_invsample (rhc, inst, trig_qc, &nda_dummy); } } @@ -1242,6 +1243,7 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info rhc_store_result_t stored; status_cb_data_t cb_data; /* Callback data for reader status callback */ bool delivered = true; + bool notify_data_available = false; TRACE ("rhc_store(%"PRIx64",%"PRIx64" si %x has_data %d:", tk->m_iid, wr_iid, statusinfo, has_data); if (!has_data && statusinfo == 0) @@ -1282,6 +1284,7 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info goto error_or_nochange; } init_trigger_info_cmn_nonmatch (&pre.c); + notify_data_available = true; } } else if (!inst_accepts_sample (rhc, inst, pwr_info, sample, has_data)) @@ -1300,7 +1303,8 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info } if (statusinfo & NN_STATUSINFO_UNREGISTER) { - dds_rhc_unregister (rhc, inst, pwr_info, sample->timestamp, &post, &trig_qc); + if (dds_rhc_unregister (rhc, inst, pwr_info, sample->timestamp, &post, &trig_qc)) + notify_data_available = true; } else { @@ -1389,11 +1393,12 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info inst->disposed_gen--; goto error_or_nochange; } + notify_data_available = true; } /* If instance became disposed, add an invalid sample if there are no samples left */ if (inst_became_disposed && inst->latest == NULL) - inst_set_invsample (rhc, inst, &trig_qc); + inst_set_invsample (rhc, inst, &trig_qc, ¬ify_data_available); update_inst (inst, pwr_info, true, sample->timestamp); @@ -1449,18 +1454,7 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info TRACE (")\n"); - const bool update_read_conditions = trigger_info_differs (&pre, &post, &trig_qc); - bool notify_data_available; - /* do not send data available notification when an instance is dropped */ - if ((post.c.qminst == ~0u) && (post.c.has_read == 0) && (post.c.has_not_read == 0) && (post.c.has_changed == false)) - notify_data_available = false; - else /* FIXME: now that trigger_info_differs incorporates details on samples added/removed, this might well be wrong */ - notify_data_available = update_read_conditions; - - if (update_read_conditions) - trigger_waitsets = update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst); - else - trigger_waitsets = false; + trigger_waitsets = trigger_info_differs (rhc, &pre, &post, &trig_qc) && update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst); assert (rhc_check_counts_locked (rhc, true, true)); @@ -1557,7 +1551,7 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ else { const bool was_empty = inst_is_empty (inst); - inst_set_invsample (rhc, inst, &trig_qc); + inst_set_invsample (rhc, inst, &trig_qc, ¬ify_data_available); if (was_empty) account_for_empty_to_nonempty_transition (rhc, inst); else @@ -1570,7 +1564,7 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ TRACE ("\n"); notify_data_available = true; - if (trigger_info_differs (&pre, &post, &trig_qc) && update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst)) + if (trigger_info_differs (rhc, &pre, &post, &trig_qc) && update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst)) trigger_waitsets = true; assert (rhc_check_counts_locked (rhc, true, false)); } @@ -1589,7 +1583,9 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ } if (trigger_waitsets) - dds_entity_status_signal (&rhc->reader->m_entity); + { + dds_entity_status_signal(&rhc->reader->m_entity); + } } } From 6e87841ea50f5cedb28f8c5ce7d583d0d1284327 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 3 Apr 2019 17:03:17 +0200 Subject: [PATCH 017/178] move MT19937 random generator to ddsrt Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_xmsg.c | 2 +- src/core/xtests/CMakeLists.txt | 2 +- src/core/xtests/mt19937ar.c | 184 ----------------------- src/core/xtests/mt19937ar.h | 46 ------ src/core/xtests/rhc_torture.c | 18 ++- src/ddsrt/CMakeLists.txt | 2 +- src/ddsrt/include/dds/ddsrt/random.h | 23 ++- src/ddsrt/src/cdtors.c | 3 + src/ddsrt/src/random.c | 205 +++++++++++++++++++++++--- src/ddsrt/src/random/posix/random.c | 17 +++ src/ddsrt/src/random/windows/random.c | 14 ++ src/ddsrt/tests/CMakeLists.txt | 1 + src/ddsrt/tests/random.c | 92 ++++++++++++ 13 files changed, 345 insertions(+), 264 deletions(-) delete mode 100644 src/core/xtests/mt19937ar.c delete mode 100644 src/core/xtests/mt19937ar.h create mode 100644 src/ddsrt/src/random/posix/random.c create mode 100644 src/ddsrt/src/random/windows/random.c create mode 100644 src/ddsrt/tests/random.c diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index ec1495d..d1c83cb 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -1261,7 +1261,7 @@ static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg) { /* We drop APPROXIMATELY a fraction of xmit_lossiness * 10**(-3) of all packets to be sent */ - if ((ddsrt_random () % 1000) < config.xmit_lossiness) + if ((ddsrt_random () % 1000) < (uint32_t) config.xmit_lossiness) { DDS_TRACE("(dropped)"); xp->call_flags = 0; diff --git a/src/core/xtests/CMakeLists.txt b/src/core/xtests/CMakeLists.txt index 9a67a6c..0b1d362 100644 --- a/src/core/xtests/CMakeLists.txt +++ b/src/core/xtests/CMakeLists.txt @@ -11,7 +11,7 @@ # idlc_generate(RhcTypes RhcTypes.idl) -add_executable(rhc_torture rhc_torture.c mt19937ar.c mt19937ar.h) +add_executable(rhc_torture rhc_torture.c) target_include_directories( rhc_torture PRIVATE diff --git a/src/core/xtests/mt19937ar.c b/src/core/xtests/mt19937ar.c deleted file mode 100644 index 31e347e..0000000 --- a/src/core/xtests/mt19937ar.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright(c) 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -/* - A C-program for MT19937, with initialization improved 2002/1/26. - Coded by Takuji Nishimura and Makoto Matsumoto. - - Before using, initialize the state by using init_genrand(seed) - or init_by_array(init_key, key_length). - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - Any feedback is very welcome. - http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html - email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) -*/ - -#include "mt19937ar.h" - -/* Period parameters */ -#define N 624 -#define M 397 -#define MATRIX_A 0x9908b0dfU /* constant vector a */ -#define UPPER_MASK 0x80000000U /* most significant w-r bits */ -#define LOWER_MASK 0x7fffffffU /* least significant r bits */ - -static uint32_t mt[N]; /* the array for the state vector */ -static uint32_t mti=N+1; /* mti==N+1 means mt[N] is not initialized */ - -/* initializes mt[N] with a seed */ -void init_genrand(uint32_t s) -{ - mt[0]= s & 0xffffffffU; - for (mti=1; mti> 30)) + mti); - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array mt[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ - mt[mti] &= 0xffffffffU; - /* for >32 bit machines */ - } -} - -/* initialize by an array with array-length */ -/* init_key is the array for initializing keys */ -/* key_length is its length */ -/* slight change for C++, 2004/2/26 */ -void init_by_array(uint32_t init_key[], size_t key_length) -{ - uint32_t i, j, k; - init_genrand(19650218U); - i=1; j=0; - k = (N>key_length ? N : (uint32_t)key_length); - for (; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525U)) - + init_key[j] + j; /* non linear */ - mt[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */ - i++; j++; - if (i>=N) { mt[0] = mt[N-1]; i=1; } - if (j>=(uint32_t)key_length) j=0; - } - for (k=N-1; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941U)) - - i; /* non linear */ - mt[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */ - i++; - if (i>=N) { mt[0] = mt[N-1]; i=1; } - } - - mt[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */ -} - -/* generates a random number on [0,0xffffffff]-interval */ -uint32_t genrand_int32(void) -{ - uint32_t y; - static uint32_t mag01[2]={0x0U, MATRIX_A}; - /* mag01[x] = x * MATRIX_A for x=0,1 */ - - if (mti >= N) { /* generate N words at one time */ - int kk; - - if (mti == N+1) /* if init_genrand() has not been called, */ - init_genrand(5489U); /* a default initial seed is used */ - - for (kk=0;kk> 1) ^ mag01[y & 0x1U]; - } - for (;kk> 1) ^ mag01[y & 0x1U]; - } - y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); - mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1U]; - - mti = 0; - } - - y = mt[mti++]; - - /* Tempering */ - y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680U; - y ^= (y << 15) & 0xefc60000U; - y ^= (y >> 18); - - return (uint32_t) y; -} - -/* generates a random number on [0,0x7fffffff]-interval */ -int32_t genrand_int31(void) -{ - return (int32_t)(genrand_int32()>>1); -} - -/* generates a random number on [0,1]-real-interval */ -double genrand_real1(void) -{ - return genrand_int32()*(1.0/4294967295.0); - /* divided by 2^32-1 */ -} - -/* generates a random number on [0,1)-real-interval */ -double genrand_real2(void) -{ - return genrand_int32()*(1.0/4294967296.0); - /* divided by 2^32 */ -} - -/* generates a random number on (0,1)-real-interval */ -double genrand_real3(void) -{ - return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); - /* divided by 2^32 */ -} - -/* generates a random number on [0,1) with 53-bit resolution*/ -double genrand_res53(void) -{ - uint32_t a=genrand_int32()>>5, b=genrand_int32()>>6; - return(a*67108864.0+b)*(1.0/9007199254740992.0); -} -/* These real versions are due to Isaku Wada, 2002/01/09 added */ diff --git a/src/core/xtests/mt19937ar.h b/src/core/xtests/mt19937ar.h deleted file mode 100644 index aaa08c8..0000000 --- a/src/core/xtests/mt19937ar.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright(c) 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef MT19937AR_H -#define MT19937AR_H - -#include -#include - -/* initializes mt[N] with a seed */ -void init_genrand(uint32_t s); - -/* initialize by an array with array-length */ -/* init_key is the array for initializing keys */ -/* key_length is its length */ -/* slight change for C++, 2004/2/26 */ -void init_by_array(uint32_t init_key[], size_t key_length); - -/* generates a random number on [0,0xffffffff]-interval */ -uint32_t genrand_int32(void); - -/* generates a random number on [0,0x7fffffff]-interval */ -int32_t genrand_int31(void); - -/* generates a random number on [0,1]-real-interval */ -double genrand_real1(void); - -/* generates a random number on [0,1)-real-interval */ -double genrand_real2(void); - -/* generates a random number on (0,1)-real-interval */ -double genrand_real3(void); - -/* generates a random number on [0,1) with 53-bit resolution*/ -double genrand_res53(void); -/* These real versions are due to Isaku Wada, 2002/01/09 added */ - -#endif diff --git a/src/core/xtests/rhc_torture.c b/src/core/xtests/rhc_torture.c index 827d04d..bc7c4fb 100644 --- a/src/core/xtests/rhc_torture.c +++ b/src/core/xtests/rhc_torture.c @@ -18,6 +18,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/sync.h" +#include "dds/ddsrt/random.h" #include "dds/dds.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds__entity.h" @@ -32,7 +33,6 @@ #include "dds__rhc.h" #include "dds/ddsi/ddsi_iid.h" -#include "mt19937ar.h" #include "RhcTypes.h" #ifndef _MSC_VER @@ -41,6 +41,8 @@ #define STATIC_ARRAY_DIM #endif +static ddsrt_prng_t prng; + static struct ddsi_sertopic *mdtopic; static struct thread_state1 *mainthread; static dds_time_t tref_dds; @@ -669,14 +671,14 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, int lastprint_pct = 0; for (int i = 0; i < count; i++) { - const int32_t keyval = (int32_t) (genrand_int32 () % N_KEYVALS); - const uint32_t which = genrand_int32 () % 3; + const int32_t keyval = (int32_t) (ddsrt_prng_random (&prng) % N_KEYVALS); + const uint32_t which = ddsrt_prng_random (&prng) % 3; uint32_t oper_base; uint32_t oper; /* generate uniform number in range 0 .. N, then map to operation following the frequency table */ do { - oper_base = genrand_int32 (); + oper_base = ddsrt_prng_random (&prng); } while (oper_base >= opthres[sizeof (opfreqs) / sizeof (opfreqs[0]) - 1]); for (oper = 0; oper < sizeof (opfreqs) / sizeof (opfreqs[0]); oper++) { @@ -745,19 +747,19 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, tkall (rhc[k], NULL, print && k == 0, states_seen); break; case 8: { - uint32_t cond = genrand_int32 () % (uint32_t) nconds; + uint32_t cond = ddsrt_prng_random (&prng) % (uint32_t) nconds; for (size_t k = 0; k < nrd; k++) rdcond (rhc[k], rhcconds[cond], NULL, 0, print && k == 0, states_seen); break; } case 9: { - uint32_t cond = genrand_int32 () % (uint32_t) nconds; + uint32_t cond = ddsrt_prng_random (&prng) % (uint32_t) nconds; for (size_t k = 0; k < nrd; k++) tkcond (rhc[k], rhcconds[cond], NULL, 0, print && k == 0, states_seen); break; } case 10: { - uint32_t cond = genrand_int32 () % (uint32_t) nconds; + uint32_t cond = ddsrt_prng_random (&prng) % (uint32_t) nconds; for (size_t k = 0; k < nrd; k++) tkcond (rhc[k], rhcconds[cond], NULL, 1, print && k == 0, states_seen); break; @@ -826,7 +828,7 @@ int main (int argc, char **argv) print = (atoi (argv[4]) != 0); printf ("prng seed %u first %d count %d print %d\n", seed, first, count, print); - init_genrand (seed); + ddsrt_prng_init_simple (&prng, seed); memset (rres_mseq, 0, sizeof (rres_mseq)); for (size_t i = 0; i < sizeof (rres_iseq) / sizeof(rres_iseq[0]); i++) diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 5179742..7830104 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -165,7 +165,7 @@ find_package(Threads REQUIRED) target_link_libraries(ddsrt INTERFACE Threads::Threads) if(WIN32) - target_link_libraries(ddsrt INTERFACE wsock32 ws2_32 iphlpapi) + target_link_libraries(ddsrt INTERFACE wsock32 ws2_32 iphlpapi bcrypt) elseif(UNIX) check_library_exists(c clock_gettime "" HAVE_CLOCK_GETTIME) if(NOT HAVE_CLOCK_GETTIME) diff --git a/src/ddsrt/include/dds/ddsrt/random.h b/src/ddsrt/include/dds/ddsrt/random.h index 4e44c82..0ef600f 100644 --- a/src/ddsrt/include/dds/ddsrt/random.h +++ b/src/ddsrt/include/dds/ddsrt/random.h @@ -12,13 +12,34 @@ #ifndef DDSRT_RANDOM_H #define DDSRT_RANDOM_H +#include +#include #include "dds/export.h" #if defined (__cplusplus) extern "C" { #endif -DDS_EXPORT long ddsrt_random(void); +#define DDSRT_MT19937_N 624 + +typedef struct ddsrt_prng_seed { + uint32_t key[8]; +} ddsrt_prng_seed_t; + +typedef struct ddsrt_prng { + uint32_t mt[DDSRT_MT19937_N]; + uint32_t mti; +} ddsrt_prng_t; + +DDS_EXPORT void ddsrt_random_init (void); +DDS_EXPORT void ddsrt_random_fini (void); + +DDS_EXPORT void ddsrt_prng_init_simple (ddsrt_prng_t *prng, uint32_t seed); +DDS_EXPORT bool ddsrt_prng_makeseed (struct ddsrt_prng_seed *seed); +DDS_EXPORT void ddsrt_prng_init (ddsrt_prng_t *prng, const struct ddsrt_prng_seed *seed); +DDS_EXPORT uint32_t ddsrt_prng_random (ddsrt_prng_t *prng); + +DDS_EXPORT uint32_t ddsrt_random (void); #if defined (__cplusplus) } diff --git a/src/ddsrt/src/cdtors.c b/src/ddsrt/src/cdtors.c index a3088fb..3888c87 100644 --- a/src/ddsrt/src/cdtors.c +++ b/src/ddsrt/src/cdtors.c @@ -13,6 +13,7 @@ #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/time.h" +#include "dds/ddsrt/random.h" #if _WIN32 /* Sockets API initialization is only necessary on Microsoft Windows. The @@ -41,6 +42,7 @@ retry: ddsrt_winsock_init(); ddsrt_time_init(); #endif + ddsrt_random_init(); ddsrt_atomic_or32(&init_status, INIT_STATUS_OK); } else { while (v > 1 && !(v & INIT_STATUS_OK)) { @@ -65,6 +67,7 @@ void ddsrt_fini (void) if (nv == 1) { ddsrt_mutex_destroy(&init_mutex); + ddsrt_random_fini(); #if _WIN32 ddsrt_winsock_fini(); ddsrt_time_fini(); diff --git a/src/ddsrt/src/random.c b/src/ddsrt/src/random.c index 582cb48..7f2943a 100644 --- a/src/ddsrt/src/random.c +++ b/src/ddsrt/src/random.c @@ -9,36 +9,197 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ + +/* + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) +*/ + #include #include +#include #include "dds/ddsrt/random.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/time.h" +#include "dds/ddsrt/process.h" -#if _WIN32 -#define _CRT_RAND_S -#include +#define N DDSRT_MT19937_N +#define M 397 +#define MATRIX_A 0x9908b0dfU /* constant vector a */ +#define UPPER_MASK 0x80000000U /* most significant w-r bits */ +#define LOWER_MASK 0x7fffffffU /* least significant r bits */ -long random (void) +static ddsrt_prng_t default_prng; +static ddsrt_mutex_t default_prng_lock; + +/* initializes mt[N] with a seed */ +static void init_genrand (ddsrt_prng_t *prng, uint32_t s) { - /* rand() is a really terribly bad PRNG */ - /* FIXME: Indeed (especially if not seeded), use rand_s instead. */ - union { long x; unsigned char c[4]; } t; - int i; - for (i = 0; i < 4; i++) - t.c[i] = (unsigned char) ((rand () >> 4) & 0xff); -#if RAND_MAX == INT32_MAX || RAND_MAX == 0x7fff - t.x &= RAND_MAX; -#elif RAND_MAX <= 0x7ffffffe - t.x %= (RAND_MAX+1); -#else -#error "RAND_MAX out of range" -#endif - return t.x; + prng->mt[0] = s; + for (prng->mti = 1; prng->mti < N; prng->mti++) + { + prng->mt[prng->mti] = (1812433253U * (prng->mt[prng->mti-1] ^ (prng->mt[prng->mti-1] >> 30)) + prng->mti); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array mt[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + } } -#endif -long ddsrt_random(void) +/* initialize by an array with array-length */ +/* init_key is the array for initializing keys */ +/* key_length is its length */ +/* slight change for C++, 2004/2/26 */ +static void init_by_array (ddsrt_prng_t *prng, const uint32_t init_key[], size_t key_length) { - /* FIXME: Not MT-safe, should use random_r (or a real PRNG) instead. */ - return random(); + uint32_t i, j, k; + init_genrand (prng, 19650218U); + i = 1; j = 0; + k = (N > key_length ? N : (uint32_t) key_length); + for (; k; k--) + { + prng->mt[i] = (prng->mt[i] ^ ((prng->mt[i-1] ^ (prng->mt[i-1] >> 30)) * 1664525U)) + init_key[j] + j; /* non linear */ + i++; j++; + if (i >= N) + { + prng->mt[0] = prng->mt[N-1]; + i=1; + } + if (j >= key_length) + { + j = 0; + } + } + for (k = N-1; k; k--) + { + prng->mt[i] = (prng->mt[i] ^ ((prng->mt[i-1] ^ (prng->mt[i-1] >> 30)) * 1566083941U)) - i; /* non linear */ + i++; + if (i >= N) + { + prng->mt[0] = prng->mt[N-1]; + i = 1; + } + } + prng->mt[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */ +} + +void ddsrt_prng_init_simple (ddsrt_prng_t *prng, uint32_t seed) +{ + init_genrand (prng, seed); +} + +void ddsrt_prng_init (ddsrt_prng_t *prng, const struct ddsrt_prng_seed *seed) +{ + init_by_array (prng, seed->key, sizeof (seed->key) / sizeof (seed->key[0])); +} + +/* generates a random number on [0,0xffffffff]-interval */ +uint32_t ddsrt_prng_random (ddsrt_prng_t *prng) +{ + /* mag01[x] = x * MATRIX_A for x=0,1 */ + static const uint32_t mag01[2] = { 0x0U, MATRIX_A }; + uint32_t y; + + if (prng->mti >= N) + { + /* generate N words at one time */ + int kk; + + for (kk=0; kk < N-M; kk++) + { + y = (prng->mt[kk] & UPPER_MASK) | (prng->mt[kk+1] & LOWER_MASK); + prng->mt[kk] = prng->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1U]; + } + for (; kk < N-1; kk++) + { + y = (prng->mt[kk] & UPPER_MASK) | (prng->mt[kk+1] & LOWER_MASK); + prng->mt[kk] = prng->mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1U]; + } + y = (prng->mt[N-1] & UPPER_MASK) | (prng->mt[0] & LOWER_MASK); + prng->mt[N-1] = prng->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1U]; + + prng->mti = 0; + } + + y = prng->mt[prng->mti++]; + + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680U; + y ^= (y << 15) & 0xefc60000U; + y ^= (y >> 18); + + return y; +} + +uint32_t ddsrt_random (void) +{ + uint32_t x; + ddsrt_mutex_lock (&default_prng_lock); + x = ddsrt_prng_random (&default_prng); + ddsrt_mutex_unlock (&default_prng_lock); + return x; +} + +void ddsrt_random_init (void) +{ + ddsrt_prng_seed_t seed; + if (!ddsrt_prng_makeseed (&seed)) + { + /* Poor man's initialisation */ + struct lengthof_seed_large_enough { + char ok[sizeof (seed.key) / sizeof (seed.key[0]) >= 3 ? 1 : -1]; + }; + memset (&seed, 0, sizeof (seed)); + dds_time_t now = dds_time (); + seed.key[0] = (uint32_t) ddsrt_getpid (); + seed.key[1] = (uint32_t) ((uint64_t) now >> 32); + seed.key[2] = (uint32_t) now; + } + ddsrt_prng_init (&default_prng, &seed); + ddsrt_mutex_init (&default_prng_lock); +} + +void ddsrt_random_fini (void) +{ + ddsrt_mutex_destroy (&default_prng_lock); } diff --git a/src/ddsrt/src/random/posix/random.c b/src/ddsrt/src/random/posix/random.c new file mode 100644 index 0000000..067f42b --- /dev/null +++ b/src/ddsrt/src/random/posix/random.c @@ -0,0 +1,17 @@ +#include +#include +#include "dds/ddsrt/random.h" + +bool ddsrt_prng_makeseed (struct ddsrt_prng_seed *seed) +{ + FILE *rndfile; + memset (seed->key, 0, sizeof (seed->key)); + if ((rndfile = fopen ("/dev/urandom", "rb")) == NULL) + return false; + else + { + size_t n = fread (seed->key, sizeof (seed->key), 1, rndfile); + fclose (rndfile); + return (n == 1); + } +} diff --git a/src/ddsrt/src/random/windows/random.c b/src/ddsrt/src/random/windows/random.c new file mode 100644 index 0000000..6c912b3 --- /dev/null +++ b/src/ddsrt/src/random/windows/random.c @@ -0,0 +1,14 @@ +#include +#define WIN32_NO_STATUS +#include +#include "bcrypt.h" +#include +#include "dds/ddsrt/random.h" + +bool ddsrt_prng_makeseed (struct ddsrt_prng_seed *seed) +{ + NTSTATUS res; + memset (seed->key, 0, sizeof (seed->key)); + res = BCryptGenRandom (NULL, (PUCHAR) seed->key, (ULONG) sizeof (seed->key), BCRYPT_USE_SYSTEM_PREFERRED_RNG); + return (res >= 0); +} diff --git a/src/ddsrt/tests/CMakeLists.txt b/src/ddsrt/tests/CMakeLists.txt index 2b3483d..552cfd2 100644 --- a/src/ddsrt/tests/CMakeLists.txt +++ b/src/ddsrt/tests/CMakeLists.txt @@ -22,6 +22,7 @@ set(sources "thread_cleanup.c" "string.c" "log.c" + "random.c" "strlcpy.c" "socket.c" "select.c") diff --git a/src/ddsrt/tests/random.c b/src/ddsrt/tests/random.c new file mode 100644 index 0000000..f1f2dca --- /dev/null +++ b/src/ddsrt/tests/random.c @@ -0,0 +1,92 @@ +/* + * 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 +#include + +#include "CUnit/Test.h" +#include "dds/ddsrt/random.h" + +#define N_PRNG 4 +#define N_DATA 10 + +CU_Test(ddsrt_random, mt19937) +{ + static const uint32_t refdata[N_DATA] = { + 3499211612u, 581869302u, 3890346734u, 3586334585u, 545404204u, + 4161255391u, 3922919429u, 949333985u, 2715962298u, 1323567403u + }; + ddsrt_prng_t prng; + ddsrt_prng_init_simple (&prng, 5489U); + for (size_t i = 0; i < N_DATA; i++) + { + uint32_t x = ddsrt_prng_random (&prng); + CU_ASSERT_EQUAL_FATAL(x, refdata[i]); + } +} + +CU_Test(ddsrt_random, makeseed) +{ + ddsrt_prng_seed_t seeds[N_PRNG]; + + /* Until proven otherwise, assume all platforms have a good way of getting multiple seeds */ + memset (seeds, 0, sizeof (seeds)); + for (size_t i = 0; i < N_PRNG; i++) + { + bool ok = ddsrt_prng_makeseed (&seeds[i]); + CU_ASSERT_FATAL(ok); + } + + /* Any pair the same is possible, but the likelihood should be so small that it is worth accepting + an intermittently failing test */ + for (size_t i = 0; i < N_PRNG; i++) + { + for (size_t j = i + 1; j < N_PRNG; j++) + CU_ASSERT_FATAL (memcmp (&seeds[i], &seeds[j], sizeof (seeds[i])) != 0); + } + + /* A short random sequence generated from each of the different seeds should be unique -- again, + there is no guarantee but only an overwhelming likelihood */ + ddsrt_prng_t prngs[N_PRNG]; + uint32_t data[N_PRNG][N_DATA]; + memset (data, 0, sizeof (data)); + for (size_t i = 0; i < N_PRNG; i++) + { + ddsrt_prng_init (&prngs[i], &seeds[i]); + for (size_t j = 0; j < N_DATA; j++) + data[i][j] = ddsrt_prng_random (&prngs[i]); + } + for (size_t i = 0; i < N_PRNG; i++) + { + for (size_t j = i + 1; j < N_PRNG; j++) + CU_ASSERT_FATAL (memcmp (&data[i], &data[j], sizeof (data[i])) != 0); + } +} + +CU_Test(ddsrt_random, default_random) +{ +#define N_BINS 128 +#define N_PER_BIN 100 + uint32_t bins[N_BINS]; + memset (bins, 0, sizeof (bins)); + for (size_t i = 0; i < N_PER_BIN * N_BINS; i++) + { + uint32_t x = ddsrt_random (); + bins[x % N_BINS]++; + } + double chisq = 0.0; + for (size_t i = 0; i < N_BINS; i++) + chisq += ((bins[i] - N_PER_BIN) * (bins[i] - N_PER_BIN)) / (double) N_PER_BIN; + /* Solve[CDF[ChiSquareDistribution[127], x] == 999/1000] */ + CU_ASSERT (chisq < 181.993); +} From 6f35d88d5426eab95c76a38d9727861c0d74506f Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 4 Apr 2019 15:35:11 +0200 Subject: [PATCH 018/178] install core/ddsi and util header files Some of the former are required to implement alternative serialisation methods; the latter is just generally useful. For the time being these are not part of the formal API and not subject to backwards compatibility. Still, they have value for quickly building tools on that use Cyclone and happen to need any of these functions. Signed-off-by: Erik Boasson --- src/core/CMakeLists.txt | 8 ++++++-- src/core/ddsi/CMakeLists.txt | 6 +++++- .../ddsi/include/dds/ddsi/probes-constants.h | 18 ------------------ src/util/CMakeLists.txt | 5 +++++ 4 files changed, 16 insertions(+), 21 deletions(-) delete mode 100644 src/core/ddsi/include/dds/ddsi/probes-constants.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 2ef2fc3..39a580f 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -53,9 +53,13 @@ include(ddsc/CMakeLists.txt) target_link_libraries(ddsc PRIVATE util) target_link_libraries(ddsc PRIVATE ddsrt) target_compile_definitions( - ddsc PUBLIC $>) + ddsc PUBLIC + $> + $>) target_include_directories( - ddsc PUBLIC $>) + ddsc PUBLIC + $> + $>) # SOVERSION should increase on incompatible ABI change set_target_properties(ddsc PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 8821665..683ad6e 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -78,7 +78,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" ddsi_iid.h ddsi_tkmap.h ddsi_vendor.h - probes-constants.h q_addrset.h q_bitset.h q_bswap.h @@ -126,3 +125,8 @@ target_sources(ddsc target_include_directories(ddsc PRIVATE "${CMAKE_CURRENT_LIST_DIR}/include") + +install( + DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include/dds" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + COMPONENT dev) diff --git a/src/core/ddsi/include/dds/ddsi/probes-constants.h b/src/core/ddsi/include/dds/ddsi/probes-constants.h deleted file mode 100644 index 83b15ab..0000000 --- a/src/core/ddsi/include/dds/ddsi/probes-constants.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef PROBES_CONSTANTS_H -#define PROBES_CONSTANTS_H -#define DROP_QUEUE_FULL 1 -#define DROP_TOO_OLD 2 -#define DROP_REORDER_FULL 3 -#define DROP_DUPLICATE 4 -#endif diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 4f44a70..84088c3 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -37,6 +37,11 @@ target_include_directories( "$" "$>") +install( + DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include/dds" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + COMPONENT dev) + # TODO: improve test inclusion. if((BUILD_TESTING) AND ((NOT DEFINED MSVC_VERSION) OR (MSVC_VERSION GREATER "1800"))) add_subdirectory(tests) From 58c0cb231730b52ec06940b766db8af210bb98df Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 7 Apr 2019 17:30:32 +0200 Subject: [PATCH 019/178] fix trace print of tkmap_instance address Fix the trace to contain a print of the address of the tkamp_instance (along with the instance id), rather than the address of the stack variable pointing to the tkmap_instance. Signed-off-by: Erik Boasson --- src/core/ddsi/src/ddsi_tkmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsi/src/ddsi_tkmap.c b/src/core/ddsi/src/ddsi_tkmap.c index fbc6094..0d1c6bd 100644 --- a/src/core/ddsi/src/ddsi_tkmap.c +++ b/src/core/ddsi/src/ddsi_tkmap.c @@ -203,7 +203,7 @@ retry: if (tk && rd) { - DDS_TRACE("tk=%p iid=%"PRIx64" ", (void *) &tk, tk->m_iid); + DDS_TRACE("tk=%p iid=%"PRIx64" ", (void *) tk, tk->m_iid); } return tk; } From 9b3a71e1abed00a96c8bd03e694dd044f9970d4f Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 19 Feb 2019 10:57:21 +0100 Subject: [PATCH 020/178] lift limits on handle allocation and reuse (#95) The old entity handle mechanism suffered from a number of problems, the most terrible one being that it would only ever allocate 1000 handles (not even have at most 1000 in use at the same time). Secondarily, it was protected by a single mutex that actually does show up as a limiting factor in, say, a polling-based throughput test with small messages. Thirdly, it tried to provide for various use cases that don't exist in practice but add complexity and overhead. This commit totally rewrites the mechanism, by replacing the old array with a hash table and allowing a near-arbitrary number of handles as well as reuse of handles. It also removes the entity "kind" bits in the most significant bits of the handles, because they only resulted in incorrect checking of argument validity. All that is taken out, but there is still more cleaning up to be done. It furthermore removes an indirection in the handle-to-entity lookup by embedding the "dds_handle_link" structure in the entity. Handle allocation is randomized to avoid the have a high probability of quickly finding an available handle (the total number of handles is limited to a number much smaller than the domain from which they are allocated). The likelihood of handle reuse is still dependent on the number of allocated handles -- the fewer handles there are, the longer the expected time to reuse. Non-randomized handles would give a few guarantees more, though. It moreover moves the code from the "util" to the "core/ddsc" component, because it really is only used for entities, and besides the new implementation relies on the deferred freeing (a.k.a. garbage collection mechanism) implemented in the core. The actual handle management has two variants, selectable with a macro: the preferred embodiment uses a concurrent hash table, the actually used one performs all operations inside a single mutex and uses a non-concurrent version of the hash table. The reason the less-predeferred embodiment is used is that the concurrent version requires the freeing of entity objects to be deferred (much like the GUID-to-entity hash tables in DDSI function, or indeed the key value to instance handle mapping). That is a fair bit of work, and the non-concurrent version is a reasonable intermediate step. Signed-off-by: Erik Boasson --- src/CMakeLists.txt | 1 - src/cmake/modules/FileIDs.cmake | 146 ------- src/core/CMakeLists.txt | 2 - src/core/ddsc/.fileids | 33 -- src/core/ddsc/CMakeLists.txt | 2 + src/core/ddsc/include/dds/dds.h | 11 +- .../ddsc/include/dds/ddsc/dds_public_impl.h | 4 +- src/core/ddsc/src/dds__entity.h | 30 +- src/core/ddsc/src/dds__err.h | 15 +- .../ddsc/src/dds__handles.h} | 131 ++---- src/core/ddsc/src/dds__publisher.h | 3 + src/core/ddsc/src/dds__subscriber.h | 3 +- src/core/ddsc/src/dds__types.h | 7 +- src/core/ddsc/src/dds_coherent.c | 46 +- src/core/ddsc/src/dds_entity.c | 205 ++++----- src/core/ddsc/src/dds_guardcond.c | 6 +- src/core/ddsc/src/dds_handles.c | 267 ++++++++++++ src/core/ddsc/src/dds_init.c | 36 +- src/core/ddsc/src/dds_participant.c | 8 +- src/core/ddsc/src/dds_publisher.c | 54 +-- src/core/ddsc/src/dds_querycond.c | 4 +- src/core/ddsc/src/dds_read.c | 6 +- src/core/ddsc/src/dds_readcond.c | 39 +- src/core/ddsc/src/dds_reader.c | 201 +++++---- src/core/ddsc/src/dds_subscriber.c | 3 + src/core/ddsc/src/dds_topic.c | 10 +- src/core/ddsc/src/dds_waitset.c | 14 +- src/core/ddsc/src/dds_writer.c | 87 ++-- src/core/ddsc/tests/CMakeLists.txt | 2 +- src/core/ddsc/tests/builtin_topics.c | 9 +- src/core/ddsc/tests/dispose.c | 24 +- src/core/ddsc/tests/entity_hierarchy.c | 50 +-- src/core/ddsc/tests/entity_status.c | 100 ++--- src/core/ddsc/tests/file_id.c | 37 -- src/core/ddsc/tests/publisher.c | 29 +- src/core/ddsc/tests/querycondition.c | 12 +- src/core/ddsc/tests/read_instance.c | 16 +- src/core/ddsc/tests/readcondition.c | 12 +- src/core/ddsc/tests/reader.c | 32 +- src/core/ddsc/tests/reader_iterator.c | 16 +- src/core/ddsc/tests/register.c | 4 +- src/core/ddsc/tests/take_instance.c | 16 +- src/core/ddsc/tests/topic.c | 4 +- src/core/ddsc/tests/unregister.c | 16 +- src/core/ddsc/tests/unsupported.c | 4 +- src/core/ddsc/tests/waitset.c | 30 +- src/core/ddsc/tests/write.c | 2 +- src/core/ddsc/tests/writer.c | 4 +- src/core/ddsi/.fileids | 40 -- src/core/ddsi/src/q_thread_inlines.c | 1 - src/tools/pubsub/common.c | 1 - src/util/CMakeLists.txt | 2 +- src/util/src/ut_handleserver.c | 393 ------------------ src/util/tests/CMakeLists.txt | 18 +- src/util/tests/handleserver.c | 304 -------------- 55 files changed, 871 insertions(+), 1681 deletions(-) delete mode 100644 src/cmake/modules/FileIDs.cmake delete mode 100644 src/core/ddsc/.fileids rename src/{util/include/dds/util/ut_handleserver.h => core/ddsc/src/dds__handles.h} (58%) create mode 100644 src/core/ddsc/src/dds_handles.c delete mode 100644 src/core/ddsc/tests/file_id.c delete mode 100644 src/core/ddsi/.fileids delete mode 100644 src/util/src/ut_handleserver.c delete mode 100644 src/util/tests/handleserver.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 19b0515..52a062e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -152,7 +152,6 @@ if(NOT (${USE_SANITIZER} STREQUAL "none")) link_libraries(-fno-omit-frame-pointer -fsanitize=${USE_SANITIZER}) endif() -include(FileIDs) include(GNUInstallDirs) include(AnalyzeBuild) # Include Coverage before CTest so that COVERAGE_COMMAND can be modified diff --git a/src/cmake/modules/FileIDs.cmake b/src/cmake/modules/FileIDs.cmake deleted file mode 100644 index 5c79198..0000000 --- a/src/cmake/modules/FileIDs.cmake +++ /dev/null @@ -1,146 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# - -# To uniquely identify the origin of every error all source files must be -# assigned a pseudo unique identifier (or module). Because only 32 bits are -# available in the return code (for now) to store the sign bit (1), return -# code (4), line number (8) and file identifier, using a deterministic hash -# will likely lead to collisions. To work around this issue a static map is -# applied, which also ensures that file identifiers are persisted accross -# versions/branches. Of course one could choose to specify the module manually -# with every return, but that is tedious and error prone. - -if(FILE_IDS_INCLUDED) - return() -endif() -set(FILE_IDS_INCLUDED true) - - -# Verify syntax for all .fileids files and ensure no source file id is used -# more than once. -file(GLOB_RECURSE fils__ LIST_DIRECTORIES false "${CMAKE_SOURCE_DIR}/.fileids") - -set(ids__) -foreach(fil__ ${fils__}) - file(READ "${fil__}" lines__) - string(REGEX REPLACE "\n" ";" lines__ ${lines__}) - foreach(line__ ${lines__}) - if("${line__}" MATCHES "^[ \t]*([0-9]+)[ \t]+.*$") - set(id__ "${CMAKE_MATCH_1}") - if(${id__} IN_LIST ids__) - set(dup__ true) - message(STATUS "Id ${id__} used more than once") - else() - list(APPEND ids__ ${id__}) - endif() - elseif(NOT "${line__}" MATCHES "^[ \t]*#") - message(FATAL_ERROR "Syntax error in ${fil__}") - endif() - endforeach() -endforeach() - -if(dup__) - message(FATAL_ERROR "Duplicate ids") -endif() - -function(JOIN lst glue var) - string(REPLACE ";" "${glue}" tmp "${${lst}}") - set(${var} "${tmp}" PARENT_SCOPE) -endfunction() - -function(FILE_ID src var) # private - # .fileids files may reside in subdirectories to keep them together with the - # files they assign an identifier to, much like .gitignore files - set(dir "${CMAKE_SOURCE_DIR}") - set(parts "${src}") - string(REGEX REPLACE "[/\\]+" ";" parts "${parts}") - while(parts) - set(map "${dir}/.fileids") - join(parts "/" fil) - list(APPEND maps "${map}^${fil}") - list(GET parts 0 part) - list(REMOVE_AT parts 0) - set(dir "${dir}/${part}") - endwhile() - - set(id) - foreach(entry ${maps}) - string(REPLACE "^" ";" entry "${entry}") - list(GET entry 0 map) - list(GET entry 1 fil) - if(EXISTS "${map}") - file(READ "${map}" contents) - string(REGEX REPLACE "\n" ";" lines "${contents}") - - foreach(line ${lines}) - if("${line}" MATCHES "^[ \t]*([0-9]+)[ \t]+(.*)$") - set(id "${CMAKE_MATCH_1}") - string(STRIP "${CMAKE_MATCH_2}" expr) - if("${fil}" STREQUAL "${expr}") - set(${var} ${id} PARENT_SCOPE) - return() - endif() - elseif(NOT "${line}" MATCHES "^[ \t]*#") - message(FATAL_ERROR "Syntax error in ${map}") - endif() - endforeach() - endif() - endforeach() -endfunction() - -# Source file properties are visible only to targets added in the same -# directory (CMakeLists.txt). -# https://cmake.org/cmake/help/latest/command/set_source_files_properties.html -function(SET_TARGET_FILE_IDS tgt) - get_target_property(external ${tgt} IMPORTED) - get_target_property(alias ${tgt} ALIASED_TARGET) - string(LENGTH "${CMAKE_SOURCE_DIR}" len) - math(EXPR len "${len} + 1") # strip slash following source dir too - - if((NOT external) AND (NOT alias)) - get_target_property(srcs ${tgt} SOURCES) - get_target_property(src_dir ${tgt} SOURCE_DIR) - foreach(src ${srcs}) - set(id) - if(IS_ABSOLUTE "${src}") - set(fil "${src}") - else() - set(fil "${src_dir}/${src}") - endif() - - get_filename_component(fil "${fil}" ABSOLUTE) - - string(FIND "${fil}" "${CMAKE_SOURCE_DIR}" pos) - if(${pos} EQUAL 0) - string(SUBSTRING "${fil}" ${len} -1 rel) - file_id("${rel}" id) - endif() - - if(id) - if(("${source_file_id_${id}}" STREQUAL "") OR - ("${source_file_id_${id}}" STREQUAL "${rel}")) - set("source_file_id_${id}" "${rel}" CACHE INTERNAL "") - set_source_files_properties( - "${src}" PROPERTIES COMPILE_DEFINITIONS __FILE_ID__=${id}) - else() - message(FATAL_ERROR "Same file id for ${rel} and ${source_file_id_${id}}") - endif() - else() - get_filename_component(ext "${rel}" EXT) - if (NOT "${ext}" MATCHES "\.h*") - message(FATAL_ERROR "No source file id for ${rel}") - endif() - endif() - endforeach() - endif() -endfunction() - diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 39a580f..071d6e6 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -64,8 +64,6 @@ target_include_directories( # SOVERSION should increase on incompatible ABI change set_target_properties(ddsc PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) -set_target_file_ids(ddsc) - # Create a pseudo-target that other targets (i.e. examples, tests) can depend # on and can also be provided as import-target by a package-file when building # those targets outside the regular Cyclone build-tree (i.e. the installed tree) diff --git a/src/core/ddsc/.fileids b/src/core/ddsc/.fileids deleted file mode 100644 index f24df98..0000000 --- a/src/core/ddsc/.fileids +++ /dev/null @@ -1,33 +0,0 @@ -# ddsc sources -40 src/dds_alloc.c -41 src/dds_coherent.c -42 src/dds_iid.c -43 src/dds_participant.c -44 src/dds_reader.c -45 src/dds_thread.c -46 src/dds_writer.c -47 src/dds_init.c -48 src/dds_publisher.c -49 src/dds_rhc.c -50 src/dds_time.c -51 src/q_osplser.c -52 src/dds_domain.c -53 src/dds_instance.c -54 src/dds_qos.c -55 src/dds_tkmap.c -56 src/dds_entity.c -57 src/dds_key.c -58 src/dds_querycond.c -59 src/dds_topic.c -60 src/dds_err.c -61 src/dds_listener.c -62 src/dds_read.c -63 src/dds_stream.c -64 src/dds_waitset.c -65 src/dds_log.c -66 src/dds_readcond.c -67 src/dds_subscriber.c -68 src/dds_write.c -70 src/dds_builtin.c -72 src/dds_guardcond.c -73 src/dds_whc.c diff --git a/src/core/ddsc/CMakeLists.txt b/src/core/ddsc/CMakeLists.txt index 5b3658e..a97ccda 100644 --- a/src/core/ddsc/CMakeLists.txt +++ b/src/core/ddsc/CMakeLists.txt @@ -22,6 +22,7 @@ PREPEND(srcs_ddsc "${CMAKE_CURRENT_LIST_DIR}/src" dds_domain.c dds_instance.c dds_qos.c + dds_handles.c dds_entity.c dds_key.c dds_querycond.c @@ -54,6 +55,7 @@ PREPEND(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src" dds__alloc.h dds__builtin.h dds__domain.h + dds__handles.h dds__entity.h dds__init.h dds__key.h diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index 124a2e6..3d5dc42 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -69,6 +69,9 @@ struct ddsi_serdata; */ DDS_EXPORT dds_domainid_t dds_domain_default (void); + +#define DDS_MIN_PSEUDO_HANDLE ((dds_entity_t) 0x7fff0000) + /* @defgroup builtintopic_constants Convenience constants for referring to builtin topics * * These constants can be used in place of an actual dds_topic_t, when creating @@ -76,10 +79,10 @@ DDS_EXPORT dds_domainid_t dds_domain_default (void); * * @{ */ -extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_DCPSPARTICIPANT; -extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_DCPSTOPIC; -extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_DCPSPUBLICATION; -extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION; +#define DDS_BUILTIN_TOPIC_DCPSPARTICIPANT ((dds_entity_t) (DDS_MIN_PSEUDO_HANDLE + 1)) +#define DDS_BUILTIN_TOPIC_DCPSTOPIC ((dds_entity_t) (DDS_MIN_PSEUDO_HANDLE + 2)) +#define DDS_BUILTIN_TOPIC_DCPSPUBLICATION ((dds_entity_t) (DDS_MIN_PSEUDO_HANDLE + 3)) +#define DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION ((dds_entity_t) (DDS_MIN_PSEUDO_HANDLE + 4)) /** @}*/ /** @name Communication Status definitions 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 923ea24..d031570 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_impl.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_impl.h @@ -96,7 +96,6 @@ dds_topic_descriptor_t; #define DDS_HANDLE_NIL 0 #define DDS_ENTITY_NIL 0 -#define DDS_ENTITY_KIND_MASK (0x7F000000) /* Should be same as UT_HANDLE_KIND_MASK. */ typedef enum dds_entity_kind { DDS_KIND_DONTCARE = 0x00000000, @@ -109,8 +108,7 @@ typedef enum dds_entity_kind DDS_KIND_COND_READ = 0x07000000, DDS_KIND_COND_QUERY = 0x08000000, DDS_KIND_COND_GUARD = 0x09000000, - DDS_KIND_WAITSET = 0x0A000000, - DDS_KIND_INTERNAL = 0x0B000000, + DDS_KIND_WAITSET = 0x0A000000 } dds_entity_kind_t; diff --git a/src/core/ddsc/src/dds__entity.h b/src/core/ddsc/src/dds__entity.h index 77ae66b..992c15a 100644 --- a/src/core/ddsc/src/dds__entity.h +++ b/src/core/ddsc/src/dds__entity.h @@ -53,6 +53,10 @@ dds_entity_add_ref_nolock(dds_entity *e); qualifier_ dds_retcode_t type_##_lock (dds_entity_t hdl, type_ **x); \ qualifier_ void type_##_unlock (type_ *x); +DDS_EXPORT inline dds_entity *dds_entity_from_handle_link (struct dds_handle_link *hdllink) { + return (dds_entity *) ((char *) hdllink - offsetof (struct dds_entity, m_hdllink)); +} + DDS_EXPORT inline bool dds_entity_is_enabled (const dds_entity *e) { return (e->m_flags & DDS_ENTITY_ENABLED) != 0; } @@ -68,11 +72,7 @@ DDS_EXPORT inline bool dds_entity_status_match (const dds_entity *e, uint32_t t) } DDS_EXPORT inline dds_entity_kind_t dds_entity_kind (const dds_entity *e) { - return (dds_entity_kind_t) (e->m_hdl & DDS_ENTITY_KIND_MASK); -} - -DDS_EXPORT inline dds_entity_kind_t dds_entity_kind_from_handle (dds_entity_t hdl) { - return (hdl > 0) ? (dds_entity_kind_t) (hdl & DDS_ENTITY_KIND_MASK) : DDS_KIND_DONTCARE; + return e->m_kind; } DDS_EXPORT void dds_entity_status_signal (dds_entity *e); @@ -80,7 +80,9 @@ DDS_EXPORT void dds_entity_status_signal (dds_entity *e); DDS_EXPORT void dds_entity_invoke_listener (const dds_entity *entity, enum dds_status_id which, const void *vst); DDS_EXPORT dds_retcode_t -dds_valid_hdl(dds_entity_t hdl, dds_entity_kind_t kind); +dds_entity_claim ( + dds_entity_t hdl, + dds_entity **eptr); DDS_EXPORT dds_retcode_t dds_entity_lock( @@ -118,14 +120,22 @@ dds_delete_impl( dds_entity_t entity, bool keep_if_explicit); -DDS_EXPORT const char * -dds__entity_kind_str( - dds_entity_t e); - DDS_EXPORT dds_domain * dds__entity_domain( dds_entity* e); +DDS_EXPORT dds_return_t +dds_generic_unimplemented_operation_manykinds( + dds_entity_t handle, + size_t nkinds, + const dds_entity_kind_t *kinds); + +DDS_EXPORT dds_return_t +dds_generic_unimplemented_operation( + dds_entity_t handle, + dds_entity_kind_t kind); + + #if defined (__cplusplus) } #endif diff --git a/src/core/ddsc/src/dds__err.h b/src/core/ddsc/src/dds__err.h index 917051a..a54be27 100644 --- a/src/core/ddsc/src/dds__err.h +++ b/src/core/ddsc/src/dds__err.h @@ -20,20 +20,7 @@ extern "C" { #endif -/* To construct return status - * Use '+' instead of '|'. Otherwise, the SAL checking doesn't - * understand when a return value is negative or positive and - * complains a lot about "A successful path through the function - * does not set the named _Out_ parameter." */ -#if !defined(__FILE_ID__) -#error "__FILE_ID__ not defined" -#endif - -#define DDS__FILE_ID__ (((__FILE_ID__ & 0x1ff)) << 22) -#define DDS__LINE__ ((__LINE__ & 0x3fff) << 8) - -#define DDS_ERRNO(err) \ - (assert(err > DDS_RETCODE_OK), -(DDS__FILE_ID__ + DDS__LINE__ + (err))) +#define DDS_ERRNO(err) (assert(err > DDS_RETCODE_OK), -(err)) #if defined (__cplusplus) } diff --git a/src/util/include/dds/util/ut_handleserver.h b/src/core/ddsc/src/dds__handles.h similarity index 58% rename from src/util/include/dds/util/ut_handleserver.h rename to src/core/ddsc/src/dds__handles.h index f0a91e0..7ceee26 100644 --- a/src/util/include/dds/util/ut_handleserver.h +++ b/src/core/ddsc/src/dds__handles.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -9,19 +9,20 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef UT_HANDLESERVER_H -#define UT_HANDLESERVER_H +#ifndef DDS__HANDLES_H +#define DDS__HANDLES_H -#include -#include - -#include "dds/export.h" #include "dds/ddsrt/time.h" +#include "dds/ddsrt/retcode.h" +#include "dds/ddsrt/atomics.h" +#include "dds/dds.h" #if defined (__cplusplus) extern "C" { #endif +struct dds_entity; + /******************************************************************************************** * * TODO CHAM-138: Header file improvements @@ -51,46 +52,8 @@ extern "C" { */ -/* - * Some error return values. - */ -typedef enum ut_handle_retcode_t { - UT_HANDLE_OK = 0, - UT_HANDLE_ERROR = -1, /* General error. */ - UT_HANDLE_CLOSED = -2, /* Handle has been previously close. */ - UT_HANDLE_DELETED = -3, /* Handle has been previously deleted. */ - UT_HANDLE_INVALID = -4, /* Handle is not a valid handle. */ - UT_HANDLE_UNEQUAL_KIND = -5, /* Handle does not contain expected kind. */ - UT_HANDLE_TIMEOUT = -6, /* Operation timed out. */ - UT_HANDLE_OUT_OF_RESOURCES = -7, /* Action isn't possible because of limited resources. */ - UT_HANDLE_NOT_INITALIZED = -8 /* Not initialized. */ -} ut_handle_retcode_t; - -/* - * The 32 bit handle - * | bits | # values | description | - * -------------------------------------------------------------------------------------- - * | 31 | 2 | positive/negative (negative can be used to indicate errors) | - * | 24-30 | 127 | handle kind (value determined by client) | - * | 0-23 | 16.777.215 | index or hash (maintained by the handleserver) | - * - * When the handle is negative, it'll contain a ut_handle_retcode_t error value. - * - * FYI: the entity id within DDSI is also 24 bits... - */ -typedef int32_t ut_handle_t; - -/* - * Handle bits - * +kkk kkkk iiii iiii iiii iiii iiii iiii - * 31| | 24| 0| - */ -#define UT_HANDLE_SIGN_MASK (0x80000000) -#define UT_HANDLE_KIND_MASK (0x7F000000) -#define UT_HANDLE_IDX_MASK (0x00FFFFFF) - -#define UT_HANDLE_DONTCARE_KIND (0) +typedef int32_t dds_handle_t; /* * The handle link type. @@ -106,14 +69,16 @@ typedef int32_t ut_handle_t; * This handlelink is invalid after the related handle is deleted and should * never be used afterwards. */ -struct ut_handlelink; - +struct dds_handle_link { + dds_handle_t hdl; + ddsrt_atomic_uint32_t cnt_flags; +}; /* * Initialize handleserver singleton. */ -DDS_EXPORT ut_handle_retcode_t -ut_handleserver_init(void); +DDS_EXPORT dds_return_t +dds_handle_server_init(void (*free_via_gc) (void *x)); /* @@ -121,7 +86,7 @@ ut_handleserver_init(void); * The handleserver is destroyed when fini() is called as often as init(). */ DDS_EXPORT void -ut_handleserver_fini(void); +dds_handle_server_fini(void); /* @@ -142,8 +107,9 @@ ut_handleserver_fini(void); * Valid handle when returned value is positive. * Otherwise negative handle is returned. */ -DDS_EXPORT ut_handle_t -ut_handle_create(int32_t kind, void *arg); +DDS_EXPORT dds_handle_t +dds_handle_create( + struct dds_handle_link *link); /* @@ -153,7 +119,8 @@ ut_handle_create(int32_t kind, void *arg); * This is a noop on an already closed handle. */ DDS_EXPORT void -ut_handle_close(ut_handle_t hdl, struct ut_handlelink *link); +dds_handle_close( + struct dds_handle_link *link); /* @@ -165,23 +132,10 @@ ut_handle_close(ut_handle_t hdl, struct ut_handlelink *link); * It will delete the information when there are no more active claims. It'll * block when necessary to wait for all possible claims to be released. */ -DDS_EXPORT ut_handle_retcode_t -ut_handle_delete( - ut_handle_t hdl, - struct ut_handlelink *link, - dds_time_t timeout); - - -/* - * Returns the status the given handle; valid/deleted/closed/etc. - * - * Returns OK when valid. - */ -ut_handle_retcode_t -ut_handle_status( - ut_handle_t hdl, - struct ut_handlelink *link, - int32_t kind); +DDS_EXPORT int32_t +dds_handle_delete( + struct dds_handle_link *link, + dds_time_t timeout); /* @@ -190,21 +144,23 @@ ut_handle_status( * * Returns OK when succeeded. */ -DDS_EXPORT ut_handle_retcode_t -ut_handle_claim( - ut_handle_t hdl, - struct ut_handlelink *link, - int32_t kind, - void **arg); +DDS_EXPORT int32_t +dds_handle_claim( + dds_handle_t hdl, + struct dds_handle_link **entity); + + +DDS_EXPORT void +dds_handle_claim_inc( + struct dds_handle_link *link); /* * The active claims count is decreased. */ DDS_EXPORT void -ut_handle_release( - ut_handle_t hdl, - struct ut_handlelink *link); +dds_handle_release( + struct dds_handle_link *link); /* @@ -217,21 +173,12 @@ ut_handle_release( * possible. */ DDS_EXPORT bool -ut_handle_is_closed( - ut_handle_t hdl, - struct ut_handlelink *link); +dds_handle_is_closed( + struct dds_handle_link *link); -/* - * This will get the link of the handle, which can be used for performance - * increase. - */ -DDS_EXPORT struct ut_handlelink* -ut_handle_get_link( - ut_handle_t hdl); - #if defined (__cplusplus) } #endif -#endif /* UT_HANDLESERVER_H */ +#endif /* DDS__HANDLES_H */ diff --git a/src/core/ddsc/src/dds__publisher.h b/src/core/ddsc/src/dds__publisher.h index 61427df..517abff 100644 --- a/src/core/ddsc/src/dds__publisher.h +++ b/src/core/ddsc/src/dds__publisher.h @@ -13,11 +13,14 @@ #define _DDS_PUBLISHER_H_ #include "dds/dds.h" +#include "dds__entity.h" #if defined (__cplusplus) extern "C" { #endif +DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_publisher, DDS_KIND_PUBLISHER) + dds_return_t dds_publisher_begin_coherent (dds_entity_t e); dds_return_t dds_publisher_end_coherent (dds_entity_t e); diff --git a/src/core/ddsc/src/dds__subscriber.h b/src/core/ddsc/src/dds__subscriber.h index 0609b03..c104255 100644 --- a/src/core/ddsc/src/dds__subscriber.h +++ b/src/core/ddsc/src/dds__subscriber.h @@ -13,12 +13,13 @@ #define _DDS_SUBSCRIBER_H_ #include "dds/dds.h" +#include "dds__entity.h" #if defined (__cplusplus) extern "C" { #endif -struct dds_entity; +DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_subscriber, DDS_KIND_SUBSCRIBER) dds_entity_t dds__create_subscriber_l( diff --git a/src/core/ddsc/src/dds__types.h b/src/core/ddsc/src/dds__types.h index 75c53b8..187aee4 100644 --- a/src/core/ddsc/src/dds__types.h +++ b/src/core/ddsc/src/dds__types.h @@ -18,7 +18,7 @@ #include "dds/ddsrt/sync.h" #include "dds/ddsi/q_rtps.h" #include "dds/util/ut_avl.h" -#include "dds/util/ut_handleserver.h" +#include "dds__handles.h" #if defined (__cplusplus) extern "C" { @@ -125,7 +125,8 @@ dds_entity_observer; typedef struct dds_entity { - ut_handle_t m_hdl; + struct dds_handle_link m_hdllink; + dds_entity_kind_t m_kind; dds_entity_deriver m_deriver; uint32_t m_refc; struct dds_entity * m_next; @@ -147,8 +148,6 @@ typedef struct dds_entity uint32_t m_status_enable; uint32_t m_cb_count; dds_entity_observer *m_observers; - - struct ut_handlelink *m_hdllink; } dds_entity; diff --git a/src/core/ddsc/src/dds_coherent.c b/src/core/ddsc/src/dds_coherent.c index 7f35660..6123a47 100644 --- a/src/core/ddsc/src/dds_coherent.c +++ b/src/core/ddsc/src/dds_coherent.c @@ -21,52 +21,14 @@ dds_return_t dds_begin_coherent( dds_entity_t entity) { - dds_return_t ret; - - switch(dds_entity_kind_from_handle(entity)) { - case DDS_KIND_READER: - case DDS_KIND_WRITER: - /* Invoking on a writer/reader behaves as if invoked on - * its parent publisher/subscriber. */ - ret = dds_begin_coherent(dds_get_parent(entity)); - break; - case DDS_KIND_PUBLISHER: - ret = dds_publisher_begin_coherent(entity); - break; - case DDS_KIND_SUBSCRIBER: - ret = dds_subscriber_begin_coherent(entity); - break; - default: - DDS_ERROR("Given entity can not control coherency\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - break; - } - return ret; + static const dds_entity_kind_t kinds[] = { DDS_KIND_READER, DDS_KIND_WRITER, DDS_KIND_PUBLISHER, DDS_KIND_SUBSCRIBER }; + return dds_generic_unimplemented_operation_manykinds (entity, sizeof (kinds) / sizeof (kinds[0]), kinds); } dds_return_t dds_end_coherent( dds_entity_t entity) { - dds_return_t ret; - - switch(dds_entity_kind_from_handle(entity)) { - case DDS_KIND_READER: - case DDS_KIND_WRITER: - /* Invoking on a writer/reader behaves as if invoked on - * its parent publisher/subscriber. */ - ret = dds_end_coherent(dds_get_parent(entity)); - break; - case DDS_KIND_PUBLISHER: - ret = dds_publisher_end_coherent(entity); - break; - case DDS_KIND_SUBSCRIBER: - ret = dds_subscriber_end_coherent(entity); - break; - default: - DDS_ERROR("Given entity can not control coherency\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - break; - } - return ret; + static const dds_entity_kind_t kinds[] = { DDS_KIND_READER, DDS_KIND_WRITER, DDS_KIND_PUBLISHER, DDS_KIND_SUBSCRIBER }; + return dds_generic_unimplemented_operation_manykinds (entity, sizeof (kinds) / sizeof (kinds[0]), kinds); } diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index cbb34d3..f8a4e14 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -22,16 +22,11 @@ #include "dds__err.h" #include "dds/version.h" -/* Sanity check. */ -#if DDS_ENTITY_KIND_MASK != UT_HANDLE_KIND_MASK -#error "DDS_ENTITY_KIND_MASK != UT_HANDLE_KIND_MASK" -#endif - +extern inline dds_entity *dds_entity_from_handle_link (struct dds_handle_link *hdllink); extern inline bool dds_entity_is_enabled (const dds_entity *e); extern inline void dds_entity_status_reset (dds_entity *e, uint32_t t); extern inline bool dds_entity_status_match (const dds_entity *e, uint32_t t); extern inline dds_entity_kind_t dds_entity_kind (const dds_entity *e); -extern inline dds_entity_kind_t dds_entity_kind_from_handle (dds_entity_t hdl); static void dds_entity_observers_signal (dds_entity *observed, uint32_t status); static void dds_entity_observers_delete (dds_entity *observed); @@ -71,10 +66,13 @@ static dds_entity *dds__nonself_parent (dds_entity *e) dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind_t kind, dds_qos_t *qos, const dds_listener_t *listener, uint32_t mask) { + dds_handle_t handle; + assert ((kind == DDS_KIND_PARTICIPANT) == (parent == NULL)); assert (e); e->m_refc = 1; + e->m_kind = kind; e->m_qos = qos; e->m_cb_count = 0; e->m_observers = NULL; @@ -116,29 +114,11 @@ dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind ddsrt_mutex_unlock (&e->m_observers_lock); } - e->m_hdllink = NULL; - e->m_hdl = ut_handle_create ((int32_t) kind, e); - if (e->m_hdl > 0) - { - e->m_hdllink = ut_handle_get_link (e->m_hdl); - assert(e->m_hdllink); - } - else - { - if (e->m_hdl == UT_HANDLE_OUT_OF_RESOURCES) { - DDS_ERROR ("Can not create new entity; too many where created previously\n"); - e->m_hdl = DDS_ERRNO (DDS_RETCODE_OUT_OF_RESOURCES); - } else if (e->m_hdl == UT_HANDLE_NOT_INITALIZED) { - DDS_ERROR (DDS_PROJECT_NAME" is not yet initialized. Please create a participant before executing an other method\n"); - e->m_hdl = DDS_ERRNO (DDS_RETCODE_PRECONDITION_NOT_MET); - } else { - DDS_ERROR ("An internal error has occurred\n"); - e->m_hdl = DDS_ERRNO (DDS_RETCODE_ERROR); - } - } + if ((handle = dds_handle_create (&e->m_hdllink)) <= 0) + return (dds_entity_t) handle; - /* An ut_handle_t is directly used as dds_entity_t. */ - return (dds_entity_t) e->m_hdl; + /* An dds_handle_t is directly used as dds_entity_t. */ + return (dds_entity_t) handle; } dds_return_t dds_delete (dds_entity_t entity) @@ -164,7 +144,7 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) dds_return_t ret; dds_retcode_t rc; - rc = dds_entity_lock (entity, UT_HANDLE_DONTCARE_KIND, &e); + rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e); if (rc != DDS_RETCODE_OK) { DDS_TRACE ("dds_delete_impl: error on locking entity %"PRIu32" keep_if_explicit %d\n", entity, (int) keep_if_explicit); @@ -183,7 +163,7 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) return DDS_RETCODE_OK; } - ut_handle_close (e->m_hdl, e->m_hdllink); + dds_handle_close (&e->m_hdllink); ddsrt_mutex_lock (&e->m_observers_lock); while (e->m_cb_count > 0) ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock); @@ -219,7 +199,7 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) { next = next_non_topic_child (child->m_next); /* This will probably delete the child entry from the current children's list */ - ret = dds_delete (child->m_hdl); + ret = dds_delete (child->m_hdllink.hdl); child = next; } child = e->m_children; @@ -227,7 +207,7 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) { next = child->m_next; assert (dds_entity_kind (child) == DDS_KIND_TOPIC); - ret = dds_delete (child->m_hdl); + ret = dds_delete (child->m_hdllink.hdl); child = next; } if (ret == DDS_RETCODE_OK && e->m_deriver.close) @@ -239,11 +219,11 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) if (ret == DDS_RETCODE_OK) { - /* The ut_handle_delete will wait until the last active claim on that handle + /* The dds_handle_delete will wait until the last active claim on that handle * is released. It is possible that this last release will be done by a thread * that was kicked during the close(). */ - if (ut_handle_delete (e->m_hdl, e->m_hdllink, timeout) != UT_HANDLE_OK) - return DDS_ERRNO (DDS_RETCODE_TIMEOUT); + if ((ret = dds_handle_delete (&e->m_hdllink, timeout)) != DDS_RETCODE_OK) + return ret; } if (ret == DDS_RETCODE_OK) @@ -301,7 +281,7 @@ dds_entity_t dds_get_parent (dds_entity_t entity) hdl = DDS_ENTITY_NIL; else { - hdl = parent->m_hdl; + hdl = parent->m_hdllink.hdl; dds_set_explicit (hdl); } dds_entity_unlock (e); @@ -317,7 +297,7 @@ dds_entity_t dds_get_participant (dds_entity_t entity) return DDS_ERRNO (rc); else { - dds_entity_t hdl = e->m_participant->m_hdl; + dds_entity_t hdl = e->m_participant->m_hdllink.hdl; dds_entity_unlock (e); return hdl; } @@ -343,8 +323,8 @@ dds_return_t dds_get_children (dds_entity_t entity, dds_entity_t *children, size { if ((size_t) n < size) { - children[n] = iter->m_hdl; - dds_set_explicit (iter->m_hdl); + children[n] = iter->m_hdllink.hdl; + dds_set_explicit (iter->m_hdllink.hdl); } n++; iter = iter->m_next; @@ -437,65 +417,65 @@ void dds_entity_invoke_listener (const dds_entity *entity, enum dds_status_id wh { case DDS_INCONSISTENT_TOPIC_STATUS_ID: { struct dds_inconsistent_topic_status const * const st = vst; - lst->on_inconsistent_topic (entity->m_hdl, *st, lst->on_inconsistent_topic_arg); + lst->on_inconsistent_topic (entity->m_hdllink.hdl, *st, lst->on_inconsistent_topic_arg); break; } case DDS_REQUESTED_DEADLINE_MISSED_STATUS_ID: { struct dds_requested_deadline_missed_status const * const st = vst; - lst->on_requested_deadline_missed (entity->m_hdl, *st, lst->on_requested_deadline_missed_arg); + lst->on_requested_deadline_missed (entity->m_hdllink.hdl, *st, lst->on_requested_deadline_missed_arg); break; } case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS_ID: { struct dds_requested_incompatible_qos_status const * const st = vst; - lst->on_requested_incompatible_qos (entity->m_hdl, *st, lst->on_requested_incompatible_qos_arg); + lst->on_requested_incompatible_qos (entity->m_hdllink.hdl, *st, lst->on_requested_incompatible_qos_arg); break; } case DDS_SAMPLE_LOST_STATUS_ID: { struct dds_sample_lost_status const * const st = vst; - lst->on_sample_lost (entity->m_hdl, *st, lst->on_sample_lost_arg); + lst->on_sample_lost (entity->m_hdllink.hdl, *st, lst->on_sample_lost_arg); break; } case DDS_SAMPLE_REJECTED_STATUS_ID: { struct dds_sample_rejected_status const * const st = vst; - lst->on_sample_rejected (entity->m_hdl, *st, lst->on_sample_rejected_arg); + lst->on_sample_rejected (entity->m_hdllink.hdl, *st, lst->on_sample_rejected_arg); break; } case DDS_LIVELINESS_CHANGED_STATUS_ID: { struct dds_liveliness_changed_status const * const st = vst; - lst->on_liveliness_changed (entity->m_hdl, *st, lst->on_liveliness_changed_arg); + lst->on_liveliness_changed (entity->m_hdllink.hdl, *st, lst->on_liveliness_changed_arg); break; } case DDS_SUBSCRIPTION_MATCHED_STATUS_ID: { struct dds_subscription_matched_status const * const st = vst; - lst->on_subscription_matched (entity->m_hdl, *st, lst->on_subscription_matched_arg); + lst->on_subscription_matched (entity->m_hdllink.hdl, *st, lst->on_subscription_matched_arg); break; } case DDS_OFFERED_DEADLINE_MISSED_STATUS_ID: { struct dds_offered_deadline_missed_status const * const st = vst; - lst->on_offered_deadline_missed (entity->m_hdl, *st, lst->on_offered_deadline_missed_arg); + lst->on_offered_deadline_missed (entity->m_hdllink.hdl, *st, lst->on_offered_deadline_missed_arg); break; } case DDS_LIVELINESS_LOST_STATUS_ID: { struct dds_liveliness_lost_status const * const st = vst; - lst->on_liveliness_lost (entity->m_hdl, *st, lst->on_liveliness_lost_arg); + lst->on_liveliness_lost (entity->m_hdllink.hdl, *st, lst->on_liveliness_lost_arg); break; } case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS_ID: { struct dds_offered_incompatible_qos_status const * const st = vst; - lst->on_offered_incompatible_qos (entity->m_hdl, *st, lst->on_offered_incompatible_qos_arg); + lst->on_offered_incompatible_qos (entity->m_hdllink.hdl, *st, lst->on_offered_incompatible_qos_arg); break; } case DDS_PUBLICATION_MATCHED_STATUS_ID: { struct dds_publication_matched_status const * const st = vst; - lst->on_publication_matched (entity->m_hdl, *st, lst->on_publication_matched_arg); + lst->on_publication_matched (entity->m_hdllink.hdl, *st, lst->on_publication_matched_arg); break; } case DDS_DATA_AVAILABLE_STATUS_ID: { - lst->on_data_available (entity->m_hdl, lst->on_data_available_arg); + lst->on_data_available (entity->m_hdllink.hdl, lst->on_data_available_arg); break; } case DDS_DATA_ON_READERS_STATUS_ID: { - lst->on_data_on_readers (entity->m_hdl, lst->on_data_on_readers_arg); + lst->on_data_on_readers (entity->m_hdllink.hdl, lst->on_data_on_readers_arg); break; } } @@ -768,45 +748,36 @@ dds_return_t dds_get_instance_handle (dds_entity_t entity, dds_instance_handle_t return ret; } - -dds_retcode_t dds_valid_hdl (dds_entity_t hdl, dds_entity_kind_t kind) +dds_retcode_t dds_entity_claim (dds_entity_t hdl, dds_entity **eptr) { - ut_handle_t utr; - if ((utr = ut_handle_status (hdl, NULL, (int32_t) kind)) == UT_HANDLE_OK) - return DDS_RETCODE_OK; - else if (hdl < 0) - return DDS_RETCODE_BAD_PARAMETER; + dds_retcode_t hres; + struct dds_handle_link *hdllink; + if ((hres = dds_handle_claim (hdl, &hdllink)) != DDS_RETCODE_OK) + return hres; else { - switch (utr) - { - case UT_HANDLE_OK: - assert (0); - /* FALLS THROUGH */ - case UT_HANDLE_UNEQUAL_KIND: - return DDS_RETCODE_ILLEGAL_OPERATION; - case UT_HANDLE_INVALID: - return DDS_RETCODE_BAD_PARAMETER; - case UT_HANDLE_DELETED: - case UT_HANDLE_CLOSED: - return DDS_RETCODE_ALREADY_DELETED; - default: - return DDS_RETCODE_ERROR; - } + *eptr = dds_entity_from_handle_link (hdllink); + return DDS_RETCODE_OK; } } dds_retcode_t dds_entity_lock (dds_entity_t hdl, dds_entity_kind_t kind, dds_entity **eptr) { - ut_handle_t utr; - void *raw; + dds_retcode_t hres; + dds_entity *e; /* When the given handle already contains an error, then return that * same error to retain the original information. */ - if ((utr = ut_handle_claim (hdl, NULL, (int32_t) kind, &raw)) == UT_HANDLE_OK) + if ((hres = dds_entity_claim (hdl, &e)) != DDS_RETCODE_OK) + return hres; + else { - dds_entity *e; - *eptr = e = raw; + if (dds_entity_kind (e) != kind && kind != DDS_KIND_DONTCARE) + { + dds_handle_release (&e->m_hdllink); + return DDS_RETCODE_ILLEGAL_OPERATION; + } + ddsrt_mutex_lock (&e->m_mutex); /* FIXME: The handle could have been closed while we were waiting for the mutex -- that should be handled differently! @@ -815,41 +786,20 @@ dds_retcode_t dds_entity_lock (dds_entity_t hdl, dds_entity_kind_t kind, dds_ent (2) preventing dds_delete_impl from doing anything once the entity is being deleted. Without (1), it would be possible to add children while trying to delete them, without (2) you're looking at crashes. */ - if (ut_handle_is_closed (hdl, e->m_hdllink)) + if (dds_handle_is_closed (&e->m_hdllink)) { dds_entity_unlock (e); - return DDS_RETCODE_ALREADY_DELETED; + return DDS_RETCODE_BAD_PARAMETER; } + *eptr = e; return DDS_RETCODE_OK; } - else if (hdl < 0) - { - return DDS_RETCODE_BAD_PARAMETER; - } - else - { - switch (utr) - { - case UT_HANDLE_OK: - assert (0); - /* FALLS THROUGH */ - case UT_HANDLE_UNEQUAL_KIND: - return DDS_RETCODE_ILLEGAL_OPERATION; - case UT_HANDLE_INVALID: - return DDS_RETCODE_BAD_PARAMETER; - case UT_HANDLE_DELETED: - case UT_HANDLE_CLOSED: - return DDS_RETCODE_ALREADY_DELETED; - default: - return DDS_RETCODE_ERROR; - } - } } void dds_entity_unlock (dds_entity *e) { ddsrt_mutex_unlock (&e->m_mutex); - ut_handle_release (e->m_hdl, e->m_hdllink); + dds_handle_release (&e->m_hdllink); } dds_return_t dds_triggered (dds_entity_t entity) @@ -965,7 +915,7 @@ static void dds_entity_observers_delete (dds_entity *observed) static void dds_entity_observers_signal (dds_entity *observed, uint32_t status) { for (dds_entity_observer *idx = observed->m_observers; idx; idx = idx->m_next) - idx->m_cb (idx->m_observer, observed->m_hdl, status); + idx->m_cb (idx->m_observer, observed->m_hdllink.hdl, status); } void dds_entity_status_signal (dds_entity *e) @@ -996,19 +946,19 @@ dds_entity_t dds_get_topic (dds_entity_t entity) { case DDS_KIND_READER: { dds_reader *rd = (dds_reader *) e; - hdl = rd->m_topic->m_entity.m_hdl; + hdl = rd->m_topic->m_entity.m_hdllink.hdl; break; } case DDS_KIND_WRITER: { dds_writer *wr = (dds_writer *) e; - hdl = wr->m_topic->m_entity.m_hdl; + hdl = wr->m_topic->m_entity.m_hdllink.hdl; break; } case DDS_KIND_COND_READ: case DDS_KIND_COND_QUERY: { assert (dds_entity_kind (e->m_parent) == DDS_KIND_READER); dds_reader *rd = (dds_reader *) e->m_parent; - hdl = rd->m_topic->m_entity.m_hdl; + hdl = rd->m_topic->m_entity.m_hdllink.hdl; break; } default: { @@ -1020,21 +970,32 @@ dds_entity_t dds_get_topic (dds_entity_t entity) return hdl; } -const char *dds__entity_kind_str (dds_entity_t e) +dds_return_t dds_generic_unimplemented_operation_manykinds (dds_entity_t handle, size_t nkinds, const dds_entity_kind_t *kinds) { - if (e <= 0) - return "(ERROR)"; - switch (e & DDS_ENTITY_KIND_MASK) + dds_entity *e; + dds_retcode_t ret; + if ((ret = dds_entity_claim (handle, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (ret); + else { - case DDS_KIND_TOPIC: return "Topic"; - case DDS_KIND_PARTICIPANT: return "Participant"; - case DDS_KIND_READER: return "Reader"; - case DDS_KIND_WRITER: return "Writer"; - case DDS_KIND_SUBSCRIBER: return "Subscriber"; - case DDS_KIND_PUBLISHER: return "Publisher"; - case DDS_KIND_COND_READ: return "ReadCondition"; - case DDS_KIND_COND_QUERY: return "QueryCondition"; - case DDS_KIND_WAITSET: return "WaitSet"; - default: return "(INVALID_ENTITY)"; + const dds_entity_kind_t actual = dds_entity_kind (e); + ret = DDS_RETCODE_ILLEGAL_OPERATION; + for (size_t i = 0; i < nkinds; i++) + { + if (kinds[i] == actual) + { + /* If the handle happens to be for an entity of the right kind, return unsupported */ + ret = DDS_RETCODE_UNSUPPORTED; + break; + } + } + dds_handle_release (&e->m_hdllink); + return DDS_ERRNO (ret); } } + +dds_return_t dds_generic_unimplemented_operation (dds_entity_t handle, dds_entity_kind_t kind) +{ + return dds_generic_unimplemented_operation_manykinds (handle, 1, &kind); +} + diff --git a/src/core/ddsc/src/dds_guardcond.c b/src/core/ddsc/src/dds_guardcond.c index c1e289a..c4feee0 100644 --- a/src/core/ddsc/src/dds_guardcond.c +++ b/src/core/ddsc/src/dds_guardcond.c @@ -43,7 +43,7 @@ dds_return_t dds_set_guardcondition (dds_entity_t condition, bool triggered) dds_retcode_t rc; if ((rc = dds_guardcond_lock (condition, &gcond)) != DDS_RETCODE_OK) - return DDS_ERRNO (dds_valid_hdl (condition, DDS_KIND_COND_GUARD)); + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); else { ddsrt_mutex_lock (&gcond->m_entity.m_observers_lock); @@ -67,7 +67,7 @@ dds_return_t dds_read_guardcondition (dds_entity_t condition, bool *triggered) *triggered = false; if ((rc = dds_guardcond_lock (condition, &gcond)) != DDS_RETCODE_OK) - return DDS_ERRNO (dds_valid_hdl (condition, DDS_KIND_COND_GUARD)); + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); else { ddsrt_mutex_lock (&gcond->m_entity.m_observers_lock); @@ -88,7 +88,7 @@ dds_return_t dds_take_guardcondition (dds_entity_t condition, bool *triggered) *triggered = false; if ((rc = dds_guardcond_lock (condition, &gcond)) != DDS_RETCODE_OK) - return DDS_ERRNO (dds_valid_hdl (condition, DDS_KIND_COND_GUARD)); + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); else { ddsrt_mutex_lock (&gcond->m_entity.m_observers_lock); diff --git a/src/core/ddsc/src/dds_handles.c b/src/core/ddsc/src/dds_handles.c new file mode 100644 index 0000000..5e4acd3 --- /dev/null +++ b/src/core/ddsc/src/dds_handles.c @@ -0,0 +1,267 @@ +/* + * 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/time.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/random.h" +#include "dds/util/ut_hopscotch.h" +#include "dds/ddsi/q_thread.h" +#include "dds__handles.h" +#include "dds__types.h" +#include "dds__err.h" + +/* FIXME: this code isn't really correct when USE_CHH is set: + - the DDS entity code doesn't really play by the awake/asleep mechanism + - there is no provision in the code for a handle being deleted concurrent to a lookup, + that is, deleting handle links should also go through the GC + entity framework needs a fair bit of rewriting anyway ... */ +#define USE_CHH 0 + +#define HDL_FLAG_CLOSED (0x80000000u) +#define HDL_COUNT_MASK (0x00ffffffu) + +/* Maximum number of handles is INT32_MAX - 1, but as the allocator relies on a + random generator for finding a free one, the time spent in the dds_handle_create + increases with an increasing number of handles. 16M handles seems likely to be + enough and makes the likely cost of allocating a new handle somewhat more + reasonable */ +#define MAX_HANDLES (INT32_MAX / 128) + +struct dds_handle_server { +#if USE_CHH + struct ut_chh *ht; +#else + struct ut_hh *ht; +#endif + size_t count; + ddsrt_mutex_t lock; + ddsrt_cond_t cond; +}; + +static struct dds_handle_server handles; + +static uint32_t handle_hash (const void *va) +{ + /* handles are already pseudo-random numbers, so not much point in hashing it again */ + const struct dds_handle_link *a = va; + return (uint32_t) a->hdl; +} + +static int handle_equal (const void *va, const void *vb) +{ + const struct dds_handle_link *a = va; + const struct dds_handle_link *b = vb; + return a->hdl == b->hdl; +} + +dds_return_t dds_handle_server_init (void (*free_via_gc) (void *x)) +{ +#if USE_CHH + handles.ht = ut_chhNew (128, handle_hash, handle_equal, free_via_gc); +#else + handles.ht = ut_hhNew (128, handle_hash, handle_equal); + (void) free_via_gc; +#endif + handles.count = 0; + ddsrt_mutex_init (&handles.lock); + ddsrt_cond_init (&handles.cond); + return DDS_RETCODE_OK; +} + +void dds_handle_server_fini (void) +{ +#if USE_CHH +#ifndef NDEBUG + struct ut_chhIter it; + assert (ut_chhIterFirst (handles.ht, &it) == NULL); +#endif + ut_chhFree (handles.ht); +#else /* USE_CHH */ +#ifndef NDEBUG + struct ut_hhIter it; + assert (ut_hhIterFirst (handles.ht, &it) == NULL); +#endif + ut_hhFree (handles.ht); +#endif /* USE_CHH */ + ddsrt_cond_destroy (&handles.cond); + ddsrt_mutex_destroy (&handles.lock); + handles.ht = NULL; +} + +#if USE_CHH +static bool hhadd (struct ut_chh *ht, void *elem) { return ut_chhAdd (ht, elem); } +#else +static bool hhadd (struct ut_hh *ht, void *elem) { return ut_hhAdd (ht, elem); } +#endif +static dds_handle_t dds_handle_create_int (struct dds_handle_link *link) +{ + ddsrt_atomic_st32 (&link->cnt_flags, 0); + do { + do { + link->hdl = (int32_t) (ddsrt_random () & INT32_MAX); + } while (link->hdl == 0 || link->hdl >= DDS_MIN_PSEUDO_HANDLE); + } while (!hhadd (handles.ht, link)); + return link->hdl; +} + +dds_handle_t dds_handle_create (struct dds_handle_link *link) +{ + dds_handle_t ret; +#if USE_CHH + struct thread_state1 * const self = lookup_thread_state (); + const bool asleep = vtime_asleep_p (self->vtime); + if (asleep) + thread_state_awake (self); +#endif + ddsrt_mutex_lock (&handles.lock); + if (handles.count == MAX_HANDLES) + { + ddsrt_mutex_unlock (&handles.lock); + ret = DDS_ERRNO (DDS_RETCODE_OUT_OF_RESOURCES); + } + else + { + handles.count++; +#if USE_CHH + ddsrt_mutex_unlock (&handles.lock); + ret = dds_handle_create_int (link); +#else + ret = dds_handle_create_int (link); + ddsrt_mutex_unlock (&handles.lock); +#endif + assert (ret > 0); + } +#if USE_CHH + if (asleep) + thread_state_asleep (self); +#endif + return ret; +} + +void dds_handle_close (struct dds_handle_link *link) +{ + ddsrt_atomic_or32 (&link->cnt_flags, HDL_FLAG_CLOSED); +} + +int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout) +{ + assert (ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_FLAG_CLOSED); + + ddsrt_mutex_lock (&handles.lock); + if ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_COUNT_MASK) != 0) + { + /* FIXME: */ + const dds_time_t abstimeout = dds_time () + timeout; + while ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_COUNT_MASK) != 0) + { + if (!ddsrt_cond_waituntil (&handles.cond, &handles.lock, abstimeout)) + { + ddsrt_mutex_unlock (&handles.lock); + fprintf (stderr, "** timeout in handle_delete **\n"); + return DDS_RETCODE_TIMEOUT; + } + } + } +#if USE_CHH + struct thread_state1 * const self = lookup_thread_state (); + const bool asleep = vtime_asleep_p (self->vtime); + if (asleep) + thread_state_awake (self); + int x = ut_chhRemove (handles.ht, link); + if (asleep) + thread_state_asleep (self); +#else + int x = ut_hhRemove (handles.ht, link); +#endif + assert(x); + (void)x; + assert (handles.count > 0); + handles.count--; + ddsrt_mutex_unlock (&handles.lock); + return DDS_RETCODE_OK; +} + +int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) +{ + struct dds_handle_link dummy = { .hdl = hdl }; + int32_t rc; + /* it makes sense to check here for initialization: the first thing any operation + (other than create_participant) does is to call dds_handle_claim on the supplied + entity, so checking here whether the library has been initialised helps avoid + crashes if someone forgets to create a participant (or allows a program to + continue after failing to create one). + + One could check that the handle is > 0, but that would catch fewer errors + without any advantages. */ + if (handles.ht == NULL) + return DDS_RETCODE_PRECONDITION_NOT_MET; + +#if USE_CHH + struct thread_state1 * const self = lookup_thread_state (); + const bool asleep = vtime_asleep_p (self->vtime); + if (asleep) + thread_state_awake (self); + *link = ut_chhLookup (handles.ht, &dummy); +#else + ddsrt_mutex_lock (&handles.lock); + *link = ut_hhLookup (handles.ht, &dummy); +#endif + if (*link == NULL) + rc = DDS_RETCODE_BAD_PARAMETER; + else + { + uint32_t cnt_flags; + /* Assume success; bail out if the object turns out to be in the process of + being deleted */ + rc = DDS_RETCODE_OK; + do { + cnt_flags = ddsrt_atomic_ld32 (&(*link)->cnt_flags); + if (cnt_flags & HDL_FLAG_CLOSED) + { + rc = DDS_RETCODE_BAD_PARAMETER; + break; + } + } while (!ddsrt_atomic_cas32 (&(*link)->cnt_flags, cnt_flags, cnt_flags + 1)); + } + +#if USE_CHH + if (asleep) + thread_state_asleep (self); +#else + ddsrt_mutex_unlock (&handles.lock); +#endif + return rc; +} + +void dds_handle_claim_inc (struct dds_handle_link *link) +{ + uint32_t x = ddsrt_atomic_inc32_nv (&link->cnt_flags); + assert (!(x & HDL_FLAG_CLOSED)); + (void) x; +} + +void dds_handle_release (struct dds_handle_link *link) +{ + if (ddsrt_atomic_dec32_ov (&link->cnt_flags) == (HDL_FLAG_CLOSED | 1)) + { + ddsrt_mutex_lock (&handles.lock); + ddsrt_cond_broadcast (&handles.cond); + ddsrt_mutex_unlock (&handles.lock); + } +} + +bool dds_handle_is_closed (struct dds_handle_link *link) +{ + return (ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_FLAG_CLOSED) != 0; +} diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 3aa8751..31a1c0a 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -16,6 +16,7 @@ #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/environ.h" #include "dds/ddsrt/process.h" +#include "dds/ddsrt/heap.h" #include "dds__init.h" #include "dds__rhc.h" #include "dds__domain.h" @@ -28,6 +29,7 @@ #include "dds/ddsi/q_servicelease.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_gc.h" #include "dds/version.h" #define DOMAIN_ID_MIN 0 @@ -38,6 +40,20 @@ struct q_globals gv; dds_globals dds_global = { .m_default_domain = DDS_DOMAIN_DEFAULT }; static struct cfgst * dds_cfgst = NULL; +static void free_via_gc_cb (struct gcreq *gcreq) +{ + void *bs = gcreq->arg; + gcreq_free (gcreq); + ddsrt_free (bs); +} + +static void free_via_gc (void *bs) +{ + struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, free_via_gc_cb); + gcreq->arg = bs; + gcreq_enqueue (gcreq); +} + dds_return_t dds_init(dds_domainid_t domain) { @@ -60,13 +76,6 @@ dds_init(dds_domainid_t domain) goto skip; } - if (ut_handleserver_init() != UT_HANDLE_OK) - { - DDS_ERROR("Failed to initialize internal handle server\n"); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); - goto fail_handleserver; - } - gv.tstart = now (); gv.exception = false; ddsrt_mutex_init (&dds_global.m_mutex); @@ -137,6 +146,13 @@ dds_init(dds_domainid_t domain) goto fail_rtps_init; } + if (dds_handle_server_init (free_via_gc) != DDS_RETCODE_OK) + { + DDS_ERROR("Failed to initialize internal handle server\n"); + ret = DDS_ERRNO(DDS_RETCODE_ERROR); + goto fail_handleserver; + } + dds__builtin_init (); if (rtps_start () < 0) @@ -178,6 +194,8 @@ skip: fail_servicelease_start: if (gv.servicelease) nn_servicelease_stop_renewing (gv.servicelease); + dds_handle_server_fini(); +fail_handleserver: rtps_stop (); fail_rtps_start: dds__builtin_fini (); @@ -198,8 +216,6 @@ fail_config_domainid: dds_cfgst = NULL; fail_config: ddsrt_mutex_destroy (&dds_global.m_mutex); - ut_handleserver_fini(); -fail_handleserver: dds_global.m_init_count--; ddsrt_mutex_unlock(init_mutex); ddsrt_fini(); @@ -217,6 +233,7 @@ extern void dds_fini (void) { if (gv.servicelease) nn_servicelease_stop_renewing (gv.servicelease); + dds_handle_server_fini(); rtps_stop (); dds__builtin_fini (); rtps_fini (); @@ -229,7 +246,6 @@ extern void dds_fini (void) config_fini (dds_cfgst); dds_cfgst = NULL; ddsrt_mutex_destroy (&dds_global.m_mutex); - ut_handleserver_fini(); dds_global.m_default_domain = DDS_DOMAIN_DEFAULT; } ddsrt_mutex_unlock(init_mutex); diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 94d42a0..35521c0 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -55,7 +55,7 @@ dds_participant_delete( assert(e); assert(thr); - assert(dds_entity_kind_from_handle(e->m_hdl) == DDS_KIND_PARTICIPANT); + assert(dds_entity_kind(e) == DDS_KIND_PARTICIPANT); if (asleep) { thread_state_awake(thr); @@ -278,9 +278,9 @@ dds_lookup_participant( ddsrt_mutex_lock (&dds_global.m_mutex); iter = dds_pp_head; while (iter) { - if(iter->m_domainid == domain_id) { - if((size_t)ret < size) { - participants[ret] = iter->m_hdl; + if (iter->m_domainid == domain_id) { + if ((size_t)ret < size) { + participants[ret] = iter->m_hdllink.hdl; } ret++; } diff --git a/src/core/ddsc/src/dds_publisher.c b/src/core/ddsc/src/dds_publisher.c index 689ba11..47365c7 100644 --- a/src/core/ddsc/src/dds_publisher.c +++ b/src/core/ddsc/src/dds_publisher.c @@ -13,11 +13,14 @@ #include #include "dds/ddsrt/misc.h" #include "dds__listener.h" +#include "dds__publisher.h" #include "dds__qos.h" #include "dds__err.h" #include "dds/ddsi/q_entity.h" #include "dds/version.h" +DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_publisher) + #define DDS_PUBLISHER_STATUS_MASK 0u static dds_return_t @@ -145,36 +148,14 @@ DDS_EXPORT dds_return_t dds_suspend( dds_entity_t publisher) { - dds_return_t ret; - - if(dds_entity_kind_from_handle(publisher) != DDS_KIND_PUBLISHER) { - DDS_ERROR("Provided entity is not a publisher kind\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - goto err; - } - /* TODO: CHAM-123 Currently unsupported. */ - DDS_ERROR("Suspend publication operation does not being supported yet\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); -err: - return ret; + return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER); } dds_return_t dds_resume( dds_entity_t publisher) { - dds_return_t ret = DDS_RETCODE_OK; - - if(dds_entity_kind_from_handle(publisher) != DDS_KIND_PUBLISHER) { - DDS_ERROR("Provided entity is not a publisher kind\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - goto err; - } - /* TODO: CHAM-123 Currently unsupported. */ - DDS_ERROR("Suspend publication operation does not being supported yet\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); -err: - return ret; + return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER); } dds_return_t @@ -182,27 +163,10 @@ dds_wait_for_acks( dds_entity_t publisher_or_writer, dds_duration_t timeout) { - dds_return_t ret; - - /* TODO: CHAM-125 Currently unsupported. */ - DDSRT_UNUSED_ARG(timeout); - - switch(dds_entity_kind_from_handle(publisher_or_writer)) { - case DDS_KIND_WRITER: - DDS_ERROR("Wait for acknowledgments on a writer is not being supported yet\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); - break; - case DDS_KIND_PUBLISHER: - DDS_ERROR("Wait for acknowledgments on a publisher is not being supported yet\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); - break; - default: - DDS_ERROR("Provided entity is not a publisher nor a writer\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - break; - } - - return ret; + if (timeout < 0) + return DDS_ERRNO (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); } dds_return_t diff --git a/src/core/ddsc/src/dds_querycond.c b/src/core/ddsc/src/dds_querycond.c index 490fc3c..0a5e50d 100644 --- a/src/core/ddsc/src/dds_querycond.c +++ b/src/core/ddsc/src/dds_querycond.c @@ -39,9 +39,9 @@ dds_create_querycondition( const bool success = (cond->m_entity.m_deriver.delete != 0); dds_reader_unlock(r); if (success) { - hdl = cond->m_entity.m_hdl; + hdl = cond->m_entity.m_hdllink.hdl; } else { - dds_delete (cond->m_entity.m_hdl); + dds_delete (cond->m_entity.m_hdllink.hdl); hdl = DDS_ERRNO(DDS_RETCODE_OUT_OF_RESOURCES); } } else { diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 9353829..af239f6 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -47,7 +47,7 @@ static dds_retcode_t dds_read_lock (dds_entity_t hdl, dds_reader **reader, dds_r DDS_ERROR ("Given entity is a reader nor a condition\n"); return DDS_RETCODE_ILLEGAL_OPERATION; } - else if ((rc = dds_entity_lock (entity->m_parent->m_hdl, DDS_KIND_READER, &parent_entity)) != DDS_RETCODE_OK) + else if ((rc = dds_entity_lock (entity->m_parent->m_hdllink.hdl, DDS_KIND_READER, &parent_entity)) != DDS_RETCODE_OK) { dds_entity_unlock (entity); DDS_ERROR ("Failed to lock condition's reader\n"); @@ -168,7 +168,7 @@ dds_read_impl( /* read/take resets data available status */ dds_entity_status_reset(&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); /* reset DATA_ON_READERS status on subscriber after successful read/take */ - if (dds_entity_kind_from_handle(rd->m_entity.m_parent->m_hdl) == DDS_KIND_SUBSCRIBER) { + if (dds_entity_kind(rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { dds_entity_status_reset(rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); } dds_read_unlock(rd, cond); @@ -225,7 +225,7 @@ dds_readcdr_impl( /* reset DATA_ON_READERS status on subscriber after successful read/take */ - if (dds_entity_kind_from_handle(rd->m_entity.m_parent->m_hdl) == DDS_KIND_SUBSCRIBER) + if (dds_entity_kind(rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { dds_entity_status_reset(rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); } diff --git a/src/core/ddsc/src/dds_readcond.c b/src/core/ddsc/src/dds_readcond.c index 3d169de..322af8e 100644 --- a/src/core/ddsc/src/dds_readcond.c +++ b/src/core/ddsc/src/dds_readcond.c @@ -36,7 +36,7 @@ dds_create_readcond( { dds_readcond * cond = dds_alloc(sizeof(*cond)); assert((kind == DDS_KIND_COND_READ && filter == 0) || (kind == DDS_KIND_COND_QUERY && filter != 0)); - cond->m_entity.m_hdl = dds_entity_init(&cond->m_entity, (dds_entity*)rd, kind, NULL, NULL, 0); + (void) dds_entity_init(&cond->m_entity, (dds_entity*)rd, kind, NULL, NULL, 0); cond->m_entity.m_deriver.delete = dds_readcond_delete; cond->m_rhc = rd->m_rd->rhc; cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE; @@ -70,7 +70,7 @@ dds_create_readcondition( dds_readcond *cond = dds_create_readcond(rd, DDS_KIND_COND_READ, mask, 0); assert(cond); assert(cond->m_entity.m_deriver.delete); - hdl = cond->m_entity.m_hdl; + hdl = cond->m_entity.m_hdllink.hdl; dds_reader_unlock(rd); } else { DDS_ERROR("Error occurred on locking reader\n"); @@ -82,20 +82,31 @@ dds_create_readcondition( dds_entity_t dds_get_datareader (dds_entity_t condition) { - dds_entity_t hdl; - - if (dds_entity_kind_from_handle(condition) == DDS_KIND_COND_READ) { - hdl = dds_get_parent(condition); - } else if (dds_entity_kind_from_handle(condition) == DDS_KIND_COND_QUERY) { - hdl = dds_get_parent(condition); - } else { - DDS_ERROR("Argument condition is not valid\n"); - hdl = DDS_ERRNO(dds_valid_hdl(condition, DDS_KIND_COND_READ)); + struct dds_entity *e; + dds_retcode_t rc; + if ((rc = dds_entity_claim (condition, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + else + { + dds_entity_t rdh; + switch (dds_entity_kind (e)) + { + case DDS_KIND_COND_READ: + case DDS_KIND_COND_QUERY: + assert (dds_entity_kind (e->m_parent) == DDS_KIND_READER); + rdh = e->m_parent->m_hdllink.hdl; + break; + default: + rdh = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + break; } - - return hdl; + dds_handle_release (&e->m_hdllink); + return rdh; + } } + + dds_return_t dds_get_mask (dds_entity_t condition, uint32_t *mask) { dds_entity *entity; @@ -109,7 +120,7 @@ dds_return_t dds_get_mask (dds_entity_t condition, uint32_t *mask) else if (dds_entity_kind (entity) != DDS_KIND_COND_READ && dds_entity_kind (entity) != DDS_KIND_COND_QUERY) { dds_entity_unlock (entity); - return DDS_ERRNO (dds_valid_hdl (condition, DDS_KIND_COND_READ)); + return DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); } else { diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 2f37d8a..bd16e39 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -81,10 +81,10 @@ dds_reader_delete( dds_reader *rd = (dds_reader*)e; dds_return_t ret; assert(e); - ret = dds_delete(rd->m_topic->m_entity.m_hdl); + ret = dds_delete(rd->m_topic->m_entity.m_hdllink.hdl); if(ret == DDS_RETCODE_OK){ - ret = dds_delete_impl(e->m_parent->m_hdl, true); - if(dds_err_nr(ret) == DDS_RETCODE_ALREADY_DELETED){ + ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true); + if(dds_err_nr(ret) == DDS_RETCODE_BAD_PARAMETER){ ret = DDS_RETCODE_OK; } } @@ -185,7 +185,7 @@ void dds_reader_data_available_cb (struct dds_reader *rd) sub->m_cb_count++; ddsrt_mutex_unlock (&sub->m_observers_lock); - lst->on_data_on_readers (sub->m_hdl, lst->on_data_on_readers_arg); + lst->on_data_on_readers (sub->m_hdllink.hdl, lst->on_data_on_readers_arg); ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); ddsrt_mutex_lock (&sub->m_observers_lock); @@ -196,7 +196,7 @@ void dds_reader_data_available_cb (struct dds_reader *rd) else if (rd->m_entity.m_listener.on_data_available) { ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); - lst->on_data_available (rd->m_entity.m_hdl, lst->on_data_available_arg); + lst->on_data_available (rd->m_entity.m_hdllink.hdl, lst->on_data_available_arg); ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); } else @@ -222,7 +222,7 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) { /* Release the initial claim that was done during the create. This * will indicate that further API deletion is now possible. */ - ut_handle_release (entity->m_hdl, entity->m_hdllink); + dds_handle_release (&entity->m_hdllink); return; } @@ -361,7 +361,7 @@ dds_create_reader( { dds_qos_t * rqos; dds_retcode_t rc; - dds_entity * sub = NULL; + dds_subscriber * sub = NULL; dds_entity_t subscriber; dds_reader * rd; struct rhc * rhc; @@ -371,31 +371,43 @@ dds_create_reader( struct thread_state1 * const thr = lookup_thread_state (); const bool asleep = !vtime_awake_p (thr->vtime); dds_return_t ret = DDS_RETCODE_OK; + bool internal_topic; - if (dds_entity_kind_from_handle(topic) != DDS_KIND_INTERNAL) { - /* Try claiming a participant. If that's not working, then it could be a subscriber. */ - if (dds_entity_kind_from_handle(participant_or_subscriber) == DDS_KIND_PARTICIPANT) { - subscriber = dds_create_subscriber(participant_or_subscriber, qos, NULL); - } else { - subscriber = participant_or_subscriber; + switch (topic) { + case DDS_BUILTIN_TOPIC_DCPSPARTICIPANT: + case DDS_BUILTIN_TOPIC_DCPSTOPIC: + case DDS_BUILTIN_TOPIC_DCPSPUBLICATION: + case DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION: + internal_topic = true; + subscriber = dds__get_builtin_subscriber(participant_or_subscriber); + t = dds__get_builtin_topic (subscriber, topic); + break; + + default: { + dds_entity *p_or_s; + if ((rc = dds_entity_claim (participant_or_subscriber, &p_or_s)) != DDS_RETCODE_OK) { + return DDS_ERRNO (rc); + } + if (dds_entity_kind (p_or_s) == DDS_KIND_PARTICIPANT) { + subscriber = dds_create_subscriber(participant_or_subscriber, qos, NULL); + } else { + subscriber = participant_or_subscriber; + } + dds_handle_release (&p_or_s->m_hdllink); + internal_topic = false; + t = topic; + break; } - t = topic; - } else { - subscriber = dds__get_builtin_subscriber(participant_or_subscriber); - t = dds__get_builtin_topic(subscriber, topic); } - rc = dds_entity_lock(subscriber, DDS_KIND_SUBSCRIBER, &sub); - if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking subscriber\n"); - reader = DDS_ERRNO(rc); + if ((rc = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK) { + reader = DDS_ERRNO (rc); goto err_sub_lock; } - if ((subscriber != participant_or_subscriber) && - (dds_entity_kind_from_handle(topic) != DDS_KIND_INTERNAL)) { + if ((subscriber != participant_or_subscriber) && !internal_topic) { /* Delete implicit subscriber if reader creation fails */ - sub->m_flags |= DDS_ENTITY_IMPLICIT; + sub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT; } rc = dds_topic_lock(t, &tp); @@ -405,7 +417,7 @@ dds_create_reader( goto err_tp_lock; } assert (tp->m_stopic); - assert (sub->m_domain == tp->m_entity.m_domain); + assert (sub->m_entity.m_domain == tp->m_entity.m_domain); /* Merge qos from topic and subscriber */ rqos = dds_create_qos (); @@ -415,8 +427,8 @@ dds_create_reader( (void)dds_copy_qos(rqos, qos); } - if(sub->m_qos){ - dds_merge_qos (rqos, sub->m_qos); + if(sub->m_entity.m_qos){ + dds_merge_qos (rqos, sub->m_entity.m_qos); } if (tp->m_entity.m_qos) { @@ -435,7 +447,7 @@ dds_create_reader( } /* Additional checks required for built-in topics */ - if (dds_entity_kind_from_handle(topic) == DDS_KIND_INTERNAL && !dds__validate_builtin_reader_qos(topic, qos)) { + if (internal_topic && !dds__validate_builtin_reader_qos(topic, qos)) { dds_delete_qos(rqos); DDS_ERROR("Invalid QoS specified for built-in topic reader"); reader = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); @@ -444,7 +456,7 @@ dds_create_reader( /* Create reader and associated read cache */ rd = dds_alloc (sizeof (*rd)); - reader = dds_entity_init (&rd->m_entity, sub, DDS_KIND_READER, rqos, listener, DDS_READER_STATUS_MASK); + reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, rqos, listener, DDS_READER_STATUS_MASK); rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED; rd->m_topic = tp; rhc = dds_rhc_new (rd, tp->m_stopic); @@ -457,19 +469,17 @@ dds_create_reader( /* Extra claim of this reader to make sure that the delete waits until DDSI * has deleted its reader as well. This can be known through the callback. */ - if (ut_handle_claim(rd->m_entity.m_hdl, rd->m_entity.m_hdllink, DDS_KIND_READER, NULL) != UT_HANDLE_OK) { - assert(0); - } + dds_handle_claim_inc (&rd->m_entity.m_hdllink); ddsrt_mutex_unlock(&tp->m_entity.m_mutex); - ddsrt_mutex_unlock(&sub->m_mutex); + ddsrt_mutex_unlock(&sub->m_entity.m_mutex); if (asleep) { thread_state_awake (thr); } - rd->m_rd = new_reader(&rd->m_entity.m_guid, NULL, &sub->m_participant->m_guid, tp->m_stopic, + rd->m_rd = new_reader(&rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, rqos, rhc, dds_reader_status_cb, rd); - ddsrt_mutex_lock(&sub->m_mutex); + ddsrt_mutex_lock(&sub->m_entity.m_mutex); ddsrt_mutex_lock(&tp->m_entity.m_mutex); assert (rd->m_rd); if (asleep) { @@ -481,9 +491,9 @@ dds_create_reader( (dds_global.m_dur_reader) (rd, rhc); } dds_topic_unlock(tp); - dds_entity_unlock(sub); + dds_subscriber_unlock(sub); - if (dds_entity_kind_from_handle(topic) == DDS_KIND_INTERNAL) { + if (internal_topic) { /* If topic is builtin, then the topic entity is local and should * be deleted because the application won't. */ dds_delete(t); @@ -494,12 +504,12 @@ dds_create_reader( err_bad_qos: dds_topic_unlock(tp); err_tp_lock: - dds_entity_unlock(sub); - if((sub->m_flags & DDS_ENTITY_IMPLICIT) != 0){ + dds_subscriber_unlock(sub); + if((sub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){ (void)dds_delete(subscriber); } err_sub_lock: - if (dds_entity_kind_from_handle(topic) == DDS_KIND_INTERNAL) { + if (internal_topic) { /* If topic is builtin, then the topic entity is local and should * be deleted because the application won't. */ dds_delete(t); @@ -509,47 +519,53 @@ err_sub_lock: void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb, void *cbarg) { - dds_reader *dds_rd; + dds_entity *dds_entity; + if (dds_entity_claim(entity, &dds_entity) != DDS_RETCODE_OK) + return; - if (ut_handle_claim(entity, NULL, DDS_KIND_READER, (void**)&dds_rd) == UT_HANDLE_OK) + if (dds_entity_kind (dds_entity) != DDS_KIND_READER) { - struct reader *rd = dds_rd->m_rd; - nn_guid_t pwrguid; - struct proxy_writer *pwr; - struct rd_pwr_match *m; - memset (&pwrguid, 0, sizeof (pwrguid)); - ddsrt_mutex_lock (&rd->e.lock); + dds_handle_release (&dds_entity->m_hdllink); + return; + } - rd->ddsi2direct_cb = cb; - rd->ddsi2direct_cbarg = cbarg; - while ((m = ut_avlLookupSuccEq (&rd_writers_treedef, &rd->writers, &pwrguid)) != NULL) + dds_reader *dds_rd = (dds_reader *) dds_entity; + struct reader *rd = dds_rd->m_rd; + nn_guid_t pwrguid; + struct proxy_writer *pwr; + struct rd_pwr_match *m; + memset (&pwrguid, 0, sizeof (pwrguid)); + ddsrt_mutex_lock (&rd->e.lock); + + rd->ddsi2direct_cb = cb; + rd->ddsi2direct_cbarg = cbarg; + while ((m = ut_avlLookupSuccEq (&rd_writers_treedef, &rd->writers, &pwrguid)) != NULL) + { + /* have to be careful walking the tree -- pretty is different, but + I want to check this before I write a lookup_succ function. */ + struct rd_pwr_match *m_next; + nn_guid_t pwrguid_next; + pwrguid = m->pwr_guid; + if ((m_next = ut_avlFindSucc (&rd_writers_treedef, &rd->writers, m)) != NULL) + pwrguid_next = m_next->pwr_guid; + else { - /* have to be careful walking the tree -- pretty is different, but - I want to check this before I write a lookup_succ function. */ - struct rd_pwr_match *m_next; - nn_guid_t pwrguid_next; - pwrguid = m->pwr_guid; - if ((m_next = ut_avlFindSucc (&rd_writers_treedef, &rd->writers, m)) != NULL) - pwrguid_next = m_next->pwr_guid; - else - { - memset (&pwrguid_next, 0xff, sizeof (pwrguid_next)); - pwrguid_next.entityid.u = (pwrguid_next.entityid.u & ~(uint32_t)0xff) | NN_ENTITYID_KIND_WRITER_NO_KEY; - } - ddsrt_mutex_unlock (&rd->e.lock); - if ((pwr = ephash_lookup_proxy_writer_guid (&pwrguid)) != NULL) - { - ddsrt_mutex_lock (&pwr->e.lock); - pwr->ddsi2direct_cb = cb; - pwr->ddsi2direct_cbarg = cbarg; - ddsrt_mutex_unlock (&pwr->e.lock); - } - pwrguid = pwrguid_next; - ddsrt_mutex_lock (&rd->e.lock); + memset (&pwrguid_next, 0xff, sizeof (pwrguid_next)); + pwrguid_next.entityid.u = (pwrguid_next.entityid.u & ~(uint32_t)0xff) | NN_ENTITYID_KIND_WRITER_NO_KEY; } ddsrt_mutex_unlock (&rd->e.lock); - ut_handle_release(entity, dds_rd->m_entity.m_hdllink); + if ((pwr = ephash_lookup_proxy_writer_guid (&pwrguid)) != NULL) + { + ddsrt_mutex_lock (&pwr->e.lock); + pwr->ddsi2direct_cb = cb; + pwr->ddsi2direct_cbarg = cbarg; + ddsrt_mutex_unlock (&pwr->e.lock); + } + pwrguid = pwrguid_next; + ddsrt_mutex_lock (&rd->e.lock); } + ddsrt_mutex_unlock (&rd->e.lock); + dds_handle_release (&dds_rd->m_entity.m_hdllink); } uint32_t dds_reader_lock_samples (dds_entity_t reader) @@ -587,23 +603,32 @@ int dds_reader_wait_for_historical_data (dds_entity_t reader, dds_duration_t max dds_entity_t dds_get_subscriber (dds_entity_t entity) { - dds_entity_t hdl; - if (dds_entity_kind_from_handle (entity) == DDS_KIND_READER) - hdl = dds_get_parent (entity); - else if (dds_entity_kind_from_handle (entity) == DDS_KIND_COND_READ || dds_entity_kind_from_handle (entity) == DDS_KIND_COND_QUERY) - { - hdl = dds_get_parent (entity); - if (hdl > 0) - hdl = dds_get_subscriber (hdl); - DDS_ERROR ("Reader of this condition is already deleted\n"); - } + dds_entity *e; + dds_retcode_t ret; + if ((ret = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) + return (dds_entity_t) DDS_ERRNO (ret); else { - DDS_ERROR ("Provided entity is not a reader nor a condition\n"); - hdl = DDS_ERRNO (dds_valid_hdl (entity, DDS_KIND_READER)); + dds_entity_t subh; + switch (dds_entity_kind (e)) + { + case DDS_KIND_READER: + assert (dds_entity_kind (e->m_parent) == DDS_KIND_SUBSCRIBER); + subh = e->m_parent->m_hdllink.hdl; + break; + case DDS_KIND_COND_READ: + case DDS_KIND_COND_QUERY: + assert (dds_entity_kind (e->m_parent) == DDS_KIND_READER); + assert (dds_entity_kind (e->m_parent->m_parent) == DDS_KIND_SUBSCRIBER); + subh = e->m_parent->m_parent->m_hdllink.hdl; + break; + default: + subh = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + break; + } + dds_handle_release (&e->m_hdllink); + return subh; } - - return hdl; } dds_return_t diff --git a/src/core/ddsc/src/dds_subscriber.c b/src/core/ddsc/src/dds_subscriber.c index 7a3281e..1a51775 100644 --- a/src/core/ddsc/src/dds_subscriber.c +++ b/src/core/ddsc/src/dds_subscriber.c @@ -13,9 +13,12 @@ #include "dds__listener.h" #include "dds__qos.h" #include "dds__err.h" +#include "dds__subscriber.h" #include "dds/ddsi/q_entity.h" #include "dds/version.h" +DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_subscriber) + #define DDS_SUBSCRIBER_STATUS_MASK \ DDS_DATA_ON_READERS_STATUS diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 940d493..acd36ac 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -40,12 +40,6 @@ const ut_avlTreedef_t dds_topictree_def = UT_AVL_TREEDEF_INITIALIZER_INDKEY 0 ); -/* builtin-topic handles */ -const dds_entity_t DDS_BUILTIN_TOPIC_DCPSPARTICIPANT = (DDS_KIND_INTERNAL + 1); -const dds_entity_t DDS_BUILTIN_TOPIC_DCPSTOPIC = (DDS_KIND_INTERNAL + 2); -const dds_entity_t DDS_BUILTIN_TOPIC_DCPSPUBLICATION = (DDS_KIND_INTERNAL + 3); -const dds_entity_t DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION = (DDS_KIND_INTERNAL + 4); - static bool is_valid_name( const char *name) @@ -198,7 +192,7 @@ dds_find_topic( st = dds_topic_lookup_locked (p->m_domain, name); if (st) { dds_entity_add_ref (&st->status_cb_entity->m_entity); - tp = st->status_cb_entity->m_entity.m_hdl; + tp = st->status_cb_entity->m_entity.m_hdllink.hdl; } else { DDS_ERROR("Topic is not being created yet\n"); tp = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); @@ -370,7 +364,7 @@ dds_create_topic_arbitrary ( hdl = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); } else { dds_entity_add_ref (&stgeneric->status_cb_entity->m_entity); - hdl = stgeneric->status_cb_entity->m_entity.m_hdl; + hdl = stgeneric->status_cb_entity->m_entity.m_hdllink.hdl; } ddsrt_mutex_unlock (&dds_global.m_mutex); } else { diff --git a/src/core/ddsc/src/dds_waitset.c b/src/core/ddsc/src/dds_waitset.c index a594049..787ce2c 100644 --- a/src/core/ddsc/src/dds_waitset.c +++ b/src/core/ddsc/src/dds_waitset.c @@ -152,7 +152,7 @@ dds_waitset_close_list( dds_attachment *next; while (idx != NULL) { next = idx->next; - (void)dds_entity_observer_unregister(idx->entity->m_hdl, waitset); + (void)dds_entity_observer_unregister(idx->entity->m_hdllink.hdl, waitset); ddsrt_free(idx); idx = next; } @@ -168,7 +168,7 @@ dds_waitset_remove_from_list( dds_attachment *prev = NULL; while (idx != NULL) { - if (idx->entity->m_hdl == observed) { + if (idx->entity->m_hdllink.hdl == observed) { if (prev == NULL) { *list = idx->next; } else { @@ -191,8 +191,8 @@ dds_waitset_close( { dds_waitset *ws = (dds_waitset*)e; - dds_waitset_close_list(&ws->observed, e->m_hdl); - dds_waitset_close_list(&ws->triggered, e->m_hdl); + dds_waitset_close_list(&ws->observed, e->m_hdllink.hdl); + dds_waitset_close_list(&ws->triggered, e->m_hdllink.hdl); /* Trigger waitset to wake up. */ ddsrt_cond_broadcast(&e->m_cond); @@ -242,7 +242,7 @@ dds_waitset_get_entities( iter = ws->observed; while (iter) { if (((size_t)ret < size) && (entities != NULL)) { - entities[ret] = iter->entity->m_hdl; + entities[ret] = iter->entity->m_hdllink.hdl; } ret++; iter = iter->next; @@ -251,7 +251,7 @@ dds_waitset_get_entities( iter = ws->triggered; while (iter) { if (((size_t)ret < size) && (entities != NULL)) { - entities[ret] = iter->entity->m_hdl; + entities[ret] = iter->entity->m_hdllink.hdl; } ret++; iter = iter->next; @@ -275,7 +275,7 @@ dds_waitset_move( dds_attachment *idx = *src; dds_attachment *prev = NULL; while (idx != NULL) { - if (idx->entity->m_hdl == entity) { + if (idx->entity->m_hdllink.hdl == entity) { /* Swap idx from src to dst. */ dds_waitset_swap(dst, src, prev, idx); diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index e15bbbf..f804fe1 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -22,6 +22,7 @@ #include "dds__qos.h" #include "dds__err.h" #include "dds__init.h" +#include "dds__publisher.h" #include "dds__topic.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds__whc.h" @@ -75,7 +76,7 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) { /* Release the initial claim that was done during the create. This * will indicate that further API deletion is now possible. */ - ut_handle_release (entity->m_hdl, entity->m_hdllink); + dds_handle_release (&entity->m_hdllink); return; } @@ -235,10 +236,10 @@ dds_writer_delete( if (asleep) { thread_state_asleep(thr); } - ret = dds_delete(wr->m_topic->m_entity.m_hdl); + ret = dds_delete(wr->m_topic->m_entity.m_hdllink.hdl); if(ret == DDS_RETCODE_OK){ - ret = dds_delete_impl(e->m_parent->m_hdl, true); - if(dds_err_nr(ret) == DDS_RETCODE_ALREADY_DELETED){ + ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true); + if(dds_err_nr(ret) == DDS_RETCODE_BAD_PARAMETER){ ret = DDS_RETCODE_OK; } } @@ -399,7 +400,7 @@ dds_create_writer( dds_qos_t * wqos; dds_writer * wr; dds_entity_t writer; - dds_entity * pub = NULL; + dds_publisher * pub = NULL; dds_topic * tp; dds_entity_t publisher; struct thread_state1 * const thr = lookup_thread_state(); @@ -407,22 +408,26 @@ dds_create_writer( ddsi_tran_conn_t conn = gv.data_conn_uc; dds_return_t ret; - /* Try claiming a participant. If that's not working, then it could be a subscriber. */ - if(dds_entity_kind_from_handle(participant_or_publisher) == DDS_KIND_PARTICIPANT){ - publisher = dds_create_publisher(participant_or_publisher, qos, NULL); - } else{ - publisher = participant_or_publisher; + { + dds_entity *p_or_p; + if ((rc = dds_entity_claim (participant_or_publisher, &p_or_p)) != DDS_RETCODE_OK) { + return DDS_ERRNO (rc); + } + if (dds_entity_kind (p_or_p) == DDS_KIND_PARTICIPANT) { + publisher = dds_create_publisher(participant_or_publisher, qos, NULL); + } else { + publisher = participant_or_publisher; + } + dds_handle_release (&p_or_p->m_hdllink); } - rc = dds_entity_lock(publisher, DDS_KIND_PUBLISHER, &pub); - if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking publisher\n"); + if ((rc = dds_publisher_lock(publisher, &pub)) != DDS_RETCODE_OK) { writer = DDS_ERRNO(rc); goto err_pub_lock; } if (publisher != participant_or_publisher) { - pub->m_flags |= DDS_ENTITY_IMPLICIT; + pub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT; } rc = dds_topic_lock(topic, &tp); @@ -432,7 +437,7 @@ dds_create_writer( goto err_tp_lock; } assert(tp->m_stopic); - assert(pub->m_domain == tp->m_entity.m_domain); + assert(pub->m_entity.m_domain == tp->m_entity.m_domain); /* Merge Topic & Publisher qos */ wqos = dds_create_qos(); @@ -442,8 +447,8 @@ dds_create_writer( (void)dds_copy_qos(wqos, qos); } - if (pub->m_qos) { - dds_merge_qos(wqos, pub->m_qos); + if (pub->m_entity.m_qos) { + dds_merge_qos(wqos, pub->m_entity.m_qos); } if (tp->m_entity.m_qos) { @@ -461,7 +466,7 @@ dds_create_writer( /* Create writer */ wr = dds_alloc(sizeof (*wr)); - writer = dds_entity_init(&wr->m_entity, pub, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK); + writer = dds_entity_init(&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK); wr->m_topic = tp; dds_entity_add_ref_nolock(&tp->m_entity); @@ -475,32 +480,30 @@ dds_create_writer( /* Extra claim of this writer to make sure that the delete waits until DDSI * has deleted its writer as well. This can be known through the callback. */ - if (ut_handle_claim(wr->m_entity.m_hdl, wr->m_entity.m_hdllink, DDS_KIND_WRITER, NULL) != UT_HANDLE_OK) { - assert(0); - } + dds_handle_claim_inc (&wr->m_entity.m_hdllink); - ddsrt_mutex_unlock(&tp->m_entity.m_mutex); - ddsrt_mutex_unlock(&pub->m_mutex); + ddsrt_mutex_unlock (&tp->m_entity.m_mutex); + ddsrt_mutex_unlock (&pub->m_entity.m_mutex); if (asleep) { thread_state_awake(thr); } - wr->m_wr = new_writer(&wr->m_entity.m_guid, NULL, &pub->m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); - ddsrt_mutex_lock(&pub->m_mutex); - ddsrt_mutex_lock(&tp->m_entity.m_mutex); + wr->m_wr = new_writer(&wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); + ddsrt_mutex_lock (&pub->m_entity.m_mutex); + ddsrt_mutex_lock (&tp->m_entity.m_mutex); assert(wr->m_wr); if (asleep) { thread_state_asleep(thr); } dds_topic_unlock(tp); - dds_entity_unlock(pub); + dds_publisher_unlock(pub); return writer; err_bad_qos: dds_topic_unlock(tp); err_tp_lock: - dds_entity_unlock(pub); - if((pub->m_flags & DDS_ENTITY_IMPLICIT) != 0){ + dds_publisher_unlock(pub); + if((pub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){ (void)dds_delete(publisher); } err_pub_lock: @@ -511,17 +514,23 @@ dds_entity_t dds_get_publisher( dds_entity_t writer) { - dds_entity_t hdl = DDS_RETCODE_OK; - - hdl = dds_valid_hdl(writer, DDS_KIND_WRITER); - if(hdl != DDS_RETCODE_OK){ - DDS_ERROR("Provided handle is not writer kind, so it is not valid\n"); - hdl = DDS_ERRNO(hdl); - } else{ - hdl = dds_get_parent(writer); + dds_entity *e; + dds_retcode_t rc; + if ((rc = dds_entity_claim (writer, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + else + { + dds_entity_t pubh; + if (dds_entity_kind (e) != DDS_KIND_WRITER) + pubh = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + else + { + assert (dds_entity_kind (e->m_parent) == DDS_KIND_PUBLISHER); + pubh = e->m_parent->m_hdllink.hdl; } - - return hdl; + dds_handle_release (&e->m_hdllink); + return pubh; + } } dds_return_t diff --git a/src/core/ddsc/tests/CMakeLists.txt b/src/core/ddsc/tests/CMakeLists.txt index bd44687..978d0c3 100644 --- a/src/core/ddsc/tests/CMakeLists.txt +++ b/src/core/ddsc/tests/CMakeLists.txt @@ -23,7 +23,7 @@ set(ddsc_test_sources "entity_api.c" "entity_hierarchy.c" "entity_status.c" - "file_id.c" + "err.c" "instance_get_key.c" "listener.c" "participant.c" diff --git a/src/core/ddsc/tests/builtin_topics.c b/src/core/ddsc/tests/builtin_topics.c index 3a63478..e4d2ff0 100644 --- a/src/core/ddsc/tests/builtin_topics.c +++ b/src/core/ddsc/tests/builtin_topics.c @@ -63,7 +63,7 @@ teardown(void) } static void -check_default_qos_of_builtin_entity(dds_entity_t entity) +check_default_qos_of_builtin_entity(dds_entity_t entity, bool isread) { dds_return_t ret; int64_t deadline; @@ -110,8 +110,7 @@ check_default_qos_of_builtin_entity(dds_entity_t entity) dds_qget_partition(qos, &plen, &partitions); // no getter for ENTITY_FACTORY - CU_ASSERT_FATAL((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_SUBSCRIBER || (entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER); - if ((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_SUBSCRIBER) { + if (!isread) { CU_ASSERT_FATAL(plen == 1); CU_ASSERT_STRING_EQUAL_FATAL(partitions[0], "__BUILT-IN PARTITION__"); } else { @@ -303,9 +302,9 @@ CU_Test(ddsc_builtin_topics, builtin_qos, .init = setup, .fini = teardown) dds_sub_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL); CU_ASSERT_FATAL(dds_sub_rdr > 0); - check_default_qos_of_builtin_entity(dds_sub_rdr); + check_default_qos_of_builtin_entity(dds_sub_rdr, 1); dds_sub_subscriber = dds_get_parent(dds_sub_rdr); CU_ASSERT_FATAL(dds_sub_subscriber > 0); - check_default_qos_of_builtin_entity(dds_sub_subscriber); + check_default_qos_of_builtin_entity(dds_sub_subscriber, 0); } diff --git a/src/core/ddsc/tests/dispose.c b/src/core/ddsc/tests/dispose.c index ee504fc..0e10c60 100644 --- a/src/core/ddsc/tests/dispose.c +++ b/src/core/ddsc/tests/dispose.c @@ -153,7 +153,7 @@ CU_Test(ddsc_writedispose, deleted, .init=disposing_init, .fini=disposing_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_writedispose(g_writer, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -170,7 +170,7 @@ CU_Test(ddsc_writedispose, null, .init=disposing_init, .fini=disposing_fini) /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_writedispose, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_writedispose, invalid_writers, .init=disposing_init, .fini=disposing_fini) { @@ -310,7 +310,7 @@ CU_Test(ddsc_writedispose_ts, deleted, .init=disposing_init, .fini=disposing_fin DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_writedispose_ts(g_writer, NULL, g_present); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -341,7 +341,7 @@ CU_Test(ddsc_writedispose_ts, timeout, .init=disposing_init, .fini=disposing_fin /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_writedispose_ts, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_writedispose_ts, invalid_writers, .init=disposing_init, .fini=disposing_fini) { @@ -510,7 +510,7 @@ CU_Test(ddsc_dispose, deleted, .init=disposing_init, .fini=disposing_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_dispose(g_writer, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -541,7 +541,7 @@ CU_Test(ddsc_dispose, timeout, .init=disposing_init, .fini=disposing_fini) /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_dispose, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_dispose, invalid_writers, .init=disposing_init, .fini=disposing_fini) { @@ -665,7 +665,7 @@ CU_Test(ddsc_dispose_ts, deleted, .init=disposing_init, .fini=disposing_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_dispose_ts(g_writer, NULL, g_present); DDSRT_WARNING_MSVC_ON(6387); /* Disable SAL warning on intentional misuse of the API */ - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -696,7 +696,7 @@ CU_Test(ddsc_dispose_ts, timeout, .init=disposing_init, .fini=disposing_fini) /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_dispose_ts, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_dispose_ts, invalid_writers, .init=disposing_init, .fini=disposing_fini) { @@ -861,7 +861,7 @@ CU_Test(ddsc_dispose_ih, deleted, .init=disposing_init, .fini=disposing_fini) dds_return_t ret; dds_delete(g_writer); ret = dds_dispose_ih(g_writer, DDS_HANDLE_NIL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -879,7 +879,7 @@ CU_Theory((dds_instance_handle_t handle), ddsc_dispose_ih, invalid_handles, .ini /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_dispose_ih, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_dispose_ih, invalid_writers, .init=disposing_init, .fini=disposing_fini) { @@ -959,7 +959,7 @@ CU_Test(ddsc_dispose_ih_ts, deleted, .init=disposing_init, .fini=disposing_fini) dds_return_t ret; dds_delete(g_writer); ret = dds_dispose_ih_ts(g_writer, DDS_HANDLE_NIL, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -977,7 +977,7 @@ CU_Theory((dds_instance_handle_t handle), ddsc_dispose_ih_ts, invalid_handles, . /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_dispose_ih_ts, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_dispose_ih_ts, invalid_writers, .init=disposing_init, .fini=disposing_fini) { diff --git a/src/core/ddsc/tests/entity_hierarchy.c b/src/core/ddsc/tests/entity_hierarchy.c index ef2f1f4..ec7e2dc 100644 --- a/src/core/ddsc/tests/entity_hierarchy.c +++ b/src/core/ddsc/tests/entity_hierarchy.c @@ -147,21 +147,21 @@ CU_Test(ddsc_entity_delete, recursive, .init=hierarchy_init, .fini=hierarchy_fin /* Check if all the entities are deleted now. */ ret = dds_get_domainid(g_participant, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_topic, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_publisher, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_subscriber, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_writer, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_reader, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_readcond, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_querycond, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -201,11 +201,11 @@ CU_Test(ddsc_entity_delete, recursive_with_deleted_topic) /* Check if the entities are actually deleted. */ ret = dds_get_domainid(g_participant, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED ); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER ); ret = dds_get_domainid(g_topic, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_writer, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); dds_delete(g_keep); } @@ -240,13 +240,13 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_participant, deleted_entities, dds_entity_t participant; dds_delete(*entity); participant = dds_get_participant(*entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(participant), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(participant), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_participant, invalid_entities) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t entity), ddsc_entity_get_participant, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini) { @@ -327,13 +327,13 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_parent, deleted_entities, .ini dds_entity_t parent; dds_delete(*entity); parent = dds_get_parent(*entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(parent), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(parent), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_parent, invalid_entities) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t entity), ddsc_entity_get_parent, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini) { @@ -478,13 +478,13 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_children, deleted_entities, .i dds_entity_t children[4]; dds_delete(*entity); ret = dds_get_children(*entity, children, 4); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_children, invalid_entities) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t entity), ddsc_entity_get_children, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini) { @@ -527,13 +527,13 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_topic, deleted_entities, .init dds_entity_t topic; dds_delete(*entity); topic = dds_get_topic(*entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_topic, invalid_entities) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t entity), ddsc_entity_get_topic, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini) { @@ -581,13 +581,13 @@ CU_Test(ddsc_entity_get_publisher, deleted_writer, .init=hierarchy_init, .fini=h dds_entity_t publisher; dds_delete(g_writer); publisher = dds_get_publisher(g_writer); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(publisher), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(publisher), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_publisher, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t entity), ddsc_entity_get_publisher, invalid_writers, .init=hierarchy_init, .fini=hierarchy_fini) { @@ -640,13 +640,13 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_subscriber, deleted_readers, . dds_entity_t subscriber; dds_delete(*entity); subscriber = dds_get_subscriber(*entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(subscriber), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(subscriber), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_subscriber, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t entity), ddsc_entity_get_subscriber, invalid_readers, .init=hierarchy_init, .fini=hierarchy_fini) { @@ -701,13 +701,13 @@ CU_Theory((dds_entity_t *cond), ddsc_entity_get_datareader, deleted_conds, .init dds_entity_t reader; dds_delete(*cond); reader = dds_get_datareader(*cond); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(reader), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(reader), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_datareader, invalid_conds) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t cond), ddsc_entity_get_datareader, invalid_conds, .init=hierarchy_init, .fini=hierarchy_fini) { diff --git a/src/core/ddsc/tests/entity_status.c b/src/core/ddsc/tests/entity_status.c index f14245f..45883fe 100644 --- a/src/core/ddsc/tests/entity_status.c +++ b/src/core/ddsc/tests/entity_status.c @@ -589,9 +589,9 @@ CU_Test(ddsc_entity, all_data_available, .init=init_entity_status, .fini=fini_en /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_enabled_status, bad_param) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t e), ddsc_get_enabled_status, bad_param) +CU_Theory((dds_entity_t e), ddsc_get_enabled_status, bad_param, .init=init_entity_status, .fini=fini_entity_status) { uint32_t mask; dds_return_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -605,7 +605,7 @@ CU_Test(ddsc_get_enabled_status, deleted_reader, .init=init_entity_status, .fini uint32_t mask; dds_delete(rea); ret = dds_get_status_mask(rea, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_get_enabled_status, illegal, .init=init_entity_status, .fini=fini_entity_status) @@ -628,9 +628,9 @@ CU_Theory((dds_entity_t *e), ddsc_get_enabled_status, status_ok, .init=init_enti /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_set_enabled_status, bad_param) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t e), ddsc_set_enabled_status, bad_param) +CU_Theory((dds_entity_t e), ddsc_set_enabled_status, bad_param, .init=init_entity_status, .fini=fini_entity_status) { dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -642,7 +642,7 @@ CU_Test(ddsc_set_enabled_status, deleted_reader, .init=init_entity_status, .fini { dds_delete(rea); ret = dds_set_status_mask(rea, 0 /*mask*/); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_set_enabled_status, illegal, .init=init_entity_status, .fini=fini_entity_status) @@ -663,9 +663,9 @@ CU_Theory((dds_entity_t *entity), ddsc_set_enabled_status, status_ok, .init=init /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_status, bad_param) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t e), ddsc_read_status, bad_param) +CU_Theory((dds_entity_t e), ddsc_read_status, bad_param, .init=init_entity_status, .fini=fini_entity_status) { uint32_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -679,7 +679,7 @@ CU_Test(ddsc_read_status, deleted_reader, .init=init_entity_status, .fini=fini_e uint32_t status; dds_delete(rea); ret = dds_read_status(rea, &status, 0 /*mask*/); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_read_status, illegal, .init=init_entity_status, .fini=fini_entity_status) @@ -715,9 +715,9 @@ CU_Test(ddsc_read_status, invalid_status_on_writer, .init=init_entity_status, .f /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_status, bad_param) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t e), ddsc_take_status, bad_param) +CU_Theory((dds_entity_t e), ddsc_take_status, bad_param, .init=init_entity_status, .fini=fini_entity_status) { uint32_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -731,7 +731,7 @@ CU_Test(ddsc_take_status, deleted_reader, .init=init_entity_status, .fini=fini_e uint32_t status; dds_delete(rea); ret = dds_take_status(rea, &status, 0 /*mask*/); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_take_status, illegal, .init=init_entity_status, .fini=fini_entity_status) { @@ -754,9 +754,9 @@ CU_Theory((dds_entity_t *e), ddsc_take_status, status_ok, .init=init_entity_stat /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_status_changes, bad_param) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t e), ddsc_get_status_changes, bad_param) +CU_Theory((dds_entity_t e), ddsc_get_status_changes, bad_param, .init=init_entity_status, .fini=fini_entity_status) { uint32_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -770,7 +770,7 @@ CU_Test(ddsc_get_status_changes, deleted_reader, .init=init_entity_status, .fini uint32_t status; dds_delete(rea); ret = dds_get_status_changes(rea, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_get_status_changes, illegal, .init=init_entity_status, .fini=fini_entity_status) @@ -793,9 +793,9 @@ CU_Theory((dds_entity_t *e), ddsc_get_status_changes, status_ok, .init=init_enti /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_triggered, bad_param) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t e), ddsc_triggered, bad_param) +CU_Theory((dds_entity_t e), ddsc_triggered, bad_param, .init=init_entity_status, .fini=fini_entity_status) { dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -807,7 +807,7 @@ CU_Test(ddsc_triggered, deleted_reader, .init=init_entity_status, .fini=fini_ent { dds_delete(rea); ret = dds_triggered(rea); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } CU_TheoryDataPoints(ddsc_triggered, status_ok) = { @@ -833,9 +833,9 @@ CU_Test(ddsc_get_inconsistent_topic_status, inconsistent_topic_status, .init=ini /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_inconsistent_topic_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t topic), ddsc_get_inconsistent_topic_status, bad_params) +CU_Theory((dds_entity_t topic), ddsc_get_inconsistent_topic_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_inconsistent_topic_status_t topic_status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -876,9 +876,9 @@ CU_Test(ddsc_get_inconsistent_topic_status, deleted_topic, .init=init_entity_sta /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_publication_matched_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t writer), ddsc_get_publication_matched_status, bad_params) +CU_Theory((dds_entity_t writer), ddsc_get_publication_matched_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_publication_matched_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -913,7 +913,7 @@ CU_Test(ddsc_get_publication_matched_status, deleted_writer, .init=init_entity_s { dds_delete(wri); ret = dds_get_publication_matched_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -930,9 +930,9 @@ CU_Test(ddsc_get_liveliness_lost_status, liveliness_lost_status, .init=init_enti /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_liveliness_lost_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t writer), ddsc_get_liveliness_lost_status, bad_params) +CU_Theory((dds_entity_t writer), ddsc_get_liveliness_lost_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_liveliness_lost_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -967,7 +967,7 @@ CU_Test(ddsc_get_liveliness_lost_status, deleted_writer, .init=init_entity_statu { dds_delete(wri); ret = dds_get_liveliness_lost_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -985,9 +985,9 @@ CU_Test(ddsc_get_offered_deadline_missed_status, offered_deadline_missed_status, /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_offered_deadline_missed_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t writer), ddsc_get_offered_deadline_missed_status, bad_params) +CU_Theory((dds_entity_t writer), ddsc_get_offered_deadline_missed_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_offered_deadline_missed_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1022,15 +1022,15 @@ CU_Test(ddsc_get_offered_deadline_missed_status, deleted_writer, .init=init_enti { dds_delete(wri); ret = dds_get_offered_deadline_missed_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_offered_incompatible_qos_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t writer), ddsc_get_offered_incompatible_qos_status, bad_params) +CU_Theory((dds_entity_t writer), ddsc_get_offered_incompatible_qos_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_offered_incompatible_qos_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1065,15 +1065,15 @@ CU_Test(ddsc_get_offered_incompatible_qos_status, deleted_writer, .init=init_ent { dds_delete(wri); ret = dds_get_offered_incompatible_qos_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_subscription_matched_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t reader), ddsc_get_subscription_matched_status, bad_params) +CU_Theory((dds_entity_t reader), ddsc_get_subscription_matched_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_subscription_matched_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1108,15 +1108,15 @@ CU_Test(ddsc_get_subscription_matched_status, deleted_reader, .init=init_entity_ { dds_delete(rea); ret = dds_get_subscription_matched_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_liveliness_changed_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t reader), ddsc_get_liveliness_changed_status, bad_params) +CU_Theory((dds_entity_t reader), ddsc_get_liveliness_changed_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_liveliness_changed_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1151,15 +1151,15 @@ CU_Test(ddsc_get_liveliness_changed_status, deleted_reader, .init=init_entity_st { dds_delete(rea); ret = dds_get_liveliness_changed_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_sample_rejected_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t reader), ddsc_get_sample_rejected_status, bad_params) +CU_Theory((dds_entity_t reader), ddsc_get_sample_rejected_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_sample_rejected_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1194,15 +1194,15 @@ CU_Test(ddsc_get_sample_rejected_status, deleted_reader, .init=init_entity_statu { dds_delete(rea); ret = dds_get_sample_rejected_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_sample_lost_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t reader), ddsc_get_sample_lost_status, bad_params) +CU_Theory((dds_entity_t reader), ddsc_get_sample_lost_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_sample_lost_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1237,7 +1237,7 @@ CU_Test(ddsc_get_sample_lost_status, deleted_reader, .init=init_entity_status, . { dds_delete(rea); ret = dds_get_sample_lost_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1255,9 +1255,9 @@ CU_Test(ddsc_get_requested_deadline_missed_status, requested_deadline_missed_sta /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_requested_deadline_missed_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t reader), ddsc_get_requested_deadline_missed_status, bad_params) +CU_Theory((dds_entity_t reader), ddsc_get_requested_deadline_missed_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_requested_deadline_missed_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1292,15 +1292,15 @@ CU_Test(ddsc_get_requested_deadline_missed_status, deleted_reader, .init=init_en { dds_delete(rea); ret = dds_get_requested_deadline_missed_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_requested_incompatible_qos_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t reader), ddsc_get_requested_incompatible_qos_status, bad_params) +CU_Theory((dds_entity_t reader), ddsc_get_requested_incompatible_qos_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_requested_incompatible_qos_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1335,7 +1335,7 @@ CU_Test(ddsc_get_requested_incompatible_qos_status, deleted_reader, .init=init_e { dds_delete(rea); ret = dds_get_requested_incompatible_qos_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/file_id.c b/src/core/ddsc/tests/file_id.c deleted file mode 100644 index a2ce5b8..0000000 --- a/src/core/ddsc/tests/file_id.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/dds.h" -#include "CUnit/Test.h" - -#include "dds/ddsrt/misc.h" - -CU_Test(ddsc_err, unique_file_id) -{ - dds_entity_t participant, reader, writer; - - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - CU_ASSERT_FATAL(participant > 0); - - /* Disable SAL warning on intentional misuse of the API */ - DDSRT_WARNING_MSVC_OFF(28020); - reader = dds_create_reader(0, 0, NULL, NULL); - CU_ASSERT_FATAL(reader < 0); - - writer = dds_create_writer(0, 0, NULL, NULL); - CU_ASSERT_FATAL(writer < 0); - - DDSRT_WARNING_MSVC_ON(28020); - - CU_ASSERT_NOT_EQUAL_FATAL(dds_err_file_id(reader), dds_err_file_id(writer)); - - dds_delete(participant); -} diff --git a/src/core/ddsc/tests/publisher.c b/src/core/ddsc/tests/publisher.c index 5ea49d3..78c5bb1 100644 --- a/src/core/ddsc/tests/publisher.c +++ b/src/core/ddsc/tests/publisher.c @@ -42,7 +42,7 @@ CU_Test(ddsc_publisher, create) /* Use NULL participant */ publisher = dds_create_publisher(0, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(publisher), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(publisher), DDS_RETCODE_PRECONDITION_NOT_MET); participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); @@ -143,21 +143,21 @@ CU_Test(ddsc_publisher, suspend_resume) /* Suspend a 0 publisher */ status = dds_suspend(0); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); /* Resume a 0 publisher */ status = dds_resume(0); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); /* Uae dds_suspend on something else than a publisher */ participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); status = dds_suspend(participant); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); /* Use dds_resume on something else than a publisher */ status = dds_resume(participant); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); /* Use dds_resume without calling dds_suspend */ publisher = dds_create_publisher(participant, NULL, NULL); @@ -193,15 +193,15 @@ CU_Test(ddsc_publisher, wait_for_acks) /* Wait_for_acks on NULL publisher or writer and zeroSec timeout */ status = dds_wait_for_acks(0, zeroSec); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); /* wait_for_acks on NULL publisher or writer and oneSec timeout */ status = dds_wait_for_acks(0, oneSec); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); /* wait_for_acks on NULL publisher or writer and DDS_INFINITE timeout */ status = dds_wait_for_acks(0, DDS_INFINITY); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); @@ -212,22 +212,23 @@ CU_Test(ddsc_publisher, wait_for_acks) /* Wait_for_acks on participant and zeroSec timeout */ status = dds_wait_for_acks(participant, zeroSec); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); /* Wait_for_acks on participant and oneSec timeout */ status = dds_wait_for_acks(participant, oneSec); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); /* Wait_for_acks on participant and DDS_INFINITE timeout */ status = dds_wait_for_acks(participant, DDS_INFINITY); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); publisher = dds_create_publisher(participant, NULL, NULL); CU_ASSERT_FATAL(publisher > 0); - /* Wait_for_acks on publisher and minusOneSec timeout */ + /* Wait_for_acks on publisher and minusOneSec timeout -- + either BAD_PARAMETER or UNSUPPORTED would be both be ok, really */ status = dds_wait_for_acks(publisher, minusOneSec); - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); /* Wait_for_acks on publisher and zeroSec timeout */ status = dds_wait_for_acks(publisher, zeroSec); @@ -248,7 +249,7 @@ CU_Test(ddsc_publisher, wait_for_acks) /* Wait_for_acks on suspended publisher and minusOneSec timeout */ status = dds_wait_for_acks(publisher, minusOneSec); - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); /* Wait_for_acks on suspended publisher and zeroSec timeout */ status = dds_wait_for_acks(publisher, zeroSec); diff --git a/src/core/ddsc/tests/querycondition.c b/src/core/ddsc/tests/querycondition.c index 1638a79..107fdd1 100644 --- a/src/core/ddsc/tests/querycondition.c +++ b/src/core/ddsc/tests/querycondition.c @@ -245,13 +245,13 @@ CU_Test(ddsc_querycondition_create, deleted_reader, .init=querycondition_init, . dds_entity_t cond; dds_delete(g_reader); cond = dds_create_querycondition(g_reader, mask, filter_mod2); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_querycondition_create, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_querycondition_create, invalid_readers, .init=querycondition_init, .fini=querycondition_fini) { @@ -297,7 +297,7 @@ CU_Test(ddsc_querycondition_get_mask, deleted, .init=querycondition_init, .fini= dds_delete(condition); mask = 0; ret = dds_get_mask(condition, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -319,7 +319,7 @@ CU_Test(ddsc_querycondition_get_mask, null, .init=querycondition_init, .fini=que /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_querycondition_get_mask, invalid_conditions) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t cond), ddsc_querycondition_get_mask, invalid_conditions, .init=querycondition_init, .fini=querycondition_fini) { @@ -924,7 +924,7 @@ CU_Test(ddsc_querycondition_read, already_deleted, .init=querycondition_init, .f /* Try to read with a deleted condition. */ ret = dds_read(condition, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1487,7 +1487,7 @@ CU_Test(ddsc_querycondition_take, already_deleted, .init=querycondition_init, .f /* Try to take with a deleted condition. */ ret = dds_take(condition, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/read_instance.c b/src/core/ddsc/tests/read_instance.c index 7ef1384..063d003 100644 --- a/src/core/ddsc/tests/read_instance.c +++ b/src/core/ddsc/tests/read_instance.c @@ -450,7 +450,7 @@ CU_Theory((dds_entity_t *rdr, dds_instance_handle_t hdl), ddsc_read_instance_mas *************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_instance, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_instance, invalid_readers, .init=read_instance_init, .fini=read_instance_fini) { @@ -464,7 +464,7 @@ CU_Theory((dds_entity_t rdr), ddsc_read_instance, invalid_readers, .init=read_in /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_instance_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_instance_wl, invalid_readers, .init=read_instance_init, .fini=read_instance_fini) { @@ -478,7 +478,7 @@ CU_Theory((dds_entity_t rdr), ddsc_read_instance_wl, invalid_readers, .init=read /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_instance_mask, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_instance_mask, invalid_readers, .init=read_instance_init, .fini=read_instance_fini) { @@ -493,7 +493,7 @@ CU_Theory((dds_entity_t rdr), ddsc_read_instance_mask, invalid_readers, .init=re /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_instance_mask_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_instance_mask_wl, invalid_readers, .init=read_instance_init, .fini=read_instance_fini) { @@ -586,7 +586,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance, already_deleted, .init=read_i ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_instance(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -600,7 +600,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance_wl, already_deleted, .init=rea ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_instance_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -615,7 +615,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance_mask, already_deleted, .init=r ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_instance_mask(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -630,7 +630,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance_mask_wl, already_deleted, .ini ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_instance_mask_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/readcondition.c b/src/core/ddsc/tests/readcondition.c index 534f51c..694d463 100644 --- a/src/core/ddsc/tests/readcondition.c +++ b/src/core/ddsc/tests/readcondition.c @@ -227,13 +227,13 @@ CU_Test(ddsc_readcondition_create, deleted_reader, .init=readcondition_init, .fi dds_entity_t cond; dds_delete(g_reader); cond = dds_create_readcondition(g_reader, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_readcondition_create, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_readcondition_create, invalid_readers, .init=readcondition_init, .fini=readcondition_fini) { @@ -279,7 +279,7 @@ CU_Test(ddsc_readcondition_get_mask, deleted, .init=readcondition_init, .fini=re dds_delete(condition); mask = 0; ret = dds_get_mask(condition, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -301,7 +301,7 @@ CU_Test(ddsc_readcondition_get_mask, null, .init=readcondition_init, .fini=readc /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_readcondition_get_mask, invalid_conditions) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t cond), ddsc_readcondition_get_mask, invalid_conditions, .init=readcondition_init, .fini=readcondition_fini) { @@ -906,7 +906,7 @@ CU_Test(ddsc_readcondition_read, already_deleted, .init=readcondition_init, .fin /* Try to read with a deleted condition. */ ret = dds_read(condition, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1462,7 +1462,7 @@ CU_Test(ddsc_readcondition_take, already_deleted, .init=readcondition_init, .fin /* Try to take with a deleted condition. */ ret = dds_take(condition, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/reader.c b/src/core/ddsc/tests/reader.c index 4698172..ad80be7 100644 --- a/src/core/ddsc/tests/reader.c +++ b/src/core/ddsc/tests/reader.c @@ -316,7 +316,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs), ddsc /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -347,7 +347,7 @@ CU_Test(ddsc_read, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_read(g_reader, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -426,7 +426,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, uint32_t maxs), ddsc_read_wl, inva /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_wl, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -457,7 +457,7 @@ CU_Test(ddsc_read_wl, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_read_wl(g_reader, g_loans, g_info, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -550,7 +550,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs), ddsc /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_mask, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_mask, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -584,7 +584,7 @@ CU_Test(ddsc_read_mask, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_read_mask(g_reader, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1098,7 +1098,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, uint32_t maxs), ddsc_read_mask_wl, /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_mask_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_mask_wl, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -1132,7 +1132,7 @@ CU_Test(ddsc_read_mask_wl, already_deleted, .init=reader_init, .fini=reader_fini /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_read_mask_wl(g_reader, g_loans, g_info, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1686,7 +1686,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs), ddsc /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -1717,7 +1717,7 @@ CU_Test(ddsc_take, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to take with a deleted reader. */ dds_delete(g_reader); ret = dds_take(g_reader, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1796,7 +1796,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, uint32_t maxs), ddsc_take_wl, inva /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_wl, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -1827,7 +1827,7 @@ CU_Test(ddsc_take_wl, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_take_wl(g_reader, g_loans, g_info, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1921,7 +1921,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs), ddsc /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_mask, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_mask, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -1955,7 +1955,7 @@ CU_Test(ddsc_take_mask, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_take_mask(g_reader, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -2602,7 +2602,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, uint32_t maxs), ddsc_take_mask_wl, /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_mask_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_mask_wl, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -2636,7 +2636,7 @@ CU_Test(ddsc_take_mask_wl, already_deleted, .init=reader_init, .fini=reader_fini /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_take_mask_wl(g_reader, g_loans, g_info, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/reader_iterator.c b/src/core/ddsc/tests/reader_iterator.c index 7a840ca..c0dbe6a 100644 --- a/src/core/ddsc/tests/reader_iterator.c +++ b/src/core/ddsc/tests/reader_iterator.c @@ -356,7 +356,7 @@ CU_Test(ddsc_read_next, reader, .init=reader_iterator_init, .fini=reader_iterato /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_next, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_next, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini) { @@ -390,7 +390,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_next, already_deleted, .init=reader_ite ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_next(*rdr, g_samples, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -472,7 +472,7 @@ CU_Test(ddsc_read_next_wl, reader, .init=reader_iterator_init, .fini=reader_iter /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_next_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_next_wl, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini) { @@ -506,7 +506,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_next_wl, already_deleted, .init=reader_ ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_next_wl(*rdr, g_loans, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -582,7 +582,7 @@ CU_Test(ddsc_take_next, reader, .init=reader_iterator_init, .fini=reader_iterato } /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_next, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_next, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini) { @@ -616,7 +616,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_next, already_deleted, .init=reader_ite ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_next(*rdr, g_samples, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -695,7 +695,7 @@ CU_Test(ddsc_take_next_wl, reader, .init=reader_iterator_init, .fini=reader_iter } /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_next_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_next_wl, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini) { @@ -729,7 +729,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_next_wl, already_deleted, .init=reader_ ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_next_wl(*rdr, g_loans, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/register.c b/src/core/ddsc/tests/register.c index a075ae5..11249dd 100644 --- a/src/core/ddsc/tests/register.c +++ b/src/core/ddsc/tests/register.c @@ -150,7 +150,7 @@ CU_Test(ddsc_register_instance, deleted_entity, .init=registering_init, .fini=re dds_instance_handle_t handle; dds_delete(g_writer); ret = dds_register_instance(g_writer, &handle, g_data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } static dds_instance_handle_t hndle = 0; @@ -173,7 +173,7 @@ CU_Theory((dds_instance_handle_t *hndl2, void *datap), ddsc_register_instance, i } CU_TheoryDataPoints(ddsc_register_instance, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_register_instance, invalid_writers, .init=registering_init, .fini=registering_fini) { diff --git a/src/core/ddsc/tests/take_instance.c b/src/core/ddsc/tests/take_instance.c index d9ef401..6fba4a6 100644 --- a/src/core/ddsc/tests/take_instance.c +++ b/src/core/ddsc/tests/take_instance.c @@ -447,7 +447,7 @@ CU_Theory((dds_entity_t *rdr, dds_instance_handle_t hdl), ddsc_take_instance_mas *************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_instance, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_instance, invalid_readers, .init=take_instance_init, .fini=take_instance_fini) { @@ -461,7 +461,7 @@ CU_Theory((dds_entity_t rdr), ddsc_take_instance, invalid_readers, .init=take_in /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_instance_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_instance_wl, invalid_readers, .init=take_instance_init, .fini=take_instance_fini) { @@ -475,7 +475,7 @@ CU_Theory((dds_entity_t rdr), ddsc_take_instance_wl, invalid_readers, .init=take /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_instance_mask, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_instance_mask, invalid_readers, .init=take_instance_init, .fini=take_instance_fini) { @@ -490,7 +490,7 @@ CU_Theory((dds_entity_t rdr), ddsc_take_instance_mask, invalid_readers, .init=ta /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_instance_mask_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_instance_mask_wl, invalid_readers, .init=take_instance_init, .fini=take_instance_fini) { @@ -583,7 +583,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance, already_deleted, .init=take_i ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_instance(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -597,7 +597,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance_wl, already_deleted, .init=tak ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_instance_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -612,7 +612,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance_mask, already_deleted, .init=t ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_instance_mask(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -627,7 +627,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance_mask_wl, already_deleted, .ini ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_instance_mask_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/topic.c b/src/core/ddsc/tests/topic.c index 665d38d..43dde13 100644 --- a/src/core/ddsc/tests/topic.c +++ b/src/core/ddsc/tests/topic.c @@ -314,7 +314,7 @@ CU_Test(ddsc_topic_get_name, deleted, .init=ddsc_topic_init, .fini=ddsc_topic_fi dds_return_t ret; dds_delete(g_topicRtmDataType); ret = dds_get_name(g_topicRtmDataType, name, MAX_NAME_SIZE); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -387,7 +387,7 @@ CU_Test(ddsc_topic_get_type_name, deleted, .init=ddsc_topic_init, .fini=ddsc_top dds_return_t ret; dds_delete(g_topicRtmDataType); ret = dds_get_type_name(g_topicRtmDataType, name, MAX_NAME_SIZE); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/unregister.c b/src/core/ddsc/tests/unregister.c index c79cb9a..e27eb32 100644 --- a/src/core/ddsc/tests/unregister.c +++ b/src/core/ddsc/tests/unregister.c @@ -152,7 +152,7 @@ CU_Test(ddsc_unregister_instance, deleted, .init=unregistering_init, .fini=unreg dds_delete(g_writer); ret = dds_unregister_instance(g_writer, g_data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -167,7 +167,7 @@ CU_Test(ddsc_unregister_instance, null, .init=unregistering_init, .fini=unregist /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_unregister_instance, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_unregister_instance, invalid_writers, .init=unregistering_init, .fini=unregistering_fini) { @@ -246,7 +246,7 @@ CU_Test(ddsc_unregister_instance_ts, deleted, .init=unregistering_init, .fini=un dds_return_t ret; dds_delete(g_writer); ret = dds_unregister_instance_ts(g_writer, g_data, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -261,7 +261,7 @@ CU_Test(ddsc_unregister_instance_ts, null, .init=unregistering_init, .fini=unreg /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_unregister_instance_ts, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_unregister_instance_ts, invalid_writers, .init=unregistering_init, .fini=unregistering_fini) { @@ -383,7 +383,7 @@ CU_Test(ddsc_unregister_instance_ih, deleted, .init=unregistering_init, .fini=un dds_return_t ret; dds_delete(g_writer); ret = dds_unregister_instance_ih(g_writer, DDS_HANDLE_NIL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -401,7 +401,7 @@ CU_Theory((dds_instance_handle_t handle), ddsc_unregister_instance_ih, invalid_h /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_unregister_instance_ih, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_unregister_instance_ih, invalid_writers, .init=unregistering_init, .fini=unregistering_fini) { @@ -481,7 +481,7 @@ CU_Test(ddsc_unregister_instance_ih_ts, deleted, .init=unregistering_init, .fini dds_return_t ret; dds_delete(g_writer); ret = dds_unregister_instance_ih_ts(g_writer, DDS_HANDLE_NIL, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -499,7 +499,7 @@ CU_Theory((dds_instance_handle_t handle), ddsc_unregister_instance_ih_ts, invali /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_unregister_instance_ih_ts, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_unregister_instance_ih_ts, invalid_writers, .init=unregistering_init, .fini=unregistering_fini) { diff --git a/src/core/ddsc/tests/unsupported.c b/src/core/ddsc/tests/unsupported.c index 2a15f25..68bf4a5 100644 --- a/src/core/ddsc/tests/unsupported.c +++ b/src/core/ddsc/tests/unsupported.c @@ -50,7 +50,7 @@ setup(void) CU_ASSERT_FATAL(e[REA] > 0); e[RCD] = dds_create_readcondition(e[REA], DDS_ANY_STATE); CU_ASSERT_FATAL(e[RCD] > 0); - e[BAD] = 1; + e[BAD] = 314159265; } static void @@ -104,7 +104,7 @@ CU_Test(ddsc_unsupported, dds_suspend_resume, .init = setup, .fini = teardown) dds_return_t result; static struct index_result pars[] = { {PUB, DDS_RETCODE_UNSUPPORTED}, - {WRI, DDS_RETCODE_BAD_PARAMETER}, + {WRI, DDS_RETCODE_ILLEGAL_OPERATION}, {BAD, DDS_RETCODE_BAD_PARAMETER} }; diff --git a/src/core/ddsc/tests/waitset.c b/src/core/ddsc/tests/waitset.c index 24c9954..9c401cb 100644 --- a/src/core/ddsc/tests/waitset.c +++ b/src/core/ddsc/tests/waitset.c @@ -226,13 +226,13 @@ CU_Test(ddsc_waitset_create, deleted_participant, .init=ddsc_waitset_basic_init, deleted = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); dds_delete(deleted); ws = dds_create_waitset(deleted); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ws), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ws), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_create, invalid_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t par), ddsc_waitset_create, invalid_params, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { @@ -269,7 +269,7 @@ CU_Theory((dds_entity_t *par), ddsc_waitset_create, non_participants, .init=ddsc *************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_attach, invalid_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), CU_DataPoints(dds_attach_t, (dds_attach_t)NULL, (dds_attach_t)&reader, (dds_attach_t)3, (dds_attach_t)0, (dds_attach_t)0, (dds_attach_t)0, (dds_attach_t)0), }; CU_Theory((dds_entity_t e, dds_attach_t a), ddsc_waitset_attach, invalid_params, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) @@ -282,7 +282,7 @@ CU_Theory((dds_entity_t e, dds_attach_t a), ddsc_waitset_attach, invalid_params, /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_attach, invalid_waitsets) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), CU_DataPoints(dds_attach_t, (dds_attach_t)NULL, (dds_attach_t)&reader, (dds_attach_t)3, (dds_attach_t)0, (dds_attach_t)0, (dds_attach_t)0, (dds_attach_t)0), }; CU_Theory((dds_entity_t ws, dds_attach_t a), ddsc_waitset_attach, invalid_waitsets, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) @@ -315,7 +315,7 @@ CU_Test(ddsc_waitset_attach, deleted_waitset, .init=ddsc_waitset_basic_init, .fi dds_return_t ret; dds_delete(waitset); ret = dds_waitset_attach(waitset, participant, 0); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -393,7 +393,7 @@ CU_Test(ddsc_waitset_attach_detach, second, .init=ddsc_waitset_basic_init, .fini *************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_detach, invalid_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t e), ddsc_waitset_detach, invalid_params, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { @@ -405,7 +405,7 @@ CU_Theory((dds_entity_t e), ddsc_waitset_detach, invalid_params, .init=ddsc_wait /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_detach, invalid_waitsets) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t ws), ddsc_waitset_detach, invalid_waitsets, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { @@ -580,13 +580,13 @@ CU_Test(ddsc_waitset_set_trigger, deleted_waitset, .init=ddsc_waitset_basic_init dds_return_t ret; dds_delete(waitset); ret = dds_waitset_set_trigger(waitset, true); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_set_trigger, invalid_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t ws), ddsc_waitset_set_trigger, invalid_params, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { @@ -625,13 +625,13 @@ CU_Test(ddsc_waitset_wait, deleted_waitset, .init=ddsc_waitset_attached_init, .f dds_return_t ret; dds_delete(waitset); ret = dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(1)); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_wait, invalid_waitsets) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t ws), ddsc_waitset_wait, invalid_waitsets, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { @@ -683,13 +683,13 @@ CU_Test(ddsc_waitset_wait_until, deleted_waitset, .init=ddsc_waitset_attached_in dds_return_t ret; dds_delete(waitset); ret = dds_waitset_wait_until(waitset, &triggered, 1, dds_time()); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_wait_until, invalid_waitsets) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t ws), ddsc_waitset_wait_until, invalid_waitsets, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { @@ -843,13 +843,13 @@ CU_Test(ddsc_waitset_get_entities, deleted_waitset, .init=ddsc_waitset_attached_ dds_entity_t entities[MAX_ENTITIES_CNT]; dds_delete(waitset); ret = dds_waitset_get_entities(waitset, entities, MAX_ENTITIES_CNT); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_get_entities, invalid_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t ws), ddsc_waitset_get_entities, invalid_params, .init=ddsc_waitset_attached_init, .fini=ddsc_waitset_attached_fini) { diff --git a/src/core/ddsc/tests/write.c b/src/core/ddsc/tests/write.c index 93dae69..2cd3f15 100644 --- a/src/core/ddsc/tests/write.c +++ b/src/core/ddsc/tests/write.c @@ -95,7 +95,7 @@ CU_Test(ddsc_write, closed_writer, .init = setup, .fini = teardown) CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_OK); status = dds_write(writer, &data); writer = 0; - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_write, null_sample, .init = setup, .fini = teardown) diff --git a/src/core/ddsc/tests/writer.c b/src/core/ddsc/tests/writer.c index f738ddb..66ce1ea 100644 --- a/src/core/ddsc/tests/writer.c +++ b/src/core/ddsc/tests/writer.c @@ -83,7 +83,7 @@ CU_Test(ddsc_create_writer, deleted_publisher, .init = setup, .fini = teardown) dds_delete(publisher); writer = dds_create_writer(publisher, topic, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_create_writer, null_topic, .init = setup, .fini = teardown) @@ -105,5 +105,5 @@ CU_Test(ddsc_create_writer, deleted_topic, .init = setup, .fini = teardown) dds_delete(topic); writer = dds_create_writer(publisher, topic, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_BAD_PARAMETER); } diff --git a/src/core/ddsi/.fileids b/src/core/ddsi/.fileids deleted file mode 100644 index 0fd013b..0000000 --- a/src/core/ddsi/.fileids +++ /dev/null @@ -1,40 +0,0 @@ -# ddsi sources -1 src/ddsi_ser.c -2 src/ddsi_ssl.c -3 src/ddsi_tcp.c -4 src/ddsi_tran.c -5 src/ddsi_udp.c -6 src/q_addrset.c -7 src/q_bitset_inlines.c -8 src/q_bswap.c -9 src/q_bswap_inlines.c -10 src/q_config.c -11 src/q_ddsi_discovery.c -12 src/q_debmon.c -13 src/q_entity.c -14 src/q_ephash.c -15 src/q_gc.c -16 src/q_init.c -17 src/q_lat_estim.c -18 src/q_lease.c -20 src/q_md5.c -21 src/q_misc.c -22 src/q_nwif.c -23 src/q_pcap.c -24 src/q_plist.c -25 src/q_qosmatch.c -26 src/q_radmin.c -27 src/q_receive.c -28 src/q_security.c -29 src/q_servicelease.c -30 src/q_sockwaitset.c -31 src/q_thread.c -32 src/q_thread_inlines.c -33 src/q_time.c -34 src/q_transmit.c -36 src/q_xevent.c -37 src/q_xmsg.c -38 src/q_freelist.c -39 src/sysdeps.c -71 src/q_builtin_topic.c - diff --git a/src/core/ddsi/src/q_thread_inlines.c b/src/core/ddsi/src/q_thread_inlines.c index 4d26a63..b16f324 100644 --- a/src/core/ddsi/src/q_thread_inlines.c +++ b/src/core/ddsi/src/q_thread_inlines.c @@ -19,4 +19,3 @@ extern inline void thread_state_asleep (struct thread_state1 *ts1); extern inline void thread_state_awake (struct thread_state1 *ts1); extern inline void thread_state_blocked (struct thread_state1 *ts1); extern inline void thread_state_unblocked (struct thread_state1 *ts1); - diff --git a/src/tools/pubsub/common.c b/src/tools/pubsub/common.c index 43322f4..be217cb 100644 --- a/src/tools/pubsub/common.c +++ b/src/tools/pubsub/common.c @@ -390,7 +390,6 @@ static void inapplicable_qos(dds_entity_kind_t qt, const char *n) { case DDS_KIND_COND_READ: en = "cond read"; break; case DDS_KIND_COND_QUERY: en = "cond query"; break; case DDS_KIND_WAITSET: en = "waitset"; break; - case DDS_KIND_INTERNAL: en = "internal"; break; default: en = "?"; break; } fprintf(stderr, "warning: %s entity ignoring inapplicable QoS \"%s\"\n", en, n); diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 84088c3..282c131 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -11,7 +11,7 @@ # include (GenerateExportHeader) -PREPEND(srcs_util "${CMAKE_CURRENT_SOURCE_DIR}/src" ut_avl.c ut_crc.c ut_expand_envvars.c ut_fibheap.c ut_handleserver.c ut_hopscotch.c ut_thread_pool.c ut_xmlparser.c) +PREPEND(srcs_util "${CMAKE_CURRENT_SOURCE_DIR}/src" ut_avl.c ut_crc.c ut_expand_envvars.c ut_fibheap.c ut_hopscotch.c ut_thread_pool.c ut_xmlparser.c) add_library(util ${srcs_util}) set_property(TARGET util PROPERTY POSITION_INDEPENDENT_CODE TRUE) diff --git a/src/util/src/ut_handleserver.c b/src/util/src/ut_handleserver.c deleted file mode 100644 index 657f05e..0000000 --- a/src/util/src/ut_handleserver.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include -#include - -#include "dds/ddsrt/cdtors.h" -#include "dds/ddsrt/heap.h" -#include "dds/ddsrt/sync.h" -#include "dds/util/ut_handleserver.h" - -/* Arbitrarily number of max handles. Should be enough for the mock. */ -#define MAX_NR_OF_HANDLES (1000) - -#define HDL_FLAG_NONE (0x00) -#define HDL_FLAG_CLOSED (0x01) - -typedef struct ut_handlelink { - ut_handle_t hdl; - void *arg; - uint32_t cnt; - uint8_t flags; -} ut_handlelink; - -typedef struct ut_handleserver { - ut_handlelink *hdls[MAX_NR_OF_HANDLES]; - int32_t last; - ddsrt_mutex_t mutex; -} ut_handleserver; - - -/* Singleton handle server. */ -static ut_handleserver *hs = NULL; - - -static ut_handle_retcode_t -lookup_handle(ut_handle_t hdl, int32_t kind, ut_handlelink **link); - -static ut_handle_t -check_handle(ut_handle_t hdl, int32_t kind); - -static void -delete_handle(int32_t idx); - - -ut_handle_retcode_t -ut_handleserver_init(void) -{ - ddsrt_init(); - /* TODO Allow re-entry (something like ddsrt_init()). */ - assert(hs == NULL); - hs = ddsrt_malloc(sizeof(ut_handleserver)); - hs->last = 0; - ddsrt_mutex_init(&hs->mutex); - return UT_HANDLE_OK; -} - - -void -ut_handleserver_fini(void) -{ - int32_t i; - - /* TODO Only destroy when this is the last fini (something like ddsrt_fini()). */ - assert(hs); - - /* Every handle should have been deleted, but make sure. */ - for (i = 0; i < hs->last; i++) { - if (hs->hdls[i] != NULL) { - /* TODO CHAM-138: Print warning. */ - ddsrt_free(hs->hdls[i]); - } - } - ddsrt_mutex_destroy(&hs->mutex); - ddsrt_free(hs); - hs = NULL; - ddsrt_fini(); -} - - -ut_handle_t -ut_handle_create( - int32_t kind, - void *arg) -{ - ut_handle_t hdl = (ut_handle_t)UT_HANDLE_OUT_OF_RESOURCES; - - /* A kind is obligatory. */ - assert(kind & UT_HANDLE_KIND_MASK); - /* The kind should extent outside its boundaries. */ - assert(!(kind & ~UT_HANDLE_KIND_MASK)); - - if (hs == NULL) { - return (ut_handle_t)UT_HANDLE_NOT_INITALIZED; - } - - ddsrt_mutex_lock(&hs->mutex); - - /* TODO CHAM-138: Improve the creation and management of handles. */ - if (hs->last < MAX_NR_OF_HANDLES) { - hdl = hs->last; - hdl |= kind; - hs->hdls[hs->last] = ddsrt_malloc(sizeof(ut_handlelink)); - hs->hdls[hs->last]->cnt = 0; - hs->hdls[hs->last]->arg = arg; - hs->hdls[hs->last]->hdl = hdl; - hs->hdls[hs->last]->flags = HDL_FLAG_NONE; - hs->last++; - } - - ddsrt_mutex_unlock(&hs->mutex); - - return hdl; -} - -void -ut_handle_close( - ut_handle_t hdl, - struct ut_handlelink *link) -{ - struct ut_handlelink *info = link; - ut_handle_retcode_t ret = UT_HANDLE_OK; - - assert(hs); - - ddsrt_mutex_lock(&hs->mutex); - if (info == NULL) { - ret = lookup_handle(hdl, UT_HANDLE_DONTCARE_KIND, &info); - } - if (ret == UT_HANDLE_OK) { - assert(info); - assert(hdl == info->hdl); - info->flags |= HDL_FLAG_CLOSED; - } - ddsrt_mutex_unlock(&hs->mutex); -} - -ut_handle_retcode_t -ut_handle_delete( - ut_handle_t hdl, - struct ut_handlelink *link, - dds_time_t timeout) -{ - struct ut_handlelink *info = link; - ut_handle_retcode_t ret = UT_HANDLE_OK; - - assert(hs); - - ddsrt_mutex_lock(&hs->mutex); - if (info == NULL) { - ret = lookup_handle(hdl, UT_HANDLE_DONTCARE_KIND, &info); - } - if (ret == UT_HANDLE_OK) { - assert(info); - assert(hdl == info->hdl); - info->flags |= HDL_FLAG_CLOSED; - - /* FIXME: Replace this polling with conditional wait. */ - ddsrt_mutex_unlock(&hs->mutex); - { - dds_duration_t delay = DDS_MSECS(10); - while ((info->cnt != 0) && timeout > 0) { - dds_sleepfor(delay); - timeout = (delay < timeout ? timeout - delay : 0); - } - } - ddsrt_mutex_lock(&hs->mutex); - - if (info->cnt == 0) { - delete_handle(hdl & UT_HANDLE_IDX_MASK); - } else { - ret = UT_HANDLE_TIMEOUT; - } - } - ddsrt_mutex_unlock(&hs->mutex); - - return ret; -} - -ut_handle_retcode_t -ut_handle_status( - ut_handle_t hdl, - struct ut_handlelink *link, - int32_t kind) -{ - struct ut_handlelink *info = link; - ut_handle_retcode_t ret = UT_HANDLE_OK; - - if (hs == NULL) { - return (ut_handle_t)UT_HANDLE_INVALID; - } - - ddsrt_mutex_lock(&hs->mutex); - if (info == NULL) { - ret = lookup_handle(hdl, kind, &info); - } - if (ret == UT_HANDLE_OK) { - assert(info); - assert(hdl == info->hdl); - if (info->flags & HDL_FLAG_CLOSED) { - ret = UT_HANDLE_CLOSED; - } - } - ddsrt_mutex_unlock(&hs->mutex); - - return ret; -} - -ut_handle_retcode_t -ut_handle_claim( - ut_handle_t hdl, - struct ut_handlelink *link, - int32_t kind, - void **arg) -{ - struct ut_handlelink *info = link; - ut_handle_retcode_t ret = UT_HANDLE_OK; - - if (arg != NULL) { - *arg = NULL; - } - - if (hs == NULL) { - return (ut_handle_t)UT_HANDLE_INVALID; - } - - ddsrt_mutex_lock(&hs->mutex); - if (info == NULL) { - ret = lookup_handle(hdl, kind, &info); - } - if (ret == UT_HANDLE_OK) { - assert(info); - assert(hdl == info->hdl); - if (info->flags & HDL_FLAG_CLOSED) { - ret = UT_HANDLE_CLOSED; - } - } - if (ret == UT_HANDLE_OK) { - info->cnt++; - if (arg != NULL) { - *arg = info->arg; - } - } - ddsrt_mutex_unlock(&hs->mutex); - - return ret; -} - - -void -ut_handle_release( - ut_handle_t hdl, - struct ut_handlelink *link) -{ - struct ut_handlelink *info = link; - ut_handle_retcode_t ret = UT_HANDLE_OK; - - assert(hs); - - ddsrt_mutex_lock(&hs->mutex); - if (info == NULL) { - ret = lookup_handle(hdl, UT_HANDLE_DONTCARE_KIND, &info); - } - if (ret == UT_HANDLE_OK) { - assert(info); - assert(hdl == info->hdl); - assert(info->cnt > 0); - info->cnt--; - } - ddsrt_mutex_unlock(&hs->mutex); -} - -bool -ut_handle_is_closed( - ut_handle_t hdl, - struct ut_handlelink *link) -{ - struct ut_handlelink *info = link; - ut_handle_retcode_t ret = UT_HANDLE_OK; - - assert(hs); - - ddsrt_mutex_lock(&hs->mutex); - if (info == NULL) { - ret = lookup_handle(hdl, UT_HANDLE_DONTCARE_KIND, &info); - } - if (ret == UT_HANDLE_OK) { - assert(info); - assert(hdl == info->hdl); - if (info->flags & HDL_FLAG_CLOSED) { - ret = UT_HANDLE_CLOSED; - } - } - ddsrt_mutex_unlock(&hs->mutex); - - /* Simulate closed for every error. */ - return (ret != UT_HANDLE_OK); -} - -struct ut_handlelink* -ut_handle_get_link( - ut_handle_t hdl) -{ - struct ut_handlelink *info; - ut_handle_retcode_t ret; - - assert(hs); - - ddsrt_mutex_lock(&hs->mutex); - ret = lookup_handle(hdl, UT_HANDLE_DONTCARE_KIND, &info); - assert(((ret == UT_HANDLE_OK) && (info != NULL)) || - ((ret != UT_HANDLE_OK) && (info == NULL)) ); - (void)ret; - ddsrt_mutex_unlock(&hs->mutex); - - return info; -} - - -static ut_handle_retcode_t -lookup_handle( - ut_handle_t hdl, - int32_t kind, - ut_handlelink **link) -{ - ut_handle_retcode_t ret; - *link = NULL; - ret = check_handle(hdl, kind); - if (ret == UT_HANDLE_OK) { - int32_t idx = (hdl & UT_HANDLE_IDX_MASK); - assert(idx < MAX_NR_OF_HANDLES); - *link = hs->hdls[idx]; - } - return ret; -} - -static ut_handle_t -check_handle( - ut_handle_t hdl, - int32_t kind) -{ - /* When handle is negative, it contains a retcode. */ - ut_handle_retcode_t ret = UT_HANDLE_OK; - if (hdl > 0) { - if (hdl & UT_HANDLE_KIND_MASK) { - int32_t idx = (hdl & UT_HANDLE_IDX_MASK); - if (idx < hs->last) { - assert(idx < MAX_NR_OF_HANDLES); - ut_handlelink *info = hs->hdls[idx]; - if (info != NULL) { - if ((info->hdl & UT_HANDLE_KIND_MASK) == (hdl & UT_HANDLE_KIND_MASK)) { - if ((kind != UT_HANDLE_DONTCARE_KIND) && - (kind != (hdl & UT_HANDLE_KIND_MASK))) { - /* It's a valid handle, but the caller expected a different kind. */ - ret = UT_HANDLE_UNEQUAL_KIND; - } - } else { - ret = UT_HANDLE_UNEQUAL_KIND; - } - } else { - ret = UT_HANDLE_DELETED; - } - } else { - ret = UT_HANDLE_INVALID; - } - } else { - ret = UT_HANDLE_INVALID; - } - } else if (hdl == 0) { - ret = UT_HANDLE_INVALID; - } else { - /* When handle is negative, it contains a retcode. */ - ret = (ut_handle_retcode_t)hdl; - } - return ret; -} - -static void -delete_handle(int32_t idx) -{ - assert(hs); - assert(idx < MAX_NR_OF_HANDLES); - ddsrt_free(hs->hdls[idx]); - hs->hdls[idx] = NULL; -} diff --git a/src/util/tests/CMakeLists.txt b/src/util/tests/CMakeLists.txt index 0d88ea0..7828517 100644 --- a/src/util/tests/CMakeLists.txt +++ b/src/util/tests/CMakeLists.txt @@ -11,19 +11,5 @@ # include(CUnit) -add_cunit_executable(cunit_util "handleserver.c") -target_link_libraries(cunit_util PRIVATE util) -target_link_libraries(cunit_util PRIVATE ddsrt) - -# Create a dummy export header. generate_export_header can only be used with -# library targets, but since the targets are linked statically, -# __declspec(dllimport) is not required anyway. -set(export_dir "${CMAKE_CURRENT_BINARY_DIR}/include/dds") -set(export_header "${export_dir}/export.h") -if(NOT EXISTS "${export_header}") - file(MAKE_DIRECTORY "${export_dir}") - file(WRITE "${export_header}" "#define DDS_EXPORT\n") -endif() - -target_include_directories( - cunit_util PRIVATE "$") +#add_cunit_executable(CUnit_util "handleserver.c") +#target_link_libraries(CUnit_util util) diff --git a/src/util/tests/handleserver.c b/src/util/tests/handleserver.c deleted file mode 100644 index ced5832..0000000 --- a/src/util/tests/handleserver.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/util/ut_handleserver.h" -#include "CUnit/Test.h" -#include "dds/ddsrt/retcode.h" -#include "dds/ddsrt/threads.h" -#include "dds/ddsrt/time.h" - -/*****************************************************************************************/ -CU_Test(util_handleserver, basic) -{ - int32_t kind = 0x10000000; - ut_handle_retcode_t ret; - ut_handle_t hdl; - int arg = 1; - void *argx; - - ret = ut_handleserver_init(); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - hdl = ut_handle_create(kind, (void*)&arg); - CU_ASSERT_FATAL(hdl > 0); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - CU_ASSERT_EQUAL_FATAL(argx, &arg); - - ut_handle_release(hdl, NULL); - - ret = ut_handle_delete(hdl, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_DELETED); - - ut_handleserver_fini(); -} - - -/*****************************************************************************************/ -CU_Test(util_handleserver, close) -{ - int32_t kind = 0x10000000; - ut_handle_retcode_t ret; - ut_handle_t hdl; - int arg = 1; - void *argx; - bool closed; - - ret = ut_handleserver_init(); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - hdl = ut_handle_create(kind, (void*)&arg); - CU_ASSERT_FATAL(hdl > 0); - - closed = ut_handle_is_closed(hdl, NULL); - CU_ASSERT_EQUAL_FATAL(closed, false); - - ut_handle_close(hdl, NULL); - - closed = ut_handle_is_closed(hdl, NULL); - CU_ASSERT_EQUAL_FATAL(closed, true); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_CLOSED); - - ret = ut_handle_delete(hdl, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_DELETED); - - ut_handleserver_fini(); -} - -/*****************************************************************************************/ -CU_Test(util_handleserver, link) -{ - int32_t kind = 0x10000000; - ut_handle_retcode_t ret; - struct ut_handlelink *link; - ut_handle_t hdl; - int arg = 1; - void *argx; - - ret = ut_handleserver_init(); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - hdl = ut_handle_create(kind, (void*)&arg); - CU_ASSERT_FATAL(hdl > 0); - - link = ut_handle_get_link(hdl); - CU_ASSERT_NOT_EQUAL_FATAL(link, NULL); - - ret = ut_handle_claim(hdl, link, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - CU_ASSERT_EQUAL_FATAL(argx, &arg); - - ut_handle_release(hdl, link); - - ret = ut_handle_delete(hdl, link, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - link = ut_handle_get_link(hdl); - CU_ASSERT_EQUAL_FATAL(link, NULL); - - ut_handleserver_fini(); -} - - -/*****************************************************************************************/ -CU_Test(util_handleserver, types) -{ - int32_t kind1 = 0x10000000; - int32_t kind2 = 0x20000000; - ut_handle_retcode_t ret; - ut_handle_t hdl1a; - ut_handle_t hdl1b; - ut_handle_t hdl2; - int arg1a = (int)'a'; - int arg1b = (int)'b'; - int arg2 = (int)'2'; - void *argx; - - ret = ut_handleserver_init(); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - hdl1a = ut_handle_create(kind1, (void*)&arg1a); - CU_ASSERT_FATAL(hdl1a > 0); - - hdl1b = ut_handle_create(kind1, (void*)&arg1b); - CU_ASSERT_FATAL(hdl1b > 0); - - hdl2 = ut_handle_create(kind2, (void*)&arg2); - CU_ASSERT_FATAL(hdl2 > 0); - - ret = ut_handle_claim(hdl1a, NULL, kind1, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - CU_ASSERT_EQUAL_FATAL(argx, &arg1a); - - ret = ut_handle_claim(hdl1b, NULL, kind1, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - CU_ASSERT_EQUAL_FATAL(argx, &arg1b); - - ret = ut_handle_claim(hdl2, NULL, kind2, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - CU_ASSERT_EQUAL_FATAL(argx, &arg2); - - ret = ut_handle_claim(hdl1a, NULL, kind2, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_UNEQUAL_KIND); - - ret = ut_handle_claim(hdl1a, NULL, kind2, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_UNEQUAL_KIND); - - ret = ut_handle_claim(hdl2, NULL, kind1, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_UNEQUAL_KIND); - - ut_handle_release(hdl1a, NULL); - ut_handle_release(hdl1b, NULL); - ut_handle_release(hdl2, NULL); - - ret = ut_handle_delete(hdl1a, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - ret = ut_handle_delete(hdl1b, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - ret = ut_handle_delete(hdl2, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - ut_handleserver_fini(); -} - - -/*****************************************************************************************/ -CU_Test(util_handleserver, timeout) -{ - int32_t kind = 0x10000000; - ut_handle_retcode_t ret; - ut_handle_t hdl; - int arg = 1; - void *argx; - - ret = ut_handleserver_init(); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - hdl = ut_handle_create(kind, (void*)&arg); - CU_ASSERT_FATAL(hdl > 0); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - CU_ASSERT_EQUAL_FATAL(argx, &arg); - - ret = ut_handle_delete(hdl, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_TIMEOUT); - - ut_handle_release(hdl, NULL); - - ret = ut_handle_delete(hdl, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - ut_handleserver_fini(); -} - - -/*****************************************************************************************/ -typedef enum thread_state_t { - STARTING, - DELETING, - STOPPED -} thread_state_t; - -typedef struct thread_arg_t { - thread_state_t state; - ut_handle_t hdl; -} thread_arg_t; - -static uint32_t -deleting_thread(void *a) -{ - thread_arg_t *arg = (thread_arg_t*)a; - const dds_time_t ten = DDS_SECS(10); - ut_handle_t ret; - - arg->state = DELETING; - /* This should block until the main test released all claims. */ - ret = ut_handle_delete(arg->hdl, NULL, ten); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - arg->state = STOPPED; - - return 0; -} - -dds_retcode_t -thread_reached_state(thread_state_t *actual, thread_state_t expected, int32_t msec) -{ - /* Convenience function. */ - dds_time_t msec10 = DDS_MSECS(10); - while ((msec > 0) && (*actual != expected)) { - dds_sleepfor(msec10); - msec -= 10; - } - return (*actual == expected) ? DDS_RETCODE_OK : DDS_RETCODE_TIMEOUT; -} - -CU_Test(util_handleserver, wakeup) -{ - int32_t kind = 0x10000000; - ut_handle_retcode_t ret; - ut_handle_t hdl; - int arg = 1; - void *argx; - - ddsrt_thread_t thread_id; - thread_arg_t thread_arg; - ddsrt_threadattr_t thread_attr; - dds_retcode_t rc; - - ret = ut_handleserver_init(); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - hdl = ut_handle_create(kind, (void*)&arg); - CU_ASSERT_FATAL(hdl > 0); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - /* Try deleting in other thread, which should block. */ - thread_arg.hdl = hdl; - thread_arg.state = STARTING; - ddsrt_threadattr_init(&thread_attr); - rc = ddsrt_thread_create(&thread_id, "deleting_thread", &thread_attr, deleting_thread, (void*)&thread_arg); - CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); - rc = thread_reached_state(&thread_arg.state, DELETING, 1000); - CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); - rc = thread_reached_state(&thread_arg.state, STOPPED, 500); - CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_TIMEOUT); - - /* First release of the hdl should not unblock the thread. */ - ut_handle_release(hdl, NULL); - rc = thread_reached_state(&thread_arg.state, STOPPED, 500); - CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_TIMEOUT); - - /* Second release of the hdl should unblock the thread. */ - ut_handle_release(hdl, NULL); - rc = thread_reached_state(&thread_arg.state, STOPPED, 500); - CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); - ddsrt_thread_join(thread_id, NULL); - - /* The handle is deleted within the thread. */ - - ut_handleserver_fini(); -} - From c3dca32a2f8dc43be79745e65adcc1066d75dc36 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 7 Apr 2019 18:47:27 +0200 Subject: [PATCH 021/178] nestable calls to thread_[state_]awake Remove all the "if asleep then awake ..." stuff from the code by making awake/asleep calls nestable, whereas before it "awake ; awake" really meant a transition through "asleep". This self-evidently necessitates fixing those places where the old behaviour was relied on upon, but fortunately those are few. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_builtin.c | 5 +- src/core/ddsc/src/dds_handles.c | 35 +++-- src/core/ddsc/src/dds_init.c | 40 +++--- src/core/ddsc/src/dds_instance.c | 90 ++++--------- src/core/ddsc/src/dds_participant.c | 23 +--- src/core/ddsc/src/dds_read.c | 30 ++--- src/core/ddsc/src/dds_reader.c | 21 +-- src/core/ddsc/src/dds_topic.c | 10 +- src/core/ddsc/src/dds_write.c | 38 ++---- src/core/ddsc/src/dds_writer.c | 54 ++------ src/core/ddsi/CMakeLists.txt | 5 +- .../ddsi/include/dds/ddsi/ddsi_threadmon.h | 31 +++++ src/core/ddsi/include/dds/ddsi/q_config.h | 4 +- src/core/ddsi/include/dds/ddsi/q_globals.h | 2 +- src/core/ddsi/include/dds/ddsi/q_lease.h | 3 +- .../ddsi/include/dds/ddsi/q_servicelease.h | 31 ----- src/core/ddsi/include/dds/ddsi/q_thread.h | 104 +++++++-------- src/core/ddsi/include/dds/ddsi/q_transmit.h | 9 +- .../{q_servicelease.c => ddsi_threadmon.c} | 108 +++++----------- src/core/ddsi/src/ddsi_tkmap.c | 8 +- src/core/ddsi/src/q_config.c | 69 ++++------ src/core/ddsi/src/q_ddsi_discovery.c | 3 +- src/core/ddsi/src/q_debmon.c | 19 +-- src/core/ddsi/src/q_entity.c | 10 +- src/core/ddsi/src/q_gc.c | 24 ++-- src/core/ddsi/src/q_init.c | 19 +-- src/core/ddsi/src/q_lease.c | 2 +- src/core/ddsi/src/q_radmin.c | 9 +- src/core/ddsi/src/q_receive.c | 46 ++++--- src/core/ddsi/src/q_thread.c | 121 ++++++++++-------- src/core/ddsi/src/q_thread_inlines.c | 21 --- src/core/ddsi/src/q_transmit.c | 32 ++--- src/core/ddsi/src/q_xevent.c | 46 +++---- src/core/ddsi/src/q_xmsg.c | 2 +- src/core/ddsi/src/sysdeps.c | 12 +- src/core/xtests/rhc_torture.c | 27 ++-- 36 files changed, 450 insertions(+), 663 deletions(-) create mode 100644 src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h delete mode 100644 src/core/ddsi/include/dds/ddsi/q_servicelease.h rename src/core/ddsi/src/{q_servicelease.c => ddsi_threadmon.c} (55%) delete mode 100644 src/core/ddsi/src/q_thread_inlines.c diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index 1cdb382..3f50c60 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -65,12 +65,11 @@ void dds__builtin_init (void) void dds__builtin_fini (void) { /* No more sources for builtin topic samples */ - struct thread_state1 * const self = lookup_thread_state (); - thread_state_awake (self); + thread_state_awake (lookup_thread_state ()); delete_local_orphan_writer (builtintopic_writer_participant); delete_local_orphan_writer (builtintopic_writer_publications); delete_local_orphan_writer (builtintopic_writer_subscriptions); - thread_state_asleep (self); + thread_state_asleep (lookup_thread_state ()); ddsi_sertopic_unref (builtin_participant_topic); ddsi_sertopic_unref (builtin_reader_topic); diff --git a/src/core/ddsc/src/dds_handles.c b/src/core/ddsc/src/dds_handles.c index 5e4acd3..560e661 100644 --- a/src/core/ddsc/src/dds_handles.c +++ b/src/core/ddsc/src/dds_handles.c @@ -117,12 +117,12 @@ static dds_handle_t dds_handle_create_int (struct dds_handle_link *link) dds_handle_t dds_handle_create (struct dds_handle_link *link) { +#if USE_CHH + struct thread_state1 * const ts1 = lookup_thread_state (); +#endif dds_handle_t ret; #if USE_CHH - struct thread_state1 * const self = lookup_thread_state (); - const bool asleep = vtime_asleep_p (self->vtime); - if (asleep) - thread_state_awake (self); + thread_state_awake (ts1); #endif ddsrt_mutex_lock (&handles.lock); if (handles.count == MAX_HANDLES) @@ -143,8 +143,7 @@ dds_handle_t dds_handle_create (struct dds_handle_link *link) assert (ret > 0); } #if USE_CHH - if (asleep) - thread_state_asleep (self); + thread_state_asleep (ts1); #endif return ret; } @@ -156,8 +155,10 @@ void dds_handle_close (struct dds_handle_link *link) int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout) { +#if USE_CHH + struct thread_state1 * const ts1 = lookup_thread_state (); +#endif assert (ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_FLAG_CLOSED); - ddsrt_mutex_lock (&handles.lock); if ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_COUNT_MASK) != 0) { @@ -174,13 +175,9 @@ int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout) } } #if USE_CHH - struct thread_state1 * const self = lookup_thread_state (); - const bool asleep = vtime_asleep_p (self->vtime); - if (asleep) - thread_state_awake (self); + thread_state_awake (ts1); int x = ut_chhRemove (handles.ht, link); - if (asleep) - thread_state_asleep (self); + thread_state_asleep (ts1); #else int x = ut_hhRemove (handles.ht, link); #endif @@ -194,6 +191,9 @@ int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout) int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) { +#if USE_CHH + struct thread_state1 * const ts1 = lookup_thread_state (); +#endif struct dds_handle_link dummy = { .hdl = hdl }; int32_t rc; /* it makes sense to check here for initialization: the first thing any operation @@ -208,10 +208,7 @@ int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) return DDS_RETCODE_PRECONDITION_NOT_MET; #if USE_CHH - struct thread_state1 * const self = lookup_thread_state (); - const bool asleep = vtime_asleep_p (self->vtime); - if (asleep) - thread_state_awake (self); + thread_state_awake (ts1); *link = ut_chhLookup (handles.ht, &dummy); #else ddsrt_mutex_lock (&handles.lock); @@ -234,10 +231,8 @@ int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) } } while (!ddsrt_atomic_cas32 (&(*link)->cnt_flags, cnt_flags, cnt_flags + 1)); } - #if USE_CHH - if (asleep) - thread_state_asleep (self); + thread_state_asleep (ts1); #else ddsrt_mutex_unlock (&handles.lock); #endif diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 31a1c0a..1efd81d 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -26,7 +26,7 @@ #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_serdata.h" -#include "dds/ddsi/q_servicelease.h" +#include "dds/ddsi/ddsi_threadmon.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_gc.h" @@ -127,15 +127,15 @@ dds_init(dds_domainid_t domain) /* Start monitoring the liveliness of all threads. */ if (!config.liveliness_monitoring) - gv.servicelease = NULL; + gv.threadmon = NULL; else { - gv.servicelease = nn_servicelease_new(0, 0); - if (gv.servicelease == NULL) + gv.threadmon = ddsi_threadmon_new (); + if (gv.threadmon == NULL) { - DDS_ERROR("Failed to create a servicelease\n"); + DDS_ERROR("Failed to create a thread monitor\n"); ret = DDS_ERRNO(DDS_RETCODE_OUT_OF_RESOURCES); - goto fail_servicelease_new; + goto fail_threadmon_new; } } @@ -162,11 +162,11 @@ dds_init(dds_domainid_t domain) goto fail_rtps_start; } - if (gv.servicelease && nn_servicelease_start_renewing(gv.servicelease) < 0) + if (gv.threadmon && ddsi_threadmon_start(gv.threadmon) < 0) { DDS_ERROR("Failed to start the servicelease\n"); ret = DDS_ERRNO(DDS_RETCODE_ERROR); - goto fail_servicelease_start; + goto fail_threadmon_start; } /* Set additional default participant properties */ @@ -191,9 +191,9 @@ skip: ddsrt_mutex_unlock(init_mutex); return DDS_RETCODE_OK; -fail_servicelease_start: - if (gv.servicelease) - nn_servicelease_stop_renewing (gv.servicelease); +fail_threadmon_start: + if (gv.threadmon) + ddsi_threadmon_stop (gv.threadmon); dds_handle_server_fini(); fail_handleserver: rtps_stop (); @@ -201,12 +201,12 @@ fail_rtps_start: dds__builtin_fini (); rtps_fini (); fail_rtps_init: - if (gv.servicelease) + if (gv.threadmon) { - nn_servicelease_free (gv.servicelease); - gv.servicelease = NULL; + ddsi_threadmon_free (gv.threadmon); + gv.threadmon = NULL; } -fail_servicelease_new: +fail_threadmon_new: downgrade_main_thread (); thread_states_fini(); fail_rtps_config: @@ -231,15 +231,15 @@ extern void dds_fini (void) dds_global.m_init_count--; if (dds_global.m_init_count == 0) { - if (gv.servicelease) - nn_servicelease_stop_renewing (gv.servicelease); + if (gv.threadmon) + ddsi_threadmon_stop (gv.threadmon); dds_handle_server_fini(); rtps_stop (); dds__builtin_fini (); rtps_fini (); - if (gv.servicelease) - nn_servicelease_free (gv.servicelease); - gv.servicelease = NULL; + if (gv.threadmon) + ddsi_threadmon_free (gv.threadmon); + gv.threadmon = NULL; downgrade_main_thread (); thread_states_fini (); diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index 4ed3b20..5d15275 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -127,8 +127,7 @@ dds_register_instance( dds_instance_handle_t *handle, const void *data) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); struct ddsi_tkmap_instance * inst; dds_writer *wr; dds_return_t ret; @@ -150,9 +149,7 @@ dds_register_instance( ret = DDS_ERRNO(rc); goto err; } - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); inst = dds_instance_find (wr->m_topic, data, true); if(inst != NULL){ *handle = inst->m_iid; @@ -161,9 +158,7 @@ dds_register_instance( DDS_ERROR("Unable to create instance\n"); ret = DDS_ERRNO(DDS_RETCODE_ERROR); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); dds_writer_unlock(wr); err: return ret; @@ -191,8 +186,7 @@ dds_unregister_instance_ts( const void *data, dds_time_t timestamp) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; dds_retcode_t rc; bool autodispose = true; @@ -219,17 +213,13 @@ dds_unregister_instance_ts( if (wr->m_entity.m_qos) { dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose); } - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); if (autodispose) { dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL); action |= DDS_WR_DISPOSE_BIT; } ret = dds_write_impl (wr, data, timestamp, action); - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); dds_writer_unlock(wr); err: return ret; @@ -241,8 +231,7 @@ dds_unregister_instance_ih_ts( dds_instance_handle_t handle, dds_time_t timestamp) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; dds_retcode_t rc; bool autodispose = true; @@ -265,9 +254,7 @@ dds_unregister_instance_ih_ts( action |= DDS_WR_DISPOSE_BIT; } - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle); if (tk) { struct ddsi_sertopic *tp = wr->m_topic->m_stopic; @@ -280,9 +267,7 @@ dds_unregister_instance_ih_ts( DDS_ERROR("No instance related with the provided handle is found\n"); ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); dds_writer_unlock(wr); err: return ret; @@ -294,24 +279,19 @@ dds_writedispose_ts( const void *data, dds_time_t timestamp) { + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret; dds_retcode_t rc; dds_writer *wr; rc = dds_writer_lock(writer, &wr); if (rc == DDS_RETCODE_OK) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); ret = dds_write_impl (wr, data, timestamp, DDS_WR_ACTION_WRITE_DISPOSE); if (ret == DDS_RETCODE_OK) { dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); dds_writer_unlock(wr); } else { DDS_ERROR("Error occurred on locking writer\n"); @@ -329,7 +309,7 @@ dds_dispose_impl( dds_time_t timestamp) { dds_return_t ret; - assert(vtime_awake_p(lookup_thread_state()->vtime)); + assert(thread_is_awake ()); assert(wr); ret = dds_write_impl(wr, data, timestamp, DDS_WR_ACTION_DISPOSE); if (ret == DDS_RETCODE_OK) { @@ -344,21 +324,16 @@ dds_dispose_ts( const void *data, dds_time_t timestamp) { + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret; dds_retcode_t rc; dds_writer *wr; rc = dds_writer_lock(writer, &wr); if (rc == DDS_RETCODE_OK) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); ret = dds_dispose_impl(wr, data, DDS_HANDLE_NIL, timestamp); - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); dds_writer_unlock(wr); } else { DDS_ERROR("Error occurred on locking writer\n"); @@ -374,18 +349,15 @@ dds_dispose_ih_ts( dds_instance_handle_t handle, dds_time_t timestamp) { + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret; dds_retcode_t rc; dds_writer *wr; rc = dds_writer_lock(writer, &wr); if (rc == DDS_RETCODE_OK) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); struct ddsi_tkmap_instance *tk; - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle)) != NULL) { struct ddsi_sertopic *tp = wr->m_topic->m_stopic; void *sample = ddsi_sertopic_alloc_sample (tp); @@ -397,9 +369,7 @@ dds_dispose_ih_ts( DDS_ERROR("No instance related with the provided handle is found\n"); ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); dds_writer_unlock(wr); } else { DDS_ERROR("Error occurred on locking writer\n"); @@ -414,6 +384,7 @@ dds_lookup_instance( dds_entity_t entity, const void *data) { + struct thread_state1 * const ts1 = lookup_thread_state (); dds_instance_handle_t ih = DDS_HANDLE_NIL; const dds_topic * topic; struct ddsi_tkmap * map = gv.m_tkmap; @@ -426,17 +397,11 @@ dds_lookup_instance( topic = dds_instance_info_by_hdl (entity); if (topic) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data); ih = ddsi_tkmap_lookup (map, sd); ddsi_serdata_unref (sd); - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); } else { DDS_ERROR("Acquired topic is NULL\n"); } @@ -458,8 +423,7 @@ dds_instance_get_key( dds_instance_handle_t ih, void *data) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret; const dds_topic * topic; struct ddsi_tkmap_instance * tk; @@ -476,9 +440,7 @@ dds_instance_get_key( ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); if ((tk = ddsi_tkmap_find_by_id(gv.m_tkmap, ih)) != NULL) { ddsi_sertopic_zero_sample (topic->m_stopic, data); ddsi_serdata_topicless_to_sample (topic->m_stopic, tk->m_sample, data, NULL, NULL); @@ -488,9 +450,7 @@ dds_instance_get_key( DDS_ERROR("No instance related with the provided entity is found\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); err: return ret; } diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 35521c0..587951a 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -48,18 +48,13 @@ static dds_return_t dds_participant_delete( dds_entity *e) { - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); dds_entity *prev = NULL; dds_entity *iter; assert(e); - assert(thr); assert(dds_entity_kind(e) == DDS_KIND_PARTICIPANT); - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (lookup_thread_state ()); dds_domain_free (e->m_domain); @@ -81,9 +76,7 @@ dds_participant_delete( assert (iter); - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (lookup_thread_state ()); /* Every dds_init needs a dds_fini. */ dds_fini(); @@ -155,8 +148,6 @@ dds_create_participant( dds_participant * pp; nn_plist_t plist; dds_qos_t * new_qos = NULL; - struct thread_state1 * thr; - bool asleep; /* Make sure DDS instance is initialized. */ ret = dds_init(domain); @@ -192,15 +183,9 @@ dds_create_participant( nn_plist_init_empty(&plist); dds_merge_qos (&plist.qos, new_qos); - thr = lookup_thread_state (); - asleep = !vtime_awake_p (thr->vtime); - if (asleep) { - thread_state_awake (thr); - } + thread_state_awake (lookup_thread_state ()); q_rc = new_participant (&guid, 0, &plist); - if (asleep) { - thread_state_asleep (thr); - } + thread_state_asleep (lookup_thread_state ()); nn_plist_fini (&plist); if (q_rc != 0) { DDS_ERROR("Internal error"); diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index af239f6..b4c5adf 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -88,16 +88,12 @@ dds_read_impl( bool lock, bool only_reader) { + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; dds_retcode_t rc; struct dds_reader * rd; struct dds_readcond * cond; - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); - if (asleep) { - thread_state_awake (thr); - } if (buf == NULL) { DDS_ERROR("The provided buffer is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); @@ -124,18 +120,19 @@ dds_read_impl( goto fail; } + thread_state_awake (ts1); rc = dds_read_lock(reader_or_condition, &rd, &cond, only_reader); if (rc != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking entity\n"); ret = DDS_ERRNO(rc); - goto fail; + goto fail_awake; } if (hand != DDS_HANDLE_NIL) { if (ddsi_tkmap_find_by_id(gv.m_tkmap, hand) == NULL) { DDS_ERROR("Could not find instance\n"); ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); dds_read_unlock(rd, cond); - goto fail; + goto fail_awake; } } /* Allocate samples if not provided (assuming all or none provided) */ @@ -173,10 +170,9 @@ dds_read_impl( } dds_read_unlock(rd, cond); +fail_awake: + thread_state_asleep (ts1); fail: - if (asleep) { - thread_state_asleep (thr); - } return ret; } @@ -191,12 +187,11 @@ dds_readcdr_impl( dds_instance_handle_t hand, bool lock) { + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; dds_retcode_t rc; struct dds_reader * rd; struct dds_readcond * cond; - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); assert (take); assert (buf); @@ -205,10 +200,7 @@ dds_readcdr_impl( assert (maxs > 0); (void)take; - if (asleep) - { - thread_state_awake (thr); - } + thread_state_awake (ts1); rc = dds_read_lock(reader_or_condition, &rd, &cond, false); if (rc >= DDS_RETCODE_OK) { ret = dds_rhc_takecdr @@ -235,11 +227,7 @@ dds_readcdr_impl( ret = DDS_ERRNO(rc); } - if (asleep) - { - thread_state_asleep (thr); - } - + thread_state_asleep (ts1); return ret; } diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index bd16e39..2c14994 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -54,23 +54,16 @@ dds_reader_close( { dds_retcode_t rc; dds_return_t ret = DDS_RETCODE_OK; - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); assert(e); - assert(thr); - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (lookup_thread_state ()); if (delete_reader(&e->m_guid) != 0) { DDS_ERROR("Internal error"); rc = DDS_RETCODE_ERROR; ret = DDS_ERRNO(rc); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (lookup_thread_state ()); return ret; } @@ -368,8 +361,6 @@ dds_create_reader( dds_topic * tp; dds_entity_t reader; dds_entity_t t; - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); dds_return_t ret = DDS_RETCODE_OK; bool internal_topic; @@ -474,17 +465,13 @@ dds_create_reader( ddsrt_mutex_unlock(&tp->m_entity.m_mutex); ddsrt_mutex_unlock(&sub->m_entity.m_mutex); - if (asleep) { - thread_state_awake (thr); - } + thread_state_awake (lookup_thread_state ()); rd->m_rd = new_reader(&rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, rqos, rhc, dds_reader_status_cb, rd); ddsrt_mutex_lock(&sub->m_entity.m_mutex); ddsrt_mutex_lock(&tp->m_entity.m_mutex); assert (rd->m_rd); - if (asleep) { - thread_state_asleep (thr); - } + thread_state_asleep (lookup_thread_state ()); /* For persistent data register reader with durability */ if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > NN_TRANSIENT_LOCAL_DURABILITY_QOS)) { diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index acd36ac..1561afd 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -313,8 +313,6 @@ dds_create_topic_arbitrary ( dds_qos_t *new_qos = NULL; dds_entity_t hdl; struct participant *ddsi_pp; - struct thread_state1 *const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); if (sertopic == NULL){ DDS_ERROR("Topic description is NULL\n"); @@ -389,17 +387,13 @@ dds_create_topic_arbitrary ( ddsrt_mutex_unlock (&dds_global.m_mutex); /* Publish Topic */ - if (asleep) { - thread_state_awake (thr); - } + thread_state_awake (lookup_thread_state ()); ddsi_pp = ephash_lookup_participant_guid (&par->m_guid); assert (ddsi_pp); if (sedp_plist) { sedp_write_topic (ddsi_pp, sedp_plist); } - if (asleep) { - thread_state_asleep (thr); - } + thread_state_asleep (lookup_thread_state ()); } qos_err: diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 3f3bb5e..3c1526c 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -148,8 +148,7 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstamp, dds_write_action action) { - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); const bool writekey = action & DDS_WR_KEY_BIT; struct writer *ddsi_wr = wr->m_wr; struct ddsi_tkmap_instance *tk; @@ -168,8 +167,7 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam if (!(wr->m_topic->filter_fn) (data, wr->m_topic->filter_ctx)) return DDS_RETCODE_OK; - if (asleep) - thread_state_awake (thr); + thread_state_awake (ts1); /* Serialize and write data or key */ d = ddsi_serdata_from_sample (ddsi_wr->topic, writekey ? SDK_KEY : SDK_DATA, data); @@ -177,7 +175,7 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam d->timestamp.v = tstamp; ddsi_serdata_ref (d); tk = ddsi_tkmap_lookup_instance_ref (d); - w_rc = write_sample_gc (wr->m_xp, ddsi_wr, d, tk); + w_rc = write_sample_gc (ts1, wr->m_xp, ddsi_wr, d, tk); if (w_rc >= 0) { @@ -199,26 +197,21 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam ret = deliver_locally (ddsi_wr, d, tk); ddsi_serdata_unref (d); ddsi_tkmap_instance_unref (tk); - - if (asleep) - thread_state_asleep (thr); + thread_state_asleep (ts1); return ret; } dds_return_t dds_writecdr_impl_lowlevel (struct writer *ddsi_wr, struct nn_xpack *xp, struct ddsi_serdata *d) { - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); struct ddsi_tkmap_instance * tk; int ret = DDS_RETCODE_OK; int w_rc; - if (asleep) - thread_state_awake (thr); - + thread_state_awake (ts1); ddsi_serdata_ref (d); tk = ddsi_tkmap_lookup_instance_ref (d); - w_rc = write_sample_gc (xp, ddsi_wr, d, tk); + w_rc = write_sample_gc (ts1, xp, ddsi_wr, d, tk); if (w_rc >= 0) { /* Flush out write unless configured to batch */ if (!config.whc_batch && xp != NULL) @@ -239,10 +232,7 @@ dds_return_t dds_writecdr_impl_lowlevel (struct writer *ddsi_wr, struct nn_xpack ret = deliver_locally (ddsi_wr, d, tk); ddsi_serdata_unref (d); ddsi_tkmap_instance_unref (tk); - - if (asleep) - thread_state_asleep (thr); - + thread_state_asleep (ts1); return ret; } @@ -263,13 +253,10 @@ void dds_write_set_batch (bool enable) void dds_write_flush (dds_entity_t writer) { - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); dds_writer *wr; dds_retcode_t rc; - - if (asleep) - thread_state_awake (thr); + thread_state_awake (ts1); if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) DDS_ERROR ("Error occurred on locking writer\n"); else @@ -277,8 +264,5 @@ void dds_write_flush (dds_entity_t writer) nn_xpack_send (wr->m_xp, true); dds_writer_unlock (wr); } - - if (asleep) - thread_state_asleep (thr); - return; + thread_state_asleep (ts1); } diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index f804fe1..06a13ef 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -192,24 +192,16 @@ dds_writer_close( { dds_return_t ret = DDS_RETCODE_OK; dds_writer *wr = (dds_writer*)e; - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = thr ? !vtime_awake_p(thr->vtime) : false; assert(e); - if (asleep) { - thread_state_awake(thr); - } - if (thr) { - nn_xpack_send (wr->m_xp, false); - } + thread_state_awake (lookup_thread_state ()); + nn_xpack_send (wr->m_xp, false); if (delete_writer (&e->m_guid) != 0) { DDS_ERROR("Internal error"); ret = DDS_ERRNO(DDS_RETCODE_ERROR); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (lookup_thread_state ()); return ret; } @@ -218,24 +210,11 @@ dds_writer_delete( dds_entity *e) { dds_writer *wr = (dds_writer*)e; - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = thr ? !vtime_awake_p(thr->vtime) : false; dds_return_t ret; - - assert(e); - assert(thr); - /* FIXME: not freeing WHC here because it is owned by the DDSI entity */ - - if (asleep) { - thread_state_awake(thr); - } - if (thr) { - nn_xpack_free(wr->m_xp); - } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_awake (lookup_thread_state ()); + nn_xpack_free(wr->m_xp); + thread_state_asleep (lookup_thread_state ()); ret = dds_delete(wr->m_topic->m_entity.m_hdllink.hdl); if(ret == DDS_RETCODE_OK){ ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true); @@ -304,15 +283,11 @@ dds_writer_qos_set( dds_qget_ownership (e->m_qos, &kind); if (kind == DDS_OWNERSHIP_EXCLUSIVE) { - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); struct writer * ddsi_wr = ((dds_writer*)e)->m_wr; dds_qset_ownership_strength (e->m_qos, qos->ownership_strength.value); - if (asleep) { - thread_state_awake (thr); - } + thread_state_awake (lookup_thread_state ()); /* FIXME: with QoS changes being unsupported by the underlying stack I wonder what will happen; locking the underlying DDSI writer is of doubtful value as well */ ddsrt_mutex_lock (&ddsi_wr->e.lock); @@ -320,10 +295,7 @@ dds_writer_qos_set( ddsi_wr->xqos->ownership_strength.value = qos->ownership_strength.value; } ddsrt_mutex_unlock (&ddsi_wr->e.lock); - - if (asleep) { - thread_state_asleep (thr); - } + thread_state_asleep (lookup_thread_state ()); } else { DDS_ERROR("Setting ownership strength doesn't make sense when the ownership is shared\n"); ret = DDS_ERRNO(DDS_RETCODE_ERROR); @@ -403,8 +375,6 @@ dds_create_writer( dds_publisher * pub = NULL; dds_topic * tp; dds_entity_t publisher; - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); ddsi_tran_conn_t conn = gv.data_conn_uc; dds_return_t ret; @@ -485,16 +455,12 @@ dds_create_writer( ddsrt_mutex_unlock (&tp->m_entity.m_mutex); ddsrt_mutex_unlock (&pub->m_entity.m_mutex); - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (lookup_thread_state ()); wr->m_wr = new_writer(&wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); ddsrt_mutex_lock (&pub->m_entity.m_mutex); ddsrt_mutex_lock (&tp->m_entity.m_mutex); assert(wr->m_wr); - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (lookup_thread_state ()); dds_topic_unlock(tp); dds_publisher_unlock(pub); return writer; diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 683ad6e..4a6bb0f 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -26,6 +26,7 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" ddsi_iid.c ddsi_tkmap.c ddsi_vendor.c + ddsi_threadmon.c q_addrset.c q_bitset_inlines.c q_bswap.c @@ -47,10 +48,8 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" q_radmin.c q_receive.c q_security.c - q_servicelease.c q_sockwaitset.c q_thread.c - q_thread_inlines.c q_time.c q_transmit.c q_inverse_uint32_set.c @@ -78,6 +77,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" ddsi_iid.h ddsi_tkmap.h ddsi_vendor.h + ddsi_threadmon.h q_addrset.h q_bitset.h q_bswap.h @@ -105,7 +105,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" q_receive.h q_rtps.h q_security.h - q_servicelease.h q_sockwaitset.h q_static_assert.h q_thread.h diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h b/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h new file mode 100644 index 0000000..7d9d346 --- /dev/null +++ b/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h @@ -0,0 +1,31 @@ +/* + * 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_THREADMON_H +#define DDSI_THREADMON_H + +#if defined (__cplusplus) +extern "C" { +#endif + +struct ddsi_threadmon; + +struct ddsi_threadmon *ddsi_threadmon_new (void); +int ddsi_threadmon_start (struct ddsi_threadmon *sl); +void ddsi_threadmon_stop (struct ddsi_threadmon *sl); +void ddsi_threadmon_free (struct ddsi_threadmon *sl); +void ddsi_threadmon_statechange_barrier (struct ddsi_threadmon *sl); + +#if defined (__cplusplus) +} +#endif + +#endif /* DDSI_THREADMON_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index c37a40e..c313682 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -267,6 +267,7 @@ struct config int forward_all_messages; int liveliness_monitoring; int noprogress_log_stacktraces; + int64_t liveliness_monitoring_interval; int prioritize_retransmit; int xpack_send_async; int multiple_recv_threads; @@ -277,9 +278,6 @@ struct config unsigned delivery_queue_maxsamples; - float servicelease_expiry_time; - float servicelease_update_factor; - int enableLoopback; enum durability_cdr durability_cdr; diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/q_globals.h index 177793c..770c569 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/q_globals.h @@ -105,7 +105,7 @@ struct q_globals { /* Queue for garbage collection requests */ struct gcreq_queue *gcreq_queue; - struct nn_servicelease *servicelease; + struct ddsi_threadmon *threadmon; /* Lease junk */ ddsrt_mutex_t leaseheap_lock; diff --git a/src/core/ddsi/include/dds/ddsi/q_lease.h b/src/core/ddsi/include/dds/ddsi/q_lease.h index 2a24abe..a139075 100644 --- a/src/core/ddsi/include/dds/ddsi/q_lease.h +++ b/src/core/ddsi/include/dds/ddsi/q_lease.h @@ -22,7 +22,6 @@ struct receiver_state; struct participant; struct lease; struct entity_common; -struct thread_state1; void lease_management_init (void); void lease_management_term (void); @@ -31,7 +30,7 @@ void lease_register (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 thread_state1 *self, nn_etime_t tnow); +int64_t check_and_handle_lease_expiration (nn_etime_t tnow); void handle_PMD (const struct receiver_state *rst, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len); diff --git a/src/core/ddsi/include/dds/ddsi/q_servicelease.h b/src/core/ddsi/include/dds/ddsi/q_servicelease.h deleted file mode 100644 index bc9c15d..0000000 --- a/src/core/ddsi/include/dds/ddsi/q_servicelease.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef NN_SERVICELEASE_H -#define NN_SERVICELEASE_H - -#if defined (__cplusplus) -extern "C" { -#endif - -struct nn_servicelease; - -struct nn_servicelease *nn_servicelease_new (void (*renew_cb) (void *arg), void *renew_arg); -int nn_servicelease_start_renewing (struct nn_servicelease *sl); -void nn_servicelease_stop_renewing (struct nn_servicelease *sl); -void nn_servicelease_free (struct nn_servicelease *sl); -void nn_servicelease_statechange_barrier (struct nn_servicelease *sl); - -#if defined (__cplusplus) -} -#endif - -#endif /* NN_SERVICELEASE_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_thread.h b/src/core/ddsi/include/dds/ddsi/q_thread.h index fef01ea..71c9e5e 100644 --- a/src/core/ddsi/include/dds/ddsi/q_thread.h +++ b/src/core/ddsi/include/dds/ddsi/q_thread.h @@ -12,6 +12,7 @@ #ifndef Q_THREAD_H #define Q_THREAD_H +#include #include "dds/export.h" #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/sync.h" @@ -30,6 +31,9 @@ extern "C" { typedef uint32_t vtime_t; typedef int32_t svtime_t; /* signed version */ +#define VTIME_NEST_MASK 0xfu +#define VTIME_TIME_MASK 0xfffffff0u +#define VTIME_TIME_SHIFT 4 /* GCC has a nifty feature allowing the specification of the required alignment: __attribute__ ((aligned (CACHE_LINE_SIZE))) in this @@ -59,7 +63,6 @@ struct logbuf; */ #define THREAD_BASE \ volatile vtime_t vtime; \ - volatile vtime_t watchdog; \ ddsrt_thread_t tid; \ ddsrt_thread_t extTid; \ enum thread_state state; \ @@ -94,8 +97,7 @@ DDS_EXPORT void thread_states_fini (void); DDS_EXPORT void upgrade_main_thread (void); DDS_EXPORT void downgrade_main_thread (void); DDS_EXPORT const struct config_thread_properties_listelem *lookup_thread_properties (const char *name); -DDS_EXPORT struct thread_state1 *create_thread (const char *name, uint32_t (*f) (void *arg), void *arg); -DDS_EXPORT struct thread_state1 *lookup_thread_state (void); +DDS_EXPORT dds_retcode_t create_thread (struct thread_state1 **ts, const char *name, uint32_t (*f) (void *arg), void *arg); DDS_EXPORT struct thread_state1 *lookup_thread_state_real (void); DDS_EXPORT int join_thread (struct thread_state1 *ts1); DDS_EXPORT void log_stack_traces (void); @@ -104,83 +106,69 @@ DDS_EXPORT struct thread_state1 * init_thread_state (const char *tname); DDS_EXPORT void reset_thread_state (struct thread_state1 *ts1); DDS_EXPORT int thread_exists (const char *name); -DDS_EXPORT inline int vtime_awake_p (vtime_t vtime) -{ - return (vtime % 2) == 0; +DDS_EXPORT inline struct thread_state1 *lookup_thread_state (void) { + struct thread_state1 *ts1 = tsd_thread_state; + if (ts1) + return ts1; + else + return lookup_thread_state_real (); } -DDS_EXPORT inline int vtime_asleep_p (vtime_t vtime) +DDS_EXPORT inline bool vtime_awake_p (vtime_t vtime) { - return (vtime % 2) == 1; + return (vtime & VTIME_NEST_MASK) != 0; } -DDS_EXPORT inline int vtime_gt (vtime_t vtime1, vtime_t vtime0) +DDS_EXPORT inline bool vtime_asleep_p (vtime_t vtime) +{ + return (vtime & VTIME_NEST_MASK) == 0; +} + +DDS_EXPORT inline bool vtime_gt (vtime_t vtime1, vtime_t vtime0) { Q_STATIC_ASSERT_CODE (sizeof (vtime_t) == sizeof (svtime_t)); - return (svtime_t) (vtime1 - vtime0) > 0; + return (svtime_t) ((vtime1 & VTIME_TIME_MASK) - (vtime0 & VTIME_TIME_MASK)) > 0; +} + +DDS_EXPORT inline bool thread_is_awake (void) +{ + return vtime_awake_p (lookup_thread_state ()->vtime); +} + +DDS_EXPORT inline bool thread_is_asleep (void) +{ + return vtime_asleep_p (lookup_thread_state ()->vtime); } DDS_EXPORT inline void thread_state_asleep (struct thread_state1 *ts1) { vtime_t vt = ts1->vtime; - vtime_t wd = ts1->watchdog; - if (vtime_awake_p (vt)) - { - ddsrt_atomic_fence_rel (); - ts1->vtime = vt + 1; - } + assert (vtime_awake_p (vt)); + /* nested calls a rare and an extra fence doesn't break things */ + ddsrt_atomic_fence_rel (); + if ((vt & VTIME_NEST_MASK) == 1) + vt += (1u << VTIME_TIME_SHIFT) - 1u; else - { - ddsrt_atomic_fence_rel (); - ts1->vtime = vt + 2; - ddsrt_atomic_fence_acq (); - } - - if ( wd % 2 ){ - ts1->watchdog = wd + 2; - } else { - ts1->watchdog = wd + 1; - } + vt -= 1u; + ts1->vtime = vt; } DDS_EXPORT inline void thread_state_awake (struct thread_state1 *ts1) { vtime_t vt = ts1->vtime; - vtime_t wd = ts1->watchdog; - if (vtime_asleep_p (vt)) - ts1->vtime = vt + 1; - else - { - ddsrt_atomic_fence_rel (); - ts1->vtime = vt + 2; - } + assert ((vt & VTIME_NEST_MASK) < VTIME_NEST_MASK); + ts1->vtime = vt + 1u; + /* nested calls a rare and an extra fence doesn't break things */ ddsrt_atomic_fence_acq (); - - if ( wd % 2 ){ - ts1->watchdog = wd + 1; - } else { - ts1->watchdog = wd + 2; - } } -DDS_EXPORT inline void thread_state_blocked (struct thread_state1 *ts1) +DDS_EXPORT inline void thread_state_awake_to_awake_no_nest (struct thread_state1 *ts1) { - vtime_t wd = ts1->watchdog; - if ( wd % 2 ){ - ts1->watchdog = wd + 2; - } else { - ts1->watchdog = wd + 1; - } -} - -DDS_EXPORT inline void thread_state_unblocked (struct thread_state1 *ts1) -{ - vtime_t wd = ts1->watchdog; - if ( wd % 2 ){ - ts1->watchdog = wd + 1; - } else { - ts1->watchdog = wd + 2; - } + vtime_t vt = ts1->vtime; + assert ((vt & VTIME_NEST_MASK) == 1); + ddsrt_atomic_fence_rel (); + ts1->vtime = vt + (1u << VTIME_TIME_SHIFT); + ddsrt_atomic_fence_acq (); } #if defined (__cplusplus) diff --git a/src/core/ddsi/include/dds/ddsi/q_transmit.h b/src/core/ddsi/include/dds/ddsi/q_transmit.h index 14330a2..19cc947 100644 --- a/src/core/ddsi/include/dds/ddsi/q_transmit.h +++ b/src/core/ddsi/include/dds/ddsi/q_transmit.h @@ -25,6 +25,7 @@ struct whc_state; struct proxy_reader; struct ddsi_serdata; struct ddsi_tkmap_instance; +struct thread_state1; /* Writing new data; serdata_twrite (serdata) is assumed to be really recentish; serdata is unref'd. If xp == NULL, data is queued, else @@ -33,10 +34,10 @@ struct ddsi_tkmap_instance; "nogc": no GC may occur, so it may not block to throttle the writer if the high water mark of the WHC is reached, which implies true KEEP_LAST behaviour. This is true for all the DDSI built-in writers. "gc": GC may occur, which means the writer history and watermarks can be anything. This must be used for all application data. */ -int write_sample_gc (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); -int write_sample_nogc (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); -int write_sample_gc_notk (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata); -int write_sample_nogc_notk (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata); +int write_sample_gc (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); +int write_sample_nogc (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); +int write_sample_gc_notk (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata); +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 */ int 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); diff --git a/src/core/ddsi/src/q_servicelease.c b/src/core/ddsi/src/ddsi_threadmon.c similarity index 55% rename from src/core/ddsi/src/q_servicelease.c rename to src/core/ddsi/src/ddsi_threadmon.c index 2ab892a..755848c 100644 --- a/src/core/ddsi/src/q_servicelease.c +++ b/src/core/ddsi/src/ddsi_threadmon.c @@ -15,7 +15,7 @@ #include "dds/ddsrt/sync.h" #include "dds/ddsrt/threads.h" -#include "dds/ddsi/q_servicelease.h" +#include "dds/ddsi/ddsi_threadmon.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_thread.h" @@ -25,32 +25,14 @@ #include "dds/ddsi/q_globals.h" /* for mattr, cattr */ #include "dds/ddsi/q_receive.h" -static dds_time_t nn_retrieve_lease_settings (void) -{ - const double leaseSec = config.servicelease_expiry_time; - double sleepSec = leaseSec * config.servicelease_update_factor; - - /* Run at no less than 1Hz: internal liveliness monitoring is slaved - to this interval as well. 1Hz lease renewals and liveliness - checks is no large burden, and performing liveliness checks once - a second is a lot more useful than doing it once every few - seconds. Besides -- we're now also gathering CPU statistics. */ - if (sleepSec > 1.0f) - return DDS_NSECS_IN_SEC; - - return ((dds_time_t)(sleepSec * DDS_NSECS_IN_SEC)) + - ((dds_time_t)(sleepSec * (double)DDS_NSECS_IN_SEC) % DDS_NSECS_IN_SEC); -} - -struct alive_wd { - char alive; - vtime_t wd; +struct alive_vt { + bool alive; + vtime_t vt; }; -struct nn_servicelease { - dds_time_t sleepTime; +struct ddsi_threadmon { int keepgoing; - struct alive_wd *av_ary; + struct alive_vt *av_ary; void (*renew_cb) (void *arg); void *renew_arg; @@ -59,37 +41,38 @@ struct nn_servicelease { struct thread_state1 *ts; }; -static uint32_t lease_renewal_thread (struct nn_servicelease *sl) +static uint32_t threadmon_thread (struct ddsi_threadmon *sl) { /* Do not check more often than once every 100ms (no particular reason why it has to be 100ms), regardless of the lease settings. Note: can't trust sl->self, may have been scheduled before the assignment. */ - const int64_t min_progress_check_intv = 100 * T_MILLISECOND; - struct thread_state1 *self = lookup_thread_state (); nn_mtime_t next_thread_cputime = { 0 }; nn_mtime_t tlast = { 0 }; - int was_alive = 1; + bool was_alive = true; unsigned i; for (i = 0; i < thread_states.nthreads; i++) { - sl->av_ary[i].alive = 1; - sl->av_ary[i].wd = thread_states.ts[i].watchdog - 1; + sl->av_ary[i].alive = true; } ddsrt_mutex_lock (&sl->lock); while (sl->keepgoing) { + /* Guard against spurious wakeups by checking only when cond_waitfor signals a timeout */ + if (ddsrt_cond_waitfor (&sl->cond, &sl->lock, config.liveliness_monitoring_interval)) + continue; + unsigned n_alive = 0; nn_mtime_t tnow = now_mt (); LOG_THREAD_CPUTIME (next_thread_cputime); - DDS_TRACE("servicelease: tnow %"PRId64":", tnow.v); + DDS_TRACE("threadmon: tnow %"PRId64":", tnow.v); /* Check progress only if enough time has passed: there is no guarantee that os_cond_timedwait wont ever return early, and we do want to avoid spurious warnings. */ - if (tnow.v < tlast.v + min_progress_check_intv) + if (tnow.v < tlast.v) { n_alive = thread_states.nthreads; } @@ -103,11 +86,10 @@ static uint32_t lease_renewal_thread (struct nn_servicelease *sl) else { vtime_t vt = thread_states.ts[i].vtime; - vtime_t wd = thread_states.ts[i].watchdog; - int alive = vtime_asleep_p (vt) || vtime_asleep_p (wd) || vtime_gt (wd, sl->av_ary[i].wd); + bool alive = vtime_asleep_p (vt) || vtime_asleep_p (sl->av_ary[i].vt) || vtime_gt (vt, sl->av_ary[i].vt); n_alive += (unsigned) alive; - DDS_TRACE(" %u(%s):%c:%u:%u->%u:", i, thread_states.ts[i].name, alive ? 'a' : 'd', vt, sl->av_ary[i].wd, wd); - sl->av_ary[i].wd = wd; + DDS_TRACE(" %u(%s):%c:%x->%x", i, thread_states.ts[i].name, alive ? 'a' : 'd', sl->av_ary[i].vt, vt); + sl->av_ary[i].vt = vt; if (sl->av_ary[i].alive != alive) { const char *name = thread_states.ts[i].name; @@ -117,31 +99,23 @@ static uint32_t lease_renewal_thread (struct nn_servicelease *sl) else msg = "once again made progress"; DDS_INFO("thread %s %s\n", name ? name : "(anon)", msg); - sl->av_ary[i].alive = (char) alive; + sl->av_ary[i].alive = alive; } } } } - /* Only renew the lease if all threads are alive, so that one - thread blocking for a while but not too extremely long will - cause warnings for that thread in the log file, but won't cause - the DDSI2 service to be marked as dead. */ if (n_alive == thread_states.nthreads) { - DDS_TRACE(": [%u] renewing\n", n_alive); - /* FIXME: perhaps it would be nice to control automatic - liveliness updates from here. - FIXME: should terminate failure of renew_cb() */ - sl->renew_cb (sl->renew_arg); - was_alive = 1; + DDS_TRACE(": [%u] OK\n", n_alive); + was_alive = true; } else { - DDS_TRACE(": [%u] NOT renewing\n", n_alive); + DDS_TRACE(": [%u] FAIL\n", n_alive); if (was_alive) log_stack_traces (); - was_alive = 0; + was_alive = false; } if (dds_get_log_mask() & DDS_LC_TIMING) @@ -151,20 +125,14 @@ static uint32_t lease_renewal_thread (struct nn_servicelease *sl) { DDS_LOG(DDS_LC_TIMING, "rusage: utime %d.%09d stime %d.%09d maxrss %ld data %ld vcsw %ld ivcsw %ld\n", - (int) u.utime / DDS_NSECS_IN_SEC, - (int) u.utime % DDS_NSECS_IN_SEC, - (int) u.stime / DDS_NSECS_IN_SEC, - (int) u.stime % DDS_NSECS_IN_SEC, + (int) (u.utime / DDS_NSECS_IN_SEC), + (int) (u.utime % DDS_NSECS_IN_SEC), + (int) (u.stime / DDS_NSECS_IN_SEC), + (int) (u.stime % DDS_NSECS_IN_SEC), u.maxrss, u.idrss, u.nvcsw, u.nivcsw); } } - ddsrt_cond_waitfor (&sl->cond, &sl->lock, sl->sleepTime); - - /* We are never active in a way that matters for the garbage - collection of old writers, &c. */ - thread_state_asleep (self); - /* While deaf, we need to make sure the receive thread wakes up every now and then to try recreating sockets & rejoining multicast groups */ @@ -175,19 +143,12 @@ static uint32_t lease_renewal_thread (struct nn_servicelease *sl) return 0; } -static void dummy_renew_cb (UNUSED_ARG (void *arg)) +struct ddsi_threadmon *ddsi_threadmon_new (void) { -} - -struct nn_servicelease *nn_servicelease_new (void (*renew_cb) (void *arg), void *renew_arg) -{ - struct nn_servicelease *sl; + struct ddsi_threadmon *sl; sl = ddsrt_malloc (sizeof (*sl)); - sl->sleepTime = nn_retrieve_lease_settings (); sl->keepgoing = -1; - sl->renew_cb = renew_cb ? renew_cb : dummy_renew_cb; - sl->renew_arg = renew_arg; sl->ts = NULL; if ((sl->av_ary = ddsrt_malloc (thread_states.nthreads * sizeof (*sl->av_ary))) == NULL) @@ -203,15 +164,14 @@ struct nn_servicelease *nn_servicelease_new (void (*renew_cb) (void *arg), void return NULL; } -int nn_servicelease_start_renewing (struct nn_servicelease *sl) +int ddsi_threadmon_start (struct ddsi_threadmon *sl) { ddsrt_mutex_lock (&sl->lock); assert (sl->keepgoing == -1); sl->keepgoing = 1; ddsrt_mutex_unlock (&sl->lock); - sl->ts = create_thread ("lease", (uint32_t (*) (void *)) lease_renewal_thread, sl); - if (sl->ts == NULL) + if (create_thread (&sl->ts, "lease", (uint32_t (*) (void *)) threadmon_thread, sl) != DDS_RETCODE_OK) goto fail_thread; return 0; @@ -220,13 +180,13 @@ int nn_servicelease_start_renewing (struct nn_servicelease *sl) return Q_ERR_UNSPECIFIED; } -void nn_servicelease_statechange_barrier (struct nn_servicelease *sl) +void ddsi_threadmon_statechange_barrier (struct ddsi_threadmon *sl) { ddsrt_mutex_lock (&sl->lock); ddsrt_mutex_unlock (&sl->lock); } -void nn_servicelease_stop_renewing (struct nn_servicelease *sl) +void ddsi_threadmon_stop (struct ddsi_threadmon *sl) { if (sl->keepgoing != -1) { @@ -238,7 +198,7 @@ void nn_servicelease_stop_renewing (struct nn_servicelease *sl) } } -void nn_servicelease_free (struct nn_servicelease *sl) +void ddsi_threadmon_free (struct ddsi_threadmon *sl) { ddsrt_cond_destroy (&sl->cond); ddsrt_mutex_destroy (&sl->lock); diff --git a/src/core/ddsi/src/ddsi_tkmap.c b/src/core/ddsi/src/ddsi_tkmap.c index 0d1c6bd..b688e09 100644 --- a/src/core/ddsi/src/ddsi_tkmap.c +++ b/src/core/ddsi/src/ddsi_tkmap.c @@ -113,7 +113,7 @@ uint64_t ddsi_tkmap_lookup (struct ddsi_tkmap * map, const struct ddsi_serdata * { struct ddsi_tkmap_instance dummy; struct ddsi_tkmap_instance * tk; - assert (vtime_awake_p(lookup_thread_state()->vtime)); + assert (thread_is_awake ()); dummy.m_sample = (struct ddsi_serdata *) sd; tk = ut_chhLookup (map->m_hh, &dummy); return (tk) ? tk->m_iid : DDS_HANDLE_NIL; @@ -125,7 +125,7 @@ struct ddsi_tkmap_instance *ddsi_tkmap_find_by_id (struct ddsi_tkmap *map, uint6 struct ut_chhIter it; struct ddsi_tkmap_instance *tk; uint32_t refc; - assert (vtime_awake_p(lookup_thread_state()->vtime)); + assert (thread_is_awake ()); for (tk = ut_chhIterFirst (map->m_hh, &it); tk; tk = ut_chhIterNext (&it)) if (tk->m_iid == iid) break; @@ -162,7 +162,7 @@ ddsi_tkmap_find( struct ddsi_tkmap_instance * tk; struct ddsi_tkmap * map = gv.m_tkmap; - assert (vtime_awake_p(lookup_thread_state()->vtime)); + assert (thread_is_awake ()); dummy.m_sample = sd; retry: if ((tk = ut_chhLookup(map->m_hh, &dummy)) != NULL) @@ -221,7 +221,7 @@ void ddsi_tkmap_instance_ref (struct ddsi_tkmap_instance *tk) void ddsi_tkmap_instance_unref (struct ddsi_tkmap_instance * tk) { uint32_t old, new; - assert (vtime_awake_p(lookup_thread_state()->vtime)); + assert (thread_is_awake ()); do { old = ddsrt_atomic_ld32(&tk->m_refc); if (old == 1) diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 07ddc4b..b613df8 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -141,7 +141,6 @@ DU(tracingOutputFileName); DU(verbosity); DUPF(logcat); DUPF(xcheck); -DUPF(float); DUPF(int); DUPF(uint); DUPF(int32); @@ -158,6 +157,7 @@ DU(duration_inf); DU(duration_ms_1hr); DU(duration_ms_1s); DU(duration_us_1s); +DU(duration_100ms_1hr); PF(duration); DUPF(standards_conformance); DUPF(besmode); @@ -516,6 +516,8 @@ static const struct cfgelem heartbeat_interval_attrs[] = { static const struct cfgelem liveliness_monitoring_attrs[] = { { ATTR("StackTraces"), 1, "true", ABSOFF(noprogress_log_stacktraces), 0, uf_boolean, 0, pf_boolean, "

This element controls whether or not to write stack traces to the DDSI2 trace when a thread fails to make progress (on select platforms only).

" }, + { ATTR("Interval"), 1, "1s", ABSOFF(liveliness_monitoring_interval), 0, uf_duration_100ms_1hr, 0, pf_duration, + "

This element controls the interval at which to check whether threads have been making progress.

" }, END_MARKER }; @@ -878,23 +880,14 @@ static const struct cfgelem ddsi2_cfgelems[] = { END_MARKER }; -/* Note: using 2e-1 instead of 0.2 to avoid use of the decimal -separator, which is locale dependent. */ -static const struct cfgelem lease_expiry_time_cfgattrs[] = { - { ATTR("update_factor"), 1, "2e-1", ABSOFF(servicelease_update_factor), 0, uf_float, 0, pf_float, NULL }, - END_MARKER +static const struct cfgelem deprecated_lease_cfgelems[] = { + WILDCARD, + END_MARKER }; -static const struct cfgelem lease_cfgelems[] = { - { LEAF_W_ATTRS("ExpiryTime", lease_expiry_time_cfgattrs), 1, "10", ABSOFF(servicelease_expiry_time), 0, uf_float, 0, pf_float, NULL }, - END_MARKER -}; - - static const struct cfgelem domain_cfgelems[] = { - { GROUP("Lease", lease_cfgelems), NULL }, { LEAF("Id"), 1, "any", ABSOFF(domainId), 0, uf_domainId, 0, pf_domainId, NULL }, - WILDCARD, + { GROUP("|Lease", deprecated_lease_cfgelems), NULL }, END_MARKER }; @@ -908,7 +901,7 @@ static const struct cfgelem root_cfgelems[] = { { "DDSI2E|DDSI2", ddsi2_cfgelems, NULL, NODATA, "

DDSI2 settings ...

" }, { "Durability", durability_cfgelems, NULL, NODATA, NULL }, - { "Lease", lease_cfgelems, NULL, NODATA, NULL }, + { GROUP("|Lease", deprecated_lease_cfgelems), NULL }, END_MARKER }; @@ -1529,7 +1522,7 @@ static int uf_string(struct cfgst *cfgst, void *parent, struct cfgelem const * c } DDSRT_WARNING_MSVC_OFF(4996); -static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *value, const struct unit *unittab, int64_t def_mult, int64_t max) +static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *value, const struct unit *unittab, int64_t def_mult, int64_t min, int64_t max) { int pos; double v_dbl; @@ -1542,14 +1535,14 @@ static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *valu return cfg_error(cfgst, "%s: empty string is not a valid value", value); } else if ( sscanf(value, "%lld%n", (long long int *) &v_int, &pos) == 1 && (mult = lookup_multiplier(cfgst, unittab, value, pos, v_int == 0, def_mult, 0)) != 0 ) { assert(mult > 0); - if ( v_int < 0 || v_int > max / mult ) + if ( v_int < 0 || v_int > max / mult || mult * v_int < min) return cfg_error(cfgst, "%s: value out of range", value); *elem = mult * v_int; return 1; } else if ( sscanf(value, "%lf%n", &v_dbl, &pos) == 1 && (mult = lookup_multiplier(cfgst, unittab, value, pos, v_dbl == 0, def_mult, 1)) != 0 ) { double dmult = (double) mult; assert(dmult > 0); - if ( v_dbl < 0 || (int64_t) (v_dbl * dmult + 0.5) > max ) + if ( (int64_t) (v_dbl * dmult + 0.5) < min || (int64_t) (v_dbl * dmult + 0.5) > max ) return cfg_error(cfgst, "%s: value out of range", value); *elem = (int64_t) (v_dbl * dmult + 0.5); return 1; @@ -1587,7 +1580,7 @@ static int uf_bandwidth(struct cfgst *cfgst, void *parent, struct cfgelem const static int uf_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { int64_t size = 0; - if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, INT32_MAX) ) + if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) ) return 0; else { uint32_t *elem = cfg_address(cfgst, parent, cfgelem); @@ -1844,7 +1837,7 @@ static int uf_maybe_memsize(struct cfgst *cfgst, void *parent, struct cfgelem co elem->isdefault = 1; elem->value = 0; return 1; - } else if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, INT32_MAX) ) { + } else if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) ) { return 0; } else { elem->isdefault = 0; @@ -1853,19 +1846,6 @@ static int uf_maybe_memsize(struct cfgst *cfgst, void *parent, struct cfgelem co } } - -static int uf_float(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - float *elem = cfg_address(cfgst, parent, cfgelem); - char *endptr; - float f; - dds_retcode_t rc = ddsrt_strtof(value, &endptr, &f); - if (rc != DDS_RETCODE_OK || *value == 0 || *endptr != 0 ) - return cfg_error(cfgst, "%s: not a floating point number", value); - *elem = f; - return 1; -} - static int uf_int(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { int *elem = cfg_address(cfgst, parent, cfgelem); @@ -1879,9 +1859,9 @@ static int uf_int(struct cfgst *cfgst, void *parent, struct cfgelem const * cons return 1; } -static int uf_duration_gen(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, const char *value, int64_t def_mult, int64_t max_ns) +static int uf_duration_gen(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, const char *value, int64_t def_mult, int64_t min_ns, int64_t max_ns) { - return uf_natint64_unit(cfgst, cfg_address(cfgst, parent, cfgelem), value, unittab_duration, def_mult, max_ns); + return uf_natint64_unit(cfgst, cfg_address(cfgst, parent, cfgelem), value, unittab_duration, def_mult, min_ns, max_ns); } static int uf_duration_inf(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) @@ -1891,23 +1871,28 @@ static int uf_duration_inf(struct cfgst *cfgst, void *parent, struct cfgelem con *elem = T_NEVER; return 1; } else { - return uf_duration_gen(cfgst, parent, cfgelem, value, 0, T_NEVER - 1); + return uf_duration_gen(cfgst, parent, cfgelem, value, 0, 0, T_NEVER - 1); } } static int uf_duration_ms_1hr(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 3600 * T_SECOND); + return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 0, 3600 * T_SECOND); } static int uf_duration_ms_1s(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, T_SECOND); + return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 0, T_SECOND); } static int uf_duration_us_1s(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - return uf_duration_gen(cfgst, parent, cfgelem, value, 1000, T_SECOND); + return uf_duration_gen(cfgst, parent, cfgelem, value, 1000, 0, T_SECOND); +} + +static int uf_duration_100ms_1hr(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) +{ + return uf_duration_gen(cfgst, parent, cfgelem, value, 0, 100 * T_MILLISECOND, 3600 * T_SECOND); } static int uf_int32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) @@ -2309,12 +2294,6 @@ static void pf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const cfg_log(cfgst, "%d%s", p->value, is_default ? " [def]" : ""); } -static void pf_float(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - float *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%f%s", *p, is_default ? " [def]" : ""); -} - static void pf_boolean(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { int *p = cfg_address(cfgst, parent, cfgelem); diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index be434dd..bf5ec02 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -172,13 +172,14 @@ static void maybe_add_pp_as_meta_to_as_disc (const struct addrset *as_meta) static int write_mpayload (struct writer *wr, int alive, nn_parameterid_t keyparam, struct nn_xmsg *mpayload) { + struct thread_state1 * const ts1 = lookup_thread_state (); struct ddsi_plist_sample plist_sample; struct ddsi_serdata *serdata; nn_xmsg_payload_to_plistsample (&plist_sample, keyparam, mpayload); serdata = ddsi_serdata_from_sample (gv.plist_topic, alive ? SDK_DATA : SDK_KEY, &plist_sample); serdata->statusinfo = alive ? 0 : NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER; serdata->timestamp = now (); - return write_sample_nogc_notk (NULL, wr, serdata); + return write_sample_nogc_notk (ts1, NULL, wr, serdata); } int spdp_write (struct participant *pp) diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index beaa9bf..8043229 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -142,12 +142,12 @@ static int print_proxy_endpoint_common (ddsi_tran_conn_t conn, const char *label } -static int print_participants (struct thread_state1 *self, ddsi_tran_conn_t conn) +static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_t conn) { struct ephash_enum_participant e; struct participant *p; int x = 0; - thread_state_awake (self); + thread_state_awake (ts1); ephash_enum_participant_init (&e); while ((p = ephash_enum_participant_next (&e)) != NULL) { @@ -223,16 +223,16 @@ static int print_participants (struct thread_state1 *self, ddsi_tran_conn_t conn } } ephash_enum_participant_fini (&e); - thread_state_asleep (self); + thread_state_asleep (ts1); return x; } -static int print_proxy_participants (struct thread_state1 *self, ddsi_tran_conn_t conn) +static int print_proxy_participants (struct thread_state1 * const ts1, ddsi_tran_conn_t conn) { struct ephash_enum_proxy_participant e; struct proxy_participant *p; int x = 0; - thread_state_awake (self); + thread_state_awake (ts1); ephash_enum_proxy_participant_init (&e); while ((p = ephash_enum_proxy_participant_next (&e)) != NULL) { @@ -296,17 +296,18 @@ static int print_proxy_participants (struct thread_state1 *self, ddsi_tran_conn_ } } ephash_enum_proxy_participant_fini (&e); - thread_state_asleep (self); + thread_state_asleep (ts1); return x; } static void debmon_handle_connection (struct debug_monitor *dm, ddsi_tran_conn_t conn) { + struct thread_state1 * const ts1 = lookup_thread_state (); struct plugin *p; int r = 0; - r += print_participants (dm->servts, conn); + r += print_participants (ts1, conn); if (r == 0) - r += print_proxy_participants (dm->servts, conn); + r += print_proxy_participants (ts1, conn); /* Note: can only add plugins (at the tail) */ ddsrt_mutex_lock (&dm->lock); @@ -379,7 +380,7 @@ struct debug_monitor *new_debug_monitor (int port) if (ddsi_listener_listen (dm->servsock) < 0) goto err_listen; dm->stop = 0; - dm->servts = create_thread("debmon", debmon_main, dm); + create_thread(&dm->servts, "debmon", debmon_main, dm); return dm; err_listen: diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index c832a9b..685543b 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -3862,14 +3862,11 @@ void purge_proxy_participants (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. */ - struct thread_state1 * const self = lookup_thread_state(); - const int self_is_awake = vtime_awake_p (self->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); struct ephash_enum_proxy_participant est; struct proxy_purge_data data; - if (!self_is_awake) - thread_state_awake(self); - + thread_state_awake (ts1); data.loc = loc; data.timestamp = now(); ephash_enum_proxy_participant_init (&est); @@ -3881,8 +3878,7 @@ void purge_proxy_participants (const nn_locator_t *loc, bool delete_from_as_disc if (delete_from_as_disc) remove_from_addrset (gv.as_disc, loc); - if (!self_is_awake) - thread_state_asleep(self); + thread_state_asleep (ts1); } int delete_proxy_participant_by_guid (const struct nn_guid * guid, nn_wctime_t timestamp, int isimplicit) diff --git a/src/core/ddsi/src/q_gc.c b/src/core/ddsi/src/q_gc.c index 915c92b..42fc0ef 100644 --- a/src/core/ddsi/src/q_gc.c +++ b/src/core/ddsi/src/q_gc.c @@ -79,7 +79,7 @@ static int threads_vtime_check (unsigned *nivs, struct idx_vtime *ivs) static uint32_t gcreq_queue_thread (struct gcreq_queue *q) { - struct thread_state1 *self = lookup_thread_state (); + struct thread_state1 * const ts1 = lookup_thread_state (); nn_mtime_t next_thread_cputime = { 0 }; dds_time_t shortsleep = 1 * T_MILLISECOND; int64_t delay = T_MILLISECOND; /* force evaluation after startup */ @@ -124,9 +124,9 @@ static uint32_t gcreq_queue_thread (struct gcreq_queue *q) very little impact on its primary purpose and be less of a burden on the system than having a separate thread or adding it to the workload of the data handling threads. */ - thread_state_awake (self); - delay = check_and_handle_lease_expiration (self, now_et ()); - thread_state_asleep (self); + thread_state_awake (ts1); + delay = check_and_handle_lease_expiration (now_et ()); + thread_state_asleep (ts1); if (gcreq) { @@ -151,9 +151,9 @@ static uint32_t gcreq_queue_thread (struct gcreq_queue *q) multi-phase delete) or freeing the delete request. Reset the current gcreq as this one obviously is no more. */ DDS_TRACE("gc %p: deleting\n", (void*)gcreq); - thread_state_awake (self); + thread_state_awake (ts1); gcreq->cb (gcreq); - thread_state_asleep (self); + thread_state_asleep (ts1); gcreq = NULL; trace_shortsleep = 1; } @@ -174,9 +174,15 @@ struct gcreq_queue *gcreq_queue_new (void) q->count = 0; ddsrt_mutex_init (&q->lock); ddsrt_cond_init (&q->cond); - q->ts = create_thread ("gc", (uint32_t (*) (void *)) gcreq_queue_thread, q); - assert (q->ts); - return q; + if (create_thread (&q->ts, "gc", (uint32_t (*) (void *)) gcreq_queue_thread, q) == DDS_RETCODE_OK) + return q; + else + { + ddsrt_mutex_destroy (&q->lock); + ddsrt_cond_destroy (&q->cond); + ddsrt_free (q); + return NULL; + } } void gcreq_queue_drain (struct gcreq_queue *q) diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 9fddd09..0b89411 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -839,7 +839,7 @@ static int setup_and_start_recv_threads (void) goto fail; } } - if ((gv.recv_threads[i].ts = create_thread (gv.recv_threads[i].name, recv_thread, &gv.recv_threads[i].arg)) == NULL) + if (create_thread (&gv.recv_threads[i].ts, gv.recv_threads[i].name, recv_thread, &gv.recv_threads[i].arg) != DDS_RETCODE_OK) { DDS_ERROR("rtps_init: failed to start thread %s\n", gv.recv_threads[i].name); goto fail; @@ -1399,7 +1399,7 @@ int rtps_start (void) } if (gv.listener) { - gv.listen_ts = create_thread ("listen", (uint32_t (*) (void *)) listen_thread, gv.listener); + create_thread (&gv.listen_ts, "listen", (uint32_t (*) (void *)) listen_thread, gv.listener); } if (gv.startup_mode) { @@ -1429,7 +1429,8 @@ static void builtins_dqueue_ready_cb (void *varg) void rtps_stop (void) { - struct thread_state1 *self = lookup_thread_state (); + struct thread_state1 * const ts1 = lookup_thread_state (); + #ifdef DDSI_INCLUDE_NETWORK_CHANNELS struct config_channel_listelem * chptr; #endif @@ -1496,14 +1497,14 @@ void rtps_stop (void) /* Clean up proxy readers, proxy writers and proxy participants. Deleting a proxy participants deletes all its readers and writers automatically */ - thread_state_awake (self); + thread_state_awake (ts1); ephash_enum_proxy_participant_init (&est); while ((proxypp = ephash_enum_proxy_participant_next (&est)) != NULL) { delete_proxy_participant_by_guid(&proxypp->e.guid, tnow, 1); } ephash_enum_proxy_participant_fini (&est); - thread_state_asleep (self); + thread_state_asleep (ts1); } { @@ -1518,7 +1519,7 @@ void rtps_stop (void) rwriters to get all SEDP and SPDP dispose+unregister messages out. FIXME: need to keep xevent thread alive for a while longer. */ - thread_state_awake (self); + thread_state_awake (ts1); ephash_enum_writer_init (&est_wr); while ((wr = ephash_enum_writer_next (&est_wr)) != NULL) { @@ -1526,7 +1527,7 @@ void rtps_stop (void) delete_writer_nolinger (&wr->e.guid); } ephash_enum_writer_fini (&est_wr); - thread_state_awake (self); + thread_state_awake_to_awake_no_nest (ts1); ephash_enum_reader_init (&est_rd); while ((rd = ephash_enum_reader_next (&est_rd)) != NULL) { @@ -1534,14 +1535,14 @@ void rtps_stop (void) (void)delete_reader (&rd->e.guid); } ephash_enum_reader_fini (&est_rd); - thread_state_awake (self); + thread_state_awake_to_awake_no_nest (ts1); ephash_enum_participant_init (&est_pp); while ((pp = ephash_enum_participant_next (&est_pp)) != NULL) { delete_participant (&pp->e.guid); } ephash_enum_participant_fini (&est_pp); - thread_state_asleep (self); + thread_state_asleep (ts1); } /* Wait until all participants are really gone => by then we can be diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index 1dac32c..0e2d99c 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -205,7 +205,7 @@ void lease_set_expiry (struct lease *l, nn_etime_t when) force_lease_check(); } -int64_t check_and_handle_lease_expiration (UNUSED_ARG (struct thread_state1 *self), nn_etime_t tnowE) +int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) { struct lease *l; int64_t delay; diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index 20eaa66..1ca2e83 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -2397,7 +2397,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 *self = lookup_thread_state (); + struct thread_state1 * const ts1 = lookup_thread_state (); nn_mtime_t next_thread_cputime = { 0 }; int keepgoing = 1; nn_guid_t rdguid, *prdguid = NULL; @@ -2416,6 +2416,7 @@ static uint32_t dqueue_thread (struct nn_dqueue *q) q->sc.first = q->sc.last = NULL; ddsrt_mutex_unlock (&q->lock); + thread_state_awake (ts1); while (sc.first) { struct nn_rsample_chain_elem *e = sc.first; @@ -2424,7 +2425,7 @@ static uint32_t dqueue_thread (struct nn_dqueue *q) if (ddsrt_atomic_dec32_ov (&q->nof_samples) == 1) { ddsrt_cond_broadcast (&q->cond); } - thread_state_awake (self); + thread_state_awake_to_awake_no_nest (ts1); switch (dqueue_elem_kind (e)) { case DQEK_DATA: @@ -2474,9 +2475,9 @@ static uint32_t dqueue_thread (struct nn_dqueue *q) break; } } - thread_state_asleep (self); } + thread_state_asleep (ts1); ddsrt_mutex_lock (&q->lock); } ddsrt_mutex_unlock (&q->lock); @@ -2506,7 +2507,7 @@ struct nn_dqueue *nn_dqueue_new (const char *name, uint32_t max_samples, nn_dque if ((thrname = ddsrt_malloc (thrnamesz)) == NULL) goto fail_thrname; snprintf (thrname, thrnamesz, "dq.%s", name); - if ((q->ts = create_thread (thrname, (uint32_t (*) (void *)) dqueue_thread, q)) == NULL) + if (create_thread (&q->ts, thrname, (uint32_t (*) (void *)) dqueue_thread, q) != DDS_RETCODE_OK) goto fail_thread; ddsrt_free (thrname); return q; diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 8671a5b..9e7f899 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -2660,9 +2660,9 @@ static struct receiver_state *rst_cow_if_needed (int *rst_live, struct nn_rmsg * static int handle_submsg_sequence ( + struct thread_state1 * const ts1, ddsi_tran_conn_t conn, const nn_locator_t *srcloc, - struct thread_state1 * const self, nn_wctime_t tnowWC, nn_etime_t tnowE, const nn_guid_prefix_t * const src_prefix, @@ -2709,10 +2709,12 @@ static int handle_submsg_sequence ts_for_latmeas = 0; timestamp = invalid_ddsi_timestamp; + assert (thread_is_asleep ()); + thread_state_awake (ts1); while (submsg <= (end - sizeof (SubmessageHeader_t))) { Submessage_t *sm = (Submessage_t *) submsg; - int byteswap; + bool byteswap; unsigned octetsToNextHeader; if (sm->smhdr.flags & SMFLAG_ENDIANNESS) @@ -2749,7 +2751,7 @@ static int handle_submsg_sequence break; } - thread_state_awake (self); + thread_state_awake_to_awake_no_nest (ts1); state_smkind = sm->smhdr.submessageId; switch (sm->smhdr.submessageId) { @@ -2855,9 +2857,7 @@ static int handle_submsg_sequence unsigned char *datap; /* valid_Data does not validate the payload */ if (!valid_Data (rst, rmsg, &sm->data, submsg_size, byteswap, &sampleinfo, &datap)) - { goto malformed; - } sampleinfo.timestamp = timestamp; sampleinfo.reception_timestamp = tnowWC; handle_Data (rst, tnowE, rmsg, &sm->data, submsg_size, &sampleinfo, datap); @@ -2886,8 +2886,10 @@ static int handle_submsg_sequence size_t len2 = decode_container (submsg1, len1); if ( len2 != 0 ) { TRACE ((")\n")); - if (handle_submsg_sequence (conn, srcloc, self, tnowWC, tnowE, src_prefix, dst_prefix, msg, (size_t) (submsg1 - msg) + len2, submsg1, rmsg) < 0) - goto malformed; + thread_state_asleep (ts1); + if (handle_submsg_sequence (conn, srcloc, tnowWC, tnowE, src_prefix, dst_prefix, msg, (size_t) (submsg1 - msg) + len2, submsg1, rmsg) < 0) + goto malformed_asleep; + thread_state_awake (ts1); } TRACE (("PT_INFO_CONTAINER END")); } @@ -2952,19 +2954,24 @@ static int handle_submsg_sequence state = "parse:shortmsg"; state_smkind = SMID_PAD; DDS_TRACE("short (size %"PRIuSIZE" exp %p act %p)", submsg_size, (void *) submsg, (void *) end); - goto malformed; + goto malformed_asleep; } + thread_state_asleep (ts1); + assert (thread_is_asleep ()); return 0; malformed: - + thread_state_asleep (ts1); + assert (thread_is_asleep ()); +malformed_asleep: + assert (thread_is_asleep ()); malformed_packet_received (msg, submsg, len, state, state_smkind, hdr->vendorid); return -1; } static bool do_packet ( - struct thread_state1 *self, + struct thread_state1 * const ts1, ddsi_tran_conn_t conn, const nn_guid_prefix_t * guidprefix, struct nn_rbufpool *rbpool @@ -3052,7 +3059,7 @@ static bool do_packet if (sz > 0 && !gv.deaf) { nn_rmsg_setsize (rmsg, (uint32_t) sz); - assert (vtime_asleep_p (self->vtime)); + assert (thread_is_asleep ()); if ((size_t)sz < RTPS_MESSAGE_HEADER_SIZE || *(uint32_t *)buff != NN_PROTOCOLID_AS_UINT32) { @@ -3078,9 +3085,8 @@ static bool do_packet PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, addrstr); } - handle_submsg_sequence (conn, &srcloc, self, now (), now_et (), &hdr->guid_prefix, guidprefix, buff, (size_t) sz, buff + RTPS_MESSAGE_HEADER_SIZE, rmsg); + handle_submsg_sequence (ts1, conn, &srcloc, now (), now_et (), &hdr->guid_prefix, guidprefix, buff, (size_t) sz, buff + RTPS_MESSAGE_HEADER_SIZE, rmsg); } - thread_state_asleep (self); } nn_rmsg_commit (rmsg); return (sz > 0); @@ -3144,13 +3150,13 @@ static void local_participant_set_fini (struct local_participant_set *lps) ddsrt_free (lps->ps); } -static void rebuild_local_participant_set (struct thread_state1 *self, struct local_participant_set *lps) +static void rebuild_local_participant_set (struct thread_state1 * const ts1, struct local_participant_set *lps) { struct ephash_enum_participant est; struct participant *pp; unsigned nps_alloc; DDS_TRACE("pp set gen changed: local %u global %"PRIu32"\n", lps->gen, ddsrt_atomic_ld32(&gv.participant_set_generation)); - thread_state_awake (self); + thread_state_awake (ts1); restart: lps->gen = ddsrt_atomic_ld32 (&gv.participant_set_generation); /* Actual local set of participants may never be older than the @@ -3195,7 +3201,7 @@ static void rebuild_local_participant_set (struct thread_state1 *self, struct lo DDS_TRACE(" set changed - restarting\n"); goto restart; } - thread_state_asleep (self); + thread_state_asleep (ts1); /* The definition of the hash enumeration allows visiting one participant multiple times, so guard against that, too. Note @@ -3361,8 +3367,8 @@ void trigger_recv_threads (void) 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 thread_state1 *self = lookup_thread_state (); 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 }; @@ -3373,7 +3379,7 @@ uint32_t recv_thread (void *vrecv_thread_arg) while (gv.rtps_keepgoing) { LOG_THREAD_CPUTIME (next_thread_cputime); - (void) do_packet (self, recv_thread_arg->u.single.conn, NULL, rbpool); + (void) do_packet (ts1, recv_thread_arg->u.single.conn, NULL, rbpool); } } else @@ -3422,7 +3428,7 @@ uint32_t recv_thread (void *vrecv_thread_arg) { /* first rebuild local participant set - unless someone's toggling "deafness", this only happens when the participant set has changed, so might as well rebuild it */ - rebuild_local_participant_set (self, &lps); + rebuild_local_participant_set (ts1, &lps); os_sockWaitsetPurge (waitset, num_fixed); for (i = 0; i < lps.nps; i++) { @@ -3443,7 +3449,7 @@ uint32_t recv_thread (void *vrecv_thread_arg) else guid_prefix = &lps.ps[(unsigned)idx - num_fixed].guid_prefix; /* Process message and clean out connection if failed or closed */ - if (!do_packet (self, conn, guid_prefix, rbpool) && !conn->m_connless) + if (!do_packet (ts1, conn, guid_prefix, rbpool) && !conn->m_connless) ddsi_conn_free (conn); } } diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index 6789407..9ca93fc 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -22,7 +22,7 @@ #include "dds/ddsrt/misc.h" #include "dds/ddsi/q_thread.h" -#include "dds/ddsi/q_servicelease.h" +#include "dds/ddsi/ddsi_threadmon.h" #include "dds/ddsi/q_error.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_config.h" @@ -34,6 +34,16 @@ static char main_thread_name[] = "main"; struct thread_states thread_states; ddsrt_thread_local struct thread_state1 *tsd_thread_state; +extern inline bool vtime_awake_p (vtime_t vtime); +extern inline bool vtime_asleep_p (vtime_t vtime); +extern inline bool vtime_gt (vtime_t vtime1, vtime_t vtime0); + +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); +extern inline void thread_state_awake_to_awake_no_nest (struct thread_state1 *ts1); void *ddsrt_malloc_aligned_cacheline (size_t size) { @@ -63,9 +73,10 @@ static void ddsrt_free_aligned (void *ptr) void thread_states_init_static (void) { - static struct thread_state1 ts = - { .state = THREAD_STATE_ALIVE, .vtime = 1, .watchdog = 1, .name = "(anon)" }; - tsd_thread_state = &ts; + static struct thread_state1 ts = { + .state = THREAD_STATE_ALIVE, .vtime = 0u, .name = "(anon)" + }; + tsd_thread_state = &ts; } void thread_states_init (unsigned maxthreads) @@ -82,8 +93,7 @@ DDSRT_WARNING_MSVC_OFF(6386); for (i = 0; i < thread_states.nthreads; i++) { thread_states.ts[i].state = THREAD_STATE_ZERO; - thread_states.ts[i].vtime = 1; - thread_states.ts[i].watchdog = 1; + thread_states.ts[i].vtime = 0u; thread_states.ts[i].name = NULL; } DDSRT_WARNING_MSVC_ON(6386); @@ -115,43 +125,9 @@ static void cleanup_thread_state (void *data) ddsrt_fini(); } -struct thread_state1 *lookup_thread_state (void) -{ - struct thread_state1 *ts1 = NULL; - char name[128]; - ddsrt_thread_t thr; - - if ((ts1 = tsd_thread_state) == NULL) { - if ((ts1 = lookup_thread_state_real()) == NULL) { - /* This situation only arises for threads that were not created using - create_thread, aka application threads. Since registering thread - state should be fully automatic the name is simply the identifier. */ - thr = ddsrt_thread_self(); - ddsrt_thread_getname(name, sizeof(name)); - ddsrt_mutex_lock(&thread_states.lock); - ts1 = init_thread_state(name); - if (ts1 != NULL) { - ddsrt_init(); - ts1->extTid = thr; - ts1->tid = thr; - DDS_TRACE("started application thread %s\n", name); - ddsrt_thread_cleanup_push(&cleanup_thread_state, NULL); - } - ddsrt_mutex_unlock(&thread_states.lock); - } - - tsd_thread_state = ts1; - } - - assert(ts1 != NULL); - - return ts1; -} - -struct thread_state1 *lookup_thread_state_real (void) +static struct thread_state1 *find_thread_state (ddsrt_thread_t tid) { if (thread_states.ts) { - ddsrt_thread_t tid = ddsrt_thread_self (); unsigned i; for (i = 0; i < thread_states.nthreads; i++) { if (ddsrt_thread_equal (thread_states.ts[i].tid, tid)) { @@ -162,6 +138,40 @@ struct thread_state1 *lookup_thread_state_real (void) return NULL; } +static struct thread_state1 *lazy_create_thread_state (ddsrt_thread_t self) +{ + /* This situation only arises for threads that were not created using + create_thread, aka application threads. Since registering thread + state should be fully automatic the name is simply the identifier. */ + struct thread_state1 *ts1; + char name[128]; + ddsrt_thread_getname (name, sizeof (name)); + ddsrt_mutex_lock (&thread_states.lock); + if ((ts1 = init_thread_state (name)) != NULL) { + ddsrt_init (); + ts1->extTid = self; + ts1->tid = self; + DDS_TRACE ("started application thread %s\n", name); + ddsrt_thread_cleanup_push (&cleanup_thread_state, NULL); + } + ddsrt_mutex_unlock (&thread_states.lock); + return ts1; +} + +struct thread_state1 *lookup_thread_state_real (void) +{ + struct thread_state1 *ts1 = tsd_thread_state; + if (ts1 == NULL) + { + ddsrt_thread_t self = ddsrt_thread_self (); + if ((ts1 = find_thread_state (self)) == NULL) + ts1 = lazy_create_thread_state (self); + tsd_thread_state = ts1; + } + assert(ts1 != NULL); + return ts1; +} + struct thread_context { struct thread_state1 *self; uint32_t (*f) (void *arg); @@ -221,7 +231,7 @@ const struct config_thread_properties_listelem *lookup_thread_properties (const return e; } -struct thread_state1 * init_thread_state (const char *tname) +struct thread_state1 *init_thread_state (const char *tname) { int cand; struct thread_state1 *ts; @@ -231,29 +241,29 @@ struct thread_state1 * init_thread_state (const char *tname) ts = &thread_states.ts[cand]; if (ts->state == THREAD_STATE_ZERO) + { assert (vtime_asleep_p (ts->vtime)); + } ts->name = ddsrt_strdup (tname); ts->state = THREAD_STATE_ALIVE; return ts; } -struct thread_state1 *create_thread (const char *name, uint32_t (*f) (void *arg), void *arg) +dds_retcode_t create_thread (struct thread_state1 **ts1, const char *name, uint32_t (*f) (void *arg), void *arg) { struct config_thread_properties_listelem const * const tprops = lookup_thread_properties (name); ddsrt_threadattr_t tattr; - struct thread_state1 *ts1; ddsrt_thread_t tid; struct thread_context *ctxt; ctxt = ddsrt_malloc (sizeof (*ctxt)); ddsrt_mutex_lock (&thread_states.lock); - ts1 = init_thread_state (name); - - if (ts1 == NULL) + *ts1 = init_thread_state (name); + if (*ts1 == NULL) goto fatal; - ctxt->self = ts1; + ctxt->self = *ts1; ctxt->f = f; ctxt->arg = arg; ddsrt_threadattr_init (&tattr); @@ -269,26 +279,27 @@ struct thread_state1 *create_thread (const char *name, uint32_t (*f) (void *arg) if (ddsrt_thread_create (&tid, name, &tattr, &create_thread_wrapper, ctxt) != DDS_RETCODE_OK) { - ts1->state = THREAD_STATE_ZERO; + (*ts1)->state = THREAD_STATE_ZERO; DDS_FATAL("create_thread: %s: ddsrt_thread_create failed\n", name); goto fatal; } - ts1->extTid = tid; /* overwrite the temporary value with the correct external one */ + (*ts1)->extTid = tid; /* overwrite the temporary value with the correct external one */ ddsrt_mutex_unlock (&thread_states.lock); - return ts1; + return DDS_RETCODE_OK; fatal: ddsrt_mutex_unlock (&thread_states.lock); ddsrt_free (ctxt); + *ts1 = NULL; abort (); - return NULL; + return DDS_RETCODE_ERROR; } static void reap_thread_state (struct thread_state1 *ts1, int sync_with_servicelease) { ddsrt_mutex_lock (&thread_states.lock); ts1->state = THREAD_STATE_ZERO; - if (sync_with_servicelease && gv.servicelease) - nn_servicelease_statechange_barrier (gv.servicelease); + if (sync_with_servicelease && gv.threadmon) + ddsi_threadmon_statechange_barrier (gv.threadmon); if (ts1->name != main_thread_name) ddsrt_free (ts1->name); ddsrt_mutex_unlock (&thread_states.lock); @@ -319,7 +330,7 @@ void reset_thread_state (struct thread_state1 *ts1) void downgrade_main_thread (void) { struct thread_state1 *ts1 = lookup_thread_state (); - thread_state_asleep (ts1); + assert (vtime_asleep_p (ts1->vtime)); /* no need to sync with service lease: already stopped */ reap_thread_state (ts1, 0); thread_states_init_static (); diff --git a/src/core/ddsi/src/q_thread_inlines.c b/src/core/ddsi/src/q_thread_inlines.c deleted file mode 100644 index b16f324..0000000 --- a/src/core/ddsi/src/q_thread_inlines.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/ddsi/q_thread.h" - -extern inline int vtime_awake_p (vtime_t vtime); -extern inline int vtime_asleep_p (vtime_t vtime); -extern inline int vtime_gt (vtime_t vtime1, vtime_t vtime0); - -extern inline void thread_state_asleep (struct thread_state1 *ts1); -extern inline void thread_state_awake (struct thread_state1 *ts1); -extern inline void thread_state_blocked (struct thread_state1 *ts1); -extern inline void thread_state_unblocked (struct thread_state1 *ts1); diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 27abfc7..086187e 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -911,7 +911,7 @@ static int writer_may_continue (const struct writer *wr, const struct whc_state } -static dds_retcode_t throttle_writer (struct nn_xpack *xp, struct writer *wr) +static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr) { /* Sleep (cond_wait) without updating the thread's vtime: the garbage collector won't free the writer while we leave it @@ -956,7 +956,7 @@ static dds_retcode_t throttle_writer (struct nn_xpack *xp, struct writer *wr) { ASSERT_MUTEX_HELD (&wr->e.lock); assert (wr->throttling == 0); - assert (vtime_awake_p (lookup_thread_state ()->vtime)); + assert (thread_is_awake ()); assert (!is_builtin_entityid(wr->e.guid.entityid, NN_VENDORID_ECLIPSE)); } @@ -988,10 +988,10 @@ static dds_retcode_t throttle_writer (struct nn_xpack *xp, struct writer *wr) result = DDS_RETCODE_TIMEOUT; if (reltimeout > 0) { - thread_state_asleep (lookup_thread_state()); + thread_state_asleep (ts1); if (ddsrt_cond_waitfor (&wr->throttle_cond, &wr->e.lock, reltimeout)) result = DDS_RETCODE_OK; - thread_state_awake (lookup_thread_state()); + thread_state_awake (ts1); whc_get_state(wr->whc, &whcst); } if (result == DDS_RETCODE_TIMEOUT) @@ -1028,7 +1028,7 @@ static int maybe_grow_whc (struct writer *wr) return 0; } -static int write_sample_eot (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 nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk, int end_of_txn, int gc_allowed) { int r; seqno_t seq; @@ -1070,14 +1070,14 @@ static int write_sample_eot (struct nn_xpack *xp, struct writer *wr, struct nn_p dds_retcode_t ores; assert(gc_allowed); /* also see beginning of the function */ if (config.prioritize_retransmit && wr->retransmitting) - ores = throttle_writer (xp, wr); + ores = throttle_writer (ts1, xp, wr); else { maybe_grow_whc (wr); if (whcst.unacked_bytes <= wr->whc_high) ores = DDS_RETCODE_OK; else - ores = throttle_writer (xp, wr); + ores = throttle_writer (ts1, xp, wr); } if (ores == DDS_RETCODE_TIMEOUT) { @@ -1168,32 +1168,34 @@ drop: return r; } -int write_sample_gc (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) +int write_sample_gc (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) { - return write_sample_eot (xp, wr, NULL, serdata, tk, 0, 1); + return write_sample_eot (ts1, xp, wr, NULL, serdata, tk, 0, 1); } -int write_sample_nogc (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) +int write_sample_nogc (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) { - return write_sample_eot (xp, wr, NULL, serdata, tk, 0, 0); + return write_sample_eot (ts1, xp, wr, NULL, serdata, tk, 0, 0); } -int write_sample_gc_notk (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata) +int write_sample_gc_notk (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata) { struct ddsi_tkmap_instance *tk; int res; + assert (thread_is_awake ()); tk = ddsi_tkmap_lookup_instance_ref (serdata); - res = write_sample_eot (xp, wr, NULL, serdata, tk, 0, 1); + res = write_sample_eot (ts1, xp, wr, NULL, serdata, tk, 0, 1); ddsi_tkmap_instance_unref (tk); return res; } -int write_sample_nogc_notk (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata) +int write_sample_nogc_notk (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata) { struct ddsi_tkmap_instance *tk; int res; + assert (thread_is_awake ()); tk = ddsi_tkmap_lookup_instance_ref (serdata); - res = write_sample_eot (xp, wr, NULL, serdata, tk, 0, 0); + res = write_sample_eot (ts1, xp, wr, NULL, serdata, tk, 0, 0); ddsi_tkmap_instance_unref (tk); return res; } diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index 0e60a2a..b5d6c86 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -504,6 +504,7 @@ struct xeventq * xeventq_new int xeventq_start (struct xeventq *evq, const char *name) { + dds_retcode_t rc; char * evqname = "tev"; assert (evq->ts == NULL); @@ -515,13 +516,13 @@ int xeventq_start (struct xeventq *evq, const char *name) } evq->terminate = 0; - evq->ts = create_thread (evqname, (uint32_t (*) (void *)) xevent_thread, evq); + rc = create_thread (&evq->ts, evqname, (uint32_t (*) (void *)) xevent_thread, evq); if (name) { ddsrt_free (evqname); } - return (evq->ts == NULL) ? Q_ERR_UNSPECIFIED : 0; + return (rc != DDS_RETCODE_OK) ? Q_ERR_UNSPECIFIED : 0; } void xeventq_stop (struct xeventq *evq) @@ -1114,7 +1115,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e } } -static void write_pmd_message (struct nn_xpack *xp, struct participant *pp, unsigned pmd_kind) +static void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack *xp, struct participant *pp, unsigned pmd_kind) { #define PMD_DATA_LENGTH 1 struct writer *wr; @@ -1146,12 +1147,12 @@ static void write_pmd_message (struct nn_xpack *xp, struct participant *pp, unsi serdata->timestamp = now (); tk = ddsi_tkmap_lookup_instance_ref(serdata); - write_sample_nogc (xp, wr, serdata, tk); + write_sample_nogc (ts1, xp, wr, serdata, tk); ddsi_tkmap_instance_unref(tk); #undef PMD_DATA_LENGTH } -static void handle_xevk_pmd_update (struct nn_xpack *xp, struct xevent *ev, nn_mtime_t tnow) +static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_xpack *xp, struct xevent *ev, nn_mtime_t tnow) { struct participant *pp; int64_t intv; @@ -1162,7 +1163,7 @@ static void handle_xevk_pmd_update (struct nn_xpack *xp, struct xevent *ev, nn_m return; } - write_pmd_message (xp, pp, PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE); + write_pmd_message (ts1, xp, pp, PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE); /* QoS changes can't change lease durations. So the only thing that could cause trouble here is that the addition or removal of a @@ -1217,7 +1218,7 @@ static void handle_xevk_delete_writer (UNUSED_ARG (struct nn_xpack *xp), struct delete_xevent (ev); } -static void handle_individual_xevent (struct xevent *xev, struct nn_xpack *xp, nn_mtime_t tnow) +static void handle_individual_xevent (struct thread_state1 * const ts1, struct xevent *xev, struct nn_xpack *xp, nn_mtime_t tnow) { switch (xev->kind) { @@ -1231,7 +1232,7 @@ static void handle_individual_xevent (struct xevent *xev, struct nn_xpack *xp, n handle_xevk_spdp (xp, xev, tnow); break; case XEVK_PMD_UPDATE: - handle_xevk_pmd_update (xp, xev, tnow); + handle_xevk_pmd_update (ts1, xp, xev, tnow); break; case XEVK_END_STARTUP_MODE: handle_xevk_end_startup_mode (xp, xev, tnow); @@ -1262,7 +1263,7 @@ static void handle_individual_xevent_nt (struct xevent_nt *xev, struct nn_xpack ddsrt_free (xev); } -static void handle_timed_xevent (struct thread_state1 *self, struct xevent *xev, struct nn_xpack *xp, nn_mtime_t tnow /* monotonic */) +static void handle_timed_xevent (struct thread_state1 * const ts1, struct xevent *xev, struct nn_xpack *xp, nn_mtime_t tnow /* monotonic */) { /* This function handles the individual xevent irrespective of whether it is a "timed" or "non-timed" xevent */ @@ -1276,14 +1277,13 @@ static void handle_timed_xevent (struct thread_state1 *self, struct xevent *xev, assert (xev->tsched.v != TSCHED_DELETE); ddsrt_mutex_unlock (&xevq->lock); - thread_state_awake (self); - handle_individual_xevent (xev, xp, tnow /* monotonic */); + handle_individual_xevent (ts1, xev, xp, tnow /* monotonic */); ddsrt_mutex_lock (&xevq->lock); ASSERT_MUTEX_HELD (&xevq->lock); } -static void handle_nontimed_xevent (struct thread_state1 *self, struct xevent_nt *xev, struct nn_xpack *xp) +static void handle_nontimed_xevent (struct xevent_nt *xev, struct nn_xpack *xp) { /* This function handles the individual xevent irrespective of whether it is a "timed" or "non-timed" xevent */ @@ -1296,7 +1296,6 @@ static void handle_nontimed_xevent (struct thread_state1 *self, struct xevent_nt assert (xev->evq == xevq); ddsrt_mutex_unlock (&xevq->lock); - thread_state_awake (self); handle_individual_xevent_nt (xev, xp); /* non-timed xevents are freed by the handlers */ ddsrt_mutex_lock (&xevq->lock); @@ -1304,11 +1303,12 @@ static void handle_nontimed_xevent (struct thread_state1 *self, struct xevent_nt ASSERT_MUTEX_HELD (&xevq->lock); } -static void handle_xevents (struct thread_state1 *self, struct xeventq *xevq, struct nn_xpack *xp, nn_mtime_t tnow /* monotonic */) +static void handle_xevents (struct thread_state1 * const ts1, struct xeventq *xevq, struct nn_xpack *xp, nn_mtime_t tnow /* monotonic */) { int xeventsToProcess = 1; ASSERT_MUTEX_HELD (&xevq->lock); + assert (thread_is_awake ()); /* The following loops give priority to the "timed" events (heartbeats, acknacks etc) if there are any. The algorithm is that we handle all @@ -1334,7 +1334,8 @@ static void handle_xevents (struct thread_state1 *self, struct xeventq *xevq, st scheduled or not), so set to TSCHED_NEVER to indicate it currently isn't. */ xev->tsched.v = T_NEVER; - handle_timed_xevent (self, xev, xp, tnow); + thread_state_awake_to_awake_no_nest (ts1); + handle_timed_xevent (ts1, xev, xp, tnow); } /* Limited-bandwidth channels means events can take a LONG time @@ -1345,7 +1346,8 @@ static void handle_xevents (struct thread_state1 *self, struct xeventq *xevq, st if (!non_timed_xmit_list_is_empty (xevq)) { struct xevent_nt *xev = getnext_from_non_timed_xmit_list (xevq); - handle_nontimed_xevent (self, xev, xp); + thread_state_awake_to_awake_no_nest (ts1); + handle_nontimed_xevent (xev, xp); tnow = now_mt (); } else @@ -1359,7 +1361,7 @@ static void handle_xevents (struct thread_state1 *self, struct xeventq *xevq, st static uint32_t xevent_thread (struct xeventq * xevq) { - struct thread_state1 *self = lookup_thread_state (); + struct thread_state1 * const ts1 = lookup_thread_state (); struct nn_xpack *xp; nn_mtime_t next_thread_cputime = { 0 }; @@ -1372,15 +1374,13 @@ static uint32_t xevent_thread (struct xeventq * xevq) LOG_THREAD_CPUTIME (next_thread_cputime); - handle_xevents (self, xevq, xp, tnow); - - /* Send to the network unlocked, as it may sleep due to bandwidth - limitation */ + thread_state_awake (ts1); + handle_xevents (ts1, xevq, xp, tnow); + /* Send to the network unlocked, as it may sleep due to bandwidth limitation */ ddsrt_mutex_unlock (&xevq->lock); nn_xpack_send (xp, false); ddsrt_mutex_lock (&xevq->lock); - - thread_state_asleep (self); + thread_state_asleep (ts1); if (!non_timed_xmit_list_is_empty (xevq) || xevq->terminate) { diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index d1c83cb..4fc0e57 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -1459,7 +1459,7 @@ void nn_xpack_sendq_init (void) void nn_xpack_sendq_start (void) { - gv.sendq_ts = create_thread("sendq", nn_xpack_sendq_thread, NULL); + create_thread (&gv.sendq_ts, "sendq", nn_xpack_sendq_thread, NULL); } void nn_xpack_sendq_stop (void) diff --git a/src/core/ddsi/src/sysdeps.c b/src/core/ddsi/src/sysdeps.c index e362823..13fa3f1 100644 --- a/src/core/ddsi/src/sysdeps.c +++ b/src/core/ddsi/src/sysdeps.c @@ -51,14 +51,14 @@ void log_stacktrace (const char *name, ddsrt_thread_t tid) if (dds_get_log_mask() == 0) ; /* no op if nothing logged */ else if (!config.noprogress_log_stacktraces) - DDS_LOG(~0u, "-- stack trace of %s requested, but traces disabled --\n", name); + DDS_LOG(~DDS_LC_FATAL, "-- stack trace of %s requested, but traces disabled --\n", name); else { const dds_time_t d = 1000000; struct sigaction act, oact; char **strs; int i; - DDS_LOG(~0u, "-- stack trace of %s requested --\n", name); + DDS_LOG(~DDS_LC_FATAL, "-- stack trace of %s requested --\n", name); act.sa_handler = log_stacktrace_sigh; act.sa_flags = 0; sigfillset (&act.sa_mask); @@ -70,15 +70,15 @@ void log_stacktrace (const char *name, ddsrt_thread_t tid) dds_sleepfor (d); sigaction (SIGXCPU, &oact, NULL); if (pthread_kill (tid.v, 0) != 0) - DDS_LOG(~0u, "-- thread exited --\n"); + DDS_LOG(~DDS_LC_FATAL, "-- thread exited --\n"); else { - DDS_LOG(~0u, "-- stack trace follows --\n"); + DDS_LOG(~DDS_LC_FATAL, "-- stack trace follows --\n"); strs = backtrace_symbols (log_stacktrace_stk.stk, log_stacktrace_stk.depth); for (i = 0; i < log_stacktrace_stk.depth; i++) - DDS_LOG(~0u, "%s\n", strs[i]); + DDS_LOG(~DDS_LC_FATAL, "%s\n", strs[i]); free (strs); - DDS_LOG(~0u, "-- end of stack trace --\n"); + DDS_LOG(~DDS_LC_FATAL, "-- end of stack trace --\n"); } ddsrt_atomic_st32 (&log_stacktrace_flag, 0); } diff --git a/src/core/xtests/rhc_torture.c b/src/core/xtests/rhc_torture.c index bc7c4fb..245d057 100644 --- a/src/core/xtests/rhc_torture.c +++ b/src/core/xtests/rhc_torture.c @@ -108,7 +108,7 @@ static uint64_t store (struct rhc *rhc, struct proxy_writer *wr, struct ddsi_ser /* beware: unrefs sd */ struct ddsi_tkmap_instance *tk; struct proxy_writer_info pwr_info; - thread_state_awake (mainthread); + thread_state_awake (lookup_thread_state ()); tk = ddsi_tkmap_lookup_instance_ref(sd); uint64_t iid = tk->m_iid; if (print) @@ -132,7 +132,7 @@ static uint64_t store (struct rhc *rhc, struct proxy_writer *wr, struct ddsi_ser pwr_info.ownership_strength = wr->c.xqos->ownership_strength.value; dds_rhc_store (rhc, &pwr_info, sd, tk); ddsi_tkmap_instance_unref (tk); - thread_state_asleep (mainthread); + thread_state_asleep (lookup_thread_state ()); ddsi_serdata_unref (sd); return iid; } @@ -171,18 +171,18 @@ static struct rhc *mkrhc (dds_reader *rd, nn_history_kind_t hk, int32_t hdepth, rqos.history.depth = hdepth; rqos.destination_order.kind = dok; nn_xqos_mergein_missing (&rqos, &gv.default_xqos_rd); - thread_state_awake (mainthread); + thread_state_awake (lookup_thread_state ()); rhc = dds_rhc_new (rd, mdtopic); dds_rhc_set_qos(rhc, &rqos); - thread_state_asleep (mainthread); + thread_state_asleep (lookup_thread_state ()); return rhc; } static void frhc (struct rhc *rhc) { - thread_state_awake (mainthread); + thread_state_awake (lookup_thread_state ()); dds_rhc_free (rhc); - thread_state_asleep (mainthread); + thread_state_asleep (lookup_thread_state ()); } static char si2is (const dds_sample_info_t *si) @@ -288,9 +288,9 @@ static void rdtkcond (struct rhc *rhc, dds_readcond *cond, const struct check *c if (print) printf ("%s:\n", opname); - thread_state_awake (mainthread); + thread_state_awake (lookup_thread_state ()); cnt = op (rhc, true, rres_ptrs, rres_iseq, (max <= 0) ? (uint32_t) (sizeof (rres_iseq) / sizeof (rres_iseq[0])) : (uint32_t) max, cond ? NO_STATE_MASK_SET : (DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE), 0, cond); - thread_state_asleep (mainthread); + thread_state_asleep (lookup_thread_state ()); if (max > 0 && cnt > max) { printf ("%s TOO MUCH DATA (%d > %d)\n", opname, cnt, max); abort (); @@ -764,8 +764,8 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, tkcond (rhc[k], rhcconds[cond], NULL, 1, print && k == 0, states_seen); break; } - case 11: - thread_state_awake (mainthread); + case 11: { + thread_state_awake (lookup_thread_state ()); struct proxy_writer_info wr_info; wr_info.auto_dispose = wr[which]->c.xqos->writer_data_lifecycle.autodispose_unregistered_instances; wr_info.guid = wr[which]->e.guid; @@ -773,8 +773,9 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, wr_info.ownership_strength = wr[which]->c.xqos->ownership_strength.value; for (size_t k = 0; k < nrd; k++) dds_rhc_unregister_wr (rhc[k], &wr_info); - thread_state_asleep (mainthread); + thread_state_asleep (lookup_thread_state ()); break; + } } if ((i % 200) == 0) @@ -869,14 +870,14 @@ int main (int argc, char **argv) { 0, 0, 0, 0, 0, 0, 0, 0 } }; rdall (rhc, c1, print, states_seen); - thread_state_awake (mainthread); + thread_state_awake (lookup_thread_state ()); struct proxy_writer_info wr0_info; wr0_info.auto_dispose = wr0->c.xqos->writer_data_lifecycle.autodispose_unregistered_instances; wr0_info.guid = wr0->e.guid; wr0_info.iid = wr0->e.iid; wr0_info.ownership_strength = wr0->c.xqos->ownership_strength.value; dds_rhc_unregister_wr (rhc, &wr0_info); - thread_state_asleep (mainthread); + thread_state_asleep (lookup_thread_state ()); const struct check c2[] = { { "ROU", iid0, wr0->e.iid, 0,0, 1, 0,1 }, { "ROU", iid0, 0, 0,0, 0, 0,0 }, From c92820677df37a3a5512b0f8fab9951b8c5b74d8 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 11 Apr 2019 15:12:17 +0200 Subject: [PATCH 022/178] enable printf format checking for dds_log Also remove superfluous parameters in a TRACE statement and fix a format specification in pong.c. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_receive.c | 2 +- src/ddsrt/include/dds/ddsrt/log.h | 4 +++- src/examples/roundtrip/pong.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 9e7f899..a442e86 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -1747,7 +1747,7 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm if (!pwr->have_seen_heartbeat && pwr->n_reliable_readers > 0) { - DDS_TRACE(": no heartbeat seen yet", PGUID (pwr->e.guid), PGUID (dst)); + DDS_TRACE(": no heartbeat seen yet"); ddsrt_mutex_unlock (&pwr->e.lock); return 1; } diff --git a/src/ddsrt/include/dds/ddsrt/log.h b/src/ddsrt/include/dds/ddsrt/log.h index b6450c0..4a08a46 100644 --- a/src/ddsrt/include/dds/ddsrt/log.h +++ b/src/ddsrt/include/dds/ddsrt/log.h @@ -25,6 +25,7 @@ #include #include "dds/export.h" +#include "dds/ddsrt/attributes.h" #if defined (__cplusplus) extern "C" { @@ -199,7 +200,8 @@ dds_log( uint32_t line, const char *func, const char *fmt, - ...); + ...) + ddsrt_attribute_format((__printf__, 5, 6)); /** * @brief Undecorated function name of the current function. diff --git a/src/examples/roundtrip/pong.c b/src/examples/roundtrip/pong.c index ef692f5..010c0c5 100644 --- a/src/examples/roundtrip/pong.c +++ b/src/examples/roundtrip/pong.c @@ -60,7 +60,7 @@ static void data_available(dds_entity_t rd, void *arg) RoundTripModule_DataType * valid_sample = &data[j]; status = dds_write_ts (writer, valid_sample, info[j].source_timestamp); if (status < 0) - DDS_FATAL("dds_write_ts: %s\n", -status); + DDS_FATAL("dds_write_ts: %d\n", -status); } } } From ec0062542c92d28956bfae1fc4336178a8a6577b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 13 Apr 2019 17:08:07 +0200 Subject: [PATCH 023/178] defer triggering dqueue thread until end-of-packet There appears to be a minor performance benefit to not waking up the delivery thread (if used) immediately upon enqueueing the first sample, but rather to wait (typically) until the end of the packet. In a latency measurement it probably makes little difference: one shouldn't use asynchronous delivery if one needs the lowest possible latency, and the end of the packet is reached rather quickly normally. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_radmin.h | 2 ++ src/core/ddsi/src/q_radmin.c | 22 +++++++++++++ src/core/ddsi/src/q_receive.c | 38 +++++++++++++++++------ 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_radmin.h b/src/core/ddsi/include/dds/ddsi/q_radmin.h index 829cdcd..e61c029 100644 --- a/src/core/ddsi/include/dds/ddsi/q_radmin.h +++ b/src/core/ddsi/include/dds/ddsi/q_radmin.h @@ -228,6 +228,8 @@ seqno_t nn_reorder_next_seq (const struct nn_reorder *reorder); struct nn_dqueue *nn_dqueue_new (const char *name, 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); void nn_dqueue_enqueue (struct nn_dqueue *q, struct nn_rsample_chain *sc, nn_reorder_result_t rres); void nn_dqueue_enqueue1 (struct nn_dqueue *q, const nn_guid_t *rdguid, struct nn_rsample_chain *sc, nn_reorder_result_t rres); void nn_dqueue_enqueue_callback (struct nn_dqueue *q, nn_dqueue_callback_t cb, void *arg); diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index 1ca2e83..8b49c64 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -2541,6 +2541,26 @@ static int nn_dqueue_enqueue_locked (struct nn_dqueue *q, struct nn_rsample_chai return must_signal; } +bool nn_dqueue_enqueue_deferred_wakeup (struct nn_dqueue *q, struct nn_rsample_chain *sc, nn_reorder_result_t rres) +{ + bool signal; + assert (rres > 0); + assert (sc->first); + assert (sc->last->next == NULL); + ddsrt_mutex_lock (&q->lock); + ddsrt_atomic_add32 (&q->nof_samples, (uint32_t) rres); + signal = nn_dqueue_enqueue_locked (q, sc); + ddsrt_mutex_unlock (&q->lock); + return signal; +} + +void dd_dqueue_enqueue_trigger (struct nn_dqueue *q) +{ + ddsrt_mutex_lock (&q->lock); + ddsrt_cond_broadcast (&q->cond); + ddsrt_mutex_unlock (&q->lock); +} + void nn_dqueue_enqueue (struct nn_dqueue *q, struct nn_rsample_chain *sc, nn_reorder_result_t rres) { assert (rres > 0); @@ -2622,6 +2642,8 @@ void nn_dqueue_wait_until_empty_if_full (struct nn_dqueue *q) if (count >= q->max_samples) { ddsrt_mutex_lock (&q->lock); + /* In case the wakeups are were all deferred */ + ddsrt_cond_broadcast (&q->cond); while (ddsrt_atomic_ld32 (&q->nof_samples) > 0) ddsrt_cond_wait (&q->cond, &q->lock); ddsrt_mutex_unlock (&q->lock); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index a442e86..8ea8c47 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -2151,7 +2151,7 @@ static void clean_defrag (struct proxy_writer *pwr) nn_defrag_notegap (pwr->defrag, 1, seq); } -static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_DataFrag_common_t *msg, const struct nn_rsample_info *sampleinfo, uint32_t fragnum, struct nn_rdata *rdata) +static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_DataFrag_common_t *msg, const struct nn_rsample_info *sampleinfo, uint32_t fragnum, struct nn_rdata *rdata, struct nn_dqueue **deferred_wakeup) { struct proxy_writer *pwr; struct nn_rsample *rsample; @@ -2251,10 +2251,23 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct receive thread's data gets interleaved -- arguably delivery needn't be exactly in-order, which would allow us to do this without pwr->e.lock held. */ - if (!pwr->deliver_synchronously) - nn_dqueue_enqueue (pwr->dqueue, &sc, rres); - else + if (pwr->deliver_synchronously) + { + /* FIXME: just in case the synchronous delivery runs into a delay caused + by the current mishandling of resource limits */ + if (*deferred_wakeup) + dd_dqueue_enqueue_trigger (*deferred_wakeup); deliver_user_data_synchronously (&sc); + } + else + { + if (nn_dqueue_enqueue_deferred_wakeup (pwr->dqueue, &sc, rres)) + { + if (*deferred_wakeup && *deferred_wakeup != pwr->dqueue) + dd_dqueue_enqueue_trigger (*deferred_wakeup); + *deferred_wakeup = pwr->dqueue; + } + } if (pwr->n_readers_out_of_sync > 0) { /* Those readers catching up with TL but in sync with the proxy @@ -2384,7 +2397,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con } } -static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap) +static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup) { DDS_TRACE("DATA(%x:%x:%x:%x -> %x:%x:%x:%x #%"PRId64"", PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, @@ -2421,14 +2434,14 @@ static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_r } else { - handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, ~0u, rdata); + handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, ~0u, rdata, deferred_wakeup); } } DDS_TRACE(")"); return 1; } -static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const DataFrag_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap) +static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const DataFrag_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup) { DDS_TRACE("DATAFRAG(%x:%x:%x:%x -> %x:%x:%x:%x #%"PRId64"/[%u..%u]", PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, @@ -2494,7 +2507,7 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct wrong, it'll simply generate a request for retransmitting a non-existent fragment. The other side SHOULD be capable of dealing with that. */ - handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, msg->fragmentStartingNum + msg->fragmentsInSubmessage - 2, rdata); + handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, msg->fragmentStartingNum + msg->fragmentsInSubmessage - 2, rdata, deferred_wakeup); } DDS_TRACE(")"); return 1; @@ -2681,6 +2694,7 @@ static int handle_submsg_sequence nn_ddsi_time_t timestamp; size_t submsg_size = 0; unsigned char * end = msg + len; + struct nn_dqueue *deferred_wakeup = NULL; /* Receiver state is dynamically allocated with lifetime bound to the message. Updates cause a new copy to be created if the @@ -2845,7 +2859,7 @@ static int handle_submsg_sequence goto malformed; sampleinfo.timestamp = timestamp; sampleinfo.reception_timestamp = tnowWC; - handle_DataFrag (rst, tnowE, rmsg, &sm->datafrag, submsg_size, &sampleinfo, datap); + handle_DataFrag (rst, tnowE, rmsg, &sm->datafrag, submsg_size, &sampleinfo, datap, &deferred_wakeup); rst_live = 1; ts_for_latmeas = 0; } @@ -2860,7 +2874,7 @@ static int handle_submsg_sequence goto malformed; sampleinfo.timestamp = timestamp; sampleinfo.reception_timestamp = tnowWC; - handle_Data (rst, tnowE, rmsg, &sm->data, submsg_size, &sampleinfo, datap); + handle_Data (rst, tnowE, rmsg, &sm->data, submsg_size, &sampleinfo, datap, &deferred_wakeup); rst_live = 1; ts_for_latmeas = 0; } @@ -2958,6 +2972,8 @@ static int handle_submsg_sequence } thread_state_asleep (ts1); assert (thread_is_asleep ()); + if (deferred_wakeup) + dd_dqueue_enqueue_trigger (deferred_wakeup); return 0; malformed: @@ -2966,6 +2982,8 @@ malformed: malformed_asleep: assert (thread_is_asleep ()); malformed_packet_received (msg, submsg, len, state, state_smkind, hdr->vendorid); + if (deferred_wakeup) + dd_dqueue_enqueue_trigger (deferred_wakeup); return -1; } From 6227fe00b330bd9c157149d752152d7899ab1535 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 13 Apr 2019 17:19:25 +0200 Subject: [PATCH 024/178] eliminate clang static analyzer false positive Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_read.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index b4c5adf..d595272 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -202,7 +202,7 @@ dds_readcdr_impl( thread_state_awake (ts1); rc = dds_read_lock(reader_or_condition, &rd, &cond, false); - if (rc >= DDS_RETCODE_OK) { + if (rc == DDS_RETCODE_OK) { ret = dds_rhc_takecdr ( rd->m_rd->rhc, lock, buf, si, maxs, From 2dd20c4273406e0dab37f19dde4155a8ba8d900d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 16 Apr 2019 17:07:09 +0200 Subject: [PATCH 025/178] add dds_entity_release counterpart to entity_claim Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds__entity.h | 3 +++ src/core/ddsc/src/dds_entity.c | 7 ++++++- src/core/ddsc/src/dds_readcond.c | 4 +--- src/core/ddsc/src/dds_reader.c | 8 ++++---- src/core/ddsc/src/dds_writer.c | 4 ++-- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/core/ddsc/src/dds__entity.h b/src/core/ddsc/src/dds__entity.h index 992c15a..34c13c5 100644 --- a/src/core/ddsc/src/dds__entity.h +++ b/src/core/ddsc/src/dds__entity.h @@ -84,6 +84,9 @@ dds_entity_claim ( dds_entity_t hdl, dds_entity **eptr); +DDS_EXPORT void dds_entity_release ( + dds_entity *e); + DDS_EXPORT dds_retcode_t dds_entity_lock( dds_entity_t hdl, diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index f8a4e14..e06beee 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -761,6 +761,11 @@ dds_retcode_t dds_entity_claim (dds_entity_t hdl, dds_entity **eptr) } } +void dds_entity_release (dds_entity *e) +{ + dds_handle_release (&e->m_hdllink); +} + dds_retcode_t dds_entity_lock (dds_entity_t hdl, dds_entity_kind_t kind, dds_entity **eptr) { dds_retcode_t hres; @@ -989,7 +994,7 @@ dds_return_t dds_generic_unimplemented_operation_manykinds (dds_entity_t handle, break; } } - dds_handle_release (&e->m_hdllink); + dds_entity_release (e); return DDS_ERRNO (ret); } } diff --git a/src/core/ddsc/src/dds_readcond.c b/src/core/ddsc/src/dds_readcond.c index 322af8e..ee37521 100644 --- a/src/core/ddsc/src/dds_readcond.c +++ b/src/core/ddsc/src/dds_readcond.c @@ -100,13 +100,11 @@ dds_entity_t dds_get_datareader (dds_entity_t condition) rdh = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); break; } - dds_handle_release (&e->m_hdllink); + dds_entity_release (e); return rdh; } } - - dds_return_t dds_get_mask (dds_entity_t condition, uint32_t *mask) { dds_entity *entity; diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 2c14994..dcc3289 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -384,7 +384,7 @@ dds_create_reader( } else { subscriber = participant_or_subscriber; } - dds_handle_release (&p_or_s->m_hdllink); + dds_entity_release (p_or_s); internal_topic = false; t = topic; break; @@ -512,7 +512,7 @@ void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb if (dds_entity_kind (dds_entity) != DDS_KIND_READER) { - dds_handle_release (&dds_entity->m_hdllink); + dds_entity_release (dds_entity); return; } @@ -552,7 +552,7 @@ void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb ddsrt_mutex_lock (&rd->e.lock); } ddsrt_mutex_unlock (&rd->e.lock); - dds_handle_release (&dds_rd->m_entity.m_hdllink); + dds_entity_release (dds_entity); } uint32_t dds_reader_lock_samples (dds_entity_t reader) @@ -613,7 +613,7 @@ dds_entity_t dds_get_subscriber (dds_entity_t entity) subh = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); break; } - dds_handle_release (&e->m_hdllink); + dds_entity_release (e); return subh; } } diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 06a13ef..5bd81d6 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -388,7 +388,7 @@ dds_create_writer( } else { publisher = participant_or_publisher; } - dds_handle_release (&p_or_p->m_hdllink); + dds_entity_release (p_or_p); } if ((rc = dds_publisher_lock(publisher, &pub)) != DDS_RETCODE_OK) { @@ -494,7 +494,7 @@ dds_get_publisher( assert (dds_entity_kind (e->m_parent) == DDS_KIND_PUBLISHER); pubh = e->m_parent->m_hdllink.hdl; } - dds_handle_release (&e->m_hdllink); + dds_entity_release (e); return pubh; } } From d6edfada814f569a5423387bd1edf4cb1cf7d2ae Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 10:38:12 +0200 Subject: [PATCH 026/178] fix deadlock between listener, deleting reader, &c If a (proxy) writer delivers data to a reader that has a data_available listener calling read/take while that reader is being deleted, blocked in set_listener waiting for the listeners to complete, then a deadlock can occur: * listener calling read/take then attempt to lock reader; * deleting the reader locks the reader, then waits for the listeners to complete while holding the lock This commits unlocks the reader before waiting for the listeners to complete. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_entity.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index e06beee..6704b6e 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -163,18 +163,23 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) return DDS_RETCODE_OK; } + /* FIXME: "closing" the handle here means a listener invoked on X + can still discover that X has become inaccessible */ + /* FIXME: RHC reads m_status_enable outside lock and might still + just invoke the listener */ dds_handle_close (&e->m_hdllink); - ddsrt_mutex_lock (&e->m_observers_lock); - while (e->m_cb_count > 0) - ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock); e->m_status_enable = 0; dds_reset_listener (&e->m_listener); e->m_trigger |= DDS_DELETING_STATUS; - ddsrt_mutex_unlock (&e->m_observers_lock); dds_entity_unlock(e); - /* Signal observers that this entity will be deleted. */ - dds_entity_status_signal (e); + /* Signal observers that this entity will be deleted and wait for + all listeners to complete. */ + ddsrt_mutex_lock (&e->m_observers_lock); + dds_entity_observers_signal (e, e->m_trigger); + while (e->m_cb_count > 0) + ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock); + ddsrt_mutex_unlock (&e->m_observers_lock); /* * Recursively delete children. @@ -547,7 +552,7 @@ dds_return_t dds_set_listener (dds_entity_t entity, const dds_listener_t *listen dds_entity *e, *x; dds_retcode_t rc; - if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + if ((rc = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) return DDS_ERRNO (rc); ddsrt_mutex_lock (&e->m_observers_lock); @@ -568,7 +573,7 @@ dds_return_t dds_set_listener (dds_entity_t entity, const dds_listener_t *listen } clear_status_with_listener (e); ddsrt_mutex_unlock (&e->m_observers_lock); - dds_entity_unlock (e); + dds_entity_release (e); pushdown_listener (entity); return DDS_RETCODE_OK; } @@ -625,7 +630,7 @@ dds_return_t dds_get_status_mask (dds_entity_t entity, uint32_t *mask) if (mask == NULL) return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); - if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + if ((rc = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) return DDS_ERRNO (rc); if (e->m_deriver.validate_status == 0) @@ -637,7 +642,7 @@ dds_return_t dds_get_status_mask (dds_entity_t entity, uint32_t *mask) ddsrt_mutex_unlock (&e->m_observers_lock); ret = DDS_RETCODE_OK; } - dds_entity_unlock(e); + dds_entity_release(e); return ret; } @@ -652,7 +657,7 @@ dds_return_t dds_set_status_mask (dds_entity_t entity, uint32_t mask) dds_retcode_t rc; dds_return_t ret; - if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + if ((rc = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) return DDS_ERRNO (rc); if (e->m_deriver.validate_status == 0) @@ -660,13 +665,16 @@ dds_return_t dds_set_status_mask (dds_entity_t entity, uint32_t mask) else if ((ret = e->m_deriver.validate_status (mask)) == DDS_RETCODE_OK) { ddsrt_mutex_lock (&e->m_observers_lock); + while (e->m_cb_count > 0) + ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock); + /* Don't block internal status triggers. */ mask |= DDS_INTERNAL_STATUS_MASK; e->m_status_enable = mask; e->m_trigger &= mask; ddsrt_mutex_unlock (&e->m_observers_lock); } - dds_entity_unlock(e); + dds_entity_release (e); return ret; } From 0202039f612f219705d2eca16bf322e8e5288e6b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 16 Apr 2019 17:09:08 +0200 Subject: [PATCH 027/178] remove dds_rhc_fini abomination It was called strangely early in the deleting of the reader, even before the DDSI reader was no longer being accessed by other threads. The immediate and obvious problem is that it resets the pointer to the upper-layer entity even though this can still be dereferenced in invoking a listener, resulting in a crash. Secondly it blocks until there are no listener calls any more (and the resetting of that pointer will prevent any further listener invocations), but a similar piece of logic is already in generic entity code that resets the mask and then waits for all listener invocations to complete. Having both is a problem. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds__rhc.h | 1 - src/core/ddsc/src/dds_init.c | 1 - src/core/ddsc/src/dds_reader.c | 10 ++++- src/core/ddsc/src/dds_rhc.c | 44 +++---------------- .../ddsi/include/dds/ddsi/ddsi_rhc_plugin.h | 1 - src/core/ddsi/src/q_entity.c | 4 -- 6 files changed, 13 insertions(+), 48 deletions(-) diff --git a/src/core/ddsc/src/dds__rhc.h b/src/core/ddsc/src/dds__rhc.h index e01f7c4..fc08a7f 100644 --- a/src/core/ddsc/src/dds__rhc.h +++ b/src/core/ddsc/src/dds__rhc.h @@ -26,7 +26,6 @@ struct proxy_writer_info; DDS_EXPORT struct rhc *dds_rhc_new (dds_reader *reader, const struct ddsi_sertopic *topic); DDS_EXPORT void dds_rhc_free (struct rhc *rhc); -DDS_EXPORT void dds_rhc_fini (struct rhc *rhc); DDS_EXPORT uint32_t dds_rhc_lock_samples (struct rhc *rhc); diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 1efd81d..e6558d5 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -273,7 +273,6 @@ void ddsi_plugin_init (void) ddsi_plugin.builtintopic_write = dds__builtin_write; ddsi_plugin.rhc_plugin.rhc_free_fn = dds_rhc_free; - ddsi_plugin.rhc_plugin.rhc_fini_fn = dds_rhc_fini; ddsi_plugin.rhc_plugin.rhc_store_fn = dds_rhc_store; ddsi_plugin.rhc_plugin.rhc_unregister_wr_fn = dds_rhc_unregister_wr; ddsi_plugin.rhc_plugin.rhc_relinquish_ownership_fn = dds_rhc_relinquish_ownership; diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index dcc3289..b3f241b 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -160,14 +160,20 @@ void dds_reader_data_available_cb (struct dds_reader *rd) status on the subscriber; secondly it is the only one for which overhead really matters. Otherwise, it is pretty much like dds_reader_status_cb. */ - struct dds_listener const * const lst = &rd->m_entity.m_listener; - dds_entity * const sub = rd->m_entity.m_parent; ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); + if (!(rd->m_entity.m_status_enable & DDS_DATA_AVAILABLE_STATUS)) + { + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); + return; + } + while (rd->m_entity.m_cb_count > 0) ddsrt_cond_wait (&rd->m_entity.m_observers_cond, &rd->m_entity.m_observers_lock); rd->m_entity.m_cb_count++; + struct dds_listener const * const lst = &rd->m_entity.m_listener; + dds_entity * const sub = rd->m_entity.m_parent; if (lst->on_data_on_readers) { ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 7f3029b..4eb64dc 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -277,7 +277,6 @@ struct rhc { /* Instance/Sample maximums from resource limits QoS */ - ddsrt_atomic_uint32_t n_cbs; /* # callbacks in progress */ int32_t max_instances; /* FIXME: probably better as uint32_t with MAX_UINT32 for unlimited */ int32_t max_samples; /* FIXME: probably better as uint32_t with MAX_UINT32 for unlimited */ int32_t max_samples_per_instance; /* FIXME: probably better as uint32_t with MAX_UINT32 for unlimited */ @@ -631,20 +630,6 @@ void dds_rhc_free (struct rhc *rhc) ddsrt_free (rhc); } -void dds_rhc_fini (struct rhc * rhc) -{ - ddsrt_mutex_lock (&rhc->lock); - rhc->reader = NULL; - ddsrt_mutex_unlock (&rhc->lock); - - /* Wait for all callbacks to complete */ - - while (ddsrt_atomic_ld32 (&rhc->n_cbs) > 0) - { - dds_sleepfor (DDS_MSECS (1)); - } -} - static void init_trigger_info_cmn_nonmatch (struct trigger_info_cmn *info) { info->qminst = ~0u; @@ -1462,17 +1447,10 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info if (rhc->reader) { - if (notify_data_available && (rhc->reader->m_entity.m_status_enable & DDS_DATA_AVAILABLE_STATUS)) - { - ddsrt_atomic_inc32 (&rhc->n_cbs); + if (notify_data_available) dds_reader_data_available_cb (rhc->reader); - ddsrt_atomic_dec32 (&rhc->n_cbs); - } - if (trigger_waitsets) - { - dds_entity_status_signal(&rhc->reader->m_entity); - } + dds_entity_status_signal (&rhc->reader->m_entity); } return delivered; @@ -1489,13 +1467,8 @@ error_or_nochange: /* Make any reader status callback */ - if (cb_data.raw_status_id >= 0 && rhc->reader && rhc->reader->m_entity.m_status_enable) - { - ddsrt_atomic_inc32 (&rhc->n_cbs); + if (cb_data.raw_status_id >= 0 && rhc->reader) dds_reader_status_cb (&rhc->reader->m_entity, &cb_data); - ddsrt_atomic_dec32 (&rhc->n_cbs); - } - return delivered; } @@ -1575,17 +1548,10 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ if (rhc->reader) { - if (notify_data_available && (rhc->reader->m_entity.m_status_enable & DDS_DATA_AVAILABLE_STATUS)) - { - ddsrt_atomic_inc32 (&rhc->n_cbs); + if (notify_data_available) dds_reader_data_available_cb (rhc->reader); - ddsrt_atomic_dec32 (&rhc->n_cbs); - } - if (trigger_waitsets) - { - dds_entity_status_signal(&rhc->reader->m_entity); - } + dds_entity_status_signal (&rhc->reader->m_entity); } } diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h b/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h index 7f884fa..57c8813 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h @@ -30,7 +30,6 @@ struct proxy_writer_info struct ddsi_rhc_plugin { void (*rhc_free_fn) (struct rhc *rhc); - void (*rhc_fini_fn) (struct rhc *rhc); bool (*rhc_store_fn) (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 685543b..3dffa18 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -3386,10 +3386,6 @@ int delete_reader (const struct nn_guid *guid) DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); return Q_ERR_UNKNOWN_ENTITY; } - if (rd->rhc) - { - (ddsi_plugin.rhc_plugin.rhc_fini_fn) (rd->rhc); - } DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid %x:%x:%x:%x) ...\n", PGUID (*guid)); ddsi_plugin.builtintopic_write (&rd->e, now(), false); ephash_remove_reader_guid (rd); From 31b8baa03be15f385519f1171f99a500114aac4a Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 10:49:51 +0200 Subject: [PATCH 028/178] block signals in ddsrt_thread_create Signal handling in multi-threaded processes is bad enough at the best of times, and as we don't really use any signals in the Cyclone code, it makes more sense to create all threads with most signals blocked. That way an application that wants to handle signals using sigwait() need not block all signals prior to creating a participant. Note that instead of blocking all signals, we block all except SIGXCPU. The reason is that the liveliness monitoring and stack trace dumping code currently relies on that signal. Signed-off-by: Erik Boasson --- src/ddsrt/src/threads/posix/threads.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ddsrt/src/threads/posix/threads.c b/src/ddsrt/src/threads/posix/threads.c index 278d796..f8dbf4c 100644 --- a/src/ddsrt/src/threads/posix/threads.c +++ b/src/ddsrt/src/threads/posix/threads.c @@ -193,6 +193,7 @@ ddsrt_thread_create ( thread_context_t *ctx; ddsrt_threadattr_t tattr; int result, create_ret; + sigset_t set, oset; assert (threadptr != NULL); assert (name != NULL); @@ -281,11 +282,18 @@ ddsrt_thread_create ( strcpy (ctx->name, name); ctx->routine = start_routine; ctx->arg = arg; + + /* Block signal delivery in our own threads (SIGXCPU is excluded so we have a way of + dumping stack traces, but that should be improved upon) */ + sigfillset (&set); + sigdelset (&set, SIGXCPU); + sigprocmask (SIG_BLOCK, &set, &oset); if ((create_ret = pthread_create (&threadptr->v, &attr, os_startRoutineWrapper, ctx)) != 0) { DDS_ERROR ("os_threadCreate(%s): pthread_create failed with error %d\n", name, create_ret); goto err_create; } + sigprocmask (SIG_SETMASK, &oset, NULL); pthread_attr_destroy (&attr); return DDS_RETCODE_OK; From a6b5229510dc62df239edeb93f38e01df10cae31 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 11:04:26 +0200 Subject: [PATCH 029/178] crash invoking data available on built-in reader The DDSI reader/writer pointers are now returned as out parameters instead of as a return value, so that the upper-layer reference is set before any listener can be invoked. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_reader.c | 6 +- src/core/ddsc/src/dds_writer.c | 4 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 4 +- src/core/ddsi/src/q_entity.c | 68 ++++++++++++----------- 4 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index b3f241b..b039495 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -472,11 +472,11 @@ dds_create_reader( ddsrt_mutex_unlock(&sub->m_entity.m_mutex); thread_state_awake (lookup_thread_state ()); - rd->m_rd = new_reader(&rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, - rqos, rhc, dds_reader_status_cb, rd); + ret = new_reader(&rd->m_rd, &rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, + rqos, rhc, dds_reader_status_cb, rd); ddsrt_mutex_lock(&sub->m_entity.m_mutex); ddsrt_mutex_lock(&tp->m_entity.m_mutex); - assert (rd->m_rd); + assert (ret == DDS_RETCODE_OK); thread_state_asleep (lookup_thread_state ()); /* For persistent data register reader with durability */ diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 5bd81d6..cd83d3e 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -456,10 +456,10 @@ dds_create_writer( ddsrt_mutex_unlock (&pub->m_entity.m_mutex); thread_state_awake (lookup_thread_state ()); - wr->m_wr = new_writer(&wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); + ret = new_writer(&wr->m_wr, &wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); ddsrt_mutex_lock (&pub->m_entity.m_mutex); ddsrt_mutex_lock (&tp->m_entity.m_mutex); - assert(wr->m_wr); + assert(ret == DDS_RETCODE_OK); thread_state_asleep (lookup_thread_state ()); dds_topic_unlock(tp); dds_publisher_unlock(pub); diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 6f79aac..9138e02 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -479,9 +479,9 @@ struct writer *get_builtin_writer (const struct participant *pp, unsigned entity GUID "ppguid". May return NULL if participant unknown or writer/reader already known. */ -struct writer *new_writer (struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg); +dds_retcode_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg); -struct reader *new_reader (struct nn_guid *rdguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc * rhc, status_cb_t status_cb, void *status_cb_arg); +dds_retcode_t new_reader (struct reader **rd_out, struct nn_guid *rdguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc * rhc, status_cb_t status_cb, void *status_cb_arg); struct whc_node; struct whc_state; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 3dffa18..565c72b 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -88,8 +88,8 @@ static const unsigned prismtech_builtin_writers_besmask = NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER | NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER; -static struct writer * new_writer_guid (const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_cbarg); -static struct reader * new_reader_guid (const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc *rhc, status_cb_t status_cb, void *status_cbarg); +static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_cbarg); +static dds_retcode_t new_reader_guid (struct reader **rd_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc *rhc, status_cb_t status_cb, void *status_cbarg); static struct participant *ref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity); static void unref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity); static void delete_proxy_group_locked (struct proxy_group *pgroup, nn_wctime_t timestamp, int isimplicit); @@ -488,7 +488,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) { subguid.entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER); - new_writer_guid (&subguid, &group_guid, pp, NULL, &gv.spdp_endpoint_xqos, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.spdp_endpoint_xqos, whc_new(1, 1, 1), LAST_WR_PARAMS); /* But we need the as_disc address set for SPDP, because we need to send it to everyone regardless of the existence of readers. */ { @@ -511,23 +511,23 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) { subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER); - new_writer_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER); - new_writer_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER); - new_writer_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(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 (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(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 (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER; } @@ -535,7 +535,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis { /* 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 (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER; } @@ -543,7 +543,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) { subguid.entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER); - new_writer_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER; } @@ -551,31 +551,31 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis if (!(flags & RTPS_PF_NO_BUILTIN_READERS)) { subguid.entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER); - new_reader_guid (&subguid, &group_guid, pp, NULL, &gv.spdp_endpoint_xqos, NULL, NULL, NULL); + new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.spdp_endpoint_xqos, NULL, NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER); - new_reader_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_DETECTOR; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER); - new_reader_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_DETECTOR; subguid.entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER); - new_reader_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); + 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 (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); + 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 (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); + 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 (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); + 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; } @@ -2779,7 +2779,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se local_reader_ary_init (&wr->rdary); } -static struct writer *new_writer_guid (const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_entity) +static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_entity) { struct writer *wr; nn_mtime_t tnow = now_mt (); @@ -2790,6 +2790,8 @@ static struct writer *new_writer_guid (const struct nn_guid *guid, const struct new_reader_writer_common (guid, topic, xqos); wr = ddsrt_malloc (sizeof (*wr)); + if (wr_out) + *wr_out = wr; /* want a pointer to the participant so that a parallel call to delete_participant won't interfere with our ability to address @@ -2822,27 +2824,25 @@ static struct writer *new_writer_guid (const struct nn_guid *guid, const struct resched_xevent_if_earlier (pp->pmd_update_xevent, tsched); } - return wr; + return DDS_RETCODE_OK; } -struct writer *new_writer (struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg) +dds_retcode_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg) { struct participant *pp; - struct writer * wr; if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "new_writer - participant %x:%x:%x:%x not found\n", PGUID (*ppguid)); - return NULL; + return DDS_RETCODE_NOT_FOUND; } /* participant can't be freed while we're mucking around cos we are awake and do not touch the thread's vtime (ephash_lookup already verifies we're awake) */ wrguid->prefix = pp->e.guid.prefix; if (pp_allocate_entityid (&wrguid->entityid, NN_ENTITYID_KIND_WRITER_WITH_KEY, pp) < 0) - return NULL; - wr = new_writer_guid (wrguid, group_guid, pp, topic, xqos, whc, status_cb, status_cb_arg); - return wr; + return DDS_RETCODE_OUT_OF_RESOURCES; + 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 (nn_entityid_t entityid, struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc) @@ -3170,8 +3170,9 @@ static void leave_mcast_helper (const nn_locator_t *n, void * varg) } #endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */ -static struct reader * new_reader_guid +static dds_retcode_t new_reader_guid ( + struct reader **rd_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, @@ -3193,6 +3194,8 @@ static struct reader * new_reader_guid new_reader_writer_common (guid, topic, xqos); rd = ddsrt_malloc (sizeof (*rd)); + if (rd_out) + *rd_out = rd; endpoint_common_init (&rd->e, &rd->c, EK_READER, guid, group_guid, pp); @@ -3300,11 +3303,12 @@ static struct reader * new_reader_guid match_reader_with_local_writers (rd, tnow); ddsi_plugin.builtintopic_write (&rd->e, now(), true); sedp_write_reader (rd); - return rd; + return DDS_RETCODE_OK; } -struct reader * new_reader +dds_retcode_t new_reader ( + struct reader **rd_out, struct nn_guid *rdguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, @@ -3316,18 +3320,16 @@ struct reader * new_reader ) { struct participant * pp; - struct reader * rd; if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "new_reader - participant %x:%x:%x:%x not found\n", PGUID (*ppguid)); - return NULL; + return DDS_RETCODE_NOT_FOUND; } rdguid->prefix = pp->e.guid.prefix; if (pp_allocate_entityid (&rdguid->entityid, NN_ENTITYID_KIND_READER_WITH_KEY, pp) < 0) - return NULL; - rd = new_reader_guid (rdguid, group_guid, pp, topic, xqos, rhc, status_cb, status_cbarg); - return rd; + return DDS_RETCODE_OUT_OF_RESOURCES; + return new_reader_guid (rd_out, rdguid, group_guid, pp, topic, xqos, rhc, status_cb, status_cbarg); } static void gc_delete_reader (struct gcreq *gcreq) From 4778d6c5dfb6853f07f81ac59ae0d65afc5e3c93 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 11:42:56 +0200 Subject: [PATCH 030/178] add QoS to ignore local readers/writers (#78) Adds a new "ignorelocal" QoS to the readers/writers to ignore local matching readers/writers, with three settings: * DDS_IGNORELOCAL_NONE: default * DDS_IGNORELOCAL_PARTICIPANT: ignores readers/writers in the same participant * DDS_IGNORELOCAL_PROCESS: ignores readers/writers in the same process These can be set/got using dds_qset_ignorelocal and dds_qget_ignorelocal. If a matching reader or writer is ignored because of this setting, it is as-if that reader or writer doesn't exist. No traffic will be generated or data retained on its behalf. There are no consequences for interoperability as this is (by definition) a local affair. Signed-off-by: Erik Boasson --- .../ddsc/include/dds/ddsc/dds_public_qos.h | 33 +++++++++++++++++++ src/core/ddsc/src/dds_qos.c | 21 ++++++++++++ src/core/ddsi/include/dds/ddsi/q_xqos.h | 12 +++++++ src/core/ddsi/src/q_entity.c | 27 +++++++++++++++ src/core/ddsi/src/q_plist.c | 10 ++++++ 5 files changed, 103 insertions(+) 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 4ffceb4..8f319c1 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h @@ -136,6 +136,16 @@ typedef enum dds_presentation_access_scope_kind } dds_presentation_access_scope_kind_t; +/** Ignore-local QoS: Applies to DataReader, DataWriter */ +typedef enum dds_ignorelocal_kind +{ + DDS_IGNORELOCAL_NONE, + DDS_IGNORELOCAL_PARTICIPANT, + DDS_IGNORELOCAL_PROCESS +} +dds_ignorelocal_kind_t; + + /** * @brief Allocate memory and initialize default QoS-policies * @@ -465,6 +475,16 @@ dds_qset_durability_service ( int32_t max_instances, int32_t max_samples_per_instance); +/** + * @brief Set the ignore-local policy of a qos structure + * + * @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy + * @param[in] ignore - True if readers and writers owned by the same participant should be ignored + */ +DDS_EXPORT void dds_qset_ignorelocal ( + dds_qos_t * __restrict qos, + dds_ignorelocal_kind_t ignore); + /** * @brief Get the userdata from a qos structure * @@ -753,6 +773,19 @@ dds_qget_durability_service ( int32_t *max_instances, int32_t *max_samples_per_instance); + /** + * @brief Get the ignore-local qos policy + * + * @param[in] qos - Pointer to a dds_qos_t structure storing the policy + * @param[in,out] ignore - Pointer that will store whether to ignore readers/writers owned by the same participant (optional) + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object + */ +DDS_EXPORT bool +dds_qget_ignorelocal ( + const dds_qos_t * __restrict qos, + dds_ignorelocal_kind_t *ignore); + #if defined (__cplusplus) } #endif diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index bc1869c..25a3ce6 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -658,6 +658,16 @@ void dds_qset_durability_service } } +void dds_qset_ignorelocal (dds_qos_t * __restrict qos, dds_ignorelocal_kind_t ignore) +{ + if (qos) { + qos->ignorelocal.value = (nn_ignorelocal_kind_t) ignore; + qos->present |= QP_CYCLONE_IGNORELOCAL; + } else { + DDS_ERROR("Argument QoS is NULL\n"); + } +} + bool dds_qget_userdata (const dds_qos_t * __restrict qos, void **value, size_t *sz) { if (!qos || !(qos->present & QP_USER_DATA)) { @@ -931,3 +941,14 @@ bool dds_qget_durability_service (const dds_qos_t * __restrict qos, dds_duration } return true; } + +bool dds_qget_ignorelocal (const dds_qos_t * __restrict qos, dds_ignorelocal_kind_t *ignore) +{ + if (!qos || !(qos->present & QP_CYCLONE_IGNORELOCAL)) { + return false; + } + if (ignore) { + *ignore = (dds_ignorelocal_kind_t) qos->ignorelocal.value; + } + return true; +} diff --git a/src/core/ddsi/include/dds/ddsi/q_xqos.h b/src/core/ddsi/include/dds/ddsi/q_xqos.h index 46a15bf..d13207d 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xqos.h +++ b/src/core/ddsi/include/dds/ddsi/q_xqos.h @@ -205,6 +205,16 @@ typedef struct nn_share_qospolicy { char *name; } nn_share_qospolicy_t; +typedef enum nn_ignorelocal_kind { + NN_NONE_IGNORELOCAL_QOS, + NN_PARTICIPANT_IGNORELOCAL_QOS, + NN_PROCESS_IGNORELOCAL_QOS +} nn_ignorelocal_kind_t; + +typedef struct nn_ignorelocal_qospolicy { + nn_ignorelocal_kind_t value; +} nn_ignorelocal_qospolicy_t; + /***/ /* Qos Present bit indices */ @@ -237,6 +247,7 @@ typedef struct nn_share_qospolicy { #define QP_PRISMTECH_ENTITY_FACTORY ((uint64_t)1 << 27) #define QP_PRISMTECH_SYNCHRONOUS_ENDPOINT ((uint64_t)1 << 28) #define QP_RTI_TYPECODE ((uint64_t)1 << 29) +#define QP_CYCLONE_IGNORELOCAL ((uint64_t)1 << 30) /* Partition QoS is not RxO according to the specification (DDS 1.2, section 7.1.3), but communication will not take place unless it @@ -290,6 +301,7 @@ typedef struct nn_xqos { /*x xR*/nn_reader_lifespan_qospolicy_t reader_lifespan; /*x xR*/nn_share_qospolicy_t share; /*xxx */nn_synchronous_endpoint_qospolicy_t synchronous_endpoint; + /* x */nn_ignorelocal_qospolicy_t ignorelocal; /* X*/nn_octetseq_t rti_typecode; } nn_xqos_t; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 565c72b..3626afd 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -2058,12 +2058,39 @@ static void connect_proxy_writer_with_reader (struct proxy_writer *pwr, struct r proxy_writer_add_connection (pwr, rd, tnow, init_count); } +static bool ignore_local_p (const nn_guid_t *guid1, const nn_guid_t *guid2, const struct nn_xqos *xqos1, const struct nn_xqos *xqos2) +{ + assert (xqos1->present & QP_CYCLONE_IGNORELOCAL); + assert (xqos2->present & QP_CYCLONE_IGNORELOCAL); + switch (xqos1->ignorelocal.value) + { + case NN_NONE_IGNORELOCAL_QOS: + break; + case NN_PARTICIPANT_IGNORELOCAL_QOS: + return memcmp (&guid1->prefix, &guid2->prefix, sizeof (guid1->prefix)) == 0; + case NN_PROCESS_IGNORELOCAL_QOS: + return true; + } + switch (xqos2->ignorelocal.value) + { + case NN_NONE_IGNORELOCAL_QOS: + break; + case NN_PARTICIPANT_IGNORELOCAL_QOS: + return memcmp (&guid1->prefix, &guid2->prefix, sizeof (guid1->prefix)) == 0; + case NN_PROCESS_IGNORELOCAL_QOS: + return true; + } + return false; +} + static void connect_writer_with_reader (struct writer *wr, struct reader *rd, nn_mtime_t tnow) { int32_t reason; (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; + if (ignore_local_p (&wr->e.guid, &rd->e.guid, wr->xqos, rd->xqos)) + return; if ((reason = qos_match_p (rd->xqos, wr->xqos)) >= 0) { writer_qos_mismatch (wr, (uint32_t)reason); diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index ad97995..c7a8222 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -2656,6 +2656,9 @@ static void xqos_init_default_common (nn_xqos_t *xqos) xqos->present |= QP_PRISMTECH_SYNCHRONOUS_ENDPOINT; xqos->synchronous_endpoint.value = 0; + + xqos->present |= QP_CYCLONE_IGNORELOCAL; + xqos->ignorelocal.value = NN_NONE_IGNORELOCAL_QOS; } void nn_xqos_init_default_reader (nn_xqos_t *xqos) @@ -2810,6 +2813,7 @@ void nn_xqos_mergein_missing (nn_xqos_t *a, const nn_xqos_t *b) CQ (PRISMTECH_READER_LIFESPAN, reader_lifespan); CQ (PRISMTECH_ENTITY_FACTORY, entity_factory); CQ (PRISMTECH_SYNCHRONOUS_ENDPOINT, synchronous_endpoint); + CQ (CYCLONE_IGNORELOCAL, ignorelocal); #undef CQ /* For allocated ones it is Not strictly necessary to use tmp, as @@ -3197,6 +3201,10 @@ uint64_t nn_xqos_delta (const nn_xqos_t *a, const nn_xqos_t *b, uint64_t mask) if (octetseqs_differ (&a->rti_typecode, &b->rti_typecode)) delta |= QP_RTI_TYPECODE; } + if (check & QP_CYCLONE_IGNORELOCAL) { + if (a->ignorelocal.value != b->ignorelocal.value) + delta |= QP_CYCLONE_IGNORELOCAL; + } return delta; } @@ -3257,6 +3265,7 @@ void nn_xqos_addtomsg (struct nn_xmsg *m, const nn_xqos_t *xqos, uint64_t wanted SIMPLE (PRISMTECH_ENTITY_FACTORY, entity_factory); SIMPLE (PRISMTECH_SYNCHRONOUS_ENDPOINT, synchronous_endpoint); FUNC_BY_REF (RTI_TYPECODE, rti_typecode, octetseq); + /* CYCLONE_IGNORELOCAL is not visible on the wire */ #undef FUNC_BY_REF #undef FUNC_BY_VAL #undef SIMPLE @@ -3467,6 +3476,7 @@ void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos) log_octetseq (cat, xqos->rti_typecode.length, xqos->rti_typecode.value); DDS_LOG(cat, ">"); }); + DO (CYCLONE_IGNORELOCAL, { LOGB1 ("ignorelocal=%u", xqos->ignorelocal.value); }); #undef PRINTARG_DUR #undef FMT_DUR From 7fb9ef2ab08a66b144b527cb9d730c14fe52cccc Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 11:43:39 +0200 Subject: [PATCH 031/178] publish built-in topics prior to matching The built-in topics for readers and writers should be published before a subscription or publication matched listener is invoked, otherwise the instance handle provided to the listener is not yet available in a reader for the corresponding topic. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_entity.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 3626afd..2c5105c 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -2832,7 +2832,10 @@ static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_gu the order if hash insert & matching creates a window during which neither of two endpoints being created in parallel can discover the other. */ + ddsrt_mutex_lock (&wr->e.lock); ephash_insert_writer_guid (wr); + ddsi_plugin.builtintopic_write (&wr->e, now(), true); + ddsrt_mutex_unlock (&wr->e.lock); /* once it exists, match it with proxy writers and broadcast existence (I don't think it matters much what the order of these @@ -2842,7 +2845,6 @@ static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_gu deleted while we do so */ match_writer_with_proxy_readers (wr, tnow); match_writer_with_local_readers (wr, tnow); - ddsi_plugin.builtintopic_write (&wr->e, now(), true); sedp_write_writer (wr); if (wr->lease_duration != T_NEVER) @@ -2890,8 +2892,8 @@ struct local_orphan_writer *new_local_orphan_writer (nn_entityid_t entityid, str memset (&wr->c.group_guid, 0, sizeof (wr->c.group_guid)); new_writer_guid_common_init (wr, topic, xqos, whc, 0, NULL); ephash_insert_writer_guid (wr); - match_writer_with_local_readers (wr, tnow); ddsi_plugin.builtintopic_write (&wr->e, now(), true); + match_writer_with_local_readers (wr, tnow); return lowr; } @@ -3325,10 +3327,13 @@ static dds_retcode_t new_reader_guid ut_avlInit (&rd_writers_treedef, &rd->writers); ut_avlInit (&rd_local_writers_treedef, &rd->local_writers); + ddsrt_mutex_lock (&rd->e.lock); ephash_insert_reader_guid (rd); + ddsi_plugin.builtintopic_write (&rd->e, now(), true); + ddsrt_mutex_unlock (&rd->e.lock); + match_reader_with_proxy_writers (rd, tnow); match_reader_with_local_writers (rd, tnow); - ddsi_plugin.builtintopic_write (&rd->e, now(), true); sedp_write_reader (rd); return DDS_RETCODE_OK; } @@ -4170,9 +4175,14 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, 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 */ + ddsrt_mutex_lock (&pwr->e.lock); ephash_insert_proxy_writer_guid (pwr); - match_proxy_writer_with_readers (pwr, tnow); ddsi_plugin.builtintopic_write (&pwr->e, timestamp, true); + ddsrt_mutex_unlock (&pwr->e.lock); + + match_proxy_writer_with_readers (pwr, tnow); ddsrt_mutex_lock (&pwr->e.lock); pwr->local_matching_inprogress = 0; @@ -4344,9 +4354,14 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, prd->assert_pp_lease = (unsigned) !!config.arrival_of_data_asserts_pp_and_ep_liveliness; ut_avlInit (&prd_writers_treedef, &prd->writers); + + /* locking the entity prevents matching while the built-in topic hasn't been published yet */ + ddsrt_mutex_lock (&prd->e.lock); ephash_insert_proxy_reader_guid (prd); - match_proxy_reader_with_writers (prd, tnow); ddsi_plugin.builtintopic_write (&prd->e, timestamp, true); + ddsrt_mutex_unlock (&prd->e.lock); + + match_proxy_reader_with_writers (prd, tnow); return 0; } From 5735b5775d2a9b25dd1a12848de74dc069a6bd95 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 11:19:30 +0200 Subject: [PATCH 032/178] add setter for partition QoS for a single name This adds dds_qset_partition1 as a convenience function to set the partition QoS to a single name. Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/ddsc/dds_public_qos.h | 14 +++++++++++++- src/core/ddsc/src/dds_qos.c | 8 ++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) 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 8f319c1..95fa4fe 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h @@ -391,7 +391,7 @@ dds_qset_time_based_filter ( * * @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy * @param[in] n - Number of partitions stored in ps - * @param[in[ ps - Pointer to string(s) storing partition name(s) + * @param[in] ps - Pointer to string(s) storing partition name(s) */ DDS_EXPORT void dds_qset_partition ( @@ -399,6 +399,18 @@ dds_qset_partition ( uint32_t n, const char ** __restrict ps); +/** + * @brief Convenience function to set the partition policy of a qos structure to a + * single name. Name may be a null pointer. + * + * @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy + * @param[in] name - Pointer to the name + */ +DDS_EXPORT void +dds_qset_partition1 ( + dds_qos_t * __restrict qos, + const char * __restrict name); + /** * @brief Set the reliability policy of a qos structure * diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index 25a3ce6..02988bf 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -558,6 +558,14 @@ void dds_qset_partition qos->present |= QP_PARTITION; } +void dds_qset_partition1 (dds_qos_t * __restrict qos, const char * __restrict name) +{ + if (name == NULL) + dds_qset_partition (qos, 0, NULL); + else + dds_qset_partition (qos, 1, (const char **) &name); +} + void dds_qset_reliability ( dds_qos_t * __restrict qos, From e965df5db76f7f4207740c81cdc1127e4abf2bda Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 11:21:52 +0200 Subject: [PATCH 033/178] add participant instance handle to builtin topics Extend the endpoint built-in topic data with the participant instance handle (the GUID was already present). Having the instance handle available makes it trivial to look up the participant, whereas a lookup of the GUID is rather impractical. Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/dds.h | 1 + src/core/ddsc/src/dds__serdata_builtintopic.h | 1 + src/core/ddsc/src/dds_serdata_builtintopic.c | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index 3d5dc42..d701117 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -210,6 +210,7 @@ typedef struct dds_builtintopic_endpoint { dds_builtintopic_guid_t key; dds_builtintopic_guid_t participant_key; + dds_instance_handle_t participant_instance_handle; char *topic_name; char *type_name; dds_qos_t *qos; diff --git a/src/core/ddsc/src/dds__serdata_builtintopic.h b/src/core/ddsc/src/dds__serdata_builtintopic.h index 46ccf88..6afe2d1 100644 --- a/src/core/ddsc/src/dds__serdata_builtintopic.h +++ b/src/core/ddsc/src/dds__serdata_builtintopic.h @@ -19,6 +19,7 @@ struct ddsi_serdata_builtintopic { struct ddsi_serdata c; nn_guid_t key; + dds_instance_handle_t pphandle; nn_xqos_t xqos; }; diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index b62d405..33da2ca 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -73,11 +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); + 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); + d->pphandle = proxypp->e.iid; } static void set_topic_type_from_sertopic (struct ddsi_serdata_builtintopic *d, const struct ddsi_sertopic *tp) @@ -96,12 +98,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); 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); assert (d->xqos.present & QP_TOPIC_NAME); assert (d->xqos.present & QP_TYPE_NAME); @@ -109,12 +113,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); 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); assert (d->xqos.present & QP_TOPIC_NAME); assert (d->xqos.present & QP_TYPE_NAME); @@ -219,6 +225,7 @@ static bool to_sample_endpoint (const struct ddsi_serdata_builtintopic *d, struc ppguid = d->key; ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; convkey (&sample->participant_key, &ppguid); + sample->participant_instance_handle = d->pphandle; if (d->c.kind == SDK_DATA) { assert (d->xqos.present & QP_TOPIC_NAME); From 6c171a890d733946992580a5ced9e86ef62c2476 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 16 Apr 2019 10:23:32 +0200 Subject: [PATCH 034/178] move util library into ddsrt As was the plan with the introduction of ddsrt; this includes renaming the identifiers to match the capitalization style and removes old junk. Signed-off-by: Erik Boasson --- docs/dev/modules.md | 4 - src/CMakeLists.txt | 1 - src/core/CMakeLists.txt | 7 +- src/core/ddsc/src/dds__domain.h | 2 +- src/core/ddsc/src/dds__handles.h | 4 +- src/core/ddsc/src/dds__types.h | 10 +- src/core/ddsc/src/dds_domain.c | 10 +- src/core/ddsc/src/dds_handles.c | 34 +- src/core/ddsc/src/dds_init.c | 2 +- src/core/ddsc/src/dds_reader.c | 4 +- src/core/ddsc/src/dds_rhc.c | 50 +- src/core/ddsc/src/dds_topic.c | 14 +- src/core/ddsc/src/dds_whc.c | 112 ++--- src/core/ddsc/src/dds_write.c | 4 +- .../include/dds/ddsi/ddsi_serdata_default.h | 2 +- .../ddsi/include/dds/ddsi/ddsi_sertopic.h | 4 +- src/core/ddsi/include/dds/ddsi/q_addrset.h | 6 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 44 +- src/core/ddsi/include/dds/ddsi/q_ephash.h | 4 +- src/core/ddsi/include/dds/ddsi/q_globals.h | 8 +- .../include/dds/ddsi/q_inverse_uint32_set.h | 6 +- src/core/ddsi/src/ddsi_mcgroup.c | 36 +- src/core/ddsi/src/ddsi_tcp.c | 38 +- src/core/ddsi/src/ddsi_tkmap.c | 24 +- src/core/ddsi/src/q_addrset.c | 108 ++--- src/core/ddsi/src/q_config.c | 56 +-- src/core/ddsi/src/q_ddsi_discovery.c | 4 +- src/core/ddsi/src/q_debmon.c | 18 +- src/core/ddsi/src/q_entity.c | 220 ++++----- src/core/ddsi/src/q_ephash.c | 22 +- src/core/ddsi/src/q_init.c | 10 +- src/core/ddsi/src/q_inverse_uint32_set.c | 38 +- src/core/ddsi/src/q_lease.c | 26 +- src/core/ddsi/src/q_nwif.c | 2 +- src/core/ddsi/src/q_plist.c | 2 +- src/core/ddsi/src/q_radmin.c | 172 +++---- src/core/ddsi/src/q_receive.c | 56 +-- src/core/ddsi/src/q_transmit.c | 16 +- src/core/ddsi/src/q_xevent.c | 52 +- src/core/ddsi/src/q_xmsg.c | 6 +- src/core/xtests/CMakeLists.txt | 2 +- src/ddsrt/CMakeLists.txt | 15 + src/ddsrt/include/dds/ddsrt/avl.h | 359 ++++++++++++++ .../include/dds/ddsrt/expand_envvars.h} | 8 +- src/ddsrt/include/dds/ddsrt/fibheap.h | 54 +++ src/ddsrt/include/dds/ddsrt/hopscotch.h | 104 ++++ .../include/dds/ddsrt/thread_pool.h} | 26 +- src/ddsrt/include/dds/ddsrt/xmlparser.h | 52 ++ src/{util/src/ut_avl.c => ddsrt/src/avl.c} | 452 +++++++++--------- .../src/expand_envvars.c} | 14 +- .../src/ut_fibheap.c => ddsrt/src/fibheap.c} | 92 ++-- .../ut_hopscotch.c => ddsrt/src/hopscotch.c} | 310 ++++++------ .../src/thread_pool.c} | 28 +- .../ut_xmlparser.c => ddsrt/src/xmlparser.c} | 74 +-- src/util/CMakeLists.txt | 48 -- src/util/include/dds/util/ut_avl.h | 359 -------------- src/util/include/dds/util/ut_crc.h | 31 -- src/util/include/dds/util/ut_fibheap.h | 54 --- src/util/include/dds/util/ut_hopscotch.h | 110 ----- src/util/include/dds/util/ut_xmlparser.h | 52 -- src/util/src/ut_crc.c | 74 --- src/util/tests/CMakeLists.txt | 15 - 62 files changed, 1702 insertions(+), 1869 deletions(-) create mode 100644 src/ddsrt/include/dds/ddsrt/avl.h rename src/{util/include/dds/util/ut_expand_envvars.h => ddsrt/include/dds/ddsrt/expand_envvars.h} (78%) create mode 100644 src/ddsrt/include/dds/ddsrt/fibheap.h create mode 100644 src/ddsrt/include/dds/ddsrt/hopscotch.h rename src/{util/include/dds/util/ut_thread_pool.h => ddsrt/include/dds/ddsrt/thread_pool.h} (69%) create mode 100644 src/ddsrt/include/dds/ddsrt/xmlparser.h rename src/{util/src/ut_avl.c => ddsrt/src/avl.c} (52%) rename src/{util/src/ut_expand_envvars.c => ddsrt/src/expand_envvars.c} (93%) rename src/{util/src/ut_fibheap.c => ddsrt/src/fibheap.c} (68%) rename src/{util/src/ut_hopscotch.c => ddsrt/src/hopscotch.c} (67%) rename src/{util/src/ut_thread_pool.c => ddsrt/src/thread_pool.c} (88%) rename src/{util/src/ut_xmlparser.c => ddsrt/src/xmlparser.c} (89%) delete mode 100644 src/util/CMakeLists.txt delete mode 100644 src/util/include/dds/util/ut_avl.h delete mode 100644 src/util/include/dds/util/ut_crc.h delete mode 100644 src/util/include/dds/util/ut_fibheap.h delete mode 100644 src/util/include/dds/util/ut_hopscotch.h delete mode 100644 src/util/include/dds/util/ut_xmlparser.h delete mode 100644 src/util/src/ut_crc.c delete mode 100644 src/util/tests/CMakeLists.txt diff --git a/docs/dev/modules.md b/docs/dev/modules.md index 721c7a7..435516c 100644 --- a/docs/dev/modules.md +++ b/docs/dev/modules.md @@ -22,10 +22,6 @@ but does offer a neat way to separate features logically. | | ddsi | RTPS-DDSI specification. | | | | |---------| - | | | util is a collection of snippets that do not require - | | util | per-target implementations and may be used by the ddsc - | | | and ddsi targets. util will be merged into ddsrt. - | |---------| | | ddsrt offers target agnostic implementations of | ddsrt | functionality required by the ddsc and ddsi targets, but | | also exports a subset of the dds\_ api directly. e.g. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 52a062e..cc63136 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -173,7 +173,6 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") add_subdirectory(idlc) add_subdirectory(ddsrt) add_subdirectory(etc) -add_subdirectory(util) add_subdirectory(core) add_subdirectory(tools) add_subdirectory(scripts) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 071d6e6..8f36723 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -50,16 +50,13 @@ endif() include(ddsi/CMakeLists.txt) include(ddsc/CMakeLists.txt) -target_link_libraries(ddsc PRIVATE util) target_link_libraries(ddsc PRIVATE ddsrt) target_compile_definitions( ddsc PUBLIC - $> - $>) + $>) target_include_directories( ddsc PUBLIC - $> - $>) + $>) # SOVERSION should increase on incompatible ABI change set_target_properties(ddsc PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) diff --git a/src/core/ddsc/src/dds__domain.h b/src/core/ddsc/src/dds__domain.h index d136184..0b13070 100644 --- a/src/core/ddsc/src/dds__domain.h +++ b/src/core/ddsc/src/dds__domain.h @@ -18,7 +18,7 @@ extern "C" { #endif -extern DDS_EXPORT const ut_avlTreedef_t dds_domaintree_def; +extern DDS_EXPORT const ddsrt_avl_treedef_t dds_domaintree_def; DDS_EXPORT dds_domain * dds_domain_create (dds_domainid_t id); DDS_EXPORT void dds_domain_free (dds_domain * domain); diff --git a/src/core/ddsc/src/dds__handles.h b/src/core/ddsc/src/dds__handles.h index 7ceee26..c13bc59 100644 --- a/src/core/ddsc/src/dds__handles.h +++ b/src/core/ddsc/src/dds__handles.h @@ -94,9 +94,9 @@ dds_handle_server_fini(void); * user data. * * A kind value != 0 has to be provided, just to make sure that no 0 handles - * will be created. It should also fit the UT_HANDLE_KIND_MASK. + * will be created. It should also fit the DDSRT_HANDLE_KIND_MASK. * In other words handle creation will fail if - * ((kind & ~UT_HANDLE_KIND_MASK != 0) || (kind & UT_HANDLE_KIND_MASK == 0)). + * ((kind & ~DDSRT_HANDLE_KIND_MASK != 0) || (kind & DDSRT_HANDLE_KIND_MASK == 0)). * * It has to do something clever to make sure that a deleted handle is not * re-issued very quickly after it was deleted. diff --git a/src/core/ddsc/src/dds__types.h b/src/core/ddsc/src/dds__types.h index 187aee4..61c7c57 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/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds__handles.h" #if defined (__cplusplus) @@ -94,9 +94,9 @@ struct dds_listener { typedef struct dds_domain { - ut_avlNode_t m_node; + ddsrt_avl_node_t m_node; dds_domainid_t m_id; - ut_avlTree_t m_topics; + ddsrt_avl_tree_t m_topics; uint32_t m_refc; } dds_domain; @@ -151,7 +151,7 @@ typedef struct dds_entity } dds_entity; -extern const ut_avlTreedef_t dds_topictree_def; +extern const ddsrt_avl_treedef_t dds_topictree_def; typedef struct dds_subscriber { @@ -283,7 +283,7 @@ typedef struct dds_globals int (*m_dur_wait) (struct dds_reader * reader, dds_duration_t timeout); void (*m_dur_init) (void); void (*m_dur_fini) (void); - ut_avlTree_t m_domains; + ddsrt_avl_tree_t m_domains; ddsrt_mutex_t m_mutex; } dds_globals; diff --git a/src/core/ddsc/src/dds_domain.c b/src/core/ddsc/src/dds_domain.c index f2dfaa4..b8c12d8 100644 --- a/src/core/ddsc/src/dds_domain.c +++ b/src/core/ddsc/src/dds_domain.c @@ -17,7 +17,7 @@ static int dds_domain_compare (const int32_t * a, const int32_t * b) return (*a == *b) ? 0 : (*a < *b) ? -1 : 1; } -const ut_avlTreedef_t dds_domaintree_def = UT_AVL_TREEDEF_INITIALIZER +const ddsrt_avl_treedef_t dds_domaintree_def = DDSRT_AVL_TREEDEF_INITIALIZER ( offsetof (dds_domain, m_node), offsetof (dds_domain, m_id), @@ -27,7 +27,7 @@ const ut_avlTreedef_t dds_domaintree_def = UT_AVL_TREEDEF_INITIALIZER dds_domain * dds_domain_find_locked (dds_domainid_t id) { - return ut_avlLookup (&dds_domaintree_def, &dds_global.m_domains, &id); + return ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &id); } dds_domain * dds_domain_create (dds_domainid_t id) @@ -39,8 +39,8 @@ dds_domain * dds_domain_create (dds_domainid_t id) { domain = dds_alloc (sizeof (*domain)); domain->m_id = id; - ut_avlInit (&dds_topictree_def, &domain->m_topics); - ut_avlInsert (&dds_domaintree_def, &dds_global.m_domains, domain); + ddsrt_avl_init (&dds_topictree_def, &domain->m_topics); + ddsrt_avl_insert (&dds_domaintree_def, &dds_global.m_domains, domain); } domain->m_refc++; ddsrt_mutex_unlock (&dds_global.m_mutex); @@ -52,7 +52,7 @@ void dds_domain_free (dds_domain * domain) ddsrt_mutex_lock (&dds_global.m_mutex); if (--domain->m_refc == 0) { - ut_avlDelete (&dds_domaintree_def, &dds_global.m_domains, domain); + ddsrt_avl_delete (&dds_domaintree_def, &dds_global.m_domains, domain); dds_free (domain); } ddsrt_mutex_unlock (&dds_global.m_mutex); diff --git a/src/core/ddsc/src/dds_handles.c b/src/core/ddsc/src/dds_handles.c index 560e661..dd509dd 100644 --- a/src/core/ddsc/src/dds_handles.c +++ b/src/core/ddsc/src/dds_handles.c @@ -15,7 +15,7 @@ #include "dds/ddsrt/sync.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/random.h" -#include "dds/util/ut_hopscotch.h" +#include "dds/ddsrt/hopscotch.h" #include "dds/ddsi/q_thread.h" #include "dds__handles.h" #include "dds__types.h" @@ -40,9 +40,9 @@ struct dds_handle_server { #if USE_CHH - struct ut_chh *ht; + struct ddsrt_chh *ht; #else - struct ut_hh *ht; + struct ddsrt_hh *ht; #endif size_t count; ddsrt_mutex_t lock; @@ -68,9 +68,9 @@ static int handle_equal (const void *va, const void *vb) dds_return_t dds_handle_server_init (void (*free_via_gc) (void *x)) { #if USE_CHH - handles.ht = ut_chhNew (128, handle_hash, handle_equal, free_via_gc); + handles.ht = ddsrt_chh_new (128, handle_hash, handle_equal, free_via_gc); #else - handles.ht = ut_hhNew (128, handle_hash, handle_equal); + handles.ht = ddsrt_hh_new (128, handle_hash, handle_equal); (void) free_via_gc; #endif handles.count = 0; @@ -83,16 +83,16 @@ void dds_handle_server_fini (void) { #if USE_CHH #ifndef NDEBUG - struct ut_chhIter it; - assert (ut_chhIterFirst (handles.ht, &it) == NULL); + struct ddsrt_chh_iter it; + assert (ddsrt_chh_iter_first (handles.ht, &it) == NULL); #endif - ut_chhFree (handles.ht); + ddsrt_chh_free (handles.ht); #else /* USE_CHH */ #ifndef NDEBUG - struct ut_hhIter it; - assert (ut_hhIterFirst (handles.ht, &it) == NULL); + struct ddsrt_hh_iter it; + assert (ddsrt_hh_iter_first (handles.ht, &it) == NULL); #endif - ut_hhFree (handles.ht); + ddsrt_hh_free (handles.ht); #endif /* USE_CHH */ ddsrt_cond_destroy (&handles.cond); ddsrt_mutex_destroy (&handles.lock); @@ -100,9 +100,9 @@ void dds_handle_server_fini (void) } #if USE_CHH -static bool hhadd (struct ut_chh *ht, void *elem) { return ut_chhAdd (ht, elem); } +static bool hhadd (struct ddsrt_chh *ht, void *elem) { return ddsrt_chh_add (ht, elem); } #else -static bool hhadd (struct ut_hh *ht, void *elem) { return ut_hhAdd (ht, elem); } +static bool hhadd (struct ddsrt_hh *ht, void *elem) { return ddsrt_hh_add (ht, elem); } #endif static dds_handle_t dds_handle_create_int (struct dds_handle_link *link) { @@ -176,10 +176,10 @@ int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout) } #if USE_CHH thread_state_awake (ts1); - int x = ut_chhRemove (handles.ht, link); + int x = ddsrt_chh_remove (handles.ht, link); thread_state_asleep (ts1); #else - int x = ut_hhRemove (handles.ht, link); + int x = ddsrt_hh_remove (handles.ht, link); #endif assert(x); (void)x; @@ -209,10 +209,10 @@ int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) #if USE_CHH thread_state_awake (ts1); - *link = ut_chhLookup (handles.ht, &dummy); + *link = ddsrt_chh_lookup (handles.ht, &dummy); #else ddsrt_mutex_lock (&handles.lock); - *link = ut_hhLookup (handles.ht, &dummy); + *link = ddsrt_hh_lookup (handles.ht, &dummy); #endif if (*link == NULL) rc = DDS_RETCODE_BAD_PARAMETER; diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index e6558d5..d51bfb0 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -123,7 +123,7 @@ dds_init(dds_domainid_t domain) } upgrade_main_thread(); - ut_avlInit(&dds_domaintree_def, &dds_global.m_domains); + ddsrt_avl_init(&dds_domaintree_def, &dds_global.m_domains); /* Start monitoring the liveliness of all threads. */ if (!config.liveliness_monitoring) diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index b039495..10951e2 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -532,14 +532,14 @@ void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb rd->ddsi2direct_cb = cb; rd->ddsi2direct_cbarg = cbarg; - while ((m = ut_avlLookupSuccEq (&rd_writers_treedef, &rd->writers, &pwrguid)) != NULL) + while ((m = ddsrt_avl_lookup_succ_eq (&rd_writers_treedef, &rd->writers, &pwrguid)) != NULL) { /* have to be careful walking the tree -- pretty is different, but I want to check this before I write a lookup_succ function. */ struct rd_pwr_match *m_next; nn_guid_t pwrguid_next; pwrguid = m->pwr_guid; - if ((m_next = ut_avlFindSucc (&rd_writers_treedef, &rd->writers, m)) != NULL) + if ((m_next = ddsrt_avl_find_succ (&rd_writers_treedef, &rd->writers, m)) != NULL) pwrguid_next = m_next->pwr_guid; else { diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 4eb64dc..74133c0 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -27,8 +27,8 @@ #include "dds__reader.h" #include "dds__rhc.h" #include "dds/ddsi/ddsi_tkmap.h" -#include "dds/util/ut_hopscotch.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/hopscotch.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_xqos.h" #include "dds/ddsi/q_error.h" #include "dds/ddsi/q_unused.h" @@ -174,7 +174,7 @@ struct lwreg struct lwregs { - struct ut_ehh * regs; + struct ddsrt_ehh * regs; }; static uint32_t lwreg_hash (const void *vl) @@ -192,36 +192,36 @@ static int lwreg_equals (const void *va, const void *vb) static void lwregs_init (struct lwregs *rt) { - rt->regs = ut_ehhNew (sizeof (struct lwreg), 1, lwreg_hash, lwreg_equals); + rt->regs = ddsrt_ehh_new (sizeof (struct lwreg), 1, lwreg_hash, lwreg_equals); } static void lwregs_fini (struct lwregs *rt) { - ut_ehhFree (rt->regs); + ddsrt_ehh_free (rt->regs); } static int lwregs_contains (struct lwregs *rt, uint64_t iid, uint64_t wr_iid) { struct lwreg dummy = { .iid = iid, .wr_iid = wr_iid }; - return ut_ehhLookup (rt->regs, &dummy) != NULL; + return ddsrt_ehh_lookup (rt->regs, &dummy) != NULL; } static int lwregs_add (struct lwregs *rt, uint64_t iid, uint64_t wr_iid) { struct lwreg dummy = { .iid = iid, .wr_iid = wr_iid }; - return ut_ehhAdd (rt->regs, &dummy); + return ddsrt_ehh_add (rt->regs, &dummy); } static int lwregs_delete (struct lwregs *rt, uint64_t iid, uint64_t wr_iid) { struct lwreg dummy = { .iid = iid, .wr_iid = wr_iid }; - return ut_ehhRemove (rt->regs, &dummy); + return ddsrt_ehh_remove (rt->regs, &dummy); } void lwregs_dump (struct lwregs *rt) { - struct ut_ehhIter it; - for (struct lwreg *r = ut_ehhIterFirst(rt->regs, &it); r; r = ut_ehhIterNext(&it)) + struct ddsrt_ehh_iter it; + for (struct lwreg *r = ddsrt_ehh_iter_first(rt->regs, &it); r; r = ddsrt_ehh_iter_next(&it)) printf("iid=%"PRIu64" wr_iid=%"PRIu64"\n", r->iid, r->wr_iid); } @@ -271,7 +271,7 @@ typedef enum rhc_store_result { } rhc_store_result_t; struct rhc { - struct ut_hh *instances; + struct ddsrt_hh *instances; struct rhc_instance *nonempty_instances; /* circular, points to most recently added one, NULL if none */ struct lwregs registrations; /* should be a global one (with lock-free lookups) */ @@ -458,7 +458,7 @@ struct rhc * dds_rhc_new (dds_reader * reader, const struct ddsi_sertopic * topi lwregs_init (&rhc->registrations); ddsrt_mutex_init (&rhc->lock); - rhc->instances = ut_hhNew (1, instance_iid_hash, instance_iid_eq); + rhc->instances = ddsrt_hh_new (1, instance_iid_hash, instance_iid_eq); rhc->topic = topic; rhc->reader = reader; @@ -620,9 +620,9 @@ static void free_instance_rhc_free_wrap (void *vnode, void *varg) void dds_rhc_free (struct rhc *rhc) { assert (rhc_check_counts_locked (rhc, true, true)); - ut_hhEnum (rhc->instances, free_instance_rhc_free_wrap, rhc); + ddsrt_hh_enum (rhc->instances, free_instance_rhc_free_wrap, rhc); assert (rhc->nonempty_instances == NULL); - ut_hhFree (rhc->instances); + ddsrt_hh_free (rhc->instances); lwregs_fini (&rhc->registrations); if (rhc->qcond_eval_samplebuf != NULL) ddsi_sertopic_free_sample (rhc->topic, rhc->qcond_eval_samplebuf, DDS_FREE_ALL); @@ -848,7 +848,7 @@ static void drop_instance_noupdate_no_writers (struct rhc *rhc, struct rhc_insta rhc->n_instances--; - ret = ut_hhRemove (rhc->instances, inst); + ret = ddsrt_hh_remove (rhc->instances, inst); assert (ret); (void) ret; @@ -1198,7 +1198,7 @@ static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst } account_for_empty_to_nonempty_transition (rhc, inst); - ret = ut_hhAdd (rhc->instances, inst); + ret = ddsrt_hh_add (rhc->instances, inst); assert (ret); (void) ret; rhc->n_instances++; @@ -1248,7 +1248,7 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info ddsrt_mutex_lock (&rhc->lock); - inst = ut_hhLookup (rhc->instances, &dummy_instance); + inst = ddsrt_hh_lookup (rhc->instances, &dummy_instance); if (inst == NULL) { /* New instance for this reader. If no data content -- not (also) @@ -1492,13 +1492,13 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ bool trigger_waitsets = false; bool notify_data_available = false; struct rhc_instance *inst; - struct ut_hhIter iter; + struct ddsrt_hh_iter iter; const uint64_t wr_iid = pwr_info->iid; const int auto_dispose = pwr_info->auto_dispose; ddsrt_mutex_lock (&rhc->lock); TRACE ("rhc_unregister_wr_iid(%"PRIx64",%d:\n", wr_iid, auto_dispose); - for (inst = ut_hhIterFirst (rhc->instances, &iter); inst; inst = ut_hhIterNext (&iter)) + for (inst = ddsrt_hh_iter_first (rhc->instances, &iter); inst; inst = ddsrt_hh_iter_next (&iter)) { if ((inst->wr_iid_islive && inst->wr_iid == wr_iid) || lwregs_contains (&rhc->registrations, inst->iid, wr_iid)) { @@ -1558,10 +1558,10 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ void dds_rhc_relinquish_ownership (struct rhc * __restrict rhc, const uint64_t wr_iid) { struct rhc_instance *inst; - struct ut_hhIter iter; + struct ddsrt_hh_iter iter; ddsrt_mutex_lock (&rhc->lock); TRACE ("rhc_relinquish_ownership(%"PRIx64":\n", wr_iid); - for (inst = ut_hhIterFirst (rhc->instances, &iter); inst; inst = ut_hhIterNext (&iter)) + for (inst = ddsrt_hh_iter_first (rhc->instances, &iter); inst; inst = ddsrt_hh_iter_next (&iter)) { if (inst->wr_iid_islive && inst->wr_iid == wr_iid) { @@ -2234,7 +2234,7 @@ bool dds_rhc_add_readcondition (dds_readcond *cond) between those attached to a waitset or not. */ struct rhc *rhc = cond->m_rhc; - struct ut_hhIter it; + struct ddsrt_hh_iter it; assert ((dds_entity_kind (&cond->m_entity) == DDS_KIND_COND_READ && cond->m_query.m_filter == 0) || (dds_entity_kind (&cond->m_entity) == DDS_KIND_COND_QUERY && cond->m_query.m_filter != 0)); @@ -2296,7 +2296,7 @@ bool dds_rhc_add_readcondition (dds_readcond *cond) samples, except for those that match the predicate. */ const dds_querycond_mask_t qcmask = cond->m_query.m_qcmask; uint32_t trigger = 0; - for (struct rhc_instance *inst = ut_hhIterFirst (rhc->instances, &it); inst != NULL; inst = ut_hhIterNext (&it)) + for (struct rhc_instance *inst = ddsrt_hh_iter_first (rhc->instances, &it); inst != NULL; inst = ddsrt_hh_iter_next (&it)) { const bool instmatch = eval_predicate_invsample (rhc, inst, cond->m_query.m_filter);; uint32_t matches = 0; @@ -2612,7 +2612,7 @@ static int rhc_check_counts_locked (struct rhc *rhc, bool check_conds, bool chec unsigned cond_match_count[CHECK_MAX_CONDS]; dds_querycond_mask_t enabled_qcmask = 0; struct rhc_instance *inst; - struct ut_hhIter iter; + struct ddsrt_hh_iter iter; dds_readcond *rciter; uint32_t i; @@ -2628,7 +2628,7 @@ static int rhc_check_counts_locked (struct rhc *rhc, bool check_conds, bool chec enabled_qcmask |= rciter->m_query.m_qcmask; } - for (inst = ut_hhIterFirst (rhc->instances, &iter); inst; inst = ut_hhIterNext (&iter)) + for (inst = ddsrt_hh_iter_first (rhc->instances, &iter); inst; inst = ddsrt_hh_iter_next (&iter)) { unsigned n_vsamples_in_instance = 0, n_read_vsamples_in_instance = 0; bool a_sample_free = true; diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 1561afd..636c4ae 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -32,7 +32,7 @@ DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_topic) #define DDS_TOPIC_STATUS_MASK \ DDS_INCONSISTENT_TOPIC_STATUS -const ut_avlTreedef_t dds_topictree_def = UT_AVL_TREEDEF_INITIALIZER_INDKEY +const ddsrt_avl_treedef_t dds_topictree_def = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY ( offsetof (struct ddsi_sertopic, avlnode), offsetof (struct ddsi_sertopic, name_typename), @@ -118,17 +118,17 @@ dds_topic_lookup_locked( const char *name) { struct ddsi_sertopic *st = NULL; - ut_avlIter_t iter; + ddsrt_avl_iter_t iter; assert (domain); assert (name); - st = ut_avlIterFirst (&dds_topictree_def, &domain->m_topics, &iter); + st = ddsrt_avl_iter_first (&dds_topictree_def, &domain->m_topics, &iter); while (st) { if (strcmp (st->name, name) == 0) { break; } - st = ut_avlIterNext (&iter); + st = ddsrt_avl_iter_next (&iter); } return st; } @@ -155,9 +155,9 @@ dds_topic_free( assert (st); ddsrt_mutex_lock (&dds_global.m_mutex); - domain = ut_avlLookup (&dds_domaintree_def, &dds_global.m_domains, &domainid); + domain = ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &domainid); if (domain != NULL) { - ut_avlDelete (&dds_topictree_def, &domain->m_topics, st); + ddsrt_avl_delete (&dds_topictree_def, &domain->m_topics, st); } ddsrt_mutex_unlock (&dds_global.m_mutex); st->status_cb_entity = NULL; @@ -172,7 +172,7 @@ dds_topic_add_locked( dds_domain * dom; dom = dds_domain_find_locked (id); assert (dom); - ut_avlInsert (&dds_topictree_def, &dom->m_topics, st); + ddsrt_avl_insert (&dds_topictree_def, &dom->m_topics, st); } DDS_EXPORT dds_entity_t diff --git a/src/core/ddsc/src/dds_whc.c b/src/core/ddsc/src/dds_whc.c index 1301ef9..5408c69 100644 --- a/src/core/ddsc/src/dds_whc.c +++ b/src/core/ddsc/src/dds_whc.c @@ -22,8 +22,8 @@ #include "dds__whc.h" #include "dds/ddsi/ddsi_tkmap.h" -#include "dds/util/ut_avl.h" -#include "dds/util/ut_hopscotch.h" +#include "dds/ddsrt/avl.h" +#include "dds/ddsrt/hopscotch.h" #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_freelist.h" @@ -47,7 +47,7 @@ struct whc_node { }; struct whc_intvnode { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; seqno_t min; seqno_t maxp1; struct whc_node *first; /* linked list of seqs with contiguous sequence numbers [min,maxp1) */ @@ -89,12 +89,12 @@ struct whc_impl { struct whc_node *maxseq_node; /* NULL if empty; if not in open_intv, open_intv is empty */ struct nn_freelist freelist; /* struct whc_node *; linked via whc_node::next_seq */ #if USE_EHH - struct ut_ehh *seq_hash; + struct ddsrt_ehh *seq_hash; #else - struct ut_hh *seq_hash; + struct ddsrt_hh *seq_hash; #endif - struct ut_hh *idx_hash; - ut_avlTree_t seq; + struct ddsrt_hh *idx_hash; + ddsrt_avl_tree_t seq; }; struct whc_sample_iter_impl { @@ -140,8 +140,8 @@ static void whc_default_sample_iter_init (const struct whc *whc, struct whc_samp static bool whc_default_sample_iter_borrow_next (struct whc_sample_iter *opaque_it, struct whc_borrowed_sample *sample); static void whc_default_free (struct whc *whc); -static const ut_avlTreedef_t whc_seq_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct whc_intvnode, avlnode), offsetof (struct whc_intvnode, min), compare_seq, 0); +static const ddsrt_avl_treedef_t whc_seq_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct whc_intvnode, avlnode), offsetof (struct whc_intvnode, min), compare_seq, 0); static const struct whc_ops whc_ops = { .insert = whc_default_insert, @@ -225,7 +225,7 @@ static struct whc_node *whc_findmax_procedurally (const struct whc_impl *whc) } else { - struct whc_intvnode *intv = ut_avlFindPred (&whc_seq_treedef, &whc->seq, whc->open_intv); + struct whc_intvnode *intv = ddsrt_avl_find_pred (&whc_seq_treedef, &whc->seq, whc->open_intv); assert (intv && intv->first); return intv->last; } @@ -239,8 +239,8 @@ static void check_whc (const struct whc_impl *whc) contiguous; all samples in seq & in seqhash; tlidx \subseteq seq; seq-number ordered list correct; &c. */ assert (whc->open_intv != NULL); - assert (whc->open_intv == ut_avlFindMax (&whc_seq_treedef, &whc->seq)); - assert (ut_avlFindSucc (&whc_seq_treedef, &whc->seq, whc->open_intv) == NULL); + assert (whc->open_intv == ddsrt_avl_find_max (&whc_seq_treedef, &whc->seq)); + assert (ddsrt_avl_find_succ (&whc_seq_treedef, &whc->seq, whc->open_intv) == NULL); if (whc->maxseq_node) { assert (whc->maxseq_node->next_seq == NULL); @@ -264,7 +264,7 @@ static void check_whc (const struct whc_impl *whc) struct whc_intvnode *firstintv; struct whc_node *cur; seqno_t prevseq = 0; - firstintv = ut_avlFindMin (&whc_seq_treedef, &whc->seq); + firstintv = ddsrt_avl_find_min (&whc_seq_treedef, &whc->seq); assert (firstintv); cur = firstintv->first; while (cur) @@ -283,10 +283,10 @@ static void insert_whcn_in_hash (struct whc_impl *whc, struct whc_node *whcn) /* precondition: whcn is not in hash */ #if USE_EHH struct whc_seq_entry e = { .seq = whcn->seq, .whcn = whcn }; - if (!ut_ehhAdd (whc->seq_hash, &e)) + if (!ddsrt_ehh_add (whc->seq_hash, &e)) assert(0); #else - if (!ut_hhAdd (whc->seq_hash, whcn)) + if (!ddsrt_hh_add (whc->seq_hash, whcn)) assert(0); #endif } @@ -296,10 +296,10 @@ static void remove_whcn_from_hash (struct whc_impl *whc, struct whc_node *whcn) /* precondition: whcn is in hash */ #if USE_EHH struct whc_seq_entry e = { .seq = whcn->seq }; - if (!ut_ehhRemove(whc->seq_hash, &e)) + if (!ddsrt_ehh_remove(whc->seq_hash, &e)) assert(0); #else - if (!ut_hhRemove(whc->seq_hash, whcn)) + if (!ddsrt_hh_remove(whc->seq_hash, whcn)) assert(0); #endif } @@ -308,14 +308,14 @@ static struct whc_node *whc_findseq (const struct whc_impl *whc, seqno_t seq) { #if USE_EHH struct whc_seq_entry e = { .seq = seq }, *r; - if ((r = ut_ehhLookup(whc->seq_hash, &e)) != NULL) + if ((r = ddsrt_ehh_lookup(whc->seq_hash, &e)) != NULL) return r->whcn; else return NULL; #else struct whc_node template; template.seq = seq; - return ut_hhLookup(whc->seq_hash, &template); + return ddsrt_hh_lookup(whc->seq_hash, &template); #endif } @@ -328,7 +328,7 @@ static struct whc_node *whc_findkey (const struct whc_impl *whc, const struct dd struct whc_idxnode *n; check_whc (whc); template.idxn.iid = ddsi_tkmap_lookup(gv.m_tkmap, serdata_key); - n = ut_hhLookup (whc->idx_hash, &template.idxn); + n = ddsrt_hh_lookup (whc->idx_hash, &template.idxn); if (n == NULL) return NULL; else @@ -359,22 +359,22 @@ struct whc *whc_new (int is_transient_local, unsigned hdepth, unsigned tldepth) whc->total_bytes = 0; whc->sample_overhead = sample_overhead; #if USE_EHH - whc->seq_hash = ut_ehhNew (sizeof (struct whc_seq_entry), 32, whc_seq_entry_hash, whc_seq_entry_eq); + whc->seq_hash = ddsrt_ehh_new (sizeof (struct whc_seq_entry), 32, whc_seq_entry_hash, whc_seq_entry_eq); #else - whc->seq_hash = ut_hhNew(32, whc_node_hash, whc_node_eq); + whc->seq_hash = ddsrt_hh_new(32, whc_node_hash, whc_node_eq); #endif if (whc->idxdepth > 0) - whc->idx_hash = ut_hhNew(32, whc_idxnode_hash_key, whc_idxnode_eq_key); + whc->idx_hash = ddsrt_hh_new(32, whc_idxnode_hash_key, whc_idxnode_eq_key); else whc->idx_hash = NULL; /* seq interval tree: always has an "open" node */ - ut_avlInit (&whc_seq_treedef, &whc->seq); + ddsrt_avl_init (&whc_seq_treedef, &whc->seq); intv = ddsrt_malloc (sizeof (*intv)); intv->min = intv->maxp1 = 1; intv->first = intv->last = NULL; - ut_avlInsert (&whc_seq_treedef, &whc->seq, intv); + ddsrt_avl_insert (&whc_seq_treedef, &whc->seq, intv); whc->open_intv = intv; whc->maxseq_node = NULL; @@ -402,11 +402,11 @@ void whc_default_free (struct whc *whc_generic) if (whc->idx_hash) { - struct ut_hhIter it; + struct ddsrt_hh_iter it; struct whc_idxnode *n; - for (n = ut_hhIterFirst(whc->idx_hash, &it); n != NULL; n = ut_hhIterNext(&it)) + for (n = ddsrt_hh_iter_first(whc->idx_hash, &it); n != NULL; n = ddsrt_hh_iter_next(&it)) ddsrt_free(n); - ut_hhFree(whc->idx_hash); + ddsrt_hh_free(whc->idx_hash); } { @@ -423,13 +423,13 @@ DDSRT_WARNING_MSVC_ON(6001); } } - ut_avlFree (&whc_seq_treedef, &whc->seq, ddsrt_free); + ddsrt_avl_free (&whc_seq_treedef, &whc->seq, ddsrt_free); nn_freelist_fini (&whc->freelist, ddsrt_free); #if USE_EHH - ut_ehhFree (whc->seq_hash); + ddsrt_ehh_free (whc->seq_hash); #else - ut_hhFree (whc->seq_hash); + ddsrt_hh_free (whc->seq_hash); #endif ddsrt_mutex_destroy (&whc->lock); ddsrt_free (whc); @@ -445,7 +445,7 @@ static void get_state_locked(const struct whc_impl *whc, struct whc_state *st) else { const struct whc_intvnode *intv; - intv = ut_avlFindMin (&whc_seq_treedef, &whc->seq); + intv = ddsrt_avl_find_min (&whc_seq_treedef, &whc->seq); /* not empty, open node may be anything but is (by definition) findmax, and whc is claimed to be non-empty, so min interval can't be empty */ @@ -476,12 +476,12 @@ static struct whc_node *find_nextseq_intv (struct whc_intvnode **p_intv, const s SEQ < Y can't exist */ #ifndef NDEBUG { - struct whc_intvnode *predintv = ut_avlLookupPredEq (&whc_seq_treedef, &whc->seq, &seq); + struct whc_intvnode *predintv = ddsrt_avl_lookup_pred_eq (&whc_seq_treedef, &whc->seq, &seq); assert (predintv == NULL || predintv->maxp1 <= seq); } #endif - if ((intv = ut_avlLookupSuccEq (&whc_seq_treedef, &whc->seq, &seq)) == NULL) { - assert (ut_avlLookupPredEq (&whc_seq_treedef, &whc->seq, &seq) == whc->open_intv); + if ((intv = ddsrt_avl_lookup_succ_eq (&whc_seq_treedef, &whc->seq, &seq)) == NULL) { + assert (ddsrt_avl_lookup_pred_eq (&whc_seq_treedef, &whc->seq, &seq) == whc->open_intv); return NULL; } else if (intv->min < intv->maxp1) { /* only if not empty interval */ assert (intv->min > seq); @@ -502,7 +502,7 @@ static struct whc_node *find_nextseq_intv (struct whc_intvnode **p_intv, const s assert (whc->maxseq_node != NULL); assert (n->seq < whc->maxseq_node->seq); n = n->next_seq; - *p_intv = ut_avlLookupPredEq (&whc_seq_treedef, &whc->seq, &n->seq); + *p_intv = ddsrt_avl_lookup_pred_eq (&whc_seq_treedef, &whc->seq, &n->seq); return n; } } @@ -538,7 +538,7 @@ static void delete_one_sample_from_idx (struct whc_impl *whc, struct whc_node *w for (i = 0; i < whc->idxdepth; i++) assert (i == idxn->headidx || idxn->hist[i] == NULL); #endif - if (!ut_hhRemove (whc->idx_hash, idxn)) + if (!ddsrt_hh_remove (whc->idx_hash, idxn)) assert (0); ddsi_tkmap_instance_unref(idxn->tk); ddsrt_free (idxn); @@ -568,7 +568,7 @@ static void free_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_s static void delete_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_idxnode *idxn) { - if (!ut_hhRemove (whc->idx_hash, idxn)) + if (!ddsrt_hh_remove (whc->idx_hash, idxn)) assert (0); free_one_instance_from_idx (whc, max_drop_seq, idxn); } @@ -612,11 +612,11 @@ static unsigned whc_default_downgrade_to_volatile (struct whc *whc_generic, stru whc->tldepth = 0; if (whc->hdepth == 0) { - struct ut_hhIter it; + struct ddsrt_hh_iter it; struct whc_idxnode *n; - for (n = ut_hhIterFirst(whc->idx_hash, &it); n != NULL; n = ut_hhIterNext(&it)) + 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); - ut_hhFree(whc->idx_hash); + ddsrt_hh_free(whc->idx_hash); whc->idxdepth = 0; whc->idx_hash = NULL; } @@ -680,9 +680,9 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i if (whcn == intv->last && intv != whc->open_intv) { struct whc_intvnode *tmp = intv; - *p_intv = ut_avlFindSucc (&whc_seq_treedef, &whc->seq, intv); + *p_intv = ddsrt_avl_find_succ (&whc_seq_treedef, &whc->seq, intv); /* only sample in interval and not the open interval => delete interval */ - ut_avlDelete (&whc_seq_treedef, &whc->seq, tmp); + ddsrt_avl_delete (&whc_seq_treedef, &whc->seq, tmp); ddsrt_free (tmp); } else @@ -703,7 +703,7 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i assert (whcn->prev_seq->seq + 1 == whcn->seq); intv->last = whcn->prev_seq; intv->maxp1--; - *p_intv = ut_avlFindSucc (&whc_seq_treedef, &whc->seq, intv); + *p_intv = ddsrt_avl_find_succ (&whc_seq_treedef, &whc->seq, intv); } else { @@ -712,7 +712,7 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i issue only, and so we can (for now) get away with splitting it greedily */ struct whc_intvnode *new_intv; - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; new_intv = ddsrt_malloc (sizeof (*new_intv)); @@ -730,9 +730,9 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i /* insert new node & continue the loop with intv set to the new interval */ - if (ut_avlLookupIPath (&whc_seq_treedef, &whc->seq, &new_intv->min, &path) != NULL) + if (ddsrt_avl_lookup_ipath (&whc_seq_treedef, &whc->seq, &new_intv->min, &path) != NULL) assert (0); - ut_avlInsertIPath (&whc_seq_treedef, &whc->seq, new_intv, &path); + ddsrt_avl_insert_ipath (&whc_seq_treedef, &whc->seq, new_intv, &path); if (intv == whc->open_intv) whc->open_intv = new_intv; @@ -744,7 +744,7 @@ static void whc_delete_one (struct whc_impl *whc, struct whc_node *whcn) { struct whc_intvnode *intv; struct whc_node *whcn_tmp = whcn; - intv = ut_avlLookupPredEq (&whc_seq_treedef, &whc->seq, &whcn->seq); + intv = ddsrt_avl_lookup_pred_eq (&whc_seq_treedef, &whc->seq, &whcn->seq); assert (intv != NULL); whc_delete_one_intv (whc, &intv, &whcn); if (whcn_tmp->prev_seq) @@ -804,7 +804,7 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s #ifndef NDEBUG whcn = find_nextseq_intv (&intv, whc, whc->max_drop_seq); assert (whcn == NULL || whcn->prev_seq == NULL); - assert (ut_avlIsSingleton (&whc->seq)); + assert (ddsrt_avl_is_singleton (&whc->seq)); #endif intv = whc->open_intv; @@ -894,7 +894,7 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se } if (whcn == intv->last) - intv = ut_avlFindSucc (&whc_seq_treedef, &whc->seq, intv); + intv = ddsrt_avl_find_succ (&whc_seq_treedef, &whc->seq, intv); if (prev_seq) prev_seq->next_seq = whcn; whcn->prev_seq = prev_seq; @@ -975,7 +975,7 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se DDS_LOG(DDS_LC_WHC, " del %p %"PRId64, (void *) oldn, oldn->seq); whc_delete_one (whc, oldn); #ifndef NDEBUG - assert(ut_hhLookup(whc->idx_hash, &template) == idxn); + assert(ddsrt_hh_lookup(whc->idx_hash, &template) == idxn); ddsi_serdata_unref(whcn_template.serdata); #endif } @@ -1069,14 +1069,14 @@ static struct whc_node *whc_default_insert_seq (struct whc_impl *whc, seqno_t ma { /* gap => need new open_intv */ struct whc_intvnode *intv1; - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; intv1 = ddsrt_malloc (sizeof (*intv1)); intv1->min = seq; intv1->maxp1 = seq + 1; intv1->first = intv1->last = newn; - if (ut_avlLookupIPath (&whc_seq_treedef, &whc->seq, &seq, &path) != NULL) + if (ddsrt_avl_lookup_ipath (&whc_seq_treedef, &whc->seq, &seq, &path) != NULL) assert (0); - ut_avlInsertIPath (&whc_seq_treedef, &whc->seq, intv1, &path); + ddsrt_avl_insert_ipath (&whc_seq_treedef, &whc->seq, intv1, &path); whc->open_intv = intv1; } @@ -1128,7 +1128,7 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se } template.idxn.iid = tk->m_iid; - if ((idxn = ut_hhLookup (whc->idx_hash, &template)) != NULL) + if ((idxn = ddsrt_hh_lookup (whc->idx_hash, &template)) != NULL) { /* Unregisters cause deleting of index entry, non-unregister of adding/overwriting in history */ DDS_LOG(DDS_LC_WHC, " idxn %p", (void *)idxn); @@ -1203,7 +1203,7 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se idxn->hist[i] = NULL; newn->idxnode = idxn; newn->idxnode_pos = 0; - if (!ut_hhAdd (whc->idx_hash, idxn)) + if (!ddsrt_hh_add (whc->idx_hash, idxn)) assert (0); } else diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 3c1526c..98a590b 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -123,14 +123,14 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay 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. */ - ut_avlIter_t it; + ddsrt_avl_iter_t it; struct pwr_rd_match *m; struct proxy_writer_info pwr_info; dds_duration_t max_block_ms = nn_from_ddsi_duration (wr->xqos->reliability.max_blocking_time); ddsrt_mutex_unlock (&wr->rdary.rdary_lock); make_proxy_writer_info (&pwr_info, &wr->e, wr->xqos); ddsrt_mutex_lock (&wr->e.lock); - for (m = ut_avlIterFirst (&wr_local_readers_treedef, &wr->local_readers, &it); m != NULL; m = ut_avlIterNext (&it)) + 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 = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) 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 403a1c0..7775e1c 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -15,7 +15,7 @@ #include "dds/ddsrt/endian.h" #include "dds/ddsi/q_plist.h" /* for nn_prismtech_writer_info */ #include "dds/ddsi/q_freelist.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_sertopic.h" diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h index 2b48ad5..edd0b02 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h @@ -13,7 +13,7 @@ #define DDSI_SERTOPIC_H #include "dds/ddsrt/atomics.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsc/dds_public_alloc.h" struct ddsi_serdata; @@ -25,7 +25,7 @@ typedef void (*topic_cb_t) (struct dds_topic * topic); struct ddsi_sertopic_ops; struct ddsi_sertopic { - ut_avlNode_t avlnode; /* index on name_typename */ + ddsrt_avl_node_t avlnode; /* index on name_typename */ const struct ddsi_sertopic_ops *ops; const struct ddsi_serdata_ops *serdata_ops; uint32_t serdata_basehash; diff --git a/src/core/ddsi/include/dds/ddsi/q_addrset.h b/src/core/ddsi/include/dds/ddsi/q_addrset.h index 500337f..22476d5 100644 --- a/src/core/ddsi/include/dds/ddsi/q_addrset.h +++ b/src/core/ddsi/include/dds/ddsi/q_addrset.h @@ -13,7 +13,7 @@ #define NN_ADDRSET_H #include "dds/ddsrt/sync.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_feature_check.h" @@ -23,14 +23,14 @@ extern "C" { #endif typedef struct addrset_node { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_locator_t loc; } * addrset_node_t; struct addrset { ddsrt_mutex_t lock; ddsrt_atomic_uint32_t refc; - ut_avlCTree_t ucaddrs, mcaddrs; + ddsrt_avl_ctree_t ucaddrs, mcaddrs; }; typedef void (*addrset_forall_fun_t) (const nn_locator_t *loc, void *arg); diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 9138e02..f6f1f8e 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -13,7 +13,7 @@ #define Q_ENTITY_H #include "dds/ddsrt/atomics.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_lat_estim.h" @@ -54,12 +54,12 @@ status_cb_data_t; typedef void (*status_cb_t) (void *entity, const status_cb_data_t *data); struct prd_wr_match { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t wr_guid; }; struct rd_pwr_match { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t pwr_guid; #ifdef DDSI_INCLUDE_SSM nn_locator_t ssm_mc_loc; @@ -68,17 +68,17 @@ struct rd_pwr_match { }; struct wr_rd_match { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t rd_guid; }; struct rd_wr_match { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t wr_guid; }; struct wr_prd_match { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t prd_guid; /* guid of the proxy reader */ unsigned assumed_in_sync: 1; /* set to 1 upon receipt of ack not nack'ing msgs */ unsigned has_replied_to_hb: 1; /* we must keep sending HBs until all readers have this set */ @@ -105,7 +105,7 @@ enum pwr_rd_match_syncstate { }; struct pwr_rd_match { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t rd_guid; nn_mtime_t tcreate; nn_count_t count; /* most recent acknack sequence number */ @@ -247,8 +247,8 @@ struct writer nn_etime_t t_rexmit_end; /* time of last 1->0 transition of "retransmitting" */ nn_etime_t t_whc_high_upd; /* time "whc_high" was last updated for controlled ramp-up of throughput */ int num_reliable_readers; /* number of matching reliable PROXY readers */ - ut_avlTree_t readers; /* all matching PROXY readers, see struct wr_prd_match */ - ut_avlTree_t local_readers; /* all matching LOCAL readers, see struct wr_rd_match */ + ddsrt_avl_tree_t readers; /* all matching PROXY readers, see struct wr_prd_match */ + ddsrt_avl_tree_t local_readers; /* all matching LOCAL readers, see struct wr_rd_match */ #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS uint32_t partition_id; #endif @@ -280,8 +280,8 @@ struct reader struct addrset *as; #endif const struct ddsi_sertopic * topic; /* topic is NULL for built-in readers */ - ut_avlTree_t writers; /* all matching PROXY writers, see struct rd_pwr_match */ - ut_avlTree_t local_writers; /* all matching LOCAL writers, see struct rd_wr_match */ + ddsrt_avl_tree_t writers; /* all matching PROXY writers, see struct rd_pwr_match */ + ddsrt_avl_tree_t local_writers; /* all matching LOCAL writers, see struct rd_wr_match */ ddsi2direct_directread_cb_t ddsi2direct_cb; void *ddsi2direct_cbarg; }; @@ -299,7 +299,7 @@ struct proxy_participant struct addrset *as_default; /* default address set to use for user data traffic */ struct addrset *as_meta; /* default address set to use for discovery traffic */ struct proxy_endpoint_common *endpoints; /* all proxy endpoints can be reached from here */ - ut_avlTree_t groups; /* table of all groups (publisher, subscriber), see struct proxy_group */ + ddsrt_avl_tree_t groups; /* table of all groups (publisher, subscriber), see struct proxy_group */ unsigned kernel_sequence_numbers : 1; /* whether this proxy participant generates OSPL kernel sequence numbers */ unsigned implicitly_created : 1; /* participants are implicitly created for Cloud/Fog discovered endpoints */ unsigned is_ddsi2_pp: 1; /* if this is the federation-leader on the remote node */ @@ -318,7 +318,7 @@ struct proxy_participant tables, but "groups" only live in the context of a proxy participant. */ struct proxy_group { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t guid; char *name; struct proxy_participant *proxypp; /* uncounted backref to proxy participant */ @@ -340,7 +340,7 @@ struct proxy_endpoint_common struct proxy_writer { struct entity_common e; struct proxy_endpoint_common c; - ut_avlTree_t readers; /* matching LOCAL readers, see pwr_rd_match */ + ddsrt_avl_tree_t readers; /* matching LOCAL readers, see pwr_rd_match */ int n_reliable_readers; /* number of those that are reliable */ int n_readers_out_of_sync; /* number of those that require special handling (accepting historical data, waiting for historical data set to become complete) */ seqno_t last_seq; /* highest known seq published by the writer, not last delivered */ @@ -373,16 +373,16 @@ struct proxy_reader { #ifdef DDSI_INCLUDE_SSM unsigned favours_ssm: 1; /* iff 1, this proxy reader favours SSM when available */ #endif - ut_avlTree_t writers; /* matching LOCAL writers */ + ddsrt_avl_tree_t writers; /* matching LOCAL writers */ }; -extern const ut_avlTreedef_t wr_readers_treedef; -extern const ut_avlTreedef_t wr_local_readers_treedef; -extern const ut_avlTreedef_t rd_writers_treedef; -extern const ut_avlTreedef_t rd_local_writers_treedef; -extern const ut_avlTreedef_t pwr_readers_treedef; -extern const ut_avlTreedef_t prd_writers_treedef; -extern const ut_avlTreedef_t deleted_participants_treedef; +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; +extern const ddsrt_avl_treedef_t deleted_participants_treedef; #define DPG_LOCAL 1 #define DPG_REMOTE 2 diff --git a/src/core/ddsi/include/dds/ddsi/q_ephash.h b/src/core/ddsi/include/dds/ddsi/q_ephash.h index e6e0d4a..cf218c3 100644 --- a/src/core/ddsi/include/dds/ddsi/q_ephash.h +++ b/src/core/ddsi/include/dds/ddsi/q_ephash.h @@ -12,7 +12,7 @@ #ifndef Q_EPHASH_H #define Q_EPHASH_H -#include "dds/util/ut_hopscotch.h" +#include "dds/ddsrt/hopscotch.h" #if defined (__cplusplus) extern "C" { @@ -39,7 +39,7 @@ struct nn_guid; struct ephash_enum { - struct ut_chhIter it; + struct ddsrt_chh_iter it; enum entity_kind kind; struct entity_common *cur; }; diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/q_globals.h index 770c569..517b699 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/q_globals.h @@ -18,7 +18,7 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/sockets.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_fibheap.h" +#include "dds/ddsrt/fibheap.h" #include "dds/ddsi/q_plist.h" #include "dds/ddsi/q_protocol.h" @@ -47,7 +47,7 @@ struct lease; struct ddsi_tran_conn; struct ddsi_tran_listener; struct ddsi_tran_factory; -struct ut_thread_pool_s; +struct ddsrt_thread_pool_s; struct debug_monitor; struct ddsi_tkmap; @@ -110,7 +110,7 @@ struct q_globals { /* Lease junk */ ddsrt_mutex_t leaseheap_lock; ddsrt_mutex_t lease_locks[N_LEASE_LOCKS]; - ut_fibheap_t leaseheap; + ddsrt_fibheap_t leaseheap; /* Transport factory */ @@ -133,7 +133,7 @@ struct q_globals { /* Thread pool */ - struct ut_thread_pool_s * thread_pool; + struct ddsrt_thread_pool_s * thread_pool; /* In many sockets mode, the receive threads maintain a local array with participant GUIDs and sockets, participant_set_generation is diff --git a/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h b/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h index 927d94c..d48cf96 100644 --- a/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h +++ b/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h @@ -12,14 +12,14 @@ #ifndef NN_INVERSE_UINT32_SET_H #define NN_INVERSE_UINT32_SET_H -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" struct inverse_uint32_set_node { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; uint32_t min, max; }; struct inverse_uint32_set { - ut_avlTree_t ids; + ddsrt_avl_tree_t ids; uint32_t cursor; uint32_t min, max; }; diff --git a/src/core/ddsi/src/ddsi_mcgroup.c b/src/core/ddsi/src/ddsi_mcgroup.c index 744ace4..51ca755 100644 --- a/src/core/ddsi/src/ddsi_mcgroup.c +++ b/src/core/ddsi/src/ddsi_mcgroup.c @@ -20,10 +20,10 @@ #include "dds/ddsi/ddsi_mcgroup.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" struct nn_group_membership_node { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; ddsi_tran_conn_t conn; nn_locator_t srcloc; nn_locator_t mcloc; @@ -32,7 +32,7 @@ struct nn_group_membership_node { struct nn_group_membership { ddsrt_mutex_t lock; - ut_avlTree_t mships; + ddsrt_avl_tree_t mships; }; static int locator_compare_no_port (const nn_locator_t *as, const nn_locator_t *bs) @@ -60,19 +60,19 @@ static int cmp_group_membership (const void *va, const void *vb) return 0; } -static ut_avlTreedef_t mship_td = UT_AVL_TREEDEF_INITIALIZER(offsetof (struct nn_group_membership_node, avlnode), 0, cmp_group_membership, 0); +static ddsrt_avl_treedef_t mship_td = DDSRT_AVL_TREEDEF_INITIALIZER(offsetof (struct nn_group_membership_node, avlnode), 0, cmp_group_membership, 0); struct nn_group_membership *new_group_membership (void) { struct nn_group_membership *mship = ddsrt_malloc (sizeof (*mship)); ddsrt_mutex_init (&mship->lock); - ut_avlInit (&mship_td, &mship->mships); + ddsrt_avl_init (&mship_td, &mship->mships); return mship; } void free_group_membership (struct nn_group_membership *mship) { - ut_avlFree (&mship_td, &mship->mships, ddsrt_free); + ddsrt_avl_free (&mship_td, &mship->mships, ddsrt_free); ddsrt_mutex_destroy (&mship->lock); ddsrt_free (mship); } @@ -80,7 +80,7 @@ void free_group_membership (struct nn_group_membership *mship) static int reg_group_membership (struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc) { struct nn_group_membership_node key, *n; - ut_avlIPath_t ip; + ddsrt_avl_ipath_t ip; int isnew; key.conn = conn; if (srcloc) @@ -88,7 +88,7 @@ static int reg_group_membership (struct nn_group_membership *mship, ddsi_tran_co else memset (&key.srcloc, 0, sizeof (key.srcloc)); key.mcloc = *mcloc; - if ((n = ut_avlLookupIPath (&mship_td, &mship->mships, &key, &ip)) != NULL) { + if ((n = ddsrt_avl_lookup_ipath (&mship_td, &mship->mships, &key, &ip)) != NULL) { isnew = 0; n->count++; } else { @@ -98,7 +98,7 @@ static int reg_group_membership (struct nn_group_membership *mship, ddsi_tran_co n->srcloc = key.srcloc; n->mcloc = key.mcloc; n->count = 1; - ut_avlInsertIPath (&mship_td, &mship->mships, n, &ip); + ddsrt_avl_insert_ipath (&mship_td, &mship->mships, n, &ip); } return isnew; } @@ -106,7 +106,7 @@ static int reg_group_membership (struct nn_group_membership *mship, ddsi_tran_co static int unreg_group_membership (struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc) { struct nn_group_membership_node key, *n; - ut_avlDPath_t dp; + ddsrt_avl_dpath_t dp; int mustdel; key.conn = conn; if (srcloc) @@ -114,7 +114,7 @@ static int unreg_group_membership (struct nn_group_membership *mship, ddsi_tran_ else memset (&key.srcloc, 0, sizeof (key.srcloc)); key.mcloc = *mcloc; - n = ut_avlLookupDPath (&mship_td, &mship->mships, &key, &dp); + n = ddsrt_avl_lookup_dpath (&mship_td, &mship->mships, &key, &dp); assert (n != NULL); assert (n->count > 0); if (--n->count > 0) @@ -122,7 +122,7 @@ static int unreg_group_membership (struct nn_group_membership *mship, ddsi_tran_ else { mustdel = 1; - ut_avlDeleteDPath (&mship_td, &mship->mships, n, &dp); + ddsrt_avl_delete_dpath (&mship_td, &mship->mships, n, &dp); ddsrt_free (n); } return mustdel; @@ -268,13 +268,13 @@ void ddsi_transfer_group_membership (ddsi_tran_conn_t conn, ddsi_tran_conn_t new are neither 0 nor maximum representable, min and max define the range of key values that relate to oldsock */ ddsrt_mutex_lock (&gv.mship->lock); - n = ut_avlLookupSuccEq (&mship_td, &gv.mship->mships, &min); + n = ddsrt_avl_lookup_succ_eq (&mship_td, &gv.mship->mships, &min); while (n != NULL && cmp_group_membership (n, &max) <= 0) { - struct nn_group_membership_node * const nn = ut_avlFindSucc (&mship_td, &gv.mship->mships, n); - ut_avlDelete (&mship_td, &gv.mship->mships, n); + struct nn_group_membership_node * const nn = ddsrt_avl_find_succ (&mship_td, &gv.mship->mships, n); + ddsrt_avl_delete (&mship_td, &gv.mship->mships, n); n->conn = newconn; - ut_avlInsert (&mship_td, &gv.mship->mships, n); + ddsrt_avl_insert (&mship_td, &gv.mship->mships, n); n = nn; } ddsrt_mutex_unlock (&gv.mship->lock); @@ -283,13 +283,13 @@ void ddsi_transfer_group_membership (ddsi_tran_conn_t conn, ddsi_tran_conn_t new int ddsi_rejoin_transferred_mcgroups (ddsi_tran_conn_t conn) { struct nn_group_membership_node *n, min, max; - ut_avlIter_t it; + ddsrt_avl_iter_t it; int ret = 0; memset(&min, 0, sizeof(min)); memset(&max, 0xff, sizeof(max)); min.conn = max.conn = conn; ddsrt_mutex_lock (&gv.mship->lock); - for (n = ut_avlIterSuccEq (&mship_td, &gv.mship->mships, &it, &min); n != NULL && ret >= 0 && cmp_group_membership(n, &max) <= 0; n = ut_avlIterNext (&it)) + for (n = ddsrt_avl_iter_succ_eq (&mship_td, &gv.mship->mships, &it, &min); n != NULL && ret >= 0 && cmp_group_membership(n, &max) <= 0; n = ddsrt_avl_iter_next (&it)) { int have_srcloc = (memcmp(&n->srcloc, &min.srcloc, sizeof(n->srcloc)) != 0); assert (n->conn == conn); diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 2bb6576..0adbd73 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -20,7 +20,7 @@ #include "dds/ddsi/ddsi_tran.h" #include "dds/ddsi/ddsi_tcp.h" #include "dds/ddsi/ddsi_ipaddr.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_nwif.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" @@ -93,12 +93,12 @@ static int ddsi_tcp_cmp_conn_wrap (const void *a, const void *b) typedef struct ddsi_tcp_node { - ut_avlNode_t m_avlnode; + ddsrt_avl_node_t m_avlnode; ddsi_tcp_conn_t m_conn; } * ddsi_tcp_node_t; -static const ut_avlTreedef_t ddsi_tcp_treedef = UT_AVL_TREEDEF_INITIALIZER_INDKEY +static const ddsrt_avl_treedef_t ddsi_tcp_treedef = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY ( offsetof (struct ddsi_tcp_node, m_avlnode), offsetof (struct ddsi_tcp_node, m_conn), @@ -107,7 +107,7 @@ static const ut_avlTreedef_t ddsi_tcp_treedef = UT_AVL_TREEDEF_INITIALIZER_INDKE ); static ddsrt_mutex_t ddsi_tcp_cache_lock_g; -static ut_avlTree_t ddsi_tcp_cache_g; +static ddsrt_avl_tree_t ddsi_tcp_cache_g; static struct ddsi_tran_factory ddsi_tcp_factory_g; static ddsi_tcp_conn_t ddsi_tcp_new_conn (ddsrt_socket_t, bool, struct sockaddr *); @@ -125,11 +125,11 @@ static char *sockaddr_to_string_with_port (char *dst, size_t sizeof_dst, const s static void ddsi_tcp_cache_dump (void) { char buff[64]; - ut_avlIter_t iter; + ddsrt_avl_iter_t iter; ddsi_tcp_node_t n; unsigned i = 0; - n = ut_avlIterFirst (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, &iter); + n = ddsrt_avl_iter_first (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, &iter); while (n) { os_sockaddrAddressPortToString ((const os_sockaddr *) &n->m_conn->m_peer_addr, buff, sizeof (buff)); @@ -140,7 +140,7 @@ static void ddsi_tcp_cache_dump (void) ddsi_name, i++, n->m_conn->m_base.m_server ? "server" : "client", n->m_conn->m_sock, n->m_conn->m_base.m_base.m_port, buff ); - n = ut_avlIterNext (&iter); + n = ddsrt_avl_iter_next (&iter); } } */ @@ -242,7 +242,7 @@ static void ddsi_tcp_conn_connect (ddsi_tcp_conn_t conn, const ddsrt_msghdr_t * } } -static void ddsi_tcp_cache_add (ddsi_tcp_conn_t conn, ut_avlIPath_t * path) +static void ddsi_tcp_cache_add (ddsi_tcp_conn_t conn, ddsrt_avl_ipath_t * path) { const char * action = "added"; ddsi_tcp_node_t node; @@ -255,11 +255,11 @@ static void ddsi_tcp_cache_add (ddsi_tcp_conn_t conn, ut_avlIPath_t * path) { node = ddsrt_malloc (sizeof (*node)); node->m_conn = conn; - ut_avlInsertIPath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node, path); + ddsrt_avl_insert_ipath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node, path); } else { - node = ut_avlLookup (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, conn); + node = ddsrt_avl_lookup (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, conn); if (node) { /* Replace connection in cache */ @@ -272,7 +272,7 @@ static void ddsi_tcp_cache_add (ddsi_tcp_conn_t conn, ut_avlIPath_t * path) { node = ddsrt_malloc (sizeof (*node)); node->m_conn = conn; - ut_avlInsert (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node); + ddsrt_avl_insert (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node); } } @@ -284,15 +284,15 @@ static void ddsi_tcp_cache_remove (ddsi_tcp_conn_t conn) { char buff[DDSI_LOCSTRLEN]; ddsi_tcp_node_t node; - ut_avlDPath_t path; + ddsrt_avl_dpath_t path; ddsrt_mutex_lock (&ddsi_tcp_cache_lock_g); - node = ut_avlLookupDPath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, conn, &path); + node = ddsrt_avl_lookup_dpath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, conn, &path); if (node) { sockaddr_to_string_with_port(buff, sizeof(buff), (struct sockaddr *)&conn->m_peer_addr); DDS_LOG(DDS_LC_TCP, "%s cache removed socket %"PRIdSOCK" to %s\n", ddsi_name, conn->m_sock, buff); - ut_avlDeleteDPath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node, &path); + ddsrt_avl_delete_dpath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node, &path); ddsi_tcp_node_free (node); } ddsrt_mutex_unlock (&ddsi_tcp_cache_lock_g); @@ -305,7 +305,7 @@ static void ddsi_tcp_cache_remove (ddsi_tcp_conn_t conn) static ddsi_tcp_conn_t ddsi_tcp_cache_find (const ddsrt_msghdr_t * msg) { - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; ddsi_tcp_node_t node; struct ddsi_tcp_conn key; ddsi_tcp_conn_t ret = NULL; @@ -317,12 +317,12 @@ static ddsi_tcp_conn_t ddsi_tcp_cache_find (const ddsrt_msghdr_t * msg) /* Check cache for existing connection to target */ ddsrt_mutex_lock (&ddsi_tcp_cache_lock_g); - node = ut_avlLookupIPath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, &key, &path); + node = ddsrt_avl_lookup_ipath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, &key, &path); if (node) { if (node->m_conn->m_base.m_closed) { - ut_avlDelete (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node); + ddsrt_avl_delete (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node); ddsi_tcp_node_free (node); } else @@ -1010,7 +1010,7 @@ static void ddsi_tcp_release_listener (ddsi_tran_listener_t listener) static void ddsi_tcp_release_factory (void) { if (ddsrt_atomic_dec32_nv (&ddsi_tcp_init_g) == 0) { - ut_avlFree (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, ddsi_tcp_node_free); + ddsrt_avl_free (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, ddsi_tcp_node_free); ddsrt_mutex_destroy (&ddsi_tcp_cache_lock_g); #ifdef DDSI_INCLUDE_SSL if (ddsi_tcp_ssl_plugin.fini) @@ -1095,7 +1095,7 @@ int ddsi_tcp_init (void) } #endif - ut_avlInit (&ddsi_tcp_treedef, &ddsi_tcp_cache_g); + ddsrt_avl_init (&ddsi_tcp_treedef, &ddsi_tcp_cache_g); ddsrt_mutex_init (&ddsi_tcp_cache_lock_g); DDS_LOG(DDS_LC_CONFIG, "%s initialized\n", ddsi_name); diff --git a/src/core/ddsi/src/ddsi_tkmap.c b/src/core/ddsi/src/ddsi_tkmap.c index b688e09..132fd5d 100644 --- a/src/core/ddsi/src/ddsi_tkmap.c +++ b/src/core/ddsi/src/ddsi_tkmap.c @@ -22,7 +22,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/ddsi_tkmap.h" -#include "dds/util/ut_hopscotch.h" +#include "dds/ddsrt/hopscotch.h" #include "dds__stream.h" #include "dds/ddsi/ddsi_serdata.h" @@ -31,7 +31,7 @@ struct ddsi_tkmap { - struct ut_chh * m_hh; + struct ddsrt_chh * m_hh; ddsrt_mutex_t m_lock; ddsrt_cond_t m_cond; }; @@ -87,7 +87,7 @@ static int dds_tk_equals_void (const void *a, const void *b) struct ddsi_tkmap *ddsi_tkmap_new (void) { struct ddsi_tkmap *tkmap = dds_alloc (sizeof (*tkmap)); - tkmap->m_hh = ut_chhNew (1, dds_tk_hash_void, dds_tk_equals_void, gc_buckets); + tkmap->m_hh = ddsrt_chh_new (1, dds_tk_hash_void, dds_tk_equals_void, gc_buckets); ddsrt_mutex_init (&tkmap->m_lock); ddsrt_cond_init (&tkmap->m_cond); return tkmap; @@ -102,8 +102,8 @@ static void free_tkmap_instance (void *vtk, UNUSED_ARG(void *f_arg)) void ddsi_tkmap_free (struct ddsi_tkmap * map) { - ut_chhEnumUnsafe (map->m_hh, free_tkmap_instance, NULL); - ut_chhFree (map->m_hh); + ddsrt_chh_enum_unsafe (map->m_hh, free_tkmap_instance, NULL); + ddsrt_chh_free (map->m_hh); ddsrt_cond_destroy (&map->m_cond); ddsrt_mutex_destroy (&map->m_lock); dds_free (map); @@ -115,18 +115,18 @@ uint64_t ddsi_tkmap_lookup (struct ddsi_tkmap * map, const struct ddsi_serdata * struct ddsi_tkmap_instance * tk; assert (thread_is_awake ()); dummy.m_sample = (struct ddsi_serdata *) sd; - tk = ut_chhLookup (map->m_hh, &dummy); + tk = ddsrt_chh_lookup (map->m_hh, &dummy); return (tk) ? tk->m_iid : DDS_HANDLE_NIL; } struct ddsi_tkmap_instance *ddsi_tkmap_find_by_id (struct ddsi_tkmap *map, uint64_t iid) { /* This is not a function that should be used liberally, as it linearly scans the key-to-iid map. */ - struct ut_chhIter it; + struct ddsrt_chh_iter it; struct ddsi_tkmap_instance *tk; uint32_t refc; assert (thread_is_awake ()); - for (tk = ut_chhIterFirst (map->m_hh, &it); tk; tk = ut_chhIterNext (&it)) + for (tk = ddsrt_chh_iter_first (map->m_hh, &it); tk; tk = ddsrt_chh_iter_next (&it)) if (tk->m_iid == iid) break; if (tk == NULL) @@ -165,7 +165,7 @@ ddsi_tkmap_find( assert (thread_is_awake ()); dummy.m_sample = sd; retry: - if ((tk = ut_chhLookup(map->m_hh, &dummy)) != NULL) + if ((tk = ddsrt_chh_lookup(map->m_hh, &dummy)) != NULL) { uint32_t new; new = ddsrt_atomic_inc32_nv(&tk->m_refc); @@ -178,7 +178,7 @@ retry: we can block until someone signals some entry is removed from the map if we take some lock & wait for some condition */ ddsrt_mutex_lock(&map->m_lock); - while ((tk = ut_chhLookup(map->m_hh, &dummy)) != NULL && (ddsrt_atomic_ld32(&tk->m_refc) & REFC_DELETE)) + while ((tk = ddsrt_chh_lookup(map->m_hh, &dummy)) != NULL && (ddsrt_atomic_ld32(&tk->m_refc) & REFC_DELETE)) ddsrt_cond_wait(&map->m_cond, &map->m_lock); ddsrt_mutex_unlock(&map->m_lock); goto retry; @@ -192,7 +192,7 @@ retry: tk->m_sample = ddsi_serdata_to_topicless (sd); ddsrt_atomic_st32 (&tk->m_refc, 1); tk->m_iid = ddsi_iid_gen (); - if (!ut_chhAdd (map->m_hh, tk)) + if (!ddsrt_chh_add (map->m_hh, tk)) { /* Lost a race from another thread, retry */ ddsi_serdata_unref (tk->m_sample); @@ -237,7 +237,7 @@ void ddsi_tkmap_instance_unref (struct ddsi_tkmap_instance * tk) struct ddsi_tkmap *map = gv.m_tkmap; /* Remove from hash table */ - int removed = ut_chhRemove(map->m_hh, tk); + int removed = ddsrt_chh_remove(map->m_hh, tk); assert (removed); (void)removed; diff --git a/src/core/ddsi/src/q_addrset.c b/src/core/ddsi/src/q_addrset.c index 48d9a4a..f8694d8 100644 --- a/src/core/ddsi/src/q_addrset.c +++ b/src/core/ddsi/src/q_addrset.c @@ -17,7 +17,7 @@ #include "dds/ddsrt/log.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/misc.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_config.h" @@ -39,8 +39,8 @@ static int compare_locators_vwrap (const void *va, const void *vb); -static const ut_avlCTreedef_t addrset_treedef = - UT_AVL_CTREEDEF_INITIALIZER (offsetof (struct addrset_node, avlnode), offsetof (struct addrset_node, loc), compare_locators_vwrap, 0); +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 (struct addrset *as, const char *ip, int port_mode, const char *msgtag, int req_mc, int mcgen_base, int mcgen_count, int mcgen_idx) { @@ -203,8 +203,8 @@ struct addrset *new_addrset (void) struct addrset *as = ddsrt_malloc (sizeof (*as)); ddsrt_atomic_st32 (&as->refc, 1); ddsrt_mutex_init (&as->lock); - ut_avlCInit (&addrset_treedef, &as->ucaddrs); - ut_avlCInit (&addrset_treedef, &as->mcaddrs); + ddsrt_avl_cinit (&addrset_treedef, &as->ucaddrs); + ddsrt_avl_cinit (&addrset_treedef, &as->mcaddrs); return as; } @@ -221,8 +221,8 @@ void unref_addrset (struct addrset *as) { if ((as != NULL) && (ddsrt_atomic_dec32_ov (&as->refc) == 1)) { - ut_avlCFree (&addrset_treedef, &as->ucaddrs, ddsrt_free); - ut_avlCFree (&addrset_treedef, &as->mcaddrs, ddsrt_free); + ddsrt_avl_cfree (&addrset_treedef, &as->ucaddrs, ddsrt_free); + ddsrt_avl_cfree (&addrset_treedef, &as->mcaddrs, ddsrt_free); ddsrt_mutex_destroy (&as->lock); ddsrt_free (as); } @@ -247,9 +247,9 @@ int is_unspec_locator (const nn_locator_t *loc) int addrset_contains_ssm (const struct addrset *as) { struct addrset_node *n; - ut_avlCIter_t it; + ddsrt_avl_citer_t it; LOCK (as); - for (n = ut_avlCIterFirst (&addrset_treedef, &as->mcaddrs, &it); n; n = ut_avlCIterNext (&it)) + for (n = ddsrt_avl_citer_first (&addrset_treedef, &as->mcaddrs, &it); n; n = ddsrt_avl_citer_next (&it)) { if (ddsi_is_ssm_mcaddr (&n->loc)) { @@ -264,9 +264,9 @@ int addrset_contains_ssm (const struct addrset *as) int addrset_any_ssm (const struct addrset *as, nn_locator_t *dst) { struct addrset_node *n; - ut_avlCIter_t it; + ddsrt_avl_citer_t it; LOCK (as); - for (n = ut_avlCIterFirst (&addrset_treedef, &as->mcaddrs, &it); n; n = ut_avlCIterNext (&it)) + for (n = ddsrt_avl_citer_first (&addrset_treedef, &as->mcaddrs, &it); n; n = ddsrt_avl_citer_next (&it)) { if (ddsi_is_ssm_mcaddr (&n->loc)) { @@ -282,9 +282,9 @@ int addrset_any_ssm (const struct addrset *as, nn_locator_t *dst) int addrset_any_non_ssm_mc (const struct addrset *as, nn_locator_t *dst) { struct addrset_node *n; - ut_avlCIter_t it; + ddsrt_avl_citer_t it; LOCK (as); - for (n = ut_avlCIterFirst (&addrset_treedef, &as->mcaddrs, &it); n; n = ut_avlCIterNext (&it)) + for (n = ddsrt_avl_citer_first (&addrset_treedef, &as->mcaddrs, &it); n; n = ddsrt_avl_citer_next (&it)) { if (!ddsi_is_ssm_mcaddr (&n->loc)) { @@ -301,8 +301,8 @@ int addrset_any_non_ssm_mc (const struct addrset *as, nn_locator_t *dst) int addrset_purge (struct addrset *as) { LOCK (as); - ut_avlCFree (&addrset_treedef, &as->ucaddrs, ddsrt_free); - ut_avlCFree (&addrset_treedef, &as->mcaddrs, ddsrt_free); + ddsrt_avl_cfree (&addrset_treedef, &as->ucaddrs, ddsrt_free); + ddsrt_avl_cfree (&addrset_treedef, &as->mcaddrs, ddsrt_free); UNLOCK (as); return 0; } @@ -311,14 +311,14 @@ void add_to_addrset (struct addrset *as, const nn_locator_t *loc) { if (!is_unspec_locator (loc)) { - ut_avlIPath_t path; - ut_avlCTree_t *tree = ddsi_is_mcaddr (loc) ? &as->mcaddrs : &as->ucaddrs; + ddsrt_avl_ipath_t path; + ddsrt_avl_ctree_t *tree = ddsi_is_mcaddr (loc) ? &as->mcaddrs : &as->ucaddrs; LOCK (as); - if (ut_avlCLookupIPath (&addrset_treedef, tree, loc, &path) == NULL) + if (ddsrt_avl_clookup_ipath (&addrset_treedef, tree, loc, &path) == NULL) { struct addrset_node *n = ddsrt_malloc (sizeof (*n)); n->loc = *loc; - ut_avlCInsertIPath (&addrset_treedef, tree, n, &path); + ddsrt_avl_cinsert_ipath (&addrset_treedef, tree, n, &path); } UNLOCK (as); } @@ -326,13 +326,13 @@ void add_to_addrset (struct addrset *as, const nn_locator_t *loc) void remove_from_addrset (struct addrset *as, const nn_locator_t *loc) { - ut_avlDPath_t path; - ut_avlCTree_t *tree = ddsi_is_mcaddr (loc) ? &as->mcaddrs : &as->ucaddrs; + ddsrt_avl_dpath_t path; + ddsrt_avl_ctree_t *tree = ddsi_is_mcaddr (loc) ? &as->mcaddrs : &as->ucaddrs; struct addrset_node *n; LOCK (as); - if ((n = ut_avlCLookupDPath (&addrset_treedef, tree, loc, &path)) != NULL) + if ((n = ddsrt_avl_clookup_dpath (&addrset_treedef, tree, loc, &path)) != NULL) { - ut_avlCDeleteDPath (&addrset_treedef, tree, n, &path); + ddsrt_avl_cdelete_dpath (&addrset_treedef, tree, n, &path); ddsrt_free (n); } UNLOCK (as); @@ -341,9 +341,9 @@ void remove_from_addrset (struct addrset *as, const nn_locator_t *loc) void copy_addrset_into_addrset_uc (struct addrset *as, const struct addrset *asadd) { struct addrset_node *n; - ut_avlCIter_t it; + ddsrt_avl_citer_t it; LOCK (asadd); - for (n = ut_avlCIterFirst (&addrset_treedef, &asadd->ucaddrs, &it); n; n = ut_avlCIterNext (&it)) + for (n = ddsrt_avl_citer_first (&addrset_treedef, &asadd->ucaddrs, &it); n; n = ddsrt_avl_citer_next (&it)) add_to_addrset (as, &n->loc); UNLOCK (asadd); } @@ -351,9 +351,9 @@ void copy_addrset_into_addrset_uc (struct addrset *as, const struct addrset *asa void copy_addrset_into_addrset_mc (struct addrset *as, const struct addrset *asadd) { struct addrset_node *n; - ut_avlCIter_t it; + ddsrt_avl_citer_t it; LOCK (asadd); - for (n = ut_avlCIterFirst (&addrset_treedef, &asadd->mcaddrs, &it); n; n = ut_avlCIterNext (&it)) + for (n = ddsrt_avl_citer_first (&addrset_treedef, &asadd->mcaddrs, &it); n; n = ddsrt_avl_citer_next (&it)) add_to_addrset (as, &n->loc); UNLOCK (asadd); } @@ -368,9 +368,9 @@ void copy_addrset_into_addrset (struct addrset *as, const struct addrset *asadd) void copy_addrset_into_addrset_no_ssm_mc (struct addrset *as, const struct addrset *asadd) { struct addrset_node *n; - ut_avlCIter_t it; + ddsrt_avl_citer_t it; LOCK (asadd); - for (n = ut_avlCIterFirst (&addrset_treedef, &asadd->mcaddrs, &it); n; n = ut_avlCIterNext (&it)) + for (n = ddsrt_avl_citer_first (&addrset_treedef, &asadd->mcaddrs, &it); n; n = ddsrt_avl_citer_next (&it)) { if (!ddsi_is_ssm_mcaddr (&n->loc)) add_to_addrset (as, &n->loc); @@ -389,14 +389,14 @@ void addrset_purge_ssm (struct addrset *as) { struct addrset_node *n; LOCK (as); - n = ut_avlCFindMin (&addrset_treedef, &as->mcaddrs); + n = ddsrt_avl_cfind_min (&addrset_treedef, &as->mcaddrs); while (n) { struct addrset_node *n1 = n; - n = ut_avlCFindSucc (&addrset_treedef, &as->mcaddrs, n); + n = ddsrt_avl_cfind_succ (&addrset_treedef, &as->mcaddrs, n); if (ddsi_is_ssm_mcaddr (&n1->loc)) { - ut_avlCDelete (&addrset_treedef, &as->mcaddrs, n1); + ddsrt_avl_cdelete (&addrset_treedef, &as->mcaddrs, n1); ddsrt_free (n1); } } @@ -412,7 +412,7 @@ size_t addrset_count (const struct addrset *as) { size_t count; LOCK (as); - count = ut_avlCCount (&as->ucaddrs) + ut_avlCCount (&as->mcaddrs); + count = ddsrt_avl_ccount (&as->ucaddrs) + ddsrt_avl_ccount (&as->mcaddrs); UNLOCK (as); return count; } @@ -426,7 +426,7 @@ size_t addrset_count_uc (const struct addrset *as) { size_t count; LOCK (as); - count = ut_avlCCount (&as->ucaddrs); + count = ddsrt_avl_ccount (&as->ucaddrs); UNLOCK (as); return count; } @@ -440,7 +440,7 @@ size_t addrset_count_mc (const struct addrset *as) { size_t count; LOCK (as); - count = ut_avlCCount (&as->mcaddrs); + count = ddsrt_avl_ccount (&as->mcaddrs); UNLOCK (as); return count; } @@ -450,7 +450,7 @@ int addrset_empty_uc (const struct addrset *as) { int isempty; LOCK (as); - isempty = ut_avlCIsEmpty (&as->ucaddrs); + isempty = ddsrt_avl_cis_empty (&as->ucaddrs); UNLOCK (as); return isempty; } @@ -459,7 +459,7 @@ int addrset_empty_mc (const struct addrset *as) { int isempty; LOCK (as); - isempty = ut_avlCIsEmpty (&as->mcaddrs); + isempty = ddsrt_avl_cis_empty (&as->mcaddrs); UNLOCK (as); return isempty; } @@ -468,7 +468,7 @@ int addrset_empty (const struct addrset *as) { int isempty; LOCK (as); - isempty = ut_avlCIsEmpty (&as->ucaddrs) && ut_avlCIsEmpty (&as->mcaddrs); + isempty = ddsrt_avl_cis_empty (&as->ucaddrs) && ddsrt_avl_cis_empty (&as->mcaddrs); UNLOCK (as); return isempty; } @@ -476,14 +476,14 @@ int addrset_empty (const struct addrset *as) int addrset_any_uc (const struct addrset *as, nn_locator_t *dst) { LOCK (as); - if (ut_avlCIsEmpty (&as->ucaddrs)) + if (ddsrt_avl_cis_empty (&as->ucaddrs)) { UNLOCK (as); return 0; } else { - const struct addrset_node *n = ut_avlCRootNonEmpty (&addrset_treedef, &as->ucaddrs); + const struct addrset_node *n = ddsrt_avl_croot_non_empty (&addrset_treedef, &as->ucaddrs); *dst = n->loc; UNLOCK (as); return 1; @@ -493,14 +493,14 @@ int addrset_any_uc (const struct addrset *as, nn_locator_t *dst) int addrset_any_mc (const struct addrset *as, nn_locator_t *dst) { LOCK (as); - if (ut_avlCIsEmpty (&as->mcaddrs)) + if (ddsrt_avl_cis_empty (&as->mcaddrs)) { UNLOCK (as); return 0; } else { - const struct addrset_node *n = ut_avlCRootNonEmpty (&addrset_treedef, &as->mcaddrs); + const struct addrset_node *n = ddsrt_avl_croot_non_empty (&addrset_treedef, &as->mcaddrs); *dst = n->loc; UNLOCK (as); return 1; @@ -527,9 +527,9 @@ size_t addrset_forall_count (struct addrset *as, addrset_forall_fun_t f, void *a arg1.f = f; arg1.arg = arg; LOCK (as); - ut_avlCWalk (&addrset_treedef, &as->mcaddrs, addrset_forall_helper, &arg1); - ut_avlCWalk (&addrset_treedef, &as->ucaddrs, addrset_forall_helper, &arg1); - count = ut_avlCCount (&as->ucaddrs) + ut_avlCCount (&as->mcaddrs); + ddsrt_avl_cwalk (&addrset_treedef, &as->mcaddrs, addrset_forall_helper, &arg1); + ddsrt_avl_cwalk (&addrset_treedef, &as->ucaddrs, addrset_forall_helper, &arg1); + count = ddsrt_avl_ccount (&as->ucaddrs) + ddsrt_avl_ccount (&as->mcaddrs); UNLOCK (as); return count; } @@ -543,22 +543,22 @@ int addrset_forone (struct addrset *as, addrset_forone_fun_t f, void *arg) { unsigned i; addrset_node_t n; - ut_avlCTree_t *trees[2]; - ut_avlCIter_t iter; + ddsrt_avl_ctree_t *trees[2]; + ddsrt_avl_citer_t iter; trees[0] = &as->mcaddrs; trees[1] = &as->ucaddrs; for (i = 0; i < 2u; i++) { - n = (addrset_node_t) ut_avlCIterFirst (&addrset_treedef, trees[i], &iter); + n = (addrset_node_t) ddsrt_avl_citer_first (&addrset_treedef, trees[i], &iter); while (n) { if ((f) (&n->loc, arg) > 0) { return 0; } - n = (addrset_node_t) ut_avlCIterNext (&iter); + n = (addrset_node_t) ddsrt_avl_citer_next (&iter); } } return -1; @@ -588,14 +588,14 @@ void nn_log_addrset (uint32_t tf, const char *prefix, const struct addrset *as) } } -static int addrset_eq_onesidederr1 (const ut_avlCTree_t *at, const ut_avlCTree_t *bt) +static int addrset_eq_onesidederr1 (const ddsrt_avl_ctree_t *at, const ddsrt_avl_ctree_t *bt) { /* Just checking the root */ - if (ut_avlCIsEmpty (at) && ut_avlCIsEmpty (bt)) { + if (ddsrt_avl_cis_empty (at) && ddsrt_avl_cis_empty (bt)) { return 1; - } else if (ut_avlCIsSingleton (at) && ut_avlCIsSingleton (bt)) { - const struct addrset_node *a = ut_avlCRootNonEmpty (&addrset_treedef, at); - const struct addrset_node *b = ut_avlCRootNonEmpty (&addrset_treedef, bt); + } else if (ddsrt_avl_cis_singleton (at) && ddsrt_avl_cis_singleton (bt)) { + const struct addrset_node *a = ddsrt_avl_croot_non_empty (&addrset_treedef, at); + const struct addrset_node *b = ddsrt_avl_croot_non_empty (&addrset_treedef, bt); return compare_locators (&a->loc, &b->loc) == 0; } else { return 0; diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index b613df8..5a412e8 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -24,15 +24,15 @@ #include "dds/ddsrt/misc.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_addrset.h" #include "dds/ddsi/q_nwif.h" #include "dds/ddsi/q_error.h" -#include "dds/util/ut_xmlparser.h" -#include "dds/util/ut_expand_envvars.h" +#include "dds/ddsrt/xmlparser.h" +#include "dds/ddsrt/expand_envvars.h" #include "dds/version.h" @@ -77,7 +77,7 @@ struct cfgst_nodekey { }; struct cfgst_node { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; struct cfgst_nodekey key; int count; int failed; @@ -85,7 +85,7 @@ struct cfgst_node { }; struct cfgst { - ut_avlTree_t found; + ddsrt_avl_tree_t found; struct config *cfg; /* error flag set so that we can continue parsing for some errors and still fail properly */ int error; @@ -119,8 +119,8 @@ the configuration, so we update this variable instead. */ static uint32_t enabled_logcats; static int cfgst_node_cmp(const void *va, const void *vb); -static const ut_avlTreedef_t cfgst_found_treedef = -UT_AVL_TREEDEF_INITIALIZER(offsetof(struct cfgst_node, avlnode), offsetof(struct cfgst_node, key), cfgst_node_cmp, 0); +static const ddsrt_avl_treedef_t cfgst_found_treedef = +DDSRT_AVL_TREEDEF_INITIALIZER(offsetof(struct cfgst_node, avlnode), offsetof(struct cfgst_node, key), cfgst_node_cmp, 0); #define DU(fname) static int uf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) #define PF(fname) static void pf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) @@ -2067,10 +2067,10 @@ static int do_update(struct cfgst *cfgst, update_fun_t upd, void *parent, struct { struct cfgst_node *n; struct cfgst_nodekey key; - ut_avlIPath_t np; + ddsrt_avl_ipath_t np; int ok; key.e = cfgelem; - if ( (n = ut_avlLookupIPath(&cfgst_found_treedef, &cfgst->found, &key, &np)) == NULL ) { + if ( (n = ddsrt_avl_lookup_ipath(&cfgst_found_treedef, &cfgst->found, &key, &np)) == NULL ) { if ( (n = ddsrt_malloc(sizeof(*n))) == NULL ) return cfg_error(cfgst, "out of memory"); @@ -2078,7 +2078,7 @@ static int do_update(struct cfgst *cfgst, update_fun_t upd, void *parent, struct n->count = 0; n->failed = 0; n->is_default = is_default; - ut_avlInsertIPath(&cfgst_found_treedef, &cfgst->found, n, &np); + ddsrt_avl_insert_ipath(&cfgst_found_treedef, &cfgst->found, n, &np); } if ( cfgelem->multiplicity == 0 || n->count < cfgelem->multiplicity ) ok = upd(cfgst, parent, cfgelem, (n->count == n->failed), value); @@ -2108,7 +2108,7 @@ static int set_defaults(struct cfgst *cfgst, void *parent, int isattr, struct cf key.e = ce; cfgst_push(cfgst, isattr, ce, parent); if ( ce->multiplicity == 1 ) { - if ( ut_avlLookup(&cfgst_found_treedef, &cfgst->found, &key) == NULL ) { + if ( ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key) == NULL ) { if ( ce->update ) { int ok1; cfgst_push(cfgst, 0, NULL, NULL); @@ -2117,9 +2117,9 @@ static int set_defaults(struct cfgst *cfgst, void *parent, int isattr, struct cf ok = ok && ok1; } } - if ( (n = ut_avlLookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { + if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { if ( clear_found ) { - ut_avlDelete(&cfgst_found_treedef, &cfgst->found, n); + ddsrt_avl_delete(&cfgst_found_treedef, &cfgst->found, n); ddsrt_free(n); } } @@ -2419,7 +2419,7 @@ static void print_configitems(struct cfgst *cfgst, void *parent, int isattr, str key.e = ce; cfgst_push(cfgst, isattr, ce, parent); if ( ce->multiplicity == 1 ) { - if ( (n = ut_avlLookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { + if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { cfgst_push(cfgst, 0, NULL, NULL); ce->print(cfgst, parent, ce, n->is_default); cfgst_pop(cfgst); @@ -2496,7 +2496,7 @@ static void free_configured_elements(struct cfgst *cfgst, void *parent, struct c if ( ce->name[0] == '>' ) /* moved, so don't care */ continue; key.e = ce; - if ( (n = ut_avlLookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { + if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { if ( ce->free && n->count > n->failed ) ce->free(cfgst, parent, ce); } @@ -2646,7 +2646,7 @@ static int proc_attr(void *varg, UNUSED_ARG(uintptr_t eleminfo), const char *nam return cfg_error(cfgst, "%s: unknown attribute", name); else { void *parent = cfgst_parent(cfgst); - char *xvalue = ut_expand_envvars(value); + char *xvalue = ddsrt_expand_envvars(value); int ok; cfgst_push(cfgst, 1, cfg_attr, parent); ok = do_update(cfgst, cfg_attr->update, parent, cfg_attr, xvalue, 0); @@ -2666,7 +2666,7 @@ static int proc_elem_data(void *varg, UNUSED_ARG(uintptr_t eleminfo), const char return cfg_error(cfgst, "%s: no data expected", value); else { void *parent = cfgst_parent(cfgst); - char *xvalue = ut_expand_envvars(value); + char *xvalue = ddsrt_expand_envvars(value); int ok; cfgst_push(cfgst, 0, NULL, parent); ok = do_update(cfgst, cfgelem->update, parent, cfgelem, xvalue, 0); @@ -2802,14 +2802,14 @@ struct cfgst * config_init (const char *configfile) cfgst = ddsrt_malloc(sizeof(*cfgst)); memset(cfgst, 0, sizeof(*cfgst)); - ut_avlInit(&cfgst_found_treedef, &cfgst->found); + ddsrt_avl_init(&cfgst_found_treedef, &cfgst->found); cfgst->cfg = &config; cfgst->error = 0; /* configfile == NULL will get you the default configuration */ if (configfile) { char *copy = ddsrt_strdup(configfile), *cursor = copy; - struct ut_xmlpCallbacks cb; + struct ddsrt_xmlp_callbacks cb; cb.attr = proc_attr; cb.elem_close = proc_elem_close; @@ -2818,14 +2818,14 @@ struct cfgst * config_init (const char *configfile) cb.error = proc_error; while (ok && cursor && cursor[0]) { - struct ut_xmlpState *qx; + struct ddsrt_xmlp_state *qx; FILE *fp; char *tok; tok = cursor; if (tok[0] == '<') { /* Read XML directly from input string */ - qx = ut_xmlpNewString (tok, cfgst, &cb); - ut_xmlpSetRequireEOF (qx, 0); + qx = ddsrt_xmlp_new_string (tok, cfgst, &cb); + ddsrt_xmlp_set_requireEOF (qx, 0); fp = NULL; } else { char *comma; @@ -2845,11 +2845,11 @@ struct cfgst * config_init (const char *configfile) } } DDSRT_WARNING_MSVC_ON(4996); - qx = ut_xmlpNewFile(fp, cfgst, &cb); + qx = ddsrt_xmlp_new_file(fp, cfgst, &cb); } cfgst_push(cfgst, 0, &root_cfgelem, &config); - ok = (ut_xmlpParse(qx) >= 0) && !cfgst->error; + ok = (ddsrt_xmlp_parse(qx) >= 0) && !cfgst->error; /* Pop until stack empty: error handling is rather brutal */ assert(!ok || cfgst->path_depth == 1); while (cfgst->path_depth > 0) { @@ -2858,9 +2858,9 @@ struct cfgst * config_init (const char *configfile) if (fp) { fclose(fp); } else if (ok) { - cursor = tok + ut_xmlpGetBufpos (qx); + cursor = tok + ddsrt_xmlp_get_bufpos (qx); } - ut_xmlpFree(qx); + ddsrt_xmlp_free(qx); while (cursor && cursor[0] == ',') { cursor++; } @@ -3019,7 +3019,7 @@ struct cfgst * config_init (const char *configfile) config.valid = 1; return cfgst; } else { - ut_avlFree(&cfgst_found_treedef, &cfgst->found, ddsrt_free); + ddsrt_avl_free(&cfgst_found_treedef, &cfgst->found, ddsrt_free); ddsrt_free(cfgst); return NULL; } @@ -3047,7 +3047,7 @@ void config_fini(struct cfgst *cfgst) memset(&config, 0, sizeof(config)); config.valid = 0; - ut_avlFree(&cfgst_found_treedef, &cfgst->found, ddsrt_free); + ddsrt_avl_free(&cfgst_found_treedef, &cfgst->found, ddsrt_free); ddsrt_free(cfgst); } diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index bf5ec02..12ab0bc 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -20,7 +20,7 @@ #include "dds/ddsrt/log.h" #include "dds/ddsrt/md5.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_misc.h" @@ -1767,7 +1767,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str statusinfo = (qos.present & PP_STATUSINFO) ? qos.statusinfo : 0; } - if (pwr && ut_avlIsEmpty (&pwr->readers)) + if (pwr && ddsrt_avl_is_empty (&pwr->readers)) { /* Wasn't empty when enqueued, but needn't still be; SPDP has no proxy writer, and is always accepted */ diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index 8043229..2e5358a 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -18,7 +18,7 @@ #include "dds/ddsrt/sync.h" #include "dds/ddsrt/misc.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_config.h" @@ -161,7 +161,7 @@ static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_ ephash_enum_reader_init (&er); while ((r = ephash_enum_reader_next (&er)) != NULL) { - ut_avlIter_t writ; + ddsrt_avl_iter_t writ; struct rd_pwr_match *m; if (r->c.pp != p) continue; @@ -170,7 +170,7 @@ static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_ #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS x += print_addrset_if_notempty (conn, " as", r->as, "\n"); #endif - for (m = ut_avlIterFirst (&rd_writers_treedef, &r->writers, &writ); m; m = ut_avlIterNext (&writ)) + for (m = ddsrt_avl_iter_first (&rd_writers_treedef, &r->writers, &writ); m; m = ddsrt_avl_iter_next (&writ)) x += cpf (conn, " pwr %x:%x:%x:%x\n", PGUID (m->pwr_guid)); ddsrt_mutex_unlock (&r->e.lock); } @@ -183,7 +183,7 @@ static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_ ephash_enum_writer_init (&ew); while ((w = ephash_enum_writer_next (&ew)) != NULL) { - ut_avlIter_t rdit; + ddsrt_avl_iter_t rdit; struct wr_prd_match *m; struct whc_state whcst; if (w->c.pp != p) @@ -207,7 +207,7 @@ static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_ x += cpf (conn, " max-drop-seq %lld\n", writer_max_drop_seq (w)); } x += print_addrset_if_notempty (conn, " as", w->as, "\n"); - for (m = ut_avlIterFirst (&wr_readers_treedef, &w->readers, &rdit); m; m = ut_avlIterNext (&rdit)) + for (m = ddsrt_avl_iter_first (&wr_readers_treedef, &w->readers, &rdit); m; m = ddsrt_avl_iter_next (&rdit)) { char wr_prd_flags[4]; wr_prd_flags[0] = m->is_reliable ? 'R' : 'U'; @@ -248,13 +248,13 @@ static int print_proxy_participants (struct thread_state1 * const ts1, ddsi_tran ephash_enum_proxy_reader_init (&er); while ((r = ephash_enum_proxy_reader_next (&er)) != NULL) { - ut_avlIter_t writ; + ddsrt_avl_iter_t writ; struct prd_wr_match *m; if (r->c.proxypp != p) continue; ddsrt_mutex_lock (&r->e.lock); print_proxy_endpoint_common (conn, "prd", &r->e, &r->c); - for (m = ut_avlIterFirst (&rd_writers_treedef, &r->writers, &writ); m; m = ut_avlIterNext (&writ)) + for (m = ddsrt_avl_iter_first (&rd_writers_treedef, &r->writers, &writ); m; m = ddsrt_avl_iter_next (&writ)) x += cpf (conn, " wr %x:%x:%x:%x\n", PGUID (m->wr_guid)); ddsrt_mutex_unlock (&r->e.lock); } @@ -267,14 +267,14 @@ static int print_proxy_participants (struct thread_state1 * const ts1, ddsi_tran ephash_enum_proxy_writer_init (&ew); while ((w = ephash_enum_proxy_writer_next (&ew)) != NULL) { - ut_avlIter_t rdit; + ddsrt_avl_iter_t rdit; struct pwr_rd_match *m; if (w->c.proxypp != p) continue; ddsrt_mutex_lock (&w->e.lock); print_proxy_endpoint_common (conn, "pwr", &w->e, &w->c); x += cpf (conn, " last_seq %lld last_fragnum %u\n", w->last_seq, w->last_fragnum); - for (m = ut_avlIterFirst (&wr_readers_treedef, &w->readers, &rdit); m; m = ut_avlIterNext (&rdit)) + for (m = ddsrt_avl_iter_first (&wr_readers_treedef, &w->readers, &rdit); m; m = ddsrt_avl_iter_next (&rdit)) { x += cpf (conn, " rd %x:%x:%x:%x (nack %lld %lld)\n", PGUID (m->rd_guid), m->seq_last_nack, m->t_last_nack); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 2c5105c..25ef9ea 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.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/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_plist.h" #include "dds/ddsi/q_lease.h" #include "dds/ddsi/q_qosmatch.h" @@ -49,34 +49,34 @@ #include "dds/ddsi/ddsi_tkmap.h" struct deleted_participant { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t guid; unsigned for_what; nn_mtime_t t_prune; }; static ddsrt_mutex_t deleted_participants_lock; -static ut_avlTree_t deleted_participants; +static ddsrt_avl_tree_t deleted_participants; static int compare_guid (const void *va, const void *vb); static void augment_wr_prd_match (void *vnode, const void *vleft, const void *vright); -const ut_avlTreedef_t wr_readers_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct wr_prd_match, avlnode), offsetof (struct wr_prd_match, prd_guid), compare_guid, augment_wr_prd_match); -const ut_avlTreedef_t wr_local_readers_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct wr_rd_match, avlnode), offsetof (struct wr_rd_match, rd_guid), compare_guid, 0); -const ut_avlTreedef_t rd_writers_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct rd_pwr_match, avlnode), offsetof (struct rd_pwr_match, pwr_guid), compare_guid, 0); -const ut_avlTreedef_t rd_local_writers_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct rd_wr_match, avlnode), offsetof (struct rd_wr_match, wr_guid), compare_guid, 0); -const ut_avlTreedef_t pwr_readers_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct pwr_rd_match, avlnode), offsetof (struct pwr_rd_match, rd_guid), compare_guid, 0); -const ut_avlTreedef_t prd_writers_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct prd_wr_match, avlnode), offsetof (struct prd_wr_match, wr_guid), compare_guid, 0); -const ut_avlTreedef_t deleted_participants_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct deleted_participant, avlnode), offsetof (struct deleted_participant, guid), compare_guid, 0); -const ut_avlTreedef_t proxypp_groups_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct proxy_group, avlnode), offsetof (struct proxy_group, guid), compare_guid, 0); +const ddsrt_avl_treedef_t wr_readers_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct wr_prd_match, avlnode), offsetof (struct wr_prd_match, prd_guid), compare_guid, augment_wr_prd_match); +const ddsrt_avl_treedef_t wr_local_readers_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct wr_rd_match, avlnode), offsetof (struct wr_rd_match, rd_guid), compare_guid, 0); +const ddsrt_avl_treedef_t rd_writers_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct rd_pwr_match, avlnode), offsetof (struct rd_pwr_match, pwr_guid), compare_guid, 0); +const ddsrt_avl_treedef_t rd_local_writers_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct rd_wr_match, avlnode), offsetof (struct rd_wr_match, wr_guid), compare_guid, 0); +const ddsrt_avl_treedef_t pwr_readers_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct pwr_rd_match, avlnode), offsetof (struct pwr_rd_match, rd_guid), compare_guid, 0); +const ddsrt_avl_treedef_t prd_writers_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct prd_wr_match, avlnode), offsetof (struct prd_wr_match, wr_guid), compare_guid, 0); +const ddsrt_avl_treedef_t deleted_participants_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct deleted_participant, avlnode), offsetof (struct deleted_participant, guid), compare_guid, 0); +const ddsrt_avl_treedef_t proxypp_groups_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct proxy_group, avlnode), offsetof (struct proxy_group, guid), compare_guid, 0); static const unsigned builtin_writers_besmask = NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER | @@ -267,13 +267,13 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e) int deleted_participants_admin_init (void) { ddsrt_mutex_init (&deleted_participants_lock); - ut_avlInit (&deleted_participants_treedef, &deleted_participants); + ddsrt_avl_init (&deleted_participants_treedef, &deleted_participants); return 0; } void deleted_participants_admin_fini (void) { - ut_avlFree (&deleted_participants_treedef, &deleted_participants, ddsrt_free); + ddsrt_avl_free (&deleted_participants_treedef, &deleted_participants, ddsrt_free); ddsrt_mutex_destroy (&deleted_participants_lock); } @@ -283,13 +283,13 @@ static void prune_deleted_participant_guids_unlocked (nn_mtime_t tnow) all circumstances, but I expect the tree to be very small at all times, so a full scan is fine, too ... */ struct deleted_participant *dpp; - dpp = ut_avlFindMin (&deleted_participants_treedef, &deleted_participants); + dpp = ddsrt_avl_find_min (&deleted_participants_treedef, &deleted_participants); while (dpp) { - struct deleted_participant *dpp1 = ut_avlFindSucc (&deleted_participants_treedef, &deleted_participants, dpp); + struct deleted_participant *dpp1 = ddsrt_avl_find_succ (&deleted_participants_treedef, &deleted_participants, dpp); if (dpp->t_prune.v < tnow.v) { - ut_avlDelete (&deleted_participants_treedef, &deleted_participants, dpp); + ddsrt_avl_delete (&deleted_participants_treedef, &deleted_participants, dpp); ddsrt_free (dpp); } dpp = dpp1; @@ -306,16 +306,16 @@ static void prune_deleted_participant_guids (nn_mtime_t tnow) static void remember_deleted_participant_guid (const struct nn_guid *guid) { struct deleted_participant *n; - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; ddsrt_mutex_lock (&deleted_participants_lock); - if (ut_avlLookupIPath (&deleted_participants_treedef, &deleted_participants, guid, &path) == NULL) + if (ddsrt_avl_lookup_ipath (&deleted_participants_treedef, &deleted_participants, guid, &path) == NULL) { if ((n = ddsrt_malloc (sizeof (*n))) != NULL) { n->guid = *guid; n->t_prune.v = T_NEVER; n->for_what = DPG_LOCAL | DPG_REMOTE; - ut_avlInsertIPath (&deleted_participants_treedef, &deleted_participants, n, &path); + ddsrt_avl_insert_ipath (&deleted_participants_treedef, &deleted_participants, n, &path); } } ddsrt_mutex_unlock (&deleted_participants_lock); @@ -327,7 +327,7 @@ int is_deleted_participant_guid (const struct nn_guid *guid, unsigned for_what) int known; ddsrt_mutex_lock (&deleted_participants_lock); prune_deleted_participant_guids_unlocked (now_mt()); - if ((n = ut_avlLookup (&deleted_participants_treedef, &deleted_participants, guid)) == NULL) + if ((n = ddsrt_avl_lookup (&deleted_participants_treedef, &deleted_participants, guid)) == NULL) known = 0; else known = ((n->for_what & for_what) != 0); @@ -340,7 +340,7 @@ static void remove_deleted_participant_guid (const struct nn_guid *guid, unsigne struct deleted_participant *n; DDS_LOG(DDS_LC_DISCOVERY, "remove_deleted_participant_guid(%x:%x:%x:%x for_what=%x)\n", PGUID (*guid), for_what); ddsrt_mutex_lock (&deleted_participants_lock); - if ((n = ut_avlLookup (&deleted_participants_treedef, &deleted_participants, guid)) != NULL) + if ((n = ddsrt_avl_lookup (&deleted_participants_treedef, &deleted_participants, guid)) != NULL) { if (config.prune_deleted_ppant.enforce_delay) { @@ -357,7 +357,7 @@ static void remove_deleted_participant_guid (const struct nn_guid *guid, unsigne } else { - ut_avlDelete (&deleted_participants_treedef, &deleted_participants, n); + ddsrt_avl_delete (&deleted_participants_treedef, &deleted_participants, n); ddsrt_free (n); } } @@ -971,13 +971,13 @@ static struct addrset *rebuild_make_all_addrs (int *nreaders, struct writer *wr) { struct addrset *all_addrs = new_addrset(); struct wr_prd_match *m; - ut_avlIter_t it; + ddsrt_avl_iter_t it; #ifdef DDSI_INCLUDE_SSM if (wr->supports_ssm && wr->ssm_as) copy_addrset_into_addrset_mc (all_addrs, wr->ssm_as); #endif *nreaders = 0; - for (m = ut_avlIterFirst (&wr_readers_treedef, &wr->readers, &it); m; m = ut_avlIterNext (&it)) + for (m = ddsrt_avl_iter_first (&wr_readers_treedef, &wr->readers, &it); m; m = ddsrt_avl_iter_next (&it)) { struct proxy_reader *prd; if ((prd = ephash_lookup_proxy_reader_guid (&m->prd_guid)) == NULL) @@ -1030,7 +1030,7 @@ static void rebuild_make_covered(int8_t **covered, const struct writer *wr, int { struct rebuild_flatten_locs_arg flarg; struct wr_prd_match *m; - ut_avlIter_t it; + ddsrt_avl_iter_t it; int rdidx, i, j; int8_t *cov = ddsrt_malloc((size_t) *nreaders * (size_t) nlocs * sizeof (*cov)); for (i = 0; i < *nreaders * nlocs; i++) @@ -1040,7 +1040,7 @@ static void rebuild_make_covered(int8_t **covered, const struct writer *wr, int #ifndef NDEBUG flarg.size = nlocs; #endif - for (m = ut_avlIterFirst (&wr_readers_treedef, &wr->readers, &it); m; m = ut_avlIterNext (&it)) + for (m = ddsrt_avl_iter_first (&wr_readers_treedef, &wr->readers, &it); m; m = ddsrt_avl_iter_next (&it)) { struct proxy_reader *prd; struct addrset *ass[] = { NULL, NULL, NULL }; @@ -1337,10 +1337,10 @@ static void writer_drop_connection (const struct nn_guid * wr_guid, const struct struct whc_node *deferred_free_list = NULL; struct wr_prd_match *m; ddsrt_mutex_lock (&wr->e.lock); - if ((m = ut_avlLookup (&wr_readers_treedef, &wr->readers, &prd->e.guid)) != NULL) + if ((m = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &prd->e.guid)) != NULL) { struct whc_state whcst; - ut_avlDelete (&wr_readers_treedef, &wr->readers, m); + ddsrt_avl_delete (&wr_readers_treedef, &wr->readers, m); rebuild_writer_addrset (wr); remove_acked_messages (wr, &whcst, &deferred_free_list); wr->num_reliable_readers -= m->is_reliable; @@ -1368,9 +1368,9 @@ static void writer_drop_local_connection (const struct nn_guid *wr_guid, struct struct wr_rd_match *m; ddsrt_mutex_lock (&wr->e.lock); - if ((m = ut_avlLookup (&wr_local_readers_treedef, &wr->local_readers, &rd->e.guid)) != NULL) + if ((m = ddsrt_avl_lookup (&wr_local_readers_treedef, &wr->local_readers, &rd->e.guid)) != NULL) { - ut_avlDelete (&wr_local_readers_treedef, &wr->local_readers, m); + ddsrt_avl_delete (&wr_local_readers_treedef, &wr->local_readers, m); local_reader_ary_remove (&wr->rdary, rd); } ddsrt_mutex_unlock (&wr->e.lock); @@ -1393,8 +1393,8 @@ static void reader_drop_connection (const struct nn_guid *rd_guid, const struct { struct rd_pwr_match *m; ddsrt_mutex_lock (&rd->e.lock); - if ((m = ut_avlLookup (&rd_writers_treedef, &rd->writers, &pwr->e.guid)) != NULL) - ut_avlDelete (&rd_writers_treedef, &rd->writers, m); + if ((m = ddsrt_avl_lookup (&rd_writers_treedef, &rd->writers, &pwr->e.guid)) != NULL) + ddsrt_avl_delete (&rd_writers_treedef, &rd->writers, m); ddsrt_mutex_unlock (&rd->e.lock); free_rd_pwr_match (m); @@ -1427,8 +1427,8 @@ static void reader_drop_local_connection (const struct nn_guid *rd_guid, const s { struct rd_wr_match *m; ddsrt_mutex_lock (&rd->e.lock); - if ((m = ut_avlLookup (&rd_local_writers_treedef, &rd->local_writers, &wr->e.guid)) != NULL) - ut_avlDelete (&rd_local_writers_treedef, &rd->local_writers, m); + if ((m = ddsrt_avl_lookup (&rd_local_writers_treedef, &rd->local_writers, &wr->e.guid)) != NULL) + ddsrt_avl_delete (&rd_local_writers_treedef, &rd->local_writers, m); ddsrt_mutex_unlock (&rd->e.lock); free_rd_wr_match (m); @@ -1486,9 +1486,9 @@ static void proxy_writer_drop_connection (const struct nn_guid *pwr_guid, struct struct pwr_rd_match *m; ddsrt_mutex_lock (&pwr->e.lock); - if ((m = ut_avlLookup (&pwr_readers_treedef, &pwr->readers, &rd->e.guid)) != NULL) + if ((m = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, &rd->e.guid)) != NULL) { - ut_avlDelete (&pwr_readers_treedef, &pwr->readers, m); + ddsrt_avl_delete (&pwr_readers_treedef, &pwr->readers, m); if (m->in_sync != PRMSS_SYNC) pwr->n_readers_out_of_sync--; if (rd->reliable) @@ -1512,10 +1512,10 @@ static void proxy_reader_drop_connection { struct prd_wr_match *m; ddsrt_mutex_lock (&prd->e.lock); - m = ut_avlLookup (&prd_writers_treedef, &prd->writers, &wr->e.guid); + m = ddsrt_avl_lookup (&prd_writers_treedef, &prd->writers, &wr->e.guid); if (m) { - ut_avlDelete (&prd_writers_treedef, &prd->writers, m); + ddsrt_avl_delete (&prd_writers_treedef, &prd->writers, m); } ddsrt_mutex_unlock (&prd->e.lock); free_prd_wr_match (m); @@ -1525,7 +1525,7 @@ static void proxy_reader_drop_connection static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) { struct wr_prd_match *m = ddsrt_malloc (sizeof (*m)); - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; int pretend_everything_acked; m->prd_guid = prd->e.guid; m->is_reliable = (prd->c.xqos->reliability.kind > NN_BEST_EFFORT_RELIABILITY_QOS); @@ -1564,7 +1564,7 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) m->seq = MAX_SEQ_NUMBER; else m->seq = wr->seq; - if (ut_avlLookupIPath (&wr_readers_treedef, &wr->readers, &prd->e.guid, &path)) + if (ddsrt_avl_lookup_ipath (&wr_readers_treedef, &wr->readers, &prd->e.guid, &path)) { DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); ddsrt_mutex_unlock (&wr->e.lock); @@ -1574,7 +1574,7 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) else { DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - ack seq %"PRId64"\n", PGUID (wr->e.guid), PGUID (prd->e.guid), m->seq); - ut_avlInsertIPath (&wr_readers_treedef, &wr->readers, m, &path); + ddsrt_avl_insert_ipath (&wr_readers_treedef, &wr->readers, m, &path); rebuild_writer_addrset (wr); wr->num_reliable_readers += m->is_reliable; ddsrt_mutex_unlock (&wr->e.lock); @@ -1618,10 +1618,10 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) static void writer_add_local_connection (struct writer *wr, struct reader *rd) { struct wr_rd_match *m = ddsrt_malloc (sizeof (*m)); - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; ddsrt_mutex_lock (&wr->e.lock); - if (ut_avlLookupIPath (&wr_local_readers_treedef, &wr->local_readers, &rd->e.guid, &path)) + if (ddsrt_avl_lookup_ipath (&wr_local_readers_treedef, &wr->local_readers, &rd->e.guid, &path)) { DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); ddsrt_mutex_unlock (&wr->e.lock); @@ -1631,7 +1631,7 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd) DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x)", PGUID (wr->e.guid), PGUID (rd->e.guid)); m->rd_guid = rd->e.guid; - ut_avlInsertIPath (&wr_local_readers_treedef, &wr->local_readers, m, &path); + ddsrt_avl_insert_ipath (&wr_local_readers_treedef, &wr->local_readers, m, &path); local_reader_ary_insert (&wr->rdary, rd); /* Store available data into the late joining reader when it is reliable (we don't do @@ -1672,7 +1672,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) { struct rd_pwr_match *m = ddsrt_malloc (sizeof (*m)); - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; m->pwr_guid = pwr->e.guid; @@ -1687,7 +1687,7 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, DDS_LOG(DDS_LC_DISCOVERY, " reader %x:%x:%x:%x init_acknack_count = %d\n", PGUID (rd->e.guid), rd->init_acknack_count); *init_count = rd->init_acknack_count; - if (ut_avlLookupIPath (&rd_writers_treedef, &rd->writers, &pwr->e.guid, &path)) + if (ddsrt_avl_lookup_ipath (&rd_writers_treedef, &rd->writers, &pwr->e.guid, &path)) { DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", PGUID (pwr->e.guid), PGUID (rd->e.guid)); @@ -1698,7 +1698,7 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, { DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr %x:%x:%x:%x rd %x:%x:%x:%x)\n", PGUID (pwr->e.guid), PGUID (rd->e.guid)); - ut_avlInsertIPath (&rd_writers_treedef, &rd->writers, m, &path); + ddsrt_avl_insert_ipath (&rd_writers_treedef, &rd->writers, m, &path); ddsrt_mutex_unlock (&rd->e.lock); #ifdef DDSI_INCLUDE_SSM @@ -1736,13 +1736,13 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, static void reader_add_local_connection (struct reader *rd, struct writer *wr) { struct rd_wr_match *m = ddsrt_malloc (sizeof (*m)); - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; m->wr_guid = wr->e.guid; ddsrt_mutex_lock (&rd->e.lock); - if (ut_avlLookupIPath (&rd_local_writers_treedef, &rd->local_writers, &wr->e.guid, &path)) + if (ddsrt_avl_lookup_ipath (&rd_local_writers_treedef, &rd->local_writers, &wr->e.guid, &path)) { DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); ddsrt_mutex_unlock (&rd->e.lock); @@ -1751,7 +1751,7 @@ static void reader_add_local_connection (struct reader *rd, struct writer *wr) else { DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x)\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); - ut_avlInsertIPath (&rd_local_writers_treedef, &rd->local_writers, m, &path); + ddsrt_avl_insert_ipath (&rd_local_writers_treedef, &rd->local_writers, m, &path); ddsrt_mutex_unlock (&rd->e.lock); if (rd->status_cb) @@ -1772,11 +1772,11 @@ static void reader_add_local_connection (struct reader *rd, struct writer *wr) static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader *rd, nn_mtime_t tnow, nn_count_t init_count) { struct pwr_rd_match *m = ddsrt_malloc (sizeof (*m)); - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; seqno_t last_deliv_seq; ddsrt_mutex_lock (&pwr->e.lock); - if (ut_avlLookupIPath (&pwr_readers_treedef, &pwr->readers, &rd->e.guid, &path)) + if (ddsrt_avl_lookup_ipath (&pwr_readers_treedef, &pwr->readers, &rd->e.guid, &path)) goto already_matched; if (pwr->c.topic == NULL && rd->topic) @@ -1816,7 +1816,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader { m->in_sync = PRMSS_SYNC; } - else if (!config.conservative_builtin_reader_startup && is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) && !ut_avlIsEmpty (&pwr->readers)) + else if (!config.conservative_builtin_reader_startup && is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) && !ddsrt_avl_is_empty (&pwr->readers)) { /* builtins really don't care about multiple copies */ m->in_sync = PRMSS_SYNC; @@ -1860,7 +1860,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader nn_reorder_new (NN_REORDER_MODE_MONOTONICALLY_INCREASING, config.secondary_reorder_maxsamples); } - ut_avlInsertIPath (&pwr_readers_treedef, &pwr->readers, m, &path); + ddsrt_avl_insert_ipath (&pwr_readers_treedef, &pwr->readers, m, &path); local_reader_ary_insert(&pwr->rdary, rd); ddsrt_mutex_unlock (&pwr->e.lock); qxev_pwr_entityid (pwr, &rd->e.guid.prefix); @@ -1890,13 +1890,13 @@ already_matched: static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer *wr) { struct prd_wr_match *m = ddsrt_malloc (sizeof (*m)); - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; m->wr_guid = wr->e.guid; ddsrt_mutex_lock (&prd->e.lock); if (prd->c.topic == NULL) prd->c.topic = ddsi_sertopic_ref (wr->topic); - if (ut_avlLookupIPath (&prd_writers_treedef, &prd->writers, &wr->e.guid, &path)) + if (ddsrt_avl_lookup_ipath (&prd_writers_treedef, &prd->writers, &wr->e.guid, &path)) { DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); @@ -1907,7 +1907,7 @@ static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer { DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x)\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); - ut_avlInsertIPath (&prd_writers_treedef, &prd->writers, m, &path); + ddsrt_avl_insert_ipath (&prd_writers_treedef, &prd->writers, m, &path); ddsrt_mutex_unlock (&prd->e.lock); qxev_prd_entityid (prd, &wr->e.guid.prefix); } @@ -2539,15 +2539,15 @@ static void augment_wr_prd_match (void *vnode, const void *vleft, const void *vr seqno_t writer_max_drop_seq (const struct writer *wr) { const struct wr_prd_match *n; - if (ut_avlIsEmpty (&wr->readers)) + if (ddsrt_avl_is_empty (&wr->readers)) return wr->seq; - n = ut_avlRootNonEmpty (&wr_readers_treedef, &wr->readers); + n = ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers); return (n->min_seq == MAX_SEQ_NUMBER) ? wr->seq : n->min_seq; } int writer_must_have_hb_scheduled (const struct writer *wr, const struct whc_state *whcst) { - if (ut_avlIsEmpty (&wr->readers) || whcst->max_seq < 0) + if (ddsrt_avl_is_empty (&wr->readers) || whcst->max_seq < 0) { /* Can't transmit a valid heartbeat if there is no data; and it wouldn't actually be sent anywhere if there are no readers, so @@ -2558,7 +2558,7 @@ int writer_must_have_hb_scheduled (const struct writer *wr, const struct whc_sta a heartbeat if no data is available. */ return 0; } - else if (!((const struct wr_prd_match *) ut_avlRootNonEmpty (&wr_readers_treedef, &wr->readers))->all_have_replied_to_hb) + else if (!((const struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->all_have_replied_to_hb) { /* Labouring under the belief that heartbeats must be sent regardless of ack state */ @@ -2800,8 +2800,8 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se assert (!is_builtin_entityid(wr->e.guid.entityid, NN_VENDORID_ECLIPSE) || (wr->whc_low == wr->whc_high && wr->whc_low == INT32_MAX)); /* Connection admin */ - ut_avlInit (&wr_readers_treedef, &wr->readers); - ut_avlInit (&wr_local_readers_treedef, &wr->local_readers); + ddsrt_avl_init (&wr_readers_treedef, &wr->readers); + ddsrt_avl_init (&wr_local_readers_treedef, &wr->local_readers); local_reader_ary_init (&wr->rdary); } @@ -2917,17 +2917,17 @@ static void gc_delete_writer (struct gcreq *gcreq) us now, because we can't be found via guid_hash anymore. We therefore need not take lock. */ - while (!ut_avlIsEmpty (&wr->readers)) + while (!ddsrt_avl_is_empty (&wr->readers)) { - struct wr_prd_match *m = ut_avlRootNonEmpty (&wr_readers_treedef, &wr->readers); - ut_avlDelete (&wr_readers_treedef, &wr->readers, m); + struct wr_prd_match *m = ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers); + ddsrt_avl_delete (&wr_readers_treedef, &wr->readers, m); proxy_reader_drop_connection (&m->prd_guid, wr); free_wr_prd_match (m); } - while (!ut_avlIsEmpty (&wr->local_readers)) + while (!ddsrt_avl_is_empty (&wr->local_readers)) { - struct wr_rd_match *m = ut_avlRootNonEmpty (&wr_local_readers_treedef, &wr->local_readers); - ut_avlDelete (&wr_local_readers_treedef, &wr->local_readers, m); + struct wr_rd_match *m = ddsrt_avl_root_non_empty (&wr_local_readers_treedef, &wr->local_readers); + ddsrt_avl_delete (&wr_local_readers_treedef, &wr->local_readers, m); reader_drop_local_connection (&m->rd_guid, wr); free_wr_rd_match (m); } @@ -3324,8 +3324,8 @@ static dds_retcode_t new_reader_guid #endif #endif - ut_avlInit (&rd_writers_treedef, &rd->writers); - ut_avlInit (&rd_local_writers_treedef, &rd->local_writers); + ddsrt_avl_init (&rd_writers_treedef, &rd->writers); + ddsrt_avl_init (&rd_local_writers_treedef, &rd->local_writers); ddsrt_mutex_lock (&rd->e.lock); ephash_insert_reader_guid (rd); @@ -3371,17 +3371,17 @@ static void gc_delete_reader (struct gcreq *gcreq) DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_reader(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (rd->e.guid)); gcreq_free (gcreq); - while (!ut_avlIsEmpty (&rd->writers)) + while (!ddsrt_avl_is_empty (&rd->writers)) { - struct rd_pwr_match *m = ut_avlRootNonEmpty (&rd_writers_treedef, &rd->writers); - ut_avlDelete (&rd_writers_treedef, &rd->writers, m); + struct rd_pwr_match *m = ddsrt_avl_root_non_empty (&rd_writers_treedef, &rd->writers); + ddsrt_avl_delete (&rd_writers_treedef, &rd->writers, m); proxy_writer_drop_connection (&m->pwr_guid, rd); free_rd_pwr_match (m); } - while (!ut_avlIsEmpty (&rd->local_writers)) + while (!ddsrt_avl_is_empty (&rd->local_writers)) { - struct rd_wr_match *m = ut_avlRootNonEmpty (&rd_local_writers_treedef, &rd->local_writers); - ut_avlDelete (&rd_local_writers_treedef, &rd->local_writers, m); + struct rd_wr_match *m = ddsrt_avl_root_non_empty (&rd_local_writers_treedef, &rd->local_writers); + ddsrt_avl_delete (&rd_local_writers_treedef, &rd->local_writers, m); writer_drop_local_connection (&m->wr_guid, rd); free_rd_wr_match (m); } @@ -3552,7 +3552,7 @@ void new_proxy_participant proxypp->as_meta = as_meta; proxypp->endpoints = NULL; proxypp->plist = nn_plist_dup (plist); - ut_avlInit (&proxypp_groups_treedef, &proxypp->groups); + ddsrt_avl_init (&proxypp_groups_treedef, &proxypp->groups); if (custom_flags & CF_INC_KERNEL_SEQUENCE_NUMBERS) @@ -3851,8 +3851,8 @@ static void delete_ppt (struct proxy_participant * proxypp, nn_wctime_t timestam proxypp->lease_expired = 1; DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt(%x:%x:%x:%x) - deleting groups\n", PGUID (proxypp->e.guid)); - while (!ut_avlIsEmpty (&proxypp->groups)) - delete_proxy_group_locked (ut_avlRoot (&proxypp_groups_treedef, &proxypp->groups), timestamp, isimplicit); + while (!ddsrt_avl_is_empty (&proxypp->groups)) + delete_proxy_group_locked (ddsrt_avl_root (&proxypp_groups_treedef, &proxypp->groups), timestamp, isimplicit); DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt(%x:%x:%x:%x) - deleting endpoints\n", PGUID (proxypp->e.guid)); c = proxypp->endpoints; @@ -3965,7 +3965,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct else { struct proxy_group *pgroup; - ut_avlIPath_t ipath; + ddsrt_avl_ipath_t ipath; int is_sub; switch (guid->entityid.u & (NN_ENTITYID_SOURCE_MASK | NN_ENTITYID_KIND_MASK)) { @@ -3980,7 +3980,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct return Q_ERR_INVALID_DATA; } ddsrt_mutex_lock (&proxypp->e.lock); - if ((pgroup = ut_avlLookupIPath (&proxypp_groups_treedef, &proxypp->groups, guid, &ipath)) != NULL) + if ((pgroup = ddsrt_avl_lookup_ipath (&proxypp_groups_treedef, &proxypp->groups, guid, &ipath)) != NULL) { /* Complete proxy group definition if it was a partial definition made by creating a proxy reader or writer, @@ -3997,7 +3997,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct pgroup->proxypp = proxypp; pgroup->name = NULL; pgroup->xqos = NULL; - ut_avlInsertIPath (&proxypp_groups_treedef, &proxypp->groups, pgroup, &ipath); + ddsrt_avl_insert_ipath (&proxypp_groups_treedef, &proxypp->groups, pgroup, &ipath); } if (name) { @@ -4021,7 +4021,7 @@ static void delete_proxy_group_locked (struct proxy_group *pgroup, nn_wctime_t t (void)isimplicit; assert ((pgroup->xqos != NULL) == (pgroup->name != NULL)); DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_group_locked %x:%x:%x:%x\n", PGUID (pgroup->guid)); - ut_avlDelete (&proxypp_groups_treedef, &proxypp->groups, pgroup); + ddsrt_avl_delete (&proxypp_groups_treedef, &proxypp->groups, pgroup); /* Publish corresponding built-in topic only if it is not a place holder: in that case we haven't announced its presence and therefore don't need to dispose it, and this saves us from having @@ -4046,7 +4046,7 @@ void delete_proxy_group (const nn_guid_t *guid, nn_wctime_t timestamp, int isimp { struct proxy_group *pgroup; ddsrt_mutex_lock (&proxypp->e.lock); - if ((pgroup = ut_avlLookup (&proxypp_groups_treedef, &proxypp->groups, guid)) != NULL) + if ((pgroup = ddsrt_avl_lookup (&proxypp_groups_treedef, &proxypp->groups, guid)) != NULL) delete_proxy_group_locked (pgroup, timestamp, isimplicit); ddsrt_mutex_unlock (&proxypp->e.lock); } @@ -4112,7 +4112,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, pwr = ddsrt_malloc (sizeof (*pwr)); proxy_endpoint_common_init (&pwr->e, &pwr->c, EK_PROXY_WRITER, guid, timestamp, proxypp, as, plist); - ut_avlInit (&pwr_readers_treedef, &pwr->readers); + ddsrt_avl_init (&pwr_readers_treedef, &pwr->readers); pwr->n_reliable_readers = 0; pwr->n_readers_out_of_sync = 0; pwr->last_seq = 0; @@ -4195,7 +4195,7 @@ void update_proxy_writer (struct proxy_writer * pwr, struct addrset * as) { struct reader * rd; struct pwr_rd_match * m; - ut_avlIter_t iter; + ddsrt_avl_iter_t iter; /* Update proxy writer endpoints (from SEDP alive) */ @@ -4208,7 +4208,7 @@ void update_proxy_writer (struct proxy_writer * pwr, struct addrset * as) unref_addrset (pwr->c.as); ref_addrset (as); pwr->c.as = as; - m = ut_avlIterFirst (&pwr_readers_treedef, &pwr->readers, &iter); + m = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &iter); while (m) { rd = ephash_lookup_reader_guid (&m->rd_guid); @@ -4216,7 +4216,7 @@ void update_proxy_writer (struct proxy_writer * pwr, struct addrset * as) { qxev_pwr_entityid (pwr, &rd->e.guid.prefix); } - m = ut_avlIterNext (&iter); + m = ddsrt_avl_iter_next (&iter); } } ddsrt_mutex_unlock (&pwr->e.lock); @@ -4240,14 +4240,14 @@ void update_proxy_reader (struct proxy_reader * prd, struct addrset * as) /* Rebuild writer endpoints */ - while ((m = ut_avlLookupSuccEq (&prd_writers_treedef, &prd->writers, &wrguid)) != NULL) + while ((m = ddsrt_avl_lookup_succ_eq (&prd_writers_treedef, &prd->writers, &wrguid)) != NULL) { struct prd_wr_match *next; nn_guid_t guid_next; struct writer * wr; wrguid = m->wr_guid; - next = ut_avlFindSucc (&prd_writers_treedef, &prd->writers, m); + next = ddsrt_avl_find_succ (&prd_writers_treedef, &prd->writers, m); if (next) { guid_next = next->wr_guid; @@ -4280,10 +4280,10 @@ static void gc_delete_proxy_writer (struct gcreq *gcreq) DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (pwr->e.guid)); gcreq_free (gcreq); - while (!ut_avlIsEmpty (&pwr->readers)) + while (!ddsrt_avl_is_empty (&pwr->readers)) { - struct pwr_rd_match *m = ut_avlRootNonEmpty (&pwr_readers_treedef, &pwr->readers); - ut_avlDelete (&pwr_readers_treedef, &pwr->readers, m); + struct pwr_rd_match *m = ddsrt_avl_root_non_empty (&pwr_readers_treedef, &pwr->readers); + ddsrt_avl_delete (&pwr_readers_treedef, &pwr->readers, m); reader_drop_connection (&m->rd_guid, pwr); update_reader_init_acknack_count (&m->rd_guid, m->count); free_pwr_rd_match (m); @@ -4353,7 +4353,7 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, "real" participant, rather than the thing we use for endpoints discovered via the DS */ prd->assert_pp_lease = (unsigned) !!config.arrival_of_data_asserts_pp_and_ep_liveliness; - ut_avlInit (&prd_writers_treedef, &prd->writers); + ddsrt_avl_init (&prd_writers_treedef, &prd->writers); /* locking the entity prevents matching while the built-in topic hasn't been published yet */ ddsrt_mutex_lock (&prd->e.lock); @@ -4374,14 +4374,14 @@ static void proxy_reader_set_delete_and_ack_all_messages (struct proxy_reader *p memset (&wrguid, 0, sizeof (wrguid)); ddsrt_mutex_lock (&prd->e.lock); prd->deleting = 1; - while ((m = ut_avlLookupSuccEq (&prd_writers_treedef, &prd->writers, &wrguid)) != NULL) + while ((m = ddsrt_avl_lookup_succ_eq (&prd_writers_treedef, &prd->writers, &wrguid)) != NULL) { /* have to be careful walking the tree -- pretty is different, but I want to check this before I write a lookup_succ function. */ struct prd_wr_match *m_a_next; nn_guid_t wrguid_next; wrguid = m->wr_guid; - if ((m_a_next = ut_avlFindSucc (&prd_writers_treedef, &prd->writers, m)) != NULL) + if ((m_a_next = ddsrt_avl_find_succ (&prd_writers_treedef, &prd->writers, m)) != NULL) wrguid_next = m_a_next->wr_guid; else { @@ -4395,11 +4395,11 @@ static void proxy_reader_set_delete_and_ack_all_messages (struct proxy_reader *p struct whc_node *deferred_free_list = NULL; struct wr_prd_match *m_wr; ddsrt_mutex_lock (&wr->e.lock); - if ((m_wr = ut_avlLookup (&wr_readers_treedef, &wr->readers, &prd->e.guid)) != NULL) + if ((m_wr = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &prd->e.guid)) != NULL) { struct whc_state whcst; m_wr->seq = MAX_SEQ_NUMBER; - ut_avlAugmentUpdate (&wr_readers_treedef, m_wr); + ddsrt_avl_augment_update (&wr_readers_treedef, m_wr); (void)remove_acked_messages (wr, &whcst, &deferred_free_list); writer_clear_retransmitting (wr); } @@ -4419,10 +4419,10 @@ static void gc_delete_proxy_reader (struct gcreq *gcreq) DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_reader(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (prd->e.guid)); gcreq_free (gcreq); - while (!ut_avlIsEmpty (&prd->writers)) + while (!ddsrt_avl_is_empty (&prd->writers)) { - struct prd_wr_match *m = ut_avlRootNonEmpty (&prd_writers_treedef, &prd->writers); - ut_avlDelete (&prd_writers_treedef, &prd->writers, m); + struct prd_wr_match *m = ddsrt_avl_root_non_empty (&prd_writers_treedef, &prd->writers); + ddsrt_avl_delete (&prd_writers_treedef, &prd->writers, m); writer_drop_connection (&m->wr_guid, prd); free_prd_wr_match (m); } diff --git a/src/core/ddsi/src/q_ephash.c b/src/core/ddsi/src/q_ephash.c index f287aae..d02fcba 100644 --- a/src/core/ddsi/src/q_ephash.c +++ b/src/core/ddsi/src/q_ephash.c @@ -15,7 +15,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/misc.h" -#include "dds/util/ut_hopscotch.h" +#include "dds/ddsrt/hopscotch.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_globals.h" @@ -25,7 +25,7 @@ #include "dds/ddsi/q_thread.h" /* for assert(thread is awake) */ struct ephash { - struct ut_chh *hash; + struct ddsrt_chh *hash; }; static const uint64_t unihashconsts[] = { @@ -80,7 +80,7 @@ struct ephash *ephash_new (void) { struct ephash *ephash; ephash = ddsrt_malloc (sizeof (*ephash)); - ephash->hash = ut_chhNew (32, hash_entity_guid_wrapper, entity_guid_eq_wrapper, gc_buckets); + ephash->hash = ddsrt_chh_new (32, hash_entity_guid_wrapper, entity_guid_eq_wrapper, gc_buckets); if (ephash->hash == NULL) { ddsrt_free (ephash); return NULL; @@ -91,7 +91,7 @@ struct ephash *ephash_new (void) void ephash_free (struct ephash *ephash) { - ut_chhFree (ephash->hash); + ddsrt_chh_free (ephash->hash); ephash->hash = NULL; ddsrt_free (ephash); } @@ -101,7 +101,7 @@ static void ephash_guid_insert (struct entity_common *e) int x; assert(gv.guid_hash); assert(gv.guid_hash->hash); - x = ut_chhAdd (gv.guid_hash->hash, e); + x = ddsrt_chh_add (gv.guid_hash->hash, e); (void)x; assert (x); } @@ -111,7 +111,7 @@ static void ephash_guid_remove (struct entity_common *e) int x; assert(gv.guid_hash); assert(gv.guid_hash->hash); - x = ut_chhRemove (gv.guid_hash->hash, e); + x = ddsrt_chh_remove (gv.guid_hash->hash, e); (void)x; assert (x); } @@ -121,7 +121,7 @@ void *ephash_lookup_guid_untyped (const struct nn_guid *guid) /* FIXME: could (now) require guid to be first in entity_common; entity_common already is first in entity */ struct entity_common e; e.guid = *guid; - return ut_chhLookup (gv.guid_hash->hash, &e); + return ddsrt_chh_lookup (gv.guid_hash->hash, &e); } static void *ephash_lookup_guid_int (const struct ephash *ephash, const struct nn_guid *guid, enum entity_kind kind) @@ -246,9 +246,9 @@ struct proxy_reader *ephash_lookup_proxy_reader_guid (const struct nn_guid *guid static void ephash_enum_init_int (struct ephash_enum *st, struct ephash *ephash, enum entity_kind kind) { st->kind = kind; - st->cur = ut_chhIterFirst (ephash->hash, &st->it); + st->cur = ddsrt_chh_iter_first (ephash->hash, &st->it); while (st->cur && st->cur->kind != st->kind) - st->cur = ut_chhIterNext (&st->it); + st->cur = ddsrt_chh_iter_next (&st->it); } void ephash_enum_init (struct ephash_enum *st, enum entity_kind kind) @@ -291,9 +291,9 @@ void *ephash_enum_next (struct ephash_enum *st) void *res = st->cur; if (st->cur) { - st->cur = ut_chhIterNext (&st->it); + st->cur = ddsrt_chh_iter_next (&st->it); while (st->cur && st->cur->kind != st->kind) - st->cur = ut_chhIterNext (&st->it); + st->cur = ddsrt_chh_iter_next (&st->it); } return res; } diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 0b89411..ee25e6c 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -19,8 +19,8 @@ #include "dds/ddsrt/string.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_avl.h" -#include "dds/util/ut_thread_pool.h" +#include "dds/ddsrt/avl.h" +#include "dds/ddsrt/thread_pool.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_rtps.h" @@ -895,7 +895,7 @@ int rtps_init (void) if (config.tp_enable) { - gv.thread_pool = ut_thread_pool_new + gv.thread_pool = ddsrt_thread_pool_new (config.tp_threads, config.tp_max_threads, 0, NULL); } @@ -1357,7 +1357,7 @@ err_find_own_ip: ddsi_tran_factories_fini (); err_udp_tcp_init: if (config.tp_enable) - ut_thread_pool_free (gv.thread_pool); + ddsrt_thread_pool_free (gv.thread_pool); return -1; } @@ -1609,7 +1609,7 @@ void rtps_fini (void) } #endif - ut_thread_pool_free (gv.thread_pool); + ddsrt_thread_pool_free (gv.thread_pool); (void) joinleave_spdp_defmcip (0); diff --git a/src/core/ddsi/src/q_inverse_uint32_set.c b/src/core/ddsi/src/q_inverse_uint32_set.c index 99d24ac..0750425 100644 --- a/src/core/ddsi/src/q_inverse_uint32_set.c +++ b/src/core/ddsi/src/q_inverse_uint32_set.c @@ -12,14 +12,14 @@ #include #include #include "dds/ddsrt/heap.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_inverse_uint32_set.h" static int uint32_t_cmp(const void *va, const void *vb); -static ut_avlTreedef_t inverse_uint32_set_td = UT_AVL_TREEDEF_INITIALIZER(offsetof(struct inverse_uint32_set_node, avlnode), offsetof(struct inverse_uint32_set_node, min), uint32_t_cmp, 0); +static ddsrt_avl_treedef_t inverse_uint32_set_td = DDSRT_AVL_TREEDEF_INITIALIZER(offsetof(struct inverse_uint32_set_node, avlnode), offsetof(struct inverse_uint32_set_node, min), uint32_t_cmp, 0); static int uint32_t_cmp(const void *va, const void *vb) { @@ -31,12 +31,12 @@ static int uint32_t_cmp(const void *va, const void *vb) static void check(const struct inverse_uint32_set *set) { #ifndef NDEBUG - ut_avlIter_t it; + ddsrt_avl_iter_t it; struct inverse_uint32_set_node *pn = NULL, *n; assert(set->min <= set->max); assert(set->cursor >= set->min); assert(set->cursor <= set->max); - for (n = ut_avlIterFirst(&inverse_uint32_set_td, &set->ids, &it); n; pn = n, n = ut_avlIterNext(&it)) + for (n = ddsrt_avl_iter_first(&inverse_uint32_set_td, &set->ids, &it); n; pn = n, n = ddsrt_avl_iter_next(&it)) { assert(n->min <= n->max); assert(n->min >= set->min); @@ -51,20 +51,20 @@ static void check(const struct inverse_uint32_set *set) void inverse_uint32_set_init(struct inverse_uint32_set *set, uint32_t min, uint32_t max) { struct inverse_uint32_set_node *n; - ut_avlInit(&inverse_uint32_set_td, &set->ids); + ddsrt_avl_init(&inverse_uint32_set_td, &set->ids); set->cursor = min; set->min = min; set->max = max; n = ddsrt_malloc(sizeof(*n)); n->min = min; n->max = max; - ut_avlInsert(&inverse_uint32_set_td, &set->ids, n); + ddsrt_avl_insert(&inverse_uint32_set_td, &set->ids, n); check(set); } void inverse_uint32_set_fini(struct inverse_uint32_set *set) { - ut_avlFree(&inverse_uint32_set_td, &set->ids, ddsrt_free); + ddsrt_avl_free(&inverse_uint32_set_td, &set->ids, ddsrt_free); } static uint32_t inverse_uint32_set_alloc_use_min(struct inverse_uint32_set *set, struct inverse_uint32_set_node *n) @@ -72,7 +72,7 @@ static uint32_t inverse_uint32_set_alloc_use_min(struct inverse_uint32_set *set, const uint32_t id = n->min; if (n->min == n->max) { - ut_avlDelete(&inverse_uint32_set_td, &set->ids, n); + ddsrt_avl_delete(&inverse_uint32_set_td, &set->ids, n); ddsrt_free(n); } else @@ -86,7 +86,7 @@ static uint32_t inverse_uint32_set_alloc_use_min(struct inverse_uint32_set *set, int inverse_uint32_set_alloc(uint32_t * const id, struct inverse_uint32_set *set) { struct inverse_uint32_set_node *n; - if ((n = ut_avlLookupPredEq(&inverse_uint32_set_td, &set->ids, &set->cursor)) != NULL && set->cursor <= n->max) { + if ((n = ddsrt_avl_lookup_pred_eq(&inverse_uint32_set_td, &set->ids, &set->cursor)) != NULL && set->cursor <= n->max) { /* n is [a,b] s.t. a <= C <= b, so C is available */ *id = set->cursor; if (n->min == set->cursor) @@ -105,15 +105,15 @@ int inverse_uint32_set_alloc(uint32_t * const id, struct inverse_uint32_set *set n1->min = set->cursor + 1; n1->max = n->max; n->max = set->cursor - 1; - ut_avlInsert(&inverse_uint32_set_td, &set->ids, n1); + ddsrt_avl_insert(&inverse_uint32_set_td, &set->ids, n1); } } - else if ((n = ut_avlLookupSucc(&inverse_uint32_set_td, &set->ids, &set->cursor)) != NULL) + else if ((n = ddsrt_avl_lookup_succ(&inverse_uint32_set_td, &set->ids, &set->cursor)) != NULL) { /* n is [a,b] s.t. a > C and all intervals [a',b'] in tree have a' <= C */ *id = inverse_uint32_set_alloc_use_min(set, n); } - else if ((n = ut_avlFindMin(&inverse_uint32_set_td, &set->ids)) != NULL) + else if ((n = ddsrt_avl_find_min(&inverse_uint32_set_td, &set->ids)) != NULL) { /* no available ids >= cursor: wrap around and use the first available */ assert(n->max < set->cursor); @@ -133,8 +133,8 @@ void inverse_uint32_set_free(struct inverse_uint32_set *set, uint32_t id) { struct inverse_uint32_set_node *n; const uint32_t idp1 = id + 1; - ut_avlIPath_t ip; - if ((n = ut_avlLookupPredEq(&inverse_uint32_set_td, &set->ids, &id)) != NULL && id <= n->max + 1) { + ddsrt_avl_ipath_t ip; + if ((n = ddsrt_avl_lookup_pred_eq(&inverse_uint32_set_td, &set->ids, &id)) != NULL && id <= n->max + 1) { if (id <= n->max) { /* n is [a,b] s.t. a <= I <= b: so it is already in the set */ @@ -143,18 +143,18 @@ void inverse_uint32_set_free(struct inverse_uint32_set *set, uint32_t id) else { struct inverse_uint32_set_node *n1; - ut_avlDPath_t dp; + ddsrt_avl_dpath_t dp; /* grow the interval, possibly coalesce with next */ - if ((n1 = ut_avlLookupDPath(&inverse_uint32_set_td, &set->ids, &idp1, &dp)) == NULL) { + if ((n1 = ddsrt_avl_lookup_dpath(&inverse_uint32_set_td, &set->ids, &idp1, &dp)) == NULL) { n->max = id; } else { n->max = n1->max; - ut_avlDeleteDPath(&inverse_uint32_set_td, &set->ids, n1, &dp); + ddsrt_avl_delete_dpath(&inverse_uint32_set_td, &set->ids, n1, &dp); ddsrt_free(n1); } } } - else if ((n = ut_avlLookupIPath(&inverse_uint32_set_td, &set->ids, &idp1, &ip)) != NULL) { + else if ((n = ddsrt_avl_lookup_ipath(&inverse_uint32_set_td, &set->ids, &idp1, &ip)) != NULL) { /* changing the key in-place here: the key value may be changing, but the structure of the tree is not or the previous case would have applied */ n->min = id; } @@ -163,7 +163,7 @@ void inverse_uint32_set_free(struct inverse_uint32_set *set, uint32_t id) /* no adjacent interval */ n = ddsrt_malloc(sizeof(*n)); n->min = n->max = id; - ut_avlInsertIPath(&inverse_uint32_set_td, &set->ids, n, &ip); + ddsrt_avl_insert_ipath(&inverse_uint32_set_td, &set->ids, n, &ip); } check(set); } diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index 0e2d99c..22dc1f4 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -16,7 +16,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_fibheap.h" +#include "dds/ddsrt/fibheap.h" #include "dds/ddsi/ddsi_serdata_default.h" #include "dds/ddsi/q_protocol.h" @@ -44,7 +44,7 @@ #define TSCHED_NOT_ON_HEAP INT64_MIN struct lease { - ut_fibheapNode_t heapnode; + ddsrt_fibheap_node_t heapnode; nn_etime_t tsched; /* access guarded by leaseheap_lock */ nn_etime_t tend; /* access guarded by lock_lease/unlock_lease */ int64_t tdur; /* constant (renew depends on it) */ @@ -53,7 +53,7 @@ struct lease { static int compare_lease_tsched (const void *va, const void *vb); -static const ut_fibheapDef_t lease_fhdef = UT_FIBHEAPDEF_INITIALIZER(offsetof (struct lease, heapnode), compare_lease_tsched); +static const ddsrt_fibheap_def_t lease_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct lease, heapnode), compare_lease_tsched); static void force_lease_check (void) { @@ -73,13 +73,13 @@ void lease_management_init (void) ddsrt_mutex_init (&gv.leaseheap_lock); for (i = 0; i < N_LEASE_LOCKS; i++) ddsrt_mutex_init (&gv.lease_locks[i]); - ut_fibheapInit (&lease_fhdef, &gv.leaseheap); + ddsrt_fibheap_init (&lease_fhdef, &gv.leaseheap); } void lease_management_term (void) { int i; - assert (ut_fibheapMin (&lease_fhdef, &gv.leaseheap) == NULL); + assert (ddsrt_fibheap_min (&lease_fhdef, &gv.leaseheap) == NULL); for (i = 0; i < N_LEASE_LOCKS; i++) ddsrt_mutex_destroy (&gv.lease_locks[i]); ddsrt_mutex_destroy (&gv.leaseheap_lock); @@ -125,7 +125,7 @@ void lease_register (struct lease *l) if (l->tend.v != T_NEVER) { l->tsched = l->tend; - ut_fibheapInsert (&lease_fhdef, &gv.leaseheap, l); + ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l); } unlock_lease (l); ddsrt_mutex_unlock (&gv.leaseheap_lock); @@ -139,7 +139,7 @@ void lease_free (struct lease *l) DDS_TRACE("lease_free(l %p guid %x:%x:%x:%x)\n", (void *) l, PGUID (l->entity->guid)); ddsrt_mutex_lock (&gv.leaseheap_lock); if (l->tsched.v != TSCHED_NOT_ON_HEAP) - ut_fibheapDelete (&lease_fhdef, &gv.leaseheap, l); + ddsrt_fibheap_delete (&lease_fhdef, &gv.leaseheap, l); ddsrt_mutex_unlock (&gv.leaseheap_lock); ddsrt_free (l); @@ -187,14 +187,14 @@ void lease_set_expiry (struct lease *l, nn_etime_t when) /* moved forward and currently scheduled (by virtue of TSCHED_NOT_ON_HEAP == INT64_MIN) */ l->tsched = l->tend; - ut_fibheapDecreaseKey (&lease_fhdef, &gv.leaseheap, l); + ddsrt_fibheap_decrease_key (&lease_fhdef, &gv.leaseheap, l); trigger = true; } else if (l->tsched.v == TSCHED_NOT_ON_HEAP && l->tend.v < T_NEVER) { /* not currently scheduled, with a finite new expiry time */ l->tsched = l->tend; - ut_fibheapInsert (&lease_fhdef, &gv.leaseheap, l); + ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l); trigger = true; } unlock_lease (l); @@ -210,13 +210,13 @@ int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) struct lease *l; int64_t delay; ddsrt_mutex_lock (&gv.leaseheap_lock); - while ((l = ut_fibheapMin (&lease_fhdef, &gv.leaseheap)) != NULL && l->tsched.v <= tnowE.v) + while ((l = ddsrt_fibheap_min (&lease_fhdef, &gv.leaseheap)) != NULL && l->tsched.v <= tnowE.v) { nn_guid_t g = l->entity->guid; enum entity_kind k = l->entity->kind; assert (l->tsched.v != TSCHED_NOT_ON_HEAP); - ut_fibheapExtractMin (&lease_fhdef, &gv.leaseheap); + ddsrt_fibheap_extract_min (&lease_fhdef, &gv.leaseheap); lock_lease (l); if (tnowE.v < l->tend.v) @@ -228,7 +228,7 @@ int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) } else { l->tsched = l->tend; unlock_lease (l); - ut_fibheapInsert (&lease_fhdef, &gv.leaseheap, l); + ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l); } continue; } @@ -270,7 +270,7 @@ int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) PGUID (proxypp->privileged_pp_guid)); l->tsched = l->tend = add_duration_to_etime (tnowE, 200 * T_MILLISECOND); unlock_lease (l); - ut_fibheapInsert (&lease_fhdef, &gv.leaseheap, l); + ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l); continue; } } diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index c013080..6e8cbef 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -31,7 +31,7 @@ #include "dds/ddsi/q_addrset.h" /* unspec locator */ #include "dds/ddsi/q_feature_check.h" #include "dds/ddsi/ddsi_ipaddr.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" static void print_sockerror (const char *msg) { diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index c7a8222..fed7f43 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -32,7 +32,7 @@ #include "dds/ddsi/q_radmin.h" /* for nn_plist_quickscan */ #include "dds/ddsi/q_static_assert.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_misc.h" /* for vendor_is_... */ /* These are internal to the parameter list processing. We never diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index 8b49c64..4a739fd 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -28,7 +28,7 @@ #include "dds/ddsrt/string.h" #include "dds/ddsrt/log.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_misc.h" @@ -812,7 +812,7 @@ static void nn_rdata_unref (struct nn_rdata *rdata) anyway). */ struct nn_defrag_iv { - ut_avlNode_t avlnode; /* for nn_rsample.defrag::fragtree */ + ddsrt_avl_node_t avlnode; /* for nn_rsample.defrag::fragtree */ uint32_t min, maxp1; struct nn_rdata *first; struct nn_rdata *last; @@ -821,14 +821,14 @@ struct nn_defrag_iv { struct nn_rsample { union { struct nn_rsample_defrag { - ut_avlNode_t avlnode; /* for nn_defrag::sampletree */ - ut_avlTree_t fragtree; + ddsrt_avl_node_t avlnode; /* for nn_defrag::sampletree */ + ddsrt_avl_tree_t fragtree; struct nn_defrag_iv *lastfrag; struct nn_rsample_info *sampleinfo; seqno_t seq; } defrag; struct nn_rsample_reorder { - ut_avlNode_t avlnode; /* for nn_reorder::sampleivtree, if head of a chain */ + ddsrt_avl_node_t avlnode; /* for nn_reorder::sampleivtree, if head of a chain */ struct nn_rsample_chain sc; /* this interval's samples, covering ... */ seqno_t min, maxp1; /* ... seq nos: [min,maxp1), but possibly with holes in it */ uint32_t n_samples; /* so this is the actual length of the chain */ @@ -837,7 +837,7 @@ struct nn_rsample { }; struct nn_defrag { - ut_avlTree_t sampletree; + ddsrt_avl_tree_t sampletree; struct nn_rsample *max_sample; /* = max(sampletree) */ uint32_t n_samples; uint32_t max_samples; @@ -847,8 +847,8 @@ struct nn_defrag { static int compare_uint32 (const void *va, const void *vb); static int compare_seqno (const void *va, const void *vb); -static const ut_avlTreedef_t defrag_sampletree_treedef = UT_AVL_TREEDEF_INITIALIZER (offsetof (struct nn_rsample, u.defrag.avlnode), offsetof (struct nn_rsample, u.defrag.seq), compare_seqno, 0); -static const ut_avlTreedef_t rsample_defrag_fragtree_treedef = UT_AVL_TREEDEF_INITIALIZER (offsetof (struct nn_defrag_iv, avlnode), offsetof (struct nn_defrag_iv, min), compare_uint32, 0); +static const ddsrt_avl_treedef_t defrag_sampletree_treedef = DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct nn_rsample, u.defrag.avlnode), offsetof (struct nn_rsample, u.defrag.seq), compare_seqno, 0); +static const ddsrt_avl_treedef_t rsample_defrag_fragtree_treedef = DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct nn_defrag_iv, avlnode), offsetof (struct nn_defrag_iv, min), compare_uint32, 0); static int compare_uint32 (const void *va, const void *vb) { @@ -870,7 +870,7 @@ struct nn_defrag *nn_defrag_new (enum nn_defrag_drop_mode drop_mode, uint32_t ma assert (max_samples >= 1); if ((d = ddsrt_malloc (sizeof (*d))) == NULL) return NULL; - ut_avlInit (&defrag_sampletree_treedef, &d->sampletree); + ddsrt_avl_init (&defrag_sampletree_treedef, &d->sampletree); d->drop_mode = drop_mode; d->max_samples = max_samples; d->n_samples = 0; @@ -903,25 +903,25 @@ static void defrag_rsample_drop (struct nn_defrag *defrag, struct nn_rsample *rs So we need to walk the fragments while guaranteeing strict "forward progress" in the memory accesses, which this particular inorder treewalk does provide. */ - ut_avlIter_t iter; + ddsrt_avl_iter_t iter; struct nn_defrag_iv *iv; DDS_LOG(DDS_LC_RADMIN, " defrag_rsample_drop (%p, %p)\n", (void *) defrag, (void *) rsample); - ut_avlDelete (&defrag_sampletree_treedef, &defrag->sampletree, rsample); + ddsrt_avl_delete (&defrag_sampletree_treedef, &defrag->sampletree, rsample); assert (defrag->n_samples > 0); defrag->n_samples--; - for (iv = ut_avlIterFirst (&rsample_defrag_fragtree_treedef, &rsample->u.defrag.fragtree, &iter); iv; iv = ut_avlIterNext (&iter)) + for (iv = ddsrt_avl_iter_first (&rsample_defrag_fragtree_treedef, &rsample->u.defrag.fragtree, &iter); iv; iv = ddsrt_avl_iter_next (&iter)) nn_fragchain_rmbias (iv->first); } void nn_defrag_free (struct nn_defrag *defrag) { struct nn_rsample *s; - s = ut_avlFindMin (&defrag_sampletree_treedef, &defrag->sampletree); + s = ddsrt_avl_find_min (&defrag_sampletree_treedef, &defrag->sampletree); while (s) { DDS_LOG(DDS_LC_RADMIN, "defrag_free(%p, sample %p seq %"PRId64")\n", (void *) defrag, (void *) s, s->u.defrag.seq); defrag_rsample_drop (defrag, s); - s = ut_avlFindMin (&defrag_sampletree_treedef, &defrag->sampletree); + s = ddsrt_avl_find_min (&defrag_sampletree_treedef, &defrag->sampletree); } assert (defrag->n_samples == 0); ddsrt_free (defrag); @@ -940,7 +940,7 @@ static int defrag_try_merge_with_succ (struct nn_rsample_defrag *sample, struct return 0; } - succ = ut_avlFindSucc (&rsample_defrag_fragtree_treedef, &sample->fragtree, node); + succ = ddsrt_avl_find_succ (&rsample_defrag_fragtree_treedef, &sample->fragtree, node); assert (succ != NULL); DDS_LOG(DDS_LC_RADMIN, " succ is %p [%u..%u)\n", (void *) succ, succ->min, succ->maxp1); if (succ->min > node->maxp1) @@ -955,7 +955,7 @@ static int defrag_try_merge_with_succ (struct nn_rsample_defrag *sample, struct /* no longer a gap between node & succ => succ will be removed from the interval tree and therefore node will become the last interval if succ currently is */ - ut_avlDelete (&rsample_defrag_fragtree_treedef, &sample->fragtree, succ); + ddsrt_avl_delete (&rsample_defrag_fragtree_treedef, &sample->fragtree, succ); if (sample->lastfrag == succ) { DDS_LOG(DDS_LC_RADMIN, " succ is lastfrag\n"); @@ -987,7 +987,7 @@ static int defrag_try_merge_with_succ (struct nn_rsample_defrag *sample, struct } } -static void defrag_rsample_addiv (struct nn_rsample_defrag *sample, struct nn_rdata *rdata, ut_avlIPath_t *path) +static void defrag_rsample_addiv (struct nn_rsample_defrag *sample, struct nn_rdata *rdata, ddsrt_avl_ipath_t *path) { struct nn_defrag_iv *newiv; if ((newiv = nn_rmsg_alloc (rdata->rmsg, sizeof (*newiv))) == NULL) @@ -997,7 +997,7 @@ static void defrag_rsample_addiv (struct nn_rsample_defrag *sample, struct nn_rd newiv->min = rdata->min; newiv->maxp1 = rdata->maxp1; nn_rdata_addbias (rdata); - ut_avlInsertIPath (&rsample_defrag_fragtree_treedef, &sample->fragtree, newiv, path); + ddsrt_avl_insert_ipath (&rsample_defrag_fragtree_treedef, &sample->fragtree, newiv, path); if (sample->lastfrag == NULL || rdata->min > sample->lastfrag->min) sample->lastfrag = newiv; } @@ -1010,7 +1010,7 @@ static struct nn_rsample *defrag_rsample_new (struct nn_rdata *rdata, const stru { struct nn_rsample *rsample; struct nn_rsample_defrag *dfsample; - ut_avlIPath_t ivpath; + ddsrt_avl_ipath_t ivpath; if ((rsample = nn_rmsg_alloc (rdata->rmsg, sizeof (*rsample))) == NULL) return NULL; @@ -1022,7 +1022,7 @@ static struct nn_rsample *defrag_rsample_new (struct nn_rdata *rdata, const stru return NULL; *dfsample->sampleinfo = *sampleinfo; - ut_avlInit (&rsample_defrag_fragtree_treedef, &dfsample->fragtree); + ddsrt_avl_init (&rsample_defrag_fragtree_treedef, &dfsample->fragtree); /* add sentinel if rdata is not the first fragment of the message */ if (rdata->min > 0) @@ -1032,12 +1032,12 @@ static struct nn_rsample *defrag_rsample_new (struct nn_rdata *rdata, const stru return NULL; sentinel->first = sentinel->last = NULL; sentinel->min = sentinel->maxp1 = 0; - ut_avlLookupIPath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &sentinel->min, &ivpath); - ut_avlInsertIPath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, sentinel, &ivpath); + ddsrt_avl_lookup_ipath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &sentinel->min, &ivpath); + ddsrt_avl_insert_ipath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, sentinel, &ivpath); } /* add an interval for the first received fragment */ - ut_avlLookupIPath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &rdata->min, &ivpath); + ddsrt_avl_lookup_ipath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &rdata->min, &ivpath); defrag_rsample_addiv (dfsample, rdata, &ivpath); return rsample; } @@ -1084,7 +1084,7 @@ static int is_complete (const struct nn_rsample_defrag *sample) one interval covering all bytes. One interval because of the greedy coalescing in add_fragment(). There is at least one interval if we get here. */ - const struct nn_defrag_iv *iv = ut_avlRoot (&rsample_defrag_fragtree_treedef, &sample->fragtree); + const struct nn_defrag_iv *iv = ddsrt_avl_root (&rsample_defrag_fragtree_treedef, &sample->fragtree); assert (iv != NULL); if (iv->min == 0 && iv->maxp1 >= sample->sampleinfo->size) { @@ -1094,7 +1094,7 @@ static int is_complete (const struct nn_rsample_defrag *sample) samples that will never be completed; dropping them in the defragmenter would be feasible by discarding all fragments of that sample collected so far. */ - assert (ut_avlIsSingleton (&sample->fragtree)); + assert (ddsrt_avl_is_singleton (&sample->fragtree)); return 1; } else @@ -1111,14 +1111,14 @@ static void rsample_convert_defrag_to_reorder (struct nn_rsample *sample) self-respecting compiler will optimise them away, and any self-respecting CPU would need to copy them via registers anyway because it uses a load-store architecture. */ - struct nn_defrag_iv *iv = ut_avlRootNonEmpty (&rsample_defrag_fragtree_treedef, &sample->u.defrag.fragtree); + struct nn_defrag_iv *iv = ddsrt_avl_root_non_empty (&rsample_defrag_fragtree_treedef, &sample->u.defrag.fragtree); struct nn_rdata *fragchain = iv->first; struct nn_rsample_info *sampleinfo = sample->u.defrag.sampleinfo; struct nn_rsample_chain_elem *sce; seqno_t seq = sample->u.defrag.seq; /* re-use memory fragment interval node for sample chain */ - sce = (struct nn_rsample_chain_elem *) ut_avlRootNonEmpty (&rsample_defrag_fragtree_treedef, &sample->u.defrag.fragtree); + sce = (struct nn_rsample_chain_elem *) ddsrt_avl_root_non_empty (&rsample_defrag_fragtree_treedef, &sample->u.defrag.fragtree); sce->fragchain = fragchain; sce->next = NULL; sce->sampleinfo = sampleinfo; @@ -1145,7 +1145,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct /* there must be a last fragment */ assert (dfsample->lastfrag); /* relatively expensive test: lastfrag, tree must be consistent */ - assert (dfsample->lastfrag == ut_avlFindMax (&rsample_defrag_fragtree_treedef, &dfsample->fragtree)); + assert (dfsample->lastfrag == ddsrt_avl_find_max (&rsample_defrag_fragtree_treedef, &dfsample->fragtree)); DDS_LOG(DDS_LC_RADMIN, " lastfrag %p [%u..%u)\n", (void *) dfsample->lastfrag, @@ -1162,7 +1162,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct else { /* Slow path: find preceding fragment by tree search */ - predeq = ut_avlLookupPredEq (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &min); + predeq = ddsrt_avl_lookup_pred_eq (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &min); assert (predeq); DDS_LOG(DDS_LC_RADMIN, " slow path: predeq = lookup %u => %p [%u..%u)\n", min, (void *) predeq, predeq->min, predeq->maxp1); @@ -1206,7 +1206,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct return is_complete (dfsample) ? sample : NULL; } else if (predeq != dfsample->lastfrag && /* if predeq is last frag, there is no succ */ - (succ = ut_avlFindSucc (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, predeq)) != NULL && + (succ = ddsrt_avl_find_succ (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, predeq)) != NULL && succ->min <= maxp1) { /* extends succ (at the low end; no guarantee each individual @@ -1236,9 +1236,9 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct { /* doesn't extend either predeq at the end or succ at the head => new interval; rdata did not cause completion of sample */ - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; DDS_LOG(DDS_LC_RADMIN, " new interval\n"); - if (ut_avlLookupIPath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &min, &path)) + if (ddsrt_avl_lookup_ipath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &min, &path)) assert (0); defrag_rsample_addiv (dfsample, rdata, &path); return NULL; @@ -1274,7 +1274,7 @@ static int defrag_limit_samples (struct nn_defrag *defrag, seqno_t seq, seqno_t break; case NN_DEFRAG_DROP_OLDEST: DDS_LOG(DDS_LC_RADMIN, " drop mode = DROP_OLDEST\n"); - sample_to_drop = ut_avlFindMin (&defrag_sampletree_treedef, &defrag->sampletree); + sample_to_drop = ddsrt_avl_find_min (&defrag_sampletree_treedef, &defrag->sampletree); assert (sample_to_drop); if (seq < sample_to_drop->u.defrag.seq) { @@ -1287,7 +1287,7 @@ static int defrag_limit_samples (struct nn_defrag *defrag, seqno_t seq, seqno_t defrag_rsample_drop (defrag, sample_to_drop); if (sample_to_drop == defrag->max_sample) { - defrag->max_sample = ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree); + defrag->max_sample = ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree); *max_seq = defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0; DDS_LOG(DDS_LC_RADMIN, " updating max_sample: now %p %"PRId64"\n", (void *) defrag->max_sample, @@ -1322,7 +1322,7 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata by adding BIAS to the refcount. */ struct nn_rsample *sample, *result; seqno_t max_seq; - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; assert (defrag->n_samples <= defrag->max_samples); @@ -1334,7 +1334,7 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata /* max_seq is used for the fast path, and is 0 when there is no last message in 'defrag'. max_seq and max_sample must be consistent. Max_sample must be consistent with tree */ - assert (defrag->max_sample == ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree)); + assert (defrag->max_sample == ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree)); max_seq = defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0; DDS_LOG(DDS_LC_RADMIN, "defrag_rsample(%p, %p [%u..%u) msg %p, %p seq %"PRId64" size %u) max_seq %p %"PRId64":\n", (void *) defrag, (void *) rdata, rdata->min, rdata->maxp1, (void *) rdata->rmsg, @@ -1358,22 +1358,22 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata child of the old maximum node */ /* FIXME: MERGE THIS ONE WITH THE NEXT */ DDS_LOG(DDS_LC_RADMIN, " new max sample\n"); - ut_avlLookupIPath (&defrag_sampletree_treedef, &defrag->sampletree, &sampleinfo->seq, &path); + ddsrt_avl_lookup_ipath (&defrag_sampletree_treedef, &defrag->sampletree, &sampleinfo->seq, &path); if ((sample = defrag_rsample_new (rdata, sampleinfo)) == NULL) return NULL; - ut_avlInsertIPath (&defrag_sampletree_treedef, &defrag->sampletree, sample, &path); + ddsrt_avl_insert_ipath (&defrag_sampletree_treedef, &defrag->sampletree, sample, &path); defrag->max_sample = sample; defrag->n_samples++; result = NULL; } - else if ((sample = ut_avlLookupIPath (&defrag_sampletree_treedef, &defrag->sampletree, &sampleinfo->seq, &path)) == NULL) + else if ((sample = ddsrt_avl_lookup_ipath (&defrag_sampletree_treedef, &defrag->sampletree, &sampleinfo->seq, &path)) == NULL) { /* a new sequence number, but smaller than the maximum */ DDS_LOG(DDS_LC_RADMIN, " new sample less than max\n"); assert (sampleinfo->seq < max_seq); if ((sample = defrag_rsample_new (rdata, sampleinfo)) == NULL) return NULL; - ut_avlInsertIPath (&defrag_sampletree_treedef, &defrag->sampletree, sample, &path); + ddsrt_avl_insert_ipath (&defrag_sampletree_treedef, &defrag->sampletree, sample, &path); defrag->n_samples++; result = NULL; } @@ -1390,12 +1390,12 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata reorder format. If it is the sample with the maximum sequence in the tree, an update of max_sample is required. */ DDS_LOG(DDS_LC_RADMIN, " complete\n"); - ut_avlDelete (&defrag_sampletree_treedef, &defrag->sampletree, result); + ddsrt_avl_delete (&defrag_sampletree_treedef, &defrag->sampletree, result); assert (defrag->n_samples > 0); defrag->n_samples--; if (result == defrag->max_sample) { - defrag->max_sample = ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree); + defrag->max_sample = ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree); DDS_LOG(DDS_LC_RADMIN, " updating max_sample: now %p %"PRId64"\n", (void *) defrag->max_sample, defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0); @@ -1403,7 +1403,7 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata rsample_convert_defrag_to_reorder (result); } - assert (defrag->max_sample == ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree)); + assert (defrag->max_sample == ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree)); return result; } @@ -1412,14 +1412,14 @@ void nn_defrag_notegap (struct nn_defrag *defrag, seqno_t min, seqno_t maxp1) /* All sequence numbers in [min,maxp1) are unavailable so any fragments in that range must be discarded. Used both for Hearbeats (by setting min=1) and for Gaps. */ - struct nn_rsample *s = ut_avlLookupSuccEq (&defrag_sampletree_treedef, &defrag->sampletree, &min); + struct nn_rsample *s = ddsrt_avl_lookup_succ_eq (&defrag_sampletree_treedef, &defrag->sampletree, &min); while (s && s->u.defrag.seq < maxp1) { - struct nn_rsample *s1 = ut_avlFindSucc (&defrag_sampletree_treedef, &defrag->sampletree, s); + struct nn_rsample *s1 = ddsrt_avl_find_succ (&defrag_sampletree_treedef, &defrag->sampletree, s); defrag_rsample_drop (defrag, s); s = s1; } - defrag->max_sample = ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree); + defrag->max_sample = ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree); } int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnum, struct nn_fragment_number_set *map, uint32_t maxsz) @@ -1428,7 +1428,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu struct nn_defrag_iv *iv; uint32_t i, fragsz, nfrags; assert (maxsz <= 256); - s = ut_avlLookup (&defrag_sampletree_treedef, &defrag->sampletree, &seq); + s = ddsrt_avl_lookup (&defrag_sampletree_treedef, &defrag->sampletree, &seq); if (s == NULL) { if (maxfragnum == UINT32_MAX) @@ -1465,7 +1465,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu are missing the first fragment. */ struct nn_defrag_iv *liv = s->u.defrag.lastfrag; nn_fragment_number_t map_end; - iv = ut_avlFindMin (&rsample_defrag_fragtree_treedef, &s->u.defrag.fragtree); + iv = ddsrt_avl_find_min (&rsample_defrag_fragtree_treedef, &s->u.defrag.fragtree); assert (iv != NULL); /* iv is first interval, iv->maxp1 is first byte beyond that => divide by fragsz to get first missing fragment */ @@ -1485,7 +1485,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu map->bitmap_base, but there is nothing to request in that case. */ map->numbits = (map_end < map->bitmap_base) ? 0 : map_end - map->bitmap_base + 1; - iv = ut_avlFindSucc (&rsample_defrag_fragtree_treedef, &s->u.defrag.fragtree, iv); + iv = ddsrt_avl_find_succ (&rsample_defrag_fragtree_treedef, &s->u.defrag.fragtree, iv); } /* Clear bitmap, then set bits for gaps in available fragments */ @@ -1515,7 +1515,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu at fragment containing maxp1 (because we don't have that byte yet), and runs until the next interval begins */ i = iv->maxp1 / fragsz; - iv = ut_avlFindSucc (&rsample_defrag_fragtree_treedef, &s->u.defrag.fragtree, iv); + iv = ddsrt_avl_find_succ (&rsample_defrag_fragtree_treedef, &s->u.defrag.fragtree, iv); } /* and set bits for missing fragments beyond the highest interval */ for (; i < map->bitmap_base + map->numbits; i++) @@ -1603,7 +1603,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu in the overview comment at the top of this file. */ struct nn_reorder { - ut_avlTree_t sampleivtree; + ddsrt_avl_tree_t sampleivtree; struct nn_rsample *max_sampleiv; /* = max(sampleivtree) */ seqno_t next_seq; enum nn_reorder_mode mode; @@ -1611,15 +1611,15 @@ struct nn_reorder { uint32_t n_samples; }; -static const ut_avlTreedef_t reorder_sampleivtree_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct nn_rsample, u.reorder.avlnode), offsetof (struct nn_rsample, u.reorder.min), compare_seqno, 0); +static const ddsrt_avl_treedef_t reorder_sampleivtree_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct nn_rsample, u.reorder.avlnode), offsetof (struct nn_rsample, u.reorder.min), compare_seqno, 0); struct nn_reorder *nn_reorder_new (enum nn_reorder_mode mode, uint32_t max_samples) { struct nn_reorder *r; if ((r = ddsrt_malloc (sizeof (*r))) == NULL) return NULL; - ut_avlInit (&reorder_sampleivtree_treedef, &r->sampleivtree); + ddsrt_avl_init (&reorder_sampleivtree_treedef, &r->sampleivtree); r->max_sampleiv = NULL; r->next_seq = 1; r->mode = mode; @@ -1644,10 +1644,10 @@ void nn_reorder_free (struct nn_reorder *r) struct nn_rsample *iv; struct nn_rsample_chain_elem *sce; /* FXIME: instead of findmin/delete, a treewalk can be used. */ - iv = ut_avlFindMin (&reorder_sampleivtree_treedef, &r->sampleivtree); + iv = ddsrt_avl_find_min (&reorder_sampleivtree_treedef, &r->sampleivtree); while (iv) { - ut_avlDelete (&reorder_sampleivtree_treedef, &r->sampleivtree, iv); + ddsrt_avl_delete (&reorder_sampleivtree_treedef, &r->sampleivtree, iv); sce = iv->u.reorder.sc.first; while (sce) { @@ -1655,17 +1655,17 @@ void nn_reorder_free (struct nn_reorder *r) nn_fragchain_unref (sce->fragchain); sce = sce1; } - iv = ut_avlFindMin (&reorder_sampleivtree_treedef, &r->sampleivtree); + iv = ddsrt_avl_find_min (&reorder_sampleivtree_treedef, &r->sampleivtree); } ddsrt_free (r); } static void reorder_add_rsampleiv (struct nn_reorder *reorder, struct nn_rsample *rsample) { - ut_avlIPath_t path; - if (ut_avlLookupIPath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &rsample->u.reorder.min, &path) != NULL) + ddsrt_avl_ipath_t path; + if (ddsrt_avl_lookup_ipath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &rsample->u.reorder.min, &path) != NULL) assert (0); - ut_avlInsertIPath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, rsample, &path); + ddsrt_avl_insert_ipath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, rsample, &path); } #ifndef NDEBUG @@ -1713,7 +1713,7 @@ static int reorder_try_append_and_discard (struct nn_reorder *reorder, struct nn appendto->u.reorder.min, appendto->u.reorder.maxp1, (void *) appendto, todiscard->u.reorder.min, todiscard->u.reorder.maxp1, (void *) todiscard); assert (todiscard->u.reorder.min == appendto->u.reorder.maxp1); - ut_avlDelete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, todiscard); + ddsrt_avl_delete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, todiscard); append_rsample_interval (appendto, todiscard); DDS_LOG(DDS_LC_RADMIN, " try_append_and_discard: max_sampleiv needs update? %s\n", (todiscard == reorder->max_sampleiv) ? "yes" : "no"); @@ -1793,8 +1793,8 @@ static void delete_last_sample (struct nn_reorder *reorder) recalc max_sampleiv. */ DDS_LOG(DDS_LC_RADMIN, " delete_last_sample: in singleton interval\n"); fragchain = last->sc.first->fragchain; - ut_avlDelete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, reorder->max_sampleiv); - reorder->max_sampleiv = ut_avlFindMax (&reorder_sampleivtree_treedef, &reorder->sampleivtree); + ddsrt_avl_delete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, reorder->max_sampleiv); + reorder->max_sampleiv = ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree); /* No harm done if it the sampleivtree is empty, except that we chose not to allow it */ assert (reorder->max_sampleiv != NULL); @@ -1847,7 +1847,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r seq; max must be set iff the reorder is non-empty. */ #ifndef NDEBUG { - struct nn_rsample *min = ut_avlFindMin (&reorder_sampleivtree_treedef, &reorder->sampleivtree); + struct nn_rsample *min = ddsrt_avl_find_min (&reorder_sampleivtree_treedef, &reorder->sampleivtree); if (min) DDS_LOG(DDS_LC_RADMIN, " min = %"PRId64" @ %p\n", min->u.reorder.min, (void *) min); assert (min == NULL || reorder->next_seq < min->u.reorder.min); @@ -1855,8 +1855,8 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r (reorder->max_sampleiv != NULL && min != NULL)); } #endif - assert ((!!ut_avlIsEmpty (&reorder->sampleivtree)) == (reorder->max_sampleiv == NULL)); - assert (reorder->max_sampleiv == NULL || reorder->max_sampleiv == ut_avlFindMax (&reorder_sampleivtree_treedef, &reorder->sampleivtree)); + assert ((!!ddsrt_avl_is_empty (&reorder->sampleivtree)) == (reorder->max_sampleiv == NULL)); + assert (reorder->max_sampleiv == NULL || reorder->max_sampleiv == ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree)); assert (reorder->n_samples <= reorder->max_samples); if (reorder->max_sampleiv) DDS_LOG(DDS_LC_RADMIN, " max = [%"PRId64",%"PRId64") @ %p\n", reorder->max_sampleiv->u.reorder.min, reorder->max_sampleiv->u.reorder.maxp1, (void *) reorder->max_sampleiv); @@ -1883,7 +1883,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r out-of-order either ends up here or in discard.) */ if (reorder->max_sampleiv != NULL) { - struct nn_rsample *min = ut_avlFindMin (&reorder_sampleivtree_treedef, &reorder->sampleivtree); + struct nn_rsample *min = ddsrt_avl_find_min (&reorder_sampleivtree_treedef, &reorder->sampleivtree); DDS_LOG(DDS_LC_RADMIN, " try append_and_discard\n"); if (reorder_try_append_and_discard (reorder, rsampleiv, min)) reorder->max_sampleiv = NULL; @@ -1908,7 +1908,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r DDS_LOG(DDS_LC_RADMIN, " discard: too old\n"); return NN_REORDER_TOO_OLD; /* don't want refcount increment */ } - else if (ut_avlIsEmpty (&reorder->sampleivtree)) + else if (ddsrt_avl_is_empty (&reorder->sampleivtree)) { /* else, if nothing's stored simply add this one, max_samples = 0 is technically allowed, and potentially useful, so check for @@ -1989,7 +1989,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r return NN_REORDER_REJECT; } - predeq = ut_avlLookupPredEq (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &s->min); + predeq = ddsrt_avl_lookup_pred_eq (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &s->min); if (predeq) DDS_LOG(DDS_LC_RADMIN, " predeq = [%"PRId64",%"PRId64") @ %p\n", predeq->u.reorder.min, predeq->u.reorder.maxp1, (void *) predeq); @@ -2002,7 +2002,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r return NN_REORDER_REJECT; } - immsucc = ut_avlLookup (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &s->maxp1); + immsucc = ddsrt_avl_lookup (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &s->maxp1); if (immsucc) DDS_LOG(DDS_LC_RADMIN, " immsucc = [%"PRId64",%"PRId64") @ %p\n", immsucc->u.reorder.min, immsucc->u.reorder.maxp1, (void *) immsucc); @@ -2040,7 +2040,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r Therefore, we can swap rsampleiv in for immsucc and avoid the case above. */ rsampleiv->u.reorder = immsucc->u.reorder; - ut_avlSwapNode (&reorder_sampleivtree_treedef, &reorder->sampleivtree, immsucc, rsampleiv); + ddsrt_avl_swap_node (&reorder_sampleivtree_treedef, &reorder->sampleivtree, immsucc, rsampleiv); if (immsucc == reorder->max_sampleiv) reorder->max_sampleiv = rsampleiv; } @@ -2072,12 +2072,12 @@ static struct nn_rsample *coalesce_intervals_touching_range (struct nn_reorder * struct nn_rsample *s, *t; *valuable = 0; /* Find first (lowest m) interval [m,n) s.t. n >= min && m <= maxp1 */ - s = ut_avlLookupPredEq (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &min); + s = ddsrt_avl_lookup_pred_eq (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &min); if (s && s->u.reorder.maxp1 >= min) { /* m <= min && n >= min (note: pred of s [m',n') necessarily has n' < m) */ #ifndef NDEBUG - struct nn_rsample *q = ut_avlFindPred (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s); + struct nn_rsample *q = ddsrt_avl_find_pred (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s); assert (q == NULL || q->u.reorder.maxp1 < min); #endif } @@ -2086,15 +2086,15 @@ static struct nn_rsample *coalesce_intervals_touching_range (struct nn_reorder * /* No good, but the first (if s = NULL) or the next one (if s != NULL) may still have m <= maxp1 (m > min is implied now). If not, no such interval. */ - s = ut_avlFindSucc (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s); + s = ddsrt_avl_find_succ (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s); if (!(s && s->u.reorder.min <= maxp1)) return NULL; } /* Append successors [m',n') s.t. m' <= maxp1 to s */ assert (s->u.reorder.min + s->u.reorder.n_samples <= s->u.reorder.maxp1); - while ((t = ut_avlFindSucc (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s)) != NULL && t->u.reorder.min <= maxp1) + while ((t = ddsrt_avl_find_succ (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s)) != NULL && t->u.reorder.min <= maxp1) { - ut_avlDelete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, t); + ddsrt_avl_delete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, t); assert (t->u.reorder.min + t->u.reorder.n_samples <= t->u.reorder.maxp1); append_rsample_interval (s, t); *valuable = 1; @@ -2126,8 +2126,8 @@ static int reorder_insert_gap (struct nn_reorder *reorder, struct nn_rdata *rdat { struct nn_rsample_chain_elem *sce; struct nn_rsample *s; - ut_avlIPath_t path; - if (ut_avlLookupIPath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &min, &path) != NULL) + ddsrt_avl_ipath_t path; + if (ddsrt_avl_lookup_ipath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &min, &path) != NULL) assert (0); if ((sce = nn_rmsg_alloc (rdata->rmsg, sizeof (*sce))) == NULL) return 0; @@ -2140,7 +2140,7 @@ static int reorder_insert_gap (struct nn_reorder *reorder, struct nn_rdata *rdat s->u.reorder.min = min; s->u.reorder.maxp1 = maxp1; s->u.reorder.n_samples = 1; - ut_avlInsertIPath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s, &path); + ddsrt_avl_insert_ipath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s, &path); return 1; } @@ -2225,7 +2225,7 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord delete_last_sample (reorder); (*refcount_adjust)++; } - reorder->max_sampleiv = ut_avlFindMax (&reorder_sampleivtree_treedef, &reorder->sampleivtree); + reorder->max_sampleiv = ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree); return res; } else if (coalesced->u.reorder.min <= reorder->next_seq) @@ -2233,11 +2233,11 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord DDS_LOG(DDS_LC_RADMIN, " coalesced = [%"PRId64",%"PRId64") @ %p containing %d samples\n", coalesced->u.reorder.min, coalesced->u.reorder.maxp1, (void *) coalesced, coalesced->u.reorder.n_samples); - ut_avlDelete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, coalesced); + ddsrt_avl_delete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, coalesced); if (coalesced->u.reorder.min <= reorder->next_seq) assert (min <= reorder->next_seq); reorder->next_seq = coalesced->u.reorder.maxp1; - reorder->max_sampleiv = ut_avlFindMax (&reorder_sampleivtree_treedef, &reorder->sampleivtree); + reorder->max_sampleiv = ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree); DDS_LOG(DDS_LC_RADMIN, " next expected: %"PRId64"\n", reorder->next_seq); *sc = coalesced->u.reorder.sc; @@ -2251,7 +2251,7 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord { DDS_LOG(DDS_LC_RADMIN, " coalesced = [%"PRId64",%"PRId64") @ %p - that is all\n", coalesced->u.reorder.min, coalesced->u.reorder.maxp1, (void *) coalesced); - reorder->max_sampleiv = ut_avlFindMax (&reorder_sampleivtree_treedef, &reorder->sampleivtree); + reorder->max_sampleiv = ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree); return valuable ? NN_REORDER_ACCEPT : NN_REORDER_REJECT; } } @@ -2264,7 +2264,7 @@ int nn_reorder_wantsample (struct nn_reorder *reorder, seqno_t seq) return 0; /* Find interval that contains seq, if we know seq. We are interested if seq is outside this interval (if any). */ - s = ut_avlLookupPredEq (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &seq); + s = ddsrt_avl_lookup_pred_eq (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &seq); return (s == NULL || s->u.reorder.maxp1 <= seq); } @@ -2307,7 +2307,7 @@ unsigned nn_reorder_nackmap (struct nn_reorder *reorder, seqno_t base, seqno_t m map->numbits = (uint32_t) (maxseq + 1 - base); nn_bitset_zero (map->numbits, map->bits); - if ((iv = ut_avlFindMin (&reorder_sampleivtree_treedef, &reorder->sampleivtree)) != NULL) + if ((iv = ddsrt_avl_find_min (&reorder_sampleivtree_treedef, &reorder->sampleivtree)) != NULL) assert (iv->u.reorder.min > base); i = base; while (iv && i < base + map->numbits) @@ -2318,7 +2318,7 @@ unsigned nn_reorder_nackmap (struct nn_reorder *reorder, seqno_t base, seqno_t m nn_bitset_set (map->numbits, map->bits, x); } i = iv->u.reorder.maxp1; - iv = ut_avlFindSucc (&reorder_sampleivtree_treedef, &reorder->sampleivtree, iv); + iv = ddsrt_avl_find_succ (&reorder_sampleivtree_treedef, &reorder->sampleivtree, iv); } if (notail && i < base + map->numbits) map->numbits = (unsigned) (i - base); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 8ea8c47..520c334 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -20,7 +20,7 @@ #include "dds/ddsrt/sync.h" #include "dds/ddsrt/string.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds__stream.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_rtps.h" @@ -767,7 +767,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac } ddsrt_mutex_lock (&wr->e.lock); - if ((rn = ut_avlLookup (&wr_readers_treedef, &wr->readers, &src)) == NULL) + if ((rn = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &src)) == NULL) { DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not a connection)", PGUID (src), PGUID (dst)); goto out; @@ -823,7 +823,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac that rn->seq <= wr->seq) */ rn->seq = wr->seq; } - ut_avlAugmentUpdate (&wr_readers_treedef, rn); + ddsrt_avl_augment_update (&wr_readers_treedef, rn); n = remove_acked_messages (wr, &whcst, &deferred_free_list); DDS_TRACE(" ACK%"PRId64" RM%u", n_ack, n); } @@ -850,7 +850,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac that rn->seq <= wr->seq) */ rn->seq = wr->seq; } - ut_avlAugmentUpdate (&wr_readers_treedef, rn); + ddsrt_avl_augment_update (&wr_readers_treedef, rn); DDS_LOG(DDS_LC_THROTTLE, "writer %x:%x:%x:%x considering reader %x:%x:%x:%x responsive again\n", PGUID (wr->e.guid), PGUID (rn->prd_guid)); } @@ -867,7 +867,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac rn->has_replied_to_hb = 1; /* walk the whole tree to ensure all proxy readers for this writer have their unack'ed info updated */ - ut_avlAugmentUpdate (&wr_readers_treedef, rn); + ddsrt_avl_augment_update (&wr_readers_treedef, rn); } if (is_preemptive_ack) { @@ -1075,7 +1075,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac return 1; } -static void handle_forall_destinations (const nn_guid_t *dst, struct proxy_writer *pwr, ut_avlWalk_t fun, void *arg) +static void handle_forall_destinations (const nn_guid_t *dst, struct proxy_writer *pwr, ddsrt_avl_walk_t fun, void *arg) { /* prefix: id: to: 0 0 all matched readers @@ -1093,12 +1093,12 @@ static void handle_forall_destinations (const nn_guid_t *dst, struct proxy_write switch ((haveprefix << 1) | haveid) { case (0 << 1) | 0: /* all: full treewalk */ - ut_avlWalk (&pwr_readers_treedef, &pwr->readers, fun, arg); + ddsrt_avl_walk (&pwr_readers_treedef, &pwr->readers, fun, arg); break; case (0 << 1) | 1: /* all with correct entityid: special filtering treewalk */ { struct pwr_rd_match *wn; - for (wn = ut_avlFindMin (&pwr_readers_treedef, &pwr->readers); wn; wn = ut_avlFindSucc (&pwr_readers_treedef, &pwr->readers, wn)) + for (wn = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); wn; wn = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, wn)) { if (wn->rd_guid.entityid.u == dst->entityid.u) fun (wn, arg); @@ -1110,13 +1110,13 @@ static void handle_forall_destinations (const nn_guid_t *dst, struct proxy_write nn_guid_t a, b; a = *dst; a.entityid.u = 0; b = *dst; b.entityid.u = ~0u; - ut_avlWalkRange (&pwr_readers_treedef, &pwr->readers, &a, &b, fun, arg); + ddsrt_avl_walk_range (&pwr_readers_treedef, &pwr->readers, &a, &b, fun, arg); } break; case (1 << 1) | 1: /* fully addressed: dst should exist (but for removal) */ { struct pwr_rd_match *wn; - if ((wn = ut_avlLookup (&pwr_readers_treedef, &pwr->readers, dst)) != NULL) + if ((wn = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, dst)) != NULL) fun (wn, arg); } break; @@ -1289,7 +1289,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct else nn_dqueue_enqueue (pwr->dqueue, &sc, res); } - for (wn = ut_avlFindMin (&pwr_readers_treedef, &pwr->readers); wn; wn = ut_avlFindSucc (&pwr_readers_treedef, &pwr->readers, wn)) + for (wn = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); wn; wn = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, wn)) if (wn->in_sync != PRMSS_SYNC) { seqno_t last_deliv_seq = 0; @@ -1324,7 +1324,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct arg.timestamp = timestamp; arg.tnow = tnow; arg.tnow_mt = now_mt (); - handle_forall_destinations (&dst, pwr, (ut_avlWalk_t) handle_Heartbeat_helper, &arg); + handle_forall_destinations (&dst, pwr, (ddsrt_avl_walk_t) handle_Heartbeat_helper, &arg); DDS_TRACE(")"); ddsrt_mutex_unlock (&pwr->e.lock); @@ -1380,7 +1380,7 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime discover a missing fragment, which differs significantly from handle_Heartbeat's scheduling of an AckNack event when it must respond. Why? Just because. */ - if (ut_avlIsEmpty (&pwr->readers) || pwr->local_matching_inprogress) + if (ddsrt_avl_is_empty (&pwr->readers) || pwr->local_matching_inprogress) DDS_TRACE(" no readers"); else { @@ -1392,19 +1392,19 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime assuming a reliable writer -> unreliable reader is rare, and so scanning the readers is acceptable if the first guess fails */ - m = ut_avlRootNonEmpty (&pwr_readers_treedef, &pwr->readers); + m = ddsrt_avl_root_non_empty (&pwr_readers_treedef, &pwr->readers); if (m->acknack_xevent == NULL) { - m = ut_avlFindMin (&pwr_readers_treedef, &pwr->readers); + m = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); while (m && m->acknack_xevent == NULL) - m = ut_avlFindSucc (&pwr_readers_treedef, &pwr->readers, m); + m = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, m); } } else if (seq < nn_reorder_next_seq (pwr->reorder)) { /* Check out-of-sync readers -- should add a bit to cheaply test whether there are any (usually there aren't) */ - m = ut_avlFindMin (&pwr_readers_treedef, &pwr->readers); + m = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); while (m) { if ((m->in_sync == PRMSS_OUT_OF_SYNC) && m->acknack_xevent != NULL && nn_reorder_wantsample (m->u.not_in_sync.reorder, seq)) @@ -1414,7 +1414,7 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime reader to decide which fragments to nack */ break; } - m = ut_avlFindSucc (&pwr_readers_treedef, &pwr->readers, m); + m = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, m); } } @@ -1495,7 +1495,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N } ddsrt_mutex_lock (&wr->e.lock); - if ((rn = ut_avlLookup (&wr_readers_treedef, &wr->readers, &src)) == NULL) + if ((rn = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &src)) == NULL) { DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not a connection", PGUID (src), PGUID (dst)); goto out; @@ -1737,7 +1737,7 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); ddsrt_mutex_lock (&pwr->e.lock); - if ((wn = ut_avlLookup (&pwr_readers_treedef, &pwr->readers, &dst)) == NULL) + if ((wn = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, &dst)) == NULL) { DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x not a connection)", PGUID (src), PGUID (dst)); ddsrt_mutex_unlock (&pwr->e.lock); @@ -2069,11 +2069,11 @@ retry: 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. */ - ut_avlIter_t it; + ddsrt_avl_iter_t it; struct pwr_rd_match *m; ddsrt_mutex_unlock (&pwr->rdary.rdary_lock); if (!pwr_locked) ddsrt_mutex_lock (&pwr->e.lock); - for (m = ut_avlIterFirst (&pwr_readers_treedef, &pwr->readers, &it); m != NULL; m = ut_avlIterNext (&it)) + for (m = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); m != NULL; m = ddsrt_avl_iter_next (&it)) { struct reader *rd; if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) @@ -2138,7 +2138,7 @@ static void clean_defrag (struct proxy_writer *pwr) if (pwr->n_readers_out_of_sync > 0) { struct pwr_rd_match *wn; - for (wn = ut_avlFindMin (&pwr_readers_treedef, &pwr->readers); wn != NULL; wn = ut_avlFindSucc (&pwr_readers_treedef, &pwr->readers, wn)) + for (wn = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); wn != NULL; wn = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, wn)) { if (wn->in_sync == PRMSS_OUT_OF_SYNC) { @@ -2199,7 +2199,7 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct return; } - if (ut_avlIsEmpty (&pwr->readers) || pwr->local_matching_inprogress) + if (ddsrt_avl_is_empty (&pwr->readers) || pwr->local_matching_inprogress) { ddsrt_mutex_unlock (&pwr->e.lock); DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x: no readers", PGUID (pwr->e.guid), PGUID (dst)); @@ -2274,9 +2274,9 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct writer may have become in sync with the proxy writer and the writer; those catching up with TL all by themselves go through the "TOO_OLD" path below. */ - ut_avlIter_t it; + ddsrt_avl_iter_t it; struct pwr_rd_match *wn; - for (wn = ut_avlIterFirst (&pwr_readers_treedef, &pwr->readers, &it); wn != NULL; wn = ut_avlIterNext (&it)) + for (wn = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); wn != NULL; wn = ddsrt_avl_iter_next (&it)) if (wn->in_sync == PRMSS_TLCATCHUP) maybe_set_reader_in_sync (pwr, wn, sampleinfo->seq); } @@ -2286,7 +2286,7 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct struct pwr_rd_match *wn; struct nn_rsample *rsample_dup = NULL; int reuse_rsample_dup = 0; - for (wn = ut_avlFindMin (&pwr_readers_treedef, &pwr->readers); wn != NULL; wn = ut_avlFindSucc (&pwr_readers_treedef, &pwr->readers, wn)) + for (wn = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); wn != NULL; wn = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, wn)) { nn_reorder_result_t rres2; if (wn->in_sync != PRMSS_OUT_OF_SYNC || sampleinfo->seq > wn->u.not_in_sync.end_of_out_of_sync_seq) @@ -2380,7 +2380,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con dst.entityid = msg->readerId; ddsrt_mutex_lock (&pwr->e.lock); - wn = ut_avlLookup (&pwr_readers_treedef, &pwr->readers, &dst); + wn = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, &dst); gap_was_valuable = handle_one_gap (pwr, wn, sampleinfo->seq, sampleinfo->seq+1, gap, &refc_adjust); nn_fragchain_adjust_refcount (gap, refc_adjust); ddsrt_mutex_unlock (&pwr->e.lock); diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 086187e..4d67295 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -15,7 +15,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_addrset.h" #include "dds/ddsi/q_xmsg.h" @@ -51,12 +51,12 @@ static const struct wr_prd_match *root_rdmatch (const struct writer *wr) { - return ut_avlRoot (&wr_readers_treedef, &wr->readers); + return ddsrt_avl_root (&wr_readers_treedef, &wr->readers); } static int have_reliable_subs (const struct writer *wr) { - if (ut_avlIsEmpty (&wr->readers) || root_rdmatch (wr)->min_seq == MAX_SEQ_NUMBER) + if (ddsrt_avl_is_empty (&wr->readers) || root_rdmatch (wr)->min_seq == MAX_SEQ_NUMBER) return 0; else return 1; @@ -152,7 +152,7 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru /* out of memory at worst slows down traffic */ return NULL; - if (ut_avlIsEmpty (&wr->readers) || wr->num_reliable_readers == 0) + if (ddsrt_avl_is_empty (&wr->readers) || wr->num_reliable_readers == 0) { /* Not really supposed to come here, at least not for the first case. Secondly, there really seems to be little use for @@ -192,9 +192,9 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru DDS_TRACE("unicasting to prd %x:%x:%x:%x ", PGUID (*prd_guid)); DDS_TRACE("(rel-prd %d seq-eq-max %d seq %"PRId64" maxseq %"PRId64")\n", wr->num_reliable_readers, - ut_avlIsEmpty (&wr->readers) ? -1 : root_rdmatch (wr)->num_reliable_readers_where_seq_equals_max, + ddsrt_avl_is_empty (&wr->readers) ? -1 : root_rdmatch (wr)->num_reliable_readers_where_seq_equals_max, wr->seq, - ut_avlIsEmpty (&wr->readers) ? (seqno_t) -1 : root_rdmatch (wr)->max_seq); + ddsrt_avl_is_empty (&wr->readers) ? (seqno_t) -1 : root_rdmatch (wr)->max_seq); if (prd_guid == NULL) { @@ -312,8 +312,8 @@ struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_ PGUID (wr->e.guid), *hbansreq ? "" : " final", (hbc->tsched.v == T_NEVER) ? POS_INFINITY_DOUBLE : (double) (hbc->tsched.v - tnow.v) / 1e9, - ut_avlIsEmpty (&wr->readers) ? -1 : root_rdmatch (wr)->min_seq, - ut_avlIsEmpty (&wr->readers) || root_rdmatch (wr)->all_have_replied_to_hb ? "" : "!", + ddsrt_avl_is_empty (&wr->readers) ? -1 : root_rdmatch (wr)->min_seq, + ddsrt_avl_is_empty (&wr->readers) || root_rdmatch (wr)->all_have_replied_to_hb ? "" : "!", whcst->max_seq, READ_SEQ_XMIT(wr)); } diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index b5d6c86..bbeb9c2 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -16,8 +16,8 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_avl.h" -#include "dds/util/ut_fibheap.h" +#include "dds/ddsrt/avl.h" +#include "dds/ddsrt/fibheap.h" #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_log.h" @@ -70,7 +70,7 @@ enum xeventkind struct xevent { - ut_fibheapNode_t heapnode; + ddsrt_fibheap_node_t heapnode; struct xeventq *evq; nn_mtime_t tsched; enum xeventkind kind; @@ -133,7 +133,7 @@ struct xevent_nt /* xmsg is self-contained / relies on reference counts */ struct nn_xmsg *msg; size_t queued_rexmit_bytes; - ut_avlNode_t msg_avlnode; + ddsrt_avl_node_t msg_avlnode; } msg_rexmit; struct { /* xmsg is self-contained / relies on reference counts */ @@ -143,8 +143,8 @@ struct xevent_nt }; struct xeventq { - ut_fibheap_t xevents; - ut_avlTree_t msg_xevents; + ddsrt_fibheap_t xevents; + ddsrt_avl_tree_t msg_xevents; struct xevent_nt *non_timed_xmit_list_oldest; struct xevent_nt *non_timed_xmit_list_newest; /* undefined if ..._oldest == NULL */ size_t queued_rexmit_bytes; @@ -164,9 +164,9 @@ static nn_mtime_t earliest_in_xeventq (struct xeventq *evq); static int msg_xevents_cmp (const void *a, const void *b); static int compare_xevent_tsched (const void *va, const void *vb); -static const ut_avlTreedef_t msg_xevents_treedef = UT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct xevent_nt, u.msg_rexmit.msg_avlnode), offsetof (struct xevent_nt, u.msg_rexmit.msg), msg_xevents_cmp, 0); +static const ddsrt_avl_treedef_t msg_xevents_treedef = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct xevent_nt, u.msg_rexmit.msg_avlnode), offsetof (struct xevent_nt, u.msg_rexmit.msg), msg_xevents_cmp, 0); -static const ut_fibheapDef_t evq_xevents_fhdef = UT_FIBHEAPDEF_INITIALIZER(offsetof (struct xevent, heapnode), compare_xevent_tsched); +static const ddsrt_fibheap_def_t evq_xevents_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct xevent, heapnode), compare_xevent_tsched); static int compare_xevent_tsched (const void *va, const void *vb) { @@ -209,21 +209,21 @@ static struct xevent_nt *lookup_msg (struct xeventq *evq, struct nn_xmsg *msg) { assert (nn_xmsg_kind (msg) == NN_XMSG_KIND_DATA_REXMIT); trace_msg ("lookup-msg", msg); - return ut_avlLookup (&msg_xevents_treedef, &evq->msg_xevents, msg); + return ddsrt_avl_lookup (&msg_xevents_treedef, &evq->msg_xevents, msg); } static void remember_msg (struct xeventq *evq, struct xevent_nt *ev) { assert (ev->kind == XEVK_MSG_REXMIT); trace_msg ("remember-msg", ev->u.msg_rexmit.msg); - ut_avlInsert (&msg_xevents_treedef, &evq->msg_xevents, ev); + ddsrt_avl_insert (&msg_xevents_treedef, &evq->msg_xevents, ev); } static void forget_msg (struct xeventq *evq, struct xevent_nt *ev) { assert (ev->kind == XEVK_MSG_REXMIT); trace_msg ("forget-msg", ev->u.msg_rexmit.msg); - ut_avlDelete (&msg_xevents_treedef, &evq->msg_xevents, ev); + ddsrt_avl_delete (&msg_xevents_treedef, &evq->msg_xevents, ev); } static void add_to_non_timed_xmit_list (struct xeventq *evq, struct xevent_nt *ev) @@ -330,7 +330,7 @@ static void free_xevent_nt (struct xeventq *evq, struct xevent_nt *ev) nn_xmsg_free (ev->u.msg.msg); break; case XEVK_MSG_REXMIT: - assert (ut_avlLookup (&msg_xevents_treedef, &evq->msg_xevents, ev->u.msg_rexmit.msg) == NULL); + assert (ddsrt_avl_lookup (&msg_xevents_treedef, &evq->msg_xevents, ev->u.msg_rexmit.msg) == NULL); update_rexmit_counts (evq, ev); nn_xmsg_free (ev->u.msg_rexmit.msg); break; @@ -351,12 +351,12 @@ void delete_xevent (struct xevent *ev) if (ev->tsched.v != T_NEVER) { ev->tsched.v = TSCHED_DELETE; - ut_fibheapDecreaseKey (&evq_xevents_fhdef, &evq->xevents, ev); + ddsrt_fibheap_decrease_key (&evq_xevents_fhdef, &evq->xevents, ev); } else { ev->tsched.v = TSCHED_DELETE; - ut_fibheapInsert (&evq_xevents_fhdef, &evq->xevents, ev); + ddsrt_fibheap_insert (&evq_xevents_fhdef, &evq->xevents, ev); } /* TSCHED_DELETE is absolute minimum time, so chances are we need to wake up the thread. The superfluous signal is harmless. */ @@ -384,12 +384,12 @@ int resched_xevent_if_earlier (struct xevent *ev, nn_mtime_t tsched) if (ev->tsched.v != T_NEVER) { ev->tsched = tsched; - ut_fibheapDecreaseKey (&evq_xevents_fhdef, &evq->xevents, ev); + ddsrt_fibheap_decrease_key (&evq_xevents_fhdef, &evq->xevents, ev); } else { ev->tsched = tsched; - ut_fibheapInsert (&evq_xevents_fhdef, &evq->xevents, ev); + ddsrt_fibheap_insert (&evq_xevents_fhdef, &evq->xevents, ev); } is_resched = 1; if (tsched.v < tbefore.v) @@ -435,7 +435,7 @@ static nn_mtime_t earliest_in_xeventq (struct xeventq *evq) { struct xevent *min; ASSERT_MUTEX_HELD (&evq->lock); - if ((min = ut_fibheapMin (&evq_xevents_fhdef, &evq->xevents)) != NULL) + if ((min = ddsrt_fibheap_min (&evq_xevents_fhdef, &evq->xevents)) != NULL) return min->tsched; else { @@ -453,7 +453,7 @@ static void qxev_insert (struct xevent *ev) if (ev->tsched.v != T_NEVER) { nn_mtime_t tbefore = earliest_in_xeventq (evq); - ut_fibheapInsert (&evq_xevents_fhdef, &evq->xevents, ev); + ddsrt_fibheap_insert (&evq_xevents_fhdef, &evq->xevents, ev); if (ev->tsched.v < tbefore.v) ddsrt_cond_signal (&evq->cond); } @@ -485,8 +485,8 @@ struct xeventq * xeventq_new /* limit to 2GB to prevent overflow (4GB - 64kB should be ok, too) */ if (max_queued_rexmit_bytes > 2147483648u) max_queued_rexmit_bytes = 2147483648u; - ut_fibheapInit (&evq_xevents_fhdef, &evq->xevents); - ut_avlInit (&msg_xevents_treedef, &evq->msg_xevents); + ddsrt_fibheap_init (&evq_xevents_fhdef, &evq->xevents); + ddsrt_avl_init (&msg_xevents_treedef, &evq->msg_xevents); evq->non_timed_xmit_list_oldest = NULL; evq->non_timed_xmit_list_newest = NULL; evq->terminate = 0; @@ -540,7 +540,7 @@ void xeventq_free (struct xeventq *evq) { struct xevent *ev; assert (evq->ts == NULL); - while ((ev = ut_fibheapExtractMin (&evq_xevents_fhdef, &evq->xevents)) != NULL) + while ((ev = ddsrt_fibheap_extract_min (&evq_xevents_fhdef, &evq->xevents)) != NULL) { if (ev->tsched.v == TSCHED_DELETE || ev->kind != XEVK_CALLBACK) free_xevent (evq, ev); @@ -559,7 +559,7 @@ void xeventq_free (struct xeventq *evq) } while (!non_timed_xmit_list_is_empty(evq)) free_xevent_nt (evq, getnext_from_non_timed_xmit_list (evq)); - assert (ut_avlIsEmpty (&evq->msg_xevents)); + assert (ddsrt_avl_is_empty (&evq->msg_xevents)); ddsrt_cond_destroy (&evq->cond); ddsrt_mutex_destroy (&evq->lock); ddsrt_free (evq); @@ -636,8 +636,8 @@ static void handle_xevk_heartbeat (struct nn_xpack *xp, struct xevent *ev, nn_mt hbansreq ? "" : " final", msg ? "sent" : "suppressed", (t_next.v == T_NEVER) ? POS_INFINITY_DOUBLE : (double)(t_next.v - tnow.v) / 1e9, - ut_avlIsEmpty (&wr->readers) ? (seqno_t) -1 : ((struct wr_prd_match *) ut_avlRootNonEmpty (&wr_readers_treedef, &wr->readers))->min_seq, - ut_avlIsEmpty (&wr->readers) || ((struct wr_prd_match *) ut_avlRootNonEmpty (&wr_readers_treedef, &wr->readers))->all_have_replied_to_hb ? "" : "!", + ddsrt_avl_is_empty (&wr->readers) ? (seqno_t) -1 : ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->min_seq, + ddsrt_avl_is_empty (&wr->readers) || ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->all_have_replied_to_hb ? "" : "!", whcst.max_seq, READ_SEQ_XMIT(wr)); resched_xevent_if_earlier (ev, t_next); wr->hbcontrol.tsched = t_next; @@ -888,7 +888,7 @@ static void handle_xevk_acknack (UNUSED_ARG (struct nn_xpack *xp), struct xevent } ddsrt_mutex_lock (&pwr->e.lock); - if ((rwn = ut_avlLookup (&pwr_readers_treedef, &pwr->readers, &ev->u.acknack.rd_guid)) == NULL) + if ((rwn = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, &ev->u.acknack.rd_guid)) == NULL) { ddsrt_mutex_unlock (&pwr->e.lock); return; @@ -1322,7 +1322,7 @@ static void handle_xevents (struct thread_state1 * const ts1, struct xeventq *xe { while (earliest_in_xeventq(xevq).v <= tnow.v) { - struct xevent *xev = ut_fibheapExtractMin (&evq_xevents_fhdef, &xevq->xevents); + struct xevent *xev = ddsrt_fibheap_extract_min (&evq_xevents_fhdef, &xevq->xevents); if (xev->tsched.v == TSCHED_DELETE) { free_xevent (xevq, xev); diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 4fc0e57..6e3a6ef 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -23,8 +23,8 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/random.h" -#include "dds/util/ut_avl.h" -#include "dds/util/ut_thread_pool.h" +#include "dds/ddsrt/avl.h" +#include "dds/ddsrt/thread_pool.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_xqos.h" @@ -1340,7 +1340,7 @@ static void nn_xpack_send1_threaded (const nn_locator_t *loc, void * varg) arg->xp = (struct nn_xpack *) varg; arg->loc = loc; ddsrt_atomic_inc32 (&arg->xp->calls); - ut_thread_pool_submit (gv.thread_pool, nn_xpack_send1_thread, arg); + ddsrt_thread_pool_submit (gv.thread_pool, nn_xpack_send1_thread, arg); } static void nn_xpack_send_real (struct nn_xpack * xp) diff --git a/src/core/xtests/CMakeLists.txt b/src/core/xtests/CMakeLists.txt index 0b1d362..02b7bfd 100644 --- a/src/core/xtests/CMakeLists.txt +++ b/src/core/xtests/CMakeLists.txt @@ -18,7 +18,7 @@ target_include_directories( "$" "$") -target_link_libraries(rhc_torture RhcTypes ddsc util) +target_link_libraries(rhc_torture RhcTypes ddsc) add_test( NAME rhc_torture diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 7830104..404f425 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -78,6 +78,21 @@ list(APPEND sources "${source_path}/strtod.c" "${source_path}/strtol.c") +list(APPEND headers + "${source_path}/dds/ddsrt/avl.h" + "${source_path}/dds/ddsrt/expand_envvars.h" + "${source_path}/dds/ddsrt/fibheap.h" + "${source_path}/dds/ddsrt/hopscotch.h" + "${source_path}/dds/ddsrt/thread_pool.h") + +list(APPEND sources + "${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") + # 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 # could use the lightweight IP stack, but later change to FreeRTOS+TCP. diff --git a/src/ddsrt/include/dds/ddsrt/avl.h b/src/ddsrt/include/dds/ddsrt/avl.h new file mode 100644 index 0000000..a99f206 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/avl.h @@ -0,0 +1,359 @@ +/* + * 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_AVL_H +#define DDSRT_AVL_H + +/* The tree library never performs memory allocations or deallocations internally. + + - Treedef_t: defines the properties of the tree, offsets, + comparison functions, augmented structures, flags -- these are + related to the code/data structure in which the tree is embedded, + and in nearly all cases known at compile time. + - avlTree_t: represents the tree, i.e., pointer to the root. + - avlNode_t: contains the administrative data for a single node in + the tree. + + For a tree node: + struct T { + avlNode_t avlnode; + int key; + }; + by definition, avlnodeoffset == offsetof(struct T, avlnode) and + keyoffset = offsetof(struct T, key). The user of the library only + ever deals in pointers to (in this case) struct T, never with + pointers to the avlNode_t, and the compare function operations on + pointers to keys, in this case pointers to "int"s. If you wish, you + can also do: keyoffset = 0, in which case the compare function + would be operating on struct T's. + + The compare function is assumed to behave just like all compare + functions in the C library: < 0, =0, >0 for left argument less + than, equal to or greater than the right argument. + + The "augment" function is automatically called whenever some of the + children of a node change, as well as when the "augment" function + has been called on some of the children. It allows you to maintain + a "summary" of the subtree -- currently only used in ddsi2e, in one + spot. + + Trees come in various "variants", configured through "treedef" + flags: + - direct/indirect key: direct meaning the key value is embedded in + the structure containing the avlNode_t, indirect meaning a + pointer to the key value is. The compare function doesn't deal + with tree nodes, but with key values. + - re-entrant: in the style of the C library, meaning, the + comparison function gets a user-supplied 3rd argument (in + particular used by mmstat). + - unique keys/duplicate keys: when keys must be unique, some + optimizations apply; it is up to the caller to ensure one doesn't + violate the uniqueness of the keys (it'll happily crash in insert + if you don't); when duplicate keys are allowed, a forward scan of + the tree will visit them in the order of insertion. + + For a tree node: + struct T { + avlnode_t avlnode; + char *key; + }; + you could set the "indirect" flag, and then you simply use + strcmp(), avoiding the need for passing templates in looking up key + values. Much nicer. + + There is also an orthogonal variant that is enforced through the + type system -- note that would be possible for all of the above as + well, but the number of cases simply explodes and none of the above + flags affects the dynamically changing data structures (just the + tree definition), unlike this one. + + - the "C" variant keeps track of the number of nodes in the tree to + support a "count" operation in O(1) time, but is otherwise + identical. + + The various initializer macros and TreedefInit functions should + make sense with this. + + All functions for looking up nodes return NULL if there is no node + satisfying the requirements. + + - Init: initializes a tree (really just: root = NULL, perhaps count = 0) + - Free: calls "freefun" on each node, which may free the node + - FreeArg: as "Free", but with an extra, user-supplied, argument + - Root: returns the root node + - Lookup: returns a node with key value "key" (ref allowdups flag) + - LookupIPath: like Lookup, but also filling an IPath_t structure + for efficient insertion in case of a failed lookup (or inserting + duplicates) + - LookupDPath: like Lookup, but also filling a DPath_t structure + that helps with deleting a node + - LookupPredEq: locates the node with the greatest key value <= "key" + - LookupSuccEq: similar, but smallest key value >= "key" + - LookupPred: similar, < "key" + - LookupSucc: similar, > "key" + - Insert: convenience function: LookupIPath ; InsertIPath + - Delete: convenience function: LookupDPath ; DeleteDPath + - InsertIPath: insert node based on the "path" obtained from LookupIPath + - DeleteDPath: delete node, using information in "path" to do so efficiently + - SwapNode: replace "oldn" by "newn" without modifying the tree + structure (the key need not be equal, but must be + FindPred(oldn).key < newn.key < FindSucc(oldn).key, where a + non-existing predecessor has key -inf and a non-existing + successor has key +inf, and where it is understood that the < + operator becomes <= if allowdups is set + - AugmentUpdate: to be called when something in "node" changes that + affects the subtree "summary" computed by the configured + "augment" function + - IsEmpty: returns 1 if tree is empty, 0 if not + - IsSingleton: returns 1 if tree contains exactly one node, 0 if not + - FindMin: returns the node with the smallest key value in the tree + - FindMax: similar, largest key value + - FindPred: preceding node in in-order treewalk + - FindSucc: similar, following node + + - Walk: calls "f" with user-supplied argument "a" once for each + node, starting at FindMin and ending at FindMax + - ConstWalk: same, but with a const tree + - WalkRange: like Walk, but only visiting nodes with key values in + range [min,max] (that's inclusive) + - ConstWalkRange: same, but with a const tree + - WalkRangeReverse: like WalkRange, but in the reverse direction + - ConstWalkRangeReverse: same, but with a const tree + - IterFirst: starts forward iteration, starting at (and returning) FindMin + - IterSuccEq: similar, starting at LookupSuccEq + - IterSucc: similar, starting at LookupSucc + - IterNext: returns FindSucc(last returned node); may not be called + if preceding IterXXX call on same "iter" returned NULL + + That's all there is to it. + + Note that all calls to Walk(f,a) can be rewritten as: + for(n=IterFirst(&it); n; n=IterNext(&it)) { f(n,a) } + or as + for(n=FindMin(); n; n=FindSucc(n)) { f(n,a) } + + The walk functions and iterators may not alter the tree + structure. If that is desired, the latter can easily be rewritten + as: + n=FindMin() ; while(n) { nn=FindSucc(n); f(n,a); n=nn } + because FindMin/FindSucc doesn't store any information to allow + fast processing. That'll allow every operation, with the obvious + exception of f(n) calling Delete(FindSucc(n)). + + Currently, all trees maintain parent pointers, but it may be worth + doing a separate set without it, as it reduces the size of + avlNode_t. But in that case, the FindMin/FindSucc option would no + longer be a reasonable option because it would be prohibitively + expensive, whereas the IterFirst/IterNext option are alway + efficiently. If one were to do a threaded tree variant, the + implemetantion of IterFirst/IterNext would become absolute trivial + and faster still, but at the cost of significantly more overhead in + memory and updates. */ + +#include +#include + +#include "dds/export.h" +#include "dds/ddsrt/attributes.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +#define DDSRT_AVL_MAX_TREEHEIGHT (12 * sizeof (void *)) + +typedef int (*ddsrt_avl_compare_t) (const void *a, const void *b); +typedef int (*ddsrt_avl_compare_r_t) (const void *a, const void *b, void *arg); +typedef void (*ddsrt_avl_augment_t) (void *node, const void *left, const void *right); +typedef void (*ddsrt_avl_walk_t) (void *node, void *arg); +typedef void (*ddsrt_avl_const_walk_t) (const void *node, void *arg); + +typedef struct ddsrt_avl_node { + struct ddsrt_avl_node *cs[2]; /* 0 = left, 1 = right */ + struct ddsrt_avl_node *parent; + int height; +} ddsrt_avl_node_t; + +#define DDSRT_AVL_TREEDEF_FLAG_INDKEY 1 +#define DDSRT_AVL_TREEDEF_FLAG_R 2 +#define DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS 4 + +typedef struct ddsrt_avl_treedef { +#if defined (__cplusplus) + ddsrt_avl_treedef() {} +#endif + size_t avlnodeoffset; + size_t keyoffset; + union { + ddsrt_avl_compare_t comparekk; + ddsrt_avl_compare_r_t comparekk_r; + } u; + ddsrt_avl_augment_t augment; + uint32_t flags; + void *cmp_arg; /* for _r variant */ +} ddsrt_avl_treedef_t; + +typedef struct ddsrt_avl_ctreedef { + ddsrt_avl_treedef_t t; +} ddsrt_avl_ctreedef_t; + +typedef struct ddsrt_avl_tree { + ddsrt_avl_node_t *root; +} ddsrt_avl_tree_t; + +typedef struct ddsrt_avl_ctree { + ddsrt_avl_tree_t t; + size_t count; +} ddsrt_avl_ctree_t; + +typedef struct ddsrt_avl_path { + int depth; /* total depth of path */ + int pnodeidx; + ddsrt_avl_node_t *parent; /* (nodeidx == 0 ? NULL : *(path[nodeidx-1])) */ + ddsrt_avl_node_t **pnode[DDSRT_AVL_MAX_TREEHEIGHT]; +} ddsrt_avl_path_t; + +typedef struct ddsrt_avl_ipath { + ddsrt_avl_path_t p; +} ddsrt_avl_ipath_t; + +typedef struct ddsrt_avl_dpath { + ddsrt_avl_path_t p; +} ddsrt_avl_dpath_t; + +typedef struct ddsrt_avl_iter { + const ddsrt_avl_treedef_t *td; + ddsrt_avl_node_t *right; + ddsrt_avl_node_t **todop; + ddsrt_avl_node_t *todo[1+DDSRT_AVL_MAX_TREEHEIGHT]; +} ddsrt_avl_iter_t; + +typedef struct ddsrt_avl_citer { + ddsrt_avl_iter_t t; +} ddsrt_avl_citer_t; + +/* avlnodeoffset and keyoffset must both be in [0,2**31-1] */ +#define DDSRT_AVL_TREEDEF_INITIALIZER(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), 0, 0 } +#define DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_INDKEY, 0 } +#define DDSRT_AVL_TREEDEF_INITIALIZER_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS, 0 } +#define DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_INDKEY|DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS, 0 } +#define DDSRT_AVL_TREEDEF_INITIALIZER_R(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_R, (cmparg) } +#define DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY_R(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_INDKEY|DDSRT_AVL_TREEDEF_FLAG_R, (cmparg) } +#define DDSRT_AVL_TREEDEF_INITIALIZER_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_R|DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS, (cmparg) } +#define DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_INDKEY|DDSRT_AVL_TREEDEF_FLAG_R|DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS, (cmparg) } + +/* Not maintaining # nodes */ + +DDS_EXPORT void ddsrt_avl_treedef_init (ddsrt_avl_treedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_t comparekk, ddsrt_avl_augment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); +DDS_EXPORT void ddsrt_avl_treedef_init_r (ddsrt_avl_treedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_r_t comparekk_r, void *cmp_arg, ddsrt_avl_augment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); + +DDS_EXPORT void ddsrt_avl_init (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_free (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void (*freefun) (void *node)) ddsrt_nonnull((1,2)); +DDS_EXPORT void ddsrt_avl_free_arg (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void (*freefun) (void *node, void *arg), void *arg) ddsrt_nonnull((1,2)); + +DDS_EXPORT void *ddsrt_avl_root (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_root_non_empty (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup_ipath (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key, ddsrt_avl_ipath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup_dpath (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key, ddsrt_avl_dpath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup_pred_eq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup_succ_eq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup_pred (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) ddsrt_nonnull_all; + +DDS_EXPORT void ddsrt_avl_insert (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *node) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_delete (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *node) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_insert_ipath (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *node, ddsrt_avl_ipath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_delete_dpath (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *node, ddsrt_avl_dpath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_swap_node (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *oldn, void *newn) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_augment_update (const ddsrt_avl_treedef_t *td, void *node) ddsrt_nonnull_all; + +DDS_EXPORT int ddsrt_avl_is_empty (const ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT int ddsrt_avl_is_singleton (const ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; + +DDS_EXPORT void *ddsrt_avl_find_min (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_find_max (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_find_pred (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); +DDS_EXPORT void *ddsrt_avl_find_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); + +DDS_EXPORT void ddsrt_avl_walk (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, ddsrt_avl_walk_t f, void *a) ddsrt_nonnull((1,2,3)); +DDS_EXPORT void ddsrt_avl_const_walk (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_const_walk_t f, void *a) ddsrt_nonnull((1,2,3)); +DDS_EXPORT void ddsrt_avl_walk_range (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); +DDS_EXPORT void ddsrt_avl_const_walk_range (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); +DDS_EXPORT void ddsrt_avl_walk_range_reverse (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) ddsrt_nonnull((1,2,3)); +DDS_EXPORT void ddsrt_avl_const_walk_range_reverse (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) ddsrt_nonnull((1,2,3)); + +DDS_EXPORT void *ddsrt_avl_iter_first (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_iter_t *iter) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_iter_succ_eq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_iter_t *iter, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_iter_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_iter_t *iter, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_iter_next (ddsrt_avl_iter_t *iter) ddsrt_nonnull_all; + +/* Maintaining # nodes */ + +#define DDSRT_AVL_CTREEDEF_INITIALIZER(avlnodeoffset, keyoffset, comparekk, augment) { DDSRT_AVL_TREEDEF_INITIALIZER (avlnodeoffset, keyoffset, comparekk, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_INDKEY(avlnodeoffset, keyoffset, comparekk, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (avlnodeoffset, keyoffset, comparekk, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_INDKEY_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_R(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_R (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_INDKEY_R(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY_R (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_R_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_INDKEY_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY_R_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } + +DDS_EXPORT void ddsrt_avl_ctreedef_init (ddsrt_avl_ctreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_t comparekk, ddsrt_avl_augment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); +DDS_EXPORT void ddsrt_avl_ctreedef_init_r (ddsrt_avl_ctreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_r_t comparekk_r, void *cmp_arg, ddsrt_avl_augment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); + +DDS_EXPORT void ddsrt_avl_cinit (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_cfree (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void (*freefun) (void *node)) ddsrt_nonnull((1,2)); +DDS_EXPORT void ddsrt_avl_cfree_arg (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void (*freefun) (void *node, void *arg), void *arg) ddsrt_nonnull((1,2)); + +DDS_EXPORT void *ddsrt_avl_croot (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_croot_non_empty (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup_ipath (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key, ddsrt_avl_ipath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup_dpath (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key, ddsrt_avl_dpath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup_pred_eq (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup_succ_eq (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup_pred (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup_succ (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) ddsrt_nonnull_all; + +DDS_EXPORT void ddsrt_avl_cinsert (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_cdelete (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_cinsert_ipath (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node, ddsrt_avl_ipath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_cdelete_dpath (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node, ddsrt_avl_dpath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_cswap_node (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *oldn, void *newn) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_caugment_update (const ddsrt_avl_ctreedef_t *td, void *node) ddsrt_nonnull_all; + +DDS_EXPORT int ddsrt_avl_cis_empty (const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT int ddsrt_avl_cis_singleton (const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT size_t ddsrt_avl_ccount (const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; + +DDS_EXPORT void *ddsrt_avl_cfind_min (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_cfind_max (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_cfind_pred (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); +DDS_EXPORT void *ddsrt_avl_cfind_succ (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); + +DDS_EXPORT void ddsrt_avl_cwalk (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, ddsrt_avl_walk_t f, void *a) ddsrt_nonnull((1,2,3)); +DDS_EXPORT void ddsrt_avl_cconst_walk (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_const_walk_t f, void *a) ddsrt_nonnull((1,2,3)); +DDS_EXPORT void ddsrt_avl_cwalk_range (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); +DDS_EXPORT void ddsrt_avl_cconst_walk_range (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); +DDS_EXPORT void ddsrt_avl_cwalk_range_reverse (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); +DDS_EXPORT void ddsrt_avl_cconst_walk_range_reverse (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); + +DDS_EXPORT void *ddsrt_avl_citer_first (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_citer_t *iter) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_citer_succ_eq (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_citer_t *iter, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_citer_succ (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_citer_t *iter, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_citer_next (ddsrt_avl_citer_t *iter) ddsrt_nonnull_all; + +#if defined (__cplusplus) +} +#endif + +#endif /* DDSRT_AVL_H */ diff --git a/src/util/include/dds/util/ut_expand_envvars.h b/src/ddsrt/include/dds/ddsrt/expand_envvars.h similarity index 78% rename from src/util/include/dds/util/ut_expand_envvars.h rename to src/ddsrt/include/dds/ddsrt/expand_envvars.h index c101679..d7b66f4 100644 --- a/src/util/include/dds/util/ut_expand_envvars.h +++ b/src/ddsrt/include/dds/ddsrt/expand_envvars.h @@ -9,8 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef UT_EXPAND_ENVVARS_H -#define UT_EXPAND_ENVVARS_H +#ifndef DDSRT_EXPAND_ENVVARS_H +#define DDSRT_EXPAND_ENVVARS_H #include "dds/export.h" @@ -19,10 +19,10 @@ extern "C" { #endif /* Expands ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, but not $X */ - DDS_EXPORT char *ut_expand_envvars(const char *string); + DDS_EXPORT char *ddsrt_expand_envvars(const char *string); /* Expands $X, ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, $ and \ can be escaped with \ */ - DDS_EXPORT char *ut_expand_envvars_sh(const char *string); + DDS_EXPORT char *ddsrt_expand_envvars_sh(const char *string); #if defined (__cplusplus) } diff --git a/src/ddsrt/include/dds/ddsrt/fibheap.h b/src/ddsrt/include/dds/ddsrt/fibheap.h new file mode 100644 index 0000000..4a2c330 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/fibheap.h @@ -0,0 +1,54 @@ +/* + * 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_FIBHEAP_H +#define DDSRT_FIBHEAP_H + +#include + +#include "dds/export.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +typedef struct ddsrt_fibheap_node { + struct ddsrt_fibheap_node *parent, *children; + struct ddsrt_fibheap_node *prev, *next; + unsigned mark: 1; + unsigned degree: 31; +} ddsrt_fibheap_node_t; + +typedef struct ddsrt_fibheap_def { + uintptr_t offset; + int (*cmp) (const void *va, const void *vb); +} ddsrt_fibheap_def_t; + +typedef struct ddsrt_fibheap { + ddsrt_fibheap_node_t *roots; /* points to root with min key value */ +} ddsrt_fibheap_t; + +#define DDSRT_FIBHEAPDEF_INITIALIZER(offset, cmp) { (offset), (cmp) } + +DDS_EXPORT void ddsrt_fibheap_def_init (ddsrt_fibheap_def_t *fhdef, uintptr_t offset, int (*cmp) (const void *va, const void *vb)); +DDS_EXPORT void ddsrt_fibheap_init (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh); +DDS_EXPORT void *ddsrt_fibheap_min (const ddsrt_fibheap_def_t *fhdef, const ddsrt_fibheap_t *fh); +DDS_EXPORT void ddsrt_fibheap_merge (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *a, ddsrt_fibheap_t *b); +DDS_EXPORT void ddsrt_fibheap_insert (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh, const void *vnode); +DDS_EXPORT void ddsrt_fibheap_delete (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh, const void *vnode); +DDS_EXPORT void *ddsrt_fibheap_extract_min (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh); +DDS_EXPORT void ddsrt_fibheap_decrease_key (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh, const void *vnode); /* to be called AFTER decreasing the key */ + +#if defined (__cplusplus) +} +#endif + +#endif /* DDSRT_FIBHEAP_H */ diff --git a/src/ddsrt/include/dds/ddsrt/hopscotch.h b/src/ddsrt/include/dds/ddsrt/hopscotch.h new file mode 100644 index 0000000..24d9213 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/hopscotch.h @@ -0,0 +1,104 @@ +/* + * 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_HOPSCOTCH_H +#define DDSRT_HOPSCOTCH_H + +#include + +#include "dds/export.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +/* Concurrent version */ +struct ddsrt_chh; +struct ddsrt_chh_bucket; +struct ddsrt_chh_iter { + struct ddsrt_chh_bucket *bs; + uint32_t size; + uint32_t cursor; +}; + +/* + * The hopscotch hash table is dependent on a proper functioning hash. + * If the hash function generates a lot of hash collisions, then it will + * not be able to handle that by design. + * It is capable of handling some collisions, but not more than 32 per + * bucket (less, when other hash values are clustered around the + * collision value). + * When proper distributed hash values are generated, then hopscotch + * works nice and quickly. + */ +typedef uint32_t (*ddsrt_hh_hash_fn) (const void *); + +/* + * Hopscotch needs to be able to compare two elements. + * Returns 0 when not equal. + */ +typedef int (*ddsrt_hh_equals_fn) (const void *, const void *); + +/* + * Hopscotch is will resize its internal buckets list when needed. It will + * call this garbage collection function with the old buckets list. The + * caller has to delete the list when it deems it safe to do so. + */ +typedef void (*ddsrt_hh_buckets_gc_fn) (void *); + +DDS_EXPORT struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets); +DDS_EXPORT void ddsrt_chh_free (struct ddsrt_chh * __restrict hh); +DDS_EXPORT void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict rt, const void * __restrict template); +DDS_EXPORT int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data); +DDS_EXPORT int ddsrt_chh_remove (struct ddsrt_chh * __restrict rt, const void * __restrict template); +DDS_EXPORT void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ +void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_iter *it); +void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it); + +/* Sequential version */ +struct ddsrt_hh; + +struct ddsrt_hh_iter { + struct ddsrt_hh *hh; + uint32_t cursor; +}; + +DDS_EXPORT struct ddsrt_hh *ddsrt_hh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals); +DDS_EXPORT void ddsrt_hh_free (struct ddsrt_hh * __restrict hh); +DDS_EXPORT void *ddsrt_hh_lookup (const struct ddsrt_hh * __restrict rt, const void * __restrict template); +DDS_EXPORT int ddsrt_hh_add (struct ddsrt_hh * __restrict rt, const void * __restrict data); +DDS_EXPORT int ddsrt_hh_remove (struct ddsrt_hh * __restrict rt, const void * __restrict template); +DDS_EXPORT void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ +DDS_EXPORT void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter); /* may delete nodes */ +DDS_EXPORT void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter); + +/* Sequential version, embedded data */ +struct ddsrt_ehh; + +struct ddsrt_ehh_iter { + struct ddsrt_ehh *hh; + uint32_t cursor; +}; + +DDS_EXPORT struct ddsrt_ehh *ddsrt_ehh_new (size_t elemsz, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals); +DDS_EXPORT void ddsrt_ehh_free (struct ddsrt_ehh * __restrict hh); +DDS_EXPORT void *ddsrt_ehh_lookup (const struct ddsrt_ehh * __restrict rt, const void * __restrict template); +DDS_EXPORT int ddsrt_ehh_add (struct ddsrt_ehh * __restrict rt, const void * __restrict data); +DDS_EXPORT int ddsrt_ehh_remove (struct ddsrt_ehh * __restrict rt, const void * __restrict template); +DDS_EXPORT void ddsrt_ehh_enum (struct ddsrt_ehh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ +DDS_EXPORT void *ddsrt_ehh_iter_first (struct ddsrt_ehh * __restrict rt, struct ddsrt_ehh_iter * __restrict iter); /* may delete nodes */ +DDS_EXPORT void *ddsrt_ehh_iter_next (struct ddsrt_ehh_iter * __restrict iter); + +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/src/util/include/dds/util/ut_thread_pool.h b/src/ddsrt/include/dds/ddsrt/thread_pool.h similarity index 69% rename from src/util/include/dds/util/ut_thread_pool.h rename to src/ddsrt/include/dds/ddsrt/thread_pool.h index 50863a9..f03fe46 100644 --- a/src/util/include/dds/util/ut_thread_pool.h +++ b/src/ddsrt/include/dds/ddsrt/thread_pool.h @@ -9,8 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef UT_THREAD_POOL_H -#define UT_THREAD_POOL_H +#ifndef DDSRT_THREAD_POOL_H +#define DDSRT_THREAD_POOL_H #include @@ -22,16 +22,16 @@ extern "C" { #endif -typedef struct ut_thread_pool_s *ut_thread_pool; +typedef struct ddsrt_thread_pool_s *ddsrt_thread_pool; /* - ut_thread_pool_new: Creates a new thread pool. Returns NULL if + ddsrt_thread_pool_new: Creates a new thread pool. Returns NULL if cannot create initial set of threads. Threads are created with the optional atribute argument. Additional threads may be created on demand up to max_threads. */ -DDS_EXPORT ut_thread_pool ut_thread_pool_new +DDS_EXPORT ddsrt_thread_pool ddsrt_thread_pool_new ( uint32_t threads, /* Initial number of threads in pool (can be 0) */ uint32_t max_threads, /* Maximum number of threads in pool (0 == infinite) */ @@ -39,25 +39,25 @@ DDS_EXPORT ut_thread_pool ut_thread_pool_new ddsrt_threadattr_t * attr /* Attributes used to create pool threads (can be NULL) */ ); -/* ut_thread_pool_free: Frees pool, destroying threads. */ +/* ddsrt_thread_pool_free: Frees pool, destroying threads. */ -DDS_EXPORT void ut_thread_pool_free (ut_thread_pool pool); +DDS_EXPORT void ddsrt_thread_pool_free (ddsrt_thread_pool pool); -/* ut_thread_pool_purge: Purge threads from pool back to initial set. */ +/* ddsrt_thread_pool_purge: Purge threads from pool back to initial set. */ -DDS_EXPORT void ut_thread_pool_purge (ut_thread_pool pool); +DDS_EXPORT void ddsrt_thread_pool_purge (ddsrt_thread_pool pool); /* - ut_thread_pool_submit: Submit a thread function and associated argument + ddsrt_thread_pool_submit: Submit a thread function and associated argument to be invoked by a thread from the pool. If no threads are available a new thread will be created on demand to handle the function unless the pool thread maximum has been reached, in which case the function is queued. Note that if the pool queue has reached it's maximum DDS_RETCODE_TRY_AGAIN is returned. */ -DDS_EXPORT dds_retcode_t ut_thread_pool_submit +DDS_EXPORT dds_retcode_t ddsrt_thread_pool_submit ( - ut_thread_pool pool, /* Thread pool instance */ + ddsrt_thread_pool pool, /* Thread pool instance */ void (*fn) (void *arg), /* Function to be invoked by thread from pool */ void * arg /* Argument passed to invoked function */ ); @@ -66,4 +66,4 @@ DDS_EXPORT dds_retcode_t ut_thread_pool_submit } #endif -#endif /* UT_THREAD_POOL_H */ +#endif /* DDSRT_THREAD_POOL_H */ diff --git a/src/ddsrt/include/dds/ddsrt/xmlparser.h b/src/ddsrt/include/dds/ddsrt/xmlparser.h new file mode 100644 index 0000000..120be63 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/xmlparser.h @@ -0,0 +1,52 @@ +/* + * 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_XMLPARSER_H +#define DDSRT_XMLPARSER_H + +#include + +#include "dds/export.h" + +#if defined (__cplusplus) +extern "C" { +#endif + + typedef int (*ddsrt_xmlp_proc_elem_open_t) (void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name); + typedef int (*ddsrt_xmlp_proc_attr_t) (void *varg, uintptr_t eleminfo, const char *name, const char *value); + typedef int (*ddsrt_xmlp_proc_elem_data_t) (void *varg, uintptr_t eleminfo, const char *data); + typedef int (*ddsrt_xmlp_proc_elem_close_t) (void *varg, uintptr_t eleminfo); + typedef void (*ddsrt_xmlp_error) (void *varg, const char *msg, int line); + + struct ddsrt_xmlp_callbacks { + ddsrt_xmlp_proc_elem_open_t elem_open; + ddsrt_xmlp_proc_attr_t attr; + ddsrt_xmlp_proc_elem_data_t elem_data; + ddsrt_xmlp_proc_elem_close_t elem_close; + ddsrt_xmlp_error error; + }; + + struct ddsrt_xmlp_state; + + DDS_EXPORT struct ddsrt_xmlp_state *ddsrt_xmlp_new_file (FILE *fp, void *varg, const struct ddsrt_xmlp_callbacks *cb); + DDS_EXPORT struct ddsrt_xmlp_state *ddsrt_xmlp_new_string (const char *string, void *varg, const struct ddsrt_xmlp_callbacks *cb); + DDS_EXPORT void ddsrt_xmlp_set_requireEOF (struct ddsrt_xmlp_state *st, int require_eof); + DDS_EXPORT size_t ddsrt_xmlp_get_bufpos (const struct ddsrt_xmlp_state *st); + DDS_EXPORT void ddsrt_xmlp_free (struct ddsrt_xmlp_state *st); + DDS_EXPORT int ddsrt_xmlp_parse (struct ddsrt_xmlp_state *st); + + DDS_EXPORT int ddsrt_xmlUnescapeInsitu (char *buffer, size_t *n); + +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/src/util/src/ut_avl.c b/src/ddsrt/src/avl.c similarity index 52% rename from src/util/src/ut_avl.c rename to src/ddsrt/src/avl.c index 3dc05e3..52ceddb 100644 --- a/src/util/src/ut_avl.c +++ b/src/ddsrt/src/avl.c @@ -15,20 +15,20 @@ #include #include "dds/ddsrt/attributes.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #define LOAD_DIRKEY(avlnode, tree) (((char *) (avlnode)) - (tree)->avlnodeoffset + (tree)->keyoffset) #define LOAD_INDKEY(avlnode, tree) (*((char **) (((char *) (avlnode)) - (tree)->avlnodeoffset + (tree)->keyoffset))) -static int comparenk (const ut_avlTreedef_t *td, const ut_avlNode_t *a, const void *b) +static int comparenk (const ddsrt_avl_treedef_t *td, const ddsrt_avl_node_t *a, const void *b) { const void *ka; - if (td->flags & UT_AVL_TREEDEF_FLAG_INDKEY) { + if (td->flags & DDSRT_AVL_TREEDEF_FLAG_INDKEY) { ka = LOAD_INDKEY (a, td); } else { ka = LOAD_DIRKEY (a, td); } - if (td->flags & UT_AVL_TREEDEF_FLAG_R) { + if (td->flags & DDSRT_AVL_TREEDEF_FLAG_R) { return td->u.comparekk_r (ka, b, td->cmp_arg); } else { return td->u.comparekk (ka, b); @@ -36,17 +36,17 @@ static int comparenk (const ut_avlTreedef_t *td, const ut_avlNode_t *a, const vo } #if 0 -static int comparenn_direct (const ut_avlTreedef_t *td, const ut_avlNode_t *a, const ut_avlNode_t *b) +static int comparenn_direct (const ddsrt_avl_treedef_t *td, const ddsrt_avl_node_t *a, const ddsrt_avl_node_t *b) { return td->comparekk (LOAD_DIRKEY (a, td), LOAD_DIRKEY (b, td)); } -static int comparenn_indirect (const ut_avlTreedef_t *td, const ut_avlNode_t *a, const ut_avlNode_t *b) +static int comparenn_indirect (const ddsrt_avl_treedef_t *td, const ddsrt_avl_node_t *a, const ddsrt_avl_node_t *b) { return td->comparekk (LOAD_INDKEY (a, td), LOAD_INDKEY (b, td)); } -static int comparenn (const ut_avlTreedef_t *td, const ut_avlNode_t *a, const ut_avlNode_t *b) +static int comparenn (const ddsrt_avl_treedef_t *td, const ddsrt_avl_node_t *a, const ddsrt_avl_node_t *b) { if (IS_INDKEY (td->keyoffset)) { return comparenn_indirect (td, a, b); @@ -56,25 +56,25 @@ static int comparenn (const ut_avlTreedef_t *td, const ut_avlNode_t *a, const ut } #endif -static ut_avlNode_t *node_from_onode (const ut_avlTreedef_t *td, char *onode) +static ddsrt_avl_node_t *node_from_onode (const ddsrt_avl_treedef_t *td, char *onode) { if (onode == NULL) { return NULL; } else { - return (ut_avlNode_t *) (onode + td->avlnodeoffset); + return (ddsrt_avl_node_t *) (onode + td->avlnodeoffset); } } -static const ut_avlNode_t *cnode_from_onode (const ut_avlTreedef_t *td, const char *onode) +static const ddsrt_avl_node_t *cnode_from_onode (const ddsrt_avl_treedef_t *td, const char *onode) { if (onode == NULL) { return NULL; } else { - return (const ut_avlNode_t *) (onode + td->avlnodeoffset); + return (const ddsrt_avl_node_t *) (onode + td->avlnodeoffset); } } -static char *onode_from_node (const ut_avlTreedef_t *td, ut_avlNode_t *node) +static char *onode_from_node (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t *node) { if (node == NULL) { return NULL; @@ -83,7 +83,7 @@ static char *onode_from_node (const ut_avlTreedef_t *td, ut_avlNode_t *node) } } -static const char *conode_from_node (const ut_avlTreedef_t *td, const ut_avlNode_t *node) +static const char *conode_from_node (const ddsrt_avl_treedef_t *td, const ddsrt_avl_node_t *node) { if (node == NULL) { return NULL; @@ -92,7 +92,7 @@ static const char *conode_from_node (const ut_avlTreedef_t *td, const ut_avlNode } } -static void treedef_init_common (ut_avlTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlAugment_t augment, uint32_t flags) +static void treedef_init_common (ddsrt_avl_treedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_augment_t augment, uint32_t flags) { assert (avlnodeoffset <= 0x7fffffff); assert (keyoffset <= 0x7fffffff); @@ -102,26 +102,26 @@ static void treedef_init_common (ut_avlTreedef_t *td, size_t avlnodeoffset, size td->flags = flags; } -void ut_avlTreedefInit (ut_avlTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_t comparekk, ut_avlAugment_t augment, uint32_t flags) +void ddsrt_avl_treedef_init (ddsrt_avl_treedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_t comparekk, ddsrt_avl_augment_t augment, uint32_t flags) { treedef_init_common (td, avlnodeoffset, keyoffset, augment, flags); td->u.comparekk = comparekk; } -void ut_avlTreedefInit_r (ut_avlTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_r_t comparekk_r, void *cmp_arg, ut_avlAugment_t augment, uint32_t flags) +void ddsrt_avl_treedef_init_r (ddsrt_avl_treedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_r_t comparekk_r, void *cmp_arg, ddsrt_avl_augment_t augment, uint32_t flags) { - treedef_init_common (td, avlnodeoffset, keyoffset, augment, flags | UT_AVL_TREEDEF_FLAG_R); + treedef_init_common (td, avlnodeoffset, keyoffset, augment, flags | DDSRT_AVL_TREEDEF_FLAG_R); td->cmp_arg = cmp_arg; td->u.comparekk_r = comparekk_r; } -void ut_avlInit (const ut_avlTreedef_t *td, ut_avlTree_t *tree) +void ddsrt_avl_init (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree) { tree->root = NULL; (void) td; } -static void treedestroy (const ut_avlTreedef_t *td, ut_avlNode_t *n, void (*freefun) (void *node)) +static void treedestroy (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t *n, void (*freefun) (void *node)) { if (n) { n->parent = NULL; @@ -133,7 +133,7 @@ static void treedestroy (const ut_avlTreedef_t *td, ut_avlNode_t *n, void (*free } } -static void treedestroy_arg (const ut_avlTreedef_t *td, ut_avlNode_t *n, void (*freefun) (void *node, void *arg), void *arg) +static void treedestroy_arg (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t *n, void (*freefun) (void *node, void *arg), void *arg) { if (n) { n->parent = NULL; @@ -145,30 +145,30 @@ static void treedestroy_arg (const ut_avlTreedef_t *td, ut_avlNode_t *n, void (* } } -void ut_avlFree (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void (*freefun) (void *node)) +void ddsrt_avl_free (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void (*freefun) (void *node)) { - ut_avlNode_t *n = tree->root; + ddsrt_avl_node_t *n = tree->root; tree->root = NULL; if (freefun) { treedestroy (td, n, freefun); } } -void ut_avlFreeArg (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void (*freefun) (void *node, void *arg), void *arg) +void ddsrt_avl_free_arg (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void (*freefun) (void *node, void *arg), void *arg) { - ut_avlNode_t *n = tree->root; + ddsrt_avl_node_t *n = tree->root; tree->root = NULL; if (freefun) { treedestroy_arg (td, n, freefun, arg); } } -static void augment (const ut_avlTreedef_t *td, ut_avlNode_t *n) +static void augment (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t *n) { td->augment (onode_from_node (td, n), conode_from_node (td, n->cs[0]), conode_from_node (td, n->cs[1])); } -static ut_avlNode_t *rotate_single (const ut_avlTreedef_t *td, ut_avlNode_t **pnode, ut_avlNode_t *node, int dir) +static ddsrt_avl_node_t *rotate_single (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t **pnode, ddsrt_avl_node_t *node, int dir) { /* rotate_single(N, dir) performs one rotation, e.g., for dir=1, a right rotation as depicted below, for dir=0 a left rotation: @@ -179,9 +179,9 @@ static ut_avlNode_t *rotate_single (const ut_avlTreedef_t *td, ut_avlNode_t **pn Since a right rotation is only ever done with the left side is overweight, _ND must be != NULL. */ - ut_avlNode_t * const parent = node->parent; - ut_avlNode_t * const node_ND = node->cs[1-dir]; - ut_avlNode_t * const node_ND_D = node_ND->cs[dir]; + ddsrt_avl_node_t * const parent = node->parent; + ddsrt_avl_node_t * const node_ND = node->cs[1-dir]; + ddsrt_avl_node_t * const node_ND_D = node_ND->cs[dir]; assert (node_ND); node_ND->cs[dir] = node; node_ND->parent = parent; @@ -200,7 +200,7 @@ static ut_avlNode_t *rotate_single (const ut_avlTreedef_t *td, ut_avlNode_t **pn return parent; } -static ut_avlNode_t *rotate_double (const ut_avlTreedef_t *td, ut_avlNode_t **pnode, ut_avlNode_t *node, int dir) +static ddsrt_avl_node_t *rotate_double (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t **pnode, ddsrt_avl_node_t *node, int dir) { /* rotate_double() performs one double rotation, which is slightly faster when written out than the equivalent: @@ -218,9 +218,9 @@ static ut_avlNode_t *rotate_double (const ut_avlTreedef_t *td, ut_avlNode_t **pn Since a right double rotation is only ever done with the N is overweight on the left side and _ND is overweight on the right side, both _ND and _ND_D must be != NULL. */ - ut_avlNode_t * const parent = node->parent; - ut_avlNode_t * const node_ND = node->cs[1-dir]; - ut_avlNode_t * const node_ND_D = node_ND->cs[dir]; + ddsrt_avl_node_t * const parent = node->parent; + ddsrt_avl_node_t * const node_ND = node->cs[1-dir]; + ddsrt_avl_node_t * const node_ND_D = node_ND->cs[dir]; assert (node_ND); assert (node_ND_D); node_ND->cs[dir] = node_ND_D->cs[1-dir]; @@ -251,16 +251,16 @@ static ut_avlNode_t *rotate_double (const ut_avlTreedef_t *td, ut_avlNode_t **pn return parent; } -static ut_avlNode_t *rotate (const ut_avlTreedef_t *td, ut_avlNode_t **pnode, ut_avlNode_t *node, int dir) +static ddsrt_avl_node_t *rotate (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t **pnode, ddsrt_avl_node_t *node, int dir) { /* _D => child in the direction of rotation (1 for right, 0 for left); _ND => child in the opposite direction. So in a right rotation, _ND_D means the grandchild that is the right child of the left child. */ - ut_avlNode_t * const node_ND = node->cs[1-dir]; + ddsrt_avl_node_t * const node_ND = node->cs[1-dir]; assert (node_ND != NULL); - ut_avlNode_t * const node_ND_ND = node_ND->cs[1-dir]; - ut_avlNode_t * const node_ND_D = node_ND->cs[dir]; + ddsrt_avl_node_t * const node_ND_ND = node_ND->cs[1-dir]; + ddsrt_avl_node_t * const node_ND_D = node_ND->cs[dir]; int height_ND_ND, height_ND_D; assert (dir == !!dir); height_ND_ND = node_ND_ND ? node_ND_ND->height : 0; @@ -272,10 +272,10 @@ static ut_avlNode_t *rotate (const ut_avlTreedef_t *td, ut_avlNode_t **pnode, ut } } -static ut_avlNode_t *rebalance_one (const ut_avlTreedef_t *td, ut_avlNode_t **pnode, ut_avlNode_t *node) +static ddsrt_avl_node_t *rebalance_one (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t **pnode, ddsrt_avl_node_t *node) { - ut_avlNode_t *node_L = node->cs[0]; - ut_avlNode_t *node_R = node->cs[1]; + ddsrt_avl_node_t *node_L = node->cs[0]; + ddsrt_avl_node_t *node_R = node->cs[1]; int height_L = node_L ? node_L->height : 0; int height_R = node_R ? node_R->height : 0; if (height_L > height_R + 1) { @@ -301,7 +301,7 @@ static ut_avlNode_t *rebalance_one (const ut_avlTreedef_t *td, ut_avlNode_t **pn } } -static void rebalance_path (const ut_avlTreedef_t *td, ut_avlPath_t *path, ut_avlNode_t *node) +static void rebalance_path (const ddsrt_avl_treedef_t *td, ddsrt_avl_path_t *path, ddsrt_avl_node_t *node) { while (node) { assert (*path->pnode[path->depth] == node); @@ -310,25 +310,25 @@ static void rebalance_path (const ut_avlTreedef_t *td, ut_avlPath_t *path, ut_av } } -static ut_avlNode_t **nodeptr_from_node (ut_avlTree_t *tree, ut_avlNode_t *node) +static ddsrt_avl_node_t **nodeptr_from_node (ddsrt_avl_tree_t *tree, ddsrt_avl_node_t *node) { - ut_avlNode_t *parent = node->parent; + ddsrt_avl_node_t *parent = node->parent; return (parent == NULL) ? &tree->root : (node == parent->cs[0]) ? &parent->cs[0] : &parent->cs[1]; } -static void rebalance_nopath (const ut_avlTreedef_t *td, ut_avlTree_t *tree, ut_avlNode_t *node) +static void rebalance_nopath (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, ddsrt_avl_node_t *node) { while (node) { - ut_avlNode_t **pnode = nodeptr_from_node (tree, node); + ddsrt_avl_node_t **pnode = nodeptr_from_node (tree, node); node = rebalance_one (td, pnode, node); } } -void *ut_avlLookup (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +void *ddsrt_avl_lookup (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { - const ut_avlNode_t *cursor = tree->root; + const ddsrt_avl_node_t *cursor = tree->root; int c; while (cursor && (c = comparenk (td, cursor, key)) != 0) { const int dir = (c <= 0); @@ -337,59 +337,59 @@ void *ut_avlLookup (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const v return (void *) conode_from_node (td, cursor); } -static const ut_avlNode_t *lookup_path (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key, ut_avlPath_t *path) +static const ddsrt_avl_node_t *lookup_path (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key, ddsrt_avl_path_t *path) { - const ut_avlNode_t *cursor = tree->root; - const ut_avlNode_t *prev = NULL; + const ddsrt_avl_node_t *cursor = tree->root; + const ddsrt_avl_node_t *prev = NULL; int c; path->depth = 0; - path->pnode[0] = (ut_avlNode_t **) &tree->root; + path->pnode[0] = (ddsrt_avl_node_t **) &tree->root; while (cursor && (c = comparenk (td, cursor, key)) != 0) { const int dir = (c <= 0); prev = cursor; - path->pnode[++path->depth] = (ut_avlNode_t **) &cursor->cs[dir]; + path->pnode[++path->depth] = (ddsrt_avl_node_t **) &cursor->cs[dir]; cursor = cursor->cs[dir]; } path->pnodeidx = path->depth; - path->parent = (ut_avlNode_t *) prev; + path->parent = (ddsrt_avl_node_t *) prev; return cursor; } -void *ut_avlLookupDPath (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key, ut_avlDPath_t *path) +void *ddsrt_avl_lookup_dpath (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key, ddsrt_avl_dpath_t *path) { - const ut_avlNode_t *node = lookup_path (td, tree, key, &path->p); + const ddsrt_avl_node_t *node = lookup_path (td, tree, key, &path->p); return (void *) conode_from_node (td, node); } -void *ut_avlLookupIPath (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key, ut_avlIPath_t *path) +void *ddsrt_avl_lookup_ipath (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key, ddsrt_avl_ipath_t *path) { - const ut_avlNode_t *node = lookup_path (td, tree, key, &path->p); + const ddsrt_avl_node_t *node = lookup_path (td, tree, key, &path->p); /* If no duplicates allowed, path may not be used for insertion, and hence there is no need to continue descending the tree. Since we can invalidate it very efficiently, do so. */ if (node) { - if (!(td->flags & UT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { + if (!(td->flags & DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { path->p.pnode[path->p.depth] = NULL; } else { - const ut_avlNode_t *cursor = node; - const ut_avlNode_t *prev; + const ddsrt_avl_node_t *cursor = node; + const ddsrt_avl_node_t *prev; int c, dir; do { c = comparenk (td, cursor, key); dir = (c <= 0); prev = cursor; - path->p.pnode[++path->p.depth] = (ut_avlNode_t **) &cursor->cs[dir]; + path->p.pnode[++path->p.depth] = (ddsrt_avl_node_t **) &cursor->cs[dir]; cursor = cursor->cs[dir]; } while (cursor); - path->p.parent = (ut_avlNode_t *) prev; + path->p.parent = (ddsrt_avl_node_t *) prev; } } return (void *) conode_from_node (td, node); } -void ut_avlInsertIPath (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vnode, ut_avlIPath_t *path) +void ddsrt_avl_insert_ipath (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *vnode, ddsrt_avl_ipath_t *path) { - ut_avlNode_t *node = node_from_onode (td, vnode); + ddsrt_avl_node_t *node = node_from_onode (td, vnode); (void) tree; node->cs[0] = NULL; node->cs[1] = NULL; @@ -405,25 +405,25 @@ void ut_avlInsertIPath (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vno rebalance_path (td, &path->p, node->parent); } -void ut_avlInsert (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vnode) +void ddsrt_avl_insert (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *vnode) { const void *node = cnode_from_onode (td, vnode); const void *key; - ut_avlIPath_t path; - if (td->flags & UT_AVL_TREEDEF_FLAG_INDKEY) { + ddsrt_avl_ipath_t path; + if (td->flags & DDSRT_AVL_TREEDEF_FLAG_INDKEY) { key = LOAD_INDKEY (node, td); } else { key = LOAD_DIRKEY (node, td); } - ut_avlLookupIPath (td, tree, key, &path); - ut_avlInsertIPath (td, tree, vnode, &path); + ddsrt_avl_lookup_ipath (td, tree, key, &path); + ddsrt_avl_insert_ipath (td, tree, vnode, &path); } -static void delete_generic (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vnode, ut_avlDPath_t *path) +static void delete_generic (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *vnode, ddsrt_avl_dpath_t *path) { - ut_avlNode_t *node = node_from_onode (td, vnode); - ut_avlNode_t **pnode; - ut_avlNode_t *whence; + ddsrt_avl_node_t *node = node_from_onode (td, vnode); + ddsrt_avl_node_t **pnode; + ddsrt_avl_node_t *whence; if (path) { assert (tree == NULL); @@ -448,7 +448,7 @@ static void delete_generic (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void } else { - ut_avlNode_t *subst; + ddsrt_avl_node_t *subst; assert (node->cs[0] != NULL); assert (node->cs[1] != NULL); @@ -502,21 +502,21 @@ static void delete_generic (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void } } -void ut_avlDeleteDPath (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vnode, ut_avlDPath_t *path) +void ddsrt_avl_delete_dpath (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *vnode, ddsrt_avl_dpath_t *path) { (void) tree; delete_generic (td, NULL, vnode, path); } -void ut_avlDelete (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vnode) +void ddsrt_avl_delete (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *vnode) { delete_generic (td, tree, vnode, NULL); } -void ut_avlSwapNode (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vold, void *vnew) +void ddsrt_avl_swap_node (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *vold, void *vnew) { - ut_avlNode_t *old = node_from_onode (td, vold); - ut_avlNode_t *new = node_from_onode (td, vnew); + ddsrt_avl_node_t *old = node_from_onode (td, vold); + ddsrt_avl_node_t *new = node_from_onode (td, vnew); *nodeptr_from_node (tree, old) = new; /* use memmove so partially overlap between old & new is allowed (yikes!, but exploited by the memory allocator, and not a big @@ -533,7 +533,7 @@ void ut_avlSwapNode (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vold, } } -static ut_avlNode_t *find_neighbour (const ut_avlNode_t *n, int dir) +static ddsrt_avl_node_t *find_neighbour (const ddsrt_avl_node_t *n, int dir) { /* dir = 0 => pred; dir = 1 = succ */ if (n->cs[dir]) { @@ -541,62 +541,62 @@ static ut_avlNode_t *find_neighbour (const ut_avlNode_t *n, int dir) while (n->cs[1-dir]) { n = n->cs[1-dir]; } - return (ut_avlNode_t *) n; + return (ddsrt_avl_node_t *) n; } else { - const ut_avlNode_t *p = n->parent; + const ddsrt_avl_node_t *p = n->parent; while (p && n == p->cs[dir]) { n = p; p = p->parent; } - return (ut_avlNode_t *) p; + return (ddsrt_avl_node_t *) p; } } -static ut_avlNode_t *find_extremum (const ut_avlTree_t *tree, int dir) +static ddsrt_avl_node_t *find_extremum (const ddsrt_avl_tree_t *tree, int dir) { - const ut_avlNode_t *n = tree->root; + const ddsrt_avl_node_t *n = tree->root; if (n) { while (n->cs[dir]) { n = n->cs[dir]; } } - return (ut_avlNode_t *) n; + return (ddsrt_avl_node_t *) n; } -void *ut_avlFindMin (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) +void *ddsrt_avl_find_min (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) { return (void *) conode_from_node (td, find_extremum (tree, 0)); } -void *ut_avlFindMax (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) +void *ddsrt_avl_find_max (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) { return (void *) conode_from_node (td, find_extremum (tree, 1)); } -void *ut_avlFindPred (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *vnode) +void *ddsrt_avl_find_pred (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *vnode) { - const ut_avlNode_t *n = cnode_from_onode (td, vnode); + const ddsrt_avl_node_t *n = cnode_from_onode (td, vnode); if (n == NULL) { - return ut_avlFindMax (td, tree); + return ddsrt_avl_find_max (td, tree); } else { return (void *) conode_from_node (td, find_neighbour (n, 0)); } } -void *ut_avlFindSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *vnode) +void *ddsrt_avl_find_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *vnode) { - const ut_avlNode_t *n = cnode_from_onode (td, vnode); + const ddsrt_avl_node_t *n = cnode_from_onode (td, vnode); if (n == NULL) { - return ut_avlFindMin (td, tree); + return ddsrt_avl_find_min (td, tree); } else { return (void *) conode_from_node (td, find_neighbour (n, 1)); } } -static void avl_iter_downleft (ut_avlIter_t *iter) +static void avl_iter_downleft (ddsrt_avl_iter_t *iter) { if (*iter->todop) { - ut_avlNode_t *n; + ddsrt_avl_node_t *n; n = (*iter->todop)->cs[0]; while (n) { assert ((int) (iter->todop - iter->todo) < (int) (sizeof (iter->todo) / sizeof (*iter->todo))); @@ -607,16 +607,16 @@ static void avl_iter_downleft (ut_avlIter_t *iter) } } -void *ut_avlIterFirst (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlIter_t *iter) +void *ddsrt_avl_iter_first (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_iter_t *iter) { iter->td = td; iter->todop = iter->todo+1; - *iter->todop = (ut_avlNode_t *) tree->root; + *iter->todop = (ddsrt_avl_node_t *) tree->root; avl_iter_downleft (iter); return onode_from_node (td, *iter->todop); } -void *ut_avlIterNext (ut_avlIter_t *iter) +void *ddsrt_avl_iter_next (ddsrt_avl_iter_t *iter) { if (iter->todop-- > iter->todo+1 && iter->right == NULL) { iter->right = (*iter->todop)->cs[1]; @@ -628,13 +628,13 @@ void *ut_avlIterNext (ut_avlIter_t *iter) return onode_from_node (iter->td, *iter->todop); } -void ut_avlWalk (const ut_avlTreedef_t *td, ut_avlTree_t *tree, ut_avlWalk_t f, void *a) +void ddsrt_avl_walk (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, ddsrt_avl_walk_t f, void *a) { - const ut_avlNode_t *todo[1+UT_AVL_MAX_TREEHEIGHT]; - const ut_avlNode_t **todop = todo+1; + const ddsrt_avl_node_t *todo[1+DDSRT_AVL_MAX_TREEHEIGHT]; + const ddsrt_avl_node_t **todop = todo+1; *todop = tree->root; while (*todop) { - ut_avlNode_t *right, *n; + ddsrt_avl_node_t *right, *n; /* First locate the minimum value in this subtree */ n = (*todop)->cs[0]; while (n) { @@ -654,27 +654,27 @@ void ut_avlWalk (const ut_avlTreedef_t *td, ut_avlTree_t *tree, ut_avlWalk_t f, } } -void ut_avlConstWalk (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlConstWalk_t f, void *a) +void ddsrt_avl_const_walk (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_const_walk_t f, void *a) { - ut_avlWalk (td, (ut_avlTree_t *) tree, (ut_avlWalk_t) f, a); + ddsrt_avl_walk (td, (ddsrt_avl_tree_t *) tree, (ddsrt_avl_walk_t) f, a); } -int ut_avlIsEmpty (const ut_avlTree_t *tree) +int ddsrt_avl_is_empty (const ddsrt_avl_tree_t *tree) { return tree->root == NULL; } -int ut_avlIsSingleton (const ut_avlTree_t *tree) +int ddsrt_avl_is_singleton (const ddsrt_avl_tree_t *tree) { int r = (tree->root && tree->root->height == 1); assert (!r || (tree->root->cs[0] == NULL && tree->root->cs[1] == NULL)); return r; } -void ut_avlAugmentUpdate (const ut_avlTreedef_t *td, void *vnode) +void ddsrt_avl_augment_update (const ddsrt_avl_treedef_t *td, void *vnode) { if (td->augment) { - ut_avlNode_t *node = node_from_onode (td, vnode); + ddsrt_avl_node_t *node = node_from_onode (td, vnode); while (node) { augment (td, node); node = node->parent; @@ -682,11 +682,11 @@ void ut_avlAugmentUpdate (const ut_avlTreedef_t *td, void *vnode) } } -static const ut_avlNode_t *fixup_predsucceq (const ut_avlTreedef_t *td, const void *key, const ut_avlNode_t *tmp, const ut_avlNode_t *cand, int dir) +static const ddsrt_avl_node_t *fixup_predsucceq (const ddsrt_avl_treedef_t *td, const void *key, const ddsrt_avl_node_t *tmp, const ddsrt_avl_node_t *cand, int dir) { if (tmp == NULL) { return cand; - } else if (!(td->flags & UT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { + } else if (!(td->flags & DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { return tmp; } else { /* key exists - but it there's no guarantee we hit the first @@ -705,10 +705,10 @@ static const ut_avlNode_t *fixup_predsucceq (const ut_avlTreedef_t *td, const vo } } -static const ut_avlNode_t *lookup_predeq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +static const ddsrt_avl_node_t *lookup_predeq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { - const ut_avlNode_t *tmp = tree->root; - const ut_avlNode_t *cand = NULL; + const ddsrt_avl_node_t *tmp = tree->root; + const ddsrt_avl_node_t *cand = NULL; int c; while (tmp && (c = comparenk (td, tmp, key)) != 0) { if (c < 0) { @@ -721,10 +721,10 @@ static const ut_avlNode_t *lookup_predeq (const ut_avlTreedef_t *td, const ut_av return fixup_predsucceq (td, key, tmp, cand, 0); } -static const ut_avlNode_t *lookup_succeq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +static const ddsrt_avl_node_t *lookup_succeq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { - const ut_avlNode_t *tmp = tree->root; - const ut_avlNode_t *cand = NULL; + const ddsrt_avl_node_t *tmp = tree->root; + const ddsrt_avl_node_t *cand = NULL; int c; while (tmp && (c = comparenk (td, tmp, key)) != 0) { if (c > 0) { @@ -737,12 +737,12 @@ static const ut_avlNode_t *lookup_succeq (const ut_avlTreedef_t *td, const ut_av return fixup_predsucceq (td, key, tmp, cand, 1); } -static const ut_avlNode_t *fixup_predsucc (const ut_avlTreedef_t *td, const void *key, const ut_avlNode_t *tmp, const ut_avlNode_t *cand, int dir) +static const ddsrt_avl_node_t *fixup_predsucc (const ddsrt_avl_treedef_t *td, const void *key, const ddsrt_avl_node_t *tmp, const ddsrt_avl_node_t *cand, int dir) { /* dir=0: pred, dir=1: succ */ if (tmp == NULL || tmp->cs[dir] == NULL) { return cand; - } else if (!(td->flags & UT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { + } else if (!(td->flags & DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { /* No duplicates, therefore the extremum in the subtree */ tmp = tmp->cs[dir]; while (tmp->cs[1-dir]) { @@ -766,10 +766,10 @@ static const ut_avlNode_t *fixup_predsucc (const ut_avlTreedef_t *td, const void } } -static const ut_avlNode_t *lookup_pred (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +static const ddsrt_avl_node_t *lookup_pred (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { - const ut_avlNode_t *tmp = tree->root; - const ut_avlNode_t *cand = NULL; + const ddsrt_avl_node_t *tmp = tree->root; + const ddsrt_avl_node_t *cand = NULL; int c; while (tmp && (c = comparenk (td, tmp, key)) != 0) { if (c < 0) { @@ -782,10 +782,10 @@ static const ut_avlNode_t *lookup_pred (const ut_avlTreedef_t *td, const ut_avlT return fixup_predsucc (td, key, tmp, cand, 0); } -static const ut_avlNode_t *lookup_succ (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +static const ddsrt_avl_node_t *lookup_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { - const ut_avlNode_t *tmp = tree->root; - const ut_avlNode_t *cand = NULL; + const ddsrt_avl_node_t *tmp = tree->root; + const ddsrt_avl_node_t *cand = NULL; int c; while (tmp && (c = comparenk (td, tmp, key)) != 0) { if (c > 0) { @@ -798,43 +798,43 @@ static const ut_avlNode_t *lookup_succ (const ut_avlTreedef_t *td, const ut_avlT return fixup_predsucc (td, key, tmp, cand, 1); } -void *ut_avlLookupSuccEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +void *ddsrt_avl_lookup_succ_eq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { return (void *) conode_from_node (td, lookup_succeq (td, tree, key)); } -void *ut_avlLookupPredEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +void *ddsrt_avl_lookup_pred_eq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { return (void *) conode_from_node (td, lookup_predeq (td, tree, key)); } -void *ut_avlLookupSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +void *ddsrt_avl_lookup_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { return (void *) conode_from_node (td, lookup_succ (td, tree, key)); } -void *ut_avlLookupPred (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +void *ddsrt_avl_lookup_pred (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { return (void *) conode_from_node (td, lookup_pred (td, tree, key)); } -void *ut_avlIterSuccEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlIter_t *iter, const void *key) +void *ddsrt_avl_iter_succ_eq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_iter_t *iter, const void *key) { - const ut_avlNode_t *tmp = tree->root; + const ddsrt_avl_node_t *tmp = tree->root; int c; iter->td = td; iter->todop = iter->todo; while (tmp && (c = comparenk (td, tmp, key)) != 0) { if (c > 0) { - *++iter->todop = (ut_avlNode_t *) tmp; + *++iter->todop = (ddsrt_avl_node_t *) tmp; tmp = tmp->cs[0]; } else { tmp = tmp->cs[1]; } } if (tmp != NULL) { - *++iter->todop = (ut_avlNode_t *) tmp; - if (td->flags & UT_AVL_TREEDEF_FLAG_ALLOWDUPS) { + *++iter->todop = (ddsrt_avl_node_t *) tmp; + if (td->flags & DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS) { /* key exists - but it there's no guarantee we hit the first one in the in-order enumeration of the tree */ tmp = tmp->cs[0]; @@ -842,7 +842,7 @@ void *ut_avlIterSuccEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_ if (comparenk (td, tmp, key) != 0) { tmp = tmp->cs[1]; } else { - *++iter->todop = (ut_avlNode_t *) tmp; + *++iter->todop = (ddsrt_avl_node_t *) tmp; tmp = tmp->cs[0]; } } @@ -856,26 +856,26 @@ void *ut_avlIterSuccEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_ } } -void *ut_avlIterSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlIter_t *iter, const void *key) +void *ddsrt_avl_iter_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_iter_t *iter, const void *key) { - const ut_avlNode_t *tmp = tree->root; + const ddsrt_avl_node_t *tmp = tree->root; int c; iter->td = td; iter->todop = iter->todo; while (tmp && (c = comparenk (td, tmp, key)) != 0) { if (c > 0) { - *++iter->todop = (ut_avlNode_t *) tmp; + *++iter->todop = (ddsrt_avl_node_t *) tmp; tmp = tmp->cs[0]; } else { tmp = tmp->cs[1]; } } if (tmp != NULL) { - if (!(td->flags & UT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { + if (!(td->flags & DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { tmp = tmp->cs[1]; if (tmp) { do { - *++iter->todop = (ut_avlNode_t *) tmp; + *++iter->todop = (ddsrt_avl_node_t *) tmp; tmp = tmp->cs[0]; } while (tmp); } @@ -883,7 +883,7 @@ void *ut_avlIterSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_av tmp = tmp->cs[1]; while (tmp) { if (comparenk (td, tmp, key) != 0) { - *++iter->todop = (ut_avlNode_t *) tmp; + *++iter->todop = (ddsrt_avl_node_t *) tmp; tmp = tmp->cs[0]; } else { tmp = tmp->cs[1]; @@ -899,10 +899,10 @@ void *ut_avlIterSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_av } } -void ut_avlWalkRange (const ut_avlTreedef_t *td, ut_avlTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) +void ddsrt_avl_walk_range (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) { - ut_avlNode_t *n, *nn; - n = (ut_avlNode_t *) lookup_succeq (td, tree, min); + ddsrt_avl_node_t *n, *nn; + n = (ddsrt_avl_node_t *) lookup_succeq (td, tree, min); while (n && comparenk (td, n, max) <= 0) { nn = find_neighbour (n, 1); f (onode_from_node (td, n), a); @@ -910,15 +910,15 @@ void ut_avlWalkRange (const ut_avlTreedef_t *td, ut_avlTree_t *tree, const void } } -void ut_avlConstWalkRange (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) +void ddsrt_avl_const_walk_range (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) { - ut_avlWalkRange (td, (ut_avlTree_t *) tree, min, max, (ut_avlWalk_t) f, a); + ddsrt_avl_walk_range (td, (ddsrt_avl_tree_t *) tree, min, max, (ddsrt_avl_walk_t) f, a); } -void ut_avlWalkRangeReverse (const ut_avlTreedef_t *td, ut_avlTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) +void ddsrt_avl_walk_range_reverse (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) { - ut_avlNode_t *n, *nn; - n = (ut_avlNode_t *) lookup_predeq (td, tree, max); + ddsrt_avl_node_t *n, *nn; + n = (ddsrt_avl_node_t *) lookup_predeq (td, tree, max); while (n && comparenk (td, n, min) >= 0) { nn = find_neighbour (n, 0); f (onode_from_node (td, n), a); @@ -926,17 +926,17 @@ void ut_avlWalkRangeReverse (const ut_avlTreedef_t *td, ut_avlTree_t *tree, cons } } -void ut_avlConstWalkRangeReverse (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) +void ddsrt_avl_const_walk_range_reverse (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) { - ut_avlWalkRangeReverse (td, (ut_avlTree_t *) tree, min, max, (ut_avlWalk_t) f, a); + ddsrt_avl_walk_range_reverse (td, (ddsrt_avl_tree_t *) tree, min, max, (ddsrt_avl_walk_t) f, a); } -void *ut_avlRoot (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) +void *ddsrt_avl_root (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) { return (void *) conode_from_node (td, tree->root); } -void *ut_avlRootNonEmpty (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) +void *ddsrt_avl_root_non_empty (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) { assert (tree->root); return (void *) conode_from_node (td, tree->root); @@ -948,201 +948,201 @@ void *ut_avlRootNonEmpty (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) **** **************************************************************************************/ -void ut_avlCTreedefInit (ut_avlCTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_t comparekk, ut_avlAugment_t augment, uint32_t flags) +void ddsrt_avl_ctreedef_init (ddsrt_avl_ctreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_t comparekk, ddsrt_avl_augment_t augment, uint32_t flags) { treedef_init_common (&td->t, avlnodeoffset, keyoffset, augment, flags); td->t.u.comparekk = comparekk; } -void ut_avlCTreedefInit_r (ut_avlCTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_r_t comparekk_r, void *cmp_arg, ut_avlAugment_t augment, uint32_t flags) +void ddsrt_avl_ctreedef_init_r (ddsrt_avl_ctreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_r_t comparekk_r, void *cmp_arg, ddsrt_avl_augment_t augment, uint32_t flags) { - treedef_init_common (&td->t, avlnodeoffset, keyoffset, augment, flags | UT_AVL_TREEDEF_FLAG_R); + treedef_init_common (&td->t, avlnodeoffset, keyoffset, augment, flags | DDSRT_AVL_TREEDEF_FLAG_R); td->t.cmp_arg = cmp_arg; td->t.u.comparekk_r = comparekk_r; } -void ut_avlCInit (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree) +void ddsrt_avl_cinit (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree) { - ut_avlInit (&td->t, &tree->t); + ddsrt_avl_init (&td->t, &tree->t); tree->count = 0; } -void ut_avlCFree (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void (*freefun) (void *node)) +void ddsrt_avl_cfree (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void (*freefun) (void *node)) { tree->count = 0; - ut_avlFree (&td->t, &tree->t, freefun); + ddsrt_avl_free (&td->t, &tree->t, freefun); } -void ut_avlCFreeArg (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void (*freefun) (void *node, void *arg), void *arg) +void ddsrt_avl_cfree_arg (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void (*freefun) (void *node, void *arg), void *arg) { tree->count = 0; - ut_avlFreeArg (&td->t, &tree->t, freefun, arg); + ddsrt_avl_free_arg (&td->t, &tree->t, freefun, arg); } -void *ut_avlCRoot (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) +void *ddsrt_avl_croot (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) { - return ut_avlRoot (&td->t, &tree->t); + return ddsrt_avl_root (&td->t, &tree->t); } -void *ut_avlCRootNonEmpty (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) +void *ddsrt_avl_croot_non_empty (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) { - return ut_avlRootNonEmpty (&td->t, &tree->t); + return ddsrt_avl_root_non_empty (&td->t, &tree->t); } -void *ut_avlCLookup (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) +void *ddsrt_avl_clookup (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) { - return ut_avlLookup (&td->t, &tree->t, key); + return ddsrt_avl_lookup (&td->t, &tree->t, key); } -void *ut_avlCLookupIPath (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key, ut_avlIPath_t *path) +void *ddsrt_avl_clookup_ipath (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key, ddsrt_avl_ipath_t *path) { - return ut_avlLookupIPath (&td->t, &tree->t, key, path); + return ddsrt_avl_lookup_ipath (&td->t, &tree->t, key, path); } -void *ut_avlCLookupDPath (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key, ut_avlDPath_t *path) +void *ddsrt_avl_clookup_dpath (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key, ddsrt_avl_dpath_t *path) { - return ut_avlLookupDPath (&td->t, &tree->t, key, path); + return ddsrt_avl_lookup_dpath (&td->t, &tree->t, key, path); } -void *ut_avlCLookupPredEq (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) +void *ddsrt_avl_clookup_pred_eq (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) { - return ut_avlLookupPredEq (&td->t, &tree->t, key); + return ddsrt_avl_lookup_pred_eq (&td->t, &tree->t, key); } -void *ut_avlCLookupSuccEq (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) +void *ddsrt_avl_clookup_succ_eq (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) { - return ut_avlLookupSuccEq (&td->t, &tree->t, key); + return ddsrt_avl_lookup_succ_eq (&td->t, &tree->t, key); } -void *ut_avlCLookupPred (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) +void *ddsrt_avl_clookup_pred (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) { - return ut_avlLookupPred (&td->t, &tree->t, key); + return ddsrt_avl_lookup_pred (&td->t, &tree->t, key); } -void *ut_avlCLookupSucc (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) +void *ddsrt_avl_clookup_succ (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) { - return ut_avlLookupSucc (&td->t, &tree->t, key); + return ddsrt_avl_lookup_succ (&td->t, &tree->t, key); } -void ut_avlCInsert (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node) +void ddsrt_avl_cinsert (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node) { tree->count++; - ut_avlInsert (&td->t, &tree->t, node); + ddsrt_avl_insert (&td->t, &tree->t, node); } -void ut_avlCDelete (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node) +void ddsrt_avl_cdelete (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node) { assert (tree->count > 0); tree->count--; - ut_avlDelete (&td->t, &tree->t, node); + ddsrt_avl_delete (&td->t, &tree->t, node); } -void ut_avlCInsertIPath (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node, ut_avlIPath_t *path) +void ddsrt_avl_cinsert_ipath (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node, ddsrt_avl_ipath_t *path) { tree->count++; - ut_avlInsertIPath (&td->t, &tree->t, node, path); + ddsrt_avl_insert_ipath (&td->t, &tree->t, node, path); } -void ut_avlCDeleteDPath (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node, ut_avlDPath_t *path) +void ddsrt_avl_cdelete_dpath (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node, ddsrt_avl_dpath_t *path) { assert (tree->count > 0); tree->count--; - ut_avlDeleteDPath (&td->t, &tree->t, node, path); + ddsrt_avl_delete_dpath (&td->t, &tree->t, node, path); } -void ut_avlCSwapNode (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *old, void *new) +void ddsrt_avl_cswap_node (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *old, void *new) { - ut_avlSwapNode (&td->t, &tree->t, old, new); + ddsrt_avl_swap_node (&td->t, &tree->t, old, new); } -void ut_avlCAugmentUpdate (const ut_avlCTreedef_t *td, void *node) +void ddsrt_avl_caugment_update (const ddsrt_avl_ctreedef_t *td, void *node) { - ut_avlAugmentUpdate (&td->t, node); + ddsrt_avl_augment_update (&td->t, node); } -int ut_avlCIsEmpty (const ut_avlCTree_t *tree) +int ddsrt_avl_cis_empty (const ddsrt_avl_ctree_t *tree) { - return ut_avlIsEmpty (&tree->t); + return ddsrt_avl_is_empty (&tree->t); } -int ut_avlCIsSingleton (const ut_avlCTree_t *tree) +int ddsrt_avl_cis_singleton (const ddsrt_avl_ctree_t *tree) { - return ut_avlIsSingleton (&tree->t); + return ddsrt_avl_is_singleton (&tree->t); } -size_t ut_avlCCount (const ut_avlCTree_t *tree) +size_t ddsrt_avl_ccount (const ddsrt_avl_ctree_t *tree) { return tree->count; } -void *ut_avlCFindMin (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) +void *ddsrt_avl_cfind_min (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) { - return ut_avlFindMin (&td->t, &tree->t); + return ddsrt_avl_find_min (&td->t, &tree->t); } -void *ut_avlCFindMax (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) +void *ddsrt_avl_cfind_max (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) { - return ut_avlFindMax (&td->t, &tree->t); + return ddsrt_avl_find_max (&td->t, &tree->t); } -void *ut_avlCFindPred (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *vnode) +void *ddsrt_avl_cfind_pred (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *vnode) { - return ut_avlFindPred (&td->t, &tree->t, vnode); + return ddsrt_avl_find_pred (&td->t, &tree->t, vnode); } -void *ut_avlCFindSucc (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *vnode) +void *ddsrt_avl_cfind_succ (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *vnode) { - return ut_avlFindSucc (&td->t, &tree->t, vnode); + return ddsrt_avl_find_succ (&td->t, &tree->t, vnode); } -void ut_avlCWalk (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, ut_avlWalk_t f, void *a) +void ddsrt_avl_cwalk (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, ddsrt_avl_walk_t f, void *a) { - ut_avlWalk (&td->t, &tree->t, f, a); + ddsrt_avl_walk (&td->t, &tree->t, f, a); } -void ut_avlCConstWalk (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlConstWalk_t f, void *a) +void ddsrt_avl_cconst_walk (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_const_walk_t f, void *a) { - ut_avlConstWalk (&td->t, &tree->t, f, a); + ddsrt_avl_const_walk (&td->t, &tree->t, f, a); } -void ut_avlCWalkRange (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) +void ddsrt_avl_cwalk_range (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) { - ut_avlWalkRange (&td->t, &tree->t, min, max, f, a); + ddsrt_avl_walk_range (&td->t, &tree->t, min, max, f, a); } -void ut_avlCConstWalkRange (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) +void ddsrt_avl_cconst_walk_range (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) { - ut_avlConstWalkRange (&td->t, &tree->t, min, max, f, a); + ddsrt_avl_const_walk_range (&td->t, &tree->t, min, max, f, a); } -void ut_avlCWalkRangeReverse (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) +void ddsrt_avl_cwalk_range_reverse (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) { - ut_avlWalkRangeReverse (&td->t, &tree->t, min, max, f, a); + ddsrt_avl_walk_range_reverse (&td->t, &tree->t, min, max, f, a); } -void ut_avlCConstWalkRangeReverse (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) +void ddsrt_avl_cconst_walk_range_reverse (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) { - ut_avlConstWalkRangeReverse (&td->t, &tree->t, min, max, f, a); + ddsrt_avl_const_walk_range_reverse (&td->t, &tree->t, min, max, f, a); } -void *ut_avlCIterFirst (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlCIter_t *iter) +void *ddsrt_avl_citer_first (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_citer_t *iter) { - return ut_avlIterFirst (&td->t, &tree->t, &iter->t); + return ddsrt_avl_iter_first (&td->t, &tree->t, &iter->t); } -void *ut_avlCIterSuccEq (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlCIter_t *iter, const void *key) +void *ddsrt_avl_citer_succ_eq (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_citer_t *iter, const void *key) { - return ut_avlIterSuccEq (&td->t, &tree->t, &iter->t, key); + return ddsrt_avl_iter_succ_eq (&td->t, &tree->t, &iter->t, key); } -void *ut_avlCIterSucc (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlCIter_t *iter, const void *key) +void *ddsrt_avl_citer_succ (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_citer_t *iter, const void *key) { - return ut_avlIterSucc (&td->t, &tree->t, &iter->t, key); + return ddsrt_avl_iter_succ (&td->t, &tree->t, &iter->t, key); } -void *ut_avlCIterNext (ut_avlCIter_t *iter) +void *ddsrt_avl_citer_next (ddsrt_avl_citer_t *iter) { /* Added this in-between t variable to satisfy SAL. */ - ut_avlIter_t *t = &(iter->t); - return ut_avlIterNext(t); + ddsrt_avl_iter_t *t = &(iter->t); + return ddsrt_avl_iter_next(t); } diff --git a/src/util/src/ut_expand_envvars.c b/src/ddsrt/src/expand_envvars.c similarity index 93% rename from src/util/src/ut_expand_envvars.c rename to src/ddsrt/src/expand_envvars.c index 3b2b999..ded0d0a 100644 --- a/src/util/src/ut_expand_envvars.c +++ b/src/ddsrt/src/expand_envvars.c @@ -19,7 +19,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" #include "dds/ddsrt/string.h" -#include "dds/util/ut_expand_envvars.h" +#include "dds/ddsrt/expand_envvars.h" typedef char * (*expand_fn)(const char *src0); @@ -157,7 +157,7 @@ static char *expand_envchar (const char **src, expand_fn expand) return expand_env (name, 0, NULL, expand); } -char *ut_expand_envvars_sh (const char *src0) +char *ddsrt_expand_envvars_sh (const char *src0) { /* Expands $X, ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms; $ and \ can be escaped with \ */ const char *src = src0; @@ -180,11 +180,11 @@ char *ut_expand_envvars_sh (const char *src0) ddsrt_free(dst); return NULL; } else if (*src == '{') { - x = expand_envbrace (&src, &ut_expand_envvars_sh); + x = expand_envbrace (&src, &ddsrt_expand_envvars_sh); } else if (isalnum ((unsigned char) *src) || *src == '_') { - x = expand_envsimple (&src, &ut_expand_envvars_sh); + x = expand_envsimple (&src, &ddsrt_expand_envvars_sh); } else { - x = expand_envchar (&src, &ut_expand_envvars_sh); + x = expand_envchar (&src, &ddsrt_expand_envvars_sh); } if (x == NULL) { ddsrt_free(dst); @@ -203,7 +203,7 @@ char *ut_expand_envvars_sh (const char *src0) return dst; } -char *ut_expand_envvars (const char *src0) +char *ddsrt_expand_envvars (const char *src0) { /* Expands ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, but not $X */ const char *src = src0; @@ -213,7 +213,7 @@ char *ut_expand_envvars (const char *src0) if (*src == '$' && *(src + 1) == '{') { char *x, *xp; src++; - x = expand_envbrace (&src, &ut_expand_envvars); + x = expand_envbrace (&src, &ddsrt_expand_envvars); if (x == NULL) { ddsrt_free(dst); return NULL; diff --git a/src/util/src/ut_fibheap.c b/src/ddsrt/src/fibheap.c similarity index 68% rename from src/util/src/ut_fibheap.c rename to src/ddsrt/src/fibheap.c index a92d186..2e3bcf8 100644 --- a/src/util/src/ut_fibheap.c +++ b/src/ddsrt/src/fibheap.c @@ -14,7 +14,7 @@ #include #include "dds/ddsrt/misc.h" -#include "dds/util/ut_fibheap.h" +#include "dds/ddsrt/fibheap.h" /* max degree: n >= F_{d+2} >= \phi^d ==> d <= log_\phi n, where \phi (as usual) is the golden ratio ~= 1.618. We know n <= (size of @@ -23,24 +23,24 @@ space). */ #define MAX_DEGREE ((unsigned) (sizeof (void *) * CHAR_BIT - 1)) -static int cmp (const ut_fibheapDef_t *fhdef, const ut_fibheapNode_t *a, const ut_fibheapNode_t *b) +static int cmp (const ddsrt_fibheap_def_t *fhdef, const ddsrt_fibheap_node_t *a, const ddsrt_fibheap_node_t *b) { return fhdef->cmp ((const char *) a - fhdef->offset, (const char *) b - fhdef->offset); } -void ut_fibheapDefInit (ut_fibheapDef_t *fhdef, uintptr_t offset, int (*cmp) (const void *va, const void *vb)) +void ddsrt_fibheap_def_init (ddsrt_fibheap_def_t *fhdef, uintptr_t offset, int (*cmp) (const void *va, const void *vb)) { fhdef->offset = offset; fhdef->cmp = cmp; } -void ut_fibheapInit (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) +void ddsrt_fibheap_init (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh) { DDSRT_UNUSED_ARG(fhdef); fh->roots = NULL; } -void *ut_fibheapMin (const ut_fibheapDef_t *fhdef, const ut_fibheap_t *fh) +void *ddsrt_fibheap_min (const ddsrt_fibheap_def_t *fhdef, const ddsrt_fibheap_t *fh) { if (fh->roots) { return (void *) ((char *) fh->roots - fhdef->offset); @@ -49,16 +49,16 @@ void *ut_fibheapMin (const ut_fibheapDef_t *fhdef, const ut_fibheap_t *fh) } } -static void ut_fibheap_merge_nonempty_list (ut_fibheapNode_t **markptr, ut_fibheapNode_t *list) +static void ddsrt_fibheap_merge_nonempty_list (ddsrt_fibheap_node_t **markptr, ddsrt_fibheap_node_t *list) { assert (list != NULL); if (*markptr == NULL) { *markptr = list; } else { - ut_fibheapNode_t * const mark = *markptr; - ut_fibheapNode_t * const old_mark_next = mark->next; - ut_fibheapNode_t * const old_list_prev = list->prev; + ddsrt_fibheap_node_t * const mark = *markptr; + ddsrt_fibheap_node_t * const old_mark_next = mark->next; + ddsrt_fibheap_node_t * const old_list_prev = list->prev; mark->next = list; old_mark_next->prev = old_list_prev; list->prev = mark; @@ -66,7 +66,7 @@ static void ut_fibheap_merge_nonempty_list (ut_fibheapNode_t **markptr, ut_fibhe } } -static void ut_fibheap_merge_into (const ut_fibheapDef_t *fhdef, ut_fibheap_t *a, ut_fibheapNode_t * const br) +static void ddsrt_fibheap_merge_into (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *a, ddsrt_fibheap_node_t * const br) { if (br == NULL) { return; @@ -74,25 +74,25 @@ static void ut_fibheap_merge_into (const ut_fibheapDef_t *fhdef, ut_fibheap_t *a a->roots = br; } else { const int c = cmp (fhdef, br, a->roots); - ut_fibheap_merge_nonempty_list (&a->roots, br); + ddsrt_fibheap_merge_nonempty_list (&a->roots, br); if (c < 0) a->roots = br; } } -void ut_fibheapMerge (const ut_fibheapDef_t *fhdef, ut_fibheap_t *a, ut_fibheap_t *b) +void ddsrt_fibheap_merge (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *a, ddsrt_fibheap_t *b) { /* merges nodes from b into a, thereafter, b is empty */ - ut_fibheap_merge_into (fhdef, a, b->roots); + ddsrt_fibheap_merge_into (fhdef, a, b->roots); b->roots = NULL; } -void ut_fibheapInsert (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const void *vnode) +void ddsrt_fibheap_insert (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh, const void *vnode) { /* fibheap node is opaque => nothing in node changes as far as caller is concerned => declare as const argument, then drop the const qualifier */ - ut_fibheapNode_t *node = (ut_fibheapNode_t *) ((char *) vnode + fhdef->offset); + ddsrt_fibheap_node_t *node = (ddsrt_fibheap_node_t *) ((char *) vnode + fhdef->offset); /* new heap of degree 0 (i.e., only containing NODE) */ node->parent = node->children = NULL; @@ -101,24 +101,24 @@ void ut_fibheapInsert (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const voi node->degree = 0; /* then merge it in */ - ut_fibheap_merge_into (fhdef, fh, node); + ddsrt_fibheap_merge_into (fhdef, fh, node); } -static void ut_fibheap_add_as_child (ut_fibheapNode_t *parent, ut_fibheapNode_t *child) +static void ddsrt_fibheap_add_as_child (ddsrt_fibheap_node_t *parent, ddsrt_fibheap_node_t *child) { parent->degree++; child->parent = parent; child->prev = child->next = child; - ut_fibheap_merge_nonempty_list (&parent->children, child); + ddsrt_fibheap_merge_nonempty_list (&parent->children, child); } -static void ut_fibheap_delete_one_from_list (ut_fibheapNode_t **markptr, ut_fibheapNode_t *node) +static void ddsrt_fibheap_delete_one_from_list (ddsrt_fibheap_node_t **markptr, ddsrt_fibheap_node_t *node) { if (node->next == node) { *markptr = NULL; } else { - ut_fibheapNode_t * const node_prev = node->prev; - ut_fibheapNode_t * const node_next = node->next; + ddsrt_fibheap_node_t * const node_prev = node->prev; + ddsrt_fibheap_node_t * const node_next = node->next; node_prev->next = node_next; node_next->prev = node_prev; if (*markptr == node) { @@ -127,10 +127,10 @@ static void ut_fibheap_delete_one_from_list (ut_fibheapNode_t **markptr, ut_fibh } } -void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) +void *ddsrt_fibheap_extract_min (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh) { - ut_fibheapNode_t *roots[MAX_DEGREE + 1]; - ut_fibheapNode_t * const min = fh->roots; + ddsrt_fibheap_node_t *roots[MAX_DEGREE + 1]; + ddsrt_fibheap_node_t * const min = fh->roots; unsigned min_degree_noninit = 0; /* empty heap => return that, alternative would be to require the @@ -147,7 +147,7 @@ void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) } /* remove min from fh->roots */ - ut_fibheap_delete_one_from_list (&fh->roots, min); + ddsrt_fibheap_delete_one_from_list (&fh->roots, min); /* FIXME: can speed up by combining a few things & improving locality of reference by scanning lists only once */ @@ -155,30 +155,30 @@ void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) /* insert min'schildren as new roots -- must fix parent pointers, and reset marks because roots are always unmarked */ if (min->children) { - ut_fibheapNode_t * const mark = min->children; - ut_fibheapNode_t *n = mark; + ddsrt_fibheap_node_t * const mark = min->children; + ddsrt_fibheap_node_t *n = mark; do { n->parent = NULL; n->mark = 0; n = n->next; } while (n != mark); - ut_fibheap_merge_nonempty_list (&fh->roots, min->children); + ddsrt_fibheap_merge_nonempty_list (&fh->roots, min->children); } /* iteratively merge roots of equal degree, completely messing up fh->roots, ... */ { - ut_fibheapNode_t *const mark = fh->roots; - ut_fibheapNode_t *n = mark; + ddsrt_fibheap_node_t *const mark = fh->roots; + ddsrt_fibheap_node_t *n = mark; do { - ut_fibheapNode_t * const n1 = n->next; + ddsrt_fibheap_node_t * const n1 = n->next; /* if n is first root with this high a degree, there's certainly not going to be another root to merge with yet */ while (n->degree < min_degree_noninit && roots[n->degree]) { unsigned const degree = n->degree; - ut_fibheapNode_t *u, *v; + ddsrt_fibheap_node_t *u, *v; if (cmp (fhdef, roots[degree], n) < 0) { u = roots[degree]; v = n; @@ -186,7 +186,7 @@ void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) u = n; v = roots[degree]; } roots[degree] = NULL; - ut_fibheap_add_as_child (u, v); + ddsrt_fibheap_add_as_child (u, v); n = u; } @@ -206,7 +206,7 @@ void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) memory at an astonishing rate, and we need to compare the root keys anyway to find the minimum */ { - ut_fibheapNode_t *mark, *cursor, *newmin; + ddsrt_fibheap_node_t *mark, *cursor, *newmin; unsigned i; for (i = 0; roots[i] == NULL; i++) { assert (i+1 < min_degree_noninit); @@ -216,7 +216,7 @@ void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) mark = cursor = roots[i]; for (++i; i < min_degree_noninit; i++) { if (roots[i]) { - ut_fibheapNode_t * const r = roots[i]; + ddsrt_fibheap_node_t * const r = roots[i]; if (cmp (fhdef, r, newmin) < 0) newmin = r; r->prev = cursor; @@ -233,17 +233,17 @@ void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) return (void *) ((char *) min - fhdef->offset); } -static void ut_fibheap_cutnode (ut_fibheap_t *fh, ut_fibheapNode_t *node) +static void ddsrt_fibheap_cutnode (ddsrt_fibheap_t *fh, ddsrt_fibheap_node_t *node) { /* by marking the node, we ensure it gets cut */ node->mark = 1; /* traverse towards the root, cutting marked nodes on the way */ while (node->parent && node->mark) { - ut_fibheapNode_t *parent = node->parent; + ddsrt_fibheap_node_t *parent = node->parent; assert (parent->degree > 0); - ut_fibheap_delete_one_from_list (&parent->children, node); + ddsrt_fibheap_delete_one_from_list (&parent->children, node); parent->degree--; node->mark = 0; @@ -252,7 +252,7 @@ static void ut_fibheap_cutnode (ut_fibheap_t *fh, ut_fibheapNode_t *node) /* we assume heap properties haven't been violated, and therefore none of the nodes we cut can become the new minimum */ - ut_fibheap_merge_nonempty_list (&fh->roots, node); + ddsrt_fibheap_merge_nonempty_list (&fh->roots, node); node = parent; } @@ -264,12 +264,12 @@ static void ut_fibheap_cutnode (ut_fibheap_t *fh, ut_fibheapNode_t *node) } } -void ut_fibheapDecreaseKey (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const void *vnode) +void ddsrt_fibheap_decrease_key (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh, const void *vnode) { /* fibheap node is opaque => nothing in node changes as far as caller is concerned => declare as const argument, then drop the const qualifier */ - ut_fibheapNode_t *node = (ut_fibheapNode_t *) ((char *) vnode + fhdef->offset); + ddsrt_fibheap_node_t *node = (ddsrt_fibheap_node_t *) ((char *) vnode + fhdef->offset); if (node->parent && cmp (fhdef, node->parent, node) <= 0) { /* heap property not violated, do nothing */ @@ -278,7 +278,7 @@ void ut_fibheapDecreaseKey (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, cons /* heap property violated by decreasing the key, but we cut it pretending nothing has happened yet, then fix up the minimum if this node is the new minimum */ - ut_fibheap_cutnode (fh, node); + ddsrt_fibheap_cutnode (fh, node); } if (cmp (fhdef, node, fh->roots) < 0) { fh->roots = node; @@ -286,19 +286,19 @@ void ut_fibheapDecreaseKey (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, cons } } -void ut_fibheapDelete (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const void *vnode) +void ddsrt_fibheap_delete (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh, const void *vnode) { /* fibheap node is opaque => nothing in node changes as far as caller is concerned => declare as const argument, then drop the const qualifier */ - ut_fibheapNode_t *node = (ut_fibheapNode_t *) ((char *) vnode + fhdef->offset); + ddsrt_fibheap_node_t *node = (ddsrt_fibheap_node_t *) ((char *) vnode + fhdef->offset); /* essentially decreasekey(node);extractmin while pretending the node key is -infinity. That means we can't directly call decreasekey, because it considers the actual value of the key. */ if (node->parent != NULL) { - ut_fibheap_cutnode (fh, node); + ddsrt_fibheap_cutnode (fh, node); } fh->roots = node; - (void) ut_fibheapExtractMin (fhdef, fh); + (void) ddsrt_fibheap_extract_min (fhdef, fh); } diff --git a/src/util/src/ut_hopscotch.c b/src/ddsrt/src/hopscotch.c similarity index 67% rename from src/util/src/ut_hopscotch.c rename to src/ddsrt/src/hopscotch.c index 276c9cb..eef7efb 100644 --- a/src/util/src/ut_hopscotch.c +++ b/src/ddsrt/src/hopscotch.c @@ -15,7 +15,7 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_hopscotch.h" +#include "dds/ddsrt/hopscotch.h" #define HH_HOP_RANGE 32 #define HH_ADD_RANGE 64 @@ -27,45 +27,45 @@ #define N_BACKING_LOCKS 32 #define N_RESIZE_LOCKS 8 -struct ut_chhBucket { +struct ddsrt_chh_bucket { ddsrt_atomic_uint32_t hopinfo; ddsrt_atomic_uint32_t timestamp; ddsrt_atomic_uint32_t lock; ddsrt_atomic_voidp_t data; }; -struct ut_chhBucketArray { +struct ddsrt_chh_bucket_array { uint32_t size; /* power of 2 */ - struct ut_chhBucket bs[]; + struct ddsrt_chh_bucket bs[]; }; -struct ut_chhBackingLock { +struct ddsrt_chh_backing_lock { ddsrt_mutex_t lock; ddsrt_cond_t cv; }; -struct ut_chh { - ddsrt_atomic_voidp_t buckets; /* struct ut_chhBucketArray * */ - struct ut_chhBackingLock backingLocks[N_BACKING_LOCKS]; - ut_hhHash_fn hash; - ut_hhEquals_fn equals; +struct ddsrt_chh { + ddsrt_atomic_voidp_t buckets; /* struct ddsrt_chh_bucket_array * */ + struct ddsrt_chh_backing_lock backingLocks[N_BACKING_LOCKS]; + ddsrt_hh_hash_fn hash; + ddsrt_hh_equals_fn equals; ddsrt_rwlock_t resize_locks[N_RESIZE_LOCKS]; - ut_hhBucketsGc_fn gc_buckets; + ddsrt_hh_buckets_gc_fn gc_buckets; }; #define CHH_MAX_TRIES 4 #define CHH_BUSY ((void *) 1) -static int ut_chhDataValid_p (void *data) +static int ddsrt_chh_data_valid_p (void *data) { return data != NULL && data != CHH_BUSY; } -static int ut_chhInit (struct ut_chh *rt, uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals, ut_hhBucketsGc_fn gc_buckets) +static int ddsrt_chh_init (struct ddsrt_chh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets) { uint32_t size; uint32_t i; - struct ut_chhBucketArray *buckets; + struct ddsrt_chh_bucket_array *buckets; size = HH_HOP_RANGE; while (size < init_size) { @@ -75,11 +75,11 @@ static int ut_chhInit (struct ut_chh *rt, uint32_t init_size, ut_hhHash_fn hash, rt->equals = equals; rt->gc_buckets = gc_buckets; - buckets = ddsrt_malloc (offsetof (struct ut_chhBucketArray, bs) + size * sizeof (*buckets->bs)); + buckets = ddsrt_malloc (offsetof (struct ddsrt_chh_bucket_array, bs) + size * sizeof (*buckets->bs)); ddsrt_atomic_stvoidp (&rt->buckets, buckets); buckets->size = size; for (i = 0; i < size; i++) { - struct ut_chhBucket *b = &buckets->bs[i]; + struct ddsrt_chh_bucket *b = &buckets->bs[i]; ddsrt_atomic_st32 (&b->hopinfo, 0); ddsrt_atomic_st32 (&b->timestamp, 0); ddsrt_atomic_st32 (&b->lock, 0); @@ -87,7 +87,7 @@ static int ut_chhInit (struct ut_chh *rt, uint32_t init_size, ut_hhHash_fn hash, } for (i = 0; i < N_BACKING_LOCKS; i++) { - struct ut_chhBackingLock *s = &rt->backingLocks[i]; + struct ddsrt_chh_backing_lock *s = &rt->backingLocks[i]; ddsrt_mutex_init (&s->lock); ddsrt_cond_init (&s->cv); } @@ -97,12 +97,12 @@ static int ut_chhInit (struct ut_chh *rt, uint32_t init_size, ut_hhHash_fn hash, return 0; } -static void ut_chhFini (struct ut_chh *rt) +static void ddsrt_chh_fini (struct ddsrt_chh *rt) { int i; ddsrt_free (ddsrt_atomic_ldvoidp (&rt->buckets)); for (i = 0; i < N_BACKING_LOCKS; i++) { - struct ut_chhBackingLock *s = &rt->backingLocks[i]; + struct ddsrt_chh_backing_lock *s = &rt->backingLocks[i]; ddsrt_cond_destroy (&s->cv); ddsrt_mutex_destroy (&s->lock); } @@ -111,10 +111,10 @@ static void ut_chhFini (struct ut_chh *rt) } } -struct ut_chh *ut_chhNew (uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals, ut_hhBucketsGc_fn gc_buckets) +struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets) { - struct ut_chh *hh = ddsrt_malloc (sizeof (*hh)); - if (ut_chhInit (hh, init_size, hash, equals, gc_buckets) < 0) { + struct ddsrt_chh *hh = ddsrt_malloc (sizeof (*hh)); + if (ddsrt_chh_init (hh, init_size, hash, equals, gc_buckets) < 0) { ddsrt_free (hh); return NULL; } else { @@ -122,22 +122,22 @@ struct ut_chh *ut_chhNew (uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn } } -void ut_chhFree (struct ut_chh * UT_HH_RESTRICT hh) +void ddsrt_chh_free (struct ddsrt_chh * __restrict hh) { - ut_chhFini (hh); + ddsrt_chh_fini (hh); ddsrt_free (hh); } #define LOCKBIT ((uint32_t)1 << 31) -static void ut_chhLockBucket (struct ut_chh *rt, uint32_t bidx) +static void ddsrt_chh_lock_bucket (struct ddsrt_chh *rt, uint32_t bidx) { /* Lock: MSB <=> LOCKBIT, LSBs <=> wait count; note that (o&LOCKBIT)==0 means a thread can sneak in when there are already waiters, changing it to o==0 would avoid that. */ - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const b = &bsary->bs[bidx]; - struct ut_chhBackingLock * const s = &rt->backingLocks[bidx % N_BACKING_LOCKS]; + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const b = &bsary->bs[bidx]; + struct ddsrt_chh_backing_lock * const s = &rt->backingLocks[bidx % N_BACKING_LOCKS]; uint32_t o, n; fastpath_retry: o = ddsrt_atomic_ld32 (&b->lock); @@ -162,11 +162,11 @@ static void ut_chhLockBucket (struct ut_chh *rt, uint32_t bidx) } } -static void ut_chhUnlockBucket (struct ut_chh *rt, uint32_t bidx) +static void ddsrt_chh_unlock_bucket (struct ddsrt_chh *rt, uint32_t bidx) { - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const b = &bsary->bs[bidx]; - struct ut_chhBackingLock * const s = &rt->backingLocks[bidx % N_BACKING_LOCKS]; + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const b = &bsary->bs[bidx]; + struct ddsrt_chh_backing_lock * const s = &rt->backingLocks[bidx % N_BACKING_LOCKS]; uint32_t o, n; retry: o = ddsrt_atomic_ld32 (&b->lock); @@ -190,9 +190,9 @@ static void ut_chhUnlockBucket (struct ut_chh *rt, uint32_t bidx) } } -static void *ut_chhLookupInternal (struct ut_chhBucketArray const * const bsary, ut_hhEquals_fn equals, const uint32_t bucket, const void *template) +static void *ddsrt_chh_lookup_internal (struct ddsrt_chh_bucket_array const * const bsary, ddsrt_hh_equals_fn equals, const uint32_t bucket, const void *template) { - struct ut_chhBucket const * const bs = bsary->bs; + struct ddsrt_chh_bucket const * const bs = bsary->bs; const uint32_t idxmask = bsary->size - 1; uint32_t timestamp; int try_counter = 0; @@ -205,7 +205,7 @@ static void *ut_chhLookupInternal (struct ut_chhBucketArray const * const bsary, for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) { const uint32_t bidx = (bucket + idx) & idxmask; void *data = ddsrt_atomic_ldvoidp (&bs[bidx].data); - if (ut_chhDataValid_p (data) && equals (data, template)) { + if (ddsrt_chh_data_valid_p (data) && equals (data, template)) { return data; } } @@ -218,7 +218,7 @@ static void *ut_chhLookupInternal (struct ut_chhBucketArray const * const bsary, for (idx = 0; idx < HH_HOP_RANGE; idx++) { const uint32_t bidx = (bucket + idx) & idxmask; void *data = ddsrt_atomic_ldvoidp (&bs[bidx].data); - if (ut_chhDataValid_p (data) && equals (data, template)) { + if (ddsrt_chh_data_valid_p (data) && equals (data, template)) { return data; } } @@ -232,19 +232,19 @@ static void *ut_chhLookupInternal (struct ut_chhBucketArray const * const bsary, ddsrt_atomic_st32 (var__, (expr_)); \ } while (0) -void *ut_chhLookup (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template) +void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict rt, const void * __restrict template) { - struct ut_chhBucketArray const * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket_array const * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); const uint32_t hash = rt->hash (template); const uint32_t idxmask = bsary->size - 1; const uint32_t bucket = hash & idxmask; - return ut_chhLookupInternal (bsary, rt->equals, bucket, template); + return ddsrt_chh_lookup_internal (bsary, rt->equals, bucket, template); } -static uint32_t ut_chhFindCloserFreeBucket (struct ut_chh *rt, uint32_t free_bucket, uint32_t *free_distance) +static uint32_t ddsrt_chh_find_closer_free_bucket (struct ddsrt_chh *rt, uint32_t free_bucket, uint32_t *free_distance) { - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const bs = bsary->bs; + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const bs = bsary->bs; const uint32_t idxmask = bsary->size - 1; uint32_t move_bucket, free_dist; move_bucket = (free_bucket - (HH_HOP_RANGE - 1)) & idxmask; @@ -260,7 +260,7 @@ static uint32_t ut_chhFindCloserFreeBucket (struct ut_chh *rt, uint32_t free_buc } } if (move_free_distance != NOT_A_BUCKET) { - ut_chhLockBucket (rt, move_bucket); + ddsrt_chh_lock_bucket (rt, move_bucket); if (start_hop_info == ddsrt_atomic_ld32 (&bs[move_bucket].hopinfo)) { uint32_t new_free_bucket = (move_bucket + move_free_distance) & idxmask; @@ -272,31 +272,31 @@ static uint32_t ut_chhFindCloserFreeBucket (struct ut_chh *rt, uint32_t free_buc ddsrt_atomic_rmw32_nonatomic (&bs[move_bucket].hopinfo, x, x & ~(1u << move_free_distance)); *free_distance -= free_dist - move_free_distance; - ut_chhUnlockBucket (rt, move_bucket); + ddsrt_chh_unlock_bucket (rt, move_bucket); return new_free_bucket; } - ut_chhUnlockBucket (rt, move_bucket); + ddsrt_chh_unlock_bucket (rt, move_bucket); } move_bucket = (move_bucket + 1) & idxmask; } return NOT_A_BUCKET; } -static void ut_chhResize (struct ut_chh *rt) +static void ddsrt_chh_resize (struct ddsrt_chh *rt) { /* doubles the size => bucket index gains one bit at the msb => start bucket is unchanged or moved into the added half of the set => those for which the (new) msb is 0 are guaranteed to fit, and so are those for which the (new) msb is 1 => never have to resize recursively */ - struct ut_chhBucketArray * const bsary0 = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const bs0 = bsary0->bs; - struct ut_chhBucketArray *bsary1; - struct ut_chhBucket *bs1; + struct ddsrt_chh_bucket_array * const bsary0 = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const bs0 = bsary0->bs; + struct ddsrt_chh_bucket_array *bsary1; + struct ddsrt_chh_bucket *bs1; uint32_t i, idxmask0, idxmask1; assert (bsary0->size > 0); - bsary1 = ddsrt_malloc (offsetof (struct ut_chhBucketArray, bs) + 2 * bsary0->size * sizeof (*bsary1->bs)); + bsary1 = ddsrt_malloc (offsetof (struct ddsrt_chh_bucket_array, bs) + 2 * bsary0->size * sizeof (*bsary1->bs)); bsary1->size = 2 * bsary0->size; bs1 = bsary1->bs; @@ -327,15 +327,15 @@ static void ut_chhResize (struct ut_chh *rt) rt->gc_buckets (bsary0); } -int ut_chhAdd (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data) +int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data) { const uint32_t hash = rt->hash (data); uint32_t size; ddsrt_rwlock_read (&rt->resize_locks[hash % N_RESIZE_LOCKS]); { - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const bs = bsary->bs; + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const bs = bsary->bs; uint32_t idxmask; uint32_t start_bucket, free_distance, free_bucket; @@ -343,9 +343,9 @@ int ut_chhAdd (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT da idxmask = size - 1; start_bucket = hash & idxmask; - ut_chhLockBucket (rt, start_bucket); - if (ut_chhLookupInternal (bsary, rt->equals, start_bucket, data)) { - ut_chhUnlockBucket (rt, start_bucket); + ddsrt_chh_lock_bucket (rt, start_bucket); + if (ddsrt_chh_lookup_internal (bsary, rt->equals, start_bucket, data)) { + ddsrt_chh_unlock_bucket (rt, start_bucket); ddsrt_rwlock_unlock (&rt->resize_locks[hash % N_RESIZE_LOCKS]); return 0; } @@ -365,77 +365,77 @@ int ut_chhAdd (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT da ddsrt_atomic_rmw32_nonatomic (&bs[start_bucket].hopinfo, x, x | (1u << free_distance)); ddsrt_atomic_fence (); ddsrt_atomic_stvoidp (&bs[free_bucket].data, (void *) data); - ut_chhUnlockBucket (rt, start_bucket); + ddsrt_chh_unlock_bucket (rt, start_bucket); ddsrt_rwlock_unlock (&rt->resize_locks[hash % N_RESIZE_LOCKS]); return 1; } - free_bucket = ut_chhFindCloserFreeBucket (rt, free_bucket, &free_distance); + free_bucket = ddsrt_chh_find_closer_free_bucket (rt, free_bucket, &free_distance); assert (free_bucket == NOT_A_BUCKET || free_bucket <= idxmask); } while (free_bucket != NOT_A_BUCKET); } - ut_chhUnlockBucket (rt, start_bucket); + ddsrt_chh_unlock_bucket (rt, start_bucket); } ddsrt_rwlock_unlock (&rt->resize_locks[hash % N_RESIZE_LOCKS]); { int i; - struct ut_chhBucketArray *bsary1; + struct ddsrt_chh_bucket_array *bsary1; for (i = 0; i < N_RESIZE_LOCKS; i++) { ddsrt_rwlock_write (&rt->resize_locks[i]); } /* another thread may have sneaked past and grown the hash table */ bsary1 = ddsrt_atomic_ldvoidp (&rt->buckets); if (bsary1->size == size) { - ut_chhResize (rt); + ddsrt_chh_resize (rt); } for (i = 0; i < N_RESIZE_LOCKS; i++) { ddsrt_rwlock_unlock (&rt->resize_locks[i]); } } - return ut_chhAdd (rt, data); + return ddsrt_chh_add (rt, data); } -int ut_chhRemove (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template) +int ddsrt_chh_remove (struct ddsrt_chh * __restrict rt, const void * __restrict template) { const uint32_t hash = rt->hash (template); ddsrt_rwlock_read (&rt->resize_locks[hash % N_RESIZE_LOCKS]); { - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const bs = bsary->bs; + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const bs = bsary->bs; const uint32_t size = bsary->size; const uint32_t idxmask = size - 1; const uint32_t bucket = hash & idxmask; uint32_t hopinfo; uint32_t idx; - ut_chhLockBucket (rt, bucket); + ddsrt_chh_lock_bucket (rt, bucket); hopinfo = ddsrt_atomic_ld32 (&bs[bucket].hopinfo); for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) { if (hopinfo & 1) { const uint32_t bidx = (bucket + idx) & idxmask; void *data = ddsrt_atomic_ldvoidp (&bs[bidx].data); - if (ut_chhDataValid_p (data) && rt->equals (data, template)) { + if (ddsrt_chh_data_valid_p (data) && rt->equals (data, template)) { ddsrt_atomic_stvoidp (&bs[bidx].data, NULL); ddsrt_atomic_rmw32_nonatomic (&bs[bucket].hopinfo, x, x & ~(1u << idx)); - ut_chhUnlockBucket (rt, bucket); + ddsrt_chh_unlock_bucket (rt, bucket); ddsrt_rwlock_unlock (&rt->resize_locks[hash % N_RESIZE_LOCKS]); return 1; } } } - ut_chhUnlockBucket (rt, bucket); + ddsrt_chh_unlock_bucket (rt, bucket); } ddsrt_rwlock_unlock (&rt->resize_locks[hash % N_RESIZE_LOCKS]); return 0; } -void ut_chhEnumUnsafe (struct ut_chh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_arg), void *f_arg) +void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg) { - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const bs = bsary->bs; + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const bs = bsary->bs; uint32_t i; for (i = 0; i < bsary->size; i++) { void *data = ddsrt_atomic_ldvoidp (&bs[i].data); @@ -445,7 +445,7 @@ void ut_chhEnumUnsafe (struct ut_chh * UT_HH_RESTRICT rt, void (*f) (void *a, vo } } -void *ut_chhIterNext (struct ut_chhIter *it) +void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it) { uint32_t i; for (i = it->cursor; i < it->size; i++) { @@ -458,30 +458,30 @@ void *ut_chhIterNext (struct ut_chhIter *it) return NULL; } -void *ut_chhIterFirst (struct ut_chh * UT_HH_RESTRICT rt, struct ut_chhIter *it) +void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_iter *it) { - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); it->bs = bsary->bs; it->size = bsary->size; it->cursor = 0; - return ut_chhIterNext (it); + return ddsrt_chh_iter_next (it); } /************* SEQUENTIAL VERSION ***************/ -struct ut_hhBucket { +struct ddsrt_hh_bucket { uint32_t hopinfo; void *data; }; -struct ut_hh { +struct ddsrt_hh { uint32_t size; /* power of 2 */ - struct ut_hhBucket *buckets; - ut_hhHash_fn hash; - ut_hhEquals_fn equals; + struct ddsrt_hh_bucket *buckets; + ddsrt_hh_hash_fn hash; + ddsrt_hh_equals_fn equals; }; -static void ut_hhInit (struct ut_hh *rt, uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals) +static void ddsrt_hh_init (struct ddsrt_hh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals) { uint32_t size = HH_HOP_RANGE; uint32_t i; @@ -498,25 +498,25 @@ static void ut_hhInit (struct ut_hh *rt, uint32_t init_size, ut_hhHash_fn hash, } } -static void ut_hhFini (struct ut_hh *rt) +static void ddsrt_hh_fini (struct ddsrt_hh *rt) { ddsrt_free (rt->buckets); } -struct ut_hh *ut_hhNew (uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals) +struct ddsrt_hh *ddsrt_hh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals) { - struct ut_hh *hh = ddsrt_malloc (sizeof (*hh)); - ut_hhInit (hh, init_size, hash, equals); + struct ddsrt_hh *hh = ddsrt_malloc (sizeof (*hh)); + ddsrt_hh_init (hh, init_size, hash, equals); return hh; } -void ut_hhFree (struct ut_hh * UT_HH_RESTRICT hh) +void ddsrt_hh_free (struct ddsrt_hh * __restrict hh) { - ut_hhFini (hh); + ddsrt_hh_fini (hh); ddsrt_free (hh); } -static void *ut_hhLookupInternal (const struct ut_hh *rt, const uint32_t bucket, const void *template) +static void *ddsrt_hh_lookup_internal (const struct ddsrt_hh *rt, const uint32_t bucket, const void *template) { const uint32_t idxmask = rt->size - 1; uint32_t hopinfo = rt->buckets[bucket].hopinfo; @@ -530,15 +530,15 @@ static void *ut_hhLookupInternal (const struct ut_hh *rt, const uint32_t bucket, return NULL; } -void *ut_hhLookup (const struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template) +void *ddsrt_hh_lookup (const struct ddsrt_hh * __restrict rt, const void * __restrict template) { const uint32_t hash = rt->hash (template); const uint32_t idxmask = rt->size - 1; const uint32_t bucket = hash & idxmask; - return ut_hhLookupInternal (rt, bucket, template); + return ddsrt_hh_lookup_internal (rt, bucket, template); } -static uint32_t ut_hhFindCloserFreeBucket (struct ut_hh *rt, uint32_t free_bucket, uint32_t *free_distance) +static uint32_t ddsrt_hh_find_closer_free_bucket (struct ddsrt_hh *rt, uint32_t free_bucket, uint32_t *free_distance) { const uint32_t idxmask = rt->size - 1; uint32_t move_bucket, free_dist; @@ -567,9 +567,9 @@ static uint32_t ut_hhFindCloserFreeBucket (struct ut_hh *rt, uint32_t free_bucke return NOT_A_BUCKET; } -static void ut_hhResize (struct ut_hh *rt) +static void ddsrt_hh_resize (struct ddsrt_hh *rt) { - struct ut_hhBucket *bs1; + struct ddsrt_hh_bucket *bs1; uint32_t i, idxmask0, idxmask1; bs1 = ddsrt_malloc (2 * rt->size * sizeof (*rt->buckets)); @@ -599,14 +599,14 @@ static void ut_hhResize (struct ut_hh *rt) rt->buckets = bs1; } -int ut_hhAdd (struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data) +int ddsrt_hh_add (struct ddsrt_hh * __restrict rt, const void * __restrict data) { const uint32_t hash = rt->hash (data); const uint32_t idxmask = rt->size - 1; const uint32_t start_bucket = hash & idxmask; uint32_t free_distance, free_bucket; - if (ut_hhLookupInternal (rt, start_bucket, data)) { + if (ddsrt_hh_lookup_internal (rt, start_bucket, data)) { return 0; } @@ -624,16 +624,16 @@ int ut_hhAdd (struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data rt->buckets[free_bucket].data = (void *) data; return 1; } - free_bucket = ut_hhFindCloserFreeBucket (rt, free_bucket, &free_distance); + free_bucket = ddsrt_hh_find_closer_free_bucket (rt, free_bucket, &free_distance); assert (free_bucket == NOT_A_BUCKET || free_bucket <= idxmask); } while (free_bucket != NOT_A_BUCKET); } - ut_hhResize (rt); - return ut_hhAdd (rt, data); + ddsrt_hh_resize (rt); + return ddsrt_hh_add (rt, data); } -int ut_hhRemove (struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template) +int ddsrt_hh_remove (struct ddsrt_hh * __restrict rt, const void * __restrict template) { const uint32_t hash = rt->hash (template); const uint32_t idxmask = rt->size - 1; @@ -655,7 +655,7 @@ int ut_hhRemove (struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT t return 0; } -void ut_hhEnum (struct ut_hh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_arg), void *f_arg) +void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg) { uint32_t i; for (i = 0; i < rt->size; i++) { @@ -666,16 +666,16 @@ void ut_hhEnum (struct ut_hh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_ar } } -void *ut_hhIterFirst (struct ut_hh * UT_HH_RESTRICT rt, struct ut_hhIter * UT_HH_RESTRICT iter) +void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter) { iter->hh = rt; iter->cursor = 0; - return ut_hhIterNext (iter); + return ddsrt_hh_iter_next (iter); } -void *ut_hhIterNext (struct ut_hhIter * UT_HH_RESTRICT iter) +void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter) { - struct ut_hh *rt = iter->hh; + struct ddsrt_hh *rt = iter->hh; while (iter->cursor < rt->size) { void *data = rt->buckets[iter->cursor].data; iter->cursor++; @@ -688,22 +688,22 @@ void *ut_hhIterNext (struct ut_hhIter * UT_HH_RESTRICT iter) /************* SEQUENTIAL VERSION WITH EMBEDDED DATA ***************/ -struct ut_ehhBucket { +struct ddsrt_ehh_bucket { uint32_t hopinfo; uint32_t inuse; char data[]; }; -struct ut_ehh { +struct ddsrt_ehh { uint32_t size; /* power of 2 */ size_t elemsz; size_t bucketsz; char *buckets; /* ehhBucket, but embedded data messes up the layout */ - ut_hhHash_fn hash; - ut_hhEquals_fn equals; + ddsrt_hh_hash_fn hash; + ddsrt_hh_equals_fn equals; }; -static void ut_ehhInit (struct ut_ehh *rt, size_t elemsz, uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals) +static void ddsrt_ehh_init (struct ddsrt_ehh *rt, size_t elemsz, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals) { uint32_t size = HH_HOP_RANGE; uint32_t i; @@ -714,36 +714,36 @@ static void ut_ehhInit (struct ut_ehh *rt, size_t elemsz, uint32_t init_size, ut rt->equals = equals; rt->size = size; rt->elemsz = elemsz; - rt->bucketsz = sizeof (struct ut_ehhBucket) + ((elemsz+7) & ~(size_t)7); + rt->bucketsz = sizeof (struct ddsrt_ehh_bucket) + ((elemsz+7) & ~(size_t)7); rt->buckets = ddsrt_malloc (size * rt->bucketsz); for (i = 0; i < size; i++) { - struct ut_ehhBucket *b = (struct ut_ehhBucket *) (rt->buckets + i * rt->bucketsz); + struct ddsrt_ehh_bucket *b = (struct ddsrt_ehh_bucket *) (rt->buckets + i * rt->bucketsz); b->hopinfo = 0; b->inuse = 0; } } -static void ut_ehhFini (struct ut_ehh *rt) +static void ddsrt_ehh_fini (struct ddsrt_ehh *rt) { ddsrt_free (rt->buckets); } -struct ut_ehh *ut_ehhNew (size_t elemsz, uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals) +struct ddsrt_ehh *ddsrt_ehh_new (size_t elemsz, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals) { - struct ut_ehh *hh = ddsrt_malloc (sizeof (*hh)); - ut_ehhInit (hh, elemsz, init_size, hash, equals); + struct ddsrt_ehh *hh = ddsrt_malloc (sizeof (*hh)); + ddsrt_ehh_init (hh, elemsz, init_size, hash, equals); return hh; } -void ut_ehhFree (struct ut_ehh * UT_HH_RESTRICT hh) +void ddsrt_ehh_free (struct ddsrt_ehh * __restrict hh) { - ut_ehhFini (hh); + ddsrt_ehh_fini (hh); ddsrt_free (hh); } -static void *ut_ehhLookupInternal (const struct ut_ehh *rt, uint32_t bucket, const void *template) +static void *ddsrt_ehh_lookup_internal (const struct ddsrt_ehh *rt, uint32_t bucket, const void *template) { - const struct ut_ehhBucket *b = (const struct ut_ehhBucket *) (rt->buckets + bucket * rt->bucketsz); + const struct ddsrt_ehh_bucket *b = (const struct ddsrt_ehh_bucket *) (rt->buckets + bucket * rt->bucketsz); uint32_t hopinfo = b->hopinfo; if (hopinfo & 1) { @@ -758,7 +758,7 @@ static void *ut_ehhLookupInternal (const struct ut_ehh *rt, uint32_t bucket, con bucket = 0; } if (hopinfo & 1) { - b = (const struct ut_ehhBucket *) (rt->buckets + bucket * rt->bucketsz); + b = (const struct ddsrt_ehh_bucket *) (rt->buckets + bucket * rt->bucketsz); if (b->inuse && rt->equals (b->data, template)) { return (void *) b->data; } @@ -767,21 +767,21 @@ static void *ut_ehhLookupInternal (const struct ut_ehh *rt, uint32_t bucket, con return NULL; } -void *ut_ehhLookup (const struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template) +void *ddsrt_ehh_lookup (const struct ddsrt_ehh * __restrict rt, const void * __restrict template) { const uint32_t hash = rt->hash (template); const uint32_t idxmask = rt->size - 1; const uint32_t bucket = hash & idxmask; - return ut_ehhLookupInternal (rt, bucket, template); + return ddsrt_ehh_lookup_internal (rt, bucket, template); } -static uint32_t ut_ehhFindCloserFreeBucket (struct ut_ehh *rt, uint32_t free_bucket, uint32_t *free_distance) +static uint32_t ddsrt_ehh_find_closer_free_bucket (struct ddsrt_ehh *rt, uint32_t free_bucket, uint32_t *free_distance) { const uint32_t idxmask = rt->size - 1; uint32_t move_bucket, free_dist; move_bucket = (free_bucket - (HH_HOP_RANGE - 1)) & idxmask; for (free_dist = HH_HOP_RANGE - 1; free_dist > 0; free_dist--) { - struct ut_ehhBucket * const mb = (struct ut_ehhBucket *) (rt->buckets + move_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket * const mb = (struct ddsrt_ehh_bucket *) (rt->buckets + move_bucket * rt->bucketsz); uint32_t move_free_distance = NOT_A_BUCKET; uint32_t mask = 1; uint32_t i; @@ -793,8 +793,8 @@ static uint32_t ut_ehhFindCloserFreeBucket (struct ut_ehh *rt, uint32_t free_buc } if (move_free_distance != NOT_A_BUCKET) { uint32_t new_free_bucket = (move_bucket + move_free_distance) & idxmask; - struct ut_ehhBucket * const fb = (struct ut_ehhBucket *) (rt->buckets + free_bucket * rt->bucketsz); - struct ut_ehhBucket * const nfb = (struct ut_ehhBucket *) (rt->buckets + new_free_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket * const fb = (struct ddsrt_ehh_bucket *) (rt->buckets + free_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket * const nfb = (struct ddsrt_ehh_bucket *) (rt->buckets + new_free_bucket * rt->bucketsz); mb->hopinfo |= 1u << free_dist; fb->inuse = 1; memcpy (fb->data, nfb->data, rt->elemsz); @@ -808,7 +808,7 @@ static uint32_t ut_ehhFindCloserFreeBucket (struct ut_ehh *rt, uint32_t free_buc return NOT_A_BUCKET; } -static void ut_ehhResize (struct ut_ehh *rt) +static void ddsrt_ehh_resize (struct ddsrt_ehh *rt) { char *bs1; uint32_t i, idxmask0, idxmask1; @@ -816,22 +816,22 @@ static void ut_ehhResize (struct ut_ehh *rt) bs1 = ddsrt_malloc (2 * rt->size * rt->bucketsz); for (i = 0; i < 2 * rt->size; i++) { - struct ut_ehhBucket *b = (struct ut_ehhBucket *) (bs1 + i * rt->bucketsz); + struct ddsrt_ehh_bucket *b = (struct ddsrt_ehh_bucket *) (bs1 + i * rt->bucketsz); b->hopinfo = 0; b->inuse = 0; } idxmask0 = rt->size - 1; idxmask1 = 2 * rt->size - 1; for (i = 0; i < rt->size; i++) { - struct ut_ehhBucket const * const b = (struct ut_ehhBucket *) (rt->buckets + i * rt->bucketsz); + struct ddsrt_ehh_bucket const * const b = (struct ddsrt_ehh_bucket *) (rt->buckets + i * rt->bucketsz); if (b->inuse) { const uint32_t hash = rt->hash (b->data); const uint32_t old_start_bucket = hash & idxmask0; const uint32_t new_start_bucket = hash & idxmask1; const uint32_t dist = (i >= old_start_bucket) ? (i - old_start_bucket) : (rt->size + i - old_start_bucket); const uint32_t newb = (new_start_bucket + dist) & idxmask1; - struct ut_ehhBucket * const nsb = (struct ut_ehhBucket *) (bs1 + new_start_bucket * rt->bucketsz); - struct ut_ehhBucket * const nb = (struct ut_ehhBucket *) (bs1 + newb * rt->bucketsz); + struct ddsrt_ehh_bucket * const nsb = (struct ddsrt_ehh_bucket *) (bs1 + new_start_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket * const nb = (struct ddsrt_ehh_bucket *) (bs1 + newb * rt->bucketsz); assert (dist < HH_HOP_RANGE); assert (!nb->inuse); nsb->hopinfo |= 1u << dist; @@ -845,20 +845,20 @@ static void ut_ehhResize (struct ut_ehh *rt) rt->buckets = bs1; } -int ut_ehhAdd (struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data) +int ddsrt_ehh_add (struct ddsrt_ehh * __restrict rt, const void * __restrict data) { const uint32_t hash = rt->hash (data); const uint32_t idxmask = rt->size - 1; const uint32_t start_bucket = hash & idxmask; uint32_t free_distance, free_bucket; - if (ut_ehhLookupInternal (rt, start_bucket, data)) { + if (ddsrt_ehh_lookup_internal (rt, start_bucket, data)) { return 0; } free_bucket = start_bucket; for (free_distance = 0; free_distance < HH_ADD_RANGE; free_distance++) { - struct ut_ehhBucket const * const fb = (struct ut_ehhBucket *) (rt->buckets + free_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket const * const fb = (struct ddsrt_ehh_bucket *) (rt->buckets + free_bucket * rt->bucketsz); if (!fb->inuse) { break; } @@ -867,73 +867,73 @@ int ut_ehhAdd (struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT da if (free_distance < HH_ADD_RANGE) { do { if (free_distance < HH_HOP_RANGE) { - struct ut_ehhBucket * const sb = (struct ut_ehhBucket *) (rt->buckets + start_bucket * rt->bucketsz); - struct ut_ehhBucket * const fb = (struct ut_ehhBucket *) (rt->buckets + free_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket * const sb = (struct ddsrt_ehh_bucket *) (rt->buckets + start_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket * const fb = (struct ddsrt_ehh_bucket *) (rt->buckets + free_bucket * rt->bucketsz); assert ((uint32_t) free_bucket == ((start_bucket + free_distance) & idxmask)); sb->hopinfo |= 1u << free_distance; fb->inuse = 1; memcpy (fb->data, data, rt->elemsz); - assert (ut_ehhLookupInternal (rt, start_bucket, data)); + assert (ddsrt_ehh_lookup_internal (rt, start_bucket, data)); return 1; } - free_bucket = ut_ehhFindCloserFreeBucket (rt, free_bucket, &free_distance); + free_bucket = ddsrt_ehh_find_closer_free_bucket (rt, free_bucket, &free_distance); assert (free_bucket == NOT_A_BUCKET || free_bucket <= idxmask); } while (free_bucket != NOT_A_BUCKET); } - ut_ehhResize (rt); - return ut_ehhAdd (rt, data); + ddsrt_ehh_resize (rt); + return ddsrt_ehh_add (rt, data); } -int ut_ehhRemove (struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template) +int ddsrt_ehh_remove (struct ddsrt_ehh * __restrict rt, const void * __restrict template) { const uint32_t hash = rt->hash (template); const uint32_t idxmask = rt->size - 1; const uint32_t bucket = hash & idxmask; uint32_t hopinfo; - struct ut_ehhBucket *sb; + struct ddsrt_ehh_bucket *sb; uint32_t idx; - sb = (struct ut_ehhBucket *) (rt->buckets + bucket * rt->bucketsz); + sb = (struct ddsrt_ehh_bucket *) (rt->buckets + bucket * rt->bucketsz); hopinfo = sb->hopinfo; for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) { if (hopinfo & 1) { const uint32_t bidx = (bucket + idx) & idxmask; - struct ut_ehhBucket *b = (struct ut_ehhBucket *) (rt->buckets + bidx * rt->bucketsz); + struct ddsrt_ehh_bucket *b = (struct ddsrt_ehh_bucket *) (rt->buckets + bidx * rt->bucketsz); if (b->inuse && rt->equals (b->data, template)) { - assert (ut_ehhLookupInternal(rt, bucket, template)); + assert (ddsrt_ehh_lookup_internal(rt, bucket, template)); b->inuse = 0; sb->hopinfo &= ~(1u << idx); return 1; } } } - assert (!ut_ehhLookupInternal(rt, bucket, template)); + assert (!ddsrt_ehh_lookup_internal(rt, bucket, template)); return 0; } -void ut_ehhEnum (struct ut_ehh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_arg), void *f_arg) +void ddsrt_ehh_enum (struct ddsrt_ehh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg) { uint32_t i; for (i = 0; i < rt->size; i++) { - struct ut_ehhBucket *b = (struct ut_ehhBucket *) (rt->buckets + i * rt->bucketsz); + struct ddsrt_ehh_bucket *b = (struct ddsrt_ehh_bucket *) (rt->buckets + i * rt->bucketsz); if (b->inuse) { f (b->data, f_arg); } } } -void *ut_ehhIterFirst (struct ut_ehh * UT_HH_RESTRICT rt, struct ut_ehhIter * UT_HH_RESTRICT iter) +void *ddsrt_ehh_iter_first (struct ddsrt_ehh * __restrict rt, struct ddsrt_ehh_iter * __restrict iter) { iter->hh = rt; iter->cursor = 0; - return ut_ehhIterNext (iter); + return ddsrt_ehh_iter_next (iter); } -void *ut_ehhIterNext (struct ut_ehhIter * UT_HH_RESTRICT iter) +void *ddsrt_ehh_iter_next (struct ddsrt_ehh_iter * __restrict iter) { - struct ut_ehh *rt = iter->hh; + struct ddsrt_ehh *rt = iter->hh; while (iter->cursor < rt->size) { - struct ut_ehhBucket *b = (struct ut_ehhBucket *) (rt->buckets + iter->cursor * rt->bucketsz); + struct ddsrt_ehh_bucket *b = (struct ddsrt_ehh_bucket *) (rt->buckets + iter->cursor * rt->bucketsz); iter->cursor++; if (b->inuse) { return b->data; diff --git a/src/util/src/ut_thread_pool.c b/src/ddsrt/src/thread_pool.c similarity index 88% rename from src/util/src/ut_thread_pool.c rename to src/ddsrt/src/thread_pool.c index acc4258..48cba27 100644 --- a/src/util/src/ut_thread_pool.c +++ b/src/ddsrt/src/thread_pool.c @@ -15,7 +15,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/threads.h" -#include "dds/util/ut_thread_pool.h" +#include "dds/ddsrt/thread_pool.h" typedef struct ddsi_work_queue_job { @@ -25,7 +25,7 @@ typedef struct ddsi_work_queue_job } * ddsi_work_queue_job_t; -struct ut_thread_pool_s +struct ddsrt_thread_pool_s { ddsi_work_queue_job_t m_jobs; /* Job queue */ ddsi_work_queue_job_t m_jobs_tail; /* Tail of job queue */ @@ -42,10 +42,10 @@ struct ut_thread_pool_s ddsrt_mutex_t m_mutex; /* Pool guard mutex */ }; -static uint32_t ut_thread_start_fn (void * arg) +static uint32_t ddsrt_thread_start_fn (void * arg) { ddsi_work_queue_job_t job; - ut_thread_pool pool = (ut_thread_pool) arg; + ddsrt_thread_pool pool = (ddsrt_thread_pool) arg; /* Thread loops, pulling jobs from queue */ @@ -88,7 +88,7 @@ static uint32_t ut_thread_start_fn (void * arg) return 0; } -static dds_retcode_t ut_thread_pool_new_thread (ut_thread_pool pool) +static dds_retcode_t ddsrt_thread_pool_new_thread (ddsrt_thread_pool pool) { static unsigned char pools = 0; /* Pool counter - TODO make atomic */ @@ -97,7 +97,7 @@ static dds_retcode_t ut_thread_pool_new_thread (ut_thread_pool pool) dds_retcode_t res; (void) snprintf (name, sizeof (name), "OSPL-%u-%u", pools++, pool->m_count++); - res = ddsrt_thread_create (&id, name, &pool->m_attr, &ut_thread_start_fn, pool); + res = ddsrt_thread_create (&id, name, &pool->m_attr, &ddsrt_thread_start_fn, pool); if (res == DDS_RETCODE_OK) { @@ -110,9 +110,9 @@ static dds_retcode_t ut_thread_pool_new_thread (ut_thread_pool pool) return res; } -ut_thread_pool ut_thread_pool_new (uint32_t threads, uint32_t max_threads, uint32_t max_queue, ddsrt_threadattr_t * attr) +ddsrt_thread_pool ddsrt_thread_pool_new (uint32_t threads, uint32_t max_threads, uint32_t max_queue, ddsrt_threadattr_t * attr) { - ut_thread_pool pool; + ddsrt_thread_pool pool; ddsi_work_queue_job_t job; /* Sanity check QoS */ @@ -144,9 +144,9 @@ ut_thread_pool ut_thread_pool_new (uint32_t threads, uint32_t max_threads, uint3 while (threads--) { - if (ut_thread_pool_new_thread (pool) != DDS_RETCODE_OK) + if (ddsrt_thread_pool_new_thread (pool) != DDS_RETCODE_OK) { - ut_thread_pool_free (pool); + ddsrt_thread_pool_free (pool); pool = NULL; break; } @@ -158,7 +158,7 @@ ut_thread_pool ut_thread_pool_new (uint32_t threads, uint32_t max_threads, uint3 return pool; } -void ut_thread_pool_free (ut_thread_pool pool) +void ddsrt_thread_pool_free (ddsrt_thread_pool pool) { ddsi_work_queue_job_t job; @@ -205,7 +205,7 @@ void ut_thread_pool_free (ut_thread_pool pool) ddsrt_free (pool); } -dds_retcode_t ut_thread_pool_submit (ut_thread_pool pool, void (*fn) (void *arg), void * arg) +dds_retcode_t ddsrt_thread_pool_submit (ddsrt_thread_pool pool, void (*fn) (void *arg), void * arg) { dds_retcode_t res = DDS_RETCODE_OK; ddsi_work_queue_job_t job; @@ -255,7 +255,7 @@ dds_retcode_t ut_thread_pool_submit (ut_thread_pool pool, void (*fn) (void *arg) if ((pool->m_thread_max == 0) || (pool->m_threads < pool->m_thread_max)) { /* OK if fails as have queued job */ - (void) ut_thread_pool_new_thread (pool); + (void) ddsrt_thread_pool_new_thread (pool); } } @@ -269,7 +269,7 @@ dds_retcode_t ut_thread_pool_submit (ut_thread_pool pool, void (*fn) (void *arg) return res; } -void ut_thread_pool_purge (ut_thread_pool pool) +void ddsrt_thread_pool_purge (ddsrt_thread_pool pool) { uint32_t total; diff --git a/src/util/src/ut_xmlparser.c b/src/ddsrt/src/xmlparser.c similarity index 89% rename from src/util/src/ut_xmlparser.c rename to src/ddsrt/src/xmlparser.c index 2d31a54..7a7e0cb 100644 --- a/src/util/src/ut_xmlparser.c +++ b/src/ddsrt/src/xmlparser.c @@ -18,7 +18,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/misc.h" #include "dds/ddsrt/string.h" -#include "dds/util/ut_xmlparser.h" +#include "dds/ddsrt/xmlparser.h" #define TOK_EOF -1 #define TOK_OPEN_TAG -2 @@ -30,7 +30,7 @@ #define NOMARKER (~(size_t)0) -struct ut_xmlpState { +struct ddsrt_xmlp_state { size_t cbufp; /* current position in cbuf */ size_t cbufn; /* number of bytes in cbuf (cbufp <= cbufn) */ size_t cbufmax; /* allocated size of cbuf (cbufn <= cbufmax) */ @@ -50,7 +50,7 @@ struct ut_xmlpState { int nest; /* current nesting level */ void *varg; /* user argument to callback functions */ int require_eof; /* if false, junk may follow top-level closing tag */ - struct ut_xmlpCallbacks cb; /* user-supplied callbacks (or stubs) */ + struct ddsrt_xmlp_callbacks cb; /* user-supplied callbacks (or stubs) */ }; static int cb_null_elem_open (void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name) @@ -93,7 +93,7 @@ static void cb_null_error (void *varg, const char *msg, int line) DDSRT_UNUSED_ARG (line); } -static void ut_xmlpNewCommon (struct ut_xmlpState *st) +static void ddsrt_xmlp_new_common (struct ddsrt_xmlp_state *st) { st->cbufp = 0; st->cbufmark = NOMARKER; @@ -111,7 +111,7 @@ static void ut_xmlpNewCommon (struct ut_xmlpState *st) st->require_eof = 1; } -static void ut_xmlpNewSetCB (struct ut_xmlpState *st, void *varg, const struct ut_xmlpCallbacks *cb) +static void ddsrt_xmlp_new_setCB (struct ddsrt_xmlp_state *st, void *varg, const struct ddsrt_xmlp_callbacks *cb) { st->varg = varg; st->cb = *cb; @@ -122,43 +122,43 @@ static void ut_xmlpNewSetCB (struct ut_xmlpState *st, void *varg, const struct u if (st->cb.error == 0) st->cb.error = cb_null_error; } -struct ut_xmlpState *ut_xmlpNewFile (FILE *fp, void *varg, const struct ut_xmlpCallbacks *cb) +struct ddsrt_xmlp_state *ddsrt_xmlp_new_file (FILE *fp, void *varg, const struct ddsrt_xmlp_callbacks *cb) { - struct ut_xmlpState *st; + struct ddsrt_xmlp_state *st; st = ddsrt_malloc (sizeof (*st)); st->cbufn = 0; st->cbufmax = 8192; st->cbuf = ddsrt_malloc (st->cbufmax); st->fp = fp; - ut_xmlpNewCommon (st); - ut_xmlpNewSetCB (st, varg, cb); + ddsrt_xmlp_new_common (st); + ddsrt_xmlp_new_setCB (st, varg, cb); return st; } -struct ut_xmlpState *ut_xmlpNewString (const char *string, void *varg, const struct ut_xmlpCallbacks *cb) +struct ddsrt_xmlp_state *ddsrt_xmlp_new_string (const char *string, void *varg, const struct ddsrt_xmlp_callbacks *cb) { - struct ut_xmlpState *st; + struct ddsrt_xmlp_state *st; st = ddsrt_malloc (sizeof (*st)); st->cbufn = strlen (string); st->cbufmax = st->cbufn; st->cbuf = (char *) string; st->fp = NULL; - ut_xmlpNewCommon (st); - ut_xmlpNewSetCB (st, varg, cb); + ddsrt_xmlp_new_common (st); + ddsrt_xmlp_new_setCB (st, varg, cb); return st; } -void ut_xmlpSetRequireEOF (struct ut_xmlpState *st, int require_eof) +void ddsrt_xmlp_set_requireEOF (struct ddsrt_xmlp_state *st, int require_eof) { st->require_eof = require_eof; } -size_t ut_xmlpGetBufpos (const struct ut_xmlpState *st) +size_t ddsrt_xmlp_get_bufpos (const struct ddsrt_xmlp_state *st) { return st->cbufp; } -void ut_xmlpFree (struct ut_xmlpState *st) +void ddsrt_xmlp_free (struct ddsrt_xmlp_state *st) { if (st->fp != NULL) { ddsrt_free (st->cbuf); @@ -167,7 +167,7 @@ void ut_xmlpFree (struct ut_xmlpState *st) ddsrt_free (st); } -static int make_chars_available (struct ut_xmlpState *st, size_t nmin) +static int make_chars_available (struct ddsrt_xmlp_state *st, size_t nmin) { size_t n, pos; pos = (st->cbufmark != NOMARKER) ? st->cbufmark : st->cbufp; @@ -201,21 +201,21 @@ static int make_chars_available (struct ut_xmlpState *st, size_t nmin) return (st->cbufn - st->cbufp >= nmin); } -static void set_input_marker (struct ut_xmlpState *st) +static void set_input_marker (struct ddsrt_xmlp_state *st) { assert (st->cbufmark == NOMARKER); st->cbufmark = st->cbufp; st->linemark = st->line; } -static void discard_input_marker (struct ut_xmlpState *st) +static void discard_input_marker (struct ddsrt_xmlp_state *st) { assert (st->cbufmark != NOMARKER); st->cbufmark = NOMARKER; st->linemark = 0; } -static void rewind_to_input_marker (struct ut_xmlpState *st) +static void rewind_to_input_marker (struct ddsrt_xmlp_state *st) { assert (st->cbufmark != NOMARKER); st->cbufp = st->cbufmark; @@ -223,7 +223,7 @@ static void rewind_to_input_marker (struct ut_xmlpState *st) discard_input_marker (st); } -static int next_char (struct ut_xmlpState *st) +static int next_char (struct ddsrt_xmlp_state *st) { char c; if (!make_chars_available (st, 1)) { @@ -236,7 +236,7 @@ static int next_char (struct ut_xmlpState *st) return c; } -static int peek_char (struct ut_xmlpState *st) +static int peek_char (struct ddsrt_xmlp_state *st) { if (!make_chars_available (st, 1)) { return TOK_EOF; @@ -244,7 +244,7 @@ static int peek_char (struct ut_xmlpState *st) return st->cbuf[st->cbufp]; } -static int peek_chars (struct ut_xmlpState *st, const char *seq, int consume) +static int peek_chars (struct ddsrt_xmlp_state *st, const char *seq, int consume) { size_t n = strlen (seq); if (!make_chars_available (st, n)) { @@ -354,13 +354,13 @@ static int unescape_insitu (char *buffer, size_t *n) } DDSRT_WARNING_MSVC_ON(4996); -static void discard_payload (struct ut_xmlpState *st) +static void discard_payload (struct ddsrt_xmlp_state *st) { st->tpp = 0; st->tpescp = 0; } -static int append_to_payload (struct ut_xmlpState *st, int c, int islit) +static int append_to_payload (struct ddsrt_xmlp_state *st, int c, int islit) { if (!islit) { st->tp[st->tpp++] = (char) c; @@ -383,7 +383,7 @@ static int append_to_payload (struct ut_xmlpState *st, int c, int islit) return 0; } -static int save_payload (char **payload, struct ut_xmlpState *st, int trim) +static int save_payload (char **payload, struct ddsrt_xmlp_state *st, int trim) { char *p; if (st->tpescp < st->tpp) { @@ -424,7 +424,7 @@ static int save_payload (char **payload, struct ut_xmlpState *st, int trim) return 0; } -static int next_token_ident (struct ut_xmlpState *st, char **payload) +static int next_token_ident (struct ddsrt_xmlp_state *st, char **payload) { while (qq_isidentcont (peek_char (st))) { if (append_to_payload (st, next_char (st), 0) < 0) { @@ -438,7 +438,7 @@ static int next_token_ident (struct ut_xmlpState *st, char **payload) } } -static int next_token_tag_withoutclose (struct ut_xmlpState *st, char **payload) +static int next_token_tag_withoutclose (struct ddsrt_xmlp_state *st, char **payload) { if (peek_chars (st, " */ while (peek_char (st) != TOK_EOF && !peek_chars (st, end, 1)) { @@ -501,7 +501,7 @@ static void processing_instruction (struct ut_xmlpState *st, const char *end) } } -static void drop_peek_token (struct ut_xmlpState *st) +static void drop_peek_token (struct ddsrt_xmlp_state *st) { st->peektok = 0; if (st->peekpayload) { @@ -510,7 +510,7 @@ static void drop_peek_token (struct ut_xmlpState *st) } } -static int next_token (struct ut_xmlpState *st, char **payload) +static int next_token (struct ddsrt_xmlp_state *st, char **payload) { /* Always return a valid pointer to allocated memory or a null pointer, regardless of token type */ @@ -566,7 +566,7 @@ static int next_token (struct ut_xmlpState *st, char **payload) } } -static int peek_token (struct ut_xmlpState *st) +static int peek_token (struct ddsrt_xmlp_state *st) { int tok; char *payload; @@ -576,7 +576,7 @@ static int peek_token (struct ut_xmlpState *st) return tok; } -static int parse_element (struct ut_xmlpState *st, uintptr_t parentinfo) +static int parse_element (struct ddsrt_xmlp_state *st, uintptr_t parentinfo) { #define PE_ERROR2(c,c1,c2) do { errc = (c); errc1 = (c1); errc2 = (c2); goto err; } while (0) #define PE_ERROR(c,c1) PE_ERROR2(c,c1,0) @@ -703,7 +703,7 @@ ok: #undef PE_ERROR2 } -int ut_xmlpParse (struct ut_xmlpState *st) +int ddsrt_xmlp_parse (struct ddsrt_xmlp_state *st) { if (peek_token (st) == TOK_EOF) { return 0; @@ -717,6 +717,6 @@ int ut_xmlpParse (struct ut_xmlpState *st) } } -int ut_xmlUnescapeInsitu (char *buffer, size_t *n) { +int ddsrt_xmlUnescapeInsitu (char *buffer, size_t *n) { return unescape_insitu (buffer, n); } diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt deleted file mode 100644 index 282c131..0000000 --- a/src/util/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# -include (GenerateExportHeader) - -PREPEND(srcs_util "${CMAKE_CURRENT_SOURCE_DIR}/src" ut_avl.c ut_crc.c ut_expand_envvars.c ut_fibheap.c ut_hopscotch.c ut_thread_pool.c ut_xmlparser.c) - -add_library(util ${srcs_util}) -set_property(TARGET util PROPERTY POSITION_INDEPENDENT_CODE TRUE) - -generate_export_header( - util - BASE_NAME - dds - EXPORT_FILE_NAME - "${CMAKE_CURRENT_BINARY_DIR}/include/dds/export.h") - -# util must NOT link with ddsrt to avoid duplicate symbols in ddsc! -# ddsrt include directories are required though. -target_compile_definitions( - util - PUBLIC - $>) -target_include_directories( - util - PUBLIC - "$" - PRIVATE - "$" - "$>") - -install( - DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include/dds" - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" - COMPONENT dev) - -# TODO: improve test inclusion. -if((BUILD_TESTING) AND ((NOT DEFINED MSVC_VERSION) OR (MSVC_VERSION GREATER "1800"))) - add_subdirectory(tests) -endif() diff --git a/src/util/include/dds/util/ut_avl.h b/src/util/include/dds/util/ut_avl.h deleted file mode 100644 index 8d3b76b..0000000 --- a/src/util/include/dds/util/ut_avl.h +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef UT_AVL_H -#define UT_AVL_H - -/* The tree library never performs memory allocations or deallocations internally. - - - Treedef_t: defines the properties of the tree, offsets, - comparison functions, augmented structures, flags -- these are - related to the code/data structure in which the tree is embedded, - and in nearly all cases known at compile time. - - avlTree_t: represents the tree, i.e., pointer to the root. - - avlNode_t: contains the administrative data for a single node in - the tree. - - For a tree node: - struct T { - avlNode_t avlnode; - int key; - }; - by definition, avlnodeoffset == offsetof(struct T, avlnode) and - keyoffset = offsetof(struct T, key). The user of the library only - ever deals in pointers to (in this case) struct T, never with - pointers to the avlNode_t, and the compare function operations on - pointers to keys, in this case pointers to "int"s. If you wish, you - can also do: keyoffset = 0, in which case the compare function - would be operating on struct T's. - - The compare function is assumed to behave just like all compare - functions in the C library: < 0, =0, >0 for left argument less - than, equal to or greater than the right argument. - - The "augment" function is automatically called whenever some of the - children of a node change, as well as when the "augment" function - has been called on some of the children. It allows you to maintain - a "summary" of the subtree -- currently only used in ddsi2e, in one - spot. - - Trees come in various "variants", configured through "treedef" - flags: - - direct/indirect key: direct meaning the key value is embedded in - the structure containing the avlNode_t, indirect meaning a - pointer to the key value is. The compare function doesn't deal - with tree nodes, but with key values. - - re-entrant: in the style of the C library, meaning, the - comparison function gets a user-supplied 3rd argument (in - particular used by mmstat). - - unique keys/duplicate keys: when keys must be unique, some - optimizations apply; it is up to the caller to ensure one doesn't - violate the uniqueness of the keys (it'll happily crash in insert - if you don't); when duplicate keys are allowed, a forward scan of - the tree will visit them in the order of insertion. - - For a tree node: - struct T { - avlnode_t avlnode; - char *key; - }; - you could set the "indirect" flag, and then you simply use - strcmp(), avoiding the need for passing templates in looking up key - values. Much nicer. - - There is also an orthogonal variant that is enforced through the - type system -- note that would be possible for all of the above as - well, but the number of cases simply explodes and none of the above - flags affects the dynamically changing data structures (just the - tree definition), unlike this one. - - - the "C" variant keeps track of the number of nodes in the tree to - support a "count" operation in O(1) time, but is otherwise - identical. - - The various initializer macros and TreedefInit functions should - make sense with this. - - All functions for looking up nodes return NULL if there is no node - satisfying the requirements. - - - Init: initializes a tree (really just: root = NULL, perhaps count = 0) - - Free: calls "freefun" on each node, which may free the node - - FreeArg: as "Free", but with an extra, user-supplied, argument - - Root: returns the root node - - Lookup: returns a node with key value "key" (ref allowdups flag) - - LookupIPath: like Lookup, but also filling an IPath_t structure - for efficient insertion in case of a failed lookup (or inserting - duplicates) - - LookupDPath: like Lookup, but also filling a DPath_t structure - that helps with deleting a node - - LookupPredEq: locates the node with the greatest key value <= "key" - - LookupSuccEq: similar, but smallest key value >= "key" - - LookupPred: similar, < "key" - - LookupSucc: similar, > "key" - - Insert: convenience function: LookupIPath ; InsertIPath - - Delete: convenience function: LookupDPath ; DeleteDPath - - InsertIPath: insert node based on the "path" obtained from LookupIPath - - DeleteDPath: delete node, using information in "path" to do so efficiently - - SwapNode: replace "oldn" by "newn" without modifying the tree - structure (the key need not be equal, but must be - FindPred(oldn).key < newn.key < FindSucc(oldn).key, where a - non-existing predecessor has key -inf and a non-existing - successor has key +inf, and where it is understood that the < - operator becomes <= if allowdups is set - - AugmentUpdate: to be called when something in "node" changes that - affects the subtree "summary" computed by the configured - "augment" function - - IsEmpty: returns 1 if tree is empty, 0 if not - - IsSingleton: returns 1 if tree contains exactly one node, 0 if not - - FindMin: returns the node with the smallest key value in the tree - - FindMax: similar, largest key value - - FindPred: preceding node in in-order treewalk - - FindSucc: similar, following node - - - Walk: calls "f" with user-supplied argument "a" once for each - node, starting at FindMin and ending at FindMax - - ConstWalk: same, but with a const tree - - WalkRange: like Walk, but only visiting nodes with key values in - range [min,max] (that's inclusive) - - ConstWalkRange: same, but with a const tree - - WalkRangeReverse: like WalkRange, but in the reverse direction - - ConstWalkRangeReverse: same, but with a const tree - - IterFirst: starts forward iteration, starting at (and returning) FindMin - - IterSuccEq: similar, starting at LookupSuccEq - - IterSucc: similar, starting at LookupSucc - - IterNext: returns FindSucc(last returned node); may not be called - if preceding IterXXX call on same "iter" returned NULL - - That's all there is to it. - - Note that all calls to Walk(f,a) can be rewritten as: - for(n=IterFirst(&it); n; n=IterNext(&it)) { f(n,a) } - or as - for(n=FindMin(); n; n=FindSucc(n)) { f(n,a) } - - The walk functions and iterators may not alter the tree - structure. If that is desired, the latter can easily be rewritten - as: - n=FindMin() ; while(n) { nn=FindSucc(n); f(n,a); n=nn } - because FindMin/FindSucc doesn't store any information to allow - fast processing. That'll allow every operation, with the obvious - exception of f(n) calling Delete(FindSucc(n)). - - Currently, all trees maintain parent pointers, but it may be worth - doing a separate set without it, as it reduces the size of - avlNode_t. But in that case, the FindMin/FindSucc option would no - longer be a reasonable option because it would be prohibitively - expensive, whereas the IterFirst/IterNext option are alway - efficiently. If one were to do a threaded tree variant, the - implemetantion of IterFirst/IterNext would become absolute trivial - and faster still, but at the cost of significantly more overhead in - memory and updates. */ - -#include -#include - -#include "dds/export.h" -#include "dds/ddsrt/attributes.h" - -#if defined (__cplusplus) -extern "C" { -#endif - -#define UT_AVL_MAX_TREEHEIGHT (12 * sizeof (void *)) - -typedef int (*ut_avlCompare_t) (const void *a, const void *b); -typedef int (*ut_avlCompare_r_t) (const void *a, const void *b, void *arg); -typedef void (*ut_avlAugment_t) (void *node, const void *left, const void *right); -typedef void (*ut_avlWalk_t) (void *node, void *arg); -typedef void (*ut_avlConstWalk_t) (const void *node, void *arg); - -typedef struct ut_avlNode { - struct ut_avlNode *cs[2]; /* 0 = left, 1 = right */ - struct ut_avlNode *parent; - int height; -} ut_avlNode_t; - -#define UT_AVL_TREEDEF_FLAG_INDKEY 1 -#define UT_AVL_TREEDEF_FLAG_R 2 -#define UT_AVL_TREEDEF_FLAG_ALLOWDUPS 4 - -typedef struct ut_avlTreedef { -#if defined (__cplusplus) - ut_avlTreedef() {} -#endif - size_t avlnodeoffset; - size_t keyoffset; - union { - ut_avlCompare_t comparekk; - ut_avlCompare_r_t comparekk_r; - } u; - ut_avlAugment_t augment; - uint32_t flags; - void *cmp_arg; /* for _r variant */ -} ut_avlTreedef_t; - -typedef struct ut_avlCTreedef { - ut_avlTreedef_t t; -} ut_avlCTreedef_t; - -typedef struct ut_avlTree { - ut_avlNode_t *root; -} ut_avlTree_t; - -typedef struct ut_avlCTree { - ut_avlTree_t t; - size_t count; -} ut_avlCTree_t; - -typedef struct ut_avlPath { - int depth; /* total depth of path */ - int pnodeidx; - ut_avlNode_t *parent; /* (nodeidx == 0 ? NULL : *(path[nodeidx-1])) */ - ut_avlNode_t **pnode[UT_AVL_MAX_TREEHEIGHT]; -} ut_avlPath_t; - -typedef struct ut_avlIPath { - ut_avlPath_t p; -} ut_avlIPath_t; - -typedef struct ut_avlDPath { - ut_avlPath_t p; -} ut_avlDPath_t; - -typedef struct ut_avlIter { - const ut_avlTreedef_t *td; - ut_avlNode_t *right; - ut_avlNode_t **todop; - ut_avlNode_t *todo[1+UT_AVL_MAX_TREEHEIGHT]; -} ut_avlIter_t; - -typedef struct ut_avlCIter { - ut_avlIter_t t; -} ut_avlCIter_t; - -/* avlnodeoffset and keyoffset must both be in [0,2**31-1] */ -#define UT_AVL_TREEDEF_INITIALIZER(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), 0, 0 } -#define UT_AVL_TREEDEF_INITIALIZER_INDKEY(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_INDKEY, 0 } -#define UT_AVL_TREEDEF_INITIALIZER_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_ALLOWDUPS, 0 } -#define UT_AVL_TREEDEF_INITIALIZER_INDKEY_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_INDKEY|UT_AVL_TREEDEF_FLAG_ALLOWDUPS, 0 } -#define UT_AVL_TREEDEF_INITIALIZER_R(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_R, (cmparg) } -#define UT_AVL_TREEDEF_INITIALIZER_INDKEY_R(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_INDKEY|UT_AVL_TREEDEF_FLAG_R, (cmparg) } -#define UT_AVL_TREEDEF_INITIALIZER_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_R|UT_AVL_TREEDEF_FLAG_ALLOWDUPS, (cmparg) } -#define UT_AVL_TREEDEF_INITIALIZER_INDKEY_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_INDKEY|UT_AVL_TREEDEF_FLAG_R|UT_AVL_TREEDEF_FLAG_ALLOWDUPS, (cmparg) } - -/* Not maintaining # nodes */ - -DDS_EXPORT void ut_avlTreedefInit (ut_avlTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_t comparekk, ut_avlAugment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); -DDS_EXPORT void ut_avlTreedefInit_r (ut_avlTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_r_t comparekk_r, void *cmp_arg, ut_avlAugment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); - -DDS_EXPORT void ut_avlInit (const ut_avlTreedef_t *td, ut_avlTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlFree (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void (*freefun) (void *node)) ddsrt_nonnull((1,2)); -DDS_EXPORT void ut_avlFreeArg (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void (*freefun) (void *node, void *arg), void *arg) ddsrt_nonnull((1,2)); - -DDS_EXPORT void *ut_avlRoot (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlRootNonEmpty (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookup (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookupIPath (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key, ut_avlIPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookupDPath (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key, ut_avlDPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookupPredEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookupSuccEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookupPred (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookupSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) ddsrt_nonnull_all; - -DDS_EXPORT void ut_avlInsert (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *node) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlDelete (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *node) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlInsertIPath (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *node, ut_avlIPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlDeleteDPath (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *node, ut_avlDPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlSwapNode (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *oldn, void *newn) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlAugmentUpdate (const ut_avlTreedef_t *td, void *node) ddsrt_nonnull_all; - -DDS_EXPORT int ut_avlIsEmpty (const ut_avlTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT int ut_avlIsSingleton (const ut_avlTree_t *tree) ddsrt_nonnull_all; - -DDS_EXPORT void *ut_avlFindMin (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlFindMax (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlFindPred (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); -DDS_EXPORT void *ut_avlFindSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); - -DDS_EXPORT void ut_avlWalk (const ut_avlTreedef_t *td, ut_avlTree_t *tree, ut_avlWalk_t f, void *a) ddsrt_nonnull((1,2,3)); -DDS_EXPORT void ut_avlConstWalk (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlConstWalk_t f, void *a) ddsrt_nonnull((1,2,3)); -DDS_EXPORT void ut_avlWalkRange (const ut_avlTreedef_t *td, ut_avlTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); -DDS_EXPORT void ut_avlConstWalkRange (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); -DDS_EXPORT void ut_avlWalkRangeReverse (const ut_avlTreedef_t *td, ut_avlTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) ddsrt_nonnull((1,2,3)); -DDS_EXPORT void ut_avlConstWalkRangeReverse (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) ddsrt_nonnull((1,2,3)); - -DDS_EXPORT void *ut_avlIterFirst (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlIter_t *iter) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlIterSuccEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlIter_t *iter, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlIterSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlIter_t *iter, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlIterNext (ut_avlIter_t *iter) ddsrt_nonnull_all; - -/* Maintaining # nodes */ - -#define UT_AVL_CTREEDEF_INITIALIZER(avlnodeoffset, keyoffset, comparekk, augment) { UT_AVL_TREEDEF_INITIALIZER (avlnodeoffset, keyoffset, comparekk, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_INDKEY(avlnodeoffset, keyoffset, comparekk, augment) { UT_AVL_TREEDEF_INITIALIZER_INDKEY (avlnodeoffset, keyoffset, comparekk, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, augment) { UT_AVL_TREEDEF_INITIALIZER_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_INDKEY_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, augment) { UT_AVL_TREEDEF_INITIALIZER_INDKEY_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_R(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { UT_AVL_TREEDEF_INITIALIZER_R (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_INDKEY_R(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { UT_AVL_TREEDEF_INITIALIZER_INDKEY_R (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { UT_AVL_TREEDEF_INITIALIZER_R_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_INDKEY_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { UT_AVL_TREEDEF_INITIALIZER_INDKEY_R_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } - -DDS_EXPORT void ut_avlCTreedefInit (ut_avlCTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_t comparekk, ut_avlAugment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); -DDS_EXPORT void ut_avlCTreedefInit_r (ut_avlCTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_r_t comparekk_r, void *cmp_arg, ut_avlAugment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); - -DDS_EXPORT void ut_avlCInit (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlCFree (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void (*freefun) (void *node)) ddsrt_nonnull((1,2)); -DDS_EXPORT void ut_avlCFreeArg (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void (*freefun) (void *node, void *arg), void *arg) ddsrt_nonnull((1,2)); - -DDS_EXPORT void *ut_avlCRoot (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCRootNonEmpty (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookup (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookupIPath (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key, ut_avlIPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookupDPath (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key, ut_avlDPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookupPredEq (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookupSuccEq (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookupPred (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookupSucc (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) ddsrt_nonnull_all; - -DDS_EXPORT void ut_avlCInsert (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlCDelete (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlCInsertIPath (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node, ut_avlIPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlCDeleteDPath (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node, ut_avlDPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlCSwapNode (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *oldn, void *newn) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlCAugmentUpdate (const ut_avlCTreedef_t *td, void *node) ddsrt_nonnull_all; - -DDS_EXPORT int ut_avlCIsEmpty (const ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT int ut_avlCIsSingleton (const ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT size_t ut_avlCCount (const ut_avlCTree_t *tree) ddsrt_nonnull_all; - -DDS_EXPORT void *ut_avlCFindMin (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCFindMax (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCFindPred (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); -DDS_EXPORT void *ut_avlCFindSucc (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); - -DDS_EXPORT void ut_avlCWalk (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, ut_avlWalk_t f, void *a) ddsrt_nonnull((1,2,3)); -DDS_EXPORT void ut_avlCConstWalk (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlConstWalk_t f, void *a) ddsrt_nonnull((1,2,3)); -DDS_EXPORT void ut_avlCWalkRange (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); -DDS_EXPORT void ut_avlCConstWalkRange (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); -DDS_EXPORT void ut_avlCWalkRangeReverse (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); -DDS_EXPORT void ut_avlCConstWalkRangeReverse (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); - -DDS_EXPORT void *ut_avlCIterFirst (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlCIter_t *iter) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCIterSuccEq (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlCIter_t *iter, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCIterSucc (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlCIter_t *iter, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCIterNext (ut_avlCIter_t *iter) ddsrt_nonnull_all; - -#if defined (__cplusplus) -} -#endif - -#endif /* UT_AVL_H */ diff --git a/src/util/include/dds/util/ut_crc.h b/src/util/include/dds/util/ut_crc.h deleted file mode 100644 index 144009f..0000000 --- a/src/util/include/dds/util/ut_crc.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef UT_CRC_H -#define UT_CRC_H - -#include -#include - -#include "dds/export.h" -#include "dds/ddsrt/attributes.h" - -#if defined (__cplusplus) -extern "C" { -#endif - -DDS_EXPORT uint32_t ut_crcCalculate (const void *buf, size_t length) ddsrt_nonnull_all ddsrt_attribute_pure; - -#if defined (__cplusplus) -} -#endif - -#endif /* UT_CRC_H */ diff --git a/src/util/include/dds/util/ut_fibheap.h b/src/util/include/dds/util/ut_fibheap.h deleted file mode 100644 index d02b9c8..0000000 --- a/src/util/include/dds/util/ut_fibheap.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef UT_FIBHEAP_H -#define UT_FIBHEAP_H - -#include - -#include "dds/export.h" - -#if defined (__cplusplus) -extern "C" { -#endif - -typedef struct ut_fibheapNode { - struct ut_fibheapNode *parent, *children; - struct ut_fibheapNode *prev, *next; - unsigned mark: 1; - unsigned degree: 31; -} ut_fibheapNode_t; - -typedef struct ut_fibheapDef { - uintptr_t offset; - int (*cmp) (const void *va, const void *vb); -} ut_fibheapDef_t; - -typedef struct ut_fibheap { - ut_fibheapNode_t *roots; /* points to root with min key value */ -} ut_fibheap_t; - -#define UT_FIBHEAPDEF_INITIALIZER(offset, cmp) { (offset), (cmp) } - -DDS_EXPORT void ut_fibheapDefInit (ut_fibheapDef_t *fhdef, uintptr_t offset, int (*cmp) (const void *va, const void *vb)); -DDS_EXPORT void ut_fibheapInit (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh); -DDS_EXPORT void *ut_fibheapMin (const ut_fibheapDef_t *fhdef, const ut_fibheap_t *fh); -DDS_EXPORT void ut_fibheapMerge (const ut_fibheapDef_t *fhdef, ut_fibheap_t *a, ut_fibheap_t *b); -DDS_EXPORT void ut_fibheapInsert (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const void *vnode); -DDS_EXPORT void ut_fibheapDelete (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const void *vnode); -DDS_EXPORT void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh); -DDS_EXPORT void ut_fibheapDecreaseKey (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const void *vnode); /* to be called AFTER decreasing the key */ - -#if defined (__cplusplus) -} -#endif - -#endif /* UT_FIBHEAP_H */ diff --git a/src/util/include/dds/util/ut_hopscotch.h b/src/util/include/dds/util/ut_hopscotch.h deleted file mode 100644 index 9c632a8..0000000 --- a/src/util/include/dds/util/ut_hopscotch.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef UT_HOPSCOTCH_H -#define UT_HOPSCOTCH_H - -#include - -#include "dds/export.h" - -#if defined (__cplusplus) -extern "C" { -#endif - -#if __STDC_VERSION__ >= 199901L -#define UT_HH_RESTRICT restrict -#else -#define UT_HH_RESTRICT -#endif - -/* Concurrent version */ -struct ut_chh; -struct ut_chhBucket; -struct ut_chhIter { - struct ut_chhBucket *bs; - uint32_t size; - uint32_t cursor; -}; - -/* - * The hopscotch hash table is dependent on a proper functioning hash. - * If the hash function generates a lot of hash collisions, then it will - * not be able to handle that by design. - * It is capable of handling some collisions, but not more than 32 per - * bucket (less, when other hash values are clustered around the - * collision value). - * When proper distributed hash values are generated, then hopscotch - * works nice and quickly. - */ -typedef uint32_t (*ut_hhHash_fn) (const void *); - -/* - * Hopscotch needs to be able to compare two elements. - * Returns 0 when not equal. - */ -typedef int (*ut_hhEquals_fn) (const void *, const void *); - -/* - * Hopscotch is will resize its internal buckets list when needed. It will - * call this garbage collection function with the old buckets list. The - * caller has to delete the list when it deems it safe to do so. - */ -typedef void (*ut_hhBucketsGc_fn) (void *); - -DDS_EXPORT struct ut_chh *ut_chhNew (uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals, ut_hhBucketsGc_fn gc_buckets); -DDS_EXPORT void ut_chhFree (struct ut_chh * UT_HH_RESTRICT hh); -DDS_EXPORT void *ut_chhLookup (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template); -DDS_EXPORT int ut_chhAdd (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data); -DDS_EXPORT int ut_chhRemove (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template); -DDS_EXPORT void ut_chhEnumUnsafe (struct ut_chh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ -void *ut_chhIterFirst (struct ut_chh * UT_HH_RESTRICT rt, struct ut_chhIter *it); -void *ut_chhIterNext (struct ut_chhIter *it); - -/* Sequential version */ -struct ut_hh; - -struct ut_hhIter { - struct ut_hh *hh; - uint32_t cursor; -}; - -DDS_EXPORT struct ut_hh *ut_hhNew (uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals); -DDS_EXPORT void ut_hhFree (struct ut_hh * UT_HH_RESTRICT hh); -DDS_EXPORT void *ut_hhLookup (const struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template); -DDS_EXPORT int ut_hhAdd (struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data); -DDS_EXPORT int ut_hhRemove (struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template); -DDS_EXPORT void ut_hhEnum (struct ut_hh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ -DDS_EXPORT void *ut_hhIterFirst (struct ut_hh * UT_HH_RESTRICT rt, struct ut_hhIter * UT_HH_RESTRICT iter); /* may delete nodes */ -DDS_EXPORT void *ut_hhIterNext (struct ut_hhIter * UT_HH_RESTRICT iter); - -/* Sequential version, embedded data */ -struct ut_ehh; - -struct ut_ehhIter { - struct ut_ehh *hh; - uint32_t cursor; -}; - -DDS_EXPORT struct ut_ehh *ut_ehhNew (size_t elemsz, uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals); -DDS_EXPORT void ut_ehhFree (struct ut_ehh * UT_HH_RESTRICT hh); -DDS_EXPORT void *ut_ehhLookup (const struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template); -DDS_EXPORT int ut_ehhAdd (struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data); -DDS_EXPORT int ut_ehhRemove (struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template); -DDS_EXPORT void ut_ehhEnum (struct ut_ehh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ -DDS_EXPORT void *ut_ehhIterFirst (struct ut_ehh * UT_HH_RESTRICT rt, struct ut_ehhIter * UT_HH_RESTRICT iter); /* may delete nodes */ -DDS_EXPORT void *ut_ehhIterNext (struct ut_ehhIter * UT_HH_RESTRICT iter); - -#if defined (__cplusplus) -} -#endif - -#endif diff --git a/src/util/include/dds/util/ut_xmlparser.h b/src/util/include/dds/util/ut_xmlparser.h deleted file mode 100644 index b7d5076..0000000 --- a/src/util/include/dds/util/ut_xmlparser.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef UT_XMLPARSER_H -#define UT_XMLPARSER_H - -#include - -#include "dds/export.h" - -#if defined (__cplusplus) -extern "C" { -#endif - - typedef int (*ut_xmlpProcElemOpen_t) (void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name); - typedef int (*ut_xmlpProcAttr_t) (void *varg, uintptr_t eleminfo, const char *name, const char *value); - typedef int (*ut_xmlpProcElemData_t) (void *varg, uintptr_t eleminfo, const char *data); - typedef int (*ut_xmlpProcElemClose_t) (void *varg, uintptr_t eleminfo); - typedef void (*ut_xmlpError) (void *varg, const char *msg, int line); - - struct ut_xmlpCallbacks { - ut_xmlpProcElemOpen_t elem_open; - ut_xmlpProcAttr_t attr; - ut_xmlpProcElemData_t elem_data; - ut_xmlpProcElemClose_t elem_close; - ut_xmlpError error; - }; - - struct ut_xmlpState; - - DDS_EXPORT struct ut_xmlpState *ut_xmlpNewFile (FILE *fp, void *varg, const struct ut_xmlpCallbacks *cb); - DDS_EXPORT struct ut_xmlpState *ut_xmlpNewString (const char *string, void *varg, const struct ut_xmlpCallbacks *cb); - DDS_EXPORT void ut_xmlpSetRequireEOF (struct ut_xmlpState *st, int require_eof); - DDS_EXPORT size_t ut_xmlpGetBufpos (const struct ut_xmlpState *st); - DDS_EXPORT void ut_xmlpFree (struct ut_xmlpState *st); - DDS_EXPORT int ut_xmlpParse (struct ut_xmlpState *st); - - DDS_EXPORT int ut_xmlUnescapeInsitu (char *buffer, size_t *n); - -#if defined (__cplusplus) -} -#endif - -#endif diff --git a/src/util/src/ut_crc.c b/src/util/src/ut_crc.c deleted file mode 100644 index 87778a9..0000000 --- a/src/util/src/ut_crc.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/util/ut_crc.h" - -static const uint32_t crc32_table[] = { - 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, - 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, - 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, - 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, - 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, - 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, - 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, - 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, - 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, - 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, - 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, - 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, - 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, - 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, - 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, - 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, - 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, - 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, - 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, - 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, - 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, - 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, - 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, - 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, - 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, - 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, - 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, - 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, - 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, - 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, - 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, - 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, - 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, - 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, - 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, - 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, - 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, - 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, - 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, - 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, - 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 -}; - -uint32_t ut_crcCalculate (const void *buf, size_t length) -{ - const unsigned char *vptr = buf; - size_t i; - uint32_t reg = 0; - unsigned char top; - for (i = 0; i < length; i++) - { - top = (unsigned char) (reg >> 24); - top ^= *vptr; - reg = (reg << 8) ^ crc32_table[top]; - vptr++; - } - return reg; -} diff --git a/src/util/tests/CMakeLists.txt b/src/util/tests/CMakeLists.txt deleted file mode 100644 index 7828517..0000000 --- a/src/util/tests/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# -include(CUnit) - -#add_cunit_executable(CUnit_util "handleserver.c") -#target_link_libraries(CUnit_util util) From 1672268481829ef92f15815d4f45a3e558767a4d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 16 Apr 2019 15:22:04 +0200 Subject: [PATCH 035/178] always append 0 byte to user/group/topic data Changes the semantics of dds_qget_{user,group,topic}data to always append a 0 byte to any non-empty value without counting it in the size. (An empty value is always represented by a null pointer and a size of 0). The advantage is that any code treating the data as the octet sequence it formally is will do exactly the same, but any code written with the knowledge that it should be a string can safely interpret it as one. Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/ddsc/dds_public_qos.h | 6 +++--- src/core/ddsc/src/dds_qos.c | 10 ++++++---- src/core/ddsi/src/q_plist.c | 6 +++--- 3 files changed, 12 insertions(+), 10 deletions(-) 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 95fa4fe..b8fc7fa 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h @@ -501,7 +501,7 @@ DDS_EXPORT void dds_qset_ignorelocal ( * @brief Get the userdata from a qos structure * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy - * @param[in,out] value - Pointer that will store the userdata + * @param[in,out] value - Pointer that will store the userdata. If sz = 0, then a null pointer, else it is a pointer to an allocated buffer of sz+1 bytes where the last byte is always 0 * @param[in,out] sz - Pointer that will store the size of userdata * * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object @@ -512,7 +512,7 @@ DDS_EXPORT bool dds_qget_userdata (const dds_qos_t * __restrict qos, void **valu * @brief Get the topicdata from a qos structure * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy - * @param[in,out] value - Pointer that will store the topicdata + * @param[in,out] value - Pointer that will store the topicdata. If sz = 0, then a null pointer, else it is a pointer to an allocated buffer of sz+1 bytes where the last byte is always 0 * @param[in,out] sz - Pointer that will store the size of topicdata * * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object @@ -523,7 +523,7 @@ DDS_EXPORT bool dds_qget_topicdata (const dds_qos_t * __restrict qos, void **val * @brief Get the groupdata from a qos structure * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy - * @param[in,out] value - Pointer that will store the groupdata + * @param[in,out] value - Pointer that will store the groupdata. If sz = 0, then a null pointer, else it is a pointer to an allocated buffer of sz+1 bytes where the last byte is always 0 * @param[in,out] sz - Pointer that will store the size of groupdata * * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index 02988bf..d95add8 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -43,6 +43,7 @@ dds_qos_data_copy_out( void ** value, size_t * sz) { + assert (data->length < UINT32_MAX); if (sz == NULL && value != NULL) { return false; } @@ -51,9 +52,10 @@ dds_qos_data_copy_out( } if (value) { if (data->length != 0) { - assert(data->value); - *value = dds_alloc(data->length); - memcpy(*value, data->value, data->length); + assert (data->value); + *value = dds_alloc (data->length + 1); + memcpy (*value, data->value, data->length); + ((char *) (*value))[data->length] = 0; } else { *value = NULL; } @@ -66,7 +68,7 @@ validate_octetseq( const nn_octetseq_t* seq) { /* default value is NULL with length 0 */ - return (((seq->length == 0) && (seq->value == NULL)) || (seq->length > 0)); + return (((seq->length == 0) && (seq->value == NULL)) || (seq->length > 0 && seq->length < UINT32_MAX)); } bool diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index fed7f43..d44cec1 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -144,7 +144,7 @@ static int validate_octetseq (const struct dd *dd, size_t *len) if (dd->bufsz < offsetof (struct cdroctetseq, value)) return Q_ERR_INVALID; *len = dd->bswap ? bswap4u (x->len) : x->len; - if (*len > dd->bufsz - offsetof (struct cdroctetseq, value)) + if (*len > dd->bufsz - offsetof (struct cdroctetseq, value) || *len >= UINT32_MAX) return Q_ERR_INVALID; return 0; } @@ -158,7 +158,7 @@ static int alias_octetseq (nn_octetseq_t *oseq, const struct dd *dd) else { const struct cdroctetseq *x = (const struct cdroctetseq *) dd->buf; - assert(len <= UINT32_MAX); /* it really is an uint32_t on the wire */ + assert(len < UINT32_MAX); /* it really is an uint32_t on the wire */ oseq->length = (uint32_t)len; oseq->value = (len == 0) ? NULL : (unsigned char *) x->value; return 0; @@ -167,7 +167,7 @@ static int alias_octetseq (nn_octetseq_t *oseq, const struct dd *dd) static int alias_blob (nn_octetseq_t *oseq, const struct dd *dd) { - assert (dd->bufsz <= UINT32_MAX); + assert (dd->bufsz < UINT32_MAX); oseq->length = (uint32_t)dd->bufsz; oseq->value = (oseq->length == 0) ? NULL : (unsigned char *) dd->buf; return 0; From 9c1a739559f60b55962d07c980d2352d82106e6d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 16 Apr 2019 17:04:21 +0200 Subject: [PATCH 036/178] suppress EHOSTUNREACH and EHOSTDOWN errors in log Signed-off-by: Erik Boasson --- src/core/ddsi/src/ddsi_udp.c | 2 +- src/ddsrt/src/sockets/posix/socket.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index a228097..0ab4489 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -167,7 +167,7 @@ static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *d rc != DDS_RETCODE_NOT_ALLOWED && rc != DDS_RETCODE_NO_CONNECTION) { - DDS_ERROR("ddsi_udp_conn_write failed with retcode %d", rc); + DDS_ERROR("ddsi_udp_conn_write failed with retcode %d\n", rc); } return (rc == DDS_RETCODE_OK ? ret : -1); } diff --git a/src/ddsrt/src/sockets/posix/socket.c b/src/ddsrt/src/sockets/posix/socket.c index 35b80d8..94b7f89 100644 --- a/src/ddsrt/src/sockets/posix/socket.c +++ b/src/ddsrt/src/sockets/posix/socket.c @@ -455,6 +455,9 @@ send_error_to_retcode(int errnum) case ENOBUFS: case ENOMEM: return DDS_RETCODE_OUT_OF_RESOURCES; + case EHOSTUNREACH: + case EHOSTDOWN: + return DDS_RETCODE_NO_CONNECTION; default: break; } From 1ecad3c047ce0d367db0436b0476669ac26a5756 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 19 Apr 2019 22:01:11 +0200 Subject: [PATCH 037/178] remove "Error occurred on locking entity" messages Those should not be printed to stderr (or wherever), there are errors returned in these cases ... Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_entity.c | 6 ++---- src/core/ddsc/src/dds_instance.c | 21 +-------------------- src/core/ddsc/src/dds_participant.c | 1 - src/core/ddsc/src/dds_read.c | 3 --- src/core/ddsc/src/dds_topic.c | 2 -- src/core/ddsc/src/dds_waitset.c | 1 - 6 files changed, 3 insertions(+), 31 deletions(-) diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index 6704b6e..7d62349 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -269,8 +269,8 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) dds_free (e); } - return ret; - } + return ret; +} dds_entity_t dds_get_parent (dds_entity_t entity) { @@ -404,11 +404,9 @@ dds_return_t dds_get_listener (dds_entity_t entity, dds_listener_t *listener) ddsrt_mutex_unlock (&e->m_observers_lock); dds_entity_unlock(e); } else { - DDS_ERROR("Error occurred on locking entity\n"); ret = DDS_ERRNO(rc); } } else { - DDS_ERROR("Argument listener is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); } diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index 5d15275..25156fe 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -134,18 +134,15 @@ dds_register_instance( dds_retcode_t rc; if(data == NULL){ - DDS_ERROR("Argument data is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } if(handle == NULL){ - DDS_ERROR("Argument handle is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } rc = dds_writer_lock(writer, &wr); if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking writer\n"); ret = DDS_ERRNO(rc); goto err; } @@ -155,7 +152,6 @@ dds_register_instance( *handle = inst->m_iid; ret = DDS_RETCODE_OK; } else { - DDS_ERROR("Unable to create instance\n"); ret = DDS_ERRNO(DDS_RETCODE_ERROR); } thread_state_asleep (ts1); @@ -194,19 +190,16 @@ dds_unregister_instance_ts( dds_writer *wr; if (data == NULL){ - DDS_ERROR("Argument data is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } if(timestamp < 0){ - DDS_ERROR("Argument timestamp has negative value\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } rc = dds_writer_lock(writer, &wr); if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking writer\n"); - ret = DDS_ERRNO(rc); + ret = DDS_ERRNO(rc); goto err; } @@ -241,7 +234,6 @@ dds_unregister_instance_ih_ts( rc = dds_writer_lock(writer, &wr); if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking writer\n"); ret = DDS_ERRNO(rc); goto err; } @@ -264,7 +256,6 @@ dds_unregister_instance_ih_ts( ret = dds_write_impl (wr, sample, timestamp, action); ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL); } else { - DDS_ERROR("No instance related with the provided handle is found\n"); ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); } thread_state_asleep (ts1); @@ -294,7 +285,6 @@ dds_writedispose_ts( thread_state_asleep (ts1); dds_writer_unlock(wr); } else { - DDS_ERROR("Error occurred on locking writer\n"); ret = DDS_ERRNO(rc); } @@ -336,7 +326,6 @@ dds_dispose_ts( thread_state_asleep (ts1); dds_writer_unlock(wr); } else { - DDS_ERROR("Error occurred on locking writer\n"); ret = DDS_ERRNO(rc); } @@ -366,13 +355,11 @@ dds_dispose_ih_ts( ret = dds_dispose_impl (wr, sample, handle, timestamp); ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL); } else { - DDS_ERROR("No instance related with the provided handle is found\n"); ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); } thread_state_asleep (ts1); dds_writer_unlock(wr); } else { - DDS_ERROR("Error occurred on locking writer\n"); ret = DDS_ERRNO(rc); } @@ -391,7 +378,6 @@ dds_lookup_instance( struct ddsi_serdata *sd; if(data == NULL){ - DDS_ERROR("Argument data is NULL\n"); goto err; } @@ -402,8 +388,6 @@ dds_lookup_instance( ih = ddsi_tkmap_lookup (map, sd); ddsi_serdata_unref (sd); thread_state_asleep (ts1); - } else { - DDS_ERROR("Acquired topic is NULL\n"); } err: return ih; @@ -429,14 +413,12 @@ dds_instance_get_key( struct ddsi_tkmap_instance * tk; if(data == NULL){ - DDS_ERROR("Argument data is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } topic = dds_instance_info_by_hdl (entity); if(topic == NULL){ - DDS_ERROR("Could not find topic related to the given entity\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } @@ -447,7 +429,6 @@ dds_instance_get_key( ddsi_tkmap_instance_unref (tk); ret = DDS_RETCODE_OK; } else { - DDS_ERROR("No instance related with the provided entity is found\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); } thread_state_asleep (ts1); diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 587951a..a0c3c03 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -37,7 +37,6 @@ dds_participant_status_validate( dds_return_t ret = DDS_RETCODE_OK; if (mask & ~(DDS_PARTICIPANT_STATUS_MASK)) { - DDS_ERROR("Argument mask is invalid\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); } diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index d595272..5be40d1 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -123,7 +123,6 @@ dds_read_impl( thread_state_awake (ts1); rc = dds_read_lock(reader_or_condition, &rd, &cond, only_reader); if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking entity\n"); ret = DDS_ERRNO(rc); goto fail_awake; } @@ -223,7 +222,6 @@ dds_readcdr_impl( } dds_read_unlock(rd, cond); } else { - DDS_ERROR("Error occurred on locking entity\n"); ret = DDS_ERRNO(rc); } @@ -695,7 +693,6 @@ dds_return_loan( rc = dds_read_lock(reader_or_condition, &rd, &cond, false); if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking entity\n"); ret = DDS_ERRNO(rc); goto fail; } diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 636c4ae..5d62fdf 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -200,7 +200,6 @@ dds_find_topic( ddsrt_mutex_unlock (&dds_global.m_mutex); dds_entity_unlock(p); } else { - DDS_ERROR("Error occurred on locking entity\n"); tp = DDS_ERRNO(rc); } } else { @@ -334,7 +333,6 @@ dds_create_topic_arbitrary ( rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking entity\n"); hdl = DDS_ERRNO(rc); goto lock_err; } diff --git a/src/core/ddsc/src/dds_waitset.c b/src/core/ddsc/src/dds_waitset.c index 787ce2c..4d5bd4b 100644 --- a/src/core/ddsc/src/dds_waitset.c +++ b/src/core/ddsc/src/dds_waitset.c @@ -217,7 +217,6 @@ dds_create_waitset( waitset->triggered = NULL; dds_entity_unlock(par); } else { - DDS_ERROR("Error occurred on locking entity\n"); hdl = DDS_ERRNO(rc); } From 1a3d5c7abab88a8a06a2a9cb01230cfe4417132a Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 20 Apr 2019 17:14:23 +0200 Subject: [PATCH 038/178] Fix DATA_AVAILABLE race condition The DATA_AVAILABLE status was reset by read and take while holding the upper-layer reader lock, but after completing the read/take operation on the RHC. As data can be written into the RHC without holding the upper-layer reader lock, new data could arrive in between the reading/taking and the resetting of the DATA_AVAILABLE status, leading to a missed detection. Resetting DATA_AVAILABLE prior to accessing the RHC solves this. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_read.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 5be40d1..6a9dc73 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -156,17 +156,19 @@ dds_read_impl( rd->m_loan_out = true; } } + + /* read/take resets data available status -- must reset before reading because + the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ + dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); + /* reset DATA_ON_READERS status on subscriber after successful read/take */ + if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { + dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); + } if (take) { ret = (dds_return_t)dds_rhc_take(rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); } else { ret = (dds_return_t)dds_rhc_read(rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); } - /* read/take resets data available status */ - dds_entity_status_reset(&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); - /* reset DATA_ON_READERS status on subscriber after successful read/take */ - if (dds_entity_kind(rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { - dds_entity_status_reset(rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); - } dds_read_unlock(rd, cond); fail_awake: @@ -202,6 +204,13 @@ dds_readcdr_impl( thread_state_awake (ts1); rc = dds_read_lock(reader_or_condition, &rd, &cond, false); if (rc == DDS_RETCODE_OK) { + /* read/take resets data available status -- must reset before reading because + the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ + dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); + /* reset DATA_ON_READERS status on subscriber after successful read/take */ + if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { + dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); + } ret = dds_rhc_takecdr ( rd->m_rd->rhc, lock, buf, si, maxs, @@ -211,15 +220,6 @@ dds_readcdr_impl( hand ); - /* read/take resets data available status */ - dds_entity_status_reset(&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); - - /* reset DATA_ON_READERS status on subscriber after successful read/take */ - - if (dds_entity_kind(rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) - { - dds_entity_status_reset(rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); - } dds_read_unlock(rd, cond); } else { ret = DDS_ERRNO(rc); From 46f61e09f5496a6c99ee6b22afcdae27d5f60a47 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 20 Apr 2019 17:17:47 +0200 Subject: [PATCH 039/178] missing m_observer_lock on (re)setting statuses Most of the places where the status flags were reset, this happened without holding m_observer_lock protecting these status flags. For most of these statuses, they are only ever set/reset while also holding the entity lock, but this is not true for all of them (DATA_AVAILABLE for example), and thus there are some cases where retrieving the status could lead to losing the raising of a (at least a DATA_AVAILABLE) status. The problem was introduced in ba46cb1140ea86c7e5321e27bc6a20dedb745ff4. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_read.c | 6 ++++++ src/core/ddsc/src/dds_reader.c | 12 ++++++++++++ src/core/ddsc/src/dds_topic.c | 2 ++ src/core/ddsc/src/dds_writer.c | 8 ++++++++ 4 files changed, 28 insertions(+) diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 6a9dc73..114e6ff 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -159,11 +159,14 @@ dds_read_impl( /* read/take resets data available status -- must reset before reading because the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); /* reset DATA_ON_READERS status on subscriber after successful read/take */ if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); + if (take) { ret = (dds_return_t)dds_rhc_take(rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); } else { @@ -206,11 +209,14 @@ dds_readcdr_impl( if (rc == DDS_RETCODE_OK) { /* read/take resets data available status -- must reset before reading because the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); /* reset DATA_ON_READERS status on subscriber after successful read/take */ if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); + ret = dds_rhc_takecdr ( rd->m_rd->rhc, lock, buf, si, maxs, diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 10951e2..6ce57b9 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -643,11 +643,13 @@ dds_get_subscription_matched_status ( if (status) { *status = rd->m_subscription_matched_status; } + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); if (rd->m_entity.m_status_enable & DDS_SUBSCRIPTION_MATCHED_STATUS) { rd->m_subscription_matched_status.total_count_change = 0; rd->m_subscription_matched_status.current_count_change = 0; dds_entity_status_reset(&rd->m_entity, DDS_SUBSCRIPTION_MATCHED_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); dds_reader_unlock(rd); fail: return ret; @@ -672,11 +674,13 @@ dds_get_liveliness_changed_status ( if (status) { *status = rd->m_liveliness_changed_status; } + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); if (rd->m_entity.m_status_enable & DDS_LIVELINESS_CHANGED_STATUS) { rd->m_liveliness_changed_status.alive_count_change = 0; rd->m_liveliness_changed_status.not_alive_count_change = 0; dds_entity_status_reset(&rd->m_entity, DDS_LIVELINESS_CHANGED_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); dds_reader_unlock(rd); fail: return ret; @@ -700,11 +704,13 @@ dds_return_t dds_get_sample_rejected_status ( if (status) { *status = rd->m_sample_rejected_status; } + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); if (rd->m_entity.m_status_enable & DDS_SAMPLE_REJECTED_STATUS) { rd->m_sample_rejected_status.total_count_change = 0; rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED; dds_entity_status_reset(&rd->m_entity, DDS_SAMPLE_REJECTED_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); dds_reader_unlock(rd); fail: return ret; @@ -728,10 +734,12 @@ dds_return_t dds_get_sample_lost_status ( if (status) { *status = rd->m_sample_lost_status; } + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); if (rd->m_entity.m_status_enable & DDS_SAMPLE_LOST_STATUS) { rd->m_sample_lost_status.total_count_change = 0; dds_entity_status_reset(&rd->m_entity, DDS_SAMPLE_LOST_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); dds_reader_unlock(rd); fail: return ret; @@ -755,10 +763,12 @@ dds_return_t dds_get_requested_deadline_missed_status ( if (status) { *status = rd->m_requested_deadline_missed_status; } + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); if (rd->m_entity.m_status_enable & DDS_REQUESTED_DEADLINE_MISSED_STATUS) { rd->m_requested_deadline_missed_status.total_count_change = 0; dds_entity_status_reset(&rd->m_entity, DDS_REQUESTED_DEADLINE_MISSED_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); dds_reader_unlock(rd); fail: return ret; @@ -782,10 +792,12 @@ dds_return_t dds_get_requested_incompatible_qos_status ( if (status) { *status = rd->m_requested_incompatible_qos_status; } + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); if (rd->m_entity.m_status_enable & DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS) { rd->m_requested_incompatible_qos_status.total_count_change = 0; dds_entity_status_reset(&rd->m_entity, DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); dds_reader_unlock(rd); fail: return ret; diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 5d62fdf..f834f00 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -669,10 +669,12 @@ dds_get_inconsistent_topic_status( if (status) { *status = t->m_inconsistent_topic_status; } + ddsrt_mutex_lock (&t->m_entity.m_observers_lock); if (t->m_entity.m_status_enable & DDS_INCONSISTENT_TOPIC_STATUS) { t->m_inconsistent_topic_status.total_count_change = 0; dds_entity_status_reset(&t->m_entity, DDS_INCONSISTENT_TOPIC_STATUS); } + ddsrt_mutex_unlock (&t->m_entity.m_observers_lock); dds_topic_unlock(t); fail: return ret; diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index cd83d3e..f98d70c 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -518,11 +518,13 @@ dds_get_publication_matched_status ( if (status) { *status = wr->m_publication_matched_status; } + ddsrt_mutex_lock (&wr->m_entity.m_observers_lock); if (wr->m_entity.m_status_enable & DDS_PUBLICATION_MATCHED_STATUS) { wr->m_publication_matched_status.total_count_change = 0; wr->m_publication_matched_status.current_count_change = 0; dds_entity_status_reset(&wr->m_entity, DDS_PUBLICATION_MATCHED_STATUS); } + ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock); dds_writer_unlock(wr); fail: return ret; @@ -547,10 +549,12 @@ dds_get_liveliness_lost_status ( if (status) { *status = wr->m_liveliness_lost_status; } + ddsrt_mutex_lock (&wr->m_entity.m_observers_lock); if (wr->m_entity.m_status_enable & DDS_LIVELINESS_LOST_STATUS) { wr->m_liveliness_lost_status.total_count_change = 0; dds_entity_status_reset(&wr->m_entity, DDS_LIVELINESS_LOST_STATUS); } + ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock); dds_writer_unlock(wr); fail: return ret; @@ -575,10 +579,12 @@ dds_get_offered_deadline_missed_status( if (status) { *status = wr->m_offered_deadline_missed_status; } + ddsrt_mutex_lock (&wr->m_entity.m_observers_lock); if (wr->m_entity.m_status_enable & DDS_OFFERED_DEADLINE_MISSED_STATUS) { wr->m_offered_deadline_missed_status.total_count_change = 0; dds_entity_status_reset(&wr->m_entity, DDS_OFFERED_DEADLINE_MISSED_STATUS); } + ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock); dds_writer_unlock(wr); fail: return ret; @@ -603,10 +609,12 @@ dds_get_offered_incompatible_qos_status ( if (status) { *status = wr->m_offered_incompatible_qos_status; } + ddsrt_mutex_lock (&wr->m_entity.m_observers_lock); if (wr->m_entity.m_status_enable & DDS_OFFERED_INCOMPATIBLE_QOS_STATUS) { wr->m_offered_incompatible_qos_status.total_count_change = 0; dds_entity_status_reset(&wr->m_entity, DDS_OFFERED_INCOMPATIBLE_QOS_STATUS); } + ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock); dds_writer_unlock(wr); fail: return ret; From 06245d0d4aa5bd490f3d368eb91144f306588426 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 11:52:43 +0200 Subject: [PATCH 040/178] initial version of permance/network check tool The current situation for performance measurements and checking network behaviour is rather unsatisfactory, as the only tools available are ``pubsub`` and the ``roundtrip`` and ``throughput`` examples. The first can do many things thanks to its thousand-and-one options, but its purpose really is to be able to read/write arbitrary data with arbitrary QoS -- though the arbitrary data bit was lost in the hacked conversion from the original code. The latter two have a terrible user interface, don't perform any verification that the measurement was successful and do not provide the results in a convenient form. Furthermore, the abuse of the two examples as the primary means for measuring performance has resulted in a reduction of their value as an example, e.g., they can do waitset- or listener-based reading (and the throughput one also polling-based), but that kind of complication does not help a new user understand what is going on. Especially not given that these features were simply hacked in. Hence the need for a new tool, one that integrates the common measurements and can be used to verify that the results make sense. It is not quite done yet, in particular it is lacking in a number of aspects: * no measurement of CPU- and network load, memory usage and context switches yet; * very limited statistics (min/max/average, if you're lucky; no interesting things such as jitter on a throughput test yet); * it can't yet gather the data from all participants in the network using DDS; * it doesn't output the data in a convenient file format yet; * it doesn't allow specifying boundaries within which the results must fall for the run to be successful. What it does verify is that all the endpoint matches that should exist given the discovered participant do in fact come into existence, reporting an error (and exiting with an exit status code of 1) if they don't, as well as checking the number of participants. With the way the DDSI protocol works, this is a pretty decent network connectivity check. The raw measurements needed for the desired statistics (apart from system-level measurements) are pretty much made, so the main thing that still needs to be done is exploit them and output them. It can already replace the examples for most benchmarks (only the 50%/90%/99% percentiles are still missing for a complete replacement). Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_read.c | 5 +- src/tools/CMakeLists.txt | 1 + src/tools/ddsperf/CMakeLists.txt | 23 + src/tools/ddsperf/ddsperf.c | 2036 +++++++++++++++++++++++++++ src/tools/ddsperf/ddsperf_types.idl | 29 + 5 files changed, 2091 insertions(+), 3 deletions(-) create mode 100644 src/tools/ddsperf/CMakeLists.txt create mode 100644 src/tools/ddsperf/ddsperf.c create mode 100644 src/tools/ddsperf/ddsperf_types.idl diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 114e6ff..37e35ec 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -686,13 +686,12 @@ dds_return_loan( dds_readcond *cond; dds_return_t ret = DDS_RETCODE_OK; - if (!buf ) { + if (!buf) { DDS_ERROR("Argument buf is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto fail; } - if(*buf == NULL && bufsz > 0){ - DDS_ERROR("Argument buf is NULL\n"); + if (*buf == NULL && bufsz > 0) { ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto fail; } diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index 7e615a1..9c2d51c 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -13,6 +13,7 @@ set(CMAKE_INSTALL_TOOLSDIR "${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}/tools add_subdirectory(pubsub) add_subdirectory(config) add_subdirectory(ddsls) +add_subdirectory(ddsperf) # VxWorks build machines use OpenJDK 8, which lack jfxrt.jar. Do not build launcher on that platform. # diff --git a/src/tools/ddsperf/CMakeLists.txt b/src/tools/ddsperf/CMakeLists.txt new file mode 100644 index 0000000..c1c12e0 --- /dev/null +++ b/src/tools/ddsperf/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# 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 +# +idlc_generate(ddsperf_types ddsperf_types.idl) +add_executable(ddsperf ddsperf.c) +target_link_libraries(ddsperf ddsperf_types ddsc) +if(WIN32) + target_compile_definitions(ddsperf PRIVATE _CRT_SECURE_NO_WARNINGS) +endif() + +install( + TARGETS ddsperf + DESTINATION "${CMAKE_INSTALL_BINDIR}" + COMPONENT dev +) diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c new file mode 100644 index 0000000..51874a4 --- /dev/null +++ b/src/tools/ddsperf/ddsperf.c @@ -0,0 +1,2036 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#define _ISOC99_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef _WIN32 +#include +#endif +#include + +#include "dds/dds.h" +#include "ddsperf_types.h" + +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/sockets.h" +#include "dds/ddsrt/threads.h" +#include "dds/ddsrt/random.h" +#include "dds/ddsrt/avl.h" +#include "dds/ddsrt/fibheap.h" + +#define UDATA_MAGIC "DDSPerf:" +#define UDATA_MAGIC_SIZE (sizeof (UDATA_MAGIC) - 1) + +enum topicsel { + KS, /* KeyedSeq type: seq#, key, sequence-of-octet */ + K32, /* Keyed32 type: seq#, key, array-of-24-octet (sizeof = 32) */ + K256, /* Keyed256 type: seq#, key, array-of-248-octet (sizeof = 256) */ + OU /* OneULong type: seq# */ +}; + +enum submode { + SM_NONE, /* no subscriber at all */ + SM_WAITSET, /* subscriber using a waitset */ + SM_POLLING, /* ... using polling, sleeping for 1ms if no data */ + SM_LISTENER /* ... using a DATA_AVAILABLE listener */ +}; + +static const char *argv0; +static volatile sig_atomic_t termflag = 0; + +/* Domain participant, guard condition for termination, domain id */ +static dds_entity_t dp; +static dds_instance_handle_t dp_handle; +static dds_entity_t termcond; +static dds_domainid_t did = DDS_DOMAIN_DEFAULT; + +/* Readers for built-in topics to get discovery information */ +static dds_entity_t rd_participants, rd_subscriptions, rd_publications; + +/* Topics, readers, writers (except for pong writers: there are + many of those) */ +static dds_entity_t tp_data, tp_ping, tp_pong; +static char tpname_data[32], tpname_ping[32], tpname_pong[32]; +static dds_entity_t sub, pub, wr_data, wr_ping, rd_data, rd_ping, rd_pong; + +/* Number of different key values to use (must be 1 for OU type) */ +static unsigned nkeyvals = 1; + +/* Topic type to use */ +static enum topicsel topicsel = OU; + +/* Data and ping/pong subscriber triggering modes */ +static enum submode submode = SM_LISTENER; +static enum submode pingpongmode = SM_LISTENER; + +/* Size of the sequence in KeyedSeq type in bytes */ +static unsigned baggagesize = 0; + +/* Whether or not to register instances prior to writing */ +static bool register_instances = true; + +/* Maximum run time in seconds */ +static double dur = HUGE_VAL; + +/* Minimum number of peers (if not met, exit status is 1) */ +static uint32_t minmatch = 0; + +/* Maximum time it may take to discover all MINMATCH peers */ +static double maxwait = HUGE_VAL; + +/* Number of participants for which all expected endpoints + have been matched (this includes the local participant + if ignorelocal is DDS_IGNORELOCAL_NONE) [protected by + disc_lock] */ +static uint32_t matchcount = 0; + +/* An error is always signalled if not all endpoints of a + participant have been discovered within a set amount of + time (5s, currently) [protected by disc_lock] */ +static uint32_t matchtimeout = 0; + +/* Data is published in bursts of this many samples */ +static unsigned burstsize = 1; + +/* Whether to use reliable or best-effort readers/writers */ +static bool reliable = true; + +/* History depth for throughput data reader and writer; 0 is + KEEP_ALL, otherwise it is KEEP_LAST histdepth. Ping/pong + always uses KEEP_LAST 1. */ +static int32_t histdepth = 0; + +/* Publishing rate in Hz, HUGE_VAL means as fast as possible, + 0 means no throughput data is published at all */ +static double rate; + +/* Fraction of throughput data samples that double as a ping + message */ +static uint32_t ping_frac = 0; + +/* Setting for "ignore local" reader/writer QoS: whether or + not to ignore readers and writers in the same particiapnt + that would otherwise match */ +static dds_ignorelocal_kind_t ignorelocal = DDS_IGNORELOCAL_PARTICIPANT; + +/* Pinging interval for roundtrip testing, 0 means as fast as + possible, DDS_INFINITY means never */ +static dds_duration_t ping_intv; + +static ddsrt_mutex_t disc_lock; + +/* Publisher statistics and lock protecting it */ +struct hist { + unsigned nbins; + uint64_t binwidth; + uint64_t bin0; /* bins are [bin0,bin0+binwidth),[bin0+binwidth,bin0+2*binwidth) */ + uint64_t binN; /* bin0 + nbins*binwidth */ + uint64_t min, max; /* min and max observed since last reset */ + uint64_t under, over; /* < bin0, >= binN */ + uint64_t bins[]; +}; + +static ddsrt_mutex_t pubstat_lock; +static struct hist *pubstat_hist; + +/* Subscriber statistics for tracking number of samples received + and lost per source */ +struct eseq_stat { + /* totals */ + uint64_t nrecv; + uint64_t nlost; + uint64_t nrecv_bytes; + + /* stats printer state */ + uint64_t nrecv_ref; + uint64_t nlost_ref; + uint64_t nrecv_bytes_ref; +}; + +struct eseq_admin { + ddsrt_mutex_t lock; + unsigned nkeys; + unsigned nph; + dds_instance_handle_t *ph; + struct eseq_stat *stats; + uint32_t **eseq; +}; + +static struct eseq_admin eseq_admin; + +/* Entry for mapping ping/data publication handle to pong writer */ +struct subthread_arg_pongwr { + dds_instance_handle_t pubhandle; + dds_instance_handle_t pphandle; + dds_entity_t wr_pong; +}; + +/* Entry for mapping pong publication handle to latency statistics */ +struct subthread_arg_pongstat { + dds_instance_handle_t pubhandle; + dds_instance_handle_t pphandle; + uint64_t min, max; + uint64_t sum; + uint32_t cnt; +}; + +/* Pong statistics is stored in n array of npongstat entries + [protected by pongstat_lock] */ +static ddsrt_mutex_t pongstat_lock; +static uint32_t npongstat; +static struct subthread_arg_pongstat *pongstat; + +/* All topics have a sequence number, this is the one of the + latest ping sent and the number of pongs received for that + sequence number. Also the time at which it was sent for + generating new ping messages in the case of loss of topology + changes, and a timestamp after which a warning is printed + when a new ping is published. [All protected by + pongwr_lock] */ +static dds_time_t cur_ping_time; +static dds_time_t twarn_ping_timeout; +static uint32_t cur_ping_seq; +static uint32_t n_pong_seen; + +/* Number of pongs expected for each ping [protected by + pongwr_lock] */ +static uint32_t n_pong_expected; + +/* Table mapping data and ping publication handles to writers + of pongs (one per participant in a unique partition so that + a participant only receives responses to its own pings) is + a simply array of npongwr entries [protected by pongwr_lock] */ +static ddsrt_mutex_t pongwr_lock; +static uint32_t npongwr; +static struct subthread_arg_pongwr *pongwr; + +/* Each subscriber thread gets its own not-quite-pre-allocated + set of samples (it does use a loan, but that loan gets reused) */ +struct subthread_arg { + dds_entity_t rd; + uint32_t max_samples; + dds_sample_info_t *iseq; + void **mseq; +}; + +/* Type used for converting GUIDs to strings, used for generating + the per-participant partition names */ +struct guidstr { + char str[36]; +}; + +/* Endpoints that can be matched; all endpoints except for a data + subscriber always exist; the data subscriber is only created if + requested */ +#define MM_RD_DATA 1u +#define MM_RD_PING 2u +#define MM_RD_PONG 4u +#define MM_WR_DATA 8u +#define MM_WR_PING 16u +#define MM_WR_PONG 32u +#define MM_ALL (2 * MM_WR_PONG - 1) + +struct ppant { + ddsrt_avl_node_t avlnode; /* embedded AVL node for handle index */ + ddsrt_fibheap_node_t fhnode; /* prio queue for timeout handling */ + dds_instance_handle_t handle; /* participant instance handle */ + dds_builtintopic_guid_t guid; /* participant GUID */ + char *hostname; /* hostname is taken from user_data QoS */ + uint32_t pid; /* pid is also taken from user_data QoS */ + dds_time_t tdisc; /* time at which it was discovered */ + dds_time_t tdeadline; /* by what time must unmatched be 0 */ + uint32_t unmatched; /* expected but not yet detected endpoints */ +}; + +static int cmp_instance_handle (const void *va, const void *vb) +{ + const dds_instance_handle_t *a = va; + const dds_instance_handle_t *b = vb; + return (*a == *b) ? 0 : (*a < *b) ? -1 : 1; +} + +/* AVL tree of ppant structures indexed on handle using cmp_instance_handle */ +static ddsrt_avl_treedef_t ppants_td = DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct ppant, avlnode), offsetof (struct ppant, handle), cmp_instance_handle, 0); +static ddsrt_avl_tree_t ppants; + +/* Priority queue (Fibonacci heap) of ppant structures with tdeadline as key */ +static int cmp_ppant_tdeadline (const void *va, const void *vb) +{ + const struct ppant *a = va; + const struct ppant *b = vb; + return (a->tdeadline == b->tdeadline) ? 0 : (a->tdeadline < b->tdeadline) ? -1 : 1; +} + +static ddsrt_fibheap_def_t ppants_to_match_fhd = DDSRT_FIBHEAPDEF_INITIALIZER (offsetof (struct ppant, fhnode), cmp_ppant_tdeadline); +static ddsrt_fibheap_t ppants_to_match; + +/* Printing error messages: error2 is for DDS errors, error3 is for usage errors */ +static void verrorx (int exitcode, const char *fmt, va_list ap) ddsrt_attribute_noreturn; +static void error2 (const char *fmt, ...) ddsrt_attribute_format ((printf, 1, 2)) ddsrt_attribute_noreturn; +static void error3 (const char *fmt, ...) ddsrt_attribute_format ((printf, 1, 2)) ddsrt_attribute_noreturn; + +static void publication_matched_listener (dds_entity_t wr, const dds_publication_matched_status_t status, void *arg); + +struct seq_keyval { + uint32_t seq; + int32_t keyval; +}; + +union data { + uint32_t seq; + struct seq_keyval seq_keyval; + KeyedSeq ks; + Keyed32 k32; + Keyed256 k256; + OneULong ou; +}; + +static void verrorx (int exitcode, const char *fmt, va_list ap) +{ + vprintf (fmt, ap); + fflush (stdout); + exit (exitcode); +} + +static void error2 (const char *fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + verrorx (2, fmt, ap); +} + +static void error3 (const char *fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + verrorx (3, fmt, ap); +} + +static char *make_guidstr (struct guidstr *buf, const dds_builtintopic_guid_t *guid) +{ + snprintf (buf->str, sizeof (buf->str), "%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x", + guid->v[0], guid->v[1], guid->v[2], guid->v[3], + guid->v[4], guid->v[5], guid->v[6], guid->v[7], + guid->v[8], guid->v[9], guid->v[10], guid->v[11], + guid->v[12], guid->v[13], guid->v[14], guid->v[15]); + return buf->str; +} + +static void hist_reset_minmax (struct hist *h) +{ + h->min = UINT64_MAX; + h->max = 0; +} + +static void hist_reset (struct hist *h) +{ + hist_reset_minmax (h); + h->under = 0; + h->over = 0; + memset (h->bins, 0, h->nbins * sizeof (*h->bins)); +} + +static struct hist *hist_new (unsigned nbins, uint64_t binwidth, uint64_t bin0) +{ + struct hist *h = malloc (sizeof (*h) + nbins * sizeof (*h->bins)); + h->nbins = nbins; + h->binwidth = binwidth; + h->bin0 = bin0; + h->binN = h->bin0 + h->nbins * h->binwidth; + hist_reset (h); + return h; +} + +static void hist_free (struct hist *h) +{ + free (h); +} + +static void hist_record (struct hist *h, uint64_t x, unsigned weight) +{ + if (x < h->min) + h->min = x; + if (x > h->max) + h->max = x; + if (x < h->bin0) + h->under += weight; + else if (x >= h->binN) + h->over += weight; + else + h->bins[(x - h->bin0) / h->binwidth] += weight; +} + +static void xsnprintf(char *buf, size_t bufsz, size_t *p, const char *fmt, ...) +{ + if (*p < bufsz) + { + int n; + va_list ap; + va_start (ap, fmt); + n = vsnprintf (buf + *p, bufsz - *p, fmt, ap); + va_end (ap); + *p += (size_t) n; + } +} + +static void hist_print (const char *prefix, struct hist *h, dds_time_t dt, int reset) +{ + const size_t l_size = sizeof(char) * h->nbins + 200 + strlen (prefix); + const size_t hist_size = sizeof(char) * h->nbins + 1; + char *l = (char *) malloc(l_size); + char *hist = (char *) malloc(hist_size); + double dt_s = (double)dt / 1e9, avg; + uint64_t peak = 0, cnt = h->under + h->over; + size_t p = 0; + + xsnprintf (l, l_size, &p, "%s", prefix); + + hist[h->nbins] = 0; + for (unsigned i = 0; i < h->nbins; i++) + { + cnt += h->bins[i]; + if (h->bins[i] > peak) + peak = h->bins[i]; + } + + const uint64_t p1 = peak / 100; + const uint64_t p10 = peak / 10; + const uint64_t p20 = 1 * peak / 5; + const uint64_t p40 = 2 * peak / 5; + const uint64_t p60 = 3 * peak / 5; + const uint64_t p80 = 4 * peak / 5; + for (unsigned i = 0; i < h->nbins; i++) + { + if (h->bins[i] == 0) hist[i] = ' '; + else if (h->bins[i] <= p1) hist[i] = '.'; + else if (h->bins[i] <= p10) hist[i] = '_'; + else if (h->bins[i] <= p20) hist[i] = '-'; + else if (h->bins[i] <= p40) hist[i] = '='; + else if (h->bins[i] <= p60) hist[i] = 'x'; + else if (h->bins[i] <= p80) hist[i] = 'X'; + else hist[i] = '@'; + } + + avg = (double) cnt / dt_s; + if (avg < 999.5) + xsnprintf (l, l_size, &p, "%5.3g", avg); + else if (avg < 1e6) + xsnprintf (l, l_size, &p, "%4.3gk", avg / 1e3); + else + xsnprintf (l, l_size, &p, "%4.3gM", avg / 1e6); + xsnprintf (l, l_size, &p, "/s "); + + if (h->min == UINT64_MAX) + xsnprintf (l, l_size, &p, " inf "); + else if (h->min < 1000) + xsnprintf (l, l_size, &p, "%3"PRIu64"n ", h->min); + else if (h->min + 500 < 1000000) + xsnprintf (l, l_size, &p, "%3"PRIu64"u ", (h->min + 500) / 1000); + else if (h->min + 500000 < 1000000000) + xsnprintf (l, l_size, &p, "%3"PRIu64"m ", (h->min + 500000) / 1000000); + else + xsnprintf (l, l_size, &p, "%3"PRIu64"s ", (h->min + 500000000) / 1000000000); + + if (h->bin0 > 0) { + int pct = (cnt == 0) ? 0 : 100 * (int) ((h->under + cnt/2) / cnt); + xsnprintf (l, l_size, &p, "%3d%% ", pct); + } + + { + int pct = (cnt == 0) ? 0 : 100 * (int) ((h->over + cnt/2) / cnt); + xsnprintf (l, l_size, &p, "|%s| %3d%%", hist, pct); + } + + if (h->max < 1000) + xsnprintf (l, l_size, &p, " %3"PRIu64"n", h->max); + else if (h->max + 500 < 1000000) + xsnprintf (l, l_size, &p, " %3"PRIu64"u", (h->max + 500) / 1000); + else if (h->max + 500000 < 1000000000) + xsnprintf (l, l_size, &p, " %3"PRIu64"m", (h->max + 500000) / 1000000); + else + xsnprintf (l, l_size, &p, " %3"PRIu64"s", (h->max + 500000000) / 1000000000); + + (void) p; + puts (l); + fflush (stdout); + free (l); + free (hist); + if (reset) + hist_reset (h); +} + +static void *make_baggage (dds_sequence_t *b, unsigned cnt) +{ + b->_maximum = b->_length = cnt; + if (cnt == 0) + b->_buffer = NULL; + else + { + b->_buffer = malloc (b->_maximum); + memset(b->_buffer, 0xee, b->_maximum); + } + return b->_buffer; +} + +static void *init_sample (union data *data, uint32_t seq) +{ + void *baggage = NULL; + switch (topicsel) + { + case KS: + data->ks.seq = seq; + data->ks.keyval = 0; + baggage = make_baggage (&data->ks.baggage, baggagesize); + break; + case K32: + data->k32.seq = seq; + data->k32.keyval = 0; + memset (data->k32.baggage, 0xee, sizeof (data->k32.baggage)); + break; + case K256: + data->k256.seq = seq; + data->k256.keyval = 0; + memset (data->k256.baggage, 0xee, sizeof (data->k256.baggage)); + break; + case OU: + data->ou.seq = seq; + break; + } + return baggage; +} + +static uint32_t pubthread (void *varg) +{ + int result; + dds_instance_handle_t *ihs; + dds_time_t ntot = 0, tfirst, tfirst0; + union data data; + uint64_t timeouts = 0; + void *baggage = NULL; + (void) varg; + + memset (&data, 0, sizeof (data)); + assert (nkeyvals > 0); + assert (topicsel != OU || nkeyvals == 1); + + baggage = init_sample (&data, 0); + ihs = malloc (nkeyvals * sizeof (dds_instance_handle_t)); + for (unsigned k = 0; k < nkeyvals; k++) + { + data.seq_keyval.keyval = (int32_t) k; + if (register_instances) + dds_register_instance (wr_data, &ihs[k], &data); + else + ihs[k] = 0; + } + data.seq_keyval.keyval = 0; + + tfirst0 = tfirst = dds_time(); + + unsigned bi = 0; + while (!termflag) + { + /* lsb of timestamp is abused to signal whether the sample is a ping requiring a response or not */ + bool reqresp = (ping_frac == 0) ? 0 : (ping_frac == UINT32_MAX) ? 1 : (ddsrt_random () <= ping_frac); + const dds_time_t t_write = (dds_time () & ~1) | reqresp; + if ((result = dds_write_ts (wr_data, &data, t_write)) != DDS_RETCODE_OK) + { + printf ("write error: %d\n", result); + fflush (stdout); + if (dds_err_nr (result) != DDS_RETCODE_TIMEOUT) + exit (2); + timeouts++; + /* retry with original timestamp, it really is just a way of reporting + blocking for an exceedingly long time */ + continue; + } + if (reqresp) + { + dds_write_flush (wr_data); + } + + const dds_time_t t_post_write = dds_time (); + dds_time_t t = t_post_write; + ddsrt_mutex_lock (&pubstat_lock); + hist_record (pubstat_hist, (uint64_t) ((t_post_write - t_write) / 1), 1); + ntot++; + ddsrt_mutex_unlock (&pubstat_lock); + + data.seq_keyval.keyval = (data.seq_keyval.keyval + 1) % (int32_t) nkeyvals; + data.seq++; + + if (rate < HUGE_VAL) + { + if (++bi == burstsize) + { + /* FIXME: should average rate over a short-ish period, rather than over the entire run */ + while (((double) (ntot / burstsize) / ((double) (t - tfirst0) / 1e9 + 5e-3)) > rate && !termflag) + { + /* FIXME: flushing manually because batching is not yet implemented properly */ + dds_write_flush (wr_data); + dds_sleepfor (DDS_MSECS (1)); + t = dds_time (); + } + bi = 0; + } + } + } + if (baggage) + free (baggage); + free (ihs); + return 0; +} + +static void init_eseq_admin (struct eseq_admin *ea, unsigned nkeys) +{ + ddsrt_mutex_init (&ea->lock); + ea->nkeys = nkeys; + ea->nph = 0; + ea->ph = NULL; + ea->stats = NULL; + ea->eseq = NULL; +} + +static void fini_eseq_admin (struct eseq_admin *ea) +{ + free (ea->ph); + free (ea->stats); + for (unsigned i = 0; i < ea->nph; i++) + free (ea->eseq[i]); + ddsrt_mutex_destroy (&ea->lock); + free (ea->eseq); +} + +static int check_eseq (struct eseq_admin *ea, uint32_t seq, uint32_t keyval, uint32_t size, const dds_instance_handle_t pubhandle) +{ + uint32_t *eseq; + if (keyval >= ea->nkeys) + { + printf ("received key %u >= nkeys %u\n", keyval, ea->nkeys); + exit (3); + } + ddsrt_mutex_lock (&ea->lock); + for (uint32_t i = 0; i < ea->nph; i++) + if (pubhandle == ea->ph[i]) + { + uint32_t e = ea->eseq[i][keyval]; + ea->eseq[i][keyval] = seq + ea->nkeys; + ea->stats[i].nrecv++; + ea->stats[i].nrecv_bytes += size; + ea->stats[i].nlost += seq - e; + ddsrt_mutex_unlock (&ea->lock); + return seq == e; + } + ea->ph = realloc (ea->ph, (ea->nph + 1) * sizeof (*ea->ph)); + ea->ph[ea->nph] = pubhandle; + ea->eseq = realloc (ea->eseq, (ea->nph + 1) * sizeof (*ea->eseq)); + ea->eseq[ea->nph] = malloc (ea->nkeys * sizeof (*ea->eseq[ea->nph])); + eseq = ea->eseq[ea->nph]; + for (unsigned i = 0; i < ea->nkeys; i++) + eseq[i] = seq + (i - keyval) + (i <= keyval ? ea->nkeys : 0); + ea->stats = realloc (ea->stats, (ea->nph + 1) * sizeof (*ea->stats)); + memset (&ea->stats[ea->nph], 0, sizeof (ea->stats[ea->nph])); + ea->stats[ea->nph].nrecv = 1; + ea->stats[ea->nph].nrecv_bytes = size; + ea->nph++; + ddsrt_mutex_unlock (&ea->lock); + return 1; +} + +static dds_instance_handle_t get_pphandle_for_pubhandle (dds_instance_handle_t pubhandle) +{ + /* FIXME: implement the get_matched_... interfaces so there's no need for keeping a reader + (and having to GC it, which I'm skipping here ...) */ + int32_t n; + void *msg = NULL; + dds_sample_info_t info; + if ((n = dds_read_instance (rd_publications, &msg, &info, 1, 1, pubhandle)) < 0) + error2 ("dds_read_instance(rd_publications, %"PRIx64") failed: %d\n", pubhandle, (int) n); + else if (n == 0 || !info.valid_data) + { + printf ("get_pong_writer: publication handle %"PRIx64" not found\n", pubhandle); + fflush (stdout); + return 0; + } + else + { + const dds_builtintopic_endpoint_t *sample = msg; + dds_instance_handle_t pphandle = sample->participant_instance_handle; + dds_return_loan (rd_publications, &msg, n); + return pphandle; + } +} + +static bool update_roundtrip (dds_instance_handle_t pubhandle, uint64_t tdelta, bool isping, uint32_t seq) +{ + bool allseen; + ddsrt_mutex_lock (&pongstat_lock); + if (isping && seq == cur_ping_seq) + allseen = (++n_pong_seen == n_pong_expected); + else + allseen = false; + for (uint32_t i = 0; i < npongstat; i++) + if (pongstat[i].pubhandle == pubhandle) + { + struct subthread_arg_pongstat * const x = &pongstat[i]; + if (tdelta < x->min) x->min = tdelta; + if (tdelta > x->max) x->max = tdelta; + x->sum += tdelta; + x->cnt++; + ddsrt_mutex_unlock (&pongstat_lock); + return allseen; + } + pongstat = realloc (pongstat, (npongstat + 1) * sizeof (*pongstat)); + struct subthread_arg_pongstat * const x = &pongstat[npongstat]; + x->pubhandle = pubhandle; + x->pphandle = get_pphandle_for_pubhandle (pubhandle); + x->min = x->max = x->sum = tdelta; + x->cnt = 1; + npongstat++; + ddsrt_mutex_unlock (&pongstat_lock); + return allseen; +} + +static dds_entity_t get_pong_writer_locked (dds_instance_handle_t pubhandle) +{ + dds_instance_handle_t pphandle; + + for (uint32_t j = 0; j < npongwr; j++) + if (pongwr[j].pubhandle == pubhandle) + return pongwr[j].wr_pong; + + /* FIXME: implement the get_matched_... interfaces so there's no need for keeping a reader + (and having to GC it, which I'm skipping here ...) */ + pphandle = get_pphandle_for_pubhandle (pubhandle); + + /* This gets called when no writer is associaed yet with pubhandle, but it may be that a writer + is associated already with pphandle (because there is the data writer and the ping writer) */ + for (uint32_t i = 0; i < npongwr; i++) + { + if (pongwr[i].pphandle == pphandle) + { + dds_entity_t wr_pong = pongwr[i].wr_pong; + if (pongwr[i].pubhandle == 0) + { + pongwr[i].pubhandle = pubhandle; + ddsrt_mutex_unlock (&pongwr_lock); + return wr_pong; + } + else + { + pongwr = realloc (pongwr, (npongwr + 1) * sizeof (*pongwr)); + pongwr[npongwr].pubhandle = pubhandle; + pongwr[npongwr].pphandle = pphandle; + pongwr[npongwr].wr_pong = wr_pong; + npongwr++; + ddsrt_mutex_unlock (&pongwr_lock); + return wr_pong; + } + } + } + printf ("get_pong_writer: participant handle %"PRIx64" not found\n", pphandle); + fflush (stdout); + return 0; +} + +static dds_entity_t get_pong_writer (dds_instance_handle_t pubhandle) +{ + dds_entity_t wr_pong = 0; + ddsrt_mutex_lock (&pongwr_lock); + wr_pong = get_pong_writer_locked (pubhandle); + ddsrt_mutex_unlock (&pongwr_lock); + return wr_pong; +} + +static bool process_data (dds_entity_t rd, struct subthread_arg *arg) +{ + uint32_t max_samples = arg->max_samples; + dds_sample_info_t *iseq = arg->iseq; + void **mseq = arg->mseq; + int32_t nread_data; + if ((nread_data = dds_take (rd, mseq, iseq, max_samples, max_samples)) < 0) + error2 ("dds_take (rd_data): %d\n", (int) nread_data); + for (int32_t i = 0; i < nread_data; i++) + { + if (iseq[i].valid_data) + { + uint32_t seq, keyval, size; + switch (topicsel) + { + case KS: { KeyedSeq *d = (KeyedSeq *) mseq[i]; keyval = d->keyval; seq = d->seq; size = 12 + d->baggage._length; } break; + case K32: { Keyed32 *d = (Keyed32 *) mseq[i]; keyval = d->keyval; seq = d->seq; size = 32; } break; + case K256: { Keyed256 *d = (Keyed256 *) mseq[i]; keyval = d->keyval; seq = d->seq; size = 256; } break; + case OU: { OneULong *d = (OneULong *) mseq[i]; keyval = 0; seq = d->seq; size = 4; } break; + } + (void) check_eseq (&eseq_admin, seq, keyval, size, iseq[i].publication_handle); + if (iseq[i].source_timestamp & 1) + { + dds_entity_t wr_pong = 0; + if ((wr_pong = get_pong_writer (iseq[i].publication_handle)) != 0) + { + dds_return_t rc; + if ((rc = dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp - 1)) < 0 && dds_err_nr(rc) != DDS_RETCODE_TIMEOUT) + error2 ("dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp): %d\n", (int) rc); + dds_write_flush (wr_pong); + } + } + } + } + return (nread_data > 0); +} + +static bool process_ping (dds_entity_t rd, struct subthread_arg *arg) +{ + /* Ping sends back Pongs with the lsb 1; Data sends back Pongs with the lsb 0. This way, the Pong handler can + figure out whether to Ping again or not by looking at the lsb. If it is 1, another Ping is required */ + uint32_t max_samples = arg->max_samples; + dds_sample_info_t *iseq = arg->iseq; + void **mseq = arg->mseq; + int32_t nread_ping; + if ((nread_ping = dds_take (rd, mseq, iseq, max_samples, max_samples)) < 0) + error2 ("dds_take (rd_data): %d\n", (int) nread_ping); + for (int32_t i = 0; i < nread_ping; i++) + { + if (iseq[i].valid_data) + { + dds_entity_t wr_pong; + if ((wr_pong = get_pong_writer (iseq[i].publication_handle)) != 0) + { + dds_return_t rc; + if ((rc = dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp | 1)) < 0 && dds_err_nr(rc) != DDS_RETCODE_TIMEOUT) + error2 ("dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp): %d\n", (int) rc); + dds_write_flush (wr_pong); + } + } + } + return (nread_ping > 0); +} + +static bool process_pong (dds_entity_t rd, struct subthread_arg *arg) +{ + uint32_t max_samples = arg->max_samples; + dds_sample_info_t *iseq = arg->iseq; + void **mseq = arg->mseq; + int32_t nread_pong; + if ((nread_pong = dds_take (rd, mseq, iseq, max_samples, max_samples)) < 0) + error2 ("dds_take (rd_pong): %d\n", (int) nread_pong); + else if (nread_pong > 0) + { + dds_time_t tnow = dds_time (); + for (int32_t i = 0; i < nread_pong; i++) + if (iseq[i].valid_data) + { + uint32_t * const seq = mseq[i]; + const bool isping = (iseq[i].source_timestamp & 1) != 0; + const bool all = update_roundtrip (iseq[i].publication_handle, (uint64_t) (tnow - iseq[i].source_timestamp) / 2, isping, *seq); + if (isping && all && ping_intv == 0) + { + /* If it is a pong sent in response to a ping, and all known nodes have responded, send out a new ping */ + dds_return_t rc; + ddsrt_mutex_lock (&pongwr_lock); + n_pong_seen = 0; + cur_ping_time = dds_time (); + cur_ping_seq = ++(*seq); + ddsrt_mutex_unlock (&pongwr_lock); + if ((rc = dds_write_ts (wr_ping, mseq[i], dds_time () | 1)) < 0 && dds_err_nr(rc) != DDS_RETCODE_TIMEOUT) + error2 ("dds_write (wr_ping, mseq[i]): %d\n", (int) rc); + dds_write_flush (wr_ping); + } + } + } + return (nread_pong > 0); +} + +static void maybe_send_new_ping (dds_time_t tnow, dds_time_t *tnextping) +{ + void *baggage; + union data data; + int32_t rc; + assert (ping_intv != DDS_INFINITY); + ddsrt_mutex_lock (&pongwr_lock); + if (tnow < cur_ping_time + (ping_intv == 0 ? DDS_SECS (1) : ping_intv)) + { + if (ping_intv == 0) + *tnextping = cur_ping_time + DDS_SECS (1); + ddsrt_mutex_unlock (&pongwr_lock); + } + else + { + if (tnow > twarn_ping_timeout) + { + printf ("[%"PRIdPID"] ping timed out ... sending new ping\n", ddsrt_getpid ()); + fflush (stdout); + } + n_pong_seen = 0; + cur_ping_time = tnow; + if (ping_intv > 0) + *tnextping = cur_ping_time + ping_intv; + else if (ping_intv == 0) + *tnextping = cur_ping_time + DDS_SECS (1); + if (ping_intv > 0 && *tnextping > twarn_ping_timeout) + twarn_ping_timeout = *tnextping + ping_intv / 2; + cur_ping_seq++; + baggage = init_sample (&data, cur_ping_seq); + ddsrt_mutex_unlock (&pongwr_lock); + if ((rc = dds_write_ts (wr_ping, &data, dds_time () | 1)) < 0 && dds_err_nr (rc) != DDS_RETCODE_TIMEOUT) + error2 ("send_new_ping: dds_write (wr_ping, &data): %d\n", (int) rc); + dds_write_flush (wr_ping); + if (baggage) + free (baggage); + } +} + +static uint32_t subthread_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_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); + while (!termflag) + { + if (!process_data (rd_data, arg)) + { + /* when we use DATA_AVAILABLE, we must read until nothing remains, or we would deadlock + if more than max_samples were available and nothing further is received */ + int32_t nxs; + if ((nxs = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY)) < 0) + error2 ("dds_waitset_wait: %d\n", (int) nxs); + } + } + return 0; +} + +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); + while (!termflag) + { + int32_t nxs; + if ((nxs = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY)) < 0) + error2 ("dds_waitset_wait: %d\n", (int) nxs); + process_ping (rd_ping, arg); + } + return 0; +} + +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); + while (!termflag) + { + int32_t nxs; + if ((nxs = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY)) < 0) + error2 ("dds_waitset_wait: %d\n", (int) nxs); + process_pong (rd_pong, arg); + } + return 0; +} + +static uint32_t subthread_polling (void *varg) +{ + struct subthread_arg * const arg = varg; + while (!termflag) + { + if (!process_data (rd_data, arg)) + dds_sleepfor (DDS_MSECS (1)); + } + return 0; +} + +static void data_available_listener (dds_entity_t rd, void *arg) +{ + process_data (rd, arg); +} + +static void ping_available_listener (dds_entity_t rd, void *arg) +{ + process_ping (rd, arg); +} + +static void pong_available_listener (dds_entity_t rd, void *arg) +{ + process_pong (rd, arg); +} + +static dds_entity_t create_pong_writer (dds_instance_handle_t pphandle, const struct guidstr *guidstr) +{ + dds_qos_t *qos; + dds_listener_t *listener; + dds_entity_t pongpub; + dds_entity_t wr_pong; + + //printf ("[%"PRIdPID"] create_pong_writer: creating writer in partition %s pubhandle %"PRIx64"\n", ddsrt_getpid (), guidstr->str, pphandle); + //fflush (stdout); + + qos = dds_create_qos (); + dds_qset_partition1 (qos, guidstr->str); + if ((pongpub = dds_create_publisher (dp, qos, NULL)) < 0) + error2 ("dds_create_publisher failed: %d\n", (int) pongpub); + dds_delete_qos (qos); + + listener = dds_create_listener ((void *) (uintptr_t) MM_RD_PONG); + dds_lset_publication_matched (listener, publication_matched_listener); + qos = dds_create_qos (); + dds_qset_history (qos, DDS_HISTORY_KEEP_LAST, 1); + dds_qset_ignorelocal (qos, ignorelocal); + if ((wr_pong = dds_create_writer (pongpub, tp_pong, qos, listener)) < 0) + error2 ("dds_create_writer(%s) failed: %d\n", tpname_pong, (int) wr_pong); + dds_delete_qos (qos); + dds_delete_listener (listener); + + ddsrt_mutex_lock (&pongwr_lock); + pongwr = realloc (pongwr, (npongwr + 1) * sizeof (*pongwr)); + pongwr[npongwr].pubhandle = 0; + pongwr[npongwr].pphandle = pphandle; + pongwr[npongwr].wr_pong = wr_pong; + npongwr++; + ddsrt_mutex_unlock (&pongwr_lock); + return wr_pong; +} + +static void delete_pong_writer (dds_instance_handle_t pphandle) +{ + uint32_t i = 0; + dds_entity_t wr_pong = 0; + ddsrt_mutex_lock (&pongwr_lock); + while (i < npongwr) + { + if (pongwr[i].pphandle != pphandle) + i++; + else + { + assert (wr_pong == 0 || wr_pong == pongwr[i].wr_pong); + memmove (&pongwr[i], &pongwr[i+1], (npongwr - i) * sizeof (pongwr[0])); + npongwr--; + } + } + ddsrt_mutex_unlock (&pongwr_lock); + if (wr_pong) + dds_delete (wr_pong); +} + +static void participant_data_listener (dds_entity_t rd, void *arg) +{ + dds_sample_info_t info; + void *msg = NULL; + uint32_t n_pong_expected_delta = 0; + int32_t n; + (void) arg; + while ((n = dds_take (rd, &msg, &info, 1, 1)) > 0) + { + struct ppant *pp; + assert (info.instance_state != DDS_ALIVE_INSTANCE_STATE || info.valid_data); + if (info.instance_state != DDS_ALIVE_INSTANCE_STATE) + { + ddsrt_avl_dpath_t dpath; + ddsrt_mutex_lock (&disc_lock); + if ((pp = ddsrt_avl_lookup_dpath (&ppants_td, &ppants, &info.instance_handle, &dpath)) != NULL) + { + printf ("[%"PRIdPID"] participant %s:%"PRIu32": gone\n", ddsrt_getpid (), pp->hostname, pp->pid); + fflush (stdout); + + if (pp->handle != dp_handle || ignorelocal == DDS_IGNORELOCAL_NONE) + { + delete_pong_writer (pp->handle); + n_pong_expected_delta--; + } + + ddsrt_avl_delete_dpath (&ppants_td, &ppants, pp, &dpath); + if (pp->tdeadline != DDS_NEVER) + ddsrt_fibheap_delete (&ppants_to_match_fhd, &ppants_to_match, pp); + free (pp); + } + ddsrt_mutex_unlock (&disc_lock); + } + else + { + const dds_builtintopic_participant_t *sample = msg; + void *vudata; + size_t usz; + ddsrt_avl_ipath_t ipath; + /* 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) + { + const char *udata = vudata; + int has_reader, pos; + long pid; + if (sscanf (udata, UDATA_MAGIC "%d:%ld%n", &has_reader, &pid, &pos) == 2 && udata[pos] == ':' && strlen (udata + pos) == usz - (unsigned) pos) + { + size_t sz = usz - (unsigned) pos; + char *hostname = malloc (sz); + memcpy (hostname, udata + pos + 1, sz); + ddsrt_mutex_lock (&disc_lock); + if ((pp = ddsrt_avl_lookup_ipath (&ppants_td, &ppants, &info.instance_handle, &ipath)) != NULL) + free (hostname); + else + { + printf ("[%"PRIdPID"] participant %s:%"PRIu32": new%s\n", ddsrt_getpid (), hostname, (uint32_t) pid, (info.instance_handle == dp_handle) ? " (self)" : ""); + pp = malloc (sizeof (*pp)); + pp->handle = info.instance_handle; + pp->guid = sample->key; + pp->hostname = hostname; + pp->pid = (uint32_t) pid; + pp->tdisc = dds_time (); + pp->tdeadline = pp->tdisc + DDS_SECS (5); + if (pp->handle != dp_handle || ignorelocal == DDS_IGNORELOCAL_NONE) + pp->unmatched = MM_ALL & ~(has_reader ? 0 : MM_RD_DATA) & ~(rd_data ? 0 : MM_WR_DATA); + else + pp->unmatched = 0; + 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++; + } + } + ddsrt_mutex_unlock (&disc_lock); + } + dds_free (vudata); + } + } + dds_return_loan (rd, &msg, n); + } + if (n < 0) + error2 ("dds_take(rd_participants): error %d\n", (int) n); + + if (n_pong_expected_delta) + { + ddsrt_mutex_lock (&pongstat_lock); + n_pong_expected += n_pong_expected_delta; + /* potential initial packet loss & lazy writer creation conspire against receiving + the expected number of responses, so allow for a few attempts before starting to + warn about timeouts */ + twarn_ping_timeout = dds_time () + DDS_MSECS (3333); + //printf ("[%"PRIdPID"] n_pong_expected = %u\n", ddsrt_getpid (), n_pong_expected); + ddsrt_mutex_unlock (&pongstat_lock); + } +} + +static void endpoint_matched_listener (uint32_t match_mask, dds_entity_t rd_epinfo, dds_instance_handle_t remote_endpoint) +{ + dds_sample_info_t info; + void *msg = NULL; + int32_t n; + + /* update participant data so this remote endpoint's participant will be known */ + participant_data_listener (rd_participants, NULL); + + /* FIXME: implement the get_matched_... interfaces so there's no need for keeping a reader + (and having to GC it, which I'm skipping here ...) */ + if ((n = dds_read_instance (rd_epinfo, &msg, &info, 1, 1, remote_endpoint)) < 0) + error2 ("dds_read_instance(rd_epinfo, %"PRIx64") failed: %d\n", remote_endpoint, (int) n); + else if (n == 0) + printf ("[%"PRIdPID"] endpoint %"PRIx64" not found\n", ddsrt_getpid (), remote_endpoint); + else + { + if (info.valid_data) + { + const dds_builtintopic_endpoint_t *sample = msg; + struct ppant *pp; + ddsrt_mutex_lock (&disc_lock); + if ((pp = ddsrt_avl_lookup (&ppants_td, &ppants, &sample->participant_instance_handle)) == NULL) + printf ("[%"PRIdPID"] participant %"PRIx64" no longer exists\n", ddsrt_getpid (), sample->participant_instance_handle); + else + { + pp->unmatched &= ~match_mask; + if (pp->unmatched == 0) + matchcount++; + } + ddsrt_mutex_unlock (&disc_lock); + } + dds_return_loan (rd_epinfo, &msg, n); + } + fflush (stdout); +} + +static const char *match_mask1_to_string (uint32_t mask) +{ + assert ((mask & ~MM_ALL) == 0); + switch (mask) + { + case MM_WR_DATA: return "data writer"; + case MM_RD_DATA: return "data reader"; + case MM_WR_PING: return "ping writer"; + case MM_RD_PING: return "ping reader"; + case MM_WR_PONG: return "pong writer"; + case MM_RD_PONG: return "pong reader"; + } + return "?"; +} + +static char *match_mask_to_string (char *buf, size_t size, uint32_t mask) +{ + size_t pos = 0; + while (pos < size && mask != 0) + { + uint32_t mask1 = mask & (~mask + 1u); + mask &= ~mask1; + int n = snprintf (buf + pos, size - (unsigned) pos, "%s%s", (pos > 0) ? ", " : "", match_mask1_to_string (mask1)); + if (n >= 0) pos += (size_t) n; + } + return buf; +} + +static void subscription_matched_listener (dds_entity_t rd, const dds_subscription_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 ... */ + (void) rd; + if (status.current_count_change > 0) + { + uint32_t mask = (uint32_t) (uintptr_t) arg; + //printf ("[%"PRIdPID"] subscription match: %s\n", ddsrt_getpid (), match_mask1_to_string (mask)); + endpoint_matched_listener (mask, rd_publications, status.last_publication_handle); + } +} + +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 ... */ + (void) wr; + if (status.current_count_change > 0) + { + uint32_t mask = (uint32_t) (uintptr_t) arg; + //printf ("[%"PRIdPID"] publication match: %s\n", ddsrt_getpid (), match_mask1_to_string (mask)); + endpoint_matched_listener (mask, rd_subscriptions, status.last_subscription_handle); + } +} + +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. */ + dds_listener_t *listener = dds_create_listener (arg); + dds_return_t rc; + dds_lset_data_available (listener, fn); + dds_listener_t *tmplistener = dds_create_listener (NULL); + if ((rc = dds_get_listener (rd, tmplistener)) < 0) + error2 ("dds_get_listener(%s) failed: %d\n", rd_name, (int) rc); + dds_merge_listener (listener, tmplistener); + dds_delete_listener (tmplistener); + + if ((rc = dds_set_listener (rd, listener)) < 0) + error2 ("dds_set_listener(%s) failed: %d\n", rd_name, (int) rc); + dds_delete_listener (listener); +} + +static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) +{ + char prefix[128]; + const double ts = (double) (tnow - tstart) / 1e9; + snprintf (prefix, sizeof (prefix), "[%"PRIdPID"] %.3f ", ddsrt_getpid (), ts); + + if (rate > 0) + { + ddsrt_mutex_lock (&pubstat_lock); + hist_print (prefix, pubstat_hist, tnow - tprev, 1); + ddsrt_mutex_unlock (&pubstat_lock); + } + + if (submode != SM_NONE) + { + struct eseq_admin * const ea = &eseq_admin; + uint64_t tot_nrecv = 0, nrecv = 0, nrecv_bytes = 0, nlost = 0; + ddsrt_mutex_lock (&ea->lock); + for (uint32_t i = 0; i < ea->nph; i++) + { + struct eseq_stat * const x = &ea->stats[i]; + tot_nrecv += x->nrecv; + nrecv += x->nrecv - x->nrecv_ref; + nlost += x->nlost - x->nlost_ref; + nrecv_bytes += x->nrecv_bytes - x->nrecv_bytes_ref; + x->nrecv_ref = x->nrecv; + x->nlost_ref = x->nlost; + x->nrecv_bytes_ref = x->nrecv_bytes; + } + ddsrt_mutex_unlock (&ea->lock); + + if (nrecv > 0) + { + printf ("%s ntot %"PRIu64" delta: %"PRIu64" lost %"PRIu64" rate %.2f Mb/s\n", + prefix, tot_nrecv, nrecv, nlost, (double) nrecv_bytes * 8 / 1e6 / (1e9 * (double) (tnow - tprev))); + } + } + + ddsrt_mutex_lock (&pongstat_lock); + for (uint32_t i = 0; i < npongstat; i++) + { + struct subthread_arg_pongstat * const x = &pongstat[i]; + if (x->cnt > 0) + { + struct ppant *pp; + ddsrt_mutex_lock (&disc_lock); + if ((pp = ddsrt_avl_lookup (&ppants_td, &ppants, &x->pphandle)) == NULL) + printf ("%s %"PRIx64" min %.3fus mean %.3fus max %.3fus cnt %"PRIu32"\n", + prefix, x->pubhandle, (double) x->min / 1e3, + (double) x->sum / (double) x->cnt / 1e3, (double) x->max / 1e3, x->cnt); + else + printf ("%s %s:%d min %.3fus mean %.3fus max %.3fus cnt %"PRIu32"\n", + prefix, pp->hostname, pp->pid, (double) x->min / 1e3, + (double) x->sum / (double) x->cnt / 1e3, (double) x->max / 1e3, x->cnt); + ddsrt_mutex_unlock (&disc_lock); + x->min = UINT64_MAX; + x->max = x->sum = x->cnt = 0; + } + } + ddsrt_mutex_unlock (&pongstat_lock); + fflush (stdout); +} + +static void subthread_arg_init (struct subthread_arg *arg, dds_entity_t rd, uint32_t max_samples) +{ + arg->rd = rd; + arg->max_samples = max_samples; + arg->mseq = malloc (arg->max_samples * sizeof (arg->mseq[0])); + arg->iseq = malloc (arg->max_samples * sizeof (arg->iseq[0])); + for (uint32_t i = 0; i < arg->max_samples; i++) + arg->mseq[i] = NULL; +} + +static void subthread_arg_fini (struct subthread_arg *arg) +{ + dds_return_loan(arg->rd, arg->mseq, (int32_t) arg->max_samples); + free (arg->mseq); + free (arg->iseq); +} + +static void signal_handler (int sig) +{ + (void) sig; + termflag = 1; + dds_set_guardcondition (termcond, true); +} + +#ifndef _WIN32 +static uint32_t sigthread (void *varg) +{ + sigset_t *set = varg; + int sig; + if (sigwait (set, &sig) == 0) + signal_handler (sig); + else + error2 ("sigwait failed: %d\n", errno); + return 0; +} +#endif + +/******************** + COMMAND LINE PARSING + ********************/ + +static void usage (void) +{ + printf ("\ +%s help\n\ +%s [OPTIONS] MODE...\n\ +\n\ +OPTIONS:\n\ + -T KS|K32|K256|OU topic:\n\ + KS seq num, key value, sequence-of-octets\n\ + K32 seq num, key value, array of 24 octets\n\ + K256 seq num, key value, array of 248 octets\n\ + OU seq num\n\ + -L allow matching with local endpoints\n\ + -u best-effort instead of reliable\n\ + -k all|N keep-all or keep-last-N for data (ping/pong is\n\ + always keep-last-1)\n\ + -n N number of key values to use for data (only for\n\ + topics with a key value)\n\ + -D DUR run for at most DUR seconds\n\ + -N COUNT require at least COUNT matching participants\n\ + -M DUR require those participants to match within DUR seconds\n\ +\n\ +MODE... is zero or more of:\n\ + ping [R[Hz]] [waitset|listener]\n\ + Send a ping upon receiving all expected pongs, or send a ping at\n\ + rate R (optionally suffixed with Hz). The triggering mode is either\n\ + a listener (default, unless -L has been specified) or a waitset.\n\ + pong [waitset|listener]\n\ + A \"dummy\" mode that serves two purposes: configuring the triggering.\n\ + mode (but it is shared with ping's mode), and suppressing the 1Hz ping\n\ + if no other options are selected. It always responds to pings.\n\ + sub [waitset|listener|polling]\n\ + Subscribe to data, with calls to take occurring either in a listener\n\ + (default), when a waitset is triggered, or by polling at 1kHz.\n\ + pub [R[Hz]] [burst N] [[ping] X%%]\n\ + Publish bursts of data at rate R, optionally suffixed with Hz. If\n\ + no rate is given or R is \"inf\", data is published as fast as\n\ + possible. Each burst is a single sample by default, but can be set\n\ + to larger value using \"burst N\".\n\ + If desired, a fraction of the samples can be treated as if it were a\n\ + ping, for this, specify a percentage either as \"ping X%%\" (the\n\ + \"ping\" keyword is optional, the %% sign is not).\n\ +\n\ +If no MODE specified, it defaults to a 1Hz ping + responding to any pings.\n\ +", argv0, argv0); + fflush (stdout); + exit (3); +} + +struct string_int_map_elem { + const char *name; + int value; +}; + +static const struct string_int_map_elem modestrings[] = { + { "ping", 1 }, + { "pong", 2 }, + { "sub", 3 }, + { "pub", 4 }, + { NULL, 0 } +}; + +static const struct string_int_map_elem pingpongmodes[] = { + { "waitset", SM_WAITSET }, + { "listener", SM_LISTENER }, + { NULL, 0 } +}; + +static int exact_string_int_map_lookup (const struct string_int_map_elem *elems, const char *label, const char *str, bool notfound_error) +{ + for (size_t i = 0; elems[i].name; i++) + if (strcmp (elems[i].name, str) == 0) + return elems[i].value; + if (notfound_error) + error3 ("%s: undefined %s", str, label); + return -1; +} + +static int string_int_map_lookup (const struct string_int_map_elem *elems, const char *label, const char *str, bool notfound_error) +{ + size_t match = SIZE_MAX; + size_t len = strlen (str); + bool ambiguous = false; + for (size_t i = 0; elems[i].name; i++) + { + if (strcmp (elems[i].name, str) == 0) + return elems[match].value; + else if (len >= 3 && strlen (elems[i].name) >= 3 && strncmp (elems[i].name, str, len) == 0) + { + if (match == SIZE_MAX) + match = i; + else + ambiguous = true; + } + } + if (ambiguous) + error3 ("%s: ambiguous %sspecification", str, label); + if (match == SIZE_MAX && notfound_error) + error3 ("%s: undefined %s", str, label); + return (match == SIZE_MAX) ? -1 : elems[match].value; +} + +static void set_mode_ping (int *xoptind, int xargc, char * const xargv[]) +{ + ping_intv = 0; + pingpongmode = SM_LISTENER; + while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1) + { + int pos; + double r; + if (strcmp (xargv[*xoptind], "inf") == 0) + { + ping_intv = 0; + } + else if (sscanf (xargv[*xoptind], "%lf%n", &r, &pos) == 1 && (xargv[*xoptind][pos] == 0 || strcmp (xargv[*xoptind] + pos, "Hz") == 0)) + { + if (r == 0) ping_intv = DDS_INFINITY; + else if (r > 0) ping_intv = (dds_duration_t) (1e9 / rate + 0.5); + else error3 ("%s: invalid ping rate\n", xargv[*xoptind]); + } + else + { + pingpongmode = (enum submode) string_int_map_lookup (pingpongmodes, "ping mode", xargv[*xoptind], true); + } + (*xoptind)++; + } +} + +static void set_mode_pong (int *xoptind, int xargc, char * const xargv[]) +{ + pingpongmode = SM_LISTENER; + while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1) + { + pingpongmode = (enum submode) string_int_map_lookup (pingpongmodes, "pong mode", xargv[*xoptind], true); + (*xoptind)++; + } +} + +static void set_mode_sub (int *xoptind, int xargc, char * const xargv[]) +{ + static const struct string_int_map_elem submodes[] = { + { "waitset", SM_WAITSET }, + { "polling", SM_POLLING }, + { "listener", SM_LISTENER }, + { NULL, 0 } + }; + submode = SM_LISTENER; + while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1) + { + submode = (enum submode) string_int_map_lookup (submodes, "subscription mode", xargv[*xoptind], true); + (*xoptind)++; + } +} + +static void set_mode_pub (int *xoptind, int xargc, char * const xargv[]) +{ + rate = HUGE_VAL; + burstsize = 1; + ping_frac = 0; + while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1) + { + int pos = 0; + double r; + if (strcmp (xargv[*xoptind], "inf") == 0 || strcmp (xargv[*xoptind], "infHz") == 0) + { + rate = HUGE_VAL; + } + else if (sscanf (xargv[*xoptind], "%lf%n", &r, &pos) == 1 && (xargv[*xoptind][pos] == 0 || strcmp (xargv[*xoptind] + pos, "Hz") == 0)) + { + if (r < 0) error3 ("%s: invalid publish rate\n", xargv[*xoptind]); + rate = r; + } + else if (strcmp (xargv[*xoptind], "burst") == 0) + { + unsigned b; + if (++(*xoptind) == xargc) + error3 ("argument missing in burst size specification\n"); + if (sscanf (xargv[*xoptind], "%u%n", &b, &pos) == 1 && xargv[*xoptind][pos] == 0) + burstsize = b; + else + error3 ("%s: invalid burst size specification\n", xargv[*xoptind]); + } + else if (sscanf (xargv[*xoptind], "%lf%n", &r, &pos) == 1 && strcmp (xargv[*xoptind] + pos, "%") == 0) + { + if (r < 0 || r > 100) error3 ("%s: ping fraction out of range\n", xargv[*xoptind]); + ping_frac = (uint32_t) (UINT32_MAX * (r / 100.0) + 0.5); + } + else if (strcmp (xargv[*xoptind], "ping") == 0 && *xoptind + 1 < xargc && sscanf (xargv[*xoptind + 1], "%lf%%%n", &rate, &pos) == 1 && xargv[*xoptind + 1][pos] == 0) + { + ++(*xoptind); + if (r < 0 || r > 100) error3 ("%s: ping fraction out of range\n", xargv[*xoptind]); + ping_frac = (uint32_t) (UINT32_MAX * (r / 100.0) + 0.5); + } + else + { + error3 ("%s: unrecognised publish specification\n", xargv[*xoptind]); + } + (*xoptind)++; + } +} + +static void set_mode (int xoptind, int xargc, char * const xargv[]) +{ + int code; + rate = 0.0; + submode = SM_NONE; + pingpongmode = SM_LISTENER; + ping_intv = (xoptind == xargc) ? DDS_SECS (1) : DDS_INFINITY; + ping_frac = 0; + while (xoptind < xargc && (code = exact_string_int_map_lookup (modestrings, "mode string", xargv[xoptind], true)) != -1) + { + xoptind++; + switch (code) + { + case 1: set_mode_ping (&xoptind, xargc, xargv); break; + case 2: set_mode_pong (&xoptind, xargc, xargv); break; + case 3: set_mode_sub (&xoptind, xargc, xargv); break; + case 4: set_mode_pub (&xoptind, xargc, xargv); break; + } + } + if (xoptind != xargc) + { + error3 ("%s: unrecognized argument\n", xargv[xoptind]); + } +} + +int main (int argc, char *argv[]) +{ + dds_entity_t ws; + dds_return_t rc; + dds_qos_t *qos; + dds_listener_t *listener; + int opt; + ddsrt_threadattr_t attr; + ddsrt_thread_t pubtid, subtid, subpingtid, subpongtid; +#ifndef _WIN32 + sigset_t sigset, osigset; + ddsrt_thread_t sigtid; +#endif + ddsrt_threadattr_init (&attr); + + argv0 = argv[0]; + + if (argc == 2 && strcmp (argv[1], "help") == 0) + usage (); + while ((opt = getopt (argc, argv, "D:n:z:k:uLT:M:N:h")) != EOF) + { + switch (opt) + { + case 'D': dur = atof (optarg); if (dur <= 0) dur = HUGE_VAL; break; + case 'n': nkeyvals = (unsigned) atoi (optarg); break; + case 'u': reliable = false; break; + case 'k': histdepth = atoi (optarg); if (histdepth < 0) histdepth = 0; break; + case 'L': ignorelocal = DDS_IGNORELOCAL_NONE; break; + case 'T': + if (strcmp (optarg, "KS") == 0) topicsel = KS; + else if (strcmp (optarg, "K32") == 0) topicsel = K32; + else if (strcmp (optarg, "K256") == 0) topicsel = K256; + else if (strcmp (optarg, "OU") == 0) topicsel = OU; + else error3 ("%s: unknown topic\n", optarg); + break; + case 'M': maxwait = atof (optarg); if (maxwait <= 0) maxwait = HUGE_VAL; break; + case 'N': minmatch = (unsigned) atoi (optarg); break; + case 'z': baggagesize = (unsigned) atoi (optarg); break; + case 'h': usage (); break; + default: error3 ("-%c: unknown option\n", opt); break; + } + } + set_mode (optind, argc, argv); + + if (nkeyvals == 0) + nkeyvals = 1; + if (topicsel == OU && nkeyvals != 1) + error3 ("-n%u invalid: topic OU has no key\n", nkeyvals); + if (topicsel != KS && baggagesize != 0) + error3 ("-z%u invalid: only topic KS has a sequence\n", baggagesize); + + ddsrt_avl_init (&ppants_td, &ppants); + ddsrt_fibheap_init (&ppants_to_match_fhd, &ppants_to_match); + + ddsrt_mutex_init (&disc_lock); + ddsrt_mutex_init (&pongstat_lock); + ddsrt_mutex_init (&pongwr_lock); + ddsrt_mutex_init (&pubstat_lock); + + pubstat_hist = hist_new (30, 1000, 0); + + qos = dds_create_qos (); + /* set user data: magic cookie, whether we have a reader for the Data topic + (all other endpoints always exist), and our hostname */ + { + unsigned pos; + char udata[256]; + pos = (unsigned) snprintf (udata, sizeof (udata), UDATA_MAGIC"%d:%"PRIdPID":", submode != SM_NONE, ddsrt_getpid ()); + assert (pos < sizeof (udata)); + if (ddsrt_gethostname (udata + pos, sizeof (udata) - pos) != DDS_RETCODE_OK) + strcpy (udata + UDATA_MAGIC_SIZE, "?"); + dds_qset_userdata (qos, udata, strlen (udata)); + } + if ((dp = dds_create_participant (did, qos, NULL)) < 0) + error2 ("dds_create_participant(domain %d) failed: %d\n", (int) did, (int) dp); + dds_delete_qos (qos); + dds_write_set_batch (true); + if ((rc = dds_get_instance_handle (dp, &dp_handle)) < 0) + error2 ("dds_get_instance_handle(participant) failed: %d\n", (int) rc); + + qos = dds_create_qos (); + dds_qset_partition1 (qos, "DDSPerf"); + if ((sub = dds_create_subscriber (dp, NULL, NULL)) < 0) + error2 ("dds_create_subscriber failed: %d\n", (int) dp); + if ((pub = dds_create_publisher (dp, NULL, NULL)) < 0) + error2 ("dds_create_publisher failed: %d\n", (int) dp); + dds_delete_qos (qos); + + { + const char *tp_suf = ""; + const dds_topic_descriptor_t *tp_desc = NULL; + switch (topicsel) + { + case KS: tp_suf = "KS"; tp_desc = &KeyedSeq_desc; break; + case K32: tp_suf = "K32"; tp_desc = &Keyed32_desc; break; + case K256: tp_suf = "K256"; tp_desc = &Keyed256_desc; break; + case OU: tp_suf = "OU"; tp_desc = &OneULong_desc; break; + } + snprintf (tpname_data, sizeof (tpname_data), "DDSPerf%cData%s", reliable ? 'R' : 'U', tp_suf); + snprintf (tpname_ping, sizeof (tpname_ping), "DDSPerf%cPing%s", reliable ? 'R' : 'U', tp_suf); + snprintf (tpname_pong, sizeof (tpname_pong), "DDSPerf%cPong%s", reliable ? 'R' : 'U', tp_suf); + qos = dds_create_qos (); + dds_qset_reliability (qos, reliable ? DDS_RELIABILITY_RELIABLE : DDS_RELIABILITY_BEST_EFFORT, DDS_SECS (1)); + if ((tp_data = dds_create_topic (dp, tp_desc, tpname_data, qos, NULL)) < 0) + error2 ("dds_create_topic(%s) failed: %d\n", tpname_data, (int) tp_data); + if ((tp_ping = dds_create_topic (dp, tp_desc, tpname_ping, qos, NULL)) < 0) + error2 ("dds_create_topic(%s) failed: %d\n", tpname_ping, (int) tp_ping); + if ((tp_pong = dds_create_topic (dp, tp_desc, tpname_pong, qos, NULL)) < 0) + error2 ("dds_create_topic(%s) failed: %d\n", tpname_pong, (int) tp_pong); + dds_delete_qos (qos); + } + + /* participants reader must exist before the "publication matched" or "subscription matched" + listener is invoked, or it won't be able to get the details (FIXME: even the DDS spec + has convenience functions for that ...) */ + listener = dds_create_listener (NULL); + dds_lset_data_available (listener, participant_data_listener); + if ((rd_participants = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPARTICIPANT, NULL, listener)) < 0) + error2 ("dds_create_reader(participants) failed: %d\n", (int) rd_participants); + dds_delete_listener (listener); + if ((rd_subscriptions = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL)) < 0) + error2 ("dds_create_reader(subscriptions) failed: %d\n", (int) rd_subscriptions); + if ((rd_publications = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, NULL, NULL)) < 0) + error2 ("dds_create_reader(publications) failed: %d\n", (int) rd_publications); + + /* ping reader/writer uses keep-last-1 history; not checking matching on these (yet) */ + qos = dds_create_qos (); + dds_qset_history (qos, DDS_HISTORY_KEEP_LAST, 1); + dds_qset_ignorelocal (qos, ignorelocal); + listener = dds_create_listener ((void *) (uintptr_t) MM_WR_PING); + dds_lset_subscription_matched (listener, subscription_matched_listener); + if ((rd_ping = dds_create_reader (sub, tp_ping, qos, listener)) < 0) + error2 ("dds_create_reader(%s) failed: %d\n", tpname_ping, (int) rd_ping); + dds_delete_listener (listener); + listener = dds_create_listener ((void *) (uintptr_t) MM_RD_PING); + dds_lset_publication_matched (listener, publication_matched_listener); + if ((wr_ping = dds_create_writer (pub, tp_ping, qos, listener)) < 0) + error2 ("dds_create_writer(%s) failed: %d\n", tpname_ping, (int) wr_ping); + dds_delete_listener (listener); + dds_delete_qos (qos); + + /* data reader/writer use a keep-all history with generous resource limits. */ + qos = dds_create_qos (); + if (histdepth == 0) + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 1); + else + dds_qset_history (qos, DDS_HISTORY_KEEP_LAST, histdepth); + dds_qset_resource_limits (qos, 10000, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED); + dds_qset_ignorelocal (qos, ignorelocal); + listener = dds_create_listener ((void *) (uintptr_t) MM_WR_DATA); + dds_lset_subscription_matched (listener, subscription_matched_listener); + if (submode != SM_NONE && (rd_data = dds_create_reader (sub, tp_data, qos, listener)) < 0) + error2 ("dds_create_reader(%s) failed: %d\n", tpname_data, (int) rd_data); + dds_delete_listener (listener); + listener = dds_create_listener ((void *) (uintptr_t) MM_RD_DATA); + dds_lset_publication_matched (listener, publication_matched_listener); + if ((wr_data = dds_create_writer (pub, tp_data, qos, listener)) < 0) + error2 ("dds_create_writer(%s) failed: %d\n", tpname_data, (int) wr_data); + dds_delete_listener (listener); + + /* We only need a pong reader when sending data with a non-zero probability + of it being a "ping", or when sending "real" pings. I.e., if + rate > 0 && ping_frac > 0) || ping_intv != DDS_NEVER + but it doesn't really hurt to have the reader either, and always creating + it and futhermore eagerly creating the pong writers means we can do more + checking. */ + { + /* participant listener should have already been called for "dp", so we + can simply look up the details on ourself to get at the GUID of the + participant */ + struct guidstr guidstr; + struct ppant *pp; + dds_entity_t sub_pong; + ddsrt_mutex_lock (&disc_lock); + if ((pp = ddsrt_avl_lookup (&ppants_td, &ppants, &dp_handle)) == NULL) + { + printf ("participant %"PRIx64" (self) not found\n", dp_handle); + exit (2); + } + make_guidstr (&guidstr, &pp->guid); + ddsrt_mutex_unlock (&disc_lock); + dds_qos_t *subqos = dds_create_qos (); + dds_qset_partition1 (subqos, guidstr.str); + if ((sub_pong = dds_create_subscriber (dp, subqos, NULL)) < 0) + error2 ("dds_create_subscriber(pong) failed: %d\n", (int) sub_pong); + dds_delete_qos (subqos); + listener = dds_create_listener ((void *) (uintptr_t) MM_WR_PONG); + dds_lset_subscription_matched (listener, subscription_matched_listener); + if ((rd_pong = dds_create_reader (sub_pong, tp_pong, qos, listener)) < 0) + error2 ("dds_create_reader(%s) failed: %d\n", tpname_pong, (int) rd_pong); + dds_delete_listener (listener); + } + dds_delete_qos (qos); + + if ((termcond = dds_create_guardcondition (dp)) < 0) + error2 ("dds_create_guardcondition(termcond) failed: %d\n", (int) termcond); + if ((ws = dds_create_waitset (dp)) < 0) + error2 ("dds_create_waitset(main) failed: %d\n", (int) ws); + if ((rc = dds_waitset_attach (ws, termcond, 0)) < 0) + error2 ("dds_waitset_attach(main, termcond) failed: %d\n", (int) rc); + + /* I hate Unix signals in multi-threaded processes ... */ +#ifdef _WIN32 + signal (SIGINT, signal_handler); +#else + sigemptyset (&sigset); + sigaddset (&sigset, SIGINT); + sigaddset (&sigset, SIGTERM); + sigprocmask (SIG_BLOCK, &sigset, &osigset); + ddsrt_thread_create (&sigtid, "sigthread", &attr, sigthread, &sigset); +#endif + + /* Make publisher & subscriber thread arguments and start the threads we + need (so what if we allocate memory for reading data even if we don't + have a reader or will never really be receiving data) */ + struct subthread_arg subarg_data, subarg_ping, subarg_pong; + init_eseq_admin (&eseq_admin, nkeyvals); + subthread_arg_init (&subarg_data, rd_data, 100); + subthread_arg_init (&subarg_ping, rd_ping, 100); + subthread_arg_init (&subarg_pong, rd_pong, 100); + uint32_t (*subthread_func) (void *arg) = 0; + switch (submode) + { + case SM_NONE: break; + case SM_WAITSET: subthread_func = subthread_waitset; break; + case SM_POLLING: subthread_func = subthread_polling; break; + case SM_LISTENER: break; + } + memset (&pubtid, 0, sizeof (pubtid)); + memset (&subtid, 0, sizeof (subtid)); + memset (&subpingtid, 0, sizeof (subpingtid)); + memset (&subpongtid, 0, sizeof (subpongtid)); + if (rate > 0) + ddsrt_thread_create (&pubtid, "pub", &attr, pubthread, NULL); + if (subthread_func != 0) + ddsrt_thread_create (&subtid, "sub", &attr, subthread_func, &subarg_data); + else if (submode == SM_LISTENER) + set_data_available_listener (rd_data, "rd_data", data_available_listener, &subarg_data); + /* Need to handle incoming "pong"s only if we can be sending "ping"s (whether that + be pings from the "ping" mode (i.e. ping_intv != DDS_NEVER), or pings embedded + in the published data stream (i.e. rate > 0 && ping_frac > 0). The trouble with + the first category is that a publication/subscription pair in the same process + would result in a "thread awake nesting" overflow (and otherwise in a stack + overflow) because each sample triggers the next. So in that particular case we + had better create a waitset. */ + const bool pingpong_waitset = (ping_intv != DDS_NEVER && ignorelocal == DDS_IGNORELOCAL_NONE) || pingpongmode == SM_WAITSET; + if (pingpong_waitset) + { + ddsrt_thread_create (&subpingtid, "sub", &attr, subpingthread_waitset, &subarg_pong); + ddsrt_thread_create (&subpongtid, "sub", &attr, subpongthread_waitset, &subarg_pong); + } + else + { + set_data_available_listener (rd_ping, "rd_ping", ping_available_listener, &subarg_ping); + set_data_available_listener (rd_pong, "rd_pong", pong_available_listener, &subarg_pong); + } + + /* Run until time limit reached or a signal received. (The time calculations + ignore the possibility of overflow around the year 2260.) */ + dds_time_t tnow = dds_time (); + const dds_time_t tstart = tnow; + dds_time_t tmatch = (maxwait == HUGE_VAL) ? DDS_NEVER : tstart + (int64_t) (maxwait * 1e9 + 0.5); + const dds_time_t tstop = (dur == HUGE_VAL) ? DDS_NEVER : tstart + (int64_t) (dur * 1e9 + 0.5); + dds_time_t tnext = tstart + DDS_SECS (1); + dds_time_t tlast = tstart; + dds_time_t tnextping = (ping_intv == DDS_INFINITY) ? DDS_NEVER : (ping_intv == 0) ? tstart + DDS_SECS (1) : tstart + ping_intv; + while (!termflag && tnow < tstop) + { + dds_time_t twakeup = DDS_NEVER; + int32_t nxs; + + /* bail out if too few readers discovered within the deadline */ + if (tnow >= tmatch) + { + bool ok; + ddsrt_mutex_lock (&disc_lock); + ok = (matchcount >= minmatch); + ddsrt_mutex_unlock (&disc_lock); + if (ok) + tmatch = DDS_NEVER; + else + { + /* set minmatch to an impossible value to avoid a match occurring between now and + the determining of the exit status from causing a successful return */ + minmatch = UINT32_MAX; + break; + } + } + + /* sometimes multicast only works one way, thus it makes sense to verify + reader/writer matching takes place within a set amount of time after + discovering the participant. */ + { + struct ppant *pp; + ddsrt_mutex_lock (&disc_lock); + while ((pp = ddsrt_fibheap_min (&ppants_to_match_fhd, &ppants_to_match)) != NULL && pp->tdeadline < tnow) + { + (void) ddsrt_fibheap_extract_min (&ppants_to_match_fhd, &ppants_to_match); + if (pp->unmatched != 0) + { + printf ("[%"PRIdPID"] participant %s:%"PRIu32": failed to match in %.3fs\n", ddsrt_getpid (), pp->hostname, pp->pid, (double) (pp->tdeadline - pp->tdisc) / 1e9); + fflush (stdout); + matchtimeout++; + } + /* keep the participant in the admin so we will never look at it again */ + pp->tdeadline = DDS_NEVER; + } + if (pp && pp->tdeadline < tnext) + { + twakeup = pp->tdeadline; + } + ddsrt_mutex_unlock (&disc_lock); + } + + /* next wakeup should be when the next event occurs */ + if (tnext < twakeup) + twakeup = tnext; + if (tstop < twakeup) + twakeup = tstop; + if (tmatch < twakeup) + twakeup = tmatch; + if (tnextping < twakeup) + twakeup = tnextping; + + if ((nxs = dds_waitset_wait_until (ws, NULL, 0, twakeup)) < 0) + error2 ("dds_waitset_wait_until(main): error %d\n", (int) nxs); + + /* try to print exactly once per second, but do gracefully handle a very late wakeup */ + tnow = dds_time (); + if (tnext <= tnow) + { + print_stats (tstart, tnow, tlast); + tlast = tnow; + if (tnow > tnext + DDS_MSECS (500)) + tnext = tnow + DDS_SECS (1); + else + tnext += DDS_SECS (1); + } + + /* If a "real" ping doesn't result in the expected number of pongs within a reasonable + time, send a new ping to restart the process. This can happen as a result of starting + or stopping a process, as a result of packet loss if best-effort reliability is + selected, or as a result of overwhelming the ping/pong from the data publishing thread + (as the QoS is a simple keep-last-1) */ + if (tnextping <= tnow) + { + maybe_send_new_ping (tnow, &tnextping); + } + } + +#if _WIN32 + signal_handler (SIGINT); +#else + { + /* get the attention of the signal handler thread */ + void (*osigint) (int); + void (*osigterm) (int); + kill (getpid (), SIGTERM); + ddsrt_thread_join (sigtid, NULL); + osigint = signal (SIGINT, SIG_IGN); + osigterm = signal (SIGTERM, SIG_IGN); + sigprocmask (SIG_SETMASK, &osigset, NULL); + signal (SIGINT, osigint); + signal (SIGINT, osigterm); + } +#endif + + if (rate > 0) + ddsrt_thread_join (pubtid, NULL); + if (subthread_func != 0) + ddsrt_thread_join (subtid, NULL); + if (pingpong_waitset) + { + ddsrt_thread_join (subpingtid, NULL); + ddsrt_thread_join (subpongtid, NULL); + } + + /* stop the listeners before deleting the readers: otherwise they may + still try to access a reader that has already become inaccessible + (not quite good, but ...) */ + dds_set_listener (rd_ping, NULL); + dds_set_listener (rd_pong, NULL); + dds_set_listener (rd_data, NULL); + dds_set_listener (rd_participants, NULL); + dds_set_listener (rd_subscriptions, NULL); + dds_set_listener (rd_publications, NULL); + + /* Delete rd_data early to workaround a deadlock deleting a reader + or writer while the receive thread (or a delivery thread) got + stuck trying to write into a reader that hit its resource limits. + + The deadlock is that the deleting of a reader/writer requires + waiting for the DDSI-level entity to be deleted (a multi-stage + GC process), and a "stuck" receive thread prevents the GC from + making progress. + + The fix is to eliminate the waiting and retrying, and instead + flip the reader's state to out-of-sync and rely on retransmits + to let it make progress once room is available again. */ + dds_delete (rd_data); + + uint64_t nlost = 0; + for (uint32_t i = 0; i < eseq_admin.nph; i++) + nlost += eseq_admin.stats[i].nlost; + fini_eseq_admin (&eseq_admin); + subthread_arg_fini (&subarg_data); + subthread_arg_fini (&subarg_ping); + subthread_arg_fini (&subarg_pong); + dds_delete (dp); + ddsrt_mutex_destroy (&disc_lock); + ddsrt_mutex_destroy (&pongwr_lock); + ddsrt_mutex_destroy (&pongstat_lock); + ddsrt_mutex_destroy (&pubstat_lock); + hist_free (pubstat_hist); + + bool ok = true; + + { + ddsrt_avl_iter_t it; + struct ppant *pp; + for (pp = ddsrt_avl_iter_first (&ppants_td, &ppants, &it); pp; pp = ddsrt_avl_iter_next (&it)) + if (pp->unmatched != 0) + { + char buf[256]; + printf ("[%"PRIdPID"] error: %s:%"PRIu32" failed to match %s\n", ddsrt_getpid (), pp->hostname, pp->pid, match_mask_to_string (buf, sizeof (buf), pp->unmatched)); + ok = false; + } + } + if (matchcount < minmatch) + { + printf ("[%"PRIdPID"] error: too few matching participants (%"PRIu32" instead of %"PRIu32")\n", ddsrt_getpid (), matchcount, minmatch); + ok = false; + } + if (nlost > 0 && (reliable && histdepth == 0)) + { + printf ("[%"PRIdPID"] error: %"PRIu64" samples lost\n", ddsrt_getpid (), nlost); + ok = false; + } + return ok ? 0 : 1; +} diff --git a/src/tools/ddsperf/ddsperf_types.idl b/src/tools/ddsperf/ddsperf_types.idl new file mode 100644 index 0000000..806f30d --- /dev/null +++ b/src/tools/ddsperf/ddsperf_types.idl @@ -0,0 +1,29 @@ +struct OneULong +{ + unsigned long seq; +}; +#pragma keylist OneULong + +struct Keyed32 +{ + unsigned long seq; + unsigned long keyval; + octet baggage[24]; +}; +#pragma keylist Keyed32 keyval + +struct Keyed256 +{ + unsigned long seq; + unsigned long keyval; + octet baggage[248]; +}; +#pragma keylist Keyed256 keyval + +struct KeyedSeq +{ + unsigned long seq; + unsigned long keyval; + sequence baggage; +}; +#pragma keylist KeyedSeq keyval From d146716d1da31aa52b961f4c51f5bcfdef328812 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 23 Apr 2019 13:25:40 +0200 Subject: [PATCH 041/178] remove Lease element from test config The element has long been meaningless and got deprecated in commit c3dca32a2f8dc43be79745e65adcc1066d75dc36. Signed-off-by: Erik Boasson --- src/core/ddsc/tests/config_simple_udp.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/core/ddsc/tests/config_simple_udp.xml b/src/core/ddsc/tests/config_simple_udp.xml index 27329bd..f96c737 100644 --- a/src/core/ddsc/tests/config_simple_udp.xml +++ b/src/core/ddsc/tests/config_simple_udp.xml @@ -16,9 +16,6 @@ 3 - - - 127.0.0.1 From 0269774a601f420446962df720712c29d2078474 Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Fri, 5 Apr 2019 15:00:48 +0200 Subject: [PATCH 042/178] Rudimentary process management. Signed-off-by: Martin Bremmer --- src/ddsrt/CMakeLists.txt | 3 +- src/ddsrt/include/dds/ddsrt/process.h | 173 ++++++++- src/ddsrt/src/process.c | 27 -- src/ddsrt/src/process/posix/process.c | 303 ++++++++++++++++ src/ddsrt/src/process/windows/process.c | 447 ++++++++++++++++++++++++ src/ddsrt/tests/CMakeLists.txt | 24 ++ src/ddsrt/tests/process.c | 284 +++++++++++++++ src/ddsrt/tests/process_app.c | 108 ++++++ src/ddsrt/tests/process_test.h.in | 42 +++ 9 files changed, 1378 insertions(+), 33 deletions(-) delete mode 100644 src/ddsrt/src/process.c create mode 100644 src/ddsrt/src/process/posix/process.c create mode 100644 src/ddsrt/src/process/windows/process.c create mode 100644 src/ddsrt/tests/process.c create mode 100644 src/ddsrt/tests/process_app.c create mode 100644 src/ddsrt/tests/process_test.h.in diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 404f425..5b49248 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -74,7 +74,6 @@ list(APPEND sources "${source_path}/io.c" "${source_path}/log.c" "${source_path}/retcode.c" - "${source_path}/process.c" "${source_path}/strtod.c" "${source_path}/strtol.c") @@ -104,7 +103,7 @@ list(APPEND sources # network stack. In order to mix-and-match various compilers, architectures, # operating systems, etc input from the build system is required. foreach(feature atomics cdtors environ heap ifaddrs random rusage - sockets string sync threads time md5) + sockets string sync threads time md5 process) if(EXISTS "${include_path}/dds/ddsrt/${feature}.h") list(APPEND headers "${include_path}/dds/ddsrt/${feature}.h") file(GLOB diff --git a/src/ddsrt/include/dds/ddsrt/process.h b/src/ddsrt/include/dds/ddsrt/process.h index b2be585..45e7099 100644 --- a/src/ddsrt/include/dds/ddsrt/process.h +++ b/src/ddsrt/include/dds/ddsrt/process.h @@ -13,11 +13,9 @@ #define DDSRT_PROCESS_H #include "dds/export.h" +#include "dds/ddsrt/time.h" #include "dds/ddsrt/types.h" - -#if defined (__cplusplus) -extern "C" { -#endif +#include "dds/ddsrt/retcode.h" #if defined(_WIN32) typedef DWORD ddsrt_pid_t; @@ -33,6 +31,11 @@ typedef pid_t ddsrt_pid_t; #endif #endif /* _WIN32 */ + +#if defined (__cplusplus) +extern "C" { +#endif + /** * @brief Return process ID (PID) of the calling process. * @@ -41,6 +44,168 @@ typedef pid_t ddsrt_pid_t; DDS_EXPORT ddsrt_pid_t ddsrt_getpid(void); + +/** + * @brief Create new process. + * + * Creates a new process using the provided executable file. It will have + * default priority and scheduling. + * + * Process arguments are represented by argv, which can be null. If argv is + * not null, then the array must be null terminated. The argv array only has + * to contain the arguments, the executable filename doesn't have to be in + * the first element, which is normally the convention. + * + * @param[in] executable Executable file name. + * @param[in] argv Arguments array. + * @param[out] pid ID of the created process. + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * Process successfully created. + * @retval DDS_RETCODE_BAD_PARAMETER + * Provided file is not available or not executable. + * @retval DDS_RETCODE_NOT_ALLOWED + * Caller is not permitted to start the process. + * @retval DDS_RETCODE_OUT_OF_RESOURCES + * Not enough resources to start the process. + * @retval DDS_RETCODE_ERROR + * Process could not be created. + */ +DDS_EXPORT dds_retcode_t +ddsrt_proc_create( + const char *executable, + char *const argv[], + ddsrt_pid_t *pid); + +/** + * @brief Wait for a specific child process to have finished. + * + * This function takes a process id and will wait until the related process + * has finished or the timeout is reached. + * + * If the process finished, then the exit code of that process will be copied + * into the given 'code' argument. + * + * Internally, the timeout can be round-up to the nearest milliseconds or + * seconds, depending on the platform. + * + * See ddsrt_proc_waitpids() for waiting on all child processes. + * + * @param[in] pid Process ID (PID) to get the exit code from. + * @param[in] timemout Time within the process is expected to finish. + * @param[out] code The exit code of the process. + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * Process has terminated and its exit code has been captured. + * @retval DDS_RETCODE_PRECONDITION_NOT_MET + * Process is still alive (only when timeout == 0). + * @retval DDS_RETCODE_TIMEOUT + * Process is still alive (even after the timeout). + * @retval DDS_RETCODE_BAD_PARAMETER + * Negative timeout. + * @retval DDS_RETCODE_NOT_FOUND + * Process unknown. + * @retval DDS_RETCODE_ERROR + * Getting the exit code failed for an unknown reason. + */ +DDS_EXPORT dds_retcode_t +ddsrt_proc_waitpid( + ddsrt_pid_t pid, + dds_duration_t timeout, + int32_t *code); + +/** + * @brief Wait for a random child process to have finished. + * + * This function will wait until anyone of the child processes has + * finished or the timeout is reached. + * + * If a process finished, then the exit code of that process will be + * copied into the given 'code' argument. The pid of the process will + * be put in the 'pid' argument. + * + * Internally, the timeout can be round-up to the nearest milliseconds or + * seconds, depending on the platform. + * + * See ddsrt_proc_waitpid() for waiting on a specific child process. + * + * @param[in] timemout Time within a process is expected to finish. + * @param[out] pid Process ID (PID) of the finished process. + * @param[out] code The exit code of the process. + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * A process has terminated. + * Its exit code and pid have been captured. + * @retval DDS_RETCODE_PRECONDITION_NOT_MET + * All child processes are still alive (only when timeout == 0). + * @retval DDS_RETCODE_TIMEOUT + * All child processes are still alive (even after the timeout). + * @retval DDS_RETCODE_BAD_PARAMETER + * Negative timeout. + * @retval DDS_RETCODE_NOT_FOUND + * There are no processes to wait for. + * @retval DDS_RETCODE_ERROR + * Getting the exit code failed for an unknown reason. + */ +DDS_EXPORT dds_retcode_t +ddsrt_proc_waitpids( + dds_duration_t timeout, + ddsrt_pid_t *pid, + int32_t *code); + +/** + * @brief Checks if a process exists. + * + * @param[in] pid Process ID (PID) to check if it exists. + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * The process exists. + * @retval DDS_RETCODE_NOT_FOUND + * The process does not exist. + * @retval DDS_RETCODE_ERROR + * Determining if a process exists or not, failed. + */ +DDS_EXPORT dds_retcode_t +ddsrt_proc_exists( + ddsrt_pid_t pid); + +/** + * @brief Kill a process. + * + * This function will try to forcefully kill the process (identified + * by pid). + * + * When DDS_RETCODE_OK is returned, it doesn't mean that the process + * was actually killed. It only indicates that the process was + * 'told' to terminate. Call ddsrt_proc_exists() to know + * for sure if the process was killed. + * + * @param[in] pid Process ID (PID) of the process to terminate. + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * Kill attempt has been started. + * @retval DDS_RETCODE_BAD_PARAMETER + * Process unknown. + * @retval DDS_RETCODE_ILLEGAL_OPERATION + * Caller is not allowed to kill the process. + * @retval DDS_RETCODE_ERROR + * Kill failed for an unknown reason. + */ +DDS_EXPORT dds_retcode_t +ddsrt_proc_kill( + ddsrt_pid_t pid); + + #if defined (__cplusplus) } #endif diff --git a/src/ddsrt/src/process.c b/src/ddsrt/src/process.c deleted file mode 100644 index 4aed282..0000000 --- a/src/ddsrt/src/process.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/ddsrt/process.h" - -#if !defined(_WIN32) -# include -#endif - -ddsrt_pid_t -ddsrt_getpid(void) -{ -#if defined(_WIN32) - return GetCurrentProcessId(); -#else - /* Mapped to taskIdSelf() in VxWorks kernel mode. */ - return getpid(); -#endif -} diff --git a/src/ddsrt/src/process/posix/process.c b/src/ddsrt/src/process/posix/process.c new file mode 100644 index 0000000..f6ed5db --- /dev/null +++ b/src/ddsrt/src/process/posix/process.c @@ -0,0 +1,303 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/heap.h" + + +ddsrt_pid_t +ddsrt_getpid(void) +{ + /* Mapped to taskIdSelf() in VxWorks kernel mode. */ + return getpid(); +} + + +/* + * This'll take a argv and prefixes it with the given prefix. + * If argv is NULL, the new argv array will only contain the prefix and a NULL. + * The result array is always terminated with NULL. + */ +static char** +prefix_argv(const char *prefix, char *const argv_in[]) +{ + char **argv_out; + size_t argc = 0; + + assert(prefix); + + if (argv_in != NULL) { + while (argv_in[argc] != NULL) { + argc++; + } + } + + argv_out = ddsrt_calloc((argc + 2), sizeof(char*)); + if (argv_out) { + size_t argi; + argv_out[0] = (char*)prefix; + for (argi = 0; argi < argc; argi++) { + argv_out[argi + 1] = (char*)argv_in[argi]; + } + argv_out[argc + 1] = NULL; + } + + return argv_out; +} + + +static void no_op(int sig) +{ + (void)sig; +} + + +static dds_retcode_t +waitpids( + ddsrt_pid_t request_pid, + dds_duration_t timeout, + ddsrt_pid_t *child_pid, + int32_t *code) +{ + struct sigaction sigactold; + struct sigaction sigact; + dds_retcode_t rv; + int options = 0; + int ret; + int s; + + if (timeout < 0) { + return DDS_RETCODE_BAD_PARAMETER; + } + + if (timeout == 0) { + options = WNOHANG; + } else if (timeout != DDS_INFINITY) { + /* Round-up timemout to alarm seconds. */ + unsigned secs; + secs = (unsigned)(timeout / DDS_NSECS_IN_SEC); + if ((timeout % DDS_NSECS_IN_SEC) != 0) { + secs++; + } + /* Be sure that the SIGALRM only wakes up waitpid. */ + sigemptyset (&sigact.sa_mask); + sigact.sa_handler = no_op; + sigact.sa_flags = 0; + sigaction (SIGALRM, &sigact, &sigactold); + /* Now, set the alarm. */ + alarm(secs); + } + + ret = waitpid(request_pid, &s, options); + if (ret > 0) { + if (code) { + if (WIFEXITED(s)) { + *code = WEXITSTATUS(s); + } else { + *code = 1; + } + } + if (child_pid) { + *child_pid = ret; + } + rv = DDS_RETCODE_OK; + } else if (ret == 0) { + /* Process is still alive. */ + rv = DDS_RETCODE_PRECONDITION_NOT_MET; + } else if ((ret == -1) && (errno == EINTR)) { + /* Interrupted, + * so process(es) likely didn't change state and are/is alive. */ + rv = DDS_RETCODE_TIMEOUT; + } else if ((ret == -1) && (errno == ECHILD)) { + /* Unknown pid. */ + rv = DDS_RETCODE_NOT_FOUND; + } else { + /* Unknown error. */ + rv = DDS_RETCODE_ERROR; + } + + if ((timeout != 0) && (timeout != DDS_INFINITY)) { + /* Clean the alarm. */ + alarm(0); + /* Reset SIGALRM actions. */ + sigaction(SIGALRM, &sigactold, NULL); + } + + return rv; +} + + + +dds_retcode_t +ddsrt_proc_create( + const char *executable, + char *const argv[], + ddsrt_pid_t *pid) +{ + dds_retcode_t rv; + char **exec_argv; + int exec_fds[2]; + int exec_err; + pid_t spawn; + ssize_t nr; + + assert(executable != NULL); + assert(pid != NULL); + + /* Prefix the argv with the executable, which is the convention. */ + exec_argv = prefix_argv(executable, argv); + if (exec_argv == NULL) { + return DDS_RETCODE_OUT_OF_RESOURCES; + } + + /* Prepare pipe to know the result of the exec. */ + if (pipe(exec_fds) == -1) { + rv = DDS_RETCODE_OUT_OF_RESOURCES; + goto fail_pipe; + } + if ((fcntl(exec_fds[0], F_SETFD, fcntl(exec_fds[0], F_GETFD) | FD_CLOEXEC) == -1) || + (fcntl(exec_fds[1], F_SETFD, fcntl(exec_fds[1], F_GETFD) | FD_CLOEXEC) == -1) ){ + rv = DDS_RETCODE_ERROR; + goto fail_fctl; + } + + /* Create a new process. */ + spawn = fork(); + if (spawn == -1) + { + rv = DDS_RETCODE_ERROR; + goto fail_fork; + } + else if (spawn == 0) + { + /* Child process */ + + /* Run the executable, replacing current process. */ + execv(executable, exec_argv); + + /* If executing this, something has gone wrong */ + exec_err = errno; + (void)write(exec_fds[1], &exec_err, sizeof(int)); + close(exec_fds[1]); + close(exec_fds[0]); + ddsrt_free(exec_argv); + _exit(1); + } + else + { + /* Parent process */ + + /* Get execv result. */ + rv = DDS_RETCODE_ERROR; + close(exec_fds[1]); + nr = read(exec_fds[0], &exec_err, sizeof(int)); + if (nr == 0) { + /* Pipe closed by successful execv. */ + rv = DDS_RETCODE_OK; + } else if (nr == sizeof(int)) { + /* Translate execv error. */ + if ((exec_err == ENOENT ) || + (exec_err == ENOEXEC) ){ + rv = DDS_RETCODE_BAD_PARAMETER; + } else if (exec_err == EACCES) { + rv = DDS_RETCODE_NOT_ALLOWED; + } + } + close(exec_fds[0]); + + if (rv == DDS_RETCODE_OK) { + /* Remember child pid. */ + *pid = spawn; + } else { + /* Remove the failed fork pid from the system list. */ + waitpid(spawn, NULL, 0); + } + } + + ddsrt_free(exec_argv); + return rv; + +fail_fork: +fail_fctl: + close(exec_fds[0]); + close(exec_fds[1]); +fail_pipe: + ddsrt_free(exec_argv); + return rv; +} + + + +dds_retcode_t +ddsrt_proc_waitpid( + ddsrt_pid_t pid, + dds_duration_t timeout, + int32_t *code) +{ + if (pid > 0) { + return waitpids(pid, timeout, NULL, code); + } + return DDS_RETCODE_BAD_PARAMETER; +} + + + +dds_retcode_t +ddsrt_proc_waitpids( + dds_duration_t timeout, + ddsrt_pid_t *pid, + int32_t *code) +{ + return waitpids(0, timeout, pid, code); +} + + + +dds_retcode_t +ddsrt_proc_exists( + ddsrt_pid_t pid) +{ + if (kill(pid, 0) == 0) + return DDS_RETCODE_OK; + else if (errno == EPERM) + return DDS_RETCODE_OK; + else if (errno == ESRCH) + return DDS_RETCODE_NOT_FOUND; + else + return DDS_RETCODE_ERROR; +} + + + +dds_retcode_t +ddsrt_proc_kill( + ddsrt_pid_t pid) +{ + if (kill(pid, SIGKILL) == 0) + return DDS_RETCODE_OK; + else if (errno == EPERM) + return DDS_RETCODE_ILLEGAL_OPERATION; + else if (errno == ESRCH) + return DDS_RETCODE_BAD_PARAMETER; + else + return DDS_RETCODE_ERROR; +} diff --git a/src/ddsrt/src/process/windows/process.c b/src/ddsrt/src/process/windows/process.c new file mode 100644 index 0000000..91cebec --- /dev/null +++ b/src/ddsrt/src/process/windows/process.c @@ -0,0 +1,447 @@ +/* + * 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 +#include +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/time.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/atomics.h" +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/timeconv.h" + + +ddsrt_pid_t +ddsrt_getpid(void) +{ + return GetCurrentProcessId(); +} + + + +static HANDLE pid_to_phdl (ddsrt_pid_t pid); +static dds_retcode_t process_get_exit_code(HANDLE phdl, int32_t *code); +static dds_retcode_t process_kill (HANDLE phdl); +static char* commandline (const char *exe, char *const argv_in[]); +static BOOL child_add (HANDLE phdl); +static void child_remove (HANDLE phdl); +static DWORD child_list (HANDLE *list, DWORD max); +static HANDLE child_handle (ddsrt_pid_t pid); + + + +dds_retcode_t +ddsrt_proc_create( + const char *executable, + char *const argv[], + ddsrt_pid_t *pid) +{ + dds_retcode_t rv = DDS_RETCODE_ERROR; + PROCESS_INFORMATION process_info; + STARTUPINFO si; + char *cmd; + LPTCH environment; + + assert(executable != NULL); + assert(pid != NULL); + + cmd = commandline(executable, argv); + if (cmd == NULL) { + return DDS_RETCODE_OUT_OF_RESOURCES; + } + + memset(&si, 0, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + + /* The new process will inherit the input/output handles. */ + /* TODO: Redirect is not working yet. */ + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + + /* Get the environment variables to pass along. */ + environment = GetEnvironmentStrings(); + if(environment){ + BOOL created; + created = CreateProcess(executable, // ApplicationName + cmd, // CommandLine + NULL, // ProcessAttributes + NULL, // ThreadAttributes + TRUE, // InheritHandles + CREATE_NO_WINDOW, // dwCreationFlags + (LPVOID)environment, // Environment + NULL, // CurrentDirectory + &si, // StartupInfo + &process_info); // ProcessInformation + if (created) { + if (child_add(process_info.hProcess)) { + *pid = process_info.dwProcessId; + rv = DDS_RETCODE_OK; + } else { + process_kill(process_info.hProcess); + rv = DDS_RETCODE_OUT_OF_RESOURCES; + } + } else { + DWORD error = GetLastError(); + if ((ERROR_FILE_NOT_FOUND == error) || + (ERROR_PATH_NOT_FOUND == error)) { + rv = DDS_RETCODE_BAD_PARAMETER; + } else if (ERROR_ACCESS_DENIED == error) { + rv = DDS_RETCODE_NOT_ALLOWED; + } + } + FreeEnvironmentStrings(environment); + } + + ddsrt_free(cmd); + + return rv; +} + + + +dds_retcode_t +ddsrt_proc_waitpid( + ddsrt_pid_t pid, + dds_duration_t timeout, + int32_t *code) +{ + dds_retcode_t rv = DDS_RETCODE_OK; + HANDLE phdl; + DWORD ret; + + if (timeout < 0) { + return DDS_RETCODE_BAD_PARAMETER; + } + + phdl = child_handle(pid); + if (phdl == 0) { + return DDS_RETCODE_NOT_FOUND; + } + + if (timeout > 0) { + ret = WaitForSingleObject(phdl, ddsrt_duration_to_msecs_ceil(timeout)); + if (ret != WAIT_OBJECT_0) { + if (ret == WAIT_TIMEOUT) { + rv = DDS_RETCODE_TIMEOUT; + } else { + rv = DDS_RETCODE_ERROR; + } + } + } + + if (rv == DDS_RETCODE_OK) { + rv = process_get_exit_code(phdl, code); + } + + if (rv == DDS_RETCODE_OK) { + child_remove(phdl); + } + + + return rv; +} + + + +dds_retcode_t +ddsrt_proc_waitpids( + dds_duration_t timeout, + ddsrt_pid_t *pid, + int32_t *code) +{ + dds_retcode_t rv = DDS_RETCODE_OK; + HANDLE hdls[MAXIMUM_WAIT_OBJECTS]; + HANDLE phdl; + DWORD cnt; + DWORD ret; + + if (timeout < 0) { + return DDS_RETCODE_BAD_PARAMETER; + } + + cnt = child_list(hdls, MAXIMUM_WAIT_OBJECTS); + if (cnt == 0) { + return DDS_RETCODE_NOT_FOUND; + } + + ret = WaitForMultipleObjects(cnt, hdls, FALSE, ddsrt_duration_to_msecs_ceil(timeout)); + if ((ret < WAIT_OBJECT_0) || (ret >= (WAIT_OBJECT_0 + cnt))) { + if (ret == WAIT_TIMEOUT) { + if (timeout == 0) { + rv = DDS_RETCODE_PRECONDITION_NOT_MET; + } else { + rv = DDS_RETCODE_TIMEOUT; + } + } else { + rv = DDS_RETCODE_ERROR; + } + } else { + /* Get the handle of the specific child that was triggered. */ + phdl = hdls[ret - WAIT_OBJECT_0]; + } + + if (rv == DDS_RETCODE_OK) { + rv = process_get_exit_code(phdl, code); + } + + if (rv == DDS_RETCODE_OK) { + if (pid) { + *pid = GetProcessId(phdl); + } + child_remove(phdl); + } + + return rv; +} + + + +dds_retcode_t +ddsrt_proc_exists( + ddsrt_pid_t pid) +{ + dds_retcode_t rv = DDS_RETCODE_NOT_FOUND; + HANDLE phdl; + + phdl = pid_to_phdl(pid); + if (phdl != 0) { + rv = process_get_exit_code(phdl, NULL); + if (rv == DDS_RETCODE_PRECONDITION_NOT_MET) { + /* Process still exists. */ + rv = DDS_RETCODE_OK; + } else if (rv == DDS_RETCODE_OK) { + /* The process has gone. */ + rv = DDS_RETCODE_NOT_FOUND; + } else { + rv = DDS_RETCODE_ERROR; + } + CloseHandle(phdl); + } + + return rv; +} + + + +dds_retcode_t +ddsrt_proc_kill( + ddsrt_pid_t pid) +{ + dds_retcode_t rv = DDS_RETCODE_BAD_PARAMETER; + HANDLE phdl; + + phdl = pid_to_phdl(pid); + if (phdl != 0) { + /* Forcefully kill. */ + rv = process_kill(phdl); + CloseHandle(phdl); + } + + return rv; +} + + + +static HANDLE +pid_to_phdl(ddsrt_pid_t pid) +{ + return OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE | PROCESS_TERMINATE, FALSE, pid); +} + + + +static dds_retcode_t +process_get_exit_code( + HANDLE phdl, + int32_t *code) +{ + dds_retcode_t rv = DDS_RETCODE_ERROR; + DWORD tr; + + assert(phdl != 0); + + if (GetExitCodeProcess(phdl, &tr)) { + if (tr == STILL_ACTIVE) { + rv = DDS_RETCODE_PRECONDITION_NOT_MET; + } else { + if (code) { + *code = (int32_t)tr; + } + rv = DDS_RETCODE_OK; + } + } + + return rv; +} + + + +/* Forcefully kill the given process. */ +static dds_retcode_t +process_kill(HANDLE phdl) +{ + assert(phdl != 0); + if (TerminateProcess(phdl, 1 /* exit code */) != 0) { + return DDS_RETCODE_OK; + } + return DDS_RETCODE_ERROR; +} + + + +/* Add quotes to a given string, escape it and add it to a buffer. */ +static char* +insert_char(char *buf, size_t *len, size_t *max, char c) +{ + static const size_t buf_inc = 64; + if (*len == *max) { + *max += buf_inc; + buf = ddsrt_realloc(buf, *max); + } + if (buf) { + buf[(*len)++] = c; + } + return buf; +} +static char* +stringify_cat(char *buf, size_t *len, size_t *max, const char *str) +{ + char last = '\0'; + + /* Start stringification with an opening double-quote. */ + buf = insert_char(buf, len, max, '\"'); + if (!buf) goto end; + + /* Copy and escape the string. */ + while ((*str) != '\0') { + if (*str == '\"') { + buf = insert_char(buf, len, max, '\\'); + if (!buf) goto end; + } + buf = insert_char(buf, len, max, *str); + if (!buf) goto end; + last = *str; + str++; + } + + /* For some reason, only the last backslash will be stripped. + * No need to escape the other backslashes. */ + if (last == '\\') { + buf = insert_char(buf, len, max, '\\'); + if (!buf) goto end; + } + + /* End stringification. */ + buf = insert_char(buf, len, max, '\"'); + if (!buf) goto end; + buf = insert_char(buf, len, max, ' '); + +end: + return buf; +} + + + +/* Create command line with executable and arguments. */ +static char* +commandline(const char *exe, char *const argv_in[]) +{ + char *cmd = NULL; + size_t len = 0; + size_t max = 0; + size_t argi; + + assert(exe); + + /* Add quoted and escaped executable. */ + cmd = stringify_cat(cmd, &len, &max, exe); + if (!cmd) goto end; + + /* Add quoted and escaped arguments. */ + if (argv_in != NULL) { + for (argi = 0; argv_in[argi] != NULL; argi++) { + cmd = stringify_cat(cmd, &len, &max, argv_in[argi]); + if (!cmd) goto end; + } + } + + /* Terminate command line string. */ + cmd = insert_char(cmd, &len, &max, '\0'); + +end: + return cmd; +} + + +/* Maintain a list of children to be able to wait for all them. */ +static ddsrt_atomic_voidp_t g_children[MAXIMUM_WAIT_OBJECTS] = {0}; + +static BOOL +child_update(HANDLE old, HANDLE new) +{ + BOOL updated = FALSE; + for (int i = 0; (i < MAXIMUM_WAIT_OBJECTS) && (!updated); i++) + { + updated = ddsrt_atomic_casvoidp(&(g_children[i]), old, new); + } + return updated; +} + +static BOOL +child_add(HANDLE phdl) +{ + return child_update(0, phdl); +} + +static void +child_remove(HANDLE phdl) +{ + (void)child_update(phdl, 0); +} + +static DWORD +child_list(HANDLE *list, DWORD max) +{ + HANDLE hdl; + int cnt = 0; + assert(list); + assert(max <= MAXIMUM_WAIT_OBJECTS); + for (int i = 0; (i < MAXIMUM_WAIT_OBJECTS); i++) + { + hdl = ddsrt_atomic_ldvoidp(&(g_children[i])); + if (hdl != 0) { + list[cnt++] = hdl; + } + } + return cnt; +} + +static HANDLE +child_handle(ddsrt_pid_t pid) +{ + HANDLE phdl = 0; + + for (int i = 0; (i < MAXIMUM_WAIT_OBJECTS) && (phdl == 0); i++) + { + phdl = ddsrt_atomic_ldvoidp(&(g_children[i])); + if (phdl != 0) { + if (GetProcessId(phdl) != pid) { + phdl = 0; + } + } + } + + return phdl; +} diff --git a/src/ddsrt/tests/CMakeLists.txt b/src/ddsrt/tests/CMakeLists.txt index 552cfd2..02c92ef 100644 --- a/src/ddsrt/tests/CMakeLists.txt +++ b/src/ddsrt/tests/CMakeLists.txt @@ -25,6 +25,7 @@ set(sources "random.c" "strlcpy.c" "socket.c" + "process.c" "select.c") add_cunit_executable(cunit_ddsrt ${sources}) @@ -42,3 +43,26 @@ endif() target_include_directories( cunit_ddsrt PRIVATE "$") + +# Create a separate test application that will be used to +# test process management. +add_executable(process_app process_app.c) +target_link_libraries(process_app PRIVATE ddsrt) +target_include_directories( + process_app + PRIVATE + "$") +# Force the app to be at the same location, no matter what platform or build type. +set_target_properties( + process_app + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR} ) +# Let the cunit application know the location and name of the test application. +set(process_app_name "${CMAKE_CURRENT_BINARY_DIR}/process_app${CMAKE_EXECUTABLE_SUFFIX}") +configure_file( + "process_test.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/process_test.h" @ONLY) + diff --git a/src/ddsrt/tests/process.c b/src/ddsrt/tests/process.c new file mode 100644 index 0000000..c000cf7 --- /dev/null +++ b/src/ddsrt/tests/process.c @@ -0,0 +1,284 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include "CUnit/Test.h" +#include "process_test.h" +#include "dds/ddsrt/time.h" +#include "dds/ddsrt/strtol.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/process.h" + + +/* + * Create a process that is expected to exit quickly. + * Compare the exit code with the expected exit code. + */ +static void create_and_test_exit(const char *arg, int code) +{ + dds_retcode_t ret; + ddsrt_pid_t pid; + int32_t status; + char *argv[] = { NULL, NULL }; + + argv[0] = (char*)arg; + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + ret = ddsrt_proc_waitpid(pid, DDS_SECS(10), &status); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + + /* Check result. */ + CU_ASSERT_EQUAL(status, code); + + /* Garbage collection when needed. */ + if (ret != DDS_RETCODE_OK) { + ddsrt_proc_kill(pid); + } +} + + +/* + * Try to create a process without arguments. + * The exit status of the process should be PROCESS_DONE_NOTHING_EXIT_CODE. + */ +CU_Test(ddsrt_process, create) +{ + create_and_test_exit(NULL, TEST_CREATE_EXIT); +} + + +/* + * Create a process that'll sleep for a while. + * Try to kill that process. + */ +CU_Test(ddsrt_process, kill) +{ + dds_retcode_t ret; + ddsrt_pid_t pid; + + /* Sleep for 20 seconds. It should be killed before then. */ + char *argv[] = { TEST_SLEEP_ARG, "20", NULL }; + + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_NOT_EQUAL_FATAL(pid, 0); + + /* Check if process is running. */ + ret = ddsrt_proc_exists(pid); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + + /* Kill it. */ + ret = ddsrt_proc_kill(pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + /* Check if process is actually gone. */ + ret = ddsrt_proc_waitpid(pid, DDS_SECS(10), NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + ret = ddsrt_proc_exists(pid); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_NOT_FOUND); +} + + +/* + * Create a process that'll return it's own pid value (reduced + * to fit the exit code range). It should match the pid that was + * returned by the process create (also reduced to be able to + * match the returned semi-pid value). + */ +CU_Test(ddsrt_process, pid) +{ + dds_retcode_t ret; + ddsrt_pid_t pid; + int32_t status; + char *argv[] = { TEST_PID_ARG, NULL }; + + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_NOT_EQUAL_FATAL(pid, 0); + + ret = ddsrt_proc_waitpid(pid, DDS_SECS(10), &status); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + + /* Compare the pid values. */ + CU_ASSERT_EQUAL(status, TEST_PID_EXIT(pid)); + + /* Garbage collection when needed. */ + if (ret != DDS_RETCODE_OK) { + ddsrt_proc_kill(pid); + } +} + + +/* + * Set a environment variable in the parent process. + * Create a process that should have access to that env var. + */ +CU_Test(ddsrt_process, env) +{ + dds_retcode_t ret; + + ret = ddsrt_setenv(TEST_ENV_VAR_NAME, TEST_ENV_VAR_VALUE); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + create_and_test_exit(TEST_ENV_ARG, TEST_ENV_EXIT); +} + + +/* + * Try to create a process with an non-existing executable file. + * It should fail. + */ +CU_Test(ddsrt_process, invalid) +{ + dds_retcode_t ret; + ddsrt_pid_t pid; + + ret = ddsrt_proc_create("ProbablyNotAnValidExecutable", NULL, &pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); + + /* Garbage collection when needed. */ + if (ret == DDS_RETCODE_OK) { + ddsrt_proc_kill(pid); + } +} + + +/* + * Create a process with a backslash in the argument + */ +CU_Test(ddsrt_process, arg_bslash) +{ + create_and_test_exit(TEST_BSLASH_ARG, TEST_BSLASH_EXIT); +} + + +/* + * Create a process with a double-quote in the argument + */ +CU_Test(ddsrt_process, arg_dquote) +{ + create_and_test_exit(TEST_DQUOTE_ARG, TEST_DQUOTE_EXIT); +} + + +/* + * Create two processes and wait for them simultaneously. + */ +CU_Test(ddsrt_process, waitpids) +{ + dds_retcode_t ret; + ddsrt_pid_t child; + ddsrt_pid_t pid1 = 0; + ddsrt_pid_t pid2 = 0; + int32_t status; + + /* Use retpid option to identify return values. */ + char *argv[] = { TEST_PID_ARG, NULL }; + + /* Start two processes. */ + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid1); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid2); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + + /* Wait for both processes to have finished. */ + while (((pid1 != 0) || (pid2 != 0)) && (ret == DDS_RETCODE_OK)) { + ret = ddsrt_proc_waitpids(DDS_SECS(10), &child, &status); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + if (child == pid1) { + CU_ASSERT_EQUAL(status, TEST_PID_EXIT(pid1)); + pid1 = 0; + } else if (child == pid2) { + CU_ASSERT_EQUAL(status, TEST_PID_EXIT(pid2)); + pid2 = 0; + } else { + CU_ASSERT(0); + } + } + + ret = ddsrt_proc_waitpids(DDS_SECS(10), &child, &status); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_NOT_FOUND); + + /* Garbage collection when needed. */ + if (pid1 != 0) { + ddsrt_proc_kill(pid1); + } + if (pid2 != 0) { + ddsrt_proc_kill(pid2); + } +} + + +/* + * Create a sleeping process. Waiting for it should timeout. + */ +CU_Test(ddsrt_process, waitpid_timeout) +{ + dds_retcode_t ret; + ddsrt_pid_t pid; + + /* Sleep for 20 seconds. We should have a timeout before then. */ + char *argv[] = { TEST_SLEEP_ARG, "20", NULL }; + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_NOT_EQUAL_FATAL(pid, 0); + + /* Timeout 0 should return DDS_RETCODE_PRECONDITION_NOT_MET when alive. */ + ret = ddsrt_proc_waitpid(pid, 0, NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); + + /* Valid timeout should return DDS_RETCODE_TIMEOUT when alive. */ + ret = ddsrt_proc_waitpid(pid, DDS_SECS(1), NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_TIMEOUT); + + /* Kill it. */ + ret = ddsrt_proc_kill(pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + /* When killed, DDS_RETCODE_OK should be returned. */ + ret = ddsrt_proc_waitpid(pid, DDS_SECS(10), NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); +} + + +/* + * Create a sleeping process. Waiting for it should timeout. + */ +CU_Test(ddsrt_process, waitpids_timeout) +{ + dds_retcode_t ret; + ddsrt_pid_t pid; + + /* Sleep for 20 seconds. We should have a timeout before then. */ + char *argv[] = { TEST_SLEEP_ARG, "20", NULL }; + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_NOT_EQUAL_FATAL(pid, 0); + + /* Timeout 0 should return DDS_RETCODE_PRECONDITION_NOT_MET when alive. */ + ret = ddsrt_proc_waitpids(0, NULL, NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); + + /* Valid timeout should return DDS_RETCODE_TIMEOUT when alive. */ + ret = ddsrt_proc_waitpids(DDS_SECS(1), NULL, NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_TIMEOUT); + + /* Kill it. */ + ret = ddsrt_proc_kill(pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + /* When killed, DDS_RETCODE_OK should be returned. */ + ret = ddsrt_proc_waitpids(DDS_SECS(10), NULL, NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); +} diff --git a/src/ddsrt/tests/process_app.c b/src/ddsrt/tests/process_app.c new file mode 100644 index 0000000..a0c402a --- /dev/null +++ b/src/ddsrt/tests/process_app.c @@ -0,0 +1,108 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include "process_test.h" +#include "dds/ddsrt/strtol.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/process.h" + + +static int test_create(void) +{ + printf(" Process: created without args.\n"); + return TEST_CREATE_EXIT; +} + +static int test_sleep(int argi, int argc, char **argv) +{ + argi++; + if (argi < argc) { + long long dorment; + ddsrt_strtoll(argv[argi], NULL, 0, &dorment); + printf(" Process: sleep %d seconds.\n", (int)dorment); + dds_sleepfor(DDS_SECS((int64_t)dorment)); + } else { + printf(" Process: no --sleep value.\n"); + return TEST_EXIT_WRONG_ARGS; + } + /* Expected to be destroyed before reaching this. */ + return TEST_EXIT_FAILURE; +} + +static int test_pid(void) +{ + int ret; + ddsrt_pid_t pid; + pid = ddsrt_getpid(); + ret = TEST_PID_EXIT(pid); + printf(" Process: pid %d reduced to %d exit code.\n", (int)pid, ret); + return ret; +} + +static int test_env(void) +{ + int ret = TEST_EXIT_FAILURE; + char *envptr = NULL; + if (ddsrt_getenv(TEST_ENV_VAR_NAME, &envptr) == DDS_RETCODE_OK) { + printf(" Process: env %s=%s.\n", TEST_ENV_VAR_NAME, envptr); + if (strcmp(envptr, TEST_ENV_VAR_VALUE) == 0) { + ret = TEST_ENV_EXIT; + } + } else { + printf(" Process: failed to get environment variable.\n"); + } + return ret; +} + +static int test_bslash(void) +{ + printf(" Process: backslash argument.\n"); + return TEST_BSLASH_EXIT; +} + +static int test_dquote(void) +{ + printf(" Process: double-quote argument.\n"); + return TEST_DQUOTE_EXIT; +} + + +/* + * The spawned application used in the process tests. + */ +int main(int argc, char **argv) +{ + int ret; + + if (argc == 1) { + ret = test_create(); + } else { + if (strcmp(argv[1], TEST_SLEEP_ARG) == 0) { + ret = test_sleep(1, argc, argv); + } else if (strcmp(argv[1], TEST_PID_ARG) == 0) { + ret = test_pid(); + } else if (strcmp(argv[1], TEST_ENV_ARG) == 0) { + ret = test_env(); + } else if (strcmp(argv[1], TEST_BSLASH_ARG) == 0) { + ret = test_bslash(); + } else if (strcmp(argv[1], TEST_DQUOTE_ARG) == 0) { + ret = test_dquote(); + } else { + printf(" Process: unknown argument.\n"); + ret = TEST_EXIT_WRONG_ARGS; + } + } + + return ret; +} diff --git a/src/ddsrt/tests/process_test.h.in b/src/ddsrt/tests/process_test.h.in new file mode 100644 index 0000000..25cd632 --- /dev/null +++ b/src/ddsrt/tests/process_test.h.in @@ -0,0 +1,42 @@ +/* + * 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_TEST_PROCESS_TEST_H +#define DDSRT_TEST_PROCESS_TEST_H + +/* Get the application name from cmake to automatically + * get the proper extension and location. */ +#define TEST_APPLICATION "@process_app_name@" + +#define TEST_SLEEP_ARG "--sleep" + +#define TEST_EXIT_GENERIC_OK (0) +#define TEST_EXIT_FAILURE (1) +#define TEST_EXIT_WRONG_ARGS (2) + +#define TEST_CREATE_ARG NULL +#define TEST_CREATE_EXIT (0) + +#define TEST_PID_ARG "--retpid" +#define TEST_PID_EXIT(pid) ((int)(int32_t)(pid % 127)) + +#define TEST_ENV_ARG "--checkenv" +#define TEST_ENV_EXIT (12) +#define TEST_ENV_VAR_NAME "TEST_ENV_VAR_NAME" +#define TEST_ENV_VAR_VALUE "TEST_ENV_VAR_VALUE" + +#define TEST_BSLASH_ARG "\\left\\\\right\\" +#define TEST_BSLASH_EXIT (int)('\\') + +#define TEST_DQUOTE_ARG "\"left\"\"right\"" +#define TEST_DQUOTE_EXIT (int)('"') + +#endif /* DDSRT_TEST_PROCESS_TEST_H */ From 17f9c361ea42be047520d756cdc3d3547182e7b7 Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Wed, 10 Apr 2019 17:57:29 +0200 Subject: [PATCH 043/178] Multi Process Testing framework Signed-off-by: Martin Bremmer --- docs/dev/mpt_req.md | 86 +++ docs/dev/multi_process_testing.md | 86 +++ docs/dev/pictures/mpt_flow.png | Bin 0 -> 74078 bytes docs/dev/pictures/mpt_tree.png | Bin 0 -> 19753 bytes src/CMakeLists.txt | 6 + src/ddsrt/include/dds/ddsrt/log.h | 2 +- src/mpt/CMakeLists.txt | 22 + src/mpt/mpt/CMakeLists.txt | 17 + src/mpt/mpt/cmake/MPT.cmake | 184 +++++ src/mpt/mpt/include/mpt/mpt.h | 158 +++++ src/mpt/mpt/include/mpt/private/mpt.h | 153 ++++ src/mpt/mpt/include/mpt/resource.h.in | 6 + src/mpt/mpt/src/main.c.in | 551 ++++++++++++++ src/mpt/tests/CMakeLists.txt | 19 + src/mpt/tests/basic/CMakeLists.txt | 23 + src/mpt/tests/basic/etc/config_any.xml | 30 + src/mpt/tests/basic/etc/config_specific.xml | 30 + src/mpt/tests/basic/helloworld.c | 63 ++ src/mpt/tests/basic/multi.c | 50 ++ src/mpt/tests/basic/procs/hello.c | 239 +++++++ src/mpt/tests/basic/procs/hello.h | 52 ++ src/mpt/tests/basic/procs/helloworlddata.idl | 9 + src/mpt/tests/self/CMakeLists.txt | 25 + src/mpt/tests/self/asserts.c | 711 +++++++++++++++++++ src/mpt/tests/self/environments.c | 96 +++ src/mpt/tests/self/etc/file | 0 src/mpt/tests/self/fixtures.c | 72 ++ src/mpt/tests/self/ipc.c | 29 + src/mpt/tests/self/resources.c | 30 + src/mpt/tests/self/usage.c | 186 +++++ 30 files changed, 2934 insertions(+), 1 deletion(-) create mode 100644 docs/dev/mpt_req.md create mode 100644 docs/dev/multi_process_testing.md create mode 100644 docs/dev/pictures/mpt_flow.png create mode 100644 docs/dev/pictures/mpt_tree.png create mode 100644 src/mpt/CMakeLists.txt create mode 100644 src/mpt/mpt/CMakeLists.txt create mode 100644 src/mpt/mpt/cmake/MPT.cmake create mode 100644 src/mpt/mpt/include/mpt/mpt.h create mode 100644 src/mpt/mpt/include/mpt/private/mpt.h create mode 100644 src/mpt/mpt/include/mpt/resource.h.in create mode 100644 src/mpt/mpt/src/main.c.in create mode 100644 src/mpt/tests/CMakeLists.txt create mode 100644 src/mpt/tests/basic/CMakeLists.txt create mode 100644 src/mpt/tests/basic/etc/config_any.xml create mode 100644 src/mpt/tests/basic/etc/config_specific.xml create mode 100644 src/mpt/tests/basic/helloworld.c create mode 100644 src/mpt/tests/basic/multi.c create mode 100644 src/mpt/tests/basic/procs/hello.c create mode 100644 src/mpt/tests/basic/procs/hello.h create mode 100644 src/mpt/tests/basic/procs/helloworlddata.idl create mode 100644 src/mpt/tests/self/CMakeLists.txt create mode 100644 src/mpt/tests/self/asserts.c create mode 100644 src/mpt/tests/self/environments.c create mode 100644 src/mpt/tests/self/etc/file create mode 100644 src/mpt/tests/self/fixtures.c create mode 100644 src/mpt/tests/self/ipc.c create mode 100644 src/mpt/tests/self/resources.c create mode 100644 src/mpt/tests/self/usage.c diff --git a/docs/dev/mpt_req.md b/docs/dev/mpt_req.md new file mode 100644 index 0000000..bcd2a90 --- /dev/null +++ b/docs/dev/mpt_req.md @@ -0,0 +1,86 @@ +# Eclipse Cyclone DDS Multi Process Testing Requirements + +This document present some requirements and considerations regarding the +[Multi Process Test Framework](multi_process_testing.md). + +## Requirements +1.1) To test certain Cyclone DDS features, multiple processes running Cyclone + DDS are needed to force communication through the whole stack. + +1.2) Should be buildable and runnable on platforms that support multiprocess + and filesystems including the ones used in the continues integration + context. + +1.3) Results should be easily analyzable within the continues integration + context and when running locally. This can be done by reporting the + results in a standard format like xunit or cunit. + +1.4) No processes must be left behind (f.i. deadlock in child process) when the + test finished (or timed out). + +1.5) When running tests parallel, they should not interfere with each other. + +1.6) Processes of the same test should be able to communicate (for settings, + syncing, etc). + +1.7) It should be possible to analyze output/messages/tracing of the parent + and child processes to be able to draw a proper test conclusion. + + +## Considerations +2.1) +The files that actually contain the tests, should be focused on those tests. +This means that the process management and setting up (and usage of) IPC +between test processes should be handled by a test framework so that the +test files can remain as clean as possible. + +2.2) +If possible, there shouldn't be a need for writing log files to a file system +when running the tests normally. It could be helpful, however, that these log +files are written when debugging related tests. + +2.3) +Preferably, the DDS communication between the processes should not leave +localhost. + + +## Intentions +There doesn't seem to be a 3rd party test framework that addresses our +requirements in a satisfactory manner. + +After some discussions with a few people (different people in different +meetings), it was decided to create our own framework and to go in the +following direction: + +- Process creation/destruction/etc is (re)introduced in the ddsrt.
+ [1.1/1.2] + +- The files that contain the tests, should be easy to understand and focus on + the tests themselves.
+ [2.1] + +- Other files (generated or in the framework) should take care of the + intricacies of starting/monitoring the proper processes with the proper + settings.
+ [1.4/1.6/2.1] + +- To do this, a similar approach of the current CUnit build will be used; + CMake will scan the test files and create runners according to macros within + the test files.
+ [2.1] + +- The tests should be executed by CTest. For now this means that a proper + runner exit code for pass/fail is enough. We would like to add CUnit like + output in the future.
+ [1.2/1.3] + +- The Cyclone DDS API contains the possibility to monitor generated log traces. + This means we won't be needing to monitor actual log files. Just register a + log callback and go from there.
+ [1.7/2.2] + +- The framework should be able to generate unique domain ids and unique topic + names when necessary. That way, tests won't interfere with each other when + running in parallel.
+ [1.5] + diff --git a/docs/dev/multi_process_testing.md b/docs/dev/multi_process_testing.md new file mode 100644 index 0000000..aa33f9d --- /dev/null +++ b/docs/dev/multi_process_testing.md @@ -0,0 +1,86 @@ +# Eclipse Cyclone DDS Multi Process Testing + +Some features and functionalities of Cyclone DDS can only be tested when +there's communication between processes. Examples are durability, security, +etc. To really make sure that these kind of features work, extended tests +with multiple processes are needed. + +This results in a number of [requirements](mpt_req.md). + +There doesn't seem to be a 3rd party test framework that addresses our +requirements in a satisfactory manner. Therefore, it was decided to create +our own Multi Process Testing (MPT) framework. + +This document will provide an overview of the MPT framework. + + +## Overview + +An MPT application is basically divided into two components +1. Tests +2. Runner + +The Tests are created by the developer. They don't need to worry about the +process management. They only have to provide process entry point(s), tests +and test processes that use these entry points. E.g. +```cpp +MPT_ProcessEntry(publisher, MPT_Args(int domain)) +{ + /* Publish a sample on the given domain. */ + MPT_ASSERT(success, "publisher failed"); +} +MPT_ProcessEntry(subscriber, MPT_Args(int domain)) +{ + /* Subscribe to a sample from the given domain. */ + MPT_ASSERT(success, "subscriber failed"); +} + +MPT_TestProcess(helloworld, domain0, pub, publisher, MPT_ArgValues(0)); +MPT_TestProcess(helloworld, domain0, sub, subscriber, MPT_ArgValues(0)); +MPT_Test(helloworld, domain0); + +MPT_TestProcess(helloworld, domain42, pub, publisher, MPT_ArgValues(42)); +MPT_TestProcess(helloworld, domain42, sub, subscriber, MPT_ArgValues(42)); +MPT_Test(helloworld, domain42); +``` + +There are more options, but see the +[usage test](../../src/mpt/tests/self/usage.c) for more elaborate examples. + +CMake will identify suites, tests and processes depending on those MPT +macros.
+It'll use that to generate part of the MPT Runner. The Runner takes care +of starting test(s) and handling the process management. + +The runner also takes care of preparing IPC between test processes so that +these processes can sync if they need to (NB, this will be a future extension). + + +#### Suite-Test-Process tree + +A process is related to a test and that test is related to a suite.
+A suite can have multiple tests and tests can have multiple processes.
+ +This results in the following tree quite naturally. + +Suite-Test-Process tree + + +#### Test execution + +There are 3 main ways to start an MPT application. +1. Without argument.
+ All tests will be run. +2. With suite and/or test name patterns as arguments.
+ A subset of tests will be run depending on the provided patterns.
+ This allows ctest to execute single tests. +3. With a specific suite/test/process combination as arguments.
+ An user will normally not use this. + +The third option is used by the MPT application itself to start a specific +test related process. It does so by restarting itself with the proper +suite/test/process combination as indicated by the test. This results +in the following flow. + +MPT application flow + diff --git a/docs/dev/pictures/mpt_flow.png b/docs/dev/pictures/mpt_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..271e74bd4b2256079fb2525f72757e9237ad5aab GIT binary patch literal 74078 zcmc$`cUV+gwmn)HQAAJ#1O!AB1O!yFL_tKdk~2!qITrCKIVw?-faIJr1!4fn8Kj6x zE^?OqW^wv-_v^m>?!CYFzVGex#{t<@d+inG8e_~cm;ZAaG5m|<7ZC^qzWB2zatOp} z8wBD^3GONQmx}ZR2Ke7O9Z9h#h-2)3NvMo)1mY$_{K;blr})KD7Y&8}qvJJ>)3`S8 z0ts(AK0o#CYjIEQjk_ES3bmisp7!j#Ka!JVCZ4y+-B6V8We;h3NW^NK_2iwuLr-n0 zK~&SCS8QgI&6R1!*RM5ZcA5mnd5GF3aMcY@7tE$KrNnTUE*%cJykA>Vb4ig%>BfcD zBsuq`vmnlm*15S1mzz&E2IF14SX_p^@Go8@=du{tUK+L>uQSJB;N~NtZ)Rx^(^6C0 z5_q}T*yLAoaBy%Wqgg0ptPcoUMcXk6zo>5J#F z#b7YYhUV}+KKIqLxJwK>wd!1}-X+X-B-H3NhqLR*V@uayLNYfXQke9T!7)ZR;AU?yo#~nii+qzZ)=m* zL>w(>AMYvmo}&_U*FakRUj4bdF}pHcA&c8xq}w##o6#A|k+W;O4*f_>Oe{??oUh4C zK@pc8oR^tdiQF>jZAAb0QCVHxQZv53z7Ac~*!1YpqrLroF7x_3ckTp_92F=V8)w-K zj-DpqTkR4d;4rTr%-7uCsXrbqEovXKl#%J^P7#aa9O&&WkxdkkrihD-EQ1b958m3? zpkOz8&bFie;)QiZJ#xF@Jate&fC<{Y^8>$2Q+=^ky}Ra0LFC*RYXA4zWL)|9xck0& zYZNoIGXC%bx3x}tEQd73{^}P3*_elE#=0H{YfU?2E(ONAE<4MIEldUM=8MT9zDL^? z^&IAA$47_9dxP~YmE+LMXf&EP#0`2l*0p5baoo-DpkK${-hQw^dr%ySw)bf<#Vq(N) zIc$!5G98xCJdYl6nwy1ZFs2nrf7mr$SJ0>3$4>UbLL*nRa6A%W?njRV*1yv_a(r!Q zc$_A8fu`DVWo+uOy1M%E4eml?-MA8MS=mmyBXbqMF_a6JbN$iLQ8>M<1^S0CwR`36 zepykG@nHU_X0UmOv-@hp`4#ROT}#UXrG+Xw40ONQx_gb|N}bc%uXMP>o!WWo9bKo= z-tI1kb3MvsXAG8MZzB?k2(nqI7ao76fWsOPa zmY?M*E#wb!%yy>u`T5a}9CRHVUZ&v8g-#&}KvLGRD%%Xg&mA2Wn7*vFwYBzL#AyU#4%Kh-+dSft!WYj&lKZeUvOI+OFRUabUK?6*3Se7!m3UBGO z!vtM_Ta9MORr1+P;r_e|U&?jwHPbWfB*@q7OceA`PB}O{?2PBpox2+F#h0M|aC;c$ z1F`TuwbHvZG>?6RVWpGbRAOu;)pmVg(wA979u^y`W?5dGOe+>r3-fScuwbPtS%fVc zT72J6C5zj3rcJfnEaqLpJCk1mhiECh%g%c{r&J~ZMUud`lGFa`1l(%UKts)w4r=g ziHSK}f3NZ$X<1)i*E@8y5$2t-r7DeKiSu{b6N!@!8D$d=laN{1*_2h#FjxqgL7-4pr=PX`+KoKr_1?`FFa`JSU4d?>;b?kdE+3_peb^ZkgEdj;U$Pt3ds zgwU>EBr~F75k4_Zt5lA-_ZqrjnvKgIr;_dD&f=*ly~nv`S1QY){Le zfQaw z;(07lTTz<|TuM~D4)<7CmXm#{!ju|e{#|>mlJ$hOcJ*~i%4EZv^Px9*ZXI1`()KvC z4}Q8aV%u3n2Satu8*XxNaOlmDB^AD>RjV>LQd|OIW2J7tqoLtvzp^%mwLc7%$CF%z zOfoiuA82%XTG}CON@#V5G1m=gnkTNVwc+96S$NP(zfbF=3EMCJu znf~MSdG~`gF-OOpXf0%OUq3XhFQdnZJv|?1Z+dF#%$YMV0jq0jX5r_vXAh6|S8|l{ zVmZxYvm{|=WQM9_8HLkHt5sMe1P4otih2`%9vs}+8TY6tEoHaYgtl!J;pQ8`dNwdH zP*hZ;d}K!`Tnh_Q4?AI`+LRba-#^eTHy@_+a)O}N+uPgT-Y%_q1xAtz`^Q@64F$$X z!e0rFV>I$GJHF|_+;`d@GAz)n+3uAU6yJr(BlL%wUhZwpva`%<^h7(c#)A6?Qm2F_ zRnDA;ueqeQT83=9QL5DTG{t)7xTLf5HsX59*(P{C;_hP`n_{ExL8bDqEw3((X> zOyPh2&|5Kg_d1C*#(VeJ?P(BFZ&Y@vMSL#3$bz?OX>3e~?UaFmAwB<@HF676_Ug+y zd1ahZPBbgEsp$e0KhkWpy1$PYM~LVO)A7P|w03@een)F-U`PlRn?c)9iD59AqNb*s zY)EM6xga|R6Mo=FOKk1Oo3PB2qPV*EcsuY8(sLZ`0F@ zrO8D`MM-?Yf;AG70oY{Wwc-Wbkg$B}>gu+)w_)M*8nFi}UneKuLz@=hle6EweLEEb zw(n)itHN#ZJZ${@`~m`XwzD0uOy$<_L&=4Ro@oofRC1b*RQ4jQKUfbm+B`kBN`!vq zLYrtexNeuz;{(J?yVcy$ zK_VOx5%KKH;o+fdJh%16O#6=?Kj4wGi5_*SskdoqQ{XwUs{||mfVNCbOqdSl8?(pa zQ*b)DxJVvi0m0V7pkydMW!XKoWm&pq4*5f~k={d$`>xqgu_&(fudf%RQ>d*_iO)rr zf?a#;>kaMT!;8)IiM38^I+~iJFy8>{LZgm0GXzCNMI!-ClaL4;ZuVlwzpu*U_y`6y z=TGzrn5|6vd86z3Q$`$qkshm?y|U`+>NVBX=%Jyi>gs&8vTQA1*lI23x{`Y)VNTR; zbnx~}wzWw~O13hqmq$cJnea+_oYSatRYj`F%j=q&?k^P7bIN%pFD3Fi%HY0GP`J&{ zZ#Cihpva~Yp+#~lFIv;4kMw?N zndTMA?N9gSYu0d>4m^X`{j}vSyj9M1BtGcgITw~r3^1Z#*y-ozvov4RB%@O^=I7^y z{c3A#H)cCc@w$xIUA7nB)g{HQQsO3whS$-no;fa9n`}ztbAHIh#U&`{fi5)`_A4zd zU0t<;MMq7Y=#588a_yQCuZxq@GlGMIgK~?}*ocU!pFg`ZWD_A)(mYX8ijqhp2Uz{* zRberjo0o^3T$Z7YW`bN?g98Ht&CTLS%;cnQTag{6PaOGD7kf=kOeCGGCtjtw#l?I4 zM&orTLSgcck}EGx86oITPvJgii-UJwqe?E-Nc53rkd3 z+VYk->~E2gkv)?&hrv{h3M!#$hrab*?0hD?yfro1IG#`T)~#)A_hJ6j*v*H9g*^no zHskuKjQlut!9CP?cW-Z?uTRgw0Emq#1**2z#KgqL#)gld-&{8IzNfP0Fe>Gv_8l1qX(iX=!zV!$5SRhKb zwY3coy8!)yeXfT^6X*ddJw5%xF!YRVqJW!0=LffifxOS3KUa*qtMB&!idzRbi$?*&abxMXZ>yhV2|Xrzu%2dKMpzJ|4pcpzP|Mqh6_r=~5Tm7~rS0wPZm=7@O-?!2B?VFN-o1Mo_3mzL zf)i?v`{Ja+W@EKH_wN@1`G*h=3_gNgx!Qb~lZ~z9)2C0cBp>neTB1wEF}3Ey;Jr;u6hv;$g@s*(2?v~0BKiUB z@pmrh~V=rZp2+OELi=|d;I?b7|f)zB+aLKq>&1#e=(#+MEDP#zzd5At&)0J(9jKcq;@P{Z|1nZW|Rh1G&^~k3);@o}y7qZJ8q#`G;cHS@uk4TN~ z!QiOf(MkI#9{oa16?dye-vR=53z8Co*d-@*l6GD z4Q?Gklmo)*=-^-hGuq0^N?7=Hgof`WvX63E5c*2_WfLBy$z_?Dn@cO-^E?I$8_Ujr z@(|T#g*#o0OJk@SSSngtS}*_*^&UB`PJH^~^kA;4?aHRL!16`kj0?VclN(g4Gn$@?I&pJB_)Mo z2p!3!e2bQrl9KZD>C-@g%;)ALKN_DtTYIl{yW_>U1z>Zq~Z0x!l)s>FSf<7k+Nz52>Y0P83I(T)z8nM$mMHP z^+1riLi@C@zh9g+Ej`_RZypOAAZ&lQ|LQa4enx7lD^M51j(Go&5C>b^;VN50Rn;Mo z%;eY-8&L5Eeo$c=XvDPw@Dlr0*3(<PvL1W#88QhDi$7@c;<#)Y5hHmd&h(Yrt!ML8BoCUu zq6YSs&j>oLzEn~9G2I#syQ~)>&=x@M;aV-7ot@3iYwPPhb!zJB3lkGoAba{!A@8!Y zv$L>R07e$}gWyU}p8==`RLG}$p}-Rf=@J9UbmF!ehPW`f~<1=X=wh85*r{ za&m&4($U%JXm3v}4DzdESJLCNXV1a}sgA?P#}5t)(kOiS$0qyj+fzV_KJYoOr;3NS zwYLkxJV2w>EG<_cio8g9%3&jeA$zFz3^u3_9!I-P)E<2F^oHNx(#WSv6_u1wuo(og z?;Fi^35$r(-ns>lZ0}bfD?oZ>OxJfZ&LinFN%|I;Q;4Lcu#YM*p{|*JaN8cjQkX|} zcj@S!;=YTFgyjfQZ|ahzxw+eP3o*l{k*)?TK5s%$xGMn^(H`>i@s%#YmJ0G`Yg^kj zVL(T79oxoa=o&y7d3kwQDH~pw)6Nc-B)SPm5f2ZKupfhb`lTD(tEio^{pFe!026?w zlq@3x0|S?Nx|wd?yvfdP2fHu~8###NFo%M8N&(;lc!MCZ71H!9_e^a1*`}6#LES(0 zMPkWLp`iHV8LD;nGX2E9wJr#hu^-*nLV;>C*}KYoNs z3BA&1vegpF1Zb2Im8z7pQdx#a$^x$t5gjcV_#NPs52gx$euO}47oANf`+*OLnQDoFs+yV!1qBZ~%~x2E$Ge>#mjV2O zg4ZKnH_Ub^$r>vF(WS^`9j%3WO#4CJZ;RL;-L{NCQq@3fkx6u zLIShbT?Pgi8y9Km;N(2Ap?X-i`S~pD>|QI_%|jhL%7Y_mzc39cV==%~2pMA=KqW%+d+M2m$FCFtx ze{XXh&>^+^?^kMSu?|nI4t}q}gWdMG`)hu)cwK*}_Z@T_kL8gn_rpDqi5@UAO5i4| zgNFP0vkq({TP$;CQ(d=B%8*OwGFgG$DNmf!siM0z{9h280k9qT`x`e@EEeL9sjU%A zH@qEiY?T>K?KT1_7PvpR#R#|j;3*-ho*lN5NRT#7U^xJg1L9Yjg@<#qgv7P=G9u|4 z#OeoJT(S}pCWHA2S*AEQv8v<55yRcP_w6qrmWfHQsOWzpz_jeO1Qc{ETFP6azJK4Y zS+Y%Rmg@;%cqOv)bT;s<@?Q2s%$m(cN z(&_*qo>!I=GjZ74i`8pcjy9~#h1`}O>$G|pMUw-TJ#BB9xV`@}_yOZH`J4M|n z74>1uMS89kR-#$0W>CK(IcYmxb zc9>e4*6T>9Bqm#}zA-Mi zNxgMU75KjE8CRql%DF*1+agN#c%LgIU(1_kw%=f;F%+dcbarUA?r5TYNL)`(f78op#(URSZa|~? z(I~^sCytfL7E9(!y#yJkqAf1tna*!Hl3%_&U@uRI+@fq%ic<%a6CV`5-C?1`Nm={G zg<~m#JiDO>trWF%8ri;Rsfz)r4_TV5vOC!kJV1G)hW`reUmQ-0A^nyI#jMjseizct zRz)qDr@g%GWwpH-O?BO5P(M@FdQ3D@A}wzAUM@PCczQ4}(x-ZqkySA+hSz0oXp*ui zwxXm~cZhP-jlK@G_PoV+I7(*aT9^6i*WdYWKJ3K>HF-35Unbof233>!nYw>uY<0D+ zF@l zx60>wl6JIWF6UDnsnMRFlgH4~iuuvJV$no0V=z`^M)PFnNTg0^Xxvwws%CSh9IKIeJ4ARn32;XlXQBqF@?E==GwlsI%(R5RUXk_|ec~ zOxdlbXXJCwK!fTX1v!;X*TUH>+8QrH`!bIG3JjT%9yAs5z-no8*vm*!@?f}LBJHYh zE}z1ygSVkXI(-H+$0ZZ;qm7ZQ0`p|oA0Y=^2JzO*SrU|#A}n7G9VO#@am;l$|Jl*X zxlM^*wqWrU)^XhQ@krs^;2Yi+$%|%-38#ejgQb5z&*N;}TbdiVBi|a3k37rIXa7w` zWR#Jq#UVc?(Oqvak0MQGc?{O@1m#HU_aeu8yeq$o310zk-n1f^Lz63l8(92x_7BevueL&=@1BWRhSS)kFi>G z>63fX|Eyf&z2p!1%M0*-s$%~K)~G-p+}Ou4!U0SXbJeP|>}#Ubh-v!a;s)CZS2|I| zv1C%Zdtl~LDp_o~L!T$jxI&#%;tuy$%$xmMF@%vnX!k%LJ#9cN{u_N{0Bm)VGs3FZ z*uVWZ8vB1}-9LnRDPzEVjFF5C4C2E!m_7z*uc>LyFr;CJe*6G^f$h$nwBlm9v{2B) zzATL^8jAd>#`_>S7NYvTzB%7j4a)zguON*BK*@2dhJ-JGDU5^D?sRlcPR_>q`p1-% zrXVs~5XIGx4T0#vM%FVK5D?%)QBhp{u&!hc6KMxZE|M}kCnv7N&D(TT>^wUeBn_m@ zKmmn)_(WmM&dvtCN;Z~Vyy6XemC-*b_To9mDM~r*ZEdMdpiChv3My>v?YI6#kiU~< ztE2NVF)J0ThlUaWZN7Y2Mp_yLuTyC~IRe+{=;W_o z0fB*OMf&>skYiZg*eEF}!MkvQ$6@h3;m6wAk?+V$9GHvv_?neguT)f20PDJJ&RGMt z2&UlL+uK7A56i}JN~d%iRS?~{VP=5Z4PA zFJ@(R_T=IJZkkbUZ~*FZy}_9#2OXpl5DA=I zZZ;_?3HZMI&Zr~Ig-X|5n=jZGn^#O~*ST^7A;tPHG(-=j+!RXf0r@4ENNT2fvPX_tV+#PNYV_3*GT$a260>ixbMmyG>6_59G#5F}|}P|&9% z$XT^&jVvr!_|4V$pOOq^$%0FOd)?EhEKEug!cDFa zrVZ`rnm>icHDJOKy7CX=!BP992V5kOXKZv6->`x-lZ~}?){fl2>()kwh8aqOiEr*J zgh`}@Q8_s~LlS;!YRU;WpDHUrLvcmA1@KwOro;>kV z%hRf|nTEIYCIl9Q&&0kyw_JWMDe@Jh&#%3LIDs|B2n&C9`w{(jHgj9L5K=2fQ z5mD4dynp}x?OQ?$3YX&?*k6s#6v_D;w8!4@QmJ!w1|yY)3urk3#7w2&JwQaffv*Sh z1{cVEkTUNvmz9zN2SAh-#|vY)VebkPvB}ZF?ypdyD0G&@JT{{&N~6T6@a2Leh>Hl% zu(gG*$OQ;ZKY#wbeED*ZS6X*>j^FQU!AdlJ?^QGYtQi||OcjRNL5lLGUGCy6UtBFPw zoID^Ce&PTTI(NLAa}2U?dfsWHZiDTLD{Tfi2sCFtwwHxU{y*QkrHGhX|AoFW6y7Gw zdw+F%vID=^QYk9jA=CuenY5Lx&h!UqNyF`mUE`f7mm+K3dx?E38KZG4$0|foG`d65 zFSAjCJPtmV&n$Zfpp$Q}H%Ulqj&>IesykZoRnv-Z2TxLEzIe4CX6 z_X*>^V%aD0I5xI4ems`ySnkH|*caK>yL_aXwq5-3AWt$~|Indtph5rTqM5me$WryC zt*mOr58K_t^S+KsW3@krm)5!qa;%8c;unKvb%)H?>eZ+&;TQHB#33RtASga8ZTJWX2}T?aRUJ z4eC{={nm{NOU2tL9vGj;Yi|L zRYUR+=I;W7g|d_T=+(g=+YXlt%z0Fm)%TmnKaAH-u!cvwcNc!wCUDcW1XN7~x7L!U@%_jI(N2fFp2X}s?H^JV|WJl_wk4D;~6 zH0WNAA)O(e(x?oxuO71!8I{O4$e@mj_k|&E3A443!ZCYCT-$1!?YZ!Jcbk!=?@v?sreCi6WU55K?N}yZ73Qh zx+3hS^`>cA<*<=;Uk*t7bG5goLt_IS^Eg>?B^mXbpH4{*)RpR@Bf6O}9nYWcU%6uyQ^{I0*t}c_w5d;;?31bXN!xR2%n){cs zxXM#%Rw(!97^|XEIN2QSw)Q%$2n1=K0OezNj45`U?{jkAl9`!L8DHEt(|<80O7nH8 zLF2+tel*~pE>rSqEc2?Yn7U+ zFYI$hicxulA9Lrj`x;K(;l^mKHzDh>Zb9A~TNF*TWW_%*-)t^%G+iaa;VDFcdXVzNM77wf&&7;5^@gi75;;r3RlDq1;6~r%&>--p5=x zz0aK0rqjHs=?|QHc!yt8Q|HR%5Ljs2|ElQ>7L=ovjUA&cD=yEg(`2yEyxV`w>mO@d zj!*e8A`7!K5BapH$2rRzR5(d@!fdY`v=#B+8MHBQFSP8~qfR@fW0kIQ!elVTWWXT1 zi6B=-Yr!I-tXy+kvXe&RgSIEbOwM75dsuB2!m`o^ZM+D%EF+GJS<~{%pW=2Wrwo_1 zk_9{3+HGOBpL{KM)Mi9Q0Ytx8+(|sGPsTIw9=pOGZ&#HFuH@8d8e6`ekzlG^4pTlU zb^osSJDUV{5i!i}%T9SQhYK_q6Vq+W$YZn92+tWmKm{QoN1b~8u%Wb%|7yDMz=Un% zSamhaVzPxaar4q8O8y1Z!dYkaXc<@u6@_NUU7kOAmFml_X7wrdL*Q+>bTVc8+t)oT zR5lkHC?OhhZp+{#A2!mtW-7%&T(*N=&=*xky{7t5t&@>#5lO7iJJ=>GSiCS0EJyFS zQnVqkdU;uYN=3JY(?A|VNjYc*y4cw3 ziPjKp(=H-6vofQj`f{Xk*OoU>Uz$1=Ih=wv`?}tltUxLqX6|%1<$^h7e4g2&hTH4n z9*_948P9jvmDpPIHh<@tWWIr=>Th9Z@joJ^eLu(s!|q^#;%$g?E|0S`@SvdadYbZ1 z-}L^ISZ%I;vpXxS2zHqcl?$b+Ut9Ly0DYHeym%9Kr+*|=;g|ntKKswa_@%_3E;L{{ z=qSkjfFBL)Iir{V*_8(A2}U=_s!)svEtGDwXVFS@^L zVa%rhuWmh3P*!erdj2$4z-^D25|m}V-g4crUlelB$UL)7c(>1G%2;U4hYu`Xnc3NB zFa-kdvEzNl_741G;4Op)(aU})-4iq^Ljx8^ni(4peb*wlc!GO{oSYo&HzXt^H*Uno z#$u&w>&Zs&x>VKFG=2L=(mkn4Xc*)YRm-JOb|UYOOUeli7t*@t4M-tbV?RCY0aK>+0$PXONG# zcNwVpVxd%!;TWs5PAMoTK%ovxje9{?D@Xs|oO)kAj%~c0;yHsp^@fQKgmiH1L6=&< zi$Nm7T|z=)2TW{s^B*f_GZNjiyNy7zh%2cM?X;U(9qChNWOs$h>?*|CgIT?ukYW#8$rbZSc0HbqPnuuY^2iqv)6@a7ELwa zKtI3u!pni{E@LU3xef|0VAestaw8>F0EjN+mjLRzxw?{D@GvmUgF&C*;>Fm9`Ynav ziM({(3MeH!2_^_I0VnX{2;*{bRY2AZTtA8YE)F1}eE9GIIO=^nsvtgJA@$Y7(64Pr zoB&r5=webWr=LJ_w2Sqc#i-rb^;;s41t8xzfNh7%a;&tx{AeF2IJN@f6{!#BL*t&? z3Q{D zY$WXW>WdHfd^Ax=Mf3}P^e-^y--oFQi79?i4uDrta9K!6N%grYMT-${8t7%jmViOuexT$q8pIFK|TTMr!WpG|Jm#vf%YQ!EtKlol0rFW+HiX6EA? zftA(NWcc&5H)Mu|aZ$4k-)%E1t|o0g7}SzD^$pr2j0@nyJ`S?O5PyKF^{-wPKXI>B z7+8#VJx#T|PU96Ftqg`G8JUobj10nCPb|eurR#J*T?jwi^ojuj!@tivpa~ppZ}3Xlqa58 zSrPoNU0^%g0RDpFAL>hheeY>XGps*o_4YRS1b$<6p{z>qi~zYF1b>{K9z@!V;^H2- zzI_u-lLK$uym^EJr0mtRQozRX?&9d^D8<;Pd{dZMJz%gii49Rg zDc!&K_py~-5W~{*&l;(xt{8%hgvk3E#jFnI91s$Wz`zy2O}2#Sm;!8RB~2t}s?AzzPnrcOE@bvohBY z{PbsC#z|4fznR!ibP_1&VPRsb$%%%KNkK`>lcJ)c3l}ax))!w}0%Fp$XMVxKsAEM) z&$7SfZHS!vyK({YAB0deZv*VJ5EDRL-dP!k9oYc$5NIB4Vh3^6?L;os z{tamT8ZhF#ij%bz43b)e)==AGIXhn zqu%r|3smmBL~YIO!L4F)gHc+okS#x6{nXtl<38Lr^7(hgd`JfRw=@SI4So}+dk>7~ zJ3YTh!Nq46m-#DA6KNp%=l-L}qOWaQZr^9OlSg1;Z996_ayeWvmUytV+m3hi(0QIz*w1I0EIZ@=&gVhuS{~l{%pBQ?rIvt$TsC1pNTlLZ z*mLmx!1oC5R~P56{zi{_AhWXD{ht*R1&S&LlwsD`58e;#2*k_O8J5@DepEU%Zct*;YZb%{3YM+QJkd4jUO-96Sxzz?Yr@2oNv2_ z=HK{y@H!q(xmae9!Xi^05}})4j6FWov^2M?r^!`0+0XxI?)+ZV7{Tm(Ff?mM8ShO< zAh4GjX!xn%e0><&MXXW0DEBVw!a=hLtzqr(*uYrh7=y{)uU@fZRi%i63O!aY!%FiqJS z^=wUY|2Oh+{^pOdwD8TODYX!|qq|=ciSGU)i~9n}oU!Mi|7HDBKhd@OR= zklmu>O53^DPvP>n_sUht%F5x5DqmCD-2!#+8T0?bUJ#jn+J2tpGdV`dhNC9GJpC?f z&e-j=2fBE+Y%40;$6K{Y`<3eBhDRl&kr=@mr%xqtPwCCUhHoOcH2SQ*=lM)cvniqm zztcFb2$s4WCv)^G3NE2*m$!-n9SqdfhB4;sPKDAb_In6VlwE7Pt&8)dRrbw&J*MEzi{p~;7>brtR;Trv>*`)YPX{&D@Khu1U2f?N z*RV!vwRRh^gTV!KyPzAUQbS?7H3H27`;wZPOCX9#;;mDW-_O$Q9({v4OPSmVkBUd&7e4FMo&h7ch@F4>i`MBs+`-U&qMXmmDNg zkQ^ed#6ZXhM#&2q)fZi$&h9r*t*0CX8;5GQVnLE`M*a`uOm%(Hp$?9X-q6Kr`;@-s zQJ2M90&vxws7~WAD+~Wd z4^F?Ji-Rztj3s7zA&WZWQ;wBk5DRXwxBn%)y!|JD3aTnbMnD>(I5>zV0L0Jy`t59oHeEhxld1hBm zQeP5u`ot&MnSV1+Fus616<96-jxA%b-$!&yiSY%{D`8<_FwcL9hHMw)ydd+n;-LtC z4xW&)y7TBSd%OsgDS^9STV@q(4T6I8ki!RLeCcyI?PWTI0K{^XIhecq(r0xT6qFv|8!^XA|XIb~ao*BO8 z+!dxsCNR~~(arp=5)Nu-o;-O1kQZ22)&dMm7dF=iv_`8~PaHg)P*NHk+|Ij#EofVT zItECNL1LX%wRj4Wmg)IW+B!jitsUQ989(lkWKDQvFM)f7jI7F}pAnQQnkQOXV2<7Z ze;>@RVl!rwu6L3Ly+7Xnx}vmGZ@h``0RgI^N4@ele>XHECRL?5VItUgeh0~Qeg}HSv*t4tmPrkYqi6JB_S~lmoH%zSmHd_- zv{FRn%wP(00g@|(!x|uV$Rq8Tw1jfu5HULh1ugNgGtR>PSzz(%iH>OuWn`*!U#^flewf z!<8ASO7vTSFJmy*zY?#wvLA|lDmqC?K)ty%#`uBwCHM+B9^j%hQ)FBm1qB5Yr3uV7 z2dJ#T1fcVQG=u6Sjbw$I3#|VF6VRoRzK1^bQVm-@wKYg^O=9nYv3KA^E|Li!J3^&r z^UUEnmUnceYy01l@Tv_}ocDa{3SJ%%l&GO(7}Q7;j9Su@yrrlF@Mh0`a9M^0#Rtxv zQp_O~%!M-$r-2BCl?n#Fb|&zWUb*tXZmtVVEiu(B2*m2~P|Z#yU4E^{1ik0$>x9p* zF17#CuaWu13%med?(@ao-PQK{kTlN(y1$hJ1 zTie-O&xM4};^5FI5Pm;6dY|Deck_YJ_clF&mHN+mGgEQR_g%RSXHq4>pTKF3W_R<8 zyuLL<5`>-fb1_iQ36+{1O)XH=23`onxwF3?WlZp?>t3SUDkzuL+p8l7hO#m+wtGf9a7%ym)<4}+?(;f#thk)JZ5I}^;qIJ@af{|QMbEA1Gu<(_XD+C+R zR=nPVw}^z46r{h@q@)QbZG`tPE-ajbvOi_0|NcTC2o<@QVn%qd%*4~&sb85DPj0DJ z+s#8AlQxLoQ1$|WhBaUsbOE_67`SAp56nKN0)ku0$B*FN0zn8|R1UlA`oexvbb$c@ zHda>f?Uq(ng|}?((9`pR6rrMW>H7Vb;Gr`iDW)#b{dKsvl|sFV=?^57Q&v`%lhXkm z%hFPo6$+&2yr3F-E**Q^2Ft6xR(GwC6zxNLl0ev3T3cHg0`@@g-QS#-fAQim_ICG! z-w#mex$YDwa|f9gHi;(itG)Vs2Du9g>Ns*C?>qt3_v!T$-;!&sg91#YzJk)N4yWi1^WDw|X62b`(U~+@Y*~#gBY%Ih`s4}49vC)G{ z3Meyjg|%B!T#QSz#4>e@bA;Y~bM6K7F$@Z&RRBoncw4os8zF$v^^dU9swvzvrnDVQY_BcmVX=IZbam_YrkQ@3OsH5aG{ zKJX)w;*u(${rO`O{569vP{;)JsZd=5din;GfP%|w#N;d#8-adk3uWQ(1+du#goIqa zbg2{s^ok0C%a=cZeK3I=Oq-xsFD@-X0SUX~vIdg9wz~QeGjm>56%UjrW2-@v8({y2 zf})#*a5zDE&0BxBBo4Dm*?4-W8G%pPL1HHz&sZDu(dWQA0d$j8e&>P8rK{{r%JT#fulvqi}LhM@!2`!+c}W ze#8O{1RS~mr!PS6?HEo#g0kJK!cdF@kAZ3<5N<)V1{5ZA)5yrkFEq3QR$Oth8axVY zl2X#r!C2b7INC&3X($9oF}7%s@6 zL4L@1Ckx`mz~CT!y;iML_t+Q=;8v`1k3|V&CpM+<)RNQJFGKCx_SV*tU7Y4U5%m?} zXy%f5l5wY;bf+50KN5o8vv?8;!*;sSEk@lf@(HSc;jDPI1EEh2hJaWDjDV$Jcto>*eFteAm{uON_&Qn-dQ*%yC==cByyUofvXdi z7;M~b5MAIHn*3v;&s0#2bPe~6w(HtAD1k|p%Suet20I-DCEh`Fb2vSu1^J*j2M$ny z^auc@W6-Z5=umT*D9n=IyL;El);7gu9D5EI6!DcWuyb&1&2@`}4`8cuAb!?E;bH<) z`o2`cqsaNIo8dD}K2%?1JT1O1UazInzMtWWf5(pKu<}xL0vG`SspaM7&W$e2&PGEC zx0BMB5?>7#M=Pt}6K@FmYO$wGJi84xENpd^U_)l+T`1j$7Xokz6c`CSV>@|J z_bH)($KSsh2Fr4^Ix;Nm)>VI)wxst|ZbrBA_N_zhBerVu#tkpwWMAK=g8HNEbTviG z+EL2kY=dcC5k=lmYQf8JGF)MymA(Ba9DGIN^?_KX-!RpgpLH}1j)HRDU#buby8d%= zas#r0rga1yf_!RAXB5xZl7n2$-k_4}y7ucVe}p)0vKWejocujwI`2&-jL#VLvo<+m z7LK6EO+xG$4hnf)%L=*IM4eq+R^ULlQRyQnIm1?2y2poyr`%v7X8W8STTy0S0x9d` z!xfMDcJKsBj9-lo3)6vfw(34FE}GfeZouS$k2^vEEv)x!t=H+uLp;;K2) zUv-L}-L7`sU5Bp6k{>7NHY$|Iah(QBz3psBU|=hpKhj^1SIq#c4>0Hv>{5UdAVso* z+R^$mUk;VOY!4qk>a(dK+RV;Y+VFQ79?0cWFU+Q#gH#Zt4#8y&4o*0lt)5-UA(LvW zrgT(1gk!{)oQf*X;dS-`m_{@T2}SY}2>7?>p9KfdZ%%gJ3u z#UB;t0PW)-mb+GF(w_}`8JtT6=YPm%YY9JA6sHW1#7N31`mA?kWo9OgYvxG9iED&c zuYNqz?2^t?uLyB>1@paV!!=P9)HFg(u33$LcGPe}lCokMWo)Ig^qXunoFXEy%O)mw z&3>kh>?5a=L+M{HIOH4A=;mZ8YXZA69Npys zTM{gLn(PdnrOj3b1FwFou>n9x;3K`u^3Zg@KLNvZ080|mc>u1)VDFC}NYBgC<3;r@ zE-ucU7fycb?&$RvQUj1P^?P#b-LuX4jKm(Y^X2cjrprr$-m!OD1G_I z3sf+FD@x8z02BH}Z{cqbpq4txo!+kKgAzJns*)%%Wbcbe5s{HOfs?ev+2^4#>JCtb zhz&H*HH}S8K-ns=1+3Uu$f|8&X4dwM|C1(UCpZ6qz-4G+5^!3)24Dvypz5Hi88VSR zKIgtI@t*oaD7+n#ccQmmn3yoSy$OMw4A`U7((WAIb2A(RdjVP|?B&a@m}95N95C*~ z1;JNJTpUUQCG_>vVq#Qt46p?9EFMXw@pEZ!n<~Crw{8Kfh2%G!bK(pw)K+t@xdS^7 z2RnNgQx}myY1&A7Y?y-iM+rCw2DYK6PoF|A{Et5xV0yz*Rv&j~G%bf38j=AvBqe=n zZk|sw&vu?%TK=K5a5n^BaS6_+Xw@rjX_0tj2Bn-rYYH`qFT@sJ)Jx9S$$gsymueUD+mz`EJq+&t*?IQpW%Un{4iL`R6LaEL$o_P>VZ z-y_s$!kfW@O@GxN)C%agxg18Q2A;h~tH&I}l(D z4GgXd!>MicP$lZn`rJZZT0EQcg(zKk^R$is6P^Eywf6w$^6%TnFQbfvik8HuDA^=J zMvCl_y(J0R8KsPhgocJhWMt1|E32p|WhR*^Wkf2Y6n^KW@An?hbN`;_e;ogx<37H1 zi_ho!T;u&dU+3#Q&zFtOB#`Nlqxgfe#a+(jy$pVa#a&5Zr#jlxvN(}f1X=})EVdu) z!+BPfW(8`0pPp`Q&zzs>ZDEgT5@l1+vQAGg96TlNuHa^zQEqpD-A^+mIT_T>I;@)> zfY%+_(O0hMJTQJxczyFLO3m)+*`T)JbP4B4B#*>PI3C0&hL;-pib+_EKYsYotkd!O zwaS45veMF6>#wS^ty!RW+< zJR)82TGwXsa-BQUvf|TnI<{r?^^)m)@SIy)_hSn~5qbi~@^RNZ&GJkXh0_zg=3m<( z+nB{hI#+OB2wiSL_$6R7P)c%tbMMg9j*NW?Az7T+S@yeRu|0+2x?y+S0JQuqejrQ! zE_27-faq;JJU@Q^#GS3iv$|fZYvaVel`L0`WcPMx8_{$co%KuE7r4IS_U4{f8rDDZ zPg#aVVU5PZ_2Sj5K)89(Q@6CRs7P0FX+5_uWC*zk$LBtXB25I_UdaRI?3bJ4cS22~ z>`LRH>~XEV_L#?!x2$#Qx>pt+)L`k_EwfGdsw#-K)Pp0C3}Mx`6E}sm8oN8L3|KaH zYatUevyJf4I66w(J&S}7m~VL^sGMQ*9Sjr}E_py7#3ux^8jgcy`nL)S&5S7_Ny*ps z^+%9JSCHl4;K0`gB5-(JTAPdPZi#I#AB{A(w~HQrauGWb02Vss*Q*z{1^^A?KB$j7 zE*PxmW^`!0i$+nP*}QA5pTJ(ZnJ4PuvNZ9|x0$v4SB5(_+%GJQ(m;C5P1F^@vNOJs zlI}w`1MHFsK=|0d&-zXEFDqd>Tly$T%)>}4G_C4970vSIY-9-Wxsiq$W5KmLw?va7 z9wf`!w1d+Q61WvpdT<{Z+3MspdJ5Yq04S^`0tmL*z54`2B~$Gdg0)%Xq3c>(i(GFQ zE)M|(dLzNx*Vp(3ebZ(D5p2+46%{CUaMPe`3+Ccz1s^I*-LTY3#I?cSHU4&&-})(( zjKD-F`LWJwc6My!NZY5ce-5Y0)^-aeB{lU3U~^-XK3jd3qbDQ^U=k2LQ-VAZzxH1+ zAst8q<7gwzT&MmhUhHdoJC=9jOamu-`;S9Ikhv*8Ee6=T86DmI_ASmZ|AZ_hn9PlU z5@Yk`&4>ks_i41-@jrrp1`1FcDsL1OpbwPb%CrJE@)bFIo<$xTT8cT?{+-QFIg?u|&GEbpi~&PwMurSw9UKbu&xc#VCn6 zc@MvdDJ-+gmM=da9L!f`aK0FfGhg^4`rVWdc)VAwT7{%UEYhXJ8(zXGQtqt=%7x%_ z-)+fZGaRkmG65n-)8 z-wBr^58M;VTnDV& zT~$tpMM=Df@ADUZT;6x$Q@k%~2`;E5kO@FKxNx@tXp-p$k(7PI8b?9r-^yFH{@h-7 zLie0?!L+W$=fDA1Z>%BetpCuBYB<33HwL5pTaYl`ibdh@XY6}7v!1o=PHIffpKy8IQ zJ|$I6O(uU4@O`#Ji?z4P{JCrBhyZCUrA z^?>V#;;*b{EwRAzxL@<7IwYfvEG+4>EWMPcUdk`-KJXmzU%hG5?}1vHGy&>y0TGee zsVSadurvrQ<5w^=H9h%b@=zKh%@e4Uo?&_6W+hpg;K;wC@q#09d})a9T>I{M>1QwM zD*p55Mfe88e17eqVgvLrEAQVw;6N2*#450>K2*%( zqTlzG;=Ep}C|RI*T%&XWa1)-&Tf%gN3EjB?&b0i)gE+|?cIv~l;mIl&*B?51^g!U) zY9dH{%E;%|!lkgo?YBcCcO$Hc@0F)wcFjE65fvW*`7l2|YJ_;YDImqBqZmtx+28&LE3o;jCTSYz)1$xD;>=l=}bjLG+7^ATa6y6%}0F zOtb2uBCn1ta7{*2b7*m)i0J6(sL0tstPkBg>00~ovZAYZ=2;(#{v!=%={pc=Gl$JJ0<4}cWscNBPxSUx++b?dtO`<588`=P@hdzwD4i5k-897 zQR6H{>6X#jJBuq}S+Sw;$&qN{_ZgE+*@`Q^SmhaGR=>UbDrn(yyx5cB6v8iFP!_Sa=dHAn8)d&cD?bF?M(FmIju6R!h5uwn6W>r-E9 zy8Ei^^J>Lc+(zPR5&Jsu%155vQ1sYdR3QC>S}_#g&L6Y9_~+X-^%VP(m2EVN+qsSI zD}PF+s8lAg+o{X9U9o#ougOG6)Tyr>X;zfPw}tG~`&z3#?D8%S&;*IsslRSXp#gi} zyjGl7VZ`@$Yjqh@Vn3^Zsk)&%j<0A%%(c)TJ56%9&ix`zD=uDRWV;e12PAv-#*HE< zQn9>>@=Lc2fxKir6yJf}2J%L_OrD;Yl zCxThGu+r1puK8%c;cqPf?`=3v1uZKi;M?aZ0f|l=ho*in$)+o0X^MDOX3&G zVC)mGyri2g@eCoy3j)&#L`l(uvr0hqg@O_09m5v5fs8IAboBj zV^VFe`EJRn_2>ON-hbz%A_Rj?8a7;DPGr2ia{gRVyWX>Y!WrUf75p?+3zb1_L6VMW zNjH0$84|Xj#jqAkzy`n}UXktbsQJGE4(LbQY>a4O^W$v!WMa=tw@eWKZpqzrcZ(`Qk1-Km%L}g2uyQK0Z{pZ=*8Q;{tslXunDc?y zPp7-=>GJJ1d^hDxPW?Qye@l$$AtgLU@P#UJzp3!f1_Gm`pp`>LHt8g+rKd$yYWKZE z=c1z63sb2x&X_b%{rNbOhh5H6J*vtPxvGjA#RH%kQNY;H$pj-5+rg|rijI!uNN@ti z12BQX!T!h*v4fPLZU6Y7wc6|5h8SloVz{rWB7m#Vp=FB_^3jW2fir0-ph80pOCnkTu#;7C}Fk^hA>xcaN_KY!Mw z2aIa*I7GzmL$pKlSx|^r=ihX9BcrP#E35I(dWOmbtajOs(4ko_D}i2CVh;xisP zLpu0HEF?sRARtJ~LiiQ3sxMuVgPi~y)ZV?d zi@#qjikit2+dU?z8{wnJ3KAO=gT!YCbO5I8WU$#@RpklyMx-OoIT~AuPX5V$lV%-r z!I6*-1Ef91mBz)Khx6pEYxXFY4eCs6AcD$NW0`X)3k$Q=Xuu^TXCOU*%uVfft4`$$ zuTr~LR(8uOy}aC%kBzj~fRlRj<_EMNz!?>Sn=9A@BE0V+LqMB-idjljG*Kkct|Bj5 z7KJ>R^C8cl0Mj@llCC|fdIpAuQ3VBGp`#e~mS6bs9%>4Wra3lcm?zK}jCbM6HnSF7 z+x_MZ=@mh7i@pYq1uJ=ONj&&AWc%U?ME3>pXlUbTXhaD6sIO~|wwxJmIVZn*cu@dx z0=M#31PM*jh0z!&hc3=8E+pV}{Qc(v1OQAI2kTdaCxf^aVWmIMH_~6d7`X7AD?GUh zxEl$ypvn4RrI+y-49@Fc?nP7AIALUL932;@sq)v-hBN5+fPSC834B-!~~&|^N4R84on>Jm_&ER#N52pOaWnl5)yE4i1G5m zezOBrE*=A>_LW4%wWz3KWEc3^lDi=o<+kVjsNRv6hA=zid{m{S+2a>RJHI&m3T8!E zUHxG?I=Xs6>7qxEl+Gx^zmjNT3;1kiCWFAnyoc6=&8?D!Q|Bh`e!M;hfd_(skxz0p zIy&71Jv^M2{S_REkiVc6jC&I643atCgRS2YE`x-Vf&ve$j;^Dj6X*JEdk2QO(dI7) zz6U8XTsxGKl5%zHfmWSeQc^64=EJRDXy25apQ=|K@Srlv>GisZdT>Jq2CXHf_m?`E z2+8yPW!20N+!io4*U#2-|FH|6A4H!_egCdM!J~?-TyJlLLg8d!6~LWAeI_v}i6SrG z2QfioqZ4W%V85Nab{)CrNiZLJckz5|WP_b&xy6>N>({T}<3DHc^A5+peUCAw1CJAl zE9b#4jLdPmB(RdKCfINU@sm*!Wo0K|>}Y&N=Ci~~I3k{5%Hagw9Q4w$Ssoqx?aPM4 zr^qj_spIa%{F&lkHqJ2*gR&ahSrAHRsm71qIb?~)qkvhs2bimOZnwN+J-C4<%Yx+)KtO}7V#V|MZK zDgq6q%f}YB9|QoX*4~osGMRaKm+#nISjZXaQiDtY4@084*N_`yWv=2^dJ_$9R#v6A z^C=jbf+z;m6K`OHitk+ZLLUd{d%eMq?AoZSSDcy^rquQHoJK1WY+*-drohj%oE#Wa zT*w&G=(TDD;%&%aeZ_-qt)0*4a?Q3 zTm69*_vr4^cfM1gCF<1Y4G@J6eGM4*TeojtuMT*Tdx!eYz8pJ_i*cT-@{SUT6r<5} zwd>nBkyV456n7O*;QTG%Iu0%_l4%HB{MFB7%pe$K(x81|hsBvd8sY}|E8r(CZ`k?d z(WB&h_nPs5d=*1#I5s9DL&JFK<0|}7;+ES)!J0IQW;EKDIZ!3$<~>z^VcwtuyA*#E zg0zv%Y?}A#^Md{CXb z^iRxVLIlA3+K&nt`x-j+AW2*l>Z$m|8tC-eCJSfD=S7)AJnTgic6HLBl> z6SpZw)c2@uc||o8mPh>DS;kVM4KR^|=@Wvr^>%4oG3ymsFk*uIk$a5BPp(e8(Q*Z~ z;Z;m9f5PNKQ_>}Y+I2z3e}5ywW#0>nO=)xk3`lb^!n}%^!;-HGgnFqJ&Hs8?i=TkuaxSXbxd zXmYbcB{TYQNTR(y%c0kRgSZEx{eOW^JuSFSyh>y$tTffyB&xEf*2sywj@feUDW#K*-!4uItg+;8x0 zPXeNwYphC4D_3eQwBJ3zGIZ5CZ2x`R`fv-(>&D5?9~gb300v z=U)X?;xU5AvPWYL^dzJes0Uo6)U>scN1K5b3ko(g2US8_(2XLsVE>^1(IC)rJZK1I zDsA@xY^yeVv{E>cujcvmEEOYol4KcMt!wqy&pOgg!esBuIK1xq7LxiVk`vClz- zGjd%8$;4=+-{^dZS{2zwa419C26@fH%F5aC?&u{MVFW(xiA#e8;Cpa%J47}hoEBuu z$WsWNKp!J>pG_Ha-T?U9p3l$EAANC4&)RzNL&KWDz(6Hc{7UxCdRt`keh2wJ!i6;a z|1QI79UZz1E@g4SzuY1KVyt!RqR~BSeGUl~ywBMVriS_=x%?QIP*+F3HJfsS-F-M3 z+nz%?d@DX)OF?+Y4oWac_tGq_#~XiyW%h6Vy`bca?5!ANhkYHQm%tAnoXzHF128#neVqSgM0r z&nP0w9XVrVs9*3;VwRks4bx6>2eT&Wl95_J=Rj~yPfv@-X!5bGRsvUGkgKLcrA&`^ z4vzeT8MDpG(H;b7MBykZ+FVm(gMt|u-$@DLqCctw34>ix2?_aXh8W*~FL1tC6Oihh znUf;{kg;>;F$af4W8GcbuWs9gQ9^4NLjcu~PjyC@@8YFPM=CZEHk@Du&m-LK-`h4K zy>*a1Ay*Bf3=EmXkStalyH@+ZbZ!~80=yvdszWMO%@A#wuC6ZBD}ZbO4%BCAnwuk8 z2gk?b(N&~(bah=A&CY-8zaqAMvUQ#y;%0vTM4C)k7(-hKK|J`=#ocP;(~7<`YT!{k zA&_}Ewex97s{J>37+$3ri%B)Mwu7)Vqap%_G!2zG-yJv$;s3o?RK!G2uiMtHkqrUe zf6#_8P!jxSOs%Z$gocJzS67qG;pt;0G{mr&j8UsGEfv8RjJqQwX0ZM*S@=g z=m{Zh60rw&(#wPA!Lee@+1yhsjaN8jZ&p>h{eLbPhreAS6n&S5Ek*H#%YZ97yKKcU z*T{~oYz5*XB1mRFHgy=v9Lxgr#q%E=iLC^s@BDkNMQ(Csnb=E+Jg?|3ayLDXy}8GyutxSVT+EmY~rDUl7gtk~lk>-6;~XVbf726d8t+vg3ugF^gCo(c0dpYdKj#G)OWxht*@uTM zse^pTF;hV@i-?8~QF;fN8)ESDhI0YDg@rG(u3opU6J$qyBWSx{xc35}GlV#gzju(rwWoh#0rhQmmTPb;KF@7;3oi&#}_Sx1kZ)y+OQRV zL*3T~s7U_ZOAm0Mwive(ZYFl}UGe9#{|A58sG;x!g2Cwk1qFurHn|$H7ewseBJDmv zv>7^tn|CNZzylx&?WA*;c-ji8Z9t|$mr-PD-q}M=dctA{dJ~)CA~@a-w?Qyt*RHir z=%eV&MS4k24(W0SLVzuPSAI&bJ#-RCwahuWHU30cw0ylmp=E#E)tjc;5pE9+^_{y@ zy%N1VJbn(}y#h-4+xPD=dGzZ^pH&5tKh)4N!8Q{Ar)LL}g#&g1@Q$**HhcG;K_mq# zW=aZ<2|I`L18sf%>*sUHL3McC0>_IxWh`0l-TWAOX7gBD{3N=9NW?^l$PeU>fZw@_ zxr?~KfNK@+i-S1$Y~)TKOk~u5s&c^ESU4J*QF5Y0mJ!^55f?9_OhpNZ6NlziBCsHT zBjQf*z92sEm>OCwaxMNi09_^oknu}jP-Q)8uAZSj%6DJUV@fpjE6aQ%_cri{3u6dpOou_7;GYv=vGVNQ5 zPI0%mvff6cye!iKlQ_TvR@UZhV-Yl5>p8lh62+;}t<34Pr)6O9tbHw4{&vSJg2`T0uqpQufK_@M$dBb_St)ns4he$ zG8)?s0b$TnU{N_({0Ql#NP_`x*vP>FDLD!N@IQRv-)3g8w7WgH{Tp5jq@K#p@5TT+ zX(QxUDg^w#m7LMjV}VaD>pP*##(TX1_oHThTZt)@OXMmt^$`{dArX;uK7L-_`o2CZ z{}Al!An(v?CU*>gX0+D~D}$A?)8D$7es46~C9pOEoEdxoBvA$bRy~LGf9DK;w33MS z`t>%D$)x-kBf%hrCa2v(ZjSc`l!su0)9K`3T^Ol>0Q>{ju#~@273(Bhblj{XXE&2U z@jks97#ovgS~xm3hTbJ0>3pk6W-g0{;94kuT0^@KGW!NvtT}IJL1Q;5x%i&VI&8i# z+$2mf^C>D_REP%e)N{aA3sO?Rhc0{tJIXn^ee{(=cQ~2sf~^ENI^*S&M##P50xWcO zZJeD?V}VDNKICG)%iO@g?$DvVvrJ+2gXkdpog`V56qJBkA#BRIX2nkUQPgy#-YY9w zcX~9-?Daj*T{=6yghEU*cd6*D9ePL@8YALjD!4ZPA9Bzq$$X=jMQMrAC*4{G#TEtz z`{}X51awC`n7bVCy_~h&u=qH@zVhW1zENxtqlZ)1DhL*sJhX4xIJ65FC-0qniiB)1 zM8WFy1-VXiCCX3LF#?42GaLDdTOB}(iDwRnZ~+kcRZ24j{A zBkkFsAOh`Ce6g^w=&KvpPWlVw2hFK2QS#wN3LDCIGSw zIWbTw{ie4BBi%eRe-iT$u}VOz3yEo|j9FIJ&0RSba>{|%boo;H=_xz{0>{9XKwrwU z8ghhmuk)ueL0X3dG?OH5hX(Wu!g*?!th z(7Q`d*|u#PJVn?7rV6)Qy};^;S$AkO8F6e}@Ac8z`ix@YiA~r5Hg1Gk;ufZ^fwhHP z6EnJunn=kiribaaCB`zMjE5N#O%)V|I4|F^>{b_f4yCsj<){s1#TusmM-bm~`g>mK zXDoquATj2!!IG1+S338#-X<(C4X<8BH`sw7_Il$tIdEoh2i_Ax*EtWA_Mb-oT_U=Y zh4QVle_1Z1&ZP}<-Tt4|p4d_D zCcqhzAmP{w;}iScOJKMF>4I4y41pm?yV@1xEJ~Jr`_2J(z(u0So%m&w@&6_WMG1br zZ@<=1qfVxi>Gj4AiR^IAZP%XP8J*C)Sw_X#*yAuV82Mg_pm z#+Kn!cvm+4?)Yw5S&aNpK5ziU!o&ObJ*P)I!nIIwqsC#N;3&!AoJ;2gAo3Kb4_r}n zS~1eh0eo+4pbS<5Cm+>y08PhH(xXQ+#eTDTap9DS$t|$5Iy%M|lc`x!m$am0T(vN! zyvAcSyLWFA$QSa4$(fldJdN7g%=6ApPH;|U8}RRfOy%1*tiQ>!46qDiRGpxZ5Dhi8 z%-3YpK`@ix&caTK-kuyt^~_AiYcJgylUXVc*vW`)00T4&02NWmdtq|~?7_O$ zVca*G>0|yn#dEr;BvVwrF}CzH`gG9DDJUoa_gBx4yMf@+#s~dWJd*%OeUje}8{cBQZv*nf_Hf7oUA#UU(j`9mX^qH=eclsHh_@F1bJD z+dr@#tln3_{BE@w1HkW!6>A3GA61y6J)^_;)^_wwbNXR%l%%*;;LkPJQ8U3uR#;q& zI$75u=#4+mYBevfDXh>Hze0*YcI-o8PAZMi<}#D(Xl^FckkCcN%Dn-#1r&j&ehRJ| zX)D)WV|lWAs)R&|Cz?7tr6eS7jPMh?U)0svA>ImwXfMK;^z^Rwk~jw##a$e9lA1hOg$ci=4Ed%tclN`FzdoXFkf*7mF)~bZPkZFxIhYNoKc%-6fQD ze8{>TK$!4}k#yO(G?$lB`^ zKY!K6$@1}$oG&wU8v>Jx&LZFShV=r>#2Z?2_BL`RQ&XWZ^(_Alga}fh@o!n1Smh%) z%O88C5;c49a`;KOLfsyIRdI0{$J+M{RVHwv^`CASwz2csw1m%6?d%O_l?I~iF&YR( zxQrv+VwUq#NYN-{WN6642$gG5eo&154zlHc&A7n#gN&}U6|_VN z`D#JYCXf*0!N!oby?d!BACRX6DI71w4(3hN)ixC}gv|=F$~+N29zjhH%E z_TWV6axGjP#)Bo1KMK)jV6^sayAGxkVf|C%-BK8IfI+I`+wcehfMRLokZ@>*2?UK` zdP>AvA#$*wvvUr-Lu6@4$%^%JG>nysii`V>$O8X3iZZ~=!<{))KiBGO!mN~`|X=&crtEx*dRxSAT37MDkDE1 z3I1VAf))IV;d9%9H(gynL0L>)0SAGJ3;X~s&d$iT!zKVNisQ5=mbCxsavB-x>+3@` zXjqh!wL>ebH6`=Eq3@oFl08q`zpM%f-23!{C#gk8Y~3wkTE%rgd@hgA{Zh{P9RVI0 za@nc*HWr27&HP5&czIi{fO1Aq%#kCw)6=<{pO3h`bdmatW}S1I9UQcsdkV8clJ1H3 zPgaiR7aZ(@Y!+&j;iru!wGH(*8l|e~BQp>cEO1p$W~N@T5FTPKU^dKl^@o9g6p>?F zBRibzR9+%g@rNHQ1bDa{Ifm5%L1&3vvtylZc=j7#%>YOSD86E_FgBhAoJ`W)ZBs+| zm7^DtbrWo}ssf*&AT;`o*1q;mPU?YlvEN9J6^e8^D5 z#R)22aGa!<75_u)8s63o7&y`TnovxDyb|5HljsLyL7uu+R#t}f9tvF{q}1V{U)-c4 z1kads#V(b6ZKwV5$j;6A#b|D0V`L!DR@Q5S)73GmJX?bC3$<{yb~K`N!>x?!11%eL zG(oTI@%%tPf8$K;qUEaWtjyoPPm@<}hmtBhKKO!e0T>I_7w!OfHE)zIBmAdPMYz1V z_l}fWh$yER>g;U;KJn;k!1_)P{hv2e5o&uZM$D4F?n>>ZCCL%EV&wPR&A zZYxxOux$Y%;^?qTol&%bci73CXx{m^{Kp331emg19UU2%nX52-6sr|!3yA-;#fU#^5J5K1TQ5mtwbh@iqQF+oOP=Ge?!iu(B&BJ0%aU40W`qM#pQ-WK60cO z<5!TX0G)VA?^e9G_91Fc zlpv%b1y4R^+<<=9zZgYB==`B^=iP4TS)?-%@rnmd_AYJ~o32QV25S3Dnb%gzBO@&h zu;>QliC|KZUZZW-IWgK0*AA6^Fe|_nX2U}>)ZW)u)jhU+Sn{;&Q=g&v*6uAv)DBd( zyzW@DJ3-i7-XyJLtvE71&WS4J@Drx3cQ0E8iu_+xie}!&soj_LzeGUaQfJem-G7I! zxiou_DPA2fOg1;&BV3>4JP^-fu37#s-wc_!yIJ@F?ZjZW^x8jN)-&_BIB!8gTBH2W zAG^1<``ae`81uV-{#eMHJ#!bI3!hnog+)1s)@E6qx($0?u%slNHSwtWxF85O0jvQU z?j9FnTpmvmjQ@N&v|_JqShrJbSPJU^A{@z1EBdwXpIL0ErIR1{$9wFZostb0v9?$) z{LjNf6Znt#v&QnDFE~sj>|7goP2wIS&VgA(6w&N`A*xwRbc<%&7mq+2%3p7Tc5@N) z-YlVD=jILgRxzu<&%(m82)EE(4$Pzr`Ch)?=_($=>%7}16KD(ux(}_4eO!GDb? z*e)@LgYaa^SYi+5`35Lq3Ync2ULgA3+XR8+l9JiXKlrNmI}rR(wU zhXeM0t&rJ%dgw|@?%yY$m;8JftPy6KyzencB^=7kkFSTx_-o?}NhUKjLv+m)9FEWY z{6>fT^#ox*MXvHBv!F=WC+^7Ab4HUCR9`yy;ekXym!P~|u6 zgh9heN$(&kI*l6T^l5ajv7W^Uvj%mebFat(L0m?8`A;x(Q&+H2O)2$0toR=mg)l3z zo0H$ZscUHo2@6|c2r_yM$d?6zm4jytG81I!ilPT+e26uU=ErLW7ThO$>A^anr;f5} zOE5|rglvrAq{8M8>(ORWn;JAuafXMF1_EtO2rpl!>$wWglp&serm1B&G&@s|Y&~!p75dTcr&$;3$=s=Ix6tC@=fY5U?F~$u z3Zy4>@SV$;a2J$}eOXsY>M(1wSMZ_hjT0S{r*y!*i&rrnR5szI`9E~*Q}T`9BRBak zd1T|0C)+3#WK%d`>GDiXP zGL_mG#ACqk4RWYB;6QgeP`{A0bUDJSQMp37lmRVN@i-bO-@ktsv97W(GaDTlfezcQ z+#;`jHc$E1_-aM{w-qneRIuP;gme|sv0w)R;9y&~Zs&Z1?~}hF6&4sg4d}5Cd0tiZ zBK5Ol$2^~3{x)Y@@WXm>E_!eWNMwW%3%F_MXyw1T4#q+$X%emTwo#w$ zLOum{a9BSzW5ku`mt=2)!^0UTz%3=-ioIh5291>-E^9Uo1Y-b|0|oR&&8{F`Ji<*J z>NuugpsOPmp{u3U1heV8fq|MZjWJXxxK6lbQ2s-}VU%Z~Hs8eogby|}4lWqxI%{ zIN}&C&@XrsVX#fhrXi(eM2&{~RI3b-TJ&??)nTx;fE17VQZ6PTaq+?hRc-ABykB47 z;(T;of6EL51?(U`xF1R=G(iA00cCQ2=b+aD^o&eojVtHDji7N|;G^R?J7`A4qqB#v z1Ek)Xt<+uuNxIMyY{Kwk4B!G=(RcC_=g?77bqT5gN%iEk?${i>6&Zlx{!R&Rgxd!Q z(iBq8w|jQ&LJtjdMxfjUtAcO0SZ{jD|1dV5El~hECwxuD4{WL_{lc?sfcEs&qJYPp z4`|-?_xD4b>1Pg=J-JoYPyo)ro**V0;Bcv4fjvLRq=4Gew1=FI2CXF?_U1Nszf-4R zQ9%Qd=3MWdy3*?E3sDbiN*`|wiilJ$V_u{vnxFplE5al*0hufitW?<4Qlm5ft@BEG zhdxomzg~K1i^VGy&!-qQ) zLG8?M&zf|#xU3Q|y)3ks})5K-7qqDzeMG*j{H2zId-zjOWe&A#}++f z?$~{3$$uU$xe(Mg%I>{uO~mX)5x6XR^In)Ip;p|& zH2vCgHT3cxD*8lkWu;+5LQH$iTnX7V2PgQWnEk;r~pcADTA zUXt3KS^2}q^$S@}q8nTl?-wLDB@!^=Yq8w*U3WPr2_%2`j8c`fT&cBPV49#Yo*eJF zOlsfAmpJAj7Bg~S+w#h~(&MruN}L>TrxAP_31|K+=JH6NRwL=CLi^YmZ7 zx#>{}#a@`XjmGWkzr5-?vD=^C+;pXqsQs58?MeMhikI=PFJO^=J0o-j-`YjKVH<- zaP#o+fJuhh0hWaG=g(vFm_+*=xj$N3F0QT<4(I-^mi}*M2|IP7@@ce*binTuXRhH9 zf)@MN+?=>&r!`qJrKE^jE+Zx{L)4CC4s*&dw-C2ro<+Gh?pw6>F~U0!F;&;s!Z~!A zQx;?XwrR(mKpqIH3?$cM*}&wEo*OhZT(GA8M=_o|i?KWMlZIWf_rZG&1_fa(zQ>OX z@bO)Uh*%T0AGQa$D6&d`@ibIbS;O{YZ>T;sn}@+^DCc2TL8_a(J~Poj$!7!tG4^*R zuukLM*8dp0hNQRMyWgPo)6p>v7sR-v!2f8~$4>Fq6{Zl7D!S-cpkECq@Wso%|B1k9 zy_W^X1}9;rxYLS5%(f1JN3E{Kz{sFq?k%+#;&&cp_BWNIqyQnI&kUsY;sxB8hhVTU z(%1PfLcT0}3UMz%moE-ZL;%{$Tnh5Ao}j{?>y-WjtQwD5L7@y53)&_S7hoSj&H&9k zZ)$>cs$NT)c&IY+;QxhYZ&BgYEN5qX$0F75V9Gv~M=CRXDjq?D)KQc&_km<@eT|lb z{Dyk%uTAIKjX6`j4X8ZMZDB6Da^WtYlX8KM9u>uT?_PVw$gBNao!e6tm4YH^zn!d} z^V=mYJ=^o8vRpankECi1Gk1DmORR1*v0&9dK$0%gI&3p@FU}mQ;Mk zyN%FU;Bq&*#2D*St6;E)ic1R`on((rrYYGQl>Ou+AILgk;XClr;aX>Y!&Cw!4cHwy zvI_xBa3I*(O@?pZwaZXXk9^%t%%M&8=&)RP{I1CCO`%%D7y6WDAX+q%V8+$q{D9Ru z49d{(@MIY-r3;ua3ed`>5Fj|AN)@d0c5ddSTRvNA6#hMS5s3oD_KsvhliAsR!4h!F z&rfFhEdP~DmxiKh=Fu;19|Liw1Q@_PT~bwLrK~)J6s5u6vboNq$W)A#@#deda5QVk z-cfsZ?p-KXnHxSX8A)Q_g2QH2LefHJDY(VpNb~{pA4j6=qQ&unoh73Fpsp?kry7`= zZYcH44w1Wku z=gVTg?58?frGB$zDoQ5=~pI zsSmOCjWh}3cwo@~DaCuj0Bj$SDT-!#X6Bc#UL}YfRw-meCkpfv*?-4jqa^@QHjw1h z^fZn(;mB zqahd$q(-&dQIIOR1e$gBJS;d0@izlKJ;G(ql+j#W+d2~@5@`mfqJ6iI7L3r;QT7>o%ZO7=+vvkzX zZV!|xey2Xa5d&x+m8pg~k^H9LR7PT=%|Oi=>Ytqob?9_)q{dig<>gN!-rCd!R zn%N_bW;9XfKi=R@4DVqMJ&tTW)JUT)T3Ra|uNh&Q3OdR-RDZNU@n~!%vE3$UVGyy$ z6Z~Ol2zw~!o)fx|Lc^*FZw!JWNR{}*hkHUFpPZX=#0`OR1yz%9+9eu-vd;`Hw>_W} zpu)rNO``rtsaKl>+3>cjDh##F9-R;PRdpb>`4Q2-20FfsDjrP7n8#JRnE8&vW4h9WyS61`_nkuKb!khtuHYU}s>e5Ml+!>boBypY-V;kr)QbH;#b^8)9M1pT@R za|UkORv)*Wk&++|AlG8Jqyqo$V^p%B7Qo|zMkc9nkEh$DH(dsMgL4C}V|$+iRj~5g zIiH?VT=t5%%*+uK-D9Jpu6+;H=z+cbamLYgK+J2IHyoMMAbs$uB81clR;i0d)bwYH z=9O0*9LAD=zqoiD5+W=exFo1NFi~y4seXVb%9*Gj5yCO)VUW8juUoQxcd z;T{L5u4!xcpf!w`+F41A3_nXA0YS*@*s|rUjq8#ml73k$*(@elsZ*BZkleJYP$J_O z=p%7=p>fK(bZmGVMe<@}ifhoH7YQaD|GWUzzr4Vt2pS-$wMmRvMne?<+z8*t2B!0s zmHz0+;Hzva?peIj;tVwJXqIz10}KY;0&f+(&sah6as8paSyaZ#1uSbe z&j-IF7B(;(6bfQQPe7h=_CTvsAwUT%2CE-lWzL}{{Py5;Oo~9?097F{3fLQOPtT3$ zpn{gK=QJqwg-!y(eyD%oWr0Z9m;4EDZ@JSy+(S9+3QRP&>BFhbiiH37pFVZo*S55b z56Yc~3GhpQHPXpWguY)TT)UNyXm~^w7V5^hKOeaP>cW|iU)9!9BqeYD+HtwT$I;mt z?OsceRr!oqkiFsrME=$Sz&0TzCf3s2j2ULH8XE`QcVpGX2gb)n!vJb(SF=T|C1ijR zlmN&aM)@TnVE|2!{6?$~C|8mE8>4Bze}5es*(NW{r_CV&;P&GY+7cBR{R)RgICWPNenSM6{d z8t^Tv)6M{UD!jjA$o-P2OKB<3+3;C`))LB zu^qd3U&Zt3ht_xd7}9g3v;>3%1!1Uedgl&m7xx%KCz=BC@awUCFG>OsJXQeIP9=iHSj-{AG|}I|H}o4q~|h<%(syY0D?~ z-58^Z2pebxQ1*b-yS3+}xS>2khTw=n?S+@ZwuhJ;t9Qi}KOfF86froaN+_D`U{3+( zU+Z1Vz;vf3$%}}*BAqIaYzs0T0lDKsuZ=*nQCRgvu4_Pc$m!%|MC~Cg zpJui8g}$HP9I~}VNXc7dIXD>&Ve>>raXqKm?7q7#0pP5GAahL$$m~JjS?usVx1|tQ zqLU!s+ueOzCI-EPjjL9{>ZL>9(%Gq_r8Pe32VEty?~XY+A;-F?xY$u*qxaB>Hv4|O zHoU}ezkYQL)d>bFft+gv3yT6Q643E$#OJ#1{03(PXiuOSS~|K9W(AAh2X`jy~GV$`zN#Jh8ldYeC2ugEPQ(S(;utRJ0q^?f)y$_H}pZ3LpC>t8&l!h6Xid<&Z%AT$K}8^{}3U+nkx`?QUuD zfX^475U=aB^ILw^Tw{NKLaogvSs%e|+tP;kwo*P|jRO%5T^$-9ovp28CR8Jd=JDd7 zyVKGnaU2jo{Qa~OUe}gXecN-#v=h$U(_O3?xPA6!#o!xyMnegs4VxcY#DDMThgWfuD<%ndZ<%9n92^__ z1+)tkSQ4wN#Bvzg+js9M6MRHs=+fSqoR;P@(#nese#?Dmc0ED~LXM8yhFRmmcZSK* z62tsuc9;i&0T=&io5uJ5f9&&n)@&kVE~wlk--n3gUIOUA2Q|QwMI51zSNYO&Z-%@R zSC?hQ3iF323d#=u1O24J#ZP~7aiJ3EfM^i^8UEPnmITl32ncz0WR*XQNen@oh z+{w$$?e!|Uj}$XFMW_lQ3%7mbqf!*-&b_f8UJrbM?1$@A>p9X7bP;Xu&!5&z zD2{#x>!__g0lgy(PlJ6npha{8hw@AdmtXlxOE9*oGZZ_vZTt3xN@GHocX|~Oa=7Mf-2&z-uv1K&0gxZ;+gG$Al?$zn?5*MCB`jdz%Zo`HK+X8wD zkPU`YuA|r?tqR)e!OJ*b%T~Uci84WcwTF*STH8o_Q0n>fDr#yCfTmZCsMmRaTUBk# zdWLk|FI(32<_$FP&PZ?ulw(@HRaVvu^gSQt=2C6&3s7=me! zLRIdHgR17ybhZXoR*;dHT3Be3)3*^555MI+png5)I>mL@O5{tvcSl?wSbZs01rf-q zmi}R;Q3SUzw(NfYSx!o@cDk{F0UsY9f@7oxnHdS56|L%FDorU+A>pew2dG~Jt2i1@ zNMS@>gWw*Fj_^1@OI%y#n40qbvaT&0QFY|>5&-(8k-IsN>GixLg6e8}8eMD1p7dGM zsOD=$O~0rL-n;LHDZ4!0l_NTid3Cyle{*;hGQt zl^-Hnz)F(V;Pke7PBt%&-dXE{iS^}W3v#0Yrx+D&!xoMTx&*47E5pr!z9g5lXUfQ$ zBO_iFSFT)1NJu~@aQ)$P6UnmMj`kWqU9e<*wDNq$;=I*&!_eDAP*^w}L#z657>v<@ zkh_zOyN-@kN*&>+e5^KJ zr&I;@ehZtelSs3q{^z^UhVeT7+>~aiE;MDFjP)k58&&#h)oZWh55G-iQwrqWh!Uwn zE+vXvuR^1BTSJ%#J?FptHbV=ij+n+)rQWHFFU9ua75-_O3_ar&Gs)zBK4fgPvydzEQeML*&OMAx2p7Iinrq) zCB3;czvRK%aNk{=8P!K#ekpzVaI|rl*pJ~7?zk+#IEd%aQd7gZ#l+{vmoNKZU7T$~ zye*`qkS2j5z&Kk`1bY;i0D12c6Z<+l3nTU_UoWEO%4A#Pmo%&Rj1%`p0@X^t1y`-j zbNl@2=^fRP3N%U!jhH4B4(4kZx2T==p$^^0oL^P#{$6xdC{M#$*Y!T1AJ9#6ZLH^{ zSEK_=f@v<#P^Mu+#Qy=VCks5lH5(h7D;rudMg%>=lh_17|ANvJ;O9pGiH*Izr1xk$ zI{Fu6We5k$=!-_$znp4@#JMH{CAF7Z7OYiL^^fNhKPR?R=;AN2y5bpaKfj%&6Z;<9 zJk6V9tl0W}Z!DAL(2ooz4?5~*dC+ZG2tAG;=McAhhGiJ_AjXhfi;RRsw+thiH%n9L zsi@c^IT9@bAS=r<_oSSh&)@_Qx`qxqAS5EH>N&Z+XwW(Zh2(I%1B@c9i&$P9-P}aZ zX82_ZkDRx&JL0#aQ4)bAIWwGV-xap?9m!*-*j<^;m6DFy+nL_*to3y0fj7H3?l1hx ztN2Fq&i&@ZW*0g2E35~NrWSN-=Br<=ic1vgz5;^mAF~sVQ~7C+c*i-rrE@zfqZ+ zmzR;vmnmJc@NR@F!Q`z&ps(NQwy3J3ogprMQv>R+PtAk|Y@PZ&bEQShDAjDeWDAeb zR~NNIyDq8xX1>TdkQg|m`)xXMUG>6=b7+YX6*8jH;cklp4qcr9R!!k13x z@d!y~uH7Xp`P}AtXZg8ywhcO3SdG4yTAt9{8S)@i{^Tj!vBN&5xz8=K^Jgz5wY=s0 znH2QP^p(bm@!;U+F(tz14GL%Pno{}|_T1cag>`k+^sBbTS)Qq()BZb)+n>61mRpCN zo-fadgZF=TwNvGUUqz0=Ew*7AqV?v6(N(s-yD;rU85x9;$qk~BG1^i35>V_ou=TGo+ z#W`y?ZZyNZkeP8H)2^EdjAwP;TUO-kM|8LPO1Yt$_j$DoU!`}X7HmJb+U-M*?7MAS ze|_3)1&tvzF6+y{PlNy+YgVmqvxK- z9D8iZf`Rw18E?m1Nik4fCIno&ZFcjkv6vxcX8-6wfxnlQfw}7n-|@rtrjrc!hxqxV zE~g8254l&_g#A=((kjfGpMMJ7cHH;lk3K7GY2&hL`mFfjxsU8*7sJS_aLqYK-F!OP z4QzHs51WpxQM%LjV&^@B^pD&3Tzbwak;W3Gzgj78^U10c-!FV$rt#$E{Q;G}yht;r z;-%}h*#DcOvg1^|t=3@fdd*AV)$97m2N!-tzxEFunL2nQex^gwi9Mbr^9ZMv z%Qt=z8$+Ick;$%+#6-aZokp>X@tlhyvBv)4|A({pj>r1{+lQ3~O`)tLDY926La8W1 zc6LLuviEFA8c1e@Wbb6}O0u#^cA43GulqRb`uwizdtKlAzJ8C}AD_qP5$AfJulMWq zd>+qZdK!6dWujgJ%g8gN%+xDz6NGBe-6pt?x~BWX}z;d%76vC$I6uKP>CEVZFR1W+G_ z@&K0exwkNW0kaF{5|xz+DB~I$HnsM3e6SD<9iN;ugVZS@;mn;XN>h!i^r_au+6Xj4 zS+GVtYMbAGJa_i4>TaR6*|gkUMO5>j*JVaCL?RaGQd>>3V>~v*&%E;px3mx|IPJs9 z&JuMyTH@eHXcC3QGs`w*vA8?+1vS*WGT01HeK4IlX!`WwE3GRxv)azdN_gf69#i=t zbH$r%rg#QHoQ7-125am3iuZhwFJ8<~EVRvhqMpQQ)mkfFp{jPCq+x8&I^xrU5L!@jS!DB(cXjaE5Y#O99^W4^SkK=8`8-(8*YZ8=??Kg zO{tEl2$BSqYbWqAb!6cT8T5o};&Y8oDb0p^G@X15S|$9jz+ZVY8$O1QBY+)MG4fL->} z3ttSdcXZ^VegSj_)CJ5Sk<8A+%T_1Cy7CvRecr%XLyGrAf`e>svH-kPl7;K)B@iUx>B{j0`3fDZ+eDw8E zj~D!})Lyz!`q^wM#`YbSVcTN#lyIBbUf+3aD2sxG@zA5J54wToJ?;6_6W1w|s;*J< z)xL~ON>1nzSsB_)G(4H@D64o^!iXYGFu`h$vl_RffQk*iFKM)Y?3O2mAc*M z@oOJNCs>swD!lqw)4~r42%2*-T;+1r9^mP^+H>{Z&);HCT8}FSxW#iMtlzu$`90~^ zl<=kR^-8re?8fS;x1;%t65G1(*gc#1;ZA02ILj!?S`b#}Vk|11miU2d!kX6Rd&l=O9?MC7x*@?-ipg`A z@AbAYr&+pKWof^FL}a1^9M z5($(GR5MEp3r2UyGt0}$y7H`~ke>ye!5=*pGCcms*8I?aQXRB$-s)m%nhO7u#n!tJ zP#;t@+qE18?X*HBj{#HD=uHiiQQLTT_`p^NJEzP~`N{Yq6w zEcmRKtNW^M=Wz2~yP3L4r-iQJY25rfy@&hq8f{k#H=C7R&Yl^a;Qv{l=#(+%z0NW= zu)krV`F+!hk}2PZOzs_T7Shi|#U|tm>uDv8hGbL;{<0i2DS8z4+^R z8+eJOZ|Co`SKm^mPKb>+e*LPCxd+fRVwkp^HopNUIh9)D@Q67c zK0ZKTFuMV=`2g`)%RPqEn6Q9~1ad2+#^9R5QR^Gw3XZ`xxwu8DtfGR%e*yE8me$sx z0hhv2!RKY~b|vH#ZY&$O=fd}b@i^v%18z{(@FNb8FrY67lnf9OnSTU84pOvF#D31b zZuU`=Q=VIp&#PT7^tG}rZ|br*(!1}XqRIT4%iJETUq>wM?U^!V>g?Tf`bTZ| z(;%8{8Mg?|F+kBU*)6u{lN=G=4<_J_M+azWrE6yW0s_XpqqM@t(m(|#SbN9C1;Iy( z1S9%-4C|DY5!F!xYiB-welS$vR}K?!Y>-1BxxRZh1J7HD3ivV={rUN0rT}zglVAk! z!38NYu~zJ0DPk}}@Vmv%3BN%y3Fr+aNzg%Hr2SSp#PIvl3mSfC;viUqfeKjr0Jb4p zy`tSHrvHul(xo!cC7?2bKQxBqv!uyIU*@MIrT15QKiFR|{k4KMw4IvwfZNymx$oP? z(01VbmJbyiM`MoW3F9M7QwuEzc3DbCM#X9)V#cIB^9pp-A+`hye^_z&2V{v^Tpoiz z1R!91f>>GjaN+g#3e+Jygql9ClB+?W=F=S5~0{cdn%1VNFP!?v)vS5#F2ugHei zVM|K@+5e;tg!Y*F0CEh0P;SSg^IfyAe1KtAR#o9fn}m`gk&k zZda}hqccN|jueE>j)7|fnEH*_syV$yLv6^AvNkU--|vs?;G0`xj{h!h;##hoC4PCb zR~~4h<8fAJ!V2=_Y7^v%+_;4>}~s;4Dwj%u7Ip?-Qa{L5gfjBNa2Qnkr0X$_K9=nzFq7Z zusGd6WVT_h`NOWwbZ6q1cy5=wOZ!PcFPN9gx))yfHZQX||@6*gOB4ya>t@?)RrHip`(y(tgmYk;pD~xMyalG)ev7 zq>=Rt6}7{*`Bq#-Z6hI)n*X+kk4Q0K`(+uM@|@A8bQ7(`OQeCwgiDc-_N)vIZ#t2$ zSQZz*))?u_8SPBFSiGU7D(69__(nIYdtKU6A~HN-WafrcV$I@M{(D)UBU+V?bsP0& z?%_Qfyv-Te+n+vA``ZYxCU-Bkgi-C^)sjUiuFdb>;p#L>A%Vi_YVNDywKkTmN6r$_ z*K?X)XX5zV=Tg~G9((xYh22NOe3dZI4dRB^iD}!1vW5nQ&I1qZJsmUogkt7oZ3mVv zebXOMzV)SErQ5MVG_eB5k`e{iT^-Rkoxcu>=Dx`j?3|x!lE0hszHQhBh$kA!U=3sE zX*Z?|y5Gz~&@HaH*;v0e9_Tkjcf0Xz;E~Atz%ZHK4-r9Q&%%zV^cPKcZnNP$A(q7C zZW3YFSGu~=vmvr*-WYenEYXfDud-x4wlU)1>$#@4I{R(;PF5t_hgLJYpDlWQ_eMgv zH9HJPPI1}Q2a74oT_MSH>|gG!VXCF#pb@El*fD52skuG*+4`b>Smg{K-P`oCSvxr< zsgKn5Ex%Bp%xs3bMddiADJ5TWGOf$CSc@Pf9#4@c;m!JfReoft>Bg2Nzt5!p08InK zGhZDu#5#S098B2sczArp;R6s`(&vb*=y_>NbF(#4ZRuviI}X!M5}x`I-6^iZw%L!1 z^Ju*!U#v97ab&sLij`7;{VqMFHSG_YNi~#WBBUPXMOB~kla=$Y z)C(QHjLyv@51rWhwchCet-oxsbQ)FiZ|P^3G2XtqZ%cb*hwR(42)hJWk2y5XIn^{B z+4brba2J03_+dV(r>_rPBz*Lz6XoqA3I|mp$X@yS@&ZB=5Xb^~8Ih?a10PHTJ0N3# z89I(6s9>9wcAeN8tGx@Zl_wzYLMbiHh2wV;bCVDKgc=6@A~t`F#Tf)ms2A;FS_V>| zwWZ|<*bShwrAZ}W8i4dHgeYR{w~w0VCuFAXi_=%=iT+Q+>Ab6>MZ$-1#P6r_%=Cm! zKz5{bwLEGw7uU&*&);@QT$WXFVUU@ZOTO&u*zljNV?t>PX>p+4c9jp7d@F-%ij}d? zW`E%Sg(VplJ&N;$8KX}Ir9{Sc8m-o3OFWLeradh$ZaR7^*qU8l_CjP2NzpF~FP~Hy z`?^%8<=?E<6{C9Ezk@e2H#Ma8yQugw%`C>HBe%6$ip9CKr<9f_K zz$QSr;N0S31W3%_jziBXc_Ii03&u`h;1-VLlOxRW){$l^|W$ zHo$QKTClrms_oQ&jlXIlq zU~Ge6o#WresRWJM2QX+unTmi(3E2WI!l<_Il@?gk%9d>{8Jtjj}LC?Ds)-w8KdPqjR)qf6S+Uxj2KU1r83TV89#TaHCXLhX&Y8 z{YUB{M{p3?4moCVk;g)^t)a}Z5aaG~!A;##);_1)DB};1Gc@=4R+xkDY+C887ad=;)n~Lg7 z^-p(gR`iXCr54W=GDjw^UAS{)+{~E5LzXAjgKhgw@tWjedlycm7@7)#M9a(DR_x-W&`^G+oIt1nx0t|F?8;YB zRTZ=vyt*;p(ILk8<=a?9&)b9q*2T6*{{NnC^T1q?E?T~+eBbcssFjZp@gtwjt+>gn zDl0ASio?|E+G8*%!8B^tiCbZ8cNKfZzW1%8F-MJs&-oFMS_PZ3ogEe)&K*bHU$&Hg zrE!(e?XxxX_^!}%z}HQuE;d}Kho-Q-U!{1Xd1)^CU7FOzRLi^{);tA8|E1x5?n%@x z3o?JGSuyx1QL*1arW)_eYl0WA=G7Dom}aJ?NJvO3(9G7>ZopUT%p0GeUXa^aPo6}! z#0e0>GwQ^Y6cu}QaaU1D#8-xNwt9GMj(EoVM&hRQ-$Z3z11+|D&b;=+5G~`IH`CGm zV6JRrc~4uLerE_Ypwaq}ZlTWsDG5}ZNxXcFt}F&`O|6}MUaMv_IHHhWh(vHDv%ICl z5onXJJ3B8<5QtD9`a-~`$!TJ?Tl8yr*Sb@UTCW$eFvqlHZ5zG3UAcp&2-%hNmf6Jy z{%_iY8c!`_C=Tu?mpJXbxp!ihvJdOZyfo)Tv+zheC2534(CgROAYc3W-9|Vn_&0LgFv{zGl@-GZbp+0hnjKl@^fq7gNLN*BY)_5KvTs^#(YatX+@|$41)7 zLc2*FHQj_#@G*52W<8+I{ys7-X)ms^j;jR95#nU9On^neVV3!x!MLqIkQ;SVzGZwuj*S%1NSth_E#x&gXMY|L zY21U(_gwj}^Npe&{%5<3p2sI7Xy;p#lAic^{PcY?{O6kaV5Z1t=N%2_2!m=-Qf~qm z8nbt$%S!pX*JzGP|Cd>}#%FEAoyPB7%c)K2?-#{Ot~_;vRZ=)nJbInD(|1foA;H*e0z&dqFvuI7S%`=8z8?w;lth z1?&>=Goe@mrvM|2L0xfpZ^Kcek8$A|fxdk4yu7>_?p1ulSn&Grct2zeRS-twAlrg! z*6W?h!p_0bS?G`fmuJZ2anr+M6k-r)doYIbX-oYGhe;g0$;ljy7p0`i>*{>m2;_MD zQulbI4a=Wb*=bimd7|@yqOc3VAW&c6`GSre2p6M!A@W@SfZ@gmk`6Ld^Fa;S<^M84 zfeNk>?#@o+o&OG*>z+G)dY&D$8;}SQVbm)a8W91Ffj!tlsLCcDiqdhlZ6VvL^?{iF z(Qc{ytz3bxuD%;f14IW`Xu_eNgBlM+91x}>BX45H4u}tjQO%+0*;$AP#I1jmF&>8z z9BysgW$uXm2!;1D!iUr}HCIttU{Z=LlG)vy!8{@`P!P8)cvZ}P>MAPpAgzr&h(`~P z_X4gKH2L5*Ap<++(3lZ{a&}JoW_yhJ&8;Ugk=%|XGZ?qK3Wud8B;*0=0NnsSd?eiu zQJu`coW>jj01F>fP3$BV6<{T0;Ka$S7g8bi>OI}ekZEoXdSG#Os)4) z61X9b9^e_rJn{j##w*`tmLgt0zQnXN1S~~$f4I((c+E3uc4{gYTRv78t|_cBSoaPy zaTC7z<0KQdtVcT^kT2E$p}8AcM8Rl=b_3-zn1nU>hnt!D?yVKVv9y3o65jpPDBHgFG?J4DUpQ(xO z1gcJO1gSUo^_gFBB!xeJyku*1?m67~G+`&FQ@2)562JWcdG*XWH*a z9GiN0oA{(?pI-Xho6aD)zZ*s77V%3zVM%eSiJm_r+?V1)DBj$TMri|L*JmGhd+#++ zu{-0_Ia~XanBiX^FvVDTMbqwz^Lfwz_5i==uv-(}al_|N{_8Ku-q_Ecxl(OcZYWknO>z}t|{lY*|^y*vp*nj=|-!D={c)dvd>&gF;eeQjfKVbhUeTxKR zG6xwpw*CM5f!*Wzhmv_8khi=4Asb21O(|{DF*mtipCxqu%Qk7U|DZMf^DNpIUpBP` zpCcXr%T4;{&(EpJT)nzR@cWJsmmly(8>XIqYdfPJ;4)0<+{r+)#;%0C!^YZLxo_zY z^)CF&_jvAslv{BC7X>_ucs{pa%nv)_-Wgs0=l+--Ekk^ z{ZYr$BSemgwYn2bO#PmOzc|PChr1a`IQGG4%`=0wD`bb*W=R?UTl25X$k>lG1sHw& zpH{v1DIJmf7ToqkBsDN@#$%6&yIw6KSYV>3AdDLHU}=Me4``9?orvbU(E|^$0{m_h7A~Wz5JmA1Z3PM}bVoRdB}pp3eT!}|zdcnwlsCsVFI7Pz7zI;PK<|H@yKa9yak~?QBH9x8{;-kz+(w4tAnk++BVB#$oG; z0CkW~arv%EEiI()wa%4F+aDP||`($pGIq^twWvglt8S`SJfawJ?SuBqWQwP5d!RKgPs# z+sJ68bia6RLBVs&CZhXEvrz%|Ro?FJb`Zg#rIh~2M*{U##>we8E)zySBe&?e041Q$ zL1~a=_zPJtkWc)$^MLsNWxORzizho#fRQkQG)A51uFs=EdaNn+$S|rmobw>2U_p@E zyd|nv2xCaOsKMF*{VmGX^q7(ziQH_j))MBP3G5X$y$2 zzkP}B?|-3cOAH#HJK3H+=VS=i>VnUB3(v6kAsjHS%cxz7Xe;)rcdMLEo+UycIHzedaEvT>sGJO(JMpM&6;2 z?RZQx%zl1pFWx5EYumU0pB6*O&9tU4w_in>e8WtAm=4uM+>cbNg zwKsSm8V1aPB_z`0s#LhJC#`1NZ<_WXRm;;~%x1$b@vn@li^oR9NSd8kE*^X_o-`(I zlXJ{{&9XP`yq~<`zB48hl-agJE}xX1sBBVguC)}*7f`HtiSxE@+DVWUX=QpeA7 z{tQg(3HzBn)%&(Gj;lxSV3AXaLCapICuDsMjNQg&f&OlXol|bOUC$HkHqy!+d|8^U zB)7TT8fshiHR(O8PRicd(*?iccKQWseF(F3tZ3$6B-hQ!PnQ+?vi`ib%gQ~>$v4w2NeC(IC+`}3 zS>xZNtXwlCyeDLQw$&^#c3G=|##Zm+7r&cSIwyG^CGeW@m)C2O<~1K%er$rLQ@_NS zWnUk8G3PN=%T9*OP}jjbj+IY;`{S}0chFDwI0ls-sNFD`U41xl48HQEr5E5d25Nd^ z;|#L%e(Ltr)^c%hTs>)5*30|yY+K|iPgd5ZT|e#Dmi$JN$(>9)rMuxtY%oni+?~MM>$WY|osq8L+|q3C zU6&dfmB~?^LN-I2Hhr$L4-=QZHGIGJOr~P~y5m5Z*CmZTmn166=xB1}Ynq!TWJxSE z?R`^Irxxdz_je@vXKN8zK2`JdJ9ybzFXa0fuTOX&%WxrwC`>yY?z^aelV=-p1m&q|aQ1rwiN^b*;X(hMLyR zdC}Z%9kQ6aTNX1}?&{dx^2vVWbcWo7{P|+;--k{gu7yAzoi#wk*n|YA5+JZ;oOrtt zlbR}r_Ni0havLGMVO$O0vXKuF@KFB%JZ^IG0CShxBB00s(LN7a@GxI@nO)BaR9UoWGn zE)4`QII>snr;BF4Y^;;9VrYC4T>3UTb?T<5+x+n}Co)!*mSy!#%NTrS-BwKZXv?1W zOU<mES~&Sq>mMkH)0q_ zM@5@cunUmn*B_x!CRNg%Z z&kz$UZrLkt{`3Cp*EC^rcq#2HBb5wUV|7fT{%bp(sIDUt*;1Al5>C%`@?#;Jl}HUSaQ4zb}=wSK!yvL>pF@U$nI!pEaV@~YCL|waJ8wXzlZspU2}1R^gR!9 z#^alu9oI?%zRj$JB}YiSiuX%wnH=Si{Z0Rzl|SvFBoj8*-oTTrl?M;0>>V?9o{1wZ z313N@^ynZ?KGo`SN2szgv*vsJ*+I9ofZ5$`&7)%Z3_^@K?-k`#zh2(#ix1E96=po1 zb6;Dj<0uRJZPVoLUq7zyZCTp+tv~=|N9MlULUGYYrAQKz6Pp@L?qG>YkW6n_e~hk+ zvP-3NSv_y+a-olsDkE@STauD{db`4bHppNZ+{mnSNG_RNW; z%3V?~Zi!zyyrc8lY|ncY{{ew!anrYzB~O$c8d{f^RM^<7=T%?DC9z&Jb7HSlQ*}8S z)*W%rRkvRIH!KGqqISHgzXHXTaKdWZ1aHU+x8thV3ExG`Wuc6=y-*8zipwn!74;REM)vp zKPlAAw39xZ9FiAbZ?32~2@x#}L+HClzkL_5>96nwi4#OA24QPYvRA>ur!fE(OS&vC zPxU?gmywkjv9;8=4EyUtw9Gq<;@&Aq?)h%4QTyvYxKno ze6~j+S+Q0Iv4H)w#hQzPh6N#nT>ql*wrnv$J*6xX0!Nh z!P^D{H^i^Qj1krMJk)r=wbHZ;2&MqFpb|fOhS^3#OUns&K%t!YVqpRaN9Kn@#d?+G zsHi180l37(-1#%;l5g78dDyp7k047eE3;@qREZf|+*RvKkyV@ z1llu9psDnpaKMi$ad>Db=T7yZM0GKdNLjR^Xv?9~#tDTV;AqxXR!r{JmZRG~86U(7 z`rOXnDKCW9sOBVqq=0d~-OZ8NjoRWM~)!q6d9juq}XI^R_wF)&T%%!qM zcFT{tFkUI?snOw!b4xlXxwj!LdBuE1G4XlP0md(7-BWS5uW&_ah!b}Yj)WYT;(5=b z%3v6kV_UwyC@^0ZBhc}X!AhL=Rtkj`yC0ciPkk=;sVh?|esYs_f+gI)B?*#W)2$f1CWheV#(~Now5qdX~`rw8~y*=RP7)I z1=D3^4-W>X{pbZuGn{QDLa|7cm6da8sO{e8`DwC{=p>Q#hW{G59!f;cjzkYIEnT8u z#5R5VMW0;l+VqWgvxU1`1Z=*#G{@$JD)Cw2s6pS8E91YD z)g1P#FRZ8Z)H3gKt$Mn-gklWxIPYypuC zSNF8k(g#N;pKP^k)92(46S>i{uvDVd^O`Q{5<__7$m#D1MHIxYFLJ`|A4(dSMtRw$ z(q9O8GEQ4!F-ctRFjQS-yjfBtvfneYn_+YF$VGKMHA;W_i-j#no>w%;e)1)x2jGZTZ9mUA7oEwS`R6w>UpCq5J1fsaErRJlxz)^~Cyt$+*16=)>7gC3Z7ZX-JN=&*}Bb_-M*-ozS5!tER=>IrIpo zffIu>09=sMU~n8u)(hOH@qM6R(&mv|TWf3Ogbi8_vzZpy>z-+^hPh?4j;5B@VHiVz za1T{GT#$k1V2jbtPz42Q0dh&8C~TaZ0emv!!wSR&#jLENEe`irPMw*8(>#7~#$i1Z zs2kDIP>wfzTo9)Dz3q0QlY@f_>_1dguC!f8Mu~FwN>l+WaRHA^U2r?IIi2s|NsXD3 z!H)$6ZW|Lzg9Eb+lj57x8#UGYCxR2L)HRje>U1{*F3dKjTgCN1E`3F{uc>=5wOiX- z)l4zxDG|d^P`IIRp845%#_^!8f_AqLE5(C0Ve}$JvojTT8>^8Q`ffK-P04B+lSih= zK56H7bCFK3{3LjWjM4p(OB`3KZH;(x)VQt&Y419di-4C*=54|EBIEIy!y#W8?XPDpC(ZuUgtyiNTBJXRg#&CF0!O=2%aKMRO(lAi7Ekekp#9Z?v z7Z=JuLWT`uk3a|)TOG>)j(zdcC5%j+t3X4AEVxbP5o zvLq#q!axCoh>$(T%d4xPOJnG|pH9#OSPwAe2C9Cre&N>!Y4j7AcmI5}e-|T4_&t;D z)GPb0F^m(dB`6c7p-5V@veHbyRR%YEC?xlqq@~Fcu7VBY7d(M0G{`86e&N+=_`YyR z-MztoPuT8eYIuYG)zFXkhSJ0@hn33N-G5-wF(i73*G17RkJyk&^oeV8;v;kf?P&&)VEGH^o&$nI8>55W!TOad7Rl%mmpB0oCF1*2TA? z)o`S;w%)UEA1eOqAM`3w8}@sX5NV9=16%kbA9nPz@^S>Hz`IxO&1v2- zY%lD5F?qmD=*AwnG#EUEw$ICO=H1aSZ*;_AJ-+`BwB|=O2Y^%&D=zZZ-k33LCN-y8CyG+MKMDLbp!b zfXUTIUD(7AO-@es_BP^F155q#W3lc6eBk{YQjO-V6)#2gK86#F%0TnBsZRo9xP}&m2~YSrr}f^*Le`yf;t#! zg;TIAXxsslI2d#)vIV%T%mG&~vK*)ayH^zEq@tn>4*dsegwoYiRWWyN1@W(;AssTY z#;LgJ^kMeqSSzZPUef*hb)i#NOvwB*?_GscgZReMZ3I)nA`w?oV|6wWW9x#Ua3{b8 zuxdyJGHbZTk}e$%|n%&~YvyDpnncsdAdSsZRE$Hv;xvAR4Ifeg*ow#s%{8c)?B zuKNp*FiIzr@WlNF*7@rYr+V6%t4EjnP@s&P;#8+(BV6kBm zz@?dO0woswUeP9!OQ4}(L3xT$t*^?!$qkPv&UP7wv~Ykt*WA^GJIV#aIvg4Rnh#2h z!KxbPN_cp<1PN|rgp%V9#1xx`U;jAXd`t`}BMMT;s!%O}!CxCL%DJ)KU|^hDUs z_vOpC{70a%^P;mGZ$C&*PB4N6tn5Y2+Y8TUjKnc4r03Vaig26EHn>m2uM?(H3!u9A z&FP?%3<@$VH-ZTOTZDjdpuZBxOoR-)$--Ih=g+axXk!~+ zPjg#Of;0$JL`-7_b}~5s1eNUCNpRQz=Usg^9=m0<^Kr3#G#hBT-kzTCGcug;oz;bj zEF$o}AU78d{OrukgUI{{355I1H1-I)-}N`)FO8EVBPYbcSQ(u^! zZ91GKShGZMbs&>S49B-kPd^T^=jdnw?mIZw&}*AmXA0YG$z*VoeJE3MU@Or$oHhtQ zXmp_{ff*(87GUs>pLoTD=)IWiSgZOo=biwQP{I>-i_%f5?F2O&oLc-6fA6_cVCtv; znCzb#$UiWq=OdYfy^|9n*7}ErP`Z#ZV&oX}8GRC3bY%TOJ#?r%HshL7SzTS)GS^%g z(^ZR&HHYy5EL<9;BxsHBvCz|x{YXdE4TeA$a!WH4udsv)Y5bHcgQ*O5QA7ngI_68q zfJtOwXQy_O5-t>E5__n5ZeS29;fYtmc|MvvIz0Ru-cg*mq<_l>8QM<->tf(W1_rqx ztAg@`-O||kpbMj6>%GQgvRjbHpp^il2@yivfPc<9So#@YeM!Ec=5^ax0~ZpfCiZJW zf-J}!OG{USd2Zr@V2vs!wcxY`e~h^-mixxuu!4FjpDSiPIB0PjwEXz7gxd^oM*6bC zCgP zb;Eyt=-&TP75MP&VuZnQ19J6#{`~p3E4P7hgW@u_T-w8j&mxKoj&VDW*q@^f6Zl)A z6V@j+A#}X%?CcASW9QoF!=$=EQ*{Fq5f;F(as+4M4Cq=liOgm%d5dfC#&aVwqXy)g~pB)V#j^oy<}ZP)400_5d9~rJzLIoc;c&g z{=7gtWIK@`{)~ihkkSzheY`@p-#>JNd`<9UH1XU`^26sed;grxi$U^mVkG*whrrk% zy0HVE8$?7r!~~lpqToM6Wuk9?y$tpLPPYEbA^yKS?4t`iS+yB>GK*OY@K>hDua zvTq5#nxa}wzqMaMQxk}W@$K7DiV6MR+wYeV#^BURk&)*~Zr-ceq$k=S_?JB<+a*cQ z5iz%oZjv&juk#!oTsX~aI1+(0_^&>f~ zTZmqi!4Zj=@bSJLOWAgV$S~$aBEnNL9gkeKIwW+V9tW@awff5P#w zMhzx`rkI)odb@{_G!q=|%m zRW;%Vi39hjY<)@Z_mgPP(UeTBkS#L9CoTjK>6QQe5S&5!9~B)dF{5qcCEZ7OPtTdX zWO3-?XO{=tmI|*c=0rPQs%o4vv{xh~C9)Cz5j3>>TcQI3<@hE3Jan2}glNxC@1{n> z9jr8o+m4FhJE6Xja_wZl_ZG=tVIQ20vNR^h?rT0LJPudqKd#|Me&3qpynmquQBKzC zy`BJ(ZErdMTp6ytL`1i74eAYnITGwMZ=7|#v-7?jOjjS?C0zJEHCrNT!usJk^!JnD zYkvOsog%v&TLj_k65m{wAHL&vWy-90c@X8$hwVE*ekP1q=T^pZdN7DWsQql9v-IQa8;=v89Yux8>-gzCh?FJ2D zA$TBLN|_`b9AiwKRL%jB!Kz9hUT>Qg;W#f0Sec>Bqs#Z!g@nr1~d zXndU}^3ZqiTJ9wIs7Uxb)7~;FT}la>J2Z4|ElNpwO z9uNc|f3H25zGqaRqn>k0@Sc&6*Q}&#_ezCqyUlLBSX~Vsww4O7p*_-Vo9fx>3r;ct z>kjL#9d_(#i5lZAhYcniAC=hQpPU?bE|77HxNKweVBr1H&cgN zyFPu%Oxx(|5(X|s?X<~>QEGw8%?CrD!}5P*$JUtTyirgQil#hk)N)=yM{9QTgcMEp z#si0&#V(!JIaWnC%VVTcgoDS=%xykx7Z^@(<$cQNVRw%$OQUdeE%J=bx`wm!jJI;=qJe@s2IciQ^pzl}B0v{{nY>3^Z>aY#yDfgnq4JZAb6h%8 zG_S2C{V9q&?uAOyCH<8cRYA>Qwc)OgOI6#oJI9$tTk573O5?Vz%vs#i(XrkLi4D`d z*pn(d-&8C!Z{u~7$tj!g`X9TrwF){I*4Ey@C)$n@J3m}L883nuj+#&hk+ykETW?tC zQKu*;m5FZ*iSs@!if}d#R_^WU7)U>Oq1lMheW};YZGGfX(~0dZVPW_DNzeNf3jfHD zQplSWu`1rIn>d`M@uo9^+dV$5NI^j{Bc~S^`^|Y);>pDtF^ibY-}w@Z;p#%~dU)g+ zzgU%umu#ksEsD2G>55Q9j0p|2y{Flt`AUrTAa9iniGt!a0sbjJ?Mpsqa)10bUU0nA zRi1WOWTs`gDk;%a%zL(5O@FN7%%+5#Tph~0Z zTmM2=dbrDEk9*4aRFK1gsKRLO#nb*F1=BH1baL`k5+)AwKeAO`hi(M_8lLpGS*z-u zcCyoP&3u#<%ETV#0trl4Ic_kBsMi&74i#9T@1=u~&%?Q_^s>fDUrnprW6r%0l`jtyf4&0`qK{;oK6|Lt?^CPxTM!=k2i|fIQIFvXx1{* zwt3$a4t42EpHx1b?g6M7Z)ZZ~Zk$(8Q7M z3stO-$#h+&I$ovRUYi_wHS=9QM6f3$tE4!4I*j3nxpn%o-g3Gcd9k|NX`P!fJRe4_ zO{3CeT?Uf$oku6e-wQ073AD_!A6dzXwIE!xrN_3g!sID{p%{l&?i46)1k=j_oRueD z-6SuB?t`QuM(S>uvDBBHjyq1XQhqMTsdjIRjN3;Ud?)TU!{lgZiyR5Bbzx6{jLID~ zBU6P8ym|WNk+n`Ywu0r;Y?SZra#P8>u@G}o4ytT8PR;lwOAELlWdbZzldkQH0)rmB&1t3c16<+9s~U7mr>x!3Ea z;KFyV30wZawfQLeSX1tFyAk`8esX(AihhdSrFwbE-hxvl+I>WQijlN6y#kw-4(w>=@Cz%jq7Ur#jSLGogCQ zDeHYc*7n`|k;;miS6o$g8Yh`{yV*Rxdq0Eh-I8KJ=#wJenaxEu0)%-jA z+0F7-g>fUC{FY?GcbQf8q)=;1b!7T4$t&koTEq8Akg!JBE`IklAEl)JKL42^CL{>E zfX=37epHg|rc)92M7!y+H!D86Z#qr(x}Cl3sBAI6ahkPHXt&Efojm23j6$9qMHOvb zB^9%wdIb`Ng&~{L@!uUfmcJI0&i|Si6h8DjD)5Nsj{1EVMcu>9(o$-R3`^(y^_xqa9i1B>Sz3M>yA|^?PaV;yhvn$LI z6qAGFJl5|vLsIkwocjwr79!db;`VOICthWPHRLH}R2 zbN9HHhYQvsDb_V9#8E1D|4|2Yver@Ux#T_VV659Y@aEa}sD-QJ>C*uTy1N;7e6e?0 zIwM+qtKu`S?l-jwhd$rQ9WNFFPZTmAaj?0((Kf?!ESsA;fcEUq!P_@>3wcenRo}sD zQ!e@hiqB0}kpq_>dFWZHJ6Psq(i~nFP?#(5HStmJv};E=$>z6&=i{?RpCgOiSW|==rQ--ZfT42Rr#JyMSHR#ystCMZA}WQ{v6EBY`1Pu z`!lS(xcKe0%!So}xvYe=wX&4kmU4&0MeT>MnPy6TknIwiY)y)J+$wdJ>_^qo7NYyU zM7T862f+~2$d~ZAVdw+gd_{Oq?&@$8?nI0vu z?f!qYBX8CI0TrDQP|Dykr$Dzesz}Ldd%gb7TQ{Uugxl^PQr=R(1NC4ip%s*Y49-)Zpi@FLhU4OdOOl-iyq{Ji0k&)Qc%ImXcW}(fr%MYq=GMr(oS=-87DA1*E1X_~dv`HHmVmnz-nk64 zw2rWCPPpbIo#SvrmfF(@njb)UN015)!ZF;C^m4UAZHYi!0mw4HxM*i>J=U7m0~*5o zc;@mJqZ}(#w}fC2dwWPS#bzp)Abbk3*MaI1NEQqSu7saI6TmWpCrMph9bD^hcB&?|crZ0Dd;eau z;&ImBs$UM=WEtVh$n8;}O(X<-qZ=+-P zVnLwf?2gA|z|2e$Y20Pk1Cjh$h+&v3r2yZ|ehlFuYXQ9rF_#Fq1OO`Ly0(N03FaxZ zCtF#0dDAg1V`3^TFCPMYh=leP+r(KS0o;$U#jbmErs>Cz(|=URUw~^EssLI8YhV&? z<>;1#Cfz~k7#JKxkK0gQ&H|4txMyLlJM}(gX>4kO4>)UCQ;3{k@iScgVy~3s4dcwR z3VtKxKLND_TQC_sv&)z37v&5)@O9ulA>En~_X%(i3C3@PZ4f(Pk0}w}!Ba0Ufx|av z?V_)6(^%()(Z@?Q4qfN5PgYn zu35pm2tp@7^q`Mt(b2%8KQ^s~RP!G$fNZFB_9ie)`8TH(H1_S@?KGa%`XZr4FTl18 zm>wYu##bZd2+{zaFu2C6Ce3e;mG_GWaXYohIDuj=z}Pmih$BV`7@g!qX5|*6_A_=9 zZ^(MVL02S5P#=>a@+z=b9dYx@TzhXyhrPXrR20mDFvc>swe5a?^MbQ;p+*X_)q%&# z`OypboY!SB=8t`Lg>db>#w5py2)ML60JX$9K4h%Atr%K&)~J zSAb0EYsEZ`6xZL8PjnoIPm~@Qagxe(s%++;jm1!(%{>?#3w4c0cZ_PXv=gfV1hk<6 z?E{vLo`sh8)Ex zWn*^4e3K-Jq+!p>$T03EmGH!-0AkuC_6-8oj@(_K%7E)#L1w|P=(^Lsn6uESmqq(Y z^?a3Gxb=-j<=QnsYCmCNPz0|qfx(ym1JP~#Mdv*gJL&1`#&_RAJ!#;`)JIuX%3X}x z01EkyCcmt${GNd%cfey)Q$OGv1`{{i$!<~fl8j$4<^Yl(YJxd5ejwi}fMAJLDHgtN zNFgwiS3g8W1vjmj*jQ{ti1IN4*S$T0tJOQN@?xAIanf7^O|Y*5R9FVwSZxjF4ptC{ zV4(ulgoNqqm~zh+#6|uEcV&h{=FFpWa&mmb2vZ*{rGmUXmynaLq~&+zQ+V=!#trV-qe?zk6-aHG9b`6e*DPAp8ayU@PH|dFzQ2Ui2cWPW8WWJf-I2tNHF%> z*A`3?T0apJ8vgpe1F~`nEH^+u9G|V~MAZ}(KM-91{tdtzsh9wJ=@HD`1_!fml|943 z+0oIln-P#wa7YODds+&LzRAf5xB$@8i^A?4EvYvRzhqBwrZG*4G>gjvLu&7l|BeWs z>Qh{)vLU1*;XuPk7(P>TABp#4SyBH;ctG5VNf4GlMlslAJHUIuJELwQCWnv^C{p?N z?+d8~6XX(@h(MV;61qhw%g-zAR%2z9)$Q@`FT|sOWFhzyoW3)7LzwJb8zE!-0*?yl zg776nvx$6m!~RdSVuy)4j29ba>#lw*#GnE{lvh(U#F#(bG(62xa|}~OR#rny&?E!< zvfsOHZXnyCrj@^o7e$yLwrX55q*2LETsKe3+-R@GnMjoK3UGf|7^gct!~b*g`*LRw zAl7q9l>c_{>i{(D{#k(fcNEWXd^L^@SM8Ke= zk?;h=(#mejx!Zqry~^g=@0}YdObV5VIL;%s1>2vi>jsK?Ov(rL?Y!TX$=vgDgpYt- zJ_rlz!VTw6CKJekQOQe@!$gOm`y#p#f@9*bySv`qyJoN%o48JNos9XD88ML4_otwj zvd6}bt-xYoOdY9dgm<)q0IKRi?t(+@KFoy(8Z5%Yc1g0E5#v+6KL?@rI9M65RkWPw zJOeu}Jgi=W@PYez;V_AtCeLP{{7;KTC?txwDGKveBQF9Pp%aib0-|%Utzwy__w~SEf z*q_HIt9bg)JJf=AFwCu?c*39vTLP}}IT^y_^ku~J=hd@y;tU554!}&3@LHw+yjEId zcy|2Cd2TN35r4a-`B#S-@axt8%iSepN+ zoUG3k9iQw5uh`K+eq5lRM9gfM+q#qUH%<4V|2UA-eNj@6m;z6uGagnBO(K&IsC z#Y#?|?N~C)%SaMDdzj$6RVveIuS1Z;LB=1Qcbd;-!k|}{{Q-sIwwntNW`CaN>8Gq@ zJ(l0rYf!L5*QJfFNr~?qx!zP(4lbDJ5=aE2YD|+ck!4eO_(jbjLO&Ck*MayRuA^N# z7bki4_!f6FhD$x#)jEvm5^Cnw6B3mZK5J*NW z_Yi7qWnMQ@6zr%@YlllxaZCssR+19S9)(t^o*kb}&C~N>!8Zy~n%Ak&)XkKL<)Vx= zhkAykW-#y6-rkbtN^|ihdcCK`xon{V=a0cQLapNrBt9D>47K0zpcAfJ8`Uf^KDN!zd6;IZ`U4oHnQ$kZ*TVBnHDJTZf$XE-H}x$8q{1w6uq==P@`p7ndkoG)o$a$ zn$tq&*LzrskNN*^-S6S7StB-e?e`M1@%#DBsFc;a*wT2ERcTxAr5u=P(J{~Yhf!a- z*)Quiq1WmibN5O2nfvP+8C@eqqbEsE@2QAY3PKhxtfBUPHM{<^4k%|_(1+5-sIp@< z*W@*KOC)agBc})D?UwIJ2+%DIuiX5`(05*zl=gCIhRZ%KIq50snHWY5?1p#Qz^a(VZKXs5|^zs zlfc*tP^^-d^QlYrhm?UvF+pSI6yqESx#&B78S5)UQ;YmZRM1fPmJGnTD-b~p5T6iR zk@rKgT2fw~tGkaw!K-T)4Ez8hp;UsFV8~`CMHBr)v|b>;+dj}7h0f4n!))E7;=4y5 z8VS@R>m&rB4E%ug*N|9Jd2z}{dAa%c@oRADh|lkT)xz1`<@~@87EJ}Xx%~kUr}{}c zH$d;!owF4es$cEd_vY+j6DQK$QYU)S$i1AoUi2NNHsrQR zyO~-5K!LVG7EL67hVef^UlZvJn$uO+QEJh_CJHpDE5@b0+j zy*ZcWi{b$+2vorpauR88*^zlm2Mars(EEuNn8EL}9}P}u{kjCn&WPDZ*x68}ilUTS zh@nWUmZ$iKVc3>(AL(8=qM2|y zZP~`=fDGRck88hA%9`kI4`V^^aq4|>P6pYvQ;vhqojWnts!GcL(4ChkXWV<~ojkWV zv%M9Sx!u$9bG=dl&d4>`1%?b6f^`z1v5XKa&BPCLXgHBPN$$YR(;t64%OX2m7W%KT zj<#7+rX+cK)Hm&huqL^E`G-Wrk(?cZ5RDRG~*NvDI&kwJ>~U_)c! zFzotB&i-2W`U~uK7j$h?rI|ED&kt%a%W!j#dbYT&7p2f?G9x6thkltDBvmu`rOaYEhuoykuEu~UaQQixqW^0_F5h%o3owOHLIcF`<}gf z9}j--*U-BvwC$sAbp2AvlI2h9{T~}Uo|o$ung$2dEp$Y~1$YLE9$?IZ+Bo#?fV?4jOhI4Sq~bZ!rah;jPvdKV@3Juh}Vf$86r**UUR+ z<|EcnRYk=F6BEZ%e{x}gyEJZ>+Icmg^LzQ~mFB>K`Kz0ZVwIJY`t?efM$^s8m2xz5 z#1&?xvH;#Fc{sV0UWUSvsJ3kIIRZ~qxiR#YPXuqUKOEnT|3J@({oLP@#$GIuw7(~4K;rm8%utIH^4z~Y0UejyHZ&%1?$ zENfM|w7V=N_owSd3ykKtm8}T!%rPx{@E{Z>j*}v@C>=Si7rXMUaXk}{N*F9>Z+|65 z-x-zRIGkwp@0{L0w&bvyO}z4rsK%Azswr%R-TJ+)n+ZD$hd#3w`CEJJxohpyA8rjr z@uz2*M^nn9C~`9o&-Fi+fNA9Or>ai(eZnR?1Ei;^i0SSS<-T%@o7OJlCI)nimAt76 zY7+5UcDB>!+pd(3KC>;jff7q2=J%cwnj0s+?q*|&TRG!D-tw~qcOrU&h4 zoQgX=zzFSgxEiz?G2&{%Xvam23PEXxRPjA)WnWOEx!39B&K<7K`Yc~6RnoJtups%y z(Ty3~D9?_fNHsKckVyJl1RPFJ$KKC_W(KTl)reOwvQAXxd-?RIbB{Qp(xb--8sx~3 zpUl0qvJ=a~VfzgCsPi~+^`EfPlY;?murH1{T9D*Frs0~Yu0hC!eJmB&A*T$=;`i>~ zM}i7~T-m$-&9he*+$@iIQK%5{+qtR9M2n&L8(zYk-Ny$<+7Jj*TJ95k5|8SK%uC6+ zzOBgGt0~`XN!;o4Cl5br_K(<6#_hbiZz73L74!f~a+U?70y5=?AfgazFdK+*Rd?>Z zT^{-&;q{(8V!1XG70#Vo#0KIZyE&&8^`igEm5eQr%dfKAF;@Vt;#OOTs%K(3O&#X` zPf)m7&|Zd7!dk_AM2QDBX+49#BUaN4ZZ@vGbjbkJ=A2Q>lZ544+D^5VtsY-dwdV0Q z+P`QuxzB@+()Z@pyLDZQQx3-Sr|QeJ4qe$Lp#};3MXw)SdGQ^LSg0X{A9`5MdW9z-j7|2@o#st0u4S8m)GWoha5 z>ddRZ!pn32okorovVX=Febe+Am9@w697L-WE35fyI}Q2?=IO@1PunXhUnIp|Su+Yf z?$;7Yyt)74`UD$Q7UtQ;nnBB_sxsdbyHHh;WyhFcG$SI>7p$0D{k@`m%8BOL0V^u? z4GgwKMjDS8!KKA^H0iaghOm1}MCX$3=zDfg4oc|jz5Ifz^=}WXx-LNAEC~N=8PabA##C>je9!G|t#@5CPbs~Gnz;kBsk+Red) zS&2xg7i>X^=t=FNsGo(mNvwsM(EIbh$w;4yj?aJlq=)E-zPtwf`>#KWqiGREIreCc ztOvCpn|NHGKdmUc!JpiksB( zqK^UJejDp^M&Vdrq*|Wz3fpW(uNfB?w=@pGhOgbU90ftX9$`D&27;N7z#I)5=E$mK z$^DQ*V&VP{Dyp{YS7D3Lj!hM@h0CtEIFVd96-;tUJ*HH)$EHI`BTvi3cMpFgO2O{@ z{I2Q7CBA;_m@zr1-T+0%L`9X565HFmJbO`fk@85hDY2yng6A0H!q?1oxk(Qg^`Ml! zB9>IuCQHY7V7UKgVI<~Lsb$Ve zjjFQssb*3V8d4JpZ^U+3S-Mb3^%u;azmK#9m%U>uoR1-i5<2U$GSU*K46L+@yN(x5 z9&|ax86iUbM&;4dr)$_n()X=>w!f`4{oW4>$JFgN%>4&eEAa94Ma8v9JDf{F+J{vu zq-9O_E@4XAS@M*QA)lIHDDsi_f^OK@ z;zA=~0ZX(?tRxpgl^+@Ze8X?{F?QIy=92PWBNYlxRd0<@BIvPnF$v5pn*R4MIP;r?iwe+jG$h;!- z(uD;DkPK@Aw8BoVII5bcG-JdfsjDmFjEZ>++HA)3VfcA2TM6)U}`A!(xRe`viHXxA}r>R=4*f=VVV+`AS{g#mOmY-sz=xj5@fF9>{!v ztEOJ+efro{iYC0iK^=ugJ?M`?rk+u1I$T@AXAsj78{mbRY*fas{8>hDlJyJTsf0Ne zxdp@2{T*>-n?a^fsih#8M@uiI;nY!8HUEI)z=>;JobN)5dz?{R(5OuJE^Z2D8c6u3 zZ?wTP-O<%m@4^isua|hO%(zx#aG%tkYGbn@;6Su_>Oxe}6{}c!8`UU3dR0CaR&07W zzmN3@zGF(N6Ie)JeGAi!93D~U+j?Dp7=^1FE^S~L>f|{&{yRJC3nuLs;pfQb7avo| z(i*qS4bTqpo4SJr5Y|4!*si4n0BWdACcp3aHO2}U$G&e0Z407;wRn5qV$H1M$Bz?q zfY}y|ds?yLn2X-W))O-uSa8E>c#~Q2D)lR>r18^dp%qt38#ZK5Zx?xEDEi4UcyE(djXY*2Yx|a+bIysZO|B zMUm`AwcDR!*TkZX$r(QgCR*Zph?F~N5!Y>0fR_$4nIe5To{3u}BPjuO*1mN4^4va} zVF8<1iCNQSft5Mg-YvQY>RsmOD6IHU&9$%R+Mi{DgUUBjX_|f=aPe|{=@I5B7=%-E zTsCi|P~yjv*3g^7NO`b-Jk6773o#TmT*@gp<%~4*e0ae`upa)`p{5LdNeM2#=hbnA zdn7H1sSCLQNgDkO!U7^bAA^36y1AC}NuK6`FKZGL2Rm0{&QbEoMlEAcOwhyDdI-guH6*Zv3#pzuM|?w_fY(3tXyx6z2Q#Q& zYybWEiBj-N{e_AYkG@X0qd_c$OGPFHBl356cv@hp#lq!7HF{yFrSO?!%kjdM#(RK7 z*ndAi`r_5-wo#TfcF~Gni^Z7bS(4b=8l38MlC0clUjA;ELN1Gy6*`onx6RE~#80}7 z47c>M4oY;&V7p`Xbdrlf(Z}XWF21*vSqbTBY3o?*)M)@PHYzkDQ7R){X9lA8@;S3- zkK^blu3H%xcyre|!O;Ud3+7SMOHJr5`b}CFObOH4x|sAl^@ZJnfmXq5(1EaN^7XUq z>`v7mIkn8|7onnqcvJcgDvy2uIV$#OF_j+4#xz@7if?bwxcrn!AMlg)%366en=yY6 z`kpS8QGOC(F@SZ?u3b-RYh#&d&l$tV^mTvB1a+WCjNc^`3VxEr!tdmzPVB&U<_GyQ zC!HS~!1!j?4e^il&`vH3dU1d9MRFqY_Oj06iO`kb+vWxO2NJ4m{ z_2#<56WXp!Sm&4)#$kB)=6?V|(!7<=kjrsX+NKHUj%wAB>G8&HoWcYZoGqTX{VLJpR{v8q|^Ner}tiK pJP9Dr*ZCo2y!Sd17q-4=>p+J^Ui!O^{WxS{rtPe$M{GPc{2RYsz|Q~x literal 0 HcmV?d00001 diff --git a/docs/dev/pictures/mpt_tree.png b/docs/dev/pictures/mpt_tree.png new file mode 100644 index 0000000000000000000000000000000000000000..eef76442e23f6ecbc77a082060f4e3257ed2b73e GIT binary patch literal 19753 zcmc({2RxR4-#30zR%XiHD-}hV*;`UZgv`<)GP60I%Bal9C}bu=&SY=OmK7p<6WM$J zKZkx@*L`2lb>H{(-2dl(o}<@GoX2r~kK?;O4v>EdWvMSwC{~n;f~>Yn?A(C6hPGMU!BQ%YuOeZt zPmDrB`*S9Gnlm;R=4;pG0+(Y&T9IEkeRY&E%Z0*^dk|fDJx9TeuwK2=L-InSa*U{>_ zyNPc3DSSDMbG7;w|7Ho1^|wB8-~C$>@~X70wrrI{r0~FnL97^&O6krB->w}D83|df zK(5acNopDv&ZThtr$0+3_P*Y`ch9UPw#aj@n1cP(sr#eV&z*9q{^`69EmnXaZNK5`Ng#>`0=GeY@R^~v{{nTCb7Bi$yLIn$?s zfq~>wo2-{E{g}G8Lb{cM?%Z@$n6VJRe@b8HN8cA%l~|jdSSy^-IkeJfaJowt0@9r++Do%a<3EUW#GTGymA3E9%q z)8jDvu0w(i93nP@tIj7-D6c3yLbk@nMyG{A$u`LXn;~Ok<9Y8>Mc9;-d!1>T>XK{P zXmptgz3oET#{LL7X0a*WZ@uSXer9Ioox0$y44gnSm*Zn}%*QC?N;d}Gjf{+r4CG{F z%N&5@@%8C@26+xH^PB)$aDwk~RTQH-`F%Foa3)=BTTX9O*ECWlDrU%&pz zygg~5;$Z(^ui_voENr=v2fMrYh1~mxS7&FZ?9QXM{M2|)x0T7}FHgy(oqoOQve=8l zY(=R{ZQbQ(sC4n8xezyUMkQ=?bhN+Ex%%1hiv2Y#jLYs!2G)9@*m3szhXoj0P2^}# zlz-|U5D>yF={ETlW~~L8^KU7tQRj_{?Z%X}v^rq*aBqG4*^z4Y^%a}Qa#qQFZ?U7L znOW*Ck1}@WXOPI?Wi_?nXV0EJf8NmC93gUwlk+4EO_Ox@_wUEpqGMvXRH7wZmlrSx z?kZtAAM~jh85vKU5U}V>Q)WSHhrL}W-IM3cZxaW`EJ6jP&&FA-~7@bo$E! z&O;43r4l6X)ZWa{x>JtPS$uKv>wDruaqZf*`H2Vy5$jB&5}oDY;_2I8{79L^v~00$3z6EM z_KMauHZFIX>&2FDH$D^|Ds|1t&CQJ$-=7qzxMVk4-JvdB=CNh(+VtsOlbD#8TD+8% zApOenGPCFA2n^cMql;+5!k~{IKjv9>@7G~=>ufMPeaJ?Lhh=&H{$%HSt(BD(v*u`_ zgeX&qFAK2S4PH>NpFP`HMyw5!(ZU_)B1gD179!m!GMNht$;s((@Z7B{TvsMTr1z&C zN_M?V2bAXv$AUk7`cxA@qaG`2CnHWqcTpkiEnmg%MJXvMc6QTmZ&l`nh8rVzSUeVG zVVE91%%m_Ks|_;9e|YB1nXM_z{?vZOGmmaY3Q9`$*5!_O*BIJ@1I3`1W`bTmB!!$h|rEy;xo7mirOHQYVR%i9lQ z@={&ulGCpq*add;{YBOeIiEg#yTyO^{(Z50A3wkE-QAC*Zt-7;OXLbPDg z=2nk$xHEO>(WJ}f)KgLh;fFo^Y(DMgtBWaaTgy#+n3b5JQrJka@o;c(V68VbHO27X z{w#B#8}$Y`2HM-RVW;{M(}1P%dx{(d1qDs&gRvNB0gQBg6m-dp_j1QxrSODyQsP>Rpi z1r^&f8EP9rAt8J`JTEb7SFe6;Y}C&-^&K0oMU#&d6i-%!tw%!Ln>@{B;?P5 zy=of@US6B+CRmMVI`#5>c6NKkwFTASZ?G0zU0s(^bE-jiRD-Piri86}IV;v+ZHc?B zrgcn#)lbWAUStGoy1la@5HId*4YmgMW&tUW|DNY$et!Pv&!1ys8Mg-Sr*>`*XoGK% zFw6O2567cNM*Skcoy(U;V3OI8^TgyGbFWz%O!Mutmpcj zmWe?vHCyweLZK3r{0ve) z`}_M>>`w6MVvVWfs%vVl!3JBMZujmJj@P(Dt@BS>wtlUfd*!gtwZj@?JsN+%Bw}>u zIQXD%p}PNjKk>FoaQ4|S>}(07foA4JV{~eoCg6~-q?Rm@FEf=Z;_82P@r&e-6Y|=I zphrV&`G59jF+?J$#(Vs6|JC*UJ!0bGdjm%+EoocZD7iw+mXDP_fPIjmi;WYq{Qg$ug%UxX3p~P5EBs< z*^WHnQ~`sLsvaN7+3-^-eqHxVuCpL*tJ}M>6y?uP;svS9!}3rZV6lOHFY5P5i*KOSV^z)aAT=%gM*bCnVH0 zcRVaEuH1S+tWG}X$FKT@66b|Tk;bjE{CpixJ$?PNZsX2HwbL3#Mppc^b%@sSb29^V!?ZT4J~Mm5wZE6c~eM8NU~cwCntx7 zSC2J{5uD{9=3uX-r3L)8{8O?$h~UCFA@t@G72TX{j)76FSeii-pk-B+zZ}=0Z7oh2 zga_f(n%zmgnl8?=9fz-!+-@$2Pe4G-#@I)&8VxhMwY8;{szypq&LU#nZx)Z9>=|6~ zNW)@HKHXKhdiCnVhYukZ^JtFZR5^F<9FJ}m<0bpMdU~%s_KG-FV9i7P0a3v1+qYFz zR3OC5>zgxcje8^EYOkOGuJ>zwy{PT57pDp`;WLA>@!!6-PtzSfSus3We?a4)w69k8 z*5Z80f|#0jT3Q+vkIqRds+5!zA~x_wz7*Eot?t3@j+))#)0VxW^vnEYgoOO`L4jtH zTHWopJm*zy%RX33E><1^mvQORB^J-k+eStMO?(xl5Wt0ng!Ry|r1us5Jo z$pPKvD_gyO>sCU$`9o{#b>~N3`=*{wXX}SZy)X)jie25^1V@h&veDDi-*1U^o$tSt z^CLDszT$2}7(~hj=b~`ahY5N3$~Q+<`N{-MtDhAYi(y2LP18)8K|WR3dOyc%u=L0M z9MWms#`cZ7qW0sL?d-A_SxYf{Yu)M+OFkk7L?p2snZNprw4_K`+<#rz(hVk`{Y74z z<90!MBV~K(*MiU)Dua)=9#ec?S`wEGneroL@Sz~4=3O+I-JaN9n}raCO72zjppZ~Q#hO-!HCFfah4bgt2(z6RjM=J_ z6a#h##44|GCNolD+b7HiHW)(t-!SS=qu^ne78k$lZXYWjUe)`Ma5RYQ_6&zbh| zhL?K-S+Ys6)gOIrjZVZ4Za?Gr+?1?5GBQxp&=$qqN+7w`Ekw!~1lvf5Fxzd-Vk@yf z8QjTs!3}SvBMS*rui}N|32(pfoDuF9MsKesD~E_N!^muLYSO1#CY`TW-QT8TL*~#z znm&vZ97lI&XRMf`#qxNA+@2);>9VyAomcUBRk!$I+0)c-sQdXK$1~>m@XXUkB95$AIBp#qEv(ZgR&wsY&@KHE z`h$vg@Dg2u$e}q=pWdBR-}TwL$x!H7WBE=!{=APyZ(|xaw>Me0vTxk>Y;<}^ZNp3M zg_4ExP!44sU0v}Rp7i-phSl#T-LK-iT5j=A&+m|-jTqMlW=k%dFAM8GlPd3M$cuj= zE+TNtHNinB?k4#+-p0T-ZffrYkFTxPZANItcUkn&3`D&=+}_2(l&mFPZ)5|_@-(`| zYj!2f)3D|g4NPveZ)7ztPMQ^j>gM`EA8Ji0!UMN{oEWFNHgeaiW$A*Q2JfU9Ih^%= ziF4}$VPo~~uS?7RO12kKy!f)OU&WU_DNVwQCGmoD{&4QxI91o!UDRDT`2bEnD^0S7 zlYup?r%6|GoI`cB17G6UBG-Q2{pC1Ll{b19G9;dqTZ~o*Mr&=3R|)_4TYD+uy~nZ)riCIo8u34GMvtgqr7y-Jhl;f`9o_*Dz9 z;t9Op3RrKrK^Re0RR#7eSt-bEwOtuD7?{U6*U8s!-@YCB^0f7hctLvl70*cqo6=B- zagQHAe&WQ-n3!1y6OmpCr(b$(K0h92VX@B1dzD^k=AJI=Kg@h7U>UAE%MYKKG%HL9 z-l`9fcqejaj=lX9>;8;7hOr@o3G!JU=0 zF1DX&B!EnDGRCI1ww8=Z%mGrxA&-@7Dk=>x*yK4?wjmQUFff4pY_bM7@5e(a05t9? zCBQ;xqgly06{_2>ee)({+!qA|5Rd*aUynC2F>!5e4f2DJA8q^ct%!(-wBB94YJOGn5e0#f$aoS)!yEY@6E=~|FOG#o(=#SNTmVU&@?ewa5X`Z z!ulcm+S)rcHEV|dhPzD4ZWN{`I503)$TIR@ccC5V0rM3I37Mi2y1TlHy73a?wJ%89 zn!Tvym;Qq1-8r^=U-AV_QCF9xa*X@nsQSopsgzv-#jv;III_71SW2&I*mj(gWI&)xzzC-QF3n^+SG~>cdF5mmkvb9nbZnu8Q8!(hX>7?p6E%_s_tJkb)ij-j3OB zYzULM4k2WvvokXej+qi8wU57X;xPx!&(Bv^E3hG6vA<^k`=!yQbpQNjctuDgd{1lA zOhm(^o%gzgpkEEEIsQrx!;{?sud2xsy|XlFR8;O0TBeX|PPM#=f!G4JlTNRWfMBvCB(s_|L_?6E1yiJtAk^E~Q3fjtY=% zhvv$S~ zw$$g(a+o~QLMj+Bg0HPvbgPdwK<1RRI_T{HvOR@>-~~Bzw}16+l#@q zD@%~S-@JKK?is)t7!gv6CpE0ov@4JJ#;NvZ=I5!=YR>^pJci~AmD7Y(Bn8n@joXXv zv<$KCo}O3H(c8n`NSQ-KWMi${#H7q^4YSvcaox9&nmImplS9nkR?v|BlLw5j3v+gfslm3vGw}xP%YHDP}#5sDrscLV+IDdlwcAtE024S)v zIg6C@e1CfS*{uef(j_IpNg(Zn_}|((DeHspv%v1Tx<%Cj(KA?L~JuNGw`^F(Wa!yN5}#RHMO)j zq;vb`Ak~2k2Z3&FZ5QJt-C=Pssyh{DALOo*xwR}PkNq%aE^&| zprzH&hM1d|TGi9D+sKn4GoPK zyKRYo5YOmCN0_ZACoexcJA3Vv*6rIPfHhH4Qog(T+J13Zmd&RlNP|NqY<;ee+jIM> zI(bB7aqy(jj=hX|I)$Vh+YEu*Xp zV%oa83?%qPUO%M*vAJzh}Y*R`c-iFf|`&03Zf4=kR(IZXG&;e^m&H2usx3;k%CnF0E4i=^*dHndX zn#lGTZKYP6$JJQFYuS3dU|t}h3maQMwt?VCGt8}f>LRw+{&ab2YD)c$n2>~o2jtiB z==IlkN;oQ1!?aCIkd*G#t5-ceJqS)1&8HFuQ>l|>c*%ae9$@#}T*0j;yfMxBz`lfs zhr=h(A7C+h=hkz~TGiqtF0r$JHW$2q_b#KTtxOnaDg(OLgmh)B-FBfRp}gxPl4#R= zdwcs*1kW9@AR4s5DNB-7q1hJtgk%}G_z_OY;PNJxi3lR^{FtMcD3>dd3AL)xONYqfB+N%w0;@V zM1Wgs1L-&_>LFP|_n4x}X~q}uQI$g~)&q2qRo^f%0dvmkV-6mo;$h80VHg~~o1Zv^ zgw}Le3h-pk)$=UA!&dC~0w@>rP`GaaNTvuL-9fuLroDrR?xMXnvgj|35b+y(EGdr2 z+W9V#oYUMnd@2e#co>O;-4#4MJTwN@@8a%C>(ux-iJX8$kwBWR9(1j@0#mX0?P(!u zk*|EA%~E>5wKkd|KqhjN2LRVl+^y_7(|?HrrGuJ?e7aVbdjVF5G8j>`{rBx8YVcbJ`{&6 zS$=Nr!ylhgrq-W4d4fQ81?AS>eF4xV|IPQ>@^*M__{+zyAL5D zA@~F|B$2$-0qW7jw`}e9{JYIMAezBXODUD zkL#e&qizP+_Q5Xo-q}z~B=hV@Ri}|dKpu*HodfApEiXSN{o|M}?#ULCibzp2dDnI? z1TPp@OiA>$*05r=0oZAyGzv2N?v2{KiJ|t^!^d?9-aclnA|0WWr`0Xq#S^|d)xwJP zp>ky6suW@hHk;u=?f%RUkk!^f5d!jjU|&Y7pohZ>ob)0?cYv%96^aZx={aV4;n_#r z1a7#bqNvLhx*`K%0czhaqlWeKF|YD^Xy(gLUubB z>azRRDAb$n&9M+Zqhh#q8w()blG|Na&l^C{0#n$YtlZ>$vLG+-gMQvw0JF}XwHPdQ z?ds}U79c)$?CL44yLazCeE18{+&A;Her)o76gsF?mTs&I>1;BsM_gbr(TP(Md#fEl zyhpJ}0iOY&uT8~XKHzXoO*?R3Kp?fivc|>jcj=nEZk_~`5o~{B0n0{jcaShK8zB#^ z;MZ1q88n_(;lG~8ecvz$ABYSO2TJ||Ook_H35tk_2uO(p1UeoH127vU^WlAWC$YzbRiTL*{Ss#}C4B){^o?!fNaFOAj!e%{&L?LJ6@idHtpahNHZ zit7WL1;h9C>q)s^y?L{chXeODGBQF(M@K-;46G$&fJmYd5WoQ2xi*MlW3G>ep1#-F zM8v_#DVSc!zaBRszEHZ}vT&c#TRkYb#SYWP2U-M>Ce+8%)P1J#xDsS`%q_7Tw^ABd z<79+!2Wf-$O;kU%E1nk%Cl{Adk^RK-L{q%y_L)$;O2`3Fn^hbk66`)bCC)Yu4uXF^ ze7q~Wuc)XP#(DhDm#@Z2+%%>XgAj@0N&R2To}ZQ^n2XJoI26wd*%JHhk5n!X%H74W zg{U6>vQ)XObQfp%B-|UbYD5_ZZLKOA;|ztMmC+BK`ZH=spDLU2vrV2Gmwbb zj;Z?4d;geI4Q$FYi|C*`MdR98ev?C+uV>*-H>hQ%NZ#7mgmz>_2B)sOjYkh|XE26w zzP|bnf;Pxx2GgtAEy2TO@ZQgHO}If_R#t)7wO(<0#KhryKL(yl`Vl%xLmdWr02b?F z#Xc`l!!uqlDP(AetQII|p4a0}Q$T+X)-Z?tS@kQ$l{vm$!O6+-2~{j-jFUikM4vLO zD3}*XFL-%ZWmR!Dao`K=Bn~QoL3k%KrB4db}V_5vA>I{=bLgl#67tqIu*kz|k_rZgokRxr(56qrUp$$@E ztKJyG47In1Mn|8uF_V~miNupr;1CwyL4NzexXcX*ke8>fMT^>vPQ_#9dq7K}pV8&k zD!K7%sNw){aL_Qg7#bRScW{TqlnoZ*Oa3 zwP6vm&^9u9vzz;%x6dQ zM$SO>mF%$x509<~*13EqnPVcA44%T7L(zz`aH>G6IP~$h_t?nh(pZ7@z*(E2+y^g9 zmmsy0dp0v;u?39HbBd&_EH$!8z|{ZcEN6o(UDw&!`TF%Ricvts<0_&V4gaDHzbt)q zqlksrr@6J&*=7igah$YCk-g&nB{nwM{lxry;nSy2U$~&@Df<5_&rz2W&Ej)?Utfl% zYt={q#;2-`sY^2MFHWz6XKe-aNSBx)Yf|aEP>S+^4yvGLN47uO9Xrv zENzUnwKeENK<*SRWC_OY1Pe?2t5>2ngQcl)ZdaskG&VKynUu#u1`-jGXIgWtXtAfi z-%wloZb2XDQUU@3`uh4HeMnADCdHQrx~d~6ZWYgSe4U`qm1d02{}Zr4OJjAQd}t{f zfZp%KTMtLi1e*<6_#=r&5WtdhgmvpUW%u3O+&n$^0p$VMvkn{-hT4fk_C+{^*-3l}dhFuf0ceoJvG z*#k}&Y%PeifQ&<&AsHi(`9Ev-wFbn~Tp{I?dj`G1meK=CAZRPt+uIv?&S0{kVmO_p z^++$y`LtON7a(_-IHVxRsqv=*zXdx_?pb~PWj3F_Ztiu)jhUn@XASbw5>8|)@>odg z=ryq9%5-f3X=sTY=C@kp5{ohbP^hW3JZ16J)79MoVA-bUW8&MlcL7USuA?{y!kZy0 zpTRSCRR|Y>!FRg$ihl&;V1O#y-OeNn)pa;~_H252xo3Bl5!gQ)D=WZN-g#UsUHzuo z+}sQbm$Iy4Jp6d)1xj4)DY%KtaszkNIRht<4#mdC0{;$p1;lJSB}Sg33-lrWdHMMO z!@SSSyW!ch;?v7`jD%`9Bg1{t%FJuX`Z&l$Q z5()e`9WAWd5Bx6b)tjM;OnJ8?22F|jI}#9_QX6vRoO4jd}9`(m2?k@l!B_<&*| zx7F!GMjL2r0N6{4i;X?E?y*&ac?NcHcR=uf6-ZHwJpB*fA<_hRV71>Eq;s8}oCn|4 zua%UQ-&WjRRsZ~(_8VRp$GNGk&G}%u$?@@iA?WxZr#|eUJmQlcFW6>r=Xt|ohxeQB#pUuO?Y*mRC6tebmUB^0(CEhc zQL!n=$jE?4b6+Uqeo7_7rbqdtMbj`;(_|?;xtiUi=Ay@@EfGgm&BY+JU?yk;G(S5T^8h>SZfTL|w>-tcbcr4ZU5S{Q5b0230;MjQS37CBrNw?0W zHj6ywOZL^6=AslFU#i4OfqqE{YW!X9sa&>M03vcW+AX9u%cul~SQrKd%+_k@H=Qy` zd-7S?K{kv7`Z97nn_f~`_rKWo5%)BKs$3hlHSx@Igc|HRix7hdHE8eq5jSt_Jliyd zZq}-T@e-NxHO0p@RG*ItdM!{s8PqWR>03I=^qqNkAQB^^_gMHN=h3pn!fyfdSp|+e zleiU+#@;ORXQplFxysp?`S`oIL{WeR&~|oA@92Bt_HD%FU3t3vF1l_ z>{8{r47UJ(9|R)+XTR z;N$Ht5Yml*s4y3f0d_{|9-b|jkr_q1dkOVC*6Ep`Y?lW5N7$scVhR)&T26C~boz%@DIr-Weg^Rn-yfA)t6b~w zoD6P~33daZ;Uwhb3q@FWkYkDh1`U?1uCC5~^SamldS{{=y1MaF=xq=*u7M!LGqG?K ze}?A>1q+Lbj?Srrzd33D-d=q+1&9g%V|cP`-LVx6As^i3PHiAOeCrOb`4N~D4u2kN zRxC*+XvhjM2cF68uU@}C&?{;_2;}YCa~g+PG=R?B@_ts-{L1^>pbNBJdY9+%X?i7(?hbP_N2j>U2_aT66uo76Yt1N3&LeGPP-!gM}`C7iSyRy+u_7 zk2S1H@=&~K-vvrJK9Ko<%Y&aX70a-;;#h$OgmbWBS3w220!SYSI#%~?$jVl&v`WXn zd?~Q`A*pbbD68PcV}rccO*S}B5&jW$SRnOIfB!yIoo@OEtRE1bG1Jijo(}=U&sU0| zq-wYevN19H@n>BYOkYm{uz8a=60}Zl#GOGr?!bSLE39Fnc_E$G3r2Lh;h(w{rx!5_ zb~Qi}Izp;;G18|^)z~8CBI0JaN!V=1{yBc2N{=GX|!K zg-I5M6-l^z4+OeDp*(CE-Rul&*rW7-9BGN*nNdV5a-@Ai@e(D{C_h*9ylkh~RnOBa zdlyF!#%MX^EZgDngh#hC5Uh~`^)#b1Tw0XyZ4f!s4lmc2zxy~Yo71P9QHaW)C%twp z|Lm|*OwlfNaScITA{NX&FrHl2LD6HxFDHXF_bm@RdTbwb_Pyh?a5$60b)YVPR zxHCZ{LU!_GN=b?MA=?cCk+{A+$xpjqOctKF@1k@2r*g%eO3)Aq$vuPNv(J>Mb9-?= zoBt>pX80J)@L)>G8taheC*i$3cPck-}!=jtVYp6_sv&0LpSWXEU|-6J?>s%S6CY?_T5hQX}lUL7B=j3z-+z!-FnP{pix5ZfVq#*ga_aH?BN}q<$SOT+OT46v?cn2yTKs}k$H&?M)!#C(U^`=}^E|Z{2`E=GMFy`Hd zSvdZdMfGpy(zXLQIH->3@9N3}d8nlO`l>!XL;7U7ffK~=X4dnEI(u1%N#054GV&4Xf z>s^8UT2d1+v^Vbz`B@^AsOW!yk5_i_@*bBaX(9aNpDcR@?A!k0Q)yn~(#<}b3L*L+ z>D@)|#fdNtC@G5`d~BJT9nB5%K` zVz-Gq-eWXExBQ&qp_+DZ>?h&*xR4jCtE&*LBjghZumPCmR*SWLh?y^%0x9i%;TQl1 zA#{R87E%MGB;X?k`M+RPmpk+g4B|m{1JuUHkNg2O_A{MO0|V71C1!E1ryv!Axq{67 zLwb5x{BA9S4JQbF6%-I+W^%H)r$-&6m?Qee#>_zM_FJ!{-^h64?S048R4IslZ8|yR z%8^Sg=nco@=EDtI+-^?;EsI~utH(+^&U6B?VT^H>;Y-^-)Zsp%H+yOviywtkCg z+;F!Tim^CVo{}*Eh=b5M1tIi85Yei60u9{pDJLf;CI%)Rh|0Y-dGdxn(2w$iJA!-# z2n?7(P-?1#<=T#XE_yTtNJ}30NvPrhGYpdnu`d`h@DndM-+%ak2${n;FAely=v@fx zcmOfJFToSfZS}X%Vh0nuGe4^oqa4CK@Z-nNL7qaVjLxLr>S5%m4MM#G+@~O`VPGUj z1V@guI<7k~?&Cp#eo)E*<0!r#iQo`fppGU)>W5bFAaC}i0H$YIzGQ%zn%W5{eZaH{ z2nZH_X1cjS$d6<4?){W#sx8Tdeg_i7FSJWE>_lBh3vLCyvR= zGjmMpB5vXTp_ceGrYwo0qDe^UDL^pZRjf4pZ!BzVFtZ;D{K%Lrz_{C#o|`N4o_@ZR z=@FOf3Z-_z^bIm0k6O_LSFCgNzk6#-#=XZ@Hs#w4?bpzlI5;|5{rEHi`v$26bC+b} z;+ojsSpbOu2&SzpEcA2kH-n@Yv`j#1Of|=BbZV(Lq+W4#-I{2M`kS(ejfNT4%YO`! zI~2FG)S-Hzs{wxib{wWDRDqz5X6{)|mrd_1zm0i*+@4-M+H;JM)4^D5WT=)Ev5RbYZaEd9vde%!JgDE3F$u%B|GjE`byaz@7D#5coC#Jx{lO;eoNSxR zRuZQQb!q<0#f;U;s|$C0Hmn~E0*bc#>90zZfC}-1s2hhAC<+x)y7-w`?imyw^~^c7 znpgph0@f4BQ^6G(d2m(?0(OpCtmpGw3IOSl%k0@maVWk*Z~>LGWsB&i#>r(i@!yO? z3_A=kYf8WU@Qm<6Z(dV?iEGb6#q6x~TMCaMHWbQucz}|48z5!W@cYV2nFZsTC&s{a zpc0Hze)dV$s_{ax;=T*2(4Y?G5<$ zc|;CV2GDxt3GdyM=3XT<9tstoP(7*$90AJX34?FxGvrQKcpPfvPUUjXYYdP(ZBoFU zSdqt(57#Swf?Q++4Klhy14BvGqnD7YrIeo|F&(rNOd0SL`5FoS6<&x$Q7C@e)7dV_ z*D6^Pt4D>AtG#_F10bMQ|NN3b2%jKb`TH*?!}TDig@&$c zm=;kX4IP8=Is+W|zO}a!qG%7PQRX|3>ci`L9}Tw$Tf-8--waXt{G8EJX}Vnk8?%F zArJlcU&1>mo1hkNr0&!f@dklw(0bPQ@4r_nPMX{hgD)dXc~bnA|Bg4*5D8|Ph9bo` z8t4D~k|e$NQyn5A=#~!!GL0wGl9EiJ+Tp~htB{y7a#72|_{%(of}Dlo*(^kv`TF8L zh#1245biA3+4=czriWN&1nMK70?NO)zfl2j+W7eHY{mX8QY{D@&ENmn7SZ-=ED8P* zSLpHv_RXKKQ6WPFoF+IhfaBKJ*Fox3hg}sg3DqrCaX;vNfK^7YAyj8lZmt7xfm5yV zEKq!d)JgVaLC0E698O{uP=uI(dx9l z`rt2{i*xIRQK9W^$XMKB;}OM6+hB#${2TKBnKB|&G~E5&m#zOB6+|+3Ad;CJ3{H=W z_wJv$nEM`<3!?qon3sfPp^tBL^A>7rYKx#ssshYUE%IJ~m8m9a@p26WLIvO)bYIQ` zj!_h&Kw2%=wzQ~~40vuWPlSh`tm6T)_fLiCz$`iNM{qbhAf@hifFy!h0_Iswq-G8P;Nf7bKJ%ef>%u)>v#BmVjZ$X^~#NQ*v>X%hiiXis^ z=mNCYz?A{F1_FjyaOV)NLKH2z)~N+9Jd86UD$1nX;}WRPd3Y=Vn71Fv1~fk{t=_sI zDk=&}-k>5D0x@M}Wd;&Ia6PFEl0S)2=Ff|#%tRtXhr@w__!HTu-{A+IFS(tTk&)NO z_907~<-63>|5cBLNYR+oGyaDvj!?xZurOK!R_Gnky*-d(ZGaAWl?I^gWdoEp z!SXzw(KWMhfABi?BP9*Z#!?-NG!#`sV!3}+zRU=dUa*g=!B^I-YiKhIS3*h$8mat; zKfXP32l=9w*2`T3X`#9GZ2-rsVM9QYkMdg9Fj>0XN*T~@eo`(sKmTk+;izDygR^r8 zh-)E722Kf@pT1Z@EV)MG<@VF6JgI#2{eJ+mqfp`A+y1GHTtFmHvsHs^Kf=(k=!Tx% zm8V-qP^p9JRJB=&sJg|9b*X}+1>Qd}<6@qtAHsNPv|_UVo7ZRmwuvp))lL)COiIC) z{~GH;eN)p3xx)e)A5rGB%`#uW%{I!SYsA4H-J{m+C*~3Rx*(^%hnHaN7K2U0x&$S^ zOR5|_76Co$1*kvz5UvT=F(=K8BL{QqQ9=qlbesXK+_4|J0vH@2qZR9SXr zz=vs}kSpw-{qG5s)S?C71NI5Pv@G;@`otQQ2%?GcCYN$qX%@M2=MLn-@M?)#oARx9 z!2Z?0U<>0!Z%ssj>=g3OmtXvKp;``rV350^#1xF}wEpFy(S7SPC{#M4qD)hfsT>+J zI;6dUPzQXdEDox0;rPe525j_qO9FNj`|spQs7~MQMpSiO9hBxaNOQwmRPNpTpqHJ5 zD2viAb*u!)^YdFzgi28FXL*YoEWEKxNKNgB zLT$^U6|W^FC%^v$3kWKrE`sRC3&_&Wr}eNV7!bzeCJNEOX!3xzM@AYUNbbU{Kpn=w zGhP%*63}75R8a}82+abG+!zg8Z(dj^jshcbt3`claRI&OSb(7U9R5? zo#i>Kq2oiP5w1}MB{#wiQOo}8$WvP=8@J;jHw56;4S-uz8jY)>GV;_B?EipAqPz@7 zJnuuQ^YW3i^TxB|9Doq%T)%Fbt>?2pzW`(*j*Ma&b~?1DxB(t(&{}dGb+y=25Kz=s;g-A*0 z5ZBxIlYtZG;G94V~ht)1?hb$hA;#w)YhX=dCBEZDrODrjvvVs31kpyxt{|(mzbDXabckg_(qVvK)vczq1_mS z-0*Ub^O(r2E(<^*`wDCpW@ff)_&kr((z+lbdj*gtgAxZ(-k&&8u{9Z!kdOe%aAjuK zx5>$4a|J`f^g)1!0!h6DGX>fLsN;v1cJSo<@BsW0unTyh0EAZ?13d?|NNP3_<|Q@m zAHcxDDJh8tLlyjVtS)4z*fFCN4e-KpEr4`HY+zlPFsg)_5U|szL7Q&nx2&u_P$a#3 zr{rl~&0M}(fSL#{N{|&Pn*Oe>t-ZQ? zb6<^psly_G!u0=Cl)L?@1m%S!sK)vKeVt7@*w?VPP?Qhw;opp|oH4D%e^$oV_EQPN zcm!Ve6skLX@9^~EtQ@@q z1s-p#89Q5!pgg>Hylqvj`}qWbNQIYCNGw&Kkg^OXx5ND2%-{kXkUToUA(LPvay4Hn z38FJEe^9%_t35!x`rrPE_&S-N<2GG5sLGJvF9_Q?7@?cjde`**F1#)brJ|^&kR^BP G$^QrWss&&G literal 0 HcmV?d00001 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc63136..e56d494 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -186,5 +186,11 @@ endif() add_subdirectory(examples) +if (BUILD_TESTING) + # Multi Process Tests + add_subdirectory(mpt) +endif() + + # Pull-in CPack and support for generating Config.cmake and packages. include(Packaging) diff --git a/src/ddsrt/include/dds/ddsrt/log.h b/src/ddsrt/include/dds/ddsrt/log.h index 4a08a46..360f9c6 100644 --- a/src/ddsrt/include/dds/ddsrt/log.h +++ b/src/ddsrt/include/dds/ddsrt/log.h @@ -107,7 +107,7 @@ typedef struct { /** Function signature that log and trace callbacks must adhere too. */ typedef void(*dds_log_write_fn_t)(void *, const dds_log_data_t *); -extern uint32_t *const dds_log_mask; +DDS_EXPORT extern uint32_t *const dds_log_mask; /** * @brief Get currently enabled log and trace categories. diff --git a/src/mpt/CMakeLists.txt b/src/mpt/CMakeLists.txt new file mode 100644 index 0000000..4b759c7 --- /dev/null +++ b/src/mpt/CMakeLists.txt @@ -0,0 +1,22 @@ +# +# 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 +# +cmake_minimum_required(VERSION 3.7) + +option(MPT_ENABLE_SELFTEST "Enable multi-process test-framework self test" OFF) + +set(MPT_CMAKE "${CMAKE_CURRENT_SOURCE_DIR}/mpt/cmake/MPT.cmake") +set(MPT_SOURCE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") +set(MPT_BINARY_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}") + +add_subdirectory(mpt) +add_subdirectory(tests) + diff --git a/src/mpt/mpt/CMakeLists.txt b/src/mpt/mpt/CMakeLists.txt new file mode 100644 index 0000000..a81fbe5 --- /dev/null +++ b/src/mpt/mpt/CMakeLists.txt @@ -0,0 +1,17 @@ +# +# 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 +# + + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/include/mpt/resource.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/mpt/resource.h" @ONLY) + + diff --git a/src/mpt/mpt/cmake/MPT.cmake b/src/mpt/mpt/cmake/MPT.cmake new file mode 100644 index 0000000..fd50b5b --- /dev/null +++ b/src/mpt/mpt/cmake/MPT.cmake @@ -0,0 +1,184 @@ +# +# 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 +# +set(MPT_DIR "${CMAKE_CURRENT_LIST_DIR}/..") + + + +function(parse_mpt_fixtures INPUT TEST_DISABLED TEST_TIMEOUT TEST_XFAIL) + set(s "[ \t\r\n]") + if(INPUT MATCHES ".disabled${s}*=${s}*([tT][rR][uU][eE]|[0-9]+)") + set(${TEST_DISABLED} "TRUE" PARENT_SCOPE) + else() + set(${TEST_DISABLED} "FALSE" PARENT_SCOPE) + endif() + + if(INPUT MATCHES ".timeout${s}*=${s}*([0-9]+)") + set(${TEST_TIMEOUT} "${CMAKE_MATCH_1}" PARENT_SCOPE) + else() + set(${TEST_TIMEOUT} "0" PARENT_SCOPE) + endif() + + if(INPUT MATCHES ".xfail${s}*=${s}*([tT][rR][uU][eE]|[0-9]+)") + set(${TEST_XFAIL} "true" PARENT_SCOPE) + else() + set(${TEST_XFAIL} "false" PARENT_SCOPE) + endif() +endfunction() + + + +function(process_mpt_source_file SOURCE_FILE SUITES TESTS PROCESSES) + unset(tests) + unset(processes) + set(x "\\*") + set(s "[ \t\r\n]") + set(s_or_x "[ \t\r\n\\*]") + set(w "[_a-zA-Z0-9]") + set(ident_expr "(${s}*${w}+${s}*)") + # Very basic type recognition, only things that contain word characters and + # pointers are handled. And since this script does not actually have to + # compile any code, type checking is left to the compiler. An error (or + # warning) will be thrown if something is off. + # + # The "type" regular expression below will match things like: + # - + # - * + # - * * + set(type_expr "(${s}*${w}+${x}*${s}+${s_or_x}*)+") + set(param_expr "${type_expr}${ident_expr}") + # Test fixture support (based on test fixtures as implemented in Criterion), + # to enable per-test (de)initializers, which is very different from + # per-suite (de)initializers, and timeouts. + # + # The following fixtures are supported: + # - init + # - fini + # - disabled + # - timeout + set(data_expr "(${s}*,${s}*\\.${w}+${s}*=[^,\\)]+)*") + + file(READ "${SOURCE_FILE}" content) + + # MPT_Test + set(test_expr "MPT_Test${s}*\\(${ident_expr},${ident_expr}${data_expr}\\)") + string(REGEX MATCHALL "${test_expr}" matches "${content}") + foreach(match ${matches}) + string(REGEX REPLACE "${test_expr}" "\\1" suite "${match}") + string(REGEX REPLACE "${test_expr}" "\\2" test "${match}") + # Remove leading and trailing whitespace + string(STRIP "${suite}" suite) + string(STRIP "${test}" test) + + # Extract fixtures that must be handled by CMake (.disabled and .timeout). + parse_mpt_fixtures("${match}" disabled timeout xfail) + list(APPEND tests "${suite}:${test}:${disabled}:${timeout}:${xfail}") + list(APPEND suites "${suite}") + endforeach() + + # MPT_TestProcess + set(process_expr "MPT_TestProcess${s}*\\(${ident_expr},${ident_expr},${ident_expr}") + string(REGEX MATCHALL "${process_expr}" matches "${content}") + foreach(match ${matches}) + string(REGEX REPLACE "${process_expr}" "\\1" suite "${match}") + string(REGEX REPLACE "${process_expr}" "\\2" test "${match}") + string(REGEX REPLACE "${process_expr}" "\\3" id "${match}") + # Remove leading and trailing whitespace + string(STRIP "${suite}" suite) + string(STRIP "${test}" test) + string(STRIP "${id}" id) + + list(APPEND processes "${suite}:${test}:${id}") + endforeach() + + set(${PROCESSES} ${processes} PARENT_SCOPE) + set(${TESTS} ${tests} PARENT_SCOPE) + set(${SUITES} ${suites} PARENT_SCOPE) +endfunction() + + + +function(add_mpt_executable TARGET) + set(sources) + set(processes) + + foreach(source ${ARGN}) + if((EXISTS "${source}" OR EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${source}")) + unset(processes) + unset(tests) + unset(suites) + + # Disable missing-field-initializers warnings as not having to specify + # every member, aka fixture, is intended behavior. + if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR + ${CMAKE_C_COMPILER_ID} STREQUAL "AppleClang" OR + ${CMAKE_C_COMPILER_ID} STREQUAL "GNU") + set_property( + SOURCE "${source}" + PROPERTY COMPILE_FLAGS -Wno-missing-field-initializers) + endif() + + process_mpt_source_file("${source}" suites tests processes) + + foreach(suite ${suites}) + set(addsuites "${addsuites}\n mpt_add_suite(mpt_suite_new(\"${suite}\"));") + endforeach() + + foreach(testcase ${tests}) + string(REPLACE ":" ";" testcase ${testcase}) + list(GET testcase 0 suite) + list(GET testcase 1 test) + list(GET testcase 2 disabled) + list(GET testcase 3 timeout) + list(GET testcase 4 xfail) + set(addtests "${addtests}\n mpt_add_test(\"${suite}\", mpt_test_new(\"${test}\", ${timeout}, ${xfail}));") + + # Add this test to ctest. + set(ctest "${TARGET}_${suite}_${test}") + add_test( + NAME ${ctest} + COMMAND ${TARGET} -s ${suite} -t ${test}) + set_property(TEST ${ctest} PROPERTY TIMEOUT ${timeout}) + set_property(TEST ${ctest} PROPERTY DISABLED ${disabled}) + endforeach() + + foreach(process ${processes}) + string(REPLACE ":" ";" process ${process}) + list(GET process 0 suite) + list(GET process 1 test) + list(GET process 2 id) + set(addprocs "${addprocs}\n mpt_add_process(\"${suite}\", \"${test}\", mpt_process_new(\"${id}\", MPT_TestProcessName(${suite}, ${test}, ${id})));") + set(procdecls "${procdecls}\nextern MPT_TestProcessDeclaration(${suite}, ${test}, ${id});") + endforeach() + + list(APPEND sources "${source}") + endif() + endforeach() + + configure_file( + "${MPT_DIR}/src/main.c.in" "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.c" @ONLY) + + add_executable( + ${TARGET} "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.c" ${sources}) + + target_include_directories(${TARGET} PRIVATE "${MPT_DIR}/include" "${MPT_BINARY_ROOT_DIR}/mpt/include") + target_link_libraries(${TARGET} PRIVATE ddsc) + + # We need the 'expand environment variables' feature that is present in the + # 'util' module. However, it is currently not possible to properly link to + # that module on Windows. In the near future, the utils will be migrated to + # ddsrt, after which we automatically have access to expand_envvars. + # But until then, use this very ugly (but quick) hack to solve our immediate + # build issues. + target_include_directories(${TARGET} PRIVATE "${CMAKE_SOURCE_DIR}/util/include") + target_sources(${TARGET} PRIVATE "${CMAKE_SOURCE_DIR}/util/src/ut_expand_envvars.c") +endfunction() + diff --git a/src/mpt/mpt/include/mpt/mpt.h b/src/mpt/mpt/include/mpt/mpt.h new file mode 100644 index 0000000..8d0522a --- /dev/null +++ b/src/mpt/mpt/include/mpt/mpt.h @@ -0,0 +1,158 @@ +/* + * 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 MPT_H_INCLUDED +#define MPT_H_INCLUDED + +#include +#include +#include "mpt/resource.h" +#include "mpt/private/mpt.h" +#include "dds/ddsrt/environ.h" + + +/* Environment name/value pair. */ +typedef struct mpt_env_ { + const char *name; + const char *value; +} mpt_env_t; + + +/* Process entry argument definitions. */ +#define MPT_Args(...) MPT_ProcessArgsSyntax, __VA_ARGS__ +#define MPT_NoArgs() MPT_ProcessArgsSyntax + +#define MPT_ArgValues(...) MPT_ProcessArgs, __VA_ARGS__ +#define MPT_NoArgValues() MPT_ProcessArgs + + +/* Process entry definition. */ +#define MPT_ProcessEntry(process, args)\ +void MPT_ProcessEntryName(process)(args) + + +/* IPC functions. */ +#define MPT_Send(str) mpt_ipc_send(MPT_ProcessArgs, str); +#define MPT_Wait(str) mpt_ipc_wait(MPT_ProcessArgs, str); + + +/* + * MPT_TestProcess generates a wrapper function that takes care of + * per-process initialization, environment settings, + * deinitialization and the actual process entry call. + */ +#define MPT_TestProcess(suite, test, name, process, args, ...) \ +MPT_TestInitDeclaration(suite, test); \ +MPT_TestFiniDeclaration(suite, test); \ +MPT_TestProcessDeclaration(suite, test, name) \ +{ \ + mpt_data_t data = MPT_Fixture(__VA_ARGS__); \ + \ + /* Always export the process name. */ \ + /* This can be used to generate unique log files fi. */ \ + ddsrt_setenv("MPT_PROCESS_NAME", \ + MPT_XSTR(MPT_TestProcessName(suite, test, name))); \ + \ + /* Initialize test related stuff first. */ \ + MPT_TestInitName(suite, test)(); \ + \ + /* Pre-process initialization. */ \ + mpt_export_env(data.environment); \ + if (data.init != NULL) { \ + data.init(); \ + } \ + \ + /* Execute the actual process entry function. */ \ + MPT_ProcessEntryName(process)(args); \ + \ + /* Teardown process and test. */ \ + if (data.fini != NULL) { \ + data.fini(); \ + } \ + MPT_TestFiniName(suite, test)(); \ +} + + +/* + * MPT_Test generates wrapper functions that take care of + * per-test initialization, environment settings and + * deinitialization. + * This is also used by CMake to determine the ctest timeout + * and disabled settings. + */ +#define MPT_Test(suite, test, ...) \ +MPT_TestInitDeclaration(suite, test) \ +{ \ + mpt_data_t data = MPT_Fixture(__VA_ARGS__); \ + mpt_export_env(data.environment); \ + if (data.init != NULL) { \ + data.init(); \ + } \ +} \ +MPT_TestFiniDeclaration(suite, test) \ +{ \ + mpt_data_t data = MPT_Fixture(__VA_ARGS__); \ + if (data.fini != NULL) { \ + data.fini(); \ + } \ +} + + +/* + * Test asserts. + * Printing is supported eg MPT_ASSERT_EQ(a, b, "foo: %s", bar") + */ +#define MPT_ASSERT(cond, ...) MPT__ASSERT__(cond, MPT_FATAL_NO, __VA_ARGS__) + +#define MPT_ASSERT_FAIL(...) MPT_ASSERT(0, __VA_ARGS__) + +#define MPT_ASSERT_EQ(value, expected, ...) MPT_ASSERT((value == expected), __VA_ARGS__) +#define MPT_ASSERT_NEQ(value, expected, ...) MPT_ASSERT((value != expected), __VA_ARGS__) +#define MPT_ASSERT_LEQ(value, expected, ...) MPT_ASSERT((value <= expected), __VA_ARGS__) +#define MPT_ASSERT_GEQ(value, expected, ...) MPT_ASSERT((value >= expected), __VA_ARGS__) +#define MPT_ASSERT_LT(value, expected, ...) MPT_ASSERT((value < expected), __VA_ARGS__) +#define MPT_ASSERT_GT(value, expected, ...) MPT_ASSERT((value > expected), __VA_ARGS__) + +#define MPT_ASSERT_NULL(value, ...) MPT_ASSERT((value == NULL), __VA_ARGS__) +#define MPT_ASSERT_NOT_NULL(value, ...) MPT_ASSERT((value != NULL), __VA_ARGS__) + +#define MPT_ASSERT_STR_EQ(value, expected, ...) MPT_ASSERT((MPT_STRCMP(value, expected, 1) == 0), __VA_ARGS__) +#define MPT_ASSERT_STR_NEQ(value, expected, ...) MPT_ASSERT((MPT_STRCMP(value, expected, 0) != 0), __VA_ARGS__) +#define MPT_ASSERT_STR_EMPTY(value, ...) MPT_ASSERT((MPT_STRLEN(value, 1) == 0), __VA_ARGS__) +#define MPT_ASSERT_STR_NOT_EMPTY(value, ...) MPT_ASSERT((MPT_STRLEN(value, 0) > 0), __VA_ARGS__) + + +/* Fatal just means that control is returned to the parent function. */ +#define MPT_ASSERT_FATAL(cond, ...) MPT__ASSERT__(cond, MPT_FATAL_YES, __VA_ARGS__) + +#define MPT_ASSERT_FATAL_FAIL(...) MPT_ASSERT_FATAL(0, __VA_ARGS__) + +#define MPT_ASSERT_FATAL_EQ(value, expected, ...) MPT_ASSERT_FATAL((value == expected), __VA_ARGS__) +#define MPT_ASSERT_FATAL_NEQ(value, expected, ...) MPT_ASSERT_FATAL((value != expected), __VA_ARGS__) +#define MPT_ASSERT_FATAL_LEQ(value, expected, ...) MPT_ASSERT_FATAL((value <= expected), __VA_ARGS__) +#define MPT_ASSERT_FATAL_GEQ(value, expected, ...) MPT_ASSERT_FATAL((value >= expected), __VA_ARGS__) +#define MPT_ASSERT_FATAL_LT(value, expected, ...) MPT_ASSERT_FATAL((value < expected), __VA_ARGS__) +#define MPT_ASSERT_FATAL_GT(value, expected, ...) MPT_ASSERT_FATAL((value > expected), __VA_ARGS__) + +#define MPT_ASSERT_FATAL_NULL(value, ...) MPT_ASSERT_FATAL((value == NULL), __VA_ARGS__) +#define MPT_ASSERT_FATAL_NOT_NULL(value, ...) MPT_ASSERT_FATAL((value != NULL), __VA_ARGS__) + +#define MPT_ASSERT_FATAL_STR_EQ(value, expected, ...) MPT_ASSERT_FATAL((MPT_STRCMP(value, expected, 1) == 0), __VA_ARGS__) +#define MPT_ASSERT_FATAL_STR_NEQ(value, expected, ...) MPT_ASSERT_FATAL((MPT_STRCMP(value, expected, 0) != 0), __VA_ARGS__) +#define MPT_ASSERT_FATAL_STR_EMPTY(value, ...) MPT_ASSERT_FATAL((MPT_STRLEN(value, 1) == 0), __VA_ARGS__) +#define MPT_ASSERT_FATAL_STR_NOT_EMPTY(value, ...) MPT_ASSERT_FATAL((MPT_STRLEN(value, 0) > 0), __VA_ARGS__) + + +/* Helpful function to check for patterns in log callbacks. */ +int mpt_patmatch(const char *pat, const char *str); + + +#endif /* MPT_H_INCLUDED */ diff --git a/src/mpt/mpt/include/mpt/private/mpt.h b/src/mpt/mpt/include/mpt/private/mpt.h new file mode 100644 index 0000000..e167e1d --- /dev/null +++ b/src/mpt/mpt/include/mpt/private/mpt.h @@ -0,0 +1,153 @@ +/* + * 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 MPT_PRIVATE_H_INCLUDED +#define MPT_PRIVATE_H_INCLUDED + +#include +#include + + +/* + * Just some helpful macros. + */ +#define MPT_XSTR(s) MPT_STR(s) +#define MPT_STR(s) #s + +#define MPT_STRCMP(value, expected, err) \ + (((value != NULL) && (expected != NULL)) ? strcmp(value, expected) : err) + +#define MPT_STRLEN(value, err) \ + ((value != NULL) ? strlen(value) : err) + +#define MPT_ProcessArgs mpt__args__, mpt__retval__ +#define MPT_ProcessArgsSyntax \ + const mpt_data_t *mpt__args__, mpt_retval_t *mpt__retval__ + + + +/* + * Name and declaration macros. + */ +#define MPT_ProcessEntryName(process) \ + MPT_ProcessEntry__ ## process + +#define MPT_TestInitName(suite, test) \ + MPT_TestInit__##suite##_##test + +#define MPT_TestInitDeclaration(suite, test) \ +void MPT_TestInitName(suite, test)(void) + +#define MPT_TestFiniName(suite, test) \ + MPT_TestFini__##suite##_##test + +#define MPT_TestFiniDeclaration(suite, test) \ +void MPT_TestFiniName(suite, test)(void) + +#define MPT_TestProcessName(suite, test, name) \ + MPT_TestProcess__##suite##_##test##_##name + +#define MPT_TestProcessDeclaration(suite, test, name) \ +void MPT_TestProcessName(suite, test, name) (MPT_ProcessArgsSyntax) + + + +/* + * MPT Assert impl. + */ +typedef enum { + MPT_SUCCESS = 0, + MPT_FAILURE +} mpt_retval_t; + +#define MPT_FATAL_YES 1 +#define MPT_FATAL_NO 0 + +#ifdef _WIN32 +/* Microsoft Visual Studio does not expand __VA_ARGS__ correctly. */ +#define MPT__ASSERT__(...) MPT__ASSERT____((__VA_ARGS__)) +#define MPT__ASSERT____(tuple) MPT__ASSERT___ tuple +#else +#define MPT__ASSERT__(...) MPT__ASSERT___(__VA_ARGS__) +#endif /* _WIN32 */ + +#define MPT__ASSERT___(cond, fatal, ...) \ + do { \ + (void)mpt__args__; /* Satisfy compiler. */ \ + if (!(cond)) { \ + if (*mpt__retval__ == MPT_SUCCESS) { \ + *mpt__retval__ = MPT_FAILURE; \ + } \ + printf("MPT_FAIL(%s, %d):\n", __FILE__, __LINE__); \ + printf(__VA_ARGS__); \ + printf("\n"); \ + if (fatal == MPT_FATAL_YES) { \ + return; \ + } \ + } \ + } while(0) + + + +/* + * MPT Fixture impl. + */ +struct mpt_env_; + +typedef void(*mpt_init_func_t)(void); +typedef void(*mpt_fini_func_t)(void); + +typedef struct { + /* Test and process fixtures. */ + mpt_init_func_t init; + mpt_fini_func_t fini; + struct mpt_env_ *environment; + /* Test fixtures. */ + bool disabled; + int timeout; + bool xfail; + /* IPC information. */ + int todo; +} mpt_data_t; + +/* Microsoft Visual Studio does not like empty struct initializers, i.e. + no fixtures are specified. To work around that issue MPT_Fixture inserts a + NULL initializer as fall back. */ +#define MPT_Comma() , +#define MPT_Reduce(one, ...) one + +#ifdef _WIN32 +/* Microsoft Visual Studio does not expand __VA_ARGS__ correctly. */ +#define MPT_Fixture__(...) MPT_Fixture____((__VA_ARGS__)) +#define MPT_Fixture____(tuple) MPT_Fixture___ tuple +#else +#define MPT_Fixture__(...) MPT_Fixture___(__VA_ARGS__) +#endif /* _WIN32 */ + +#define MPT_Fixture___(throw, away, value, ...) value + +#define MPT_Fixture_(throwaway, ...) \ + MPT_Fixture__(throwaway, ((mpt_data_t){ 0 }), ((mpt_data_t){ __VA_ARGS__ })) + +#define MPT_Fixture(...) \ + MPT_Fixture_( MPT_Comma MPT_Reduce(__VA_ARGS__,) (), __VA_ARGS__ ) + + + +/* + * MPT Support functions. + */ +void mpt_export_env(const struct mpt_env_ *env); +void mpt_ipc_send(MPT_ProcessArgsSyntax, const char *str); +void mpt_ipc_wait(MPT_ProcessArgsSyntax, const char *str); + + +#endif /* MPT_PRIVATE_H_INCLUDED */ diff --git a/src/mpt/mpt/include/mpt/resource.h.in b/src/mpt/mpt/include/mpt/resource.h.in new file mode 100644 index 0000000..13c5711 --- /dev/null +++ b/src/mpt/mpt/include/mpt/resource.h.in @@ -0,0 +1,6 @@ +#ifndef MPT_RESOURCE_H_INCLUDED +#define MPT_RESOURCE_H_INCLUDED + +#define MPT_SOURCE_ROOT_DIR "@MPT_SOURCE_ROOT_DIR@" + +#endif /* MPT_RESOURCE_H_INCLUDED */ diff --git a/src/mpt/mpt/src/main.c.in b/src/mpt/mpt/src/main.c.in new file mode 100644 index 0000000..31f0689 --- /dev/null +++ b/src/mpt/mpt/src/main.c.in @@ -0,0 +1,551 @@ +#include +#include +#include +#include +#include "mpt/mpt.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/environ.h" +#include "dds/util/ut_expand_envvars.h" + +#ifndef _WIN32 +#include +#else +#define EX_USAGE (64) +#define EX_SOFTWARE (70) +#endif /* _WIN32 */ + + + +/************************************************ + * Support functions. + ************************************************/ +int +mpt_patmatch(const char *pat, const char *str) +{ + while (*pat) { + if (*pat == '?') { + /* any character will do */ + if (*str++ == 0) { + return 0; + } + pat++; + } else if (*pat == '*') { + /* collapse a sequence of wildcards, requiring as many + characters in str as there are ?s in the sequence */ + while (*pat == '*' || *pat == '?') { + if (*pat == '?' && *str++ == 0) { + return 0; + } + pat++; + } + /* try matching on all positions where str matches pat */ + while (*str) { + if (*str == *pat && mpt_patmatch(pat+1, str+1)) { + return 1; + } + str++; + } + return *pat == 0; + } else { + /* only an exact match */ + if (*str++ != *pat++) { + return 0; + } + } + } + + return *str == 0; +} + +void +mpt_export_env(const mpt_env_t *env) +{ + if (env) { + while ((env->name != NULL) && (env->value != NULL)) { + char *expanded = ut_expand_envvars(env->value); + ddsrt_setenv(env->name, expanded); + ddsrt_free(expanded); + env++; + } + } +} + +void +mpt_ipc_send(MPT_ProcessArgsSyntax, const char *str) +{ + (void)str; + (void)mpt__args__; + /* TODO: implement. */ + MPT_ASSERT(0, "mpt_ipc_send not implemented"); +} + +void +mpt_ipc_wait(MPT_ProcessArgsSyntax, const char *str) +{ + (void)str; + (void)mpt__args__; + /* TODO: implement. */ + MPT_ASSERT(0, "mpt_ipc_wait not implemented"); +} + + + +/************************************************ + * Processes. + ************************************************/ +@procdecls@ + +typedef void(*mpt_func_proc_t)( + const mpt_data_t *mpt__args__, mpt_retval_t *mpt__retval__); + +typedef struct mpt_process_ { + const char* name; + ddsrt_pid_t pid; + mpt_func_proc_t process; + struct mpt_process_ *next; +} mpt_process_t; + +static mpt_process_t* +mpt_process_new(const char* name, mpt_func_proc_t process) +{ + mpt_process_t *proc; + proc = ddsrt_malloc(sizeof(mpt_process_t)); + proc->pid = 0; + proc->name = name; + proc->process = process; + proc->next = NULL; + return proc; +} + +static void +mpt_process_freelist(mpt_process_t *proc) +{ + if (proc) { + mpt_process_freelist(proc->next); + if (proc->pid != 0) { + printf("Process %s kill(%d)\n", proc->name, (int)proc->pid); + ddsrt_proc_kill(proc->pid); + } + ddsrt_free(proc); + } +} + + + +/************************************************ + * Tests. + ************************************************/ +typedef struct mpt_test_ { + const char* name; + bool xfail; + dds_duration_t timeout; + mpt_process_t *procs; + struct mpt_test_ *next; +} mpt_test_t; + +static mpt_test_t* +mpt_test_new(const char* name, int secs, bool xf) +{ + mpt_test_t *test; + test = ddsrt_malloc(sizeof(mpt_test_t)); + test->procs = NULL; + test->name = name; + test->xfail = xf; + + /* This test will stop after a given timeout. However, when running in + * ctest, we'd like to use the ctest provided timeout functionality. + * So, make sure that the 'manual' timeout takes longer than the ctest + * timeout. */ + if (secs == 0) { + test->timeout = DDS_SECS(1600); + } else { + test->timeout = DDS_SECS(secs * 2); + } + + return test; +} + +static void +mpt_test_freelist(mpt_test_t *test) +{ + if (test) { + mpt_process_freelist(test->procs); + mpt_test_freelist(test->next); + } + ddsrt_free(test); +} + +static void +mpt_test_add_process(mpt_test_t *test, mpt_process_t *proc) +{ + /* Prepend */ + proc->next = test->procs; + test->procs = proc; +} + + + +/************************************************ + * Suites. + ************************************************/ +typedef struct mpt_suite_ { + const char* name; + mpt_test_t *tests; + struct mpt_suite_ *next; +} mpt_suite_t; + +static mpt_suite_t* +mpt_suite_new(const char* name) +{ + mpt_suite_t *suite; + suite = ddsrt_malloc(sizeof(mpt_suite_t)); + suite->tests = NULL; + suite->name = name; + return suite; +} + +static void +mpt_suite_freelist(mpt_suite_t *suite) +{ + if (suite) { + mpt_test_freelist(suite->tests); + mpt_suite_freelist(suite->next); + } + ddsrt_free(suite); +} + +static void +mpt_suite_add_test(mpt_suite_t *suite, mpt_test_t *test) +{ + /* Prepend */ + test->next = suite->tests; + suite->tests = test; +} + +static mpt_test_t* +mpt_suite_find_test( + mpt_suite_t *suite, const char *tname) +{ + mpt_test_t *found = suite->tests; + while (found) { + if (mpt_patmatch(tname, found->name)) { + break; + } + found = found->next; + } + return found; +} + + + +/************************************************ + * Root. + ************************************************/ +mpt_suite_t *root = NULL; + +static void +mpt_add_suite(mpt_suite_t *suite) +{ + /* Prepend */ + suite->next = root; + root = suite; +} + +static mpt_suite_t* +mpt_find_suite(const char *sname) +{ + mpt_suite_t *found = root; + while (found) { + if (mpt_patmatch(sname, found->name)) { + break; + } + found = found->next; + } + return found; +} + +static void +mpt_add_test(const char *sname, mpt_test_t *test) +{ + mpt_suite_t *suite = mpt_find_suite(sname); + assert(suite); + mpt_suite_add_test(suite, test); +} + +static void +mpt_add_process(const char *sname, const char *tname, mpt_process_t *proc) +{ + mpt_suite_t *suite = mpt_find_suite(sname); + mpt_test_t *test = mpt_suite_find_test(suite, tname); + assert(suite); + assert(test); + mpt_test_add_process(test, proc); +} + +static void +mpt_free(void) +{ + mpt_suite_freelist(root); + root = NULL; +} + + + +/************************************************ + * Runner. + ************************************************/ +static int +mpt_run_test(const char *exe, mpt_suite_t *suite, mpt_test_t *test) +{ + int result = EXIT_SUCCESS; + mpt_process_t *proc; + dds_retcode_t retcode; + char *argv[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + + argv[0] = "-s"; + argv[1] = (char*)suite->name; + argv[2] = "-t"; + argv[3] = (char*)test->name; + + /* Start the processes. */ + proc = test->procs; + while ((proc) && (result == EXIT_SUCCESS)) { + if (proc == test->procs) { + printf("\n\n"); + printf("=====================================================\n"); + printf("Suite: %s\n", suite->name); + printf("Test: %s\n", test->name); + printf("=====================================================\n"); + } + argv[4] = "-p"; + argv[5] = (char*)proc->name; + retcode = ddsrt_proc_create(exe, argv, &proc->pid); + if (retcode != DDS_RETCODE_OK) { + printf("Start %s::%s::%s failed\n", suite->name, test->name, proc->name); + proc->pid = 0; + result = EXIT_FAILURE; + } + proc = proc->next; + } + + /* Wait for the processes. */ + retcode = DDS_RETCODE_OK; + while ((result == EXIT_SUCCESS) && (retcode == DDS_RETCODE_OK)) { + int32_t status; + ddsrt_pid_t pid; + /* A second/third/etc wait will restart the timeout. + * This means that the end timeout can take longer than the requested + * test timeout. However, that's good enough for our purpose. */ + retcode = ddsrt_proc_waitpids(test->timeout, &pid, &status); + if (retcode == DDS_RETCODE_OK) { + proc = test->procs; + while (proc) { + if (proc->pid == pid) { + break; + } + proc = proc->next; + } + if (proc) { + proc->pid = 0; + if (status != 0) { + printf("Process %s::%s::%s failed (%d)\n", suite->name, test->name, proc->name, status); + result = EXIT_FAILURE; + } + } else { + printf("Wait for processes of %s::%s return unknown pid %d\n", suite->name, test->name, (int)pid); + result = EXIT_FAILURE; + } + } else if (retcode != DDS_RETCODE_NOT_FOUND) { + printf("Wait for processes of %s::%s failed (%d)\n", suite->name, test->name, (int)retcode); + result = EXIT_FAILURE; + } + } + + /* Be sure to kill all remaining processes when needed. */ + if (result != EXIT_SUCCESS) { + proc = test->procs; + while (proc) { + if (proc->pid != 0) { + printf("Process %s::%s::%s kill(%d)\n", suite->name, test->name, proc->name, (int)proc->pid); + ddsrt_proc_kill(proc->pid); + ddsrt_proc_waitpid(proc->pid, DDS_SECS(10), NULL); + proc->pid = 0; + } + proc = proc->next; + } + } + + /* Revert result when we expect the test to have failed. */ + if (test->xfail) { + result = ((result == EXIT_SUCCESS) ? EXIT_FAILURE : EXIT_SUCCESS); + } + + return result; +} + +static int +mpt_run_tests(const char *exe, const char *spattern, const char *tpattern) +{ + int result = EXIT_SUCCESS; + mpt_suite_t *suite = root; + while (suite) { + if (mpt_patmatch(spattern, suite->name)) { + mpt_test_t *test = suite->tests; + while (test) { + if (mpt_patmatch(tpattern, test->name)) { + int run = mpt_run_test(exe, suite, test); + if (run != EXIT_SUCCESS) { + result = run; + } + } + test = test->next; + } + } + suite = suite->next; + } + return result; +} + +static int +mpt_run_proc(mpt_process_t *proc) +{ + mpt_retval_t retval = MPT_SUCCESS; + mpt_data_t args; + proc->process(&args, &retval); + return (retval == MPT_SUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +static int +mpt_run_procs(const char *spattern, const char *tpattern, const char *ppattern) +{ + int result = EXIT_SUCCESS; + mpt_suite_t *suite = root; + while (suite) { + if (mpt_patmatch(spattern, suite->name)) { + mpt_test_t *test = suite->tests; + while (test) { + if (mpt_patmatch(tpattern, test->name)) { + mpt_process_t *proc = test->procs; + while (proc) { + if (mpt_patmatch(ppattern, proc->name)) { + int run = mpt_run_proc(proc); + if (run != EXIT_SUCCESS) { + result = run; + } + } + proc = proc->next; + } + } + test = test->next; + } + } + suite = suite->next; + } + return result; +} + + + +/************************************************ + * Main functionality. + ************************************************/ +static struct { + bool print_help; + const char *suite; + const char *test; + const char *process; +} opts = { + false, + "*", + "*", + NULL +}; + +static int parse_options(int argc, char *argv[]) +{ + int err = 0; + + for (int i = 1; err == 0 && i < argc; i++) { + switch ((argv[i][0] == '-') ? argv[i][1] : 0) { + case 'h': + opts.print_help = true; + break; + case 's': + if ((i+1) < argc) { + opts.suite = argv[++i]; + break; + } + /* FALLS THROUGH */ + case 't': + if ((i+1) < argc) { + opts.test = argv[++i]; + break; + } + /* FALLS THROUGH */ + case 'p': + if ((i+1) < argc) { + opts.process = argv[++i]; + break; + } + /* FALLS THROUGH */ + default: + err = 1; + break; + } + } + + return err; +} + +static void usage(const char *name) +{ + fprintf(stderr, "Usage: %s OPTIONS\n", name); + fprintf(stderr, "Try '%s -h' for more information\n", name); +} + +static void help(const char *name) +{ + printf("Usage: %s [OPTIONS]\n", name); + printf("\n"); + printf("Possible options:\n"); + printf(" -h display this help and exit\n"); + printf(" -s PATTERN run only tests in suites matching pattern\n"); + printf(" -t PATTERN run only test matching pattern\n"); + printf(" -p PROCESS run only process matching pattern\n"); + printf("\n"); + printf("Exit codes:\n"); + printf(" %-2d Successful termination\n", EXIT_SUCCESS); + printf(" %-2d One or more failing test cases\n", EXIT_FAILURE); + printf(" %-2d Command line usage error\n", EX_USAGE); + printf(" %-2d Internal software error\n", EX_SOFTWARE); +} + +int main(int argc, char *argv[]) +{ + int result = EXIT_SUCCESS; + + if (parse_options(argc, argv) != 0) { + usage(argv[0]); + return EX_USAGE; + } else if (opts.print_help) { + help(argv[0]); + return result; + } + + atexit(mpt_free); + @addsuites@ + @addtests@ + @addprocs@ + + if (opts.process == NULL) { + /* Run test(s). */ + result = mpt_run_tests(argv[0], opts.suite, opts.test); + } else { + /* Run process(es). */ + result = mpt_run_procs(opts.suite, opts.test, opts.process); + } + + return result; +} + diff --git a/src/mpt/tests/CMakeLists.txt b/src/mpt/tests/CMakeLists.txt new file mode 100644 index 0000000..91a9183 --- /dev/null +++ b/src/mpt/tests/CMakeLists.txt @@ -0,0 +1,19 @@ +# +# 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 +# +cmake_minimum_required(VERSION 3.7) + +if(MPT_ENABLE_SELFTEST) + add_subdirectory(self) +endif() + +add_subdirectory(basic) + diff --git a/src/mpt/tests/basic/CMakeLists.txt b/src/mpt/tests/basic/CMakeLists.txt new file mode 100644 index 0000000..cb2efba --- /dev/null +++ b/src/mpt/tests/basic/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# 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(${MPT_CMAKE}) + +set(sources + "procs/hello.c" + "helloworld.c" + "multi.c") + +add_mpt_executable(mpt_basic ${sources}) + +idlc_generate(mpt_basic_helloworlddata_lib "procs/helloworlddata.idl") +target_link_libraries(mpt_basic PRIVATE mpt_basic_helloworlddata_lib) + diff --git a/src/mpt/tests/basic/etc/config_any.xml b/src/mpt/tests/basic/etc/config_any.xml new file mode 100644 index 0000000..68e0e0a --- /dev/null +++ b/src/mpt/tests/basic/etc/config_any.xml @@ -0,0 +1,30 @@ + + + + any + + + + auto + true + true + + + lax + + + + diff --git a/src/mpt/tests/basic/etc/config_specific.xml b/src/mpt/tests/basic/etc/config_specific.xml new file mode 100644 index 0000000..2ae3286 --- /dev/null +++ b/src/mpt/tests/basic/etc/config_specific.xml @@ -0,0 +1,30 @@ + + + + ${DOMAIN_ID} + + + + auto + true + true + + + lax + + + + diff --git a/src/mpt/tests/basic/helloworld.c b/src/mpt/tests/basic/helloworld.c new file mode 100644 index 0000000..c959edb --- /dev/null +++ b/src/mpt/tests/basic/helloworld.c @@ -0,0 +1,63 @@ +#include "dds/dds.h" +#include "mpt/mpt.h" +#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */ +#include "procs/hello.h" /* publisher and subscriber entry points. */ + + +/* + * Tests to check simple communication between a publisher and subscriber. + * The published text should be received by the subscriber. + */ + + +/* Environments */ +static mpt_env_t environment_any[] = { + { "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/basic/etc" }, + { "CYCLONEDDS_URI", "file://${ETC_DIR}/config_any.xml" }, + { NULL, NULL } +}; +static mpt_env_t environment_42[] = { + { "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/basic/etc" }, + { "DOMAIN_ID", "42" }, + { "CYCLONEDDS_URI", "file://${ETC_DIR}/config_specific.xml" }, + { NULL, NULL } +}; + + + +/********************************************************************** + * No CYCLONEDDS_URI set. + **********************************************************************/ +#define TEST_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "hello_def", 1, "No environment set") +MPT_TestProcess(helloworld, default, pub, hello_publisher, TEST_ARGS); +MPT_TestProcess(helloworld, default, sub, hello_subscriber, TEST_ARGS); +MPT_Test(helloworld, default, .init=hello_init, .fini=hello_fini); +#undef TEST_ARGS + + + +/********************************************************************** + * Config domain is any. Test domain is default. + **********************************************************************/ +#define TEST_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "hello_any", 1, "Some nice text over any domain") +MPT_TestProcess(helloworld, domain_any, pub, hello_publisher, TEST_ARGS); +MPT_TestProcess(helloworld, domain_any, sub, hello_subscriber, TEST_ARGS); +MPT_Test(helloworld, domain_any, .init=hello_init, .fini=hello_fini, .environment=environment_any); +#undef TEST_ARGS + + + +/********************************************************************** + * Pub: Config domain is any. Test domain is 42. + * Sub: Config domain is 42 (through DOMAIN_ID env). Test domain is default. + **********************************************************************/ +#define TEST_PUB_ARGS MPT_ArgValues(42, "hello_42", 1, "Now domain 42 is used") +#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "hello_42", 1, "Now domain 42 is used") +MPT_TestProcess(helloworld, domain_42, pub, hello_publisher, TEST_PUB_ARGS, .environment=environment_any); +MPT_TestProcess(helloworld, domain_42, sub, hello_subscriber, TEST_SUB_ARGS, .environment=environment_42); +MPT_Test(helloworld, domain_42, .init=hello_init, .fini=hello_fini); +#undef TEST_SUB_ARGS +#undef TEST_PUB_ARGS + + + diff --git a/src/mpt/tests/basic/multi.c b/src/mpt/tests/basic/multi.c new file mode 100644 index 0000000..4ed5743 --- /dev/null +++ b/src/mpt/tests/basic/multi.c @@ -0,0 +1,50 @@ +#include "mpt/mpt.h" +#include "procs/hello.h" + + +/* + * Tests to check communication between multiple publisher(s) and subscriber(s). + */ + + +/* + * The publisher expects 2 publication matched. + * The subscribers expect 1 sample each. + */ +#define TEST_PUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubsubsub", 2, "pubsubsub") +#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubsubsub", 1, "pubsubsub") +MPT_TestProcess(multi, pubsubsub, pub, hello_publisher, TEST_PUB_ARGS); +MPT_TestProcess(multi, pubsubsub, sub1, hello_subscriber, TEST_SUB_ARGS); +MPT_TestProcess(multi, pubsubsub, sub2, hello_subscriber, TEST_SUB_ARGS); +MPT_Test(multi, pubsubsub, .init=hello_init, .fini=hello_fini); +#undef TEST_SUB_ARGS +#undef TEST_PUB_ARGS + + +/* + * The publishers expect 1 publication matched each. + * The subscriber expects 2 samples. + */ +#define TEST_PUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubpubsub", 1, "pubpubsub") +#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubpubsub", 2, "pubpubsub") +MPT_TestProcess(multi, pubpubsub, pub1, hello_publisher, TEST_PUB_ARGS); +MPT_TestProcess(multi, pubpubsub, pub2, hello_publisher, TEST_PUB_ARGS); +MPT_TestProcess(multi, pubpubsub, sub, hello_subscriber, TEST_SUB_ARGS); +MPT_Test(multi, pubpubsub, .init=hello_init, .fini=hello_fini); +#undef TEST_SUB_ARGS +#undef TEST_PUB_ARGS + + +/* + * The publishers expect 2 publication matched each. + * The subscribers expect 2 samples each. + */ +#define TEST_PUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubpubsubsub", 2, "pubpubsubsub") +#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubpubsubsub", 2, "pubpubsubsub") +MPT_TestProcess(multi, pubpubsubsub, pub1, hello_publisher, TEST_PUB_ARGS); +MPT_TestProcess(multi, pubpubsubsub, pub2, hello_publisher, TEST_PUB_ARGS); +MPT_TestProcess(multi, pubpubsubsub, sub1, hello_subscriber, TEST_SUB_ARGS); +MPT_TestProcess(multi, pubpubsubsub, sub2, hello_subscriber, TEST_SUB_ARGS); +MPT_Test(multi, pubpubsubsub, .init=hello_init, .fini=hello_fini); +#undef TEST_SUB_ARGS +#undef TEST_PUB_ARGS diff --git a/src/mpt/tests/basic/procs/hello.c b/src/mpt/tests/basic/procs/hello.c new file mode 100644 index 0000000..2c68a84 --- /dev/null +++ b/src/mpt/tests/basic/procs/hello.c @@ -0,0 +1,239 @@ +#include +#include +#include + +#include "mpt/mpt.h" + +#include "dds/dds.h" +#include "helloworlddata.h" + +#include "dds/ddsrt/time.h" +#include "dds/ddsrt/strtol.h" +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/cdtors.h" +#include "dds/ddsrt/sync.h" + + +/* An array of one message (aka sample in dds terms) will be used. */ +#define MAX_SAMPLES 1 + +static int g_publication_matched_count = 0; +static ddsrt_mutex_t g_mutex; +static ddsrt_cond_t g_cond; + +static void +publication_matched_cb( + dds_entity_t writer, + const dds_publication_matched_status_t status, + void* arg) +{ + (void)arg; + (void)writer; + ddsrt_mutex_lock(&g_mutex); + g_publication_matched_count = (int)status.current_count; + ddsrt_cond_broadcast(&g_cond); + ddsrt_mutex_unlock(&g_mutex); +} + +static void +data_available_cb( + dds_entity_t reader, + void* arg) +{ + (void)arg; + (void)reader; + ddsrt_mutex_lock(&g_mutex); + ddsrt_cond_broadcast(&g_cond); + ddsrt_mutex_unlock(&g_mutex); +} + +void +hello_init(void) +{ + ddsrt_init(); + ddsrt_mutex_init(&g_mutex); + ddsrt_cond_init(&g_cond); +} + +void +hello_fini(void) +{ + ddsrt_cond_destroy(&g_cond); + ddsrt_mutex_destroy(&g_mutex); + ddsrt_fini(); +} + + +/* + * The HelloWorld publisher. + * It waits for a publication matched, and then writes a sample. + * It quits when the publication matched has been reset again. + */ +MPT_ProcessEntry(hello_publisher, + MPT_Args(dds_domainid_t domainid, + const char *topic_name, + int sub_cnt, + const char *text)) +{ + HelloWorldData_Msg msg; + dds_listener_t *listener; + dds_entity_t participant; + dds_entity_t topic; + dds_entity_t writer; + dds_return_t rc; + dds_qos_t *qos; + int id = (int)ddsrt_getpid(); + + assert(topic_name); + assert(text); + + printf("=== [Publisher(%d)] Start(%d) ...\n", id, domainid); + + /* + * A reliable volatile sample, written after publication matched, can still + * be lost when the subscriber wasn't able to match its subscription yet. + * Use transient_local reliable to make sure the sample is received. + */ + qos = dds_create_qos(); + dds_qset_durability(qos, DDS_DURABILITY_TRANSIENT_LOCAL); + dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_SECS(10)); + + /* Use listener to get number of publications matched. */ + listener = dds_create_listener(NULL); + MPT_ASSERT_FATAL_NOT_NULL(listener, "Could not create listener"); + dds_lset_publication_matched(listener, publication_matched_cb); + + /* Create a Writer. */ + participant = dds_create_participant (domainid, NULL, NULL); + MPT_ASSERT_FATAL_GT(participant, 0, "Could not create participant: %s\n", dds_strretcode(-participant)); + + topic = dds_create_topic ( + participant, &HelloWorldData_Msg_desc, topic_name, qos, NULL); + MPT_ASSERT_FATAL_GT(topic, 0, "Could not create topic: %s\n", dds_strretcode(-topic)); + + writer = dds_create_writer (participant, topic, qos, listener); + MPT_ASSERT_FATAL_GT(writer, 0, "Could not create writer: %s\n", dds_strretcode(-writer)); + + /* Wait for expected nr of subscriber(s). */ + ddsrt_mutex_lock(&g_mutex); + while (g_publication_matched_count != sub_cnt) { + ddsrt_cond_waitfor(&g_cond, &g_mutex, DDS_INFINITY); + } + ddsrt_mutex_unlock(&g_mutex); + + /* Write sample. */ + msg.userID = (int32_t)id; + msg.message = (char*)text; + printf("=== [Publisher(%d)] Send: { %d, %s }\n", id, msg.userID, msg.message); + rc = dds_write (writer, &msg); + MPT_ASSERT_EQ(rc, DDS_RETCODE_OK, "Could not write sample\n"); + + /* Wait for subscriber(s) to have finished. */ + ddsrt_mutex_lock(&g_mutex); + while (g_publication_matched_count != 0) { + ddsrt_cond_waitfor(&g_cond, &g_mutex, DDS_INFINITY); + } + ddsrt_mutex_unlock(&g_mutex); + + rc = dds_delete (participant); + MPT_ASSERT_EQ(rc, DDS_RETCODE_OK, "Teardown failed\n"); + + dds_delete_listener(listener); + dds_delete_qos(qos); + + printf("=== [Publisher(%d)] Done\n", id); +} + + +/* + * The HelloWorld subscriber. + * It waits for sample(s) and checks the content. + */ +MPT_ProcessEntry(hello_subscriber, + MPT_Args(dds_domainid_t domainid, + const char *topic_name, + int sample_cnt, + const char *text)) +{ + HelloWorldData_Msg *msg; + void *samples[MAX_SAMPLES]; + dds_sample_info_t infos[MAX_SAMPLES]; + dds_listener_t *listener; + dds_entity_t participant; + dds_entity_t topic; + dds_entity_t reader; + dds_return_t rc; + dds_qos_t *qos; + int recv_cnt; + int id = (int)ddsrt_getpid(); + + assert(topic_name); + assert(text); + + printf("--- [Subscriber(%d)] Start(%d) ...\n", id, domainid); + + /* + * A reliable volatile sample, written after publication matched, can still + * be lost when the subscriber wasn't able to match its subscription yet. + * Use transient_local reliable to make sure the sample is received. + */ + qos = dds_create_qos(); + dds_qset_durability(qos, DDS_DURABILITY_TRANSIENT_LOCAL); + dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_SECS(10)); + + /* Use listener to get data available trigger. */ + listener = dds_create_listener(NULL); + MPT_ASSERT_FATAL_NOT_NULL(listener, "Could not create listener"); + dds_lset_data_available(listener, data_available_cb); + + /* Create a Reader. */ + participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); + MPT_ASSERT_FATAL_GT(participant, 0, "Could not create participant: %s\n", dds_strretcode(-participant)); + topic = dds_create_topic ( + participant, &HelloWorldData_Msg_desc, topic_name, qos, NULL); + MPT_ASSERT_FATAL_GT(topic, 0, "Could not create topic: %s\n", dds_strretcode(-topic)); + reader = dds_create_reader (participant, topic, qos, listener); + MPT_ASSERT_FATAL_GT(reader, 0, "Could not create reader: %s\n", dds_strretcode(-reader)); + + printf("--- [Subscriber(%d)] Waiting for %d sample(s) ...\n", id, sample_cnt); + + /* Initialize sample buffer, by pointing the void pointer within + * the buffer array to a valid sample memory location. */ + samples[0] = HelloWorldData_Msg__alloc (); + + /* Wait until expected nr of samples have been taken. */ + ddsrt_mutex_lock(&g_mutex); + recv_cnt = 0; + while (recv_cnt < sample_cnt) { + /* Use a take with mask to work around the #146 issue. */ + rc = dds_take_mask(reader, samples, infos, MAX_SAMPLES, MAX_SAMPLES, DDS_NEW_VIEW_STATE); + MPT_ASSERT_GEQ(rc, 0, "Could not read: %s\n", dds_strretcode(-rc)); + + /* Check if we read some data and it is valid. */ + if ((rc > 0) && (infos[0].valid_data)) { + /* Print Message. */ + msg = (HelloWorldData_Msg*)samples[0]; + printf("--- [Subscriber(%d)] Received: { %d, %s }\n", id, + msg->userID, msg->message); + MPT_ASSERT_STR_EQ(msg->message, text, + "Messages do not match: \"%s\" vs \"%s\"\n", + msg->message, text); + recv_cnt++; + } else { + ddsrt_cond_waitfor(&g_cond, &g_mutex, DDS_INFINITY); + } + } + ddsrt_mutex_unlock(&g_mutex); + + /* Free the data location. */ + HelloWorldData_Msg_free (samples[0], DDS_FREE_ALL); + + rc = dds_delete (participant); + MPT_ASSERT_EQ(rc, DDS_RETCODE_OK, "Teardown failed\n"); + + dds_delete_listener(listener); + dds_delete_qos(qos); + + printf("--- [Subscriber(%d)] Done\n", id); +} diff --git a/src/mpt/tests/basic/procs/hello.h b/src/mpt/tests/basic/procs/hello.h new file mode 100644 index 0000000..b1d1772 --- /dev/null +++ b/src/mpt/tests/basic/procs/hello.h @@ -0,0 +1,52 @@ +/* + * 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 + */ + +/** @file + * + * @brief DDS C Communication Status API + * + * This header file defines the public API of the Communication Status in the + * Eclipse Cyclone DDS C language binding. + */ +#ifndef MPT_BASIC_PROCS_HELLO_H +#define MPT_BASIC_PROCS_HELLO_H + +#include +#include + +#include "dds/dds.h" +#include "mpt/mpt.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +void hello_init(void); +void hello_fini(void); + +MPT_ProcessEntry(hello_publisher, + MPT_Args(dds_domainid_t domainid, + const char *topic_name, + int sub_cnt, + const char *text)); + +MPT_ProcessEntry(hello_subscriber, + MPT_Args(dds_domainid_t domainid, + const char *topic_name, + int sample_cnt, + const char *text)); + +#if defined (__cplusplus) +} +#endif + +#endif /* MPT_BASIC_PROCS_HELLO_H */ diff --git a/src/mpt/tests/basic/procs/helloworlddata.idl b/src/mpt/tests/basic/procs/helloworlddata.idl new file mode 100644 index 0000000..9561d75 --- /dev/null +++ b/src/mpt/tests/basic/procs/helloworlddata.idl @@ -0,0 +1,9 @@ +module HelloWorldData +{ + struct Msg + { + long userID; + string message; + }; + #pragma keylist Msg userID +}; diff --git a/src/mpt/tests/self/CMakeLists.txt b/src/mpt/tests/self/CMakeLists.txt new file mode 100644 index 0000000..8203b5d --- /dev/null +++ b/src/mpt/tests/self/CMakeLists.txt @@ -0,0 +1,25 @@ +# +# 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(${MPT_CMAKE}) + +message(STATUS "MPT selftest enabled: some test will fail deliberately") + +set(sources + "asserts.c" + "environments.c" + "fixtures.c" + "ipc.c" + "resources.c" + "usage.c") + +add_mpt_executable(mpt_self ${sources}) + diff --git a/src/mpt/tests/self/asserts.c b/src/mpt/tests/self/asserts.c new file mode 100644 index 0000000..72495a1 --- /dev/null +++ b/src/mpt/tests/self/asserts.c @@ -0,0 +1,711 @@ +#include +#include +#include "mpt/mpt.h" +#include "dds/ddsrt/time.h" + +static int dummy; + + + +/************************************************************ + * Test MPT_ASSERT + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT, MPT_Args(const char *exp, int cond)) +{ + assert(exp); + MPT_ASSERT(cond, "MPT_ASSERT(%d), 1st, expect: %s", cond, exp); + MPT_ASSERT(cond, "MPT_ASSERT(%d), 2nd, expect: %s", cond, exp); +} +MPT_TestProcess(MPT_ASSERT, pass, id, proc_MPT_ASSERT, MPT_ArgValues("PASS", 1)); +MPT_TestProcess(MPT_ASSERT, fail, id, proc_MPT_ASSERT, MPT_ArgValues("FAIL", 0)); +MPT_Test(MPT_ASSERT, pass, .xfail=false); +MPT_Test(MPT_ASSERT, fail, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FAIL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FAIL, MPT_NoArgs()) +{ + MPT_ASSERT_FAIL("MPT_ASSERT_FAIL(), 1st, expect a fail, always"); + MPT_ASSERT_FAIL("MPT_ASSERT_FAIL(), 2nd, expect a fail, always"); +} +MPT_TestProcess(MPT_ASSERT_FAIL, call, id, proc_MPT_ASSERT_FAIL, MPT_NoArgValues()); +MPT_Test(MPT_ASSERT_FAIL, call, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_EQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_EQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%d, %d), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%d, %d), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_EQ_int, eq, id, proc_MPT_ASSERT_EQ_int, MPT_ArgValues("PASS", 1, 1)); +MPT_TestProcess(MPT_ASSERT_EQ_int, lt, id, proc_MPT_ASSERT_EQ_int, MPT_ArgValues("FAIL", 1, 2)); +MPT_TestProcess(MPT_ASSERT_EQ_int, gt, id, proc_MPT_ASSERT_EQ_int, MPT_ArgValues("FAIL", 3, 2)); +MPT_Test(MPT_ASSERT_EQ_int, eq, .xfail=false); +MPT_Test(MPT_ASSERT_EQ_int, lt, .xfail=true); +MPT_Test(MPT_ASSERT_EQ_int, gt, .xfail=true); + + +MPT_ProcessEntry(proc_MPT_ASSERT_EQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%f, %f), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%f, %f), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_EQ_double, eq, id, proc_MPT_ASSERT_EQ_double, MPT_ArgValues("PASS", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_EQ_double, lt, id, proc_MPT_ASSERT_EQ_double, MPT_ArgValues("FAIL", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_EQ_double, gt, id, proc_MPT_ASSERT_EQ_double, MPT_ArgValues("FAIL", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_EQ_double, eq, .xfail=false); +MPT_Test(MPT_ASSERT_EQ_double, lt, .xfail=true); +MPT_Test(MPT_ASSERT_EQ_double, gt, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_NEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_NEQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%d, %d), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%d, %d), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_NEQ_int, eq, id, proc_MPT_ASSERT_NEQ_int, MPT_ArgValues("FAIL", 1, 1)); +MPT_TestProcess(MPT_ASSERT_NEQ_int, lt, id, proc_MPT_ASSERT_NEQ_int, MPT_ArgValues("PASS", 1, 2)); +MPT_TestProcess(MPT_ASSERT_NEQ_int, gt, id, proc_MPT_ASSERT_NEQ_int, MPT_ArgValues("PASS", 3, 2)); +MPT_Test(MPT_ASSERT_NEQ_int, eq, .xfail=true); +MPT_Test(MPT_ASSERT_NEQ_int, lt, .xfail=false); +MPT_Test(MPT_ASSERT_NEQ_int, gt, .xfail=false); + + +MPT_ProcessEntry(proc_MPT_ASSERT_NEQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%f, %f), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%f, %f), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_NEQ_double, eq, id, proc_MPT_ASSERT_NEQ_double, MPT_ArgValues("FAIL", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_NEQ_double, lt, id, proc_MPT_ASSERT_NEQ_double, MPT_ArgValues("PASS", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_NEQ_double, gt, id, proc_MPT_ASSERT_NEQ_double, MPT_ArgValues("PASS", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_NEQ_double, eq, .xfail=true); +MPT_Test(MPT_ASSERT_NEQ_double, lt, .xfail=false); +MPT_Test(MPT_ASSERT_NEQ_double, gt, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_LEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_LEQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%d, %d), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%d, %d), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_LEQ_int, eq, id, proc_MPT_ASSERT_LEQ_int, MPT_ArgValues("PASS", 1, 1)); +MPT_TestProcess(MPT_ASSERT_LEQ_int, lt, id, proc_MPT_ASSERT_LEQ_int, MPT_ArgValues("PASS", 1, 2)); +MPT_TestProcess(MPT_ASSERT_LEQ_int, gt, id, proc_MPT_ASSERT_LEQ_int, MPT_ArgValues("FAIL", 3, 2)); +MPT_Test(MPT_ASSERT_LEQ_int, eq, .xfail=false); +MPT_Test(MPT_ASSERT_LEQ_int, lt, .xfail=false); +MPT_Test(MPT_ASSERT_LEQ_int, gt, .xfail=true); + + +MPT_ProcessEntry(proc_MPT_ASSERT_LEQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%f, %f), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%f, %f), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_LEQ_double, eq, id, proc_MPT_ASSERT_LEQ_double, MPT_ArgValues("PASS", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_LEQ_double, lt, id, proc_MPT_ASSERT_LEQ_double, MPT_ArgValues("PASS", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_LEQ_double, gt, id, proc_MPT_ASSERT_LEQ_double, MPT_ArgValues("FAIL", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_LEQ_double, eq, .xfail=false); +MPT_Test(MPT_ASSERT_LEQ_double, lt, .xfail=false); +MPT_Test(MPT_ASSERT_LEQ_double, gt, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_GEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_GEQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%d, %d), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%d, %d), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_GEQ_int, eq, id, proc_MPT_ASSERT_GEQ_int, MPT_ArgValues("PASS", 1, 1)); +MPT_TestProcess(MPT_ASSERT_GEQ_int, lt, id, proc_MPT_ASSERT_GEQ_int, MPT_ArgValues("FAIL", 1, 2)); +MPT_TestProcess(MPT_ASSERT_GEQ_int, gt, id, proc_MPT_ASSERT_GEQ_int, MPT_ArgValues("PASS", 3, 2)); +MPT_Test(MPT_ASSERT_GEQ_int, eq, .xfail=false); +MPT_Test(MPT_ASSERT_GEQ_int, lt, .xfail=true); +MPT_Test(MPT_ASSERT_GEQ_int, gt, .xfail=false); + + +MPT_ProcessEntry(proc_MPT_ASSERT_GEQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%f, %f), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%f, %f), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_GEQ_double, eq, id, proc_MPT_ASSERT_GEQ_double, MPT_ArgValues("PASS", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_GEQ_double, lt, id, proc_MPT_ASSERT_GEQ_double, MPT_ArgValues("FAIL", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_GEQ_double, gt, id, proc_MPT_ASSERT_GEQ_double, MPT_ArgValues("PASS", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_GEQ_double, eq, .xfail=false); +MPT_Test(MPT_ASSERT_GEQ_double, lt, .xfail=true); +MPT_Test(MPT_ASSERT_GEQ_double, gt, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_LT + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_LT_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%d, %d), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%d, %d), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_LT_int, eq, id, proc_MPT_ASSERT_LT_int, MPT_ArgValues("FAIL", 1, 1)); +MPT_TestProcess(MPT_ASSERT_LT_int, lt, id, proc_MPT_ASSERT_LT_int, MPT_ArgValues("PASS", 1, 2)); +MPT_TestProcess(MPT_ASSERT_LT_int, gt, id, proc_MPT_ASSERT_LT_int, MPT_ArgValues("FAIL", 3, 2)); +MPT_Test(MPT_ASSERT_LT_int, eq, .xfail=true); +MPT_Test(MPT_ASSERT_LT_int, lt, .xfail=false); +MPT_Test(MPT_ASSERT_LT_int, gt, .xfail=true); + + +MPT_ProcessEntry(proc_MPT_ASSERT_LT_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%f, %f), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%f, %f), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_LT_double, eq, id, proc_MPT_ASSERT_LT_double, MPT_ArgValues("FAIL", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_LT_double, lt, id, proc_MPT_ASSERT_LT_double, MPT_ArgValues("PASS", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_LT_double, gt, id, proc_MPT_ASSERT_LT_double, MPT_ArgValues("FAIL", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_LT_double, eq, .xfail=true); +MPT_Test(MPT_ASSERT_LT_double, lt, .xfail=false); +MPT_Test(MPT_ASSERT_LT_double, gt, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_GT + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_GT_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%d, %d), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%d, %d), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_GT_int, eq, id, proc_MPT_ASSERT_GT_int, MPT_ArgValues("FAIL", 1, 1)); +MPT_TestProcess(MPT_ASSERT_GT_int, lt, id, proc_MPT_ASSERT_GT_int, MPT_ArgValues("FAIL", 1, 2)); +MPT_TestProcess(MPT_ASSERT_GT_int, gt, id, proc_MPT_ASSERT_GT_int, MPT_ArgValues("PASS", 3, 2)); +MPT_Test(MPT_ASSERT_GT_int, eq, .xfail=true); +MPT_Test(MPT_ASSERT_GT_int, lt, .xfail=true); +MPT_Test(MPT_ASSERT_GT_int, gt, .xfail=false); + + +MPT_ProcessEntry(proc_MPT_ASSERT_GT_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%f, %f), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%f, %f), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_GT_double, eq, id, proc_MPT_ASSERT_GT_double, MPT_ArgValues("FAIL", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_GT_double, lt, id, proc_MPT_ASSERT_GT_double, MPT_ArgValues("FAIL", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_GT_double, gt, id, proc_MPT_ASSERT_GT_double, MPT_ArgValues("PASS", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_GT_double, eq, .xfail=true); +MPT_Test(MPT_ASSERT_GT_double, lt, .xfail=true); +MPT_Test(MPT_ASSERT_GT_double, gt, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_NULL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_NULL, MPT_Args(const char *exp, const void* ptr)) +{ + assert(exp); + MPT_ASSERT_NULL(ptr, "MPT_ASSERT_NULL(%p), expect: %s", ptr, exp); +} +MPT_TestProcess(MPT_ASSERT_NULL, addr, id, proc_MPT_ASSERT_NULL, MPT_ArgValues("FAIL", &dummy)); +MPT_TestProcess(MPT_ASSERT_NULL, null, id, proc_MPT_ASSERT_NULL, MPT_ArgValues("PASS", NULL)); +MPT_Test(MPT_ASSERT_NULL, addr, .xfail=true); +MPT_Test(MPT_ASSERT_NULL, null, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_NOT_NULL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_NOT_NULL, MPT_Args(const char *exp, const void* ptr)) +{ + assert(exp); + MPT_ASSERT_NOT_NULL(ptr, "MPT_ASSERT_NOT_NULL(%p), expect: %s", ptr, exp); +} +MPT_TestProcess(MPT_ASSERT_NOT_NULL, addr, id, proc_MPT_ASSERT_NOT_NULL, MPT_ArgValues("PASS", &dummy)); +MPT_TestProcess(MPT_ASSERT_NOT_NULL, null, id, proc_MPT_ASSERT_NOT_NULL, MPT_ArgValues("FAIL", NULL)); +MPT_Test(MPT_ASSERT_NOT_NULL, addr, .xfail=false); +MPT_Test(MPT_ASSERT_NOT_NULL, null, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_STR_EQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_STR_EQ, MPT_Args(const char *exp, const char* val1, const char* val2)) +{ + assert(exp); + MPT_ASSERT_STR_EQ(val1, val2, "MPT_ASSERT_STR_EQ(%s, %s), expect: %s", + val1 ? val1 : "", + val2 ? val2 : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_STR_EQ, eq, id, proc_MPT_ASSERT_STR_EQ, MPT_ArgValues("PASS", "foo", "foo")); +MPT_TestProcess(MPT_ASSERT_STR_EQ, neq, id, proc_MPT_ASSERT_STR_EQ, MPT_ArgValues("FAIL", "foo", "bar")); +MPT_TestProcess(MPT_ASSERT_STR_EQ, null1, id, proc_MPT_ASSERT_STR_EQ, MPT_ArgValues("FAIL", NULL, "foo")); +MPT_TestProcess(MPT_ASSERT_STR_EQ, null2, id, proc_MPT_ASSERT_STR_EQ, MPT_ArgValues("FAIL", "foo", NULL)); +MPT_Test(MPT_ASSERT_STR_EQ, eq, .xfail=false); +MPT_Test(MPT_ASSERT_STR_EQ, neq, .xfail=true); +MPT_Test(MPT_ASSERT_STR_EQ, null1, .xfail=true); +MPT_Test(MPT_ASSERT_STR_EQ, null2, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_STR_NEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_STR_NEQ, MPT_Args(const char *exp, const char* val1, const char* val2)) +{ + assert(exp); + MPT_ASSERT_STR_NEQ(val1, val2, "MPT_ASSERT_STR_NEQ(%s, %s), expect: %s", + val1 ? val1 : "", + val2 ? val2 : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_STR_NEQ, eq, id, proc_MPT_ASSERT_STR_NEQ, MPT_ArgValues("FAIL", "foo", "foo")); +MPT_TestProcess(MPT_ASSERT_STR_NEQ, neq, id, proc_MPT_ASSERT_STR_NEQ, MPT_ArgValues("PASS", "foo", "bar")); +MPT_TestProcess(MPT_ASSERT_STR_NEQ, null1, id, proc_MPT_ASSERT_STR_NEQ, MPT_ArgValues("FAIL", NULL, "foo")); +MPT_TestProcess(MPT_ASSERT_STR_NEQ, null2, id, proc_MPT_ASSERT_STR_NEQ, MPT_ArgValues("FAIL", "foo", NULL)); +MPT_Test(MPT_ASSERT_STR_NEQ, eq, .xfail=true); +MPT_Test(MPT_ASSERT_STR_NEQ, neq, .xfail=false); +MPT_Test(MPT_ASSERT_STR_NEQ, null1, .xfail=true); +MPT_Test(MPT_ASSERT_STR_NEQ, null2, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_STR_EMPTY + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_STR_EMPTY, MPT_Args(const char *exp, const char* val)) +{ + assert(exp); + MPT_ASSERT_STR_EMPTY(val, "MPT_ASSERT_STR_EMPTY(%s), expect: %s", + val ? val : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_STR_EMPTY, nempty, id, proc_MPT_ASSERT_STR_EMPTY, MPT_ArgValues("FAIL", "foo")); +MPT_TestProcess(MPT_ASSERT_STR_EMPTY, empty, id, proc_MPT_ASSERT_STR_EMPTY, MPT_ArgValues("PASS", "")); +MPT_TestProcess(MPT_ASSERT_STR_EMPTY, null, id, proc_MPT_ASSERT_STR_EMPTY, MPT_ArgValues("FAIL", NULL)); +MPT_Test(MPT_ASSERT_STR_EMPTY, nempty, .xfail=true); +MPT_Test(MPT_ASSERT_STR_EMPTY, empty, .xfail=false); +MPT_Test(MPT_ASSERT_STR_EMPTY, null, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_STR_NOT_EMPTY + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_STR_NOT_EMPTY, MPT_Args(const char *exp, const char* val)) +{ + assert(exp); + MPT_ASSERT_STR_NOT_EMPTY(val, "MPT_ASSERT_STR_NOT_EMPTY(%s), expect: %s", + val ? val : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_STR_NOT_EMPTY, nempty, id, proc_MPT_ASSERT_STR_NOT_EMPTY, MPT_ArgValues("PASS", "foo")); +MPT_TestProcess(MPT_ASSERT_STR_NOT_EMPTY, empty, id, proc_MPT_ASSERT_STR_NOT_EMPTY, MPT_ArgValues("FAIL", "")); +MPT_TestProcess(MPT_ASSERT_STR_NOT_EMPTY, null, id, proc_MPT_ASSERT_STR_NOT_EMPTY, MPT_ArgValues("FAIL", NULL)); +MPT_Test(MPT_ASSERT_STR_NOT_EMPTY, nempty, .xfail=false); +MPT_Test(MPT_ASSERT_STR_NOT_EMPTY, empty, .xfail=true); +MPT_Test(MPT_ASSERT_STR_NOT_EMPTY, null, .xfail=true); + + + +/*****************************************************************************/ + + + +/************************************************************ + * Test MPT_ASSERT_FATAL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL, MPT_Args(const char *exp, int cond)) +{ + assert(exp); + MPT_ASSERT_FATAL(cond, "MPT_ASSERT_FATAL(%d), expect: %s", cond, exp); + MPT_ASSERT(cond, "MPT_ASSERT(%d) after a fatal", cond); +} + +MPT_TestProcess(MPT_ASSERT_FATAL, pass, id, proc_MPT_ASSERT_FATAL, MPT_ArgValues("PASS", 1)); +MPT_Test(MPT_ASSERT_FATAL, pass, .xfail=false); + +MPT_TestProcess(MPT_ASSERT_FATAL, fail, id, proc_MPT_ASSERT_FATAL, MPT_ArgValues("FAIL", 0)); +MPT_Test(MPT_ASSERT_FATAL, fail, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_FAIL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_FAIL, MPT_NoArgs()) +{ + MPT_ASSERT_FATAL_FAIL("MPT_ASSERT_FATAL_FAIL(), expect a fail, always"); + MPT_ASSERT_FAIL("MPT_ASSERT_FAIL() after a fatal"); +} + +MPT_TestProcess(MPT_ASSERT_FATAL_FAIL, fail, id, proc_MPT_ASSERT_FATAL_FAIL, MPT_NoArgValues()); +MPT_Test(MPT_ASSERT_FATAL_FAIL, fail, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_EQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_EQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_EQ(val1, val2, "MPT_ASSERT_FATAL_EQ(%d, %d), expect: %s", val1, val2, exp); + MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%d, %d) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_EQ_int, eq, id, proc_MPT_ASSERT_FATAL_EQ_int, MPT_ArgValues("PASS", 1, 1)); +MPT_TestProcess(MPT_ASSERT_FATAL_EQ_int, lt, id, proc_MPT_ASSERT_FATAL_EQ_int, MPT_ArgValues("FAIL", 1, 2)); +MPT_TestProcess(MPT_ASSERT_FATAL_EQ_int, gt, id, proc_MPT_ASSERT_FATAL_EQ_int, MPT_ArgValues("FAIL", 3, 2)); +MPT_Test(MPT_ASSERT_FATAL_EQ_int, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_EQ_int, lt, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_EQ_int, gt, .xfail=true); + + +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_EQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_EQ(val1, val2, "MPT_ASSERT_FATAL_EQ(%f, %f), expect: %s", val1, val2, exp); + MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%f, %f) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_EQ_double, eq, id, proc_MPT_ASSERT_FATAL_EQ_double, MPT_ArgValues("PASS", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_FATAL_EQ_double, lt, id, proc_MPT_ASSERT_FATAL_EQ_double, MPT_ArgValues("FAIL", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_FATAL_EQ_double, gt, id, proc_MPT_ASSERT_FATAL_EQ_double, MPT_ArgValues("FAIL", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_FATAL_EQ_double, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_EQ_double, lt, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_EQ_double, gt, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_NEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_NEQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_NEQ(val1, val2, "MPT_ASSERT_FATAL_NEQ(%d, %d), expect: %s", val1, val2, exp); + MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%d, %d) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_int, eq, id, proc_MPT_ASSERT_FATAL_NEQ_int, MPT_ArgValues("FAIL", 1, 1)); +MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_int, lt, id, proc_MPT_ASSERT_FATAL_NEQ_int, MPT_ArgValues("PASS", 1, 2)); +MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_int, gt, id, proc_MPT_ASSERT_FATAL_NEQ_int, MPT_ArgValues("PASS", 3, 2)); +MPT_Test(MPT_ASSERT_FATAL_NEQ_int, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_NEQ_int, lt, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_NEQ_int, gt, .xfail=false); + + +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_NEQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_NEQ(val1, val2, "MPT_ASSERT_FATAL_NEQ(%f, %f), expect: %s", val1, val2, exp); + MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%f, %f) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_double, eq, id, proc_MPT_ASSERT_FATAL_NEQ_double, MPT_ArgValues("FAIL", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_double, lt, id, proc_MPT_ASSERT_FATAL_NEQ_double, MPT_ArgValues("PASS", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_double, gt, id, proc_MPT_ASSERT_FATAL_NEQ_double, MPT_ArgValues("PASS", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_FATAL_NEQ_double, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_NEQ_double, lt, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_NEQ_double, gt, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_LEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_LEQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_LEQ(val1, val2, "MPT_ASSERT_FATAL_LEQ(%d, %d), expect: %s", val1, val2, exp); + MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%d, %d) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_int, eq, id, proc_MPT_ASSERT_FATAL_LEQ_int, MPT_ArgValues("PASS", 1, 1)); +MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_int, lt, id, proc_MPT_ASSERT_FATAL_LEQ_int, MPT_ArgValues("PASS", 1, 2)); +MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_int, gt, id, proc_MPT_ASSERT_FATAL_LEQ_int, MPT_ArgValues("FAIL", 3, 2)); +MPT_Test(MPT_ASSERT_FATAL_LEQ_int, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_LEQ_int, lt, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_LEQ_int, gt, .xfail=true); + + +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_LEQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_LEQ(val1, val2, "MPT_ASSERT_FATAL_LEQ(%f, %f), expect: %s", val1, val2, exp); + MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%f, %f) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_double, eq, id, proc_MPT_ASSERT_FATAL_LEQ_double, MPT_ArgValues("PASS", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_double, lt, id, proc_MPT_ASSERT_FATAL_LEQ_double, MPT_ArgValues("PASS", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_double, gt, id, proc_MPT_ASSERT_FATAL_LEQ_double, MPT_ArgValues("FAIL", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_FATAL_LEQ_double, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_LEQ_double, lt, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_LEQ_double, gt, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_GEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_GEQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_GEQ(val1, val2, "MPT_ASSERT_FATAL_GEQ(%d, %d), expect: %s", val1, val2, exp); + MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%d, %d) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_int, eq, id, proc_MPT_ASSERT_FATAL_GEQ_int, MPT_ArgValues("PASS", 1, 1)); +MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_int, lt, id, proc_MPT_ASSERT_FATAL_GEQ_int, MPT_ArgValues("FAIL", 1, 2)); +MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_int, gt, id, proc_MPT_ASSERT_FATAL_GEQ_int, MPT_ArgValues("PASS", 3, 2)); +MPT_Test(MPT_ASSERT_FATAL_GEQ_int, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_GEQ_int, lt, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_GEQ_int, gt, .xfail=false); + + +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_GEQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_GEQ(val1, val2, "MPT_ASSERT_FATAL_GEQ(%f, %f), expect: %s", val1, val2, exp); + MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%f, %f) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_double, eq, id, proc_MPT_ASSERT_FATAL_GEQ_double, MPT_ArgValues("PASS", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_double, lt, id, proc_MPT_ASSERT_FATAL_GEQ_double, MPT_ArgValues("FAIL", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_double, gt, id, proc_MPT_ASSERT_FATAL_GEQ_double, MPT_ArgValues("PASS", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_FATAL_GEQ_double, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_GEQ_double, lt, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_GEQ_double, gt, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_LT + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_LT_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_LT(val1, val2, "MPT_ASSERT_FATAL_LT(%d, %d), expect: %s", val1, val2, exp); + MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%d, %d) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_LT_int, eq, id, proc_MPT_ASSERT_FATAL_LT_int, MPT_ArgValues("FAIL", 1, 1)); +MPT_TestProcess(MPT_ASSERT_FATAL_LT_int, lt, id, proc_MPT_ASSERT_FATAL_LT_int, MPT_ArgValues("PASS", 1, 2)); +MPT_TestProcess(MPT_ASSERT_FATAL_LT_int, gt, id, proc_MPT_ASSERT_FATAL_LT_int, MPT_ArgValues("FAIL", 3, 2)); +MPT_Test(MPT_ASSERT_FATAL_LT_int, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_LT_int, lt, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_LT_int, gt, .xfail=true); + + +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_LT_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_LT(val1, val2, "MPT_ASSERT_FATAL_LT(%f, %f), expect: %s", val1, val2, exp); + MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%f, %f) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_LT_double, eq, id, proc_MPT_ASSERT_FATAL_LT_double, MPT_ArgValues("FAIL", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_FATAL_LT_double, lt, id, proc_MPT_ASSERT_FATAL_LT_double, MPT_ArgValues("PASS", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_FATAL_LT_double, gt, id, proc_MPT_ASSERT_FATAL_LT_double, MPT_ArgValues("FAIL", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_FATAL_LT_double, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_LT_double, lt, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_LT_double, gt, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_GT + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_GT_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_GT(val1, val2, "MPT_ASSERT_FATAL_GT(%d, %d), expect: %s", val1, val2, exp); + MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%d, %d) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_GT_int, eq, id, proc_MPT_ASSERT_FATAL_GT_int, MPT_ArgValues("FAIL", 1, 1)); +MPT_TestProcess(MPT_ASSERT_FATAL_GT_int, lt, id, proc_MPT_ASSERT_FATAL_GT_int, MPT_ArgValues("FAIL", 1, 2)); +MPT_TestProcess(MPT_ASSERT_FATAL_GT_int, gt, id, proc_MPT_ASSERT_FATAL_GT_int, MPT_ArgValues("PASS", 3, 2)); +MPT_Test(MPT_ASSERT_FATAL_GT_int, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_GT_int, lt, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_GT_int, gt, .xfail=false); + + +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_GT_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_GT(val1, val2, "MPT_ASSERT_FATAL_GT(%f, %f), expect: %s", val1, val2, exp); + MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%f, %f) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_GT_double, eq, id, proc_MPT_ASSERT_FATAL_GT_double, MPT_ArgValues("FAIL", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_FATAL_GT_double, lt, id, proc_MPT_ASSERT_FATAL_GT_double, MPT_ArgValues("FAIL", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_FATAL_GT_double, gt, id, proc_MPT_ASSERT_FATAL_GT_double, MPT_ArgValues("PASS", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_FATAL_GT_double, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_GT_double, lt, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_GT_double, gt, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_NULL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_NULL, MPT_Args(const char *exp, const void* ptr)) +{ + assert(exp); + MPT_ASSERT_FATAL_NULL(ptr, "MPT_ASSERT_FATAL_NULL(%p), expect: %s", ptr, exp); +} +MPT_TestProcess(MPT_ASSERT_FATAL_NULL, addr, id, proc_MPT_ASSERT_FATAL_NULL, MPT_ArgValues("FAIL", &dummy)); +MPT_TestProcess(MPT_ASSERT_FATAL_NULL, null, id, proc_MPT_ASSERT_FATAL_NULL, MPT_ArgValues("PASS", NULL)); +MPT_Test(MPT_ASSERT_FATAL_NULL, addr, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_NULL, null, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_NOT_NULL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_NOT_NULL, MPT_Args(const char *exp, const void* ptr)) +{ + assert(exp); + MPT_ASSERT_FATAL_NOT_NULL(ptr, "MPT_ASSERT_FATAL_NOT_NULL(%p), expect: %s", ptr, exp); +} +MPT_TestProcess(MPT_ASSERT_FATAL_NOT_NULL, addr, id, proc_MPT_ASSERT_FATAL_NOT_NULL, MPT_ArgValues("PASS", &dummy)); +MPT_TestProcess(MPT_ASSERT_FATAL_NOT_NULL, null, id, proc_MPT_ASSERT_FATAL_NOT_NULL, MPT_ArgValues("FAIL", NULL)); +MPT_Test(MPT_ASSERT_FATAL_NOT_NULL, addr, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_NOT_NULL, null, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_STR_EQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_STR_EQ, MPT_Args(const char *exp, const char* val1, const char* val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_STR_EQ(val1, val2, "MPT_ASSERT_FATAL_STR_EQ(%s, %s), expect: %s", + val1 ? val1 : "", + val2 ? val2 : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EQ, eq, id, proc_MPT_ASSERT_FATAL_STR_EQ, MPT_ArgValues("PASS", "foo", "foo")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EQ, neq, id, proc_MPT_ASSERT_FATAL_STR_EQ, MPT_ArgValues("FAIL", "foo", "bar")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EQ, null1, id, proc_MPT_ASSERT_FATAL_STR_EQ, MPT_ArgValues("FAIL", NULL, "foo")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EQ, null2, id, proc_MPT_ASSERT_FATAL_STR_EQ, MPT_ArgValues("FAIL", "foo", NULL)); +MPT_Test(MPT_ASSERT_FATAL_STR_EQ, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_STR_EQ, neq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_STR_EQ, null1, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_STR_EQ, null2, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_STR_NEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_Args(const char *exp, const char* val1, const char* val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_STR_NEQ(val1, val2, "MPT_ASSERT_FATAL_STR_NEQ(%s, %s), expect: %s", + val1 ? val1 : "", + val2 ? val2 : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NEQ, eq, id, proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_ArgValues("FAIL", "foo", "foo")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NEQ, neq, id, proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_ArgValues("PASS", "foo", "bar")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NEQ, null1, id, proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_ArgValues("FAIL", NULL, "foo")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NEQ, null2, id, proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_ArgValues("FAIL", "foo", NULL)); +MPT_Test(MPT_ASSERT_FATAL_STR_NEQ, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_STR_NEQ, neq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_STR_NEQ, null1, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_STR_NEQ, null2, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_STR_EMPTY + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_STR_EMPTY, MPT_Args(const char *exp, const char* val)) +{ + assert(exp); + MPT_ASSERT_FATAL_STR_EMPTY(val, "MPT_ASSERT_FATAL_STR_EMPTY(%s), expect: %s", + val ? val : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EMPTY, nempty, id, proc_MPT_ASSERT_FATAL_STR_EMPTY, MPT_ArgValues("FAIL", "foo")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EMPTY, empty, id, proc_MPT_ASSERT_FATAL_STR_EMPTY, MPT_ArgValues("PASS", "")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EMPTY, null, id, proc_MPT_ASSERT_FATAL_STR_EMPTY, MPT_ArgValues("FAIL", NULL)); +MPT_Test(MPT_ASSERT_FATAL_STR_EMPTY, nempty, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_STR_EMPTY, empty, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_STR_EMPTY, null, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_STR_NOT_EMPTY + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_STR_NOT_EMPTY, MPT_Args(const char *exp, const char* val)) +{ + assert(exp); + MPT_ASSERT_FATAL_STR_NOT_EMPTY(val, "MPT_ASSERT_FATAL_STR_NOT_EMPTY(%s), expect: %s", + val ? val : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NOT_EMPTY, nempty, id, proc_MPT_ASSERT_FATAL_STR_NOT_EMPTY, MPT_ArgValues("PASS", "foo")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NOT_EMPTY, empty, id, proc_MPT_ASSERT_FATAL_STR_NOT_EMPTY, MPT_ArgValues("FAIL", "")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NOT_EMPTY, null, id, proc_MPT_ASSERT_FATAL_STR_NOT_EMPTY, MPT_ArgValues("FAIL", NULL)); +MPT_Test(MPT_ASSERT_FATAL_STR_NOT_EMPTY, nempty, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_STR_NOT_EMPTY, empty, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_STR_NOT_EMPTY, null, .xfail=true); + + + +/*****************************************************************************/ + + + +/************************************************************ + * Test propagation, + * Check if failure/success is actually propagated to ctest. + ************************************************************/ +MPT_ProcessEntry(proc_propagation, MPT_Args(const char *exp, int cond, dds_duration_t delay)) +{ + assert(exp); + if (delay > 0) { + dds_sleepfor(delay); + } + MPT_ASSERT(cond, "MPT_ASSERT(%d), expect: %s", cond, exp); +} +/* This should pass in the ctest results. */ +MPT_TestProcess(propagation, pass, id1, proc_propagation, MPT_ArgValues("PASS", 1, 0)); +MPT_TestProcess(propagation, pass, id2, proc_propagation, MPT_ArgValues("PASS", 1, 0)); +MPT_Test(propagation, pass); +/* This should fail in the ctest results. */ +MPT_TestProcess(propagation, fail_1st, id1, proc_propagation, MPT_ArgValues("FAIL", 0, 0)); +MPT_TestProcess(propagation, fail_1st, id2, proc_propagation, MPT_ArgValues("PASS", 1, DDS_SECS(1))); +MPT_Test(propagation, fail_1st); +/* This should fail in the ctest results. */ +MPT_TestProcess(propagation, fail_2nd, id1, proc_propagation, MPT_ArgValues("PASS", 1, 0)); +MPT_TestProcess(propagation, fail_2nd, id2, proc_propagation, MPT_ArgValues("FAIL", 0, DDS_SECS(1))); +MPT_Test(propagation, fail_2nd); + diff --git a/src/mpt/tests/self/environments.c b/src/mpt/tests/self/environments.c new file mode 100644 index 0000000..9b6dc97 --- /dev/null +++ b/src/mpt/tests/self/environments.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include "mpt/mpt.h" +#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */ +#include "dds/ddsrt/environ.h" + + + +/************************************************************ + * Process + ************************************************************/ +MPT_ProcessEntry(proc_environments, MPT_Args(mpt_env_t *exp)) +{ + assert(exp); + while ((exp->name != NULL) && (exp->value != NULL)) { + /* The environment variable value should match the expected value. */ + char *ptr = NULL; + ddsrt_getenv(exp->name, &ptr); + if (ptr) { + MPT_ASSERT((strcmp(exp->value, ptr) == 0), "%s: found \"%s\", expected \"%s\"", exp->name, ptr, exp->value); + } else { + MPT_ASSERT(0, "Expected \"%s\" not found in environment", exp->name); + } + exp++; + } +} + + + +/************************************************************ + * Basic environment tests + ************************************************************/ +static mpt_env_t environ_basic[] = { + { "MY_ENV_VAR1", "1" }, + { "MY_ENV_VAR2", "2" }, + { NULL, NULL } +}; + +MPT_TestProcess(environment, proc, id, proc_environments, MPT_ArgValues(environ_basic), .environment=environ_basic); +MPT_Test(environment, proc); + +MPT_TestProcess(environment, test, id, proc_environments, MPT_ArgValues(environ_basic)); +MPT_Test(environment, test, .environment=environ_basic); + + + +/************************************************************ + * Expanding variables environment tests + ************************************************************/ +static mpt_env_t environ_expand[] = { + { "1", "b" }, + { "2", "${1}l" }, + { "3", "${2}aat" }, + { "4", "bla${1}${2}a${3}" }, + { NULL, NULL } +}; +static mpt_env_t expect_expand[] = { + { "1", "b" }, + { "2", "bl" }, + { "3", "blaat" }, + { "4", "blabblablaat" }, + { NULL, NULL } +}; + +MPT_TestProcess(environment, expand_proc, id, proc_environments, MPT_ArgValues(expect_expand), .environment=environ_expand); +MPT_Test(environment, expand_proc); + +MPT_TestProcess(environment, expand_test, id, proc_environments, MPT_ArgValues(expect_expand)); +MPT_Test(environment, expand_test, .environment=environ_expand); + + + +/************************************************************ + * Environment inheritance test + ************************************************************/ +static mpt_env_t environ_test[] = { + { "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/self/etc" }, + { "OVERRULE", "NO" }, + { NULL, NULL } +}; +static mpt_env_t environ_proc[] = { + { "CYCLONE_URI", "file://${ETC_DIR}/ospl.xml" }, + { "OVERRULE", "YES" }, + { "EXTRA", "proc" }, + { NULL, NULL } +}; +static mpt_env_t environ_test_proc[] = { + { "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/self/etc" }, + { "CYCLONE_URI", "file://"MPT_SOURCE_ROOT_DIR"/tests/self/etc/ospl.xml" }, + { "OVERRULE", "YES" }, + { "EXTRA", "proc" }, + { NULL, NULL } +}; +MPT_TestProcess(environment, inheritance, id, proc_environments, MPT_ArgValues(environ_test_proc), .environment=environ_proc); +MPT_Test(environment, inheritance, .environment=environ_test); diff --git a/src/mpt/tests/self/etc/file b/src/mpt/tests/self/etc/file new file mode 100644 index 0000000..e69de29 diff --git a/src/mpt/tests/self/fixtures.c b/src/mpt/tests/self/fixtures.c new file mode 100644 index 0000000..25b5782 --- /dev/null +++ b/src/mpt/tests/self/fixtures.c @@ -0,0 +1,72 @@ +#include +#include "mpt/mpt.h" +#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */ +#include "dds/ddsrt/time.h" + + + +/************************************************************ + * Support functions + ************************************************************/ +static int g_initcnt = 0; +static void init_inc(void) +{ + g_initcnt++; +}; + + + +/************************************************************ + * Processes + ************************************************************/ +MPT_ProcessEntry(proc_initcnt, MPT_Args(int init)) +{ + MPT_ASSERT((g_initcnt == init), "init count: %d vs %d", g_initcnt, init); +} + +MPT_ProcessEntry(proc_sleep, MPT_Args(dds_duration_t delay)) +{ + MPT_ASSERT((delay > 0), "basically just to satisfy the compiler"); + dds_sleepfor(delay); +} + + + +/************************************************************ + * Init fixture tests + ************************************************************/ +MPT_TestProcess(init, none, id, proc_initcnt, MPT_ArgValues(0)); +MPT_Test(init, none); + +MPT_TestProcess(init, null, id, proc_initcnt, MPT_ArgValues(0), .init=NULL); +MPT_Test(init, null, .init=NULL); + +MPT_TestProcess(init, proc, id, proc_initcnt, MPT_ArgValues(1), .init=init_inc); +MPT_Test(init, proc); + +MPT_TestProcess(init, test, id, proc_initcnt, MPT_ArgValues(1)); +MPT_Test(init, test, .init=init_inc); + +MPT_TestProcess(init, test_proc, id, proc_initcnt, MPT_ArgValues(2), .init=init_inc); +MPT_Test(init, test_proc, .init=init_inc); + + + +/************************************************************ + * Disable fixture tests + ************************************************************/ +MPT_TestProcess(disabled, _true, id, proc_initcnt, MPT_ArgValues(0)); +MPT_Test(disabled, _true, .disabled=true); + +MPT_TestProcess(disabled, _false, id, proc_initcnt, MPT_ArgValues(0)); +MPT_Test(disabled, _false, .disabled=false); + + + +/************************************************************ + * Timeout fixture tests + ************************************************************/ +/* See if a child process is killed when the parent is killed. + * This can only really be done manually, unfortunately. */ +MPT_TestProcess(timeout, child_culling, id, proc_sleep, MPT_ArgValues(DDS_SECS(120))); +MPT_Test(timeout, child_culling, .timeout=1); diff --git a/src/mpt/tests/self/ipc.c b/src/mpt/tests/self/ipc.c new file mode 100644 index 0000000..932c6e6 --- /dev/null +++ b/src/mpt/tests/self/ipc.c @@ -0,0 +1,29 @@ +#include +#include "mpt/mpt.h" + + + +/************************************************************ + * Processes + ************************************************************/ +MPT_ProcessEntry(proc_ipc_send, MPT_NoArgs()) +{ + /* This will fail and cause an internal MPT assert as long + * as IPC is not yet implemented. */ + MPT_Send("todo: implement"); +} +MPT_ProcessEntry(proc_ipc_wait, MPT_NoArgs()) +{ + /* This will fail and cause an internal MPT assert as long + * as IPC is not yet implemented. */ + MPT_Wait("todo: implement"); +} + + + +/************************************************************ + * Tests + ************************************************************/ +MPT_TestProcess(ipc, TODO, id1, proc_ipc_send, MPT_NoArgValues()); +MPT_TestProcess(ipc, TODO, id2, proc_ipc_wait, MPT_NoArgValues()); +MPT_Test(ipc, TODO); diff --git a/src/mpt/tests/self/resources.c b/src/mpt/tests/self/resources.c new file mode 100644 index 0000000..9cba731 --- /dev/null +++ b/src/mpt/tests/self/resources.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include "mpt/mpt.h" +#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */ + +/************************************************************ + * Processes + ************************************************************/ +MPT_ProcessEntry(proc_file, MPT_NoArgs()) +{ + const char *test_file = MPT_SOURCE_ROOT_DIR"/tests/self/etc/file"; +#if _WIN32 + struct _stat buffer; + int ret = _stat(test_file,&buffer); +#else + struct stat buffer; + int ret = stat(test_file,&buffer); +#endif + MPT_ASSERT((ret == 0), "%s", test_file); +} + + + +/************************************************************ + * Test if MPT_SOURCE_ROOT_DIR is a valid location. + ************************************************************/ +MPT_TestProcess(resources, root_dir, id, proc_file, MPT_NoArgValues()); +MPT_Test(resources, root_dir); + diff --git a/src/mpt/tests/self/usage.c b/src/mpt/tests/self/usage.c new file mode 100644 index 0000000..1621810 --- /dev/null +++ b/src/mpt/tests/self/usage.c @@ -0,0 +1,186 @@ +#include +#include "mpt/mpt.h" +#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */ + + +/****************************************************************************** + * First, we need a process entry-point that can be used in tests. + *****************************************************************************/ +/* | name | arguments | */ +MPT_ProcessEntry(proc_noargs, MPT_NoArgs()) +{ + // Do stuff + + // The test processes will use asserts to indicate success/failures. + MPT_ASSERT(1, "The problem is: %s", "existential crisis"); + + // No need to return anything, that's handled by the assert calls. +} + +/****************************************************************************** + * A process entry-point can have arguments. + *****************************************************************************/ +/* | name | arguments | */ +MPT_ProcessEntry(proc_args, MPT_Args(int domain, const char* text)) +{ + int expected = 1; + MPT_ASSERT(expected == domain, "proc_args(%d, %s)", domain, text); +} + +/****************************************************************************** + * Process entry-points can communicate to be able to sync fi. + *****************************************************************************/ +MPT_ProcessEntry(proc_recv, MPT_NoArgs()) +{ + /* This will wait until another process sends the same string. */ + MPT_Wait("some state reached"); +} +MPT_ProcessEntry(proc_send, MPT_NoArgs()) +{ + /* If this fails, an internal MPT_ASSERT will be triggered. + * The same is true for MPT_Wait(). */ + MPT_Send("some state reached"); +} + + + +/****************************************************************************** + * Test: suitename_testA + ****************************************************************************** + * A simple test that starts two processes. Because a test can use the same + * process entry-point to start multiple processes, each process has to have + * its own unique id within the test. + */ +/* | process identification | entry-point | arguments | */ +MPT_TestProcess(suitename, testA, id1, proc_noargs, MPT_NoArgValues()); +MPT_TestProcess(suitename, testA, id2, proc_noargs, MPT_NoArgValues()); +MPT_Test(suitename, testA); + + + + +/****************************************************************************** + * Test: suitename_testB + ****************************************************************************** + * Of course, different processes can be started as well. + * Argument values are provided per test process. + */ +MPT_TestProcess(suitename, testB, id1, proc_noargs, MPT_NoArgValues( )); +MPT_TestProcess(suitename, testB, id2, proc_args, MPT_ArgValues(1, "2")); +MPT_TestProcess(suitename, testB, id3, proc_args, MPT_ArgValues(1, "3")); +MPT_Test(suitename, testB); + + + + +/****************************************************************************** + * Test: suitename_testC + ****************************************************************************** + * The processes can have different or equal 'system environments'. + */ +mpt_env_t environment_C1[] = { + { "CYCLONEDDS_URI", "file://config1.xml" }, + { "PERMISSIONS", "file://permissions.p7s" }, + { "GOVERNANCE", "file://governance.p7s" }, + { NULL, NULL } +}; +mpt_env_t environment_C2[] = { + { "CYCLONEDDS_URI", "file://config2.xml" }, + { "PERMISSIONS", "file://permissions.p7s" }, + { "GOVERNANCE", "file://governance.p7s" }, + { NULL, NULL } +}; +MPT_TestProcess(suitename, testC, id1, proc_noargs, MPT_NoArgValues(), .environment=environment_C1); +MPT_TestProcess(suitename, testC, id2, proc_noargs, MPT_NoArgValues(), .environment=environment_C1); +MPT_TestProcess(suitename, testC, id3, proc_noargs, MPT_NoArgValues(), .environment=environment_C2); +MPT_Test(suitename, testC); + + + + +/****************************************************************************** + * Test: suitename_testD + ****************************************************************************** + * The two environments in the previous example are partly the same. + * It's possible set the environment on test level. The environment variables + * related to the test are set before the ones related to a process. This + * means that a process can overrule variables. + * + * The following test is the same as the previous one. + */ +mpt_env_t environment_D1[] = { + { "CYCLONEDDS_URI", "file://config1.xml" }, + { "PERMISSIONS", "file://permissions.p7s" }, + { "GOVERNANCE", "file://governance.p7s" }, + { NULL, NULL } +}; +mpt_env_t environment_D2[] = { + { "CYCLONEDDS_URI", "file://config2.xml" }, + { NULL, NULL } +}; +MPT_TestProcess(suitename, testD, id1, proc_noargs, MPT_NoArgValues()); +MPT_TestProcess(suitename, testD, id2, proc_noargs, MPT_NoArgValues()); +MPT_TestProcess(suitename, testD, id3, proc_noargs, MPT_NoArgValues(), .environment=environment_D2); +MPT_Test(suitename, testD, .environment=environment_D1); + + + + +/****************************************************************************** + * Test: suitename_testE + ****************************************************************************** + * Environment variables will be expanded. + * Also, the MPT_SOURCE_ROOT_DIR define contains a string to that particular + * directory. + * This can be combined to easily point to files. + */ +mpt_env_t environment_E[] = { + { "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/self/etc" }, + { "CYCLONEDDS_URI", "file://${ETC_DIR}/config.xml" }, + { NULL, NULL } +}; +MPT_TestProcess(suitename, testE, id, proc_noargs, MPT_NoArgValues(), .environment=environment_E); +MPT_Test(suitename, testE); + + + + +/****************************************************************************** + * Test: suitename_testF + ****************************************************************************** + * The processes and tests can use init/fini fixtures. + * The test init is executed before the process init. + * The process fini is executed before the test fini. + */ +void proc_setup(void) { /* do stuff */ } +void proc_teardown(void) { /* do stuff */ } +void test_setup(void) { /* do stuff */ } +void test_teardown(void) { /* do stuff */ } +MPT_TestProcess(suitename, testF, id1, proc_noargs, MPT_NoArgValues(), .init=proc_setup); +MPT_TestProcess(suitename, testF, id2, proc_noargs, MPT_NoArgValues(), .fini=proc_teardown); +MPT_TestProcess(suitename, testF, id3, proc_noargs, MPT_NoArgValues(), .init=proc_setup, .fini=proc_teardown); +MPT_Test(suitename, testF, .init=test_setup, .fini=test_teardown); + + + + +/****************************************************************************** + * Test: suitename_testG + ****************************************************************************** + * The timeout and disable options are handled by test fixtures. + */ +MPT_TestProcess(suitename, testG, id1, proc_noargs, MPT_NoArgValues()); +MPT_TestProcess(suitename, testG, id2, proc_noargs, MPT_NoArgValues()); +MPT_Test(suitename, testG, .timeout=10, .disabled=true); + + + + +/****************************************************************************** + * Test: suitename_testH + ****************************************************************************** + * See the process entries to notice the MPT Send/Wait IPC. + */ +MPT_TestProcess(suitename, testH, id1, proc_recv, MPT_NoArgValues()); +MPT_TestProcess(suitename, testH, id2, proc_send, MPT_NoArgValues()); +MPT_Test(suitename, testH); From 973ae87e1786e35ae781640b82b4e2bebe05514f Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Thu, 11 Apr 2019 14:10:08 +0200 Subject: [PATCH 044/178] Moved expand_envvars. Signed-off-by: Martin Bremmer --- src/core/ddsi/src/q_config.c | 1 + src/ddsrt/include/dds/ddsrt/environ.h | 44 +++++++++++ src/ddsrt/tests/environ.c | 105 +++++++++++++++++++++++++- src/mpt/mpt/cmake/MPT.cmake | 9 --- src/mpt/mpt/src/main.c.in | 3 +- 5 files changed, 150 insertions(+), 12 deletions(-) diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 5a412e8..bf1781d 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -22,6 +22,7 @@ #include "dds/ddsrt/string.h" #include "dds/ddsrt/strtod.h" #include "dds/ddsrt/misc.h" +#include "dds/ddsrt/environ.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" #include "dds/ddsrt/avl.h" diff --git a/src/ddsrt/include/dds/ddsrt/environ.h b/src/ddsrt/include/dds/ddsrt/environ.h index 48953c2..67a8c29 100644 --- a/src/ddsrt/include/dds/ddsrt/environ.h +++ b/src/ddsrt/include/dds/ddsrt/environ.h @@ -96,6 +96,50 @@ ddsrt_unsetenv( const char *name) ddsrt_nonnull_all; +/** + * @brief Expand environment variables within string. + * + * Expands ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, but not $X. + * + * The result string should be freed with ddsrt_free(). + * + * @param[in] string String to expand. + * + * @returns Allocated char*. + * + * @retval NULL + * Expansion failed. + * @retval Pointer + * Copy of the string argument with the environment + * variables expanded. + */ +DDS_EXPORT char* +ddsrt_expand_envvars( + const char *string); + +/** + * @brief Expand environment variables within string. + * + * Expands $X, ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, $ and \ + * can be escaped with \. + * + * The result string should be freed with ddsrt_free(). + * + * @param[in] string String to expand. + * + * @returns Allocated char*. + * + * @retval NULL + * Expansion failed. + * @retval Pointer + * Copy of the string argument with the environment + * variables expanded. + */ +DDS_EXPORT char* +ddsrt_expand_envvars_sh( + const char *string); + + #if defined(__cplusplus) } #endif diff --git a/src/ddsrt/tests/environ.c b/src/ddsrt/tests/environ.c index 56f7468..b69acf4 100644 --- a/src/ddsrt/tests/environ.c +++ b/src/ddsrt/tests/environ.c @@ -14,6 +14,7 @@ #include "CUnit/Theory.h" #include "dds/ddsrt/environ.h" #include "dds/ddsrt/misc.h" +#include "dds/ddsrt/heap.h" CU_TheoryDataPoints(ddsrt_environ, bad_name) = { CU_DataPoints(const char *, "", "foo=") @@ -91,8 +92,110 @@ CU_Test(ddsrt_environ, getenv) CU_ASSERT_STRING_EQUAL(ptr, "bar"); } - /* Ensure environement is as it was. */ + /* Ensure environment is as it was. */ rc = ddsrt_unsetenv(name); CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); } +CU_TheoryDataPoints(ddsrt_environ, expand) = { + CU_DataPoints(const char *, + "${X}", "$X", "X", "${Y}", "${Q}", "${X", + "${X:-ALT}", "${Q:-ALT}", "${X:-${Y}}", "${Q:-${Y}}", "${X:-$Y}", "${Q:-$Y}", "${X:-}", "${Q:-}", + "${X:+SET}", "${Q:+SET}", "${X:+${Y}}", "${Q:+${Y}}", "${X:+$Y}", "${Q:+$Y}", "${X:+}", "${Q:+}", + "${X:?SET}", "${Q:?SET}", "${X:?${Y}}", "${Q:?${Y}}", "${X:?$Y}", "${Q:?$Y}", "${X:?}", "${Q:?}"), + CU_DataPoints(const char *, + "TEST", "$X", "X", "FOO", "", NULL, + "TEST", "ALT", "TEST", "FOO", "TEST", "$Y", "TEST", "", + "SET", "", "FOO", "", "$Y", "", "", "", + "TEST", NULL, "TEST", NULL, "TEST", NULL, "TEST", NULL) +}; +CU_Theory((const char *var, const char *expect), ddsrt_environ, expand) +{ + dds_retcode_t rc; + static const char x_name[] = "X"; + static const char x_value[] = "TEST"; + static const char y_name[] = "Y"; + static const char y_value[] = "FOO"; + char *ptr; + + /* Ensure that the vars are not used yet. */ + rc = ddsrt_unsetenv(x_name); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + rc = ddsrt_unsetenv(y_name); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + + /* Set the env vars to check expansion. */ + rc = ddsrt_setenv(x_name, x_value); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + rc = ddsrt_setenv(y_name, y_value); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + + /* Expand a string with available environment variables. */ + ptr = ddsrt_expand_envvars(var); + if (ptr) { + /* printf("==== %10s: expand(%s), expect(%s))\n", var, ptr, expect); */ + CU_ASSERT_STRING_EQUAL(ptr, expect); + ddsrt_free(ptr); + } else { + /* printf("==== %10s: expand(), expect())\n", var ? var : ""); */ + CU_ASSERT_PTR_NULL(expect); + } + + /* Ensure to reset the environment is as it was. */ + rc = ddsrt_unsetenv(y_name); + CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); + rc = ddsrt_unsetenv(x_name); + CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); +} + + +CU_TheoryDataPoints(ddsrt_environ, expand_sh) = { + CU_DataPoints(const char *, + "${X}", "$X", "X", "${Y}", "${Q}", "${X", + "${X:-ALT}", "${Q:-ALT}", "${X:-${Y}}", "${Q:-${Y}}", "${X:-$Y}", "${Q:-$Y}", "${X:-}", "${Q:-}", + "${X:+SET}", "${Q:+SET}", "${X:+${Y}}", "${Q:+${Y}}", "${X:+$Y}", "${Q:+$Y}", "${X:+}", "${Q:+}", + "${X:?SET}", "${Q:?SET}", "${X:?${Y}}", "${Q:?${Y}}", "${X:?$Y}", "${Q:?$Y}", "${X:?}", "${Q:?}"), + CU_DataPoints(const char *, + "TEST", "TEST", "X", "FOO", "", NULL, + "TEST", "ALT", "TEST", "FOO", "TEST", "FOO", "TEST", "", + "SET", "", "FOO", "", "FOO", "", "", "", + "TEST", NULL, "TEST", NULL, "TEST", NULL, "TEST", NULL) +}; +CU_Theory((const char *var, const char *expect), ddsrt_environ, expand_sh) +{ + dds_retcode_t rc; + static const char x_name[] = "X"; + static const char x_value[] = "TEST"; + static const char y_name[] = "Y"; + static const char y_value[] = "FOO"; + char *ptr; + + /* Ensure that the vars are not used yet. */ + rc = ddsrt_unsetenv(x_name); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + rc = ddsrt_unsetenv(y_name); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + + /* Set the env vars to check expansion. */ + rc = ddsrt_setenv(x_name, x_value); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + rc = ddsrt_setenv(y_name, y_value); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + + /* Expand a string with available environment variables. */ + ptr = ddsrt_expand_envvars_sh(var); + if (ptr) { + /* printf("==== %10s: expand(%s), expect(%s))\n", var, ptr, expect); */ + CU_ASSERT_STRING_EQUAL(ptr, expect); + ddsrt_free(ptr); + } else { + /* printf("==== %10s: expand(), expect())\n", var ? var : ""); */ + CU_ASSERT_PTR_NULL(expect); + } + + /* Ensure to reset the environment is as it was. */ + rc = ddsrt_unsetenv(y_name); + CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); + rc = ddsrt_unsetenv(x_name); + CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); +} diff --git a/src/mpt/mpt/cmake/MPT.cmake b/src/mpt/mpt/cmake/MPT.cmake index fd50b5b..a9fad3d 100644 --- a/src/mpt/mpt/cmake/MPT.cmake +++ b/src/mpt/mpt/cmake/MPT.cmake @@ -171,14 +171,5 @@ function(add_mpt_executable TARGET) target_include_directories(${TARGET} PRIVATE "${MPT_DIR}/include" "${MPT_BINARY_ROOT_DIR}/mpt/include") target_link_libraries(${TARGET} PRIVATE ddsc) - - # We need the 'expand environment variables' feature that is present in the - # 'util' module. However, it is currently not possible to properly link to - # that module on Windows. In the near future, the utils will be migrated to - # ddsrt, after which we automatically have access to expand_envvars. - # But until then, use this very ugly (but quick) hack to solve our immediate - # build issues. - target_include_directories(${TARGET} PRIVATE "${CMAKE_SOURCE_DIR}/util/include") - target_sources(${TARGET} PRIVATE "${CMAKE_SOURCE_DIR}/util/src/ut_expand_envvars.c") endfunction() diff --git a/src/mpt/mpt/src/main.c.in b/src/mpt/mpt/src/main.c.in index 31f0689..fb5aaba 100644 --- a/src/mpt/mpt/src/main.c.in +++ b/src/mpt/mpt/src/main.c.in @@ -6,7 +6,6 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/environ.h" -#include "dds/util/ut_expand_envvars.h" #ifndef _WIN32 #include @@ -63,7 +62,7 @@ mpt_export_env(const mpt_env_t *env) { if (env) { while ((env->name != NULL) && (env->value != NULL)) { - char *expanded = ut_expand_envvars(env->value); + char *expanded = ddsrt_expand_envvars(env->value); ddsrt_setenv(env->name, expanded); ddsrt_free(expanded); env++; From 44ce20ebe0abf64f0450c88102bd6de2403fa023 Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Thu, 11 Apr 2019 14:17:47 +0200 Subject: [PATCH 045/178] Fixed proc compile warning. Signed-off-by: Martin Bremmer --- src/ddsrt/src/process/posix/process.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ddsrt/src/process/posix/process.c b/src/ddsrt/src/process/posix/process.c index f6ed5db..d9c4c72 100644 --- a/src/ddsrt/src/process/posix/process.c +++ b/src/ddsrt/src/process/posix/process.c @@ -22,6 +22,7 @@ #include "dds/ddsrt/process.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/log.h" ddsrt_pid_t @@ -196,7 +197,9 @@ ddsrt_proc_create( /* If executing this, something has gone wrong */ exec_err = errno; - (void)write(exec_fds[1], &exec_err, sizeof(int)); + if (write(exec_fds[1], &exec_err, sizeof(int)) < (ssize_t)sizeof(int)) { + DDS_ERROR("Could not write proc error pipe.\n"); + } close(exec_fds[1]); close(exec_fds[0]); ddsrt_free(exec_argv); From 74ca68e55080fc14e78318949971483e831b1061 Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Fri, 19 Apr 2019 14:42:31 +0200 Subject: [PATCH 046/178] Improved mpt default timeout. Signed-off-by: Martin Bremmer --- src/mpt/CMakeLists.txt | 1 + src/mpt/mpt/cmake/MPT.cmake | 4 +--- src/mpt/mpt/include/mpt/mpt.h | 1 - src/mpt/mpt/include/mpt/resource.h.in | 1 + src/mpt/mpt/src/main.c.in | 5 ++--- src/mpt/tests/self/fixtures.c | 3 +++ 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/mpt/CMakeLists.txt b/src/mpt/CMakeLists.txt index 4b759c7..5c9ec7f 100644 --- a/src/mpt/CMakeLists.txt +++ b/src/mpt/CMakeLists.txt @@ -16,6 +16,7 @@ option(MPT_ENABLE_SELFTEST "Enable multi-process test-framework self test" OFF) set(MPT_CMAKE "${CMAKE_CURRENT_SOURCE_DIR}/mpt/cmake/MPT.cmake") set(MPT_SOURCE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") set(MPT_BINARY_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}") +set(MPT_DEFAULT_TIMEOUT "60") add_subdirectory(mpt) add_subdirectory(tests) diff --git a/src/mpt/mpt/cmake/MPT.cmake b/src/mpt/mpt/cmake/MPT.cmake index a9fad3d..fa57c2b 100644 --- a/src/mpt/mpt/cmake/MPT.cmake +++ b/src/mpt/mpt/cmake/MPT.cmake @@ -11,8 +11,6 @@ # set(MPT_DIR "${CMAKE_CURRENT_LIST_DIR}/..") - - function(parse_mpt_fixtures INPUT TEST_DISABLED TEST_TIMEOUT TEST_XFAIL) set(s "[ \t\r\n]") if(INPUT MATCHES ".disabled${s}*=${s}*([tT][rR][uU][eE]|[0-9]+)") @@ -24,7 +22,7 @@ function(parse_mpt_fixtures INPUT TEST_DISABLED TEST_TIMEOUT TEST_XFAIL) if(INPUT MATCHES ".timeout${s}*=${s}*([0-9]+)") set(${TEST_TIMEOUT} "${CMAKE_MATCH_1}" PARENT_SCOPE) else() - set(${TEST_TIMEOUT} "0" PARENT_SCOPE) + set(${TEST_TIMEOUT} "${MPT_DEFAULT_TIMEOUT}" PARENT_SCOPE) endif() if(INPUT MATCHES ".xfail${s}*=${s}*([tT][rR][uU][eE]|[0-9]+)") diff --git a/src/mpt/mpt/include/mpt/mpt.h b/src/mpt/mpt/include/mpt/mpt.h index 8d0522a..719c9d6 100644 --- a/src/mpt/mpt/include/mpt/mpt.h +++ b/src/mpt/mpt/include/mpt/mpt.h @@ -154,5 +154,4 @@ MPT_TestFiniDeclaration(suite, test) \ /* Helpful function to check for patterns in log callbacks. */ int mpt_patmatch(const char *pat, const char *str); - #endif /* MPT_H_INCLUDED */ diff --git a/src/mpt/mpt/include/mpt/resource.h.in b/src/mpt/mpt/include/mpt/resource.h.in index 13c5711..258e597 100644 --- a/src/mpt/mpt/include/mpt/resource.h.in +++ b/src/mpt/mpt/include/mpt/resource.h.in @@ -2,5 +2,6 @@ #define MPT_RESOURCE_H_INCLUDED #define MPT_SOURCE_ROOT_DIR "@MPT_SOURCE_ROOT_DIR@" +#define MPT_DEFAULT_TIMEOUT (@MPT_DEFAULT_TIMEOUT@) /* Seconds. */ #endif /* MPT_RESOURCE_H_INCLUDED */ diff --git a/src/mpt/mpt/src/main.c.in b/src/mpt/mpt/src/main.c.in index fb5aaba..14ca113 100644 --- a/src/mpt/mpt/src/main.c.in +++ b/src/mpt/mpt/src/main.c.in @@ -157,10 +157,9 @@ mpt_test_new(const char* name, int secs, bool xf) * So, make sure that the 'manual' timeout takes longer than the ctest * timeout. */ if (secs == 0) { - test->timeout = DDS_SECS(1600); - } else { - test->timeout = DDS_SECS(secs * 2); + secs = MPT_DEFAULT_TIMEOUT; } + test->timeout = DDS_SECS(secs + 5); return test; } diff --git a/src/mpt/tests/self/fixtures.c b/src/mpt/tests/self/fixtures.c index 25b5782..a07bc6f 100644 --- a/src/mpt/tests/self/fixtures.c +++ b/src/mpt/tests/self/fixtures.c @@ -70,3 +70,6 @@ MPT_Test(disabled, _false, .disabled=false); * This can only really be done manually, unfortunately. */ MPT_TestProcess(timeout, child_culling, id, proc_sleep, MPT_ArgValues(DDS_SECS(120))); MPT_Test(timeout, child_culling, .timeout=1); + +MPT_TestProcess(timeout, default_timeout, id, proc_sleep, MPT_ArgValues(DDS_SECS(120))); +MPT_Test(timeout, default_timeout); From e9f6ec6f48d9ef0858f14dc23b7aea757fe6f8ca Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Wed, 24 Apr 2019 15:13:30 +0200 Subject: [PATCH 047/178] Be sure to not trigger the SIGCHLD Signed-off-by: Martin Bremmer --- src/ddsrt/src/process/posix/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ddsrt/src/process/posix/process.c b/src/ddsrt/src/process/posix/process.c index d9c4c72..d42877f 100644 --- a/src/ddsrt/src/process/posix/process.c +++ b/src/ddsrt/src/process/posix/process.c @@ -181,6 +181,9 @@ ddsrt_proc_create( goto fail_fctl; } + /* Be sure to not trigger the SIGCHLD. */ + signal(SIGCHLD, SIG_DFL); + /* Create a new process. */ spawn = fork(); if (spawn == -1) From 7a705eabf06a0db8e7fa36e7073be9d287b4d0a4 Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Thu, 25 Apr 2019 13:29:11 +0200 Subject: [PATCH 048/178] Removed expand_envvars.h Signed-off-by: Martin Bremmer --- src/core/ddsi/src/q_config.c | 1 - src/ddsrt/CMakeLists.txt | 1 - src/ddsrt/include/dds/ddsrt/expand_envvars.h | 31 -------------------- src/ddsrt/src/expand_envvars.c | 1 - 4 files changed, 34 deletions(-) delete mode 100644 src/ddsrt/include/dds/ddsrt/expand_envvars.h diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index bf1781d..f3ea0a7 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -33,7 +33,6 @@ #include "dds/ddsi/q_error.h" #include "dds/ddsrt/xmlparser.h" -#include "dds/ddsrt/expand_envvars.h" #include "dds/version.h" diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 5b49248..cda6f18 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -79,7 +79,6 @@ list(APPEND sources list(APPEND headers "${source_path}/dds/ddsrt/avl.h" - "${source_path}/dds/ddsrt/expand_envvars.h" "${source_path}/dds/ddsrt/fibheap.h" "${source_path}/dds/ddsrt/hopscotch.h" "${source_path}/dds/ddsrt/thread_pool.h") diff --git a/src/ddsrt/include/dds/ddsrt/expand_envvars.h b/src/ddsrt/include/dds/ddsrt/expand_envvars.h deleted file mode 100644 index d7b66f4..0000000 --- a/src/ddsrt/include/dds/ddsrt/expand_envvars.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef DDSRT_EXPAND_ENVVARS_H -#define DDSRT_EXPAND_ENVVARS_H - -#include "dds/export.h" - -#if defined (__cplusplus) -extern "C" { -#endif - - /* Expands ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, but not $X */ - DDS_EXPORT char *ddsrt_expand_envvars(const char *string); - - /* Expands $X, ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, $ and \ can be escaped with \ */ - DDS_EXPORT char *ddsrt_expand_envvars_sh(const char *string); - -#if defined (__cplusplus) -} -#endif - -#endif diff --git a/src/ddsrt/src/expand_envvars.c b/src/ddsrt/src/expand_envvars.c index ded0d0a..dbaa33a 100644 --- a/src/ddsrt/src/expand_envvars.c +++ b/src/ddsrt/src/expand_envvars.c @@ -19,7 +19,6 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" #include "dds/ddsrt/string.h" -#include "dds/ddsrt/expand_envvars.h" typedef char * (*expand_fn)(const char *src0); From d2ebbbc880d6ad020d900a813f9d9b0c7a2d3a0d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 25 Apr 2019 11:43:19 +0200 Subject: [PATCH 049/178] address a handful of compiler warnings in ddsperf These are fortunately all false positives. Signed-off-by: Erik Boasson --- src/tools/ddsperf/ddsperf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index 51874a4..7052233 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -664,7 +664,7 @@ static dds_instance_handle_t get_pphandle_for_pubhandle (dds_instance_handle_t p dds_sample_info_t info; if ((n = dds_read_instance (rd_publications, &msg, &info, 1, 1, pubhandle)) < 0) error2 ("dds_read_instance(rd_publications, %"PRIx64") failed: %d\n", pubhandle, (int) n); - else if (n == 0 || !info.valid_data) + if (n == 0 || !info.valid_data) { printf ("get_pong_writer: publication handle %"PRIx64" not found\n", pubhandle); fflush (stdout); @@ -772,7 +772,7 @@ static bool process_data (dds_entity_t rd, struct subthread_arg *arg) { if (iseq[i].valid_data) { - uint32_t seq, keyval, size; + uint32_t seq = 0, keyval = 0, size = 0; switch (topicsel) { case KS: { KeyedSeq *d = (KeyedSeq *) mseq[i]; keyval = d->keyval; seq = d->seq; size = 12 + d->baggage._length; } break; @@ -783,7 +783,7 @@ static bool process_data (dds_entity_t rd, struct subthread_arg *arg) (void) check_eseq (&eseq_admin, seq, keyval, size, iseq[i].publication_handle); if (iseq[i].source_timestamp & 1) { - dds_entity_t wr_pong = 0; + dds_entity_t wr_pong; if ((wr_pong = get_pong_writer (iseq[i].publication_handle)) != 0) { dds_return_t rc; From b686ba858c2a04a9d70d0131c9e42fb8dcdb5693 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 29 Apr 2019 09:24:18 +0200 Subject: [PATCH 050/178] make internal header files more C++ friendly Generally one doesn't need to include any internal header files in an application, but the (unstable) interface for application-defined sample representation and serialization does require including some. It turns out a keyword clash had to be resolved (typename => type_name) and that a whole bunch of them were missing the #ifdef __cplusplus / extern "C" bit. It further turned out that one had to pull in nearly all of the type definitions, including some typedefs that are illegal in C++, e.g., typedef struct os_sockWaitset *os_sockWaitset; C++ is right to forbid this, but Cyclone's header files were wrong to force inclusion of so much irrelevant stuff. This commit leaves these typedefs in place, but eliminates a few header file inclusions to avoid the problem. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds__guardcond.h | 8 +++ src/core/ddsc/src/dds__readcond.h | 8 +++ src/core/ddsc/src/dds__serdata_builtintopic.h | 8 +++ src/core/ddsc/src/dds_init.c | 1 + src/core/ddsc/src/dds_instance.c | 2 +- src/core/ddsc/src/dds_read.c | 1 + src/core/ddsc/src/dds_reader.c | 1 + src/core/ddsc/src/dds_serdata_builtintopic.c | 2 +- src/core/ddsc/src/dds_sertopic_builtintopic.c | 9 +-- src/core/ddsc/src/dds_topic.c | 12 ++-- src/core/ddsc/src/dds_whc.c | 1 + src/core/ddsc/src/dds_writer.c | 1 + src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h | 10 ++- src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h | 8 +++ src/core/ddsi/include/dds/ddsi/ddsi_raweth.h | 8 +++ .../ddsi/include/dds/ddsi/ddsi_rhc_plugin.h | 8 +++ src/core/ddsi/include/dds/ddsi/ddsi_serdata.h | 65 ++++++++++++++----- .../include/dds/ddsi/ddsi_serdata_default.h | 8 +++ .../ddsi/include/dds/ddsi/ddsi_sertopic.h | 18 +++-- src/core/ddsi/include/dds/ddsi/ddsi_ssl.h | 8 +++ src/core/ddsi/include/dds/ddsi/ddsi_tcp.h | 16 +++++ src/core/ddsi/include/dds/ddsi/ddsi_tran.h | 17 ++++- src/core/ddsi/include/dds/ddsi/ddsi_udp.h | 8 +++ src/core/ddsi/include/dds/ddsi/q_bitset.h | 8 +++ src/core/ddsi/include/dds/ddsi/q_bswap.h | 8 +-- src/core/ddsi/include/dds/ddsi/q_debmon.h | 10 ++- src/core/ddsi/include/dds/ddsi/q_entity.h | 8 ++- src/core/ddsi/include/dds/ddsi/q_freelist.h | 8 +++ src/core/ddsi/include/dds/ddsi/q_init.h | 8 +++ .../include/dds/ddsi/q_inverse_uint32_set.h | 8 +++ src/core/ddsi/include/dds/ddsi/q_radmin.h | 1 - src/core/ddsi/include/dds/ddsi/q_xmsg.h | 1 + src/core/ddsi/src/ddsi_eth.h | 8 +++ src/core/ddsi/src/ddsi_ipaddr.c | 1 + src/core/ddsi/src/ddsi_mcgroup.c | 1 + src/core/ddsi/src/ddsi_raweth.c | 1 + src/core/ddsi/src/ddsi_serdata_default.c | 1 + src/core/ddsi/src/ddsi_sertopic.c | 4 +- src/core/ddsi/src/ddsi_tcp.c | 1 + src/core/ddsi/src/ddsi_tran.c | 1 + src/core/ddsi/src/ddsi_udp.c | 1 + src/core/ddsi/src/q_debmon.c | 2 +- src/core/ddsi/src/q_entity.c | 6 +- src/core/ddsi/src/q_plist.c | 1 + src/core/ddsi/src/q_receive.c | 4 +- src/core/ddsi/src/q_transmit.c | 4 +- src/ddsrt/include/dds/ddsrt/atomics/arm.h | 9 ++- src/ddsrt/include/dds/ddsrt/atomics/gcc.h | 9 ++- src/ddsrt/include/dds/ddsrt/atomics/msvc.h | 9 ++- src/ddsrt/include/dds/ddsrt/atomics/sun.h | 7 ++ src/ddsrt/include/dds/ddsrt/cdtors.h | 8 +++ src/ddsrt/include/dds/ddsrt/md5.h | 7 +- src/ddsrt/include/dds/ddsrt/retcode.h | 8 +++ src/ddsrt/include/dds/ddsrt/rusage.h | 8 +++ src/ddsrt/include/dds/ddsrt/sockets.h | 8 +++ src/ddsrt/include/dds/ddsrt/strtod.h | 8 +++ 56 files changed, 345 insertions(+), 60 deletions(-) diff --git a/src/core/ddsc/src/dds__guardcond.h b/src/core/ddsc/src/dds__guardcond.h index 7d57643..f317dc5 100644 --- a/src/core/ddsc/src/dds__guardcond.h +++ b/src/core/ddsc/src/dds__guardcond.h @@ -14,10 +14,18 @@ #include "dds__entity.h" +#if defined (__cplusplus) +extern "C" { +#endif + dds_guardcond* dds_create_guardcond( dds_participant *pp); DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_guardcond, DDS_KIND_COND_GUARD) +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsc/src/dds__readcond.h b/src/core/ddsc/src/dds__readcond.h index aa0494e..f76137c 100644 --- a/src/core/ddsc/src/dds__readcond.h +++ b/src/core/ddsc/src/dds__readcond.h @@ -14,6 +14,10 @@ #include "dds__entity.h" +#if defined (__cplusplus) +extern "C" { +#endif + dds_readcond * dds_create_readcond( dds_reader *rd, @@ -21,4 +25,8 @@ dds_create_readcond( uint32_t mask, dds_querycondition_filter_fn filter); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsc/src/dds__serdata_builtintopic.h b/src/core/ddsc/src/dds__serdata_builtintopic.h index 6afe2d1..1c4d548 100644 --- a/src/core/ddsc/src/dds__serdata_builtintopic.h +++ b/src/core/ddsc/src/dds__serdata_builtintopic.h @@ -16,6 +16,10 @@ #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_sertopic.h" +#if defined (__cplusplus) +extern "C" { +#endif + struct ddsi_serdata_builtintopic { struct ddsi_serdata c; nn_guid_t key; @@ -39,4 +43,8 @@ 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); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index d51bfb0..9e74180 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -30,6 +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/version.h" #define DOMAIN_ID_MIN 0 diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index 25156fe..903d7ee 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -22,7 +22,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" dds_return_t dds_writedispose( diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 37e35ec..2791a44 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -19,6 +19,7 @@ #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_entity.h" +#include "dds/ddsi/q_globals.h" #include "dds/ddsi/ddsi_sertopic.h" static dds_retcode_t dds_read_lock (dds_entity_t hdl, dds_reader **reader, dds_readcond **condition, bool only_reader) diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 6ce57b9..be86ed3 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -23,6 +23,7 @@ #include "dds__topic.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" +#include "dds/ddsi/q_globals.h" #include "dds__builtin.h" #include "dds/ddsi/ddsi_sertopic.h" diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index 33da2ca..5cbd47b 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -91,7 +91,7 @@ static void set_topic_type_from_sertopic (struct ddsi_serdata_builtintopic *d, c } if (!(d->xqos.present & QP_TYPE_NAME)) { - d->xqos.type_name = dds_string_dup (tp->typename); + d->xqos.type_name = dds_string_dup (tp->type_name); d->xqos.present |= QP_TYPE_NAME; } } diff --git a/src/core/ddsc/src/dds_sertopic_builtintopic.c b/src/core/ddsc/src/dds_sertopic_builtintopic.c index 05c9544..7773a13 100644 --- a/src/core/ddsc/src/dds_sertopic_builtintopic.c +++ b/src/core/ddsc/src/dds_sertopic_builtintopic.c @@ -21,6 +21,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" #include "dds/ddsi/ddsi_sertopic.h" +#include "dds/ddsi/ddsi_iid.h" #include "dds__serdata_builtintopic.h" /* 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 */ @@ -30,10 +31,10 @@ struct ddsi_sertopic *new_sertopic_builtintopic (enum ddsi_sertopic_builtintopic struct ddsi_sertopic_builtintopic *tp = ddsrt_malloc (sizeof (*tp)); tp->c.iid = ddsi_iid_gen(); tp->c.name = dds_string_dup (name); - tp->c.typename = dds_string_dup (typename); - const size_t name_typename_size = strlen (tp->c.name) + 1 + strlen (tp->c.typename) + 1; - tp->c.name_typename = dds_alloc (name_typename_size); - snprintf (tp->c.name_typename, name_typename_size, "%s/%s", tp->c.name, tp->c.typename); + tp->c.type_name = dds_string_dup (typename); + const size_t name_typename_size = strlen (tp->c.name) + 1 + strlen (tp->c.type_name) + 1; + tp->c.name_type_name = dds_alloc (name_typename_size); + snprintf (tp->c.name_type_name, name_typename_size, "%s/%s", tp->c.name, tp->c.type_name); tp->c.ops = &ddsi_sertopic_ops_builtintopic; tp->c.serdata_ops = &ddsi_serdata_ops_builtintopic; tp->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (tp->c.serdata_ops); diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index f834f00..747976c 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -35,7 +35,7 @@ DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_topic) const ddsrt_avl_treedef_t dds_topictree_def = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY ( offsetof (struct ddsi_sertopic, avlnode), - offsetof (struct ddsi_sertopic, name_typename), + offsetof (struct ddsi_sertopic, name_type_name), (int (*) (const void *, const void *)) strcmp, 0 ); @@ -285,7 +285,7 @@ static bool dupdef_qos_ok(const dds_qos_t *qos, const struct ddsi_sertopic *st) static bool sertopic_equivalent (const struct ddsi_sertopic *a, const struct ddsi_sertopic *b) { - if (strcmp (a->name_typename, b->name_typename) != 0) + if (strcmp (a->name_type_name, b->name_type_name) != 0) return false; if (a->serdata_basehash != b->serdata_basehash) return false; @@ -447,9 +447,9 @@ dds_create_topic( st->c.iid = ddsi_iid_gen (); st->c.status_cb = dds_topic_status_cb; st->c.status_cb_entity = NULL; /* set by dds_create_topic_arbitrary */ - st->c.name_typename = key; + st->c.name_type_name = key; st->c.name = dds_string_dup (name); - st->c.typename = dds_string_dup (typename); + st->c.type_name = dds_string_dup (typename); st->c.ops = &ddsi_sertopic_ops_default; st->c.serdata_ops = desc->m_nkeys ? &ddsi_serdata_ops_cdr : &ddsi_serdata_ops_cdr_nokey; st->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (st->c.serdata_ops); @@ -471,7 +471,7 @@ dds_create_topic( /* Set Topic meta data (for SEDP publication) */ plist.qos.topic_name = dds_string_dup (st->c.name); - plist.qos.type_name = dds_string_dup (st->c.typename); + plist.qos.type_name = dds_string_dup (st->c.type_name); plist.qos.present |= (QP_TOPIC_NAME | QP_TYPE_NAME); if (desc->m_meta) { plist.type_description = dds_string_dup (desc->m_meta); @@ -643,7 +643,7 @@ dds_get_type_name( ret = DDS_ERRNO(rc); goto fail; } - (void)snprintf(name, size, "%s", t->m_stopic->typename); + (void)snprintf(name, size, "%s", t->m_stopic->type_name); dds_topic_unlock(t); ret = DDS_RETCODE_OK; fail: diff --git a/src/core/ddsc/src/dds_whc.c b/src/core/ddsc/src/dds_whc.c index 5408c69..b63ca62 100644 --- a/src/core/ddsc/src/dds_whc.c +++ b/src/core/ddsc/src/dds_whc.c @@ -27,6 +27,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" #define USE_EHH 0 diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index f98d70c..b36bfc9 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -14,6 +14,7 @@ #include "dds/dds.h" #include "dds/version.h" #include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_xmsg.h" diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h b/src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h index 3bc6f2f..9c7f1d3 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h @@ -14,11 +14,19 @@ #include "dds/ddsi/ddsi_tran.h" -enum ddsi_nearby_address_result ddsi_ipaddr_is_nearby_address (ddsi_tran_factory_t tran, const nn_locator_t *loc, size_t ninterf, const struct nn_interface interf[]); +#if defined (__cplusplus) +extern "C" { +#endif + +enum ddsi_nearby_address_result ddsi_ipaddr_is_nearby_address (ddsi_tran_factory_t tran, const nn_locator_t *loc, 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); void ddsi_ipaddr_from_loc (struct sockaddr_storage *dst, const nn_locator_t *src); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h b/src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h index 018237a..f4dc36f 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h @@ -14,6 +14,10 @@ #include "dds/ddsi/ddsi_tran.h" +#if defined (__cplusplus) +extern "C" { +#endif + struct nn_group_membership; struct nn_group_membership *new_group_membership (void); @@ -23,4 +27,8 @@ int ddsi_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_lo void ddsi_transfer_group_membership (ddsi_tran_conn_t conn, ddsi_tran_conn_t newconn); int ddsi_rejoin_transferred_mcgroups (ddsi_tran_conn_t conn); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_raweth.h b/src/core/ddsi/include/dds/ddsi/ddsi_raweth.h index e81472e..da60a24 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_raweth.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_raweth.h @@ -12,6 +12,14 @@ #ifndef DDSI_RAWETH_H #define DDSI_RAWETH_H +#if defined (__cplusplus) +extern "C" { +#endif + int ddsi_raweth_init (void); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h b/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h index 57c8813..1d37ecf 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h @@ -12,6 +12,10 @@ #ifndef DDSI_RHC_PLUGIN_H #define DDSI_RHC_PLUGIN_H +#if defined (__cplusplus) +extern "C" { +#endif + struct rhc; struct nn_xqos; struct ddsi_tkmap_instance; @@ -42,4 +46,8 @@ struct ddsi_rhc_plugin DDS_EXPORT void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct nn_xqos *xqos); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h index 0bddb32..866910a 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h @@ -16,6 +16,10 @@ #include "dds/ddsi/q_time.h" #include "dds/ddsi/ddsi_sertopic.h" +#if defined (__cplusplus) +extern "C" { +#endif + struct nn_rdata; struct nn_keyhash; @@ -40,37 +44,62 @@ struct ddsi_serdata { nn_mtime_t twrite; /* write time, not source timestamp, set post-throttling */ }; -/* Serialised size of sample: uint32_t because the protocol can't handle samples larger than 4GB anyway */ +/* Serialised size of sample inclusive of DDSI encoding header + - uint32_t because the protocol can't handle samples larger than 4GB anyway + - FIXME: get the encoding header out of the serialised data */ typedef uint32_t (*ddsi_serdata_size_t) (const struct ddsi_serdata *d); /* Free a serdata (called by unref when refcount goes to 0) */ typedef void (*ddsi_serdata_free_t) (struct ddsi_serdata *d); -/* Construct a serdata from a fragchain received over the network */ +/* Construct a serdata from a fragchain received over the network + - "kind" is KEY or DATA depending on the type of payload + - "size" is the serialised size of the sample, inclusive of DDSI encoding header + - the first fragchain always contains the encoding header in its entirety + - fragchains may overlap, though I have never seen any DDS implementation + actually send such nasty fragments + - 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); /* 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); -/* Construct a serdata from an application sample */ +/* Construct a serdata from an application sample + - "kind" is KEY or DATA depending on the operation invoked by the application; + e.g., write results in kind = DATA, dispose in kind = KEY. The important bit + is to not assume anything of the contents of non-key fields if kind = KEY + unless additional application knowledge is available */ typedef struct ddsi_serdata * (*ddsi_serdata_from_sample_t) (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, const void *sample); -/* Construct a topic-less serdata with a keyvalue given a normal serdata (either key or data) - used for tkmap */ +/* Construct a topic-less serdata with just a keyvalue given a normal serdata (either key or data) + - used for mapping key values to instance ids in tkmap + - two reasons: size (keys are typically smaller than samples), and data in tkmap + is shared across topics + - whether a serdata is topicless or not is known from the context, and the topic + field may have any value for a topicless serdata (so in some cases, one can + simply do "return ddsi_serdata_ref(d);" + */ typedef struct ddsi_serdata * (*ddsi_serdata_to_topicless_t) (const struct ddsi_serdata *d); -/* Fill buffer with 'size' bytes of serialised data, starting from 'off'; 0 <= off < off+sz <= - alignup4(size(d)) */ +/* Fill buffer with 'size' bytes of serialised data, starting from 'off' + - 0 <= off < off+sz <= alignup4(size(d)) + - bytes at offsets 0 .. 3 are DDSI encoding header, size(d) includes that header + - what to copy for bytes in [size(d), alignup4(size(d))) depends on the serdata + implementation, the protocol treats them as undefined + - FIXME: get the encoding header out of the serialised data */ typedef void (*ddsi_serdata_to_ser_t) (const struct ddsi_serdata *d, size_t off, size_t sz, void *buf); -/* Provide a pointer to 'size' bytes of serialised data, starting from 'off'; 0 <= off < off+sz <= - alignup4(size(d)); it must remain valid until the corresponding call to to_ser_unref. Multiple - calls to to_ser_ref() may be issued in parallel, the separate ref/unref bit is there to at least - have the option of lazily creating the serialised representation and freeing it when no one needs - it, while the sample itself remains valid */ +/* Provide a pointer to 'size' bytes of serialised data, starting from 'off' + - see ddsi_serdata_to_ser_t above + - instead of copying, this gives a reference that must remain valid until the + corresponding call to to_ser_unref + - multiple calls to to_ser_ref() may be issued in parallel + - lazily creating the serialised representation is allowed (though I'm not sure + how that would work with knowing the serialised size beforehand ...) */ typedef struct ddsi_serdata * (*ddsi_serdata_to_ser_ref_t) (const struct ddsi_serdata *d, size_t off, size_t sz, ddsrt_iovec_t *ref); -/* Release a lock on serialised data, ref must be a pointer previously obtained by calling - to_ser_ref(d, off, sz) for some offset off. */ +/* Release a lock on serialised data + - ref was previousy filled by ddsi_serdata_to_ser_ref_t */ typedef void (*ddsi_serdata_to_ser_unref_t) (struct ddsi_serdata *d, const ddsrt_iovec_t *ref); /* Turn serdata into an application sample (or just the key values if only key values are @@ -83,11 +112,11 @@ typedef void (*ddsi_serdata_to_ser_unref_t) (struct ddsi_serdata *d, const ddsrt by the caller.) */ typedef bool (*ddsi_serdata_to_sample_t) (const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim); -/* Create a sample from a topicless serdata, as returned by serdata_to_topicless. This sample - obviously has just the key fields filled in, and is used for generating invalid samples. */ +/* Create a sample from a topicless serdata, as returned by serdata_to_topicless. This sample + obviously has just the key fields filled in and is used for generating invalid samples. */ typedef bool (*ddsi_serdata_topicless_to_sample_t) (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim); -/* Test key values of two serdatas for equality. The two will have the same ddsi_serdata_ops, +/* Test key values of two serdatas for equality. The two will have the same ddsi_serdata_ops, but are not necessarily of the same topic (one can decide to never consider them equal if they are of different topics, of course; but the nice thing about _not_ doing that is that all instances with a certain key value with have the same instance id, and that in turn makes @@ -166,4 +195,8 @@ DDS_EXPORT inline bool ddsi_serdata_eqkey (const struct ddsi_serdata *a, const s return a->ops->eqkey (a, b); } +#if defined (__cplusplus) +} +#endif + #endif 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 7775e1c..c61bb97 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -22,6 +22,10 @@ #include "dds/dds.h" #include "dds__topic.h" +#if defined (__cplusplus) +extern "C" { +#endif + #if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN #define CDR_BE 0x0000 #define CDR_LE 0x0100 @@ -125,4 +129,8 @@ extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_rawcdr; struct serdatapool * ddsi_serdatapool_new (void); void ddsi_serdatapool_free (struct serdatapool * pool); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h index edd0b02..172af62 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h @@ -16,6 +16,10 @@ #include "dds/ddsrt/avl.h" #include "dds/ddsc/dds_public_alloc.h" +#if defined (__cplusplus) +extern "C" { +#endif + struct ddsi_serdata; struct ddsi_serdata_ops; @@ -29,9 +33,9 @@ struct ddsi_sertopic { const struct ddsi_sertopic_ops *ops; const struct ddsi_serdata_ops *serdata_ops; uint32_t serdata_basehash; - char *name_typename; + char *name_type_name; char *name; - char *typename; + char *type_name; uint64_t iid; ddsrt_atomic_uint32_t refc; /* counts refs from entities, not from data */ @@ -39,12 +43,14 @@ struct ddsi_sertopic { struct dds_topic * status_cb_entity; }; +/* Called when the refcount dropped to zero */ typedef void (*ddsi_sertopic_deinit_t) (struct ddsi_sertopic *tp); -/* Release any memory allocated by ddsi_sertopic_to_sample */ +/* Zero out a sample, used for generating samples from just a key value and in cleaning up + after dds_return_loan */ typedef void (*ddsi_sertopic_zero_samples_t) (const struct ddsi_sertopic *d, void *samples, size_t count); -/* Release any memory allocated by ddsi_sertopic_to_sample */ +/* (Re)allocate an array of samples, used in growing loaned sample arrays in dds_read */ typedef void (*ddsi_sertopic_realloc_samples_t) (void **ptrs, const struct ddsi_sertopic *d, void *old, size_t oldcount, size_t count); /* Release any memory allocated by ddsi_sertopic_to_sample (also undo sertopic_alloc_sample if "op" so requests) */ @@ -86,4 +92,8 @@ DDS_EXPORT inline void ddsi_sertopic_free_sample (const struct ddsi_sertopic *tp ddsi_sertopic_free_samples (tp, &sample, 1, op); } +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_ssl.h b/src/core/ddsi/include/dds/ddsi/ddsi_ssl.h index 493289e..edddd26 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_ssl.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_ssl.h @@ -20,8 +20,16 @@ #endif #include +#if defined (__cplusplus) +extern "C" { +#endif + struct ddsi_ssl_plugins; void ddsi_ssl_config_plugin (struct ddsi_ssl_plugins *plugin); +#if defined (__cplusplus) +} +#endif + #endif #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h b/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h index bdf28d9..380dac3 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h @@ -18,6 +18,10 @@ #include "dds/ddsi/ddsi_ssl.h" +#if defined (__cplusplus) +extern "C" { +#endif + struct ddsi_ssl_plugins { bool (*init) (void); @@ -31,8 +35,20 @@ struct ddsi_ssl_plugins SSL * (*accept) (BIO *bio, ddsrt_socket_t *sock); }; +#if defined (__cplusplus) +} +#endif + +#endif + +#if defined (__cplusplus) +extern "C" { #endif int ddsi_tcp_init (void); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_tran.h b/src/core/ddsi/include/dds/ddsi/ddsi_tran.h index fa10474..11b48cb 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_tran.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_tran.h @@ -14,9 +14,16 @@ /* DDSI Transport module */ -#include "dds/ddsi/q_globals.h" +#include "dds/ddsrt/ifaddrs.h" +#include "dds/ddsrt/atomics.h" #include "dds/ddsi/q_protocol.h" +#if defined (__cplusplus) +extern "C" { +#endif + +struct nn_interface; + /* Types supporting handles */ #define DDSI_TRAN_CONN 1 @@ -69,7 +76,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, size_t ninterf, const struct nn_interface interf[]); +typedef enum ddsi_nearby_address_result (*ddsi_is_nearby_address_fn_t) (ddsi_tran_factory_t tran, const nn_locator_t *loc, size_t ninterf, const struct nn_interface *interf); enum ddsi_locator_from_string_result { AFSR_OK, /* conversion succeeded */ @@ -239,7 +246,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 nn_locator_t *loc); int ddsi_is_ssm_mcaddr (const nn_locator_t *loc); -enum ddsi_nearby_address_result ddsi_is_nearby_address (const nn_locator_t *loc, size_t ninterf, const struct nn_interface interf[]); +enum ddsi_nearby_address_result ddsi_is_nearby_address (const nn_locator_t *loc, size_t ninterf, const struct nn_interface *interf); enum ddsi_locator_from_string_result ddsi_locator_from_string (nn_locator_t *loc, const char *str); @@ -271,4 +278,8 @@ inline ddsi_tran_conn_t ddsi_listener_accept (ddsi_tran_listener_t listener) { void ddsi_listener_unblock (ddsi_tran_listener_t listener); void ddsi_listener_free (ddsi_tran_listener_t listener); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_udp.h b/src/core/ddsi/include/dds/ddsi/ddsi_udp.h index 4dece96..1305dab 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_udp.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_udp.h @@ -12,6 +12,14 @@ #ifndef _DDSI_UDP_H_ #define _DDSI_UDP_H_ +#if defined (__cplusplus) +extern "C" { +#endif + int ddsi_udp_init (void); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/q_bitset.h b/src/core/ddsi/include/dds/ddsi/q_bitset.h index ec81027..630d16a 100644 --- a/src/core/ddsi/include/dds/ddsi/q_bitset.h +++ b/src/core/ddsi/include/dds/ddsi/q_bitset.h @@ -18,6 +18,10 @@ #include "dds/ddsi/q_unused.h" +#if defined (__cplusplus) +extern "C" { +#endif + inline int nn_bitset_isset (uint32_t numbits, const uint32_t *bits, uint32_t idx) { return idx < numbits && (bits[idx/32] & (UINT32_C(1) << (31 - (idx%32)))); @@ -52,4 +56,8 @@ inline void nn_bitset_one (uint32_t numbits, uint32_t *bits) } } +#if defined (__cplusplus) +} +#endif + #endif /* NN_BITSET_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_bswap.h b/src/core/ddsi/include/dds/ddsi/q_bswap.h index 7478f87..6f8cbff 100644 --- a/src/core/ddsi/include/dds/ddsi/q_bswap.h +++ b/src/core/ddsi/include/dds/ddsi/q_bswap.h @@ -19,6 +19,10 @@ #include "dds/ddsi/q_rtps.h" /* for nn_guid_t, nn_guid_prefix_t */ #include "dds/ddsi/q_protocol.h" /* for nn_sequence_number_t */ +#if defined (__cplusplus) +extern "C" { +#endif + inline uint16_t bswap2u (uint16_t x) { return (uint16_t) ((x >> 8) | (x << 8)); @@ -84,10 +88,6 @@ inline void bswapSN (nn_sequence_number_t *sn) #define fromBE8u(x) (x) #endif -#if defined (__cplusplus) -extern "C" { -#endif - nn_guid_prefix_t nn_hton_guid_prefix (nn_guid_prefix_t p); nn_guid_prefix_t nn_ntoh_guid_prefix (nn_guid_prefix_t p); nn_entityid_t nn_hton_entityid (nn_entityid_t e); diff --git a/src/core/ddsi/include/dds/ddsi/q_debmon.h b/src/core/ddsi/include/dds/ddsi/q_debmon.h index d6e4c1c..77348c2 100644 --- a/src/core/ddsi/include/dds/ddsi/q_debmon.h +++ b/src/core/ddsi/include/dds/ddsi/q_debmon.h @@ -12,6 +12,10 @@ #ifndef Q_DEBMON_H #define Q_DEBMON_H +#if defined (__cplusplus) +extern "C" { +#endif + 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); @@ -20,4 +24,8 @@ struct debug_monitor *new_debug_monitor (int 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); -#endif /* defined(__ospli_osplo__q_debmon__) */ +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index f6f1f8e..f606786 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -14,6 +14,7 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/avl.h" +#include "dds/ddsrt/sync.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_lat_estim.h" @@ -32,11 +33,14 @@ struct xevent; struct nn_reorder; struct nn_defrag; struct nn_dqueue; +struct nn_rsample_info; +struct nn_rdata; struct addrset; struct ddsi_sertopic; struct whc; struct nn_xqos; struct nn_plist; +struct lease; struct proxy_group; struct proxy_endpoint_common; @@ -159,7 +163,7 @@ struct participant unsigned bes; /* built-in endpoint set */ unsigned 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 ... */ - nn_plist_t *plist; /* settings/QoS for this participant */ + struct nn_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; @@ -294,7 +298,7 @@ struct proxy_participant unsigned bes; /* built-in endpoint set */ unsigned prismtech_bes; /* prismtech-specific extension of built-in endpoints set */ nn_guid_t privileged_pp_guid; /* if this PP depends on another PP for its SEDP writing */ - nn_plist_t *plist; /* settings/QoS for this participant */ + struct nn_plist *plist; /* settings/QoS for this participant */ ddsrt_atomic_voidp_t lease; /* lease object for this participant, for automatic leases */ struct addrset *as_default; /* default address set to use for user data traffic */ struct addrset *as_meta; /* default address set to use for discovery traffic */ diff --git a/src/core/ddsi/include/dds/ddsi/q_freelist.h b/src/core/ddsi/include/dds/ddsi/q_freelist.h index 8e40ff7..8fcafa7 100644 --- a/src/core/ddsi/include/dds/ddsi/q_freelist.h +++ b/src/core/ddsi/include/dds/ddsi/q_freelist.h @@ -15,6 +15,10 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/sync.h" +#if defined (__cplusplus) +extern "C" { +#endif + #define FREELIST_SIMPLE 1 #define FREELIST_ATOMIC_LIFO 2 #define FREELIST_DOUBLE 3 @@ -74,4 +78,8 @@ 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); void *nn_freelist_pop (struct nn_freelist *fl); +#if defined (__cplusplus) +} +#endif + #endif /* NN_FREELIST_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_init.h b/src/core/ddsi/include/dds/ddsi/q_init.h index c9794f0..a1f9cef 100644 --- a/src/core/ddsi/include/dds/ddsi/q_init.h +++ b/src/core/ddsi/include/dds/ddsi/q_init.h @@ -12,7 +12,15 @@ #ifndef Q_INIT_H #define Q_INIT_H +#if defined (__cplusplus) +extern "C" { +#endif + int create_multicast_sockets(void); int joinleave_spdp_defmcip (int dojoin); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h b/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h index d48cf96..cd93009 100644 --- a/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h +++ b/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h @@ -14,6 +14,10 @@ #include "dds/ddsrt/avl.h" +#if defined (__cplusplus) +extern "C" { +#endif + struct inverse_uint32_set_node { ddsrt_avl_node_t avlnode; uint32_t min, max; @@ -29,4 +33,8 @@ void inverse_uint32_set_fini(struct inverse_uint32_set *set); int inverse_uint32_set_alloc(uint32_t * const id, struct inverse_uint32_set *set); void inverse_uint32_set_free(struct inverse_uint32_set *set, uint32_t id); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/q_radmin.h b/src/core/ddsi/include/dds/ddsi/q_radmin.h index e61c029..95df0a7 100644 --- a/src/core/ddsi/include/dds/ddsi/q_radmin.h +++ b/src/core/ddsi/include/dds/ddsi/q_radmin.h @@ -14,7 +14,6 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/threads.h" -#include "dds/ddsi/q_rtps.h" #include "dds/ddsi/ddsi_tran.h" #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 9236c44..ef634a9 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xmsg.h +++ b/src/core/ddsi/include/dds/ddsi/q_xmsg.h @@ -29,6 +29,7 @@ struct proxy_writer; struct nn_prismtech_participant_version_info; struct nn_prismtech_writer_info; +struct nn_prismtech_eotinfo; struct nn_xmsgpool; struct nn_xmsg_data; struct nn_xmsg; diff --git a/src/core/ddsi/src/ddsi_eth.h b/src/core/ddsi/src/ddsi_eth.h index 60d17b7..472d3e7 100644 --- a/src/core/ddsi/src/ddsi_eth.h +++ b/src/core/ddsi/src/ddsi_eth.h @@ -14,6 +14,14 @@ #include "dds/ddsi/ddsi_tran.h" +#if defined (__cplusplus) +extern "C" { +#endif + int ddsi_eth_enumerate_interfaces(ddsi_tran_factory_t fact, ddsrt_ifaddrs_t **ifs); +#if defined (__cplusplus) +} +#endif + #endif /* DDSI_ETH_H */ diff --git a/src/core/ddsi/src/ddsi_ipaddr.c b/src/core/ddsi/src/ddsi_ipaddr.c index c124b89..88b00c5 100644 --- a/src/core/ddsi/src/ddsi_ipaddr.c +++ b/src/core/ddsi/src/ddsi_ipaddr.c @@ -18,6 +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" int ddsi_ipaddr_compare (const struct sockaddr *const sa1, const struct sockaddr *const sa2) { diff --git a/src/core/ddsi/src/ddsi_mcgroup.c b/src/core/ddsi/src/ddsi_mcgroup.c index 51ca755..4fc2eb1 100644 --- a/src/core/ddsi/src/ddsi_mcgroup.c +++ b/src/core/ddsi/src/ddsi_mcgroup.c @@ -20,6 +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/ddsrt/avl.h" struct nn_group_membership_node { diff --git a/src/core/ddsi/src/ddsi_raweth.c b/src/core/ddsi/src/ddsi_raweth.c index be789b9..98cb1d5 100644 --- a/src/core/ddsi/src/ddsi_raweth.c +++ b/src/core/ddsi/src/ddsi_raweth.c @@ -18,6 +18,7 @@ #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_error.h" #include "dds/ddsi/q_pcap.h" +#include "dds/ddsi/q_globals.h" #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index c7c2cf9..03e340e 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -24,6 +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_serdata_default.h" #define MAX_POOL_SIZE 16384 diff --git a/src/core/ddsi/src/ddsi_sertopic.c b/src/core/ddsi/src/ddsi_sertopic.c index c4971b2..a309289 100644 --- a/src/core/ddsi/src/ddsi_sertopic.c +++ b/src/core/ddsi/src/ddsi_sertopic.c @@ -37,9 +37,9 @@ void ddsi_sertopic_unref (struct ddsi_sertopic *sertopic) if (ddsrt_atomic_dec32_ov (&sertopic->refc) == 1) { ddsi_sertopic_deinit (sertopic); - ddsrt_free (sertopic->name_typename); + ddsrt_free (sertopic->name_type_name); ddsrt_free (sertopic->name); - ddsrt_free (sertopic->typename); + ddsrt_free (sertopic->type_name); ddsrt_free (sertopic); } } diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 0adbd73..2a48e78 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -25,6 +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" #define INVALID_PORT (~0u) diff --git a/src/core/ddsi/src/ddsi_tran.c b/src/core/ddsi/src/ddsi_tran.c index 1d07228..c1ef648 100644 --- a/src/core/ddsi/src/ddsi_tran.c +++ b/src/core/ddsi/src/ddsi_tran.c @@ -19,6 +19,7 @@ #include "dds/ddsi/ddsi_tran.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" +#include "dds/ddsi/q_globals.h" static ddsi_tran_factory_t ddsi_tran_factories = NULL; diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 0ab4489..628c7e0 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -25,6 +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" extern void ddsi_factory_conn_init (ddsi_tran_factory_t factory, ddsi_tran_conn_t conn); diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index 2e5358a..35ed218 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -121,7 +121,7 @@ static int print_any_endpoint_common (ddsi_tran_conn_t conn, const char *label, if (xqos->partition.n > 1) cpf (conn, "}"); x += cpf (conn, ".%s/%s", topic && topic->name ? topic->name : (xqos->present & QP_TOPIC_NAME) ? xqos->topic_name : "(null)", - topic && topic->typename ? topic->typename : (xqos->present & QP_TYPE_NAME) ? xqos->type_name : "(null)"); + topic && topic->type_name ? topic->type_name : (xqos->present & QP_TYPE_NAME) ? xqos->type_name : "(null)"); } cpf (conn, "\n"); return x; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 25ef9ea..31437b0 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -2383,7 +2383,7 @@ static void new_reader_writer_common (const struct nn_guid *guid, const struct d PGUID (*guid), partition, partition_suffix, topic ? topic->name : "(null)", - topic ? topic->typename : "(null)"); + topic ? topic->type_name : "(null)"); } static void endpoint_common_init (struct entity_common *e, struct endpoint_common *c, enum entity_kind kind, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp) @@ -2415,7 +2415,7 @@ static int set_topic_type_name (nn_xqos_t *xqos, const struct ddsi_sertopic * to if (!(xqos->present & QP_TYPE_NAME) && topic) { xqos->present |= QP_TYPE_NAME; - xqos->type_name = ddsrt_strdup (topic->typename); + xqos->type_name = ddsrt_strdup (topic->type_name); } if (!(xqos->present & QP_TOPIC_NAME) && topic) { @@ -2881,7 +2881,7 @@ struct local_orphan_writer *new_local_orphan_writer (nn_entityid_t entityid, str struct writer *wr; nn_mtime_t tnow = now_mt (); - DDS_LOG(DDS_LC_DISCOVERY, "new_local_orphan_writer(%s/%s)\n", topic->name, topic->typename); + DDS_LOG(DDS_LC_DISCOVERY, "new_local_orphan_writer(%s/%s)\n", topic->name, topic->type_name); lowr = ddsrt_malloc (sizeof (*lowr)); wr = &lowr->wr; diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index d44cec1..c02a63d 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -28,6 +28,7 @@ #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_protocol.h" /* for NN_STATUSINFO_... */ #include "dds/ddsi/q_radmin.h" /* for nn_plist_quickscan */ #include "dds/ddsi/q_static_assert.h" diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 520c334..4ae45ce 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -1885,7 +1885,7 @@ static struct ddsi_serdata *extract_sample_from_data "data(application, vendor %u.%u): %x:%x:%x:%x #%"PRId64": deserialization %s/%s failed (%s)\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (guid), sampleinfo->seq, - topic->name, topic->typename, + topic->name, topic->type_name, failmsg ? failmsg : "for reasons unknown" ); } @@ -2388,7 +2388,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con if (gap_was_valuable) { const char *tname = pwr->c.topic ? pwr->c.topic->name : "(null)"; - const char *ttname = pwr->c.topic ? pwr->c.topic->typename : "(null)"; + const char *ttname = pwr->c.topic ? pwr->c.topic->type_name : "(null)"; DDS_WARNING ("dropping oversize (%u > %u) sample %"PRId64" from remote writer %x:%x:%x:%x %s/%s\n", sampleinfo->size, config.max_sample_size, sampleinfo->seq, PGUIDPREFIX (rst->src_guid_prefix), msg->writerId.u, diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 4d67295..c83c008 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -868,7 +868,7 @@ static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist char ppbuf[1024]; int tmp; const char *tname = wr->topic ? wr->topic->name : "(null)"; - const char *ttname = wr->topic ? wr->topic->typename : "(null)"; + const char *ttname = wr->topic ? wr->topic->type_name : "(null)"; ppbuf[0] = '\0'; tmp = sizeof (ppbuf) - 1; DDS_TRACE("write_sample %x:%x:%x:%x #%"PRId64"", PGUID (wr->e.guid), seq); @@ -1043,7 +1043,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * char ppbuf[1024]; int tmp; const char *tname = wr->topic ? wr->topic->name : "(null)"; - const char *ttname = wr->topic ? wr->topic->typename : "(null)"; + const char *ttname = wr->topic ? wr->topic->type_name : "(null)"; ppbuf[0] = '\0'; tmp = sizeof (ppbuf) - 1; DDS_WARNING ("dropping oversize (%u > %u) sample from local writer %x:%x:%x:%x %s/%s:%s%s\n", diff --git a/src/ddsrt/include/dds/ddsrt/atomics/arm.h b/src/ddsrt/include/dds/ddsrt/atomics/arm.h index e0b0d1c..863e483 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/arm.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/arm.h @@ -12,6 +12,10 @@ #ifndef DDSRT_ATOMICS_ARM_H #define DDSRT_ATOMICS_ARM_H +#if defined (__cplusplus) +extern "C" { +#endif + #if !defined(__arm__) #define __arm__ #endif @@ -209,5 +213,8 @@ inline void ddsrt_atomic_fence_rel (void) { ddsrt_atomic_fence (); } -#endif /* DDSRT_ATOMICS_ARM_H */ +#if defined (__cplusplus) +} +#endif +#endif /* DDSRT_ATOMICS_ARM_H */ diff --git a/src/ddsrt/include/dds/ddsrt/atomics/gcc.h b/src/ddsrt/include/dds/ddsrt/atomics/gcc.h index 0c62272..4da5f29 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/gcc.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/gcc.h @@ -14,6 +14,10 @@ #include "dds/ddsrt/misc.h" +#if defined (__cplusplus) +extern "C" { +#endif + #if ( DDSRT_HAVE_ATOMIC64 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) || \ (!DDSRT_HAVE_ATOMIC64 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) # define DDSRT_HAVE_ATOMIC_LIFO 1 @@ -287,5 +291,8 @@ inline void ddsrt_atomic_fence_rel (void) { ddsrt_atomic_fence (); } -#endif /* DDSRT_ATOMICS_GCC_H */ +#if defined (__cplusplus) +} +#endif +#endif /* DDSRT_ATOMICS_GCC_H */ diff --git a/src/ddsrt/include/dds/ddsrt/atomics/msvc.h b/src/ddsrt/include/dds/ddsrt/atomics/msvc.h index 01260aa..e4418e1 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/msvc.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/msvc.h @@ -14,6 +14,10 @@ #include "dds/ddsrt/misc.h" +#if defined (__cplusplus) +extern "C" { +#endif + /* x86 has supported 64-bit CAS for a long time, so Windows ought to provide all the interlocked operations for 64-bit operands on x86 platforms, but it doesn't. */ @@ -295,5 +299,8 @@ inline void ddsrt_atomic_fence_rel (void) { #undef DDSRT_ATOMIC_PTROP -#endif /* DDSRT_ATOMICS_MSVC_H */ +#if defined (__cplusplus) +} +#endif +#endif /* DDSRT_ATOMICS_MSVC_H */ diff --git a/src/ddsrt/include/dds/ddsrt/atomics/sun.h b/src/ddsrt/include/dds/ddsrt/atomics/sun.h index bd364d4..74a7469 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/sun.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/sun.h @@ -11,6 +11,10 @@ */ #include +#if defined (__cplusplus) +extern "C" { +#endif + #define DDSRT_ATOMIC64_SUPPORT 1 /* LD, ST */ @@ -239,3 +243,6 @@ inline void ddsrt_atomic_fence_rel (void) { membar_exit (); } +#if defined (__cplusplus) +} +#endif diff --git a/src/ddsrt/include/dds/ddsrt/cdtors.h b/src/ddsrt/include/dds/ddsrt/cdtors.h index 0b3e733..89e8cdb 100644 --- a/src/ddsrt/include/dds/ddsrt/cdtors.h +++ b/src/ddsrt/include/dds/ddsrt/cdtors.h @@ -15,10 +15,18 @@ #include "dds/export.h" #include "dds/ddsrt/sync.h" +#if defined (__cplusplus) +extern "C" { +#endif + DDS_EXPORT void ddsrt_init(void); DDS_EXPORT void ddsrt_fini(void); DDS_EXPORT ddsrt_mutex_t *ddsrt_get_singleton_mutex(void); +#if defined (__cplusplus) +} +#endif + #endif /* DDSRT_CDTORS_H */ diff --git a/src/ddsrt/include/dds/ddsrt/md5.h b/src/ddsrt/include/dds/ddsrt/md5.h index 4777d04..5d0f167 100644 --- a/src/ddsrt/include/dds/ddsrt/md5.h +++ b/src/ddsrt/include/dds/ddsrt/md5.h @@ -63,6 +63,7 @@ #define DDSRT_MD5_H #include +#include "dds/export.h" /* * This package supports both compile-time and run-time determination of CPU @@ -90,13 +91,13 @@ extern "C" #endif /* Initialize the algorithm. */ -void ddsrt_md5_init(ddsrt_md5_state_t *pms); +DDS_EXPORT void ddsrt_md5_init(ddsrt_md5_state_t *pms); /* Append a string to the message. */ -void ddsrt_md5_append(ddsrt_md5_state_t *pms, const ddsrt_md5_byte_t *data, unsigned nbytes); +DDS_EXPORT void ddsrt_md5_append(ddsrt_md5_state_t *pms, const ddsrt_md5_byte_t *data, unsigned nbytes); /* Finish the message and return the digest. */ -void ddsrt_md5_finish(ddsrt_md5_state_t *pms, ddsrt_md5_byte_t digest[16]); +DDS_EXPORT void ddsrt_md5_finish(ddsrt_md5_state_t *pms, ddsrt_md5_byte_t digest[16]); #ifdef __cplusplus } /* end extern "C" */ diff --git a/src/ddsrt/include/dds/ddsrt/retcode.h b/src/ddsrt/include/dds/ddsrt/retcode.h index 8651e22..f57626d 100644 --- a/src/ddsrt/include/dds/ddsrt/retcode.h +++ b/src/ddsrt/include/dds/ddsrt/retcode.h @@ -5,6 +5,10 @@ #include "dds/export.h" +#if defined (__cplusplus) +extern "C" { +#endif + typedef int32_t dds_retcode_t; /* @@ -86,4 +90,8 @@ typedef int32_t dds_retcode_t; */ DDS_EXPORT const char *dds_strretcode(dds_retcode_t ret); +#if defined (__cplusplus) +} +#endif + #endif /* DDS_RETCODE_H */ diff --git a/src/ddsrt/include/dds/ddsrt/rusage.h b/src/ddsrt/include/dds/ddsrt/rusage.h index 2147876..040ce2e 100644 --- a/src/ddsrt/include/dds/ddsrt/rusage.h +++ b/src/ddsrt/include/dds/ddsrt/rusage.h @@ -17,6 +17,10 @@ #include "dds/ddsrt/time.h" #include "dds/ddsrt/retcode.h" +#if defined (__cplusplus) +extern "C" { +#endif + typedef struct { dds_time_t utime; /* User CPU time used. */ dds_time_t stime; /* System CPU time used. */ @@ -47,4 +51,8 @@ typedef struct { */ DDS_EXPORT dds_retcode_t ddsrt_getrusage(int who, ddsrt_rusage_t *usage); +#if defined (__cplusplus) +} +#endif + #endif /* DDSRT_RUSAGE_H */ diff --git a/src/ddsrt/include/dds/ddsrt/sockets.h b/src/ddsrt/include/dds/ddsrt/sockets.h index 645af42..ec5efa3 100644 --- a/src/ddsrt/include/dds/ddsrt/sockets.h +++ b/src/ddsrt/include/dds/ddsrt/sockets.h @@ -14,6 +14,10 @@ #include "dds/ddsrt/sockets/posix.h" #endif +#if defined (__cplusplus) +extern "C" { +#endif + #define INET_ADDRSTRLEN_EXTENDED (INET_ADDRSTRLEN + 6) /* ":12345" */ #if DDSRT_HAVE_IPV6 @@ -261,4 +265,8 @@ ddsrt_gethostbyname( ddsrt_hostent_t **hentp); #endif +#if defined (__cplusplus) +} +#endif + #endif /* DDSRT_SOCKETS_H */ diff --git a/src/ddsrt/include/dds/ddsrt/strtod.h b/src/ddsrt/include/dds/ddsrt/strtod.h index 739ee94..f8bb511 100644 --- a/src/ddsrt/include/dds/ddsrt/strtod.h +++ b/src/ddsrt/include/dds/ddsrt/strtod.h @@ -22,6 +22,10 @@ #include "dds/export.h" #include "dds/ddsrt/retcode.h" +#if defined (__cplusplus) +extern "C" { +#endif + /** * @brief Convert a string to a double precision floating point number. * @@ -72,4 +76,8 @@ ddsrt_dtostr(double src, char *str, size_t size); DDS_EXPORT int ddsrt_ftostr(float src, char *str, size_t size); +#if defined (__cplusplus) +} +#endif + #endif /* DDSRT_STRTOD_H */ From ca35c7afb2362c914456211df11d78e9f68688c5 Mon Sep 17 00:00:00 2001 From: YuSheng Date: Tue, 30 Apr 2019 01:09:40 +0800 Subject: [PATCH 051/178] add RPATH for compiled tools to find the libddsc.so (#153) * add RPATH for compiled tools to find the libddsc.so Signed-off-by: YuSheng --- src/CMakeLists.txt | 5 +++++ src/tools/pubsub/CMakeLists.txt | 1 + 2 files changed, 6 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e56d494..d1539dd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -154,6 +154,11 @@ endif() include(GNUInstallDirs) include(AnalyzeBuild) +if(APPLE) + set(CMAKE_INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR}") +else() + set(CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") +endif() # Include Coverage before CTest so that COVERAGE_COMMAND can be modified # in the Coverage module should that ever be necessary. include(Coverage) diff --git a/src/tools/pubsub/CMakeLists.txt b/src/tools/pubsub/CMakeLists.txt index f7244c7..62a9494 100644 --- a/src/tools/pubsub/CMakeLists.txt +++ b/src/tools/pubsub/CMakeLists.txt @@ -11,6 +11,7 @@ # add_executable(pubsub pubsub.c common.c testtype.c porting.c) target_link_libraries(pubsub ddsc) + if(WIN32) target_compile_definitions(pubsub PRIVATE _CRT_SECURE_NO_WARNINGS) endif() From c9d827e420b7074a9b319f2faaddae09ed0d961f Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Mon, 29 Apr 2019 15:57:14 +0200 Subject: [PATCH 052/178] Fix warnings related to fixed type integers Signed-off-by: Jeroen Koekkoek --- src/core/ddsc/src/dds_init.c | 6 +- src/core/ddsc/src/dds_qos.c | 2 +- src/core/ddsc/src/dds_rhc.c | 26 ++-- src/core/ddsc/src/dds_write.c | 4 +- src/core/ddsi/include/dds/ddsi/q_rtps.h | 1 + src/core/ddsi/src/ddsi_tcp.c | 18 +-- src/core/ddsi/src/ddsi_threadmon.c | 2 +- src/core/ddsi/src/ddsi_udp.c | 14 +-- src/core/ddsi/src/q_ddsi_discovery.c | 72 +++++------ src/core/ddsi/src/q_entity.c | 154 ++++++++++++------------ src/core/ddsi/src/q_init.c | 16 +-- src/core/ddsi/src/q_lease.c | 16 +-- src/core/ddsi/src/q_nwif.c | 6 +- src/core/ddsi/src/q_plist.c | 44 +++---- src/core/ddsi/src/q_radmin.c | 32 ++--- src/core/ddsi/src/q_receive.c | 120 +++++++++--------- src/core/ddsi/src/q_sockwaitset.c | 2 +- src/core/ddsi/src/q_thread.c | 2 +- src/core/ddsi/src/q_transmit.c | 20 +-- src/core/ddsi/src/q_xevent.c | 38 +++--- src/core/ddsi/src/q_xmsg.c | 16 +-- src/tools/ddsperf/ddsperf.c | 4 +- 22 files changed, 308 insertions(+), 307 deletions(-) diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 9e74180..9db9187 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -96,7 +96,7 @@ dds_init(dds_domainid_t domain) { if (domain < 0 || domain > 230) { - DDS_ERROR("requested domain id %d is out of range\n", domain); + DDS_ERROR("requested domain id %"PRId32" is out of range\n", domain); ret = DDS_ERRNO(DDS_RETCODE_ERROR); goto fail_config_domainid; } @@ -106,7 +106,7 @@ dds_init(dds_domainid_t domain) } else if (domain != config.domainId.value) { - DDS_ERROR("requested domain id %d is inconsistent with configured value %d\n", domain, config.domainId.value); + DDS_ERROR("requested domain id %"PRId32" is inconsistent with configured value %"PRId32"\n", domain, config.domainId.value); ret = DDS_ERRNO(DDS_RETCODE_ERROR); goto fail_config_domainid; } @@ -298,7 +298,7 @@ dds__check_domain( if (domain != dds_global.m_default_domain) { DDS_ERROR("Inconsistent domain configuration detected: domain on " - "configuration: %d, domain %d\n", dds_global.m_default_domain, domain); + "configuration: %"PRId32", domain %"PRId32"\n", dds_global.m_default_domain, domain); ret = DDS_ERRNO(DDS_RETCODE_ERROR); } } diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index d95add8..b53d046 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -537,7 +537,7 @@ void dds_qset_partition return ; } if(n && !ps) { - DDS_ERROR("Argument ps is NULL, but n (%u) > 0", n); + DDS_ERROR("Argument ps is NULL, but n (%"PRIu32") > 0", n); return ; } diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 74133c0..79a134a 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -1757,7 +1757,7 @@ static int dds_rhc_read_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ ddsrt_mutex_lock (&rhc->lock); } - TRACE ("read_w_qminv(%p,%p,%p,%u,%x,%p) - inst %u nonempty %u disp %u nowr %u new %u samples %u+%u read %u+%u\n", + TRACE ("read_w_qminv(%p,%p,%p,%"PRIu32",%x,%p) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32"+%"PRIu32" read %"PRIu32"+%"PRIu32"\n", (void *) rhc, (void *) values, (void *) info_seq, max_samples, qminv, (void *) cond, rhc->n_instances, rhc->n_nonempty_instances, rhc->n_not_alive_disposed, rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, rhc->n_invsamples, @@ -1858,7 +1858,7 @@ static int dds_rhc_read_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ } while (inst != end && n < max_samples); } - TRACE ("read: returning %u\n", n); + TRACE ("read: returning %"PRIu32"\n", n); assert (rhc_check_counts_locked (rhc, true, false)); ddsrt_mutex_unlock (&rhc->lock); @@ -1880,7 +1880,7 @@ static int dds_rhc_take_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ ddsrt_mutex_lock (&rhc->lock); } - TRACE ("take_w_qminv(%p,%p,%p,%u,%x) - inst %u nonempty %u disp %u nowr %u new %u samples %u+%u read %u+%u\n", + TRACE ("take_w_qminv(%p,%p,%p,%"PRIu32",%x) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32"+%"PRIu32" read %"PRIu32"+%"PRIu32"\n", (void*) rhc, (void*) values, (void*) info_seq, max_samples, qminv, rhc->n_instances, rhc->n_nonempty_instances, rhc->n_not_alive_disposed, rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, @@ -2020,7 +2020,7 @@ static int dds_rhc_take_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ inst = inst1; } } - TRACE ("take: returning %u\n", n); + TRACE ("take: returning %"PRIu32"\n", n); assert (rhc_check_counts_locked (rhc, true, false)); ddsrt_mutex_unlock (&rhc->lock); @@ -2043,7 +2043,7 @@ static int dds_rhc_takecdr_w_qminv (struct rhc *rhc, bool lock, struct ddsi_serd ddsrt_mutex_lock (&rhc->lock); } - TRACE ("take_w_qminv(%p,%p,%p,%u,%x) - inst %u nonempty %u disp %u nowr %u new %u samples %u+%u read %u+%u\n", + TRACE ("take_w_qminv(%p,%p,%p,%"PRIu32",%x) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32"+%"PRIu32" read %"PRIu32"+%"PRIu32"\n", (void*) rhc, (void*) values, (void*) info_seq, max_samples, qminv, rhc->n_instances, rhc->n_nonempty_instances, rhc->n_not_alive_disposed, rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, @@ -2172,7 +2172,7 @@ static int dds_rhc_takecdr_w_qminv (struct rhc *rhc, bool lock, struct ddsi_serd inst = inst1; } } - TRACE ("take: returning %u\n", n); + TRACE ("take: returning %"PRIu32"\n", n); assert (rhc_check_counts_locked (rhc, true, false)); ddsrt_mutex_unlock (&rhc->lock); @@ -2205,7 +2205,7 @@ static uint32_t rhc_get_cond_trigger (struct rhc_instance * const inst, const dd m = m && !inst_is_empty (inst); break; default: - DDS_FATAL("update_readconditions: sample_states invalid: %x\n", c->m_sample_states); + DDS_FATAL("update_readconditions: sample_states invalid: %"PRIx32"\n", c->m_sample_states); } return m ? 1 : 0; } @@ -2221,7 +2221,7 @@ static bool cond_is_sample_state_dependent (const struct dds_readcond *cond) case 0: return false; default: - DDS_FATAL("update_readconditions: sample_states invalid: %x\n", cond->m_sample_states); + DDS_FATAL("update_readconditions: sample_states invalid: %"PRIx32"\n", cond->m_sample_states); return false; } } @@ -2322,7 +2322,7 @@ bool dds_rhc_add_readcondition (dds_readcond *cond) if (cond->m_entity.m_trigger) dds_entity_status_signal (&cond->m_entity); - TRACE ("add_readcondition(%p, %x, %x, %x) => %p qminv %x ; rhc %u conds\n", + TRACE ("add_readcondition(%p, %"PRIx32", %"PRIx32", %"PRIx32") => %p qminv %"PRIx32" ; rhc %"PRIu32" conds\n", (void *) rhc, cond->m_sample_states, cond->m_view_states, cond->m_instance_states, (void *) cond, cond->m_qminv, rhc->nconds); @@ -2362,10 +2362,10 @@ static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, dds_readcond *iter; bool m_pre, m_post; - TRACE ("update_conditions_locked(%p %p) - inst %u nonempty %u disp %u nowr %u new %u samples %u read %u\n", + TRACE ("update_conditions_locked(%p %p) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32" read %"PRIu32"\n", (void *) rhc, (void *) inst, rhc->n_instances, rhc->n_nonempty_instances, rhc->n_not_alive_disposed, rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, rhc->n_vread); - TRACE (" read -[%d,%d]+[%d,%d] qcmask -[%x,%x]+[%x,%x]\n", + TRACE (" read -[%d,%d]+[%d,%d] qcmask -[%"PRIx32",%"PRIx32"]+[%"PRIx32",%"PRIx32"]\n", trig_qc->dec_invsample_read, trig_qc->dec_sample_read, trig_qc->inc_invsample_read, trig_qc->inc_sample_read, trig_qc->dec_conds_invsample, trig_qc->dec_conds_sample, trig_qc->inc_conds_invsample, trig_qc->inc_conds_sample); @@ -2404,7 +2404,7 @@ static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, m_post = m_post && (post->c.has_read + post->c.has_not_read); break; default: - DDS_FATAL ("update_readconditions: sample_states invalid: %x\n", iter->m_sample_states); + DDS_FATAL ("update_readconditions: sample_states invalid: %"PRIx32"\n", iter->m_sample_states); } TRACE (" cond %p %08"PRIx32": ", (void *) iter, iter->m_query.m_qcmask); @@ -2464,7 +2464,7 @@ static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, mdelta += (trig_qc->inc_conds_sample & qcmask) != 0; break; default: - DDS_FATAL ("update_readconditions: sample_states invalid: %x\n", iter->m_sample_states); + DDS_FATAL ("update_readconditions: sample_states invalid: %"PRIx32"\n", iter->m_sample_states); } if (m_pre == m_post) diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 98a590b..032141a 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -106,7 +106,7 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay unsigned i; make_proxy_writer_info (&pwr_info, &wr->e, wr->xqos); for (i = 0; rdary[i]; i++) { - DDS_TRACE ("reader %x:%x:%x:%x\n", PGUID (rdary[i]->e.guid)); + DDS_TRACE ("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; } @@ -135,7 +135,7 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay struct reader *rd; if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) { - DDS_TRACE("reader-via-guid %x:%x:%x:%x\n", PGUID (rd->e.guid)); + DDS_TRACE("reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid)); /* Copied the return value ignore from DDSI deliver_user_data() function. */ if ((ret = try_store (rd->rhc, &pwr_info, payload, tk, &max_block_ms)) != DDS_RETCODE_OK) break; diff --git a/src/core/ddsi/include/dds/ddsi/q_rtps.h b/src/core/ddsi/include/dds/ddsi/q_rtps.h index 731fbd9..57e3d0a 100644 --- a/src/core/ddsi/include/dds/ddsi/q_rtps.h +++ b/src/core/ddsi/include/dds/ddsi/q_rtps.h @@ -37,6 +37,7 @@ typedef int64_t seqno_t; #define PGUIDPREFIX(gp) (gp).u[0], (gp).u[1], (gp).u[2] #define PGUID(g) PGUIDPREFIX ((g).prefix), (g).entityid.u +#define PGUIDFMT "%"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32 /* predefined entity ids; here viewed as an unsigned int, on the network as four bytes corresponding to the integer in network byte diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 2a48e78..8d7ec2b 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -154,7 +154,7 @@ static unsigned short get_socket_port (ddsrt_socket_t socket) ret = ddsrt_getsockname(socket, (struct sockaddr *)&addr, &addrlen); if (ret != DDS_RETCODE_OK) { - DDS_ERROR("ddsi_tcp_get_socket_port: ddsrt_getsockname retcode %d\n", ret); + DDS_ERROR("ddsi_tcp_get_socket_port: ddsrt_getsockname retcode %"PRId32"\n", ret); return 0; } return ddsrt_sockaddr_get_port((struct sockaddr *)&addr); @@ -435,7 +435,7 @@ static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s } else { - DDS_LOG(DDS_LC_TCP, "%s read: sock %"PRIdSOCK" error %d\n", ddsi_name, tcp->m_sock, rc); + DDS_LOG(DDS_LC_TCP, "%s read: sock %"PRIdSOCK" error %"PRId32"\n", ddsi_name, tcp->m_sock, rc); break; } } @@ -500,7 +500,7 @@ static ssize_t ddsi_tcp_block_write } else { - DDS_LOG(DDS_LC_TCP, "%s write: sock %"PRIdSOCK" error %d\n", ddsi_name, conn->m_sock, rc); + DDS_LOG(DDS_LC_TCP, "%s write: sock %"PRIdSOCK" error %"PRId32"\n", ddsi_name, conn->m_sock, rc); break; } } @@ -638,7 +638,7 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const nn_locator_t *d break; default: if (! conn->m_base.m_closed && (conn->m_sock != DDSRT_INVALID_SOCKET)) - DDS_WARNING("%s write failed on socket %"PRIdSOCK" with errno %d\n", ddsi_name, conn->m_sock, rc); + DDS_WARNING("%s write failed on socket %"PRIdSOCK" with errno %"PRId32"\n", ddsi_name, conn->m_sock, rc); break; } } @@ -775,11 +775,11 @@ static ddsi_tran_conn_t ddsi_tcp_accept (ddsi_tran_listener_t listener) { (void)ddsrt_getsockname (tl->m_sock, (struct sockaddr *) &addr, &addrlen); sockaddr_to_string_with_port(buff, sizeof(buff), (struct sockaddr *)&addr); - DDS_LOG((rc == DDS_RETCODE_OK) ? DDS_LC_ERROR : DDS_LC_FATAL, "%s accept failed on socket %"PRIdSOCK" at %s retcode %d\n", ddsi_name, tl->m_sock, buff, rc); + DDS_LOG((rc == DDS_RETCODE_OK) ? DDS_LC_ERROR : DDS_LC_FATAL, "%s accept failed on socket %"PRIdSOCK" at %s retcode %"PRId32"\n", ddsi_name, tl->m_sock, buff, rc); } else if (getpeername (sock, (struct sockaddr *) &addr, &addrlen) == -1) { - DDS_WARNING("%s accepted new socket %"PRIdSOCK" on socket %"PRIdSOCK" but no peer address, errno %d\n", ddsi_name, sock, tl->m_sock, rc); + DDS_WARNING("%s accepted new socket %"PRIdSOCK" on socket %"PRIdSOCK" but no peer address, errno %"PRId32"\n", ddsi_name, sock, tl->m_sock, rc); ddsrt_close (sock); } else @@ -886,7 +886,7 @@ static ddsi_tran_listener_t ddsi_tcp_create_listener (int port, ddsi_tran_qos_t ret = ddsrt_getsockname(sock, (struct sockaddr *)&addr, &addrlen); if (ret != DDS_RETCODE_OK) { - DDS_ERROR("ddsi_tcp_create_listener: ddsrt_getsockname returned %d\n", ret); + DDS_ERROR("ddsi_tcp_create_listener: ddsrt_getsockname returned %"PRId32"\n", ret); ddsi_tcp_sock_free(sock, NULL); ddsrt_free(tl); return NULL; @@ -958,7 +958,7 @@ static void ddsi_tcp_unblock_listener (ddsi_tran_listener_t listener) ret = ddsrt_getsockname(tl->m_sock, (struct sockaddr *)&addr, &addrlen); if (ret != DDS_RETCODE_OK) { - DDS_WARNING("%s failed to get listener address error %d\n", ddsi_name, ret); + DDS_WARNING("%s failed to get listener address error %"PRId32"\n", ddsi_name, ret); } else { switch (addr.ss_family) { case AF_INET: @@ -988,7 +988,7 @@ static void ddsi_tcp_unblock_listener (ddsi_tran_listener_t listener) { char buff[DDSI_LOCSTRLEN]; sockaddr_to_string_with_port(buff, sizeof(buff), (struct sockaddr *)&addr); - DDS_WARNING("%s failed to connect to own listener (%s) error %d\n", ddsi_name, buff, ret); + DDS_WARNING("%s failed to connect to own listener (%s) error %"PRId32"\n", ddsi_name, buff, ret); } } ddsi_tcp_sock_free (sock, NULL); diff --git a/src/core/ddsi/src/ddsi_threadmon.c b/src/core/ddsi/src/ddsi_threadmon.c index 755848c..f257261 100644 --- a/src/core/ddsi/src/ddsi_threadmon.c +++ b/src/core/ddsi/src/ddsi_threadmon.c @@ -88,7 +88,7 @@ static uint32_t threadmon_thread (struct ddsi_threadmon *sl) vtime_t vt = thread_states.ts[i].vtime; bool alive = vtime_asleep_p (vt) || vtime_asleep_p (sl->av_ary[i].vt) || vtime_gt (vt, sl->av_ary[i].vt); n_alive += (unsigned) alive; - DDS_TRACE(" %u(%s):%c:%x->%x", i, thread_states.ts[i].name, alive ? 'a' : 'd', sl->av_ary[i].vt, vt); + DDS_TRACE(" %u(%s):%c:%"PRIx32"->%"PRIx32, i, thread_states.ts[i].name, alive ? 'a' : 'd', sl->av_ary[i].vt, vt); sl->av_ary[i].vt = vt; if (sl->av_ary[i].alive != alive) { diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 628c7e0..53135f1 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -103,7 +103,7 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s else if (rc != DDS_RETCODE_BAD_PARAMETER && rc != DDS_RETCODE_NO_CONNECTION) { - DDS_ERROR("UDP recvmsg sock %d: ret %d retcode %d\n", (int) ((ddsi_udp_conn_t) conn)->m_sock, (int) ret, rc); + DDS_ERROR("UDP recvmsg sock %d: ret %d retcode %"PRId32"\n", (int) ((ddsi_udp_conn_t) conn)->m_sock, (int) ret, rc); ret = -1; } return ret; @@ -168,7 +168,7 @@ static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *d rc != DDS_RETCODE_NOT_ALLOWED && rc != DDS_RETCODE_NO_CONNECTION) { - DDS_ERROR("ddsi_udp_conn_write failed with retcode %d\n", rc); + DDS_ERROR("ddsi_udp_conn_write failed with retcode %"PRId32"\n", rc); } return (rc == DDS_RETCODE_OK ? ret : -1); } @@ -220,7 +220,7 @@ static unsigned short get_socket_port (ddsrt_socket_t socket) ret = ddsrt_getsockname (socket, (struct sockaddr *)&addr, &addrlen); if (ret != DDS_RETCODE_OK) { - DDS_ERROR("ddsi_udp_get_socket_port: getsockname returned %d\n", ret); + DDS_ERROR("ddsi_udp_get_socket_port: getsockname returned %"PRId32"\n", ret); return 0; } @@ -273,7 +273,7 @@ static ddsi_tran_conn_t ddsi_udp_create_conn DDS_TRACE ( - "ddsi_udp_create_conn %s socket %"PRIdSOCK" port %u\n", + "ddsi_udp_create_conn %s socket %"PRIdSOCK" port %"PRIu32"\n", mcast ? "multicast" : "unicast", uc->m_sock, uc->m_base.m_base.m_port @@ -284,7 +284,7 @@ static ddsi_tran_conn_t ddsi_udp_create_conn dds_retcode_t rc; rc = ddsrt_setsockopt(sock, IPPROTO_IP, IP_TOS, (char *)&uc->m_diffserv, sizeof(uc->m_diffserv)); if (rc != DDS_RETCODE_OK) - DDS_ERROR("ddsi_udp_create_conn: set diffserv retcode %d\n", rc); + DDS_ERROR("ddsi_udp_create_conn: set diffserv retcode %"PRId32"\n", rc); } #endif } @@ -294,7 +294,7 @@ static ddsi_tran_conn_t ddsi_udp_create_conn { DDS_ERROR ( - "UDP make_socket failed for %s port %u\n", + "UDP make_socket failed for %s port %"PRIu32"\n", mcast ? "multicast" : "unicast", port ); @@ -395,7 +395,7 @@ static void ddsi_udp_release_conn (ddsi_tran_conn_t conn) ddsi_udp_conn_t uc = (ddsi_udp_conn_t) conn; DDS_TRACE ( - "ddsi_udp_release_conn %s socket %"PRIdSOCK" port %u\n", + "ddsi_udp_release_conn %s socket %"PRIdSOCK" port %"PRIu32"\n", conn->m_base.m_multicast ? "multicast" : "unicast", uc->m_sock, uc->m_base.m_base.m_port diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 12ab0bc..98e89f7 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -198,11 +198,11 @@ int spdp_write (struct participant *pp) return 0; } - DDS_TRACE("spdp_write(%x:%x:%x:%x)\n", PGUID (pp->e.guid)); + DDS_TRACE("spdp_write("PGUIDFMT")\n", PGUID (pp->e.guid)); if ((wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL) { - DDS_TRACE("spdp_write(%x:%x:%x:%x) - builtin participant writer not found\n", PGUID (pp->e.guid)); + DDS_TRACE("spdp_write("PGUIDFMT") - builtin participant writer not found\n", PGUID (pp->e.guid)); return 0; } @@ -307,7 +307,7 @@ int spdp_write (struct participant *pp) size = strlen(node) + strlen(DDS_VERSION) + strlen(DDS_HOST_NAME) + strlen(DDS_TARGET_NAME) + 4; /* + ///'\0' */ ps.prismtech_participant_version_info.internals = ddsrt_malloc(size); (void) snprintf(ps.prismtech_participant_version_info.internals, size, "%s/%s/%s/%s", node, DDS_VERSION, DDS_HOST_NAME, DDS_TARGET_NAME); - DDS_TRACE("spdp_write(%x:%x:%x:%x) - internals: %s\n", PGUID (pp->e.guid), ps.prismtech_participant_version_info.internals); + DDS_TRACE("spdp_write("PGUIDFMT") - internals: %s\n", PGUID (pp->e.guid), ps.prismtech_participant_version_info.internals); } /* 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. */ @@ -335,7 +335,7 @@ int spdp_dispose_unregister (struct participant *pp) if ((wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL) { - DDS_TRACE("spdp_dispose_unregister(%x:%x:%x:%x) - builtin participant writer not found\n", PGUID (pp->e.guid)); + DDS_TRACE("spdp_dispose_unregister("PGUIDFMT") - builtin participant writer not found\n", PGUID (pp->e.guid)); return 0; } @@ -416,7 +416,7 @@ static int handle_SPDP_dead (const struct receiver_state *rst, nn_wctime_t times if (datap->present & PP_PARTICIPANT_GUID) { guid = datap->participant_guid; - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x", PGUID (guid)); + DDS_LOG(DDS_LC_DISCOVERY, " %"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32, PGUID (guid)); assert (guid.entityid.u == NN_ENTITYID_PARTICIPANT); if (delete_proxy_participant_by_guid (&guid, timestamp, 0) < 0) { @@ -481,7 +481,7 @@ static void make_participants_dependent_on_ddsi2 (const nn_guid_t *ddsi2guid, nn { if (vendor_is_eclipse_or_opensplice (pp->vendor) && pp->e.guid.prefix.u[0] == ddsi2guid->prefix.u[0] && !pp->is_ddsi2_pp) { - DDS_TRACE("proxy participant %x:%x:%x:%x depends on ddsi2 %x:%x:%x:%x", PGUID (pp->e.guid), PGUID (*ddsi2guid)); + DDS_TRACE("proxy participant "PGUIDFMT" depends on ddsi2 "PGUIDFMT, PGUID (pp->e.guid), PGUID (*ddsi2guid)); ddsrt_mutex_lock (&pp->e.lock); pp->privileged_pp_guid = *ddsi2guid; ddsrt_mutex_unlock (&pp->e.lock); @@ -501,7 +501,7 @@ static void make_participants_dependent_on_ddsi2 (const nn_guid_t *ddsi2guid, nn if (pp != NULL) { - DDS_TRACE("make_participants_dependent_on_ddsi2: ddsi2 %x:%x:%x:%x is no more, delete %x:%x:%x:%x\n", PGUID (*ddsi2guid), PGUID (pp->e.guid)); + DDS_TRACE("make_participants_dependent_on_ddsi2: ddsi2 "PGUIDFMT" is no more, delete "PGUIDFMT"\n", PGUID (*ddsi2guid), PGUID (pp->e.guid)); delete_proxy_participant_by_guid (&pp->e.guid, timestamp, 1); } } @@ -569,7 +569,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time if (is_deleted_participant_guid (&datap->participant_guid, DPG_REMOTE)) { - DDS_LOG(DDS_LC_TRACE, "SPDP ST0 %x:%x:%x:%x (recently deleted)", PGUID (datap->participant_guid)); + DDS_LOG(DDS_LC_TRACE, "SPDP ST0 "PGUIDFMT" (recently deleted)", PGUID (datap->participant_guid)); return 1; } @@ -579,7 +579,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time islocal = 1; if (islocal) { - DDS_LOG(DDS_LC_TRACE, "SPDP ST0 %x:%x:%x:%x (local %d)", islocal, PGUID (datap->participant_guid)); + DDS_LOG(DDS_LC_TRACE, "SPDP ST0 "PGUIDFMT" (local %d)", PGUID (datap->participant_guid), islocal); return 0; } } @@ -590,7 +590,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time are even skipping the automatic lease renewal. Therefore do it regardless of config.arrival_of_data_asserts_pp_and_ep_liveliness. */ - DDS_LOG(DDS_LC_TRACE, "SPDP ST0 %x:%x:%x:%x (known)", PGUID (datap->participant_guid)); + DDS_LOG(DDS_LC_TRACE, "SPDP ST0 "PGUIDFMT" (known)", PGUID (datap->participant_guid)); lease_renew (ddsrt_atomic_ldvoidp (&proxypp->lease), now_et ()); ddsrt_mutex_lock (&proxypp->e.lock); if (proxypp->implicitly_created) @@ -603,7 +603,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time return 0; } - DDS_LOG(DDS_LC_DISCOVERY, "SPDP ST0 %x:%x:%x:%x bes %x ptbes %x NEW", PGUID (datap->participant_guid), builtin_endpoint_set, prismtech_builtin_endpoint_set); + DDS_LOG(DDS_LC_DISCOVERY, "SPDP ST0 "PGUIDFMT" bes %x ptbes %x NEW", PGUID (datap->participant_guid), builtin_endpoint_set, prismtech_builtin_endpoint_set); if (datap->present & PP_PARTICIPANT_LEASE_DURATION) { @@ -643,7 +643,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time if ((builtin_endpoint_set & bes_sedp_announcer_mask) != bes_sedp_announcer_mask && memcmp (&privileged_pp_guid, &datap->participant_guid, sizeof (nn_guid_t)) != 0) { - DDS_LOG(DDS_LC_DISCOVERY, " (depends on %x:%x:%x:%x)", PGUID (privileged_pp_guid)); + DDS_LOG(DDS_LC_DISCOVERY, " (depends on "PGUIDFMT")", PGUID (privileged_pp_guid)); /* never expire lease for this proxy: it won't actually expire until the "privileged" one expires anyway */ lease_duration = nn_to_ddsi_duration (T_NEVER); @@ -659,7 +659,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time { privileged_pp_guid.prefix = ddsi2->e.guid.prefix; lease_duration = nn_to_ddsi_duration (T_NEVER); - DDS_LOG(DDS_LC_DISCOVERY, " (depends on %x:%x:%x:%x)", PGUID (privileged_pp_guid)); + DDS_LOG(DDS_LC_DISCOVERY, " (depends on "PGUIDFMT")", PGUID (privileged_pp_guid)); } } else @@ -772,7 +772,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time of DDSI2. */ if (ephash_lookup_proxy_participant_guid (&privileged_pp_guid) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "make_participants_dependent_on_ddsi2: ddsi2 %x:%x:%x:%x is no more, delete %x:%x:%x:%x\n", PGUID (privileged_pp_guid), PGUID (datap->participant_guid)); + DDS_LOG(DDS_LC_DISCOVERY, "make_participants_dependent_on_ddsi2: ddsi2 "PGUIDFMT" is no more, delete "PGUIDFMT"\n", PGUID (privileged_pp_guid), PGUID (datap->participant_guid)); delete_proxy_participant_by_guid (&datap->participant_guid, timestamp, 1); } } @@ -943,7 +943,7 @@ static int sedp_write_endpoint nn_xmsg_addpar_sentinel (mpayload); nn_plist_fini (&ps); - DDS_LOG(DDS_LC_DISCOVERY, "sedp: write for %x:%x:%x:%x via %x:%x:%x:%x\n", PGUID (*epguid), PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "sedp: write for "PGUIDFMT" via "PGUIDFMT"\n", PGUID (*epguid), PGUID (wr->e.guid)); ret = write_mpayload (wr, alive, PID_ENDPOINT_GUID, mpayload); nn_xmsg_free (mpayload); return ret; @@ -953,7 +953,7 @@ static struct writer *get_sedp_writer (const struct participant *pp, unsigned en { struct writer *sedp_wr = get_builtin_writer (pp, entityid); if (sedp_wr == NULL) - DDS_FATAL("sedp_write_writer: no SEDP builtin writer %x for %x:%x:%x:%x\n", entityid, PGUID (pp->e.guid)); + DDS_FATAL("sedp_write_writer: no SEDP builtin writer %x for "PGUIDFMT"\n", entityid, PGUID (pp->e.guid)); return sedp_wr; } @@ -1036,14 +1036,14 @@ static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppg { nn_vendorid_t actual_vendorid; /* Some endpoint that we discovered through the DS, but then it must have at least some locators */ - DDS_TRACE(" from-DS %x:%x:%x:%x", PGUID (privguid)); + DDS_TRACE(" from-DS %"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32, PGUID (privguid)); /* avoid "no address" case, so we never create the proxy participant for nothing (FIXME: rework some of this) */ if (!(datap->present & (PP_UNICAST_LOCATOR | PP_MULTICAST_LOCATOR))) { DDS_TRACE(" data locator absent\n"); goto err; } - DDS_TRACE(" new-proxypp %x:%x:%x:%x\n", PGUID (*ppguid)); + DDS_TRACE(" new-proxypp "PGUIDFMT"\n", PGUID (*ppguid)); /* We need to handle any source of entities, but we really want to try to keep the GIDs (and certainly the systemId component) unchanged for OSPL. The new proxy participant will take the GID from the GUID if it is from a "modern" OSPL that advertises it includes all GIDs in @@ -1076,7 +1076,7 @@ static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppg } else { struct addrset *as_default, *as_meta; nn_plist_t tmp_plist; - DDS_TRACE(" from-ddsi2 %x:%x:%x:%x", PGUID (privguid)); + DDS_TRACE(" from-ddsi2 "PGUIDFMT, PGUID (privguid)); nn_plist_init_empty (&pp_plist); ddsrt_mutex_lock (&privpp->e.lock); @@ -1118,7 +1118,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat if (!(datap->present & PP_ENDPOINT_GUID)) E (" no guid?\n", err); - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x", PGUID (datap->endpoint_guid)); + DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT, PGUID (datap->endpoint_guid)); ppguid.prefix = datap->endpoint_guid.prefix; ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; @@ -1141,7 +1141,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat if ((pp = implicitly_create_proxypp (&ppguid, datap, src_guid_prefix, vendorid, timestamp)) == NULL) E ("?\n", err); /* Repeat regular SEDP trace for convenience */ - DDS_LOG(DDS_LC_DISCOVERY, "SEDP ST0 %x:%x:%x:%x (cont)", PGUID (datap->endpoint_guid)); + DDS_LOG(DDS_LC_DISCOVERY, "SEDP ST0 "PGUIDFMT" (cont)", PGUID (datap->endpoint_guid)); } xqos = &datap->qos; @@ -1200,7 +1200,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat if (vendor_is_cloud (vendorid) && pp->implicitly_created && memcmp(&pp->privileged_pp_guid.prefix, src_guid_prefix, sizeof(pp->privileged_pp_guid.prefix)) != 0) { nn_etime_t never = { T_NEVER }; - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x attach-to-DS %x:%x:%x:%x", PGUID(pp->e.guid), PGUIDPREFIX(*src_guid_prefix), pp->privileged_pp_guid.entityid.u); + DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT" attach-to-DS "PGUIDFMT, PGUID(pp->e.guid), PGUIDPREFIX(*src_guid_prefix), pp->privileged_pp_guid.entityid.u); ddsrt_mutex_lock (&pp->e.lock); pp->privileged_pp_guid.prefix = *src_guid_prefix; lease_set_expiry(ddsrt_atomic_ldvoidp(&pp->lease), never); @@ -1253,7 +1253,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat if ((datap->endpoint_guid.entityid.u & NN_ENTITYID_SOURCE_MASK) == NN_ENTITYID_SOURCE_VENDOR && !vendor_is_eclipse_or_prismtech (vendorid)) { - DDS_LOG(DDS_LC_DISCOVERY, "ignoring vendor-specific endpoint %x:%x:%x:%x\n", PGUID (datap->endpoint_guid)); + DDS_LOG(DDS_LC_DISCOVERY, "ignoring vendor-specific endpoint "PGUIDFMT"\n", PGUID (datap->endpoint_guid)); } else { @@ -1310,7 +1310,7 @@ static void handle_SEDP_dead (nn_plist_t *datap, nn_wctime_t timestamp) DDS_LOG(DDS_LC_DISCOVERY, " no guid?\n"); return; } - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x", PGUID (datap->endpoint_guid)); + DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT, PGUID (datap->endpoint_guid)); if (is_writer_entityid (datap->endpoint_guid.entityid)) { res = delete_proxy_writer (&datap->endpoint_guid, timestamp, 0); @@ -1394,7 +1394,7 @@ int sedp_write_topic (struct participant *pp, const struct nn_plist *datap) nn_plist_addtomsg (mpayload, datap, ~(uint64_t)0, delta); nn_xmsg_addpar_sentinel (mpayload); - DDS_TRACE("sedp: write topic %s via %x:%x:%x:%x\n", datap->qos.topic_name, PGUID (sedp_wr->e.guid)); + DDS_TRACE("sedp: write topic %s via "PGUIDFMT"\n", datap->qos.topic_name, PGUID (sedp_wr->e.guid)); ret = write_mpayload (sedp_wr, 1, PID_TOPIC_NAME, mpayload); nn_xmsg_free (mpayload); return ret; @@ -1441,7 +1441,7 @@ int sedp_write_cm_participant (struct participant *pp, int alive) } nn_xmsg_addpar_sentinel (mpayload); - DDS_TRACE("sedp: write CMParticipant ST%x for %x:%x:%x:%x via %x:%x:%x:%x\n", + DDS_TRACE("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); @@ -1514,7 +1514,7 @@ int sedp_write_cm_publisher (const struct nn_plist *datap, int alive) if ((pp = group_guid_to_participant (&datap->group_guid)) == NULL) { - DDS_TRACE("sedp: write CMPublisher alive:%d for %x:%x:%x:%x dropped: no participant\n", + DDS_TRACE("sedp: write CMPublisher alive:%d for "PGUIDFMT" dropped: no participant\n", alive, PGUID (datap->group_guid)); return 0; } @@ -1550,7 +1550,7 @@ int sedp_write_cm_subscriber (const struct nn_plist *datap, int alive) if ((pp = group_guid_to_participant (&datap->group_guid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "sedp: write CMSubscriber alive:%d for %x:%x:%x:%x dropped: no participant\n", + DDS_LOG(DDS_LC_DISCOVERY, "sedp: write CMSubscriber alive:%d for "PGUIDFMT" dropped: no participant\n", alive, PGUID (datap->group_guid)); return 0; } @@ -1583,7 +1583,7 @@ static void handle_SEDP_GROUP_alive (nn_plist_t *datap /* note: potentially modi if (!(datap->present & PP_GROUP_GUID)) E (" no guid?\n", err); - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x", PGUID (datap->group_guid)); + DDS_LOG(DDS_LC_DISCOVERY, " %"PRIx32"%"PRIx32"%"PRIx32"%"PRIx32, PGUID (datap->group_guid)); ppguid.prefix = datap->group_guid.prefix; ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; @@ -1608,7 +1608,7 @@ static void handle_SEDP_GROUP_dead (nn_plist_t *datap, nn_wctime_t timestamp) DDS_LOG(DDS_LC_DISCOVERY, " no guid?\n"); return; } - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x\n", PGUID (datap->group_guid)); + DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT"\n", PGUID (datap->group_guid)); delete_proxy_group (&datap->group_guid, timestamp, 0); } @@ -1757,7 +1757,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH, 0, &src)) < 0) { if (plist_ret != Q_ERR_INCOMPATIBLE) - DDS_WARNING("data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": invalid inline qos\n", + DDS_WARNING("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n", src.vendorid.id[0], src.vendorid.id[1], PGUID (srcguid), sampleinfo->seq); goto done_upd_deliv; } @@ -1781,7 +1781,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str { if (datasz == 0 || !(data_smhdr_flags & DATA_FLAG_DATAFLAG)) { - DDS_WARNING("data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": " + DDS_WARNING("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": " "built-in data but no payload\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (srcguid), sampleinfo->seq); @@ -1795,7 +1795,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str hasn't been checked fully yet. */ if (!(data_smhdr_flags & DATA_FLAG_KEYFLAG)) { - DDS_WARNING("data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": " + DDS_WARNING("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": " "dispose/unregister of built-in data but payload not just key\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (srcguid), sampleinfo->seq); @@ -1837,7 +1837,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str pid = PID_ENDPOINT_GUID; break; default: - DDS_LOG(DDS_LC_DISCOVERY, "data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": mapping keyhash to ENDPOINT_GUID", + DDS_LOG(DDS_LC_DISCOVERY, "data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": mapping keyhash to ENDPOINT_GUID", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (srcguid), sampleinfo->seq); pid = PID_ENDPOINT_GUID; @@ -1854,7 +1854,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str } else { - DDS_WARNING("data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": " + DDS_WARNING("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": " "dispose/unregister with no content\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (srcguid), sampleinfo->seq); @@ -1882,7 +1882,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str handle_SEDP_GROUP (sampleinfo->rst, timestamp, statusinfo, datap, datasz); break; default: - DDS_LOG (DDS_LC_DISCOVERY, "data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": not handled\n", + DDS_LOG (DDS_LC_DISCOVERY, "data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": not handled\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (srcguid), sampleinfo->seq); break; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 31437b0..beba3f8 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -338,7 +338,7 @@ int is_deleted_participant_guid (const struct nn_guid *guid, unsigned for_what) static void remove_deleted_participant_guid (const struct nn_guid *guid, unsigned for_what) { struct deleted_participant *n; - DDS_LOG(DDS_LC_DISCOVERY, "remove_deleted_participant_guid(%x:%x:%x:%x for_what=%x)\n", PGUID (*guid), for_what); + DDS_LOG(DDS_LC_DISCOVERY, "remove_deleted_participant_guid("PGUIDFMT" for_what=%x)\n", PGUID (*guid), for_what); ddsrt_mutex_lock (&deleted_participants_lock); if ((n = ddsrt_avl_lookup (&deleted_participants_treedef, &deleted_participants, guid)) != NULL) { @@ -380,7 +380,7 @@ int pp_allocate_entityid(nn_entityid_t *id, unsigned kind, struct participant *p } else { - DDS_ERROR("pp_allocate_entityid(%x:%x:%x:%x): all ids in use\n", PGUID(pp->e.guid)); + DDS_ERROR("pp_allocate_entityid("PGUIDFMT"): all ids in use\n", PGUID(pp->e.guid)); ret = Q_ERR_OUT_OF_IDS; } ddsrt_mutex_unlock (&pp->e.lock); @@ -431,12 +431,12 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis else { ddsrt_mutex_unlock (&gv.participant_set_lock); - DDS_ERROR("new_participant(%x:%x:%x:%x, %x) failed: max participants reached\n", PGUID (*ppguid), flags); + DDS_ERROR("new_participant("PGUIDFMT", %x) failed: max participants reached\n", PGUID (*ppguid), flags); return Q_ERR_OUT_OF_IDS; } } - DDS_LOG(DDS_LC_DISCOVERY, "new_participant(%x:%x:%x:%x, %x)\n", PGUID (*ppguid), flags); + DDS_LOG(DDS_LC_DISCOVERY, "new_participant("PGUIDFMT", %x)\n", PGUID (*ppguid), flags); pp = ddsrt_malloc (sizeof (*pp)); @@ -454,7 +454,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis if (dds_get_log_mask() & DDS_LC_DISCOVERY) { - DDS_LOG(DDS_LC_DISCOVERY, "PARTICIPANT %x:%x:%x:%x QOS={", PGUID (pp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "PARTICIPANT "PGUIDFMT" QOS={", PGUID (pp->e.guid)); nn_log_xqos(DDS_LC_DISCOVERY, &pp->plist->qos); DDS_LOG(DDS_LC_DISCOVERY, "}\n"); } @@ -692,7 +692,7 @@ static struct participant *ref_participant (struct participant *pp, const struct stguid = *guid_of_refing_entity; else memset (&stguid, 0, sizeof (stguid)); - DDS_LOG(DDS_LC_DISCOVERY, "ref_participant(%x:%x:%x:%x @ %p <- %x:%x:%x:%x @ %p) user %d builtin %d\n", + DDS_LOG(DDS_LC_DISCOVERY, "ref_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); ddsrt_mutex_unlock (&pp->refc_lock); return pp; @@ -733,7 +733,7 @@ static void unref_participant (struct participant *pp, const struct nn_guid *gui stguid = *guid_of_refing_entity; else memset (&stguid, 0, sizeof (stguid)); - DDS_LOG(DDS_LC_DISCOVERY, "unref_participant(%x:%x:%x:%x @ %p <- %x:%x:%x:%x @ %p) user %d builtin %d\n", + DDS_LOG(DDS_LC_DISCOVERY, "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) @@ -845,7 +845,7 @@ static void unref_participant (struct participant *pp, const struct nn_guid *gui static void gc_delete_participant (struct gcreq *gcreq) { struct participant *pp = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_participant(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (pp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_participant(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pp->e.guid)); gcreq_free (gcreq); unref_participant (pp, NULL); } @@ -1235,7 +1235,7 @@ static void rebuild_writer_addrset (struct writer *wr) wr->as = newas; unref_addrset (oldas); - DDS_LOG(DDS_LC_DISCOVERY, "rebuild_writer_addrset(%x:%x:%x:%x):", PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "rebuild_writer_addrset("PGUIDFMT"):", PGUID (wr->e.guid)); nn_log_addrset(DDS_LC_DISCOVERY, "", wr->as); DDS_LOG(DDS_LC_DISCOVERY, "\n"); } @@ -1461,14 +1461,14 @@ static void update_reader_init_acknack_count (const struct nn_guid *rd_guid, nn_ /* Update the initial acknack sequence number for the reader. See also reader_add_connection(). */ - DDS_LOG(DDS_LC_DISCOVERY, "update_reader_init_acknack_count (%x:%x:%x:%x, %d): ", PGUID (*rd_guid), count); + DDS_LOG(DDS_LC_DISCOVERY, "update_reader_init_acknack_count ("PGUIDFMT", %"PRId32"): ", PGUID (*rd_guid), count); if ((rd = ephash_lookup_reader_guid (rd_guid)) != NULL) { ddsrt_mutex_lock (&rd->e.lock); - DDS_LOG(DDS_LC_DISCOVERY, "%d -> ", rd->init_acknack_count); + DDS_LOG(DDS_LC_DISCOVERY, "%"PRId32" -> ", rd->init_acknack_count); if (count > rd->init_acknack_count) rd->init_acknack_count = count; - DDS_LOG(DDS_LC_DISCOVERY, "%d\n", count); + DDS_LOG(DDS_LC_DISCOVERY, "%"PRId32"\n", count); ddsrt_mutex_unlock (&rd->e.lock); } else @@ -1538,7 +1538,7 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) ddsrt_mutex_lock (&prd->e.lock); if (prd->deleting) { - DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - prd is being deleted\n", + DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - prd is being deleted\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); pretend_everything_acked = 1; } @@ -1566,14 +1566,14 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) m->seq = wr->seq; if (ddsrt_avl_lookup_ipath (&wr_readers_treedef, &wr->readers, &prd->e.guid, &path)) { - DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - already connected\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); ddsrt_mutex_unlock (&wr->e.lock); nn_lat_estim_fini (&m->hb_to_ack_latency); ddsrt_free (m); } else { - DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - ack seq %"PRId64"\n", PGUID (wr->e.guid), PGUID (prd->e.guid), m->seq); + DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - ack seq %"PRId64"\n", PGUID (wr->e.guid), PGUID (prd->e.guid), m->seq); ddsrt_avl_insert_ipath (&wr_readers_treedef, &wr->readers, m, &path); rebuild_writer_addrset (wr); wr->num_reliable_readers += m->is_reliable; @@ -1623,13 +1623,13 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd) ddsrt_mutex_lock (&wr->e.lock); if (ddsrt_avl_lookup_ipath (&wr_local_readers_treedef, &wr->local_readers, &rd->e.guid, &path)) { - DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT") - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); ddsrt_mutex_unlock (&wr->e.lock); ddsrt_free (m); return; } - DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x)", PGUID (wr->e.guid), PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT")", PGUID (wr->e.guid), PGUID (rd->e.guid)); m->rd_guid = rd->e.guid; ddsrt_avl_insert_ipath (&wr_local_readers_treedef, &wr->local_readers, m, &path); local_reader_ary_insert (&wr->rdary, rd); @@ -1684,19 +1684,19 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, writer will always see monotonically increasing sequence numbers from one particular reader. This is then used for the pwr_rd_match initialization */ - DDS_LOG(DDS_LC_DISCOVERY, " reader %x:%x:%x:%x init_acknack_count = %d\n", PGUID (rd->e.guid), rd->init_acknack_count); + DDS_LOG(DDS_LC_DISCOVERY, " reader "PGUIDFMT" init_acknack_count = %"PRId32"\n", PGUID (rd->e.guid), rd->init_acknack_count); *init_count = rd->init_acknack_count; if (ddsrt_avl_lookup_ipath (&rd_writers_treedef, &rd->writers, &pwr->e.guid, &path)) { - DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", + DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT") - already connected\n", PGUID (pwr->e.guid), PGUID (rd->e.guid)); ddsrt_mutex_unlock (&rd->e.lock); ddsrt_free (m); } else { - DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr %x:%x:%x:%x rd %x:%x:%x:%x)\n", + DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT")\n", PGUID (pwr->e.guid), PGUID (rd->e.guid)); ddsrt_avl_insert_ipath (&rd_writers_treedef, &rd->writers, m, &path); ddsrt_mutex_unlock (&rd->e.lock); @@ -1744,13 +1744,13 @@ static void reader_add_local_connection (struct reader *rd, struct writer *wr) if (ddsrt_avl_lookup_ipath (&rd_local_writers_treedef, &rd->local_writers, &wr->e.guid, &path)) { - DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT") - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); ddsrt_mutex_unlock (&rd->e.lock); ddsrt_free (m); } else { - DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x)\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT")\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); ddsrt_avl_insert_ipath (&rd_local_writers_treedef, &rd->local_writers, m, &path); ddsrt_mutex_unlock (&rd->e.lock); @@ -1787,7 +1787,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader pwr->ddsi2direct_cbarg = rd->ddsi2direct_cbarg; } - DDS_LOG(DDS_LC_DISCOVERY, " proxy_writer_add_connection(pwr %x:%x:%x:%x rd %x:%x:%x:%x)", + DDS_LOG(DDS_LC_DISCOVERY, " proxy_writer_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT")", PGUID (pwr->e.guid), PGUID (rd->e.guid)); m->rd_guid = rd->e.guid; m->tcreate = now_mt (); @@ -1880,7 +1880,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader already_matched: assert (is_builtin_entityid (pwr->e.guid.entityid, pwr->c.vendor) ? (pwr->c.topic == NULL) : (pwr->c.topic != NULL)); - DDS_LOG(DDS_LC_DISCOVERY, " proxy_writer_add_connection(pwr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", + DDS_LOG(DDS_LC_DISCOVERY, " proxy_writer_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT") - already connected\n", PGUID (pwr->e.guid), PGUID (rd->e.guid)); ddsrt_mutex_unlock (&pwr->e.lock); ddsrt_free (m); @@ -1898,14 +1898,14 @@ static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer prd->c.topic = ddsi_sertopic_ref (wr->topic); if (ddsrt_avl_lookup_ipath (&prd_writers_treedef, &prd->writers, &wr->e.guid, &path)) { - DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - already connected\n", + DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - already connected\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); ddsrt_mutex_unlock (&prd->e.lock); ddsrt_free (m); } else { - DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x)\n", + DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr "PGUIDFMT" prd "PGUIDFMT")\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); ddsrt_avl_insert_ipath (&prd_writers_treedef, &prd->writers, m, &path); ddsrt_mutex_unlock (&prd->e.lock); @@ -2259,7 +2259,7 @@ static void generic_do_match (struct entity_common *e, nn_mtime_t tnow) enum entity_kind mkind = generic_do_match_mkind(e->kind); if (!is_builtin_entityid (e->guid.entityid, NN_VENDORID_ECLIPSE)) { - DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s %x:%x:%x:%x) scanning all %ss\n", + DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s "PGUIDFMT") scanning all %ss\n", generic_do_match_kindstr_us (e->kind), generic_do_match_kindstr_us (mkind), generic_do_match_kindabbrev (e->kind), PGUID (e->guid), generic_do_match_kindstr(mkind)); @@ -2280,7 +2280,7 @@ static void generic_do_match (struct entity_common *e, nn_mtime_t tnow) /* Built-ins have fixed QoS */ nn_entityid_t tgt_ent = builtin_entityid_match (e->guid.entityid); enum entity_kind pkind = generic_do_match_isproxy (e) ? EK_PARTICIPANT : EK_PROXY_PARTICIPANT; - DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s %x:%x:%x:%x) scanning %sparticipants tgt=%x\n", + DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s "PGUIDFMT") scanning %sparticipants tgt=%"PRIx32"\n", generic_do_match_kindstr_us (e->kind), generic_do_match_kindstr_us (mkind), generic_do_match_kindabbrev (e->kind), PGUID (e->guid), generic_do_match_isproxy (e) ? "" : "proxy ", @@ -2311,7 +2311,7 @@ static void generic_do_local_match (struct entity_common *e, nn_mtime_t tnow) /* never a need for local matches on discovery endpoints */ return; mkind = generic_do_local_match_mkind(e->kind); - DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s %x:%x:%x:%x) scanning all %ss\n", + DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s "PGUIDFMT") scanning all %ss\n", generic_do_match_kindstr_us (e->kind), generic_do_match_kindstr_us (mkind), generic_do_match_kindabbrev (e->kind), PGUID (e->guid), generic_do_match_kindstr(mkind)); @@ -2378,7 +2378,7 @@ static void new_reader_writer_common (const struct nn_guid *guid, const struct d if (xqos->partition.n > 1) partition_suffix = "+"; } - DDS_LOG(DDS_LC_DISCOVERY, "new_%s(guid %x:%x:%x:%x, %s%s.%s/%s)\n", + DDS_LOG(DDS_LC_DISCOVERY, "new_%s(guid "PGUIDFMT", %s%s.%s/%s)\n", is_writer_entityid (guid->entityid) ? "writer" : "reader", PGUID (*guid), partition, partition_suffix, @@ -2607,7 +2607,7 @@ unsigned remove_acked_messages (struct writer *wr, struct whc_state *whcst, stru writer_clear_retransmitting (wr); if (wr->state == WRST_LINGERING && whcst->unacked_bytes == 0) { - DDS_LOG(DDS_LC_DISCOVERY, "remove_acked_messages: deleting lingering writer %x:%x:%x:%x\n", PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "remove_acked_messages: deleting lingering writer "PGUIDFMT"\n", PGUID (wr->e.guid)); delete_writer_nolinger_locked (wr); } return n; @@ -2646,7 +2646,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se assert (wr->xqos->aliased == 0); set_topic_type_name (wr->xqos, topic); - DDS_LOG(DDS_LC_DISCOVERY, "WRITER %x:%x:%x:%x QOS={", PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "WRITER "PGUIDFMT" QOS={", PGUID (wr->e.guid)); nn_log_xqos (DDS_LC_DISCOVERY, wr->xqos); DDS_LOG(DDS_LC_DISCOVERY, "}\n"); @@ -2738,7 +2738,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se wr->supports_ssm = 1; wr->ssm_as = new_addrset (); add_to_addrset (wr->ssm_as, &loc); - DDS_LOG(DDS_LC_DISCOVERY, "writer %x:%x:%x:%x: ssm=%d", PGUID (wr->e.guid), wr->supports_ssm); + DDS_LOG(DDS_LC_DISCOVERY, "writer "PGUIDFMT": ssm=%d", PGUID (wr->e.guid), wr->supports_ssm); nn_log_addrset (DDS_LC_DISCOVERY, "", wr->ssm_as); DDS_LOG(DDS_LC_DISCOVERY, "\n"); } @@ -2751,7 +2751,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se if (!is_builtin_entityid (wr->e.guid.entityid, ownvendorid)) { struct config_channel_listelem *channel = find_channel (wr->xqos->transport_priority); - DDS_LOG(DDS_LC_DISCOVERY, "writer %x:%x:%x:%x: transport priority %d => channel '%s' priority %d\n", + DDS_LOG(DDS_LC_DISCOVERY, "writer "PGUIDFMT": transport priority %d => channel '%s' priority %d\n", PGUID (wr->e.guid), wr->xqos->transport_priority.value, channel->name, channel->priority); wr->evq = channel->evq ? channel->evq : gv.xevents; } @@ -2779,7 +2779,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se if (wr->xqos->liveliness.kind != NN_AUTOMATIC_LIVELINESS_QOS || nn_from_ddsi_duration (wr->xqos->liveliness.lease_duration) != T_NEVER) { - DDS_LOG(DDS_LC_DISCOVERY, "writer %x:%x:%x:%x: incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (wr->e.guid), (int) wr->xqos->liveliness.kind, nn_from_ddsi_duration (wr->xqos->liveliness.lease_duration)); + DDS_LOG(DDS_LC_DISCOVERY, "writer "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (wr->e.guid), (int) wr->xqos->liveliness.kind, nn_from_ddsi_duration (wr->xqos->liveliness.lease_duration)); } wr->lease_duration = T_NEVER; /* FIXME */ @@ -2862,7 +2862,7 @@ dds_retcode_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "new_writer - participant %x:%x:%x:%x not found\n", PGUID (*ppguid)); + DDS_LOG(DDS_LC_DISCOVERY, "new_writer - participant "PGUIDFMT" not found\n", PGUID (*ppguid)); return DDS_RETCODE_NOT_FOUND; } /* participant can't be freed while we're mucking around cos we are @@ -2900,7 +2900,7 @@ struct local_orphan_writer *new_local_orphan_writer (nn_entityid_t entityid, str static void gc_delete_writer (struct gcreq *gcreq) { struct writer *wr = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_writer(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_writer(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (wr->e.guid)); gcreq_free (gcreq); /* We now allow GC while blocked on a full WHC, but we still don't allow deleting a writer while blocked on it. The writer's state must be DELETING by the time we get here, and that means the transmit path is no longer blocked. It doesn't imply that the write thread is no longer in throttle_writer(), just that if it is, it will soon return from there. Therefore, block until it isn't throttling anymore. We can safely lock the writer, as we're on the separate GC thread. */ @@ -2959,7 +2959,7 @@ static void gc_delete_writer (struct gcreq *gcreq) static void gc_delete_writer_throttlewait (struct gcreq *gcreq) { struct writer *wr = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_writer_throttlewait(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_writer_throttlewait(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (wr->e.guid)); /* We now allow GC while blocked on a full WHC, but we still don't allow deleting a writer while blocked on it. The writer's state must be DELETING by the time we get here, and that means the transmit path is no longer blocked. It doesn't imply that the write thread is no longer in throttle_writer(), just that if it is, it will soon return from there. Therefore, block until it isn't throttling anymore. We can safely lock the writer, as we're on the separate GC thread. */ assert (wr->state == WRST_DELETING); ddsrt_mutex_lock (&wr->e.lock); @@ -2972,7 +2972,7 @@ static void gc_delete_writer_throttlewait (struct gcreq *gcreq) static void writer_set_state (struct writer *wr, enum writer_state newstate) { ASSERT_MUTEX_HELD (&wr->e.lock); - DDS_LOG(DDS_LC_DISCOVERY, "writer_set_state(%x:%x:%x:%x) state transition %d -> %d\n", PGUID (wr->e.guid), wr->state, newstate); + DDS_LOG(DDS_LC_DISCOVERY, "writer_set_state("PGUIDFMT") state transition %d -> %d\n", PGUID (wr->e.guid), wr->state, newstate); assert (newstate > wr->state); if (wr->state == WRST_OPERATIONAL) { @@ -2989,7 +2989,7 @@ static void writer_set_state (struct writer *wr, enum writer_state newstate) int delete_writer_nolinger_locked (struct writer *wr) { - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid %x:%x:%x:%x) ...\n", PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (wr->e.guid)); ASSERT_MUTEX_HELD (&wr->e.lock); ddsi_plugin.builtintopic_write (&wr->e, now(), false); local_reader_ary_setinvalid (&wr->rdary); @@ -3011,10 +3011,10 @@ int delete_writer_nolinger (const struct nn_guid *guid) assert (is_writer_entityid (guid->entityid)); if ((wr = ephash_lookup_writer_guid (guid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid)); return Q_ERR_UNKNOWN_ENTITY; } - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid %x:%x:%x:%x) ...\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (*guid)); ddsrt_mutex_lock (&wr->e.lock); delete_writer_nolinger_locked (wr); ddsrt_mutex_unlock (&wr->e.lock); @@ -3034,10 +3034,10 @@ int delete_writer (const struct nn_guid *guid) struct whc_state whcst; if ((wr = ephash_lookup_writer_guid (guid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid)); return Q_ERR_UNKNOWN_ENTITY; } - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) ...\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") ...\n", PGUID (*guid)); ddsrt_mutex_lock (&wr->e.lock); /* If no unack'ed data, don't waste time or resources (expected to @@ -3047,7 +3047,7 @@ int delete_writer (const struct nn_guid *guid) whc_get_state(wr->whc, &whcst); if (whcst.unacked_bytes == 0) { - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) - no unack'ed samples\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") - no unack'ed samples\n", PGUID (*guid)); delete_writer_nolinger_locked (wr); ddsrt_mutex_unlock (&wr->e.lock); } @@ -3059,7 +3059,7 @@ int delete_writer (const struct nn_guid *guid) ddsrt_mutex_unlock (&wr->e.lock); tsched = add_duration_to_mtime (now_mt (), config.writer_linger_duration); mtime_to_sec_usec (&tsec, &tusec, tsched); - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) - unack'ed samples, will delete when ack'd or at t = %"PRId32".%06"PRId32"\n", + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") - unack'ed samples, will delete when ack'd or at t = %"PRId32".%06"PRId32"\n", PGUID (*guid), tsec, tusec); qxev_delete_writer (tsched, &wr->e.guid); } @@ -3078,7 +3078,7 @@ void writer_exit_startup_mode (struct writer *wr) cnt += remove_acked_messages (wr, &whcst, &deferred_free_list); cnt += whc_downgrade_to_volatile (wr->whc, &whcst); writer_clear_retransmitting (wr); - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x: dropped %u samples\n", PGUID(wr->e.guid), cnt); + DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT": dropped %u samples\n", PGUID(wr->e.guid), cnt); } ddsrt_mutex_unlock (&wr->e.lock); whc_free_deferred_free_list (wr->whc, deferred_free_list); @@ -3237,7 +3237,7 @@ static dds_retcode_t new_reader_guid if (dds_get_log_mask() & DDS_LC_DISCOVERY) { - DDS_LOG(DDS_LC_DISCOVERY, "READER %x:%x:%x:%x QOS={", PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "READER "PGUIDFMT" QOS={", PGUID (rd->e.guid)); nn_log_xqos (DDS_LC_DISCOVERY, rd->xqos); DDS_LOG(DDS_LC_DISCOVERY, "}\n"); } @@ -3268,7 +3268,7 @@ static dds_retcode_t new_reader_guid if (rd->xqos->liveliness.kind != NN_AUTOMATIC_LIVELINESS_QOS || nn_from_ddsi_duration (rd->xqos->liveliness.lease_duration) != T_NEVER) { - DDS_LOG(DDS_LC_DISCOVERY, "reader %x:%x:%x:%x: incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (rd->e.guid), (int) rd->xqos->liveliness.kind, nn_from_ddsi_duration (rd->xqos->liveliness.lease_duration)); + DDS_LOG(DDS_LC_DISCOVERY, "reader "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (rd->e.guid), (int) rd->xqos->liveliness.kind, nn_from_ddsi_duration (rd->xqos->liveliness.lease_duration)); } #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS @@ -3302,7 +3302,7 @@ static dds_retcode_t new_reader_guid addrset_forall (rd->as, join_mcast_helper, gv.data_conn_mc); if (dds_get_log_mask() & DDS_LC_DISCOVERY) { - DDS_LOG(DDS_LC_DISCOVERY, "READER %x:%x:%x:%x locators={", PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "READER "PGUIDFMT" locators={", PGUID (rd->e.guid)); nn_log_addrset(DDS_LC_DISCOVERY, "", rd->as); DDS_LOG(DDS_LC_DISCOVERY, "}\n"); } @@ -3320,7 +3320,7 @@ static dds_retcode_t new_reader_guid } #ifdef DDSI_INCLUDE_SSM if (rd->favours_ssm) - DDS_LOG(DDS_LC_DISCOVERY, "READER %x:%x:%x:%x ssm=%d\n", PGUID (rd->e.guid), rd->favours_ssm); + DDS_LOG(DDS_LC_DISCOVERY, "READER "PGUIDFMT" ssm=%d\n", PGUID (rd->e.guid), rd->favours_ssm); #endif #endif @@ -3355,7 +3355,7 @@ dds_retcode_t new_reader if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "new_reader - participant %x:%x:%x:%x not found\n", PGUID (*ppguid)); + DDS_LOG(DDS_LC_DISCOVERY, "new_reader - participant "PGUIDFMT" not found\n", PGUID (*ppguid)); return DDS_RETCODE_NOT_FOUND; } rdguid->prefix = pp->e.guid.prefix; @@ -3368,7 +3368,7 @@ static void gc_delete_reader (struct gcreq *gcreq) { /* see gc_delete_writer for comments */ struct reader *rd = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_reader(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_reader(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (rd->e.guid)); gcreq_free (gcreq); while (!ddsrt_avl_is_empty (&rd->writers)) @@ -3417,10 +3417,10 @@ int delete_reader (const struct nn_guid *guid) assert (!is_writer_entityid (guid->entityid)); if ((rd = ephash_lookup_reader_guid (guid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid)); return Q_ERR_UNKNOWN_ENTITY; } - DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid %x:%x:%x:%x) ...\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid "PGUIDFMT") ...\n", PGUID (*guid)); ddsi_plugin.builtintopic_write (&rd->e, now(), false); ephash_remove_reader_guid (rd); gcreq_reader (rd); @@ -3754,7 +3754,7 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p { assert (proxypp->endpoints == NULL); ddsrt_mutex_unlock (&proxypp->e.lock); - DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant(%x:%x:%x:%x): refc=0, freeing\n", PGUID (proxypp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant("PGUIDFMT"): refc=0, freeing\n", PGUID (proxypp->e.guid)); unref_addrset (proxypp->as_default); @@ -3771,7 +3771,7 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p { assert (refc == 1); ddsrt_mutex_unlock (&proxypp->e.lock); - DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant(%x:%x:%x:%x): refc=%u, no endpoints, implicitly created, deleting\n", PGUID (proxypp->e.guid), (unsigned) refc); + DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant("PGUIDFMT"): refc=%u, no endpoints, implicitly created, deleting\n", PGUID (proxypp->e.guid), (unsigned) refc); delete_proxy_participant_by_guid(&proxypp->e.guid, tnow, 1); /* Deletion is still (and has to be) asynchronous. A parallel endpoint creation may or may not succeed, and if it succeeds it will be deleted along with the proxy participant. So "your @@ -3780,14 +3780,14 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p else { ddsrt_mutex_unlock (&proxypp->e.lock); - DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant(%x:%x:%x:%x): refc=%u\n", PGUID (proxypp->e.guid), (unsigned) refc); + DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant("PGUIDFMT"): refc=%u\n", PGUID (proxypp->e.guid), (unsigned) refc); } } static void gc_delete_proxy_participant (struct gcreq *gcreq) { struct proxy_participant *proxypp = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_participant(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (proxypp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_participant(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (proxypp->e.guid)); gcreq_free (gcreq); unref_proxy_participant (proxypp, NULL); } @@ -3820,7 +3820,7 @@ static void delete_or_detach_dependent_pp (struct proxy_participant *p, struct p { nn_etime_t texp = add_duration_to_etime (now_et(), config.ds_grace_period); /* Clear dependency (but don't touch entity id, which must be 0x1c1) and set the lease ticking */ - DDS_LOG(DDS_LC_DISCOVERY, "%x:%x:%x:%x detach-from-DS %x:%x:%x:%x\n", PGUID(p->e.guid), PGUID(proxypp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, PGUIDFMT" detach-from-DS "PGUIDFMT"\n", PGUID(p->e.guid), PGUID(proxypp->e.guid)); memset (&p->privileged_pp_guid.prefix, 0, sizeof (p->privileged_pp_guid.prefix)); lease_set_expiry (ddsrt_atomic_ldvoidp (&p->lease), texp); ddsrt_mutex_unlock (&p->e.lock); @@ -3833,7 +3833,7 @@ static void delete_ppt (struct proxy_participant * proxypp, nn_wctime_t timestam int ret; /* if any proxy participants depend on this participant, delete them */ - DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt(%x:%x:%x:%x) - deleting dependent proxy participants\n", PGUID (proxypp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt("PGUIDFMT") - deleting dependent proxy participants\n", PGUID (proxypp->e.guid)); { struct ephash_enum_proxy_participant est; struct proxy_participant *p; @@ -3850,11 +3850,11 @@ static void delete_ppt (struct proxy_participant * proxypp, nn_wctime_t timestam if (isimplicit) proxypp->lease_expired = 1; - DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt(%x:%x:%x:%x) - deleting groups\n", PGUID (proxypp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt("PGUIDFMT") - deleting groups\n", PGUID (proxypp->e.guid)); while (!ddsrt_avl_is_empty (&proxypp->groups)) delete_proxy_group_locked (ddsrt_avl_root (&proxypp_groups_treedef, &proxypp->groups), timestamp, isimplicit); - DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt(%x:%x:%x:%x) - deleting endpoints\n", PGUID (proxypp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt("PGUIDFMT") - deleting endpoints\n", PGUID (proxypp->e.guid)); c = proxypp->endpoints; while (c) { @@ -3915,7 +3915,7 @@ int delete_proxy_participant_by_guid (const struct nn_guid * guid, nn_wctime_t t { struct proxy_participant * ppt; - DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_participant_by_guid(%x:%x:%x:%x) ", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_participant_by_guid("PGUIDFMT") ", PGUID (*guid)); ddsrt_mutex_lock (&gv.lock); ppt = ephash_lookup_proxy_participant_guid (guid); if (ppt == NULL) @@ -3959,7 +3959,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; if ((proxypp = ephash_lookup_proxy_participant_guid (&ppguid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group(%x:%x:%x:%x) - unknown participant\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group("PGUIDFMT") - unknown participant\n", PGUID (*guid)); return 0; } else @@ -3976,7 +3976,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct is_sub = 1; break; default: - DDS_WARNING("new_proxy_group: unrecognised entityid: %x\n", guid->entityid.u); + DDS_WARNING("new_proxy_group: unrecognised entityid: %"PRIx32"\n", guid->entityid.u); return Q_ERR_INVALID_DATA; } ddsrt_mutex_lock (&proxypp->e.lock); @@ -3991,7 +3991,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct else { /* Always have a guid, may not have a gid */ - DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group(%x:%x:%x:%x): new\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group("PGUIDFMT"): new\n", PGUID (*guid)); pgroup = ddsrt_malloc (sizeof (*pgroup)); pgroup->guid = *guid; pgroup->proxypp = proxypp; @@ -4002,7 +4002,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct if (name) { assert (xqos != NULL); - DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group(%x:%x:%x:%x): setting name (%s) and qos\n", PGUID (*guid), name); + DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group("PGUIDFMT"): setting name (%s) and qos\n", PGUID (*guid), name); pgroup->name = ddsrt_strdup (name); pgroup->xqos = nn_xqos_dup (xqos); nn_xqos_mergein_missing (pgroup->xqos, is_sub ? &gv.default_xqos_sub : &gv.default_xqos_pub); @@ -4020,7 +4020,7 @@ static void delete_proxy_group_locked (struct proxy_group *pgroup, nn_wctime_t t (void)timestamp; (void)isimplicit; assert ((pgroup->xqos != NULL) == (pgroup->name != NULL)); - DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_group_locked %x:%x:%x:%x\n", PGUID (pgroup->guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_group_locked "PGUIDFMT"\n", PGUID (pgroup->guid)); ddsrt_avl_delete (&proxypp_groups_treedef, &proxypp->groups, pgroup); /* Publish corresponding built-in topic only if it is not a place holder: in that case we haven't announced its presence and @@ -4105,7 +4105,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, if ((proxypp = ephash_lookup_proxy_participant_guid (ppguid)) == NULL) { - DDS_WARNING("new_proxy_writer(%x:%x:%x:%x): proxy participant unknown\n", PGUID (*guid)); + DDS_WARNING("new_proxy_writer("PGUIDFMT"): proxy participant unknown\n", PGUID (*guid)); return Q_ERR_UNKNOWN_ENTITY; } @@ -4277,7 +4277,7 @@ void update_proxy_reader (struct proxy_reader * prd, struct addrset * as) static void gc_delete_proxy_writer (struct gcreq *gcreq) { struct proxy_writer *pwr = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (pwr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pwr->e.guid)); gcreq_free (gcreq); while (!ddsrt_avl_is_empty (&pwr->readers)) @@ -4299,7 +4299,7 @@ int delete_proxy_writer (const struct nn_guid *guid, nn_wctime_t timestamp, int { struct proxy_writer *pwr; (void)isimplicit; - DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_writer (%x:%x:%x:%x) ", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_writer ("PGUIDFMT") ", PGUID (*guid)); ddsrt_mutex_lock (&gv.lock); if ((pwr = ephash_lookup_proxy_writer_guid (guid)) == NULL) { @@ -4337,7 +4337,7 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, if ((proxypp = ephash_lookup_proxy_participant_guid (ppguid)) == NULL) { - DDS_WARNING("new_proxy_reader(%x:%x:%x:%x): proxy participant unknown\n", PGUID (*guid)); + DDS_WARNING("new_proxy_reader("PGUIDFMT"): proxy participant unknown\n", PGUID (*guid)); return Q_ERR_UNKNOWN_ENTITY; } @@ -4416,7 +4416,7 @@ static void proxy_reader_set_delete_and_ack_all_messages (struct proxy_reader *p static void gc_delete_proxy_reader (struct gcreq *gcreq) { struct proxy_reader *prd = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_reader(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (prd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_reader(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (prd->e.guid)); gcreq_free (gcreq); while (!ddsrt_avl_is_empty (&prd->writers)) @@ -4435,7 +4435,7 @@ int delete_proxy_reader (const struct nn_guid *guid, nn_wctime_t timestamp, int { struct proxy_reader *prd; (void)isimplicit; - DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_reader (%x:%x:%x:%x) ", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_reader ("PGUIDFMT") ", PGUID (*guid)); ddsrt_mutex_lock (&gv.lock); if ((prd = ephash_lookup_proxy_reader_guid (guid)) == NULL) { @@ -4496,7 +4496,7 @@ static void gc_delete_proxy_writer_dqueue_bubble_cb (struct gcreq *gcreq) { /* delete proxy_writer, phase 3 */ struct proxy_writer *pwr = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer_dqueue_bubble(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (pwr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer_dqueue_bubble(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pwr->e.guid)); gcreq_requeue (gcreq, gc_delete_proxy_writer); } @@ -4505,7 +4505,7 @@ static void gc_delete_proxy_writer_dqueue (struct gcreq *gcreq) /* delete proxy_writer, phase 2 */ struct proxy_writer *pwr = gcreq->arg; struct nn_dqueue *dqueue = pwr->dqueue; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer_dqueue(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (pwr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer_dqueue(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pwr->e.guid)); nn_dqueue_enqueue_callback (dqueue, (void (*) (void *)) gc_delete_proxy_writer_dqueue_bubble_cb, gcreq); } diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index ee25e6c..c6e4a8f 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -647,7 +647,7 @@ int joinleave_spdp_defmcip (int dojoin) unref_addrset (as); if (arg.errcount) { - DDS_ERROR("rtps_init: failed to join multicast groups for domain %d participant %d\n", config.domainId.value, config.participantIndex); + DDS_ERROR("rtps_init: failed to join multicast groups for domain %"PRId32" participant %d\n", config.domainId.value, config.participantIndex); return -1; } return 0; @@ -679,7 +679,7 @@ int create_multicast_sockets(void) gv.disc_conn_mc = disc; gv.data_conn_mc = data; - DDS_TRACE("Multicast Ports: discovery %d data %d \n", + DDS_TRACE("Multicast Ports: discovery %"PRIu32" data %"PRIu32" \n", ddsi_conn_port (gv.disc_conn_mc), ddsi_conn_port (gv.data_conn_mc)); return 1; @@ -1060,7 +1060,7 @@ int rtps_init (void) { if (make_uc_sockets (&port_disc_uc, &port_data_uc, config.participantIndex) < 0) { - DDS_ERROR("rtps_init: failed to create unicast sockets for domain %d participant %d\n", config.domainId.value, config.participantIndex); + DDS_ERROR("rtps_init: failed to create unicast sockets for domain %"PRId32" participant %d\n", config.domainId.value, config.participantIndex); goto err_unicast_sockets; } } @@ -1078,13 +1078,13 @@ int rtps_init (void) continue; else /* Oops! */ { - DDS_ERROR("rtps_init: failed to create unicast sockets for domain %d participant %d\n", config.domainId.value, ppid); + DDS_ERROR("rtps_init: failed to create unicast sockets for domain %"PRId32" participant %d\n", config.domainId.value, ppid); goto err_unicast_sockets; } } if (ppid > config.maxAutoParticipantIndex) { - DDS_ERROR("rtps_init: failed to find a free participant index for domain %d\n", config.domainId.value); + DDS_ERROR("rtps_init: failed to find a free participant index for domain %"PRId32"\n", config.domainId.value); goto err_unicast_sockets; } config.participantIndex = ppid; @@ -1093,9 +1093,9 @@ int rtps_init (void) { assert(0); } - DDS_LOG(DDS_LC_CONFIG, "rtps_init: uc ports: disc %u data %u\n", port_disc_uc, port_data_uc); + DDS_LOG(DDS_LC_CONFIG, "rtps_init: uc ports: disc %"PRIu32" data %"PRIu32"\n", port_disc_uc, port_data_uc); } - DDS_LOG(DDS_LC_CONFIG, "rtps_init: domainid %d participantid %d\n", config.domainId.value, config.participantIndex); + DDS_LOG(DDS_LC_CONFIG, "rtps_init: domainid %"PRId32" participantid %d\n", config.domainId.value, config.participantIndex); if (config.pcap_file && *config.pcap_file) { @@ -1115,7 +1115,7 @@ int rtps_init (void) if (gv.m_factory->m_connless) { if (!(config.many_sockets_mode == MSM_NO_UNICAST && config.allowMulticast)) - DDS_TRACE("Unicast Ports: discovery %d data %d\n", ddsi_conn_port (gv.disc_conn_uc), ddsi_conn_port (gv.data_conn_uc)); + DDS_TRACE("Unicast Ports: discovery %"PRIu32" data %"PRIu32"\n", ddsi_conn_port (gv.disc_conn_uc), ddsi_conn_port (gv.data_conn_uc)); if (config.allowMulticast) { diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index 22dc1f4..4ec8892 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -108,7 +108,7 @@ struct lease *lease_new (nn_etime_t texpire, int64_t tdur, struct entity_common struct lease *l; if ((l = ddsrt_malloc (sizeof (*l))) == NULL) return NULL; - DDS_TRACE("lease_new(tdur %"PRId64" guid %x:%x:%x:%x) @ %p\n", tdur, PGUID (e->guid), (void *) l); + DDS_TRACE("lease_new(tdur %"PRId64" guid "PGUIDFMT") @ %p\n", tdur, PGUID (e->guid), (void *) l); l->tdur = tdur; l->tend = texpire; l->tsched.v = TSCHED_NOT_ON_HEAP; @@ -118,7 +118,7 @@ struct lease *lease_new (nn_etime_t texpire, int64_t tdur, struct entity_common void lease_register (struct lease *l) { - DDS_TRACE("lease_register(l %p guid %x:%x:%x:%x)\n", (void *) l, PGUID (l->entity->guid)); + DDS_TRACE("lease_register(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid)); ddsrt_mutex_lock (&gv.leaseheap_lock); lock_lease (l); assert (l->tsched.v == TSCHED_NOT_ON_HEAP); @@ -136,7 +136,7 @@ void lease_register (struct lease *l) void lease_free (struct lease *l) { - DDS_TRACE("lease_free(l %p guid %x:%x:%x:%x)\n", (void *) l, PGUID (l->entity->guid)); + DDS_TRACE("lease_free(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid)); ddsrt_mutex_lock (&gv.leaseheap_lock); if (l->tsched.v != TSCHED_NOT_ON_HEAP) ddsrt_fibheap_delete (&lease_fhdef, &gv.leaseheap, l); @@ -167,9 +167,9 @@ void lease_renew (struct lease *l, nn_etime_t tnowE) int32_t tsec, tusec; DDS_TRACE(" L("); if (l->entity->guid.entityid.u == NN_ENTITYID_PARTICIPANT) - DDS_TRACE(":%x", l->entity->guid.entityid.u); + DDS_TRACE(":%"PRIx32, l->entity->guid.entityid.u); else - DDS_TRACE("%x:%x:%x:%x", PGUID (l->entity->guid)); + DDS_TRACE(""PGUIDFMT"", PGUID (l->entity->guid)); etime_to_sec_usec (&tsec, &tusec, tend_new); DDS_TRACE(" %"PRId32".%06"PRId32")", tsec, tusec); } @@ -233,7 +233,7 @@ int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) continue; } - DDS_LOG(DDS_LC_DISCOVERY, "lease expired: l %p guid %x:%x:%x:%x tend %"PRId64" < now %"PRId64"\n", (void *) l, PGUID (g), l->tend.v, tnowE.v); + DDS_LOG(DDS_LC_DISCOVERY, "lease expired: l %p guid "PGUIDFMT" tend %"PRId64" < now %"PRId64"\n", (void *) l, PGUID (g), l->tend.v, tnowE.v); /* If the proxy participant is relying on another participant for writing its discovery data (on the privileged participant, @@ -266,7 +266,7 @@ int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) if ((proxypp = ephash_lookup_proxy_participant_guid (&g)) != NULL && ephash_lookup_proxy_participant_guid (&proxypp->privileged_pp_guid) != NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "but postponing because privileged pp %x:%x:%x:%x is still live\n", + DDS_LOG(DDS_LC_DISCOVERY, "but postponing because privileged pp "PGUIDFMT" is still live\n", PGUID (proxypp->privileged_pp_guid)); l->tsched = l->tend = add_duration_to_etime (tnowE, 200 * T_MILLISECOND); unlock_lease (l); @@ -350,7 +350,7 @@ void handle_PMD (UNUSED_ARG (const struct receiver_state *rst), nn_wctime_t time nn_guid_prefix_t p = nn_ntoh_guid_prefix (pmd->participantGuidPrefix); unsigned kind = ntohl (pmd->kind); unsigned length = bswap ? bswap4u (pmd->length) : pmd->length; - DDS_TRACE(" pp %x:%x:%x kind %u data %u", p.u[0], p.u[1], p.u[2], kind, length); + DDS_TRACE(" pp %"PRIx32":%"PRIx32":%"PRIx32" kind %u data %u", p.u[0], p.u[1], p.u[2], kind, length); if (len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value) < length) debug_print_rawdata (" SHORT2", pmd->value, len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value)); else diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index 6e8cbef..3f5ac27 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -123,13 +123,13 @@ static int set_rcvbuf (ddsrt_socket_t socket) { /* NN_ERROR does more than just DDS_ERROR(), hence the duplication */ if (config.socket_min_rcvbuf_size.isdefault) - DDS_LOG(DDS_LC_CONFIG, "failed to increase socket receive buffer size to %u bytes, continuing with %u bytes\n", socket_min_rcvbuf_size, ReceiveBufferSize); + DDS_LOG(DDS_LC_CONFIG, "failed to increase socket receive buffer size to %"PRIu32" bytes, continuing with %"PRIu32" bytes\n", socket_min_rcvbuf_size, ReceiveBufferSize); else - DDS_ERROR("failed to increase socket receive buffer size to %u bytes, continuing with %u bytes\n", socket_min_rcvbuf_size, ReceiveBufferSize); + DDS_ERROR("failed to increase socket receive buffer size to %"PRIu32" bytes, continuing with %"PRIu32" bytes\n", socket_min_rcvbuf_size, ReceiveBufferSize); } else { - DDS_LOG(DDS_LC_CONFIG, "socket receive buffer size set to %u bytes\n", ReceiveBufferSize); + DDS_LOG(DDS_LC_CONFIG, "socket receive buffer size set to %"PRIu32" bytes\n", ReceiveBufferSize); } } return 0; diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index c02a63d..a83f9f9 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -257,7 +257,7 @@ static int alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) seq += sizeof (uint32_t); if (strseq->n >= UINT_MAX / sizeof(*strs)) { - DDS_TRACE("plist/alias_stringseq: length %u out of range\n", strseq->n); + DDS_TRACE("plist/alias_stringseq: length %"PRIu32" out of range\n", strseq->n); return Q_ERR_INVALID; } else if (strseq->n == 0) @@ -1185,7 +1185,7 @@ static int valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct return 0; else { - DDS_TRACE("plist/valid_participant_guid: prefix is 0 but entityid is not (%u)\n", g->entityid.u); + DDS_TRACE("plist/valid_participant_guid: prefix is 0 but entityid is not (%"PRIu32")\n", g->entityid.u); return Q_ERR_INVALID; } } @@ -1195,7 +1195,7 @@ static int valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct } else { - DDS_TRACE("plist/valid_participant_guid: entityid not a participant entityid (%u)\n", g->entityid.u); + DDS_TRACE("plist/valid_participant_guid: entityid not a participant entityid (%"PRIu32")\n", g->entityid.u); return Q_ERR_INVALID; } } @@ -1209,7 +1209,7 @@ static int valid_group_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd return 0; else { - DDS_TRACE("plist/valid_group_guid: prefix is 0 but entityid is not (%u)\n", g->entityid.u); + DDS_TRACE("plist/valid_group_guid: prefix is 0 but entityid is not (%"PRIu32")\n", g->entityid.u); return Q_ERR_INVALID; } } @@ -1234,7 +1234,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) return 0; else { - DDS_TRACE("plist/valid_endpoint_guid: prefix is 0 but entityid is not (%x)\n", g->entityid.u); + DDS_TRACE("plist/valid_endpoint_guid: prefix is 0 but entityid is not (%"PRIx32")\n", g->entityid.u); return Q_ERR_INVALID; } } @@ -1253,7 +1253,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) return 0; else { - DDS_TRACE("plist/valid_endpoint_guid[src=USER,proto=%u.%u]: invalid kind (%x)\n", + DDS_TRACE("plist/valid_endpoint_guid[src=USER,proto=%u.%u]: invalid kind (%"PRIx32")\n", dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u & NN_ENTITYID_KIND_MASK); return Q_ERR_INVALID; @@ -1278,7 +1278,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) return 0; else { - DDS_TRACE("plist/valid_endpoint_guid[src=BUILTIN,proto=%u.%u]: invalid entityid (%x)\n", + DDS_TRACE("plist/valid_endpoint_guid[src=BUILTIN,proto=%u.%u]: invalid entityid (%"PRIx32")\n", dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u); return Q_ERR_INVALID; } @@ -1302,14 +1302,14 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) return 0; else { - DDS_TRACE("plist/valid_endpoint_guid[src=VENDOR,proto=%u.%u]: unexpected entityid (%x)\n", + DDS_TRACE("plist/valid_endpoint_guid[src=VENDOR,proto=%u.%u]: unexpected entityid (%"PRIx32")\n", dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u); return 0; } } } default: - DDS_TRACE("plist/valid_endpoint_guid: invalid source (%x)\n", g->entityid.u); + DDS_TRACE("plist/valid_endpoint_guid: invalid source (%"PRIx32")\n", g->entityid.u); return Q_ERR_INVALID; } } @@ -1329,7 +1329,7 @@ static int do_guid (nn_guid_t *dst, uint64_t *present, uint64_t fl, int (*valid) that has long since changed (even if I don't know exactly when) */ if (fl == PP_PARTICIPANT_GUID && vendor_is_twinoaks (dd->vendorid) && dst->entityid.u == 0 && ! NN_STRICT_P) { - DDS_LOG(DDS_LC_DISCOVERY, "plist(vendor %u.%u): rewriting invalid participant guid %x:%x:%x:%x\n", + DDS_LOG(DDS_LC_DISCOVERY, "plist(vendor %u.%u): rewriting invalid participant guid "PGUIDFMT, dd->vendorid.id[0], dd->vendorid.id[1], PGUID (*dst)); dst->entityid.u = NN_ENTITYID_PARTICIPANT; } @@ -2122,9 +2122,9 @@ static int init_one_parameter dest->aliased |= PP_PRISMTECH_EOTINFO; if (dds_get_log_mask() & DDS_LC_PLIST) { - DDS_LOG(DDS_LC_PLIST, "eotinfo: txn %u {", q->transactionId); + DDS_LOG(DDS_LC_PLIST, "eotinfo: txn %"PRIu32" {", q->transactionId); for (i = 0; i < q->n; i++) - DDS_LOG(DDS_LC_PLIST, " %x:%u", q->tids[i].writer_entityid.u, q->tids[i].transactionId); + DDS_LOG(DDS_LC_PLIST, " %"PRIx32":%"PRIu32, q->tids[i].writer_entityid.u, q->tids[i].transactionId); DDS_LOG(DDS_LC_PLIST, " }\n"); } return 0; @@ -3421,12 +3421,12 @@ void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos) DDS_LOG(cat, "}"); }); DO (GROUP_DATA, { - LOGB1 ("group_data=%u<", xqos->group_data.length); + LOGB1 ("group_data=%"PRIu32"<", xqos->group_data.length); log_octetseq (cat, xqos->group_data.length, xqos->group_data.value); DDS_LOG(cat, ">"); }); DO (TOPIC_DATA, { - LOGB1 ("topic_data=%u<", xqos->topic_data.length); + LOGB1 ("topic_data=%"PRIu32"<", xqos->topic_data.length); log_octetseq (cat, xqos->topic_data.length, xqos->topic_data.value); DDS_LOG(cat, ">"); }); @@ -3434,25 +3434,25 @@ void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos) DO (DURABILITY_SERVICE, { LOGB0 ("durability_service="); DDS_LOG(cat, FMT_DUR, PRINTARG_DUR (xqos->durability_service.service_cleanup_delay)); - DDS_LOG(cat, ":{%d:%d}", xqos->durability_service.history.kind, xqos->durability_service.history.depth); - DDS_LOG(cat, ":{%d:%d:%d}", xqos->durability_service.resource_limits.max_samples, xqos->durability_service.resource_limits.max_instances, xqos->durability_service.resource_limits.max_samples_per_instance); + DDS_LOG(cat, ":{%u:%"PRId32"}", xqos->durability_service.history.kind, xqos->durability_service.history.depth); + DDS_LOG(cat, ":{%"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, { LOGB2 ("liveliness=%d:"FMT_DUR, xqos->liveliness.kind, PRINTARG_DUR (xqos->liveliness.lease_duration)); }); DO (RELIABILITY, { LOGB2 ("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, { LOGB2 ("history=%d:%d", xqos->history.kind, xqos->history.depth); }); - DO (RESOURCE_LIMITS, { LOGB3 ("resource_limits=%d:%d:%d", xqos->resource_limits.max_samples, xqos->resource_limits.max_instances, xqos->resource_limits.max_samples_per_instance); }); - DO (TRANSPORT_PRIORITY, { LOGB1 ("transport_priority=%d", xqos->transport_priority.value); }); + DO (HISTORY, { LOGB2 ("history=%d:%"PRId32, xqos->history.kind, xqos->history.depth); }); + DO (RESOURCE_LIMITS, { LOGB3 ("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=%u<", xqos->user_data.length); + LOGB1 ("user_data=%"PRIu32"<", xqos->user_data.length); log_octetseq (cat, xqos->user_data.length, xqos->user_data.value); DDS_LOG(cat, ">"); }); DO (OWNERSHIP, { LOGB1 ("ownership=%d", xqos->ownership.kind); }); - DO (OWNERSHIP_STRENGTH, { LOGB1 ("ownership_strength=%d", xqos->ownership_strength.value); }); + 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, { LOGB5 ("reader_data_lifecycle="FMT_DUR":"FMT_DUR":%u:%u:%d", PRINTARG_DUR (xqos->reader_data_lifecycle.autopurge_nowriter_samples_delay), PRINTARG_DUR (xqos->reader_data_lifecycle.autopurge_disposed_samples_delay), xqos->reader_data_lifecycle.autopurge_dispose_all, xqos->reader_data_lifecycle.enable_invalid_samples, (int) xqos->reader_data_lifecycle.invalid_sample_visibility); }); DO (PRISMTECH_WRITER_DATA_LIFECYCLE, { @@ -3473,7 +3473,7 @@ void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos) DO (PRISMTECH_ENTITY_FACTORY, { LOGB1 ("entity_factory=%u", xqos->entity_factory.autoenable_created_entities); }); DO (PRISMTECH_SYNCHRONOUS_ENDPOINT, { LOGB1 ("synchronous_endpoint=%u", xqos->synchronous_endpoint.value); }); DO (RTI_TYPECODE, { - LOGB1 ("rti_typecode=%u<", xqos->rti_typecode.length); + LOGB1 ("rti_typecode=%"PRIu32"<", xqos->rti_typecode.length); log_octetseq (cat, xqos->rti_typecode.length, xqos->rti_typecode.value); DDS_LOG(cat, ">"); }); diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index 4a739fd..a45d4e0 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -484,7 +484,7 @@ static void *nn_rbuf_alloc (struct nn_rbufpool *rbufpool) /* Note: only one thread calls nn_rmsg_new on a pool */ uint32_t asize = max_rmsg_size_w_hdr (rbufpool->max_rmsg_size); struct nn_rbuf *rb; - DDS_LOG(DDS_LC_RADMIN, "rmsg_rbuf_alloc(%p, %u)\n", (void *) rbufpool, asize); + DDS_LOG(DDS_LC_RADMIN, "rmsg_rbuf_alloc(%p, %"PRIu32")\n", (void *) rbufpool, asize); ASSERT_RBUFPOOL_OWNER (rbufpool); rb = rbufpool->current; assert (rb != NULL); @@ -501,7 +501,7 @@ static void *nn_rbuf_alloc (struct nn_rbufpool *rbufpool) assert ((uint32_t) (rb->u.raw + rb->size - rb->freeptr) >= asize); } - DDS_LOG(DDS_LC_RADMIN, "rmsg_rbuf_alloc(%p, %u) = %p\n", (void *) rbufpool, asize, (void *) rb->freeptr); + DDS_LOG(DDS_LC_RADMIN, "rmsg_rbuf_alloc(%p, %"PRIu32") = %p\n", (void *) rbufpool, asize, (void *) rb->freeptr); #if USE_VALGRIND VALGRIND_MEMPOOL_ALLOC (rbufpool, rb->freeptr, asize); #endif @@ -540,7 +540,7 @@ struct nn_rmsg *nn_rmsg_new (struct nn_rbufpool *rbufpool) void nn_rmsg_setsize (struct nn_rmsg *rmsg, uint32_t size) { uint32_t size8 = align8uint32 (size); - DDS_LOG(DDS_LC_RADMIN, "rmsg_setsize(%p, %u => %u)\n", (void *) rmsg, size, size8); + DDS_LOG(DDS_LC_RADMIN, "rmsg_setsize(%p, %"PRIu32" => %"PRIu32")\n", (void *) rmsg, size, size8); ASSERT_RBUFPOOL_OWNER (rmsg->chunk.rbuf->rbufpool); ASSERT_RMSG_UNCOMMITTED (rmsg); assert (ddsrt_atomic_ld32 (&rmsg->refcount) == RMSG_REFCOUNT_UNCOMMITTED_BIAS); @@ -601,7 +601,7 @@ void nn_rmsg_commit (struct nn_rmsg *rmsg) happens to be such that any asynchronous activities have completed before we got to commit. */ struct nn_rmsg_chunk *chunk = rmsg->lastchunk; - DDS_LOG(DDS_LC_RADMIN, "rmsg_commit(%p) refcount 0x%x last-chunk-size %u\n", + DDS_LOG(DDS_LC_RADMIN, "rmsg_commit(%p) refcount 0x%"PRIx32" last-chunk-size %"PRIu32"\n", (void *) rmsg, rmsg->refcount.v, chunk->size); ASSERT_RBUFPOOL_OWNER (chunk->rbuf->rbufpool); ASSERT_RMSG_UNCOMMITTED (rmsg); @@ -665,7 +665,7 @@ void *nn_rmsg_alloc (struct nn_rmsg *rmsg, uint32_t size) struct nn_rbuf *rbuf = chunk->rbuf; uint32_t size8 = align8uint32 (size); void *ptr; - DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %u => %u)\n", (void *) rmsg, size, size8); + DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %"PRIu32" => %"PRIu32")\n", (void *) rmsg, size, size8); ASSERT_RBUFPOOL_OWNER (rbuf->rbufpool); ASSERT_RMSG_UNCOMMITTED (rmsg); assert ((chunk->size % 8) == 0); @@ -675,12 +675,12 @@ void *nn_rmsg_alloc (struct nn_rmsg *rmsg, uint32_t size) { struct nn_rbufpool *rbufpool = rbuf->rbufpool; struct nn_rmsg_chunk *newchunk; - DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %u) limit hit - new chunk\n", (void *) rmsg, size); + DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %"PRIu32") limit hit - new chunk\n", (void *) rmsg, size); commit_rmsg_chunk (chunk); newchunk = nn_rbuf_alloc (rbufpool); if (newchunk == NULL) { - DDS_WARNING ("nn_rmsg_alloc: can't allocate more memory (%u bytes) ... giving up\n", size); + DDS_WARNING ("nn_rmsg_alloc: can't allocate more memory (%"PRIu32" bytes) ... giving up\n", size); return NULL; } init_rmsg_chunk (newchunk, rbufpool->current); @@ -690,7 +690,7 @@ void *nn_rmsg_alloc (struct nn_rmsg *rmsg, uint32_t size) ptr = chunk->u.payload + chunk->size; chunk->size += size8; - DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %u) = %p\n", (void *) rmsg, size, ptr); + DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %"PRIu32") = %p\n", (void *) rmsg, size, ptr); #if USE_VALGRIND if (chunk == &rmsg->chunk) { VALGRIND_MEMPOOL_CHANGE (rbuf->rbufpool, rmsg, rmsg, offsetof (struct nn_rmsg, chunk.u.payload) + chunk->size); @@ -717,7 +717,7 @@ struct nn_rdata *nn_rdata_new (struct nn_rmsg *rmsg, uint32_t start, uint32_t en #ifndef NDEBUG ddsrt_atomic_st32 (&d->refcount_bias_added, 0); #endif - DDS_LOG(DDS_LC_RADMIN, "rdata_new(%p, bytes [%u,%u), submsg @ %u, payload @ %u) = %p\n", (void *) rmsg, start, endp1, NN_RDATA_SUBMSG_OFF (d), NN_RDATA_PAYLOAD_OFF (d), (void *) d); + DDS_LOG(DDS_LC_RADMIN, "rdata_new(%p, bytes [%"PRIu32",%"PRIu32"), submsg @ %u, payload @ %u) = %p\n", (void *) rmsg, start, endp1, NN_RDATA_SUBMSG_OFF (d), NN_RDATA_PAYLOAD_OFF (d), (void *) d); return d; } @@ -931,7 +931,7 @@ static int defrag_try_merge_with_succ (struct nn_rsample_defrag *sample, struct { struct nn_defrag_iv *succ; - DDS_LOG(DDS_LC_RADMIN, " defrag_try_merge_with_succ(%p [%u..%u)):\n", + DDS_LOG(DDS_LC_RADMIN, " defrag_try_merge_with_succ(%p [%"PRIu32"..%"PRIu32")):\n", (void *) node, node->min, node->maxp1); if (node == sample->lastfrag) { @@ -942,7 +942,7 @@ static int defrag_try_merge_with_succ (struct nn_rsample_defrag *sample, struct succ = ddsrt_avl_find_succ (&rsample_defrag_fragtree_treedef, &sample->fragtree, node); assert (succ != NULL); - DDS_LOG(DDS_LC_RADMIN, " succ is %p [%u..%u)\n", (void *) succ, succ->min, succ->maxp1); + DDS_LOG(DDS_LC_RADMIN, " succ is %p [%"PRIu32"..%"PRIu32")\n", (void *) succ, succ->min, succ->maxp1); if (succ->min > node->maxp1) { DDS_LOG(DDS_LC_RADMIN, " gap between node and succ\n"); @@ -1147,7 +1147,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct /* relatively expensive test: lastfrag, tree must be consistent */ assert (dfsample->lastfrag == ddsrt_avl_find_max (&rsample_defrag_fragtree_treedef, &dfsample->fragtree)); - DDS_LOG(DDS_LC_RADMIN, " lastfrag %p [%u..%u)\n", + DDS_LOG(DDS_LC_RADMIN, " lastfrag %p [%"PRIu32"..%"PRIu32")\n", (void *) dfsample->lastfrag, dfsample->lastfrag->min, dfsample->lastfrag->maxp1); @@ -1164,7 +1164,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct /* Slow path: find preceding fragment by tree search */ predeq = ddsrt_avl_lookup_pred_eq (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &min); assert (predeq); - DDS_LOG(DDS_LC_RADMIN, " slow path: predeq = lookup %u => %p [%u..%u)\n", + DDS_LOG(DDS_LC_RADMIN, " slow path: predeq = lookup %"PRIu32" => %p [%"PRIu32"..%"PRIu32")\n", min, (void *) predeq, predeq->min, predeq->maxp1); } @@ -1213,7 +1213,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct fragment in the chain adds value); but doesn't overlap with predeq so the tree structure doesn't change even though the key does change */ - DDS_LOG(DDS_LC_RADMIN, " extending succ %p [%u..%u) at head\n", + DDS_LOG(DDS_LC_RADMIN, " extending succ %p [%"PRIu32"..%"PRIu32") at head\n", (void *) succ, succ->min, succ->maxp1); nn_rdata_addbias (rdata); rdata->nextfrag = succ->first; @@ -1336,7 +1336,7 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata consistent. Max_sample must be consistent with tree */ assert (defrag->max_sample == ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree)); max_seq = defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0; - DDS_LOG(DDS_LC_RADMIN, "defrag_rsample(%p, %p [%u..%u) msg %p, %p seq %"PRId64" size %u) max_seq %p %"PRId64":\n", + DDS_LOG(DDS_LC_RADMIN, "defrag_rsample(%p, %p [%"PRIu32"..%"PRIu32") msg %p, %p seq %"PRId64" size %"PRIu32") max_seq %p %"PRId64":\n", (void *) defrag, (void *) rdata, rdata->min, rdata->maxp1, (void *) rdata->rmsg, (void *) sampleinfo, sampleinfo->seq, sampleinfo->size, (void *) defrag->max_sample, max_seq); @@ -2230,7 +2230,7 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord } else if (coalesced->u.reorder.min <= reorder->next_seq) { - DDS_LOG(DDS_LC_RADMIN, " coalesced = [%"PRId64",%"PRId64") @ %p containing %d samples\n", + DDS_LOG(DDS_LC_RADMIN, " coalesced = [%"PRId64",%"PRId64") @ %p containing %"PRId32" samples\n", coalesced->u.reorder.min, coalesced->u.reorder.maxp1, (void *) coalesced, coalesced->u.reorder.n_samples); ddsrt_avl_delete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, coalesced); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 4ae45ce..5aae883 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -93,7 +93,7 @@ static void maybe_set_reader_in_sync (struct proxy_writer *pwr, struct pwr_rd_ma case PRMSS_OUT_OF_SYNC: if (nn_reorder_next_seq (wn->u.not_in_sync.reorder) - 1 >= wn->u.not_in_sync.end_of_out_of_sync_seq) { - DDS_TRACE(" msr_in_sync(%x:%x:%x:%x out-of-sync to tlcatchup)", PGUID (wn->rd_guid)); + DDS_TRACE(" msr_in_sync("PGUIDFMT" out-of-sync to tlcatchup)", PGUID (wn->rd_guid)); wn->in_sync = PRMSS_TLCATCHUP; maybe_set_reader_in_sync (pwr, wn, last_deliv_seq); } @@ -627,14 +627,14 @@ static void force_heartbeat_to_peer (struct writer *wr, const struct whc_state * } add_Gap (m, wr, prd, seq, seq+1, 1, &bits); add_Heartbeat (m, wr, whcst, hbansreq, prd->e.guid.entityid, 1); - DDS_TRACE("force_heartbeat_to_peer: %x:%x:%x:%x -> %x:%x:%x:%x - whc empty, queueing gap #%"PRId64" + heartbeat for transmit\n", + DDS_TRACE("force_heartbeat_to_peer: "PGUIDFMT" -> "PGUIDFMT" - whc empty, queueing gap #%"PRId64" + heartbeat for transmit\n", PGUID (wr->e.guid), PGUID (prd->e.guid), seq); } else { /* Send a Heartbeat just to this peer */ add_Heartbeat (m, wr, whcst, hbansreq, prd->e.guid.entityid, 0); - DDS_TRACE("force_heartbeat_to_peer: %x:%x:%x:%x -> %x:%x:%x:%x - queue for transmit\n", + DDS_TRACE("force_heartbeat_to_peer: "PGUIDFMT" -> "PGUIDFMT" - queue for transmit\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); } qxev_msg (wr->evq, m); @@ -729,7 +729,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac src.entityid = msg->readerId; dst.prefix = rst->dst_guid_prefix; dst.entityid = msg->writerId; - DDS_TRACE("ACKNACK(%s#%d:%"PRId64"/%u:", msg->smhdr.flags & ACKNACK_FLAG_FINAL ? "F" : "", + DDS_TRACE("ACKNACK(%s#%"PRId32":%"PRId64"/%"PRIu32":", msg->smhdr.flags & ACKNACK_FLAG_FINAL ? "F" : "", *countp, fromSN (msg->readerSNState.bitmap_base), msg->readerSNState.numbits); for (i = 0; i < msg->readerSNState.numbits; i++) DDS_TRACE("%c", nn_bitset_isset (msg->readerSNState.numbits, msg->readerSNState.bits, i) ? '1' : '0'); @@ -737,13 +737,13 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac if (!rst->forme) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not-for-me)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst)); return 1; } if ((wr = ephash_lookup_writer_guid (&dst)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x?)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"?)", PGUID (src), PGUID (dst)); return 1; } /* Always look up the proxy reader -- even though we don't need for @@ -752,7 +752,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac only retrieve it when needed. */ if ((prd = ephash_lookup_proxy_reader_guid (&src)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x? -> %x:%x:%x:%x)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst)); return 1; } @@ -762,14 +762,14 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac if (!wr->reliable) /* note: reliability can't be changed */ { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not a reliable writer!)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not a reliable writer!)", PGUID (src), PGUID (dst)); return 1; } ddsrt_mutex_lock (&wr->e.lock); if ((rn = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &src)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not a connection)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not a connection)", PGUID (src), PGUID (dst)); goto out; } @@ -789,10 +789,10 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac if (!accept_ack_or_hb_w_timeout (*countp, &rn->next_acknack, tnow, &rn->t_acknack_accepted, is_preemptive_ack)) { - DDS_TRACE(" [%x:%x:%x:%x -> %x:%x:%x:%x])", PGUID (src), PGUID (dst)); + DDS_TRACE(" ["PGUIDFMT" -> "PGUIDFMT"])", PGUID (src), PGUID (dst)); goto out; } - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst)); /* Update latency estimates if we have a timestamp -- won't actually work so well if the timestamp can be a left over from some other @@ -851,7 +851,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac rn->seq = wr->seq; } ddsrt_avl_augment_update (&wr_readers_treedef, rn); - DDS_LOG(DDS_LC_THROTTLE, "writer %x:%x:%x:%x considering reader %x:%x:%x:%x responsive again\n", PGUID (wr->e.guid), PGUID (rn->prd_guid)); + DDS_LOG(DDS_LC_THROTTLE, "writer "PGUIDFMT" considering reader "PGUIDFMT" responsive again\n", PGUID (wr->e.guid), PGUID (rn->prd_guid)); } /* Second, the NACK bits (literally, that is). To do so, attempt to @@ -1143,7 +1143,7 @@ static void handle_Heartbeat_helper (struct pwr_rd_match * const wn, struct hand /* Not supposed to respond to repeats and old heartbeats. */ if (!accept_ack_or_hb_w_timeout (msg->count, &wn->next_heartbeat, arg->tnow, &wn->t_heartbeat_accepted, 0)) { - DDS_TRACE(" (%x:%x:%x:%x)", PGUID (wn->rd_guid)); + DDS_TRACE(" ("PGUIDFMT")", PGUID (wn->rd_guid)); return; } @@ -1154,7 +1154,7 @@ static void handle_Heartbeat_helper (struct pwr_rd_match * const wn, struct hand refseq = nn_reorder_next_seq (pwr->reorder) - 1; else refseq = nn_reorder_next_seq (wn->u.not_in_sync.reorder) - 1; - DDS_TRACE(" %x:%x:%x:%x@%"PRId64"%s", PGUID (wn->rd_guid), refseq, (wn->in_sync == PRMSS_SYNC) ? "(sync)" : (wn->in_sync == PRMSS_TLCATCHUP) ? "(tlcatchup)" : ""); + DDS_TRACE(" "PGUIDFMT"@%"PRId64"%s", PGUID (wn->rd_guid), refseq, (wn->in_sync == PRMSS_SYNC) ? "(sync)" : (wn->in_sync == PRMSS_TLCATCHUP) ? "(tlcatchup)" : ""); /* Reschedule AckNack transmit if deemed appropriate; unreliable readers have acknack_xevent == NULL and can't do this. @@ -1214,17 +1214,17 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct dst.prefix = rst->dst_guid_prefix; dst.entityid = msg->readerId; - DDS_TRACE("HEARTBEAT(%s#%d:%"PRId64"..%"PRId64" ", msg->smhdr.flags & HEARTBEAT_FLAG_FINAL ? "F" : "", msg->count, firstseq, lastseq); + DDS_TRACE("HEARTBEAT(%s#%"PRId32":%"PRId64"..%"PRId64" ", msg->smhdr.flags & HEARTBEAT_FLAG_FINAL ? "F" : "", msg->count, firstseq, lastseq); if (!rst->forme) { - DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x not-for-me)", PGUID (src), PGUID (dst)); + DDS_TRACE(""PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst)); return 1; } if ((pwr = ephash_lookup_proxy_writer_guid (&src)) == NULL) { - DDS_TRACE("%x:%x:%x:%x? -> %x:%x:%x:%x)", PGUID (src), PGUID (dst)); + DDS_TRACE(""PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst)); return 1; } @@ -1232,7 +1232,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct if (pwr->assert_pp_lease) lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); - DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x:", PGUID (src), PGUID (dst)); + DDS_TRACE(""PGUIDFMT" -> "PGUIDFMT":", PGUID (src), PGUID (dst)); ddsrt_mutex_lock (&pwr->e.lock); @@ -1311,7 +1311,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct if (wn->u.not_in_sync.end_of_tl_seq == MAX_SEQ_NUMBER) { wn->u.not_in_sync.end_of_out_of_sync_seq = wn->u.not_in_sync.end_of_tl_seq = fromSN (msg->lastSN); - DDS_TRACE(" end-of-tl-seq(rd %x:%x:%x:%x #%"PRId64")", PGUID(wn->rd_guid), wn->u.not_in_sync.end_of_tl_seq); + DDS_TRACE(" end-of-tl-seq(rd "PGUIDFMT" #%"PRId64")", PGUID(wn->rd_guid), wn->u.not_in_sync.end_of_tl_seq); } maybe_set_reader_in_sync (pwr, wn, last_deliv_seq); } @@ -1343,16 +1343,16 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime dst.prefix = rst->dst_guid_prefix; dst.entityid = msg->readerId; - DDS_TRACE("HEARTBEATFRAG(#%d:%"PRId64"/[1,%u]", msg->count, seq, fragnum+1); + DDS_TRACE("HEARTBEATFRAG(#%"PRId32":%"PRId64"/[1,%u]", msg->count, seq, fragnum+1); if (!rst->forme) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not-for-me)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst)); return 1; } if ((pwr = ephash_lookup_proxy_writer_guid (&src)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x? -> %x:%x:%x:%x)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst)); return 1; } @@ -1360,7 +1360,7 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime if (pwr->assert_pp_lease) lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst)); ddsrt_mutex_lock (&pwr->e.lock); if (seq > pwr->last_seq) @@ -1459,19 +1459,19 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N dst.prefix = rst->dst_guid_prefix; dst.entityid = msg->writerId; - DDS_TRACE("NACKFRAG(#%d:%"PRId64"/%u/%u:", *countp, seq, msg->fragmentNumberState.bitmap_base, msg->fragmentNumberState.numbits); + DDS_TRACE("NACKFRAG(#%"PRId32":%"PRId64"/%u/%"PRIu32":", *countp, seq, msg->fragmentNumberState.bitmap_base, msg->fragmentNumberState.numbits); for (i = 0; i < msg->fragmentNumberState.numbits; i++) DDS_TRACE("%c", nn_bitset_isset (msg->fragmentNumberState.numbits, msg->fragmentNumberState.bits, i) ? '1' : '0'); if (!rst->forme) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not-for-me)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst)); return 1; } if ((wr = ephash_lookup_writer_guid (&dst)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x?)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"?)", PGUID (src), PGUID (dst)); return 1; } /* Always look up the proxy reader -- even though we don't need for @@ -1480,7 +1480,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N only retrieve it when needed. */ if ((prd = ephash_lookup_proxy_reader_guid (&src)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x? -> %x:%x:%x:%x)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst)); return 1; } @@ -1490,25 +1490,25 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N if (!wr->reliable) /* note: reliability can't be changed */ { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not a reliable writer)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not a reliable writer)", PGUID (src), PGUID (dst)); return 1; } ddsrt_mutex_lock (&wr->e.lock); if ((rn = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &src)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not a connection", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not a connection", PGUID (src), PGUID (dst)); goto out; } /* Ignore old NackFrags (see also handle_AckNack) */ if (*countp < rn->next_nackfrag) { - DDS_TRACE(" [%x:%x:%x:%x -> %x:%x:%x:%x]", PGUID (src), PGUID (dst)); + DDS_TRACE(" ["PGUIDFMT" -> "PGUIDFMT"]", PGUID (src), PGUID (dst)); goto out; } rn->next_nackfrag = *countp + 1; - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst)); /* Resend the requested fragments if we still have the sample, send a Gap if we don't have them anymore. */ @@ -1569,7 +1569,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N static int handle_InfoDST (struct receiver_state *rst, const InfoDST_t *msg, const nn_guid_prefix_t *dst_prefix) { rst->dst_guid_prefix = nn_ntoh_guid_prefix (msg->guid_prefix); - DDS_TRACE("INFODST(%x:%x:%x)", PGUIDPREFIX (rst->dst_guid_prefix)); + DDS_TRACE("INFODST(%"PRIx32":%"PRIx32":%"PRIx32")", PGUIDPREFIX (rst->dst_guid_prefix)); if (rst->dst_guid_prefix.u[0] == 0 && rst->dst_guid_prefix.u[1] == 0 && rst->dst_guid_prefix.u[2] == 0) { if (dst_prefix) @@ -1591,7 +1591,7 @@ static int handle_InfoSRC (struct receiver_state *rst, const InfoSRC_t *msg) rst->src_guid_prefix = nn_ntoh_guid_prefix (msg->guid_prefix); rst->protocol_version = msg->version; rst->vendor = msg->vendorid; - DDS_TRACE("INFOSRC(%x:%x:%x vendor %u.%u)", + DDS_TRACE("INFOSRC(%"PRIx32":%"PRIx32":%"PRIx32" vendor %u.%u)", PGUIDPREFIX (rst->src_guid_prefix), rst->vendor.id[0], rst->vendor.id[1]); return 1; } @@ -1710,7 +1710,7 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm dst.entityid = msg->readerId; gapstart = fromSN (msg->gapStart); listbase = fromSN (msg->gapList.bitmap_base); - DDS_TRACE("GAP(%"PRId64"..%"PRId64"/%u ", gapstart, listbase, msg->gapList.numbits); + DDS_TRACE("GAP(%"PRId64"..%"PRId64"/%"PRIu32" ", gapstart, listbase, msg->gapList.numbits); /* There is no _good_ reason for a writer to start the bitmap with a 1 bit, but check for it just in case, to reduce the number of @@ -1722,13 +1722,13 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm if (!rst->forme) { - DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x not-for-me)", PGUID (src), PGUID (dst)); + DDS_TRACE(""PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst)); return 1; } if ((pwr = ephash_lookup_proxy_writer_guid (&src)) == NULL) { - DDS_TRACE("%x:%x:%x:%x? -> %x:%x:%x:%x)", PGUID (src), PGUID (dst)); + DDS_TRACE(""PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst)); return 1; } @@ -1739,11 +1739,11 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm ddsrt_mutex_lock (&pwr->e.lock); if ((wn = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, &dst)) == NULL) { - DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x not a connection)", PGUID (src), PGUID (dst)); + DDS_TRACE(PGUIDFMT" -> "PGUIDFMT" not a connection)", PGUID (src), PGUID (dst)); ddsrt_mutex_unlock (&pwr->e.lock); return 1; } - DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x", PGUID (src), PGUID (dst)); + DDS_TRACE(PGUIDFMT" -> "PGUIDFMT, PGUID (src), PGUID (dst)); if (!pwr->have_seen_heartbeat && pwr->n_reliable_readers > 0) { @@ -1831,8 +1831,8 @@ static struct ddsi_serdata *extract_sample_from_data { const struct proxy_writer *pwr = sampleinfo->pwr; nn_guid_t guid = pwr ? pwr->e.guid : null_guid; /* can't be null _yet_, but that might change some day */ - DDS_TRACE("data(application, vendor %u.%u): %x:%x:%x:%x #%"PRId64 - ": write without proper payload (data_smhdr_flags 0x%x size %u)\n", + DDS_TRACE("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); @@ -1882,7 +1882,7 @@ static struct ddsi_serdata *extract_sample_from_data nn_guid_t guid = pwr ? pwr->e.guid : null_guid; /* can't be null _yet_, but that might change some day */ DDS_WARNING ( - "data(application, vendor %u.%u): %x:%x:%x:%x #%"PRId64": deserialization %s/%s failed (%s)\n", + "data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": deserialization %s/%s failed (%s)\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (guid), sampleinfo->seq, topic->name, topic->type_name, @@ -1988,7 +1988,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH | PP_COHERENT_SET | PP_PRISMTECH_EOTINFO, 0, &src)) < 0) { if (plist_ret != Q_ERR_INCOMPATIBLE) - DDS_WARNING ("data(application, vendor %u.%u): %x:%x:%x:%x #%"PRId64": invalid inline qos\n", + DDS_WARNING ("data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n", src.vendorid.id[0], src.vendorid.id[1], PGUID (pwr->e.guid), sampleinfo->seq); return 0; } @@ -2047,7 +2047,7 @@ retry: unsigned i; for (i = 0; rdary[i]; i++) { - DDS_TRACE("reader %x:%x:%x:%x\n", PGUID (rdary[i]->e.guid)); + DDS_TRACE("reader "PGUIDFMT"\n", PGUID (rdary[i]->e.guid)); if (! (ddsi_plugin.rhc_plugin.rhc_store_fn) (rdary[i]->rhc, &pwr_info, payload, tk)) { if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock); @@ -2078,7 +2078,7 @@ retry: struct reader *rd; if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) { - DDS_TRACE("reader-via-guid %x:%x:%x:%x\n", PGUID (rd->e.guid)); + DDS_TRACE("reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid)); (void) (ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk); } } @@ -2090,7 +2090,7 @@ retry: else { struct reader *rd = ephash_lookup_reader_guid (rdguid);; - DDS_TRACE(" %"PRId64"=>%x:%x:%x:%x%s\n", sampleinfo->seq, PGUID (*rdguid), rd ? "" : "?"); + DDS_TRACE(" %"PRId64"=>"PGUIDFMT"%s\n", sampleinfo->seq, PGUID (*rdguid), rd ? "" : "?"); while (rd && ! (ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk) && ephash_lookup_proxy_writer_guid (&pwr->e.guid)) { if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock); @@ -2166,7 +2166,7 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct nn_guid_t src; src.prefix = rst->src_guid_prefix; src.entityid = msg->writerId; - DDS_TRACE(" %x:%x:%x:%x? -> %x:%x:%x:%x", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT"? -> "PGUIDFMT, PGUID (src), PGUID (dst)); return; } @@ -2195,14 +2195,14 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct if (!pwr->have_seen_heartbeat && pwr->n_reliable_readers > 0) { ddsrt_mutex_unlock (&pwr->e.lock); - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x: no heartbeat seen yet", PGUID (pwr->e.guid), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT": no heartbeat seen yet", PGUID (pwr->e.guid), PGUID (dst)); return; } if (ddsrt_avl_is_empty (&pwr->readers) || pwr->local_matching_inprogress) { ddsrt_mutex_unlock (&pwr->e.lock); - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x: no readers", PGUID (pwr->e.guid), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT": no readers", PGUID (pwr->e.guid), PGUID (dst)); return; } @@ -2359,7 +2359,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con cause periodic warnings. */ if (msg->writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) { - DDS_WARNING ("dropping oversize (%u > %u) SPDP sample %"PRId64" from remote writer %x:%x:%x:%x\n", + DDS_WARNING ("dropping oversize (%"PRIu32" > %"PRIu32") SPDP sample %"PRId64" from remote writer "PGUIDFMT"\n", sampleinfo->size, config.max_sample_size, sampleinfo->seq, PGUIDPREFIX (rst->src_guid_prefix), msg->writerId.u); } @@ -2389,7 +2389,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con { const char *tname = pwr->c.topic ? pwr->c.topic->name : "(null)"; const char *ttname = pwr->c.topic ? pwr->c.topic->type_name : "(null)"; - DDS_WARNING ("dropping oversize (%u > %u) sample %"PRId64" from remote writer %x:%x:%x:%x %s/%s\n", + DDS_WARNING ("dropping oversize (%"PRIu32" > %"PRIu32") sample %"PRId64" from remote writer "PGUIDFMT" %s/%s\n", sampleinfo->size, config.max_sample_size, sampleinfo->seq, PGUIDPREFIX (rst->src_guid_prefix), msg->writerId.u, tname, ttname); @@ -2399,7 +2399,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup) { - DDS_TRACE("DATA(%x:%x:%x:%x -> %x:%x:%x:%x #%"PRId64"", + DDS_TRACE("DATA("PGUIDFMT" -> "PGUIDFMT" #%"PRId64, PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u, fromSN (msg->x.writerSN)); @@ -2443,7 +2443,7 @@ static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_r static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const DataFrag_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup) { - DDS_TRACE("DATAFRAG(%x:%x:%x:%x -> %x:%x:%x:%x #%"PRId64"/[%u..%u]", + DDS_TRACE("DATAFRAG("PGUIDFMT" -> "PGUIDFMT" #%"PRId64"/[%u..%u]", PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u, fromSN (msg->x.writerSN), @@ -2463,7 +2463,7 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct uint32_t begin, endp1; if (msg->x.writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) { - DDS_WARNING ("DATAFRAG(%x:%x:%x:%x #%"PRId64" -> %x:%x:%x:%x) - fragmented builtin data not yet supported\n", + DDS_WARNING ("DATAFRAG("PGUIDFMT" #%"PRId64" -> "PGUIDFMT") - fragmented builtin data not yet supported\n", PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, fromSN (msg->x.writerSN), PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u); return 1; @@ -2496,7 +2496,7 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct here */ endp1 = msg->sampleSize; } - DDS_TRACE("/[%u..%u) of %u", begin, endp1, msg->sampleSize); + DDS_TRACE("/[%"PRIu32"..%"PRIu32") of %"PRIu32, begin, endp1, msg->sampleSize); rdata = nn_rdata_new (rmsg, begin, endp1, submsg_offset, payload_offset); @@ -2910,7 +2910,7 @@ static int handle_submsg_sequence #endif /* DDSI_INCLUDE_ENCRYPTION */ break; default: - DDS_TRACE("(unknown id %u?)\n", sm->pt_infocontainer.id); + DDS_TRACE("(unknown id %"PRIu32"?)\n", sm->pt_infocontainer.id); } } break; @@ -2919,7 +2919,7 @@ static int handle_submsg_sequence #if 0 state = "parse:msg_len"; #endif - DDS_TRACE("MSG_LEN(%u)", ((MsgLen_t*) sm)->length); + DDS_TRACE("MSG_LEN(%"PRIu32")", ((MsgLen_t*) sm)->length); break; } case SMID_PT_ENTITY_ID: @@ -3086,7 +3086,7 @@ static bool do_packet else if (hdr->version.major != RTPS_MAJOR || (hdr->version.major == RTPS_MAJOR && hdr->version.minor < RTPS_MINOR_MINIMUM)) { if ((hdr->version.major == RTPS_MAJOR && hdr->version.minor < RTPS_MINOR_MINIMUM)) - DDS_TRACE("HDR(%x:%x:%x vendor %d.%d) len %lu\n, version mismatch: %d.%d\n", + DDS_TRACE("HDR(%"PRIx32":%"PRIx32":%"PRIx32" vendor %d.%d) len %lu\n, version mismatch: %d.%d\n", PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, hdr->version.major, hdr->version.minor); if (NN_PEDANTIC_P) malformed_packet_received_nosubmsg (buff, sz, "header", hdr->vendorid); @@ -3099,7 +3099,7 @@ static bool do_packet { char addrstr[DDSI_LOCSTRLEN]; ddsi_locator_to_string(addrstr, sizeof(addrstr), &srcloc); - DDS_TRACE("HDR(%x:%x:%x vendor %d.%d) len %lu from %s\n", + DDS_TRACE("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); } @@ -3173,7 +3173,7 @@ static void rebuild_local_participant_set (struct thread_state1 * const ts1, str struct ephash_enum_participant est; struct participant *pp; unsigned nps_alloc; - DDS_TRACE("pp set gen changed: local %u global %"PRIu32"\n", lps->gen, ddsrt_atomic_ld32(&gv.participant_set_generation)); + DDS_TRACE("pp set gen changed: local %"PRIu32" global %"PRIu32"\n", lps->gen, ddsrt_atomic_ld32(&gv.participant_set_generation)); thread_state_awake (ts1); restart: lps->gen = ddsrt_atomic_ld32 (&gv.participant_set_generation); @@ -3201,7 +3201,7 @@ static void rebuild_local_participant_set (struct thread_state1 * const ts1, str { lps->ps[lps->nps].m_conn = pp->m_conn; lps->ps[lps->nps].guid_prefix = pp->e.guid.prefix; - DDS_TRACE(" pp %x:%x:%x:%x handle %"PRIdSOCK"\n", PGUID (pp->e.guid), ddsi_conn_handle (pp->m_conn)); + DDS_TRACE(" pp "PGUIDFMT" handle %"PRIdSOCK"\n", PGUID (pp->e.guid), ddsi_conn_handle (pp->m_conn)); lps->nps++; } } diff --git a/src/core/ddsi/src/q_sockwaitset.c b/src/core/ddsi/src/q_sockwaitset.c index 7d811e7..f8a761f 100644 --- a/src/core/ddsi/src/q_sockwaitset.c +++ b/src/core/ddsi/src/q_sockwaitset.c @@ -873,7 +873,7 @@ os_sockWaitsetCtx os_sockWaitsetWait (os_sockWaitset ws) dds_retcode_t rc = ddsrt_select (fdmax, rdset, NULL, NULL, DDS_INFINITY, &n); if (rc != DDS_RETCODE_OK && rc != DDS_RETCODE_INTERRUPTED && rc != DDS_RETCODE_TRY_AGAIN) { - DDS_WARNING("os_sockWaitsetWait: select failed, retcode = %d", rc); + DDS_WARNING("os_sockWaitsetWait: select failed, retcode = %"PRId32, rc); break; } } diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index 9ca93fc..e8ed142 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -275,7 +275,7 @@ dds_retcode_t create_thread (struct thread_state1 **ts1, const char *name, uint3 if (!tprops->stack_size.isdefault) tattr.stackSize = tprops->stack_size.value; } - DDS_TRACE("create_thread: %s: class %d priority %d stack %u\n", name, (int) tattr.schedClass, tattr.schedPriority, tattr.stackSize); + DDS_TRACE("create_thread: %s: class %d priority %"PRId32" stack %"PRIu32"\n", name, (int) tattr.schedClass, tattr.schedPriority, tattr.stackSize); if (ddsrt_thread_create (&tid, name, &tattr, &create_thread_wrapper, ctxt) != DDS_RETCODE_OK) { diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index c83c008..7401d3b 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -185,11 +185,11 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru } } - DDS_TRACE("writer_hbcontrol: wr %x:%x:%x:%x ", PGUID (wr->e.guid)); + DDS_TRACE("writer_hbcontrol: wr "PGUIDFMT" ", PGUID (wr->e.guid)); if (prd_guid == NULL) DDS_TRACE("multicasting "); else - DDS_TRACE("unicasting to prd %x:%x:%x:%x ", PGUID (*prd_guid)); + DDS_TRACE("unicasting to prd "PGUIDFMT" ", PGUID (*prd_guid)); DDS_TRACE("(rel-prd %d seq-eq-max %d seq %"PRId64" maxseq %"PRId64")\n", wr->num_reliable_readers, ddsrt_avl_is_empty (&wr->readers) ? -1 : root_rdmatch (wr)->num_reliable_readers_where_seq_equals_max, @@ -209,7 +209,7 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru struct proxy_reader *prd; if ((prd = ephash_lookup_proxy_reader_guid (prd_guid)) == NULL) { - DDS_TRACE("writer_hbcontrol: wr %x:%x:%x:%x unknown prd %x:%x:%x:%x\n", PGUID (wr->e.guid), PGUID (*prd_guid)); + DDS_TRACE("writer_hbcontrol: wr "PGUIDFMT" unknown prd "PGUIDFMT"\n", PGUID (wr->e.guid), PGUID (*prd_guid)); nn_xmsg_free (msg); return NULL; } @@ -308,7 +308,7 @@ struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_ if (msg) { - DDS_TRACE("heartbeat(wr %x:%x:%x:%x%s) piggybacked, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n", + DDS_TRACE("heartbeat(wr "PGUIDFMT"%s) piggybacked, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n", PGUID (wr->e.guid), *hbansreq ? "" : " final", (hbc->tsched.v == T_NEVER) ? POS_INFINITY_DOUBLE : (double) (hbc->tsched.v - tnow.v) / 1e9, @@ -635,7 +635,7 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli nn_xmsg_serdata (*pmsg, serdata, fragstart, fraglen); nn_xmsg_submsg_setnext (*pmsg, sm_marker); #if 0 - DDS_TRACE("queue data%s %x:%x:%x:%x #%lld/%u[%u..%u)\n", + DDS_TRACE("queue data%s "PGUIDFMT" #%lld/%u[%u..%u)\n", fragging ? "frag" : "", PGUID (wr->e.guid), seq, fragnum+1, fragstart, fragstart + fraglen); #endif @@ -871,10 +871,10 @@ static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist const char *ttname = wr->topic ? wr->topic->type_name : "(null)"; ppbuf[0] = '\0'; tmp = sizeof (ppbuf) - 1; - DDS_TRACE("write_sample %x:%x:%x:%x #%"PRId64"", PGUID (wr->e.guid), seq); + DDS_TRACE("write_sample "PGUIDFMT" #%"PRId64, PGUID (wr->e.guid), seq); if (plist != 0 && (plist->present & PP_COHERENT_SET)) DDS_TRACE(" C#%"PRId64"", fromSN (plist->coherent_set_seqno)); - DDS_TRACE(": ST%u %s/%s:%s%s\n", serdata->statusinfo, tname, ttname, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)"); + DDS_TRACE(": ST%"PRIu32" %s/%s:%s%s\n", serdata->statusinfo, tname, ttname, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)"); } assert (wr->reliable || have_reliable_subs (wr) == 0); @@ -960,7 +960,7 @@ static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct n assert (!is_builtin_entityid(wr->e.guid.entityid, NN_VENDORID_ECLIPSE)); } - DDS_LOG(DDS_LC_THROTTLE, "writer %x:%x:%x:%x waiting for whc to shrink below low-water mark (whc %"PRIuSIZE" low=%u high=%u)\n", PGUID (wr->e.guid), whcst.unacked_bytes, wr->whc_low, wr->whc_high); + DDS_LOG(DDS_LC_THROTTLE, "writer "PGUIDFMT" waiting for whc to shrink below low-water mark (whc %"PRIuSIZE" low=%"PRIu32" high=%"PRIu32")\n", PGUID (wr->e.guid), whcst.unacked_bytes, wr->whc_low, wr->whc_high); wr->throttling++; wr->throttle_count++; @@ -1007,7 +1007,7 @@ static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct n ddsrt_cond_broadcast (&wr->throttle_cond); } - DDS_LOG(DDS_LC_THROTTLE, "writer %x:%x:%x:%x done waiting for whc to shrink below low-water mark (whc %"PRIuSIZE" low=%u high=%u)\n", PGUID (wr->e.guid), whcst.unacked_bytes, wr->whc_low, wr->whc_high); + DDS_LOG(DDS_LC_THROTTLE, "writer "PGUIDFMT" done waiting for whc to shrink below low-water mark (whc %"PRIuSIZE" low=%"PRIu32" high=%"PRIu32")\n", PGUID (wr->e.guid), whcst.unacked_bytes, wr->whc_low, wr->whc_high); return result; } @@ -1046,7 +1046,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * const char *ttname = wr->topic ? wr->topic->type_name : "(null)"; ppbuf[0] = '\0'; tmp = sizeof (ppbuf) - 1; - DDS_WARNING ("dropping oversize (%u > %u) sample from local writer %x:%x:%x:%x %s/%s:%s%s\n", + DDS_WARNING ("dropping oversize (%"PRIu32" > %"PRIu32") sample from local writer "PGUIDFMT" %s/%s:%s%s\n", ddsi_serdata_size (serdata), config.max_sample_size, PGUID (wr->e.guid), tname, ttname, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)"); diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index bbeb9c2..e4b107b 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -196,7 +196,7 @@ static void trace_msg (const char *func, const struct nn_xmsg *m) seqno_t wrseq; nn_fragment_number_t wrfragid; nn_xmsg_guid_seq_fragid (m, &wrguid, &wrseq, &wrfragid); - DDS_TRACE(" %s(%x:%x:%x:%x/%"PRId64"/%u)", func, PGUID (wrguid), wrseq, wrfragid); + DDS_TRACE(" %s("PGUIDFMT"/%"PRId64"/%u)", func, PGUID (wrguid), wrseq, wrfragid); } } #else @@ -604,7 +604,7 @@ static void handle_xevk_heartbeat (struct nn_xpack *xp, struct xevent *ev, nn_mt if ((wr = ephash_lookup_writer_guid (&ev->u.heartbeat.wr_guid)) == NULL) { - DDS_TRACE("heartbeat(wr %x:%x:%x:%x) writer gone\n", + DDS_TRACE("heartbeat(wr "PGUIDFMT") writer gone\n", PGUID (ev->u.heartbeat.wr_guid)); return; } @@ -631,7 +631,7 @@ static void handle_xevk_heartbeat (struct nn_xpack *xp, struct xevent *ev, nn_mt t_next.v = tnow.v + writer_hbcontrol_intv (wr, &whcst, tnow); } - DDS_TRACE("heartbeat(wr %x:%x:%x:%x%s) %s, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n", + DDS_TRACE("heartbeat(wr "PGUIDFMT"%s) %s, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n", PGUID (wr->e.guid), hbansreq ? "" : " final", msg ? "sent" : "suppressed", @@ -826,7 +826,7 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p nn_xmsg_shrink (msg, sm_marker, ACKNACK_SIZE (an->readerSNState.numbits)); nn_xmsg_submsg_setnext (msg, sm_marker); - DDS_TRACE("acknack %x:%x:%x:%x -> %x:%x:%x:%x: #%d:%"PRId64"/%u:", + DDS_TRACE("acknack "PGUIDFMT" -> "PGUIDFMT": #%"PRId32":%"PRId64"/%"PRIu32":", PGUID (rwn->rd_guid), PGUID (pwr->e.guid), rwn->count, base, an->readerSNState.numbits); for (ui = 0; ui != an->readerSNState.numbits; ui++) @@ -857,7 +857,7 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p *countp = ++pwr->nackfragcount; nn_xmsg_submsg_setnext (msg, sm_marker); - DDS_TRACE(" + nackfrag #%d:%"PRId64"/%u/%u:", *countp, fromSN (nf->writerSN), nf->fragmentNumberState.bitmap_base, nf->fragmentNumberState.numbits); + DDS_TRACE(" + nackfrag #%"PRId32":%"PRId64"/%u/%"PRIu32":", *countp, fromSN (nf->writerSN), nf->fragmentNumberState.bitmap_base, nf->fragmentNumberState.numbits); for (ui = 0; ui != nf->fragmentNumberState.numbits; ui++) DDS_TRACE("%c", nn_bitset_isset (nf->fragmentNumberState.numbits, nf->fragmentNumberState.bits, ui) ? '1' : '0'); } @@ -922,12 +922,12 @@ static void handle_xevk_acknack (UNUSED_ARG (struct nn_xpack *xp), struct xevent eventually. */ resched_xevent_if_earlier (ev, add_duration_to_mtime (tnow, config.auto_resched_nack_delay)); } - DDS_TRACE("send acknack(rd %x:%x:%x:%x -> pwr %x:%x:%x:%x)\n", + DDS_TRACE("send acknack(rd "PGUIDFMT" -> pwr "PGUIDFMT")\n", PGUID (ev->u.acknack.rd_guid), PGUID (ev->u.acknack.pwr_guid)); } else { - DDS_TRACE("skip acknack(rd %x:%x:%x:%x -> pwr %x:%x:%x:%x): no address\n", + DDS_TRACE("skip acknack(rd "PGUIDFMT" -> pwr "PGUIDFMT"): no address\n", PGUID (ev->u.acknack.rd_guid), PGUID (ev->u.acknack.pwr_guid)); msg = NULL; } @@ -1009,7 +1009,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e if ((pp = ephash_lookup_participant_guid (&ev->u.spdp.pp_guid)) == NULL) { - DDS_TRACE("handle_xevk_spdp %x:%x:%x:%x - unknown guid\n", + DDS_TRACE("handle_xevk_spdp "PGUIDFMT" - unknown guid\n", PGUID (ev->u.spdp.pp_guid)); if (ev->u.spdp.directed) delete_xevent (ev); @@ -1018,7 +1018,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e if ((spdp_wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL) { - DDS_TRACE("handle_xevk_spdp %x:%x:%x:%x - spdp writer of participant not found\n", + DDS_TRACE("handle_xevk_spdp "PGUIDFMT" - spdp writer of participant not found\n", PGUID (ev->u.spdp.pp_guid)); if (ev->u.spdp.directed) delete_xevent (ev); @@ -1040,7 +1040,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e prd = ephash_lookup_proxy_reader_guid (&guid); do_write = (prd != NULL); if (!do_write) - DDS_TRACE("xmit spdp: no proxy reader %x:%x:%x:%x\n", PGUID (guid)); + DDS_TRACE("xmit spdp: no proxy reader "PGUIDFMT"\n", PGUID (guid)); } if (do_write && !resend_spdp_sample_by_guid_key (spdp_wr, &ev->u.spdp.pp_guid, prd)) @@ -1065,7 +1065,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e } else { - DDS_TRACE("xmit spdp: suppressing early spdp response from %x:%x:%x:%x to %x:%x:%x:%x\n", + DDS_TRACE("xmit spdp: suppressing early spdp response from "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x\n", PGUID (pp->e.guid), PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_PARTICIPANT); } #endif @@ -1080,7 +1080,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e else { nn_mtime_t tnext = add_duration_to_mtime (tnow, T_SECOND); - DDS_TRACE("xmit spdp %x:%x:%x:%x to %x:%x:%x:%x (resched %gs)\n", + DDS_TRACE("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %gs)\n", PGUID (pp->e.guid), PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER, (double)(tnext.v - tnow.v) / 1e9); @@ -1107,7 +1107,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e intv = config.spdp_interval; tnext = add_duration_to_mtime (tnow, intv); - DDS_TRACE("xmit spdp %x:%x:%x:%x to %x:%x:%x:%x (resched %gs)\n", + DDS_TRACE("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %gs)\n", PGUID (pp->e.guid), PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER, (double)(tnext.v - tnow.v) / 1e9); @@ -1128,7 +1128,7 @@ static void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack if ((wr = get_builtin_writer (pp, NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER)) == NULL) { - DDS_TRACE("write_pmd_message(%x:%x:%x:%x) - builtin pmd writer not found\n", PGUID (pp->e.guid)); + DDS_TRACE("write_pmd_message("PGUIDFMT") - builtin pmd writer not found\n", PGUID (pp->e.guid)); return; } @@ -1178,7 +1178,7 @@ static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_ if (intv == T_NEVER) { tnext.v = T_NEVER; - DDS_TRACE("resched pmd(%x:%x:%x:%x): never\n", PGUID (pp->e.guid)); + DDS_TRACE("resched pmd("PGUIDFMT"): never\n", PGUID (pp->e.guid)); } else { @@ -1188,7 +1188,7 @@ static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_ tnext.v = tnow.v + intv - 2 * T_SECOND; else tnext.v = tnow.v + 4 * intv / 5; - DDS_TRACE("resched pmd(%x:%x:%x:%x): %gs\n", PGUID (pp->e.guid), (double)(tnext.v - tnow.v) / 1e9); + DDS_TRACE("resched pmd("PGUIDFMT"): %gs\n", PGUID (pp->e.guid), (double)(tnext.v - tnow.v) / 1e9); } resched_xevent_if_earlier (ev, tnext); @@ -1213,7 +1213,7 @@ static void handle_xevk_end_startup_mode (UNUSED_ARG (struct nn_xpack *xp), stru 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. */ - DDS_TRACE("handle_xevk_delete_writer: %x:%x:%x:%x\n", PGUID (ev->u.delete_writer.guid)); + DDS_TRACE("handle_xevk_delete_writer: "PGUIDFMT"\n", PGUID (ev->u.delete_writer.guid)); delete_writer_nolinger (&ev->u.delete_writer.guid); delete_xevent (ev); } @@ -1439,7 +1439,7 @@ void qxev_prd_entityid (struct proxy_reader * prd, nn_guid_prefix_t * id) msg = nn_xmsg_new (gv.xmsgpool, id, sizeof (EntityId_t), NN_XMSG_KIND_CONTROL); if (nn_xmsg_setdstPRD (msg, prd) == 0) { - DDS_TRACE(" qxev_prd_entityid (%x:%x:%x)\n", PGUIDPREFIX (*id)); + DDS_TRACE(" qxev_prd_entityid (%"PRIx32":%"PRIx32":%"PRIx32")\n", PGUIDPREFIX (*id)); nn_xmsg_add_entityid (msg); ddsrt_mutex_lock (&gv.xevents->lock); ev = qxev_common_nt (gv.xevents, XEVK_ENTITYID); @@ -1466,7 +1466,7 @@ void qxev_pwr_entityid (struct proxy_writer * pwr, nn_guid_prefix_t * id) msg = nn_xmsg_new (gv.xmsgpool, id, sizeof (EntityId_t), NN_XMSG_KIND_CONTROL); if (nn_xmsg_setdstPWR (msg, pwr) == 0) { - DDS_TRACE(" qxev_pwr_entityid (%x:%x:%x)\n", PGUIDPREFIX (*id)); + DDS_TRACE(" qxev_pwr_entityid (%"PRIx32":%"PRIx32":%"PRIx32")\n", PGUIDPREFIX (*id)); nn_xmsg_add_entityid (msg); ddsrt_mutex_lock (&pwr->evq->lock); ev = qxev_common_nt (pwr->evq, XEVK_ENTITYID); diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 6e3a6ef..3e8e0fa 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -590,7 +590,7 @@ int nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd) } else { - DDS_WARNING("nn_xmsg_setdstPRD: no address for %x:%x:%x:%x", PGUID (prd->e.guid)); + DDS_WARNING("nn_xmsg_setdstPRD: no address for "PGUIDFMT"", PGUID (prd->e.guid)); return Q_ERR_NO_ADDRESS; } } @@ -603,7 +603,7 @@ int nn_xmsg_setdstPWR (struct nn_xmsg *m, const struct proxy_writer *pwr) nn_xmsg_setdst1 (m, &pwr->e.guid.prefix, &loc); return 0; } - DDS_WARNING("nn_xmsg_setdstPRD: no address for %x:%x:%x:%x", PGUID (pwr->e.guid)); + DDS_WARNING("nn_xmsg_setdstPRD: no address for "PGUIDFMT, PGUID (pwr->e.guid)); return Q_ERR_NO_ADDRESS; } @@ -659,7 +659,7 @@ int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct nn_xmsg *m, const stru assert (m->kindspecific.data.readerId_off != 0); assert (madd->kindspecific.data.readerId_off != 0); - DDS_TRACE(" (%x:%x:%x:%x#%"PRId64"/%u:", + DDS_TRACE(" ("PGUIDFMT"#%"PRId64"/%u:", PGUID (m->kindspecific.data.wrguid), m->kindspecific.data.wrseq, m->kindspecific.data.wrfragid + 1); switch (m->dstmode) @@ -1359,7 +1359,7 @@ static void nn_xpack_send_real (struct nn_xpack * xp) if (dds_get_log_mask() & DDS_LC_TRACE) { int i; - DDS_TRACE("nn_xpack_send %u:", xp->msg_len.length); + DDS_TRACE("nn_xpack_send %"PRIu32":", xp->msg_len.length); for (i = 0; i < (int) xp->niov; i++) { DDS_TRACE(" %p:%lu", (void *) xp->iov[i].iov_base, (unsigned long) xp->iov[i].iov_len); @@ -1412,7 +1412,7 @@ static void nn_xpack_send_real (struct nn_xpack * xp) DDS_TRACE(" ]\n"); if (calls) { - DDS_LOG(DDS_LC_TRAFFIC, "traffic-xmit (%lu) %u\n", (unsigned long) calls, xp->msg_len.length); + DDS_LOG(DDS_LC_TRAFFIC, "traffic-xmit (%lu) %"PRIu32"\n", (unsigned long) calls, xp->msg_len.length); } nn_xmsg_chain_release (&xp->included_msgs); nn_xpack_reinit (xp); @@ -1641,7 +1641,7 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag But do make sure we can't run out of iovecs. */ assert (niov + NN_XMSG_MAX_SUBMESSAGE_IOVECS <= NN_XMSG_MAX_MESSAGE_IOVECS); - DDS_TRACE("xpack_addmsg %p %p %u(", (void *) xp, (void *) m, flags); + DDS_TRACE("xpack_addmsg %p %p %"PRIu32"(", (void *) xp, (void *) m, flags); switch (m->kind) { case NN_XMSG_KIND_CONTROL: @@ -1649,7 +1649,7 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag break; case NN_XMSG_KIND_DATA: case NN_XMSG_KIND_DATA_REXMIT: - DDS_TRACE("%s(%x:%x:%x:%x:#%"PRId64"/%u)", + DDS_TRACE("%s("PGUIDFMT":#%"PRId64"/%u)", (m->kind == NN_XMSG_KIND_DATA) ? "data" : "rexmit", PGUID (m->kindspecific.data.wrguid), m->kindspecific.data.wrseq, @@ -1784,7 +1784,7 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag if (xpo_niov > 0 && sz > config.max_msg_size) { - DDS_TRACE(" => now niov %d sz %"PRIuSIZE" > max_msg_size %u, nn_xpack_send niov %d sz %u now\n", (int) niov, sz, config.max_msg_size, (int) xpo_niov, xpo_sz); + DDS_TRACE(" => now niov %d sz %"PRIuSIZE" > max_msg_size %"PRIu32", nn_xpack_send niov %d sz %"PRIu32" now\n", (int) niov, sz, config.max_msg_size, (int) xpo_niov, xpo_sz); xp->msg_len.length = xpo_sz; xp->niov = xpo_niov; nn_xpack_send (xp, false); diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index 7052233..ca6dc3d 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -624,7 +624,7 @@ static int check_eseq (struct eseq_admin *ea, uint32_t seq, uint32_t keyval, uin uint32_t *eseq; if (keyval >= ea->nkeys) { - printf ("received key %u >= nkeys %u\n", keyval, ea->nkeys); + printf ("received key %"PRIu32" >= nkeys %u\n", keyval, ea->nkeys); exit (3); } ddsrt_mutex_lock (&ea->lock); @@ -1315,7 +1315,7 @@ static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) prefix, x->pubhandle, (double) x->min / 1e3, (double) x->sum / (double) x->cnt / 1e3, (double) x->max / 1e3, x->cnt); else - printf ("%s %s:%d min %.3fus mean %.3fus max %.3fus cnt %"PRIu32"\n", + printf ("%s %s:%"PRIu32" min %.3fus mean %.3fus max %.3fus cnt %"PRIu32"\n", prefix, pp->hostname, pp->pid, (double) x->min / 1e3, (double) x->sum / (double) x->cnt / 1e3, (double) x->max / 1e3, x->cnt); ddsrt_mutex_unlock (&disc_lock); From fc5a349a722fdd86698a4ded0f7f44556ca5856b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 2 May 2019 11:14:07 +0800 Subject: [PATCH 053/178] out-of-bounds write nn_bitset_one w multiple of 32 nn_bitset_one sets the specified number of bits by first memset'ing the words, then clearing bits set in a final partial word. It mishandled the case where the number of bits is a multiple of 32, clearing the entire word following the last one it was to touch. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_bitset.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/ddsi/include/dds/ddsi/q_bitset.h b/src/core/ddsi/include/dds/ddsi/q_bitset.h index 630d16a..a359f82 100644 --- a/src/core/ddsi/include/dds/ddsi/q_bitset.h +++ b/src/core/ddsi/include/dds/ddsi/q_bitset.h @@ -49,6 +49,7 @@ inline void nn_bitset_one (uint32_t numbits, uint32_t *bits) memset (bits, 0xff, 4 * ((numbits + 31) / 32)); /* clear bits "accidentally" set */ + if ((numbits % 32) != 0) { const uint32_t k = numbits / 32; const uint32_t n = numbits % 32; From 6011422566f752b4e3d1ebbb5564d60bd22dcb8b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 2 May 2019 11:19:41 +0800 Subject: [PATCH 054/178] ddsperf: fix calculation of data rate in Mb/s Multiplying time-in-ns since previous output line by 1e9 instead of dividing it by 1e9 resulted in bit rate showing up as 0Mb/s. Signed-off-by: Erik Boasson --- src/tools/ddsperf/ddsperf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index ca6dc3d..8dd8656 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -1298,7 +1298,7 @@ static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) if (nrecv > 0) { printf ("%s ntot %"PRIu64" delta: %"PRIu64" lost %"PRIu64" rate %.2f Mb/s\n", - prefix, tot_nrecv, nrecv, nlost, (double) nrecv_bytes * 8 / 1e6 / (1e9 * (double) (tnow - tprev))); + prefix, tot_nrecv, nrecv, nlost, (double) nrecv_bytes * 8 * 1e3 / (double) (tnow - tprev)); } } From d693d8eac9b1c058f35fc053525ebda0050714c9 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 2 May 2019 11:23:35 +0800 Subject: [PATCH 055/178] limit WHC, serdata, xmsg freelist memory use (#168) High sample rates require rather high rates of allocating and freeing WHC nodes, serialised samples (serdata), and RTPS message fragments (xmsg). A bunch of dedicated parallel allocators help take some pressure off the regular malloc/free calls. However, these used to gobble up memory like crazy, in part because of rather generous limits, and in part because there was no restriction on the size of the samples that would be cached, and it could end up caching large numbers of multi-MB samples. It should be noted that there is no benefit to caching large samples anyway, because the sample rate will be that much lower. This commit reduces the maximum number of entries for all three cases, it furthermore limits the maximum size of a serdata or xmsg that can be cached, and finally instead of instantiating a separate allocator for WHC nodes per WHC, it now shares one across all WHCs. Total memory use should now be limited to a couple of MB. The caching can be disabled by setting ``FREELIST_TYPE`` to ``FREELIST_NONE`` in ``q_freelist.h``. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_whc.c | 38 +++++++++++++++------ src/core/ddsi/include/dds/ddsi/q_freelist.h | 10 ++++-- src/core/ddsi/src/ddsi_serdata_default.c | 9 +++-- src/core/ddsi/src/q_freelist.c | 32 ++++++++++++++++- src/core/ddsi/src/q_transmit.c | 10 ++++-- src/core/ddsi/src/q_xmsg.c | 10 ++++-- 6 files changed, 89 insertions(+), 20 deletions(-) diff --git a/src/core/ddsc/src/dds_whc.c b/src/core/ddsc/src/dds_whc.c index b63ca62..2992990 100644 --- a/src/core/ddsc/src/dds_whc.c +++ b/src/core/ddsc/src/dds_whc.c @@ -88,7 +88,6 @@ struct whc_impl { 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 */ - struct nn_freelist freelist; /* struct whc_node *; linked via whc_node::next_seq */ #if USE_EHH struct ddsrt_ehh *seq_hash; #else @@ -124,7 +123,7 @@ static struct whc_node *whc_findseq (const struct whc_impl *whc, seqno_t seq); static void insert_whcn_in_hash (struct whc_impl *whc, struct whc_node *whcn); static void whc_delete_one (struct whc_impl *whc, struct whc_node *whcn); static int compare_seq (const void *va, const void *vb); -static void free_deferred_free_list (struct whc_impl *whc, struct whc_node *deferred_free_list); +static void free_deferred_free_list (struct whc_node *deferred_free_list); static void get_state_locked(const struct whc_impl *whc, struct whc_state *st); static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list); @@ -159,6 +158,17 @@ static const struct whc_ops whc_ops = { .free = whc_default_free }; +/* Number of instantiated WHCs and a global freelist for WHC nodes that gets + initialized lazily and cleaned up automatically when the last WHC is freed. + Protected by dds_global.m_mutex. + + sizeof (whc_node) on 64-bit machines ~ 100 bytes, so this is ~1MB + 8k entries seems to be roughly the amount needed for minimum samples, + maximum message size and a short round-trip time */ +#define MAX_FREELIST_SIZE 8192 +static uint32_t whc_count; +static struct nn_freelist whc_node_freelist; + #if USE_EHH static uint32_t whc_seq_entry_hash (const void *vn) { @@ -379,8 +389,10 @@ struct whc *whc_new (int is_transient_local, unsigned hdepth, unsigned tldepth) whc->open_intv = intv; whc->maxseq_node = NULL; - /* hack */ - nn_freelist_init (&whc->freelist, UINT32_MAX, offsetof (struct whc_node, next_seq)); + ddsrt_mutex_lock (&dds_global.m_mutex); + if (whc_count++ == 0) + nn_freelist_init (&whc_node_freelist, MAX_FREELIST_SIZE, offsetof (struct whc_node, next_seq)); + ddsrt_mutex_unlock (&dds_global.m_mutex); check_whc (whc); return (struct whc *)whc; @@ -425,7 +437,11 @@ DDSRT_WARNING_MSVC_ON(6001); } ddsrt_avl_free (&whc_seq_treedef, &whc->seq, ddsrt_free); - nn_freelist_fini (&whc->freelist, ddsrt_free); + + ddsrt_mutex_lock (&dds_global.m_mutex); + if (--whc_count == 0) + nn_freelist_fini (&whc_node_freelist, ddsrt_free); + ddsrt_mutex_unlock (&dds_global.m_mutex); #if USE_EHH ddsrt_ehh_free (whc->seq_hash); @@ -753,11 +769,11 @@ static void whc_delete_one (struct whc_impl *whc, struct whc_node *whcn) if (whcn_tmp->next_seq) whcn_tmp->next_seq->prev_seq = whcn_tmp->prev_seq; whcn_tmp->next_seq = NULL; - free_deferred_free_list (whc, whcn_tmp); + free_deferred_free_list (whcn_tmp); whc->seq_size--; } -static void free_deferred_free_list (struct whc_impl *whc, struct whc_node *deferred_free_list) +static void free_deferred_free_list (struct whc_node *deferred_free_list) { if (deferred_free_list) { @@ -769,7 +785,7 @@ static void free_deferred_free_list (struct whc_impl *whc, struct whc_node *defe if (!cur->borrowed) free_whc_node_contents (cur); } - cur = nn_freelist_pushmany (&whc->freelist, deferred_free_list, last, n); + cur = nn_freelist_pushmany (&whc_node_freelist, deferred_free_list, last, n); while (cur) { struct whc_node *tmp = cur; @@ -781,8 +797,8 @@ static void free_deferred_free_list (struct whc_impl *whc, struct whc_node *defe static void whc_default_free_deferred_free_list (struct whc *whc_generic, struct whc_node *deferred_free_list) { - struct whc_impl * const whc = (struct whc_impl *)whc_generic; - free_deferred_free_list(whc, deferred_free_list); + (void) whc_generic; + free_deferred_free_list (deferred_free_list); } static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list) @@ -1028,7 +1044,7 @@ static struct whc_node *whc_default_insert_seq (struct whc_impl *whc, seqno_t ma { struct whc_node *newn = NULL; - if ((newn = nn_freelist_pop (&whc->freelist)) == NULL) + if ((newn = nn_freelist_pop (&whc_node_freelist)) == NULL) newn = ddsrt_malloc (sizeof (*newn)); newn->seq = seq; newn->plist = plist; diff --git a/src/core/ddsi/include/dds/ddsi/q_freelist.h b/src/core/ddsi/include/dds/ddsi/q_freelist.h index 8fcafa7..75b4fc0 100644 --- a/src/core/ddsi/include/dds/ddsi/q_freelist.h +++ b/src/core/ddsi/include/dds/ddsi/q_freelist.h @@ -19,7 +19,7 @@ extern "C" { #endif -#define FREELIST_SIMPLE 1 +#define FREELIST_NONE 1 #define FREELIST_ATOMIC_LIFO 2 #define FREELIST_DOUBLE 3 @@ -33,7 +33,13 @@ extern "C" { #endif #endif -#if FREELIST_TYPE == FREELIST_ATOMIC_LIFO +#if FREELIST_TYPE == FREELIST_NONE + +struct nn_freelist { + char dummy; +}; + +#elif FREELIST_TYPE == FREELIST_ATOMIC_LIFO struct nn_freelist { ddsrt_atomic_lifo_t x; diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 03e340e..167cc8b 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -27,7 +27,12 @@ #include "dds/ddsi/q_globals.h" #include "dds/ddsi/ddsi_serdata_default.h" -#define MAX_POOL_SIZE 16384 +/* 8k entries in the freelist seems to be roughly the amount needed to send + minimum-size (well, 4 bytes) samples as fast as possible over loopback + while using large messages -- actually, it stands to reason that this would + be the same as the WHC node pool size */ +#define MAX_POOL_SIZE 8192 +#define MAX_SIZE_FOR_POOL 256 #define CLEAR_PADDING 0 #ifndef NDEBUG @@ -205,7 +210,7 @@ static void serdata_default_free(struct ddsi_serdata *dcmn) { struct ddsi_serdata_default *d = (struct ddsi_serdata_default *)dcmn; assert(ddsrt_atomic_ld32(&d->c.refc) == 0); - if (!nn_freelist_push (&gv.serpool->freelist, d)) + if (d->size > MAX_SIZE_FOR_POOL || !nn_freelist_push (&gv.serpool->freelist, d)) dds_free (d); } diff --git a/src/core/ddsi/src/q_freelist.c b/src/core/ddsi/src/q_freelist.c index 78e2a77..fd7aef7 100644 --- a/src/core/ddsi/src/q_freelist.c +++ b/src/core/ddsi/src/q_freelist.c @@ -18,7 +18,37 @@ #include "dds/ddsrt/threads.h" #include "dds/ddsi/q_freelist.h" -#if FREELIST_TYPE == FREELIST_ATOMIC_LIFO +#if FREELIST_TYPE == FREELIST_NONE + +void nn_freelist_init (struct nn_freelist *fl, uint32_t max, off_t linkoff) +{ + (void) fl; (void) max; (void) linkoff; +} + +void nn_freelist_fini (struct nn_freelist *fl, void (*free) (void *elem)) +{ + (void) fl; (void) free; +} + +bool nn_freelist_push (struct nn_freelist *fl, void *elem) +{ + (void) fl; (void) elem; + return false; +} + +void *nn_freelist_pushmany (struct nn_freelist *fl, void *first, void *last, uint32_t n) +{ + (void) fl; (void) first; (void) last; (void) n; + return first; +} + +void *nn_freelist_pop (struct nn_freelist *fl) +{ + (void) fl; + return NULL; +} + +#elif FREELIST_TYPE == FREELIST_ATOMIC_LIFO void nn_freelist_init (struct nn_freelist *fl, uint32_t max, off_t linkoff) { diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 7401d3b..3a208ba 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -400,7 +400,9 @@ void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_sta static int create_fragment_message_simple (struct writer *wr, seqno_t seq, struct ddsi_serdata *serdata, struct nn_xmsg **pmsg) { #define TEST_KEYHASH 0 - const size_t expected_inline_qos_size = 4+8+20+4 + 32; + /* 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 nn_xmsg_marker sm_marker; unsigned char contentflag = 0; Data_t *data; @@ -423,6 +425,7 @@ static int create_fragment_message_simple (struct writer *wr, seqno_t seq, struc ASSERT_MUTEX_HELD (&wr->e.lock); + /* INFO_TS: 12 bytes, Data_t: 24 bytes, expected inline QoS: 32 => should be single chunk */ if ((*pmsg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (Data_t) + expected_inline_qos_size, NN_XMSG_KIND_DATA)) == NULL) return Q_ERR_OUT_OF_MEMORY; @@ -484,7 +487,9 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli Expected inline QoS size: header(4) + statusinfo(8) + keyhash(20) + sentinel(4). Plus some spare cos I can't be bothered. */ const int set_smhdr_flags_asif_data = config.buggy_datafrag_flags_mode; - const size_t expected_inline_qos_size = 4+8+20+4 + 32; + /* 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 nn_xmsg_marker sm_marker; void *sm; Data_DataFrag_common_t *ddcmn; @@ -508,6 +513,7 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli fragging = (config.fragment_size < size); + /* INFO_TS: 12 bytes, DataFrag_t: 36 bytes, expected inline QoS: 32 => should be single chunk */ if ((*pmsg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (DataFrag_t) + expected_inline_qos_size, xmsg_kind)) == NULL) return Q_ERR_OUT_OF_MEMORY; diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 3e8e0fa..3c0eae0 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -241,13 +241,18 @@ static size_t align4u (size_t x) Great expectations, but so far still wanting. */ +/* We need about as many as will fit in a message; an otherwise unadorned data message is ~ 40 bytes + for a really small sample, no key hash, no status info, and message sizes are (typically) < 64kB + so we can expect not to need more than ~ 1600 xmsg at a time. Powers-of-two are nicer :) */ +#define MAX_FREELIST_SIZE 2048 + static void nn_xmsg_realfree (struct nn_xmsg *m); struct nn_xmsgpool *nn_xmsgpool_new (void) { struct nn_xmsgpool *pool; pool = ddsrt_malloc (sizeof (*pool)); - nn_freelist_init (&pool->freelist, UINT32_MAX, offsetof (struct nn_xmsg, link.older)); + nn_freelist_init (&pool->freelist, MAX_FREELIST_SIZE, offsetof (struct nn_xmsg, link.older)); return pool; } @@ -352,7 +357,8 @@ void nn_xmsg_free (struct nn_xmsg *m) unref_addrset (m->dstaddr.all.as); unref_addrset (m->dstaddr.all.as_group); } - if (!nn_freelist_push (&pool->freelist, m)) + /* Only cache the smallest xmsgs; data messages store the payload by reference and are small */ + if (m->maxsz > NN_XMSG_CHUNK_SIZE || !nn_freelist_push (&pool->freelist, m)) { nn_xmsg_realfree (m); } From d700657cb721c6f3b707c3308c522e760b9a120c Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 2 May 2019 15:22:28 +0800 Subject: [PATCH 056/178] ddsperf latnecy should include median, 90% and 99% Signed-off-by: Erik Boasson --- src/tools/ddsperf/ddsperf.c | 67 ++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index 8dd8656..f93cc61 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -39,6 +39,8 @@ #define UDATA_MAGIC "DDSPerf:" #define UDATA_MAGIC_SIZE (sizeof (UDATA_MAGIC) - 1) +#define PINGPONG_RAWSIZE 20000 + enum topicsel { KS, /* KeyedSeq type: seq#, key, sequence-of-octet */ K32, /* Keyed32 type: seq#, key, array-of-24-octet (sizeof = 32) */ @@ -158,6 +160,7 @@ struct eseq_stat { uint64_t nrecv; uint64_t nlost; uint64_t nrecv_bytes; + uint32_t last_size; /* stats printer state */ uint64_t nrecv_ref; @@ -190,6 +193,7 @@ struct subthread_arg_pongstat { uint64_t min, max; uint64_t sum; uint32_t cnt; + uint64_t *raw; }; /* Pong statistics is stored in n array of npongstat entries @@ -636,6 +640,7 @@ static int check_eseq (struct eseq_admin *ea, uint32_t seq, uint32_t keyval, uin ea->stats[i].nrecv++; ea->stats[i].nrecv_bytes += size; ea->stats[i].nlost += seq - e; + ea->stats[i].last_size = size; ddsrt_mutex_unlock (&ea->lock); return seq == e; } @@ -650,6 +655,7 @@ static int check_eseq (struct eseq_admin *ea, uint32_t seq, uint32_t keyval, uin memset (&ea->stats[ea->nph], 0, sizeof (ea->stats[ea->nph])); ea->stats[ea->nph].nrecv = 1; ea->stats[ea->nph].nrecv_bytes = size; + ea->stats[ea->nph].last_size = size; ea->nph++; ddsrt_mutex_unlock (&ea->lock); return 1; @@ -694,6 +700,8 @@ static bool update_roundtrip (dds_instance_handle_t pubhandle, uint64_t tdelta, if (tdelta < x->min) x->min = tdelta; if (tdelta > x->max) x->max = tdelta; x->sum += tdelta; + if (x->cnt < PINGPONG_RAWSIZE) + x->raw[x->cnt] = tdelta; x->cnt++; ddsrt_mutex_unlock (&pongstat_lock); return allseen; @@ -704,6 +712,8 @@ static bool update_roundtrip (dds_instance_handle_t pubhandle, uint64_t tdelta, x->pphandle = get_pphandle_for_pubhandle (pubhandle); x->min = x->max = x->sum = tdelta; x->cnt = 1; + x->raw = malloc (PINGPONG_RAWSIZE * sizeof (*x->raw)); + x->raw[0] = tdelta; npongstat++; ddsrt_mutex_unlock (&pongstat_lock); return allseen; @@ -1264,6 +1274,13 @@ static void set_data_available_listener (dds_entity_t rd, const char *rd_name, d dds_delete_listener (listener); } +static int cmp_uint64 (const void *va, const void *vb) +{ + const uint64_t *a = va; + const uint64_t *b = vb; + return (*a == *b) ? 0 : (*a < *b) ? -1 : 1; +} + static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) { char prefix[128]; @@ -1281,6 +1298,7 @@ static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) { struct eseq_admin * const ea = &eseq_admin; uint64_t tot_nrecv = 0, nrecv = 0, nrecv_bytes = 0, nlost = 0; + uint32_t last_size = 0; ddsrt_mutex_lock (&ea->lock); for (uint32_t i = 0; i < ea->nph; i++) { @@ -1289,6 +1307,7 @@ static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) nrecv += x->nrecv - x->nrecv_ref; nlost += x->nlost - x->nlost_ref; nrecv_bytes += x->nrecv_bytes - x->nrecv_bytes_ref; + last_size = x->last_size; x->nrecv_ref = x->nrecv; x->nlost_ref = x->nlost; x->nrecv_bytes_ref = x->nrecv_bytes; @@ -1297,33 +1316,53 @@ static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) if (nrecv > 0) { - printf ("%s ntot %"PRIu64" delta: %"PRIu64" lost %"PRIu64" rate %.2f Mb/s\n", - prefix, tot_nrecv, nrecv, nlost, (double) nrecv_bytes * 8 * 1e3 / (double) (tnow - tprev)); + printf ("%s size %"PRIu32" ntot %"PRIu64" delta: %"PRIu64" lost %"PRIu64" rate %.2f Mb/s\n", + prefix, last_size, tot_nrecv, nrecv, nlost, (double) nrecv_bytes * 8 * 1e3 / (double) (tnow - tprev)); } } + uint64_t *newraw = malloc (PINGPONG_RAWSIZE * sizeof (*newraw)); ddsrt_mutex_lock (&pongstat_lock); for (uint32_t i = 0; i < npongstat; i++) { struct subthread_arg_pongstat * const x = &pongstat[i]; - if (x->cnt > 0) + struct subthread_arg_pongstat y = *x; + x->raw = newraw; + x->min = UINT64_MAX; + x->max = x->sum = x->cnt = 0; + /* pongstat entries get added at the end, npongstat only grows: so can safely + unlock the stats in between nodes for calculating percentiles */ + ddsrt_mutex_unlock (&pongstat_lock); + + if (y.cnt > 0) { + const uint32_t rawcnt = (y.cnt > PINGPONG_RAWSIZE) ? PINGPONG_RAWSIZE : y.cnt; + char ppinfo[128]; struct ppant *pp; ddsrt_mutex_lock (&disc_lock); - if ((pp = ddsrt_avl_lookup (&ppants_td, &ppants, &x->pphandle)) == NULL) - printf ("%s %"PRIx64" min %.3fus mean %.3fus max %.3fus cnt %"PRIu32"\n", - prefix, x->pubhandle, (double) x->min / 1e3, - (double) x->sum / (double) x->cnt / 1e3, (double) x->max / 1e3, x->cnt); + if ((pp = ddsrt_avl_lookup (&ppants_td, &ppants, &y.pphandle)) == NULL) + snprintf (ppinfo, sizeof (ppinfo), "%"PRIx64, y.pubhandle); else - printf ("%s %s:%"PRIu32" min %.3fus mean %.3fus max %.3fus cnt %"PRIu32"\n", - prefix, pp->hostname, pp->pid, (double) x->min / 1e3, - (double) x->sum / (double) x->cnt / 1e3, (double) x->max / 1e3, x->cnt); + snprintf (ppinfo, sizeof (ppinfo), "%s:%"PRIu32, pp->hostname, pp->pid); ddsrt_mutex_unlock (&disc_lock); - x->min = UINT64_MAX; - x->max = x->sum = x->cnt = 0; + + qsort (y.raw, rawcnt, sizeof (*y.raw), cmp_uint64); + printf ("%s %s mean %.3fus min %.3fus 50%% %.3fus 90%% %.3fus 99%% %.3fus max %.3fus cnt %"PRIu32"\n", + prefix, ppinfo, + (double) y.sum / (double) y.cnt / 1e3, + (double) y.min / 1e3, + (double) y.raw[rawcnt - (rawcnt + 1) / 2] / 1e3, + (double) y.raw[rawcnt - (rawcnt + 9) / 10] / 1e3, + (double) y.raw[rawcnt - (rawcnt + 99) / 100] / 1e3, + (double) y.max / 1e3, + y.cnt); } + newraw = y.raw; + + ddsrt_mutex_lock (&pongstat_lock); } ddsrt_mutex_unlock (&pongstat_lock); + free (newraw); fflush (stdout); } @@ -1644,6 +1683,10 @@ int main (int argc, char *argv[]) error3 ("-n%u invalid: topic OU has no key\n", nkeyvals); if (topicsel != KS && baggagesize != 0) error3 ("-z%u invalid: only topic KS has a sequence\n", baggagesize); + if (baggagesize != 0 && baggagesize < 12) + error3 ("-z%u invalid: too small to allow for overhead\n", baggagesize); + else if (baggagesize > 0) + baggagesize -= 12; ddsrt_avl_init (&ppants_td, &ppants); ddsrt_fibheap_init (&ppants_to_match_fhd, &ppants_to_match); From a7c7ac54c3e44001c9a590fb5062f85cb3aba4bc Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 2 May 2019 16:26:28 +0800 Subject: [PATCH 057/178] make ddsperf polling/waitset mode selectable again Signed-off-by: Erik Boasson --- src/tools/ddsperf/ddsperf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index f93cc61..cef4870 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -1493,7 +1493,7 @@ static int string_int_map_lookup (const struct string_int_map_elem *elems, const for (size_t i = 0; elems[i].name; i++) { if (strcmp (elems[i].name, str) == 0) - return elems[match].value; + return elems[i].value; else if (len >= 3 && strlen (elems[i].name) >= 3 && strncmp (elems[i].name, str, len) == 0) { if (match == SIZE_MAX) From b5251d03908cffb864e807ac5bc65502c7b61995 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 4 May 2019 13:20:30 +0800 Subject: [PATCH 058/178] remove legacy configuration settings These settings all constitute settings from the long history of the DDSI stack predating Eclipse Cyclone DDS and can reasonably be presumed never to have been used in Cyclone. Their removal is therefore not expected to break backwards compatibility (which would be anyway be limited to Cyclone complaining about undefined settings at startup): * Tracing/Timestamps[@absolute]: has always been ignored * Tracing/Timestamps: has always been ignored * General/EnableLoopback: ignored for quite some time, before that changing it from the default resulted in crashes. * General/StartupModeDuration: it did what it advertised (retain data in the history caches of volatile writers as-if they were transient-local with a durability history setting of keep-last 1 for the first few seconds after startup of the DDSI stack) but had no purpose other than complicating things as the volatile readers ignored the data anyway. * General/StartupModeCoversTransient: see previous -- and besides, transient data is not supported yet in Cyclone. * Compatibility/RespondToRtiInitZeroAckWithInvalidHeartbeat: arguably a good setting given that DDSI < 2.3 explicitly requires that all HEARTBEAT messages sent by a writer advertise the existence of at least 1 sample, but this has been fixed in DDSI 2.3. As this requirement was never respected by most DDSI implementations, there is no point in retaining the setting, while it does remove a rather tricky problem immediately after writer startup involving the conjuring up of a sample that was annihilated immediately before it could have been observed. That conjuring up (as it turns out) can cause a malformed message to go out (one that is harmless in itself). Fixing the generation of that malformed message while the entire point of the trick is moot in DDSI 2.3 is a bit silly. Note that full DDSI 2.3 compliance needs a bit more work, so not bumping the DDSI protocol version number yet. * Compatibility/AckNackNumbitsEmptySet: changing it from 0 breaks compatibility with (at least) RTI Connext, and its reason for existence disappers with a fix in DDSI 2.3. * Internal/AggressiveKeepLastWhc: changing the setting from the default made no sense whatsoever in Cyclone -- it would only add flow-control and potentially block a keep-last writer where the spec forbids that. * Internal/LegacyFragmentation: a left-over from almost a decade ago when it was discovered that the specification was inconsistent in the use of the message header flags for fragmented data, and this stack for a while used the non-common interpretation. There is no reasonable way of making the two modes compatible, and this setting merely existed to deal with the compatibility issue with some ancient OpenSplice DDS version. * Durability/Encoding: historical junk. * WatchDog and Lease: never had any function in Cyclone. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_writer.c | 29 +- src/core/ddsi/include/dds/ddsi/q_config.h | 24 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 3 - src/core/ddsi/include/dds/ddsi/q_globals.h | 7 - src/core/ddsi/include/dds/ddsi/q_misc.h | 2 +- src/core/ddsi/include/dds/ddsi/q_xevent.h | 1 - src/core/ddsi/src/q_config.c | 3656 ++++++++++---------- src/core/ddsi/src/q_ddsi_discovery.c | 2 +- src/core/ddsi/src/q_entity.c | 48 +- src/core/ddsi/src/q_init.c | 13 - src/core/ddsi/src/q_receive.c | 55 +- src/core/ddsi/src/q_transmit.c | 28 +- src/core/ddsi/src/q_xevent.c | 43 - 13 files changed, 1771 insertions(+), 2140 deletions(-) diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index b36bfc9..f144e35 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -313,38 +313,13 @@ dds_writer_qos_set( static struct whc *make_whc(const dds_qos_t *qos) { - bool startup_mode; bool handle_as_transient_local; unsigned hdepth, tldepth; - /* Startup mode causes the writer to treat data in its WHC as if - transient-local, for the first few seconds after startup of the - DDSI service. It is done for volatile reliable writers only - (which automatically excludes all builtin writers) or for all - writers except volatile best-effort & transient-local ones. - - Which one to use depends on whether merge policies are in effect - in durability. If yes, then durability will take care of all - transient & persistent data; if no, DDSI discovery usually takes - too long and this'll save you. - - Note: may still be cleared, if it turns out we are not maintaining - an index at all (e.g., volatile KEEP_ALL) */ - if (config.startup_mode_full) { - startup_mode = gv.startup_mode && - (qos->durability.kind >= NN_TRANSIENT_DURABILITY_QOS || - (qos->durability.kind == NN_VOLATILE_DURABILITY_QOS && - qos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS)); - } else { - startup_mode = gv.startup_mode && - (qos->durability.kind == NN_VOLATILE_DURABILITY_QOS && - qos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS); - } - /* 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 == NN_TRANSIENT_LOCAL_DURABILITY_QOS); - if (!config.aggressive_keep_last_whc || qos->history.kind == NN_KEEP_ALL_HISTORY_QOS) + if (qos->history.kind == NN_KEEP_ALL_HISTORY_QOS) hdepth = 0; else hdepth = (unsigned)qos->history.depth; @@ -353,8 +328,6 @@ static struct whc *make_whc(const dds_qos_t *qos) tldepth = 0; else tldepth = (unsigned)qos->durability_service.history.depth; - } else if (startup_mode) { - tldepth = (hdepth == 0) ? 1 : hdepth; } else { tldepth = 0; } diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index c313682..50ceb51 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -237,7 +237,6 @@ struct config FILE *tracingOutputFile; char *tracingOutputFileName; int tracingTimestamps; - int tracingRelativeTimestamps; int tracingAppendToFile; unsigned allowMulticast; enum transport_selector transport_selector; @@ -254,7 +253,6 @@ struct config char *assumeMulticastCapable; int64_t spdp_interval; int64_t spdp_response_delay_max; - int64_t startup_mode_duration; int64_t lease_duration; int64_t const_hb_intv_sched; int64_t const_hb_intv_sched_min; @@ -263,8 +261,6 @@ struct config enum retransmit_merging retransmit_merging; int64_t retransmit_merging_period; int squash_participants; - int startup_mode_full; - int forward_all_messages; int liveliness_monitoring; int noprogress_log_stacktraces; int64_t liveliness_monitoring_interval; @@ -278,10 +274,6 @@ struct config unsigned delivery_queue_maxsamples; - int enableLoopback; - enum durability_cdr durability_cdr; - - int buggy_datafrag_flags_mode; int do_topic_discovery; uint32_t max_msg_size; @@ -298,9 +290,7 @@ struct config int tcp_use_peeraddr_for_unicast; #ifdef DDSI_INCLUDE_SSL - /* SSL support for TCP */ - int ssl_enable; int ssl_verify; int ssl_verify_client; @@ -310,17 +300,13 @@ struct config char * ssl_key_pass; char * ssl_ciphers; struct ssl_min_version ssl_min_version; - #endif /* Thread pool configuration */ - int tp_enable; uint32_t tp_threads; uint32_t tp_max_threads; - int advertise_builtin_topic_writers; - #ifdef DDSI_INCLUDE_NETWORK_CHANNELS struct config_channel_listelem *channels; struct config_channel_listelem *max_channel; /* channel with highest prio; always computed */ @@ -343,7 +329,6 @@ struct config uint32_t rmsg_chunk_size; /**<< size of a chunk in the receive buffer */ uint32_t rbuf_size; /* << size of a single receiver buffer */ enum besmode besmode; - int aggressive_keep_last_whc; int conservative_builtin_reader_startup; int meas_hb_to_ack_latency; int suppress_spdp_multicast; @@ -389,8 +374,6 @@ struct config int explicitly_publish_qos_set_to_default; enum many_sockets_mode many_sockets_mode; int arrival_of_data_asserts_pp_and_ep_liveliness; - int acknack_numbits_emptyset; - int respond_to_rti_init_zero_ack_with_invalid_heartbeat; int assume_rti_has_pmd_endpoints; int port_dg; @@ -406,14 +389,9 @@ struct config int initial_deaf; int initial_mute; int64_t initial_deaf_mute_reset; + int use_multicast_if_mreqn; struct prune_deleted_ppant prune_deleted_ppant; - - /* not used by ddsi2, only validated; user layer directly accesses - the configuration tree */ - ddsrt_sched_t watchdog_sched_class; - int32_t watchdog_sched_priority; - q__schedPrioClass watchdog_sched_priority_class; }; struct ddsi_plugin diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index f606786..4c0c4bd 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -233,8 +233,6 @@ struct writer enum writer_state state; unsigned reliable: 1; /* iff 1, writer is reliable <=> heartbeat_xevent != NULL */ unsigned handle_as_transient_local: 1; /* controls whether data is retained in WHC */ - unsigned aggressive_keep_last: 1; /* controls whether KEEP_LAST will overwrite samples that haven't been ACK'd yet */ - unsigned startup_mode: 1; /* causes data to be treated as T-L for a while */ 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 */ #ifdef DDSI_INCLUDE_SSM @@ -570,7 +568,6 @@ void update_proxy_writer (struct proxy_writer * pwr, struct addrset *as); int new_proxy_group (const struct nn_guid *guid, const char *name, const struct nn_xqos *xqos, nn_wctime_t timestamp); void delete_proxy_group (const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit); -void writer_exit_startup_mode (struct writer *wr); uint64_t writer_instance_id (const struct nn_guid *guid); /* Call this to empty all address sets of all writers to stop all outgoing traffic, or to diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/q_globals.h index 517b699..857bd4c 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/q_globals.h @@ -223,13 +223,6 @@ struct q_globals { /* Flag cleared when stopping (receive threads). FIXME. */ int rtps_keepgoing; - /* Startup mode causes data to be treated as transient-local with - depth 1 (i.e., stored in the WHCs and regurgitated on request) to - cover the start-up delay of the discovery protocols. Because all - discovery data is shared, this is strictly a start-up issue of the - service. */ - int startup_mode; - /* Start time of the DDSI2 service, for logging relative time stamps, should I ever so desire. */ nn_wctime_t tstart; diff --git a/src/core/ddsi/include/dds/ddsi/q_misc.h b/src/core/ddsi/include/dds/ddsi/q_misc.h index dcc4224..f410ebb 100644 --- a/src/core/ddsi/include/dds/ddsi/q_misc.h +++ b/src/core/ddsi/include/dds/ddsi/q_misc.h @@ -29,7 +29,7 @@ inline nn_sequence_number_t toSN (seqno_t n) { return x; } -unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr, int datafrag_as_data); +unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr); #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS int WildcardOverlap(char * p1, char * p2); diff --git a/src/core/ddsi/include/dds/ddsi/q_xevent.h b/src/core/ddsi/include/dds/ddsi/q_xevent.h index 3ab7242..ef356f4 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xevent.h +++ b/src/core/ddsi/include/dds/ddsi/q_xevent.h @@ -61,7 +61,6 @@ DDS_EXPORT struct xevent *qxev_heartbeat (struct xeventq *evq, nn_mtime_t tsched DDS_EXPORT struct xevent *qxev_acknack (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *pwr_guid, const nn_guid_t *rd_guid); DDS_EXPORT struct xevent *qxev_spdp (nn_mtime_t tsched, const nn_guid_t *pp_guid, const nn_guid_t *proxypp_guid); DDS_EXPORT struct xevent *qxev_pmd_update (nn_mtime_t tsched, const nn_guid_t *pp_guid); -DDS_EXPORT struct xevent *qxev_end_startup_mode (nn_mtime_t tsched); DDS_EXPORT struct xevent *qxev_delete_writer (nn_mtime_t tsched, const nn_guid_t *guid); /* cb will be called with now = T_NEVER if the event is still enqueued when when xeventq_free starts cleaning up */ diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index f3ea0a7..6c22b64 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -53,57 +53,57 @@ struct q_security_plugins q_security_plugin = { NULL, NULL, NULL, NULL, NULL, NU #endif struct unit { - const char *name; - int64_t multiplier; + const char *name; + int64_t multiplier; }; struct cfgelem { - const char *name; - const struct cfgelem *children; - const struct cfgelem *attributes; - int multiplicity; - const char *defvalue; /* NULL -> no default */ - int relative_offset; - int elem_offset; - init_fun_t init; - update_fun_t update; - free_fun_t free; - print_fun_t print; - const char *description; + const char *name; + const struct cfgelem *children; + const struct cfgelem *attributes; + int multiplicity; + const char *defvalue; /* NULL -> no default */ + int relative_offset; + int elem_offset; + init_fun_t init; + update_fun_t update; + free_fun_t free; + print_fun_t print; + const char *description; }; struct cfgst_nodekey { - const struct cfgelem *e; + const struct cfgelem *e; }; struct cfgst_node { - ddsrt_avl_node_t avlnode; - struct cfgst_nodekey key; - int count; - int failed; - int is_default; + ddsrt_avl_node_t avlnode; + struct cfgst_nodekey key; + int count; + int failed; + int is_default; }; struct cfgst { - ddsrt_avl_tree_t found; - struct config *cfg; - /* error flag set so that we can continue parsing for some errors and still fail properly */ - int error; + ddsrt_avl_tree_t found; + struct config *cfg; + /* error flag set so that we can continue parsing for some errors and still fail properly */ + int error; - /* path_depth, isattr and path together control the formatting of - error messages by cfg_error() */ - int path_depth; - int isattr[MAX_PATH_DEPTH]; - const struct cfgelem *path[MAX_PATH_DEPTH]; - void *parent[MAX_PATH_DEPTH]; + /* path_depth, isattr and path together control the formatting of + error messages by cfg_error() */ + int path_depth; + int isattr[MAX_PATH_DEPTH]; + const struct cfgelem *path[MAX_PATH_DEPTH]; + void *parent[MAX_PATH_DEPTH]; }; /* "trace" is special: it enables (nearly) everything */ static const char *logcat_names[] = { - "fatal", "error", "warning", "info", "config", "discovery", "data", "radmin", "timing", "traffic", "topic", "tcp", "plist", "whc", "throttle", "rhc", "trace", NULL + "fatal", "error", "warning", "info", "config", "discovery", "data", "radmin", "timing", "traffic", "topic", "tcp", "plist", "whc", "throttle", "rhc", "trace", NULL }; static const uint32_t logcat_codes[] = { - DDS_LC_FATAL, DDS_LC_ERROR, DDS_LC_WARNING, DDS_LC_INFO, DDS_LC_CONFIG, DDS_LC_DISCOVERY, DDS_LC_DATA, DDS_LC_RADMIN, DDS_LC_TIMING, DDS_LC_TRAFFIC, DDS_LC_TOPIC, DDS_LC_TCP, DDS_LC_PLIST, DDS_LC_WHC, DDS_LC_THROTTLE, DDS_LC_RHC, DDS_LC_ALL + DDS_LC_FATAL, DDS_LC_ERROR, DDS_LC_WARNING, DDS_LC_INFO, DDS_LC_CONFIG, DDS_LC_DISCOVERY, DDS_LC_DATA, DDS_LC_RADMIN, DDS_LC_TIMING, DDS_LC_TRAFFIC, DDS_LC_TOPIC, DDS_LC_TCP, DDS_LC_PLIST, DDS_LC_WHC, DDS_LC_THROTTLE, DDS_LC_RHC, DDS_LC_ALL }; /* "trace" is special: it enables (nearly) everything */ @@ -115,12 +115,12 @@ static const uint32_t xcheck_codes[] = { }; /* We want the tracing/verbosity settings to be fixed while parsing -the configuration, so we update this variable instead. */ + the configuration, so we update this variable instead. */ static uint32_t enabled_logcats; static int cfgst_node_cmp(const void *va, const void *vb); static const ddsrt_avl_treedef_t cfgst_found_treedef = -DDSRT_AVL_TREEDEF_INITIALIZER(offsetof(struct cfgst_node, avlnode), offsetof(struct cfgst_node, key), cfgst_node_cmp, 0); + DDSRT_AVL_TREEDEF_INITIALIZER(offsetof(struct cfgst_node, avlnode), offsetof(struct cfgst_node, key), cfgst_node_cmp, 0); #define DU(fname) static int uf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) #define PF(fname) static void pf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) @@ -135,7 +135,6 @@ DU(boolean_default); #if 0 PF(boolean_default); #endif -DUPF(negated_boolean); DUPF(string); DU(tracingOutputFileName); DU(verbosity); @@ -143,8 +142,8 @@ DUPF(logcat); DUPF(xcheck); DUPF(int); DUPF(uint); -DUPF(int32); #if 0 +DUPF(int32); DUPF(uint32); #endif DU(natint); @@ -162,7 +161,6 @@ PF(duration); DUPF(standards_conformance); DUPF(besmode); DUPF(retransmit_merging); -DUPF(sched_prio_class); DUPF(sched_class); DUPF(maybe_memsize); DUPF(maybe_int32); @@ -173,7 +171,6 @@ DUPF(cipher); DUPF(bandwidth); #endif DUPF(domainId); -DUPF(durability_cdr); DUPF(transport_selector); DUPF(many_sockets_mode); DU(deaf_mute); @@ -221,17 +218,16 @@ DI(if_thread_properties); #define DEPRECATED_ATTR(name) "|" name, NULL, NULL /* MOVED: whereto must be a path relative to DDSI2Service, may not be used in/for lists and only for elements, may not be chained */ #define MOVED(name, whereto) ">" name, NULL, NULL, 0, whereto, 0, 0, 0, 0, 0, 0, NULL -static const struct cfgelem timestamp_cfgattrs[] = { - { ATTR("absolute"), 1, "false", ABSOFF(tracingRelativeTimestamps), 0, uf_negated_boolean, 0, pf_negated_boolean, - "

This option has no effect

" }, - END_MARKER -}; - +#if 0 +#define BLURB(text) text +#else +#define BLURB(text) NULL +#endif static const struct cfgelem general_cfgelems[] = { - { LEAF("NetworkInterfaceAddress"), 1, "auto", ABSOFF(networkAddressString), 0, uf_networkAddress, ff_free, pf_networkAddress, - "

This element specifies the preferred network interface for use by DDSI2E. The preferred network interface determines the IP address that DDSI2E advertises in the discovery protocol (but see also General/ExternalNetworkAddress), and is also the only interface over which multicasts are transmitted. The interface can be identified by its IP address, network interface name or network portion of the address. If the value \"auto\" is entered here, DDSI2E will select what it considers the most suitable interface.

" }, - { LEAF("MulticastRecvNetworkInterfaceAddresses"), 1, "preferred", ABSOFF(networkRecvAddressStrings), 0, uf_networkAddresses, ff_networkAddresses, pf_networkAddresses, - "

This element specifies on which network interfaces DDSI2E listens to multicasts. The following options are available:

\n\ + { LEAF("NetworkInterfaceAddress"), 1, "auto", ABSOFF(networkAddressString), 0, uf_networkAddress, ff_free, pf_networkAddress, + BLURB("

This element specifies the preferred network interface for use by DDSI2E. The preferred network interface determines the IP address that DDSI2E advertises in the discovery protocol (but see also General/ExternalNetworkAddress), and is also the only interface over which multicasts are transmitted. The interface can be identified by its IP address, network interface name or network portion of the address. If the value \"auto\" is entered here, DDSI2E will select what it considers the most suitable interface.

") }, + { LEAF("MulticastRecvNetworkInterfaceAddresses"), 1, "preferred", ABSOFF(networkRecvAddressStrings), 0, uf_networkAddresses, ff_networkAddresses, pf_networkAddresses, + BLURB("

This element specifies on which network interfaces DDSI2E listens to multicasts. The following options are available:

\n\
    \n\
  • all: listen for multicasts on all multicast-capable interfaces; or
  • \n\
  • any: listen for multicasts on the operating system default interface; or
  • \n\ @@ -239,177 +235,169 @@ static const struct cfgelem general_cfgelems[] = {
  • none: does not listen for multicasts on any interface; or
  • \n\
  • a comma-separated list of network addresses: configures DDSI2E to listen for multicasts on all of the listed addresses.
  • \n\
\n\ -

If DDSI2E is in IPv6 mode and the address of the preferred network interface is a link-local address, \"all\" is treated as a synonym for \"preferred\" and a comma-separated list is treated as \"preferred\" if it contains the preferred interface and as \"none\" if not.

" }, -{ LEAF("ExternalNetworkAddress"), 1, "auto", ABSOFF(externalAddressString), 0, uf_networkAddress, ff_free, pf_networkAddress, -"

This element allows explicitly overruling the network address DDSI2E advertises in the discovery protocol, which by default is the address of the preferred network interface (General/NetworkInterfaceAddress), to allow DDSI2E to communicate across a Network Address Translation (NAT) device.

" }, -{ LEAF("ExternalNetworkMask"), 1, "0.0.0.0", ABSOFF(externalMaskString), 0, uf_string, ff_free, pf_string, -"

This element specifies the network mask of the external network address. This element is relevant only when an external network address (General/ExternalNetworkAddress) is explicitly configured. In this case locators received via the discovery protocol that are within the same external subnet (as defined by this mask) will be translated to an internal address by replacing the network portion of the external address with the corresponding portion of the preferred network interface address. This option is IPv4-only.

" }, -{ LEAF("AllowMulticast"), 1, "true", ABSOFF(allowMulticast), 0, uf_allow_multicast, 0, pf_allow_multicast, -"

This element controls whether DDSI2E uses multicasts for data traffic.

\n\ +

If DDSI2E is in IPv6 mode and the address of the preferred network interface is a link-local address, \"all\" is treated as a synonym for \"preferred\" and a comma-separated list is treated as \"preferred\" if it contains the preferred interface and as \"none\" if not.

") }, + { LEAF("ExternalNetworkAddress"), 1, "auto", ABSOFF(externalAddressString), 0, uf_networkAddress, ff_free, pf_networkAddress, + BLURB("

This element allows explicitly overruling the network address DDSI2E advertises in the discovery protocol, which by default is the address of the preferred network interface (General/NetworkInterfaceAddress), to allow DDSI2E to communicate across a Network Address Translation (NAT) device.

") }, + { LEAF("ExternalNetworkMask"), 1, "0.0.0.0", ABSOFF(externalMaskString), 0, uf_string, ff_free, pf_string, + BLURB("

This element specifies the network mask of the external network address. This element is relevant only when an external network address (General/ExternalNetworkAddress) is explicitly configured. In this case locators received via the discovery protocol that are within the same external subnet (as defined by this mask) will be translated to an internal address by replacing the network portion of the external address with the corresponding portion of the preferred network interface address. This option is IPv4-only.

") }, + { LEAF("AllowMulticast"), 1, "true", ABSOFF(allowMulticast), 0, uf_allow_multicast, 0, pf_allow_multicast, + BLURB("

This element controls whether DDSI2E uses multicasts for data traffic.

\n\

It is a comma-separated list of some of the following keywords: \"spdp\", \"asm\", \"ssm\", or either of \"false\" or \"true\".

\n\
    \n\
  • spdp: enables the use of ASM (any-source multicast) for participant discovery, joining the multicast group on the discovery socket, transmitting SPDP messages to this group, but never advertising nor using any multicast address in any discovery message, thus forcing unicast communications for all endpoint discovery and user data.
  • \n\
  • asm: enables the use of ASM for all traffic (including SPDP)
  • \n\
  • ssm: enables the use of SSM (source-specific multicast) for all non-SPDP traffic (if supported)
  • \n\
\n\ -

When set to \"false\" all multicasting is disabled. The default, \"true\" enables full use of multicasts. Listening for multicasts can be controlled by General/MulticastRecvNetworkInterfaceAddresses.

" }, -{ LEAF("MulticastTimeToLive"), 1, "32", ABSOFF(multicast_ttl), 0, uf_natint_255, 0, pf_int, -"

This element specifies the time-to-live setting for outgoing multicast packets.

" }, -{ LEAF("DontRoute"), 1, "false", ABSOFF(dontRoute), 0, uf_boolean, 0, pf_boolean, -"

This element allows setting the SO_DONTROUTE option for outgoing packets, to bypass the local routing tables. This is generally useful only when the routing tables cannot be trusted, which is highly unusual.

" }, -{ LEAF ("UseIPv6"), 1, "default", ABSOFF (compat_use_ipv6), 0, uf_boolean_default, 0, pf_nop, -"

Deprecated (use Transport instead)

" }, -{ LEAF ("Transport"), 1, "default", ABSOFF (transport_selector), 0, uf_transport_selector, 0, pf_transport_selector, -"

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

" }, -{ LEAF("EnableMulticastLoopback"), 1, "true", ABSOFF(enableMulticastLoopback), 0, uf_boolean, 0, pf_boolean, -"

This element specifies whether DDSI2E allows IP multicast packets to be visible to all DDSI participants in the same node, including itself. It must be \"true\" for intra-node multicast communications, but if a node runs only a single DDSI2E service and does not host any other DDSI-capable programs, it should be set to \"false\" for improved performance.

" }, -{ DEPRECATED_LEAF("EnableLoopback"), 1, "false", ABSOFF(enableLoopback), 0, uf_boolean, 0, pf_boolean, -"

This element specifies whether DDSI packets are visible to all DDSI participants in the same process. It must be \"true\" for intra-process communications, i.e. a reader and writer communicating in the same address space. If enabled and using multicast then EnableMulticastLoopback must also be enabled.

" }, -{ LEAF("StartupModeDuration"), 1, "2 s", ABSOFF(startup_mode_duration), 0, uf_duration_ms_1hr, 0, pf_duration, -"

This element specifies how long the DDSI2E remains in its \"startup\" mode. While in \"startup\" mode all volatile reliable data published on the local node is retained as-if it were transient-local data, allowing existing readers on remote nodes to obtain the data even though discovering them takes some time. Best-effort data by definition need not arrive, and transient and persistent data are covered by the durability service.

\n\ -

Once the system is stable, DDSI2E keeps track of the existence of remote readers whether or not matching writers exist locally, avoiding this discovery delay and ensuring this is merely a node startup issue.

\n\ -

Setting General/StartupModeDuration to 0s will disable it.

" }, -{ LEAF("StartupModeCoversTransient"), 1, "true", ABSOFF(startup_mode_full), 0, uf_boolean, 0, pf_boolean, -"

This element configures whether startup-mode should also cover transient and persistent data, for configurations where the durability service does not take care of it. Configurations without defined merge policies best leave this enabled.

" }, -{ LEAF("MaxMessageSize"), 1, "4096 B", ABSOFF(max_msg_size), 0, uf_memsize, 0, pf_memsize, -"

This element specifies the maximum size of the UDP payload that DDSI2E will generate. DDSI2E will try to maintain this limit within the bounds of the DDSI specification, which means that in some cases (especially for very low values of MaxMessageSize) larger payloads may sporadically be observed (currently up to 1192 B).

\n\ -

On some networks it may be necessary to set this item to keep the packetsize below the MTU to prevent IP fragmentation. In those cases, it is generally advisable to also consider reducing Internal/FragmentSize.

" }, -{ LEAF("FragmentSize"), 1, "1280 B", ABSOFF(fragment_size), 0, uf_memsize, 0, pf_memsize, -"

This element specifies the size of DDSI sample fragments generated by DDSI2E. Samples larger than FragmentSize are fragmented into fragments of FragmentSize bytes each, except the last one, which may be smaller. The DDSI spec mandates a minimum fragment size of 1025 bytes, but DDSI2E will do whatever size is requested, accepting fragments of which the size is at least the minimum of 1025 and FragmentSize.

" }, -END_MARKER +

When set to \"false\" all multicasting is disabled. The default, \"true\" enables full use of multicasts. Listening for multicasts can be controlled by General/MulticastRecvNetworkInterfaceAddresses.

") }, + { LEAF("MulticastTimeToLive"), 1, "32", ABSOFF(multicast_ttl), 0, uf_natint_255, 0, pf_int, + BLURB("

This element specifies the time-to-live setting for outgoing multicast packets.

") }, + { LEAF("DontRoute"), 1, "false", ABSOFF(dontRoute), 0, uf_boolean, 0, pf_boolean, + BLURB("

This element allows setting the SO_DONTROUTE option for outgoing packets, to bypass the local routing tables. This is generally useful only when the routing tables cannot be trusted, which is highly unusual.

") }, + { LEAF ("UseIPv6"), 1, "default", ABSOFF (compat_use_ipv6), 0, uf_boolean_default, 0, pf_nop, + BLURB("

Deprecated (use Transport instead)

") }, + { LEAF ("Transport"), 1, "default", ABSOFF (transport_selector), 0, uf_transport_selector, 0, pf_transport_selector, + BLURB("

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

") }, + { LEAF("EnableMulticastLoopback"), 1, "true", ABSOFF(enableMulticastLoopback), 0, uf_boolean, 0, pf_boolean, + BLURB("

This element specifies whether DDSI2E allows IP multicast packets to be visible to all DDSI participants in the same node, including itself. It must be \"true\" for intra-node multicast communications, but if a node runs only a single DDSI2E service and does not host any other DDSI-capable programs, it should be set to \"false\" for improved performance.

") }, + { LEAF("MaxMessageSize"), 1, "4096 B", ABSOFF(max_msg_size), 0, uf_memsize, 0, pf_memsize, + BLURB("

This element specifies the maximum size of the UDP payload that DDSI2E will generate. DDSI2E will try to maintain this limit within the bounds of the DDSI specification, which means that in some cases (especially for very low values of MaxMessageSize) larger payloads may sporadically be observed (currently up to 1192 B).

\n\ +

On some networks it may be necessary to set this item to keep the packetsize below the MTU to prevent IP fragmentation. In those cases, it is generally advisable to also consider reducing Internal/FragmentSize.

") }, + { LEAF("FragmentSize"), 1, "1280 B", ABSOFF(fragment_size), 0, uf_memsize, 0, pf_memsize, + BLURB("

This element specifies the size of DDSI sample fragments generated by DDSI2E. Samples larger than FragmentSize are fragmented into fragments of FragmentSize bytes each, except the last one, which may be smaller. The DDSI spec mandates a minimum fragment size of 1025 bytes, but DDSI2E will do whatever size is requested, accepting fragments of which the size is at least the minimum of 1025 and FragmentSize.

") }, + END_MARKER }; #ifdef DDSI_INCLUDE_ENCRYPTION static const struct cfgelem securityprofile_cfgattrs[] = { - { ATTR("Name"), 1, NULL, RELOFF(config_securityprofile_listelem, name), 0, uf_string, ff_free, pf_string, - "

This attribute specifies the name of this DDSI2E security profile. Two security profiles cannot have the same name.

" }, - { ATTR("Cipher"), 1, "null", RELOFF(config_securityprofile_listelem, cipher), 0, uf_cipher, 0, pf_cipher, - "

This attribute specifies the cipher to be used for encrypting traffic over network partitions secured by this security profile. The possible ciphers are:

\n\ + { ATTR("Name"), 1, NULL, RELOFF(config_securityprofile_listelem, name), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies the name of this DDSI2E security profile. Two security profiles cannot have the same name.

") }, + { ATTR("Cipher"), 1, "null", RELOFF(config_securityprofile_listelem, cipher), 0, uf_cipher, 0, pf_cipher, + BLURB("

This attribute specifies the cipher to be used for encrypting traffic over network partitions secured by this security profile. The possible ciphers are:

\n\
  • aes128: AES with a 128-bit key;
  • \n\
  • aes192: AES with a 192-bit key;
  • \n\
  • aes256: AES with a 256-bit key;
  • \n\
  • blowfish: the Blowfish cipher with a 128 bit key;
  • \n\
  • null: no encryption;
\n\ -

SHA1 is used on conjunction with all ciphers except \"null\" to ensure data integrity.

" }, -{ ATTR("CipherKey"), 1, "", RELOFF(config_securityprofile_listelem, key), 0, uf_string, ff_free, pf_key, -"

The CipherKey attribute is used to define the secret key required by the cipher selected using the Cipher attribute. The value can be a URI referencing an external file containing the secret key, or the secret key can be defined in-place as a string value.

\n\ +

SHA1 is used on conjunction with all ciphers except \"null\" to ensure data integrity.

") }, + { ATTR("CipherKey"), 1, "", RELOFF(config_securityprofile_listelem, key), 0, uf_string, ff_free, pf_key, + BLURB("

The CipherKey attribute is used to define the secret key required by the cipher selected using the Cipher attribute. The value can be a URI referencing an external file containing the secret key, or the secret key can be defined in-place as a string value.

\n\

The key must be specified as a hexadecimal string with each character representing 4 bits of the key. E.g., 1ABC represents the 16-bit key 0001 1010 1011 1100. The key should not follow a well-known pattern and must exactly match the key length of the selected cipher.

\n\

A malformed key will cause the security profile to be marked as invalid, and disable all network partitions secured by the (invalid) security profile to prevent information leaks.

\n\ -

As all DDS applications require read access to the XML configuration file, for security reasons it is recommended to store the secret key in an external file in the file system, referenced by its URI. The file should be protected against read and write access from other users on the host.

" }, -END_MARKER +

As all DDS applications require read access to the XML configuration file, for security reasons it is recommended to store the secret key in an external file in the file system, referenced by its URI. The file should be protected against read and write access from other users on the host.

") }, + END_MARKER }; static const struct cfgelem security_cfgelems[] = { - { LEAF_W_ATTRS("SecurityProfile", securityprofile_cfgattrs), 0, 0, ABSOFF(securityProfiles), if_security_profile, 0, 0, 0, - "

This element defines a DDSI2E security profile.

" }, - END_MARKER + { LEAF_W_ATTRS("SecurityProfile", securityprofile_cfgattrs), 0, 0, ABSOFF(securityProfiles), if_security_profile, 0, 0, 0, + BLURB("

This element defines a DDSI2E security profile.

") }, + END_MARKER }; #endif /* DDSI_INCLUDE_ENCRYPTION */ #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS static const struct cfgelem networkpartition_cfgattrs[] = { - { ATTR("Name"), 1, NULL, RELOFF(config_networkpartition_listelem, name), 0, uf_string, ff_free, pf_string, - "

This attribute specifies the name of this DDSI2E network partition. Two network partitions cannot have the same name.

" }, - { ATTR("Address"), 1, NULL, RELOFF(config_networkpartition_listelem, address_string), 0, uf_string, ff_free, pf_string, - "

This attribute specifies the multicast addresses associated with the network partition as a comma-separated list. Readers matching this network partition (cf. Partitioning/PartitionMappings) will listen for multicasts on all of these addresses and advertise them in the discovery protocol. The writers will select the most suitable address from the addresses advertised by the readers.

" }, - { ATTR("Connected"), 1, "true", RELOFF(config_networkpartition_listelem, connected), 0, uf_boolean, 0, pf_boolean, - "

This attribute is a placeholder.

" }, + { ATTR("Name"), 1, NULL, RELOFF(config_networkpartition_listelem, name), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies the name of this DDSI2E network partition. Two network partitions cannot have the same name.

") }, + { ATTR("Address"), 1, NULL, RELOFF(config_networkpartition_listelem, address_string), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies the multicast addresses associated with the network partition as a comma-separated list. Readers matching this network partition (cf. Partitioning/PartitionMappings) will listen for multicasts on all of these addresses and advertise them in the discovery protocol. The writers will select the most suitable address from the addresses advertised by the readers.

") }, + { ATTR("Connected"), 1, "true", RELOFF(config_networkpartition_listelem, connected), 0, uf_boolean, 0, pf_boolean, + BLURB("

This attribute is a placeholder.

") }, #ifdef DDSI_INCLUDE_ENCRYPTION - { ATTR("SecurityProfile"), 1, "null", RELOFF(config_networkpartition_listelem, profileName), 0, uf_string, ff_free, pf_string, - "

This attribute selects the DDSI2E security profile for encrypting the traffic mapped to this DDSI2E network partition. The default \"null\" means the network partition is unsecured; any other name refers to a security profile defined using the Security/SecurityProfile elements.

" }, + { ATTR("SecurityProfile"), 1, "null", RELOFF(config_networkpartition_listelem, profileName), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute selects the DDSI2E security profile for encrypting the traffic mapped to this DDSI2E network partition. The default \"null\" means the network partition is unsecured; any other name refers to a security profile defined using the Security/SecurityProfile elements.

") }, #endif /* DDSI_INCLUDE_ENCRYPTION */ - END_MARKER + END_MARKER }; static const struct cfgelem networkpartitions_cfgelems[] = { - { LEAF_W_ATTRS("NetworkPartition", networkpartition_cfgattrs), 0, 0, ABSOFF(networkPartitions), if_network_partition, 0, 0, 0, - "

This element defines a DDSI2E network partition.

" }, - END_MARKER + { LEAF_W_ATTRS("NetworkPartition", networkpartition_cfgattrs), 0, 0, ABSOFF(networkPartitions), if_network_partition, 0, 0, 0, + BLURB("

This element defines a DDSI2E network partition.

") }, + END_MARKER }; static const struct cfgelem ignoredpartitions_cfgattrs[] = { - { ATTR("DCPSPartitionTopic"), 1, NULL, RELOFF(config_ignoredpartition_listelem, DCPSPartitionTopic), 0, uf_string, ff_free, pf_string, - "

This attribute specifies a partition and a topic expression, separated by a single '.', that are used to determine if a given partition and topic will be ignored or not. The expressions may use the usual wildcards '*' and '?'. DDSI2E will consider an wildcard DCPS partition to match an expression iff there exists a string that satisfies both expressions.

" }, - END_MARKER + { ATTR("DCPSPartitionTopic"), 1, NULL, RELOFF(config_ignoredpartition_listelem, DCPSPartitionTopic), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies a partition and a topic expression, separated by a single '.', that are used to determine if a given partition and topic will be ignored or not. The expressions may use the usual wildcards '*' and '?'. DDSI2E will consider an wildcard DCPS partition to match an expression iff there exists a string that satisfies both expressions.

") }, + END_MARKER }; static const struct cfgelem ignoredpartitions_cfgelems[] = { - { LEAF_W_ATTRS("IgnoredPartition", ignoredpartitions_cfgattrs), 0, 0, ABSOFF(ignoredPartitions), if_ignored_partition, 0, 0, 0, - "

This element can be used to prevent certain combinations of DCPS partition and topic from being transmitted over the network. DDSI2E will complete ignore readers and writers for which all DCPS partitions as well as their topic is ignored, not even creating DDSI readers and writers to mirror the DCPS ones.

" }, - END_MARKER + { LEAF_W_ATTRS("IgnoredPartition", ignoredpartitions_cfgattrs), 0, 0, ABSOFF(ignoredPartitions), if_ignored_partition, 0, 0, 0, + BLURB("

This element can be used to prevent certain combinations of DCPS partition and topic from being transmitted over the network. DDSI2E will complete ignore readers and writers for which all DCPS partitions as well as their topic is ignored, not even creating DDSI readers and writers to mirror the DCPS ones.

") }, + END_MARKER }; static const struct cfgelem partitionmappings_cfgattrs[] = { - { ATTR("NetworkPartition"), 1, NULL, RELOFF(config_partitionmapping_listelem, networkPartition), 0, uf_string, ff_free, pf_string, - "

This attribute specifies which DDSI2E network partition is to be used for DCPS partition/topic combinations matching the DCPSPartitionTopic attribute within this PartitionMapping element.

" }, - { ATTR("DCPSPartitionTopic"), 1, NULL, RELOFF(config_partitionmapping_listelem, DCPSPartitionTopic), 0, uf_string, ff_free, pf_string, - "

This attribute specifies a partition and a topic expression, separated by a single '.', that are used to determine if a given partition and topic maps to the DDSI2E network partition named by the NetworkPartition attribute in this PartitionMapping element. The expressions may use the usual wildcards '*' and '?'. DDSI2E will consider a wildcard DCPS partition to match an expression if there exists a string that satisfies both expressions.

" }, - END_MARKER + { ATTR("NetworkPartition"), 1, NULL, RELOFF(config_partitionmapping_listelem, networkPartition), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies which DDSI2E network partition is to be used for DCPS partition/topic combinations matching the DCPSPartitionTopic attribute within this PartitionMapping element.

") }, + { ATTR("DCPSPartitionTopic"), 1, NULL, RELOFF(config_partitionmapping_listelem, DCPSPartitionTopic), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies a partition and a topic expression, separated by a single '.', that are used to determine if a given partition and topic maps to the DDSI2E network partition named by the NetworkPartition attribute in this PartitionMapping element. The expressions may use the usual wildcards '*' and '?'. DDSI2E will consider a wildcard DCPS partition to match an expression if there exists a string that satisfies both expressions.

") }, + END_MARKER }; static const struct cfgelem partitionmappings_cfgelems[] = { - { LEAF_W_ATTRS("PartitionMapping", partitionmappings_cfgattrs), 0, 0, ABSOFF(partitionMappings), if_partition_mapping, 0, 0, 0, - "

This element defines a mapping from a DCPS partition/topic combination to a DDSI2E network partition. This allows partitioning data flows by using special multicast addresses for part of the data and possibly also encrypting the data flow.

" }, - END_MARKER + { LEAF_W_ATTRS("PartitionMapping", partitionmappings_cfgattrs), 0, 0, ABSOFF(partitionMappings), if_partition_mapping, 0, 0, 0, + BLURB("

This element defines a mapping from a DCPS partition/topic combination to a DDSI2E network partition. This allows partitioning data flows by using special multicast addresses for part of the data and possibly also encrypting the data flow.

") }, + END_MARKER }; static const struct cfgelem partitioning_cfgelems[] = { - { GROUP("NetworkPartitions", networkpartitions_cfgelems), - "

The NetworkPartitions element specifies the DDSI2E network partitions.

" }, - { GROUP("IgnoredPartitions", ignoredpartitions_cfgelems), - "

The IgnoredPartitions element specifies DCPS partition/topic combinations that are not distributed over the network.

" }, - { GROUP("PartitionMappings", partitionmappings_cfgelems), - "

The PartitionMappings element specifies the mapping from DCPS partition/topic combinations to DDSI2E network partitions.

" }, - END_MARKER + { GROUP("NetworkPartitions", networkpartitions_cfgelems), + BLURB("

The NetworkPartitions element specifies the DDSI2E network partitions.

") }, + { GROUP("IgnoredPartitions", ignoredpartitions_cfgelems), + BLURB("

The IgnoredPartitions element specifies DCPS partition/topic combinations that are not distributed over the network.

") }, + { GROUP("PartitionMappings", partitionmappings_cfgelems), + BLURB("

The PartitionMappings element specifies the mapping from DCPS partition/topic combinations to DDSI2E network partitions.

") }, + END_MARKER }; #endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */ #ifdef DDSI_INCLUDE_NETWORK_CHANNELS static const struct cfgelem channel_cfgelems[] = { #ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING - { LEAF("DataBandwidthLimit"), 1, "inf", RELOFF(config_channel_listelem, data_bandwidth_limit), 0, uf_bandwidth, 0, pf_bandwidth, - "

This element specifies the maximum transmit rate of new samples and directly related data, for this channel. Bandwidth limiting uses a leaky bucket scheme. The default value \"inf\" means DDSI2E imposes no limitation, the underlying operating system and hardware will likely limit the maimum transmit rate.

" }, - { LEAF("AuxiliaryBandwidthLimit"), 1, "inf", RELOFF(config_channel_listelem, auxiliary_bandwidth_limit), 0, uf_bandwidth, 0, pf_bandwidth, - "

This element specifies the maximum transmit rate of auxiliary traffic on this channel (e.g. retransmits, heartbeats, etc). Bandwidth limiting uses a leaky bucket scheme. The default value \"inf\" means DDSI2E imposes no limitation, the underlying operating system and hardware will likely limit the maimum transmit rate.

" }, + { LEAF("DataBandwidthLimit"), 1, "inf", RELOFF(config_channel_listelem, data_bandwidth_limit), 0, uf_bandwidth, 0, pf_bandwidth, + BLURB("

This element specifies the maximum transmit rate of new samples and directly related data, for this channel. Bandwidth limiting uses a leaky bucket scheme. The default value \"inf\" means DDSI2E imposes no limitation, the underlying operating system and hardware will likely limit the maimum transmit rate.

") }, + { LEAF("AuxiliaryBandwidthLimit"), 1, "inf", RELOFF(config_channel_listelem, auxiliary_bandwidth_limit), 0, uf_bandwidth, 0, pf_bandwidth, + BLURB("

This element specifies the maximum transmit rate of auxiliary traffic on this channel (e.g. retransmits, heartbeats, etc). Bandwidth limiting uses a leaky bucket scheme. The default value \"inf\" means DDSI2E imposes no limitation, the underlying operating system and hardware will likely limit the maimum transmit rate.

") }, #endif - { LEAF("DiffServField"), 1, "0", RELOFF(config_channel_listelem, diffserv_field), 0, uf_natint, 0, pf_int, - "

This element describes the DiffServ setting the channel will apply to the networking messages. This parameter determines the value of the diffserv field of the IP version 4 packets sent on this channel which allows QoS setting to be applied to the network traffic send on this channel.
\n\ + { LEAF("DiffServField"), 1, "0", RELOFF(config_channel_listelem, diffserv_field), 0, uf_natint, 0, pf_int, + BLURB("

This element describes the DiffServ setting the channel will apply to the networking messages. This parameter determines the value of the diffserv field of the IP version 4 packets sent on this channel which allows QoS setting to be applied to the network traffic send on this channel.
\n\ Windows platform support for setting the diffserv field is dependent on the OS version.
\n\ For Windows versions XP SP2 and 2003 to use the diffserv field the following parameter should be added to the register:

\n\ HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\TcpIp\\Parameters\\DisableUserTOSSetting

\n\ The type of this parameter is a DWORD and its value should be set to 0 to allow setting of the diffserv field.

\n\ For Windows version 7 or higher a new API (qWAVE) has been introduced. For these platforms the specified diffserv value is mapped to one of the support traffic types.\n\ The mapping is as follows: 1-8 background traffic; 9-40 excellent traffic; 41-55 audio/video traffic; 56 voice traffic; 57-63 control traffic.\n\ -When an application is run without Administrative priveleges then only the diffserv value of 0, 8, 40 or 56 is allowed.

" }, -END_MARKER +When an application is run without Administrative priveleges then only the diffserv value of 0, 8, 40 or 56 is allowed.

") }, + END_MARKER }; static const struct cfgelem channel_cfgattrs[] = { - { ATTR("Name"), 1, NULL, RELOFF(config_channel_listelem, name), 0, uf_string, ff_free, pf_string, - "

This attribute specifies name of this channel. The name should uniquely identify the channel.

" }, - { ATTR("TransportPriority"), 1, "0", RELOFF(config_channel_listelem, priority), 0, uf_natint, 0, pf_int, - "

This attribute sets the transport priority threshold for the channel. Each DCPS data writer has a \"transport_priority\" QoS and this QoS is used to select a channel for use by this writer. The selected channel is the one with the largest threshold not greater than the writer's transport priority, and if no such channel exists, the channel with the lowest threshold.

" }, - END_MARKER + { ATTR("Name"), 1, NULL, RELOFF(config_channel_listelem, name), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies name of this channel. The name should uniquely identify the channel.

") }, + { ATTR("TransportPriority"), 1, "0", RELOFF(config_channel_listelem, priority), 0, uf_natint, 0, pf_int, + BLURB("

This attribute sets the transport priority threshold for the channel. Each DCPS data writer has a \"transport_priority\" QoS and this QoS is used to select a channel for use by this writer. The selected channel is the one with the largest threshold not greater than the writer's transport priority, and if no such channel exists, the channel with the lowest threshold.

") }, + END_MARKER }; static const struct cfgelem channels_cfgelems[] = { - { MGROUP("Channel", channel_cfgelems, channel_cfgattrs), 42, 0, ABSOFF(channels), if_channel, 0, 0, 0, - "

This element defines a channel.

" }, - END_MARKER + { MGROUP("Channel", channel_cfgelems, channel_cfgattrs), 42, 0, ABSOFF(channels), if_channel, 0, 0, 0, + BLURB("

This element defines a channel.

") }, + END_MARKER }; #endif /* DDSI_INCLUDE_NETWORK_CHANNELS */ static const struct cfgelem thread_properties_sched_cfgelems[] = { - { LEAF("Class"), 1, "default", RELOFF(config_thread_properties_listelem, sched_class), 0, uf_sched_class, 0, pf_sched_class, - "

This element specifies the thread scheduling class (realtime, timeshare or default). The user may need special privileges from the underlying operating system to be able to assign some of the privileged scheduling classes.

" }, - { LEAF("Priority"), 1, "default", RELOFF(config_thread_properties_listelem, sched_priority), 0, uf_maybe_int32, 0, pf_maybe_int32, - "

This element specifies the thread priority (decimal integer or default). Only priorities that are supported by the underlying operating system can be assigned to this element. The user may need special privileges from the underlying operating system to be able to assign some of the privileged priorities.

" }, - END_MARKER + { LEAF("Class"), 1, "default", RELOFF(config_thread_properties_listelem, sched_class), 0, uf_sched_class, 0, pf_sched_class, + BLURB("

This element specifies the thread scheduling class (realtime, timeshare or default). The user may need special privileges from the underlying operating system to be able to assign some of the privileged scheduling classes.

") }, + { LEAF("Priority"), 1, "default", RELOFF(config_thread_properties_listelem, sched_priority), 0, uf_maybe_int32, 0, pf_maybe_int32, + BLURB("

This element specifies the thread priority (decimal integer or default). Only priorities that are supported by the underlying operating system can be assigned to this element. The user may need special privileges from the underlying operating system to be able to assign some of the privileged priorities.

") }, + END_MARKER }; static const struct cfgelem thread_properties_cfgattrs[] = { - { ATTR("Name"), 1, NULL, RELOFF(config_thread_properties_listelem, name), 0, uf_string, ff_free, pf_string, - "

The Name of the thread for which properties are being set. The following threads exist:

\n\ + { ATTR("Name"), 1, NULL, RELOFF(config_thread_properties_listelem, name), 0, uf_string, ff_free, pf_string, + BLURB("

The Name of the thread for which properties are being set. The following threads exist:

\n\
  • gc: garbage collector thread involved in deleting entities;
  • \n\
  • recv: receive thread, taking data from the network and running the protocol state machine;
  • \n\
  • dq.builtins: delivery thread for DDSI-builtin data, primarily for discovery;
  • \n\ @@ -417,370 +405,352 @@ static const struct cfgelem thread_properties_cfgattrs[] = {
  • tev: general timed-event handling, retransmits and discovery;
  • \n\
  • xmit.CHAN: transmit thread for channel CHAN;
  • \n\
  • dq.CHAN: delivery thread for channel CHAN;
  • \n\ -
  • tev.CHAN: timed-even thread for channel CHAN.
" }, -END_MARKER +
  • tev.CHAN: timed-even thread for channel CHAN.
  • ") }, + END_MARKER }; static const struct cfgelem thread_properties_cfgelems[] = { - { GROUP("Scheduling", thread_properties_sched_cfgelems), - "

    This element configures the scheduling properties of the thread.

    " }, - { LEAF("StackSize"), 1, "default", RELOFF(config_thread_properties_listelem, stack_size), 0, uf_maybe_memsize, 0, pf_maybe_memsize, - "

    This element configures the stack size for this thread. The default value default leaves the stack size at the operating system default.

    " }, - END_MARKER + { GROUP("Scheduling", thread_properties_sched_cfgelems), + BLURB("

    This element configures the scheduling properties of the thread.

    ") }, + { LEAF("StackSize"), 1, "default", RELOFF(config_thread_properties_listelem, stack_size), 0, uf_maybe_memsize, 0, pf_maybe_memsize, + BLURB("

    This element configures the stack size for this thread. The default value default leaves the stack size at the operating system default.

    ") }, + END_MARKER }; static const struct cfgelem threads_cfgelems[] = { - { MGROUP("Thread", thread_properties_cfgelems, thread_properties_cfgattrs), 1000, 0, ABSOFF(thread_properties), if_thread_properties, 0, 0, 0, - "

    This element is used to set thread properties.

    " }, - END_MARKER + { MGROUP("Thread", thread_properties_cfgelems, thread_properties_cfgattrs), 1000, 0, ABSOFF(thread_properties), if_thread_properties, 0, 0, 0, + BLURB("

    This element is used to set thread properties.

    ") }, + END_MARKER }; static const struct cfgelem compatibility_cfgelems[] = { - { LEAF("StandardsConformance"), 1, "lax", ABSOFF(standards_conformance), 0, uf_standards_conformance, 0, pf_standards_conformance, - "

    This element sets the level of standards conformance of this instance of the DDSI2E Service. Stricter conformance typically means less interoperability with other implementations. Currently three modes are defined:

    \n\ + { LEAF("StandardsConformance"), 1, "lax", ABSOFF(standards_conformance), 0, uf_standards_conformance, 0, pf_standards_conformance, + BLURB("

    This element sets the level of standards conformance of this instance of the DDSI2E Service. Stricter conformance typically means less interoperability with other implementations. Currently three modes are defined:

    \n\
    • pedantic: very strictly conform to the specification, ultimately for compliancy testing, but currently of little value because it adheres even to what will most likely turn out to be editing errors in the DDSI standard. Arguably, as long as no errata have been published it is the current text that is in effect, and that is what pedantic currently does.
    • \n\
    • strict: a slightly less strict view of the standard than does pedantic: it follows the established behaviour where the standard is obviously in error.
    • \n\
    • lax: attempt to provide the smoothest possible interoperability, anticipating future revisions of elements in the standard in areas that other implementations do not adhere to, even though there is no good reason not to.
    \n\ -

    The default setting is \"lax\".

    " }, -{ LEAF("ExplicitlyPublishQosSetToDefault"), 1, "false", ABSOFF(explicitly_publish_qos_set_to_default), 0, uf_boolean, 0, pf_boolean, -"

    This element specifies whether QoS settings set to default values are explicitly published in the discovery protocol. Implementations are to use the default value for QoS settings not published, which allows a significant reduction of the amount of data that needs to be exchanged for the discovery protocol, but this requires all implementations to adhere to the default values specified by the specifications.

    \n\ -

    When interoperability is required with an implementation that does not follow the specifications in this regard, setting this option to true will help.

    " }, -{ LEAF ("ManySocketsMode"), 1, "single", ABSOFF (many_sockets_mode), 0, uf_many_sockets_mode, 0, pf_many_sockets_mode, -"

    This option specifies whether a network socket will be created for each domain participant on a host. The specification seems to assume that each participant has a unique address, and setting this option will ensure this to be the case. This is not the defeault.

    \n\ -

    Disabling it slightly improves performance and reduces network traffic somewhat. It also causes the set of port numbers needed by DDSI2E to become predictable, which may be useful for firewall and NAT configuration.

    " }, -{ LEAF("ArrivalOfDataAssertsPpAndEpLiveliness"), 1, "true", ABSOFF(arrival_of_data_asserts_pp_and_ep_liveliness), 0, uf_boolean, 0, pf_boolean, -"

    When set to true, arrival of a message from a peer asserts liveliness of that peer. When set to false, only SPDP and explicit lease renewals have this effect.

    " }, -{ LEAF("AckNackNumbitsEmptySet"), 1, "0", ABSOFF(acknack_numbits_emptyset), 0, uf_natint, 0, pf_int, -"

    This element governs the representation of an acknowledgement message that does not also negatively-acknowledge some samples. If set to 0, the generated acknowledgements have an invalid form and will be reject by the strict and pedantic conformance modes, but several other implementation require this setting for smooth interoperation.

    \n\ -

    If set to 1, all acknowledgements sent by DDSI2E adhere the form of acknowledgement messages allowed by the standard, but this causes problems when interoperating with these other implementations. The strict and pedantic standards conformance modes always overrule an AckNackNumbitsEmptySet=0 to prevent the transmitting of invalid messages.

    " }, -{ LEAF("RespondToRtiInitZeroAckWithInvalidHeartbeat"), 1, "false", ABSOFF(respond_to_rti_init_zero_ack_with_invalid_heartbeat), 0, uf_boolean, 0, pf_boolean, -"

    This element allows a closer mimicking of the behaviour of some other DDSI implementations, albeit at the cost of generating even more invalid messages. Setting it to true ensures a Heartbeat can be sent at any time when a remote node requests one, setting it to false delays it until a valid one can be sent.

    \n\ -

    The latter is fully compliant with the specification, and no adverse effects have been observed. It is the default.

    " }, -{ LEAF("AssumeRtiHasPmdEndpoints"), 1, "false", ABSOFF(assume_rti_has_pmd_endpoints), 0, uf_boolean, 0, pf_boolean, -"

    This option assumes ParticipantMessageData endpoints required by the liveliness protocol are present in RTI participants even when not properly advertised by the participant discovery protocol.

    " }, -END_MARKER +

    The default setting is \"lax\".

    ") }, + { LEAF("ExplicitlyPublishQosSetToDefault"), 1, "false", ABSOFF(explicitly_publish_qos_set_to_default), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element specifies whether QoS settings set to default values are explicitly published in the discovery protocol. Implementations are to use the default value for QoS settings not published, which allows a significant reduction of the amount of data that needs to be exchanged for the discovery protocol, but this requires all implementations to adhere to the default values specified by the specifications.

    \n\ +

    When interoperability is required with an implementation that does not follow the specifications in this regard, setting this option to true will help.

    ") }, + { LEAF ("ManySocketsMode"), 1, "single", ABSOFF (many_sockets_mode), 0, uf_many_sockets_mode, 0, pf_many_sockets_mode, + BLURB("

    This option specifies whether a network socket will be created for each domain participant on a host. The specification seems to assume that each participant has a unique address, and setting this option will ensure this to be the case. This is not the defeault.

    \n\ +

    Disabling it slightly improves performance and reduces network traffic somewhat. It also causes the set of port numbers needed by DDSI2E to become predictable, which may be useful for firewall and NAT configuration.

    ") }, + { LEAF("ArrivalOfDataAssertsPpAndEpLiveliness"), 1, "true", ABSOFF(arrival_of_data_asserts_pp_and_ep_liveliness), 0, uf_boolean, 0, pf_boolean, + BLURB("

    When set to true, arrival of a message from a peer asserts liveliness of that peer. When set to false, only SPDP and explicit lease renewals have this effect.

    ") }, + { LEAF("AssumeRtiHasPmdEndpoints"), 1, "false", ABSOFF(assume_rti_has_pmd_endpoints), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This option assumes ParticipantMessageData endpoints required by the liveliness protocol are present in RTI participants even when not properly advertised by the participant discovery protocol.

    ") }, + END_MARKER }; static const struct cfgelem unsupp_test_cfgelems[] = { - { LEAF("XmitLossiness"), 1, "0", ABSOFF(xmit_lossiness), 0, uf_int, 0, pf_int, - "

    This element controls the fraction of outgoing packets to drop, specified as samples per thousand.

    " }, - END_MARKER + { LEAF("XmitLossiness"), 1, "0", ABSOFF(xmit_lossiness), 0, uf_int, 0, pf_int, + BLURB("

    This element controls the fraction of outgoing packets to drop, specified as samples per thousand.

    ") }, + END_MARKER }; static const struct cfgelem unsupp_watermarks_cfgelems[] = { - { LEAF("WhcLow"), 1, "1 kB", ABSOFF(whc_lowwater_mark), 0, uf_memsize, 0, pf_memsize, - "

    This element sets the low-water mark for the DDSI2E WHCs, expressed in bytes. A suspended writer resumes transmitting when its DDSI2E WHC shrinks to this size.

    " }, - { LEAF("WhcHigh"), 1, "100 kB", ABSOFF(whc_highwater_mark), 0, uf_memsize, 0, pf_memsize, - "

    This element sets the maximum allowed high-water mark for the DDSI2E WHCs, expressed in bytes. A writer is suspended when the WHC reaches this size.

    " }, - { LEAF("WhcHighInit"), 1, "30 kB", ABSOFF(whc_init_highwater_mark), 0, uf_maybe_memsize, 0, pf_maybe_memsize, - "

    This element sets the initial level of the high-water mark for the DDSI2E WHCs, expressed in bytes.

    " }, - { LEAF("WhcAdaptive|WhcAdaptative"), 1, "true", ABSOFF(whc_adaptive), 0, uf_boolean, 0, pf_boolean, - "

    This element controls whether DDSI2E will adapt the high-water mark to current traffic conditions, based on retransmit requests and transmit pressure.

    " }, - END_MARKER + { LEAF("WhcLow"), 1, "1 kB", ABSOFF(whc_lowwater_mark), 0, uf_memsize, 0, pf_memsize, + BLURB("

    This element sets the low-water mark for the DDSI2E WHCs, expressed in bytes. A suspended writer resumes transmitting when its DDSI2E WHC shrinks to this size.

    ") }, + { LEAF("WhcHigh"), 1, "100 kB", ABSOFF(whc_highwater_mark), 0, uf_memsize, 0, pf_memsize, + BLURB("

    This element sets the maximum allowed high-water mark for the DDSI2E WHCs, expressed in bytes. A writer is suspended when the WHC reaches this size.

    ") }, + { LEAF("WhcHighInit"), 1, "30 kB", ABSOFF(whc_init_highwater_mark), 0, uf_maybe_memsize, 0, pf_maybe_memsize, + BLURB("

    This element sets the initial level of the high-water mark for the DDSI2E WHCs, expressed in bytes.

    ") }, + { LEAF("WhcAdaptive|WhcAdaptative"), 1, "true", ABSOFF(whc_adaptive), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element controls whether DDSI2E will adapt the high-water mark to current traffic conditions, based on retransmit requests and transmit pressure.

    ") }, + END_MARKER }; static const struct cfgelem control_topic_cfgattrs[] = { - { DEPRECATED_ATTR("Enable"), 1, "false", ABSOFF(enable_control_topic), 0, uf_boolean, 0, pf_boolean, - "

    This element controls whether DDSI2E should create a topic to control DDSI2E's behaviour dynamically.

    " - }, - { DEPRECATED_ATTR("InitialReset"), 1, "inf", ABSOFF(initial_deaf_mute_reset), 0, uf_duration_inf, 0, pf_duration, - "

    This element controls after how much time an initial deaf/mute state will automatically reset.

    " - }, - END_MARKER + { DEPRECATED_ATTR("Enable"), 1, "false", ABSOFF(enable_control_topic), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element controls whether DDSI2E should create a topic to control DDSI2E's behaviour dynamically.

    ") }, + { DEPRECATED_ATTR("InitialReset"), 1, "inf", ABSOFF(initial_deaf_mute_reset), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This element controls after how much time an initial deaf/mute state will automatically reset.

    ") }, + END_MARKER }; static const struct cfgelem control_topic_cfgelems[] = { - { DEPRECATED_LEAF ("Deaf"), 1, "false", ABSOFF (initial_deaf), 0, uf_deaf_mute, 0, pf_boolean, - "

    This element controls whether DDSI2E defaults to deaf mode or to normal mode. This controls both the initial behaviour and what behaviour it auto-reverts to.

    " }, - { DEPRECATED_LEAF ("Mute"), 1, "false", ABSOFF (initial_mute), 0, uf_deaf_mute, 0, pf_boolean, - "

    This element controls whether DDSI2E defaults to mute mode or to normal mode. This controls both the initial behaviour and what behaviour it auto-reverts to.

    " }, - END_MARKER + { DEPRECATED_LEAF ("Deaf"), 1, "false", ABSOFF (initial_deaf), 0, uf_deaf_mute, 0, pf_boolean, + BLURB("

    This element controls whether DDSI2E defaults to deaf mode or to normal mode. This controls both the initial behaviour and what behaviour it auto-reverts to.

    ") }, + { DEPRECATED_LEAF ("Mute"), 1, "false", ABSOFF (initial_mute), 0, uf_deaf_mute, 0, pf_boolean, + BLURB("

    This element controls whether DDSI2E defaults to mute mode or to normal mode. This controls both the initial behaviour and what behaviour it auto-reverts to.

    ") }, + END_MARKER }; static const struct cfgelem rediscovery_blacklist_duration_attrs[] = { - { ATTR("enforce"), 1, "false", ABSOFF(prune_deleted_ppant.enforce_delay), 0, uf_boolean, 0, pf_boolean, - "

    This attribute controls whether the configured time during which recently deleted participants will not be rediscovered (i.e., \"black listed\") is enforced and following complete removal of the participant in DDSI2E, or whether it can be rediscovered earlier provided all traces of that participant have been removed already.

    " }, - END_MARKER + { ATTR("enforce"), 1, "false", ABSOFF(prune_deleted_ppant.enforce_delay), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This attribute controls whether the configured time during which recently deleted participants will not be rediscovered (i.e., \"black listed\") is enforced and following complete removal of the participant in DDSI2E, or whether it can be rediscovered earlier provided all traces of that participant have been removed already.

    ") }, + END_MARKER }; static const struct cfgelem heartbeat_interval_attrs[] = { - { ATTR ("min"), 1, "5 ms", ABSOFF (const_hb_intv_min), 0, uf_duration_inf, 0, pf_duration, - "

    This attribute sets the minimum interval that must have passed since the most recent heartbeat from a writer, before another asynchronous (not directly related to writing) will be sent.

    " }, - { ATTR ("minsched"), 1, "20 ms", ABSOFF (const_hb_intv_sched_min), 0, uf_duration_inf, 0, pf_duration, - "

    This attribute sets the minimum interval for periodic heartbeats. Other events may still cause heartbeats to go out.

    " }, - { ATTR ("max"), 1, "8 s", ABSOFF (const_hb_intv_sched_max), 0, uf_duration_inf, 0, pf_duration, - "

    This attribute sets the maximum interval for periodic heartbeats.

    " }, - END_MARKER + { ATTR ("min"), 1, "5 ms", ABSOFF (const_hb_intv_min), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This attribute sets the minimum interval that must have passed since the most recent heartbeat from a writer, before another asynchronous (not directly related to writing) will be sent.

    ") }, + { ATTR ("minsched"), 1, "20 ms", ABSOFF (const_hb_intv_sched_min), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This attribute sets the minimum interval for periodic heartbeats. Other events may still cause heartbeats to go out.

    ") }, + { ATTR ("max"), 1, "8 s", ABSOFF (const_hb_intv_sched_max), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This attribute sets the maximum interval for periodic heartbeats.

    ") }, + END_MARKER }; static const struct cfgelem liveliness_monitoring_attrs[] = { { ATTR("StackTraces"), 1, "true", ABSOFF(noprogress_log_stacktraces), 0, uf_boolean, 0, pf_boolean, - "

    This element controls whether or not to write stack traces to the DDSI2 trace when a thread fails to make progress (on select platforms only).

    " }, + BLURB("

    This element controls whether or not to write stack traces to the DDSI2 trace when a thread fails to make progress (on select platforms only).

    ") }, { ATTR("Interval"), 1, "1s", ABSOFF(liveliness_monitoring_interval), 0, uf_duration_100ms_1hr, 0, pf_duration, - "

    This element controls the interval at which to check whether threads have been making progress.

    " }, + BLURB("

    This element controls the interval at which to check whether threads have been making progress.

    ") }, END_MARKER }; static const struct cfgelem multiple_recv_threads_attrs[] = { { ATTR("maxretries"), 1, "4294967295", ABSOFF(recv_thread_stop_maxretries), 0, uf_uint, 0, pf_uint, - "

    Receive threads dedicated to a single socket can only be triggered for termination by sending a packet. Reception of any packet will do, so termination failure due to packet loss is exceedingly unlikely, but to eliminate all risks, it will retry as many times as specified by this attribute before aborting.

    " }, + BLURB("

    Receive threads dedicated to a single socket can only be triggered for termination by sending a packet. Reception of any packet will do, so termination failure due to packet loss is exceedingly unlikely, but to eliminate all risks, it will retry as many times as specified by this attribute before aborting.

    ") }, END_MARKER }; static const struct cfgelem unsupp_cfgelems[] = { - { MOVED("MaxMessageSize", "General/MaxMessageSize") }, - { MOVED("FragmentSize", "General/FragmentSize") }, - { LEAF("DeliveryQueueMaxSamples"), 1, "256", ABSOFF(delivery_queue_maxsamples), 0, uf_uint, 0, pf_uint, - "

    This element controls the Maximum size of a delivery queue, expressed in samples. Once a delivery queue is full, incoming samples destined for that queue are dropped until space becomes available again.

    " }, - { LEAF("PrimaryReorderMaxSamples"), 1, "64", ABSOFF(primary_reorder_maxsamples), 0, uf_uint, 0, pf_uint, - "

    This element sets the maximum size in samples of a primary re-order administration. Each proxy writer has one primary re-order administration to buffer the packet flow in case some packets arrive out of order. Old samples are forwarded to secondary re-order administrations associated with readers in need of historical data.

    " }, - { LEAF("SecondaryReorderMaxSamples"), 1, "16", ABSOFF(secondary_reorder_maxsamples), 0, uf_uint, 0, pf_uint, - "

    This element sets the maximum size in samples of a secondary re-order administration. The secondary re-order administration is per reader in need of historical data.

    " }, - { LEAF("DefragUnreliableMaxSamples"), 1, "4", ABSOFF(defrag_unreliable_maxsamples), 0, uf_uint, 0, pf_uint, - "

    This element sets the maximum number of samples that can be defragmented simultaneously for a best-effort writers.

    " }, - { LEAF("DefragReliableMaxSamples"), 1, "16", ABSOFF(defrag_reliable_maxsamples), 0, uf_uint, 0, pf_uint, - "

    This element sets the maximum number of samples that can be defragmented simultaneously for a reliable writer. This has to be large enough to handle retransmissions of historical data in addition to new samples.

    " }, - { LEAF("BuiltinEndpointSet"), 1, "writers", ABSOFF(besmode), 0, uf_besmode, 0, pf_besmode, - "

    This element controls which participants will have which built-in endpoints for the discovery and liveliness protocols. Valid values are:

    \n\ + { MOVED("MaxMessageSize", "General/MaxMessageSize") }, + { MOVED("FragmentSize", "General/FragmentSize") }, + { LEAF("DeliveryQueueMaxSamples"), 1, "256", ABSOFF(delivery_queue_maxsamples), 0, uf_uint, 0, pf_uint, + BLURB("

    This element controls the Maximum size of a delivery queue, expressed in samples. Once a delivery queue is full, incoming samples destined for that queue are dropped until space becomes available again.

    ") }, + { LEAF("PrimaryReorderMaxSamples"), 1, "64", ABSOFF(primary_reorder_maxsamples), 0, uf_uint, 0, pf_uint, + BLURB("

    This element sets the maximum size in samples of a primary re-order administration. Each proxy writer has one primary re-order administration to buffer the packet flow in case some packets arrive out of order. Old samples are forwarded to secondary re-order administrations associated with readers in need of historical data.

    ") }, + { LEAF("SecondaryReorderMaxSamples"), 1, "16", ABSOFF(secondary_reorder_maxsamples), 0, uf_uint, 0, pf_uint, + BLURB("

    This element sets the maximum size in samples of a secondary re-order administration. The secondary re-order administration is per reader in need of historical data.

    ") }, + { LEAF("DefragUnreliableMaxSamples"), 1, "4", ABSOFF(defrag_unreliable_maxsamples), 0, uf_uint, 0, pf_uint, + BLURB("

    This element sets the maximum number of samples that can be defragmented simultaneously for a best-effort writers.

    ") }, + { LEAF("DefragReliableMaxSamples"), 1, "16", ABSOFF(defrag_reliable_maxsamples), 0, uf_uint, 0, pf_uint, + BLURB("

    This element sets the maximum number of samples that can be defragmented simultaneously for a reliable writer. This has to be large enough to handle retransmissions of historical data in addition to new samples.

    ") }, + { LEAF("BuiltinEndpointSet"), 1, "writers", ABSOFF(besmode), 0, uf_besmode, 0, pf_besmode, + BLURB("

    This element controls which participants will have which built-in endpoints for the discovery and liveliness protocols. Valid values are:

    \n\
    • full: all participants have all endpoints;
    • \n\
    • writers: all participants have the writers, but just one has the readers;
    • \n\
    • minimal: only one participant has built-in endpoints.
    \n\ -

    The default is writers, as this is thought to be compliant and reasonably efficient. Minimal may or may not be compliant but is most efficient, and full is inefficient but certain to be compliant. See also Internal/ConservativeBuiltinReaderStartup.

    " }, -{ LEAF("AggressiveKeepLastWhc|AggressiveKeepLast1Whc"), 1, "true", ABSOFF(aggressive_keep_last_whc), 0, uf_boolean, 0, pf_boolean, -"

    This element controls whether to drop a reliable sample from a DDSI2E WHC before all readers have acknowledged it as soon as a later sample becomes available. It only affects DCPS data writers with a history QoS setting of KEEP_LAST with depth 1. The default setting, false, mimics the behaviour of the OpenSplice RT networking and is necessary to make the behaviour of wait_for_acknowledgements() consistent across the networking services.

    " }, -{ LEAF("ConservativeBuiltinReaderStartup"), 1, "false", ABSOFF(conservative_builtin_reader_startup), 0, uf_boolean, 0, pf_boolean, -"

    This element forces all DDSI2E built-in discovery-related readers to request all historical data, instead of just one for each \"topic\". There is no indication that any of the current DDSI implementations requires changing of this setting, but it is conceivable that an implementation might track which participants have been informed of the existence of endpoints and which have not been, refusing communication with those that have \"can't\" know.

    \n\ -

    Should it be necessary to hide DDSI2E's shared discovery behaviour, set this to true and Internal/BuiltinEndpointSet to full.

    " }, -{ LEAF("MeasureHbToAckLatency"), 1, "false", ABSOFF(meas_hb_to_ack_latency), 0, uf_boolean, 0, pf_boolean, -"

    This element enables heartbeat-to-ack latency among DDSI2E services by prepending timestamps to Heartbeat and AckNack messages and calculating round trip times. This is non-standard behaviour. The measured latencies are quite noisy and are currently not used anywhere.

    " }, -{ LEAF("SuppressSPDPMulticast"), 1, "false", ABSOFF(suppress_spdp_multicast), 0, uf_boolean, 0, pf_boolean, -"

    The element controls whether the mandatory multicasting of the participant discovery packets occurs. Completely disabling multicasting requires this element be set to true, and generally requires explicitly listing peers to ping for unicast discovery.

    \n\ -

    See also General/AllowMulticast.

    " }, -{ LEAF("UnicastResponseToSPDPMessages"), 1, "true", ABSOFF(unicast_response_to_spdp_messages), 0, uf_boolean, 0, pf_boolean, -"

    This element controls whether the response to a newly discovered participant is sent as a unicasted SPDP packet, instead of rescheduling the periodic multicasted one. There is no known benefit to setting this to false.

    " }, -{ LEAF("SynchronousDeliveryPriorityThreshold"), 1, "0", ABSOFF(synchronous_delivery_priority_threshold), 0, uf_int, 0, pf_int, -"

    This element controls whether samples sent by a writer with QoS settings latency_budget <= SynchronousDeliveryLatencyBound and transport_priority greater than or equal to this element's value will be delivered synchronously from the \"recv\" thread, all others will be delivered asynchronously through delivery queues. This reduces latency at the expense of aggregate bandwidth.

    " }, -{ LEAF("SynchronousDeliveryLatencyBound"), 1, "inf", ABSOFF(synchronous_delivery_latency_bound), 0, uf_duration_inf, 0, pf_duration, -"

    This element controls whether samples sent by a writer with QoS settings transport_priority >= SynchronousDeliveryPriorityThreshold and a latency_budget at most this element's value will be delivered synchronously from the \"recv\" thread, all others will be delivered asynchronously through delivery queues. This reduces latency at the expense of aggregate bandwidth.

    " }, -{ LEAF("MaxParticipants"), 1, "0", ABSOFF(max_participants), 0, uf_natint, 0, pf_int, -"

    This elements configures the maximum number of DCPS domain participants this DDSI2E instance is willing to service. 0 is unlimited.

    " }, -{ LEAF("AccelerateRexmitBlockSize"), 1, "0", ABSOFF(accelerate_rexmit_block_size), 0, uf_uint, 0, pf_uint, -"

    Proxy readers that are assumed to sill be retrieving historical data get this many samples retransmitted when they NACK something, even if some of these samples have sequence numbers outside the set covered by the NACK.

    " }, -{ LEAF("RetransmitMerging"), 1, "adaptive", ABSOFF(retransmit_merging), 0, uf_retransmit_merging, 0, pf_retransmit_merging, -"

    This elements controls the addressing and timing of retransmits. Possible values are:

    \n\ +

    The default is writers, as this is thought to be compliant and reasonably efficient. Minimal may or may not be compliant but is most efficient, and full is inefficient but certain to be compliant. See also Internal/ConservativeBuiltinReaderStartup.

    ") }, + { LEAF("ConservativeBuiltinReaderStartup"), 1, "false", ABSOFF(conservative_builtin_reader_startup), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element forces all DDSI2E built-in discovery-related readers to request all historical data, instead of just one for each \"topic\". There is no indication that any of the current DDSI implementations requires changing of this setting, but it is conceivable that an implementation might track which participants have been informed of the existence of endpoints and which have not been, refusing communication with those that have \"can't\" know.

    \n\ +

    Should it be necessary to hide DDSI2E's shared discovery behaviour, set this to true and Internal/BuiltinEndpointSet to full.

    ") }, + { LEAF("MeasureHbToAckLatency"), 1, "false", ABSOFF(meas_hb_to_ack_latency), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element enables heartbeat-to-ack latency among DDSI2E services by prepending timestamps to Heartbeat and AckNack messages and calculating round trip times. This is non-standard behaviour. The measured latencies are quite noisy and are currently not used anywhere.

    ") }, + { LEAF("SuppressSPDPMulticast"), 1, "false", ABSOFF(suppress_spdp_multicast), 0, uf_boolean, 0, pf_boolean, + BLURB("

    The element controls whether the mandatory multicasting of the participant discovery packets occurs. Completely disabling multicasting requires this element be set to true, and generally requires explicitly listing peers to ping for unicast discovery.

    \n\ +

    See also General/AllowMulticast.

    ") }, + { LEAF("UnicastResponseToSPDPMessages"), 1, "true", ABSOFF(unicast_response_to_spdp_messages), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element controls whether the response to a newly discovered participant is sent as a unicasted SPDP packet, instead of rescheduling the periodic multicasted one. There is no known benefit to setting this to false.

    ") }, + { LEAF("SynchronousDeliveryPriorityThreshold"), 1, "0", ABSOFF(synchronous_delivery_priority_threshold), 0, uf_int, 0, pf_int, + BLURB("

    This element controls whether samples sent by a writer with QoS settings latency_budget <= SynchronousDeliveryLatencyBound and transport_priority greater than or equal to this element's value will be delivered synchronously from the \"recv\" thread, all others will be delivered asynchronously through delivery queues. This reduces latency at the expense of aggregate bandwidth.

    ") }, + { LEAF("SynchronousDeliveryLatencyBound"), 1, "inf", ABSOFF(synchronous_delivery_latency_bound), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This element controls whether samples sent by a writer with QoS settings transport_priority >= SynchronousDeliveryPriorityThreshold and a latency_budget at most this element's value will be delivered synchronously from the \"recv\" thread, all others will be delivered asynchronously through delivery queues. This reduces latency at the expense of aggregate bandwidth.

    ") }, + { LEAF("MaxParticipants"), 1, "0", ABSOFF(max_participants), 0, uf_natint, 0, pf_int, + BLURB("

    This elements configures the maximum number of DCPS domain participants this DDSI2E instance is willing to service. 0 is unlimited.

    ") }, + { LEAF("AccelerateRexmitBlockSize"), 1, "0", ABSOFF(accelerate_rexmit_block_size), 0, uf_uint, 0, pf_uint, + BLURB("

    Proxy readers that are assumed to sill be retrieving historical data get this many samples retransmitted when they NACK something, even if some of these samples have sequence numbers outside the set covered by the NACK.

    ") }, + { LEAF("RetransmitMerging"), 1, "adaptive", ABSOFF(retransmit_merging), 0, uf_retransmit_merging, 0, pf_retransmit_merging, + BLURB("

    This elements controls the addressing and timing of retransmits. Possible values are:

    \n\
    • never: retransmit only to the NACK-ing reader;
    • \n \
    • adaptive: attempt to combine retransmits needed for reliability, but send historical (transient-local) data to the requesting reader only;
    • \n\
    • always: do not distinguish between different causes, always try to merge.
    \n\ -

    The default is adaptive. See also Internal/RetransmitMergingPeriod.

    " }, -{ LEAF("RetransmitMergingPeriod"), 1, "5 ms", ABSOFF(retransmit_merging_period), 0, uf_duration_us_1s, 0, pf_duration, -"

    This setting determines the size of the time window in which a NACK of some sample is ignored because a retransmit of that sample has been multicasted too recently. This setting has no effect on unicasted retransmits.

    \n\ -

    See also Internal/RetransmitMerging.

    " }, -{ LEAF_W_ATTRS("HeartbeatInterval", heartbeat_interval_attrs), 1, "100 ms", ABSOFF(const_hb_intv_sched), 0, uf_duration_inf, 0, pf_duration, - "

    This elemnents allows configuring the base interval for sending writer heartbeats and the bounds within it can vary.

    " }, -{ LEAF("MaxQueuedRexmitBytes"), 1, "50 kB", ABSOFF(max_queued_rexmit_bytes), 0, uf_memsize, 0, pf_memsize, -"

    This setting limits the maximum number of bytes queued for retransmission. The default value of 0 is unlimited unless an AuxiliaryBandwidthLimit has been set, in which case it becomes NackDelay * AuxiliaryBandwidthLimit. It must be large enough to contain the largest sample that may need to be retransmitted.

    " }, -{ LEAF("MaxQueuedRexmitMessages"), 1, "200", ABSOFF(max_queued_rexmit_msgs), 0, uf_uint, 0, pf_uint, -"

    This settings limits the maximum number of samples queued for retransmission.

    " }, -{ LEAF("LeaseDuration"), 1, "10 s", ABSOFF(lease_duration), 0, uf_duration_ms_1hr, 0, pf_duration, -"

    This setting controls the default participant lease duration.

    " }, -{ LEAF("WriterLingerDuration"), 1, "1 s", ABSOFF(writer_linger_duration), 0, uf_duration_ms_1hr, 0, pf_duration, -"

    This setting controls the maximum duration for which actual deletion of a reliable writer with unacknowledged data in its history will be postponed to provide proper reliable transmission.

    " }, -{ LEAF("MinimumSocketReceiveBufferSize"), 1, "default", ABSOFF(socket_min_rcvbuf_size), 0, uf_maybe_memsize, 0, pf_maybe_memsize, -"

    This setting controls the minimum size of socket receive buffers. The operating system provides some size receive buffer upon creation of the socket, this option can be used to increase the size of the buffer beyond that initially provided by the operating system. If the buffer size cannot be increased to the specified size, an error is reported.

    \n\ -

    The default setting is the word \"default\", which means DDSI2E will attempt to increase the buffer size to 1MB, but will silently accept a smaller buffer should that attempt fail.

    " }, -{ LEAF("MinimumSocketSendBufferSize"), 1, "64 KiB", ABSOFF(socket_min_sndbuf_size), 0, uf_memsize, 0, pf_memsize, -"

    This setting controls the minimum size of socket send buffers. This setting can only increase the size of the send buffer, if the operating system by default creates a larger buffer, it is left unchanged.

    " }, -{ LEAF("NackDelay"), 1, "10 ms", ABSOFF(nack_delay), 0, uf_duration_ms_1hr, 0, pf_duration, -"

    This setting controls the delay between receipt of a HEARTBEAT indicating missing samples and a NACK (ignored when the HEARTBEAT requires an answer). However, no NACK is sent if a NACK had been scheduled already for a response earlier than the delay requests: then that NACK will incorporate the latest information.

    " }, -{ LEAF("AutoReschedNackDelay"), 1, "1 s", ABSOFF(auto_resched_nack_delay), 0, uf_duration_inf, 0, pf_duration, -"

    This setting controls the interval with which a reader will continue NACK'ing missing samples in the absence of a response from the writer, as a protection mechanism against writers incorrectly stopping the sending of HEARTBEAT messages.

    " }, -{ LEAF("PreEmptiveAckDelay"), 1, "10 ms", ABSOFF(preemptive_ack_delay), 0, uf_duration_ms_1hr, 0, pf_duration, -"

    This setting controls the delay between the discovering a remote writer and sending a pre-emptive AckNack to discover the range of data available.

    " }, -{ LEAF("ScheduleTimeRounding"), 1, "0 ms", ABSOFF(schedule_time_rounding), 0, uf_duration_ms_1hr, 0, pf_duration, -"

    This setting allows the timing of scheduled events to be rounded up so that more events can be handled in a single cycle of the event queue. The default is 0 and causes no rounding at all, i.e. are scheduled exactly, whereas a value of 10ms would mean that events are rounded up to the nearest 10 milliseconds.

    " }, +

    The default is adaptive. See also Internal/RetransmitMergingPeriod.

    ") }, + { LEAF("RetransmitMergingPeriod"), 1, "5 ms", ABSOFF(retransmit_merging_period), 0, uf_duration_us_1s, 0, pf_duration, + BLURB("

    This setting determines the size of the time window in which a NACK of some sample is ignored because a retransmit of that sample has been multicasted too recently. This setting has no effect on unicasted retransmits.

    \n\ +

    See also Internal/RetransmitMerging.

    ") }, + { LEAF_W_ATTRS("HeartbeatInterval", heartbeat_interval_attrs), 1, "100 ms", ABSOFF(const_hb_intv_sched), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This elemnents allows configuring the base interval for sending writer heartbeats and the bounds within it can vary.

    ") }, + { LEAF("MaxQueuedRexmitBytes"), 1, "50 kB", ABSOFF(max_queued_rexmit_bytes), 0, uf_memsize, 0, pf_memsize, + BLURB("

    This setting limits the maximum number of bytes queued for retransmission. The default value of 0 is unlimited unless an AuxiliaryBandwidthLimit has been set, in which case it becomes NackDelay * AuxiliaryBandwidthLimit. It must be large enough to contain the largest sample that may need to be retransmitted.

    ") }, + { LEAF("MaxQueuedRexmitMessages"), 1, "200", ABSOFF(max_queued_rexmit_msgs), 0, uf_uint, 0, pf_uint, + BLURB("

    This settings limits the maximum number of samples queued for retransmission.

    ") }, + { LEAF("LeaseDuration"), 1, "10 s", ABSOFF(lease_duration), 0, uf_duration_ms_1hr, 0, pf_duration, + BLURB("

    This setting controls the default participant lease duration.

    ") }, + { LEAF("WriterLingerDuration"), 1, "1 s", ABSOFF(writer_linger_duration), 0, uf_duration_ms_1hr, 0, pf_duration, + BLURB("

    This setting controls the maximum duration for which actual deletion of a reliable writer with unacknowledged data in its history will be postponed to provide proper reliable transmission.

    ") }, + { LEAF("MinimumSocketReceiveBufferSize"), 1, "default", ABSOFF(socket_min_rcvbuf_size), 0, uf_maybe_memsize, 0, pf_maybe_memsize, + BLURB("

    This setting controls the minimum size of socket receive buffers. The operating system provides some size receive buffer upon creation of the socket, this option can be used to increase the size of the buffer beyond that initially provided by the operating system. If the buffer size cannot be increased to the specified size, an error is reported.

    \n\ +

    The default setting is the word \"default\", which means DDSI2E will attempt to increase the buffer size to 1MB, but will silently accept a smaller buffer should that attempt fail.

    ") }, + { LEAF("MinimumSocketSendBufferSize"), 1, "64 KiB", ABSOFF(socket_min_sndbuf_size), 0, uf_memsize, 0, pf_memsize, + BLURB("

    This setting controls the minimum size of socket send buffers. This setting can only increase the size of the send buffer, if the operating system by default creates a larger buffer, it is left unchanged.

    ") }, + { LEAF("NackDelay"), 1, "10 ms", ABSOFF(nack_delay), 0, uf_duration_ms_1hr, 0, pf_duration, + BLURB("

    This setting controls the delay between receipt of a HEARTBEAT indicating missing samples and a NACK (ignored when the HEARTBEAT requires an answer). However, no NACK is sent if a NACK had been scheduled already for a response earlier than the delay requests: then that NACK will incorporate the latest information.

    ") }, + { LEAF("AutoReschedNackDelay"), 1, "1 s", ABSOFF(auto_resched_nack_delay), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This setting controls the interval with which a reader will continue NACK'ing missing samples in the absence of a response from the writer, as a protection mechanism against writers incorrectly stopping the sending of HEARTBEAT messages.

    ") }, + { LEAF("PreEmptiveAckDelay"), 1, "10 ms", ABSOFF(preemptive_ack_delay), 0, uf_duration_ms_1hr, 0, pf_duration, + BLURB("

    This setting controls the delay between the discovering a remote writer and sending a pre-emptive AckNack to discover the range of data available.

    ") }, + { LEAF("ScheduleTimeRounding"), 1, "0 ms", ABSOFF(schedule_time_rounding), 0, uf_duration_ms_1hr, 0, pf_duration, + BLURB("

    This setting allows the timing of scheduled events to be rounded up so that more events can be handled in a single cycle of the event queue. The default is 0 and causes no rounding at all, i.e. are scheduled exactly, whereas a value of 10ms would mean that events are rounded up to the nearest 10 milliseconds.

    ") }, #ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING -{ LEAF("AuxiliaryBandwidthLimit"), 1, "inf", ABSOFF(auxiliary_bandwidth_limit), 0, uf_bandwidth, 0, pf_bandwidth, -"

    This element specifies the maximum transmit rate of auxiliary traffic not bound to a specific channel, such as discovery traffic, as well as auxiliary traffic related to a certain channel if that channel has elected to share this global AuxiliaryBandwidthLimit. Bandwidth limiting uses a leaky bucket scheme. The default value \"inf\" means DDSI2E imposes no limitation, the underlying operating system and hardware will likely limit the maimum transmit rate.

    " }, + { LEAF("AuxiliaryBandwidthLimit"), 1, "inf", ABSOFF(auxiliary_bandwidth_limit), 0, uf_bandwidth, 0, pf_bandwidth, + BLURB("

    This element specifies the maximum transmit rate of auxiliary traffic not bound to a specific channel, such as discovery traffic, as well as auxiliary traffic related to a certain channel if that channel has elected to share this global AuxiliaryBandwidthLimit. Bandwidth limiting uses a leaky bucket scheme. The default value \"inf\" means DDSI2E imposes no limitation, the underlying operating system and hardware will likely limit the maimum transmit rate.

    ") }, #endif -{ LEAF("DDSI2DirectMaxThreads"), 1, "1", ABSOFF(ddsi2direct_max_threads), 0, uf_uint, 0, pf_uint, -"

    This element sets the maximum number of extra threads for an experimental, undocumented and unsupported direct mode.

    " }, -{ LEAF("SquashParticipants"), 1, "false", ABSOFF(squash_participants), 0, uf_boolean, 0, pf_boolean, -"

    This element controls whether DDSI2E advertises all the domain participants it serves in DDSI (when set to false), or rather only one domain participant (the one corresponding to the DDSI2E process; when set to true). In the latter case DDSI2E becomes the virtual owner of all readers and writers of all domain participants, dramatically reducing discovery traffic (a similar effect can be obtained by setting Internal/BuiltinEndpointSet to \"minimal\" but with less loss of information).

    " }, -{ LEAF("LegacyFragmentation"), 1, "false", ABSOFF(buggy_datafrag_flags_mode), 0, uf_boolean, 0, pf_boolean, -"

    This option enables a backwards-compatible, non-compliant setting and interpretation of the control flags in fragmented data messages. To be enabled only when requiring interoperability between compliant and non-compliant versions of DDSI2E for large messages.

    " }, -{ LEAF("SPDPResponseMaxDelay"), 1, "0 ms", ABSOFF(spdp_response_delay_max), 0, uf_duration_ms_1s, 0, pf_duration, -"

    Maximum pseudo-random delay in milliseconds between discovering a remote participant and responding to it.

    " }, -{ LEAF("LateAckMode"), 1, "false", ABSOFF(late_ack_mode), 0, uf_boolean, 0, pf_boolean, -"

    Ack a sample only when it has been delivered, instead of when committed to delivering it.

    " }, -{ LEAF("ForwardAllMessages"), 1, "false", ABSOFF(forward_all_messages), 0, uf_boolean, 0, pf_boolean, -"

    Forward all messages from a writer, rather than trying to forward each sample only once. The default of trying to forward each sample only once filters out duplicates for writers in multiple partitions under nearly all circumstances, but may still publish the odd duplicate. Note: the current implementation also can lose in contrived test cases, that publish more than 2**32 samples using a single data writer in conjunction with carefully controlled management of the writer history via cooperating local readers.

    " }, -{ LEAF("RetryOnRejectBestEffort"), 1, "false", ABSOFF(retry_on_reject_besteffort), 0, uf_boolean, 0, pf_boolean, -"

    Whether or not to locally retry pushing a received best-effort sample into the reader caches when resource limits are reached.

    " }, -{ LEAF("GenerateKeyhash"), 1, "false", ABSOFF(generate_keyhash), 0, uf_boolean, 0, pf_boolean, -"

    When true, include keyhashes in outgoing data for topics with keys.

    " }, -{ LEAF("MaxSampleSize"), 1, "2147483647 B", ABSOFF(max_sample_size), 0, uf_memsize, 0, pf_memsize, -"

    This setting controls the maximum (CDR) serialised size of samples that DDSI2E will forward in either direction. Samples larger than this are discarded with a warning.

    " }, -{ LEAF("WriteBatch"), 1, "false", ABSOFF(whc_batch), 0, uf_boolean, 0, pf_boolean, -"

    This element enables the batching of write operations. By default each write operation writes through the write cache and out onto the transport. Enabling write batching causes multiple small write operations to be aggregated within the write cache into a single larger write. This gives greater throughput at the expense of latency. Currently there is no mechanism for the write cache to automatically flush itself, so that if write batching is enabled, the application may havee to use the dds_write_flush function to ensure thta all samples are written.

    " }, -{ LEAF_W_ATTRS("LivelinessMonitoring", liveliness_monitoring_attrs), 1, "false", ABSOFF(liveliness_monitoring), 0, uf_boolean, 0, pf_boolean, -"

    This element controls whether or not implementation should internally monitor its own liveliness. If liveliness monitoring is enabled, stack traces can be dumped automatically when some thread appears to have stopped making progress.

    " }, -{ LEAF("MonitorPort"), 1, "-1", ABSOFF(monitor_port), 0, uf_int, 0, pf_int, -"

    This element allows configuring a service that dumps a text description of part the internal state to TCP clients. By default (-1), this is disabled; specifying 0 means a kernel-allocated port is used; a positive number is used as the TCP port number.

    " }, -{ LEAF("AssumeMulticastCapable"), 1, "", ABSOFF(assumeMulticastCapable), 0, uf_string, ff_free, pf_string, -"

    This element controls which network interfaces are assumed to be capable of multicasting even when the interface flags returned by the operating system state it is not (this provides a workaround for some platforms). It is a comma-separated lists of patterns (with ? and * wildcards) against which the interface names are matched.

    " }, -{ LEAF("PrioritizeRetransmit"), 1, "true", ABSOFF(prioritize_retransmit), 0, uf_boolean, 0, pf_boolean, -"

    This element controls whether retransmits are prioritized over new data, speeding up recovery.

    " }, -{ LEAF("UseMulticastIfMreqn"), 1, "0", ABSOFF(use_multicast_if_mreqn), 0, uf_int, 0, pf_int, -"

    Do not use.

    " }, -{ LEAF("SendAsync"), 1, "false", ABSOFF(xpack_send_async), 0, uf_boolean, 0, pf_boolean, -"

    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, -"

    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("DDSI2DirectMaxThreads"), 1, "1", ABSOFF(ddsi2direct_max_threads), 0, uf_uint, 0, pf_uint, + BLURB("

    This element sets the maximum number of extra threads for an experimental, undocumented and unsupported direct mode.

    ") }, + { LEAF("SquashParticipants"), 1, "false", ABSOFF(squash_participants), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element controls whether DDSI2E advertises all the domain participants it serves in DDSI (when set to false), or rather only one domain participant (the one corresponding to the DDSI2E process; when set to true). In the latter case DDSI2E becomes the virtual owner of all readers and writers of all domain participants, dramatically reducing discovery traffic (a similar effect can be obtained by setting Internal/BuiltinEndpointSet to \"minimal\" but with less loss of information).

    ") }, + { LEAF("SPDPResponseMaxDelay"), 1, "0 ms", ABSOFF(spdp_response_delay_max), 0, uf_duration_ms_1s, 0, pf_duration, + BLURB("

    Maximum pseudo-random delay in milliseconds between discovering a remote participant and responding to it.

    ") }, + { LEAF("LateAckMode"), 1, "false", ABSOFF(late_ack_mode), 0, uf_boolean, 0, pf_boolean, + BLURB("

    Ack a sample only when it has been delivered, instead of when committed to delivering it.

    ") }, + { LEAF("RetryOnRejectBestEffort"), 1, "false", ABSOFF(retry_on_reject_besteffort), 0, uf_boolean, 0, pf_boolean, + BLURB("

    Whether or not to locally retry pushing a received best-effort sample into the reader caches when resource limits are reached.

    ") }, + { LEAF("GenerateKeyhash"), 1, "false", ABSOFF(generate_keyhash), 0, uf_boolean, 0, pf_boolean, + BLURB("

    When true, include keyhashes in outgoing data for topics with keys.

    ") }, + { LEAF("MaxSampleSize"), 1, "2147483647 B", ABSOFF(max_sample_size), 0, uf_memsize, 0, pf_memsize, + BLURB("

    This setting controls the maximum (CDR) serialised size of samples that DDSI2E will forward in either direction. Samples larger than this are discarded with a warning.

    ") }, + { LEAF("WriteBatch"), 1, "false", ABSOFF(whc_batch), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element enables the batching of write operations. By default each write operation writes through the write cache and out onto the transport. Enabling write batching causes multiple small write operations to be aggregated within the write cache into a single larger write. This gives greater throughput at the expense of latency. Currently there is no mechanism for the write cache to automatically flush itself, so that if write batching is enabled, the application may havee to use the dds_write_flush function to ensure thta all samples are written.

    ") }, + { LEAF_W_ATTRS("LivelinessMonitoring", liveliness_monitoring_attrs), 1, "false", ABSOFF(liveliness_monitoring), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element controls whether or not implementation should internally monitor its own liveliness. If liveliness monitoring is enabled, stack traces can be dumped automatically when some thread appears to have stopped making progress.

    ") }, + { LEAF("MonitorPort"), 1, "-1", ABSOFF(monitor_port), 0, uf_int, 0, pf_int, + BLURB("

    This element allows configuring a service that dumps a text description of part the internal state to TCP clients. By default (-1), this is disabled; specifying 0 means a kernel-allocated port is used; a positive number is used as the TCP port number.

    ") }, + { LEAF("AssumeMulticastCapable"), 1, "", ABSOFF(assumeMulticastCapable), 0, uf_string, ff_free, pf_string, + BLURB("

    This element controls which network interfaces are assumed to be capable of multicasting even when the interface flags returned by the operating system state it is not (this provides a workaround for some platforms). It is a comma-separated lists of patterns (with ? and * wildcards) against which the interface names are matched.

    ") }, + { LEAF("PrioritizeRetransmit"), 1, "true", ABSOFF(prioritize_retransmit), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element controls whether retransmits are prioritized over new data, speeding up recovery.

    ") }, + { LEAF("UseMulticastIfMreqn"), 1, "0", ABSOFF(use_multicast_if_mreqn), 0, uf_int, 0, pf_int, + BLURB("

    Do not use.

    ") }, + { LEAF("SendAsync"), 1, "false", ABSOFF(xpack_send_async), 0, uf_boolean, 0, pf_boolean, + 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, - "

    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).

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

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

    " }, -{ GROUP("Test", unsupp_test_cfgelems), -"

    Testing options.

    " }, -{ GROUP("Watermarks", unsupp_watermarks_cfgelems), -"

    Watermarks for flow-control.

    " }, -{ LEAF("EnableExpensiveChecks"), 1, "", ABSOFF(enabled_xchecks), 0, uf_xcheck, 0, pf_xcheck, - "

    This element enables expensive checks in builds with assertions enabled and is ignored otherwise. Recognised categories are:

    \n\ + 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).

    ") }, + { 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), + BLURB("

    Testing options.

    ") }, + { GROUP("Watermarks", unsupp_watermarks_cfgelems), + BLURB("

    Watermarks for flow-control.

    ") }, + { LEAF("EnableExpensiveChecks"), 1, "", ABSOFF(enabled_xchecks), 0, uf_xcheck, 0, pf_xcheck, + BLURB("

    This element enables expensive checks in builds with assertions enabled and is ignored otherwise. Recognised categories are:

    \n\
    • whc: writer history cache checking
    • \n\
    • rhc: reader history cache checking
    • \n\ -

      In addition, there is the keyword all that enables all checks.

      " }, - -END_MARKER +

      In addition, there is the keyword all that enables all checks.

      ") }, + END_MARKER }; -static const struct cfgelem sizing_cfgelems[] = -{ - { LEAF("ReceiveBufferSize"), 1, "1 MiB", ABSOFF(rbuf_size), 0, uf_memsize, 0, pf_memsize, - "

      This element sets the size of a single receive buffer. Many receive buffers may be needed. The minimum workable size a little bit larger than Sizing/ReceiveBufferChunkSize, and the value used is taken as the configured value and the actual minimum workable size.

      " }, - { LEAF("ReceiveBufferChunkSize"), 1, "128 KiB", ABSOFF(rmsg_chunk_size), 0, uf_memsize, 0, pf_memsize, - "

      This element specifies the size of one allocation unit in the receive buffer. Must be greater than the maximum packet size by a modest amount (too large packets are dropped). Each allocation is shrunk immediately after processing a message, or freed straightaway.

      " }, - END_MARKER +static const struct cfgelem sizing_cfgelems[] = { + { LEAF("ReceiveBufferSize"), 1, "1 MiB", ABSOFF(rbuf_size), 0, uf_memsize, 0, pf_memsize, + BLURB("

      This element sets the size of a single receive buffer. Many receive buffers may be needed. The minimum workable size a little bit larger than Sizing/ReceiveBufferChunkSize, and the value used is taken as the configured value and the actual minimum workable size.

      ") }, + { LEAF("ReceiveBufferChunkSize"), 1, "128 KiB", ABSOFF(rmsg_chunk_size), 0, uf_memsize, 0, pf_memsize, + BLURB("

      This element specifies the size of one allocation unit in the receive buffer. Must be greater than the maximum packet size by a modest amount (too large packets are dropped). Each allocation is shrunk immediately after processing a message, or freed straightaway.

      ") }, + END_MARKER }; static const struct cfgelem discovery_ports_cfgelems[] = { - { LEAF("Base"), 1, "7400", ABSOFF(port_base), 0, uf_port, 0, pf_int, - "

      This element specifies the base port number (refer to the DDSI 2.1 specification, section 9.6.1, constant PB).

      " }, - { LEAF("DomainGain"), 1, "250", ABSOFF(port_dg), 0, uf_int, 0, pf_int, - "

      This element specifies the domain gain, relating domain ids to sets of port numbers (refer to the DDSI 2.1 specification, section 9.6.1, constant DG).

      " }, - { LEAF("ParticipantGain"), 1, "2", ABSOFF(port_pg), 0, uf_int, 0, pf_int, - "

      This element specifies the participant gain, relating p0, articipant index to sets of port numbers (refer to the DDSI 2.1 specification, section 9.6.1, constant PG).

      " }, - { LEAF("MulticastMetaOffset"), 1, "0", ABSOFF(port_d0), 0, uf_int, 0, pf_int, - "

      This element specifies the port number for multicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d0).

      " }, - { LEAF("UnicastMetaOffset"), 1, "10", ABSOFF(port_d1), 0, uf_int, 0, pf_int, - "

      This element specifies the port number for unicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d1).

      " }, - { LEAF("MulticastDataOffset"), 1, "1", ABSOFF(port_d2), 0, uf_int, 0, pf_int, - "

      This element specifies the port number for multicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d2).

      " }, - { LEAF("UnicastDataOffset"), 1, "11", ABSOFF(port_d3), 0, uf_int, 0, pf_int, - "

      This element specifies the port number for unicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d3).

      " }, - END_MARKER + { LEAF("Base"), 1, "7400", ABSOFF(port_base), 0, uf_port, 0, pf_int, + BLURB("

      This element specifies the base port number (refer to the DDSI 2.1 specification, section 9.6.1, constant PB).

      ") }, + { LEAF("DomainGain"), 1, "250", ABSOFF(port_dg), 0, uf_int, 0, pf_int, + BLURB("

      This element specifies the domain gain, relating domain ids to sets of port numbers (refer to the DDSI 2.1 specification, section 9.6.1, constant DG).

      ") }, + { LEAF("ParticipantGain"), 1, "2", ABSOFF(port_pg), 0, uf_int, 0, pf_int, + BLURB("

      This element specifies the participant gain, relating p0, articipant index to sets of port numbers (refer to the DDSI 2.1 specification, section 9.6.1, constant PG).

      ") }, + { LEAF("MulticastMetaOffset"), 1, "0", ABSOFF(port_d0), 0, uf_int, 0, pf_int, + BLURB("

      This element specifies the port number for multicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d0).

      ") }, + { LEAF("UnicastMetaOffset"), 1, "10", ABSOFF(port_d1), 0, uf_int, 0, pf_int, + BLURB("

      This element specifies the port number for unicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d1).

      ") }, + { LEAF("MulticastDataOffset"), 1, "1", ABSOFF(port_d2), 0, uf_int, 0, pf_int, + BLURB("

      This element specifies the port number for multicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d2).

      ") }, + { LEAF("UnicastDataOffset"), 1, "11", ABSOFF(port_d3), 0, uf_int, 0, pf_int, + BLURB("

      This element specifies the port number for unicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d3).

      ") }, + END_MARKER }; static const struct cfgelem tcp_cfgelems[] = { - { LEAF ("Enable"), 1, "default", ABSOFF (compat_tcp_enable), 0, uf_boolean_default, 0, pf_nop, - "

      This element enables the optional TCP transport - deprecated, use General/Transport instead.

      " }, - { LEAF("NoDelay"), 1, "true", ABSOFF(tcp_nodelay), 0, uf_boolean, 0, pf_boolean, - "

      This element enables the TCP_NODELAY socket option, preventing multiple DDSI messages being sent in the same TCP request. Setting this option typically optimises latency over throughput.

      " }, - { LEAF("Port"), 1, "-1", ABSOFF(tcp_port), 0, uf_dyn_port, 0, pf_int, - "

      This element specifies the TCP port number on which DDSI2E accepts connections. If the port is set it is used in entity locators, published with DDSI discovery. Dynamically allocated if zero. Disabled if -1 or not configured. If disabled other DDSI services will not be able to establish connections with the service, the service can only communicate by establishing connections to other services.

      " }, - { LEAF("ReadTimeout"), 1, "2 s", ABSOFF(tcp_read_timeout), 0, uf_duration_ms_1hr, 0, pf_duration, - "

      This element specifies the timeout for blocking TCP read operations. If this timeout expires then the connection is closed.

      " }, - { LEAF("WriteTimeout"), 1, "2 s", ABSOFF(tcp_write_timeout), 0, uf_duration_ms_1hr, 0, pf_duration, - "

      This element specifies the timeout for blocking TCP write operations. If this timeout expires then the connection is closed.

      " }, - { LEAF ("AlwaysUsePeeraddrForUnicast"), 1, "false", ABSOFF (tcp_use_peeraddr_for_unicast), 0, uf_boolean, 0, pf_boolean, - "

      Setting this to true means the unicast addresses in SPDP packets will be ignored and the peer address from the TCP connection will be used instead. This may help work around incorrectly advertised addresses when using TCP.

      " }, - END_MARKER + { LEAF ("Enable"), 1, "default", ABSOFF (compat_tcp_enable), 0, uf_boolean_default, 0, pf_nop, + BLURB("

      This element enables the optional TCP transport - deprecated, use General/Transport instead.

      ") }, + { LEAF("NoDelay"), 1, "true", ABSOFF(tcp_nodelay), 0, uf_boolean, 0, pf_boolean, + BLURB("

      This element enables the TCP_NODELAY socket option, preventing multiple DDSI messages being sent in the same TCP request. Setting this option typically optimises latency over throughput.

      ") }, + { LEAF("Port"), 1, "-1", ABSOFF(tcp_port), 0, uf_dyn_port, 0, pf_int, + BLURB("

      This element specifies the TCP port number on which DDSI2E accepts connections. If the port is set it is used in entity locators, published with DDSI discovery. Dynamically allocated if zero. Disabled if -1 or not configured. If disabled other DDSI services will not be able to establish connections with the service, the service can only communicate by establishing connections to other services.

      ") }, + { LEAF("ReadTimeout"), 1, "2 s", ABSOFF(tcp_read_timeout), 0, uf_duration_ms_1hr, 0, pf_duration, + BLURB("

      This element specifies the timeout for blocking TCP read operations. If this timeout expires then the connection is closed.

      ") }, + { LEAF("WriteTimeout"), 1, "2 s", ABSOFF(tcp_write_timeout), 0, uf_duration_ms_1hr, 0, pf_duration, + BLURB("

      This element specifies the timeout for blocking TCP write operations. If this timeout expires then the connection is closed.

      ") }, + { LEAF ("AlwaysUsePeeraddrForUnicast"), 1, "false", ABSOFF (tcp_use_peeraddr_for_unicast), 0, uf_boolean, 0, pf_boolean, + BLURB("

      Setting this to true means the unicast addresses in SPDP packets will be ignored and the peer address from the TCP connection will be used instead. This may help work around incorrectly advertised addresses when using TCP.

      ") }, + END_MARKER }; #ifdef DDSI_INCLUDE_SSL static const struct cfgelem ssl_cfgelems[] = { - { LEAF("Enable"), 1, "false", ABSOFF(ssl_enable), 0, uf_boolean, 0, pf_boolean, - "

      This enables SSL/TLS for TCP.

      " }, - { LEAF("CertificateVerification"), 1, "true", ABSOFF(ssl_verify), 0, uf_boolean, 0, pf_boolean, - "

      If disabled this allows SSL connections to occur even if an X509 certificate fails verification.

      " }, - { LEAF("VerifyClient"), 1, "true", ABSOFF(ssl_verify_client), 0, uf_boolean, 0, pf_boolean, - "

      This enables an SSL server checking the X509 certificate of a connecting client.

      " }, - { LEAF("SelfSignedCertificates"), 1, "false", ABSOFF(ssl_self_signed), 0, uf_boolean, 0, pf_boolean, - "

      This enables the use of self signed X509 certificates.

      " }, - { LEAF("KeystoreFile"), 1, "keystore", ABSOFF(ssl_keystore), 0, uf_string, ff_free, pf_string, - "

      The SSL/TLS key and certificate store file name. The keystore must be in PEM format.

      " }, - { LEAF("KeyPassphrase"), 1, "secret", ABSOFF(ssl_key_pass), 0, uf_string, ff_free, pf_string, - "

      The SSL/TLS key pass phrase for encrypted keys.

      " }, - { LEAF("Ciphers"), 1, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH", ABSOFF(ssl_ciphers), 0, uf_string, ff_free, pf_string, - "

      The set of ciphers used by SSL/TLS

      " }, - { LEAF("EntropyFile"), 1, "", ABSOFF(ssl_rand_file), 0, uf_string, ff_free, pf_string, - "

      The SSL/TLS random entropy file name.

      " }, - { LEAF("MinimumTLSVersion"), 1, "1.3", ABSOFF(ssl_min_version), 0, uf_min_tls_version, 0, pf_min_tls_version, - "

      The minimum TLS version that may be negotiated, valid values are 1.2 and 1.3.

      " }, - END_MARKER + { LEAF("Enable"), 1, "false", ABSOFF(ssl_enable), 0, uf_boolean, 0, pf_boolean, + BLURB("

      This enables SSL/TLS for TCP.

      ") }, + { LEAF("CertificateVerification"), 1, "true", ABSOFF(ssl_verify), 0, uf_boolean, 0, pf_boolean, + BLURB("

      If disabled this allows SSL connections to occur even if an X509 certificate fails verification.

      ") }, + { LEAF("VerifyClient"), 1, "true", ABSOFF(ssl_verify_client), 0, uf_boolean, 0, pf_boolean, + BLURB("

      This enables an SSL server checking the X509 certificate of a connecting client.

      ") }, + { LEAF("SelfSignedCertificates"), 1, "false", ABSOFF(ssl_self_signed), 0, uf_boolean, 0, pf_boolean, + BLURB("

      This enables the use of self signed X509 certificates.

      ") }, + { LEAF("KeystoreFile"), 1, "keystore", ABSOFF(ssl_keystore), 0, uf_string, ff_free, pf_string, + BLURB("

      The SSL/TLS key and certificate store file name. The keystore must be in PEM format.

      ") }, + { LEAF("KeyPassphrase"), 1, "secret", ABSOFF(ssl_key_pass), 0, uf_string, ff_free, pf_string, + BLURB("

      The SSL/TLS key pass phrase for encrypted keys.

      ") }, + { LEAF("Ciphers"), 1, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH", ABSOFF(ssl_ciphers), 0, uf_string, ff_free, pf_string, + BLURB("

      The set of ciphers used by SSL/TLS

      ") }, + { LEAF("EntropyFile"), 1, "", ABSOFF(ssl_rand_file), 0, uf_string, ff_free, pf_string, + BLURB("

      The SSL/TLS random entropy file name.

      ") }, + { LEAF("MinimumTLSVersion"), 1, "1.3", ABSOFF(ssl_min_version), 0, uf_min_tls_version, 0, pf_min_tls_version, + BLURB("

      The minimum TLS version that may be negotiated, valid values are 1.2 and 1.3.

      ") }, + END_MARKER }; #endif static const struct cfgelem tp_cfgelems[] = { - { LEAF("Enable"), 1, "false", ABSOFF(tp_enable), 0, uf_boolean, 0, pf_boolean, - "

      This element enables the optional thread pool.

      " }, - { LEAF("Threads"), 1, "4", ABSOFF(tp_threads), 0, uf_natint, 0, pf_int, - "

      This elements configures the initial number of threads in the thread pool.

      " }, - { LEAF("ThreadMax"), 1, "8", ABSOFF(tp_max_threads), 0, uf_natint, 0, pf_int, - "

      This elements configures the maximum number of threads in the thread pool.

      " }, - END_MARKER + { LEAF("Enable"), 1, "false", ABSOFF(tp_enable), 0, uf_boolean, 0, pf_boolean, + BLURB("

      This element enables the optional thread pool.

      ") }, + { LEAF("Threads"), 1, "4", ABSOFF(tp_threads), 0, uf_natint, 0, pf_int, + BLURB("

      This elements configures the initial number of threads in the thread pool.

      ") }, + { LEAF("ThreadMax"), 1, "8", ABSOFF(tp_max_threads), 0, uf_natint, 0, pf_int, + BLURB("

      This elements configures the maximum number of threads in the thread pool.

      ") }, + END_MARKER }; static const struct cfgelem discovery_peer_cfgattrs[] = { - { ATTR("Address"), 1, NULL, RELOFF(config_peer_listelem, peer), 0, uf_ipv4, ff_free, pf_string, - "

      This element specifies an IP address to which discovery packets must be sent, in addition to the default multicast address (see also General/AllowMulticast). Both a hostnames and a numerical IP address is accepted; the hostname or IP address may be suffixed with :PORT to explicitly set the port to which it must be sent. Multiple Peers may be specified.

      " }, - END_MARKER + { ATTR("Address"), 1, NULL, RELOFF(config_peer_listelem, peer), 0, uf_ipv4, ff_free, pf_string, + BLURB("

      This element specifies an IP address to which discovery packets must be sent, in addition to the default multicast address (see also General/AllowMulticast). Both a hostnames and a numerical IP address is accepted; the hostname or IP address may be suffixed with :PORT to explicitly set the port to which it must be sent. Multiple Peers may be specified.

      ") }, + END_MARKER }; static const struct cfgelem discovery_peers_group_cfgelems[] = { - { MGROUP("Peer", NULL, discovery_peer_cfgattrs), 0, NULL, ABSOFF(peers_group), if_peer, 0, 0, 0, - "

      This element statically configures an addresses for discovery.

      " }, - END_MARKER + { MGROUP("Peer", NULL, discovery_peer_cfgattrs), 0, NULL, ABSOFF(peers_group), if_peer, 0, 0, 0, + BLURB("

      This element statically configures an addresses for discovery.

      ") }, + END_MARKER }; static const struct cfgelem discovery_peers_cfgelems[] = { - { MGROUP("Peer", NULL, discovery_peer_cfgattrs), 0, NULL, ABSOFF(peers), if_peer, 0, 0, 0, - "

      This element statically configures an addresses for discovery.

      " }, - { GROUP("Group", discovery_peers_group_cfgelems), - "

      This element statically configures a fault tolerant group of addresses for discovery. Each member of the group is tried in sequence until one succeeds.

      " }, - END_MARKER + { MGROUP("Peer", NULL, discovery_peer_cfgattrs), 0, NULL, ABSOFF(peers), if_peer, 0, 0, 0, + BLURB("

      This element statically configures an addresses for discovery.

      ") }, + { GROUP("Group", discovery_peers_group_cfgelems), + BLURB("

      This element statically configures a fault tolerant group of addresses for discovery. Each member of the group is tried in sequence until one succeeds.

      ") }, + END_MARKER }; static const struct cfgelem discovery_cfgelems[] = { - { LEAF("AdvertiseBuiltinTopicWriters"), 1, "true", ABSOFF(advertise_builtin_topic_writers), 0, uf_boolean, 0, pf_boolean, - "

      This element controls whether or not DDSI2E advertises writers for the built-in topics from its discovery for backwards compatibility with older OpenSplice versions.

      " }, - { LEAF("DSGracePeriod"), 1, "30 s", ABSOFF(ds_grace_period), 0, uf_duration_inf, 0, pf_duration, - "

      This setting controls for how long endpoints discovered via a Cloud discovery service will survive after the discovery service disappeared, allowing reconnect without loss of data when the discovery service restarts (or another instance takes over).

      " }, - { GROUP("Peers", discovery_peers_cfgelems), - "

      This element statically configures addresses for discovery.

      " }, - { LEAF("ParticipantIndex"), 1, "none", ABSOFF(participantIndex), 0, uf_participantIndex, 0, pf_participantIndex, - "

      This element specifies the DDSI participant index used by this instance of the DDSI2E service for discovery purposes. Only one such participant id is used, independent of the number of actual DomainParticipants on the node. It is either:

      \n\ + { LEAF("DSGracePeriod"), 1, "30 s", ABSOFF(ds_grace_period), 0, uf_duration_inf, 0, pf_duration, + BLURB("

      This setting controls for how long endpoints discovered via a Cloud discovery service will survive after the discovery service disappeared, allowing reconnect without loss of data when the discovery service restarts (or another instance takes over).

      ") }, + { GROUP("Peers", discovery_peers_cfgelems), + BLURB("

      This element statically configures addresses for discovery.

      ") }, + { LEAF("ParticipantIndex"), 1, "none", ABSOFF(participantIndex), 0, uf_participantIndex, 0, pf_participantIndex, + BLURB("

      This element specifies the DDSI participant index used by this instance of the DDSI2E service for discovery purposes. Only one such participant id is used, independent of the number of actual DomainParticipants on the node. It is either:

      \n\
      • auto: which will attempt to automatically determine an available participant index (see also Discovery/MaxAutoParticipantIndex), or
      • \n \
      • a non-negative integer less than 120, or
      • \n\
      • none:, which causes it to use arbitrary port numbers for unicast sockets which entirely removes the constraints on the participant index but makes unicast discovery impossible.
      \n\ -

      The default is auto. The participant index is part of the port number calculation and if predictable port numbers are needed and fixing the participant index has no adverse effects, it is recommended that the second be option be used.

      " }, -{ LEAF("MaxAutoParticipantIndex"), 1, "9", ABSOFF(maxAutoParticipantIndex), 0, uf_natint, 0, pf_int, -"

      This element specifies the maximum DDSI participant index selected by this instance of the DDSI2E service if the Discovery/ParticipantIndex is \"auto\".

      " }, -{ LEAF("SPDPMulticastAddress"), 1, "239.255.0.1", ABSOFF(spdpMulticastAddressString), 0, uf_ipv4, ff_free, pf_string, -"

      This element specifies the multicast address that is used as the destination for the participant discovery packets. In IPv4 mode the default is the (standardised) 239.255.0.1, in IPv6 mode it becomes ff02::ffff:239.255.0.1, which is a non-standardised link-local multicast address.

      " }, -{ LEAF("SPDPInterval"), 1, "30 s", ABSOFF(spdp_interval), 0, uf_duration_ms_1hr, 0, pf_duration, -"

      This element specifies the interval between spontaneous transmissions of participant discovery packets.

      " }, -{ LEAF("DefaultMulticastAddress"), 1, "auto", ABSOFF(defaultMulticastAddressString), 0, uf_networkAddress, 0, pf_networkAddress, -"

      This element specifies the default multicast address for all traffic other than participant discovery packets. It defaults to Discovery/SPDPMulticastAddress.

      " }, -{ LEAF("EnableTopicDiscovery"), 1, "true", ABSOFF(do_topic_discovery), 0, uf_boolean, 0, pf_boolean, -"

      Do not use.

      " }, -{ GROUP("Ports", discovery_ports_cfgelems), -"

      The Ports element allows specifying various parameters related to the port numbers used for discovery. These all have default values specified by the DDSI 2.1 specification and rarely need to be changed.

      " }, -END_MARKER +

      The default is auto. The participant index is part of the port number calculation and if predictable port numbers are needed and fixing the participant index has no adverse effects, it is recommended that the second be option be used.

      ") }, + { LEAF("MaxAutoParticipantIndex"), 1, "9", ABSOFF(maxAutoParticipantIndex), 0, uf_natint, 0, pf_int, + BLURB("

      This element specifies the maximum DDSI participant index selected by this instance of the DDSI2E service if the Discovery/ParticipantIndex is \"auto\".

      ") }, + { LEAF("SPDPMulticastAddress"), 1, "239.255.0.1", ABSOFF(spdpMulticastAddressString), 0, uf_ipv4, ff_free, pf_string, + BLURB("

      This element specifies the multicast address that is used as the destination for the participant discovery packets. In IPv4 mode the default is the (standardised) 239.255.0.1, in IPv6 mode it becomes ff02::ffff:239.255.0.1, which is a non-standardised link-local multicast address.

      ") }, + { LEAF("SPDPInterval"), 1, "30 s", ABSOFF(spdp_interval), 0, uf_duration_ms_1hr, 0, pf_duration, + BLURB("

      This element specifies the interval between spontaneous transmissions of participant discovery packets.

      ") }, + { LEAF("DefaultMulticastAddress"), 1, "auto", ABSOFF(defaultMulticastAddressString), 0, uf_networkAddress, 0, pf_networkAddress, + BLURB("

      This element specifies the default multicast address for all traffic other than participant discovery packets. It defaults to Discovery/SPDPMulticastAddress.

      ") }, + { LEAF("EnableTopicDiscovery"), 1, "true", ABSOFF(do_topic_discovery), 0, uf_boolean, 0, pf_boolean, + BLURB("

      Do not use.

      ") }, + { GROUP("Ports", discovery_ports_cfgelems), + BLURB("

      The Ports element allows specifying various parameters related to the port numbers used for discovery. These all have default values specified by the DDSI 2.1 specification and rarely need to be changed.

      ") }, + END_MARKER }; static const struct cfgelem tracing_cfgelems[] = { - { LEAF("EnableCategory"), 1, "", 0, 0, 0, uf_logcat, 0, pf_logcat, - "

      This element enables individual logging categories. These are enabled in addition to those enabled by Tracing/Verbosity. Recognised categories are:

      \n\ + { LEAF("EnableCategory"), 1, "", 0, 0, 0, uf_logcat, 0, pf_logcat, + BLURB("

      This element enables individual logging categories. These are enabled in addition to those enabled by Tracing/Verbosity. Recognised categories are:

      \n\
      • fatal: all fatal errors, errors causing immediate termination
      • \n\
      • error: failures probably impacting correctness but not necessarily causing immediate termination
      • \n\
      • warning: abnormal situations that will likely not impact correctness
      • \n\ @@ -796,9 +766,9 @@ static const struct cfgelem tracing_cfgelems[] = {
      • topic: tracing of topic definitions
      • \n\
      • >i>plist: tracing of discovery parameter list interpretation
      \n\

      In addition, there is the keyword trace that enables all but radmin, topic, plist and whc

      .\n\ -

      The categorisation of tracing output is incomplete and hence most of the verbosity levels and categories are not of much use in the current release. This is an ongoing process and here we describe the target situation rather than the current situation. Currently, the most useful is trace.

      " }, -{ LEAF("Verbosity"), 1, "none", 0, 0, 0, uf_verbosity, 0, pf_nop, -"

      This element enables standard groups of categories, based on a desired verbosity level. This is in addition to the categories enabled by the Tracing/EnableCategory setting. Recognised verbosity levels and the categories they map to are:

      \n\ +

      The categorisation of tracing output is incomplete and hence most of the verbosity levels and categories are not of much use in the current release. This is an ongoing process and here we describe the target situation rather than the current situation. Currently, the most useful is trace.

      ") }, + { LEAF("Verbosity"), 1, "none", 0, 0, 0, uf_verbosity, 0, pf_nop, + BLURB("

      This element enables standard groups of categories, based on a desired verbosity level. This is in addition to the categories enabled by the Tracing/EnableCategory setting. Recognised verbosity levels and the categories they map to are:

      \n\
      • none: no DDSI2E log
      • \n\
      • severe: error and fatal
      • \n\
      • warning: severe + warning
      • \n\ @@ -808,112 +778,74 @@ static const struct cfgelem tracing_cfgelems[] = {
      • finer: fine + traffic and timing
      • \n\
      • finest: finer + trace
      \n\

      While none prevents any message from being written to a DDSI2 log file.

      \n\ -

      The categorisation of tracing output is incomplete and hence most of the verbosity levels and categories are not of much use in the current release. This is an ongoing process and here we describe the target situation rather than the current situation. Currently, the most useful verbosity levels are config, fine and finest.

      " }, -{ LEAF("OutputFile"), 1, DDS_PROJECT_NAME_NOSPACE_SMALL".log", ABSOFF(tracingOutputFileName), 0, uf_tracingOutputFileName, ff_free, pf_string, -"

      This option specifies where the logging is printed to. Note that stdout and stderr are treated as special values, representing \"standard out\" and \"standard error\" respectively. No file is created unless logging categories are enabled using the Tracing/Verbosity or Tracing/EnabledCategory settings.

      " }, -{ LEAF_W_ATTRS("Timestamps", timestamp_cfgattrs), 1, "true", ABSOFF(tracingTimestamps), 0, uf_boolean, 0, pf_boolean, -"

      This option has no effect.

      " }, -{ LEAF("AppendToFile"), 1, "false", ABSOFF(tracingAppendToFile), 0, uf_boolean, 0, pf_boolean, -"

      This option specifies whether the output is to be appended to an existing log file. The default is to create a new log file each time, which is generally the best option if a detailed log is generated.

      " }, -{ LEAF("PacketCaptureFile"), 1, "", ABSOFF(pcap_file), 0, uf_string, ff_free, pf_string, -"

      This option specifies the file to which received and sent packets will be logged in the \"pcap\" format suitable for analysis using common networking tools, such as WireShark. IP and UDP headers are ficitious, in particular the destination address of received packets. The TTL may be used to distinguish between sent and received packets: it is 255 for sent packets and 128 for received ones. Currently IPv4 only.

      " }, -END_MARKER -}; - -static const struct cfgelem sched_prio_cfgattrs[] = { - { ATTR("priority_kind"), 1, "relative", ABSOFF(watchdog_sched_priority_class), 0, uf_sched_prio_class, 0, pf_sched_prio_class, - "

      This attribute specifies whether the specified Priority is a relative or absolute priority.

      " }, - END_MARKER -}; - -static const struct cfgelem sched_cfgelems[] = { - { LEAF("Class"), 1, "default", ABSOFF(watchdog_sched_class), 0, uf_sched_class, 0, pf_sched_class, - "

      This element specifies the thread scheduling class that will be used by the watchdog thread. The user may need the appropriate privileges from the underlying operating system to be able to assign some of the privileged scheduling classes.

      " }, - { LEAF_W_ATTRS("Priority", sched_prio_cfgattrs), 1, "0", ABSOFF(watchdog_sched_priority), 0, uf_int32, 0, pf_int32, - "

      This element specifies the thread priority. Only priorities that are supported by the underlying operating system can be assigned to this element. The user may need special privileges from the underlying operating system to be able to assign some of the privileged priorities.

      " }, - END_MARKER -}; - -static const struct cfgelem watchdog_cfgelems[] = { - { GROUP("Scheduling", sched_cfgelems), - "

      This element specifies the type of OS scheduling class will be used by the thread that announces its liveliness periodically.

      " }, - END_MARKER +

      The categorisation of tracing output is incomplete and hence most of the verbosity levels and categories are not of much use in the current release. This is an ongoing process and here we describe the target situation rather than the current situation. Currently, the most useful verbosity levels are config, fine and finest.

      ") }, + { LEAF("OutputFile"), 1, DDS_PROJECT_NAME_NOSPACE_SMALL".log", ABSOFF(tracingOutputFileName), 0, uf_tracingOutputFileName, ff_free, pf_string, + BLURB("

      This option specifies where the logging is printed to. Note that stdout and stderr are treated as special values, representing \"standard out\" and \"standard error\" respectively. No file is created unless logging categories are enabled using the Tracing/Verbosity or Tracing/EnabledCategory settings.

      ") }, + { LEAF("AppendToFile"), 1, "false", ABSOFF(tracingAppendToFile), 0, uf_boolean, 0, pf_boolean, + BLURB("

      This option specifies whether the output is to be appended to an existing log file. The default is to create a new log file each time, which is generally the best option if a detailed log is generated.

      ") }, + { LEAF("PacketCaptureFile"), 1, "", ABSOFF(pcap_file), 0, uf_string, ff_free, pf_string, + BLURB("

      This option specifies the file to which received and sent packets will be logged in the \"pcap\" format suitable for analysis using common networking tools, such as WireShark. IP and UDP headers are ficitious, in particular the destination address of received packets. The TTL may be used to distinguish between sent and received packets: it is 255 for sent packets and 128 for received ones. Currently IPv4 only.

      ") }, + END_MARKER }; static const struct cfgelem ddsi2_cfgelems[] = { - { GROUP("General", general_cfgelems), - "

      The General element specifies overall DDSI2E service settings.

      " }, + { GROUP("General", general_cfgelems), + BLURB("

      The General element specifies overall DDSI2E service settings.

      ") }, #ifdef DDSI_INCLUDE_ENCRYPTION - { GROUP("Security", security_cfgelems), - "

      The Security element specifies DDSI2E security profiles that can be used to encrypt traffic mapped to DDSI2E network partitions.

      " }, + { GROUP("Security", security_cfgelems), + BLURB("

      The Security element specifies DDSI2E security profiles that can be used to encrypt traffic mapped to DDSI2E network partitions.

      ") }, #endif #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS - { GROUP("Partitioning", partitioning_cfgelems), - "

      The Partitioning element specifies DDSI2E network partitions and how DCPS partition/topic combinations are mapped onto the network partitions.

      " }, + { GROUP("Partitioning", partitioning_cfgelems), + BLURB("

      The Partitioning element specifies DDSI2E network partitions and how DCPS partition/topic combinations are mapped onto the network partitions.

      ") }, #endif #ifdef DDSI_INCLUDE_NETWORK_CHANNELS - { GROUP("Channels", channels_cfgelems), - "

      This element is used to group a set of channels. The channels are independent data paths through DDSI2E and by using separate threads and setting their priorities appropriately, chanenls can be used to map transport priorities to operating system scheduler priorities, ensuring system-wide end-to-end priority preservation.

      " }, + { GROUP("Channels", channels_cfgelems), + BLURB("

      This element is used to group a set of channels. The channels are independent data paths through DDSI2E and by using separate threads and setting their priorities appropriately, chanenls can be used to map transport priorities to operating system scheduler priorities, ensuring system-wide end-to-end priority preservation.

      ") }, #endif - { GROUP("Threads", threads_cfgelems), - "

      This element is used to set thread properties.

      " }, - { GROUP("Sizing", sizing_cfgelems), - "

      The Sizing element specifies a variety of configuration settings dealing with expected system sizes, buffer sizes, &c.

      " }, - { GROUP("Compatibility", compatibility_cfgelems), - "

      The Compatibility elements allows specifying various settings related to compatability with standards and with other DDSI implementations.

      " }, - { GROUP("Discovery", discovery_cfgelems), - "

      The Discovery element allows specifying various parameters related to the discovery of peers.

      " }, - { GROUP("Tracing", tracing_cfgelems), - "

      The Tracing element controls the amount and type of information that is written into the tracing log by the DDSI service. This is useful to track the DDSI service during application development.

      " }, - { GROUP("Internal|Unsupported", unsupp_cfgelems), - "

      The Internal elements deal with a variety of settings that evolving and that are not necessarily fully supported. For the vast majority of the Internal settings, the functionality per-se is supported, but the right to change the way the options control the functionality is reserved. This includes renaming or moving options.

      " }, - { GROUP("Watchdog", watchdog_cfgelems), - "

      This element specifies the type of OS scheduling class will be used by the thread that announces its liveliness periodically.

      " }, - { GROUP("TCP", tcp_cfgelems), - "

      The TCP element allows specifying various parameters related to running DDSI over TCP.

      " }, - { GROUP("ThreadPool", tp_cfgelems), - "

      The ThreadPool element allows specifying various parameters related to using a thread pool to send DDSI messages to multiple unicast addresses (TCP or UDP).

      " }, + { GROUP("Threads", threads_cfgelems), + BLURB("

      This element is used to set thread properties.

      ") }, + { GROUP("Sizing", sizing_cfgelems), + BLURB("

      The Sizing element specifies a variety of configuration settings dealing with expected system sizes, buffer sizes, &c.

      ") }, + { GROUP("Compatibility", compatibility_cfgelems), + BLURB("

      The Compatibility elements allows specifying various settings related to compatability with standards and with other DDSI implementations.

      ") }, + { GROUP("Discovery", discovery_cfgelems), + BLURB("

      The Discovery element allows specifying various parameters related to the discovery of peers.

      ") }, + { GROUP("Tracing", tracing_cfgelems), + BLURB("

      The Tracing element controls the amount and type of information that is written into the tracing log by the DDSI service. This is useful to track the DDSI service during application development.

      ") }, + { GROUP("Internal|Unsupported", unsupp_cfgelems), + BLURB("

      The Internal elements deal with a variety of settings that evolving and that are not necessarily fully supported. For the vast majority of the Internal settings, the functionality per-se is supported, but the right to change the way the options control the functionality is reserved. This includes renaming or moving options.

      ") }, + { GROUP("TCP", tcp_cfgelems), + BLURB("

      The TCP element allows specifying various parameters related to running DDSI over TCP.

      ") }, + { GROUP("ThreadPool", tp_cfgelems), + BLURB("

      The ThreadPool element allows specifying various parameters related to using a thread pool to send DDSI messages to multiple unicast addresses (TCP or UDP).

      ") }, #ifdef DDSI_INCLUDE_SSL - { GROUP("SSL", ssl_cfgelems), - "

      The SSL element allows specifying various parameters related to using SSL/TLS for DDSI over TCP.

      " }, + { GROUP("SSL", ssl_cfgelems), + BLURB("

      The SSL element allows specifying various parameters related to using SSL/TLS for DDSI over TCP.

      ") }, #endif - END_MARKER -}; - -static const struct cfgelem deprecated_lease_cfgelems[] = { - WILDCARD, END_MARKER }; static const struct cfgelem domain_cfgelems[] = { - { LEAF("Id"), 1, "any", ABSOFF(domainId), 0, uf_domainId, 0, pf_domainId, NULL }, - { GROUP("|Lease", deprecated_lease_cfgelems), NULL }, - END_MARKER -}; - -static const struct cfgelem durability_cfgelems[] = { - { LEAF("Encoding"), 1, "CDR_CLIENT", ABSOFF(durability_cdr), 0, uf_durability_cdr, 0, pf_durability_cdr, NULL }, - END_MARKER + { LEAF("Id"), 1, "any", ABSOFF(domainId), 0, uf_domainId, 0, pf_domainId, NULL }, + END_MARKER }; static const struct cfgelem root_cfgelems[] = { - { "Domain", domain_cfgelems, NULL, NODATA, NULL }, - { "DDSI2E|DDSI2", ddsi2_cfgelems, NULL, NODATA, - "

      DDSI2 settings ...

      " }, - { "Durability", durability_cfgelems, NULL, NODATA, NULL }, - { GROUP("|Lease", deprecated_lease_cfgelems), NULL }, - END_MARKER + { "Domain", domain_cfgelems, NULL, NODATA, NULL }, + { "DDSI2E|DDSI2", ddsi2_cfgelems, NULL, NODATA, + BLURB("

      DDSI2 settings ...

      ") }, + END_MARKER }; -static const struct cfgelem cyclonedds_root_cfgelems[] = -{ - { DDS_PROJECT_NAME_NOSPACE, root_cfgelems, NULL, NODATA, NULL }, - END_MARKER +static const struct cfgelem cyclonedds_root_cfgelems[] = { + { DDS_PROJECT_NAME_NOSPACE, root_cfgelems, NULL, NODATA, NULL }, + END_MARKER }; -static const struct cfgelem root_cfgelem = -{ "root", cyclonedds_root_cfgelems, NULL, NODATA, NULL }; - +static const struct cfgelem root_cfgelem = { + "root", cyclonedds_root_cfgelems, NULL, NODATA, NULL +}; #undef ATTR #undef GROUP @@ -930,401 +862,390 @@ struct config config; struct ddsi_plugin ddsi_plugin; static const struct unit unittab_duration[] = { - { "ns", 1 }, - { "us", 1000 }, - { "ms", T_MILLISECOND }, - { "s", T_SECOND }, - { "min", 60 * T_SECOND }, - { "hr", 3600 * T_SECOND }, - { "day", 24 * 3600 * T_SECOND }, - { NULL, 0 } + { "ns", 1 }, + { "us", 1000 }, + { "ms", T_MILLISECOND }, + { "s", T_SECOND }, + { "min", 60 * T_SECOND }, + { "hr", 3600 * T_SECOND }, + { "day", 24 * 3600 * T_SECOND }, + { NULL, 0 } }; /* note: order affects whether printed as KiB or kB, for consistency -with bandwidths and pedanticness, favour KiB. */ + with bandwidths and pedanticness, favour KiB. */ static const struct unit unittab_memsize[] = { - { "B", 1 }, - { "KiB", 1024 }, - { "kB", 1024 }, - { "MiB", 1048576 }, - { "MB", 1048576 }, - { "GiB", 1073741824 }, - { "GB", 1073741824 }, - { NULL, 0 } + { "B", 1 }, + { "KiB", 1024 }, + { "kB", 1024 }, + { "MiB", 1048576 }, + { "MB", 1048576 }, + { "GiB", 1073741824 }, + { "GB", 1073741824 }, + { NULL, 0 } }; #ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING static const struct unit unittab_bandwidth_bps[] = { - { "b/s", 1 },{ "bps", 1 }, - { "Kib/s", 1024 },{ "Kibps", 1024 }, - { "kb/s", 1000 },{ "kbps", 1000 }, - { "Mib/s", 1048576 },{ "Mibps", 1000 }, - { "Mb/s", 1000000 },{ "Mbps", 1000000 }, - { "Gib/s", 1073741824 },{ "Gibps", 1073741824 }, - { "Gb/s", 1000000000 },{ "Gbps", 1000000000 }, - { "B/s", 8 },{ "Bps", 8 }, - { "KiB/s", 8 * 1024 },{ "KiBps", 8 * 1024 }, - { "kB/s", 8 * 1000 },{ "kBps", 8 * 1000 }, - { "MiB/s", 8 * 1048576 },{ "MiBps", 8 * 1048576 }, - { "MB/s", 8 * 1000000 },{ "MBps", 8 * 1000000 }, - { "GiB/s", 8 * (int64_t) 1073741824 },{ "GiBps", 8 * (int64_t) 1073741824 }, - { "GB/s", 8 * (int64_t) 1000000000 },{ "GBps", 8 * (int64_t) 1000000000 }, - { NULL, 0 } + { "b/s", 1 },{ "bps", 1 }, + { "Kib/s", 1024 },{ "Kibps", 1024 }, + { "kb/s", 1000 },{ "kbps", 1000 }, + { "Mib/s", 1048576 },{ "Mibps", 1000 }, + { "Mb/s", 1000000 },{ "Mbps", 1000000 }, + { "Gib/s", 1073741824 },{ "Gibps", 1073741824 }, + { "Gb/s", 1000000000 },{ "Gbps", 1000000000 }, + { "B/s", 8 },{ "Bps", 8 }, + { "KiB/s", 8 * 1024 },{ "KiBps", 8 * 1024 }, + { "kB/s", 8 * 1000 },{ "kBps", 8 * 1000 }, + { "MiB/s", 8 * 1048576 },{ "MiBps", 8 * 1048576 }, + { "MB/s", 8 * 1000000 },{ "MBps", 8 * 1000000 }, + { "GiB/s", 8 * (int64_t) 1073741824 },{ "GiBps", 8 * (int64_t) 1073741824 }, + { "GB/s", 8 * (int64_t) 1000000000 },{ "GBps", 8 * (int64_t) 1000000000 }, + { NULL, 0 } }; static const struct unit unittab_bandwidth_Bps[] = { - { "B/s", 1 },{ "Bps", 1 }, - { "KiB/s", 1024 },{ "KiBps", 1024 }, - { "kB/s", 1000 },{ "kBps", 1000 }, - { "MiB/s", 1048576 },{ "MiBps", 1048576 }, - { "MB/s", 1000000 },{ "MBps", 1000000 }, - { "GiB/s", 1073741824 },{ "GiBps", 1073741824 }, - { "GB/s", 1000000000 },{ "GBps", 1000000000 }, - { NULL, 0 } + { "B/s", 1 },{ "Bps", 1 }, + { "KiB/s", 1024 },{ "KiBps", 1024 }, + { "kB/s", 1000 },{ "kBps", 1000 }, + { "MiB/s", 1048576 },{ "MiBps", 1048576 }, + { "MB/s", 1000000 },{ "MBps", 1000000 }, + { "GiB/s", 1073741824 },{ "GiBps", 1073741824 }, + { "GB/s", 1000000000 },{ "GBps", 1000000000 }, + { NULL, 0 } }; #endif static void cfgst_push(struct cfgst *cfgst, int isattr, const struct cfgelem *elem, void *parent) { - assert(cfgst->path_depth < MAX_PATH_DEPTH); - assert(isattr == 0 || isattr == 1); - cfgst->isattr[cfgst->path_depth] = isattr; - cfgst->path[cfgst->path_depth] = elem; - cfgst->parent[cfgst->path_depth] = parent; - cfgst->path_depth++; + assert(cfgst->path_depth < MAX_PATH_DEPTH); + assert(isattr == 0 || isattr == 1); + cfgst->isattr[cfgst->path_depth] = isattr; + cfgst->path[cfgst->path_depth] = elem; + cfgst->parent[cfgst->path_depth] = parent; + cfgst->path_depth++; } static void cfgst_pop(struct cfgst *cfgst) { - assert(cfgst->path_depth > 0); - cfgst->path_depth--; + assert(cfgst->path_depth > 0); + cfgst->path_depth--; } static const struct cfgelem *cfgst_tos(const struct cfgst *cfgst) { - assert(cfgst->path_depth > 0); - return cfgst->path[cfgst->path_depth - 1]; + assert(cfgst->path_depth > 0); + return cfgst->path[cfgst->path_depth - 1]; } static void *cfgst_parent(const struct cfgst *cfgst) { - assert(cfgst->path_depth > 0); - return cfgst->parent[cfgst->path_depth - 1]; + assert(cfgst->path_depth > 0); + return cfgst->parent[cfgst->path_depth - 1]; } struct cfg_note_buf { - size_t bufpos; - size_t bufsize; - char *buf; + size_t bufpos; + size_t bufsize; + char *buf; }; static size_t cfg_note_vsnprintf(struct cfg_note_buf *bb, const char *fmt, va_list ap) { - int x; - x = vsnprintf(bb->buf + bb->bufpos, bb->bufsize - bb->bufpos, fmt, ap); - if ( x >= 0 && (size_t) x >= bb->bufsize - bb->bufpos ) { - size_t nbufsize = ((bb->bufsize + (size_t) x + 1) + 1023) & (size_t) (-1024); - char *nbuf = ddsrt_realloc(bb->buf, nbufsize); - bb->buf = nbuf; - bb->bufsize = nbufsize; - return nbufsize; - } - if ( x < 0 ) - DDS_FATAL("cfg_note_vsnprintf: vsnprintf failed\n"); - else - bb->bufpos += (size_t) x; - return 0; + int x; + x = vsnprintf(bb->buf + bb->bufpos, bb->bufsize - bb->bufpos, fmt, ap); + if ( x >= 0 && (size_t) x >= bb->bufsize - bb->bufpos ) { + size_t nbufsize = ((bb->bufsize + (size_t) x + 1) + 1023) & (size_t) (-1024); + char *nbuf = ddsrt_realloc(bb->buf, nbufsize); + bb->buf = nbuf; + bb->bufsize = nbufsize; + return nbufsize; + } + if ( x < 0 ) + DDS_FATAL("cfg_note_vsnprintf: vsnprintf failed\n"); + else + bb->bufpos += (size_t) x; + return 0; } static void cfg_note_snprintf(struct cfg_note_buf *bb, const char *fmt, ...) { - /* The reason the 2nd call to os_vsnprintf is here and not inside - cfg_note_vsnprintf is because I somehow doubt that all platforms - implement va_copy() */ - va_list ap; - size_t r; + /* The reason the 2nd call to os_vsnprintf is here and not inside + cfg_note_vsnprintf is because I somehow doubt that all platforms + implement va_copy() */ + va_list ap; + size_t r; + va_start(ap, fmt); + r = cfg_note_vsnprintf(bb, fmt, ap); + va_end(ap); + if ( r > 0 ) { + int s; va_start(ap, fmt); - r = cfg_note_vsnprintf(bb, fmt, ap); + s = vsnprintf(bb->buf + bb->bufpos, bb->bufsize - bb->bufpos, fmt, ap); + if ( s < 0 || (size_t) s >= bb->bufsize - bb->bufpos ) + DDS_FATAL("cfg_note_snprintf: vsnprintf failed\n"); va_end(ap); - if ( r > 0 ) { - int s; - va_start(ap, fmt); - s = vsnprintf(bb->buf + bb->bufpos, bb->bufsize - bb->bufpos, fmt, ap); - if ( s < 0 || (size_t) s >= bb->bufsize - bb->bufpos ) - DDS_FATAL("cfg_note_snprintf: vsnprintf failed\n"); - va_end(ap); - bb->bufpos += (size_t) s; - } + bb->bufpos += (size_t) s; + } } static size_t cfg_note(struct cfgst *cfgst, uint32_t cat, size_t bsz, const char *fmt, va_list ap) { - /* Have to snprintf our way to a single string so we can OS_REPORT - as well as nn_log. Otherwise configuration errors will be lost - completely on platforms where stderr doesn't actually work for - outputting error messages (this includes Windows because of the - way "ospl start" does its thing). */ - struct cfg_note_buf bb; - int i, sidx; - size_t r; + /* Have to snprintf our way to a single string so we can OS_REPORT + as well as nn_log. Otherwise configuration errors will be lost + completely on platforms where stderr doesn't actually work for + outputting error messages (this includes Windows because of the + way "ospl start" does its thing). */ + struct cfg_note_buf bb; + int i, sidx; + size_t r; - if (cat & DDS_LC_ERROR) { - cfgst->error = 1; - } - - bb.bufpos = 0; - bb.bufsize = (bsz == 0) ? 1024 : bsz; - if ( (bb.buf = ddsrt_malloc(bb.bufsize)) == NULL ) - DDS_FATAL("cfg_note: out of memory\n"); - - cfg_note_snprintf(&bb, "config: "); - - /* Path to element/attribute causing the error. Have to stop once an - attribute is reached: a NULL marker may have been pushed onto the - stack afterward in the default handling. */ - sidx = 0; - while ( sidx < cfgst->path_depth && cfgst->path[sidx]->name == NULL ) - sidx++; - for ( i = sidx; i < cfgst->path_depth && (i == sidx || !cfgst->isattr[i - 1]); i++ ) { - if ( cfgst->path[i] == NULL ) { - assert(i > sidx); - cfg_note_snprintf(&bb, "/#text"); - } else if ( cfgst->isattr[i] ) { - cfg_note_snprintf(&bb, "[@%s]", cfgst->path[i]->name); - } else { - const char *p = strchr(cfgst->path[i]->name, '|'); - int n = p ? (int) (p - cfgst->path[i]->name) : (int) strlen(cfgst->path[i]->name); - cfg_note_snprintf(&bb, "%s%*.*s", (i == sidx) ? "" : "/", n, n, cfgst->path[i]->name); - } - } - - cfg_note_snprintf(&bb, ": "); - if ( (r = cfg_note_vsnprintf(&bb, fmt, ap)) > 0 ) { - /* Can't reset ap ... and va_copy isn't widely available - so - instead abort and hope the caller tries again with a larger - initial buffer */ - ddsrt_free(bb.buf); - return r; - } - - switch ( cat ) { - case DDS_LC_CONFIG: - DDS_LOG(cat, "%s\n", bb.buf); - break; - case DDS_LC_WARNING: - DDS_WARNING("%s\n", bb.buf); - break; - case DDS_LC_ERROR: - DDS_ERROR("%s\n", bb.buf); - break; - default: - DDS_FATAL("cfg_note unhandled category %u for message %s\n", (unsigned) cat, bb.buf); - break; + if (cat & DDS_LC_ERROR) { + cfgst->error = 1; + } + + bb.bufpos = 0; + bb.bufsize = (bsz == 0) ? 1024 : bsz; + if ( (bb.buf = ddsrt_malloc(bb.bufsize)) == NULL ) + DDS_FATAL("cfg_note: out of memory\n"); + + cfg_note_snprintf(&bb, "config: "); + + /* Path to element/attribute causing the error. Have to stop once an + attribute is reached: a NULL marker may have been pushed onto the + stack afterward in the default handling. */ + sidx = 0; + while ( sidx < cfgst->path_depth && cfgst->path[sidx]->name == NULL ) + sidx++; + for ( i = sidx; i < cfgst->path_depth && (i == sidx || !cfgst->isattr[i - 1]); i++ ) { + if ( cfgst->path[i] == NULL ) { + assert(i > sidx); + cfg_note_snprintf(&bb, "/#text"); + } else if ( cfgst->isattr[i] ) { + cfg_note_snprintf(&bb, "[@%s]", cfgst->path[i]->name); + } else { + const char *p = strchr(cfgst->path[i]->name, '|'); + int n = p ? (int) (p - cfgst->path[i]->name) : (int) strlen(cfgst->path[i]->name); + cfg_note_snprintf(&bb, "%s%*.*s", (i == sidx) ? "" : "/", n, n, cfgst->path[i]->name); } + } + cfg_note_snprintf(&bb, ": "); + if ( (r = cfg_note_vsnprintf(&bb, fmt, ap)) > 0 ) { + /* Can't reset ap ... and va_copy isn't widely available - so + instead abort and hope the caller tries again with a larger + initial buffer */ ddsrt_free(bb.buf); - return 0; + return r; + } + + switch ( cat ) { + case DDS_LC_CONFIG: + DDS_LOG(cat, "%s\n", bb.buf); + break; + case DDS_LC_WARNING: + DDS_WARNING("%s\n", bb.buf); + break; + case DDS_LC_ERROR: + DDS_ERROR("%s\n", bb.buf); + break; + default: + DDS_FATAL("cfg_note unhandled category %u for message %s\n", (unsigned) cat, bb.buf); + break; + } + + ddsrt_free(bb.buf); + return 0; } #if WARN_DEPRECATED_ALIAS || WARN_DEPRECATED_UNIT static void cfg_warning(struct cfgst *cfgst, const char *fmt, ...) { - va_list ap; - size_t bsz = 0; - do { - va_start(ap, fmt); - bsz = cfg_note(cfgst, DDS_LC_WARNING, bsz, fmt, ap); - va_end(ap); - } while ( bsz > 0 ); + va_list ap; + size_t bsz = 0; + do { + va_start(ap, fmt); + bsz = cfg_note(cfgst, DDS_LC_WARNING, bsz, fmt, ap); + va_end(ap); + } while ( bsz > 0 ); } #endif static int cfg_error(struct cfgst *cfgst, const char *fmt, ...) { - va_list ap; - size_t bsz = 0; - do { - va_start(ap, fmt); - bsz = cfg_note(cfgst, DDS_LC_ERROR, bsz, fmt, ap); - va_end(ap); - } while ( bsz > 0 ); - return 0; + va_list ap; + size_t bsz = 0; + do { + va_start(ap, fmt); + bsz = cfg_note(cfgst, DDS_LC_ERROR, bsz, fmt, ap); + va_end(ap); + } while ( bsz > 0 ); + return 0; } static int cfg_log(struct cfgst *cfgst, const char *fmt, ...) { - va_list ap; - size_t bsz = 0; - do { - va_start(ap, fmt); - bsz = cfg_note(cfgst, DDS_LC_CONFIG, bsz, fmt, ap); - va_end(ap); - } while ( bsz > 0 ); - return 0; + va_list ap; + size_t bsz = 0; + do { + va_start(ap, fmt); + bsz = cfg_note(cfgst, DDS_LC_CONFIG, bsz, fmt, ap); + va_end(ap); + } while ( bsz > 0 ); + return 0; } static int list_index(const char *list[], const char *elem) { - int i; - for ( i = 0; list[i] != NULL; i++ ) { - if ( ddsrt_strcasecmp(list[i], elem) == 0 ) - return i; - } - return -1; + int i; + for ( i = 0; list[i] != NULL; i++ ) { + if ( ddsrt_strcasecmp(list[i], elem) == 0 ) + return i; + } + return -1; } static int64_t lookup_multiplier(struct cfgst *cfgst, const struct unit *unittab, const char *value, int unit_pos, int value_is_zero, int64_t def_mult, int err_on_unrecognised) { - assert(0 <= unit_pos && (size_t) unit_pos <= strlen(value)); - while ( value[unit_pos] == ' ' ) - unit_pos++; - if ( value[unit_pos] == 0 ) { - if ( value_is_zero ) { - /* No matter what unit, 0 remains just that. For convenience, - always allow 0 to be specified without a unit */ - return 1; - } else if ( def_mult == 0 && err_on_unrecognised ) { - cfg_error(cfgst, "%s: unit is required", value); - return 0; - } else { -#if WARN_DEPRECATED_UNIT - cfg_warning(cfgst, "%s: use of default unit is deprecated", value); -#endif - return def_mult; - } + assert(0 <= unit_pos && (size_t) unit_pos <= strlen(value)); + while ( value[unit_pos] == ' ' ) + unit_pos++; + if ( value[unit_pos] == 0 ) { + if ( value_is_zero ) { + /* No matter what unit, 0 remains just that. For convenience, + always allow 0 to be specified without a unit */ + return 1; + } else if ( def_mult == 0 && err_on_unrecognised ) { + cfg_error(cfgst, "%s: unit is required", value); + return 0; } else { - int i; - for ( i = 0; unittab[i].name != NULL; i++ ) { - if ( strcmp(unittab[i].name, value + unit_pos) == 0 ) - return unittab[i].multiplier; - } - if ( err_on_unrecognised ) - cfg_error(cfgst, "%s: unrecognised unit", value + unit_pos); - return 0; +#if WARN_DEPRECATED_UNIT + cfg_warning(cfgst, "%s: use of default unit is deprecated", value); +#endif + return def_mult; } + } else { + int i; + for ( i = 0; unittab[i].name != NULL; i++ ) { + if ( strcmp(unittab[i].name, value + unit_pos) == 0 ) + return unittab[i].multiplier; + } + if ( err_on_unrecognised ) + cfg_error(cfgst, "%s: unrecognised unit", value + unit_pos); + return 0; + } } static void *cfg_address(UNUSED_ARG(struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem) { - assert(cfgelem->multiplicity == 1); - return (char *) parent + cfgelem->elem_offset; + assert(cfgelem->multiplicity == 1); + return (char *) parent + cfgelem->elem_offset; } static void *cfg_deref_address(UNUSED_ARG(struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem) { - assert(cfgelem->multiplicity != 1); - return *((void **) ((char *) parent + cfgelem->elem_offset)); + assert(cfgelem->multiplicity != 1); + return *((void **) ((char *) parent + cfgelem->elem_offset)); } static void *if_common(UNUSED_ARG(struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem, unsigned size) { - struct config_listelem **current = (struct config_listelem **) ((char *) parent + cfgelem->elem_offset); - struct config_listelem *new = ddsrt_malloc(size); - new->next = *current; - *current = new; - return new; + struct config_listelem **current = (struct config_listelem **) ((char *) parent + cfgelem->elem_offset); + struct config_listelem *new = ddsrt_malloc(size); + new->next = *current; + *current = new; + return new; } static int if_thread_properties(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - struct config_thread_properties_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(*new)); - if ( new == NULL ) - return -1; - new->name = NULL; - return 0; + struct config_thread_properties_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(*new)); + if ( new == NULL ) + return -1; + new->name = NULL; + return 0; } #ifdef DDSI_INCLUDE_NETWORK_CHANNELS static int if_channel(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - struct config_channel_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(*new)); - if ( new == NULL ) - return -1; - new->name = NULL; - new->channel_reader_ts = NULL; - new->dqueue = NULL; - new->queueId = 0; - new->evq = NULL; - new->transmit_conn = NULL; - return 0; + struct config_channel_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(*new)); + if ( new == NULL ) + return -1; + new->name = NULL; + new->channel_reader_ts = NULL; + new->dqueue = NULL; + new->queueId = 0; + new->evq = NULL; + new->transmit_conn = NULL; + return 0; } #endif /* DDSI_INCLUDE_NETWORK_CHANNELS */ #ifdef DDSI_INCLUDE_ENCRYPTION static int if_security_profile(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - if ( if_common(cfgst, parent, cfgelem, sizeof(struct config_securityprofile_listelem)) == NULL ) - return -1; - return 0; + if ( if_common(cfgst, parent, cfgelem, sizeof(struct config_securityprofile_listelem)) == NULL ) + return -1; + return 0; } #endif /* DDSI_INCLUDE_ENCRYPTION */ #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS static int if_network_partition(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - struct config_networkpartition_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(*new)); - if ( new == NULL ) - return -1; - new->address_string = NULL; + struct config_networkpartition_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(*new)); + if ( new == NULL ) + return -1; + new->address_string = NULL; #ifdef DDSI_INCLUDE_ENCRYPTION - new->profileName = NULL; - new->securityProfile = NULL; + new->profileName = NULL; + new->securityProfile = NULL; #endif /* DDSI_INCLUDE_ENCRYPTION */ - return 0; + return 0; } static int if_ignored_partition(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - if ( if_common(cfgst, parent, cfgelem, sizeof(struct config_ignoredpartition_listelem)) == NULL ) - return -1; - return 0; + if ( if_common(cfgst, parent, cfgelem, sizeof(struct config_ignoredpartition_listelem)) == NULL ) + return -1; + return 0; } static int if_partition_mapping(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - if ( if_common(cfgst, parent, cfgelem, sizeof(struct config_partitionmapping_listelem)) == NULL ) - return -1; - return 0; + if ( if_common(cfgst, parent, cfgelem, sizeof(struct config_partitionmapping_listelem)) == NULL ) + return -1; + return 0; } #endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */ static int if_peer(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - struct config_peer_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(struct config_peer_listelem)); - if ( new == NULL ) - return -1; - new->peer = NULL; - return 0; + struct config_peer_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(struct config_peer_listelem)); + if ( new == NULL ) + return -1; + new->peer = NULL; + return 0; } static void ff_free(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - void **elem = cfg_address(cfgst, parent, cfgelem); - ddsrt_free(*elem); + void **elem = cfg_address(cfgst, parent, cfgelem); + ddsrt_free(*elem); } static int uf_boolean(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - static const char *vs[] = { "false", "true", NULL }; - int *elem = cfg_address(cfgst, parent, cfgelem); - int idx = list_index(vs, value); - if ( idx < 0 ) - return cfg_error(cfgst, "'%s': undefined value", value); - else { - *elem = idx; - return 1; - } -} - -static int uf_negated_boolean(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) -{ - if ( !uf_boolean(cfgst, parent, cfgelem, first, value) ) - return 0; - else { - int *elem = cfg_address(cfgst, parent, cfgelem); - *elem = !*elem; - return 1; - } + static const char *vs[] = { "false", "true", NULL }; + int *elem = cfg_address(cfgst, parent, cfgelem); + int idx = list_index(vs, value); + if ( idx < 0 ) + return cfg_error(cfgst, "'%s': undefined value", value); + else { + *elem = idx; + return 1; + } } static int uf_boolean_default (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) @@ -1359,78 +1280,78 @@ static void pf_boolean_default (struct cfgst *cfgst, void *parent, struct cfgele static int do_uint32_bitset(struct cfgst *cfgst, uint32_t *cats, const char **names, const uint32_t *codes, const char *value) { - char *copy = ddsrt_strdup(value), *cursor = copy, *tok; - while ( (tok = ddsrt_strsep(&cursor, ",")) != NULL ) { - int idx = list_index(names, tok); - if ( idx < 0 ) { - int ret = cfg_error(cfgst, "'%s' in '%s' undefined", tok, value); - ddsrt_free(copy); - return ret; - } - *cats |= codes[idx]; + char *copy = ddsrt_strdup(value), *cursor = copy, *tok; + while ( (tok = ddsrt_strsep(&cursor, ",")) != NULL ) { + int idx = list_index(names, tok); + if ( idx < 0 ) { + int ret = cfg_error(cfgst, "'%s' in '%s' undefined", tok, value); + ddsrt_free(copy); + return ret; } - ddsrt_free(copy); - return 1; + *cats |= codes[idx]; + } + ddsrt_free(copy); + return 1; } static int uf_logcat(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) { - return do_uint32_bitset (cfgst, &enabled_logcats, logcat_names, logcat_codes, value); + return do_uint32_bitset (cfgst, &enabled_logcats, logcat_names, logcat_codes, value); } static int uf_xcheck(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - uint32_t *elem = cfg_address(cfgst, parent, cfgelem); - return do_uint32_bitset (cfgst, elem, xcheck_names, xcheck_codes, value); + uint32_t *elem = cfg_address(cfgst, parent, cfgelem); + return do_uint32_bitset (cfgst, elem, xcheck_names, xcheck_codes, value); } static int uf_verbosity(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) { - static const char *vs[] = { - "finest", "finer", "fine", "config", "info", "warning", "severe", "none", NULL - }; - static const uint32_t lc[] = { - DDS_LC_ALL, DDS_LC_TRAFFIC | DDS_LC_TIMING, DDS_LC_DISCOVERY | DDS_LC_THROTTLE, DDS_LC_CONFIG, DDS_LC_INFO, DDS_LC_WARNING, DDS_LC_ERROR | DDS_LC_FATAL, 0, 0 - }; - int idx = list_index(vs, value); - assert(sizeof(vs) / sizeof(*vs) == sizeof(lc) / sizeof(*lc)); - if ( idx < 0 ) - return cfg_error(cfgst, "'%s': undefined value", value); - else { - int i; - for ( i = (int) (sizeof(vs) / sizeof(*vs)) - 1; i >= idx; i-- ) - enabled_logcats |= lc[i]; - return 1; - } + static const char *vs[] = { + "finest", "finer", "fine", "config", "info", "warning", "severe", "none", NULL + }; + static const uint32_t lc[] = { + DDS_LC_ALL, DDS_LC_TRAFFIC | DDS_LC_TIMING, DDS_LC_DISCOVERY | DDS_LC_THROTTLE, DDS_LC_CONFIG, DDS_LC_INFO, DDS_LC_WARNING, DDS_LC_ERROR | DDS_LC_FATAL, 0, 0 + }; + int idx = list_index(vs, value); + assert(sizeof(vs) / sizeof(*vs) == sizeof(lc) / sizeof(*lc)); + if ( idx < 0 ) + return cfg_error(cfgst, "'%s': undefined value", value); + else { + int i; + for ( i = (int) (sizeof(vs) / sizeof(*vs)) - 1; i >= idx; i-- ) + enabled_logcats |= lc[i]; + return 1; + } } static int uf_besmode(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) { - static const char *vs[] = { - "full", "writers", "minimal", NULL - }; - static const enum besmode ms[] = { - BESMODE_FULL, BESMODE_WRITERS, BESMODE_MINIMAL, 0, - }; - int idx = list_index(vs, value); - enum besmode *elem = cfg_address(cfgst, parent, cfgelem); - assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms)); - if ( idx < 0 ) - return cfg_error(cfgst, "'%s': undefined value", value); - *elem = ms[idx]; - return 1; + static const char *vs[] = { + "full", "writers", "minimal", NULL + }; + static const enum besmode ms[] = { + BESMODE_FULL, BESMODE_WRITERS, BESMODE_MINIMAL, 0, + }; + int idx = list_index(vs, value); + enum besmode *elem = cfg_address(cfgst, parent, cfgelem); + assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms)); + if ( idx < 0 ) + return cfg_error(cfgst, "'%s': undefined value", value); + *elem = ms[idx]; + return 1; } static void pf_besmode(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - enum besmode *p = cfg_address(cfgst, parent, cfgelem); - const char *str = "INVALID"; - switch ( *p ) { - case BESMODE_FULL: str = "full"; break; - case BESMODE_WRITERS: str = "writers"; break; - case BESMODE_MINIMAL: str = "minimal"; break; - } - cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); + enum besmode *p = cfg_address(cfgst, parent, cfgelem); + const char *str = "INVALID"; + switch ( *p ) { + case BESMODE_FULL: str = "full"; break; + case BESMODE_WRITERS: str = "writers"; break; + case BESMODE_MINIMAL: str = "minimal"; break; + } + cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); } #ifdef DDSI_INCLUDE_SSL @@ -1458,436 +1379,371 @@ static void pf_min_tls_version(struct cfgst *cfgst, void *parent, struct cfgelem } #endif -static int uf_durability_cdr(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) -{ - static const char *vs[] = { "cdr_le", "cdr_be", "cdr_server", "cdr_client", NULL }; - static const enum durability_cdr ms[] = { DUR_CDR_LE, DUR_CDR_BE, DUR_CDR_SERVER, DUR_CDR_CLIENT, 0 }; - int idx = list_index(vs, value); - enum durability_cdr * elem = cfg_address(cfgst, parent, cfgelem); - if ( idx < 0 ) { - return cfg_error(cfgst, "'%s': undefined value", value); - } - *elem = ms[idx]; - return 1; -} - -static void pf_durability_cdr(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - enum durability_cdr *p = cfg_address(cfgst, parent, cfgelem); - const char *str = "INVALID"; - switch ( *p ) { - case DUR_CDR_LE: str = "cdr_le"; break; - case DUR_CDR_BE: str = "cdr_be"; break; - case DUR_CDR_SERVER: str = "cdr_server"; break; - case DUR_CDR_CLIENT: str = "cdr_client"; break; - } - cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); -} - - static int uf_retransmit_merging(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) { - static const char *vs[] = { - "never", "adaptive", "always", NULL - }; - static const enum retransmit_merging ms[] = { - REXMIT_MERGE_NEVER, REXMIT_MERGE_ADAPTIVE, REXMIT_MERGE_ALWAYS, 0, - }; - int idx = list_index(vs, value); - enum retransmit_merging *elem = cfg_address(cfgst, parent, cfgelem); - assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms)); - if ( idx < 0 ) - return cfg_error(cfgst, "'%s': undefined value", value); - *elem = ms[idx]; - return 1; + static const char *vs[] = { + "never", "adaptive", "always", NULL + }; + static const enum retransmit_merging ms[] = { + REXMIT_MERGE_NEVER, REXMIT_MERGE_ADAPTIVE, REXMIT_MERGE_ALWAYS, 0, + }; + int idx = list_index(vs, value); + enum retransmit_merging *elem = cfg_address(cfgst, parent, cfgelem); + assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms)); + if ( idx < 0 ) + return cfg_error(cfgst, "'%s': undefined value", value); + *elem = ms[idx]; + return 1; } static void pf_retransmit_merging(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - enum retransmit_merging *p = cfg_address(cfgst, parent, cfgelem); - const char *str = "INVALID"; - switch ( *p ) { - case REXMIT_MERGE_NEVER: str = "never"; break; - case REXMIT_MERGE_ADAPTIVE: str = "adaptive"; break; - case REXMIT_MERGE_ALWAYS: str = "always"; break; - } - cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); + enum retransmit_merging *p = cfg_address(cfgst, parent, cfgelem); + const char *str = "INVALID"; + switch ( *p ) { + case REXMIT_MERGE_NEVER: str = "never"; break; + case REXMIT_MERGE_ADAPTIVE: str = "adaptive"; break; + case REXMIT_MERGE_ALWAYS: str = "always"; break; + } + cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); } static int uf_string(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - char **elem = cfg_address(cfgst, parent, cfgelem); - *elem = ddsrt_strdup(value); - return 1; + char **elem = cfg_address(cfgst, parent, cfgelem); + *elem = ddsrt_strdup(value); + return 1; } DDSRT_WARNING_MSVC_OFF(4996); static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *value, const struct unit *unittab, int64_t def_mult, int64_t min, int64_t max) { - int pos; - double v_dbl; - int64_t v_int; - int64_t mult; - /* try convert as integer + optional unit; if that fails, try - floating point + optional unit (round, not truncate, to integer) */ - if ( *value == 0 ) { - *elem = 0; /* some static analyzers don't "get it" */ - return cfg_error(cfgst, "%s: empty string is not a valid value", value); - } else if ( sscanf(value, "%lld%n", (long long int *) &v_int, &pos) == 1 && (mult = lookup_multiplier(cfgst, unittab, value, pos, v_int == 0, def_mult, 0)) != 0 ) { - assert(mult > 0); - if ( v_int < 0 || v_int > max / mult || mult * v_int < min) - return cfg_error(cfgst, "%s: value out of range", value); - *elem = mult * v_int; - return 1; - } else if ( sscanf(value, "%lf%n", &v_dbl, &pos) == 1 && (mult = lookup_multiplier(cfgst, unittab, value, pos, v_dbl == 0, def_mult, 1)) != 0 ) { - double dmult = (double) mult; - assert(dmult > 0); - if ( (int64_t) (v_dbl * dmult + 0.5) < min || (int64_t) (v_dbl * dmult + 0.5) > max ) - return cfg_error(cfgst, "%s: value out of range", value); - *elem = (int64_t) (v_dbl * dmult + 0.5); - return 1; - } else { - *elem = 0; /* some static analyzers don't "get it" */ - return cfg_error(cfgst, "%s: invalid value", value); - } + int pos; + double v_dbl; + int64_t v_int; + int64_t mult; + /* try convert as integer + optional unit; if that fails, try + floating point + optional unit (round, not truncate, to integer) */ + if ( *value == 0 ) { + *elem = 0; /* some static analyzers don't "get it" */ + return cfg_error(cfgst, "%s: empty string is not a valid value", value); + } else if ( sscanf(value, "%lld%n", (long long int *) &v_int, &pos) == 1 && (mult = lookup_multiplier(cfgst, unittab, value, pos, v_int == 0, def_mult, 0)) != 0 ) { + assert(mult > 0); + if ( v_int < 0 || v_int > max / mult || mult * v_int < min) + return cfg_error(cfgst, "%s: value out of range", value); + *elem = mult * v_int; + return 1; + } else if ( sscanf(value, "%lf%n", &v_dbl, &pos) == 1 && (mult = lookup_multiplier(cfgst, unittab, value, pos, v_dbl == 0, def_mult, 1)) != 0 ) { + double dmult = (double) mult; + assert(dmult > 0); + if ( (int64_t) (v_dbl * dmult + 0.5) < min || (int64_t) (v_dbl * dmult + 0.5) > max ) + return cfg_error(cfgst, "%s: value out of range", value); + *elem = (int64_t) (v_dbl * dmult + 0.5); + return 1; + } else { + *elem = 0; /* some static analyzers don't "get it" */ + return cfg_error(cfgst, "%s: invalid value", value); + } } DDSRT_WARNING_MSVC_ON(4996); #ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING static int uf_bandwidth(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - int64_t bandwidth_bps = 0; - if ( strncmp(value, "inf", 3) == 0 ) { - /* special case: inf needs no unit */ - int *elem = cfg_address(cfgst, parent, cfgelem); - if ( strspn(value + 3, " ") != strlen(value + 3) && - lookup_multiplier(cfgst, unittab_bandwidth_bps, value, 3, 1, 8, 1) == 0 ) - return 0; - *elem = 0; - return 1; - } else if ( !uf_natint64_unit(cfgst, &bandwidth_bps, value, unittab_bandwidth_bps, 8, INT64_MAX) ) { - return 0; - } else if ( bandwidth_bps / 8 > INT_MAX ) { - return cfg_error(cfgst, "%s: value out of range", value); - } else { - uint32_t *elem = cfg_address(cfgst, parent, cfgelem); - *elem = (uint32_t) (bandwidth_bps / 8); - return 1; - } + int64_t bandwidth_bps = 0; + if ( strncmp(value, "inf", 3) == 0 ) { + /* special case: inf needs no unit */ + int *elem = cfg_address(cfgst, parent, cfgelem); + if ( strspn(value + 3, " ") != strlen(value + 3) && + lookup_multiplier(cfgst, unittab_bandwidth_bps, value, 3, 1, 8, 1) == 0 ) + return 0; + *elem = 0; + return 1; + } else if ( !uf_natint64_unit(cfgst, &bandwidth_bps, value, unittab_bandwidth_bps, 8, INT64_MAX) ) { + return 0; + } else if ( bandwidth_bps / 8 > INT_MAX ) { + return cfg_error(cfgst, "%s: value out of range", value); + } else { + uint32_t *elem = cfg_address(cfgst, parent, cfgelem); + *elem = (uint32_t) (bandwidth_bps / 8); + return 1; + } } #endif static int uf_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - int64_t size = 0; - if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) ) - return 0; - else { - uint32_t *elem = cfg_address(cfgst, parent, cfgelem); - *elem = (uint32_t) size; - return 1; - } + int64_t size = 0; + if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) ) + return 0; + else { + uint32_t *elem = cfg_address(cfgst, parent, cfgelem); + *elem = (uint32_t) size; + return 1; + } } #ifdef DDSI_INCLUDE_ENCRYPTION static int uf_cipher(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - if ( q_security_plugin.cipher_type_from_string ) { - q_cipherType *elem = cfg_address(cfgst, parent, cfgelem); - if ( (q_security_plugin.cipher_type_from_string) (value, elem) ) { - return 1; - } else { - return cfg_error(cfgst, "%s: undefined value", value); - } + if ( q_security_plugin.cipher_type_from_string ) { + q_cipherType *elem = cfg_address(cfgst, parent, cfgelem); + if ( (q_security_plugin.cipher_type_from_string) (value, elem) ) { + return 1; + } else { + return cfg_error(cfgst, "%s: undefined value", value); } - return 1; + } + return 1; } #endif /* DDSI_INCLUDE_ENCRYPTION */ static int uf_tracingOutputFileName(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) { - struct config *cfg = cfgst->cfg; - { - cfg->tracingOutputFileName = ddsrt_strdup(value); - } - return 1; + struct config *cfg = cfgst->cfg; + { + cfg->tracingOutputFileName = ddsrt_strdup(value); + } + return 1; } static int uf_ipv4(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) { - /* Not actually doing any checking yet */ - return uf_string(cfgst, parent, cfgelem, first, value); + /* Not actually doing any checking yet */ + return uf_string(cfgst, parent, cfgelem, first, value); } static int uf_networkAddress(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) { - if ( ddsrt_strcasecmp(value, "auto") != 0 ) - return uf_ipv4(cfgst, parent, cfgelem, first, value); - else { - char **elem = cfg_address(cfgst, parent, cfgelem); - *elem = NULL; - return 1; - } + if ( ddsrt_strcasecmp(value, "auto") != 0 ) + return uf_ipv4(cfgst, parent, cfgelem, first, value); + else { + char **elem = cfg_address(cfgst, parent, cfgelem); + *elem = NULL; + return 1; + } } static void ff_networkAddresses(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - char ***elem = cfg_address(cfgst, parent, cfgelem); - int i; - for ( i = 0; (*elem)[i]; i++ ) - ddsrt_free((*elem)[i]); - ddsrt_free(*elem); + char ***elem = cfg_address(cfgst, parent, cfgelem); + int i; + for ( i = 0; (*elem)[i]; i++ ) + ddsrt_free((*elem)[i]); + ddsrt_free(*elem); } static int uf_networkAddresses_simple(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - char ***elem = cfg_address(cfgst, parent, cfgelem); - if ( (*elem = ddsrt_malloc(2 * sizeof(char *))) == NULL ) - return cfg_error(cfgst, "out of memory"); - if ( ((*elem)[0] = ddsrt_strdup(value)) == NULL ) { - ddsrt_free(*elem); - *elem = NULL; - return cfg_error(cfgst, "out of memory"); - } - (*elem)[1] = NULL; - return 1; + char ***elem = cfg_address(cfgst, parent, cfgelem); + if ( (*elem = ddsrt_malloc(2 * sizeof(char *))) == NULL ) + return cfg_error(cfgst, "out of memory"); + if ( ((*elem)[0] = ddsrt_strdup(value)) == NULL ) { + ddsrt_free(*elem); + *elem = NULL; + return cfg_error(cfgst, "out of memory"); + } + (*elem)[1] = NULL; + return 1; } static int uf_networkAddresses(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) { - /* Check for keywords first */ + /* Check for keywords first */ + { + static const char *keywords[] = { "all", "any", "none" }; + int i; + for ( i = 0; i < (int) (sizeof(keywords) / sizeof(*keywords)); i++ ) { + if ( ddsrt_strcasecmp(value, keywords[i]) == 0 ) + return uf_networkAddresses_simple(cfgst, parent, cfgelem, first, keywords[i]); + } + } + + /* If not keyword, then comma-separated list of addresses */ + { + char ***elem = cfg_address(cfgst, parent, cfgelem); + char *copy; + unsigned count; + + /* First count how many addresses we have - but do it stupidly by + counting commas and adding one (so two commas in a row are both + counted) */ { - static const char *keywords[] = { "all", "any", "none" }; - int i; - for ( i = 0; i < (int) (sizeof(keywords) / sizeof(*keywords)); i++ ) { - if ( ddsrt_strcasecmp(value, keywords[i]) == 0 ) - return uf_networkAddresses_simple(cfgst, parent, cfgelem, first, keywords[i]); - } + const char *scan = value; + count = 1; + while ( *scan ) + count += (*scan++ == ','); } - /* If not keyword, then comma-separated list of addresses */ + copy = ddsrt_strdup(value); + + /* Allocate an array of address strings (which may be oversized a + bit because of the counting of the commas) */ + *elem = ddsrt_malloc((count + 1) * sizeof(char *)); + { - char ***elem = cfg_address(cfgst, parent, cfgelem); - char *copy; - unsigned count; - - /* First count how many addresses we have - but do it stupidly by - counting commas and adding one (so two commas in a row are both - counted) */ - { - const char *scan = value; - count = 1; - while ( *scan ) - count += (*scan++ == ','); - } - - copy = ddsrt_strdup(value); - - /* Allocate an array of address strings (which may be oversized a - bit because of the counting of the commas) */ - *elem = ddsrt_malloc((count + 1) * sizeof(char *)); - - { - char *cursor = copy, *tok; - unsigned idx = 0; - while ( (tok = ddsrt_strsep(&cursor, ",")) != NULL ) { - assert(idx < count); - (*elem)[idx] = ddsrt_strdup(tok); - idx++; - } - (*elem)[idx] = NULL; - } - ddsrt_free(copy); + char *cursor = copy, *tok; + unsigned idx = 0; + while ( (tok = ddsrt_strsep(&cursor, ",")) != NULL ) { + assert(idx < count); + (*elem)[idx] = ddsrt_strdup(tok); + idx++; + } + (*elem)[idx] = NULL; } - return 1; + ddsrt_free(copy); + } + return 1; } static int uf_allow_multicast(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { #ifdef DDSI_INCLUDE_SSM - static const char *vs[] = { "false", "spdp", "asm", "ssm", "true", NULL }; - static const unsigned bs[] = { AMC_FALSE, AMC_SPDP, AMC_ASM, AMC_SSM, AMC_TRUE }; + static const char *vs[] = { "false", "spdp", "asm", "ssm", "true", NULL }; + static const unsigned bs[] = { AMC_FALSE, AMC_SPDP, AMC_ASM, AMC_SSM, AMC_TRUE }; #else - static const char *vs[] = { "false", "spdp", "asm", "true", NULL }; - static const unsigned bs[] = { AMC_FALSE, AMC_SPDP, AMC_ASM, AMC_TRUE }; + static const char *vs[] = { "false", "spdp", "asm", "true", NULL }; + static const unsigned bs[] = { AMC_FALSE, AMC_SPDP, AMC_ASM, AMC_TRUE }; #endif - char *copy = ddsrt_strdup(value), *cursor = copy, *tok; - unsigned *elem = cfg_address(cfgst, parent, cfgelem); - if ( copy == NULL ) - return cfg_error(cfgst, "out of memory"); - *elem = 0; - while ( (tok = ddsrt_strsep(&cursor, ",")) != NULL ) { - int idx = list_index(vs, tok); - if ( idx < 0 ) { - int ret = cfg_error(cfgst, "'%s' in '%s' undefined", tok, value); - ddsrt_free(copy); - return ret; - } - *elem |= bs[idx]; + char *copy = ddsrt_strdup(value), *cursor = copy, *tok; + unsigned *elem = cfg_address(cfgst, parent, cfgelem); + if ( copy == NULL ) + return cfg_error(cfgst, "out of memory"); + *elem = 0; + while ( (tok = ddsrt_strsep(&cursor, ",")) != NULL ) { + int idx = list_index(vs, tok); + if ( idx < 0 ) { + int ret = cfg_error(cfgst, "'%s' in '%s' undefined", tok, value); + ddsrt_free(copy); + return ret; } - ddsrt_free(copy); - return 1; + *elem |= bs[idx]; + } + ddsrt_free(copy); + return 1; } static void pf_allow_multicast(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - unsigned *p = cfg_address(cfgst, parent, cfgelem); - const char *str = "INVALID"; - switch ( *p ) { - case AMC_FALSE: str = "false"; break; - case AMC_SPDP: str = "spdp"; break; - case AMC_ASM: str = "asm"; break; + unsigned *p = cfg_address(cfgst, parent, cfgelem); + const char *str = "INVALID"; + switch ( *p ) { + case AMC_FALSE: str = "false"; break; + case AMC_SPDP: str = "spdp"; break; + case AMC_ASM: str = "asm"; break; #ifdef DDSI_INCLUDE_SSM - case AMC_SSM: str = "ssm"; break; - case (AMC_SPDP | AMC_ASM): str = "spdp,asm"; break; - case (AMC_SPDP | AMC_SSM): str = "spdp,ssm"; break; + case AMC_SSM: str = "ssm"; break; + case (AMC_SPDP | AMC_ASM): str = "spdp,asm"; break; + case (AMC_SPDP | AMC_SSM): str = "spdp,ssm"; break; #endif - case AMC_TRUE: str = "true"; break; - } - cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); -} - -static int uf_sched_prio_class(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - int ret; - q__schedPrioClass *prio; - - assert(value != NULL); - - prio = cfg_address(cfgst, parent, cfgelem); - - if ( ddsrt_strcasecmp(value, "relative") == 0 ) { - *prio = Q__SCHED_PRIO_RELATIVE; - ret = 1; - } else if ( ddsrt_strcasecmp(value, "absolute") == 0 ) { - *prio = Q__SCHED_PRIO_ABSOLUTE; - ret = 1; - } else { - ret = cfg_error(cfgst, "'%s': undefined value", value); - } - - return ret; -} - -static void pf_sched_prio_class(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - char *str; - q__schedPrioClass *prio = cfg_address(cfgst, parent, cfgelem); - - if ( *prio == Q__SCHED_PRIO_RELATIVE ) { - str = "relative"; - } else if ( *prio == Q__SCHED_PRIO_ABSOLUTE ) { - str = "absolute"; - } else { - str = "INVALID"; - } - - cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); + case AMC_TRUE: str = "true"; break; + } + cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); } static int uf_sched_class(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - static const char *vs[] = { "realtime", "timeshare", "default" }; - static const ddsrt_sched_t ms[] = { DDSRT_SCHED_REALTIME, DDSRT_SCHED_TIMESHARE, DDSRT_SCHED_DEFAULT }; - int idx = list_index(vs, value); - ddsrt_sched_t *elem = cfg_address(cfgst, parent, cfgelem); - assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms)); - if ( idx < 0 ) - return cfg_error(cfgst, "'%s': undefined value", value); - *elem = ms[idx]; - return 1; + static const char *vs[] = { "realtime", "timeshare", "default" }; + static const ddsrt_sched_t ms[] = { DDSRT_SCHED_REALTIME, DDSRT_SCHED_TIMESHARE, DDSRT_SCHED_DEFAULT }; + int idx = list_index(vs, value); + ddsrt_sched_t *elem = cfg_address(cfgst, parent, cfgelem); + assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms)); + if ( idx < 0 ) + return cfg_error(cfgst, "'%s': undefined value", value); + *elem = ms[idx]; + return 1; } static void pf_sched_class(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - ddsrt_sched_t *p = cfg_address(cfgst, parent, cfgelem); - const char *str = "INVALID"; - switch ( *p ) { - case DDSRT_SCHED_DEFAULT: str = "default"; break; - case DDSRT_SCHED_TIMESHARE: str = "timeshare"; break; - case DDSRT_SCHED_REALTIME: str = "realtime"; break; - } - cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); + ddsrt_sched_t *p = cfg_address(cfgst, parent, cfgelem); + const char *str = "INVALID"; + switch ( *p ) { + case DDSRT_SCHED_DEFAULT: str = "default"; break; + case DDSRT_SCHED_TIMESHARE: str = "timeshare"; break; + case DDSRT_SCHED_REALTIME: str = "realtime"; break; + } + cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); } DDSRT_WARNING_MSVC_OFF(4996); static int uf_maybe_int32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - struct config_maybe_int32 *elem = cfg_address(cfgst, parent, cfgelem); - int pos; - if ( ddsrt_strcasecmp(value, "default") == 0 ) { - elem->isdefault = 1; - elem->value = 0; - return 1; - } else if ( sscanf(value, "%"PRId32"%n", &elem->value, &pos) == 1 && value[pos] == 0 ) { - elem->isdefault = 0; - return 1; - } else { - return cfg_error(cfgst, "'%s': neither 'default' nor a decimal integer\n", value); - } + struct config_maybe_int32 *elem = cfg_address(cfgst, parent, cfgelem); + int pos; + if ( ddsrt_strcasecmp(value, "default") == 0 ) { + elem->isdefault = 1; + elem->value = 0; + return 1; + } else if ( sscanf(value, "%"PRId32"%n", &elem->value, &pos) == 1 && value[pos] == 0 ) { + elem->isdefault = 0; + return 1; + } else { + return cfg_error(cfgst, "'%s': neither 'default' nor a decimal integer\n", value); + } } DDSRT_WARNING_MSVC_ON(4996); static int uf_maybe_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - struct config_maybe_uint32 *elem = cfg_address(cfgst, parent, cfgelem); - int64_t size = 0; - if ( ddsrt_strcasecmp(value, "default") == 0 ) { - elem->isdefault = 1; - elem->value = 0; - return 1; - } else if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) ) { - return 0; - } else { - elem->isdefault = 0; - elem->value = (uint32_t) size; - return 1; - } + struct config_maybe_uint32 *elem = cfg_address(cfgst, parent, cfgelem); + int64_t size = 0; + if ( ddsrt_strcasecmp(value, "default") == 0 ) { + elem->isdefault = 1; + elem->value = 0; + return 1; + } else if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) ) { + return 0; + } else { + elem->isdefault = 0; + elem->value = (uint32_t) size; + return 1; + } } static int uf_int(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - int *elem = cfg_address(cfgst, parent, cfgelem); - char *endptr; - long v = strtol(value, &endptr, 10); - if ( *value == 0 || *endptr != 0 ) - return cfg_error(cfgst, "%s: not a decimal integer", value); - if ( v != (int) v ) - return cfg_error(cfgst, "%s: value out of range", value); - *elem = (int) v; - return 1; + int *elem = cfg_address(cfgst, parent, cfgelem); + char *endptr; + long v = strtol(value, &endptr, 10); + if ( *value == 0 || *endptr != 0 ) + return cfg_error(cfgst, "%s: not a decimal integer", value); + if ( v != (int) v ) + return cfg_error(cfgst, "%s: value out of range", value); + *elem = (int) v; + return 1; } static int uf_duration_gen(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, const char *value, int64_t def_mult, int64_t min_ns, int64_t max_ns) { - return uf_natint64_unit(cfgst, cfg_address(cfgst, parent, cfgelem), value, unittab_duration, def_mult, min_ns, max_ns); + return uf_natint64_unit(cfgst, cfg_address(cfgst, parent, cfgelem), value, unittab_duration, def_mult, min_ns, max_ns); } static int uf_duration_inf(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - if ( ddsrt_strcasecmp(value, "inf") == 0 ) { - int64_t *elem = cfg_address(cfgst, parent, cfgelem); - *elem = T_NEVER; - return 1; - } else { - return uf_duration_gen(cfgst, parent, cfgelem, value, 0, 0, T_NEVER - 1); - } + if ( ddsrt_strcasecmp(value, "inf") == 0 ) { + int64_t *elem = cfg_address(cfgst, parent, cfgelem); + *elem = T_NEVER; + return 1; + } else { + return uf_duration_gen(cfgst, parent, cfgelem, value, 0, 0, T_NEVER - 1); + } } static int uf_duration_ms_1hr(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 0, 3600 * T_SECOND); + return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 0, 3600 * T_SECOND); } static int uf_duration_ms_1s(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 0, T_SECOND); + return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 0, T_SECOND); } static int uf_duration_us_1s(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - return uf_duration_gen(cfgst, parent, cfgelem, value, 1000, 0, T_SECOND); + return uf_duration_gen(cfgst, parent, cfgelem, value, 1000, 0, T_SECOND); } static int uf_duration_100ms_1hr(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) @@ -1895,56 +1751,58 @@ static int uf_duration_100ms_1hr(struct cfgst *cfgst, void *parent, struct cfgel return uf_duration_gen(cfgst, parent, cfgelem, value, 0, 100 * T_MILLISECOND, 3600 * T_SECOND); } +#if 0 static int uf_int32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - int32_t *elem = cfg_address(cfgst, parent, cfgelem); - char *endptr; - long v = strtol(value, &endptr, 10); - if ( *value == 0 || *endptr != 0 ) - return cfg_error(cfgst, "%s: not a decimal integer", value); - if ( v != (int32_t) v ) - return cfg_error(cfgst, "%s: value out of range", value); - *elem = (int32_t) v; - return 1; + int32_t *elem = cfg_address(cfgst, parent, cfgelem); + char *endptr; + long v = strtol(value, &endptr, 10); + if ( *value == 0 || *endptr != 0 ) + return cfg_error(cfgst, "%s: not a decimal integer", value); + if ( v != (int32_t) v ) + return cfg_error(cfgst, "%s: value out of range", value); + *elem = (int32_t) v; + return 1; } +#endif #if 0 static int uf_uint32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - uint32_t *elem = cfg_address(cfgst, parent, cfgelem); - char *endptr; - unsigned long v = strtoul(value, &endptr, 10); - if ( *value == 0 || *endptr != 0 ) - return cfg_error(cfgst, "%s: not a decimal integer", value); - if ( v != (uint32_t) v ) - return cfg_error(cfgst, "%s: value out of range", value); - *elem = (uint32_t) v; - return 1; + uint32_t *elem = cfg_address(cfgst, parent, cfgelem); + char *endptr; + unsigned long v = strtoul(value, &endptr, 10); + if ( *value == 0 || *endptr != 0 ) + return cfg_error(cfgst, "%s: not a decimal integer", value); + if ( v != (uint32_t) v ) + return cfg_error(cfgst, "%s: value out of range", value); + *elem = (uint32_t) v; + return 1; } #endif static int uf_uint(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - unsigned *elem = cfg_address(cfgst, parent, cfgelem); - char *endptr; - unsigned long v = strtoul(value, &endptr, 10); - if ( *value == 0 || *endptr != 0 ) - return cfg_error(cfgst, "%s: not a decimal integer", value); - if ( v != (unsigned) v ) - return cfg_error(cfgst, "%s: value out of range", value); - *elem = (unsigned) v; - return 1; + unsigned *elem = cfg_address(cfgst, parent, cfgelem); + char *endptr; + unsigned long v = strtoul(value, &endptr, 10); + if ( *value == 0 || *endptr != 0 ) + return cfg_error(cfgst, "%s: not a decimal integer", value); + if ( v != (unsigned) v ) + return cfg_error(cfgst, "%s: value out of range", value); + *elem = (unsigned) v; + return 1; } static int uf_int_min_max(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value, int min, int max) { - int *elem = cfg_address(cfgst, parent, cfgelem); - if ( !uf_int(cfgst, parent, cfgelem, first, value) ) - return 0; - else if ( *elem < min || *elem > max ) - return cfg_error(cfgst, "%s: out of range", value); - else - return 1; + int *elem = cfg_address(cfgst, parent, cfgelem); + if ( !uf_int(cfgst, parent, cfgelem, first, value) ) + return 0; + else if ( *elem < min || *elem > max ) + return cfg_error(cfgst, "%s: out of range", value); + else + return 1; } DDSRT_WARNING_MSVC_OFF(4996); @@ -1967,36 +1825,36 @@ DDSRT_WARNING_MSVC_ON(4996); static int uf_participantIndex(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) { - int *elem = cfg_address(cfgst, parent, cfgelem); - if ( ddsrt_strcasecmp(value, "auto") == 0 ) { - *elem = PARTICIPANT_INDEX_AUTO; - return 1; - } else if ( ddsrt_strcasecmp(value, "none") == 0 ) { - *elem = PARTICIPANT_INDEX_NONE; - return 1; - } else { - return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, 120); - } + int *elem = cfg_address(cfgst, parent, cfgelem); + if ( ddsrt_strcasecmp(value, "auto") == 0 ) { + *elem = PARTICIPANT_INDEX_AUTO; + return 1; + } else if ( ddsrt_strcasecmp(value, "none") == 0 ) { + *elem = PARTICIPANT_INDEX_NONE; + return 1; + } else { + return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, 120); + } } static int uf_port(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) { - return uf_int_min_max(cfgst, parent, cfgelem, first, value, 1, 65535); + return uf_int_min_max(cfgst, parent, cfgelem, first, value, 1, 65535); } static int uf_dyn_port(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) { - return uf_int_min_max(cfgst, parent, cfgelem, first, value, -1, 65535); + return uf_int_min_max(cfgst, parent, cfgelem, first, value, -1, 65535); } static int uf_natint(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) { - return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, INT32_MAX); + return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, INT32_MAX); } static int uf_natint_255(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) { - return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, 255); + return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, 255); } static int uf_transport_selector (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) @@ -2065,76 +1923,76 @@ static int uf_deaf_mute (struct cfgst *cfgst, void *parent, struct cfgelem const static int do_update(struct cfgst *cfgst, update_fun_t upd, void *parent, struct cfgelem const * const cfgelem, const char *value, int is_default) { - struct cfgst_node *n; - struct cfgst_nodekey key; - ddsrt_avl_ipath_t np; - int ok; - key.e = cfgelem; - if ( (n = ddsrt_avl_lookup_ipath(&cfgst_found_treedef, &cfgst->found, &key, &np)) == NULL ) { - if ( (n = ddsrt_malloc(sizeof(*n))) == NULL ) - return cfg_error(cfgst, "out of memory"); + struct cfgst_node *n; + struct cfgst_nodekey key; + ddsrt_avl_ipath_t np; + int ok; + key.e = cfgelem; + if ( (n = ddsrt_avl_lookup_ipath(&cfgst_found_treedef, &cfgst->found, &key, &np)) == NULL ) { + if ( (n = ddsrt_malloc(sizeof(*n))) == NULL ) + return cfg_error(cfgst, "out of memory"); - n->key = key; - n->count = 0; - n->failed = 0; - n->is_default = is_default; - ddsrt_avl_insert_ipath(&cfgst_found_treedef, &cfgst->found, n, &np); - } - if ( cfgelem->multiplicity == 0 || n->count < cfgelem->multiplicity ) - ok = upd(cfgst, parent, cfgelem, (n->count == n->failed), value); - else - ok = cfg_error(cfgst, "only %d instance(s) allowed", cfgelem->multiplicity); - n->count++; - if ( !ok ) { - n->failed++; - } - return ok; + n->key = key; + n->count = 0; + n->failed = 0; + n->is_default = is_default; + ddsrt_avl_insert_ipath(&cfgst_found_treedef, &cfgst->found, n, &np); + } + if ( cfgelem->multiplicity == 0 || n->count < cfgelem->multiplicity ) + ok = upd(cfgst, parent, cfgelem, (n->count == n->failed), value); + else + ok = cfg_error(cfgst, "only %d instance(s) allowed", cfgelem->multiplicity); + n->count++; + if ( !ok ) { + n->failed++; + } + return ok; } static int set_default(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - if ( cfgelem->defvalue == NULL ) - return cfg_error(cfgst, "element missing in configuration"); - return do_update(cfgst, cfgelem->update, parent, cfgelem, cfgelem->defvalue, 1); + if ( cfgelem->defvalue == NULL ) + return cfg_error(cfgst, "element missing in configuration"); + return do_update(cfgst, cfgelem->update, parent, cfgelem, cfgelem->defvalue, 1); } static int set_defaults(struct cfgst *cfgst, void *parent, int isattr, struct cfgelem const * const cfgelem, int clear_found) { - const struct cfgelem *ce; - int ok = 1; - for ( ce = cfgelem; ce && ce->name; ce++ ) { - struct cfgst_node *n; - struct cfgst_nodekey key; - key.e = ce; - cfgst_push(cfgst, isattr, ce, parent); - if ( ce->multiplicity == 1 ) { - if ( ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key) == NULL ) { - if ( ce->update ) { - int ok1; - cfgst_push(cfgst, 0, NULL, NULL); - ok1 = set_default(cfgst, parent, ce); - cfgst_pop(cfgst); - ok = ok && ok1; - } - } - if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { - if ( clear_found ) { - ddsrt_avl_delete(&cfgst_found_treedef, &cfgst->found, n); - ddsrt_free(n); - } - } - if ( ce->children ) { - int ok1 = set_defaults(cfgst, parent, 0, ce->children, clear_found); - ok = ok && ok1; - } - if ( ce->attributes ) { - int ok1 = set_defaults(cfgst, parent, 1, ce->attributes, clear_found); - ok = ok && ok1; - } + const struct cfgelem *ce; + int ok = 1; + for ( ce = cfgelem; ce && ce->name; ce++ ) { + struct cfgst_node *n; + struct cfgst_nodekey key; + key.e = ce; + cfgst_push(cfgst, isattr, ce, parent); + if ( ce->multiplicity == 1 ) { + if ( ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key) == NULL ) { + if ( ce->update ) { + int ok1; + cfgst_push(cfgst, 0, NULL, NULL); + ok1 = set_default(cfgst, parent, ce); + cfgst_pop(cfgst); + ok = ok && ok1; } - cfgst_pop(cfgst); + } + if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { + if ( clear_found ) { + ddsrt_avl_delete(&cfgst_found_treedef, &cfgst->found, n); + ddsrt_free(n); + } + } + if ( ce->children ) { + int ok1 = set_defaults(cfgst, parent, 0, ce->children, clear_found); + ok = ok && ok1; + } + if ( ce->attributes ) { + int ok1 = set_defaults(cfgst, parent, 1, ce->attributes, clear_found); + ok = ok && ok1; + } } - return ok; + cfgst_pop(cfgst); + } + return ok; } static void pf_nop(UNUSED_ARG(struct cfgst *cfgst), UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int is_default)) @@ -2143,127 +2001,129 @@ static void pf_nop(UNUSED_ARG(struct cfgst *cfgst), UNUSED_ARG(void *parent), UN static void pf_string(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - char **p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%s%s", *p ? *p : "(null)", is_default ? " [def]" : ""); + char **p = cfg_address(cfgst, parent, cfgelem); + cfg_log(cfgst, "%s%s", *p ? *p : "(null)", is_default ? " [def]" : ""); } static void pf_int64_unit(struct cfgst *cfgst, int64_t value, int is_default, const struct unit *unittab, const char *zero_unit) { - if ( value == 0 ) { - /* 0s is a bit of a special case: we don't want to print 0hr (or - whatever unit will have the greatest multiplier), so hard-code - as 0s */ - cfg_log(cfgst, "0 %s%s", zero_unit, is_default ? " [def]" : ""); - } else { - int64_t m = 0; - const char *unit = NULL; - int i; - for ( i = 0; unittab[i].name != NULL; i++ ) { - if ( unittab[i].multiplier > m && (value % unittab[i].multiplier) == 0 ) { - m = unittab[i].multiplier; - unit = unittab[i].name; - } - } - assert(m > 0); - assert(unit != NULL); - cfg_log(cfgst, "%lld %s%s", value / m, unit, is_default ? " [def]" : ""); + if ( value == 0 ) { + /* 0s is a bit of a special case: we don't want to print 0hr (or + whatever unit will have the greatest multiplier), so hard-code + as 0s */ + cfg_log(cfgst, "0 %s%s", zero_unit, is_default ? " [def]" : ""); + } else { + int64_t m = 0; + const char *unit = NULL; + int i; + for ( i = 0; unittab[i].name != NULL; i++ ) { + if ( unittab[i].multiplier > m && (value % unittab[i].multiplier) == 0 ) { + m = unittab[i].multiplier; + unit = unittab[i].name; + } } + assert(m > 0); + assert(unit != NULL); + cfg_log(cfgst, "%lld %s%s", value / m, unit, is_default ? " [def]" : ""); + } } #ifdef DDSI_INCLUDE_ENCRYPTION static void pf_key(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int is_default)) { - cfg_log(cfgst, ""); + cfg_log(cfgst, ""); } static void pf_cipher(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - q_cipherType *p = cfg_address(cfgst, parent, cfgelem); - if ( q_security_plugin.cipher_type ) { - cfg_log(cfgst, "%s%s", (q_security_plugin.cipher_type) (*p), is_default ? " [def]" : ""); - } + q_cipherType *p = cfg_address(cfgst, parent, cfgelem); + if ( q_security_plugin.cipher_type ) { + cfg_log(cfgst, "%s%s", (q_security_plugin.cipher_type) (*p), is_default ? " [def]" : ""); + } } #endif /* DDSI_INCLUDE_ENCRYPTION */ static void pf_networkAddress(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - char **p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%s%s", *p ? *p : "auto", is_default ? " [def]" : ""); + char **p = cfg_address(cfgst, parent, cfgelem); + cfg_log(cfgst, "%s%s", *p ? *p : "auto", is_default ? " [def]" : ""); } static void pf_participantIndex(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - int *p = cfg_address(cfgst, parent, cfgelem); - switch ( *p ) { - case PARTICIPANT_INDEX_NONE: - cfg_log(cfgst, "none%s", is_default ? " [def]" : ""); - break; - case PARTICIPANT_INDEX_AUTO: - cfg_log(cfgst, "auto%s", is_default ? " [def]" : ""); - break; - default: - cfg_log(cfgst, "%d%s", *p, is_default ? " [def]" : ""); - break; - } + int *p = cfg_address(cfgst, parent, cfgelem); + switch ( *p ) { + case PARTICIPANT_INDEX_NONE: + cfg_log(cfgst, "none%s", is_default ? " [def]" : ""); + break; + case PARTICIPANT_INDEX_AUTO: + cfg_log(cfgst, "auto%s", is_default ? " [def]" : ""); + break; + default: + cfg_log(cfgst, "%d%s", *p, is_default ? " [def]" : ""); + break; + } } static void pf_networkAddresses(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - int i; - char ***p = cfg_address(cfgst, parent, cfgelem); - for ( i = 0; (*p)[i] != NULL; i++ ) - cfg_log(cfgst, "%s%s", (*p)[i], is_default ? " [def]" : ""); + int i; + char ***p = cfg_address(cfgst, parent, cfgelem); + for ( i = 0; (*p)[i] != NULL; i++ ) + cfg_log(cfgst, "%s%s", (*p)[i], is_default ? " [def]" : ""); } static void pf_int(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - int *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%d%s", *p, is_default ? " [def]" : ""); + int *p = cfg_address(cfgst, parent, cfgelem); + cfg_log(cfgst, "%d%s", *p, is_default ? " [def]" : ""); } static void pf_uint(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - unsigned *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%u%s", *p, is_default ? " [def]" : ""); + unsigned *p = cfg_address(cfgst, parent, cfgelem); + cfg_log(cfgst, "%u%s", *p, is_default ? " [def]" : ""); } static void pf_duration(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - const int64_t *elem = cfg_address(cfgst, parent, cfgelem); - if ( *elem == T_NEVER ) - cfg_log(cfgst, "inf%s", is_default ? " [def]" : ""); - else - pf_int64_unit(cfgst, *elem, is_default, unittab_duration, "s"); + const int64_t *elem = cfg_address(cfgst, parent, cfgelem); + if ( *elem == T_NEVER ) + cfg_log(cfgst, "inf%s", is_default ? " [def]" : ""); + else + pf_int64_unit(cfgst, *elem, is_default, unittab_duration, "s"); } #ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING static void pf_bandwidth(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - const uint32_t *elem = cfg_address(cfgst, parent, cfgelem); - if ( *elem == 0 ) - cfg_log(cfgst, "inf%s", is_default ? " [def]" : ""); - else - pf_int64_unit(cfgst, *elem, is_default, unittab_bandwidth_Bps, "B/s"); + const uint32_t *elem = cfg_address(cfgst, parent, cfgelem); + if ( *elem == 0 ) + cfg_log(cfgst, "inf%s", is_default ? " [def]" : ""); + else + pf_int64_unit(cfgst, *elem, is_default, unittab_bandwidth_Bps, "B/s"); } #endif static void pf_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - const int *elem = cfg_address(cfgst, parent, cfgelem); - pf_int64_unit(cfgst, *elem, is_default, unittab_memsize, "B"); + const int *elem = cfg_address(cfgst, parent, cfgelem); + pf_int64_unit(cfgst, *elem, is_default, unittab_memsize, "B"); } +#if 0 static void pf_int32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - int32_t *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%d%s", *p, is_default ? " [def]" : ""); + int32_t *p = cfg_address(cfgst, parent, cfgelem); + cfg_log(cfgst, "%d%s", *p, is_default ? " [def]" : ""); } +#endif #if 0 static void pf_uint32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - uint32_t *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%u%s", *p, is_default ? " [def]" : ""); + uint32_t *p = cfg_address(cfgst, parent, cfgelem); + cfg_log(cfgst, "%u%s", *p, is_default ? " [def]" : ""); } #endif @@ -2278,11 +2138,11 @@ static void pf_maybe_int32(struct cfgst *cfgst, void *parent, struct cfgelem con static void pf_maybe_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - struct config_maybe_uint32 *p = cfg_address(cfgst, parent, cfgelem); - if ( p->isdefault ) - cfg_log(cfgst, "default%s", is_default ? " [def]" : ""); - else - pf_int64_unit(cfgst, p->value, is_default, unittab_memsize, "B"); + struct config_maybe_uint32 *p = cfg_address(cfgst, parent, cfgelem); + if ( p->isdefault ) + cfg_log(cfgst, "default%s", is_default ? " [def]" : ""); + else + pf_int64_unit(cfgst, p->value, is_default, unittab_memsize, "B"); } static void pf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) @@ -2296,584 +2156,578 @@ static void pf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const static void pf_boolean(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - int *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%s%s", *p ? "true" : "false", is_default ? " [def]" : ""); -} - -static void pf_negated_boolean(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - int *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%s%s", *p ? "false" : "true", is_default ? " [def]" : ""); + int *p = cfg_address(cfgst, parent, cfgelem); + cfg_log(cfgst, "%s%s", *p ? "true" : "false", is_default ? " [def]" : ""); } static int uf_standards_conformance(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - static const char *vs[] = { - "pedantic", "strict", "lax", NULL - }; - static const uint32_t lc[] = { - NN_SC_PEDANTIC, NN_SC_STRICT, NN_SC_LAX, 0 - }; - enum nn_standards_conformance *elem = cfg_address(cfgst, parent, cfgelem); - int idx = list_index(vs, value); - assert(sizeof(vs) / sizeof(*vs) == sizeof(lc) / sizeof(*lc)); - if ( idx < 0 ) - return cfg_error(cfgst, "'%s': undefined value", value); - else { - *elem = lc[idx]; - return 1; - } + static const char *vs[] = { + "pedantic", "strict", "lax", NULL + }; + static const uint32_t lc[] = { + NN_SC_PEDANTIC, NN_SC_STRICT, NN_SC_LAX, 0 + }; + enum nn_standards_conformance *elem = cfg_address(cfgst, parent, cfgelem); + int idx = list_index(vs, value); + assert(sizeof(vs) / sizeof(*vs) == sizeof(lc) / sizeof(*lc)); + if ( idx < 0 ) + return cfg_error(cfgst, "'%s': undefined value", value); + else { + *elem = lc[idx]; + return 1; + } } static void pf_standards_conformance(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - enum nn_standards_conformance *p = cfg_address(cfgst, parent, cfgelem); - const char *str = "INVALID"; - switch ( *p ) { - case NN_SC_PEDANTIC: str = "pedantic"; break; - case NN_SC_STRICT: str = "strict"; break; - case NN_SC_LAX: str = "lax"; break; - } - cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); + enum nn_standards_conformance *p = cfg_address(cfgst, parent, cfgelem); + const char *str = "INVALID"; + switch ( *p ) { + case NN_SC_PEDANTIC: str = "pedantic"; break; + case NN_SC_STRICT: str = "strict"; break; + case NN_SC_LAX: str = "lax"; break; + } + cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); } static unsigned uint32_popcnt (uint32_t x) { - unsigned n = 0; - while (x != 0) - { - n += ((x & 1u) != 0); - x >>= 1; - } - return n; + unsigned n = 0; + while (x != 0) + { + n += ((x & 1u) != 0); + x >>= 1; + } + return n; } static void do_print_uint32_bitset (struct cfgst *cfgst, uint32_t mask, size_t ncodes, const char **names, const uint32_t *codes, const char *suffix) { - char res[256] = "", *resp = res; - const char *prefix = ""; + char res[256] = "", *resp = res; + const char *prefix = ""; #ifndef NDEBUG - { - size_t max = 0; - for (size_t i = 0; i < ncodes; i++ ) - max += 1 + strlen(names[i]); - max += 11; /* ,0x%x */ - max += 1; /* \0 */ - assert(max <= sizeof(res)); - } + { + size_t max = 0; + for (size_t i = 0; i < ncodes; i++ ) + max += 1 + strlen(names[i]); + max += 11; /* ,0x%x */ + max += 1; /* \0 */ + assert(max <= sizeof(res)); + } #endif - while (mask) { - size_t i_best = 0; - unsigned pc_best = 0; - for (size_t i = 0; i < ncodes; i++) { - uint32_t m = mask & codes[i]; - if (m == codes[i]) { - unsigned pc = uint32_popcnt (m); - if (pc > pc_best) { - i_best = i; - pc_best = pc; - } - } - } - if (pc_best != 0) { - resp += snprintf(resp, 256, "%s%s", prefix, names[i_best]); - mask &= ~codes[i_best]; - prefix = ","; - } else { - resp += snprintf (resp, 256, "%s0x%x", prefix, (unsigned) mask); - mask = 0; + while (mask) { + size_t i_best = 0; + unsigned pc_best = 0; + for (size_t i = 0; i < ncodes; i++) { + uint32_t m = mask & codes[i]; + if (m == codes[i]) { + unsigned pc = uint32_popcnt (m); + if (pc > pc_best) { + i_best = i; + pc_best = pc; } + } } - assert (resp <= res + sizeof(res)); - cfg_log (cfgst, "%s%s", res, suffix); + if (pc_best != 0) { + resp += snprintf(resp, 256, "%s%s", prefix, names[i_best]); + mask &= ~codes[i_best]; + prefix = ","; + } else { + resp += snprintf (resp, 256, "%s0x%x", prefix, (unsigned) mask); + mask = 0; + } + } + assert (resp <= res + sizeof(res)); + cfg_log (cfgst, "%s%s", res, suffix); } static void pf_logcat(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int is_default)) { - /* can't do default indicator: user may have specified Verbosity, in - which case EnableCategory is at default, but for these two - settings, I don't mind. */ - do_print_uint32_bitset (cfgst, config.enabled_logcats, sizeof(logcat_codes) / sizeof(*logcat_codes), logcat_names, logcat_codes, ""); + /* can't do default indicator: user may have specified Verbosity, in + which case EnableCategory is at default, but for these two + settings, I don't mind. */ + do_print_uint32_bitset (cfgst, config.enabled_logcats, sizeof(logcat_codes) / sizeof(*logcat_codes), logcat_names, logcat_codes, ""); } static void pf_xcheck(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { - const uint32_t *p = cfg_address(cfgst, parent, cfgelem); + const uint32_t *p = cfg_address(cfgst, parent, cfgelem); #ifndef NDEBUG - const char *suffix = is_default ? " [def]" : ""; + const char *suffix = is_default ? " [def]" : ""; #else - const char *suffix = " [ignored]"; - (void)is_default; + const char *suffix = " [ignored]"; + (void)is_default; #endif - do_print_uint32_bitset (cfgst, *p, sizeof(xcheck_codes) / sizeof(*xcheck_codes), xcheck_names, xcheck_codes, suffix); + do_print_uint32_bitset (cfgst, *p, sizeof(xcheck_codes) / sizeof(*xcheck_codes), xcheck_names, xcheck_codes, suffix); } static void print_configitems(struct cfgst *cfgst, void *parent, int isattr, struct cfgelem const * const cfgelem, int unchecked) { - const struct cfgelem *ce; - for ( ce = cfgelem; ce && ce->name; ce++ ) { - struct cfgst_nodekey key; - struct cfgst_node *n; - if ( ce->name[0] == '>' || ce->name[0] == '|') /* moved or deprecated, so don't care */ - continue; - key.e = ce; - cfgst_push(cfgst, isattr, ce, parent); - if ( ce->multiplicity == 1 ) { - if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { - cfgst_push(cfgst, 0, NULL, NULL); - ce->print(cfgst, parent, ce, n->is_default); - cfgst_pop(cfgst); - } else { - if ( unchecked && ce->print ) { - cfgst_push(cfgst, 0, NULL, NULL); - ce->print(cfgst, parent, ce, 0); - cfgst_pop(cfgst); - } - } + const struct cfgelem *ce; + for ( ce = cfgelem; ce && ce->name; ce++ ) { + struct cfgst_nodekey key; + struct cfgst_node *n; + if ( ce->name[0] == '>' || ce->name[0] == '|') /* moved or deprecated, so don't care */ + continue; + key.e = ce; + cfgst_push(cfgst, isattr, ce, parent); + if ( ce->multiplicity == 1 ) { + if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { + cfgst_push(cfgst, 0, NULL, NULL); + ce->print(cfgst, parent, ce, n->is_default); + cfgst_pop(cfgst); + } else { + if ( unchecked && ce->print ) { + cfgst_push(cfgst, 0, NULL, NULL); + ce->print(cfgst, parent, ce, 0); + cfgst_pop(cfgst); + } + } - if ( ce->children ) - print_configitems(cfgst, parent, 0, ce->children, unchecked); - if ( ce->attributes ) - print_configitems(cfgst, parent, 1, ce->attributes, unchecked); - } else { - struct config_listelem *p = cfg_deref_address(cfgst, parent, ce); - while ( p ) { - cfgst_push(cfgst, 0, NULL, NULL); - if ( ce->print ) { - ce->print(cfgst, p, ce, 0); - } - cfgst_pop(cfgst); - if ( ce->attributes ) - print_configitems(cfgst, p, 1, ce->attributes, 1); - if ( ce->children ) - print_configitems(cfgst, p, 0, ce->children, 1); - p = p->next; - } + if ( ce->children ) + print_configitems(cfgst, parent, 0, ce->children, unchecked); + if ( ce->attributes ) + print_configitems(cfgst, parent, 1, ce->attributes, unchecked); + } else { + struct config_listelem *p = cfg_deref_address(cfgst, parent, ce); + while ( p ) { + cfgst_push(cfgst, 0, NULL, NULL); + if ( ce->print ) { + ce->print(cfgst, p, ce, 0); } cfgst_pop(cfgst); + if ( ce->attributes ) + print_configitems(cfgst, p, 1, ce->attributes, 1); + if ( ce->children ) + print_configitems(cfgst, p, 0, ce->children, 1); + p = p->next; + } } + cfgst_pop(cfgst); + } } static void free_all_elements(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - const struct cfgelem *ce; + const struct cfgelem *ce; - for ( ce = cfgelem; ce && ce->name; ce++ ) { - if ( ce->name[0] == '>' ) /* moved, so don't care */ - continue; + for ( ce = cfgelem; ce && ce->name; ce++ ) { + if ( ce->name[0] == '>' ) /* moved, so don't care */ + continue; - if ( ce->free ) - ce->free(cfgst, parent, ce); + if ( ce->free ) + ce->free(cfgst, parent, ce); - if ( ce->multiplicity == 1 ) { - if ( ce->children ) - free_all_elements(cfgst, parent, ce->children); - if ( ce->attributes ) - free_all_elements(cfgst, parent, ce->attributes); - } else { - struct config_listelem *p = cfg_deref_address(cfgst, parent, ce); - struct config_listelem *r; - while ( p ) { - if ( ce->attributes ) - free_all_elements(cfgst, p, ce->attributes); - if ( ce->children ) - free_all_elements(cfgst, p, ce->children); - r = p; - p = p->next; - ddsrt_free(r); - } - } + if ( ce->multiplicity == 1 ) { + if ( ce->children ) + free_all_elements(cfgst, parent, ce->children); + if ( ce->attributes ) + free_all_elements(cfgst, parent, ce->attributes); + } else { + struct config_listelem *p = cfg_deref_address(cfgst, parent, ce); + struct config_listelem *r; + while ( p ) { + if ( ce->attributes ) + free_all_elements(cfgst, p, ce->attributes); + if ( ce->children ) + free_all_elements(cfgst, p, ce->children); + r = p; + p = p->next; + ddsrt_free(r); + } } + } } static void free_configured_elements(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - const struct cfgelem *ce; - for ( ce = cfgelem; ce && ce->name; ce++ ) { - struct cfgst_nodekey key; - struct cfgst_node *n; - if ( ce->name[0] == '>' ) /* moved, so don't care */ - continue; - key.e = ce; - if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { - if ( ce->free && n->count > n->failed ) - ce->free(cfgst, parent, ce); - } - - if ( ce->multiplicity == 1 ) { - if ( ce->children ) - free_configured_elements(cfgst, parent, ce->children); - if ( ce->attributes ) - free_configured_elements(cfgst, parent, ce->attributes); - } else { - struct config_listelem *p = cfg_deref_address(cfgst, parent, ce); - struct config_listelem *r; - while ( p ) { - if ( ce->attributes ) - free_all_elements(cfgst, p, ce->attributes); - if ( ce->children ) - free_all_elements(cfgst, p, ce->children); - r = p; - p = p->next; - ddsrt_free(r); - } - } + const struct cfgelem *ce; + for ( ce = cfgelem; ce && ce->name; ce++ ) { + struct cfgst_nodekey key; + struct cfgst_node *n; + if ( ce->name[0] == '>' ) /* moved, so don't care */ + continue; + key.e = ce; + if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { + if ( ce->free && n->count > n->failed ) + ce->free(cfgst, parent, ce); } + + if ( ce->multiplicity == 1 ) { + if ( ce->children ) + free_configured_elements(cfgst, parent, ce->children); + if ( ce->attributes ) + free_configured_elements(cfgst, parent, ce->attributes); + } else { + struct config_listelem *p = cfg_deref_address(cfgst, parent, ce); + struct config_listelem *r; + while ( p ) { + if ( ce->attributes ) + free_all_elements(cfgst, p, ce->attributes); + if ( ce->children ) + free_all_elements(cfgst, p, ce->children); + r = p; + p = p->next; + ddsrt_free(r); + } + } + } } static int matching_name_index(const char *name_w_aliases, const char *name) { - const char *ns = name_w_aliases, *p = strchr(ns, '|'); - int idx = 0; - while ( p ) { - if ( ddsrt_strncasecmp(ns, name, (size_t) (p - ns)) == 0 && name[p - ns] == 0 ) { - /* ns upto the pipe symbol is a prefix of name, and name is terminated at that point */ - return idx; - } - /* If primary name followed by '||' instead of '|', aliases are non-warning */ - ns = p + 1 + (idx == 0 && p[1] == '|'); - p = strchr(ns, '|'); - idx++; + const char *ns = name_w_aliases, *p = strchr(ns, '|'); + int idx = 0; + while ( p ) { + if ( ddsrt_strncasecmp(ns, name, (size_t) (p - ns)) == 0 && name[p - ns] == 0 ) { + /* ns upto the pipe symbol is a prefix of name, and name is terminated at that point */ + return idx; } - return (ddsrt_strcasecmp(ns, name) == 0) ? idx : -1; + /* If primary name followed by '||' instead of '|', aliases are non-warning */ + ns = p + 1 + (idx == 0 && p[1] == '|'); + p = strchr(ns, '|'); + idx++; + } + return (ddsrt_strcasecmp(ns, name) == 0) ? idx : -1; } static const struct cfgelem *lookup_redirect(const char *target) { - const struct cfgelem *cfgelem = ddsi2_cfgelems; - char *target_copy = ddsrt_strdup(target), *p1; - const char *p = target_copy; - while ( p ) { - p1 = strchr(p, '/'); - if ( p1 ) *p1++ = 0; - for ( ; cfgelem->name; cfgelem++ ) { - /* not supporting multiple redirects */ - assert(cfgelem->name[0] != '>'); - if ( matching_name_index(cfgelem->name, p) >= 0 ) - break; - } - if ( p1 ) { - cfgelem = cfgelem->children; - } - p = p1; + const struct cfgelem *cfgelem = ddsi2_cfgelems; + char *target_copy = ddsrt_strdup(target), *p1; + const char *p = target_copy; + while ( p ) { + p1 = strchr(p, '/'); + if ( p1 ) *p1++ = 0; + for ( ; cfgelem->name; cfgelem++ ) { + /* not supporting multiple redirects */ + assert(cfgelem->name[0] != '>'); + if ( matching_name_index(cfgelem->name, p) >= 0 ) + break; } - ddsrt_free(target_copy); - return cfgelem; + if ( p1 ) { + cfgelem = cfgelem->children; + } + p = p1; + } + ddsrt_free(target_copy); + return cfgelem; } static int proc_elem_open(void *varg, UNUSED_ARG(uintptr_t parentinfo), UNUSED_ARG(uintptr_t *eleminfo), const char *name) { - struct cfgst * const cfgst = varg; - const struct cfgelem *cfgelem = cfgst_tos(cfgst); - const struct cfgelem *cfg_subelem; - int moved = 0; - if ( cfgelem == NULL ) { - /* Ignoring, but do track the structure so we can know when to stop ignoring */ - cfgst_push(cfgst, 0, NULL, NULL); - return 1; - } - for ( cfg_subelem = cfgelem->children; cfg_subelem && cfg_subelem->name && strcmp(cfg_subelem->name, "*") != 0; cfg_subelem++ ) { - const char *csename = cfg_subelem->name; - int idx; - moved = (csename[0] == '>'); - if ( moved ) - csename++; - idx = matching_name_index(csename, name); + struct cfgst * const cfgst = varg; + const struct cfgelem *cfgelem = cfgst_tos(cfgst); + const struct cfgelem *cfg_subelem; + int moved = 0; + if ( cfgelem == NULL ) { + /* Ignoring, but do track the structure so we can know when to stop ignoring */ + cfgst_push(cfgst, 0, NULL, NULL); + return 1; + } + for ( cfg_subelem = cfgelem->children; cfg_subelem && cfg_subelem->name && strcmp(cfg_subelem->name, "*") != 0; cfg_subelem++ ) { + const char *csename = cfg_subelem->name; + int idx; + moved = (csename[0] == '>'); + if ( moved ) + csename++; + idx = matching_name_index(csename, name); #if WARN_DEPRECATED_ALIAS - if ( idx > 0 ) { - if (csename[0] == '|') { - cfg_warning(cfgst, "'%s': deprecated setting", name); - } else { - int n = (int) (strchr(csename, '|') - csename); - if ( csename[n + 1] != '|' ) { - cfg_warning(cfgst, "'%s': deprecated alias for '%*.*s'", name, n, n, csename); - } - } - } -#endif - if ( idx >= 0 ) { - break; + if ( idx > 0 ) { + if (csename[0] == '|') { + cfg_warning(cfgst, "'%s': deprecated setting", name); + } else { + int n = (int) (strchr(csename, '|') - csename); + if ( csename[n + 1] != '|' ) { + cfg_warning(cfgst, "'%s': deprecated alias for '%*.*s'", name, n, n, csename); } + } } - if ( cfg_subelem == NULL || cfg_subelem->name == NULL ) { - cfgst_push(cfgst, 0, NULL, NULL); - return cfg_error(cfgst, "%s: unknown element", name); - } else if ( strcmp(cfg_subelem->name, "*") == 0 ) { - /* Push a marker that we are to ignore this part of the DOM tree */ - cfgst_push(cfgst, 0, NULL, NULL); - return 1; - } else { - void *parent, *dynparent; +#endif + if ( idx >= 0 ) { + break; + } + } + if ( cfg_subelem == NULL || cfg_subelem->name == NULL ) { + cfgst_push(cfgst, 0, NULL, NULL); + return cfg_error(cfgst, "%s: unknown element", name); + } else if ( strcmp(cfg_subelem->name, "*") == 0 ) { + /* Push a marker that we are to ignore this part of the DOM tree */ + cfgst_push(cfgst, 0, NULL, NULL); + return 1; + } else { + void *parent, *dynparent; - if ( moved ) { + if ( moved ) { #if WARN_DEPRECATED_ALIAS - cfg_warning(cfgst, "'%s': deprecated alias for '%s'", name, cfg_subelem->defvalue); + cfg_warning(cfgst, "'%s': deprecated alias for '%s'", name, cfg_subelem->defvalue); #endif - cfg_subelem = lookup_redirect(cfg_subelem->defvalue); - } - - parent = cfgst_parent(cfgst); - assert(cfgelem->init || cfgelem->multiplicity == 1); /*multi-items must have an init-func */ - if ( cfg_subelem->init ) { - if ( cfg_subelem->init(cfgst, parent, cfg_subelem) < 0 ) - return 0; - } - - if ( cfg_subelem->multiplicity != 1 ) - dynparent = cfg_deref_address(cfgst, parent, cfg_subelem); - else - dynparent = parent; - - cfgst_push(cfgst, 0, cfg_subelem, dynparent); - return 1; + cfg_subelem = lookup_redirect(cfg_subelem->defvalue); } + + parent = cfgst_parent(cfgst); + assert(cfgelem->init || cfgelem->multiplicity == 1); /*multi-items must have an init-func */ + if ( cfg_subelem->init ) { + if ( cfg_subelem->init(cfgst, parent, cfg_subelem) < 0 ) + return 0; + } + + if ( cfg_subelem->multiplicity != 1 ) + dynparent = cfg_deref_address(cfgst, parent, cfg_subelem); + else + dynparent = parent; + + cfgst_push(cfgst, 0, cfg_subelem, dynparent); + return 1; + } } static int proc_attr(void *varg, UNUSED_ARG(uintptr_t eleminfo), const char *name, const char *value) { - /* All attributes are processed immediately after opening the element */ - struct cfgst * const cfgst = varg; - const struct cfgelem *cfgelem = cfgst_tos(cfgst); - const struct cfgelem *cfg_attr; - if ( cfgelem == NULL ) - return 1; - for ( cfg_attr = cfgelem->attributes; cfg_attr && cfg_attr->name; cfg_attr++ ) { - if ( ddsrt_strcasecmp(cfg_attr->name, name) == 0 ) - break; - } - if ( cfg_attr == NULL || cfg_attr->name == NULL ) - return cfg_error(cfgst, "%s: unknown attribute", name); - else { - void *parent = cfgst_parent(cfgst); - char *xvalue = ddsrt_expand_envvars(value); - int ok; - cfgst_push(cfgst, 1, cfg_attr, parent); - ok = do_update(cfgst, cfg_attr->update, parent, cfg_attr, xvalue, 0); - cfgst_pop(cfgst); - ddsrt_free(xvalue); - return ok; - } + /* All attributes are processed immediately after opening the element */ + struct cfgst * const cfgst = varg; + const struct cfgelem *cfgelem = cfgst_tos(cfgst); + const struct cfgelem *cfg_attr; + if ( cfgelem == NULL ) + return 1; + for ( cfg_attr = cfgelem->attributes; cfg_attr && cfg_attr->name; cfg_attr++ ) { + if ( ddsrt_strcasecmp(cfg_attr->name, name) == 0 ) + break; + } + if ( cfg_attr == NULL || cfg_attr->name == NULL ) + return cfg_error(cfgst, "%s: unknown attribute", name); + else { + void *parent = cfgst_parent(cfgst); + char *xvalue = ddsrt_expand_envvars(value); + int ok; + cfgst_push(cfgst, 1, cfg_attr, parent); + ok = do_update(cfgst, cfg_attr->update, parent, cfg_attr, xvalue, 0); + cfgst_pop(cfgst); + ddsrt_free(xvalue); + return ok; + } } static int proc_elem_data(void *varg, UNUSED_ARG(uintptr_t eleminfo), const char *value) { - struct cfgst * const cfgst = varg; - const struct cfgelem *cfgelem = cfgst_tos(cfgst); - if ( cfgelem == NULL ) - return 1; - if ( cfgelem->update == 0 ) - return cfg_error(cfgst, "%s: no data expected", value); - else { - void *parent = cfgst_parent(cfgst); - char *xvalue = ddsrt_expand_envvars(value); - int ok; - cfgst_push(cfgst, 0, NULL, parent); - ok = do_update(cfgst, cfgelem->update, parent, cfgelem, xvalue, 0); - cfgst_pop(cfgst); - ddsrt_free(xvalue); - return ok; - } + struct cfgst * const cfgst = varg; + const struct cfgelem *cfgelem = cfgst_tos(cfgst); + if ( cfgelem == NULL ) + return 1; + if ( cfgelem->update == 0 ) + return cfg_error(cfgst, "%s: no data expected", value); + else { + void *parent = cfgst_parent(cfgst); + char *xvalue = ddsrt_expand_envvars(value); + int ok; + cfgst_push(cfgst, 0, NULL, parent); + ok = do_update(cfgst, cfgelem->update, parent, cfgelem, xvalue, 0); + cfgst_pop(cfgst); + ddsrt_free(xvalue); + return ok; + } } static int proc_elem_close(void *varg, UNUSED_ARG(uintptr_t eleminfo)) { - struct cfgst * const cfgst = varg; - const struct cfgelem * cfgelem = cfgst_tos(cfgst); - int ok = 1; - if ( cfgelem && cfgelem->multiplicity != 1 ) { - void *parent = cfgst_parent(cfgst); - int ok1; - ok1 = set_defaults(cfgst, parent, 1, cfgelem->attributes, 1); - ok = ok && ok1; - ok1 = set_defaults(cfgst, parent, 0, cfgelem->children, 1); - ok = ok && ok1; - } - cfgst_pop(cfgst); - return ok; + struct cfgst * const cfgst = varg; + const struct cfgelem * cfgelem = cfgst_tos(cfgst); + int ok = 1; + if ( cfgelem && cfgelem->multiplicity != 1 ) { + void *parent = cfgst_parent(cfgst); + int ok1; + ok1 = set_defaults(cfgst, parent, 1, cfgelem->attributes, 1); + ok = ok && ok1; + ok1 = set_defaults(cfgst, parent, 0, cfgelem->children, 1); + ok = ok && ok1; + } + cfgst_pop(cfgst); + return ok; } static void proc_error(void *varg, const char *msg, int line) { - struct cfgst * const cfgst = varg; - cfg_error(cfgst, "parser error %s at line %d", msg, line); + struct cfgst * const cfgst = varg; + cfg_error(cfgst, "parser error %s at line %d", msg, line); } static int cfgst_node_cmp(const void *va, const void *vb) { - return memcmp(va, vb, sizeof(struct cfgst_nodekey)); + return memcmp(va, vb, sizeof(struct cfgst_nodekey)); } #ifdef DDSI_INCLUDE_NETWORK_CHANNELS static int set_default_channel(struct config *cfg) { - if ( cfg->channels == NULL ) { - /* create one default channel if none configured */ - struct config_channel_listelem *c; - if ( (c = ddsrt_malloc(sizeof(*c))) == NULL ) - return ERR_OUT_OF_MEMORY; - c->next = NULL; - c->name = ddsrt_strdup("user"); - c->priority = 0; - c->resolution = 1 * T_MILLISECOND; + if ( cfg->channels == NULL ) { + /* create one default channel if none configured */ + struct config_channel_listelem *c; + if ( (c = ddsrt_malloc(sizeof(*c))) == NULL ) + return ERR_OUT_OF_MEMORY; + c->next = NULL; + c->name = ddsrt_strdup("user"); + c->priority = 0; + c->resolution = 1 * T_MILLISECOND; #ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING - c->data_bandwidth_limit = 0; - c->auxiliary_bandwidth_limit = 0; + c->data_bandwidth_limit = 0; + c->auxiliary_bandwidth_limit = 0; #endif - c->diffserv_field = 0; - c->channel_reader_ts = NULL; - c->queueId = 0; - c->dqueue = NULL; - c->evq = NULL; - c->transmit_conn = NULL; - cfg->channels = c; - } - return 0; + c->diffserv_field = 0; + c->channel_reader_ts = NULL; + c->queueId = 0; + c->dqueue = NULL; + c->evq = NULL; + c->transmit_conn = NULL; + cfg->channels = c; + } + return 0; } static int sort_channels_cmp(const void *va, const void *vb) { - const struct config_channel_listelem * const *a = va; - const struct config_channel_listelem * const *b = vb; - return ((*a)->priority == (*b)->priority) ? 0 : ((*a)->priority < (*b)->priority) ? -1 : 1; + const struct config_channel_listelem * const *a = va; + const struct config_channel_listelem * const *b = vb; + return ((*a)->priority == (*b)->priority) ? 0 : ((*a)->priority < (*b)->priority) ? -1 : 1; } static int sort_channels_check_nodups(struct config *cfg) { - /* Selecting a channel is much easier & more elegant if the channels - are sorted on descending priority. While we do retain the list - structure, sorting is much easier in an array, and hence we - convert back and forth. */ - struct config_channel_listelem **ary, *c; - unsigned i, n; - int result; + /* Selecting a channel is much easier & more elegant if the channels + are sorted on descending priority. While we do retain the list + structure, sorting is much easier in an array, and hence we + convert back and forth. */ + struct config_channel_listelem **ary, *c; + unsigned i, n; + int result; - n = 0; - for ( c = cfg->channels; c; c = c->next ) - n++; - assert(n > 0); + n = 0; + for ( c = cfg->channels; c; c = c->next ) + n++; + assert(n > 0); - ary = ddsrt_malloc(n * sizeof(*ary)); + ary = ddsrt_malloc(n * sizeof(*ary)); - i = 0; - for ( c = cfg->channels; c; c = c->next ) - ary[i++] = c; - qsort(ary, n, sizeof(*ary), sort_channels_cmp); + i = 0; + for ( c = cfg->channels; c; c = c->next ) + ary[i++] = c; + qsort(ary, n, sizeof(*ary), sort_channels_cmp); - result = 0; - for ( i = 0; i < n - 1; i++ ) { - if ( ary[i]->priority == ary[i + 1]->priority ) { - DDS_ERROR("config: duplicate channel definition for priority %u: channels %s and %s\n", - ary[i]->priority, ary[i]->name, ary[i + 1]->name); - result = ERR_ENTITY_EXISTS; - } + result = 0; + for ( i = 0; i < n - 1; i++ ) { + if ( ary[i]->priority == ary[i + 1]->priority ) { + DDS_ERROR("config: duplicate channel definition for priority %u: channels %s and %s\n", + ary[i]->priority, ary[i]->name, ary[i + 1]->name); + result = ERR_ENTITY_EXISTS; } + } - if ( result == 0 ) { - cfg->channels = ary[0]; - for ( i = 0; i < n - 1; i++ ) - ary[i]->next = ary[i + 1]; - ary[i]->next = NULL; - cfg->max_channel = ary[i]; - } + if ( result == 0 ) { + cfg->channels = ary[0]; + for ( i = 0; i < n - 1; i++ ) + ary[i]->next = ary[i + 1]; + ary[i]->next = NULL; + cfg->max_channel = ary[i]; + } - ddsrt_free(ary); - return result; + ddsrt_free(ary); + return result; } #endif /* DDSI_INCLUDE_NETWORK_CHANNELS */ struct cfgst * config_init (const char *configfile) { - int ok = 1; - struct cfgst *cfgst; + int ok = 1; + struct cfgst *cfgst; - memset(&config, 0, sizeof(config)); + memset(&config, 0, sizeof(config)); - config.tracingOutputFile = stderr; - config.enabled_logcats = DDS_LC_ERROR | DDS_LC_WARNING; + config.tracingOutputFile = stderr; + config.enabled_logcats = DDS_LC_ERROR | DDS_LC_WARNING; - /* eventually, we domainId.value will be the real domain id selected, even if it was configured - to the default of "any" and has "isdefault" set; initializing it to the default-default - value of 0 means "any" in the config & DDS_DOMAIN_DEFAULT in create participant automatically - ends up on the right value */ - config.domainId.value = 0; + /* eventually, we domainId.value will be the real domain id selected, even if it was configured + to the default of "any" and has "isdefault" set; initializing it to the default-default + value of 0 means "any" in the config & DDS_DOMAIN_DEFAULT in create participant automatically + ends up on the right value */ + config.domainId.value = 0; - cfgst = ddsrt_malloc(sizeof(*cfgst)); - memset(cfgst, 0, sizeof(*cfgst)); + cfgst = ddsrt_malloc(sizeof(*cfgst)); + memset(cfgst, 0, sizeof(*cfgst)); - ddsrt_avl_init(&cfgst_found_treedef, &cfgst->found); - cfgst->cfg = &config; - cfgst->error = 0; + ddsrt_avl_init(&cfgst_found_treedef, &cfgst->found); + cfgst->cfg = &config; + cfgst->error = 0; - /* configfile == NULL will get you the default configuration */ - if (configfile) { - char *copy = ddsrt_strdup(configfile), *cursor = copy; - struct ddsrt_xmlp_callbacks cb; + /* configfile == NULL will get you the default configuration */ + if (configfile) { + char *copy = ddsrt_strdup(configfile), *cursor = copy; + struct ddsrt_xmlp_callbacks cb; - cb.attr = proc_attr; - cb.elem_close = proc_elem_close; - cb.elem_data = proc_elem_data; - cb.elem_open = proc_elem_open; - cb.error = proc_error; + cb.attr = proc_attr; + cb.elem_close = proc_elem_close; + cb.elem_data = proc_elem_data; + cb.elem_open = proc_elem_open; + cb.error = proc_error; - while (ok && cursor && cursor[0]) { - struct ddsrt_xmlp_state *qx; - FILE *fp; - char *tok; - tok = cursor; - if (tok[0] == '<') { - /* Read XML directly from input string */ - qx = ddsrt_xmlp_new_string (tok, cfgst, &cb); - ddsrt_xmlp_set_requireEOF (qx, 0); - fp = NULL; - } else { - char *comma; - if ((comma = strchr (cursor, ',')) == NULL) { - cursor = NULL; - } else { - *comma = 0; - cursor = comma + 1; - } - DDSRT_WARNING_MSVC_OFF(4996); - if ((fp = fopen(tok, "r")) == NULL) { - if (strncmp(tok, "file://", 7) != 0 || (fp = fopen(tok + 7, "r")) == NULL) { - DDS_ERROR("can't open configuration file %s\n", tok); - ddsrt_free(copy); - ddsrt_free(cfgst); - return NULL; - } - } - DDSRT_WARNING_MSVC_ON(4996); - qx = ddsrt_xmlp_new_file(fp, cfgst, &cb); - } - cfgst_push(cfgst, 0, &root_cfgelem, &config); - - ok = (ddsrt_xmlp_parse(qx) >= 0) && !cfgst->error; - /* Pop until stack empty: error handling is rather brutal */ - assert(!ok || cfgst->path_depth == 1); - while (cfgst->path_depth > 0) { - cfgst_pop(cfgst); - } - if (fp) { - fclose(fp); - } else if (ok) { - cursor = tok + ddsrt_xmlp_get_bufpos (qx); - } - ddsrt_xmlp_free(qx); - while (cursor && cursor[0] == ',') { - cursor++; - } + while (ok && cursor && cursor[0]) { + struct ddsrt_xmlp_state *qx; + FILE *fp; + char *tok; + tok = cursor; + if (tok[0] == '<') { + /* Read XML directly from input string */ + qx = ddsrt_xmlp_new_string (tok, cfgst, &cb); + ddsrt_xmlp_set_requireEOF (qx, 0); + fp = NULL; + } else { + char *comma; + if ((comma = strchr (cursor, ',')) == NULL) { + cursor = NULL; + } else { + *comma = 0; + cursor = comma + 1; } - ddsrt_free(copy); - } + DDSRT_WARNING_MSVC_OFF(4996); + if ((fp = fopen(tok, "r")) == NULL) { + if (strncmp(tok, "file://", 7) != 0 || (fp = fopen(tok + 7, "r")) == NULL) { + DDS_ERROR("can't open configuration file %s\n", tok); + ddsrt_free(copy); + ddsrt_free(cfgst); + return NULL; + } + } + DDSRT_WARNING_MSVC_ON(4996); + qx = ddsrt_xmlp_new_file(fp, cfgst, &cb); + } + cfgst_push(cfgst, 0, &root_cfgelem, &config); - /* Set defaults for everything not set that we have a default value - for, signal errors for things unset but without a default. */ - { - int ok1 = set_defaults(cfgst, cfgst->cfg, 0, root_cfgelems, 0); - ok = ok && ok1; + ok = (ddsrt_xmlp_parse(qx) >= 0) && !cfgst->error; + /* Pop until stack empty: error handling is rather brutal */ + assert(!ok || cfgst->path_depth == 1); + while (cfgst->path_depth > 0) { + cfgst_pop(cfgst); + } + if (fp) { + fclose(fp); + } else if (ok) { + cursor = tok + ddsrt_xmlp_get_bufpos (qx); + } + ddsrt_xmlp_free(qx); + while (cursor && cursor[0] == ',') { + cursor++; + } } + ddsrt_free(copy); + } + + /* Set defaults for everything not set that we have a default value + for, signal errors for things unset but without a default. */ + { + int ok1 = set_defaults(cfgst, cfgst->cfg, 0, root_cfgelems, 0); + ok = ok && ok1; + } /* Compatibility settings of IPv6, TCP -- a bit too complicated for @@ -2887,7 +2741,7 @@ struct cfgst * config_init (const char *configfile) cfgst->cfg->transport_selector = (config.compat_use_ipv6 == BOOLDEF_TRUE) ? TRANS_TCP6 : TRANS_TCP; else cfgst->cfg->transport_selector = (config.compat_use_ipv6 == BOOLDEF_TRUE) ? TRANS_UDP6 : TRANS_UDP; - break; + break; case TRANS_TCP: ok1 = !(cfgst->cfg->compat_tcp_enable == BOOLDEF_FALSE || cfgst->cfg->compat_use_ipv6 == BOOLDEF_TRUE); break; @@ -2912,200 +2766,200 @@ struct cfgst * config_init (const char *configfile) } #ifdef DDSI_INCLUDE_NETWORK_CHANNELS - /* Default channel gets set outside set_defaults -- a bit too - complicated for the poor framework */ + /* Default channel gets set outside set_defaults -- a bit too + complicated for the poor framework */ - if ( set_default_channel(cfgst->cfg) < 0 ) { - ok = 0; - } - if ( cfgst->cfg->channels && sort_channels_check_nodups(cfgst->cfg) < 0 ) { - ok = 0; - } + if ( set_default_channel(cfgst->cfg) < 0 ) { + ok = 0; + } + if ( cfgst->cfg->channels && sort_channels_check_nodups(cfgst->cfg) < 0 ) { + ok = 0; + } #endif #ifdef DDSI_INCLUDE_ENCRYPTION - /* Check security profiles */ - { - struct config_securityprofile_listelem *s = config.securityProfiles; - while ( s ) { - switch ( s->cipher ) { - case Q_CIPHER_UNDEFINED: - case Q_CIPHER_NULL: - /* nop */ - if ( s->key && strlen(s->key) > 0 ) { - DDS_INFO("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: %s: cipher key not required\n", s->key); - } - break; + /* Check security profiles */ + { + struct config_securityprofile_listelem *s = config.securityProfiles; + while ( s ) { + switch ( s->cipher ) { + case Q_CIPHER_UNDEFINED: + case Q_CIPHER_NULL: + /* nop */ + if ( s->key && strlen(s->key) > 0 ) { + DDS_INFO("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: %s: cipher key not required\n", s->key); + } + break; - default: - /* read the cipherkey if present */ - if ( !s->key || strlen(s->key) == 0 ) { - DDS_ERROR("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: cipher key missing\n"); - ok = 0; - } else if ( q_security_plugin.valid_uri && !(q_security_plugin.valid_uri) (s->cipher, s->key) ) { - DDS_ERROR("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: %s : incorrect key\n", s->key); - ok = 0; - } - } - s = s->next; - } + default: + /* read the cipherkey if present */ + if ( !s->key || strlen(s->key) == 0 ) { + DDS_ERROR("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: cipher key missing\n"); + ok = 0; + } else if ( q_security_plugin.valid_uri && !(q_security_plugin.valid_uri) (s->cipher, s->key) ) { + DDS_ERROR("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: %s : incorrect key\n", s->key); + ok = 0; + } + } + s = s->next; } + } #endif /* DDSI_INCLUDE_ENCRYPTION */ #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS - /* Assign network partition ids */ + /* Assign network partition ids */ #ifdef DDSI_INCLUDE_ENCRYPTION - /* also create links from the network partitions to the - securityProfiles and signal errors if profiles do not exist */ + /* also create links from the network partitions to the + securityProfiles and signal errors if profiles do not exist */ #endif /* DDSI_INCLUDE_ENCRYPTION */ - { - struct config_networkpartition_listelem *p = config.networkPartitions; - config.nof_networkPartitions = 0; - while ( p ) { + { + struct config_networkpartition_listelem *p = config.networkPartitions; + config.nof_networkPartitions = 0; + while ( p ) { #ifdef DDSI_INCLUDE_ENCRYPTION - if ( ddsrt_strcasecmp(p->profileName, "null") == 0 ) - p->securityProfile = NULL; - else { - struct config_securityprofile_listelem *s = config.securityProfiles; - while ( s && ddsrt_strcasecmp(p->profileName, s->name) != 0 ) - s = s->next; - if ( s ) - p->securityProfile = s; - else { - DDS_ERROR("config: DDSI2Service/Partitioning/NetworkPartitions/NetworkPartition[@securityprofile]: %s: unknown securityprofile\n", p->profileName); - ok = 0; - } - } -#endif /* DDSI_INCLUDE_ENCRYPTION */ - config.nof_networkPartitions++; - /* also use crc32 just like native nw and ordinary ddsi2e, only - for interoperability because it is asking for trouble & - forces us to include a crc32 routine when we have md5 - available anyway */ - p->partitionId = config.nof_networkPartitions; /* starting at 1 */ - p->partitionHash = crc32_calc(p->name, strlen(p->name)); - p = p->next; + if ( ddsrt_strcasecmp(p->profileName, "null") == 0 ) + p->securityProfile = NULL; + else { + struct config_securityprofile_listelem *s = config.securityProfiles; + while ( s && ddsrt_strcasecmp(p->profileName, s->name) != 0 ) + s = s->next; + if ( s ) + p->securityProfile = s; + else { + DDS_ERROR("config: DDSI2Service/Partitioning/NetworkPartitions/NetworkPartition[@securityprofile]: %s: unknown securityprofile\n", p->profileName); + ok = 0; } + } +#endif /* DDSI_INCLUDE_ENCRYPTION */ + config.nof_networkPartitions++; + /* also use crc32 just like native nw and ordinary ddsi2e, only + for interoperability because it is asking for trouble & + forces us to include a crc32 routine when we have md5 + available anyway */ + p->partitionId = config.nof_networkPartitions; /* starting at 1 */ + p->partitionHash = crc32_calc(p->name, strlen(p->name)); + p = p->next; } + } - /* Create links from the partitionmappings to the network partitions - and signal errors if partitions do not exist */ - { - struct config_partitionmapping_listelem * m = config.partitionMappings; - while ( m ) { - struct config_networkpartition_listelem * p = config.networkPartitions; - while ( p && ddsrt_strcasecmp(m->networkPartition, p->name) != 0 ) { - p = p->next; - } - if ( p ) { - m->partition = p; - } else { - DDS_ERROR("config: DDSI2Service/Partitioning/PartitionMappings/PartitionMapping[@networkpartition]: %s: unknown partition\n", m->networkPartition); - ok = 0; - } - m = m->next; - } + /* Create links from the partitionmappings to the network partitions + and signal errors if partitions do not exist */ + { + struct config_partitionmapping_listelem * m = config.partitionMappings; + while ( m ) { + struct config_networkpartition_listelem * p = config.networkPartitions; + while ( p && ddsrt_strcasecmp(m->networkPartition, p->name) != 0 ) { + p = p->next; + } + if ( p ) { + m->partition = p; + } else { + DDS_ERROR("config: DDSI2Service/Partitioning/PartitionMappings/PartitionMapping[@networkpartition]: %s: unknown partition\n", m->networkPartition); + ok = 0; + } + m = m->next; } + } #endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */ - /* Now switch to configured tracing settings */ - config.enabled_logcats = enabled_logcats; + /* Now switch to configured tracing settings */ + config.enabled_logcats = enabled_logcats; - if ( !ok ) { - free_configured_elements(cfgst, cfgst->cfg, root_cfgelems); - } + if ( !ok ) { + free_configured_elements(cfgst, cfgst->cfg, root_cfgelems); + } - if ( ok ) { - config.valid = 1; - return cfgst; - } else { - ddsrt_avl_free(&cfgst_found_treedef, &cfgst->found, ddsrt_free); - ddsrt_free(cfgst); - return NULL; - } + if ( ok ) { + config.valid = 1; + return cfgst; + } else { + ddsrt_avl_free(&cfgst_found_treedef, &cfgst->found, ddsrt_free); + ddsrt_free(cfgst); + return NULL; + } } void config_print_cfgst(struct cfgst *cfgst) { - if ( cfgst == NULL ) - return; - print_configitems(cfgst, cfgst->cfg, 0, root_cfgelems, 0); + if ( cfgst == NULL ) + return; + print_configitems(cfgst, cfgst->cfg, 0, root_cfgelems, 0); } void config_fini(struct cfgst *cfgst) { - assert(cfgst); - assert(cfgst->cfg == &config); - assert(config.valid); + assert(cfgst); + assert(cfgst->cfg == &config); + assert(config.valid); - free_all_elements(cfgst, cfgst->cfg, root_cfgelems); - dds_set_log_file(stderr); - dds_set_trace_file(stderr); - if (config.tracingOutputFile && config.tracingOutputFile != stdout && config.tracingOutputFile != stderr) { - fclose(config.tracingOutputFile); - } - memset(&config, 0, sizeof(config)); - config.valid = 0; + free_all_elements(cfgst, cfgst->cfg, root_cfgelems); + dds_set_log_file(stderr); + dds_set_trace_file(stderr); + if (config.tracingOutputFile && config.tracingOutputFile != stdout && config.tracingOutputFile != stderr) { + fclose(config.tracingOutputFile); + } + memset(&config, 0, sizeof(config)); + config.valid = 0; - ddsrt_avl_free(&cfgst_found_treedef, &cfgst->found, ddsrt_free); - ddsrt_free(cfgst); + ddsrt_avl_free(&cfgst_found_treedef, &cfgst->found, ddsrt_free); + ddsrt_free(cfgst); } #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS static char *get_partition_search_pattern(const char *partition, const char *topic) { - size_t sz = strlen(partition) + strlen(topic) + 2; - char *pt = ddsrt_malloc(sz); - snprintf(pt, sz, "%s.%s", partition, topic); - return pt; + size_t sz = strlen(partition) + strlen(topic) + 2; + char *pt = ddsrt_malloc(sz); + snprintf(pt, sz, "%s.%s", partition, topic); + return pt; } struct config_partitionmapping_listelem *find_partitionmapping(const char *partition, const char *topic) { - char *pt = get_partition_search_pattern(partition, topic); - struct config_partitionmapping_listelem *pm; - for ( pm = config.partitionMappings; pm; pm = pm->next ) - if ( WildcardOverlap(pt, pm->DCPSPartitionTopic) ) - break; - ddsrt_free(pt); - return pm; + char *pt = get_partition_search_pattern(partition, topic); + struct config_partitionmapping_listelem *pm; + for ( pm = config.partitionMappings; pm; pm = pm->next ) + if ( WildcardOverlap(pt, pm->DCPSPartitionTopic) ) + break; + ddsrt_free(pt); + return pm; } struct config_networkpartition_listelem *find_networkpartition_by_id(uint32_t id) { - struct config_networkpartition_listelem *np; - for ( np = config.networkPartitions; np; np = np->next ) - if ( np->partitionId == id ) - return np; - return 0; + struct config_networkpartition_listelem *np; + for ( np = config.networkPartitions; np; np = np->next ) + if ( np->partitionId == id ) + return np; + return 0; } int is_ignored_partition(const char *partition, const char *topic) { - char *pt = get_partition_search_pattern(partition, topic); - struct config_ignoredpartition_listelem *ip; - for ( ip = config.ignoredPartitions; ip; ip = ip->next ) - if ( WildcardOverlap(pt, ip->DCPSPartitionTopic) ) - break; - ddsrt_free(pt); - return ip != NULL; + char *pt = get_partition_search_pattern(partition, topic); + struct config_ignoredpartition_listelem *ip; + for ( ip = config.ignoredPartitions; ip; ip = ip->next ) + if ( WildcardOverlap(pt, ip->DCPSPartitionTopic) ) + break; + ddsrt_free(pt); + return ip != NULL; } #endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */ #ifdef DDSI_INCLUDE_NETWORK_CHANNELS struct config_channel_listelem *find_channel(nn_transport_priority_qospolicy_t transport_priority) { - struct config_channel_listelem *c; - /* Channel selection is to use the channel with the lowest priority - not less than transport_priority, or else the one with the - highest priority. */ - assert(config.channels != NULL); - assert(config.max_channel != NULL); - for ( c = config.channels; c; c = c->next ) { - assert(c->next == NULL || c->next->priority > c->priority); - if ( transport_priority.value <= c->priority ) - return c; - } - return config.max_channel; + struct config_channel_listelem *c; + /* Channel selection is to use the channel with the lowest priority + not less than transport_priority, or else the one with the + highest priority. */ + assert(config.channels != NULL); + assert(config.max_channel != NULL); + for ( c = config.channels; c; c = c->next ) { + assert(c->next == NULL || c->next->priority > c->priority); + if ( transport_priority.value <= c->priority ) + return c; + } + return config.max_channel; } #endif /* DDSI_INCLUDE_NETWORK_CHANNELS */ diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 98e89f7..a6e32cd 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -1719,7 +1719,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str from the submsg to always conform to that of the "Data" submessage regardless of the input. */ msg = (Data_DataFrag_common_t *) NN_RMSG_PAYLOADOFF (fragchain->rmsg, NN_RDATA_SUBMSG_OFF (fragchain)); - data_smhdr_flags = normalize_data_datafrag_flags (&msg->smhdr, config.buggy_datafrag_flags_mode); + data_smhdr_flags = normalize_data_datafrag_flags (&msg->smhdr); srcguid.prefix = sampleinfo->rst->src_guid_prefix; srcguid.entityid = msg->writerId; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index beba3f8..53c0bc6 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -2657,39 +2657,11 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se { assert (wr->xqos->history.kind == NN_KEEP_LAST_HISTORY_QOS); assert (wr->xqos->durability.kind == NN_TRANSIENT_LOCAL_DURABILITY_QOS); - wr->aggressive_keep_last = 1; - } - else - { - wr->aggressive_keep_last = (config.aggressive_keep_last_whc && wr->xqos->history.kind == NN_KEEP_LAST_HISTORY_QOS); } wr->handle_as_transient_local = (wr->xqos->durability.kind == NN_TRANSIENT_LOCAL_DURABILITY_QOS); wr->include_keyhash = config.generate_keyhash && ((wr->e.guid.entityid.u & NN_ENTITYID_KIND_MASK) == NN_ENTITYID_KIND_WRITER_WITH_KEY); - /* Startup mode causes the writer to treat data in its WHC as if - transient-local, for the first few seconds after startup of the - DDSI service. It is done for volatile reliable writers only - (which automatically excludes all builtin writers) or for all - writers except volatile best-effort & transient-local ones. - - Which one to use depends on whether merge policies are in effect - in durability. If yes, then durability will take care of all - transient & persistent data; if no, DDSI discovery usually takes - too long and this'll save you. - - Note: may still be cleared, if it turns out we are not maintaining - an index at all (e.g., volatile KEEP_ALL) */ - if (config.startup_mode_full) { - wr->startup_mode = gv.startup_mode && - (wr->xqos->durability.kind >= NN_TRANSIENT_DURABILITY_QOS || - (wr->xqos->durability.kind == NN_VOLATILE_DURABILITY_QOS && - wr->xqos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS)); - } else { - wr->startup_mode = gv.startup_mode && - (wr->xqos->durability.kind == NN_VOLATILE_DURABILITY_QOS && - wr->xqos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS); - } wr->topic = ddsi_sertopic_ref (topic); wr->as = new_addrset (); wr->as_group = NULL; @@ -2784,7 +2756,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se wr->lease_duration = T_NEVER; /* FIXME */ wr->whc = whc; - if (wr->xqos->history.kind == NN_KEEP_LAST_HISTORY_QOS && wr->aggressive_keep_last) + if (wr->xqos->history.kind == NN_KEEP_LAST_HISTORY_QOS) { /* hdepth > 0 => "aggressive keep last", and in that case: why bother blocking for a slow receiver when the entire point of @@ -3066,24 +3038,6 @@ int delete_writer (const struct nn_guid *guid) return 0; } -void writer_exit_startup_mode (struct writer *wr) -{ - struct whc_node *deferred_free_list = NULL; - ddsrt_mutex_lock (&wr->e.lock); - if (wr->startup_mode) - { - unsigned cnt = 0; - struct whc_state whcst; - wr->startup_mode = 0; - cnt += remove_acked_messages (wr, &whcst, &deferred_free_list); - cnt += whc_downgrade_to_volatile (wr->whc, &whcst); - writer_clear_retransmitting (wr); - DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT": dropped %u samples\n", PGUID(wr->e.guid), cnt); - } - ddsrt_mutex_unlock (&wr->e.lock); - whc_free_deferred_free_list (wr->whc, deferred_free_list); -} - uint64_t writer_instance_id (const struct nn_guid *guid) { struct entity_common *e; diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index c6e4a8f..add93b5 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -501,12 +501,6 @@ int rtps_config_prep (struct cfgst *cfgst) if (config.max_participants == 0) config.max_participants = 100; } - if (NN_STRICT_P) - { - /* Should not be sending invalid messages when strict */ - config.respond_to_rti_init_zero_ack_with_invalid_heartbeat = 0; - config.acknack_numbits_emptyset = 1; - } if (config.max_queued_rexmit_bytes == 0) { #ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING @@ -1002,9 +996,6 @@ int rtps_init (void) } #endif - gv.startup_mode = (config.startup_mode_duration > 0) ? 1 : 0; - DDS_LOG(DDS_LC_CONFIG, "startup-mode: %s\n", gv.startup_mode ? "enabled" : "disabled"); - (ddsi_plugin.init_fn) (); gv.xmsgpool = nn_xmsgpool_new (); @@ -1401,10 +1392,6 @@ int rtps_start (void) { create_thread (&gv.listen_ts, "listen", (uint32_t (*) (void *)) listen_thread, gv.listener); } - if (gv.startup_mode) - { - qxev_end_startup_mode (add_duration_to_mtime (now_mt (), config.startup_mode_duration)); - } if (config.monitor_port >= 0) { gv.debmon = new_debug_monitor (config.monitor_port); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 5aae883..a706067 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -438,7 +438,6 @@ static int valid_Data (const struct receiver_state *rst, struct nn_rmsg *rmsg, D static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rmsg, DataFrag_t *msg, size_t size, int byteswap, struct nn_rsample_info *sampleinfo, unsigned char **payloadp) { /* on success: sampleinfo->{rst,statusinfo,pt_wr_info_zoff,bswap,complex_qos} all set */ - const int interpret_smhdr_flags_asif_data = config.buggy_datafrag_flags_mode; uint32_t payloadsz; nn_guid_t pwr_guid; unsigned char *ptr; @@ -446,14 +445,6 @@ static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rms if (size < sizeof (*msg)) return 0; /* too small even for fixed fields */ - if (interpret_smhdr_flags_asif_data) - { - /* D=1 && K=1 is invalid in this version of the protocol */ - if ((msg->x.smhdr.flags & (DATA_FLAG_DATAFLAG | DATA_FLAG_KEYFLAG)) == - (DATA_FLAG_DATAFLAG | DATA_FLAG_KEYFLAG)) - return 0; - } - if (byteswap) { msg->x.extraFlags = bswap2u (msg->x.extraFlags); @@ -497,13 +488,6 @@ static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rms if (sampleinfo->seq <= 0 && sampleinfo->seq != NN_SEQUENCE_NUMBER_UNKNOWN) return 0; - if (interpret_smhdr_flags_asif_data) - { - if ((msg->x.smhdr.flags & (DATA_FLAG_DATAFLAG | DATA_FLAG_KEYFLAG)) == 0) - /* may not fragment if not needed => surely _some_ payload must be present! */ - return 0; - } - /* QoS and/or payload, so octetsToInlineQos must be within the msg; since the serialized data and serialized parameter lists have a 4 byte header, that one, too must fit */ @@ -607,36 +591,10 @@ static void force_heartbeat_to_peer (struct writer *wr, const struct whc_state * return; } - if (WHCST_ISEMPTY(whcst) && !config.respond_to_rti_init_zero_ack_with_invalid_heartbeat) - { - /* If WHC is empty, we send a Gap combined with a Heartbeat. The - Gap reuses the latest sequence number (or consumes a new one if - the writer hasn't sent anything yet), therefore for the reader - it is as-if a Data submessage had once been sent with that - sequence number and it now receives an unsollicited response to - a NACK ... */ - uint32_t bits = 0; - seqno_t seq; - if (wr->seq > 0) - seq = wr->seq; - else - { - /* never sent anything, pretend we did */ - seq = wr->seq = 1; - UPDATE_SEQ_XMIT_LOCKED(wr, 1); - } - add_Gap (m, wr, prd, seq, seq+1, 1, &bits); - add_Heartbeat (m, wr, whcst, hbansreq, prd->e.guid.entityid, 1); - DDS_TRACE("force_heartbeat_to_peer: "PGUIDFMT" -> "PGUIDFMT" - whc empty, queueing gap #%"PRId64" + heartbeat for transmit\n", - PGUID (wr->e.guid), PGUID (prd->e.guid), seq); - } - else - { - /* Send a Heartbeat just to this peer */ - add_Heartbeat (m, wr, whcst, hbansreq, prd->e.guid.entityid, 0); - DDS_TRACE("force_heartbeat_to_peer: "PGUIDFMT" -> "PGUIDFMT" - queue for transmit\n", + /* Send a Heartbeat just to this peer */ + add_Heartbeat (m, wr, whcst, hbansreq, prd->e.guid.entityid, 0); + DDS_TRACE("force_heartbeat_to_peer: "PGUIDFMT" -> "PGUIDFMT" - queue for transmit\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); - } qxev_msg (wr->evq, m); } @@ -1892,16 +1850,13 @@ static struct ddsi_serdata *extract_sample_from_data return sample; } -unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr, int datafrag_as_data) +unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr) { switch ((SubmessageKind_t) smhdr->submessageId) { case SMID_DATA: return smhdr->flags; case SMID_DATA_FRAG: - if (datafrag_as_data) - return smhdr->flags; - else { unsigned char common = smhdr->flags & DATA_FLAG_INLINE_QOS; Q_STATIC_ASSERT_CODE (DATA_FLAG_INLINE_QOS == DATAFRAG_FLAG_INLINE_QOS); @@ -1955,7 +1910,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st DataFrag header, so for the fixed-position things that we're interested in here, both can be treated as Data submessages. */ msg = (Data_DataFrag_common_t *) NN_RMSG_PAYLOADOFF (fragchain->rmsg, NN_RDATA_SUBMSG_OFF (fragchain)); - data_smhdr_flags = normalize_data_datafrag_flags (&msg->smhdr, config.buggy_datafrag_flags_mode); + data_smhdr_flags = normalize_data_datafrag_flags (&msg->smhdr); /* Extract QoS's to the extent necessary. The expected case has all we need predecoded into a few bits in the sample info. diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 3a208ba..cc086a6 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -352,13 +352,8 @@ void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_sta We're not really allowed to generate heartbeats when the WHC is empty, but it appears RTI sort-of needs them ... Now we use GAPs, and allocate a sequence number specially for that. */ - assert (config.respond_to_rti_init_zero_ack_with_invalid_heartbeat || wr->seq >= 1); max = wr->seq; - min = max; - if (config.respond_to_rti_init_zero_ack_with_invalid_heartbeat) - { - min += 1; - } + min = max + 1; } else { @@ -378,14 +373,9 @@ void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_sta if (seq_xmit >= min) { /* Advertise some but not all data */ max = seq_xmit; - } else if (config.respond_to_rti_init_zero_ack_with_invalid_heartbeat) { + } else { /* if we can generate an empty heartbeat => do so. */ max = min - 1; - } else { - /* claim the existence of a sample we possibly haven't set - yet, at worst this causes a retransmission (but the - NackDelay usually takes care of that). */ - max = min; } } } @@ -484,10 +474,7 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli Note: fragnum is 0-based here, 1-based in DDSI. But 0-based is much easier ... - Expected inline QoS size: header(4) + statusinfo(8) + keyhash(20) - + sentinel(4). Plus some spare cos I can't be bothered. */ - const int set_smhdr_flags_asif_data = config.buggy_datafrag_flags_mode; - /* actual expected_inline_qos_size is typically 0, but always claiming 32 bytes won't make + 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 nn_xmsg_marker sm_marker; @@ -569,10 +556,7 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli } else { - const unsigned char contentflag = - set_smhdr_flags_asif_data - ? (serdata->kind == SDK_KEY ? DATA_FLAG_KEYFLAG : DATA_FLAG_DATAFLAG) - : (serdata->kind == SDK_KEY ? DATAFRAG_FLAG_KEYFLAG : 0); + const unsigned char contentflag = (serdata->kind == SDK_KEY ? DATAFRAG_FLAG_KEYFLAG : 0); DataFrag_t *frag = sm; /* empty means size = 0, which means it never needs fragmenting */ assert (serdata->kind != SDK_EMPTY); @@ -887,7 +871,7 @@ static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist if (wr->reliable && have_reliable_subs (wr)) do_insert = 1; - else if (wr->handle_as_transient_local || wr->startup_mode) + else if (wr->handle_as_transient_local) do_insert = 1; else do_insert = 0; @@ -1041,7 +1025,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * nn_mtime_t tnow; /* 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 == NN_KEEP_LAST_HISTORY_QOS && wr->aggressive_keep_last && wr->whc_low == INT32_MAX)); + assert(gc_allowed || (wr->xqos->history.kind == NN_KEEP_LAST_HISTORY_QOS && wr->whc_low == INT32_MAX)); (void)gc_allowed; if (ddsi_serdata_size (serdata) > config.max_sample_size) diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index e4b107b..dc959c0 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -63,7 +63,6 @@ enum xeventkind XEVK_ACKNACK, XEVK_SPDP, XEVK_PMD_UPDATE, - XEVK_END_STARTUP_MODE, XEVK_DELETE_WRITER, XEVK_CALLBACK }; @@ -93,10 +92,6 @@ struct xevent #if 0 struct { } info; -#endif -#if 0 - struct { - } end_startup_mode; #endif struct { nn_guid_t guid; @@ -312,7 +307,6 @@ static void free_xevent (struct xeventq *evq, struct xevent *ev) case XEVK_ACKNACK: case XEVK_SPDP: case XEVK_PMD_UPDATE: - case XEVK_END_STARTUP_MODE: case XEVK_DELETE_WRITER: case XEVK_CALLBACK: break; @@ -805,15 +799,6 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p an->smhdr.flags |= ACKNACK_FLAG_FINAL; } - /* If we refuse to send invalid AckNacks, grow a length-0 bitmap and - zero-fill it. Cleared bits are meaningless (DDSI 2.1, table 8.33, - although RTI seems to think otherwise). */ - if (numbits == 0 && config.acknack_numbits_emptyset > 0) - { - an->readerSNState.numbits = (unsigned) config.acknack_numbits_emptyset; - nn_bitset_zero (an->readerSNState.numbits, an->readerSNState.bits); - } - { /* Count field is at a variable offset ... silly DDSI spec. */ nn_count_t *countp = @@ -1195,21 +1180,6 @@ static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_ ddsrt_mutex_unlock (&pp->e.lock); } -static void handle_xevk_end_startup_mode (UNUSED_ARG (struct nn_xpack *xp), struct xevent *ev, UNUSED_ARG (nn_mtime_t tnow)) -{ - struct ephash_enum_writer est; - struct writer *wr; - assert (gv.startup_mode); - DDS_LOG(DDS_LC_DISCOVERY, "end startup mode\n"); - gv.startup_mode = 0; - /* FIXME: MEMBAR needed for startup mode (or use a lock) */ - ephash_enum_writer_init (&est); - while ((wr = ephash_enum_writer_next (&est)) != NULL) - writer_exit_startup_mode (wr); - ephash_enum_writer_fini (&est); - delete_xevent (ev); -} - 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. */ @@ -1234,9 +1204,6 @@ static void handle_individual_xevent (struct thread_state1 * const ts1, struct x case XEVK_PMD_UPDATE: handle_xevk_pmd_update (ts1, xp, xev, tnow); break; - case XEVK_END_STARTUP_MODE: - handle_xevk_end_startup_mode (xp, xev, tnow); - break; case XEVK_DELETE_WRITER: handle_xevk_delete_writer (xp, xev, tnow); break; @@ -1582,16 +1549,6 @@ struct xevent *qxev_pmd_update (nn_mtime_t tsched, const nn_guid_t *pp_guid) return ev; } -struct xevent *qxev_end_startup_mode (nn_mtime_t tsched) -{ - struct xevent *ev; - ddsrt_mutex_lock (&gv.xevents->lock); - ev = qxev_common (gv.xevents, tsched, XEVK_END_STARTUP_MODE); - qxev_insert (ev); - ddsrt_mutex_unlock (&gv.xevents->lock); - return ev; -} - struct xevent *qxev_delete_writer (nn_mtime_t tsched, const nn_guid_t *guid) { struct xevent *ev; From 6bf13fbaa5663e6970715fc3cf00b48123bd30dd Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 4 May 2019 13:50:02 +0800 Subject: [PATCH 059/178] remove Internal/SuppressSPDPMulticast setting The Internal/SuppressSPDPMulticast setting was one of several ways to prevent the sending of participant discovery multicast messages while still allowing multicast to be used for data communications. That functionality has long since been subsumed by the AllowMulticast setting (AllowMulticast = spdp,amc & Internal/SuppressSPDPMulticast is equivalent to AllowMulticast = amc). Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_config.h | 1 - src/core/ddsi/src/q_config.c | 5 +---- src/core/ddsi/src/q_ddsi_discovery.c | 2 +- src/core/ddsi/src/q_init.c | 17 +++-------------- 4 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index 50ceb51..08f3d6e 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -331,7 +331,6 @@ struct config enum besmode besmode; int conservative_builtin_reader_startup; int meas_hb_to_ack_latency; - int suppress_spdp_multicast; int unicast_response_to_spdp_messages; int synchronous_delivery_priority_threshold; int64_t synchronous_delivery_latency_bound; diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 6c22b64..39ae17b 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -245,7 +245,7 @@ static const struct cfgelem general_cfgelems[] = {

      It is a comma-separated list of some of the following keywords: \"spdp\", \"asm\", \"ssm\", or either of \"false\" or \"true\".

      \n\
        \n\
      • spdp: enables the use of ASM (any-source multicast) for participant discovery, joining the multicast group on the discovery socket, transmitting SPDP messages to this group, but never advertising nor using any multicast address in any discovery message, thus forcing unicast communications for all endpoint discovery and user data.
      • \n\ -
      • asm: enables the use of ASM for all traffic (including SPDP)
      • \n\ +
      • asm: enables the use of ASM for all traffic, including receiving SPDP but not transmitting SPDP messages via multicast
      • \n\
      • ssm: enables the use of SSM (source-specific multicast) for all non-SPDP traffic (if supported)
      • \n\
      \n\

      When set to \"false\" all multicasting is disabled. The default, \"true\" enables full use of multicasts. Listening for multicasts can be controlled by General/MulticastRecvNetworkInterfaceAddresses.

      ") }, @@ -531,9 +531,6 @@ static const struct cfgelem unsupp_cfgelems[] = {

      Should it be necessary to hide DDSI2E's shared discovery behaviour, set this to true and Internal/BuiltinEndpointSet to full.

      ") }, { LEAF("MeasureHbToAckLatency"), 1, "false", ABSOFF(meas_hb_to_ack_latency), 0, uf_boolean, 0, pf_boolean, BLURB("

      This element enables heartbeat-to-ack latency among DDSI2E services by prepending timestamps to Heartbeat and AckNack messages and calculating round trip times. This is non-standard behaviour. The measured latencies are quite noisy and are currently not used anywhere.

      ") }, - { LEAF("SuppressSPDPMulticast"), 1, "false", ABSOFF(suppress_spdp_multicast), 0, uf_boolean, 0, pf_boolean, - BLURB("

      The element controls whether the mandatory multicasting of the participant discovery packets occurs. Completely disabling multicasting requires this element be set to true, and generally requires explicitly listing peers to ping for unicast discovery.

      \n\ -

      See also General/AllowMulticast.

      ") }, { LEAF("UnicastResponseToSPDPMessages"), 1, "true", ABSOFF(unicast_response_to_spdp_messages), 0, uf_boolean, 0, pf_boolean, BLURB("

      This element controls whether the response to a newly discovered participant is sent as a unicasted SPDP packet, instead of rescheduling the periodic multicasted one. There is no known benefit to setting this to false.

      ") }, { LEAF("SynchronousDeliveryPriorityThreshold"), 1, "0", ABSOFF(synchronous_delivery_priority_threshold), 0, uf_int, 0, pf_int, diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index a6e32cd..8a75416 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -160,7 +160,7 @@ static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_sam static void maybe_add_pp_as_meta_to_as_disc (const struct addrset *as_meta) { - if (addrset_empty_mc (as_meta)) + if (addrset_empty_mc (as_meta) || !(config.allowMulticast & AMC_SPDP)) { nn_locator_t loc; if (addrset_any_uc (as_meta, &loc)) diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index add93b5..2c4601d 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -313,11 +313,6 @@ static int set_spdp_address (void) return -1; } #endif - if (!(config.allowMulticast & AMC_SPDP) || config.suppress_spdp_multicast) - { - /* Explicitly disabling SPDP multicasting is always possible */ - set_unspec_locator (&gv.loc_spdp_mc); - } return 0; } @@ -331,11 +326,6 @@ static int set_default_mc_address (void) return rc; else if (rc == 0) gv.loc_default_mc = gv.loc_spdp_mc; - if (!(config.allowMulticast & ~AMC_SPDP)) - { - /* no multicasting beyond SPDP */ - set_unspec_locator (&gv.loc_default_mc); - } gv.loc_meta_mc = gv.loc_default_mc; return 0; } @@ -791,7 +781,7 @@ static int setup_and_start_recv_threads (void) gv.recv_threads[0].arg.mode = RTM_MANY; if (gv.m_factory->m_connless && config.many_sockets_mode != MSM_NO_UNICAST && config.multiple_recv_threads) { - if (ddsi_is_mcaddr (&gv.loc_default_mc) && !ddsi_is_ssm_mcaddr (&gv.loc_default_mc)) + if (ddsi_is_mcaddr (&gv.loc_default_mc) && !ddsi_is_ssm_mcaddr (&gv.loc_default_mc) && (config.allowMulticast & AMC_ASM)) { /* Multicast enabled, but it isn't an SSM address => handle data multicasts on a separate thread (the trouble with SSM addresses is that we only join matching writers, which our own sockets typically would not be) */ gv.recv_threads[gv.n_recv_threads].name = "recvMC"; @@ -911,7 +901,6 @@ int rtps_init (void) config.publish_uc_locators = (config.tcp_port != -1); config.enable_uc_locators = 1; /* TCP affects what features are supported/required */ - config.suppress_spdp_multicast = 1; config.many_sockets_mode = MSM_SINGLE_UNICAST; config.allowMulticast = AMC_FALSE; if (ddsi_tcp_init () < 0) @@ -940,7 +929,6 @@ int rtps_init (void) if (!gv.interfaces[gv.selected_interface].mc_capable) { DDS_WARNING("selected interface is not multicast-capable: disabling multicast\n"); - config.suppress_spdp_multicast = 1; 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 @@ -1234,7 +1222,8 @@ int rtps_init (void) ); gv.as_disc = new_addrset (); - add_to_addrset (gv.as_disc, &gv.loc_spdp_mc); + if (config.allowMulticast & AMC_SPDP) + add_to_addrset (gv.as_disc, &gv.loc_spdp_mc); /* If multicast was enabled but not available, always add the local interface to the discovery address set. Conversion via string and add_peer_addresses has the benefit that the port number expansion happens automatically. */ From 62ccd9f7da401ea47d0e325a6d99c3a5cc833da2 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 4 May 2019 14:42:05 +0800 Subject: [PATCH 060/178] Move CycloneDDS/DDSI2E/* to CycloneDDS/* in config The entirely historical "DDSI2E" element within the CycloneDDS configuration element is herewith eliminated. All settings contained in that element (such as General, Discovery, Tracing) are now subelements of the CycloneDDS top-level element. Old configurations continue to work but will print a deprecation warning: //CycloneDDS/DDSI2E: settings moved to //CycloneDDS Any warnings/errors related for an element //CycloneDDS/DDSI2E/x will be reported as errors for the new location, that is, for //CycloneDDS/x. As the "settings moved" warning always precedes any other such warning, confusion will hopefully be avoided. Signed-off-by: Erik Boasson --- src/core/ddsc/tests/config_simple_udp.xml | 36 ++++++------- src/core/ddsi/src/q_config.c | 57 ++++++++++++--------- src/mpt/tests/basic/etc/config_any.xml | 26 +++++----- src/mpt/tests/basic/etc/config_specific.xml | 26 +++++----- 4 files changed, 74 insertions(+), 71 deletions(-) diff --git a/src/core/ddsc/tests/config_simple_udp.xml b/src/core/ddsc/tests/config_simple_udp.xml index f96c737..52eb377 100644 --- a/src/core/ddsc/tests/config_simple_udp.xml +++ b/src/core/ddsc/tests/config_simple_udp.xml @@ -16,23 +16,21 @@ 3 - - - 127.0.0.1 - true - true - - - lax - - - warning - vortexdds-.${NON_EXISTENT_ENV_VARIABLE:-l}${CYCLONEDDS_URI:+o}g - - - ${MAX_PARTICIPANTS} - 100 ms - - - + + 127.0.0.1 + true + true + + + lax + + + warning + vortexdds-.${NON_EXISTENT_ENV_VARIABLE:-l}${CYCLONEDDS_URI:+o}g + + + ${MAX_PARTICIPANTS} + 100 ms + + diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 39ae17b..d9c37db 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -508,8 +508,8 @@ static const struct cfgelem multiple_recv_threads_attrs[] = { }; static const struct cfgelem unsupp_cfgelems[] = { - { MOVED("MaxMessageSize", "General/MaxMessageSize") }, - { MOVED("FragmentSize", "General/FragmentSize") }, + { MOVED("MaxMessageSize", "CycloneDDS/General/MaxMessageSize") }, + { MOVED("FragmentSize", "CycloneDDS/General/FragmentSize") }, { LEAF("DeliveryQueueMaxSamples"), 1, "256", ABSOFF(delivery_queue_maxsamples), 0, uf_uint, 0, pf_uint, BLURB("

      This element controls the Maximum size of a delivery queue, expressed in samples. Once a delivery queue is full, incoming samples destined for that queue are dropped until space becomes available again.

      ") }, { LEAF("PrimaryReorderMaxSamples"), 1, "64", ABSOFF(primary_reorder_maxsamples), 0, uf_uint, 0, pf_uint, @@ -785,7 +785,14 @@ static const struct cfgelem tracing_cfgelems[] = { END_MARKER }; -static const struct cfgelem ddsi2_cfgelems[] = { +static const struct cfgelem domain_cfgelems[] = { + { LEAF("Id"), 1, "any", ABSOFF(domainId), 0, uf_domainId, 0, pf_domainId, NULL }, + END_MARKER +}; + +static const struct cfgelem root_cfgelems[] = { + { GROUP("Domain", domain_cfgelems), + BLURB("

      The General element specifying Domain related settings.

      ") }, { GROUP("General", general_cfgelems), BLURB("

      The General element specifies overall DDSI2E service settings.

      ") }, #ifdef DDSI_INCLUDE_ENCRYPTION @@ -820,18 +827,7 @@ static const struct cfgelem ddsi2_cfgelems[] = { { GROUP("SSL", ssl_cfgelems), BLURB("

      The SSL element allows specifying various parameters related to using SSL/TLS for DDSI over TCP.

      ") }, #endif - END_MARKER -}; - -static const struct cfgelem domain_cfgelems[] = { - { LEAF("Id"), 1, "any", ABSOFF(domainId), 0, uf_domainId, 0, pf_domainId, NULL }, - END_MARKER -}; - -static const struct cfgelem root_cfgelems[] = { - { "Domain", domain_cfgelems, NULL, NODATA, NULL }, - { "DDSI2E|DDSI2", ddsi2_cfgelems, NULL, NODATA, - BLURB("

      DDSI2 settings ...

      ") }, + { MOVED("DDSI2E|DDSI2", "CycloneDDS") }, END_MARKER }; @@ -841,7 +837,7 @@ static const struct cfgelem cyclonedds_root_cfgelems[] = { }; static const struct cfgelem root_cfgelem = { - "root", cyclonedds_root_cfgelems, NULL, NODATA, NULL + "/", cyclonedds_root_cfgelems, NULL, NODATA, NULL }; #undef ATTR @@ -1014,17 +1010,27 @@ static size_t cfg_note(struct cfgst *cfgst, uint32_t cat, size_t bsz, const char sidx = 0; while ( sidx < cfgst->path_depth && cfgst->path[sidx]->name == NULL ) sidx++; + const struct cfgelem *prev_path = NULL; for ( i = sidx; i < cfgst->path_depth && (i == sidx || !cfgst->isattr[i - 1]); i++ ) { if ( cfgst->path[i] == NULL ) { assert(i > sidx); cfg_note_snprintf(&bb, "/#text"); } else if ( cfgst->isattr[i] ) { cfg_note_snprintf(&bb, "[@%s]", cfgst->path[i]->name); + } else if (cfgst->path[i] == prev_path) { + /* skip printing this level: it means a group contained an element indicating that + it was moved to the first group (i.e., stripping a level) -- this is currently + only used for stripping out the DDSI2E level, and the sole purpose of this + special case is making any warnings from elements contained within it look + reasonable by always printing the new location */ } else { - const char *p = strchr(cfgst->path[i]->name, '|'); - int n = p ? (int) (p - cfgst->path[i]->name) : (int) strlen(cfgst->path[i]->name); - cfg_note_snprintf(&bb, "%s%*.*s", (i == sidx) ? "" : "/", n, n, cfgst->path[i]->name); + /* first character is '>' means it was moved, so print what follows instead */ + const char *name = cfgst->path[i]->name + ((cfgst->path[i]->name[0] == '>') ? 1 : 0); + const char *p = strchr(name, '|'); + int n = p ? (int) (p - name) : (int) strlen(name); + cfg_note_snprintf(&bb, "%s%*.*s", (i == sidx) ? "" : "/", n, n, name); } + prev_path = cfgst->path[i]; } cfg_note_snprintf(&bb, ": "); @@ -1938,7 +1944,7 @@ static int do_update(struct cfgst *cfgst, update_fun_t upd, void *parent, struct if ( cfgelem->multiplicity == 0 || n->count < cfgelem->multiplicity ) ok = upd(cfgst, parent, cfgelem, (n->count == n->failed), value); else - ok = cfg_error(cfgst, "only %d instance(s) allowed", cfgelem->multiplicity); + ok = cfg_error(cfgst, "only %d instance%s allowed", cfgelem->multiplicity, (cfgelem->multiplicity == 1) ? "" : "s"); n->count++; if ( !ok ) { n->failed++; @@ -2392,7 +2398,7 @@ static int matching_name_index(const char *name_w_aliases, const char *name) static const struct cfgelem *lookup_redirect(const char *target) { - const struct cfgelem *cfgelem = ddsi2_cfgelems; + const struct cfgelem *cfgelem = cyclonedds_root_cfgelems; char *target_copy = ddsrt_strdup(target), *p1; const char *p = target_copy; while ( p ) { @@ -2458,10 +2464,13 @@ static int proc_elem_open(void *varg, UNUSED_ARG(uintptr_t parentinfo), UNUSED_A void *parent, *dynparent; if ( moved ) { -#if WARN_DEPRECATED_ALIAS - cfg_warning(cfgst, "'%s': deprecated alias for '%s'", name, cfg_subelem->defvalue); -#endif + struct cfgelem const * const cfg_subelem_orig = cfg_subelem; cfg_subelem = lookup_redirect(cfg_subelem->defvalue); +#if WARN_DEPRECATED_ALIAS + cfgst_push(cfgst, 0, cfg_subelem_orig, NULL); + cfg_warning(cfgst, "setting%s moved to //%s", cfg_subelem->children ? "s" : "", cfg_subelem_orig->defvalue); + cfgst_pop(cfgst); +#endif } parent = cfgst_parent(cfgst); diff --git a/src/mpt/tests/basic/etc/config_any.xml b/src/mpt/tests/basic/etc/config_any.xml index 68e0e0a..71b410f 100644 --- a/src/mpt/tests/basic/etc/config_any.xml +++ b/src/mpt/tests/basic/etc/config_any.xml @@ -13,18 +13,16 @@ any - - - auto - true - true - - - lax - - - + + auto + true + true + + + lax + + diff --git a/src/mpt/tests/basic/etc/config_specific.xml b/src/mpt/tests/basic/etc/config_specific.xml index 2ae3286..c6ccf33 100644 --- a/src/mpt/tests/basic/etc/config_specific.xml +++ b/src/mpt/tests/basic/etc/config_specific.xml @@ -13,18 +13,16 @@ ${DOMAIN_ID} - - - auto - true - true - - - lax - - - + + auto + true + true + + + lax + + From b8e4b2a49b366b48d98c041a206ef4376358b584 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 4 May 2019 15:21:52 +0800 Subject: [PATCH 061/178] don't modify input string in XML parser The XML parser has two modes: it can parse a file or parse a caller-owned string. In the former case, it owns its buffer and shifts the contents to make room for more data read in from the file. This shifting may not happen when parsing a string. Signed-off-by: Erik Boasson --- src/ddsrt/src/xmlparser.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/ddsrt/src/xmlparser.c b/src/ddsrt/src/xmlparser.c index 7a7e0cb..e22bf09 100644 --- a/src/ddsrt/src/xmlparser.c +++ b/src/ddsrt/src/xmlparser.c @@ -179,22 +179,22 @@ static int make_chars_available (struct ddsrt_xmlp_state *st, size_t nmin) return 1; } /* ensure buffer space is available */ - if (pos + nmin > st->cbufmax) { - memmove (st->cbuf, st->cbuf + pos, st->cbufn - pos); - st->cbufn -= pos; - st->cbufp -= pos; - if (st->cbufmark != NOMARKER) { - st->cbufmark -= pos; - } - } - /* buffer is owned by caller if fp = NULL, and by us if fp != NULL */ - if (st->cbufp + st->cbufmax < nmin && st->fp != NULL) { - st->cbufmax = st->cbufp + nmin; - st->cbuf = ddsrt_realloc (st->cbuf, st->cbufmax); - } - /* try to refill buffer if a backing file is present; eof (or end-of-string) is - reached when this doesn't add any bytes to the buffer */ if (st->fp != NULL) { + if (pos + nmin > st->cbufmax) { + memmove (st->cbuf, st->cbuf + pos, st->cbufn - pos); + st->cbufn -= pos; + st->cbufp -= pos; + if (st->cbufmark != NOMARKER) { + st->cbufmark -= pos; + } + } + /* buffer is owned by caller if fp = NULL, and by us if fp != NULL */ + if (st->cbufp + st->cbufmax < nmin) { + st->cbufmax = st->cbufp + nmin; + st->cbuf = ddsrt_realloc (st->cbuf, st->cbufmax); + } + /* try to refill buffer if a backing file is present; eof (or end-of-string) is + reached when this doesn't add any bytes to the buffer */ n = fread (st->cbuf + st->cbufn, 1, st->cbufmax - st->cbufn, st->fp); st->cbufn += n; } From 5ca66f5bda337964a5a509702ba78a979d2fe024 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 4 May 2019 15:26:53 +0800 Subject: [PATCH 062/178] Allow closing config elems with if from envvar The Cyclone DDS configuration is in principle an XML document, but it is possible to write configuration fragments directly in the CYCLONEDDS_URI environment variable. In that case, it is quite annoying to have to enter the full closing tags all the time, and so it now allows closing elements with a simple when not reading them from a file. While it would be trivial to also allow this when reading the configuration from a file, it seems that promulgating invalid XML would be bad form ... and besides, in that case editors can help keep everything in order. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_config.c | 2 +- src/ddsrt/include/dds/ddsrt/xmlparser.h | 5 ++++- src/ddsrt/src/xmlparser.c | 26 +++++++++++++++---------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index d9c37db..d12bc21 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -2685,7 +2685,7 @@ struct cfgst * config_init (const char *configfile) if (tok[0] == '<') { /* Read XML directly from input string */ qx = ddsrt_xmlp_new_string (tok, cfgst, &cb); - ddsrt_xmlp_set_requireEOF (qx, 0); + ddsrt_xmlp_set_options (qx, DDSRT_XMLP_ANONYMOUS_CLOSE_TAG); fp = NULL; } else { char *comma; diff --git a/src/ddsrt/include/dds/ddsrt/xmlparser.h b/src/ddsrt/include/dds/ddsrt/xmlparser.h index 120be63..e33815b 100644 --- a/src/ddsrt/include/dds/ddsrt/xmlparser.h +++ b/src/ddsrt/include/dds/ddsrt/xmlparser.h @@ -36,9 +36,12 @@ extern "C" { struct ddsrt_xmlp_state; +#define DDSRT_XMLP_REQUIRE_EOF 1u /* set by default; if not set, junk may follow top-level closing tag */ +#define DDSRT_XMLP_ANONYMOUS_CLOSE_TAG 2u /* clear by default; if set allow closing an element with instead of */ + DDS_EXPORT struct ddsrt_xmlp_state *ddsrt_xmlp_new_file (FILE *fp, void *varg, const struct ddsrt_xmlp_callbacks *cb); DDS_EXPORT struct ddsrt_xmlp_state *ddsrt_xmlp_new_string (const char *string, void *varg, const struct ddsrt_xmlp_callbacks *cb); - DDS_EXPORT void ddsrt_xmlp_set_requireEOF (struct ddsrt_xmlp_state *st, int require_eof); + DDS_EXPORT void ddsrt_xmlp_set_options (struct ddsrt_xmlp_state *st, unsigned options); DDS_EXPORT size_t ddsrt_xmlp_get_bufpos (const struct ddsrt_xmlp_state *st); DDS_EXPORT void ddsrt_xmlp_free (struct ddsrt_xmlp_state *st); DDS_EXPORT int ddsrt_xmlp_parse (struct ddsrt_xmlp_state *st); diff --git a/src/ddsrt/src/xmlparser.c b/src/ddsrt/src/xmlparser.c index e22bf09..ded4337 100644 --- a/src/ddsrt/src/xmlparser.c +++ b/src/ddsrt/src/xmlparser.c @@ -49,7 +49,7 @@ struct ddsrt_xmlp_state { size_t tpescp; /* still escape sequences in tpescp .. tpp */ int nest; /* current nesting level */ void *varg; /* user argument to callback functions */ - int require_eof; /* if false, junk may follow top-level closing tag */ + unsigned options; struct ddsrt_xmlp_callbacks cb; /* user-supplied callbacks (or stubs) */ }; @@ -108,7 +108,7 @@ static void ddsrt_xmlp_new_common (struct ddsrt_xmlp_state *st) st->peekpayload = NULL; st->nest = 0; st->error = 0; - st->require_eof = 1; + st->options = DDSRT_XMLP_REQUIRE_EOF; } static void ddsrt_xmlp_new_setCB (struct ddsrt_xmlp_state *st, void *varg, const struct ddsrt_xmlp_callbacks *cb) @@ -148,9 +148,9 @@ struct ddsrt_xmlp_state *ddsrt_xmlp_new_string (const char *string, void *varg, return st; } -void ddsrt_xmlp_set_requireEOF (struct ddsrt_xmlp_state *st, int require_eof) +void ddsrt_xmlp_set_options (struct ddsrt_xmlp_state *st, unsigned options) { - st->require_eof = require_eof; + st->options = options; } size_t ddsrt_xmlp_get_bufpos (const struct ddsrt_xmlp_state *st) @@ -451,11 +451,14 @@ static int next_token_tag_withoutclose (struct ddsrt_xmlp_state *st, char **payl next_char (st); } /* we only do tag names that are identifiers */ - if (!qq_isidentfirst (peek_char (st))) { + if (peek_char (st) == '>' && (st->options & DDSRT_XMLP_ANONYMOUS_CLOSE_TAG)) { + return TOK_SHORTHAND_CLOSE_TAG; + } else if (!qq_isidentfirst (peek_char (st))) { return TOK_ERROR; + } else { + next_token_ident (st, payload); + return tok; } - next_token_ident (st, payload); - return tok; } } @@ -560,6 +563,9 @@ static int next_token (struct ddsrt_xmlp_state *st, char **payload) } } if (tok == TOK_ERROR) { + char msg[512]; + (void) snprintf (msg, sizeof (msg), "invalid token encountered"); + st->cb.error (st->varg, msg, st->line); st->error = 1; } return tok; @@ -674,10 +680,10 @@ static int parse_element (struct ddsrt_xmlp_state *st, uintptr_t parentinfo) } } st->nest--; - if (next_token (st, &ename) != TOK_CLOSE_TAG || next_char (st) != '>') { + if (((tok = next_token (st, &ename)) != TOK_CLOSE_TAG && tok != TOK_SHORTHAND_CLOSE_TAG) || next_char (st) != '>') { PE_LOCAL_ERROR ("expecting closing tag", name); } - if (strcmp (name, ename) != 0) { + if (tok != TOK_SHORTHAND_CLOSE_TAG && strcmp (name, ename) != 0) { PE_LOCAL_ERROR ("open/close tag mismatch", ename); } ret = st->cb.elem_close (st->varg, eleminfo); @@ -709,7 +715,7 @@ int ddsrt_xmlp_parse (struct ddsrt_xmlp_state *st) return 0; } else { int ret = parse_element (st, 0); - if (ret < 0|| !st->require_eof || next_token (st, NULL) == TOK_EOF ) { + if (ret < 0|| !(st->options & DDSRT_XMLP_REQUIRE_EOF) || next_token (st, NULL) == TOK_EOF ) { return ret; } else { return -1; From f27baa71e4f28cac8c085b73ea8e91ddcdff7bd9 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 5 May 2019 10:05:16 +0800 Subject: [PATCH 063/178] fix assert on appl thread existing after dds_fini The thread state management used by the GC and the liveliness monitoring lazily creates entries for application threads that call (certain) Cyclone API functions. It arranges for the entry allocated to such a thread to be cleared once the thread terminates. This means that if such a thread still exists once the last participant is deleted (and Cyclone deinitializes), the corresponding thread entry still exists as well. The assertion that all (known) threads must have stopped on shutting down Cyclone is therefore incorrect. This commit introduces a special state for thread entries that were created lazily. It does monitor that they do not stay in the "awake" state for too long, but otherwise doesn't care much about them. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_thread.h | 7 +-- src/core/ddsi/src/ddsi_threadmon.c | 8 +-- src/core/ddsi/src/q_thread.c | 73 ++++++++--------------- 3 files changed, 33 insertions(+), 55 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_thread.h b/src/core/ddsi/include/dds/ddsi/q_thread.h index 71c9e5e..4d572d2 100644 --- a/src/core/ddsi/include/dds/ddsi/q_thread.h +++ b/src/core/ddsi/include/dds/ddsi/q_thread.h @@ -49,8 +49,9 @@ typedef int32_t svtime_t; /* signed version */ #define Q_THREAD_SCHEDPRIO_DEFAULT 0 enum thread_state { - THREAD_STATE_ZERO, - THREAD_STATE_ALIVE + THREAD_STATE_ZERO, /* known to be dead */ + THREAD_STATE_LAZILY_CREATED, /* lazily created in response because an application used it. Reclaimed if the thread terminates, but not considered an error if all of Cyclone is shutdown while this thread hasn't terminated yet */ + THREAD_STATE_ALIVE /* known to be alive - for Cyclone internal threads */ }; struct logbuf; @@ -101,8 +102,6 @@ DDS_EXPORT dds_retcode_t create_thread (struct thread_state1 **ts, const char *n DDS_EXPORT struct thread_state1 *lookup_thread_state_real (void); DDS_EXPORT int join_thread (struct thread_state1 *ts1); DDS_EXPORT void log_stack_traces (void); -DDS_EXPORT struct thread_state1 *get_thread_state (ddsrt_thread_t id); -DDS_EXPORT struct thread_state1 * init_thread_state (const char *tname); DDS_EXPORT void reset_thread_state (struct thread_state1 *ts1); DDS_EXPORT int thread_exists (const char *name); diff --git a/src/core/ddsi/src/ddsi_threadmon.c b/src/core/ddsi/src/ddsi_threadmon.c index f257261..6098d71 100644 --- a/src/core/ddsi/src/ddsi_threadmon.c +++ b/src/core/ddsi/src/ddsi_threadmon.c @@ -62,7 +62,7 @@ static uint32_t threadmon_thread (struct ddsi_threadmon *sl) if (ddsrt_cond_waitfor (&sl->cond, &sl->lock, config.liveliness_monitoring_interval)) continue; - unsigned n_alive = 0; + unsigned n_alive = 0, n_unused = 0; nn_mtime_t tnow = now_mt (); LOG_THREAD_CPUTIME (next_thread_cputime); @@ -81,8 +81,8 @@ static uint32_t threadmon_thread (struct ddsi_threadmon *sl) tlast = tnow; for (i = 0; i < thread_states.nthreads; i++) { - if (thread_states.ts[i].state != THREAD_STATE_ALIVE) - n_alive++; + if (thread_states.ts[i].state == THREAD_STATE_ZERO) + n_unused++; else { vtime_t vt = thread_states.ts[i].vtime; @@ -105,7 +105,7 @@ static uint32_t threadmon_thread (struct ddsi_threadmon *sl) } } - if (n_alive == thread_states.nthreads) + if (n_alive + n_unused == thread_states.nthreads) { DDS_TRACE(": [%u] OK\n", n_alive); was_alive = true; diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index e8ed142..6cf4a47 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -45,6 +45,8 @@ extern inline void thread_state_asleep (struct thread_state1 *ts1); extern inline void thread_state_awake (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, enum thread_state state); + void *ddsrt_malloc_aligned_cacheline (size_t size) { /* This wastes some space, but we use it only once and it isn't a @@ -115,16 +117,6 @@ void thread_states_fini (void) thread_states.ts = NULL; } -static void cleanup_thread_state (void *data) -{ - struct thread_state1 *ts = get_thread_state(ddsrt_thread_self()); - (void)data; - assert(ts->state == THREAD_STATE_ALIVE); - assert(vtime_asleep_p(ts->vtime)); - reset_thread_state(ts); - ddsrt_fini(); -} - static struct thread_state1 *find_thread_state (ddsrt_thread_t tid) { if (thread_states.ts) { @@ -138,6 +130,19 @@ static struct thread_state1 *find_thread_state (ddsrt_thread_t tid) return NULL; } +static void cleanup_thread_state (void *data) +{ + struct thread_state1 *ts = find_thread_state(ddsrt_thread_self()); + (void)data; + if (ts) + { + assert(ts->state == THREAD_STATE_LAZILY_CREATED); + assert(vtime_asleep_p(ts->vtime)); + reset_thread_state(ts); + } + ddsrt_fini(); +} + static struct thread_state1 *lazy_create_thread_state (ddsrt_thread_t self) { /* This situation only arises for threads that were not created using @@ -147,7 +152,7 @@ static struct thread_state1 *lazy_create_thread_state (ddsrt_thread_t self) char name[128]; ddsrt_thread_getname (name, sizeof (name)); ddsrt_mutex_lock (&thread_states.lock); - if ((ts1 = init_thread_state (name)) != NULL) { + if ((ts1 = init_thread_state (name, THREAD_STATE_LAZILY_CREATED)) != NULL) { ddsrt_init (); ts1->extTid = self; ts1->tid = self; @@ -191,18 +196,11 @@ static uint32_t create_thread_wrapper (void *ptr) static int find_free_slot (const char *name) { - unsigned i; - int cand; - for (i = 0, cand = -1; i < thread_states.nthreads; i++) - { - if (thread_states.ts[i].state != THREAD_STATE_ALIVE) - cand = (int) i; + for (unsigned i = 0; i < thread_states.nthreads; i++) if (thread_states.ts[i].state == THREAD_STATE_ZERO) - break; - } - if (cand == -1) - DDS_FATAL("create_thread: %s: no free slot\n", name ? name : "(anon)"); - return cand; + return (int) i; + DDS_FATAL("create_thread: %s: no free slot\n", name ? name : "(anon)"); + return -1; } void upgrade_main_thread (void) @@ -215,7 +213,7 @@ void upgrade_main_thread (void) ts1 = &thread_states.ts[cand]; if (ts1->state == THREAD_STATE_ZERO) assert (vtime_asleep_p (ts1->vtime)); - ts1->state = THREAD_STATE_ALIVE; + ts1->state = THREAD_STATE_LAZILY_CREATED; ts1->tid = ddsrt_thread_self (); ts1->name = main_thread_name; ddsrt_mutex_unlock (&thread_states.lock); @@ -231,7 +229,7 @@ const struct config_thread_properties_listelem *lookup_thread_properties (const return e; } -struct thread_state1 *init_thread_state (const char *tname) +static struct thread_state1 *init_thread_state (const char *tname, enum thread_state state) { int cand; struct thread_state1 *ts; @@ -240,12 +238,9 @@ struct thread_state1 *init_thread_state (const char *tname) return NULL; ts = &thread_states.ts[cand]; - if (ts->state == THREAD_STATE_ZERO) - { - assert (vtime_asleep_p (ts->vtime)); - } + assert (vtime_asleep_p (ts->vtime)); ts->name = ddsrt_strdup (tname); - ts->state = THREAD_STATE_ALIVE; + ts->state = state; return ts; } @@ -259,7 +254,7 @@ dds_retcode_t create_thread (struct thread_state1 **ts1, const char *name, uint3 ctxt = ddsrt_malloc (sizeof (*ctxt)); ddsrt_mutex_lock (&thread_states.lock); - *ts1 = init_thread_state (name); + *ts1 = init_thread_state (name, THREAD_STATE_ALIVE); if (*ts1 == NULL) goto fatal; @@ -336,28 +331,12 @@ void downgrade_main_thread (void) thread_states_init_static (); } -struct thread_state1 *get_thread_state (ddsrt_thread_t id) -{ - unsigned i; - struct thread_state1 *ts = NULL; - - for (i = 0; i < thread_states.nthreads; i++) - { - if (ddsrt_thread_equal (thread_states.ts[i].extTid, id)) - { - ts = &thread_states.ts[i]; - break; - } - } - return ts; -} - void log_stack_traces (void) { unsigned i; for (i = 0; i < thread_states.nthreads; i++) { - if (thread_states.ts[i].state == THREAD_STATE_ALIVE) + if (thread_states.ts[i].state != THREAD_STATE_ZERO) { log_stacktrace (thread_states.ts[i].name, thread_states.ts[i].tid); } From 2afb578a0ac52bc265afcc17cc8c7ada78682b7d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 5 May 2019 11:22:14 +0800 Subject: [PATCH 064/178] remove name arg from dds_create_topic_arbitrary The name parameter and the name in the sertopic parameter had to match because it used the one as a key in a lookup checking whether the topic exists already, and the other as key for the nodes in that index. As the name is (currently) included in the sertopic, it shouldn't be passed in separately as well. Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/dds.h | 4 +--- src/core/ddsc/src/dds_builtin.c | 2 +- src/core/ddsc/src/dds_topic.c | 29 +++++++++++++---------------- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index d701117..07b1545 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -967,8 +967,7 @@ dds_create_topic( * matching is done on a combination of topic name and type name. * * @param[in] participant Participant on which to create the topic. - * @param[in] sertopic Internal description of the topic type. - * @param[in] name Name of the topic. + * @param[in] sertopic Internal description of the topic type (includes name). * @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). * @param[in] sedp_plist Topic description to be published as part of discovery (if NULL, not published). @@ -987,7 +986,6 @@ DDS_EXPORT dds_entity_t dds_create_topic_arbitrary ( dds_entity_t participant, struct ddsi_sertopic *sertopic, - const char *name, const dds_qos_t *qos, const dds_listener_t *listener, const struct nn_plist *sedp_plist); diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index 3f50c60..fff187a 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -97,7 +97,7 @@ dds_entity_t dds__get_builtin_topic (dds_entity_t e, dds_entity_t topic) } dds_qos_t *qos = dds__create_builtin_qos (); - tp = dds_create_topic_arbitrary (pp, sertopic, sertopic->name, qos, NULL, NULL); + tp = dds_create_topic_arbitrary (pp, sertopic, qos, NULL, NULL); dds_delete_qos (qos); return tp; } diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 747976c..c0cb41d 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -191,6 +191,11 @@ dds_find_topic( ddsrt_mutex_lock (&dds_global.m_mutex); st = dds_topic_lookup_locked (p->m_domain, name); if (st) { + /* FIXME: calling addref is wrong because the Cyclone library has no + knowledge of the reference and hence simply deleting the participant + won't make the ref count drop to 0. On the other hand, the DDS spec + says find_topic (and a second call to create_topic) return a new + proxy that must separately be deleted. */ dds_entity_add_ref (&st->status_cb_entity->m_entity); tp = st->status_cb_entity->m_entity.m_hdllink.hdl; } else { @@ -300,7 +305,6 @@ DDS_EXPORT dds_entity_t dds_create_topic_arbitrary ( dds_entity_t participant, struct ddsi_sertopic *sertopic, - const char *name, const dds_qos_t *qos, const dds_listener_t *listener, const nn_plist_t *sedp_plist) @@ -319,18 +323,6 @@ dds_create_topic_arbitrary ( goto bad_param_err; } - if (name == NULL) { - DDS_ERROR("Topic name is NULL\n"); - hdl = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - goto bad_param_err; - } - - if (!is_valid_name(name)) { - DDS_ERROR("Topic name contains characters that are not allowed\n"); - hdl = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - goto bad_param_err; - } - rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); if (rc != DDS_RETCODE_OK) { hdl = DDS_ERRNO(rc); @@ -349,8 +341,8 @@ dds_create_topic_arbitrary ( /* Check if topic already exists with same name */ ddsrt_mutex_lock (&dds_global.m_mutex); - if ((stgeneric = dds_topic_lookup_locked (par->m_domain, name)) != NULL) { - if (!sertopic_equivalent (stgeneric,sertopic)) { + if ((stgeneric = dds_topic_lookup_locked (par->m_domain, sertopic->name)) != NULL) { + if (!sertopic_equivalent (stgeneric, sertopic)) { /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */ DDS_ERROR("Create topic with mismatching type\n"); hdl = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); @@ -359,6 +351,11 @@ dds_create_topic_arbitrary ( DDS_ERROR("Create topic with mismatching qos\n"); hdl = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); } else { + /* FIXME: calling addref is wrong because the Cyclone library has no + knowledge of the reference and hence simply deleting the participant + won't make the ref count drop to 0. On the other hand, the DDS spec + says find_topic (and a second call to create_topic) return a new + proxy that must separately be deleted. */ dds_entity_add_ref (&stgeneric->status_cb_entity->m_entity); hdl = stgeneric->status_cb_entity->m_entity.m_hdllink.hdl; } @@ -487,7 +484,7 @@ dds_create_topic( } } - hdl = dds_create_topic_arbitrary(participant, &st->c, name, qos, listener, &plist); + hdl = dds_create_topic_arbitrary(participant, &st->c, qos, listener, &plist); ddsi_sertopic_unref (&st->c); nn_plist_fini (&plist); From dba4e6d391a75440654b740f389e72256858a3bf Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 5 May 2019 11:25:18 +0800 Subject: [PATCH 065/178] change sertopic "deinit" to "free" The primary reason is that this allows the implementator of the sertopic to freely select an allocation strategy, instead of being forced to allocate the sertopic itself and the names it contains in the common header with ddsrt_malloc. The secondary reason is that it brings it in line with the serdata. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_sertopic_builtintopic.c | 9 ++++++--- src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h | 8 ++++---- src/core/ddsi/src/ddsi_sertopic.c | 8 ++------ src/core/ddsi/src/ddsi_sertopic_default.c | 10 +++++++--- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/core/ddsc/src/dds_sertopic_builtintopic.c b/src/core/ddsc/src/dds_sertopic_builtintopic.c index 7773a13..b38deba 100644 --- a/src/core/ddsc/src/dds_sertopic_builtintopic.c +++ b/src/core/ddsc/src/dds_sertopic_builtintopic.c @@ -45,9 +45,12 @@ struct ddsi_sertopic *new_sertopic_builtintopic (enum ddsi_sertopic_builtintopic return &tp->c; } -static void sertopic_builtin_deinit (struct ddsi_sertopic *tp) +static void sertopic_builtin_free (struct ddsi_sertopic *tp) { - (void)tp; + ddsrt_free (tp->name_type_name); + ddsrt_free (tp->name); + ddsrt_free (tp->type_name); + ddsrt_free (tp); } static void free_pp (void *vsample) @@ -141,7 +144,7 @@ static void sertopic_builtin_free_samples (const struct ddsi_sertopic *sertopic_ } const struct ddsi_sertopic_ops ddsi_sertopic_ops_builtintopic = { - .deinit = sertopic_builtin_deinit, + .free = sertopic_builtin_free, .zero_samples = sertopic_builtin_zero_samples, .realloc_samples = sertopic_builtin_realloc_samples, .free_samples = sertopic_builtin_free_samples diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h index 172af62..3f7ae75 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h @@ -44,7 +44,7 @@ struct ddsi_sertopic { }; /* Called when the refcount dropped to zero */ -typedef void (*ddsi_sertopic_deinit_t) (struct ddsi_sertopic *tp); +typedef void (*ddsi_sertopic_free_t) (struct ddsi_sertopic *tp); /* Zero out a sample, used for generating samples from just a key value and in cleaning up after dds_return_loan */ @@ -57,7 +57,7 @@ typedef void (*ddsi_sertopic_realloc_samples_t) (void **ptrs, const struct ddsi_ typedef void (*ddsi_sertopic_free_samples_t) (const struct ddsi_sertopic *d, void **ptrs, size_t count, dds_free_op_t op); struct ddsi_sertopic_ops { - ddsi_sertopic_deinit_t deinit; + ddsi_sertopic_free_t free; ddsi_sertopic_zero_samples_t zero_samples; ddsi_sertopic_realloc_samples_t realloc_samples; ddsi_sertopic_free_samples_t free_samples; @@ -67,8 +67,8 @@ DDS_EXPORT struct ddsi_sertopic *ddsi_sertopic_ref (const struct ddsi_sertopic * 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 inline void ddsi_sertopic_deinit (struct ddsi_sertopic *tp) { - tp->ops->deinit (tp); +DDS_EXPORT inline void ddsi_sertopic_free (struct ddsi_sertopic *tp) { + tp->ops->free (tp); } DDS_EXPORT inline void ddsi_sertopic_zero_samples (const struct ddsi_sertopic *tp, void *samples, size_t count) { tp->ops->zero_samples (tp, samples, count); diff --git a/src/core/ddsi/src/ddsi_sertopic.c b/src/core/ddsi/src/ddsi_sertopic.c index a309289..3ce5ef1 100644 --- a/src/core/ddsi/src/ddsi_sertopic.c +++ b/src/core/ddsi/src/ddsi_sertopic.c @@ -36,11 +36,7 @@ void ddsi_sertopic_unref (struct ddsi_sertopic *sertopic) { if (ddsrt_atomic_dec32_ov (&sertopic->refc) == 1) { - ddsi_sertopic_deinit (sertopic); - ddsrt_free (sertopic->name_type_name); - ddsrt_free (sertopic->name); - ddsrt_free (sertopic->type_name); - ddsrt_free (sertopic); + ddsi_sertopic_free (sertopic); } } } @@ -58,7 +54,7 @@ uint32_t ddsi_sertopic_compute_serdata_basehash (const struct ddsi_serdata_ops * return res; } -extern inline void ddsi_sertopic_deinit (struct ddsi_sertopic *tp); +extern inline void ddsi_sertopic_free (struct ddsi_sertopic *tp); extern inline void ddsi_sertopic_zero_samples (const struct ddsi_sertopic *tp, void *samples, size_t count); extern inline void ddsi_sertopic_realloc_samples (void **ptrs, const struct ddsi_sertopic *tp, void *old, size_t oldcount, size_t count); extern inline void ddsi_sertopic_free_samples (const struct ddsi_sertopic *tp, void **ptrs, size_t count, dds_free_op_t op); diff --git a/src/core/ddsi/src/ddsi_sertopic_default.c b/src/core/ddsi/src/ddsi_sertopic_default.c index 3fff736..81a40c7 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/heap.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" @@ -23,9 +24,12 @@ /* 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 */ -static void sertopic_default_deinit (struct ddsi_sertopic *tp) +static void sertopic_default_free (struct ddsi_sertopic *tp) { - (void)tp; + ddsrt_free (tp->name_type_name); + ddsrt_free (tp->name); + ddsrt_free (tp->type_name); + ddsrt_free (tp); } static void sertopic_default_zero_samples (const struct ddsi_sertopic *sertopic_common, void *sample, size_t count) @@ -76,7 +80,7 @@ static void sertopic_default_free_samples (const struct ddsi_sertopic *sertopic_ } const struct ddsi_sertopic_ops ddsi_sertopic_ops_default = { - .deinit = sertopic_default_deinit, + .free = sertopic_default_free, .zero_samples = sertopic_default_zero_samples, .realloc_samples = sertopic_default_realloc_samples, .free_samples = sertopic_default_free_samples From aa2715f4fe2e6bebfab9936ec5d369a4becd74d4 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Thu, 23 May 2019 14:27:56 +0200 Subject: [PATCH 066/178] Add support for FreeRTOS and lwIP (#166) Add support for FreeRTOS and lwIP Signed-off-by: Jeroen Koekkoek --- docs/dev/freertos.md | 103 ++++ ports/freertos-posix/CMakeLists.txt | 126 ++++ ports/freertos-posix/README.md | 83 +++ ports/freertos-posix/freertos-sim.cmake.in | 33 ++ ports/freertos-posix/include/FreeRTOSConfig.h | 74 +++ ports/freertos-posix/src/loader.c | 165 ++++++ src/CMakeLists.txt | 4 +- src/cmake/modules/CUnit/src/main.c.in | 4 - src/cmake/modules/FindCUnit.cmake | 13 +- .../modules/GenerateDummyExportHeader.cmake | 51 ++ src/cmake/modules/Packaging.cmake | 2 +- src/core/CMakeLists.txt | 12 +- src/core/ddsc/tests/participant.c | 1 - src/core/ddsi/include/dds/ddsi/q_log.h | 4 + src/core/ddsi/src/ddsi_raweth.c | 2 +- src/core/ddsi/src/ddsi_tcp.c | 6 + src/core/ddsi/src/ddsi_threadmon.c | 4 +- src/core/ddsi/src/ddsi_udp.c | 3 +- src/core/ddsi/src/q_nwif.c | 33 +- src/core/ddsi/src/q_sockwaitset.c | 57 +- src/core/ddsi/src/sysdeps.c | 2 +- src/ddsrt/CMakeLists.txt | 70 ++- src/ddsrt/cmake/ifaddrs.c | 23 + src/ddsrt/cmake/process.c | 18 + src/ddsrt/cmake/rusage.c | 19 + src/ddsrt/include/dds/ddsrt/endian.h | 10 +- src/ddsrt/include/dds/ddsrt/process.h | 19 +- src/ddsrt/include/dds/ddsrt/rusage.h | 12 + src/ddsrt/include/dds/ddsrt/sockets.h | 4 + src/ddsrt/include/dds/ddsrt/sockets/posix.h | 32 +- src/ddsrt/include/dds/ddsrt/sockets/windows.h | 2 +- src/ddsrt/include/dds/ddsrt/sync.h | 4 +- src/ddsrt/include/dds/ddsrt/sync/freertos.h | 93 +++ src/ddsrt/include/dds/ddsrt/threads.h | 6 +- .../include/dds/ddsrt/threads/freertos.h | 35 ++ src/ddsrt/include/dds/ddsrt/threads/posix.h | 6 + src/ddsrt/include/dds/ddsrt/threads/windows.h | 2 + src/ddsrt/include/dds/ddsrt/time.h | 4 + src/ddsrt/include/dds/ddsrt/time/freertos.h | 53 ++ src/ddsrt/include/dds/ddsrt/types/posix.h | 4 + src/ddsrt/src/heap/freertos/heap.c | 136 +++++ src/ddsrt/src/ifaddrs/lwip/ifaddrs.c | 207 +++++++ src/ddsrt/src/process/freertos/process.c | 22 + src/ddsrt/src/rusage/freertos/rusage.c | 96 +++ src/ddsrt/src/sockets.c | 34 +- .../sockets/include/dds/ddsrt/sockets_priv.h | 4 +- src/ddsrt/src/sockets/posix/gethostname.c | 31 +- src/ddsrt/src/sockets/posix/socket.c | 48 +- src/ddsrt/src/sync/freertos/sync.c | 469 +++++++++++++++ src/ddsrt/src/sync/freertos/tasklist.c | 396 +++++++++++++ src/ddsrt/src/threads/freertos/threads.c | 545 ++++++++++++++++++ .../threads/include/dds/ddsrt/threads_priv.h | 6 - src/ddsrt/src/threads/posix/threads.c | 6 + src/ddsrt/src/threads/windows/threads.c | 6 + src/ddsrt/src/time.c | 2 +- src/ddsrt/src/time/freertos/time.c | 53 ++ src/ddsrt/tests/CMakeLists.txt | 100 ++-- src/ddsrt/tests/ifaddrs.c | 12 +- src/ddsrt/tests/log.c | 16 +- src/ddsrt/tests/select.c | 36 +- src/ddsrt/tests/socket.c | 56 +- src/ddsrt/tests/sync.c | 4 +- src/ddsrt/tests/tasklist.c | 341 +++++++++++ src/ddsrt/tests/thread.c | 38 +- src/examples/roundtrip/ping.c | 6 +- src/examples/roundtrip/pong.c | 6 +- src/tools/ddsperf/ddsperf.c | 17 +- 67 files changed, 3691 insertions(+), 200 deletions(-) create mode 100644 docs/dev/freertos.md create mode 100644 ports/freertos-posix/CMakeLists.txt create mode 100644 ports/freertos-posix/README.md create mode 100644 ports/freertos-posix/freertos-sim.cmake.in create mode 100644 ports/freertos-posix/include/FreeRTOSConfig.h create mode 100644 ports/freertos-posix/src/loader.c create mode 100644 src/cmake/modules/GenerateDummyExportHeader.cmake create mode 100644 src/ddsrt/cmake/ifaddrs.c create mode 100644 src/ddsrt/cmake/process.c create mode 100644 src/ddsrt/cmake/rusage.c create mode 100644 src/ddsrt/include/dds/ddsrt/sync/freertos.h create mode 100644 src/ddsrt/include/dds/ddsrt/threads/freertos.h create mode 100644 src/ddsrt/include/dds/ddsrt/time/freertos.h create mode 100644 src/ddsrt/src/heap/freertos/heap.c create mode 100644 src/ddsrt/src/ifaddrs/lwip/ifaddrs.c create mode 100644 src/ddsrt/src/process/freertos/process.c create mode 100644 src/ddsrt/src/rusage/freertos/rusage.c create mode 100644 src/ddsrt/src/sync/freertos/sync.c create mode 100644 src/ddsrt/src/sync/freertos/tasklist.c create mode 100644 src/ddsrt/src/threads/freertos/threads.c create mode 100644 src/ddsrt/src/time/freertos/time.c create mode 100644 src/ddsrt/tests/tasklist.c diff --git a/docs/dev/freertos.md b/docs/dev/freertos.md new file mode 100644 index 0000000..e877f4b --- /dev/null +++ b/docs/dev/freertos.md @@ -0,0 +1,103 @@ +# FreeRTOS + +[FreeRTOS][1] is real-time operating system kernel for embedded devices. Think +of it as a thread library rather than a general purpose operating system like +Linux or Microsoft Windows. Out-of-the-box, FreeRTOS provides support for +tasks (threads), mutexes, semaphores and software times. Third-party modules +are available to add features. e.g. [lwIP][2] can be used to add networking. + +> FreeRTOS+lwIP is currently supported by Eclipse Cyclone DDS. Support for other +> network stacks, e.g. [FreeRTOS+TCP][3], may be added in the future. + +> Eclipse Cyclone DDS does not make use of [FreeRTOS+POSIX][4] because it was +> not available at the time. Future versions of Eclipse Cyclone DDS may or may +> not require FreeRTOS+POSIX for compatibility when it becomes stable. + +[1]: https://www.freertos.org/ +[2]: https://savannah.nongnu.org/projects/lwip/ +[3]: https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/index.html +[4]: https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_POSIX/index.html + + +## Target + +FreeRTOS provides an operating system kernel. Batteries are not included. i.e. +no C library or device drivers. Third-party distributions, known as board +support packages (BSP), for various (hardware) platforms are available though. + +Board support packages, apart from FreeRTOS, contain: + +* C library. Often ships with the compiler toolchain, e.g. + [IAR Embedded Workbench][5] includes the DLIB runtime, but open source + libraries can also be used. e.g. The [Xilinx Software Development Kit][6] + includes newlib. +* Device drivers. Generally available from the hardware vendor, e.g. NXP or + Xilinx. Device drivers for extra components, like a real-time clock, must + also be included in the board support package. + +[5]: https://www.iar.com/iar-embedded-workbench/ +[6]: https://www.xilinx.com/products/design-tools/embedded-software/sdk.html + +A board support package is linked with the application by the toolchain to +generate a binary that can be flashed to the target. + + +### Requirements + +Eclipse Cyclone DDS requires certain compile-time options to be enabled in +FreeRTOS (`FreeRTOSConfig.h`) and lwIP (`lwipopts.h`) for correct operation. +The compiler will croak when a required compile-time option is not enabled. + +Apart from the aforementioned compile-time options, the target and toolchain +must provide the following. +* Support for thread-local storage (TLS) from the compiler and linker. +* Berkeley socket API compatible socket interface. +* Real-time clock (RTC). A high-precision real-time clock is preferred, but + the monotonic clock can be combined with an offset obtained from e.g. the + network if the target lacks an actual real-time clock. A proper + `clock_gettime` implementation is required to retrieve the wall clock time. + + +### Thread-local storage + +FreeRTOS tasks are not threads and compiler supported thread-local storage +(tls) might not work as desired/expected under FreeRTOS on embedded targets. +i.e. the address of a given variable defined with *__thread* may be the same +for different tasks. + +The compiler generates code to retrieve a unique address per thread when it +encounters a variable defined with *__thread*. What code it generates depends +on the compiler and the target it generates the code for. e.g. `iccarm.exe` +that comes with IAR Embedded Workbench requires `__aeabi_read_tp` to be +implemented and `mb-gcc` that comes with the Xilinx SDK requires +`__tls_get_addr` to be implemented. + +The implementation for each of these functions is more-or-less the same. +Generally speaking they require the number of bytes to allocate, call +`pvTaskGetThreadLocalStoragePointer` and return the address of the memory +block to the caller. + + +## Simulator + +FreeRTOS ports for Windows and POSIX exist to test compatibility. How to +cross-compile Eclipse Cyclone DDS for the [FreeRTOS Windows Port][7] or +the unofficial [FreeRTOS POSIX Port][8] can be found in the msvc and +[posix](/ports/freertos-posix) port directories. + +[7]: https://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html +[8]: https://github.com/shlinym/FreeRTOS-Sim.git + + +## Known Limitations + +Triggering the socket waitset is not (yet) implemented for FreeRTOS+lwIP. This +introduces issues in scenarios where it is required. + + * Receive threads require a trigger to shutdown or a thread may block + indefinitely if no packet arrives from the network. + * Sockets are created dynamically if ManySocketsMode is used and a participant + is created, or TCP is used. A trigger is issued after the sockets are added + to the set if I/O multiplexing logic does not automatically wait for data + on the newly created sockets as well. + diff --git a/ports/freertos-posix/CMakeLists.txt b/ports/freertos-posix/CMakeLists.txt new file mode 100644 index 0000000..005e13b --- /dev/null +++ b/ports/freertos-posix/CMakeLists.txt @@ -0,0 +1,126 @@ +# +# 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 +# +cmake_minimum_required(VERSION 3.5) +project(FreeRTOS-Sim VERSION 10.0.2.0) + +include(GNUInstallDirs) + +# Some distributions place libraries in lib64 when the architecture is x86_64, +# but since the simulator is compiled with -m32, lib is a better name. +if(UNIX AND CMAKE_INSTALL_LIBDIR STREQUAL "lib64") + set(CMAKE_INSTALL_LIBDIR "lib") +endif() + +# Conflicts may be introduced when placing the libraries or headers in the +# default system locations, i.e. /usr/lib and /usr/include on *NIX platforms. +# The install prefix must therefore be postfixed with the project name. +if(UNIX) + set(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/${CMAKE_PROJECT_NAME}") +endif() + +set(ENTRYPOINT "real_main" + CACHE STRING "Alternate name of original entrypoint") +set(FREERTOS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/FreeRTOS-Sim" + CACHE STRING "Location of FreeRTOS POSIX Port sources") + +set(source_path "${FREERTOS_SOURCE_DIR}/Source") + +list(APPEND sources + "${source_path}/croutine.c" + "${source_path}/event_groups.c" + "${source_path}/list.c" + "${source_path}/queue.c" + "${source_path}/tasks.c" + "${source_path}/timers.c" + "${source_path}/portable/MemMang/heap_3.c" + "${source_path}/portable/GCC/POSIX/port.c") + +list(APPEND headers + "${source_path}/include/croutine.h" + "${source_path}/include/deprecated_definitions.h" + "${source_path}/include/event_groups.h" + "${source_path}/include/FreeRTOS.h" + "${source_path}/include/list.h" + "${source_path}/include/mpu_prototypes.h" + "${source_path}/include/mpu_wrappers.h" + "${source_path}/include/portable.h" + "${source_path}/include/projdefs.h" + "${source_path}/include/queue.h" + "${source_path}/include/semphr.h" + "${source_path}/include/StackMacros.h" + "${source_path}/include/task.h" + "${source_path}/include/timers.h" + "${source_path}/portable/GCC/POSIX/portmacro.h") + +list(APPEND headers + "${CMAKE_CURRENT_SOURCE_DIR}/include/FreeRTOSConfig.h") + +add_library(freertos-sim ${sources}) +target_compile_definitions( + freertos-sim PUBLIC __GCC_POSIX=1 MAX_NUMBER_OF_TASKS=300) +target_compile_options( + freertos-sim + PUBLIC + -m32 + PRIVATE + -W -Wall -Werror -Wmissing-braces -Wno-cast-align -Wparentheses -Wshadow + -Wno-sign-compare -Wswitch -Wuninitialized -Wunknown-pragmas + -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value + -Wunused-variable -Wmissing-prototypes) +target_include_directories( + freertos-sim + PUBLIC + "$" + "$" + "$" + "$") +target_link_libraries( + freertos-sim PUBLIC -m32 -pthread) + +if(CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR + CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO") + target_compile_options(freertos-sim PUBLIC -ggdb) + target_link_libraries(freertos-sim PUBLIC -ggdb) +endif() + +# The FreeRTOS POSIX Port does not require hardware to be initialized (unless +# lwIP is used), but the scheduler must be started before it is safe to execute +# application code. A "loader" is built to avoid modifications to existing +# code. The generated toolchain file will automatically redefine "main" to +# "real_main". The "real_main" function is executed once the scheduler is +# started. +# +# The loader is not part of the freertos-sim target as it has no place in the +# board support package. +add_library(freertos-sim-loader + "${CMAKE_CURRENT_SOURCE_DIR}/src/loader.c") +set_source_files_properties( + "${CMAKE_CURRENT_SOURCE_DIR}/src/loader.c" + PROPERTIES COMPILE_DEFINITIONS real_main=${ENTRYPOINT}) +target_link_libraries(freertos-sim-loader freertos-sim) + +install( + FILES ${headers} + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + +configure_file("freertos-sim.cmake.in" "freertos-sim.cmake" @ONLY) +install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/freertos-sim.cmake" + DESTINATION "${CMAKE_INSTALL_DATADIR}") + +install( + TARGETS freertos-sim freertos-sim-loader + EXPORT "${CMAKE_PROJECT_NAME}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") + diff --git a/ports/freertos-posix/README.md b/ports/freertos-posix/README.md new file mode 100644 index 0000000..f812374 --- /dev/null +++ b/ports/freertos-posix/README.md @@ -0,0 +1,83 @@ +# FreeRTOS POSIX Port + +FreeRTOS is a supported platform for Eclipse Cyclone DDS. This document +explains how to build and run Eclipse Cyclone DDS on the FreeRTOS POSIX Port. +For basic information, see: [freertos.md](/docs/dev/freertos.md). + +As the steps for building and running on the FreeRTOS POSIX Port are largely +the same as building and running on an actual embedded target, this document +should provide an excellent starting point for users. Apart from that, the +simulator can be used to verify commits do not break FreeRTOS compatibility. + +> lwIP can also be used in combination with both UNIX and Windows targets, but +> the simulator does not yet have integration. Once integration between both +> is figured out, this document should be updated accordingly. + + +## Build and install the simulator + +The FreeRTOS POSIX Port is not maintained by the FreeRTOS project. Various +projects are maintained across the internet. At the time of writing, the +version maintained by [Shilin][1] seemed the best as the version maintained by +[megakilo][2] was archived. + +[1]: https://github.com/shlinym/FreeRTOS-Sim.git +[2]: https://github.com/megakilo/FreeRTOS-Sim + +> A [FreeRTOS Linux Port][3] is in the works. Once it becomes stable, please +> update this document accordingly. + +[3]: https://sourceforge.net/p/freertos/discussion/382005/thread/f28af711/ + + +1. Clone the repository. The `CMakeLists.txt` in this directory assumes the + sources are available `./FreeRTOS-Sim` by default, but a different location + can be specified using the CMake option `FREERTOS_SOURCE_DIR`. + ``` +git clone https://github.com/shlinym/FreeRTOS-Sim.git +``` + +2. Specify an installation prefix and build the simulator like any other + CMake project. + ``` +mkdir build +cd build +cmake -DCMAKE_INSTALL_PREFIX=$(pwd)/install .. +cmake --build . --target install +``` + +> A CMake toolchain file is generated and installed into a `share` directory +> located under CMAKE\_INSTALL\_PREFIX/FreeRTOS-Sim. The compiler that CMake +> discovers and uses to build the simulator is exported in the toolchain file +> and will also be used to build Eclipse Cyclone DDS in the following steps. + + +## Build Eclipse Cyclone DDS for the simulator + +1. Change to the root of the repository and install the dependencies. + ``` +mkdir build +cd build +conan install -s arch=x86 .. +``` + +> For actual cross-compilation environments the instructions above will not +> install the correct packages. Even when e.g. Clang instead of GCC was used +> to build the simulator, the mismatch between Conan and CMake will break the +> build. To install the correct packages for the target, specify the required +> settings e.g. when the simulator was built using Clang 7.0, use +> `conan install -s arch=x86 -s compiler=clang -s compiler.version=7.0 ..`. +> If packages are not yet available for the target, as is usually the case +> with actual embedded targets, export the path to the toolchain file in the +> `CONAN_CMAKE_TOOLCHAIN_FILE` environment variable and add the `-b` flag to +> build the packages. + +2. Build Eclipse Cyclone DDS. + ``` +$ cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain/file -DWITH_FREERTOS=on ../src +``` + +> Examples (and tests) can be executed like usual. The simulator provides a +> *loader* that initializes the hardware (not used on non-embedded targets), +> starts the scheduler and loads the application. + diff --git a/ports/freertos-posix/freertos-sim.cmake.in b/ports/freertos-posix/freertos-sim.cmake.in new file mode 100644 index 0000000..73b85f2 --- /dev/null +++ b/ports/freertos-posix/freertos-sim.cmake.in @@ -0,0 +1,33 @@ +# +# 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 +# + +# +# CMake toolchain file generated by @CMAKE_PROJECT_NAME@ +# + +set(CMAKE_C_COMPILER "@CMAKE_C_COMPILER@") +set(CMAKE_CXX_COMPILER "@CMAKE_CXX_COMPILER@") + +set(include_path "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@") +set(library_path "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@") + +set(CMAKE_C_FLAGS "-I${include_path} -Dmain=@ENTRYPOINT@ -m32") +set(CMAKE_EXE_LINKER_FLAGS "-L${library_path}") +set(CMAKE_SHARED_LINKER_FLAGS "-L${library_path}") +set(CMAKE_C_STANDARD_LIBRARIES "-Wl,--start-group,-lfreertos-sim,-lfreertos-sim-loader,--end-group -m32 -lpthread") + +set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + diff --git a/ports/freertos-posix/include/FreeRTOSConfig.h b/ports/freertos-posix/include/FreeRTOSConfig.h new file mode 100644 index 0000000..a149f88 --- /dev/null +++ b/ports/freertos-posix/include/FreeRTOSConfig.h @@ -0,0 +1,74 @@ +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 1 +#define configTICK_RATE_HZ ( ( portTickType ) 1000 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 64 ) /* This can be made smaller if required. */ +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 64 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 16 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configCHECK_FOR_STACK_OVERFLOW 0 /* Do not use this option on the PC port. */ +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 20 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +//#define configMAX_SYSCALL_INTERRUPT_PRIORITY 1 + +#define configUSE_QUEUE_SETS 1 +#define configUSE_TASK_NOTIFICATIONS 1 + +/* Software timer related configuration options. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 20 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +#define configMAX_PRIORITIES ( 10 ) + +#define configGENERATE_RUN_TIME_STATS 1 + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. In most cases the linker will remove unused +functions anyway. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 /* Do not use this option on the PC port. */ +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_pcTaskGetTaskName 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetHandle 1 + +/* It is a good idea to define configASSERT() while developing. configASSERT() +uses the same semantics as the standard C assert() macro. */ +extern void vAssertCalled( unsigned long ulLine, const char * const pcFileName ); +#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __LINE__, __FILE__ ) + +#endif /* FREERTOS_CONFIG_H */ diff --git a/ports/freertos-posix/src/loader.c b/ports/freertos-posix/src/loader.c new file mode 100644 index 0000000..baec424 --- /dev/null +++ b/ports/freertos-posix/src/loader.c @@ -0,0 +1,165 @@ +/* + * 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 + */ + +/* + * Launcher to run existing programs in the FreeRTOS+lwIP Simulator. + * + * Verification of FreeRTOS+lwIP compatibility in Continuous Integration (CI) + * setups is another intended purpose. + */ + +#include +#include +#include +#include +#include +#include +#if _WIN32 +# define EX_OK (0) +# define EX_USAGE (64) +# define LF "\r\n" +#else +# include +# define LF "\n" +#endif + +#include +#include + +/* Setup system hardware. */ +void prvSetupHardware(void) +{ + /* No hardware to setup when running in the simulator. */ + return; +} + +void vAssertCalled(unsigned long ulLine, const char * const pcFileName) +{ + taskENTER_CRITICAL(); + { + fprintf(stderr, "[ASSERT] %s:%lu"LF, pcFileName, ulLine); + } + taskEXIT_CRITICAL(); + abort(); +} + +void vApplicationMallocFailedHook(void) +{ + vAssertCalled(__LINE__, __FILE__); +} + +void vApplicationIdleHook(void) { return; } + +void vApplicationTickHook( void ) { return; } + +static void usage(const char *name) +{ + static const char fmt[] = + "Usage: %s LAUNCHER_OPTIONS -- PROGRAM_OPTIONS"LF + "Try '%s -h' for more information"LF; + + fprintf(stderr, fmt, name, name); +} + +static void help(const char *name) +{ + static const char fmt[] = + "Usage: %s LAUNCHER_OPTIONS -- PROGRAM_OPTIONS"LF + ""LF + "Launcher options:"LF + " -h Show this help message and exit"LF; + + fprintf(stdout, fmt, name); +} + +typedef struct { + int argc; + char **argv; +} args_t; + +extern int real_main(int argc, char *argv[]); + +static void vMainTask(void *ptr) +{ + args_t *args = (args_t *)ptr; + /* Reset getopt global variables. */ + opterr = 1; + optind = 1; + (void)real_main(args->argc, args->argv); + vPortFree(args->argv); + vPortFree(args); + vTaskDelete(NULL); + _Exit(0); +} + +int +main(int argc, char *argv[]) +{ + int opt; + char *name; + args_t *args = NULL; + + /* Determine program name. */ + assert(argc >= 0 && argv[0] != NULL); + name = strrchr(argv[0], '/'); + if (name != NULL) { + name++; + } else { + name = argv[0]; + } + + if ((args = pvPortMalloc(sizeof(*args))) == NULL) { + return EX_OSERR; + } + + memset(args, 0, sizeof(*args)); + + /* Parse command line options. */ + while ((opt = getopt(argc, argv, ":a:dg:hn:")) != -1) { + switch (opt) { + case 'h': + help(name); + exit(EX_OK); + case '?': + fprintf(stderr, "Unknown option '%c'"LF, opt); + usage(name); + exit(EX_USAGE); + case ':': + /* fall through */ + default: + fprintf(stderr, "Option '%c' requires an argument"LF, opt); + usage(name); + exit(EX_USAGE); + } + } + + /* Copy leftover arguments into a new array. */ + args->argc = (argc - optind) + 1; + args->argv = pvPortMalloc((args->argc + 1) * sizeof(*args->argv)); + if (args->argv == NULL) { + return EX_OSERR; + } + args->argv[0] = argv[0]; + for (int i = optind, j = 1; i < argc; i++, j++) { + args->argv[j] = argv[i]; + } + + prvSetupHardware(); + + xTaskCreate(vMainTask, name, + configMINIMAL_STACK_SIZE, args, (tskIDLE_PRIORITY + 1UL), + (xTaskHandle *) NULL); + + vTaskStartScheduler(); + + return EX_SOFTWARE; +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d1539dd..ba9fb57 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -191,11 +191,9 @@ endif() add_subdirectory(examples) -if (BUILD_TESTING) - # Multi Process Tests +if(BUILD_TESTING AND HAVE_MULTI_PROCESS) add_subdirectory(mpt) endif() - # Pull-in CPack and support for generating Config.cmake and packages. include(Packaging) diff --git a/src/cmake/modules/CUnit/src/main.c.in b/src/cmake/modules/CUnit/src/main.c.in index 2be3165..a61ac85 100644 --- a/src/cmake/modules/CUnit/src/main.c.in +++ b/src/cmake/modules/CUnit/src/main.c.in @@ -13,12 +13,8 @@ #include #include -#ifndef _WIN32 -#include -#else #define EX_USAGE (64) #define EX_SOFTWARE (70) -#endif /* _WIN32 */ #include #include diff --git a/src/cmake/modules/FindCUnit.cmake b/src/cmake/modules/FindCUnit.cmake index 5b19165..518ed8a 100644 --- a/src/cmake/modules/FindCUnit.cmake +++ b/src/cmake/modules/FindCUnit.cmake @@ -11,7 +11,12 @@ # set(CUNIT_HEADER "CUnit/CUnit.h") -find_path(CUNIT_INCLUDE_DIR ${CUNIT_HEADER}) +if(CONAN_INCLUDE_DIRS) + find_path(CUNIT_INCLUDE_DIR ${CUNIT_HEADER} HINTS ${CONAN_INCLUDE_DIRS}) +else() + find_path(CUNIT_INCLUDE_DIR ${CUNIT_HEADER}) +endif() + mark_as_advanced(CUNIT_INCLUDE_DIR) if(CUNIT_INCLUDE_DIR AND EXISTS "${CUNIT_INCLUDE_DIR}/${CUNIT_HEADER}") @@ -25,7 +30,11 @@ if(CUNIT_INCLUDE_DIR AND EXISTS "${CUNIT_INCLUDE_DIR}/${CUNIT_HEADER}") set(CUNIT_VERSION "${CUNIT_VERSION_MAJOR}.${CUNIT_VERSION_MINOR}-${CUNIT_VERSION_PATCH}") endif() -find_library(CUNIT_LIBRARY cunit) +if(CONAN_LIB_DIRS) + find_library(CUNIT_LIBRARY cunit HINTS ${CONAN_LIB_DIRS}) +else() + find_library(CUNIT_LIBRARY cunit) +endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args( diff --git a/src/cmake/modules/GenerateDummyExportHeader.cmake b/src/cmake/modules/GenerateDummyExportHeader.cmake new file mode 100644 index 0000000..8a26e15 --- /dev/null +++ b/src/cmake/modules/GenerateDummyExportHeader.cmake @@ -0,0 +1,51 @@ +# 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 + +function(GENERATE_DUMMY_EXPORT_HEADER _target) + set(_opts) + set(_single_opts BASE_NAME EXPORT_FILE_NAME) + set(_multi_opts) + cmake_parse_arguments(_args "${_opts}" "${_single_opts}" "${_multi_opts}" ${ARGN}) + + if(NOT _target) + message(FATAL_ERROR "Target not specified") + elseif(NOT TARGET ${_target}) + message(FATAL_ERROR "Target ${_target} does not exist") + endif() + + string(TOUPPER _target_uc "${_target}") + string(TOLOWER _target_lc "${_target}") + + if(_args_EXPORT_FILE_NAME) + set(_path "${_args_EXPORT_FILE_NAME}") + else() + set(_path "${CMAKE_CURRENT_BINARY_DIR}/${_target_lc}_export.h") + endif() + + if(_args_BASE_NAME) + string(TOUPPER "${_args_BASE_NAME}" _base_name) + else() + set(_base_name "${_target_uc}") + endif() + + get_filename_component(_dir "${_path}" DIRECTORY) + get_filename_component(_file "${_path}" NAME) + + if(NOT IS_DIRECTORY "${_dir}") + file(MAKE_DIRECTORY "${_dir}") + endif() + + set(_content +"/* Dummy export header generated by CMake. */ +#define ${_base_name}_EXPORT\n") + + file(WRITE "${_path}" "${_content}") +endfunction() + diff --git a/src/cmake/modules/Packaging.cmake b/src/cmake/modules/Packaging.cmake index 9f0e53d..9b76487 100644 --- a/src/cmake/modules/Packaging.cmake +++ b/src/cmake/modules/Packaging.cmake @@ -37,7 +37,7 @@ install( "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}Version.cmake" DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" COMPONENT dev) -if(DDSC_SHARED AND ((NOT DEFINED BUILD_SHARED_LIBS) OR BUILD_SHARED_LIBS)) +if((NOT DEFINED BUILD_SHARED_LIBS) OR BUILD_SHARED_LIBS) # Generates Targets.cmake file included by Config.cmake. # The files are placed in CMakeFiles/Export in the build tree. install( diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8f36723..f08808e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -19,16 +19,10 @@ FUNCTION(PREPEND var prefix) SET(${var} "${listVar}" PARENT_SCOPE) ENDFUNCTION(PREPEND) -option(DDSC_SHARED "Build DDSC as a shared library" ON) - -if(DDSC_SHARED AND ((NOT DEFINED BUILD_SHARED_LIBS) OR BUILD_SHARED_LIBS)) - # BUILD_SHARED_LIBS is set to off by for example VxWorks DKM environment - add_library(ddsc SHARED "") +if (BUILD_SHARED_LIBS OR NOT DEFINED BUILD_SHARED_LIBS) + add_library(ddsc SHARED) else() - if(DDSC_SHARED) - message(STATUS "Option DDSC_SHARED ignored. Only static libraries supported on this platform.") - endif() - add_library(ddsc "") + add_library(ddsc) endif() add_definitions(-DDDSI_INCLUDE_NETWORK_PARTITIONS -DDDSI_INCLUDE_SSM) diff --git a/src/core/ddsc/tests/participant.c b/src/core/ddsc/tests/participant.c index 14a8171..6b7155d 100644 --- a/src/core/ddsc/tests/participant.c +++ b/src/core/ddsc/tests/participant.c @@ -92,7 +92,6 @@ CU_Test(ddsc_participant, create_with_conf_no_env) { //invalid domain participant = dds_create_participant (1, NULL, NULL); - printf("\n participant is %d\n", participant); CU_ASSERT_FATAL(participant < 0); //valid specific domain value diff --git a/src/core/ddsi/include/dds/ddsi/q_log.h b/src/core/ddsi/include/dds/ddsi/q_log.h index 7a0bfda..2c9dc29 100644 --- a/src/core/ddsi/include/dds/ddsi/q_log.h +++ b/src/core/ddsi/include/dds/ddsi/q_log.h @@ -23,6 +23,7 @@ extern "C" { #endif /* LOG_THREAD_CPUTIME must be considered private. */ +#if DDSRT_HAVE_RUSAGE #define LOG_THREAD_CPUTIME(guard) \ do { \ if (dds_get_log_mask() & DDS_LC_TIMING) { \ @@ -40,6 +41,9 @@ extern "C" { } \ } \ } while (0) +#else +#define LOG_THREAD_CPUTIME(guard) (void)(guard) +#endif /* DDSRT_HAVE_RUSAGE */ #if defined (__cplusplus) } diff --git a/src/core/ddsi/src/ddsi_raweth.c b/src/core/ddsi/src/ddsi_raweth.c index 98cb1d5..dc409c7 100644 --- a/src/core/ddsi/src/ddsi_raweth.c +++ b/src/core/ddsi/src/ddsi_raweth.c @@ -24,7 +24,7 @@ #include "dds/ddsrt/log.h" #include "dds/ddsrt/sockets.h" -#ifdef __linux +#if defined(__linux) && !LWIP_SOCKET #include #include #include diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 8d7ec2b..676099c 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -368,7 +368,13 @@ static bool ddsi_tcp_select (ddsrt_socket_t sock, bool read, size_t pos) int32_t ready = 0; FD_ZERO (&fds); +#if LWIP_SOCKET == 1 + DDSRT_WARNING_GNUC_OFF(sign-conversion) +#endif FD_SET (sock, &fds); +#if LWIP_SOCKET == 1 + DDSRT_WARNING_GNUC_ON(sign-conversion) +#endif DDS_LOG(DDS_LC_TCP, "%s blocked %s: sock %d\n", ddsi_name, read ? "read" : "write", (int) sock); do { diff --git a/src/core/ddsi/src/ddsi_threadmon.c b/src/core/ddsi/src/ddsi_threadmon.c index 6098d71..1f9d4af 100644 --- a/src/core/ddsi/src/ddsi_threadmon.c +++ b/src/core/ddsi/src/ddsi_threadmon.c @@ -118,13 +118,14 @@ static uint32_t threadmon_thread (struct ddsi_threadmon *sl) was_alive = false; } +#if DDSRT_HAVE_RUSAGE if (dds_get_log_mask() & DDS_LC_TIMING) { ddsrt_rusage_t u; if (ddsrt_getrusage (DDSRT_RUSAGE_SELF, &u) == DDS_RETCODE_OK) { DDS_LOG(DDS_LC_TIMING, - "rusage: utime %d.%09d stime %d.%09d maxrss %ld data %ld vcsw %ld ivcsw %ld\n", + "rusage: utime %d.%09d stime %d.%09d maxrss %zu data %zu vcsw %zu ivcsw %zu\n", (int) (u.utime / DDS_NSECS_IN_SEC), (int) (u.utime % DDS_NSECS_IN_SEC), (int) (u.stime / DDS_NSECS_IN_SEC), @@ -132,6 +133,7 @@ static uint32_t threadmon_thread (struct ddsi_threadmon *sl) u.maxrss, u.idrss, u.nvcsw, u.nivcsw); } } +#endif /* DDSRT_HAVE_RUSAGE */ /* While deaf, we need to make sure the receive thread wakes up every now and then to try recreating sockets & rejoining multicast diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 53135f1..e2e1576 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -138,9 +138,10 @@ static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *d #if DDSRT_MSGHDR_FLAGS msg.msg_flags = (int) flags; #else + msg.msg_flags = 0; DDSRT_UNUSED_ARG(flags); #endif -#ifdef MSG_NOSIGNAL +#if MSG_NOSIGNAL && !LWIP_SOCKET sendflags |= MSG_NOSIGNAL; #endif do { diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index 3f5ac27..f15f9dd 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -96,12 +96,18 @@ static int set_rcvbuf (ddsrt_socket_t socket) uint32_t ReceiveBufferSize; socklen_t optlen = (socklen_t) sizeof (ReceiveBufferSize); uint32_t socket_min_rcvbuf_size; + dds_retcode_t rc; if (config.socket_min_rcvbuf_size.isdefault) socket_min_rcvbuf_size = 1048576; else socket_min_rcvbuf_size = config.socket_min_rcvbuf_size.value; - if (ddsrt_getsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) &ReceiveBufferSize, &optlen) != DDS_RETCODE_OK) - { + rc = ddsrt_getsockopt( + socket, SOL_SOCKET, SO_RCVBUF, (char *) &ReceiveBufferSize, &optlen); + /* TCP/IP stack may not support SO_RCVBUF. */ + if (rc == DDS_RETCODE_BAD_PARAMETER) { + DDS_LOG(DDS_LC_CONFIG, "cannot retrieve socket receive buffer size\n"); + return 0; + } else if (rc != DDS_RETCODE_OK) { print_sockerror ("get SO_RCVBUF"); return -2; } @@ -139,8 +145,13 @@ static int set_sndbuf (ddsrt_socket_t socket) { unsigned SendBufferSize; socklen_t optlen = (socklen_t) sizeof(SendBufferSize); - if (ddsrt_getsockopt(socket, SOL_SOCKET, SO_SNDBUF,(char *)&SendBufferSize, &optlen) != DDS_RETCODE_OK) - { + dds_retcode_t rc; + rc = ddsrt_getsockopt( + socket, SOL_SOCKET, SO_SNDBUF,(char *)&SendBufferSize, &optlen); + if (rc == DDS_RETCODE_BAD_PARAMETER) { + DDS_LOG(DDS_LC_CONFIG, "cannot retrieve socket send buffer size\n"); + return 0; + } else if (rc != DDS_RETCODE_OK) { print_sockerror ("get SO_SNDBUF"); return -2; } @@ -191,12 +202,16 @@ static int set_reuse_options (ddsrt_socket_t socket) /* Set REUSEADDR (if available on platform) for multicast sockets, leave unicast sockets alone. */ int one = 1; - - if (ddsrt_setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof (one)) != DDS_RETCODE_OK) - { + dds_retcode_t rc = ddsrt_setsockopt ( + socket, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof (one)); + if (rc == DDS_RETCODE_BAD_PARAMETER) { + DDS_LOG(DDS_LC_CONFIG, "cannot enable address reuse on socket\n"); + return 0; + } else if (rc != DDS_RETCODE_OK) { print_sockerror ("SO_REUSEADDR"); return -2; } + return 0; } @@ -266,7 +281,7 @@ static int set_mc_options_transmit_ipv4 (ddsrt_socket_t socket) unsigned char loop; dds_retcode_t ret; -#if defined __linux || defined __APPLE__ +#if (defined(__linux) || defined(__APPLE__)) && !LWIP_SOCKET if (config.use_multicast_if_mreqn) { struct ip_mreqn mreqn; @@ -470,7 +485,7 @@ int find_own_ip (const char *requested_address) continue; } -#ifdef __linux +#if defined(__linux) && !LWIP_SOCKET if (ifa->addr->sa_family == AF_PACKET) { /* FIXME: weirdo warning warranted */ diff --git a/src/core/ddsi/src/q_sockwaitset.c b/src/core/ddsi/src/q_sockwaitset.c index f8a761f..833312d 100644 --- a/src/core/ddsi/src/q_sockwaitset.c +++ b/src/core/ddsi/src/q_sockwaitset.c @@ -509,7 +509,7 @@ int os_sockWaitsetNextEvent (os_sockWaitsetCtx ctx, ddsi_tran_conn_t * conn) #define OSPL_PIPENAMESIZE 26 #endif -#ifndef _WIN32 +#if !_WIN32 && !LWIP_SOCKET #ifndef __VXWORKS__ #include @@ -524,7 +524,7 @@ int os_sockWaitsetNextEvent (os_sockWaitsetCtx ctx, ddsi_tran_conn_t * conn) #include #endif -#endif /* _WIN32 */ +#endif /* !_WIN32 && !LWIP_SOCKET */ typedef struct os_sockWaitsetSet { @@ -586,7 +586,7 @@ fail: closesocket (s2); return -1; } -#elif defined (VXWORKS_RTP) || defined (_WRS_KERNEL) +#elif defined(__VXWORKS__) static int make_pipe (int pfd[2]) { char pipename[OSPL_PIPENAMESIZE]; @@ -609,7 +609,7 @@ fail_open0: fail_pipedev: return -1; } -#else +#elif !defined(LWIP_SOCKET) static int make_pipe (int pfd[2]) { return pipe (pfd); @@ -644,7 +644,11 @@ os_sockWaitset os_sockWaitsetNew (void) ws->fdmax_plus_1 = FD_SETSIZE; #endif -#if defined (VXWORKS_RTP) || defined (_WRS_KERNEL) +#if defined(LWIP_SOCKET) + ws->pipe[0] = -1; + ws->pipe[1] = -1; + result = 0; +#elif defined(__VXWORKS__) int make_pipe (int pfd[2]) { char pipename[OSPL_PIPENAMESIZE]; @@ -679,15 +683,21 @@ os_sockWaitset os_sockWaitsetNew (void) assert (result != -1); (void) result; +#if !defined(LWIP_SOCKET) ws->set.fds[0] = ws->pipe[0]; +#else + ws->set.fds[0] = 0; +#endif ws->set.conns[0] = NULL; -#if ! defined (VXWORKS_RTP) && ! defined ( _WRS_KERNEL ) && ! defined (_WIN32) +#if !defined(__VXWORKS__) && !defined(_WIN32) && !defined(LWIP_SOCKET) fcntl (ws->pipe[0], F_SETFD, fcntl (ws->pipe[0], F_GETFD) | FD_CLOEXEC); fcntl (ws->pipe[1], F_SETFD, fcntl (ws->pipe[1], F_GETFD) | FD_CLOEXEC); #endif +#if !defined(LWIP_SOCKET) FD_SET (ws->set.fds[0], &ws->ctx.rdset); -#if ! defined (_WIN32) +#endif +#if !defined(_WIN32) ws->fdmax_plus_1 = ws->set.fds[0] + 1; #endif @@ -716,18 +726,18 @@ static void os_sockWaitsetFreeCtx (os_sockWaitsetCtx ctx) void os_sockWaitsetFree (os_sockWaitset ws) { -#ifdef VXWORKS_RTP +#if defined(__VXWORKS__) && defined(__RTP__) char nameBuf[OSPL_PIPENAMESIZE]; ioctl (ws->pipe[0], FIOGETNAME, &nameBuf); #endif -#if defined (_WIN32) +#if defined(_WIN32) closesocket (ws->pipe[0]); closesocket (ws->pipe[1]); -#else +#elif !defined(LWIP_SOCKET) close (ws->pipe[0]); close (ws->pipe[1]); #endif -#ifdef VXWORKS_RTP +#if defined(__VXWORKS__) && defined(__RTP__) pipeDevDelete ((char*) &nameBuf, 0); #endif os_sockWaitsetFreeSet (&ws->set); @@ -738,6 +748,9 @@ void os_sockWaitsetFree (os_sockWaitset ws) void os_sockWaitsetTrigger (os_sockWaitset ws) { +#if defined(LWIP_SOCKET) + (void)ws; +#else char buf = 0; int n; @@ -750,6 +763,7 @@ void os_sockWaitsetTrigger (os_sockWaitset ws) { DDS_WARNING("os_sockWaitsetTrigger: write failed on trigger pipe\n"); } +#endif } int os_sockWaitsetAdd (os_sockWaitset ws, ddsi_tran_conn_t conn) @@ -863,10 +877,19 @@ os_sockWaitsetCtx os_sockWaitsetWait (os_sockWaitset ws) rdset = &ctx->rdset; FD_ZERO (rdset); +#if !defined(LWIP_SOCKET) for (u = 0; u < dst->n; u++) { FD_SET (dst->fds[u], rdset); } +#else + for (u = 1; u < dst->n; u++) + { + DDSRT_WARNING_GNUC_OFF(sign-conversion) + FD_SET (dst->fds[u], rdset); + DDSRT_WARNING_GNUC_ON(sign-conversion) + } +#endif /* LWIP_SOCKET */ do { @@ -883,6 +906,7 @@ os_sockWaitsetCtx os_sockWaitsetWait (os_sockWaitset ws) { /* this simply skips the trigger fd */ ctx->index = 1; +#if ! defined(LWIP_SOCKET) if (FD_ISSET (dst->fds[0], rdset)) { char buf; @@ -898,19 +922,26 @@ os_sockWaitsetCtx os_sockWaitsetWait (os_sockWaitset ws) assert (0); } } +#endif /* LWIP_SOCKET */ return ctx; } return NULL; } +#if defined(LWIP_SOCKET) +DDSRT_WARNING_GNUC_OFF(sign-conversion) +#endif + int os_sockWaitsetNextEvent (os_sockWaitsetCtx ctx, ddsi_tran_conn_t * conn) { while (ctx->index < ctx->set.n) { unsigned idx = ctx->index++; ddsrt_socket_t fd = ctx->set.fds[idx]; +#if ! defined (LWIP_SOCKET) assert(idx > 0); +#endif if (FD_ISSET (fd, &ctx->rdset)) { *conn = ctx->set.conns[idx]; @@ -921,6 +952,10 @@ int os_sockWaitsetNextEvent (os_sockWaitsetCtx ctx, ddsi_tran_conn_t * conn) return -1; } +#if defined(LWIP_SOCKET) +DDSRT_WARNING_GNUC_ON(sign-conversion) +#endif + #else #error "no mode selected" #endif diff --git a/src/core/ddsi/src/sysdeps.c b/src/core/ddsi/src/sysdeps.c index 13fa3f1..c233f16 100644 --- a/src/core/ddsi/src/sysdeps.c +++ b/src/core/ddsi/src/sysdeps.c @@ -20,7 +20,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/sysdeps.h" -#if !(defined __APPLE__ || defined __linux) || (__GNUC__ > 0 && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40100) +#if DDSRT_WITH_FREERTOS || !(defined __APPLE__ || defined __linux) || (__GNUC__ > 0 && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40100) void log_stacktrace (const char *name, ddsrt_thread_t tid) { DDSRT_UNUSED_ARG (name); diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index cda6f18..28069d0 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -11,12 +11,44 @@ # include(CheckCSourceCompiles) include(CheckLibraryExists) +include(GenerateDummyExportHeader) + +# Lightweight IP stack can be used on non-embedded targets too, but the +# runtime must be instructed to use it instead of the native stack. Of course +# for embedded targets there is no "native" stack and the runtime module must +# always be instructed to use an "alternative" stack. +option(WITH_LWIP "Use lightweight IP stack" OFF) +option(WITH_DNS "Enable domain name lookups" ON) +option(WITH_FREERTOS "Build for FreeRTOS" OFF) function(check_runtime_feature SOURCE_FILE) + get_target_property(_defs ddsrt INTERFACE_COMPILE_DEFINITIONS) + foreach(_def ${_defs}) + set(_strdefs "${_strdefs} -D${_def}") + endforeach() + + # Generate dummy export header required by feature tests. + generate_dummy_export_header( + ddsrt + BASE_NAME dds + EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/cmake/include/dds/export.h") + set(_strincs "${CMAKE_CURRENT_BINARY_DIR}/cmake/include") + + get_target_property(_incs ddsrt INTERFACE_INCLUDE_DIRECTORIES) + foreach(_inc ${_incs}) + set(_strincs "${_strincs};${_inc}") + endforeach() + + if(_strincs) + set(_strincs "-DINCLUDE_DIRECTORIES:STRING=${_strincs}") + endif() + set(expr "cmake_([_a-zA-Z0-9]+)=([_a-zA-Z0-9]+)") try_compile( foo "${CMAKE_BINARY_DIR}" SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE}" + CMAKE_FLAGS "${_strincs}" + COMPILE_DEFINITIONS "${_strdefs}" OUTPUT_VARIABLE output) string(REGEX MATCHALL "${expr}" matches "${output}") foreach(match ${matches}) @@ -26,7 +58,9 @@ function(check_runtime_feature SOURCE_FILE) endforeach() endfunction() -if(APPLE) +if(WITH_FREERTOS) + set(system_name freertos) +elseif(APPLE) set(system_name darwin) else() string(TOLOWER ${CMAKE_SYSTEM_NAME} system_name) @@ -38,6 +72,15 @@ endif() # ship an older version, so an interface library with public sources is used # as a workaround for now. add_library(ddsrt INTERFACE) + +foreach(opt WITH_LWIP WITH_DNS WITH_FREERTOS) + if(${opt}) + target_compile_definitions(ddsrt INTERFACE DDSRT_${opt}=1) + else() + target_compile_definitions(ddsrt INTERFACE DDSRT_${opt}=0) + endif() +endforeach() + target_include_directories( ddsrt INTERFACE "$" @@ -124,10 +167,9 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage # feature does not exist in cmake, the feature is expected to be # implemented for all targets. string(TOUPPER "${feature}" feature_uc) + set(HAVE_${feature_uc} TRUE) if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/${feature}.c") - check_runtime_feature(cmake/${feature}.c) - else() - set(HAVE_${feature_uc} TRUE) + check_runtime_feature("cmake/${feature}.c") endif() if(HAVE_${feature_uc}) @@ -137,7 +179,15 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage list(APPEND sources "${source_path}/${feature}.c") endif() set(system_exists FALSE) - foreach(system ${system_name} posix) + + # Allow custom implementations for a feature. e.g. lwip as opposed to + # windows or posix. + set(_system_name "${system_name}") + if(NOT HAVE_${feature_uc} MATCHES "[tT][rR][uU][eE]") + set(_system_name "${HAVE_${feature_uc}}") + endif() + + foreach(system ${_system_name} posix) # Headers that must remain private but are required by other runtime # source files must be located in src//dds/ddsrt. if(IS_DIRECTORY "${source_path}/${feature}/include") @@ -173,9 +223,13 @@ endforeach() target_sources(ddsrt INTERFACE ${sources}) -set(CMAKE_THREAD_PREFER_PTHREAD TRUE) -find_package(Threads REQUIRED) -target_link_libraries(ddsrt INTERFACE Threads::Threads) +set(HAVE_MULTI_PROCESS ${HAVE_MULTI_PROCESS} PARENT_SCOPE) + +if(NOT WITH_FREERTOS) + set(CMAKE_THREAD_PREFER_PTHREAD TRUE) + find_package(Threads REQUIRED) + target_link_libraries(ddsrt INTERFACE Threads::Threads) +endif() if(WIN32) target_link_libraries(ddsrt INTERFACE wsock32 ws2_32 iphlpapi bcrypt) diff --git a/src/ddsrt/cmake/ifaddrs.c b/src/ddsrt/cmake/ifaddrs.c new file mode 100644 index 0000000..aaa61f5 --- /dev/null +++ b/src/ddsrt/cmake/ifaddrs.c @@ -0,0 +1,23 @@ +/* + * 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/ifaddrs.h" + +#if DDSRT_WITH_LWIP +# if LWIP_SOCKET +# error "cmake_HAVE_IFADDRS=lwip" +# else +# error "cmake_HAVE_IFADDRS=false" +# endif +#else +# error "cmake_HAVE_IFADDRS=true" +#endif + diff --git a/src/ddsrt/cmake/process.c b/src/ddsrt/cmake/process.c new file mode 100644 index 0000000..a1f3561 --- /dev/null +++ b/src/ddsrt/cmake/process.c @@ -0,0 +1,18 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include "dds/ddsrt/process.h" + +#if DDSRT_HAVE_PROCESS +# error "cmake_HAVE_MULTI_PROCESS=true" +#else +# error "cmake_HAVE_MULTI_PROCESS=false" +#endif diff --git a/src/ddsrt/cmake/rusage.c b/src/ddsrt/cmake/rusage.c new file mode 100644 index 0000000..c9c6154 --- /dev/null +++ b/src/ddsrt/cmake/rusage.c @@ -0,0 +1,19 @@ +/* + * 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/rusage.h" + +#if DDSRT_HAVE_RUSAGE +# error "cmake_HAVE_RUSAGE=TRUE" +#else +# error "cmake_HAVE_RUSAGE=FALSE" +#endif + diff --git a/src/ddsrt/include/dds/ddsrt/endian.h b/src/ddsrt/include/dds/ddsrt/endian.h index a046b09..c1b831b 100644 --- a/src/ddsrt/include/dds/ddsrt/endian.h +++ b/src/ddsrt/include/dds/ddsrt/endian.h @@ -25,7 +25,15 @@ extern "C" { # else # define DDSRT_ENDIAN DDSRT_LITTLE_ENDIAN # endif -#else /* _WIN32 */ +/* _WIN32 */ +#elif defined(__IAR_SYSTEMS_ICC__) +# if __LITTLE_ENDIAN__ == 1 +# define DDSRT_ENDIAN DDSRT_LITTLE_ENDIAN +# else +# define DDSRT_ENDIAN DDSRT_BIG_ENDIAN +# endif +/* __IAR_SYSTEMS_ICC__ */ +#else # if defined(__BYTE_ORDER__) # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ # define DDSRT_ENDIAN DDSRT_BIG_ENDIAN diff --git a/src/ddsrt/include/dds/ddsrt/process.h b/src/ddsrt/include/dds/ddsrt/process.h index 45e7099..592508c 100644 --- a/src/ddsrt/include/dds/ddsrt/process.h +++ b/src/ddsrt/include/dds/ddsrt/process.h @@ -17,19 +17,30 @@ #include "dds/ddsrt/types.h" #include "dds/ddsrt/retcode.h" -#if defined(_WIN32) +#if DDSRT_WITH_FREERTOS +#include +#include +typedef TaskHandle_t ddsrt_pid_t; /* typedef void *TaskHandle_t */ +#define PRIdPID "p" +#define DDSRT_HAVE_MULTI_PROCESS 0 +/* DDSRT_WITH_FREERTOS */ +#elif defined(_WIN32) typedef DWORD ddsrt_pid_t; #define PRIdPID "u" -#else /* _WIN32 */ +#define DDSRT_HAVE_MULTI_PROCESS 1 +/* _WIN32 */ +#else #include #if defined(_WRS_KERNEL) typedef RTP_ID ddsrt_pid_t; /* typedef struct wind_rtp *RTP_ID */ #define PRIdPID PRIuPTR +#define DDSRT_HAVE_MULTI_PROCESS 0 #else typedef pid_t ddsrt_pid_t; #define PRIdPID "d" +#define DDSRT_HAVE_MULTI_PROCESS 1 +#endif #endif -#endif /* _WIN32 */ #if defined (__cplusplus) @@ -44,6 +55,7 @@ extern "C" { DDS_EXPORT ddsrt_pid_t ddsrt_getpid(void); +#if DDSRT_HAVE_MULTI_PROCESS /** * @brief Create new process. @@ -205,6 +217,7 @@ DDS_EXPORT dds_retcode_t ddsrt_proc_kill( ddsrt_pid_t pid); +#endif /* DDSRT_HAVE_MULTI_PROCESS */ #if defined (__cplusplus) } diff --git a/src/ddsrt/include/dds/ddsrt/rusage.h b/src/ddsrt/include/dds/ddsrt/rusage.h index 040ce2e..a58de6b 100644 --- a/src/ddsrt/include/dds/ddsrt/rusage.h +++ b/src/ddsrt/include/dds/ddsrt/rusage.h @@ -14,6 +14,18 @@ #include +#if DDSRT_WITH_FREERTOS +#include +# if configUSE_TRACE_FACILITY == 1 && \ + configGENERATE_RUN_TIME_STATS == 1 +# define DDSRT_HAVE_RUSAGE 1 +# else +# define DDSRT_HAVE_RUSAGE 0 +#endif +#else +# define DDSRT_HAVE_RUSAGE 1 +#endif + #include "dds/ddsrt/time.h" #include "dds/ddsrt/retcode.h" diff --git a/src/ddsrt/include/dds/ddsrt/sockets.h b/src/ddsrt/include/dds/ddsrt/sockets.h index ec5efa3..3876320 100644 --- a/src/ddsrt/include/dds/ddsrt/sockets.h +++ b/src/ddsrt/include/dds/ddsrt/sockets.h @@ -3,6 +3,10 @@ #include +#if !defined(DDSRT_WITH_DNS) +# define DDSRT_WITH_DNS 1 +#endif + #include "dds/export.h" #include "dds/ddsrt/types.h" #include "dds/ddsrt/attributes.h" diff --git a/src/ddsrt/include/dds/ddsrt/sockets/posix.h b/src/ddsrt/include/dds/ddsrt/sockets/posix.h index a9697af..a6f9574 100644 --- a/src/ddsrt/include/dds/ddsrt/sockets/posix.h +++ b/src/ddsrt/include/dds/ddsrt/sockets/posix.h @@ -12,12 +12,17 @@ #ifndef DDSRT_SOCKETS_POSIX_H #define DDSRT_SOCKETS_POSIX_H +#if DDSRT_WITH_LWIP +#include +#include +#else #include #include #include #include #include #include +#endif #if defined(__cplusplus) extern "C" { @@ -27,21 +32,38 @@ typedef int ddsrt_socket_t; #define DDSRT_INVALID_SOCKET (-1) #define PRIdSOCK "d" -#define DDSRT_HAVE_IPV6 1 -#define DDSRT_HAVE_DNS 1 -#define DDSRT_HAVE_SSM 1 +#if LWIP_SOCKET +# if LWIP_IPV6 +# define DDSRT_HAVE_IPV6 1 +# endif +# if LWIP_DNS && LWIP_SOCKET +# define DDSRT_HAVE_DNS DDSRT_WITH_DNS +# endif +# define DDSRT_HAVE_SSM 0 + +# define IFF_UP 0x1 +# define IFF_BROADCAST 0x2 +# define IFF_LOOPBACK 0x8 +# define IFF_POINTOPOINT 0x10 +# define IFF_MULTICAST 0x1000 +#else /* LWIP_SOCKET */ +# define DDSRT_HAVE_IPV6 1 +# define DDSRT_HAVE_DNS DDSRT_WITH_DNS +# define DDSRT_HAVE_SSM 1 +#endif /* LWIP_SOCKET */ typedef struct iovec ddsrt_iovec_t; typedef size_t ddsrt_iov_len_t; -#if defined(__linux) +#if defined(__linux) && !LWIP_SOCKET typedef size_t ddsrt_msg_iovlen_t; #else /* POSIX says int (which macOS, FreeBSD, Solaris do) */ typedef int ddsrt_msg_iovlen_t; #endif typedef struct msghdr ddsrt_msghdr_t; -#if defined(__sun) && !defined(_XPG4_2) +#if (defined(__sun) && !defined(_XPG4_2)) || \ + (defined(LWIP_SOCKET)) # define DDSRT_MSGHDR_FLAGS 0 #else # define DDSRT_MSGHDR_FLAGS 1 diff --git a/src/ddsrt/include/dds/ddsrt/sockets/windows.h b/src/ddsrt/include/dds/ddsrt/sockets/windows.h index 277dfe7..1735d39 100644 --- a/src/ddsrt/include/dds/ddsrt/sockets/windows.h +++ b/src/ddsrt/include/dds/ddsrt/sockets/windows.h @@ -13,7 +13,7 @@ typedef SOCKET ddsrt_socket_t; #define PRIdSOCK PRIuPTR #define DDSRT_HAVE_IPV6 1 -#define DDSRT_HAVE_DNS 1 +#define DDSRT_HAVE_DNS DDSRT_WITH_DNS #if defined(NTDDI_VERSION) && \ defined(_WIN32_WINNT_WS03) && \ diff --git a/src/ddsrt/include/dds/ddsrt/sync.h b/src/ddsrt/include/dds/ddsrt/sync.h index 8228aab..f071237 100644 --- a/src/ddsrt/include/dds/ddsrt/sync.h +++ b/src/ddsrt/include/dds/ddsrt/sync.h @@ -18,7 +18,9 @@ #include "dds/ddsrt/retcode.h" #include "dds/ddsrt/attributes.h" -#if _WIN32 +#if DDSRT_WITH_FREERTOS +#include "dds/ddsrt/sync/freertos.h" +#elif _WIN32 #include "dds/ddsrt/sync/windows.h" #else #include "dds/ddsrt/sync/posix.h" diff --git a/src/ddsrt/include/dds/ddsrt/sync/freertos.h b/src/ddsrt/include/dds/ddsrt/sync/freertos.h new file mode 100644 index 0000000..4d05578 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/sync/freertos.h @@ -0,0 +1,93 @@ +/* + * 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_SYNC_FREERTOS_H +#define DDSRT_SYNC_FREERTOS_H + +#include +#include +#include +#include + +#include "dds/ddsrt/atomics.h" + +#if (INCLUDE_vTaskSuspend != 1) +/* INCLUDE_vTaskSuspend must be set to 1 to make xSemaphoreTake wait + indefinitely when passed portMAX_DELAY. See reference manual. */ +#error "INCLUDE_vTaskSuspend != 1 in FreeRTOSConfig.h" +#endif + +#if defined (__cplusplus) +extern "C" { +#endif + +typedef struct { + SemaphoreHandle_t sem; +} ddsrt_mutex_t; + +typedef struct { + size_t len; + size_t cnt; + size_t off; + size_t end; + TaskHandle_t *tasks; +} ddsrt_tasklist_t; + +typedef struct { + SemaphoreHandle_t sem; + ddsrt_tasklist_t tasks; +} ddsrt_cond_t; + +/* This readers-writer lock implementation does not prefer writers over readers + or vice versa. Multiple readers are allowed to hold the lock simultaneously + and can acquire it directly if no writers are queued. However, if a writer + is queued, new readers and writers are queued behind it in order. Any reader + that acquires the lock after a writer frees it, notifies the next task. If + that task tries to acquire a write lock it waits until the reader frees the + lock. However, if the task tries to acquire a read lock it will succeed, and + notify the next task, etc. */ +typedef struct { + SemaphoreHandle_t sem; + ddsrt_tasklist_t tasks; + int32_t state; + uint32_t cnt; + uint32_t rdcnt; + uint32_t wrcnt; +} ddsrt_rwlock_t; + +typedef ddsrt_atomic_uint32_t ddsrt_once_t; +#define DDSRT_ONCE_INIT { .v = (1<<0) /* ONCE_NOT_STARTED */ } + + +/* The declarations below are here for tests and must be considered private. */ + +/* Number of buckets to grow buffer by. */ +#define DDSRT_TASKLIST_CHUNK (5) +/* Number of buckets to allocate initially. */ +#define DDSRT_TASKLIST_INITIAL (DDSRT_TASKLIST_CHUNK * 2) + +int ddsrt_tasklist_init(ddsrt_tasklist_t *list); +void ddsrt_tasklist_fini(ddsrt_tasklist_t *list); +void ddsrt_tasklist_ltrim(ddsrt_tasklist_t *list); +void ddsrt_tasklist_rtrim(ddsrt_tasklist_t *list); +void ddsrt_tasklist_pack(ddsrt_tasklist_t *list); +int ddsrt_tasklist_shrink(ddsrt_tasklist_t *list); +int ddsrt_tasklist_grow(ddsrt_tasklist_t *list); +ssize_t ddsrt_tasklist_find(ddsrt_tasklist_t *list, TaskHandle_t task); +TaskHandle_t ddsrt_tasklist_peek(ddsrt_tasklist_t *list, TaskHandle_t task); +TaskHandle_t ddsrt_tasklist_pop(ddsrt_tasklist_t *list, TaskHandle_t task); +int ddsrt_tasklist_push(ddsrt_tasklist_t *list, TaskHandle_t task); + +#if defined (__cplusplus) +} +#endif + +#endif /* DDSRT_SYNC_FREERTOS_H */ diff --git a/src/ddsrt/include/dds/ddsrt/threads.h b/src/ddsrt/include/dds/ddsrt/threads.h index 7497002..32f49bd 100644 --- a/src/ddsrt/include/dds/ddsrt/threads.h +++ b/src/ddsrt/include/dds/ddsrt/threads.h @@ -25,7 +25,9 @@ #include "dds/ddsrt/attributes.h" #include "dds/ddsrt/retcode.h" -#if _WIN32 +#if DDSRT_WITH_FREERTOS +#include "dds/ddsrt/threads/freertos.h" +#elif _WIN32 #include "dds/ddsrt/threads/windows.h" #else #include "dds/ddsrt/threads/posix.h" @@ -206,9 +208,11 @@ ddsrt_thread_getname( * * @param[in] name Name for current thread. */ +#if DDSRT_HAVE_THREAD_SETNAME DDS_EXPORT void ddsrt_thread_setname( const char *__restrict name); +#endif /** * @brief Push cleanup handler onto the cleanup stack diff --git a/src/ddsrt/include/dds/ddsrt/threads/freertos.h b/src/ddsrt/include/dds/ddsrt/threads/freertos.h new file mode 100644 index 0000000..73b2c7a --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/threads/freertos.h @@ -0,0 +1,35 @@ +/* + * 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_THREADS_FREERTOS_H +#define DDSRT_THREADS_FREERTOS_H + +#include +#include + +#define DDSRT_HAVE_THREAD_SETNAME (0) + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef struct { + TaskHandle_t task; +} ddsrt_thread_t; + +typedef UBaseType_t ddsrt_tid_t; +#define PRIdTID "lu" + +#if defined(__cplusplus) +} +#endif + +#endif /* DDSRT_THREADS_FREERTOS_H */ diff --git a/src/ddsrt/include/dds/ddsrt/threads/posix.h b/src/ddsrt/include/dds/ddsrt/threads/posix.h index 63d193d..0d15c27 100644 --- a/src/ddsrt/include/dds/ddsrt/threads/posix.h +++ b/src/ddsrt/include/dds/ddsrt/threads/posix.h @@ -14,6 +14,12 @@ #include +#if defined(__VXWORKS__) +#define DDSRT_HAVE_THREAD_SETNAME (0) +#else +#define DDSRT_HAVE_THREAD_SETNAME (1) +#endif + #if defined (__cplusplus) extern "C" { #endif diff --git a/src/ddsrt/include/dds/ddsrt/threads/windows.h b/src/ddsrt/include/dds/ddsrt/threads/windows.h index e7eda64..3354d65 100644 --- a/src/ddsrt/include/dds/ddsrt/threads/windows.h +++ b/src/ddsrt/include/dds/ddsrt/threads/windows.h @@ -14,6 +14,8 @@ #include "dds/ddsrt/types.h" +#define DDSRT_HAVE_THREAD_SETNAME (1) + #if defined (__cplusplus) extern "C" { #endif diff --git a/src/ddsrt/include/dds/ddsrt/time.h b/src/ddsrt/include/dds/ddsrt/time.h index 37fcfa3..a474fb4 100644 --- a/src/ddsrt/include/dds/ddsrt/time.h +++ b/src/ddsrt/include/dds/ddsrt/time.h @@ -146,4 +146,8 @@ DDS_EXPORT size_t ddsrt_ctime(dds_time_t abstime, char *str, size_t size); } #endif +#if DDSRT_WITH_FREERTOS +#include "dds/ddsrt/time/freertos.h" +#endif + #endif /* DDSRT_TIME_H */ diff --git a/src/ddsrt/include/dds/ddsrt/time/freertos.h b/src/ddsrt/include/dds/ddsrt/time/freertos.h new file mode 100644 index 0000000..09525ee --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/time/freertos.h @@ -0,0 +1,53 @@ +/* + * 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_TIME_FREERTOS_H +#define DDSRT_TIME_FREERTOS_H + +#include +#include + +#if defined (__cplusplus) +extern "C" { +#endif + +#define DDSRT_NSECS_PER_TICK (DDS_NSECS_IN_SEC / configTICK_RATE_HZ) + +inline TickType_t +ddsrt_duration_to_ticks_ceil( + dds_duration_t reltime) +{ + TickType_t ticks = 0; + + assert(portMAX_DELAY > configTICK_RATE_HZ); + + if (reltime == DDS_INFINITY) { + ticks = portMAX_DELAY; + } else if (reltime > 0) { + dds_duration_t max_nsecs = + (DDS_INFINITY / DDSRT_NSECS_PER_TICK < portMAX_DELAY + ? DDS_INFINITY - 1 : portMAX_DELAY * DDSRT_NSECS_PER_TICK); + + if (reltime > max_nsecs - (DDSRT_NSECS_PER_TICK - 1)) { + ticks = portMAX_DELAY; + } else { + ticks = (TickType_t)((reltime + (DDSRT_NSECS_PER_TICK - 1)) / DDSRT_NSECS_PER_TICK); + } + } + + return ticks; +} + +#if defined (__cplusplus) +} +#endif + +#endif /* DDSRT_TIME_FREERTOS_H */ diff --git a/src/ddsrt/include/dds/ddsrt/types/posix.h b/src/ddsrt/include/dds/ddsrt/types/posix.h index 6088737..1344dc1 100644 --- a/src/ddsrt/include/dds/ddsrt/types/posix.h +++ b/src/ddsrt/include/dds/ddsrt/types/posix.h @@ -14,6 +14,10 @@ #include #include +#if defined(__IAR_SYSTEMS_ICC__) +typedef long int ssize_t; +#else #include +#endif #endif /* DDSRT_TYPES_POSIX_H */ diff --git a/src/ddsrt/src/heap/freertos/heap.c b/src/ddsrt/src/heap/freertos/heap.c new file mode 100644 index 0000000..01782c4 --- /dev/null +++ b/src/ddsrt/src/heap/freertos/heap.c @@ -0,0 +1,136 @@ +/* + * 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 + +#if defined(configSUPPORT_DYNAMIC_ALLOCATION) && \ + (configSUPPORT_DYNAMIC_ALLOCATION == 0) +# error Dynamic memory allocation is not supported +#endif + +#include +#include +#include +#include + +static const size_t ofst = sizeof(size_t); + +void *ddsrt_malloc_s(size_t size) +{ + void *ptr = NULL; + + if (size == 0) { + size = 1; + } + + if ((SIZE_MAX - size) < ofst) { + errno = ERANGE; + } else { + ptr = pvPortMalloc(size + ofst); + if (ptr == NULL) { + errno = ENOMEM; + } else { + *((size_t *)ptr) = size; + ptr += ofst; + } + } + + return ptr; +} + +void *ddsrt_malloc(size_t size) +{ + void *ptr; + + if ((ptr = ddsrt_malloc_s(size)) == NULL) { + abort(); + } + + return ptr; +} + +void *ddsrt_calloc_s(size_t nmemb, size_t size) +{ + void *ptr = NULL; + + if (nmemb == 0 || size == 0) { + nmemb = size = 1; + } + + if ((SIZE_MAX / nmemb) <= size) { + errno = ERANGE; + } else { + ptr = ddsrt_malloc_s(nmemb * size); + (void)memset(ptr, 0, nmemb * size); + } + + return ptr; +} + +void *ddsrt_calloc(size_t nmemb, size_t size) +{ + void *ptr = NULL; + + if ((ptr = ddsrt_calloc_s(nmemb, size)) == NULL) { + abort(); + } + + return ptr; +} + +/* pvPortMalloc may be used instead of directly invoking malloc and free as + offered by the standard C library. Unfortunately FreeRTOS does not offer a + realloc compatible function and extra information must be embedded in every + memory block in order to support reallocation of memory (otherwise the + number of bytes that must be copied is unavailable). */ +void *ddsrt_realloc_s(void *memblk, size_t size) +{ + void *ptr = NULL; + size_t origsize = 0; + + if (memblk != NULL) { + origsize = *((size_t *)(memblk - ofst)); + } + + if (size != origsize || origsize == 0) { + if ((ptr = ddsrt_malloc_s(size)) == NULL) { + return NULL; + } + if (memblk != NULL) { + if (size > 0) { + (void)memcpy(ptr, memblk, size > origsize ? origsize : size); + } + vPortFree(memblk - ofst); + } + memblk = ptr; + } + + return memblk; +} + +void *ddsrt_realloc(void *memblk, size_t size) +{ + void *ptr = NULL; + + if ((ptr = ddsrt_realloc_s(memblk, size)) == NULL) { + abort(); + } + + return ptr; +} + +void +ddsrt_free(void *ptr) +{ + if (ptr != NULL) { + vPortFree(ptr - ofst); + } +} diff --git a/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c b/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c new file mode 100644 index 0000000..9d1e64e --- /dev/null +++ b/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c @@ -0,0 +1,207 @@ +/* + * 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 +#include /* netif_list */ +#include + +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/io.h" +#include "dds/ddsrt/ifaddrs.h" +#include "dds/ddsrt/retcode.h" +#include "dds/ddsrt/string.h" + +extern const int *const os_supp_afs; + +static uint32_t +getflags( + const struct netif *netif, + const ip_addr_t *addr) +{ + uint32_t flags = 0; + + if (netif->flags & NETIF_FLAG_UP) { + flags |= IFF_UP; + } + if (netif->flags & NETIF_FLAG_BROADCAST) { + flags |= IFF_BROADCAST; + } + if (netif->flags & NETIF_FLAG_IGMP) { + flags |= IFF_MULTICAST; + } + if (ip_addr_isloopback(addr)) { + flags |= IFF_LOOPBACK; + } + + return flags; +} + +static void +sockaddr_from_ip_addr( + struct sockaddr *sockaddr, + const ip_addr_t *addr) +{ + if (IP_IS_V4(addr)) { + memset(sockaddr, 0, sizeof(struct sockaddr_in)); + ((struct sockaddr_in *)sockaddr)->sin_len = sizeof(struct sockaddr_in); + ((struct sockaddr_in *)sockaddr)->sin_family = AF_INET; + inet_addr_from_ip4addr(&((struct sockaddr_in *)sockaddr)->sin_addr, addr); +#if DDSRT_HAVE_IPV6 + } else { + assert(IP_IS_V6(addr)); + memset(sockaddr, 0, sizeof(struct sockaddr_in6)); + ((struct sockaddr_in6 *)sockaddr)->sin6_len = sizeof(struct sockaddr_in6); + ((struct sockaddr_in6 *)sockaddr)->sin6_family = AF_INET6; + inet6_addr_from_ip6addr(&((struct sockaddr_in6 *)sockaddr)->sin6_addr, addr); +#endif + } +} + +static dds_retcode_t +copyaddr( + ddsrt_ifaddrs_t **ifap, + const struct netif *netif, + const ip_addr_t *addr) +{ + dds_retcode_t rc = DDS_RETCODE_OK; + ddsrt_ifaddrs_t *ifa; + struct sockaddr_storage sa; + + assert(ifap != NULL); + assert(netif != NULL); + assert(addr != NULL); + + sockaddr_from_ip_addr((struct sockaddr *)&sa, addr); + + /* Network interface name is of the form "et0", where the first two letters + are the "name" field and the digit is the num field of the netif + structure as described in lwip/netif.h */ + + if ((ifa = ddsrt_calloc_s(1, sizeof(*ifa))) == NULL || + (ifa->addr = ddsrt_memdup(&sa, sa.s2_len)) == NULL || + (ddsrt_asprintf(&ifa->name, "%s%d", netif->name, netif->num) == -1)) + { + rc = DDS_RETCODE_OUT_OF_RESOURCES; + } else { + ifa->flags = getflags(netif, addr); + ifa->index = netif->num; + + if (IP_IS_V4(addr)) { + static const size_t sz = sizeof(struct sockaddr_in); + if ((ifa->netmask = ddsrt_calloc_s(1, sz)) == NULL || + (ifa->broadaddr = ddsrt_calloc_s(1, sz)) == NULL) + { + rc = DDS_RETCODE_OUT_OF_RESOURCES; + } else { + ip_addr_t broadaddr = IPADDR4_INIT( + ip_2_ip4(&netif->ip_addr)->addr | + ip_2_ip4(&netif->netmask)->addr); + + sockaddr_from_ip_addr((struct sockaddr*)ifa->netmask, &netif->netmask); + sockaddr_from_ip_addr((struct sockaddr*)ifa->broadaddr, &broadaddr); + } + } + } + + if (rc == DDS_RETCODE_OK) { + *ifap = ifa; + } else { + ddsrt_freeifaddrs(ifa); + } + + return rc; +} + +dds_retcode_t +ddsrt_getifaddrs( + ddsrt_ifaddrs_t **ifap, + const int *afs) +{ + dds_retcode_t rc = DDS_RETCODE_OK; + int use_ip4, use_ip6; + struct netif *netif; + ddsrt_ifaddrs_t *ifa, *next_ifa, *root_ifa; + + assert(ifap != NULL); + + if (afs == NULL) { + afs = os_supp_afs; + } + + use_ip4 = use_ip6 = 0; + for (int i = 0; afs[i] != DDSRT_AF_TERM; i++) { + if (afs[i] == AF_INET) { + use_ip4 = 1; + } else if (afs[i] == AF_INET6) { + use_ip6 = 1; + } + } + + ifa = next_ifa = root_ifa = NULL; + + for (netif = netif_list; + netif != NULL && rc == DDS_RETCODE_OK; + netif = netif->next) + { + if (use_ip4 && IP_IS_V4(&netif->ip_addr)) { + rc = copyaddr(&next_ifa, netif, &netif->ip_addr); + if (rc == DDS_RETCODE_OK) { + if (ifa == NULL) { + ifa = root_ifa = next_ifa; + } else { + ifa->next = next_ifa; + ifa = next_ifa; + } + } + } + +#if DDSRT_HAVE_IPV6 + if (use_ip6) { + int pref = 1; +again: + /* List preferred IPv6 address first. */ + for (int i = 0; + i < LWIP_IPV6_NUM_ADDRESSES && rc == DDS_RETCODE_OK; + i++) + { + if ((ip6_addr_ispreferred(netif->ip_addr_state[i]) && pref) || + (ip6_addr_isvalid(netif->ip_addr_state[i]) && !pref)) + { + rc = copyaddr(&next_ifa, netif, &netif->ip_addr[i]); + if (rc == DDS_RETCODE_OK) { + if (ifa == NULL) { + ifa = root_ifa = next_ifa; + } else { + ifa->next = next_ifa; + ifa = next_ifa; + } + } + } + } + + if (rc == DDS_RETCODE_OK && pref) { + pref = 0; + goto again; + } + } +#endif + } + + if (rc == DDS_RETCODE_OK) { + *ifap = ifa; + } else { + ddsrt_freeifaddrs(root_ifa); + } + + return rc; +} diff --git a/src/ddsrt/src/process/freertos/process.c b/src/ddsrt/src/process/freertos/process.c new file mode 100644 index 0000000..b299888 --- /dev/null +++ b/src/ddsrt/src/process/freertos/process.c @@ -0,0 +1,22 @@ +/* + * 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/process.h" + +#include +#include + +ddsrt_pid_t +ddsrt_getpid(void) +{ + return xTaskGetCurrentTaskHandle(); +} + diff --git a/src/ddsrt/src/rusage/freertos/rusage.c b/src/ddsrt/src/rusage/freertos/rusage.c new file mode 100644 index 0000000..1f9d2f3 --- /dev/null +++ b/src/ddsrt/src/rusage/freertos/rusage.c @@ -0,0 +1,96 @@ +/* + * 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 + +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/rusage.h" + +/* Task CPU time statistics require a high resolution timer. FreeRTOS + recommends a time base between 10 and 100 times faster than the tick + interrupt (https://www.freertos.org/rtos-run-time-stats.html), but does not + define a macro or function to retrieve the base. */ + +/* Require time base to be defined for conversion to nanoseconds. */ + +#define DDSRT_NSECS_IN_RUSAGE_TIME_BASE (1) /* FIXME: Make configurable! */ + +#if !defined(DDSRT_NSECS_IN_RUSAGE_TIME_BASE) +#error "Time base for run time stats is not defined" +#endif + +static dds_retcode_t +rusage_self(ddsrt_rusage_t *usage) +{ + dds_retcode_t rc = DDS_RETCODE_OK; + dds_duration_t nsecs; + UBaseType_t cnt, len; + TaskStatus_t *states = NULL, *ptr; + size_t size; + + do { + len = uxTaskGetNumberOfTasks(); + size = len * sizeof(*states); + if ((ptr = ddsrt_realloc_s(states, size)) == NULL) { + rc = DDS_RETCODE_OUT_OF_RESOURCES; + } else { + states = ptr; + /* uxTaskGetSystemState returns 0 if the TaskStatus_t buffer is not + sufficiently large enough. */ + cnt = uxTaskGetSystemState(states, len, NULL); + } + } while (rc == DDS_RETCODE_OK && cnt == 0); + + if (rc == DDS_RETCODE_OK) { + memset(usage, 0, sizeof(*usage)); + + for (len = cnt, cnt = 0; cnt < len; cnt++) { + nsecs = states[cnt].ulRunTimeCounter * DDSRT_NSECS_IN_RUSAGE_TIME_BASE; + usage->stime += nsecs; /* FIXME: Protect against possible overflow! */ + } + } + + ddsrt_free(states); + + return rc; +} + +static dds_retcode_t +rusage_thread(ddsrt_rusage_t *usage) +{ + TaskStatus_t states; + + memset(usage, 0, sizeof(*usage)); + memset(&states, 0, sizeof(states)); + vTaskGetInfo(xTaskGetCurrentTaskHandle(), &states, pdFALSE, eInvalid); + usage->stime = states.ulRunTimeCounter * DDSRT_NSECS_IN_RUSAGE_TIME_BASE; + + return DDS_RETCODE_OK; +} + +dds_retcode_t +ddsrt_getrusage(int who, ddsrt_rusage_t *usage) +{ + dds_retcode_t rc; + + assert(who == DDSRT_RUSAGE_SELF || who == DDSRT_RUSAGE_THREAD); + assert(usage != NULL); + + if (who == DDSRT_RUSAGE_THREAD) { + rc = rusage_thread(usage); + } else { + rc = rusage_self(usage); + } + + return rc; +} diff --git a/src/ddsrt/src/sockets.c b/src/ddsrt/src/sockets.c index d559a80..48e3282 100644 --- a/src/ddsrt/src/sockets.c +++ b/src/ddsrt/src/sockets.c @@ -15,19 +15,21 @@ #include #include -#if !defined(_WIN32) -#include -#include -#include -# if defined(__linux) -# include /* sockaddr_ll */ -# endif /* __linux */ -#endif /* _WIN32 */ - #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" #include "dds/ddsrt/sockets_priv.h" +#if !LWIP_SOCKET +# if !defined(_WIN32) +# include +# include +# include +# if defined(__linux) +# include /* sockaddr_ll */ +# endif /* __linux */ +# endif /* _WIN32 */ +#endif /* LWIP_SOCKET */ + extern inline struct timeval * ddsrt_duration_to_timeval_ceil(dds_duration_t reltime, struct timeval *tv); @@ -37,7 +39,7 @@ const struct in6_addr ddsrt_in6addr_loopback = IN6ADDR_LOOPBACK_INIT; #endif const int afs[] = { -#ifdef __linux +#if defined(__linux) && !LWIP_SOCKET AF_PACKET, #endif /* __linux */ #if DDSRT_HAVE_IPV6 @@ -62,7 +64,7 @@ ddsrt_sockaddr_get_size(const struct sockaddr *const sa) sz = sizeof(struct sockaddr_in6); break; #endif /* DDSRT_HAVE_IPV6 */ -#ifdef __linux +#if defined(__linux) && !LWIP_SOCKET case AF_PACKET: sz = sizeof(struct sockaddr_ll); break; @@ -218,6 +220,9 @@ dds_retcode_t ddsrt_sockaddrtostr(const void *sa, char *buf, size_t size) assert(sa != NULL); assert(buf != NULL); +#if LWIP_SOCKET +DDSRT_WARNING_GNUC_OFF(sign-conversion) +#endif switch (((struct sockaddr *)sa)->sa_family) { case AF_INET: ptr = inet_ntop( @@ -232,6 +237,9 @@ dds_retcode_t ddsrt_sockaddrtostr(const void *sa, char *buf, size_t size) default: return DDS_RETCODE_BAD_PARAMETER; } +#if LWIP_SOCKET +DDSRT_WARNING_GNUC_ON(sign-conversion) +#endif if (ptr == NULL) { return DDS_RETCODE_NOT_ENOUGH_SPACE; @@ -312,10 +320,14 @@ ddsrt_gethostbyname(const char *name, int af, ddsrt_hostent_t **hentp) /* Other system error. */ return DDS_RETCODE_ERROR; #endif +#if defined(EAI_BADFLAGS) case EAI_BADFLAGS: /* Invalid flags in hints.ai_flags. */ +#endif case EAI_FAMILY: /* Address family not supported. */ case EAI_SERVICE: /* Service not available for socket type. */ +#if defined(EAI_SOCKTYPE) case EAI_SOCKTYPE: /* Socket type not supported. */ +#endif case 0: { struct addrinfo *ai; size_t addrno, naddrs, size; diff --git a/src/ddsrt/src/sockets/include/dds/ddsrt/sockets_priv.h b/src/ddsrt/src/sockets/include/dds/ddsrt/sockets_priv.h index 8a41203..6c793d3 100644 --- a/src/ddsrt/src/sockets/include/dds/ddsrt/sockets_priv.h +++ b/src/ddsrt/src/sockets/include/dds/ddsrt/sockets_priv.h @@ -52,10 +52,10 @@ ddsrt_duration_to_timeval_ceil(dds_duration_t reltime, struct timeval *tv) return NULL; } else if (reltime > 0) { dds_duration_t max_nsecs; - if (DDS_INFINITY > DDSRT_TIME_T_MAX) { - assert(DDSRT_TIME_T_MAX == INT32_MAX); + if (DDSRT_TIME_T_MAX == INT32_MAX) { max_nsecs = INT32_MAX * DDS_NSECS_IN_SEC; } else { + assert(DDSRT_TIME_T_MAX == INT64_MAX); max_nsecs = DDSRT_TIME_T_MAX / DDS_NSECS_IN_SEC; } diff --git a/src/ddsrt/src/sockets/posix/gethostname.c b/src/ddsrt/src/sockets/posix/gethostname.c index de71a44..fbdd7c4 100644 --- a/src/ddsrt/src/sockets/posix/gethostname.c +++ b/src/ddsrt/src/sockets/posix/gethostname.c @@ -10,21 +10,41 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include #include #include +#include "dds/ddsrt/sockets.h" +#include "dds/ddsrt/string.h" + +#if !LWIP_SOCKET +#include +#endif + #if defined(__VXWORKS__) #include #endif /* __VXWORKS__ */ -#if !defined(HOST_NAME_MAX) && defined(_POSIX_HOST_NAME_MAX) -# define HOST_NAME_MAX _POSIX_HOST_NAME_MAX +#if !defined(HOST_NAME_MAX) +# if LWIP_SOCKET +# define HOST_NAME_MAX DNS_MAX_NAME_LENGTH +# elif defined(_POSIX_HOST_NAME_MAX) +# define HOST_NAME_MAX _POSIX_HOST_NAME_MAX +# endif #endif -#include "dds/ddsrt/sockets.h" -#include "dds/ddsrt/string.h" +#if LWIP_SOCKET +dds_retcode_t +ddsrt_gethostname( + char *name, + size_t len) +{ + if (ddsrt_strlcpy(name, "localhost", len) >= len) { + return DDS_RETCODE_NOT_ENOUGH_SPACE; + } + return DDS_RETCODE_OK; +} +#else dds_retcode_t ddsrt_gethostname( char *name, @@ -59,3 +79,4 @@ ddsrt_gethostname( return DDS_RETCODE_ERROR; } +#endif diff --git a/src/ddsrt/src/sockets/posix/socket.c b/src/ddsrt/src/sockets/posix/socket.c index 94b7f89..7334483 100644 --- a/src/ddsrt/src/sockets/posix/socket.c +++ b/src/ddsrt/src/sockets/posix/socket.c @@ -10,10 +10,14 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include #include #include +#include "dds/ddsrt/log.h" +#include "dds/ddsrt/misc.h" +#include "dds/ddsrt/sockets_priv.h" + +#if !LWIP_SOCKET #if defined(__VXWORKS__) #include #include @@ -21,6 +25,7 @@ #else #include #endif /* __VXWORKS__ */ +#include #include #include #ifdef __sun @@ -30,10 +35,7 @@ #ifdef __APPLE__ #include #endif /* __APPLE__ */ - -#include "dds/ddsrt/log.h" -#include "dds/ddsrt/misc.h" -#include "dds/ddsrt/sockets_priv.h" +#endif /* LWIP_SOCKET */ dds_retcode_t ddsrt_socket(ddsrt_socket_t *sockptr, int domain, int type, int protocol) @@ -254,6 +256,15 @@ ddsrt_getsockopt( void *optval, socklen_t *optlen) { +#if LWIP_SOCKET + if (optname == SO_SNDBUF || optname == SO_RCVBUF) + return DDS_RETCODE_BAD_PARAMETER; +# if !SO_REUSE + if (optname == SO_REUSEADDR) + return DDS_RETCODE_BAD_PARAMETER; +# endif /* SO_REUSE */ +#endif /* LWIP_SOCKET */ + if (getsockopt(sock, level, optname, optval, optlen) == 0) return DDS_RETCODE_OK; @@ -279,6 +290,15 @@ ddsrt_setsockopt( const void *optval, socklen_t optlen) { +#if LWIP_SOCKET + if (optname == SO_SNDBUF || optname == SO_RCVBUF) + return DDS_RETCODE_BAD_PARAMETER; +# if !SO_REUSE + if (optname == SO_REUSEADDR) + return DDS_RETCODE_BAD_PARAMETER; +# endif /* SO_REUSE */ +#endif /* LWIP_SOCKET */ + switch (optname) { case SO_SNDBUF: case SO_RCVBUF: @@ -405,6 +425,24 @@ ddsrt_recv( return recv_error_to_retcode(errno); } +#if LWIP_SOCKET && !defined(recvmsg) +static ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) +{ + assert(msg->msg_iovlen == 1); + assert(msg->msg_controllen == 0); + + msg->msg_flags = 0; + + return recvfrom( + sockfd, + msg->msg_iov[0].iov_base, + msg->msg_iov[0].iov_len, + flags, + msg->msg_name, + &msg->msg_namelen); +} +#endif /* LWIP_SOCKET */ + dds_retcode_t ddsrt_recvmsg( ddsrt_socket_t sock, diff --git a/src/ddsrt/src/sync/freertos/sync.c b/src/ddsrt/src/sync/freertos/sync.c new file mode 100644 index 0000000..6b75f7f --- /dev/null +++ b/src/ddsrt/src/sync/freertos/sync.c @@ -0,0 +1,469 @@ +/* + * 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 +#include +#include +#include + +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/log.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/timeconv.h" + +void ddsrt_mutex_init(ddsrt_mutex_t *mutex) +{ + SemaphoreHandle_t sem; + + assert(mutex != NULL); + + if ((sem = xSemaphoreCreateMutex()) == NULL) { + abort(); + } + + (void)memset(mutex, 0, sizeof(*mutex)); + mutex->sem = sem; +} + +void ddsrt_mutex_destroy(ddsrt_mutex_t *mutex) +{ + assert(mutex != NULL); + + vSemaphoreDelete(mutex->sem); + (void)memset(mutex, 0, sizeof(*mutex)); +} + +static bool +mutex_lock(ddsrt_mutex_t *mutex, int blk) +{ + assert(mutex != NULL); + + if (xSemaphoreTake(mutex->sem, (blk == 1 ? portMAX_DELAY : 0)) != pdPASS) { + DDS_TRACE("Failed to lock 0x%p", mutex); + /* xSemaphoreTake will only return pdFAIL on timeout. The wait will be + indefinite if INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h + and portMAX_DELAY was passed. */ + assert(blk == 0); + return false; + } + + return true; +} + +void ddsrt_mutex_lock(ddsrt_mutex_t *mutex) +{ + if (!mutex_lock(mutex, 1)) { + abort(); + } +} + +bool ddsrt_mutex_trylock(ddsrt_mutex_t *mutex) +{ + return mutex_lock(mutex, 0); +} + +void ddsrt_mutex_unlock(ddsrt_mutex_t *mutex) +{ + assert(mutex != NULL); + + if (xSemaphoreGive(mutex->sem) != pdPASS) { + DDS_TRACE("Failed to unlock 0x%p", mutex->sem); + abort(); + } +} + +static dds_retcode_t +cond_timedwait( + ddsrt_cond_t *cond, + ddsrt_mutex_t *mutex, + dds_duration_t reltime) +{ + dds_retcode_t rc = DDS_RETCODE_OK; + dds_time_t abstime; + TaskHandle_t task; + TickType_t ticks = 0; + + assert(cond != NULL); + assert(mutex != NULL); + + abstime = ddsrt_time_add_duration(dds_time(), reltime); + ticks = ddsrt_duration_to_ticks_ceil(reltime); + + xSemaphoreTake(cond->sem, portMAX_DELAY); + ddsrt_mutex_unlock(mutex); + + task = xTaskGetCurrentTaskHandle(); + /* Register current task with condition. */ + ddsrt_tasklist_push(&cond->tasks, task); + /* Discard pending notifications. */ + ulTaskNotifyTake(1, 0); + + xSemaphoreGive(cond->sem); + /* Wait to be notified. */ + switch (ulTaskNotifyTake(1, ticks)) { + case 0: + xSemaphoreTake(cond->sem, ticks); + ddsrt_tasklist_pop(&cond->tasks, task); + xSemaphoreGive(cond->sem); + break; + default: + /* Task already removed from condition. */ + break; + } + + /* Timeout must only be returned if the time has actually passed. */ + if (dds_time() >= abstime) { + rc = DDS_RETCODE_TIMEOUT; + } + + ddsrt_mutex_lock(mutex); + + return rc; +} + +void ddsrt_cond_init(ddsrt_cond_t *cond) +{ + SemaphoreHandle_t sem; + ddsrt_tasklist_t tasks; + + assert(cond != NULL); + + if (ddsrt_tasklist_init(&tasks) == -1) { + abort(); + } + if ((sem = xSemaphoreCreateMutex()) == NULL) { + ddsrt_tasklist_fini(&tasks); + abort(); + } + + (void)memset(cond, 0, sizeof(*cond)); + cond->sem = sem; + cond->tasks = tasks; +} + +void ddsrt_cond_destroy(ddsrt_cond_t *cond) +{ + assert(cond != NULL); + + vSemaphoreDelete(cond->sem); + ddsrt_tasklist_fini(&cond->tasks); + (void)memset(cond, 0, sizeof(*cond)); +} + +void ddsrt_cond_wait(ddsrt_cond_t *cond, ddsrt_mutex_t *mutex) +{ + assert(cond != NULL); + assert(mutex != NULL); + + (void)cond_timedwait(cond, mutex, DDS_INFINITY); +} + +bool +ddsrt_cond_waitfor( + ddsrt_cond_t *cond, + ddsrt_mutex_t *mutex, + dds_duration_t reltime) +{ + dds_retcode_t rc; + + assert(cond != NULL); + assert(mutex != NULL); + + switch ((rc = cond_timedwait(cond, mutex, reltime))) { + case DDS_RETCODE_OUT_OF_RESOURCES: + abort(); + case DDS_RETCODE_TIMEOUT: + return false; + default: + assert(rc == DDS_RETCODE_OK); + break; + } + + return true; +} + +bool +ddsrt_cond_waituntil( + ddsrt_cond_t *cond, + ddsrt_mutex_t *mutex, + dds_time_t abstime) +{ + dds_retcode_t rc; + dds_time_t time; + dds_duration_t reltime; + + assert(cond != NULL); + assert(mutex != NULL); + + time = dds_time(); + reltime = (abstime > time ? abstime - time : 0); + + switch ((rc = cond_timedwait(cond, mutex, reltime))) { + case DDS_RETCODE_OUT_OF_RESOURCES: + abort(); + case DDS_RETCODE_TIMEOUT: + return false; + default: + assert(rc == DDS_RETCODE_OK); + break; + } + + return true; +} + +void ddsrt_cond_signal(ddsrt_cond_t *cond) +{ + TaskHandle_t task; + + assert(cond != NULL); + + xSemaphoreTake(cond->sem, portMAX_DELAY); + if ((task = ddsrt_tasklist_pop(&cond->tasks, NULL)) != NULL) { + xTaskNotifyGive(task); + } + xSemaphoreGive(cond->sem); +} + +void ddsrt_cond_broadcast(ddsrt_cond_t *cond) +{ + TaskHandle_t task; + + assert(cond != NULL); + + xSemaphoreTake(cond->sem, portMAX_DELAY); + while ((task = ddsrt_tasklist_pop(&cond->tasks, NULL)) != NULL) { + xTaskNotifyGive(task); + } + xSemaphoreGive(cond->sem); +} + +#define WRITE_LOCKED (-1) +#define UNLOCKED (0) +#define READ_LOCKED (1) + +void ddsrt_rwlock_init(ddsrt_rwlock_t *rwlock) +{ + SemaphoreHandle_t sem; + ddsrt_tasklist_t tasks; + + assert(rwlock != NULL); + + if (ddsrt_tasklist_init(&tasks) == -1) { + abort(); + } + if ((sem = xSemaphoreCreateMutex()) == NULL) { + ddsrt_tasklist_fini(&tasks); + abort(); + } + + memset(rwlock, 0, sizeof(*rwlock)); + rwlock->sem = sem; + rwlock->tasks = tasks; + rwlock->state = UNLOCKED; +} + +void ddsrt_rwlock_destroy(ddsrt_rwlock_t *rwlock) +{ + assert(rwlock != NULL); + + vSemaphoreDelete(rwlock->sem); + ddsrt_tasklist_fini(&rwlock->tasks); + memset(rwlock, 0, sizeof(*rwlock)); +} + +void ddsrt_rwlock_read(ddsrt_rwlock_t *rwlock) +{ + TaskHandle_t task = xTaskGetCurrentTaskHandle(); + + assert(rwlock != NULL); + + xSemaphoreTake(rwlock->sem, portMAX_DELAY); + rwlock->rdcnt++; + if (rwlock->wrcnt != 0) { + ddsrt_tasklist_push(&rwlock->tasks, task); + /* Discard pending notifications. */ + ulTaskNotifyTake(1, 0); + xSemaphoreGive(rwlock->sem); + /* Wait to be notified. */ + ulTaskNotifyTake(1, portMAX_DELAY); + xSemaphoreTake(rwlock->sem, portMAX_DELAY); + ddsrt_tasklist_pop(&rwlock->tasks, task); + } + assert(rwlock->state == UNLOCKED || + rwlock->state == READ_LOCKED); + rwlock->cnt++; + rwlock->state = READ_LOCKED; + /* Notify next task, if any. */ + if ((task = ddsrt_tasklist_peek(&rwlock->tasks, NULL)) != NULL) { + xTaskNotifyGive(task); + } + xSemaphoreGive(rwlock->sem); +} + +void ddsrt_rwlock_write(ddsrt_rwlock_t *rwlock) +{ + TaskHandle_t task = xTaskGetCurrentTaskHandle(); + + assert(rwlock != NULL); + + xSemaphoreTake(rwlock->sem, portMAX_DELAY); + rwlock->wrcnt++; + if (rwlock->rdcnt != 0 || rwlock->wrcnt != 1) { + ddsrt_tasklist_push(&rwlock->tasks, task); + do { + /* Discard pending notifications. */ + ulTaskNotifyTake(1, 0); + xSemaphoreGive(rwlock->sem); + /* Wait to be notified. */ + ulTaskNotifyTake(1, portMAX_DELAY); + xSemaphoreTake(rwlock->sem, portMAX_DELAY); + } while (rwlock->state != UNLOCKED); + ddsrt_tasklist_pop(&rwlock->tasks, task); + } + assert(rwlock->cnt == 0); + assert(rwlock->state == UNLOCKED); + rwlock->cnt++; + rwlock->state = WRITE_LOCKED; + xSemaphoreGive(rwlock->sem); +} + +bool ddsrt_rwlock_tryread(ddsrt_rwlock_t *rwlock) +{ + bool locked = false; + TaskHandle_t task; + + assert(rwlock != NULL); + + xSemaphoreTake(rwlock->sem, portMAX_DELAY); + if (rwlock->wrcnt == 0) { + locked = true; + rwlock->cnt++; + rwlock->rdcnt++; + rwlock->state = READ_LOCKED; + /* Notify next task, if any. */ + if ((task = ddsrt_tasklist_peek(&rwlock->tasks, NULL)) != NULL) { + xTaskNotifyGive(task); + } + } + xSemaphoreGive(rwlock->sem); + + return locked; +} + +bool ddsrt_rwlock_trywrite(ddsrt_rwlock_t *rwlock) +{ + bool locked = false; + + assert(rwlock != NULL); + + xSemaphoreTake(rwlock->sem, 0); + if (rwlock->rdcnt == 0 && rwlock->wrcnt == 0) { + locked = true; + rwlock->cnt++; + rwlock->wrcnt++; + rwlock->state = WRITE_LOCKED; + } + xSemaphoreGive(rwlock->sem); + + return locked; +} + +void ddsrt_rwlock_unlock(ddsrt_rwlock_t *rwlock) +{ + TaskHandle_t task; + + assert(rwlock != NULL); + + xSemaphoreTake(rwlock->sem, portMAX_DELAY); + assert(rwlock->cnt != 0); + rwlock->cnt--; + if (rwlock->state == READ_LOCKED) { + assert(rwlock->rdcnt != 0); + rwlock->rdcnt--; + if (rwlock->rdcnt == 0) { + rwlock->state = UNLOCKED; + } + } else { + assert(rwlock->state == WRITE_LOCKED); + assert(rwlock->wrcnt != 0); + assert(rwlock->cnt == 0); + rwlock->wrcnt--; + rwlock->state = UNLOCKED; + } + /* Notify next task, if any. */ + if ((rwlock->state == UNLOCKED) && + (task = ddsrt_tasklist_peek(&rwlock->tasks, NULL)) != NULL) + { + assert(rwlock->rdcnt != 0 || + rwlock->wrcnt != 0); + xTaskNotifyGive(task); + } + xSemaphoreGive(rwlock->sem); +} + +#define ONCE_NOT_STARTED (1<<0) +#define ONCE_IN_PROGRESS (1<<1) +#define ONCE_FINISHED (1<<2) + +/* Wait one millisecond (tick) between polls. */ +static const TickType_t once_delay = (configTICK_RATE_HZ / 1000); + +void +ddsrt_once( + ddsrt_once_t *control, + ddsrt_once_fn init_fn) +{ + int ret, brk = 0; + uint32_t stat; + + while (brk == 0) { + stat = ddsrt_atomic_ld32(control); + /* Verify once control was initialized properly. */ + assert(stat == ONCE_NOT_STARTED || + stat == ONCE_IN_PROGRESS || + stat == ONCE_FINISHED); + + if ((stat & ONCE_FINISHED) != 0) { + /* The initialization function has been executed. No reason to block + execution of this thread. Continue. */ + brk = 1; + } else if ((stat & ONCE_IN_PROGRESS) != 0) { + /* Another thread is executing the initialization function. Wait around + for it to be finished. The polling loop is required because FreeRTOS + does not offer futexes. */ + vTaskDelay(once_delay); + /* Repeat. */ + } else { + /* No thread was executing the initialization function (one might be + executing it now) at the time of the load. If the atomic compare and + swap operation is successful, this thread will run the initialization + function. */ + if (ddsrt_atomic_cas32( + control, ONCE_NOT_STARTED, ONCE_IN_PROGRESS) != 0) + { + /* Function must never block or yield, see reference manual. */ + init_fn(); + + ret = (0 == ddsrt_atomic_cas32( + control, ONCE_IN_PROGRESS, ONCE_FINISHED)); + assert(ret == 0); (void)ret; + + brk = 1; + } else { + /* Another thread updated the state first. Repeat. */ + } + } + } + + return; +} diff --git a/src/ddsrt/src/sync/freertos/tasklist.c b/src/ddsrt/src/sync/freertos/tasklist.c new file mode 100644 index 0000000..6d03415 --- /dev/null +++ b/src/ddsrt/src/sync/freertos/tasklist.c @@ -0,0 +1,396 @@ +/* + * 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 + +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/sync.h" + +/* Task list is a buffer used to keep track of blocked tasks. The buffer is + cyclic to avoid memory (re)allocation as much as possible. To avoid memory + relocation, the window is allowed to be sparse too. + + Active buckets must always reside in the window denoted by the first active + bucket and the last active bucket. + + A buffer with 10 buckets will be neatly packed at first. + + X : Used bucket in window. + o : Empty (invalidated) bucket. + + ----------------------- + | X X X X X o o o o o | length: 10, count: 5 + --^-------^------------ + 1st nth + + As soon as the first task is unblocked. + + ----------------------- + | o X X X X o o o o o | length: 10, count: 4 + ----^-----^------------ + 1st nth + + After a while the window will wrap around. + + ----------------------- + | X X X o o o o o X X | length: 10, count: 5 + ------^-----------^---- + nth 1st + + When a task is popped, e.g. a task was not notified in due time. + + ----------------------- + | o X X o X X o o o o | length: 10, count: 4 + ----^-------^---------- + 1st nth +*/ + +#ifndef NDEBUG + +static void tasklist_assert(ddsrt_tasklist_t *list) +{ + size_t i; + + assert(list != NULL); + + if (list->cnt == 0) { + assert(list->off == 0); + assert(list->end == 0); + assert(list->len == DDSRT_TASKLIST_INITIAL); + for (i = 0; i < list->len; i++) { + assert(list->tasks[i] == NULL); + } + } + + /* FIXME: add more checks */ +} +#else +#define tasklist_assert(...) +#endif /* NDEBUG */ + +int ddsrt_tasklist_init(ddsrt_tasklist_t *list) +{ + TaskHandle_t *p; + + assert(list != NULL); + + p = ddsrt_malloc(DDSRT_TASKLIST_INITIAL * sizeof(*list->tasks)); + if (p == NULL) { + return -1; + } + + memset(list, 0, sizeof(*list)); + memset(p, 0, DDSRT_TASKLIST_INITIAL * sizeof(*list->tasks)); + list->tasks = p; + list->len = DDSRT_TASKLIST_INITIAL; + + return 0; +} + +void ddsrt_tasklist_fini(ddsrt_tasklist_t *list) +{ + ddsrt_free(list->tasks); + memset(list, 0, sizeof(*list)); +} + +void ddsrt_tasklist_ltrim(ddsrt_tasklist_t *list) +{ + size_t i; + + assert(list != NULL); + assert(list->cnt != 0); + + i = list->off; + for (; i < list->len - 1 && list->tasks[i] == NULL; i++) { } + /* Take into account wrap around. */ + if (list->tasks[i] == NULL) { + assert(i == list->len - 1); + assert(list->off > list->end); + i = 0; + /* Trim invalidated buckets from head. */ + for (; i < list->len - 1 && list->tasks[i] == NULL; i++) { } + } + list->off = i; +} + +void ddsrt_tasklist_rtrim(ddsrt_tasklist_t *list) +{ + size_t i; + + assert(list != NULL); + assert(list->cnt != 0); + + i = list->end; + for (; i > 0 && list->tasks[i] == NULL; i--) { } + /* Take into account wrap around. */ + if (list->tasks[i] == NULL) { + assert(i == 0); + assert(list->off > list->end); + i = list->len - 1; + /* Trim invalidated buckets from tail. */ + for (; i > 0 && list->tasks[i] == NULL; i--) { } + } + list->end = i; +} + +void ddsrt_tasklist_pack(ddsrt_tasklist_t *list) +{ + size_t i, j; + + /* Pack operation is trickier on wrap around. */ + if (list->end < list->off) { + /* Compress tail. + * + * ------------------------- ----------------------- + * | c . d . e | . a . b . | >> | c d e . . | . a . b | + * ------------------------- ----------------------- + */ + for (i = j = 0; i <= list->end; i++) { + if (list->tasks[i] != NULL) { + if (i != j) { + list->tasks[j] = list->tasks[i]; + } + j++; + } + } + + assert(j != 0); + list->end = (j == 0 ? 0 : j - 1); + + /* Compress head. + * + * ------------------------- ------------------------- + * | c d e . . | . a . b . | >> | c d e . . | . . . a b | + * ------------------------- ------------------------- + */ + for (i = j = list->len - 1; i >= list->off; i--) { + if (list->tasks[i] != NULL) { + if (i != j) { + list->tasks[j] = list->tasks[i]; + } + j--; + } + } + + assert(j != list->len - 1); + list->off = (j == list->len - 1 ? list->len - 1 : j + 1); + } else { + /* Compress. + * + * ------------------------- -------------------------- + * | . . a . . | b . c d e | >> | a b c d e | . . . . . | + * ------------------------- -------------------------- + */ + for (i = list->off, j = 0; i <= list->end; i++) { + if (list->tasks[i] != NULL) { + if (i != j) { + list->tasks[j] = list->tasks[i]; + } + j++; + } + } + assert(j != 0); + list->off = 0; + list->end = j - 1; + assert(list->end == list->cnt - 1); + } +} + +int ddsrt_tasklist_shrink(ddsrt_tasklist_t *list) +{ + static const size_t x = DDSRT_TASKLIST_CHUNK; + TaskHandle_t *p; + size_t mv = 0, n; + + assert(list != NULL); + + /* Shrink by one chunk too, but only if the difference is at least two + chunks to avoid memory (re)allocation if a task is pushed and popped + just over the boundary. */ + if (list->cnt > (list->len - (x * 2)) || (list->len - x) < DDSRT_TASKLIST_INITIAL) + { + return 0; + } + + /* List can be sparse. Pack to ensure list can be compacted. */ + ddsrt_tasklist_pack(list); + + /* Pack operation moved head to end of buffer on wrap around. Move head back + to not discard it on reallocation. */ + if (list->off != 0) { + assert(list->end < list->off); + mv = (list->len - list->off) * sizeof(*p); + memmove(list->tasks + (list->off - x), list->tasks + list->off, mv); + list->off -= x; + } + + n = list->len - x; + if ((p = ddsrt_realloc(list->tasks, n * sizeof(*p))) == NULL) { + /* Move head back to end of buffer. */ + if (mv != 0) { + memmove(list->tasks + (list->off + x), list->tasks + list->off, mv); + list->off += x; + } + return -1; + } + + list->tasks = p; + list->len = n; + + return 0; +} + +int ddsrt_tasklist_grow(ddsrt_tasklist_t *list) +{ + static const size_t x = DDSRT_TASKLIST_CHUNK; + TaskHandle_t *p; + size_t n; + + assert(list != NULL); + /* Should not be called if room is available. */ + assert(list->cnt == list->len); + + n = list->len + x; + if ((p = ddsrt_realloc(list->tasks, n * sizeof(*p))) == NULL) { + return -1; + } + + /* Move head to end of newly allocated memory. */ + if (list->off != 0) { + assert(list->end < list->off); + memmove(p + (list->off + x), p + list->off, (list->len - list->off) * sizeof(*p)); + list->off += x; + } + + /* Zero newly allocated memory. */ + memset(p + (list->end + 1), 0, x * sizeof(*p)); + + list->tasks = p; + list->len = n; + + return 0; +} + +ssize_t ddsrt_tasklist_find(ddsrt_tasklist_t *list, TaskHandle_t task) +{ + size_t i, n; + + assert(task != NULL); + + /* No need to check if list is empty. */ + if (list->cnt != 0) { + /* Task list is circular, so window does not have to be consecutive. */ + n = list->off <= list->end ? list->end : list->len - 1; + for (i = list->off; i <= n; i++) { + if (list->tasks[i] == task) + return (ssize_t)i; + } + + if (list->off > list->end) { + n = list->end; + for (i = 0; i <= n; i++) { + if (list->tasks[i] == task) + return (ssize_t)i; + } + } + } + + return -1; +} + +TaskHandle_t ddsrt_tasklist_peek(ddsrt_tasklist_t *list, TaskHandle_t task) +{ + tasklist_assert(list); + + if (list->cnt == 0) { + return NULL; + } else if (task != NULL) { + return ddsrt_tasklist_find(list, task) == -1 ? NULL : task; + } + + return list->tasks[list->off]; +} + +TaskHandle_t ddsrt_tasklist_pop(ddsrt_tasklist_t *list, TaskHandle_t task) +{ + ssize_t i; + + tasklist_assert(list); + + if (list->cnt == 0) { + return NULL; + } else if (task == NULL) { + i = (ssize_t)list->off; + } else if ((i = ddsrt_tasklist_find(list, task)) == -1) { + return NULL; + } + + task = list->tasks[i]; + if (task != NULL) { + /* Invalidate bucket. */ + list->tasks[i] = NULL; + list->cnt--; + + if (list->cnt == 0) { + list->off = list->end = 0; + } else if (i == (ssize_t)list->end) { + /* Trim invalidated buckets from tail of window. */ + ddsrt_tasklist_rtrim(list); + } else if (i == (ssize_t)list->off) { + /* Trim invalidated buckets from head of window. */ + ddsrt_tasklist_ltrim(list); + } else { + /* Window is now sparse. */ + } + + if (list->cnt <= (list->len - DDSRT_TASKLIST_CHUNK*2)) { + /* Shrink operation failure can safely be ignored. */ + (void)ddsrt_tasklist_shrink(list); + } + } + + return task; +} + +int ddsrt_tasklist_push(ddsrt_tasklist_t *list, TaskHandle_t task) +{ + tasklist_assert(list); + assert(task != NULL); + + /* Ensure task is not listed. */ + if (ddsrt_tasklist_find(list, task) != -1) { + return 0; + } + /* Grow number of buckets if none are available. */ + if (list->cnt == list->len) { + if (ddsrt_tasklist_grow(list) == -1) { + return -1; + } + list->end++; + /* Wrap around if there is room at the head. */ + } else if (list->end == list->len - 1 && list->off != 0) { + list->end = 0; + } else { + /* List can be sparse. */ + if (list->end == list->len - 1 || list->end + 1 == list->off) { + ddsrt_tasklist_pack(list); + } + /* Room is guaranteed to be available at the tail. */ + list->end += (list->cnt > 0); + } + + list->tasks[list->end] = task; + list->cnt++; + + return 0; +} diff --git a/src/ddsrt/src/threads/freertos/threads.c b/src/ddsrt/src/threads/freertos/threads.c new file mode 100644 index 0000000..20a536e --- /dev/null +++ b/src/ddsrt/src/threads/freertos/threads.c @@ -0,0 +1,545 @@ +/* + * 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 + +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/retcode.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/threads_priv.h" + +typedef enum { + THREAD_STARTING = 0, + THREAD_RUNNING, + THREAD_EXITING /* Indicates the thread has returned from the specified + start_routine, but FreeRTOS may not report it as deleted + yet. */ +} thread_state_t; + +typedef struct { + ddsrt_thread_routine_t func; + void *arg; + TaskHandle_t task; /* Thread identifier for looking up thread context from + another thread. Read-only, read by other threads. */ + thread_state_t stat; + thread_cleanup_t *dtors; /* Cleanup routines. Private. */ + uint32_t ret; /* Return value. NULL if thread has not terminated, maybe + NULL if thread has terminated, read by other thread(s) + after termination. */ + TaskHandle_t blkd; /* Thread blocked until thread terminates. may or may + not be empty when thread terminates. Written by other + thread, protected by registry mutex. */ +} thread_context_t; + +/* Thread registry (in combination with thread context) is required to properly + implement thread join functionality. */ + +/* Threads have their own context. The context is automatically allocated and + initialized, either when the thread is created (local threads) or when the + API is first used. */ + +/* FIXME: The same mechanism more-or-less exists in DDSI, perhaps more of the + logic in DDSI can be moved down at some point? */ +typedef struct { + ddsrt_mutex_t mutex; + /* The number of available spaces in the thread context array does not have + to equal the number of used spaces. e.g. when a memory allocation for a + new thread context array fails when destroying a context it is better to + leave one space unused. */ + thread_context_t **ctxs; + size_t cnt; + size_t len; +} thread_registry_t; + +static ddsrt_thread_local thread_context_t *thread_context = NULL; + +static thread_registry_t thread_registry; + +static ddsrt_once_t thread_registry_once = DDSRT_ONCE_INIT; + +static uint32_t non_local_thread(void *arg) { (void)arg; return 0;} + +/* FreeRTOS documentation states vTaskGetInfo is intended for debugging because + its use results in the scheduler remaining suspended for an extended period, + but the scheduler is only suspended if eTaskState is not eInvalid. */ +ddsrt_tid_t +ddsrt_gettid(void) +{ + TaskStatus_t status; + + vTaskGetInfo(xTaskGetCurrentTaskHandle(), &status, pdFALSE, eInvalid); + + return status.xTaskNumber; +} + +ddsrt_thread_t +ddsrt_thread_self(void) +{ + ddsrt_thread_t thr = { .task = xTaskGetCurrentTaskHandle() }; + + return thr; +} + +bool ddsrt_thread_equal(ddsrt_thread_t a, ddsrt_thread_t b) +{ + return (a.task == b.task); +} + +size_t +ddsrt_thread_getname(char *__restrict name, size_t size) +{ + char *ptr; + + assert(name != NULL); + assert(size >= 1); + + if ((ptr = pcTaskGetName(NULL)) == NULL) { + ptr = ""; + } + + return ddsrt_strlcpy(name, ptr, size); +} + +static void +thread_registry_init(void) +{ + /* One time initialization guaranteed by ddsrt_once. */ + (void)memset(&thread_registry, 0, sizeof(thread_registry)); + ddsrt_mutex_init(&thread_registry.mutex); +} + +static thread_context_t * +thread_context_find(TaskHandle_t task) +{ + thread_context_t *ctx = NULL; + + for (size_t i = 0; i < thread_registry.cnt && ctx == NULL; i++) { + if (thread_registry.ctxs[i] != NULL && + thread_registry.ctxs[i]->task == task) + { + ctx = thread_registry.ctxs[i]; + } + } + + return ctx; +} + +static dds_retcode_t +thread_context_create(thread_context_t **ctxptr) +{ + dds_retcode_t rc = DDS_RETCODE_OK; + size_t len; + thread_context_t *ctx = NULL, **ctxs = NULL; + + assert(ctxptr != NULL); + + ctx = ddsrt_calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + rc = DDS_RETCODE_OUT_OF_RESOURCES; + } else { + if (thread_registry.cnt < thread_registry.len) { + len = thread_registry.len; + ctxs = thread_registry.ctxs; + } else { + assert(thread_registry.cnt == thread_registry.len); + len = thread_registry.len + 1; + ctxs = ddsrt_realloc(thread_registry.ctxs, len * sizeof(ctx)); + } + + if (ctxs == NULL) { + ddsrt_free(ctx); + rc = DDS_RETCODE_OUT_OF_RESOURCES; + } else { + ctxs[thread_registry.cnt++] = *ctxptr = ctx; + thread_registry.len = len; + thread_registry.ctxs = ctxs; + } + } + + return rc; +} + +#define thread_context_require() thread_context_acquire(NULL) + +static dds_retcode_t +thread_context_acquire(thread_context_t **ctxptr) +{ + dds_retcode_t rc = DDS_RETCODE_OK; + thread_context_t *ctx = thread_context; + + if (ctx == NULL) { + /* Dynamically initialize global thread registry (exactly once). */ + ddsrt_once(&thread_registry_once, &thread_registry_init); + + ddsrt_mutex_lock(&thread_registry.mutex); + if ((rc = thread_context_create(&ctx)) == 0) { + /* This situation only arises for non-native (not created in our code) + threads. Some members must therefore still be initialized to ensure + proper operation. */ + ctx->func = &non_local_thread; + ctx->stat = THREAD_RUNNING; + ctx->task = xTaskGetCurrentTaskHandle(); + } + ddsrt_mutex_unlock(&thread_registry.mutex); + thread_context = ctx; + } else { + assert(ctx->func != NULL); + assert(ctx->stat == THREAD_RUNNING); + assert(ctx->task == xTaskGetCurrentTaskHandle()); + } + + if (rc == DDS_RETCODE_OK && ctxptr != NULL) { + assert(ctx != NULL); + *ctxptr = ctx; + } + + return rc; +} + +static void +thread_context_destroy(thread_context_t *ctx) +{ + size_t i = 0; + thread_context_t **arr; + + if (ctx != NULL) { + while (i < thread_registry.cnt && thread_registry.ctxs[i] != ctx) { + i++; + } + + if (i < thread_registry.cnt) { + thread_registry.ctxs[i] = NULL; + if (i < (thread_registry.cnt - 1)) { + (void)memmove( + thread_registry.ctxs + (i), + thread_registry.ctxs + (i+1), + (thread_registry.cnt - (i+1)) * sizeof(*thread_registry.ctxs)); + } + thread_registry.cnt--; + + /* Free contexts when count reaches zero. */ + if (thread_registry.cnt == 0) { + ddsrt_free(thread_registry.ctxs); + thread_registry.ctxs = NULL; + thread_registry.len = 0; + } else { + arr = ddsrt_realloc( + thread_registry.ctxs, + thread_registry.cnt * sizeof(*thread_registry.ctxs)); + /* Ignore allocation failure, save free spot. */ + if (arr != NULL) { + thread_registry.ctxs = arr; + thread_registry.len = thread_registry.cnt; + } + } + } + + ddsrt_free(ctx); + } +} + +static void +thread_fini(thread_context_t *ctx, uint32_t ret) +{ + thread_cleanup_t *tail; + + assert(ctx != NULL); + + /* Acquire registry lock to publish task result and state. */ + ddsrt_mutex_lock(&thread_registry.mutex); + + /* Pop all cleanup handlers from the thread's cleanup stack. */ + while ((tail = ctx->dtors) != NULL) { + ctx->dtors = tail->prev; + if (tail->routine != 0) { + tail->routine(tail->arg); + } + ddsrt_free(tail); + } + + /* FreeRTOS can report task state, but doesn't register the result or + notifies a thread that wants to join. */ + ctx->ret = ret; + ctx->stat = THREAD_EXITING; + + /* Thread resources will be leaked (especially for non-local threads) + if not reclaimed by a thread join. Local threads (threads created + within the DDS stack) are required to be joined. Thread resource + leakage for local threads must be considered a bug. Non-local + threads, however, are not aware that there are resources that must + be reclaimed and local threads might not be aware that there are + non-local threads that must be joined. Therefore, if a non-local thread + exits, it's resources are reclaimed if no thread is waiting to join. */ + if (ctx->blkd != NULL) { + /* Task join functionality is based on notifications, as it is + significantly faster than using a queue, semaphore or event group to + perform an equivalent operation. + + When a task receives a notification, it's notification state is set to + pending. When it reads it's notification state, the notification state + is set to not-pending. A task can wait, with an optional time out, for + it's notification state to become pending. */ + + /* Ignore result, there's nothing that can be done on failure and it always + returns pdPASS. */ + (void)xTaskNotifyGive(ctx->blkd); + } else if (ctx->func == &non_local_thread) { + assert(ret == 0); + thread_context_destroy(ctx); + } + + ddsrt_mutex_unlock(&thread_registry.mutex); +} + +static void +thread_start_routine(void *arg) +{ + thread_context_t *ctx = (thread_context_t *)arg; + uint32_t ret; + + ddsrt_mutex_lock(&thread_registry.mutex); + /* Context for the current task is always correctly initialized and + registered at this stage. It's not strictly required to update task + state, but the synchronization itself is. */ + ctx->stat = THREAD_RUNNING; + ddsrt_mutex_unlock(&thread_registry.mutex); + + /* Thread-local storage is initialized by the function that creates the + thread because a reference to the thread's context is stored and + synchronization is considerably easier if it's handled there. */ + + thread_context = ctx; + ret = ctx->func(ctx->arg); + + thread_fini(ctx, ret); /* DO NOT DEREFERENCE THREAD CONTEXT ANYMORE! */ + + /* Delete current task. */ + vTaskDelete(NULL); +} + +/* xTaskCreate takes the stack depth in the number of words (NOT bytes). In + practice this simply means it multiplies the given number with the size + of StackType_t in bytes (see tasks.c). FreeRTOSConfig.h must define + configMINIMAL_STACK_SIZE, which is the stack size in words allocated for + the idle task. */ +#define WORD_SIZE (sizeof(StackType_t)) +/* configMINIMAL_STACK_SIZE is applied as the default stack size. Whether or + not this is considered a sane default depends on the target. The default can + be adjusted in FreeRTOSConfig.h Of course the configuration file also allows + the user to change it on a per-thread basis at runtime. */ +#define MIN_STACK_SIZE ((uint16_t)(configMINIMAL_STACK_SIZE * WORD_SIZE)) + +dds_retcode_t +ddsrt_thread_create( + ddsrt_thread_t *thread, + const char *name, + const ddsrt_threadattr_t *attr, + ddsrt_thread_routine_t start_routine, + void *arg) +{ + dds_retcode_t rc; + TaskHandle_t task; + UBaseType_t prio; + uint16_t size = MIN_STACK_SIZE; + thread_context_t *ctx = NULL; + + assert(thread != NULL); + assert(name != NULL); + assert(attr != NULL); + assert(start_routine != 0); + + if ((rc = thread_context_require()) != DDS_RETCODE_OK) { + return rc; + } + + /* Non-realtime scheduling does not exist in FreeRTOS. */ + if (attr->schedClass != DDSRT_SCHED_DEFAULT && + attr->schedClass != DDSRT_SCHED_REALTIME) + { + return DDS_RETCODE_BAD_PARAMETER; + } else if (attr->schedPriority < 0 || + attr->schedPriority > (configMAX_PRIORITIES - 1)) + { + return DDS_RETCODE_BAD_PARAMETER; + } + + /* Stack size is quietly increased to match at least the minimum. */ + if (attr->stackSize > size) { + size = (uint16_t)(attr->stackSize / WORD_SIZE); + if (attr->stackSize % WORD_SIZE) { + size++; + } + } + + /* Assume that when the default priority of zero (0) is specified, the user + wants the thread to inherit the priority of the calling thread. */ + assert(0 == tskIDLE_PRIORITY); + if (attr->schedPriority == 0) { + prio = uxTaskPriorityGet(NULL); + } else { + prio = (UBaseType_t)attr->schedPriority; + } + + ddsrt_mutex_lock(&thread_registry.mutex); + + /* Thread context is allocated here so that it can be handled when no more + memory is available. Simply storing the entire context in thread-local + storage would have been possible, but would require the implementation to + define and allocate a separate struct in order to support thread joins. */ + if ((rc = thread_context_create(&ctx)) == DDS_RETCODE_OK) { + ctx->func = start_routine; + ctx->arg = arg; + + if (pdPASS != xTaskCreate( + &thread_start_routine, name, size, ctx, prio, &task)) + { + thread_context_destroy(ctx); + rc = DDS_RETCODE_OUT_OF_RESOURCES; + } else { + thread->task = ctx->task = task; + } + } + + ddsrt_mutex_unlock(&thread_registry.mutex); + + return rc; +} + +void +ddsrt_thread_init(void) +{ + if (thread_context_require() != DDS_RETCODE_OK) { + assert(0); + } +} + +void +ddsrt_thread_fini(void) +{ + thread_context_t *ctx; + + /* NO-OP if no context exists since thread-local storage and cleanup + handler references are both stored in the thread context. */ + if ((ctx = thread_context) != NULL) { + assert(ctx->func != &non_local_thread); + thread_fini(ctx, 0); + } +} + +dds_retcode_t +ddsrt_thread_join(ddsrt_thread_t thread, uint32_t *thread_result) +{ + dds_retcode_t rc; + thread_context_t *ctx; + eTaskState status; + + if ((rc = thread_context_require()) != DDS_RETCODE_OK) { + return rc; + } + + ddsrt_mutex_lock(&thread_registry.mutex); + ctx = thread_context_find(thread.task); + if (ctx != NULL) { + /* Task should never be joined by multiple tasks simultaneously */ + assert(ctx->blkd == NULL); + rc = DDS_RETCODE_TRY_AGAIN; + + do { + (void)memset(&status, 0, sizeof(status)); + status = eTaskGetState(thread.task); + if (status == eDeleted) { + /* FreeRTOS reports the task is deleted. Require the context to exist, + fetch the result and free the context afterwards. */ + assert(ctx != NULL); + rc = DDS_RETCODE_OK; + } else if (status != eInvalid) { + assert(ctx != NULL); + /* FreeRTOS reports the task is still active. That does not mean the + task has not yet returned from start_routine. */ + if (ctx->stat == THREAD_EXITING) { + /* Thread context will not be accessed by the thread itself anymore + and it should be safe to free it. */ + rc = DDS_RETCODE_OK; + } else { + ctx->blkd = xTaskGetCurrentTaskHandle(); + + /* Reset notify state and counter. */ + ulTaskNotifyTake(pdTRUE, 0); + + ddsrt_mutex_unlock(&thread_registry.mutex); + + /* Wait to be notified. */ + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + + ddsrt_mutex_lock(&thread_registry.mutex); + } + } else { + rc = DDS_RETCODE_BAD_PARAMETER; + } + } while (rc == DDS_RETCODE_TRY_AGAIN); + + if (rc == DDS_RETCODE_OK) { + if (thread_result != NULL) { + *thread_result = ctx->ret; + } + thread_context_destroy(ctx); + } + } + + ddsrt_mutex_unlock(&thread_registry.mutex); + + return rc; +} + +dds_retcode_t +ddsrt_thread_cleanup_push(void (*routine)(void *), void *arg) +{ + dds_retcode_t rc = DDS_RETCODE_OK; + thread_cleanup_t *tail = NULL; + thread_context_t *ctx; + + assert(routine != NULL); + + if (thread_context_acquire(&ctx) == 0) { + if ((tail = ddsrt_malloc(sizeof(*tail))) == NULL) { + rc = DDS_RETCODE_OUT_OF_RESOURCES; + } else { + tail->prev = ctx->dtors; + tail->routine = routine; + tail->arg = arg; + ctx->dtors = tail; + } + } + + return rc; +} + +dds_retcode_t +ddsrt_thread_cleanup_pop(int execute) +{ + thread_cleanup_t *tail; + thread_context_t *ctx; + + if (thread_context_acquire(&ctx) == 0) { + if ((tail = ctx->dtors) != NULL) { + ctx->dtors = tail->prev; + if (execute) { + tail->routine(tail->arg); + } + ddsrt_free(tail); + } + } + + return DDS_RETCODE_OK; +} diff --git a/src/ddsrt/src/threads/include/dds/ddsrt/threads_priv.h b/src/ddsrt/src/threads/include/dds/ddsrt/threads_priv.h index b10118c..659a201 100644 --- a/src/ddsrt/src/threads/include/dds/ddsrt/threads_priv.h +++ b/src/ddsrt/src/threads/include/dds/ddsrt/threads_priv.h @@ -14,12 +14,6 @@ #include "dds/ddsrt/threads.h" -typedef struct { - char *name; - ddsrt_thread_routine_t routine; - void *arg; -} thread_context_t; - /** \brief Internal structure used to store cleanup handlers (private) */ typedef struct { void *prev; diff --git a/src/ddsrt/src/threads/posix/threads.c b/src/ddsrt/src/threads/posix/threads.c index f8dbf4c..92eec22 100644 --- a/src/ddsrt/src/threads/posix/threads.c +++ b/src/ddsrt/src/threads/posix/threads.c @@ -31,6 +31,12 @@ #include "dds/ddsrt/threads_priv.h" #include "dds/ddsrt/types.h" +typedef struct { + char *name; + ddsrt_thread_routine_t routine; + void *arg; +} thread_context_t; + #if defined(__linux) #include #define MAXTHREADNAMESIZE (15) /* 16 bytes including null-terminating byte. */ diff --git a/src/ddsrt/src/threads/windows/threads.c b/src/ddsrt/src/threads/windows/threads.c index ffba453..23830ab 100644 --- a/src/ddsrt/src/threads/windows/threads.c +++ b/src/ddsrt/src/threads/windows/threads.c @@ -16,6 +16,12 @@ #include "dds/ddsrt/string.h" #include "dds/ddsrt/threads_priv.h" +typedef struct { + char *name; + ddsrt_thread_routine_t routine; + void *arg; +} thread_context_t; + static uint32_t os_startRoutineWrapper( void *threadContext) diff --git a/src/ddsrt/src/time.c b/src/ddsrt/src/time.c index 01e4033..3f344f3 100644 --- a/src/ddsrt/src/time.c +++ b/src/ddsrt/src/time.c @@ -18,7 +18,7 @@ extern inline dds_time_t ddsrt_time_add_duration(dds_time_t abstime, dds_duration_t reltime); -#if !defined(_WIN32) +#if !_WIN32 && !DDSRT_WITH_FREERTOS #include void dds_sleepfor(dds_duration_t n) diff --git a/src/ddsrt/src/time/freertos/time.c b/src/ddsrt/src/time/freertos/time.c new file mode 100644 index 0000000..39ee345 --- /dev/null +++ b/src/ddsrt/src/time/freertos/time.c @@ -0,0 +1,53 @@ +/* + * 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 +#define _POSIX_TIMERS +#include + +#include "dds/ddsrt/time.h" + +extern inline TickType_t ddsrt_duration_to_ticks_ceil(dds_duration_t reltime); + +dds_time_t dds_time(void) +{ + struct timespec ts; + +#if __STDC_VERSION__ >= 201112L + timespec_get(&ts, TIME_UTC); +#else + (void)clock_gettime(CLOCK_REALTIME, &ts); +#endif + + return (ts.tv_sec * DDS_NSECS_IN_SEC) + ts.tv_nsec; +} + +#define NSECS_PER_TICK (DDS_NSECS_IN_SEC / configTICK_RATE_HZ) + +dds_time_t ddsrt_time_monotonic (void) +{ + return (xTaskGetTickCount() * NSECS_PER_TICK); +} + +dds_time_t ddsrt_time_elapsed (void) +{ + /* Elapsed time clock not (yet) supported on this platform. */ + return ddsrt_time_monotonic (); +} + +void dds_sleepfor (dds_duration_t reltime) +{ + TickType_t ticks; + + ticks = ddsrt_duration_to_ticks_ceil(reltime); + vTaskDelay(ticks); +} diff --git a/src/ddsrt/tests/CMakeLists.txt b/src/ddsrt/tests/CMakeLists.txt index 02c92ef..42a8df4 100644 --- a/src/ddsrt/tests/CMakeLists.txt +++ b/src/ddsrt/tests/CMakeLists.txt @@ -10,59 +10,63 @@ # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # include(CUnit) +include(GenerateDummyExportHeader) -set(sources - "atomics.c" - "environ.c" - "heap.c" - "ifaddrs.c" - "sync.c" - "strtoll.c" - "thread.c" - "thread_cleanup.c" - "string.c" - "log.c" - "random.c" - "strlcpy.c" - "socket.c" - "process.c" - "select.c") +list(APPEND sources + "atomics.c" + "environ.c" + "heap.c" + "ifaddrs.c" + "sync.c" + "strtoll.c" + "thread.c" + "thread_cleanup.c" + "string.c" + "log.c" + "random.c" + "strlcpy.c" + "socket.c" + "select.c") -add_cunit_executable(cunit_ddsrt ${sources}) -target_link_libraries(cunit_ddsrt PRIVATE ddsrt) - -# Create a dummy export header. generate_export_header can only be used with -# library targets, but since the targets are linked statically, -# __declspec(dllimport) is not required anyway. -set(export_dir "${CMAKE_CURRENT_BINARY_DIR}/include/dds") -set(export_header "${export_dir}/export.h") -if(NOT EXISTS "${export_header}") - file(MAKE_DIRECTORY "${export_dir}") - file(WRITE "${export_header}" "#define DDS_EXPORT\n") +if(HAVE_MULTI_PROCESS) + list(APPEND sources "process.c") +endif() +if(WITH_FREERTOS) + list(APPEND sources "tasklist.c") endif() +add_cunit_executable(cunit_ddsrt ${sources}) +target_link_libraries( + cunit_ddsrt PRIVATE ddsrt) target_include_directories( cunit_ddsrt PRIVATE "$") +generate_dummy_export_header( + cunit_ddsrt + BASE_NAME dds + EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/export.h") -# Create a separate test application that will be used to -# test process management. -add_executable(process_app process_app.c) -target_link_libraries(process_app PRIVATE ddsrt) -target_include_directories( - process_app - PRIVATE - "$") -# Force the app to be at the same location, no matter what platform or build type. -set_target_properties( - process_app - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR} - RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR} - RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR} - RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR} ) -# Let the cunit application know the location and name of the test application. -set(process_app_name "${CMAKE_CURRENT_BINARY_DIR}/process_app${CMAKE_EXECUTABLE_SUFFIX}") -configure_file( - "process_test.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/process_test.h" @ONLY) +if(HAVE_MULTI_PROCESS) + # A separate application is required to test process management. + add_executable(process_app process_app.c) + target_link_libraries(process_app PRIVATE ddsrt) + target_include_directories( + process_app + PRIVATE + "$") + # Force the app to be at the same location, no matter what platform or build type. + # FIXME: What if custom targets are added? + # FIXME: What debug and release builds are mixed on Windows and macOS? + set_target_properties( + process_app + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR} ) + # Let the cunit application know the location and name of the test application. + set(process_app_name "${CMAKE_CURRENT_BINARY_DIR}/process_app${CMAKE_EXECUTABLE_SUFFIX}") + configure_file( + "process_test.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/process_test.h" @ONLY) +endif() diff --git a/src/ddsrt/tests/ifaddrs.c b/src/ddsrt/tests/ifaddrs.c index ae8ea0b..50166da 100644 --- a/src/ddsrt/tests/ifaddrs.c +++ b/src/ddsrt/tests/ifaddrs.c @@ -9,10 +9,10 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include "CUnit/Test.h" #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/ifaddrs.h" #include "dds/ddsrt/retcode.h" +#include "CUnit/Test.h" /* FIXME: It's not possible to predict what network interfaces are available on a given host. To properly test all combinations the abstracted @@ -117,9 +117,9 @@ CU_Test(ddsrt_getifaddrs, empty_filter) ddsrt_freeifaddrs(ifa_root); } -#ifdef DDSRT_HAVE_IPV6 CU_Test(ddsrt_getifaddrs, ipv6) { +#ifdef DDSRT_HAVE_IPV6 if (ipv6_enabled == 1) { dds_retcode_t ret; int have_ipv6 = 0; @@ -149,12 +149,16 @@ CU_Test(ddsrt_getifaddrs, ipv6) } else { CU_PASS("IPv6 disabled in test environment"); } +#else + CU_PASS("IPv6 is not supported"); +#endif } /* Assume at least one IPv4 and one IPv6 interface are available when IPv6 is available on the platform. */ CU_Test(ddsrt_getifaddrs, ipv4_n_ipv6) { +#if DDSRT_HAVE_IPV6 if (ipv6_enabled == 1) { dds_retcode_t ret; int have_ipv4 = 0; @@ -182,6 +186,8 @@ CU_Test(ddsrt_getifaddrs, ipv4_n_ipv6) } else { CU_PASS("IPv6 disabled in test environment"); } +#else + CU_PASS("IPv6 is not supported"); +#endif /* DDSRT_HAVE_IPV6 */ } -#endif /* DDSRT_HAVE_IPV6 */ diff --git a/src/ddsrt/tests/log.c b/src/ddsrt/tests/log.c index 2c619c9..a5e66cf 100644 --- a/src/ddsrt/tests/log.c +++ b/src/ddsrt/tests/log.c @@ -311,8 +311,8 @@ static ddsrt_mutex_t mutex; struct arg { ddsrt_cond_t *cond; ddsrt_mutex_t *mutex; - dds_time_t stamp; - dds_duration_t pause; + dds_time_t before; + dds_time_t after; }; static void dummy(void *ptr, const dds_log_data_t *data) @@ -326,10 +326,10 @@ static void block(void *ptr, const dds_log_data_t *data) (void)data; struct arg *arg = (struct arg *)ptr; ddsrt_mutex_lock(arg->mutex); - arg->stamp = dds_time(); + arg->before = dds_time(); ddsrt_cond_broadcast(arg->cond); ddsrt_mutex_unlock(arg->mutex); - dds_sleepfor(arg->pause); + arg->after = dds_time(); } static uint32_t run(void *ptr) @@ -347,7 +347,6 @@ static uint32_t run(void *ptr) CU_Test(dds_log, synchronous_sink_changes, .fini=reset) { struct arg arg; - dds_time_t diff, stamp; ddsrt_thread_t tid; ddsrt_threadattr_t tattr; dds_retcode_t ret; @@ -357,7 +356,6 @@ CU_Test(dds_log, synchronous_sink_changes, .fini=reset) (void)memset(&arg, 0, sizeof(arg)); arg.mutex = &mutex; arg.cond = &cond; - arg.pause = 1000000; ddsrt_mutex_lock(&mutex); dds_set_log_sink(&block, &arg); @@ -366,9 +364,7 @@ CU_Test(dds_log, synchronous_sink_changes, .fini=reset) CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ddsrt_cond_wait(&cond, &mutex); dds_set_log_sink(dummy, NULL); - stamp = dds_time(); - CU_ASSERT(arg.stamp < stamp); - diff = stamp - arg.stamp; - CU_ASSERT(arg.pause < diff); + CU_ASSERT(arg.before < arg.after); + CU_ASSERT(arg.after < dds_time()); } diff --git a/src/ddsrt/tests/select.c b/src/ddsrt/tests/select.c index ab7bf0e..7d99096 100644 --- a/src/ddsrt/tests/select.c +++ b/src/ddsrt/tests/select.c @@ -9,10 +9,10 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include "CUnit/Theory.h" -#include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/sockets_priv.h" +#include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/threads.h" +#include "CUnit/Theory.h" CU_Init(ddsrt_select) { @@ -139,7 +139,7 @@ static const char mesg[] = "foobar"; static uint32_t select_timeout_routine(void *ptr) { - int cnt = -1; + int32_t cnt = -1; dds_retcode_t rc; dds_time_t before, after; dds_duration_t delay; @@ -148,7 +148,13 @@ static uint32_t select_timeout_routine(void *ptr) uint32_t res = 0; FD_ZERO(&rdset); +#if LWIP_SOCKET + DDSRT_WARNING_GNUC_OFF(sign-conversion) +#endif FD_SET(arg->sock, &rdset); +#if LWIP_SOCKET + DDSRT_WARNING_GNUC_ON(sign-conversion) +#endif before = dds_time(); rc = ddsrt_select(arg->sock + 1, &rdset, NULL, NULL, arg->delay, &cnt); @@ -157,11 +163,15 @@ static uint32_t select_timeout_routine(void *ptr) fprintf(stderr, "Waited for %"PRId64" (nanoseconds)\n", delay); fprintf(stderr, "Expected to wait %"PRId64" (nanoseconds)\n", arg->delay); - fprintf(stderr, "ddsrt_select returned %d\n", rc); - fprintf(stderr, "ddsrt_select reported %d ready\n", cnt); + fprintf(stderr, "ddsrt_select returned %"PRId32"\n", rc); + fprintf(stderr, "ddsrt_select reported %"PRId32" ready\n", cnt); if (rc == DDS_RETCODE_TIMEOUT) { res = (((after - delay) >= (arg->delay - arg->skew)) && (cnt == 0)); + /* Running in the FreeRTOS simulator causes some trouble as interrupts are + simulated using signals causing the select call to be interrupted. */ + } else if (rc == DDS_RETCODE_INTERRUPTED) { + res = (cnt == -1); } return res; @@ -207,13 +217,19 @@ static uint32_t recv_routine(void *ptr) { thread_arg_t *arg = (thread_arg_t*)ptr; - int nfds = 0; + int32_t nfds = 0; fd_set rdset; ssize_t rcvd = -1; char buf[sizeof(mesg)]; FD_ZERO(&rdset); +#if LWIP_SOCKET + DDSRT_WARNING_GNUC_OFF(sign-conversion) +#endif FD_SET(arg->sock, &rdset); +#if LWIP_SOCKET + DDSRT_WARNING_GNUC_ON(sign-conversion) +#endif (void)ddsrt_select(arg->sock + 1, &rdset, NULL, NULL, arg->delay, &nfds); @@ -260,7 +276,7 @@ static uint32_t recvmsg_routine(void *ptr) { thread_arg_t *arg = (thread_arg_t*)ptr; - int nfds = 0; + int32_t nfds = 0; fd_set rdset; ssize_t rcvd = -1; char buf[sizeof(mesg)]; @@ -274,7 +290,13 @@ static uint32_t recvmsg_routine(void *ptr) msg.msg_iovlen = 1; FD_ZERO(&rdset); +#if LWIP_SOCKET + DDSRT_WARNING_GNUC_OFF(sign-conversion) +#endif FD_SET(arg->sock, &rdset); +#if LWIP_SOCKET + DDSRT_WARNING_GNUC_ON(sign-conversion) +#endif (void)ddsrt_select(arg->sock + 1, &rdset, NULL, NULL, arg->delay, &nfds); diff --git a/src/ddsrt/tests/socket.c b/src/ddsrt/tests/socket.c index db89e2a..366c4b2 100644 --- a/src/ddsrt/tests/socket.c +++ b/src/ddsrt/tests/socket.c @@ -9,17 +9,17 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include -#include -#include -#include - -#include "CUnit/Theory.h" +#include "dds/ddsrt/sockets.h" #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/endian.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/misc.h" -#include "dds/ddsrt/sockets.h" +#include "dds/ddsrt/string.h" +#include "CUnit/Theory.h" + +#include +#include +#include DDSRT_WARNING_MSVC_OFF(4305) #if DDSRT_ENDIAN == DDSRT_BIG_ENDIAN @@ -79,8 +79,8 @@ CU_Theory((char *str, int af, dds_retcode_t exp), ddsrt_sockaddrfromstr, ipv4, . sockaddrfromstr_test(str, af, exp); } -#if DDSRT_HAVE_IPV6 CU_TheoryDataPoints(ddsrt_sockaddrfromstr, ipv6) = { +#if DDSRT_HAVE_IPV6 CU_DataPoints(char *, "127.0.0.1", "::1", "::1", "::", "nip"), @@ -90,13 +90,20 @@ CU_TheoryDataPoints(ddsrt_sockaddrfromstr, ipv6) = { CU_DataPoints(dds_retcode_t, DDS_RETCODE_BAD_PARAMETER, DDS_RETCODE_OK, DDS_RETCODE_BAD_PARAMETER, DDS_RETCODE_OK, DDS_RETCODE_BAD_PARAMETER) +#endif /* DDSRT_HAVE_IPV6 */ }; CU_Theory((char *str, int af, dds_retcode_t exp), ddsrt_sockaddrfromstr, ipv6, .init=setup, .fini=teardown) { +#if DDSRT_HAVE_IPV6 sockaddrfromstr_test(str, af, exp); -} +#else + (void)str; + (void)af; + (void)exp; + CU_PASS("IPV6 is not supported"); #endif /* DDSRT_HAVE_IPV6 */ +} CU_Test(ddsrt_sockaddrtostr, bad_sockaddr, .init=setup, .fini=teardown) { @@ -128,16 +135,19 @@ CU_Test(ddsrt_sockaddrtostr, ipv4) CU_Test(ddsrt_sockaddrtostr, ipv6) { +#if DDSRT_HAVE_IPV6 dds_retcode_t rc; char buf[128] = { 0 }; rc = ddsrt_sockaddrtostr(&ipv6_loopback, buf, sizeof(buf)); CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); CU_ASSERT_STRING_EQUAL(buf, "::1"); +#else + CU_PASS("IPv6 is not supported"); +#endif } CU_Test(ddsrt_sockets, gethostname) { - int ret; dds_retcode_t rc; char sysbuf[200], buf[200]; @@ -146,8 +156,12 @@ CU_Test(ddsrt_sockets, gethostname) CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); sysbuf[0] = '\0'; - ret = gethostname(sysbuf, sizeof(sysbuf)); +#if LWIP_SOCKET + ddsrt_strlcpy(sysbuf, "localhost", sizeof(sysbuf)); +#else + int ret = gethostname(sysbuf, sizeof(sysbuf)); CU_ASSERT_EQUAL(ret, 0); +#endif CU_ASSERT(strcmp(buf, sysbuf) == 0); rc = ddsrt_gethostname(buf, strlen(buf) - 1); @@ -169,6 +183,7 @@ static void gethostbyname_test(char *name, int af, dds_retcode_t exp) } ddsrt_free(hent); } +#endif CU_TheoryDataPoints(ddsrt_gethostbyname, ipv4) = { CU_DataPoints(char *, "", "127.0.0.1", "127.0.0.1"), @@ -178,21 +193,34 @@ CU_TheoryDataPoints(ddsrt_gethostbyname, ipv4) = { CU_Theory((char *name, int af, dds_retcode_t exp), ddsrt_gethostbyname, ipv4, .init=setup, .fini=teardown) { +#if DDSRT_HAVE_DNS gethostbyname_test(name, af, exp); +#else + (void)name; + (void)af; + (void)exp; + CU_PASS("DNS is not supported"); +#endif } -#if DDSRT_HAVE_IPV6 /* Lookup of IPv4 address and specifying AF_INET6 is not invalid as it may return an IPV4-mapped IPv6 address. */ CU_TheoryDataPoints(ddsrt_gethostbyname, ipv6) = { +#if DDSRT_HAVE_IPV6 && DDSRT_HAVE_DNS CU_DataPoints(char *, "::1", "::1", "::1"), CU_DataPoints(int, AF_INET, AF_INET6, AF_UNSPEC), CU_DataPoints(dds_retcode_t, DDS_RETCODE_HOST_NOT_FOUND, DDS_RETCODE_OK, DDS_RETCODE_OK) +#endif /* DDSRT_HAVE_IPV6 */ }; CU_Theory((char *name, int af, dds_retcode_t exp), ddsrt_gethostbyname, ipv6, .init=setup, .fini=teardown) { +#if DDSRT_HAVE_IPV6 && DDSRT_HAVE_DNS gethostbyname_test(name, af, exp); -} +#else + (void)name; + (void)af; + (void)exp; + CU_PASS("DNS and IPv6 are not supported"); #endif /* DDSRT_HAVE_IPV6 */ -#endif /* DDSRT_HAVE_DNS */ +} diff --git a/src/ddsrt/tests/sync.c b/src/ddsrt/tests/sync.c index 1f8031c..d009353 100644 --- a/src/ddsrt/tests/sync.c +++ b/src/ddsrt/tests/sync.c @@ -270,7 +270,7 @@ static uint32_t waitfor_routine(void *ptr) reltime = after - before; fprintf(stderr, "waited for %"PRId64" (nanoseconds)\n", reltime); fprintf(stderr, "expected to wait %"PRId64" (nanoseconds)\n", arg->reltime); - fprintf(stderr, "woke up %u times\n", cnt); + fprintf(stderr, "woke up %"PRIu32" times\n", cnt); ddsrt_mutex_unlock(&arg->lock); if (reltime >= arg->reltime) { /* Ensure that the condition variable at least waited for the amount of @@ -322,7 +322,7 @@ static uint32_t waituntil_routine(void *ptr) ddsrt_mutex_unlock(&arg->lock); fprintf(stderr, "waited until %"PRId64" (nanoseconds)\n", after); fprintf(stderr, "expected to wait until %"PRId64" (nanoseconds)\n", arg->abstime); - fprintf(stderr, "woke up %u times\n", cnt); + fprintf(stderr, "woke up %"PRIu32" times\n", cnt); if (after > arg->abstime) { res = cnt < 3; /* An arbitrary number to ensure the implementation did not just spin, aka is completely broken. */ diff --git a/src/ddsrt/tests/tasklist.c b/src/ddsrt/tests/tasklist.c new file mode 100644 index 0000000..81134c8 --- /dev/null +++ b/src/ddsrt/tests/tasklist.c @@ -0,0 +1,341 @@ +/* + * 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/sync.h" + +#include "CUnit/Theory.h" + +/* FreeRTOS specific! */ + +static void fill(ddsrt_tasklist_t *list) +{ + CU_ASSERT_PTR_NOT_NULL_FATAL(list); + CU_ASSERT_EQUAL_FATAL(list->len, DDSRT_TASKLIST_INITIAL); + + for (size_t i = 1; i <= DDSRT_TASKLIST_INITIAL; i++) { + ddsrt_tasklist_push(list, (TaskHandle_t)i); + CU_ASSERT_EQUAL_FATAL(list->cnt, i); + CU_ASSERT_EQUAL_FATAL(list->off, 0); + CU_ASSERT_EQUAL_FATAL(list->end, i - 1); + } + + CU_ASSERT_EQUAL_FATAL(list->len, DDSRT_TASKLIST_INITIAL); + CU_ASSERT_EQUAL_FATAL(list->cnt, DDSRT_TASKLIST_INITIAL); + CU_ASSERT_EQUAL_FATAL(list->off, 0); + CU_ASSERT_EQUAL_FATAL(list->end, DDSRT_TASKLIST_INITIAL - 1); +} + +static void fill_wrapped(ddsrt_tasklist_t *list) +{ + size_t i; + + fill(list); + + for (i = 1; i <= DDSRT_TASKLIST_CHUNK; i++) { + ddsrt_tasklist_pop(list, NULL); + CU_ASSERT_EQUAL_FATAL(list->cnt, DDSRT_TASKLIST_INITIAL - i); + CU_ASSERT_EQUAL_FATAL(list->off, i); + CU_ASSERT_EQUAL_FATAL(list->end, DDSRT_TASKLIST_INITIAL - 1); + } + + for (i = (DDSRT_TASKLIST_INITIAL+1); i <= (DDSRT_TASKLIST_INITIAL+DDSRT_TASKLIST_CHUNK); i++) { + ddsrt_tasklist_push(list, (TaskHandle_t)i); + CU_ASSERT_EQUAL_FATAL(list->cnt, i - DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL_FATAL(list->off, DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL_FATAL(list->end, (i - 1) - DDSRT_TASKLIST_INITIAL); + } + + CU_ASSERT_EQUAL_FATAL(list->len, DDSRT_TASKLIST_INITIAL); + CU_ASSERT_EQUAL_FATAL(list->cnt, DDSRT_TASKLIST_INITIAL); + CU_ASSERT_EQUAL_FATAL(list->off, DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL_FATAL(list->end, DDSRT_TASKLIST_CHUNK - 1); +} + +typedef void(*fill_t)(ddsrt_tasklist_t *); + +CU_TheoryDataPoints(ddsrt_sync, tasklist_pop_all) = { + CU_DataPoints(fill_t, &fill, &fill_wrapped), + CU_DataPoints(size_t, 1, DDSRT_TASKLIST_CHUNK + 1), + CU_DataPoints(size_t, DDSRT_TASKLIST_INITIAL, DDSRT_TASKLIST_INITIAL + DDSRT_TASKLIST_CHUNK) +}; + +/* Most basic test to verify behavior is correct for simple use case. */ +CU_Theory((fill_t func, size_t first, size_t last), ddsrt_sync, tasklist_pop_all) +{ + TaskHandle_t task; + ddsrt_tasklist_t list; + + ddsrt_tasklist_init(&list); + func(&list); + + task = ddsrt_tasklist_pop(&list, NULL); + CU_ASSERT_PTR_EQUAL(task, (TaskHandle_t)first); + + for (size_t i = first + 1; i < last; i++) { + task = ddsrt_tasklist_pop(&list, NULL); + CU_ASSERT_PTR_EQUAL(task, (TaskHandle_t)i); + } + + CU_ASSERT_EQUAL(list.cnt, 1); + CU_ASSERT_EQUAL(list.off, ((DDSRT_TASKLIST_INITIAL*2) - last) - 1); + CU_ASSERT_EQUAL(list.end, ((DDSRT_TASKLIST_INITIAL*2) - last) - 1); + task = ddsrt_tasklist_pop(&list, NULL); + CU_ASSERT_PTR_EQUAL(task, (TaskHandle_t)last); + task = ddsrt_tasklist_pop(&list, NULL); + CU_ASSERT_PTR_NULL(task); + CU_ASSERT_EQUAL(list.cnt, 0); + CU_ASSERT_EQUAL(list.off, 0); + CU_ASSERT_EQUAL(list.end, 0); + + ddsrt_tasklist_fini(&list); +} + +CU_TheoryDataPoints(ddsrt_sync, tasklist_pop_n_push) = { + CU_DataPoints(fill_t, + &fill, &fill, &fill, &fill, + &fill_wrapped, &fill_wrapped, &fill_wrapped, &fill_wrapped, &fill_wrapped), + CU_DataPoints(TaskHandle_t, /* Task to pop. */ + (TaskHandle_t)NULL, + (TaskHandle_t)1, + (TaskHandle_t)DDSRT_TASKLIST_CHUNK, + (TaskHandle_t)DDSRT_TASKLIST_INITIAL, + (TaskHandle_t)NULL, + (TaskHandle_t)(DDSRT_TASKLIST_CHUNK + 1), + (TaskHandle_t)DDSRT_TASKLIST_INITIAL, + (TaskHandle_t)(DDSRT_TASKLIST_INITIAL + 1), + (TaskHandle_t)(DDSRT_TASKLIST_INITIAL + DDSRT_TASKLIST_CHUNK)), + CU_DataPoints(size_t, /* Expected position to clear. */ + 0, 0, DDSRT_TASKLIST_CHUNK - 1, DDSRT_TASKLIST_INITIAL - 1, + DDSRT_TASKLIST_CHUNK, DDSRT_TASKLIST_CHUNK, DDSRT_TASKLIST_INITIAL - 1, 0, DDSRT_TASKLIST_CHUNK - 1), + CU_DataPoints(size_t, /* Expected position of pushed task. */ + 0, 0, DDSRT_TASKLIST_INITIAL - 1, DDSRT_TASKLIST_INITIAL - 1, + DDSRT_TASKLIST_CHUNK, DDSRT_TASKLIST_CHUNK, DDSRT_TASKLIST_CHUNK, DDSRT_TASKLIST_CHUNK - 1, DDSRT_TASKLIST_CHUNK - 1) +}; + +/* Test to verify tasklist is correctly updated (trimmed and packed) when the + tasklist is sparse. */ +CU_Theory((fill_t func, TaskHandle_t task, size_t pos, size_t end), ddsrt_sync, tasklist_pop_n_push) +{ + ddsrt_tasklist_t list; + + ddsrt_tasklist_init(&list); + func(&list); + + if (task == NULL) { + ddsrt_tasklist_pop(&list, NULL); + } else { + CU_ASSERT_PTR_EQUAL(ddsrt_tasklist_pop(&list, task), task); + CU_ASSERT_PTR_NULL(ddsrt_tasklist_pop(&list, task)); + } + CU_ASSERT_PTR_EQUAL(list.tasks[pos], NULL); + task = (TaskHandle_t)(DDSRT_TASKLIST_INITIAL*2); + CU_ASSERT_NOT_EQUAL_FATAL(ddsrt_tasklist_push(&list, task), -1); + CU_ASSERT_PTR_EQUAL(list.tasks[end], task); + CU_ASSERT_EQUAL(list.len, DDSRT_TASKLIST_INITIAL); + CU_ASSERT_EQUAL(list.cnt, DDSRT_TASKLIST_INITIAL); + + ddsrt_tasklist_fini(&list); +} + +CU_Test(ddsrt_sync, tasklist_ltrim) +{ + ddsrt_tasklist_t list; + + ddsrt_tasklist_init(&list); + fill(&list); + + ddsrt_tasklist_pop(&list, (TaskHandle_t)2); + ddsrt_tasklist_pop(&list, (TaskHandle_t)3); + CU_ASSERT_EQUAL(list.cnt, DDSRT_TASKLIST_INITIAL - 2); + CU_ASSERT_EQUAL(list.off, 0); + CU_ASSERT_EQUAL(list.end, 9); + ddsrt_tasklist_pop(&list, (TaskHandle_t)1); + CU_ASSERT_EQUAL(list.cnt, DDSRT_TASKLIST_INITIAL - 3); + CU_ASSERT_EQUAL(list.off, 3); + CU_ASSERT_EQUAL(list.end, 9); + + ddsrt_tasklist_fini(&list); +} + +CU_Test(ddsrt_sync, tasklist_rtrim) +{ + ddsrt_tasklist_t list; + + ddsrt_tasklist_init(&list); + fill(&list); + + ddsrt_tasklist_pop(&list, (TaskHandle_t)(DDSRT_TASKLIST_INITIAL - 1)); + ddsrt_tasklist_pop(&list, (TaskHandle_t)(DDSRT_TASKLIST_INITIAL - 2)); + CU_ASSERT_EQUAL(list.cnt, DDSRT_TASKLIST_INITIAL - 2); + CU_ASSERT_EQUAL(list.off, 0); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_INITIAL - 1); + ddsrt_tasklist_pop(&list, (TaskHandle_t)DDSRT_TASKLIST_INITIAL); + CU_ASSERT_EQUAL(list.cnt, DDSRT_TASKLIST_INITIAL - 3); + CU_ASSERT_EQUAL(list.off, 0); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_INITIAL - 4); + + ddsrt_tasklist_fini(&list); +} + +CU_Test(ddsrt_sync, tasklist_wrapped_ltrim) +{ + ddsrt_tasklist_t list; + + ddsrt_tasklist_init(&list); + fill_wrapped(&list); + + for (size_t i = DDSRT_TASKLIST_CHUNK+2; i < DDSRT_TASKLIST_INITIAL; i++) { + ddsrt_tasklist_pop(&list, (TaskHandle_t)i); + } + CU_ASSERT_EQUAL(list.cnt, DDSRT_TASKLIST_INITIAL - (DDSRT_TASKLIST_CHUNK - 2)); + CU_ASSERT_EQUAL(list.off, DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_CHUNK - 1); + ddsrt_tasklist_pop(&list, (TaskHandle_t)(DDSRT_TASKLIST_CHUNK+1)); + CU_ASSERT_EQUAL(list.cnt, DDSRT_TASKLIST_INITIAL - (DDSRT_TASKLIST_CHUNK - 1)); + CU_ASSERT_EQUAL(list.off, DDSRT_TASKLIST_INITIAL - 1); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_CHUNK - 1); + ddsrt_tasklist_pop(&list, (TaskHandle_t)(DDSRT_TASKLIST_INITIAL+1)); + ddsrt_tasklist_pop(&list, (TaskHandle_t)DDSRT_TASKLIST_INITIAL); + CU_ASSERT_EQUAL(list.cnt, DDSRT_TASKLIST_INITIAL - (DDSRT_TASKLIST_CHUNK + 1)); + CU_ASSERT_EQUAL(list.off, 1); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_CHUNK - 1); + + ddsrt_tasklist_fini(&list); +} + +CU_Test(ddsrt_sync, tasklist_wrapped_rtrim) +{ + ddsrt_tasklist_t list; + size_t last = DDSRT_TASKLIST_INITIAL + DDSRT_TASKLIST_CHUNK; + + ddsrt_tasklist_init(&list); + fill_wrapped(&list); + + for (size_t i = last - 1; i > DDSRT_TASKLIST_INITIAL + 1; i--) { + ddsrt_tasklist_pop(&list, (TaskHandle_t)i); + } + CU_ASSERT_EQUAL(list.cnt, (DDSRT_TASKLIST_INITIAL - DDSRT_TASKLIST_CHUNK) + 2); + CU_ASSERT_EQUAL(list.off, DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_CHUNK - 1); + ddsrt_tasklist_pop(&list, (TaskHandle_t)(DDSRT_TASKLIST_INITIAL + DDSRT_TASKLIST_CHUNK)); + CU_ASSERT_EQUAL(list.cnt, (DDSRT_TASKLIST_INITIAL - DDSRT_TASKLIST_CHUNK) + 1); + CU_ASSERT_EQUAL(list.off, DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL(list.end, 0); + ddsrt_tasklist_pop(&list, (TaskHandle_t)(DDSRT_TASKLIST_INITIAL - 1)); + ddsrt_tasklist_pop(&list, (TaskHandle_t)(DDSRT_TASKLIST_INITIAL - 2)); + ddsrt_tasklist_pop(&list, (TaskHandle_t)(DDSRT_TASKLIST_INITIAL + 1)); + CU_ASSERT_EQUAL(list.cnt, (DDSRT_TASKLIST_INITIAL - DDSRT_TASKLIST_CHUNK) - 2); + CU_ASSERT_EQUAL(list.off, DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_INITIAL - 1); + ddsrt_tasklist_pop(&list, (TaskHandle_t)DDSRT_TASKLIST_INITIAL); + CU_ASSERT_EQUAL(list.cnt, (DDSRT_TASKLIST_INITIAL - DDSRT_TASKLIST_CHUNK) - 3); + CU_ASSERT_EQUAL(list.off, DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_INITIAL - 4); + + ddsrt_tasklist_fini(&list); +} + +CU_Test(ddsrt_sync, tasklist_resize) +{ + ddsrt_tasklist_t list; + int ret; + + ddsrt_tasklist_init(&list); + fill(&list); + + /* Grow one past initial. Buffer should increase by chunk. */ + ret = ddsrt_tasklist_push(&list, (TaskHandle_t)(DDSRT_TASKLIST_INITIAL + 1)); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_EQUAL(list.len, DDSRT_TASKLIST_INITIAL + DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL(list.off, 0); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_INITIAL); + /* Grow one past initial+chunk. Buffer should increase by chunk again. */ + for (size_t i = 2; i <= DDSRT_TASKLIST_CHUNK + 1; i++) { + ret = ddsrt_tasklist_push(&list, (TaskHandle_t)(DDSRT_TASKLIST_INITIAL + i)); + CU_ASSERT_EQUAL_FATAL(ret, 0); + } + CU_ASSERT_EQUAL(list.len, DDSRT_TASKLIST_INITIAL + (DDSRT_TASKLIST_CHUNK*2)); + CU_ASSERT_EQUAL(list.off, 0); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_INITIAL + DDSRT_TASKLIST_CHUNK); + + /* Shrink one past initial+chunk. Buffer should not decrease by chunk. */ + for (size_t i = 1; i <= DDSRT_TASKLIST_CHUNK; i++) { + ddsrt_tasklist_pop(&list, (TaskHandle_t)i); + } + CU_ASSERT_EQUAL(list.len, DDSRT_TASKLIST_INITIAL + (DDSRT_TASKLIST_CHUNK*2)); + CU_ASSERT_EQUAL(list.off, DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_INITIAL + DDSRT_TASKLIST_CHUNK); + + /* Shrink to initial. Buffer should decrease by chunk. */ + ddsrt_tasklist_pop(&list, (TaskHandle_t)(DDSRT_TASKLIST_CHUNK + 1)); + CU_ASSERT_EQUAL(list.len, DDSRT_TASKLIST_INITIAL + DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL(list.off, 0); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_INITIAL - 1); + + /* Shrink to initial-chunk. Buffer should decrease by chunk. */ + for (size_t i = DDSRT_TASKLIST_CHUNK+1; i <= (DDSRT_TASKLIST_CHUNK*2)+1; i++) { + ddsrt_tasklist_pop(&list, (TaskHandle_t)i); + CU_ASSERT_EQUAL_FATAL(ret, 0); + } + CU_ASSERT_EQUAL(list.len, DDSRT_TASKLIST_INITIAL); + CU_ASSERT_EQUAL(list.off, 0); + CU_ASSERT_EQUAL(list.end, (DDSRT_TASKLIST_INITIAL - DDSRT_TASKLIST_CHUNK) - 1); + + ddsrt_tasklist_fini(&list); +} + +CU_Test(ddsrt_sync, tasklist_wrapped_resize) +{ + ddsrt_tasklist_t list; + int ret; + + ddsrt_tasklist_init(&list); + fill_wrapped(&list); + + /* Grow one past initial. Buffer should increase by chunk. */ + ret = ddsrt_tasklist_push(&list, (TaskHandle_t)(DDSRT_TASKLIST_INITIAL + DDSRT_TASKLIST_CHUNK + 1)); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_EQUAL(list.len, DDSRT_TASKLIST_INITIAL + DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL(list.off, DDSRT_TASKLIST_INITIAL); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_CHUNK); + /* Grow one past initial+chunk. Buffer should increase by chunk again. */ + for (size_t i = 2; i <= (DDSRT_TASKLIST_CHUNK + 1); i++) { + ret = ddsrt_tasklist_push(&list, (TaskHandle_t)(DDSRT_TASKLIST_INITIAL + DDSRT_TASKLIST_CHUNK + i)); + CU_ASSERT_EQUAL_FATAL(ret, 0); + } + CU_ASSERT_EQUAL(list.len, DDSRT_TASKLIST_INITIAL + (DDSRT_TASKLIST_CHUNK*2)); + CU_ASSERT_EQUAL(list.off, DDSRT_TASKLIST_INITIAL + DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_INITIAL); + + /* Shrink one past initial+chunk. Buffer should not decrease by chunk. */ + for (size_t i = 1; i <= DDSRT_TASKLIST_CHUNK; i++) { + ddsrt_tasklist_pop(&list, (TaskHandle_t)(DDSRT_TASKLIST_CHUNK + i)); + } + CU_ASSERT_EQUAL(list.len, DDSRT_TASKLIST_INITIAL + (DDSRT_TASKLIST_CHUNK*2)); + CU_ASSERT_EQUAL(list.off, 0); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_INITIAL); + + /* Shrink to initial. Buffer should decrease by chunk. */ + ddsrt_tasklist_pop(&list, (TaskHandle_t)((DDSRT_TASKLIST_CHUNK*2) + 1)); + CU_ASSERT_EQUAL(list.len, DDSRT_TASKLIST_INITIAL + DDSRT_TASKLIST_CHUNK); + CU_ASSERT_EQUAL(list.off, 0); + CU_ASSERT_EQUAL(list.end, DDSRT_TASKLIST_INITIAL - 1); + + /* Shrink to initial-chunk. Buffer should decrease by chunk. */ + for (size_t i = 2; i <= DDSRT_TASKLIST_CHUNK + 1; i++) { + ddsrt_tasklist_pop(&list, (TaskHandle_t)((DDSRT_TASKLIST_CHUNK*2) + i)); + } + CU_ASSERT_EQUAL(list.len, DDSRT_TASKLIST_INITIAL); + CU_ASSERT_EQUAL(list.off, 0); + CU_ASSERT_EQUAL(list.end, (DDSRT_TASKLIST_INITIAL - DDSRT_TASKLIST_CHUNK) - 1); + + ddsrt_tasklist_fini(&list); +} diff --git a/src/ddsrt/tests/thread.c b/src/ddsrt/tests/thread.c index 8b3ff5d..8814440 100644 --- a/src/ddsrt/tests/thread.c +++ b/src/ddsrt/tests/thread.c @@ -11,9 +11,12 @@ */ #include #include -#if !defined(_WIN32) -#include -#include +#if DDSRT_WITH_FREERTOS +# include +# include +#elif !defined(_WIN32) +# include +# include #endif #include "CUnit/Theory.h" @@ -30,7 +33,10 @@ static int32_t min_other_prio = 250; CU_Init(ddsrt_thread) { ddsrt_init(); -#if defined(WIN32) +#if DDSRT_WITH_FREERTOS + max_other_prio = max_fifo_prio = configMAX_PRIORITIES - 1; + min_other_prio = min_fifo_prio = tskIDLE_PRIORITY + 1; +#elif defined(WIN32) max_fifo_prio = THREAD_PRIORITY_HIGHEST; min_fifo_prio = THREAD_PRIORITY_LOWEST; max_other_prio = THREAD_PRIORITY_HIGHEST; @@ -68,7 +74,12 @@ uint32_t thread_main(void *ptr) attr = arg->attr; -#if _WIN32 +#if DDSRT_WITH_FREERTOS + int prio = (int)uxTaskPriorityGet(NULL); + if (prio == attr->schedPriority) { + arg->res = 1; + } +#elif _WIN32 int prio = GetThreadPriority(GetCurrentThread()); if (prio == THREAD_PRIORITY_ERROR_RETURN) abort(); @@ -113,7 +124,12 @@ CU_Theory((ddsrt_sched_t sched, int32_t *prio, uint32_t exp), ddsrt_thread, crea ddsrt_threadattr_t attr; thread_arg_t arg; -#if defined(__VXWORKS__) +#if DDSRT_WITH_FREERTOS + if (sched == DDSRT_SCHED_TIMESHARE) { + skip = 1; + CU_PASS("FreeRTOS only support SCHED_FIFO"); + } +#elif defined(__VXWORKS__) # if defined(_WRS_KERNEL) if (sched == DDSRT_SCHED_TIMESHARE) { skip = 1; @@ -150,7 +166,9 @@ CU_Test(ddsrt_thread, thread_id) { int eq = 0; ddsrt_thread_t thr; -#if defined(_WIN32) +#if DDSRT_WITH_FREERTOS + TaskHandle_t task; +#elif defined(_WIN32) DWORD _tid; #else pthread_t _thr; @@ -158,7 +176,10 @@ CU_Test(ddsrt_thread, thread_id) thr = ddsrt_thread_self(); -#if defined(_WIN32) +#if DDSRT_WITH_FREERTOS + task = xTaskGetCurrentTaskHandle(); + eq = (thr.task == task); +#elif defined(_WIN32) _tid = GetCurrentThreadId(); eq = (thr.tid == _tid); #else @@ -230,4 +251,3 @@ CU_Test(ddsrt_thread, attribute) CU_ASSERT_EQUAL(attr.schedPriority, 0); CU_ASSERT_EQUAL(attr.stackSize, 0); } - diff --git a/src/examples/roundtrip/ping.c b/src/examples/roundtrip/ping.c index 9b09c3a..d24541e 100644 --- a/src/examples/roundtrip/ping.c +++ b/src/examples/roundtrip/ping.c @@ -116,7 +116,7 @@ static bool CtrlHandler (DWORD fdwCtrlType) dds_waitset_set_trigger (waitSet, true); return true; //Don't let other handlers handle this key } -#else +#elif !DDSRT_WITH_FREERTOS static void CtrlHandler (int sig) { (void)sig; @@ -249,7 +249,7 @@ int main (int argc, char *argv[]) /* Register handler for Ctrl-C */ #ifdef _WIN32 SetConsoleCtrlHandler ((PHANDLER_ROUTINE)CtrlHandler, TRUE); -#else +#elif !DDSRT_WITH_FREERTOS struct sigaction sat, oldAction; sat.sa_handler = CtrlHandler; sigemptyset (&sat.sa_mask); @@ -411,7 +411,7 @@ done: #ifdef _WIN32 SetConsoleCtrlHandler (0, FALSE); -#else +#elif !DDSRT_WITH_FREERTOS sigaction (SIGINT, &oldAction, 0); #endif diff --git a/src/examples/roundtrip/pong.c b/src/examples/roundtrip/pong.c index 010c0c5..992ba75 100644 --- a/src/examples/roundtrip/pong.c +++ b/src/examples/roundtrip/pong.c @@ -20,7 +20,7 @@ static bool CtrlHandler (DWORD fdwCtrlType) dds_waitset_set_trigger (waitSet, true); return true; //Don't let other handlers handle this key } -#else +#elif !DDSRT_WITH_FREERTOS static void CtrlHandler (int sig) { (void)sig; @@ -87,7 +87,7 @@ int main (int argc, char *argv[]) #ifdef _WIN32 SetConsoleCtrlHandler ((PHANDLER_ROUTINE)CtrlHandler, TRUE); -#else +#elif !DDSRT_WITH_FREERTOS struct sigaction sat, oldAction; sat.sa_handler = CtrlHandler; sigemptyset (&sat.sa_mask); @@ -130,7 +130,7 @@ int main (int argc, char *argv[]) #ifdef _WIN32 SetConsoleCtrlHandler (0, FALSE); -#else +#elif !DDSRT_WITH_FREERTOS sigaction (SIGINT, &oldAction, 0); #endif diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index cef4870..06f1970 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -19,9 +19,6 @@ #include #include #include -#ifndef _WIN32 -#include -#endif #include #include "dds/dds.h" @@ -36,6 +33,10 @@ #include "dds/ddsrt/avl.h" #include "dds/ddsrt/fibheap.h" +#if !defined(_WIN32) && !defined(LWIP_SOCKET) +#include +#endif + #define UDATA_MAGIC "DDSPerf:" #define UDATA_MAGIC_SIZE (sizeof (UDATA_MAGIC) - 1) @@ -1383,14 +1384,16 @@ static void subthread_arg_fini (struct subthread_arg *arg) free (arg->iseq); } +#if !DDSRT_WITH_FREERTOS static void signal_handler (int sig) { (void) sig; termflag = 1; dds_set_guardcondition (termcond, true); } +#endif -#ifndef _WIN32 +#if !_WIN32 && !DDSRT_WITH_FREERTOS static uint32_t sigthread (void *varg) { sigset_t *set = varg; @@ -1642,7 +1645,7 @@ int main (int argc, char *argv[]) int opt; ddsrt_threadattr_t attr; ddsrt_thread_t pubtid, subtid, subpingtid, subpongtid; -#ifndef _WIN32 +#if !_WIN32 && !DDSRT_WITH_FREERTOS sigset_t sigset, osigset; ddsrt_thread_t sigtid; #endif @@ -1841,7 +1844,7 @@ int main (int argc, char *argv[]) /* I hate Unix signals in multi-threaded processes ... */ #ifdef _WIN32 signal (SIGINT, signal_handler); -#else +#elif !DDSRT_WITH_FREERTOS sigemptyset (&sigset); sigaddset (&sigset, SIGINT); sigaddset (&sigset, SIGTERM); @@ -1989,7 +1992,7 @@ int main (int argc, char *argv[]) #if _WIN32 signal_handler (SIGINT); -#else +#elif !DDSRT_WITH_FREERTOS { /* get the attention of the signal handler thread */ void (*osigint) (int); From e3428ad1d850ba1113ee8a14894b4645fc00fea6 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Tue, 21 May 2019 23:14:14 +0200 Subject: [PATCH 067/178] Add Coverity Scan target to .travis.yml Signed-off-by: Jeroen Koekkoek --- .travis.yml | 188 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 119 insertions(+), 69 deletions(-) diff --git a/.travis.yml b/.travis.yml index e619bf6..70b0781 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,41 @@ language: c -# Platform descriptions -# NOTE: These can be used in creating the build matrix by making use of the -# anchor/alias YAML features. +# Coverity Scan can be configured through Travis addons, but this allows for +# more control over the build instructions and does not require the addition +# of a coverity_scan branch in the repository. travisci_build_coverity_scan.sh +# does more checks before it decides to download Coverity (around 500M), but +# these instructions assume Coverity Scan is not installed if the directory +# does not exist and expects the download to fail if the token is incorrect. +# Coverity Scan quota are not checked as the Coverity enabled build must only +# run from cron. +install_coverity: &install_coverity + if [ -n "${COVERITY_SCAN}" ]; then + COVERITY_DIR="/tmp/coverity-scan-analysis"; + COVERITY_ARCHIVE="/tmp/cov-analysis-${COV_PLATFORM}.tgz"; + test ! -d "${COVERITY_DIR}" && + mkdir -p "${COVERITY_DIR}" && + curl -f -s -F project="${TRAVIS_REPO_SLUG}" + -F token="${COVERITY_SCAN_TOKEN}" + -o "${COVERITY_ARCHIVE}" + "https://scan.coverity.com/download/cxx/${COV_PLATFORM}" && + tar -xzf "${COVERITY_ARCHIVE}" -C "${COVERITY_DIR}"; + COVERITY_ANALYSIS=$(find "${COVERITY_DIR}" -type d -name "cov-analysis*"); + eval "export PATH=\"${PATH}:${COVERITY_ANALYSIS}/bin\""; + eval "export SCAN_BUILD=\"cov-build --dir cov-int\""; + cov-configure --comptype ${COV_COMPTYPE} --compiler ${CC} --template; + fi + +submit_to_coverity_scan: &submit_to_coverity_scan + if [ -n "${COVERITY_SCAN}" ]; then + tar -czf analysis-results.tgz cov-int && + curl -f -v -F project="${TRAVIS_REPO_SLUG}" + -F token="${COVERITY_SCAN_TOKEN}" + -F file=@analysis-results.tgz + -F version=$(git rev-parse --short HEAD) + -F description="Travis CI build" + "https://scan.coverity.com/builds"; + fi + linux_gcc8: &linux_gcc8 os: linux dist: xenial @@ -12,6 +45,13 @@ linux_gcc8: &linux_gcc8 update: true sources: [ ubuntu-toolchain-r-test ] packages: [ gcc-8 g++-8 ] + before_install: + - eval "export CC=gcc-8" + - eval "export CXX=g++-8" + - eval "export COV_COMPTYPE=gcc COV_PLATFORM=linux64" + install: + - *install_coverity + - pip install conan --upgrade --user linux_clang: &linux_clang os: linux @@ -20,6 +60,12 @@ linux_clang: &linux_clang addons: apt: update: true + before_install: + - eval "export CC=clang" + - eval "export CXX=clang++" + - eval "export COV_COMPTYPE=clang COV_PLATFORM=linux64" + install: + - pip install conan --upgrade --user osx_xcode10_1: &osx_xcode10_1 os: osx @@ -29,86 +75,86 @@ osx_xcode10_1: &osx_xcode10_1 homebrew: packages: - pyenv-virtualenv + before_install: + - eval "export CC=clang" + - eval "export CXX=clang++" + - eval "export COV_COMPTYPE=clang COV_PLATFORM=macOSX" + install: + - eval "$(pyenv init -)" + - pyenv virtualenv conan + - pyenv rehash + - pyenv activate conan + - pip install conan --upgrade windows_vs2017: &windows_vs2017 os: windows + # Conan will automatically determine the best compiler for a given platform + # based on educated guesses. The first check is based on the CC and CXX + # environment variables, the second (on Windows) is to check if Microsoft + # Visual Studio is installed. On Travis CC and CXX are set to gcc on + # Microsoft Windows targets as well, this has the undesired effect that MSVC + # is not detected, unsetting CC and CXX solves that problem. + # + # + # !!! IMPORTANT !!! + # + # Microsoft Windows instances freeze at "install:" if secure environment + # variables are used. There is no option to export secrets only for + # specified platforms. The "filter_secrets: false" option is used to disable + # the filter for Microsoft Windows instances. This is not an issue if the + # secret is removed from the environment at the earliest opportunity, before + # risk of exposure, as secrets are always removed from the environment for + # pull requests and are still filtered when exported to the environment. The + # secret of course will not be available for Microsoft Windows builds, but + # for Coverity Scan, that is fine. + filter_secrets: false + before_install: + - eval "unset COVERITY_SCAN_TOKEN" + - eval "unset CC" + - eval "unset CXX" + - eval "export COV_COMPTYPE=msvc COV_PLATFORM=win64" + - JAVA_HOME=$(find "/c/Program Files/Android/jdk/" -name "*openjdk*" | sort | head -n 1) + - export JAVA_HOME + - export PATH="${PATH}:${JAVA_HOME}/bin" + # Windows targets in Travis are still very much in beta and Python is not yet + # available and installation of Python through Chocolaty does not work well. + # The real fix is to wait until Python and pip are both available on the + # target. Until then download Conan from the official website and simply add + # the extracted folder to the path. + install: + - choco install innoextract + - choco install maven --ignore-dependencies + - wget -q https://dl.bintray.com/conan/installers/conan-win-64_1_10_0.exe + - innoextract conan-win-64_1_10_0.exe + - eval "export PATH=\"$(pwd)/app/conan:${PATH}\"" -matrix: +jobs: include: - <<: *linux_gcc8 - env: [ BUILD_TYPE=Debug, C_COMPILER=gcc-8, CXX_COMPILER=g++-8, USE_SANITIZER=none ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, GENERATOR="Unix Makefiles", COVERITY_SCAN=true ] + if: type = cron - <<: *linux_gcc8 - env: [ BUILD_TYPE=Release, C_COMPILER=gcc-8, CXX_COMPILER=g++-8, USE_SANITIZER=none ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, GENERATOR="Unix Makefiles" ] + - <<: *linux_gcc8 + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, GENERATOR="Unix Makefiles" ] - <<: *linux_clang - env: [ BUILD_TYPE=Debug, C_COMPILER=clang, CXX_COMPILER=clang++, USE_SANITIZER=address ] + env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, GENERATOR="Unix Makefiles" ] - <<: *linux_clang - env: [ BUILD_TYPE=Release, C_COMPILER=clang, CXX_COMPILER=clang++, USE_SANITIZER=none ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, GENERATOR="Unix Makefiles" ] - <<: *osx_xcode10_1 - env: [ BUILD_TYPE=Debug, C_COMPILER=clang, CXX_COMPILER=clang++, USE_SANITIZER=address ] + env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, GENERATOR="Unix Makefiles" ] - <<: *osx_xcode10_1 - env: [ BUILD_TYPE=Release, C_COMPILER=clang, CXX_COMPILER=clang++, USE_SANITIZER=none ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, GENERATOR="Unix Makefiles" ] - <<: *windows_vs2017 - env: [ ARCH=x86, BUILD_TYPE=Debug, GENERATOR="Visual Studio 15 2017" ] + env: [ ARCH=x86, ASAN=none, BUILD_TYPE=Debug, GENERATOR="Visual Studio 15 2017" ] - <<: *windows_vs2017 - env: [ ARCH=x86_64, BUILD_TYPE=Debug, GENERATOR="Visual Studio 15 2017" ] + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, GENERATOR="Visual Studio 15 2017 Win64" ] - <<: *windows_vs2017 - env: [ ARCH=x86_64, BUILD_TYPE=Release, GENERATOR="Visual Studio 15 2017" ] - -# Conan will automatically determine the best compiler for a given platform -# based on educated guesses. The first check is based on the CC and CXX -# environment variables, the second (on Windows) is to check if Microsoft -# Visual Studio is installed. On Travis CC and CXX are set to gcc on Microsoft -# Windows targets as well, this has the undesired effect that MSVC is not -# detected, unsetting CC and CXX solves that problem. -before_install: - - if [ "${TRAVIS_OS_NAME}" = "windows" ]; then - eval "unset CC"; - eval "unset CXX"; - JAVA_HOME=$(find "/c/Program Files/Android/jdk/" -name "*openjdk*" | sort | head -n 1); - export JAVA_HOME; - export PATH="${PATH}:${JAVA_HOME}/bin"; - else - eval "export CC=${C_COMPILER}"; - eval "export CXX=${CXX_COMPILER}"; - fi - -# Windows targets in Travis are still very much in beta and Python is not yet -# available and installation of Python through Chocolaty does not work well. -# The real fix is to wait until Python and pip are both available on the -# target. Until then download Conan from the official website and simply add -# the extracted folder to the path. -install: - - if [ "${TRAVIS_OS_NAME}" = "windows" ]; then - choco install innoextract; - choco install maven --ignore-dependencies; - wget -q https://dl.bintray.com/conan/installers/conan-win-64_1_10_0.exe; - innoextract conan-win-64_1_10_0.exe; - eval "export PATH=\"$(pwd)/app/conan:${PATH}\""; - elif [ "${TRAVIS_OS_NAME}" = "osx" ]; then - eval "$(pyenv init -)"; - pyenv virtualenv conan; - pyenv rehash; - pyenv activate conan; - pip install conan --upgrade; - else - pip install conan --upgrade --user; - fi - - conan profile new default --detect + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, GENERATOR="Visual Studio 15 2017 Win64" ] before_script: + - conan profile new default --detect - conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan - - conan profile get settings.arch default - - if [ -z "${ARCH}" ]; then - eval "export ARCH=\"$(conan profile get settings.arch default)\""; - fi - - if [ "${TRAVIS_OS_NAME}" = "windows" ]; then - GENERATOR_ARCH=$(if [ "${ARCH}" = "x86_64" ]; then echo " Win64"; fi); - eval "export GENERATOR=\"${GENERATOR}${GENERATOR_ARCH}\""; - eval "export USE_SANITIZER=none"; - else - eval "export GENERATOR=\"Unix Makefiles\""; - fi - - export script: - mkdir build @@ -116,12 +162,12 @@ script: - conan install -b missing -s arch=${ARCH} -s build_type=${BUILD_TYPE} .. - cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=$(pwd)/install - -DUSE_SANITIZER=${USE_SANITIZER} + -DUSE_SANITIZER=${ASAN} -DBUILD_TESTING=on -G "${GENERATOR}" ../src - - cmake --build . --config ${BUILD_TYPE} --target install + - ${SCAN_BUILD} cmake --build . --config ${BUILD_TYPE} --target install - CYCLONEDDS_URI='all' ctest -T test -C ${BUILD_TYPE} - - if [ "${USE_SANITIZER}" != "none" ]; then + - if [ "${ASAN}" != "none" ]; then CMAKE_LINKER_FLAGS="-DCMAKE_LINKER_FLAGS=-fsanitize=${USE_SANITIZER}"; CMAKE_C_FLAGS="-DCMAKE_C_FLAGS=-fsanitize=${USE_SANITIZER}"; fi @@ -132,4 +178,8 @@ script: ${CMAKE_LINKER_FLAGS} -G "${GENERATOR}" .. - cmake --build . --config ${BUILD_TYPE} + - cd "${TRAVIS_BUILD_DIR}/build" + +#after_success: +# - *submit_to_coverity_scan From c2cf340a1b5742ddcc0c22bce0905a13c3a664f7 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 7 May 2019 14:09:26 +0800 Subject: [PATCH 068/178] various ddsperf fixes * As a simple matter of code hygiene, in particular to aid in checking for leaks, ddsperf should free all memory it allocates on exit. * Remove spurious mutex unlock in ddsperf * Removing a participant means removing one or two entries from the "pong writers" array ("pong wr"), and there it read 1 element beyond the end of the array while moving the remaining elements forward. * Constant-rate pinging was broken because of two reasons, one worse than the other: * setting the rate had a mismatch in variables (publication rate and command-line argument) resulting in a completely wrong ping interval; the code now has a bit more clear variable naming ... * the timing of the pings was relative to the current time, but the wakeup a little delayed, resulting in a lower rate than requested. It now simply adds the ping interval to the scheduled ping time, rather than the time at which the ping is being sent. To guard against really late wakeups, rates that are too high, suspending the machine, &c. it will in extremis delay the next ping. Signed-off-by: Erik Boasson --- src/tools/ddsperf/ddsperf.c | 85 +++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index 06f1970..d270095 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -123,7 +123,7 @@ static int32_t histdepth = 0; /* Publishing rate in Hz, HUGE_VAL means as fast as possible, 0 means no throughput data is published at all */ -static double rate; +static double pub_rate; /* Fraction of throughput data samples that double as a ping message */ @@ -138,6 +138,10 @@ static dds_ignorelocal_kind_t ignorelocal = DDS_IGNORELOCAL_PARTICIPANT; possible, DDS_INFINITY means never */ static dds_duration_t ping_intv; +/* Number of times a new ping was sent before all expected + pongs had been received */ +static uint32_t ping_timeouts = 0; + static ddsrt_mutex_t disc_lock; /* Publisher statistics and lock protecting it */ @@ -582,12 +586,12 @@ static uint32_t pubthread (void *varg) data.seq_keyval.keyval = (data.seq_keyval.keyval + 1) % (int32_t) nkeyvals; data.seq++; - if (rate < HUGE_VAL) + if (pub_rate < HUGE_VAL) { if (++bi == burstsize) { /* FIXME: should average rate over a short-ish period, rather than over the entire run */ - while (((double) (ntot / burstsize) / ((double) (t - tfirst0) / 1e9 + 5e-3)) > rate && !termflag) + while (((double) (ntot / burstsize) / ((double) (t - tfirst0) / 1e9 + 5e-3)) > pub_rate && !termflag) { /* FIXME: flushing manually because batching is not yet implemented properly */ dds_write_flush (wr_data); @@ -742,7 +746,6 @@ static dds_entity_t get_pong_writer_locked (dds_instance_handle_t pubhandle) if (pongwr[i].pubhandle == 0) { pongwr[i].pubhandle = pubhandle; - ddsrt_mutex_unlock (&pongwr_lock); return wr_pong; } else @@ -752,7 +755,6 @@ static dds_entity_t get_pong_writer_locked (dds_instance_handle_t pubhandle) pongwr[npongwr].pphandle = pphandle; pongwr[npongwr].wr_pong = wr_pong; npongwr++; - ddsrt_mutex_unlock (&pongwr_lock); return wr_pong; } } @@ -885,19 +887,32 @@ static void maybe_send_new_ping (dds_time_t tnow, dds_time_t *tnextping) } else { - if (tnow > twarn_ping_timeout) + if (n_pong_seen < n_pong_expected) { - printf ("[%"PRIdPID"] ping timed out ... sending new ping\n", ddsrt_getpid ()); - fflush (stdout); + ping_timeouts++; + if (tnow > twarn_ping_timeout) + { + printf ("[%"PRIdPID"] ping timed out (total %"PRIu32" times) ... sending new ping\n", ddsrt_getpid (), ping_timeouts); + twarn_ping_timeout = tnow + DDS_SECS (1); + fflush (stdout); + } } n_pong_seen = 0; - cur_ping_time = tnow; - if (ping_intv > 0) + if (ping_intv == 0) + { + *tnextping = tnow + DDS_SECS (1); + cur_ping_time = tnow; + } + else + { + /* tnow should be ~ cur_ping_time + ping_intv, but it won't be if the + wakeup was delayed significantly, the machine was suspended in the + meantime, so slow down if we can't keep up */ + cur_ping_time += ping_intv; + if (cur_ping_time < tnow - ping_intv / 2) + cur_ping_time = tnow; *tnextping = cur_ping_time + ping_intv; - else if (ping_intv == 0) - *tnextping = cur_ping_time + DDS_SECS (1); - if (ping_intv > 0 && *tnextping > twarn_ping_timeout) - twarn_ping_timeout = *tnextping + ping_intv / 2; + } cur_ping_seq++; baggage = init_sample (&data, cur_ping_seq); ddsrt_mutex_unlock (&pongwr_lock); @@ -1053,7 +1068,7 @@ static void delete_pong_writer (dds_instance_handle_t pphandle) else { assert (wr_pong == 0 || wr_pong == pongwr[i].wr_pong); - memmove (&pongwr[i], &pongwr[i+1], (npongwr - i) * sizeof (pongwr[0])); + memmove (&pongwr[i], &pongwr[i+1], (npongwr - i - 1) * sizeof (pongwr[0])); npongwr--; } } @@ -1062,6 +1077,13 @@ static void delete_pong_writer (dds_instance_handle_t pphandle) dds_delete (wr_pong); } +static void free_ppant (void *vpp) +{ + struct ppant *pp = vpp; + free (pp->hostname); + free (pp); +} + static void participant_data_listener (dds_entity_t rd, void *arg) { dds_sample_info_t info; @@ -1091,7 +1113,7 @@ static void participant_data_listener (dds_entity_t rd, void *arg) ddsrt_avl_delete_dpath (&ppants_td, &ppants, pp, &dpath); if (pp->tdeadline != DDS_NEVER) ddsrt_fibheap_delete (&ppants_to_match_fhd, &ppants_to_match, pp); - free (pp); + free_ppant (pp); } ddsrt_mutex_unlock (&disc_lock); } @@ -1288,7 +1310,7 @@ static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) const double ts = (double) (tnow - tstart) / 1e9; snprintf (prefix, sizeof (prefix), "[%"PRIdPID"] %.3f ", ddsrt_getpid (), ts); - if (rate > 0) + if (pub_rate > 0) { ddsrt_mutex_lock (&pubstat_lock); hist_print (prefix, pubstat_hist, tnow - tprev, 1); @@ -1519,15 +1541,15 @@ static void set_mode_ping (int *xoptind, int xargc, char * const xargv[]) while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1) { int pos; - double r; + double ping_rate; if (strcmp (xargv[*xoptind], "inf") == 0) { ping_intv = 0; } - else if (sscanf (xargv[*xoptind], "%lf%n", &r, &pos) == 1 && (xargv[*xoptind][pos] == 0 || strcmp (xargv[*xoptind] + pos, "Hz") == 0)) + else if (sscanf (xargv[*xoptind], "%lf%n", &ping_rate, &pos) == 1 && (xargv[*xoptind][pos] == 0 || strcmp (xargv[*xoptind] + pos, "Hz") == 0)) { - if (r == 0) ping_intv = DDS_INFINITY; - else if (r > 0) ping_intv = (dds_duration_t) (1e9 / rate + 0.5); + if (ping_rate == 0) ping_intv = DDS_INFINITY; + else if (ping_rate > 0) ping_intv = (dds_duration_t) (1e9 / ping_rate + 0.5); else error3 ("%s: invalid ping rate\n", xargv[*xoptind]); } else @@ -1566,7 +1588,7 @@ static void set_mode_sub (int *xoptind, int xargc, char * const xargv[]) static void set_mode_pub (int *xoptind, int xargc, char * const xargv[]) { - rate = HUGE_VAL; + pub_rate = HUGE_VAL; burstsize = 1; ping_frac = 0; while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1) @@ -1575,12 +1597,12 @@ static void set_mode_pub (int *xoptind, int xargc, char * const xargv[]) double r; if (strcmp (xargv[*xoptind], "inf") == 0 || strcmp (xargv[*xoptind], "infHz") == 0) { - rate = HUGE_VAL; + pub_rate = HUGE_VAL; } else if (sscanf (xargv[*xoptind], "%lf%n", &r, &pos) == 1 && (xargv[*xoptind][pos] == 0 || strcmp (xargv[*xoptind] + pos, "Hz") == 0)) { if (r < 0) error3 ("%s: invalid publish rate\n", xargv[*xoptind]); - rate = r; + pub_rate = r; } else if (strcmp (xargv[*xoptind], "burst") == 0) { @@ -1597,7 +1619,7 @@ static void set_mode_pub (int *xoptind, int xargc, char * const xargv[]) if (r < 0 || r > 100) error3 ("%s: ping fraction out of range\n", xargv[*xoptind]); ping_frac = (uint32_t) (UINT32_MAX * (r / 100.0) + 0.5); } - else if (strcmp (xargv[*xoptind], "ping") == 0 && *xoptind + 1 < xargc && sscanf (xargv[*xoptind + 1], "%lf%%%n", &rate, &pos) == 1 && xargv[*xoptind + 1][pos] == 0) + else if (strcmp (xargv[*xoptind], "ping") == 0 && *xoptind + 1 < xargc && sscanf (xargv[*xoptind + 1], "%lf%%%n", &pub_rate, &pos) == 1 && xargv[*xoptind + 1][pos] == 0) { ++(*xoptind); if (r < 0 || r > 100) error3 ("%s: ping fraction out of range\n", xargv[*xoptind]); @@ -1614,7 +1636,7 @@ static void set_mode_pub (int *xoptind, int xargc, char * const xargv[]) static void set_mode (int xoptind, int xargc, char * const xargv[]) { int code; - rate = 0.0; + pub_rate = 0.0; submode = SM_NONE; pingpongmode = SM_LISTENER; ping_intv = (xoptind == xargc) ? DDS_SECS (1) : DDS_INFINITY; @@ -1872,7 +1894,7 @@ int main (int argc, char *argv[]) memset (&subtid, 0, sizeof (subtid)); memset (&subpingtid, 0, sizeof (subpingtid)); memset (&subpongtid, 0, sizeof (subpongtid)); - if (rate > 0) + if (pub_rate > 0) ddsrt_thread_create (&pubtid, "pub", &attr, pubthread, NULL); if (subthread_func != 0) ddsrt_thread_create (&subtid, "sub", &attr, subthread_func, &subarg_data); @@ -2007,7 +2029,7 @@ int main (int argc, char *argv[]) } #endif - if (rate > 0) + if (pub_rate > 0) ddsrt_thread_join (pubtid, NULL); if (subthread_func != 0) ddsrt_thread_join (subtid, NULL); @@ -2054,6 +2076,10 @@ int main (int argc, char *argv[]) ddsrt_mutex_destroy (&pongstat_lock); ddsrt_mutex_destroy (&pubstat_lock); hist_free (pubstat_hist); + free (pongwr); + for (uint32_t i = 0; i < npongstat; i++) + free (pongstat[i].raw); + free (pongstat); bool ok = true; @@ -2068,6 +2094,9 @@ int main (int argc, char *argv[]) ok = false; } } + + ddsrt_avl_free (&ppants_td, &ppants, free_ppant); + if (matchcount < minmatch) { printf ("[%"PRIdPID"] error: too few matching participants (%"PRIu32" instead of %"PRIu32")\n", ddsrt_getpid (), matchcount, minmatch); From a6d92aac8c1010357ad63da5d5d3cee4bdffe4e2 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 7 May 2019 15:00:40 +0800 Subject: [PATCH 069/178] config input handling improvements This commit changes a few things in the config handling: * When reading the configuration from multiple sources, a source can now override settings already set by a preceding source for settings that are not lists. Previously, trying to change the value of a setting in a subsequence file would be considered an error, just like trying to set the value of a particular setting multiple times in a single configuration file. * A configuration fragment in CYCLONEDDS_URI now no longer requires the CycloneDDS top-level tag to be specified. If it is missing it will be assumed. This is only true for configuration fragments contained in CYCLONEDDS_URI, not for data read from a file. * A configuration fragment in CYCLONEDDS_URI no longer requires that all elements are properly closed: a missing close tag is treated as-if it is the end of the fragment and any elements are implicitly closed. Again this does not apply to files. * The configuration dump now lists explicitly which sources affected each setting, with a default value indicated by an empty set. The result of the latter two is that one can almost pretend that it is a sane format instead of XML. For example, if one would like to override tracing settings, one could just write: CYCLONEDDS_URI="$CYCLONEDDS_URI,finest" Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_config.h | 3 +- src/core/ddsi/src/q_config.c | 2370 ++++++++++----------- src/core/ddsi/src/q_init.c | 4 +- src/ddsrt/include/dds/ddsrt/xmlparser.h | 6 +- src/ddsrt/src/xmlparser.c | 24 +- 5 files changed, 1159 insertions(+), 1248 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index 08f3d6e..b0e160c 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -238,7 +238,7 @@ struct config char *tracingOutputFileName; int tracingTimestamps; int tracingAppendToFile; - unsigned allowMulticast; + uint32_t allowMulticast; enum transport_selector transport_selector; enum boolean_default compat_use_ipv6; enum boolean_default compat_tcp_enable; @@ -413,6 +413,7 @@ struct cfgst; struct cfgst *config_init (const char *configfile); void config_print_cfgst (struct cfgst *cfgst); +void config_free_source_info (struct cfgst *cfgst); void config_fini (struct cfgst *cfgst); #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index d12bc21..cde5e86 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -10,6 +10,7 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include +#include #include #include #include @@ -36,8 +37,6 @@ #include "dds/version.h" -#define WARN_DEPRECATED_ALIAS 1 -#define WARN_DEPRECATED_UNIT 1 #define MAX_PATH_DEPTH 10 /* max nesting level of configuration elements */ struct cfgelem; @@ -46,7 +45,7 @@ struct cfgst; typedef int(*init_fun_t) (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem); typedef int(*update_fun_t) (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value); typedef void(*free_fun_t) (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem); -typedef void(*print_fun_t) (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default); +typedef void(*print_fun_t) (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources); #ifdef DDSI_INCLUDE_SECURITY struct q_security_plugins q_security_plugin = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; @@ -74,14 +73,21 @@ struct cfgelem { struct cfgst_nodekey { const struct cfgelem *e; + void *p; }; struct cfgst_node { ddsrt_avl_node_t avlnode; struct cfgst_nodekey key; int count; + uint32_t sources; int failed; - int is_default; +}; + +enum implicit_toplevel { + ITL_DISALLOWED, + ITL_ALLOWED, + ITL_INSERTED }; struct cfgst { @@ -90,6 +96,11 @@ struct cfgst { /* error flag set so that we can continue parsing for some errors and still fail properly */ int error; + enum implicit_toplevel implicit_toplevel; + + /* current input, mask with 1 bit set */ + uint32_t source; + /* path_depth, isattr and path together control the formatting of error messages by cfg_error() */ int path_depth; @@ -98,22 +109,6 @@ struct cfgst { void *parent[MAX_PATH_DEPTH]; }; -/* "trace" is special: it enables (nearly) everything */ -static const char *logcat_names[] = { - "fatal", "error", "warning", "info", "config", "discovery", "data", "radmin", "timing", "traffic", "topic", "tcp", "plist", "whc", "throttle", "rhc", "trace", NULL -}; -static const uint32_t logcat_codes[] = { - DDS_LC_FATAL, DDS_LC_ERROR, DDS_LC_WARNING, DDS_LC_INFO, DDS_LC_CONFIG, DDS_LC_DISCOVERY, DDS_LC_DATA, DDS_LC_RADMIN, DDS_LC_TIMING, DDS_LC_TRAFFIC, DDS_LC_TOPIC, DDS_LC_TCP, DDS_LC_PLIST, DDS_LC_WHC, DDS_LC_THROTTLE, DDS_LC_RHC, DDS_LC_ALL -}; - -/* "trace" is special: it enables (nearly) everything */ -static const char *xcheck_names[] = { - "whc", "rhc", "all", NULL -}; -static const uint32_t xcheck_codes[] = { - DDS_XCHECK_WHC, DDS_XCHECK_RHC, ~(uint32_t)0 -}; - /* We want the tracing/verbosity settings to be fixed while parsing the configuration, so we update this variable instead. */ static uint32_t enabled_logcats; @@ -123,7 +118,7 @@ static const ddsrt_avl_treedef_t cfgst_found_treedef = DDSRT_AVL_TREEDEF_INITIALIZER(offsetof(struct cfgst_node, avlnode), offsetof(struct cfgst_node, key), cfgst_node_cmp, 0); #define DU(fname) static int uf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) -#define PF(fname) static void pf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) +#define PF(fname) static void pf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) #define DUPF(fname) DU(fname) ; PF(fname) PF(nop); DUPF(networkAddress); @@ -310,7 +305,7 @@ static const struct cfgelem networkpartition_cfgattrs[] = { }; static const struct cfgelem networkpartitions_cfgelems[] = { - { LEAF_W_ATTRS("NetworkPartition", networkpartition_cfgattrs), 0, 0, ABSOFF(networkPartitions), if_network_partition, 0, 0, 0, + { LEAF_W_ATTRS("NetworkPartition", networkpartition_cfgattrs), 2, 0, ABSOFF(networkPartitions), if_network_partition, 0, 0, 0, BLURB("

      This element defines a DDSI2E network partition.

      ") }, END_MARKER }; @@ -909,7 +904,11 @@ static const struct unit unittab_bandwidth_Bps[] = { }; #endif -static void cfgst_push(struct cfgst *cfgst, int isattr, const struct cfgelem *elem, void *parent) +static void free_configured_elements (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem); +static void free_configured_element (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem); +static const struct cfgelem *lookup_element (const char *target); + +static void cfgst_push (struct cfgst *cfgst, int isattr, const struct cfgelem *elem, void *parent) { assert(cfgst->path_depth < MAX_PATH_DEPTH); assert(isattr == 0 || isattr == 1); @@ -919,19 +918,19 @@ static void cfgst_push(struct cfgst *cfgst, int isattr, const struct cfgelem *el cfgst->path_depth++; } -static void cfgst_pop(struct cfgst *cfgst) +static void cfgst_pop (struct cfgst *cfgst) { assert(cfgst->path_depth > 0); cfgst->path_depth--; } -static const struct cfgelem *cfgst_tos(const struct cfgst *cfgst) +static const struct cfgelem *cfgst_tos (const struct cfgst *cfgst) { assert(cfgst->path_depth > 0); return cfgst->path[cfgst->path_depth - 1]; } -static void *cfgst_parent(const struct cfgst *cfgst) +static void *cfgst_parent (const struct cfgst *cfgst) { assert(cfgst->path_depth > 0); return cfgst->parent[cfgst->path_depth - 1]; @@ -943,46 +942,47 @@ struct cfg_note_buf { char *buf; }; -static size_t cfg_note_vsnprintf(struct cfg_note_buf *bb, const char *fmt, va_list ap) +static size_t cfg_note_vsnprintf (struct cfg_note_buf *bb, const char *fmt, va_list ap) { int x; x = vsnprintf(bb->buf + bb->bufpos, bb->bufsize - bb->bufpos, fmt, ap); - if ( x >= 0 && (size_t) x >= bb->bufsize - bb->bufpos ) { + if (x >= 0 && (size_t) x >= bb->bufsize - bb->bufpos) + { size_t nbufsize = ((bb->bufsize + (size_t) x + 1) + 1023) & (size_t) (-1024); - char *nbuf = ddsrt_realloc(bb->buf, nbufsize); + char *nbuf = ddsrt_realloc (bb->buf, nbufsize); bb->buf = nbuf; bb->bufsize = nbufsize; return nbufsize; } - if ( x < 0 ) + if (x < 0) DDS_FATAL("cfg_note_vsnprintf: vsnprintf failed\n"); else bb->bufpos += (size_t) x; return 0; } -static void cfg_note_snprintf(struct cfg_note_buf *bb, const char *fmt, ...) +static void cfg_note_snprintf (struct cfg_note_buf *bb, const char *fmt, ...) { /* The reason the 2nd call to os_vsnprintf is here and not inside cfg_note_vsnprintf is because I somehow doubt that all platforms implement va_copy() */ va_list ap; size_t r; - va_start(ap, fmt); - r = cfg_note_vsnprintf(bb, fmt, ap); - va_end(ap); - if ( r > 0 ) { + va_start (ap, fmt); + r = cfg_note_vsnprintf (bb, fmt, ap); + va_end (ap); + if (r > 0) { int s; - va_start(ap, fmt); - s = vsnprintf(bb->buf + bb->bufpos, bb->bufsize - bb->bufpos, fmt, ap); - if ( s < 0 || (size_t) s >= bb->bufsize - bb->bufpos ) - DDS_FATAL("cfg_note_snprintf: vsnprintf failed\n"); - va_end(ap); + va_start (ap, fmt); + s = vsnprintf (bb->buf + bb->bufpos, bb->bufsize - bb->bufpos, fmt, ap); + if (s < 0 || (size_t) s >= bb->bufsize - bb->bufpos) + DDS_FATAL ("cfg_note_snprintf: vsnprintf failed\n"); + va_end (ap); bb->bufpos += (size_t) s; } } -static size_t cfg_note(struct cfgst *cfgst, uint32_t cat, size_t bsz, const char *fmt, va_list ap) +static size_t cfg_note (struct cfgst *cfgst, uint32_t cat, size_t bsz, const char *fmt, const char *suffix, va_list ap) { /* Have to snprintf our way to a single string so we can OS_REPORT as well as nn_log. Otherwise configuration errors will be lost @@ -993,177 +993,196 @@ static size_t cfg_note(struct cfgst *cfgst, uint32_t cat, size_t bsz, const char int i, sidx; size_t r; - if (cat & DDS_LC_ERROR) { + if (cat & DDS_LC_ERROR) cfgst->error = 1; - } bb.bufpos = 0; bb.bufsize = (bsz == 0) ? 1024 : bsz; - if ( (bb.buf = ddsrt_malloc(bb.bufsize)) == NULL ) - DDS_FATAL("cfg_note: out of memory\n"); + if ((bb.buf = ddsrt_malloc(bb.bufsize)) == NULL) + DDS_FATAL ("cfg_note: out of memory\n"); - cfg_note_snprintf(&bb, "config: "); + cfg_note_snprintf (&bb, "config: "); /* Path to element/attribute causing the error. Have to stop once an attribute is reached: a NULL marker may have been pushed onto the stack afterward in the default handling. */ sidx = 0; - while ( sidx < cfgst->path_depth && cfgst->path[sidx]->name == NULL ) + while (sidx < cfgst->path_depth && cfgst->path[sidx]->name == NULL) sidx++; const struct cfgelem *prev_path = NULL; - for ( i = sidx; i < cfgst->path_depth && (i == sidx || !cfgst->isattr[i - 1]); i++ ) { - if ( cfgst->path[i] == NULL ) { + for (i = sidx; i < cfgst->path_depth && (i == sidx || !cfgst->isattr[i - 1]); i++) + { + if (cfgst->path[i] == NULL) + { assert(i > sidx); - cfg_note_snprintf(&bb, "/#text"); - } else if ( cfgst->isattr[i] ) { - cfg_note_snprintf(&bb, "[@%s]", cfgst->path[i]->name); - } else if (cfgst->path[i] == prev_path) { + cfg_note_snprintf (&bb, "/#text"); + } + else if (cfgst->isattr[i]) + { + cfg_note_snprintf (&bb, "[@%s]", cfgst->path[i]->name); + } + else if (cfgst->path[i] == prev_path) + { /* skip printing this level: it means a group contained an element indicating that it was moved to the first group (i.e., stripping a level) -- this is currently only used for stripping out the DDSI2E level, and the sole purpose of this special case is making any warnings from elements contained within it look reasonable by always printing the new location */ - } else { + } + else + { /* first character is '>' means it was moved, so print what follows instead */ const char *name = cfgst->path[i]->name + ((cfgst->path[i]->name[0] == '>') ? 1 : 0); - const char *p = strchr(name, '|'); + const char *p = strchr (name, '|'); int n = p ? (int) (p - name) : (int) strlen(name); - cfg_note_snprintf(&bb, "%s%*.*s", (i == sidx) ? "" : "/", n, n, name); + cfg_note_snprintf (&bb, "%s%*.*s", (i == sidx) ? "" : "/", n, n, name); } prev_path = cfgst->path[i]; } - cfg_note_snprintf(&bb, ": "); - if ( (r = cfg_note_vsnprintf(&bb, fmt, ap)) > 0 ) { + cfg_note_snprintf (&bb, ": "); + if ((r = cfg_note_vsnprintf (&bb, fmt, ap)) > 0) + { /* Can't reset ap ... and va_copy isn't widely available - so instead abort and hope the caller tries again with a larger initial buffer */ - ddsrt_free(bb.buf); + ddsrt_free (bb.buf); return r; } - switch ( cat ) { + cfg_note_snprintf (&bb, "%s", suffix); + switch (cat) + { case DDS_LC_CONFIG: - DDS_LOG(cat, "%s\n", bb.buf); + DDS_LOG (cat, "%s\n", bb.buf); break; case DDS_LC_WARNING: - DDS_WARNING("%s\n", bb.buf); + DDS_WARNING ("%s\n", bb.buf); break; case DDS_LC_ERROR: - DDS_ERROR("%s\n", bb.buf); + DDS_ERROR ("%s\n", bb.buf); break; default: - DDS_FATAL("cfg_note unhandled category %u for message %s\n", (unsigned) cat, bb.buf); + DDS_FATAL ("cfg_note unhandled category %u for message %s\n", (unsigned) cat, bb.buf); break; } - ddsrt_free(bb.buf); + ddsrt_free (bb.buf); return 0; } -#if WARN_DEPRECATED_ALIAS || WARN_DEPRECATED_UNIT -static void cfg_warning(struct cfgst *cfgst, const char *fmt, ...) +static void cfg_warning (struct cfgst *cfgst, const char *fmt, ...) { va_list ap; size_t bsz = 0; do { - va_start(ap, fmt); - bsz = cfg_note(cfgst, DDS_LC_WARNING, bsz, fmt, ap); - va_end(ap); - } while ( bsz > 0 ); + va_start (ap, fmt); + bsz = cfg_note (cfgst, DDS_LC_WARNING, bsz, fmt, "", ap); + va_end (ap); + } while (bsz > 0); } -#endif -static int cfg_error(struct cfgst *cfgst, const char *fmt, ...) +static int cfg_error (struct cfgst *cfgst, const char *fmt, ...) { va_list ap; size_t bsz = 0; do { - va_start(ap, fmt); - bsz = cfg_note(cfgst, DDS_LC_ERROR, bsz, fmt, ap); - va_end(ap); - } while ( bsz > 0 ); + va_start (ap, fmt); + bsz = cfg_note (cfgst, DDS_LC_ERROR, bsz, fmt, "", ap); + va_end (ap); + } while (bsz > 0); return 0; } -static int cfg_log(struct cfgst *cfgst, const char *fmt, ...) +static int cfg_logelem (struct cfgst *cfgst, uint32_t sources, const char *fmt, ...) { + /* 89 = 1 + 2 + 31 + 1 + 10 + 2*22: the number of characters in + a string formed by concatenating all numbers from 0 .. 31 in decimal notation, + 31 separators, a opening and closing brace pair, a terminating 0, and a leading + space */ + char srcinfo[89]; va_list ap; size_t bsz = 0; + srcinfo[0] = ' '; + srcinfo[1] = '{'; + int pos = 2; + for (uint32_t i = 0, m = 1; i < 32; i++, m <<= 1) + if (sources & m) + pos += snprintf (srcinfo + pos, sizeof (srcinfo) - (size_t) pos, "%s%"PRIu32, (pos == 2) ? "" : ",", i); + srcinfo[pos] = '}'; + srcinfo[pos + 1] = 0; + assert ((size_t) pos <= sizeof (srcinfo) - 2); do { - va_start(ap, fmt); - bsz = cfg_note(cfgst, DDS_LC_CONFIG, bsz, fmt, ap); - va_end(ap); - } while ( bsz > 0 ); + va_start (ap, fmt); + bsz = cfg_note (cfgst, DDS_LC_CONFIG, bsz, fmt, srcinfo, ap); + va_end (ap); + } while (bsz > 0); return 0; } -static int list_index(const char *list[], const char *elem) +static int list_index (const char *list[], const char *elem) { - int i; - for ( i = 0; list[i] != NULL; i++ ) { - if ( ddsrt_strcasecmp(list[i], elem) == 0 ) + for (int i = 0; list[i] != NULL; i++) + if (ddsrt_strcasecmp (list[i], elem) == 0) return i; - } return -1; } -static int64_t lookup_multiplier(struct cfgst *cfgst, const struct unit *unittab, const char *value, int unit_pos, int value_is_zero, int64_t def_mult, int err_on_unrecognised) +static int64_t lookup_multiplier (struct cfgst *cfgst, const struct unit *unittab, const char *value, int unit_pos, int value_is_zero, int64_t def_mult, int err_on_unrecognised) { - assert(0 <= unit_pos && (size_t) unit_pos <= strlen(value)); - while ( value[unit_pos] == ' ' ) + assert (0 <= unit_pos && (size_t) unit_pos <= strlen(value)); + while (value[unit_pos] == ' ') unit_pos++; - if ( value[unit_pos] == 0 ) { - if ( value_is_zero ) { + if (value[unit_pos] == 0) + { + if (value_is_zero) { /* No matter what unit, 0 remains just that. For convenience, always allow 0 to be specified without a unit */ return 1; - } else if ( def_mult == 0 && err_on_unrecognised ) { - cfg_error(cfgst, "%s: unit is required", value); + } else if (def_mult == 0 && err_on_unrecognised) { + cfg_error (cfgst, "%s: unit is required", value); return 0; } else { -#if WARN_DEPRECATED_UNIT - cfg_warning(cfgst, "%s: use of default unit is deprecated", value); -#endif + cfg_warning (cfgst, "%s: use of default unit is deprecated", value); return def_mult; } - } else { - int i; - for ( i = 0; unittab[i].name != NULL; i++ ) { - if ( strcmp(unittab[i].name, value + unit_pos) == 0 ) + } + else + { + for (int i = 0; unittab[i].name != NULL; i++) + if (strcmp(unittab[i].name, value + unit_pos) == 0) return unittab[i].multiplier; - } - if ( err_on_unrecognised ) + if (err_on_unrecognised) cfg_error(cfgst, "%s: unrecognised unit", value + unit_pos); return 0; } } -static void *cfg_address(UNUSED_ARG(struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem) +static void *cfg_address (UNUSED_ARG (struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem) { - assert(cfgelem->multiplicity == 1); + assert (cfgelem->multiplicity == 1); return (char *) parent + cfgelem->elem_offset; } -static void *cfg_deref_address(UNUSED_ARG(struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem) +static void *cfg_deref_address (UNUSED_ARG (struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem) { - assert(cfgelem->multiplicity != 1); + assert (cfgelem->multiplicity != 1); return *((void **) ((char *) parent + cfgelem->elem_offset)); } -static void *if_common(UNUSED_ARG(struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem, unsigned size) +static void *if_common (UNUSED_ARG (struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem, unsigned size) { struct config_listelem **current = (struct config_listelem **) ((char *) parent + cfgelem->elem_offset); - struct config_listelem *new = ddsrt_malloc(size); + struct config_listelem *new = ddsrt_malloc (size); new->next = *current; *current = new; return new; } -static int if_thread_properties(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) +static int if_thread_properties (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - struct config_thread_properties_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(*new)); - if ( new == NULL ) + struct config_thread_properties_listelem *new = if_common (cfgst, parent, cfgelem, sizeof(*new)); + if (new == NULL) return -1; new->name = NULL; return 0; @@ -1172,8 +1191,8 @@ static int if_thread_properties(struct cfgst *cfgst, void *parent, struct cfgele #ifdef DDSI_INCLUDE_NETWORK_CHANNELS static int if_channel(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - struct config_channel_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(*new)); - if ( new == NULL ) + struct config_channel_listelem *new = if_common (cfgst, parent, cfgelem, sizeof(*new)); + if (new == NULL) return -1; new->name = NULL; new->channel_reader_ts = NULL; @@ -1186,19 +1205,19 @@ static int if_channel(struct cfgst *cfgst, void *parent, struct cfgelem const * #endif /* DDSI_INCLUDE_NETWORK_CHANNELS */ #ifdef DDSI_INCLUDE_ENCRYPTION -static int if_security_profile(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) +static int if_security_profile (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - if ( if_common(cfgst, parent, cfgelem, sizeof(struct config_securityprofile_listelem)) == NULL ) + if (if_common (cfgst, parent, cfgelem, sizeof (struct config_securityprofile_listelem)) == NULL) return -1; return 0; } #endif /* DDSI_INCLUDE_ENCRYPTION */ #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS -static int if_network_partition(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) +static int if_network_partition (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - struct config_networkpartition_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(*new)); - if ( new == NULL ) + struct config_networkpartition_listelem *new = if_common (cfgst, parent, cfgelem, sizeof(*new)); + if (new == NULL) return -1; new->address_string = NULL; #ifdef DDSI_INCLUDE_ENCRYPTION @@ -1208,214 +1227,114 @@ static int if_network_partition(struct cfgst *cfgst, void *parent, struct cfgele return 0; } -static int if_ignored_partition(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) +static int if_ignored_partition (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - if ( if_common(cfgst, parent, cfgelem, sizeof(struct config_ignoredpartition_listelem)) == NULL ) + if (if_common (cfgst, parent, cfgelem, sizeof (struct config_ignoredpartition_listelem)) == NULL) return -1; return 0; } -static int if_partition_mapping(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) +static int if_partition_mapping (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - if ( if_common(cfgst, parent, cfgelem, sizeof(struct config_partitionmapping_listelem)) == NULL ) + if (if_common (cfgst, parent, cfgelem, sizeof (struct config_partitionmapping_listelem)) == NULL) return -1; return 0; } #endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */ -static int if_peer(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) +static int if_peer (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - struct config_peer_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(struct config_peer_listelem)); - if ( new == NULL ) + struct config_peer_listelem *new = if_common (cfgst, parent, cfgelem, sizeof (struct config_peer_listelem)); + if (new == NULL) return -1; new->peer = NULL; return 0; } -static void ff_free(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) +static void ff_free (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - void **elem = cfg_address(cfgst, parent, cfgelem); - ddsrt_free(*elem); + void ** const elem = cfg_address (cfgst, parent, cfgelem); + ddsrt_free (*elem); } -static int uf_boolean(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) +static void pf_nop (UNUSED_ARG (struct cfgst *cfgst), UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (uint32_t sources)) { - static const char *vs[] = { "false", "true", NULL }; - int *elem = cfg_address(cfgst, parent, cfgelem); - int idx = list_index(vs, value); - if ( idx < 0 ) - return cfg_error(cfgst, "'%s': undefined value", value); - else { - *elem = idx; - return 1; - } } -static int uf_boolean_default (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) +static int do_uint32_bitset (struct cfgst *cfgst, uint32_t *cats, const char **names, const uint32_t *codes, const char *value) { - static const char *vs[] = { "default", "false", "true", NULL }; - static const enum boolean_default ms[] = { - BOOLDEF_DEFAULT, BOOLDEF_FALSE, BOOLDEF_TRUE, 0, - }; - enum boolean_default *elem = cfg_address (cfgst, parent, cfgelem); - int idx = list_index (vs, value); - assert (sizeof (vs) / sizeof (*vs) == sizeof (ms) / sizeof (*ms)); - if (idx < 0) - return cfg_error (cfgst, "'%s': undefined value", value); - *elem = ms[idx]; - return 1; -} - -#if 0 -static void pf_boolean_default (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - enum besmode *p = cfg_address (cfgst, parent, cfgelem); - const char *str = "INVALID"; - switch (*p) + char *copy = ddsrt_strdup (value), *cursor = copy, *tok; + while ((tok = ddsrt_strsep (&cursor, ",")) != NULL) { - case BOOLDEF_DEFAULT: str = "default"; break; - case BOOLDEF_FALSE: str = "false"; break; - case BOOLDEF_TRUE: str = "true"; break; - } - cfg_log (cfgst, "%s%s", str, is_default ? " [def]" : ""); -} -#endif - -static int do_uint32_bitset(struct cfgst *cfgst, uint32_t *cats, const char **names, const uint32_t *codes, const char *value) -{ - char *copy = ddsrt_strdup(value), *cursor = copy, *tok; - while ( (tok = ddsrt_strsep(&cursor, ",")) != NULL ) { - int idx = list_index(names, tok); - if ( idx < 0 ) { - int ret = cfg_error(cfgst, "'%s' in '%s' undefined", tok, value); - ddsrt_free(copy); + const int idx = list_index (names, tok); + if (idx < 0) + { + const int ret = cfg_error (cfgst, "'%s' in '%s' undefined", tok, value); + ddsrt_free (copy); return ret; } *cats |= codes[idx]; } - ddsrt_free(copy); + ddsrt_free (copy); return 1; } -static int uf_logcat(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) +static unsigned uint32_popcnt (uint32_t x) { - return do_uint32_bitset (cfgst, &enabled_logcats, logcat_names, logcat_codes, value); -} - -static int uf_xcheck(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - uint32_t *elem = cfg_address(cfgst, parent, cfgelem); - return do_uint32_bitset (cfgst, elem, xcheck_names, xcheck_codes, value); -} - -static int uf_verbosity(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) -{ - static const char *vs[] = { - "finest", "finer", "fine", "config", "info", "warning", "severe", "none", NULL - }; - static const uint32_t lc[] = { - DDS_LC_ALL, DDS_LC_TRAFFIC | DDS_LC_TIMING, DDS_LC_DISCOVERY | DDS_LC_THROTTLE, DDS_LC_CONFIG, DDS_LC_INFO, DDS_LC_WARNING, DDS_LC_ERROR | DDS_LC_FATAL, 0, 0 - }; - int idx = list_index(vs, value); - assert(sizeof(vs) / sizeof(*vs) == sizeof(lc) / sizeof(*lc)); - if ( idx < 0 ) - return cfg_error(cfgst, "'%s': undefined value", value); - else { - int i; - for ( i = (int) (sizeof(vs) / sizeof(*vs)) - 1; i >= idx; i-- ) - enabled_logcats |= lc[i]; - return 1; + unsigned n = 0; + while (x != 0) + { + n += ((x & 1u) != 0); + x >>= 1; } + return n; } -static int uf_besmode(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) +static void do_print_uint32_bitset (struct cfgst *cfgst, uint32_t mask, size_t ncodes, const char **names, const uint32_t *codes, uint32_t sources, const char *suffix) { - static const char *vs[] = { - "full", "writers", "minimal", NULL - }; - static const enum besmode ms[] = { - BESMODE_FULL, BESMODE_WRITERS, BESMODE_MINIMAL, 0, - }; - int idx = list_index(vs, value); - enum besmode *elem = cfg_address(cfgst, parent, cfgelem); - assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms)); - if ( idx < 0 ) - return cfg_error(cfgst, "'%s': undefined value", value); - *elem = ms[idx]; - return 1; -} - -static void pf_besmode(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - enum besmode *p = cfg_address(cfgst, parent, cfgelem); - const char *str = "INVALID"; - switch ( *p ) { - case BESMODE_FULL: str = "full"; break; - case BESMODE_WRITERS: str = "writers"; break; - case BESMODE_MINIMAL: str = "minimal"; break; + char res[256] = "", *resp = res; + const char *prefix = ""; +#ifndef NDEBUG + { + size_t max = 0; + for (size_t i = 0; i < ncodes; i++) + max += 1 + strlen (names[i]); + max += 11; /* ,0x%x */ + max += 1; /* \0 */ + assert (max <= sizeof (res)); } - cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); -} - -#ifdef DDSI_INCLUDE_SSL -static int uf_min_tls_version(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) -{ - static const char *vs[] = { - "1.2", "1.3", NULL - }; - static const struct ssl_min_version ms[] = { - {1,2}, {1,3}, {0,0} - }; - int idx = list_index(vs, value); - struct ssl_min_version *elem = cfg_address(cfgst, parent, cfgelem); - assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms)); - if ( idx < 0 ) - return cfg_error(cfgst, "'%s': undefined value", value); - *elem = ms[idx]; - return 1; -} - -static void pf_min_tls_version(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - struct ssl_min_version *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%d.%d%s", p->major, p->minor, is_default ? " [def]" : ""); -} #endif - -static int uf_retransmit_merging(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) -{ - static const char *vs[] = { - "never", "adaptive", "always", NULL - }; - static const enum retransmit_merging ms[] = { - REXMIT_MERGE_NEVER, REXMIT_MERGE_ADAPTIVE, REXMIT_MERGE_ALWAYS, 0, - }; - int idx = list_index(vs, value); - enum retransmit_merging *elem = cfg_address(cfgst, parent, cfgelem); - assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms)); - if ( idx < 0 ) - return cfg_error(cfgst, "'%s': undefined value", value); - *elem = ms[idx]; - return 1; -} - -static void pf_retransmit_merging(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - enum retransmit_merging *p = cfg_address(cfgst, parent, cfgelem); - const char *str = "INVALID"; - switch ( *p ) { - case REXMIT_MERGE_NEVER: str = "never"; break; - case REXMIT_MERGE_ADAPTIVE: str = "adaptive"; break; - case REXMIT_MERGE_ALWAYS: str = "always"; break; + while (mask) + { + size_t i_best = 0; + unsigned pc_best = 0; + for (size_t i = 0; i < ncodes; i++) + { + uint32_t m = mask & codes[i]; + if (m == codes[i]) + { + unsigned pc = uint32_popcnt (m); + if (pc > pc_best) + { + i_best = i; + pc_best = pc; + } + } + } + if (pc_best != 0) + { + resp += snprintf (resp, 256, "%s%s", prefix, names[i_best]); + mask &= ~codes[i_best]; + prefix = ","; + } + else + { + resp += snprintf (resp, 256, "%s0x%x", prefix, (unsigned) mask); + mask = 0; + } } - cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); -} - -static int uf_string(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - char **elem = cfg_address(cfgst, parent, cfgelem); - *elem = ddsrt_strdup(value); - return 1; + assert (resp <= res + sizeof (res)); + cfg_logelem (cfgst, sources, "%s%s", res, suffix); } DDSRT_WARNING_MSVC_OFF(4996); @@ -1427,145 +1346,366 @@ static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *valu int64_t mult; /* try convert as integer + optional unit; if that fails, try floating point + optional unit (round, not truncate, to integer) */ - if ( *value == 0 ) { + if (*value == 0) { *elem = 0; /* some static analyzers don't "get it" */ return cfg_error(cfgst, "%s: empty string is not a valid value", value); - } else if ( sscanf(value, "%lld%n", (long long int *) &v_int, &pos) == 1 && (mult = lookup_multiplier(cfgst, unittab, value, pos, v_int == 0, def_mult, 0)) != 0 ) { + } else if (sscanf (value, "%lld%n", (long long int *) &v_int, &pos) == 1 && (mult = lookup_multiplier (cfgst, unittab, value, pos, v_int == 0, def_mult, 0)) != 0) { assert(mult > 0); - if ( v_int < 0 || v_int > max / mult || mult * v_int < min) - return cfg_error(cfgst, "%s: value out of range", value); + if (v_int < 0 || v_int > max / mult || mult * v_int < min) + return cfg_error (cfgst, "%s: value out of range", value); *elem = mult * v_int; return 1; - } else if ( sscanf(value, "%lf%n", &v_dbl, &pos) == 1 && (mult = lookup_multiplier(cfgst, unittab, value, pos, v_dbl == 0, def_mult, 1)) != 0 ) { + } else if (sscanf(value, "%lf%n", &v_dbl, &pos) == 1 && (mult = lookup_multiplier (cfgst, unittab, value, pos, v_dbl == 0, def_mult, 1)) != 0) { double dmult = (double) mult; - assert(dmult > 0); - if ( (int64_t) (v_dbl * dmult + 0.5) < min || (int64_t) (v_dbl * dmult + 0.5) > max ) + assert (dmult > 0); + if ((int64_t) (v_dbl * dmult + 0.5) < min || (int64_t) (v_dbl * dmult + 0.5) > max) return cfg_error(cfgst, "%s: value out of range", value); *elem = (int64_t) (v_dbl * dmult + 0.5); return 1; } else { *elem = 0; /* some static analyzers don't "get it" */ - return cfg_error(cfgst, "%s: invalid value", value); + return cfg_error (cfgst, "%s: invalid value", value); } } DDSRT_WARNING_MSVC_ON(4996); +static void pf_int64_unit (struct cfgst *cfgst, int64_t value, uint32_t sources, const struct unit *unittab, const char *zero_unit) +{ + if (value == 0) { + /* 0s is a bit of a special case: we don't want to print 0hr (or + whatever unit will have the greatest multiplier), so hard-code + as 0s */ + cfg_logelem (cfgst, sources, "0 %s", zero_unit); + } else { + int64_t m = 0; + const char *unit = NULL; + int i; + for (i = 0; unittab[i].name != NULL; i++) + { + if (unittab[i].multiplier > m && (value % unittab[i].multiplier) == 0) + { + m = unittab[i].multiplier; + unit = unittab[i].name; + } + } + assert (m > 0); + assert (unit != NULL); + cfg_logelem (cfgst, sources, "%lld %s", value / m, unit); + } +} + +#define GENERIC_ENUM_CTYPE_UF(type_, c_type_) \ + struct en_##type_##_vs_ms_check { \ + char length_eq[(sizeof (en_##type_##_vs) / sizeof (*en_##type_##_vs) == \ + sizeof (en_##type_##_ms) / sizeof (*en_##type_##_ms)) ? 1 : -1]; \ + }; \ + \ + static int uf_##type_ (struct cfgst *cfgst, void *parent, UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value) \ + { \ + const int idx = list_index (en_##type_##_vs, value); \ + c_type_ * const elem = cfg_address (cfgst, parent, cfgelem); \ + /* idx >= length of ms check is to shut up clang's static analyzer */ \ + if (idx < 0 || idx >= (int) (sizeof (en_##type_##_ms) / sizeof (en_##type_##_ms[0]))) \ + return cfg_error (cfgst, "'%s': undefined value", value); \ + *elem = en_##type_##_ms[idx]; \ + return 1; \ + } +#define GENERIC_ENUM_CTYPE_PF(type_, c_type_) \ + static void pf_##type_ (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) \ + { \ + c_type_ const * const p = cfg_address (cfgst, parent, cfgelem); \ + const char *str = "INVALID"; \ + /* i < length of ms check is to shut up clang's static analyzer */ \ + for (int i = 0; en_##type_##_vs[i] != NULL && i < (int) (sizeof (en_##type_##_ms) / sizeof (en_##type_##_ms[0])); i++) { \ + if (en_##type_##_ms[i] == *p) \ + { \ + str = en_##type_##_vs[i]; \ + break; \ + } \ + } \ + cfg_logelem(cfgst, sources, "%s", str); \ + } +#define GENERIC_ENUM_CTYPE(type_, c_type_) \ + GENERIC_ENUM_CTYPE_UF(type_, c_type_) \ + GENERIC_ENUM_CTYPE_PF(type_, c_type_) +#define GENERIC_ENUM_UF(type_) GENERIC_ENUM_CTYPE_UF(type_, enum type_) +#define GENERIC_ENUM(type_) GENERIC_ENUM_CTYPE(type_, enum type_) + +static const char *en_boolean_vs[] = { "false", "true", NULL }; +static const int en_boolean_ms[] = { 0, 1, 0 }; +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) + +static const char *en_besmode_vs[] = { "full", "writers", "minimal", NULL }; +static const enum besmode en_besmode_ms[] = { BESMODE_FULL, BESMODE_WRITERS, BESMODE_MINIMAL, 0 }; +GENERIC_ENUM (besmode) + +static const char *en_retransmit_merging_vs[] = { "never", "adaptive", "always", NULL }; +static const enum retransmit_merging en_retransmit_merging_ms[] = { REXMIT_MERGE_NEVER, REXMIT_MERGE_ADAPTIVE, REXMIT_MERGE_ALWAYS, 0 }; +GENERIC_ENUM (retransmit_merging) + +static const char *en_sched_class_vs[] = { "realtime", "timeshare", "default", NULL }; +static const ddsrt_sched_t en_sched_class_ms[] = { DDSRT_SCHED_REALTIME, DDSRT_SCHED_TIMESHARE, DDSRT_SCHED_DEFAULT, 0 }; +GENERIC_ENUM_CTYPE (sched_class, ddsrt_sched_t) + +static const char *en_transport_selector_vs[] = { "default", "udp", "udp6", "tcp", "tcp6", "raweth", NULL }; +static const enum transport_selector en_transport_selector_ms[] = { TRANS_DEFAULT, TRANS_UDP, TRANS_UDP6, TRANS_TCP, TRANS_TCP6, TRANS_RAWETH, 0 }; +GENERIC_ENUM (transport_selector) + +/* by putting the "true" and "false" aliases at the end, they won't come out of the + generic printing function */ +static const char *en_many_sockets_mode_vs[] = { "single", "none", "many", "false", "true", NULL }; +static const enum many_sockets_mode en_many_sockets_mode_ms[] = { + MSM_SINGLE_UNICAST, MSM_NO_UNICAST, MSM_MANY_UNICAST, MSM_SINGLE_UNICAST, MSM_MANY_UNICAST, 0 }; +GENERIC_ENUM (many_sockets_mode) + +static const char *en_standards_conformance_vs[] = { "pedantic", "strict", "lax", NULL }; +static const enum nn_standards_conformance en_standards_conformance_ms[] = { NN_SC_PEDANTIC, NN_SC_STRICT, NN_SC_LAX, 0 }; +GENERIC_ENUM_CTYPE (standards_conformance, enum nn_standards_conformance) + +/* "trace" is special: it enables (nearly) everything */ +static const char *logcat_names[] = { + "fatal", "error", "warning", "info", "config", "discovery", "data", "radmin", "timing", "traffic", "topic", "tcp", "plist", "whc", "throttle", "rhc", "trace", NULL +}; +static const uint32_t logcat_codes[] = { + DDS_LC_FATAL, DDS_LC_ERROR, DDS_LC_WARNING, DDS_LC_INFO, DDS_LC_CONFIG, DDS_LC_DISCOVERY, DDS_LC_DATA, DDS_LC_RADMIN, DDS_LC_TIMING, DDS_LC_TRAFFIC, DDS_LC_TOPIC, DDS_LC_TCP, DDS_LC_PLIST, DDS_LC_WHC, DDS_LC_THROTTLE, DDS_LC_RHC, DDS_LC_ALL +}; + +static int uf_logcat (struct cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value) +{ + return do_uint32_bitset (cfgst, &enabled_logcats, logcat_names, logcat_codes, value); +} + +static int uf_verbosity (struct cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value) +{ + static const char *vs[] = { + "finest", "finer", "fine", "config", "info", "warning", "severe", "none", NULL + }; + static const uint32_t lc[] = { + DDS_LC_ALL, DDS_LC_TRAFFIC | DDS_LC_TIMING, DDS_LC_DISCOVERY | DDS_LC_THROTTLE, DDS_LC_CONFIG, DDS_LC_INFO, DDS_LC_WARNING, DDS_LC_ERROR | DDS_LC_FATAL, 0, 0 + }; + const int idx = list_index (vs, value); + assert (sizeof (vs) / sizeof (*vs) == sizeof (lc) / sizeof (*lc)); + if (idx < 0) + return cfg_error (cfgst, "'%s': undefined value", value); + for (int i = (int) (sizeof (vs) / sizeof (*vs)) - 1; i >= idx; i--) + enabled_logcats |= lc[i]; + return 1; +} + +static void pf_logcat (struct cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), uint32_t sources) +{ + /* EnableCategory is also (and often) set by Verbosity, so make an effort to locate the sources for verbosity and merge them in */ + struct cfgst_node *n; + struct cfgst_nodekey key; + key.e = lookup_element ("CycloneDDS/Tracing/Verbosity"); + key.p = NULL; + assert (key.e != NULL); + if ((n = ddsrt_avl_lookup_succ_eq (&cfgst_found_treedef, &cfgst->found, &key)) != NULL && n->key.e == key.e) + sources |= n->sources; + do_print_uint32_bitset (cfgst, config.enabled_logcats, sizeof (logcat_codes) / sizeof (*logcat_codes), logcat_names, logcat_codes, sources, ""); +} + +static const char *xcheck_names[] = { + "whc", "rhc", "all", NULL +}; +static const uint32_t xcheck_codes[] = { + DDS_XCHECK_WHC, DDS_XCHECK_RHC, ~(uint32_t) 0 +}; + +static int uf_xcheck (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) +{ + uint32_t * const elem = cfg_address (cfgst, parent, cfgelem); + return do_uint32_bitset (cfgst, elem, xcheck_names, xcheck_codes, value); +} + +static void pf_xcheck (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) +{ + const uint32_t * const p = cfg_address (cfgst, parent, cfgelem); +#ifndef NDEBUG + const char *suffix = ""; +#else + const char *suffix = " [ignored]"; +#endif + do_print_uint32_bitset (cfgst, *p, sizeof (xcheck_codes) / sizeof (*xcheck_codes), xcheck_names, xcheck_codes, sources, suffix); +} + +#ifdef DDSI_INCLUDE_SSL +static int uf_min_tls_version (struct cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value) +{ + static const char *vs[] = { + "1.2", "1.3", NULL + }; + static const struct ssl_min_version ms[] = { + {1,2}, {1,3}, {0,0} + }; + const int idx = list_index (vs, value); + struct ssl_min_version * const elem = cfg_address (cfgst, parent, cfgelem); + assert (sizeof (vs) / sizeof (*vs) == sizeof (ms) / sizeof (*ms)); + if (idx < 0) + return cfg_error(cfgst, "'%s': undefined value", value); + *elem = ms[idx]; + return 1; +} + +static void pf_min_tls_version (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) +{ + struct ssl_min_version * const p = cfg_address (cfgst, parent, cfgelem); + cfg_logelem (cfgst, sources, "%d.%d", p->major, p->minor); +} +#endif + +static int uf_string (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) +{ + char ** const elem = cfg_address (cfgst, parent, cfgelem); + *elem = ddsrt_strdup (value); + return 1; +} + +static void pf_string (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) +{ + char ** const p = cfg_address (cfgst, parent, cfgelem); + cfg_logelem (cfgst, sources, "%s", *p ? *p : "(null)"); +} + #ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING -static int uf_bandwidth(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) +static int uf_bandwidth (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) { int64_t bandwidth_bps = 0; - if ( strncmp(value, "inf", 3) == 0 ) { + if (strncmp (value, "inf", 3) == 0) { /* special case: inf needs no unit */ - int *elem = cfg_address(cfgst, parent, cfgelem); - if ( strspn(value + 3, " ") != strlen(value + 3) && - lookup_multiplier(cfgst, unittab_bandwidth_bps, value, 3, 1, 8, 1) == 0 ) + uint32_t * const elem = cfg_address (cfgst, parent, cfgelem); + if (strspn (value + 3, " ") != strlen (value + 3) && + lookup_multiplier (cfgst, unittab_bandwidth_bps, value, 3, 1, 8, 1) == 0) return 0; *elem = 0; return 1; - } else if ( !uf_natint64_unit(cfgst, &bandwidth_bps, value, unittab_bandwidth_bps, 8, INT64_MAX) ) { + } else if (!uf_natint64_unit (cfgst, &bandwidth_bps, value, unittab_bandwidth_bps, 8, INT64_MAX)) { return 0; - } else if ( bandwidth_bps / 8 > INT_MAX ) { - return cfg_error(cfgst, "%s: value out of range", value); + } else if (bandwidth_bps / 8 > INT_MAX) { + return cfg_error (cfgst, "%s: value out of range", value); } else { - uint32_t *elem = cfg_address(cfgst, parent, cfgelem); + uint32_t * const elem = cfg_address (cfgst, parent, cfgelem); *elem = (uint32_t) (bandwidth_bps / 8); return 1; } } + +static void pf_bandwidth(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) +{ + uint32_t const * const elem = cfg_address (cfgst, parent, cfgelem); + if (*elem == 0) + cfg_logelem (cfgst, sources, "inf"); + else + pf_int64_unit (cfgst, *elem, sources, unittab_bandwidth_Bps, "B/s"); +} #endif -static int uf_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) +static int uf_memsize (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) { int64_t size = 0; - if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) ) + if (!uf_natint64_unit (cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX)) return 0; else { - uint32_t *elem = cfg_address(cfgst, parent, cfgelem); + uint32_t * const elem = cfg_address (cfgst, parent, cfgelem); *elem = (uint32_t) size; return 1; } } +static void pf_memsize (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) +{ + int const * const elem = cfg_address (cfgst, parent, cfgelem); + pf_int64_unit (cfgst, *elem, sources, unittab_memsize, "B"); +} + #ifdef DDSI_INCLUDE_ENCRYPTION static int uf_cipher(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - if ( q_security_plugin.cipher_type_from_string ) { - q_cipherType *elem = cfg_address(cfgst, parent, cfgelem); - if ( (q_security_plugin.cipher_type_from_string) (value, elem) ) { - return 1; - } else { - return cfg_error(cfgst, "%s: undefined value", value); - } + if (q_security_plugin.cipher_type_from_string) + { + q_cipherType * const elem = cfg_address (cfgst, parent, cfgelem); + if (! q_security_plugin.cipher_type_from_string (value, elem)) + return cfg_error (cfgst, "%s: undefined value", value); } return 1; } + +static void pf_cipher (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) +{ + q_cipherType const * const p = cfg_address (cfgst, parent, cfgelem); + if (q_security_plugin.cipher_type) + cfg_logelem (cfgst, sources, "%s", (q_security_plugin.cipher_type) (*p)); +} + +static void pf_key (struct cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), uint32_t sources) +{ + cfg_logelem (cfgst, sources, ""); +} #endif /* DDSI_INCLUDE_ENCRYPTION */ - -static int uf_tracingOutputFileName(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) +static int uf_tracingOutputFileName (struct cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value) { - struct config *cfg = cfgst->cfg; - { - cfg->tracingOutputFileName = ddsrt_strdup(value); - } + struct config * const cfg = cfgst->cfg; + cfg->tracingOutputFileName = ddsrt_strdup (value); return 1; } -static int uf_ipv4(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) +static int uf_ipv4 (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) { /* Not actually doing any checking yet */ - return uf_string(cfgst, parent, cfgelem, first, value); + return uf_string (cfgst, parent, cfgelem, first, value); } -static int uf_networkAddress(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) +static int uf_networkAddress (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) { - if ( ddsrt_strcasecmp(value, "auto") != 0 ) - return uf_ipv4(cfgst, parent, cfgelem, first, value); - else { - char **elem = cfg_address(cfgst, parent, cfgelem); + if (ddsrt_strcasecmp (value, "auto") != 0) + return uf_ipv4 (cfgst, parent, cfgelem, first, value); + else + { + char ** const elem = cfg_address (cfgst, parent, cfgelem); *elem = NULL; return 1; } } -static void ff_networkAddresses(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) +static void pf_networkAddress (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) { - char ***elem = cfg_address(cfgst, parent, cfgelem); - int i; - for ( i = 0; (*elem)[i]; i++ ) - ddsrt_free((*elem)[i]); - ddsrt_free(*elem); + char ** const p = cfg_address (cfgst, parent, cfgelem); + cfg_logelem (cfgst, sources, "%s", *p ? *p : "auto"); } -static int uf_networkAddresses_simple(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) +static int uf_networkAddresses_simple (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) { - char ***elem = cfg_address(cfgst, parent, cfgelem); - if ( (*elem = ddsrt_malloc(2 * sizeof(char *))) == NULL ) - return cfg_error(cfgst, "out of memory"); - if ( ((*elem)[0] = ddsrt_strdup(value)) == NULL ) { - ddsrt_free(*elem); + char *** const elem = cfg_address (cfgst, parent, cfgelem); + if ((*elem = ddsrt_malloc (2 * sizeof(char *))) == NULL) + return cfg_error (cfgst, "out of memory"); + if (((*elem)[0] = ddsrt_strdup (value)) == NULL) { + ddsrt_free (*elem); *elem = NULL; - return cfg_error(cfgst, "out of memory"); + return cfg_error (cfgst, "out of memory"); } (*elem)[1] = NULL; return 1; } -static int uf_networkAddresses(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) +static int uf_networkAddresses (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) { /* Check for keywords first */ { static const char *keywords[] = { "all", "any", "none" }; - int i; - for ( i = 0; i < (int) (sizeof(keywords) / sizeof(*keywords)); i++ ) { - if ( ddsrt_strcasecmp(value, keywords[i]) == 0 ) - return uf_networkAddresses_simple(cfgst, parent, cfgelem, first, keywords[i]); + for (int i = 0; i < (int) (sizeof (keywords) / sizeof (*keywords)); i++) { + if (ddsrt_strcasecmp (value, keywords[i]) == 0) + return uf_networkAddresses_simple (cfgst, parent, cfgelem, first, keywords[i]); } } /* If not keyword, then comma-separated list of addresses */ { - char ***elem = cfg_address(cfgst, parent, cfgelem); + char *** const elem = cfg_address (cfgst, parent, cfgelem); char *copy; unsigned count; @@ -1575,128 +1715,102 @@ static int uf_networkAddresses(struct cfgst *cfgst, void *parent, struct cfgelem { const char *scan = value; count = 1; - while ( *scan ) + while (*scan) count += (*scan++ == ','); } - copy = ddsrt_strdup(value); + copy = ddsrt_strdup (value); /* Allocate an array of address strings (which may be oversized a bit because of the counting of the commas) */ - *elem = ddsrt_malloc((count + 1) * sizeof(char *)); + *elem = ddsrt_malloc ((count + 1) * sizeof(char *)); { char *cursor = copy, *tok; unsigned idx = 0; - while ( (tok = ddsrt_strsep(&cursor, ",")) != NULL ) { - assert(idx < count); - (*elem)[idx] = ddsrt_strdup(tok); + while ((tok = ddsrt_strsep (&cursor, ",")) != NULL) { + assert (idx < count); + (*elem)[idx] = ddsrt_strdup (tok); idx++; } (*elem)[idx] = NULL; } - ddsrt_free(copy); + ddsrt_free (copy); } return 1; } -static int uf_allow_multicast(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) +static void pf_networkAddresses (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) { + char *** const p = cfg_address (cfgst, parent, cfgelem); + for (int i = 0; (*p)[i] != NULL; i++) + cfg_logelem (cfgst, sources, "%s", (*p)[i]); +} + +static void ff_networkAddresses (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) +{ + char *** const elem = cfg_address (cfgst, parent, cfgelem); + for (int i = 0; (*elem)[i]; i++) + ddsrt_free ((*elem)[i]); + ddsrt_free (*elem); +} + #ifdef DDSI_INCLUDE_SSM - static const char *vs[] = { "false", "spdp", "asm", "ssm", "true", NULL }; - static const unsigned bs[] = { AMC_FALSE, AMC_SPDP, AMC_ASM, AMC_SSM, AMC_TRUE }; +static const char *allow_multicast_names[] = { "false", "spdp", "asm", "ssm", "true", NULL }; +static const uint32_t allow_multicast_codes[] = { AMC_FALSE, AMC_SPDP, AMC_ASM, AMC_SSM, AMC_TRUE }; #else - static const char *vs[] = { "false", "spdp", "asm", "true", NULL }; - static const unsigned bs[] = { AMC_FALSE, AMC_SPDP, AMC_ASM, AMC_TRUE }; +static const char *allow_multicast_names[] = { "false", "spdp", "asm", "true", NULL }; +static const uint32_t allow_multicast_codes[] = { AMC_FALSE, AMC_SPDP, AMC_ASM, AMC_TRUE }; #endif - char *copy = ddsrt_strdup(value), *cursor = copy, *tok; - unsigned *elem = cfg_address(cfgst, parent, cfgelem); - if ( copy == NULL ) - return cfg_error(cfgst, "out of memory"); - *elem = 0; - while ( (tok = ddsrt_strsep(&cursor, ",")) != NULL ) { - int idx = list_index(vs, tok); - if ( idx < 0 ) { - int ret = cfg_error(cfgst, "'%s' in '%s' undefined", tok, value); - ddsrt_free(copy); - return ret; - } - *elem |= bs[idx]; - } - ddsrt_free(copy); - return 1; + +static int uf_allow_multicast (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) +{ + uint32_t * const elem = cfg_address (cfgst, parent, cfgelem); + return do_uint32_bitset (cfgst, elem, allow_multicast_names, allow_multicast_codes, value); } -static void pf_allow_multicast(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) +static void pf_allow_multicast(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) { - unsigned *p = cfg_address(cfgst, parent, cfgelem); - const char *str = "INVALID"; - switch ( *p ) { - case AMC_FALSE: str = "false"; break; - case AMC_SPDP: str = "spdp"; break; - case AMC_ASM: str = "asm"; break; -#ifdef DDSI_INCLUDE_SSM - case AMC_SSM: str = "ssm"; break; - case (AMC_SPDP | AMC_ASM): str = "spdp,asm"; break; - case (AMC_SPDP | AMC_SSM): str = "spdp,ssm"; break; -#endif - case AMC_TRUE: str = "true"; break; - } - cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); -} - -static int uf_sched_class(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - static const char *vs[] = { "realtime", "timeshare", "default" }; - static const ddsrt_sched_t ms[] = { DDSRT_SCHED_REALTIME, DDSRT_SCHED_TIMESHARE, DDSRT_SCHED_DEFAULT }; - int idx = list_index(vs, value); - ddsrt_sched_t *elem = cfg_address(cfgst, parent, cfgelem); - assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms)); - if ( idx < 0 ) - return cfg_error(cfgst, "'%s': undefined value", value); - *elem = ms[idx]; - return 1; -} - -static void pf_sched_class(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - ddsrt_sched_t *p = cfg_address(cfgst, parent, cfgelem); - const char *str = "INVALID"; - switch ( *p ) { - case DDSRT_SCHED_DEFAULT: str = "default"; break; - case DDSRT_SCHED_TIMESHARE: str = "timeshare"; break; - case DDSRT_SCHED_REALTIME: str = "realtime"; break; - } - cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); + uint32_t *p = cfg_address (cfgst, parent, cfgelem); + do_print_uint32_bitset (cfgst, *p, sizeof (allow_multicast_codes) / sizeof (*allow_multicast_codes), allow_multicast_names, allow_multicast_codes, sources, ""); } DDSRT_WARNING_MSVC_OFF(4996); -static int uf_maybe_int32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) +static int uf_maybe_int32 (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) { - struct config_maybe_int32 *elem = cfg_address(cfgst, parent, cfgelem); + struct config_maybe_int32 * const elem = cfg_address (cfgst, parent, cfgelem); int pos; - if ( ddsrt_strcasecmp(value, "default") == 0 ) { + if (ddsrt_strcasecmp (value, "default") == 0) { elem->isdefault = 1; elem->value = 0; return 1; - } else if ( sscanf(value, "%"PRId32"%n", &elem->value, &pos) == 1 && value[pos] == 0 ) { + } else if (sscanf (value, "%"SCNd32"%n", &elem->value, &pos) == 1 && value[pos] == 0) { elem->isdefault = 0; return 1; } else { - return cfg_error(cfgst, "'%s': neither 'default' nor a decimal integer\n", value); + return cfg_error (cfgst, "'%s': neither 'default' nor a decimal integer\n", value); } } DDSRT_WARNING_MSVC_ON(4996); -static int uf_maybe_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) +static void pf_maybe_int32 (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) { - struct config_maybe_uint32 *elem = cfg_address(cfgst, parent, cfgelem); + struct config_maybe_int32 const * const p = cfg_address (cfgst, parent, cfgelem); + if (p->isdefault) + cfg_logelem (cfgst, sources, "default"); + else + cfg_logelem (cfgst, sources, "%d", p->value); +} + +static int uf_maybe_memsize (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) +{ + struct config_maybe_uint32 * const elem = cfg_address (cfgst, parent, cfgelem); int64_t size = 0; - if ( ddsrt_strcasecmp(value, "default") == 0 ) { + if (ddsrt_strcasecmp (value, "default") == 0) { elem->isdefault = 1; elem->value = 0; return 1; - } else if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) ) { + } else if (!uf_natint64_unit (cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX)) { return 0; } else { elem->isdefault = 0; @@ -1705,139 +1819,43 @@ static int uf_maybe_memsize(struct cfgst *cfgst, void *parent, struct cfgelem co } } -static int uf_int(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) +static void pf_maybe_memsize (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) { - int *elem = cfg_address(cfgst, parent, cfgelem); + struct config_maybe_uint32 const * const p = cfg_address (cfgst, parent, cfgelem); + if (p->isdefault) + cfg_logelem (cfgst, sources, "default"); + else + pf_int64_unit (cfgst, p->value, sources, unittab_memsize, "B"); +} + +static int uf_int (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) +{ + int * const elem = cfg_address (cfgst, parent, cfgelem); char *endptr; - long v = strtol(value, &endptr, 10); - if ( *value == 0 || *endptr != 0 ) - return cfg_error(cfgst, "%s: not a decimal integer", value); - if ( v != (int) v ) - return cfg_error(cfgst, "%s: value out of range", value); + long v = strtol (value, &endptr, 10); + if (*value == 0 || *endptr != 0) + return cfg_error (cfgst, "%s: not a decimal integer", value); + if (v != (int) v) + return cfg_error (cfgst, "%s: value out of range", value); *elem = (int) v; return 1; } -static int uf_duration_gen(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, const char *value, int64_t def_mult, int64_t min_ns, int64_t max_ns) +static int uf_int_min_max (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value, int min, int max) { - return uf_natint64_unit(cfgst, cfg_address(cfgst, parent, cfgelem), value, unittab_duration, def_mult, min_ns, max_ns); -} - -static int uf_duration_inf(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - if ( ddsrt_strcasecmp(value, "inf") == 0 ) { - int64_t *elem = cfg_address(cfgst, parent, cfgelem); - *elem = T_NEVER; - return 1; - } else { - return uf_duration_gen(cfgst, parent, cfgelem, value, 0, 0, T_NEVER - 1); - } -} - -static int uf_duration_ms_1hr(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 0, 3600 * T_SECOND); -} - -static int uf_duration_ms_1s(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 0, T_SECOND); -} - -static int uf_duration_us_1s(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - return uf_duration_gen(cfgst, parent, cfgelem, value, 1000, 0, T_SECOND); -} - -static int uf_duration_100ms_1hr(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - return uf_duration_gen(cfgst, parent, cfgelem, value, 0, 100 * T_MILLISECOND, 3600 * T_SECOND); -} - -#if 0 -static int uf_int32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - int32_t *elem = cfg_address(cfgst, parent, cfgelem); - char *endptr; - long v = strtol(value, &endptr, 10); - if ( *value == 0 || *endptr != 0 ) - return cfg_error(cfgst, "%s: not a decimal integer", value); - if ( v != (int32_t) v ) - return cfg_error(cfgst, "%s: value out of range", value); - *elem = (int32_t) v; - return 1; -} -#endif - -#if 0 -static int uf_uint32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - uint32_t *elem = cfg_address(cfgst, parent, cfgelem); - char *endptr; - unsigned long v = strtoul(value, &endptr, 10); - if ( *value == 0 || *endptr != 0 ) - return cfg_error(cfgst, "%s: not a decimal integer", value); - if ( v != (uint32_t) v ) - return cfg_error(cfgst, "%s: value out of range", value); - *elem = (uint32_t) v; - return 1; -} -#endif - -static int uf_uint(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - unsigned *elem = cfg_address(cfgst, parent, cfgelem); - char *endptr; - unsigned long v = strtoul(value, &endptr, 10); - if ( *value == 0 || *endptr != 0 ) - return cfg_error(cfgst, "%s: not a decimal integer", value); - if ( v != (unsigned) v ) - return cfg_error(cfgst, "%s: value out of range", value); - *elem = (unsigned) v; - return 1; -} - -static int uf_int_min_max(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value, int min, int max) -{ - int *elem = cfg_address(cfgst, parent, cfgelem); - if ( !uf_int(cfgst, parent, cfgelem, first, value) ) + int *elem = cfg_address (cfgst, parent, cfgelem); + if (!uf_int (cfgst, parent, cfgelem, first, value)) return 0; - else if ( *elem < min || *elem > max ) - return cfg_error(cfgst, "%s: out of range", value); + else if (*elem < min || *elem > max) + return cfg_error (cfgst, "%s: out of range", value); else return 1; } -DDSRT_WARNING_MSVC_OFF(4996); -static int uf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) +static void pf_int (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) { - struct config_maybe_int32 *elem = cfg_address(cfgst, parent, cfgelem); - int pos; - if (ddsrt_strcasecmp(value, "any") == 0) { - elem->isdefault = 1; - elem->value = 0; - return 1; - } else if (sscanf(value, "%"PRId32"%n", &elem->value, &pos) == 1 && value[pos] == 0 && elem->value >= 0 && elem->value <= 230) { - elem->isdefault = 0; - return 1; - } else { - return cfg_error(cfgst, "'%s': neither 'any' nor a decimal integer in 0 .. 230\n", value); - } -} -DDSRT_WARNING_MSVC_ON(4996); - -static int uf_participantIndex(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) -{ - int *elem = cfg_address(cfgst, parent, cfgelem); - if ( ddsrt_strcasecmp(value, "auto") == 0 ) { - *elem = PARTICIPANT_INDEX_AUTO; - return 1; - } else if ( ddsrt_strcasecmp(value, "none") == 0 ) { - *elem = PARTICIPANT_INDEX_NONE; - return 1; - } else { - return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, 120); - } + int const * const p = cfg_address (cfgst, parent, cfgelem); + cfg_logelem (cfgst, sources, "%d", *p); } static int uf_port(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) @@ -1860,63 +1878,126 @@ static int uf_natint_255(struct cfgst *cfgst, void *parent, struct cfgelem const return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, 255); } -static int uf_transport_selector (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) +static int uf_uint (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) { - static const char *vs[] = { "default", "udp", "udp6", "tcp", "tcp6", "raweth", NULL }; - static const enum transport_selector ms[] = { - TRANS_DEFAULT, TRANS_UDP, TRANS_UDP6, TRANS_TCP, TRANS_TCP6, TRANS_RAWETH, 0, - }; - enum transport_selector *elem = cfg_address (cfgst, parent, cfgelem); - int idx = list_index (vs, value); - assert (sizeof (vs) / sizeof (*vs) == sizeof (ms) / sizeof (*ms)); - if (idx < 0) - return cfg_error (cfgst, "'%s': undefined value", value); - *elem = ms[idx]; + unsigned * const elem = cfg_address (cfgst, parent, cfgelem); + char *endptr; + unsigned long v = strtoul (value, &endptr, 10); + if (*value == 0 || *endptr != 0) + return cfg_error (cfgst, "%s: not a decimal integer", value); + if (v != (unsigned) v) + return cfg_error (cfgst, "%s: value out of range", value); + *elem = (unsigned) v; return 1; } -static void pf_transport_selector (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) +static void pf_uint (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) { - enum transport_selector *p = cfg_address (cfgst, parent, cfgelem); - const char *str = "INVALID"; - switch (*p) - { - case TRANS_DEFAULT: str = "default"; break; - case TRANS_UDP: str = "udp"; break; - case TRANS_UDP6: str = "udp6"; break; - case TRANS_TCP: str = "tcp"; break; - case TRANS_TCP6: str = "tcp6"; break; - case TRANS_RAWETH: str = "raweth"; break; - } - cfg_log (cfgst, "%s%s", str, is_default ? " [def]" : ""); + unsigned const * const p = cfg_address (cfgst, parent, cfgelem); + cfg_logelem (cfgst, sources, "%u", *p); } -static int uf_many_sockets_mode (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) +static int uf_duration_gen (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, const char *value, int64_t def_mult, int64_t min_ns, int64_t max_ns) { - static const char *vs[] = { "false", "true", "single", "none", "many", NULL }; - static const enum many_sockets_mode ms[] = { - MSM_SINGLE_UNICAST, MSM_MANY_UNICAST, MSM_SINGLE_UNICAST, MSM_NO_UNICAST, MSM_MANY_UNICAST, 0, - }; - enum many_sockets_mode *elem = cfg_address (cfgst, parent, cfgelem); - int idx = list_index (vs, value); - assert (sizeof (vs) / sizeof (*vs) == sizeof (ms) / sizeof (*ms)); - if (idx < 0) - return cfg_error (cfgst, "'%s': undefined value", value); - *elem = ms[idx]; - return 1; + return uf_natint64_unit (cfgst, cfg_address (cfgst, parent, cfgelem), value, unittab_duration, def_mult, min_ns, max_ns); } -static void pf_many_sockets_mode (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) +static int uf_duration_inf (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) { - enum many_sockets_mode *p = cfg_address (cfgst, parent, cfgelem); - const char *str = "INVALID"; + if (ddsrt_strcasecmp (value, "inf") == 0) { + int64_t * const elem = cfg_address (cfgst, parent, cfgelem); + *elem = T_NEVER; + return 1; + } else { + return uf_duration_gen (cfgst, parent, cfgelem, value, 0, 0, T_NEVER - 1); + } +} + +static int uf_duration_ms_1hr (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) +{ + return uf_duration_gen (cfgst, parent, cfgelem, value, T_MILLISECOND, 0, 3600 * T_SECOND); +} + +static int uf_duration_ms_1s (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) +{ + return uf_duration_gen (cfgst, parent, cfgelem, value, T_MILLISECOND, 0, T_SECOND); +} + +static int uf_duration_us_1s (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) +{ + return uf_duration_gen (cfgst, parent, cfgelem, value, 1000, 0, T_SECOND); +} + +static int uf_duration_100ms_1hr (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) +{ + return uf_duration_gen (cfgst, parent, cfgelem, value, 0, 100 * T_MILLISECOND, 3600 * T_SECOND); +} + +static void pf_duration (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) +{ + int64_t const * const elem = cfg_address (cfgst, parent, cfgelem); + if (*elem == T_NEVER) + cfg_logelem (cfgst, sources, "inf"); + else + pf_int64_unit (cfgst, *elem, sources, unittab_duration, "s"); +} + +DDSRT_WARNING_MSVC_OFF(4996); +static int uf_domainId (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) +{ + struct config_maybe_int32 * const elem = cfg_address (cfgst, parent, cfgelem); + int pos; + if (ddsrt_strcasecmp (value, "any") == 0) { + elem->isdefault = 1; + elem->value = 0; + return 1; + } else if (sscanf (value, "%"SCNd32"%n", &elem->value, &pos) == 1 && value[pos] == 0 && elem->value >= 0 && elem->value <= 230) { + elem->isdefault = 0; + return 1; + } else { + return cfg_error (cfgst, "'%s': neither 'any' nor a decimal integer in 0 .. 230\n", value); + } +} +DDSRT_WARNING_MSVC_ON(4996); + +static void pf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) +{ + struct config_maybe_int32 const * const p = cfg_address (cfgst, parent, cfgelem); + if (p->isdefault) + cfg_logelem (cfgst, sources, "any (%d)", p->value); + else + cfg_logelem (cfgst, sources, "%d", p->value); +} + +static int uf_participantIndex (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) +{ + int * const elem = cfg_address (cfgst, parent, cfgelem); + if (ddsrt_strcasecmp (value, "auto") == 0) { + *elem = PARTICIPANT_INDEX_AUTO; + return 1; + } else if (ddsrt_strcasecmp (value, "none") == 0) { + *elem = PARTICIPANT_INDEX_NONE; + return 1; + } else { + return uf_int_min_max (cfgst, parent, cfgelem, first, value, 0, 120); + } +} + +static void pf_participantIndex (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) +{ + int const * const p = cfg_address (cfgst, parent, cfgelem); switch (*p) { - case MSM_SINGLE_UNICAST: str = "single"; break; - case MSM_MANY_UNICAST: str = "many"; break; - case MSM_NO_UNICAST: str = "none"; break; + case PARTICIPANT_INDEX_NONE: + cfg_logelem (cfgst, sources, "none"); + break; + case PARTICIPANT_INDEX_AUTO: + cfg_logelem (cfgst, sources, "auto"); + break; + default: + cfg_logelem (cfgst, sources, "%d", *p); + break; } - cfg_log (cfgst, "%s%s", str, is_default ? " [def]" : ""); } static int uf_deaf_mute (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) @@ -1924,657 +2005,432 @@ static int uf_deaf_mute (struct cfgst *cfgst, void *parent, struct cfgelem const return uf_boolean (cfgst, parent, cfgelem, first, value); } -static int do_update(struct cfgst *cfgst, update_fun_t upd, void *parent, struct cfgelem const * const cfgelem, const char *value, int is_default) +static struct cfgst_node *lookup_or_create_elem_record (struct cfgst *cfgst, struct cfgelem const * const cfgelem, void *parent, uint32_t source) { struct cfgst_node *n; struct cfgst_nodekey key; ddsrt_avl_ipath_t np; - int ok; key.e = cfgelem; - if ( (n = ddsrt_avl_lookup_ipath(&cfgst_found_treedef, &cfgst->found, &key, &np)) == NULL ) { - if ( (n = ddsrt_malloc(sizeof(*n))) == NULL ) - return cfg_error(cfgst, "out of memory"); - + key.p = parent; + if ((n = ddsrt_avl_lookup_ipath (&cfgst_found_treedef, &cfgst->found, &key, &np)) == NULL) + { + if ((n = ddsrt_malloc (sizeof (*n))) == NULL) + { + cfg_error (cfgst, "out of memory"); + return NULL; + } n->key = key; n->count = 0; n->failed = 0; - n->is_default = is_default; - ddsrt_avl_insert_ipath(&cfgst_found_treedef, &cfgst->found, n, &np); - } - if ( cfgelem->multiplicity == 0 || n->count < cfgelem->multiplicity ) - ok = upd(cfgst, parent, cfgelem, (n->count == n->failed), value); - else - ok = cfg_error(cfgst, "only %d instance%s allowed", cfgelem->multiplicity, (cfgelem->multiplicity == 1) ? "" : "s"); - n->count++; - if ( !ok ) { - n->failed++; - } - return ok; -} - -static int set_default(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) -{ - if ( cfgelem->defvalue == NULL ) - return cfg_error(cfgst, "element missing in configuration"); - return do_update(cfgst, cfgelem->update, parent, cfgelem, cfgelem->defvalue, 1); -} - -static int set_defaults(struct cfgst *cfgst, void *parent, int isattr, struct cfgelem const * const cfgelem, int clear_found) -{ - const struct cfgelem *ce; - int ok = 1; - for ( ce = cfgelem; ce && ce->name; ce++ ) { - struct cfgst_node *n; - struct cfgst_nodekey key; - key.e = ce; - cfgst_push(cfgst, isattr, ce, parent); - if ( ce->multiplicity == 1 ) { - if ( ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key) == NULL ) { - if ( ce->update ) { - int ok1; - cfgst_push(cfgst, 0, NULL, NULL); - ok1 = set_default(cfgst, parent, ce); - cfgst_pop(cfgst); - ok = ok && ok1; - } - } - if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { - if ( clear_found ) { - ddsrt_avl_delete(&cfgst_found_treedef, &cfgst->found, n); - ddsrt_free(n); - } - } - if ( ce->children ) { - int ok1 = set_defaults(cfgst, parent, 0, ce->children, clear_found); - ok = ok && ok1; - } - if ( ce->attributes ) { - int ok1 = set_defaults(cfgst, parent, 1, ce->attributes, clear_found); - ok = ok && ok1; - } - } - cfgst_pop(cfgst); - } - return ok; -} - -static void pf_nop(UNUSED_ARG(struct cfgst *cfgst), UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int is_default)) -{ -} - -static void pf_string(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - char **p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%s%s", *p ? *p : "(null)", is_default ? " [def]" : ""); -} - -static void pf_int64_unit(struct cfgst *cfgst, int64_t value, int is_default, const struct unit *unittab, const char *zero_unit) -{ - if ( value == 0 ) { - /* 0s is a bit of a special case: we don't want to print 0hr (or - whatever unit will have the greatest multiplier), so hard-code - as 0s */ - cfg_log(cfgst, "0 %s%s", zero_unit, is_default ? " [def]" : ""); - } else { - int64_t m = 0; - const char *unit = NULL; - int i; - for ( i = 0; unittab[i].name != NULL; i++ ) { - if ( unittab[i].multiplier > m && (value % unittab[i].multiplier) == 0 ) { - m = unittab[i].multiplier; - unit = unittab[i].name; - } - } - assert(m > 0); - assert(unit != NULL); - cfg_log(cfgst, "%lld %s%s", value / m, unit, is_default ? " [def]" : ""); - } -} - -#ifdef DDSI_INCLUDE_ENCRYPTION -static void pf_key(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int is_default)) -{ - cfg_log(cfgst, ""); -} - -static void pf_cipher(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - q_cipherType *p = cfg_address(cfgst, parent, cfgelem); - if ( q_security_plugin.cipher_type ) { - cfg_log(cfgst, "%s%s", (q_security_plugin.cipher_type) (*p), is_default ? " [def]" : ""); - } -} -#endif /* DDSI_INCLUDE_ENCRYPTION */ - -static void pf_networkAddress(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - char **p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%s%s", *p ? *p : "auto", is_default ? " [def]" : ""); -} - -static void pf_participantIndex(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - int *p = cfg_address(cfgst, parent, cfgelem); - switch ( *p ) { - case PARTICIPANT_INDEX_NONE: - cfg_log(cfgst, "none%s", is_default ? " [def]" : ""); - break; - case PARTICIPANT_INDEX_AUTO: - cfg_log(cfgst, "auto%s", is_default ? " [def]" : ""); - break; - default: - cfg_log(cfgst, "%d%s", *p, is_default ? " [def]" : ""); - break; - } -} - -static void pf_networkAddresses(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - int i; - char ***p = cfg_address(cfgst, parent, cfgelem); - for ( i = 0; (*p)[i] != NULL; i++ ) - cfg_log(cfgst, "%s%s", (*p)[i], is_default ? " [def]" : ""); -} - -static void pf_int(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - int *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%d%s", *p, is_default ? " [def]" : ""); -} - -static void pf_uint(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - unsigned *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%u%s", *p, is_default ? " [def]" : ""); -} - -static void pf_duration(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - const int64_t *elem = cfg_address(cfgst, parent, cfgelem); - if ( *elem == T_NEVER ) - cfg_log(cfgst, "inf%s", is_default ? " [def]" : ""); - else - pf_int64_unit(cfgst, *elem, is_default, unittab_duration, "s"); -} - -#ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING -static void pf_bandwidth(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - const uint32_t *elem = cfg_address(cfgst, parent, cfgelem); - if ( *elem == 0 ) - cfg_log(cfgst, "inf%s", is_default ? " [def]" : ""); - else - pf_int64_unit(cfgst, *elem, is_default, unittab_bandwidth_Bps, "B/s"); -} -#endif - -static void pf_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - const int *elem = cfg_address(cfgst, parent, cfgelem); - pf_int64_unit(cfgst, *elem, is_default, unittab_memsize, "B"); -} - -#if 0 -static void pf_int32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - int32_t *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%d%s", *p, is_default ? " [def]" : ""); -} -#endif - -#if 0 -static void pf_uint32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - uint32_t *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%u%s", *p, is_default ? " [def]" : ""); -} -#endif - -static void pf_maybe_int32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - struct config_maybe_int32 *p = cfg_address(cfgst, parent, cfgelem); - if ( p->isdefault ) - cfg_log(cfgst, "default%s", is_default ? " [def]" : ""); - else - cfg_log(cfgst, "%d%s", p->value, is_default ? " [def]" : ""); -} - -static void pf_maybe_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - struct config_maybe_uint32 *p = cfg_address(cfgst, parent, cfgelem); - if ( p->isdefault ) - cfg_log(cfgst, "default%s", is_default ? " [def]" : ""); - else - pf_int64_unit(cfgst, p->value, is_default, unittab_memsize, "B"); -} - -static void pf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - struct config_maybe_int32 *p = cfg_address(cfgst, parent, cfgelem); - if ( p->isdefault ) - cfg_log(cfgst, "any (%d)%s", p->value, is_default ? " [def]" : ""); - else - cfg_log(cfgst, "%d%s", p->value, is_default ? " [def]" : ""); -} - -static void pf_boolean(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - int *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%s%s", *p ? "true" : "false", is_default ? " [def]" : ""); -} - -static int uf_standards_conformance(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - static const char *vs[] = { - "pedantic", "strict", "lax", NULL - }; - static const uint32_t lc[] = { - NN_SC_PEDANTIC, NN_SC_STRICT, NN_SC_LAX, 0 - }; - enum nn_standards_conformance *elem = cfg_address(cfgst, parent, cfgelem); - int idx = list_index(vs, value); - assert(sizeof(vs) / sizeof(*vs) == sizeof(lc) / sizeof(*lc)); - if ( idx < 0 ) - return cfg_error(cfgst, "'%s': undefined value", value); - else { - *elem = lc[idx]; - return 1; - } -} - -static void pf_standards_conformance(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - enum nn_standards_conformance *p = cfg_address(cfgst, parent, cfgelem); - const char *str = "INVALID"; - switch ( *p ) { - case NN_SC_PEDANTIC: str = "pedantic"; break; - case NN_SC_STRICT: str = "strict"; break; - case NN_SC_LAX: str = "lax"; break; - } - cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); -} - -static unsigned uint32_popcnt (uint32_t x) -{ - unsigned n = 0; - while (x != 0) - { - n += ((x & 1u) != 0); - x >>= 1; + n->sources = source; + ddsrt_avl_insert_ipath (&cfgst_found_treedef, &cfgst->found, n, &np); } return n; } -static void do_print_uint32_bitset (struct cfgst *cfgst, uint32_t mask, size_t ncodes, const char **names, const uint32_t *codes, const char *suffix) +static int do_update (struct cfgst *cfgst, update_fun_t upd, void *parent, struct cfgelem const * const cfgelem, const char *value, uint32_t source) { - char res[256] = "", *resp = res; - const char *prefix = ""; -#ifndef NDEBUG + struct cfgst_node *n; + int ok; + n = lookup_or_create_elem_record (cfgst, cfgelem, parent, source); + if (cfgelem->multiplicity == 1 && n->count == 1 && source > n->sources) + free_configured_element (cfgst, parent, cfgelem); + if (cfgelem->multiplicity == 0 || n->count < cfgelem->multiplicity) + ok = upd (cfgst, parent, cfgelem, (n->count == n->failed), value); + else + ok = cfg_error (cfgst, "only %d instance%s allowed", cfgelem->multiplicity, (cfgelem->multiplicity == 1) ? "" : "s"); + n->count++; + n->sources |= source; + if (!ok) + n->failed++; + return ok; +} + +static int set_default (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) +{ + if (cfgelem->defvalue == NULL) + return cfg_error (cfgst, "element missing in configuration"); + return do_update (cfgst, cfgelem->update, parent, cfgelem, cfgelem->defvalue, 0); +} + +static int set_defaults (struct cfgst *cfgst, void *parent, int isattr, struct cfgelem const * const cfgelem) +{ + int ok = 1; + for (const struct cfgelem *ce = cfgelem; ce && ce->name; ce++) { - size_t max = 0; - for (size_t i = 0; i < ncodes; i++ ) - max += 1 + strlen(names[i]); - max += 11; /* ,0x%x */ - max += 1; /* \0 */ - assert(max <= sizeof(res)); - } -#endif - while (mask) { - size_t i_best = 0; - unsigned pc_best = 0; - for (size_t i = 0; i < ncodes; i++) { - uint32_t m = mask & codes[i]; - if (m == codes[i]) { - unsigned pc = uint32_popcnt (m); - if (pc > pc_best) { - i_best = i; - pc_best = pc; + struct cfgst_node *n; + struct cfgst_nodekey key; + key.e = ce; + key.p = parent; + cfgst_push (cfgst, isattr, ce, parent); + if (ce->multiplicity == 1) + { + if ((n = ddsrt_avl_lookup (&cfgst_found_treedef, &cfgst->found, &key)) == NULL) + { + if (ce->update) + { + int ok1; + cfgst_push (cfgst, 0, NULL, NULL); + ok1 = set_default (cfgst, parent, ce); + cfgst_pop (cfgst); + ok = ok && ok1; } } + if (ce->children) + ok = ok && set_defaults (cfgst, parent, 0, ce->children); + if (ce->attributes) + ok = ok && set_defaults (cfgst, parent, 1, ce->attributes); } - if (pc_best != 0) { - resp += snprintf(resp, 256, "%s%s", prefix, names[i_best]); - mask &= ~codes[i_best]; - prefix = ","; - } else { - resp += snprintf (resp, 256, "%s0x%x", prefix, (unsigned) mask); - mask = 0; - } + cfgst_pop (cfgst); } - assert (resp <= res + sizeof(res)); - cfg_log (cfgst, "%s%s", res, suffix); + return ok; } -static void pf_logcat(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int is_default)) -{ - /* can't do default indicator: user may have specified Verbosity, in - which case EnableCategory is at default, but for these two - settings, I don't mind. */ - do_print_uint32_bitset (cfgst, config.enabled_logcats, sizeof(logcat_codes) / sizeof(*logcat_codes), logcat_names, logcat_codes, ""); -} -static void pf_xcheck(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) +static void print_configitems (struct cfgst *cfgst, void *parent, int isattr, struct cfgelem const * const cfgelem, uint32_t sources) { - const uint32_t *p = cfg_address(cfgst, parent, cfgelem); -#ifndef NDEBUG - const char *suffix = is_default ? " [def]" : ""; -#else - const char *suffix = " [ignored]"; - (void)is_default; -#endif - do_print_uint32_bitset (cfgst, *p, sizeof(xcheck_codes) / sizeof(*xcheck_codes), xcheck_names, xcheck_codes, suffix); -} - -static void print_configitems(struct cfgst *cfgst, void *parent, int isattr, struct cfgelem const * const cfgelem, int unchecked) -{ - const struct cfgelem *ce; - for ( ce = cfgelem; ce && ce->name; ce++ ) { + for (const struct cfgelem *ce = cfgelem; ce && ce->name; ce++) + { struct cfgst_nodekey key; struct cfgst_node *n; - if ( ce->name[0] == '>' || ce->name[0] == '|') /* moved or deprecated, so don't care */ + if (ce->name[0] == '>' || ce->name[0] == '|') /* moved or deprecated, so don't care */ continue; key.e = ce; - cfgst_push(cfgst, isattr, ce, parent); - if ( ce->multiplicity == 1 ) { - if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { - cfgst_push(cfgst, 0, NULL, NULL); - ce->print(cfgst, parent, ce, n->is_default); - cfgst_pop(cfgst); - } else { - if ( unchecked && ce->print ) { - cfgst_push(cfgst, 0, NULL, NULL); - ce->print(cfgst, parent, ce, 0); - cfgst_pop(cfgst); - } - } + key.p = parent; + cfgst_push (cfgst, isattr, ce, parent); + if ((n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL) + sources = n->sources; - if ( ce->children ) - print_configitems(cfgst, parent, 0, ce->children, unchecked); - if ( ce->attributes ) - print_configitems(cfgst, parent, 1, ce->attributes, unchecked); - } else { - struct config_listelem *p = cfg_deref_address(cfgst, parent, ce); - while ( p ) { - cfgst_push(cfgst, 0, NULL, NULL); - if ( ce->print ) { - ce->print(cfgst, p, ce, 0); - } + if (ce->multiplicity == 1) + { + cfgst_push (cfgst, 0, NULL, NULL); + if (ce->print) + ce->print (cfgst, parent, ce, sources); + cfgst_pop (cfgst); + if (ce->children) + print_configitems (cfgst, parent, 0, ce->children, sources); + if (ce->attributes) + print_configitems (cfgst, parent, 1, ce->attributes, sources); + } + else + { + struct config_listelem *p = cfg_deref_address (cfgst, parent, ce); + while (p) + { + cfgst_push (cfgst, 0, NULL, NULL); + if (ce->print) + ce->print (cfgst, p, ce, sources); cfgst_pop(cfgst); - if ( ce->attributes ) - print_configitems(cfgst, p, 1, ce->attributes, 1); - if ( ce->children ) - print_configitems(cfgst, p, 0, ce->children, 1); + if (ce->attributes) + print_configitems (cfgst, p, 1, ce->attributes, sources); + if (ce->children) + print_configitems (cfgst, p, 0, ce->children, sources); p = p->next; } } - cfgst_pop(cfgst); + cfgst_pop (cfgst); } } -static void free_all_elements(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) +static void free_all_elements (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - const struct cfgelem *ce; - - for ( ce = cfgelem; ce && ce->name; ce++ ) { - if ( ce->name[0] == '>' ) /* moved, so don't care */ + for (const struct cfgelem *ce = cfgelem; ce && ce->name; ce++) + { + if (ce->name[0] == '>') /* moved, so don't care */ continue; - if ( ce->free ) - ce->free(cfgst, parent, ce); + if (ce->free) + ce->free (cfgst, parent, ce); - if ( ce->multiplicity == 1 ) { - if ( ce->children ) - free_all_elements(cfgst, parent, ce->children); - if ( ce->attributes ) - free_all_elements(cfgst, parent, ce->attributes); + if (ce->multiplicity == 1) { + if (ce->children) + free_all_elements (cfgst, parent, ce->children); + if (ce->attributes) + free_all_elements (cfgst, parent, ce->attributes); } else { - struct config_listelem *p = cfg_deref_address(cfgst, parent, ce); - struct config_listelem *r; - while ( p ) { - if ( ce->attributes ) - free_all_elements(cfgst, p, ce->attributes); - if ( ce->children ) - free_all_elements(cfgst, p, ce->children); - r = p; - p = p->next; - ddsrt_free(r); + struct config_listelem *p = cfg_deref_address (cfgst, parent, ce); + while (p) { + struct config_listelem *p1 = p->next; + if (ce->attributes) + free_all_elements (cfgst, p, ce->attributes); + if (ce->children) + free_all_elements (cfgst, p, ce->children); + ddsrt_free (p); + p = p1; } } } } -static void free_configured_elements(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) +static void free_configured_element (struct cfgst *cfgst, void *parent, struct cfgelem const * const ce) { - const struct cfgelem *ce; - for ( ce = cfgelem; ce && ce->name; ce++ ) { - struct cfgst_nodekey key; - struct cfgst_node *n; - if ( ce->name[0] == '>' ) /* moved, so don't care */ - continue; - key.e = ce; - if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { - if ( ce->free && n->count > n->failed ) - ce->free(cfgst, parent, ce); - } + struct cfgst_nodekey key; + struct cfgst_node *n; + if (ce->name[0] == '>') /* moved, so don't care */ + return; + key.e = ce; + key.p = parent; + if ((n = ddsrt_avl_lookup (&cfgst_found_treedef, &cfgst->found, &key)) != NULL) + { + if (ce->free && n->count > n->failed) + ce->free (cfgst, parent, ce); + n->count = n->failed = 0; + } - if ( ce->multiplicity == 1 ) { - if ( ce->children ) - free_configured_elements(cfgst, parent, ce->children); - if ( ce->attributes ) - free_configured_elements(cfgst, parent, ce->attributes); - } else { - struct config_listelem *p = cfg_deref_address(cfgst, parent, ce); - struct config_listelem *r; - while ( p ) { - if ( ce->attributes ) - free_all_elements(cfgst, p, ce->attributes); - if ( ce->children ) - free_all_elements(cfgst, p, ce->children); - r = p; - p = p->next; - ddsrt_free(r); - } + if (ce->multiplicity == 1) + { + if (ce->children) + free_configured_elements (cfgst, parent, ce->children); + if (ce->attributes) + free_configured_elements (cfgst, parent, ce->attributes); + } + else + { + /* FIXME: this used to require free_all_elements because there would be no record stored for + configuration elements within lists, but with that changed, I think this can now just use + free_configured_elements */ + struct config_listelem *p = cfg_deref_address (cfgst, parent, ce); + while (p) { + struct config_listelem * const p1 = p->next; + if (ce->attributes) + free_all_elements (cfgst, p, ce->attributes); + if (ce->children) + free_all_elements (cfgst, p, ce->children); + ddsrt_free (p); + p = p1; } } } -static int matching_name_index(const char *name_w_aliases, const char *name) +static void free_configured_elements (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - const char *ns = name_w_aliases, *p = strchr(ns, '|'); + for (const struct cfgelem *ce = cfgelem; ce && ce->name; ce++) + free_configured_element (cfgst, parent, ce); +} + +static int matching_name_index (const char *name_w_aliases, const char *name) +{ + const char *ns = name_w_aliases, *p = strchr (ns, '|'); int idx = 0; - while ( p ) { - if ( ddsrt_strncasecmp(ns, name, (size_t) (p - ns)) == 0 && name[p - ns] == 0 ) { + while (p) + { + if (ddsrt_strncasecmp (ns, name, (size_t) (p - ns)) == 0 && name[p - ns] == 0) + { /* ns upto the pipe symbol is a prefix of name, and name is terminated at that point */ return idx; } /* If primary name followed by '||' instead of '|', aliases are non-warning */ ns = p + 1 + (idx == 0 && p[1] == '|'); - p = strchr(ns, '|'); + p = strchr (ns, '|'); idx++; } - return (ddsrt_strcasecmp(ns, name) == 0) ? idx : -1; + return (ddsrt_strcasecmp (ns, name) == 0) ? idx : -1; } -static const struct cfgelem *lookup_redirect(const char *target) +static const struct cfgelem *lookup_element (const char *target) { const struct cfgelem *cfgelem = cyclonedds_root_cfgelems; - char *target_copy = ddsrt_strdup(target), *p1; + char *target_copy = ddsrt_strdup (target); const char *p = target_copy; - while ( p ) { - p1 = strchr(p, '/'); - if ( p1 ) *p1++ = 0; - for ( ; cfgelem->name; cfgelem++ ) { - /* not supporting multiple redirects */ - assert(cfgelem->name[0] != '>'); - if ( matching_name_index(cfgelem->name, p) >= 0 ) + while (p) + { + char *p1 = strchr (p, '/'); + if (p1) + *p1++ = 0; + for (; cfgelem->name; cfgelem++) + { + /* not supporting chained redirects */ + assert (cfgelem->name[0] != '>'); + if (matching_name_index (cfgelem->name, p) >= 0) break; } - if ( p1 ) { + if (p1) cfgelem = cfgelem->children; - } p = p1; } - ddsrt_free(target_copy); + ddsrt_free (target_copy); return cfgelem; } -static int proc_elem_open(void *varg, UNUSED_ARG(uintptr_t parentinfo), UNUSED_ARG(uintptr_t *eleminfo), const char *name) +static int proc_elem_open (void *varg, UNUSED_ARG (uintptr_t parentinfo), UNUSED_ARG (uintptr_t *eleminfo), const char *name) { struct cfgst * const cfgst = varg; - const struct cfgelem *cfgelem = cfgst_tos(cfgst); + + if (cfgst->implicit_toplevel == ITL_ALLOWED) + { + assert (cyclonedds_root_cfgelems[1].name == NULL); + if (ddsrt_strcasecmp (name, cyclonedds_root_cfgelems[0].name) == 0) + cfgst->implicit_toplevel = ITL_DISALLOWED; + else + { + int x = proc_elem_open (cfgst, 0, 0, cyclonedds_root_cfgelems[0].name); + assert (x > 0); + (void) x; + cfgst->implicit_toplevel = ITL_INSERTED; + } + } + + const struct cfgelem *cfgelem = cfgst_tos (cfgst); const struct cfgelem *cfg_subelem; int moved = 0; - if ( cfgelem == NULL ) { + + if (cfgelem == NULL) + { /* Ignoring, but do track the structure so we can know when to stop ignoring */ - cfgst_push(cfgst, 0, NULL, NULL); + cfgst_push (cfgst, 0, NULL, NULL); return 1; } - for ( cfg_subelem = cfgelem->children; cfg_subelem && cfg_subelem->name && strcmp(cfg_subelem->name, "*") != 0; cfg_subelem++ ) { + for (cfg_subelem = cfgelem->children; cfg_subelem && cfg_subelem->name && strcmp (cfg_subelem->name, "*") != 0; cfg_subelem++) + { const char *csename = cfg_subelem->name; int idx; moved = (csename[0] == '>'); - if ( moved ) + if (moved) csename++; - idx = matching_name_index(csename, name); -#if WARN_DEPRECATED_ALIAS - if ( idx > 0 ) { - if (csename[0] == '|') { - cfg_warning(cfgst, "'%s': deprecated setting", name); - } else { - int n = (int) (strchr(csename, '|') - csename); - if ( csename[n + 1] != '|' ) { - cfg_warning(cfgst, "'%s': deprecated alias for '%*.*s'", name, n, n, csename); + idx = matching_name_index (csename, name); + if (idx > 0) + { + if (csename[0] == '|') + cfg_warning (cfgst, "'%s': deprecated setting", name); + else + { + int n = (int) (strchr (csename, '|') - csename); + if (csename[n + 1] != '|') { + cfg_warning (cfgst, "'%s': deprecated alias for '%*.*s'", name, n, n, csename); } } } -#endif - if ( idx >= 0 ) { + if (idx >= 0) break; - } } - if ( cfg_subelem == NULL || cfg_subelem->name == NULL ) { - cfgst_push(cfgst, 0, NULL, NULL); - return cfg_error(cfgst, "%s: unknown element", name); - } else if ( strcmp(cfg_subelem->name, "*") == 0 ) { + if (cfg_subelem == NULL || cfg_subelem->name == NULL) + { + cfg_error (cfgst, "%s: unknown element", name); + cfgst_push (cfgst, 0, NULL, NULL); + return 0; + } + else if (strcmp (cfg_subelem->name, "*") == 0) + { /* Push a marker that we are to ignore this part of the DOM tree */ - cfgst_push(cfgst, 0, NULL, NULL); + cfgst_push (cfgst, 0, NULL, NULL); return 1; - } else { + } + else + { void *parent, *dynparent; - if ( moved ) { + if (moved) + { struct cfgelem const * const cfg_subelem_orig = cfg_subelem; - cfg_subelem = lookup_redirect(cfg_subelem->defvalue); -#if WARN_DEPRECATED_ALIAS - cfgst_push(cfgst, 0, cfg_subelem_orig, NULL); - cfg_warning(cfgst, "setting%s moved to //%s", cfg_subelem->children ? "s" : "", cfg_subelem_orig->defvalue); - cfgst_pop(cfgst); -#endif + cfg_subelem = lookup_element (cfg_subelem->defvalue); + cfgst_push (cfgst, 0, cfg_subelem_orig, NULL); + cfg_warning (cfgst, "setting%s moved to //%s", cfg_subelem->children ? "s" : "", cfg_subelem_orig->defvalue); + cfgst_pop (cfgst); } - parent = cfgst_parent(cfgst); - assert(cfgelem->init || cfgelem->multiplicity == 1); /*multi-items must have an init-func */ - if ( cfg_subelem->init ) { - if ( cfg_subelem->init(cfgst, parent, cfg_subelem) < 0 ) + parent = cfgst_parent (cfgst); + assert (cfgelem->init || cfgelem->multiplicity == 1); /* multi-items must have an init-func */ + if (cfg_subelem->init) + { + if (cfg_subelem->init (cfgst, parent, cfg_subelem) < 0) return 0; } - if ( cfg_subelem->multiplicity != 1 ) - dynparent = cfg_deref_address(cfgst, parent, cfg_subelem); - else + if (cfg_subelem->multiplicity == 1) dynparent = parent; + else + dynparent = cfg_deref_address (cfgst, parent, cfg_subelem); - cfgst_push(cfgst, 0, cfg_subelem, dynparent); + cfgst_push (cfgst, 0, cfg_subelem, dynparent); + + if (cfg_subelem == &cyclonedds_root_cfgelems[0]) + cfgst->source = (cfgst->source == 0) ? 1 : cfgst->source << 1; return 1; } } -static int proc_attr(void *varg, UNUSED_ARG(uintptr_t eleminfo), const char *name, const char *value) +static int proc_update_cfgelem (struct cfgst * cfgst, const struct cfgelem *ce, const char *value, bool isattr) { - /* All attributes are processed immediately after opening the element */ - struct cfgst * const cfgst = varg; - const struct cfgelem *cfgelem = cfgst_tos(cfgst); - const struct cfgelem *cfg_attr; - if ( cfgelem == NULL ) - return 1; - for ( cfg_attr = cfgelem->attributes; cfg_attr && cfg_attr->name; cfg_attr++ ) { - if ( ddsrt_strcasecmp(cfg_attr->name, name) == 0 ) - break; - } - if ( cfg_attr == NULL || cfg_attr->name == NULL ) - return cfg_error(cfgst, "%s: unknown attribute", name); - else { - void *parent = cfgst_parent(cfgst); - char *xvalue = ddsrt_expand_envvars(value); - int ok; - cfgst_push(cfgst, 1, cfg_attr, parent); - ok = do_update(cfgst, cfg_attr->update, parent, cfg_attr, xvalue, 0); - cfgst_pop(cfgst); - ddsrt_free(xvalue); - return ok; - } -} - -static int proc_elem_data(void *varg, UNUSED_ARG(uintptr_t eleminfo), const char *value) -{ - struct cfgst * const cfgst = varg; - const struct cfgelem *cfgelem = cfgst_tos(cfgst); - if ( cfgelem == NULL ) - return 1; - if ( cfgelem->update == 0 ) - return cfg_error(cfgst, "%s: no data expected", value); - else { - void *parent = cfgst_parent(cfgst); - char *xvalue = ddsrt_expand_envvars(value); - int ok; - cfgst_push(cfgst, 0, NULL, parent); - ok = do_update(cfgst, cfgelem->update, parent, cfgelem, xvalue, 0); - cfgst_pop(cfgst); - ddsrt_free(xvalue); - return ok; - } -} - -static int proc_elem_close(void *varg, UNUSED_ARG(uintptr_t eleminfo)) -{ - struct cfgst * const cfgst = varg; - const struct cfgelem * cfgelem = cfgst_tos(cfgst); - int ok = 1; - if ( cfgelem && cfgelem->multiplicity != 1 ) { - void *parent = cfgst_parent(cfgst); - int ok1; - ok1 = set_defaults(cfgst, parent, 1, cfgelem->attributes, 1); - ok = ok && ok1; - ok1 = set_defaults(cfgst, parent, 0, cfgelem->children, 1); - ok = ok && ok1; - } - cfgst_pop(cfgst); + void *parent = cfgst_parent (cfgst); + char *xvalue = ddsrt_expand_envvars (value); + int ok; + cfgst_push (cfgst, isattr, isattr ? ce : NULL, parent); + ok = do_update (cfgst, ce->update, parent, ce, xvalue, cfgst->source); + cfgst_pop (cfgst); + ddsrt_free (xvalue); return ok; } -static void proc_error(void *varg, const char *msg, int line) +static int proc_attr(void *varg, UNUSED_ARG (uintptr_t eleminfo), const char *name, const char *value) { + /* All attributes are processed immediately after opening the element */ struct cfgst * const cfgst = varg; - cfg_error(cfgst, "parser error %s at line %d", msg, line); + const struct cfgelem *cfgelem = cfgst_tos (cfgst); + const struct cfgelem *cfg_attr; + if (cfgelem == NULL) + return 1; + for (cfg_attr = cfgelem->attributes; cfg_attr && cfg_attr->name; cfg_attr++) + if (ddsrt_strcasecmp(cfg_attr->name, name) == 0) + break; + if (cfg_attr == NULL || cfg_attr->name == NULL) + return cfg_error (cfgst, "%s: unknown attribute", name); + else + return proc_update_cfgelem (cfgst, cfg_attr, value, true); } - -static int cfgst_node_cmp(const void *va, const void *vb) +static int proc_elem_data (void *varg, UNUSED_ARG (uintptr_t eleminfo), const char *value) { - return memcmp(va, vb, sizeof(struct cfgst_nodekey)); + struct cfgst * const cfgst = varg; + const struct cfgelem *cfgelem = cfgst_tos (cfgst); + if (cfgelem == NULL) + return 1; + if (cfgelem->update == 0) + return cfg_error (cfgst, "%s: no data expected", value); + else + return proc_update_cfgelem (cfgst, cfgelem, value, false); +} + +static int proc_elem_close (void *varg, UNUSED_ARG (uintptr_t eleminfo)) +{ + struct cfgst * const cfgst = varg; + const struct cfgelem * cfgelem = cfgst_tos (cfgst); + int ok = 1; + if (cfgelem && cfgelem->multiplicity != 1) + { + void *parent = cfgst_parent (cfgst); + int ok1; + ok1 = set_defaults (cfgst, parent, 1, cfgelem->attributes); + ok = ok && ok1; + ok1 = set_defaults (cfgst, parent, 0, cfgelem->children); + ok = ok && ok1; + } + cfgst_pop (cfgst); + return ok; +} + +static void proc_error (void *varg, const char *msg, int line) +{ + struct cfgst * const cfgst = varg; + cfg_error (cfgst, "parser error %s at line %d", msg, line); +} + +static int cfgst_node_cmp (const void *va, const void *vb) +{ + return memcmp (va, vb, sizeof (struct cfgst_nodekey)); } #ifdef DDSI_INCLUDE_NETWORK_CHANNELS -static int set_default_channel(struct config *cfg) +static int set_default_channel (struct config *cfg) { - if ( cfg->channels == NULL ) { + if (cfg->channels == NULL) + { /* create one default channel if none configured */ struct config_channel_listelem *c; - if ( (c = ddsrt_malloc(sizeof(*c))) == NULL ) + if ((c = ddsrt_malloc (sizeof (*c))) == NULL) return ERR_OUT_OF_MEMORY; c->next = NULL; - c->name = ddsrt_strdup("user"); + c->name = ddsrt_strdup ("user"); c->priority = 0; c->resolution = 1 * T_MILLISECOND; #ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING @@ -2592,14 +2448,14 @@ static int set_default_channel(struct config *cfg) return 0; } -static int sort_channels_cmp(const void *va, const void *vb) +static int sort_channels_cmp (const void *va, const void *vb) { const struct config_channel_listelem * const *a = va; const struct config_channel_listelem * const *b = vb; return ((*a)->priority == (*b)->priority) ? 0 : ((*a)->priority < (*b)->priority) ? -1 : 1; } -static int sort_channels_check_nodups(struct config *cfg) +static int sort_channels_check_nodups (struct config *cfg) { /* Selecting a channel is much easier & more elegant if the channels are sorted on descending priority. While we do retain the list @@ -2610,45 +2466,71 @@ static int sort_channels_check_nodups(struct config *cfg) int result; n = 0; - for ( c = cfg->channels; c; c = c->next ) + for (c = cfg->channels; c; c = c->next) n++; assert(n > 0); - ary = ddsrt_malloc(n * sizeof(*ary)); + ary = ddsrt_malloc (n * sizeof (*ary)); i = 0; - for ( c = cfg->channels; c; c = c->next ) + for (c = cfg->channels; c; c = c->next) ary[i++] = c; - qsort(ary, n, sizeof(*ary), sort_channels_cmp); + qsort (ary, n, sizeof (*ary), sort_channels_cmp); result = 0; - for ( i = 0; i < n - 1; i++ ) { - if ( ary[i]->priority == ary[i + 1]->priority ) { + for (i = 0; i < n - 1; i++) { + if (ary[i]->priority == ary[i + 1]->priority) { DDS_ERROR("config: duplicate channel definition for priority %u: channels %s and %s\n", ary[i]->priority, ary[i]->name, ary[i + 1]->name); result = ERR_ENTITY_EXISTS; } } - if ( result == 0 ) { + if (result == 0) + { cfg->channels = ary[0]; - for ( i = 0; i < n - 1; i++ ) + for (i = 0; i < n - 1; i++) ary[i]->next = ary[i + 1]; ary[i]->next = NULL; cfg->max_channel = ary[i]; } - ddsrt_free(ary); + ddsrt_free (ary); return result; } #endif /* DDSI_INCLUDE_NETWORK_CHANNELS */ -struct cfgst * config_init (const char *configfile) +static FILE *config_open_file (char *tok, char **cursor) +{ + assert (*tok && !(isspace ((unsigned char) *tok) || *tok == ',')); + FILE *fp; + char *comma; + if ((comma = strchr (tok, ',')) == NULL) + *cursor = NULL; + else + { + *comma = 0; + *cursor = comma + 1; + } + DDSRT_WARNING_MSVC_OFF(4996); + if ((fp = fopen (tok, "r")) == NULL) + { + if (strncmp (tok, "file://", 7) != 0 || (fp = fopen (tok + 7, "r")) == NULL) + { + DDS_ERROR ("can't open configuration file %s\n", tok); + return NULL; + } + } + DDSRT_WARNING_MSVC_ON(4996); + return fp; +} + +struct cfgst *config_init (const char *configfile) { int ok = 1; struct cfgst *cfgst; - memset(&config, 0, sizeof(config)); + memset (&config, 0, sizeof (config)); config.tracingOutputFile = stderr; config.enabled_logcats = DDS_LC_ERROR | DDS_LC_WARNING; @@ -2659,16 +2541,17 @@ struct cfgst * config_init (const char *configfile) ends up on the right value */ config.domainId.value = 0; - cfgst = ddsrt_malloc(sizeof(*cfgst)); - memset(cfgst, 0, sizeof(*cfgst)); + cfgst = ddsrt_malloc (sizeof (*cfgst)); + memset (cfgst, 0, sizeof (*cfgst)); - ddsrt_avl_init(&cfgst_found_treedef, &cfgst->found); + ddsrt_avl_init (&cfgst_found_treedef, &cfgst->found); cfgst->cfg = &config; cfgst->error = 0; + cfgst->source = 0; /* configfile == NULL will get you the default configuration */ if (configfile) { - char *copy = ddsrt_strdup(configfile), *cursor = copy; + char *copy = ddsrt_strdup (configfile), *cursor = copy; struct ddsrt_xmlp_callbacks cb; cb.attr = proc_attr; @@ -2677,64 +2560,58 @@ struct cfgst * config_init (const char *configfile) cb.elem_open = proc_elem_open; cb.error = proc_error; - while (ok && cursor && cursor[0]) { + while (*cursor && (isspace ((unsigned char) *cursor) || *cursor == ',')) + cursor++; + while (ok && cursor && cursor[0]) + { struct ddsrt_xmlp_state *qx; FILE *fp; char *tok; tok = cursor; - if (tok[0] == '<') { + if (tok[0] == '<') + { /* Read XML directly from input string */ qx = ddsrt_xmlp_new_string (tok, cfgst, &cb); - ddsrt_xmlp_set_options (qx, DDSRT_XMLP_ANONYMOUS_CLOSE_TAG); + ddsrt_xmlp_set_options (qx, DDSRT_XMLP_ANONYMOUS_CLOSE_TAG | DDSRT_XMLP_MISSING_CLOSE_AS_EOF); fp = NULL; - } else { - char *comma; - if ((comma = strchr (cursor, ',')) == NULL) { - cursor = NULL; - } else { - *comma = 0; - cursor = comma + 1; - } - DDSRT_WARNING_MSVC_OFF(4996); - if ((fp = fopen(tok, "r")) == NULL) { - if (strncmp(tok, "file://", 7) != 0 || (fp = fopen(tok + 7, "r")) == NULL) { - DDS_ERROR("can't open configuration file %s\n", tok); - ddsrt_free(copy); - ddsrt_free(cfgst); - return NULL; - } - } - DDSRT_WARNING_MSVC_ON(4996); - qx = ddsrt_xmlp_new_file(fp, cfgst, &cb); } - cfgst_push(cfgst, 0, &root_cfgelem, &config); + else if ((fp = config_open_file (tok, &cursor)) == NULL) + { + ddsrt_free (copy); + goto error; + } + else + { + qx = ddsrt_xmlp_new_file (fp, cfgst, &cb); + } - ok = (ddsrt_xmlp_parse(qx) >= 0) && !cfgst->error; + cfgst->implicit_toplevel = (fp == NULL) ? ITL_ALLOWED : ITL_DISALLOWED; + cfgst_push (cfgst, 0, &root_cfgelem, &config); + ok = (ddsrt_xmlp_parse (qx) >= 0) && !cfgst->error; + assert (!ok || + (cfgst->path_depth == 1 && cfgst->implicit_toplevel != ITL_INSERTED) || + (cfgst->path_depth == 2 && cfgst->implicit_toplevel == ITL_INSERTED)); /* Pop until stack empty: error handling is rather brutal */ - assert(!ok || cfgst->path_depth == 1); - while (cfgst->path_depth > 0) { - cfgst_pop(cfgst); - } - if (fp) { - fclose(fp); - } else if (ok) { + while (cfgst->path_depth > 0) + cfgst_pop (cfgst); + if (fp != NULL) + fclose (fp); + else if (ok) cursor = tok + ddsrt_xmlp_get_bufpos (qx); - } - ddsrt_xmlp_free(qx); - while (cursor && cursor[0] == ',') { - cursor++; + ddsrt_xmlp_free (qx); + assert (fp == NULL || cfgst->implicit_toplevel != ITL_INSERTED); + if (cursor) + { + while (*cursor && (isspace ((unsigned char) cursor[0]) || cursor[0] == ',')) + cursor++; } } - ddsrt_free(copy); + ddsrt_free (copy); } /* Set defaults for everything not set that we have a default value for, signal errors for things unset but without a default. */ - { - int ok1 = set_defaults(cfgst, cfgst->cfg, 0, root_cfgelems, 0); - ok = ok && ok1; - } - + ok = ok && set_defaults (cfgst, cfgst->cfg, 0, root_cfgelems); /* Compatibility settings of IPv6, TCP -- a bit too complicated for the poor framework */ @@ -2774,36 +2651,37 @@ struct cfgst * config_init (const char *configfile) #ifdef DDSI_INCLUDE_NETWORK_CHANNELS /* Default channel gets set outside set_defaults -- a bit too complicated for the poor framework */ - - if ( set_default_channel(cfgst->cfg) < 0 ) { + if (set_default_channel (cfgst->cfg) < 0) ok = 0; - } - if ( cfgst->cfg->channels && sort_channels_check_nodups(cfgst->cfg) < 0 ) { + if (cfgst->cfg->channels && sort_channels_check_nodups (cfgst->cfg) < 0) ok = 0; - } #endif #ifdef DDSI_INCLUDE_ENCRYPTION /* Check security profiles */ { struct config_securityprofile_listelem *s = config.securityProfiles; - while ( s ) { - switch ( s->cipher ) { + while (s) + { + switch (s->cipher) + { case Q_CIPHER_UNDEFINED: case Q_CIPHER_NULL: /* nop */ - if ( s->key && strlen(s->key) > 0 ) { - DDS_INFO("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: %s: cipher key not required\n", s->key); - } + if (s->key && strlen(s->key) > 0) + DDS_INFO ("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: %s: cipher key not required\n", s->key); break; default: /* read the cipherkey if present */ - if ( !s->key || strlen(s->key) == 0 ) { - DDS_ERROR("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: cipher key missing\n"); + if (!s->key || strlen(s->key) == 0) + { + DDS_ERROR ("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: cipher key missing\n"); ok = 0; - } else if ( q_security_plugin.valid_uri && !(q_security_plugin.valid_uri) (s->cipher, s->key) ) { - DDS_ERROR("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: %s : incorrect key\n", s->key); + } + else if (q_security_plugin.valid_uri && !(q_security_plugin.valid_uri) (s->cipher, s->key)) + { + DDS_ERROR ("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: %s : incorrect key\n", s->key); ok = 0; } } @@ -2821,17 +2699,20 @@ struct cfgst * config_init (const char *configfile) { struct config_networkpartition_listelem *p = config.networkPartitions; config.nof_networkPartitions = 0; - while ( p ) { + while (p) + { #ifdef DDSI_INCLUDE_ENCRYPTION - if ( ddsrt_strcasecmp(p->profileName, "null") == 0 ) + if (ddsrt_strcasecmp(p->profileName, "null") == 0) p->securityProfile = NULL; - else { + else + { struct config_securityprofile_listelem *s = config.securityProfiles; - while ( s && ddsrt_strcasecmp(p->profileName, s->name) != 0 ) + while (s && ddsrt_strcasecmp(p->profileName, s->name) != 0) s = s->next; - if ( s ) + if (s) p->securityProfile = s; - else { + else + { DDS_ERROR("config: DDSI2Service/Partitioning/NetworkPartitions/NetworkPartition[@securityprofile]: %s: unknown securityprofile\n", p->profileName); ok = 0; } @@ -2852,15 +2733,16 @@ struct cfgst * config_init (const char *configfile) and signal errors if partitions do not exist */ { struct config_partitionmapping_listelem * m = config.partitionMappings; - while ( m ) { + while (m) + { struct config_networkpartition_listelem * p = config.networkPartitions; - while ( p && ddsrt_strcasecmp(m->networkPartition, p->name) != 0 ) { + while (p && ddsrt_strcasecmp(m->networkPartition, p->name) != 0) p = p->next; - } - if ( p ) { + if (p) m->partition = p; - } else { - DDS_ERROR("config: DDSI2Service/Partitioning/PartitionMappings/PartitionMapping[@networkpartition]: %s: unknown partition\n", m->networkPartition); + else + { + DDS_ERROR ("config: DDSI2Service/Partitioning/PartitionMappings/PartitionMapping[@networkpartition]: %s: unknown partition\n", m->networkPartition); ok = 0; } m = m->next; @@ -2871,89 +2753,94 @@ struct cfgst * config_init (const char *configfile) /* Now switch to configured tracing settings */ config.enabled_logcats = enabled_logcats; - if ( !ok ) { - free_configured_elements(cfgst, cfgst->cfg, root_cfgelems); - } - - if ( ok ) { + if (ok) + { config.valid = 1; return cfgst; - } else { - ddsrt_avl_free(&cfgst_found_treedef, &cfgst->found, ddsrt_free); - ddsrt_free(cfgst); - return NULL; } + +error: + free_configured_elements (cfgst, cfgst->cfg, root_cfgelems); + ddsrt_avl_free (&cfgst_found_treedef, &cfgst->found, ddsrt_free); + ddsrt_free (cfgst); + return NULL; } -void config_print_cfgst(struct cfgst *cfgst) +void config_print_cfgst (struct cfgst *cfgst) { - if ( cfgst == NULL ) + if (cfgst == NULL) return; - print_configitems(cfgst, cfgst->cfg, 0, root_cfgelems, 0); + print_configitems (cfgst, cfgst->cfg, 0, root_cfgelems, 0); } -void config_fini(struct cfgst *cfgst) +void config_free_source_info (struct cfgst *cfgst) { - assert(cfgst); - assert(cfgst->cfg == &config); - assert(config.valid); + assert (!cfgst->error); + ddsrt_avl_free (&cfgst_found_treedef, &cfgst->found, ddsrt_free); +} - free_all_elements(cfgst, cfgst->cfg, root_cfgelems); - dds_set_log_file(stderr); - dds_set_trace_file(stderr); +void config_fini (struct cfgst *cfgst) +{ + assert (cfgst); + assert (cfgst->cfg == &config); + assert (config.valid); + + free_all_elements (cfgst, cfgst->cfg, root_cfgelems); + dds_set_log_file (stderr); + dds_set_trace_file (stderr); if (config.tracingOutputFile && config.tracingOutputFile != stdout && config.tracingOutputFile != stderr) { fclose(config.tracingOutputFile); } - memset(&config, 0, sizeof(config)); + memset (&config, 0, sizeof (config)); config.valid = 0; - ddsrt_avl_free(&cfgst_found_treedef, &cfgst->found, ddsrt_free); - ddsrt_free(cfgst); + ddsrt_avl_free (&cfgst_found_treedef, &cfgst->found, ddsrt_free); + ddsrt_free (cfgst); } #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS -static char *get_partition_search_pattern(const char *partition, const char *topic) +static char *get_partition_search_pattern (const char *partition, const char *topic) { - size_t sz = strlen(partition) + strlen(topic) + 2; - char *pt = ddsrt_malloc(sz); - snprintf(pt, sz, "%s.%s", partition, topic); + size_t sz = strlen (partition) + strlen (topic) + 2; + char *pt = ddsrt_malloc (sz); + snprintf (pt, sz, "%s.%s", partition, topic); return pt; } -struct config_partitionmapping_listelem *find_partitionmapping(const char *partition, const char *topic) +struct config_partitionmapping_listelem *find_partitionmapping (const char *partition, const char *topic) { - char *pt = get_partition_search_pattern(partition, topic); + char *pt = get_partition_search_pattern (partition, topic); struct config_partitionmapping_listelem *pm; - for ( pm = config.partitionMappings; pm; pm = pm->next ) - if ( WildcardOverlap(pt, pm->DCPSPartitionTopic) ) + for (pm = config.partitionMappings; pm; pm = pm->next) + if (WildcardOverlap (pt, pm->DCPSPartitionTopic)) break; - ddsrt_free(pt); + ddsrt_free (pt); return pm; } -struct config_networkpartition_listelem *find_networkpartition_by_id(uint32_t id) +struct config_networkpartition_listelem *find_networkpartition_by_id (uint32_t id) { struct config_networkpartition_listelem *np; - for ( np = config.networkPartitions; np; np = np->next ) - if ( np->partitionId == id ) + for (np = config.networkPartitions; np; np = np->next) + if (np->partitionId == id) return np; return 0; } -int is_ignored_partition(const char *partition, const char *topic) +int is_ignored_partition (const char *partition, const char *topic) { - char *pt = get_partition_search_pattern(partition, topic); + char *pt = get_partition_search_pattern (partition, topic); struct config_ignoredpartition_listelem *ip; - for ( ip = config.ignoredPartitions; ip; ip = ip->next ) - if ( WildcardOverlap(pt, ip->DCPSPartitionTopic) ) + for (ip = config.ignoredPartitions; ip; ip = ip->next) + if (WildcardOverlap(pt, ip->DCPSPartitionTopic)) break; - ddsrt_free(pt); + ddsrt_free (pt); return ip != NULL; } #endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */ #ifdef DDSI_INCLUDE_NETWORK_CHANNELS -struct config_channel_listelem *find_channel(nn_transport_priority_qospolicy_t transport_priority) +struct config_channel_listelem *find_channel (nn_transport_priority_qospolicy_t transport_priority) { struct config_channel_listelem *c; /* Channel selection is to use the channel with the lowest priority @@ -2961,9 +2848,10 @@ struct config_channel_listelem *find_channel(nn_transport_priority_qospolicy_t t highest priority. */ assert(config.channels != NULL); assert(config.max_channel != NULL); - for ( c = config.channels; c; c = c->next ) { + for (c = config.channels; c; c = c->next) + { assert(c->next == NULL || c->next->priority > c->priority); - if ( transport_priority.value <= c->priority ) + if (transport_priority.value <= c->priority) return c; } return config.max_channel; diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 2c4601d..b2c947d 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -584,8 +584,10 @@ int rtps_config_prep (struct cfgst *cfgst) thread_states_init (max_threads); } - /* Now the per-thread-log-buffers are set up, so print the configuration */ + /* Now the per-thread-log-buffers are set up, so print the configuration. After this there + is no value to the source information for the various configuration elements, so free those. */ config_print_cfgst (cfgst); + config_free_source_info (cfgst); return 0; err_config_late_error: diff --git a/src/ddsrt/include/dds/ddsrt/xmlparser.h b/src/ddsrt/include/dds/ddsrt/xmlparser.h index e33815b..9c29a89 100644 --- a/src/ddsrt/include/dds/ddsrt/xmlparser.h +++ b/src/ddsrt/include/dds/ddsrt/xmlparser.h @@ -36,9 +36,9 @@ extern "C" { struct ddsrt_xmlp_state; -#define DDSRT_XMLP_REQUIRE_EOF 1u /* set by default; if not set, junk may follow top-level closing tag */ -#define DDSRT_XMLP_ANONYMOUS_CLOSE_TAG 2u /* clear by default; if set allow closing an element with instead of */ - +#define DDSRT_XMLP_REQUIRE_EOF 1u /* set by default; if not set, junk may follow top-level closing tag */ +#define DDSRT_XMLP_ANONYMOUS_CLOSE_TAG 2u /* clear by default; if set allow closing an element with instead of */ +#define DDSRT_XMLP_MISSING_CLOSE_AS_EOF 4u /* clear by default; if set, treat missing close tag as EOF */ DDS_EXPORT struct ddsrt_xmlp_state *ddsrt_xmlp_new_file (FILE *fp, void *varg, const struct ddsrt_xmlp_callbacks *cb); DDS_EXPORT struct ddsrt_xmlp_state *ddsrt_xmlp_new_string (const char *string, void *varg, const struct ddsrt_xmlp_callbacks *cb); DDS_EXPORT void ddsrt_xmlp_set_options (struct ddsrt_xmlp_state *st, unsigned options); diff --git a/src/ddsrt/src/xmlparser.c b/src/ddsrt/src/xmlparser.c index ded4337..193522b 100644 --- a/src/ddsrt/src/xmlparser.c +++ b/src/ddsrt/src/xmlparser.c @@ -35,6 +35,7 @@ struct ddsrt_xmlp_state { size_t cbufn; /* number of bytes in cbuf (cbufp <= cbufn) */ size_t cbufmax; /* allocated size of cbuf (cbufn <= cbufmax) */ size_t cbufmark; /* NORMARKER or marker position (cbufmark <= cbufp) for rewinding */ + int eof; /* fake EOF (for treating missing close tags as EOF) */ char *cbuf; /* parser input buffer */ FILE *fp; /* file to refill cbuf from, or NULL if parsing a string */ int line; /* current line number */ @@ -97,6 +98,7 @@ static void ddsrt_xmlp_new_common (struct ddsrt_xmlp_state *st) { st->cbufp = 0; st->cbufmark = NOMARKER; + st->eof = 0; st->tpp = 0; st->tpescp = 0; st->tpsz = 1024; @@ -170,6 +172,9 @@ void ddsrt_xmlp_free (struct ddsrt_xmlp_state *st) static int make_chars_available (struct ddsrt_xmlp_state *st, size_t nmin) { size_t n, pos; + if (st->eof) { + return 0; + } pos = (st->cbufmark != NOMARKER) ? st->cbufmark : st->cbufp; assert (st->cbufn >= st->cbufp); assert (st->cbufmax >= st->cbufn); @@ -215,6 +220,11 @@ static void discard_input_marker (struct ddsrt_xmlp_state *st) st->linemark = 0; } +static int have_input_marker (struct ddsrt_xmlp_state *st) +{ + return (st->cbufmark != NOMARKER); +} + static void rewind_to_input_marker (struct ddsrt_xmlp_state *st) { assert (st->cbufmark != NOMARKER); @@ -668,7 +678,7 @@ static int parse_element (struct ddsrt_xmlp_state *st, uintptr_t parentinfo) if (save_payload (&content, st, 1) < 0) { PE_ERROR ("invalid character sequence", 0); } else if (content != NULL) { - if(*content != '\0') { + if (*content != '\0') { ret = st->cb.elem_data (st->varg, eleminfo, content); ddsrt_free (content); if (ret < 0) { @@ -680,12 +690,22 @@ static int parse_element (struct ddsrt_xmlp_state *st, uintptr_t parentinfo) } } st->nest--; + set_input_marker (st); if (((tok = next_token (st, &ename)) != TOK_CLOSE_TAG && tok != TOK_SHORTHAND_CLOSE_TAG) || next_char (st) != '>') { - PE_LOCAL_ERROR ("expecting closing tag", name); + if (!(st->options & DDSRT_XMLP_MISSING_CLOSE_AS_EOF)) { + PE_LOCAL_ERROR ("expecting closing tag", name); + } else { + rewind_to_input_marker (st); + st->eof = 1; + tok = TOK_SHORTHAND_CLOSE_TAG; + } } if (tok != TOK_SHORTHAND_CLOSE_TAG && strcmp (name, ename) != 0) { PE_LOCAL_ERROR ("open/close tag mismatch", ename); } + if (have_input_marker (st)) { + discard_input_marker (st); + } ret = st->cb.elem_close (st->varg, eleminfo); goto ok; default: From d16264fd82133158777d0c233353cc535045f800 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 7 May 2019 15:12:31 +0800 Subject: [PATCH 070/178] a read/take returning no data must be a no-op In all cases where read/take allocates memory for storing samples but the result turns out to be an empty set, the (observable) state of the system should end up unchanged. It turns out several cases were/are considered: * application supplies buffers (i.e., buf[0] != NULL): no memory allocated, so no issue. * reader has no cached set ("m_loan" in the current code): read/take allocated memory, cached the address and marked it as in use ("m_loan_out"), and modified buf[0] (and subsequent entries). To undo this on returning an empty set, it now: resets the "m_loan_out" flag to allow the cached buffer to be reused, and sets buf[0] back to NULL. * reader has a cached set, but it is not marked in use: read/take marked it as in use and modified buf[0] (and subsequent entries). To undo this, it now resets "m_loan_out" to indicate the cached buffer is not in use, and sets buf[0] back to NULL. * reader has a cached set that is currently in use: read/take allocated memory and updated buf[0] (and subsequent entries) but left the cached state alone. To undo this, it now frees the memory and sets buf[0] back to NULL. With this, in any path where the application lets dds_read/dds_take allocate memory for the samples: * it can still safely call dds_return_loan with buf[0] and the actual return value of read/take (even if an error code), and whatever memory was allocated will not be leaked; * but it no longer has to do so when the result was empty (or error). Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_read.c | 39 ++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 2791a44..1702a25 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -94,6 +94,10 @@ dds_read_impl( dds_retcode_t rc; struct dds_reader * rd; struct dds_readcond * cond; + unsigned nodata_cleanups = 0; +#define NC_CLEAR_LOAN_OUT 1u +#define NC_FREE_BUF 2u +#define NC_RESET_BUF 4u if (buf == NULL) { DDS_ERROR("The provided buffer is NULL\n"); @@ -140,21 +144,25 @@ dds_read_impl( /* Allocate, use or reallocate loan cached on reader */ if (rd->m_loan_out) { ddsi_sertopic_realloc_samples (buf, rd->m_topic->m_stopic, NULL, 0, maxs); + nodata_cleanups = NC_FREE_BUF | NC_RESET_BUF; } else { if (rd->m_loan) { if (rd->m_loan_size < maxs) { ddsi_sertopic_realloc_samples (buf, rd->m_topic->m_stopic, rd->m_loan, rd->m_loan_size, maxs); rd->m_loan = buf[0]; rd->m_loan_size = maxs; + nodata_cleanups = NC_RESET_BUF; } else { - buf[0] = rd->m_loan; + buf[0] = rd->m_loan; + nodata_cleanups = NC_RESET_BUF; } - } else { - ddsi_sertopic_realloc_samples (buf, rd->m_topic->m_stopic, NULL, 0, maxs); - rd->m_loan = buf[0]; - rd->m_loan_size = maxs; - } + } else { + ddsi_sertopic_realloc_samples (buf, rd->m_topic->m_stopic, NULL, 0, maxs); + rd->m_loan = buf[0]; + rd->m_loan_size = maxs; + } rd->m_loan_out = true; + nodata_cleanups |= NC_CLEAR_LOAN_OUT; } } @@ -169,9 +177,24 @@ dds_read_impl( ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); if (take) { - ret = (dds_return_t)dds_rhc_take(rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); + ret = (dds_return_t) dds_rhc_take (rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); } else { - ret = (dds_return_t)dds_rhc_read(rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); + ret = (dds_return_t) dds_rhc_read (rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); + } + + /* if no data read, restore the state to what it was before the call, with the sole + exception of holding on to a buffer we just allocated and that is pointed to by + rd->m_loan */ + if (ret <= 0 && nodata_cleanups) { + if (nodata_cleanups & NC_CLEAR_LOAN_OUT) { + rd->m_loan_out = false; + } + if (nodata_cleanups & NC_FREE_BUF) { + ddsi_sertopic_free_samples (rd->m_topic->m_stopic, buf[0], maxs, DDS_FREE_ALL); + } + if (nodata_cleanups & NC_RESET_BUF) { + buf[0] = NULL; + } } dds_read_unlock(rd, cond); From d91e7b34c9134c035c507ea2f27a2968b5b556ad Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 7 May 2019 15:14:34 +0800 Subject: [PATCH 071/178] fix init leak if network interface not found If at startup the requested interface cannot be found (or no suitable interface exists), the code failed to release all memory allocated in the process. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_init.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index b2c947d..df26b1d 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -1330,13 +1330,10 @@ err_set_ext_address: ddsrt_free (n); } err_set_recvips: - { - int i; - for (i = 0; i < gv.n_interfaces; i++) - ddsrt_free (gv.interfaces[i].name); - } err_find_own_ip: - ddsi_tran_factories_fini (); + for (int i = 0; i < gv.n_interfaces; i++) + ddsrt_free (gv.interfaces[i].name); + ddsi_tran_factories_fini (); err_udp_tcp_init: if (config.tp_enable) ddsrt_thread_pool_free (gv.thread_pool); @@ -1665,11 +1662,8 @@ DDSRT_WARNING_MSVC_ON(6001); ddsrt_free (n); } - { - int i; - for (i = 0; i < (int) gv.n_interfaces; i++) - ddsrt_free (gv.interfaces[i].name); - } + for (int i = 0; i < (int) gv.n_interfaces; i++) + ddsrt_free (gv.interfaces[i].name); ddsi_serdatapool_free (gv.serpool); nn_xmsgpool_free (gv.xmsgpool); From 3067a69c92715a19861f13302639d5a9a8943f38 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 10 May 2019 17:59:06 +0800 Subject: [PATCH 072/178] validate and normalize received CDR data The CDR deserializer failed to check it was staying within the bounds of the received data, and it turns out it also was inconsistent in its interpretation of the (undocumented) serializer instructions. This commit adds some information on the instruction format obtained by reverse engineering the code and studying the output of the IDL preprocessor, and furthermore changes a lot of the types used in the (de)serializer code to have some more compiler support. The IDL preprocessor is untouched and the generated instructinos do exactly the same thing (except where change was needed). The bulk of this commit replaces the implementation of the (de)serializer. It is still rather ugly, but at least the very long functions with several levels of nested conditions and switch statements have been split out into multiple functions. Most of these have single call-sites, so the compiler hopefully inlines them nicely. The other important thing is that it adds a "normalize" function that validates the structure of the CDR and performs byteswapping if necessary. This means the deserializer can now assume a well-formed input in native byte-order. Checks and conditional byteswaps have been removed accordingly. It changes some types to make a compile-time distinction between read-only, native-endianness input, a native-endianness output, and a big-endian output for dealing with key hashes. This should reduce the risk of accidentally mixing endianness or modifying an input stream. The preprocessor has been modified to indicate the presence of unions in a topic type in the descriptor flags. If a union is present, any memory allocated in a sample is freed first and the sample is zero'd out prior to deserializing the new value. This is to prevent reading garbage pointers for strings and sequences when switching union cases. The test tool has been included in the commit but it does not get run by itself. Firstly, it requires the presence of OpenSplice DDS as an alternative implementation to check the CDR processing against. Secondly, it takes quite a while to run and is of no interest unless one changes something in the (de)serialization. Finally, I have no idea why there was a "CDR stream" interface among the public functions. The existing interfaces are fundamentally broken by the removal of arbitrary-endianness streams, and the interfaces were already incapable of proper error notification. So, they have been removed. Signed-off-by: Erik Boasson --- src/core/ddsc/CMakeLists.txt | 3 - src/core/ddsc/include/dds/dds.h | 1 - .../ddsc/include/dds/ddsc/dds_public_impl.h | 172 +- .../ddsc/include/dds/ddsc/dds_public_stream.h | 108 - src/core/ddsc/src/dds__key.h | 35 - src/core/ddsc/src/dds__stream.h | 87 +- src/core/ddsc/src/dds_alloc.c | 2 + src/core/ddsc/src/dds_key.c | 126 - src/core/ddsc/src/dds_serdata_builtintopic.c | 1 - src/core/ddsc/src/dds_stream.c | 3000 +++++++++-------- .../include/dds/ddsi/ddsi_serdata_default.h | 9 +- src/core/ddsi/src/ddsi_serdata_default.c | 189 +- src/core/ddsi/src/q_receive.c | 7 +- src/core/xtests/cdrtest/CMakeLists.txt | 46 + src/core/xtests/cdrtest/cdrtest.pl | 403 +++ .../cyclonedds/generator/ArrayType.java | 10 + .../cyclonedds/generator/BasicType.java | 5 + .../generator/BoundedStringType.java | 5 + .../cyclonedds/generator/EnumType.java | 5 + .../cyclonedds/generator/GenVisitor.java | 4 + .../cyclonedds/generator/SequenceType.java | 10 + .../cyclonedds/generator/StructType.java | 17 + .../eclipse/cyclonedds/generator/Type.java | 1 + .../cyclonedds/generator/TypedefType.java | 5 + .../cyclonedds/generator/UnionType.java | 5 + 25 files changed, 2315 insertions(+), 1941 deletions(-) delete mode 100644 src/core/ddsc/include/dds/ddsc/dds_public_stream.h delete mode 100644 src/core/ddsc/src/dds__key.h delete mode 100644 src/core/ddsc/src/dds_key.c create mode 100644 src/core/xtests/cdrtest/CMakeLists.txt create mode 100644 src/core/xtests/cdrtest/cdrtest.pl diff --git a/src/core/ddsc/CMakeLists.txt b/src/core/ddsc/CMakeLists.txt index a97ccda..4af6cb5 100644 --- a/src/core/ddsc/CMakeLists.txt +++ b/src/core/ddsc/CMakeLists.txt @@ -24,7 +24,6 @@ PREPEND(srcs_ddsc "${CMAKE_CURRENT_LIST_DIR}/src" dds_qos.c dds_handles.c dds_entity.c - dds_key.c dds_querycond.c dds_topic.c dds_listener.c @@ -48,7 +47,6 @@ PREPEND(hdrs_public_ddsc "$ +#include #include "dds/export.h" #include "dds/ddsc/dds_public_alloc.h" -#include "dds/ddsc/dds_public_stream.h" #if defined (__cplusplus) extern "C" { @@ -71,6 +72,7 @@ dds_topic_descriptor_t; #define DDS_TOPIC_NO_OPTIMIZE 0x0001 #define DDS_TOPIC_FIXED_KEY 0x0002 +#define DDS_TOPIC_CONTAINS_UNION 0x0004 /* Masks for read condition, read, take: there is only one mask here, @@ -119,89 +121,119 @@ typedef int32_t dds_domainid_t; /* Topic encoding instruction types */ -#define DDS_OP_RTS 0x00000000 -#define DDS_OP_ADR 0x01000000 -#define DDS_OP_JSR 0x02000000 -#define DDS_OP_JEQ 0x03000000 +enum dds_stream_opcode { + /* return from subroutine, exits top-level + [RTS, 0, 0, 0] */ + DDS_OP_RTS = 0x00 << 24, + /* data field + [ADR, nBY, 0, k] [offset] + [ADR, STR, 0, k] [offset] + [ADR, BST, 0, k] [offset] [bound] + [ADR, SEQ, nBY, 0] [offset] + [ADR, SEQ, STR, 0] [offset] + [ADR, SEQ, BST, 0] [offset] [bound] + [ADR, SEQ, s, 0] [offset] [elem-size] [next-insn, elem-insn] + where s = {SEQ,ARR,UNI,STU} + [ADR, ARR, nBY, k] [offset] [alen] + [ADR, ARR, STR, 0] [offset] [alen] + [ADR, ARR, BST, 0] [offset] [alen] [0] [bound] + [ADR, ARR, s, 0] [offset] [alen] [next-insn, elem-insn] [elem-size] + where s = {SEQ,ARR,UNI,STU} + [ADR, UNI, d, z] [offset] [alen] [next-insn, cases] + where + d = discriminant type of {1BY,2BY,4BY} + z = default present/not present (DDS_OP_FLAG_DEF) + offset = discriminant offset + followed by alen case labels: in JEQ format + note: [ADR, STU, ...] is illegal + where + s = subtype + k = key/not key (DDS_OP_FLAG_KEY) + [offset] = field offset from start of element in memory + [elem-size] = element size in memory + [bound] = string bound + 1 + [alen] = array length, number of cases + [next-insn] = (unsigned 16 bits) offset to instruction for next field, from start of insn + [elem-insn] = (unsigned 16 bits) offset to first instruction for element, from start of insn + [cases] = (unsigned 16 bits) offset to first case label, from start of insn + */ + DDS_OP_ADR = 0x01 << 24, + /* jump-to-subroutine (apparently not used at the moment) + [JSR, 0, e] + where + e = (signed 16 bits) offset to first instruction in subroutine, from start of insn + instruction sequence must end in RTS, execution resumes at instruction + following JSR */ + DDS_OP_JSR = 0x02 << 24, + /* union case + [JEQ, nBY, 0] [disc] [offset] + [JEQ, STR, 0] [disc] [offset] + [JEQ, s, e] [disc] [offset] + where + s = subtype other than {nBY,STR} + e = (unsigned 16 bits) offset to first instruction for case, from start of insn + instruction sequence must end in RTS, at which point executes continues + at the next field's instruction as specified by the union */ + DDS_OP_JEQ = 0x03 << 24 +}; -/* Core type flags - - 1BY : One byte simple type - 2BY : Two byte simple type - 4BY : Four byte simple type - 8BY : Eight byte simple type - STR : String - BST : Bounded string - SEQ : Sequence - ARR : Array - UNI : Union - STU : Struct -*/ - -#define DDS_OP_VAL_1BY 0x01 -#define DDS_OP_VAL_2BY 0x02 -#define DDS_OP_VAL_4BY 0x03 -#define DDS_OP_VAL_8BY 0x04 -#define DDS_OP_VAL_STR 0x05 -#define DDS_OP_VAL_BST 0x06 -#define DDS_OP_VAL_SEQ 0x07 -#define DDS_OP_VAL_ARR 0x08 -#define DDS_OP_VAL_UNI 0x09 -#define DDS_OP_VAL_STU 0x0a - -#define DDS_OP_TYPE_1BY (DDS_OP_VAL_1BY << 16) -#define DDS_OP_TYPE_2BY (DDS_OP_VAL_2BY << 16) -#define DDS_OP_TYPE_4BY (DDS_OP_VAL_4BY << 16) -#define DDS_OP_TYPE_8BY (DDS_OP_VAL_8BY << 16) -#define DDS_OP_TYPE_STR (DDS_OP_VAL_STR << 16) -#define DDS_OP_TYPE_SEQ (DDS_OP_VAL_SEQ << 16) -#define DDS_OP_TYPE_ARR (DDS_OP_VAL_ARR << 16) -#define DDS_OP_TYPE_UNI (DDS_OP_VAL_UNI << 16) -#define DDS_OP_TYPE_STU (DDS_OP_VAL_STU << 16) -#define DDS_OP_TYPE_BST (DDS_OP_VAL_BST << 16) +enum dds_stream_typecode { + DDS_OP_VAL_1BY = 0x01, /* one byte simple type (char, octet, boolean) */ + DDS_OP_VAL_2BY = 0x02, /* two byte simple type ((unsigned) short) */ + DDS_OP_VAL_4BY = 0x03, /* four byte simple type ((unsigned) long, enums, float) */ + DDS_OP_VAL_8BY = 0x04, /* eight byte simple type ((unsigned) long long, double) */ + DDS_OP_VAL_STR = 0x05, /* string */ + DDS_OP_VAL_BST = 0x06, /* bounded string */ + DDS_OP_VAL_SEQ = 0x07, /* sequence */ + DDS_OP_VAL_ARR = 0x08, /* array */ + DDS_OP_VAL_UNI = 0x09, /* union */ + DDS_OP_VAL_STU = 0x0a /* struct */ +}; +/* primary type code for DDS_OP_ADR, DDS_OP_JEQ */ +enum dds_stream_typecode_primary { + DDS_OP_TYPE_1BY = DDS_OP_VAL_1BY << 16, + DDS_OP_TYPE_2BY = DDS_OP_VAL_2BY << 16, + DDS_OP_TYPE_4BY = DDS_OP_VAL_4BY << 16, + DDS_OP_TYPE_8BY = DDS_OP_VAL_8BY << 16, + DDS_OP_TYPE_STR = DDS_OP_VAL_STR << 16, + DDS_OP_TYPE_BST = DDS_OP_VAL_BST << 16, + DDS_OP_TYPE_SEQ = DDS_OP_VAL_SEQ << 16, + DDS_OP_TYPE_ARR = DDS_OP_VAL_ARR << 16, + DDS_OP_TYPE_UNI = DDS_OP_VAL_UNI << 16, + DDS_OP_TYPE_STU = DDS_OP_VAL_STU << 16 +}; #define DDS_OP_TYPE_BOO DDS_OP_TYPE_1BY + +/* sub-type code: + - encodes element type for DDS_OP_TYPE_{SEQ,ARR}, + - discriminant type for DDS_OP_TYPE_UNI */ +enum dds_stream_typecode_subtype { + DDS_OP_SUBTYPE_1BY = DDS_OP_VAL_1BY << 8, + DDS_OP_SUBTYPE_2BY = DDS_OP_VAL_2BY << 8, + DDS_OP_SUBTYPE_4BY = DDS_OP_VAL_4BY << 8, + DDS_OP_SUBTYPE_8BY = DDS_OP_VAL_8BY << 8, + DDS_OP_SUBTYPE_STR = DDS_OP_VAL_STR << 8, + DDS_OP_SUBTYPE_BST = DDS_OP_VAL_BST << 8, + DDS_OP_SUBTYPE_SEQ = DDS_OP_VAL_SEQ << 8, + DDS_OP_SUBTYPE_ARR = DDS_OP_VAL_ARR << 8, + DDS_OP_SUBTYPE_UNI = DDS_OP_VAL_UNI << 8, + DDS_OP_SUBTYPE_STU = DDS_OP_VAL_STU << 8 +}; #define DDS_OP_SUBTYPE_BOO DDS_OP_SUBTYPE_1BY -#define DDS_OP_SUBTYPE_1BY (DDS_OP_VAL_1BY << 8) -#define DDS_OP_SUBTYPE_2BY (DDS_OP_VAL_2BY << 8) -#define DDS_OP_SUBTYPE_4BY (DDS_OP_VAL_4BY << 8) -#define DDS_OP_SUBTYPE_8BY (DDS_OP_VAL_8BY << 8) -#define DDS_OP_SUBTYPE_STR (DDS_OP_VAL_STR << 8) -#define DDS_OP_SUBTYPE_SEQ (DDS_OP_VAL_SEQ << 8) -#define DDS_OP_SUBTYPE_ARR (DDS_OP_VAL_ARR << 8) -#define DDS_OP_SUBTYPE_UNI (DDS_OP_VAL_UNI << 8) -#define DDS_OP_SUBTYPE_STU (DDS_OP_VAL_STU << 8) -#define DDS_OP_SUBTYPE_BST (DDS_OP_VAL_BST << 8) - -#define DDS_OP_FLAG_KEY 0x01 -#define DDS_OP_FLAG_DEF 0x02 +#define DDS_OP_FLAG_KEY 0x01 /* key field: applicable to {1,2,4,8}BY, STR, BST, ARR-of-{1,2,4,8}BY */ +#define DDS_OP_FLAG_DEF 0x02 /* union has a default case (for DDS_OP_ADR | DDS_OP_TYPE_UNI) */ /** * Description : Enable or disable write batching. Overrides default configuration - * setting for write batching (DDSI2E/Internal/WriteBatch). + * setting for write batching (Internal/WriteBatch). * * Arguments : * -# enable Enables or disables write batching for all writers. */ DDS_EXPORT void dds_write_set_batch (bool enable); -/** - * Description : Install tcp/ssl and encryption support. Depends on openssl. - * - * Arguments : - * -# None - */ -DDS_EXPORT void dds_ssl_plugin (void); - -/** - * Description : Install client durability support. Depends on OSPL server. - * - * Arguments : - * -# None - */ -DDS_EXPORT void dds_durability_plugin (void); - #if defined (__cplusplus) } #endif diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_stream.h b/src/core/ddsc/include/dds/ddsc/dds_public_stream.h deleted file mode 100644 index 6a3d56f..0000000 --- a/src/core/ddsc/include/dds/ddsc/dds_public_stream.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -/** @file - * - * @brief DDS C Stream API - * - * This header file defines the public API of the Streams in the - * Eclipse Cyclone DDS C language binding. - */ -#ifndef DDS_STREAM_H -#define DDS_STREAM_H - -#include -#include -#include - -#include "dds/export.h" - -#if defined (__cplusplus) -extern "C" { -#endif - -struct dds_sequence; - -typedef union -{ - uint8_t * p8; - uint16_t * p16; - uint32_t * p32; - uint64_t * p64; - float * pf; - double * pd; - void * pv; -} -dds_uptr_t; - -typedef struct dds_stream -{ - dds_uptr_t m_buffer; /* Union of pointers to start of buffer */ - uint32_t m_size; /* Buffer size */ - uint32_t m_index; /* Read/write offset from start of buffer */ - bool m_endian; /* Endian: big (false) or little (true) */ - bool m_failed; /* Attempt made to read beyond end of buffer */ -} -dds_stream_t; - -#define DDS_STREAM_BE false -#define DDS_STREAM_LE true - -DDS_EXPORT dds_stream_t * dds_stream_create (uint32_t size); -DDS_EXPORT dds_stream_t * dds_stream_from_buffer (const void *buf, size_t sz, int bswap); -DDS_EXPORT void dds_stream_delete (dds_stream_t * st); -DDS_EXPORT void dds_stream_fini (dds_stream_t * st); -DDS_EXPORT void dds_stream_reset (dds_stream_t * st); -DDS_EXPORT void dds_stream_init (dds_stream_t * st, uint32_t size); -DDS_EXPORT void dds_stream_grow (dds_stream_t * st, uint32_t size); -DDS_EXPORT bool dds_stream_endian (void); - -struct dds_topic_descriptor; -DDS_EXPORT void dds_stream_read_sample_w_desc (dds_stream_t * is, void * data, const struct dds_topic_descriptor * desc); -DDS_EXPORT bool dds_stream_read_bool (dds_stream_t * is); -DDS_EXPORT uint8_t dds_stream_read_uint8 (dds_stream_t * is); -DDS_EXPORT uint16_t dds_stream_read_uint16 (dds_stream_t * is); -DDS_EXPORT uint32_t dds_stream_read_uint32 (dds_stream_t * is); -DDS_EXPORT uint64_t dds_stream_read_uint64 (dds_stream_t * is); -DDS_EXPORT float dds_stream_read_float (dds_stream_t * is); -DDS_EXPORT double dds_stream_read_double (dds_stream_t * is); -DDS_EXPORT char * dds_stream_read_string (dds_stream_t * is); -DDS_EXPORT void dds_stream_read_buffer (dds_stream_t * is, uint8_t * buffer, uint32_t len); - -inline char dds_stream_read_char (dds_stream_t *is) { return (char) dds_stream_read_uint8 (is); } -inline int8_t dds_stream_read_int8 (dds_stream_t *is) { return (int8_t) dds_stream_read_uint8 (is); } -inline int16_t dds_stream_read_int16 (dds_stream_t *is) { return (int16_t) dds_stream_read_uint16 (is); } -inline int32_t dds_stream_read_int32 (dds_stream_t *is) { return (int32_t) dds_stream_read_uint32 (is); } -inline int64_t dds_stream_read_int64 (dds_stream_t *is) { return (int64_t) dds_stream_read_uint64 (is); } - -DDS_EXPORT void dds_stream_write_bool (dds_stream_t * os, bool val); -DDS_EXPORT void dds_stream_write_uint8 (dds_stream_t * os, uint8_t val); -DDS_EXPORT void dds_stream_write_uint16 (dds_stream_t * os, uint16_t val); -DDS_EXPORT void dds_stream_write_uint32 (dds_stream_t * os, uint32_t val); -DDS_EXPORT void dds_stream_write_uint64 (dds_stream_t * os, uint64_t val); -DDS_EXPORT void dds_stream_write_float (dds_stream_t * os, float val); -DDS_EXPORT void dds_stream_write_double (dds_stream_t * os, double val); -DDS_EXPORT void dds_stream_write_string (dds_stream_t * os, const char * val); -DDS_EXPORT void dds_stream_write_buffer (dds_stream_t * os, uint32_t len, const uint8_t * buffer); -DDS_EXPORT void *dds_stream_address (dds_stream_t * s); -DDS_EXPORT void *dds_stream_alignto (dds_stream_t * s, uint32_t a); - -inline void dds_stream_write_char (dds_stream_t * os, char val) { dds_stream_write_uint8 (os, (uint8_t) val); } -inline void dds_stream_write_int8 (dds_stream_t * os, int8_t val) { dds_stream_write_uint8 (os, (uint8_t) val); } -inline void dds_stream_write_int16 (dds_stream_t * os, int16_t val) { dds_stream_write_uint16 (os, (uint16_t) val); } -inline void dds_stream_write_int32 (dds_stream_t * os, int32_t val) { dds_stream_write_uint32 (os, (uint32_t) val); } -inline void dds_stream_write_int64 (dds_stream_t * os, int64_t val) { dds_stream_write_uint64 (os, (uint64_t) val); } - -#if defined (__cplusplus) -} -#endif -#endif diff --git a/src/core/ddsc/src/dds__key.h b/src/core/ddsc/src/dds__key.h deleted file mode 100644 index b01f8bf..0000000 --- a/src/core/ddsc/src/dds__key.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef _DDS_KEY_H_ -#define _DDS_KEY_H_ - -#include "dds__types.h" - -struct dds_key_hash; - -#if defined (__cplusplus) -extern "C" { -#endif - -void dds_key_md5 (struct dds_key_hash * kh); - -void dds_key_gen -( - const dds_topic_descriptor_t * const desc, - struct dds_key_hash * kh, - const char * sample -); - -#if defined (__cplusplus) -} -#endif -#endif diff --git a/src/core/ddsc/src/dds__stream.h b/src/core/ddsc/src/dds__stream.h index 79eadd1..347f667 100644 --- a/src/core/ddsc/src/dds__stream.h +++ b/src/core/ddsc/src/dds__stream.h @@ -19,47 +19,46 @@ extern "C" { #endif -void dds_stream_write_sample -( - dds_stream_t * os, - const void * data, - const struct ddsi_sertopic_default * topic -); -void dds_stream_read_sample -( - dds_stream_t * is, - void * data, - const struct ddsi_sertopic_default * topic -); +typedef struct dds_istream { + const unsigned char *m_buffer; + uint32_t m_size; /* Buffer size */ + uint32_t m_index; /* Read/write offset from start of buffer */ +} dds_istream_t; -size_t dds_stream_check_optimize (const dds_topic_descriptor_t * desc); -void dds_stream_from_serdata_default (dds_stream_t * s, const struct ddsi_serdata_default *d); -void dds_stream_add_to_serdata_default (dds_stream_t * s, struct ddsi_serdata_default **d); +typedef struct dds_ostream { + unsigned char *m_buffer; + uint32_t m_size; /* Buffer size */ + uint32_t m_index; /* Read/write offset from start of buffer */ +} dds_ostream_t; -void dds_stream_write_key (dds_stream_t * os, const char * sample, const struct ddsi_sertopic_default * topic); -uint32_t dds_stream_extract_key (dds_stream_t *is, dds_stream_t *os, const uint32_t *ops, const bool just_key); -void dds_stream_read_key -( - dds_stream_t * is, - char * sample, - const dds_topic_descriptor_t * desc -); -void dds_stream_read_keyhash -( - dds_stream_t * is, - dds_key_hash_t * kh, - const dds_topic_descriptor_t * desc, - const bool just_key -); -char * dds_stream_reuse_string -( - dds_stream_t * is, - char * str, - const uint32_t bound -); -DDS_EXPORT void dds_stream_swap (void * buff, uint32_t size, uint32_t num); +typedef struct dds_ostreamBE { + dds_ostream_t x; +} dds_ostreamBE_t; -extern const uint32_t dds_op_size[5]; +DDS_EXPORT void dds_ostream_init (dds_ostream_t * __restrict st, uint32_t size); +DDS_EXPORT void dds_ostream_fini (dds_ostream_t * __restrict st); +DDS_EXPORT void dds_ostreamBE_init (dds_ostreamBE_t * __restrict st, uint32_t size); +DDS_EXPORT void dds_ostreamBE_fini (dds_ostreamBE_t * __restrict st); + +bool dds_stream_normalize (void * __restrict data, uint32_t size, bool bswap, const struct ddsi_sertopic_default * __restrict topic, bool just_key); + +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); + +size_t dds_stream_check_optimize (const dds_topic_descriptor_t * __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); +void dds_ostreamBE_from_serdata_default (dds_ostreamBE_t * __restrict s, struct ddsi_serdata_default * __restrict d); +void dds_ostreamBE_add_to_serdata_default (dds_ostreamBE_t * __restrict s, struct ddsi_serdata_default ** __restrict d); + +void dds_stream_write_key (dds_ostream_t * __restrict os, const char * __restrict sample, const struct ddsi_sertopic_default * __restrict topic); +void dds_stream_write_keyBE (dds_ostreamBE_t * __restrict os, const char * __restrict sample, const struct ddsi_sertopic_default * __restrict topic); +void dds_stream_extract_key_from_data (dds_istream_t * __restrict is, dds_ostream_t * __restrict os, const struct ddsi_sertopic_default * __restrict topic); +void dds_stream_extract_keyBE_from_data (dds_istream_t * __restrict is, dds_ostreamBE_t * __restrict os, const struct ddsi_sertopic_default * __restrict topic); +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); + +void dds_stream_read_key (dds_istream_t * __restrict is, char * __restrict sample, const struct ddsi_sertopic_default * __restrict topic); /* For marshalling op code handling */ @@ -70,14 +69,14 @@ extern const uint32_t dds_op_size[5]; #define DDS_OP_FLAGS_MASK 0x000000ff #define DDS_JEQ_TYPE_MASK 0x00ff0000 -#define DDS_OP(o) ((o) & DDS_OP_MASK) -#define DDS_OP_TYPE(o) (((o) & DDS_OP_TYPE_MASK) >> 16) -#define DDS_OP_SUBTYPE(o) (((o) & DDS_OP_SUBTYPE_MASK) >> 8) -#define DDS_OP_FLAGS(o) ((o) & DDS_OP_FLAGS_MASK) +#define DDS_OP(o) ((enum dds_stream_opcode) ((o) & DDS_OP_MASK)) +#define DDS_OP_TYPE(o) ((enum dds_stream_typecode) (((o) & DDS_OP_TYPE_MASK) >> 16)) +#define DDS_OP_SUBTYPE(o) ((enum dds_stream_typecode) (((o) & DDS_OP_SUBTYPE_MASK) >> 8)) +#define DDS_OP_FLAGS(o) ((o) & DDS_OP_FLAGS_MASK) #define DDS_OP_ADR_JSR(o) ((o) & DDS_OP_JMP_MASK) -#define DDS_OP_JUMP(o) ((int16_t) ((o) & DDS_OP_JMP_MASK)) +#define DDS_OP_JUMP(o) ((int16_t) ((o) & DDS_OP_JMP_MASK)) #define DDS_OP_ADR_JMP(o) ((o) >> 16) -#define DDS_JEQ_TYPE(o) (((o) & DDS_JEQ_TYPE_MASK) >> 16) +#define DDS_JEQ_TYPE(o) ((enum dds_stream_typecode) (((o) & DDS_JEQ_TYPE_MASK) >> 16)) #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds_alloc.c b/src/core/ddsc/src/dds_alloc.c index 954f77d..ffe575b 100644 --- a/src/core/ddsc/src/dds_alloc.c +++ b/src/core/ddsc/src/dds_alloc.c @@ -179,6 +179,8 @@ void dds_sample_free_contents (char * data, const uint32_t * ops) if (seq->_release) { dds_free (seq->_buffer); + seq->_maximum = 0; + seq->_length = 0; seq->_buffer = NULL; } break; diff --git a/src/core/ddsc/src/dds_key.c b/src/core/ddsc/src/dds_key.c deleted file mode 100644 index b919c85..0000000 --- a/src/core/ddsc/src/dds_key.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include -#include - -#include "dds/ddsrt/md5.h" -#include "dds__key.h" -#include "dds__stream.h" -#include "dds/ddsi/ddsi_serdata.h" -#include "dds/ddsi/q_bswap.h" - -#ifndef NDEBUG -static bool keyhash_is_reset(const dds_key_hash_t *kh) -{ - return !kh->m_set; -} -#endif - -/* - dds_key_gen: Generates key and keyhash for a sample. - See section 9.6.3.3 of DDSI spec. -*/ - -static void dds_key_gen_stream (const dds_topic_descriptor_t * const desc, dds_stream_t *os, const char *sample) -{ - const char * src; - const uint32_t * op; - uint32_t i; - uint32_t len = 0; - - for (i = 0; i < desc->m_nkeys; i++) - { - op = desc->m_ops + desc->m_keys[i].m_index; - src = sample + op[1]; - assert ((*op & DDS_OP_FLAG_KEY) && ((DDS_OP_MASK & *op) == DDS_OP_ADR)); - - switch (DDS_OP_TYPE (*op)) - { - case DDS_OP_VAL_1BY: - { - dds_stream_write_uint8 (os, *((const uint8_t *) src)); - break; - } - case DDS_OP_VAL_2BY: - { - dds_stream_write_uint16 (os, *((const uint16_t *) src)); - break; - } - case DDS_OP_VAL_4BY: - { - dds_stream_write_uint32 (os, *((const uint32_t *) src)); - break; - } - case DDS_OP_VAL_8BY: - { - dds_stream_write_uint64 (os, *((const uint64_t *) src)); - break; - } - case DDS_OP_VAL_STR: - { - src = *((char**) src); - } - /* FALLS THROUGH */ - case DDS_OP_VAL_BST: - { - len = (uint32_t) (strlen (src) + 1); - dds_stream_write_uint32 (os, len); - dds_stream_write_buffer (os, len, (const uint8_t *) src); - break; - } - case DDS_OP_VAL_ARR: - { - uint32_t size = dds_op_size[DDS_OP_SUBTYPE (*op)]; - char *dst; - len = size * op[2]; - dst = dds_stream_alignto (os, op[2]); - dds_stream_write_buffer (os, len, (const uint8_t *) src); - if (dds_stream_endian () && (size != 1u)) - dds_stream_swap (dst, size, op[2]); - break; - } - default: assert (0); - } - } -} - -void dds_key_gen (const dds_topic_descriptor_t * const desc, dds_key_hash_t * kh, const char * sample) -{ - assert(keyhash_is_reset(kh)); - - kh->m_set = 1; - if (desc->m_nkeys == 0) - kh->m_iskey = 1; - else if (desc->m_flagset & DDS_TOPIC_FIXED_KEY) - { - dds_stream_t os; - kh->m_iskey = 1; - dds_stream_init(&os, 0); - os.m_endian = 0; - os.m_buffer.pv = kh->m_hash; - os.m_size = 16; - dds_key_gen_stream (desc, &os, sample); - } - else - { - dds_stream_t os; - ddsrt_md5_state_t md5st; - kh->m_iskey = 0; - dds_stream_init(&os, 64); - os.m_endian = 0; - dds_key_gen_stream (desc, &os, sample); - ddsrt_md5_init (&md5st); - ddsrt_md5_append (&md5st, os.m_buffer.p8, os.m_index); - ddsrt_md5_finish (&md5st, (unsigned char *) kh->m_hash); - dds_stream_fini (&os); - } -} diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index 5cbd47b..f043783 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -19,7 +19,6 @@ #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" -#include "dds__key.h" #include "dds__stream.h" #include "dds__serdata_builtintopic.h" #include "dds/ddsi/ddsi_tkmap.h" diff --git a/src/core/ddsc/src/dds_stream.c b/src/core/ddsc/src/dds_stream.c index 9d7505c..2c724a9 100644 --- a/src/core/ddsc/src/dds_stream.c +++ b/src/core/ddsc/src/dds_stream.c @@ -14,1660 +14,1662 @@ #include "dds/ddsrt/endian.h" #include "dds/ddsrt/md5.h" +#include "dds/ddsrt/heap.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds__stream.h" -#include "dds__key.h" #include "dds__alloc.h" -//#define OP_DEBUG_READ 1 -//#define OP_DEBUG_WRITE 1 -//#define OP_DEBUG_KEY 1 - -#if defined OP_DEBUG_WRITE || defined OP_DEBUG_READ || defined OP_DEBUG_KEY -static const char * stream_op_type[11] = -{ - NULL, "1Byte", "2Byte", "4Byte", "8Byte", "String", - "BString", "Sequence", "Array", "Union", "Struct" -}; -#endif - #if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN #define DDS_ENDIAN true #else #define DDS_ENDIAN false #endif -const uint32_t dds_op_size[5] = { 0, 1u, 2u, 4u, 8u }; +static void dds_stream_write (dds_ostream_t * __restrict os, const char * __restrict data, const uint32_t * __restrict ops); +static void dds_stream_read (dds_istream_t * __restrict is, char * __restrict data, const uint32_t * __restrict ops); -static void dds_stream_write (dds_stream_t * os, const char * data, const uint32_t * ops); -static void dds_stream_read (dds_stream_t * is, char * data, const uint32_t * ops); - -#define DDS_SWAP16(v) \ - ((uint16_t)(((v) >> 8) | ((v) << 8))) -#define DDS_SWAP32(v) \ - (((v) >> 24) | \ - (((v) & 0x00ff0000) >> 8) | \ - (((v) & 0x0000ff00) << 8) | \ - ((v) << 24)) -#define DDS_SWAP64(v) \ - (((v)) >> 56) | \ - ((((v)) & 0x00ff000000000000) >> 40) | \ - ((((v)) & 0x0000ff0000000000) >> 24) | \ - ((((v)) & 0x000000ff00000000) >> 8) | \ - ((((v)) & 0x00000000ff000000) << 8) | \ - ((((v)) & 0x0000000000ff0000) << 24) | \ - ((((v)) & 0x000000000000ff00) << 40) | \ - (((v)) << 56) - -#define DDS_CDR_ALIGN2(s) ((s)->m_index = ((s)->m_index + 1U) & ~1U) -#define DDS_CDR_ALIGN4(s) ((s)->m_index = ((s)->m_index + 3U) & ~3U) -#define DDS_CDR_ALIGN8(s) ((s)->m_index = ((s)->m_index + 7U) & ~7U) -#define DDS_CDR_ALIGNTO(s,n) ((s)->m_index = ((s)->m_index + (n-1)) & ~(n-1)) -#define DDS_CDR_ALIGNED(s,n) ((n) && ((s)->m_index % (n)) == 0) - -#define DDS_CDR_ADDRESS(c, type) ((type*) &((c)->m_buffer.p8[(c)->m_index])) -#define DDS_CDR_RESET(c) \ - (c)->m_index = 0ul; \ - (c)->m_failed = false; -#define DDS_CDR_RESIZE(c,l) if (((c)->m_size < ((l) + (c)->m_index))) dds_stream_grow (c, l) -#define DDS_CDR_REINIT(c,s) \ - DDS_CDR_RESET(c); \ - (c)->m_endian = DDS_ENDIAN; \ - if ((c)->m_size < (s)) dds_stream_grow (c, s) - -#ifndef NDEBUG -#define DDS_IS_OK(s,n) (!((s)->m_failed = ((s)->m_index + (n)) > (s)->m_size)) -#else -#define DDS_IS_OK(s,n) (true) -#endif - -#define DDS_IS_GET1(s) (s)->m_buffer.p8[(s)->m_index++] - -#define DDS_IS_GET2(s,v) \ - (v) = *DDS_CDR_ADDRESS ((s), uint16_t); \ - if ((s)->m_endian != DDS_ENDIAN) (v) = DDS_SWAP16 ((v)); \ - (s)->m_index += 2 - -#define DDS_IS_GET4(s,v,t) \ - (v) = *DDS_CDR_ADDRESS ((s), t); \ - if ((s)->m_endian != DDS_ENDIAN) (v) = (t)(DDS_SWAP32 ((uint32_t) (v))); \ - (s)->m_index += 4; - -#define DDS_IS_GET8(s,v,t) \ - (v) = *DDS_CDR_ADDRESS ((s), t); \ - if ((s)->m_endian != DDS_ENDIAN) (v) = (t)(DDS_SWAP64 ((uint64_t) (v))); \ - (s)->m_index += 8 - -#define DDS_IS_GET_BYTES(s,b,l) \ - memcpy (b, DDS_CDR_ADDRESS ((s), void), l); \ - (s)->m_index += (l) - -#define DDS_OS_PUT1(s,v) \ - DDS_CDR_RESIZE (s, 1u); \ - *DDS_CDR_ADDRESS (s, uint8_t) = v; \ - (s)->m_index += 1 - -#define DDS_OS_PUT2(s,v) \ - DDS_CDR_ALIGN2 (s); \ - DDS_CDR_RESIZE (s, 2u); \ - *DDS_CDR_ADDRESS (s, uint16_t) = ((s)->m_endian == DDS_ENDIAN) ? \ - v : DDS_SWAP16 ((uint16_t) (v)); \ - (s)->m_index += 2 - -#define DDS_OS_PUT4(s,v,t) \ - DDS_CDR_ALIGN4 (s); \ - DDS_CDR_RESIZE (s, 4u); \ - *DDS_CDR_ADDRESS (s, t) = ((s)->m_endian == DDS_ENDIAN) ? \ - v : DDS_SWAP32 ((uint32_t) (v)); \ - (s)->m_index += 4 - -#define DDS_OS_PUT8(s,v,t) \ - DDS_CDR_ALIGN8 (s); \ - DDS_CDR_RESIZE (s, 8u); \ - *DDS_CDR_ADDRESS (s, t) = ((s)->m_endian == DDS_ENDIAN) ? \ - v : DDS_SWAP64 ((uint64_t) (v)); \ - (s)->m_index += 8 - -#define DDS_OS_PUT_BYTES(s,b,l) \ - DDS_CDR_RESIZE (s, l); \ - memcpy (DDS_CDR_ADDRESS (s, void), b, l); \ - (s)->m_index += (l) - -bool dds_stream_endian (void) -{ - return DDS_ENDIAN; -} - -size_t dds_stream_check_optimize (const dds_topic_descriptor_t * desc) -{ - dds_stream_t os; - void * sample = dds_alloc (desc->m_size); - uint8_t * ptr1; - uint8_t * ptr2; - uint32_t size = desc->m_size; - uint8_t val = 1; - - dds_stream_init (&os, size); - ptr1 = (uint8_t*) sample; - ptr2 = os.m_buffer.p8; - while (size--) - { - *ptr1++ = val; - *ptr2++ = val++; - } - - dds_stream_write (&os, sample, desc->m_ops); - size = (memcmp (sample, os.m_buffer.p8, desc->m_size) == 0) ? os.m_index : 0; - - dds_sample_free_contents (sample, desc->m_ops); - dds_free (sample); - dds_stream_fini (&os); - DDS_TRACE("Marshalling for type: %s is%s optimised\n", desc->m_typename, size ? "" : " not"); - return size; -} - -dds_stream_t * dds_stream_create (uint32_t size) -{ - dds_stream_t * stream = (dds_stream_t*) dds_alloc (sizeof (*stream)); - dds_stream_init (stream, size); - return stream; -} - -void dds_stream_delete (dds_stream_t * st) -{ - dds_stream_fini (st); - dds_free (st); -} - -void dds_stream_fini (dds_stream_t * st) -{ - if (st->m_size) - { - dds_free (st->m_buffer.p8); - } -} - -void dds_stream_init (dds_stream_t * st, uint32_t size) -{ - memset (st, 0, sizeof (*st)); - DDS_CDR_REINIT (st, size); -} - -void dds_stream_reset (dds_stream_t * st) -{ - DDS_CDR_RESET (st); -} - -void dds_stream_grow (dds_stream_t * st, uint32_t size) +static void dds_ostream_grow (dds_ostream_t * __restrict st, uint32_t size) { uint32_t needed = size + st->m_index; /* Reallocate on 4k boundry */ uint32_t newSize = (needed & ~(uint32_t)0xfff) + 0x1000; - uint8_t * old = st->m_buffer.p8; + uint8_t *old = st->m_buffer; - st->m_buffer.p8 = dds_realloc (old, newSize); - memset (st->m_buffer.p8 + st->m_size, 0, newSize - st->m_size); + st->m_buffer = ddsrt_realloc (old, newSize); st->m_size = newSize; } -bool dds_stream_read_bool (dds_stream_t * is) +static void dds_cdr_resize (dds_ostream_t * __restrict s, uint32_t l) { - return (dds_stream_read_uint8 (is) != 0); + if (s->m_size < l + s->m_index) + dds_ostream_grow (s, l); } -uint8_t dds_stream_read_uint8 (dds_stream_t * is) +void dds_ostream_init (dds_ostream_t * __restrict st, uint32_t size) { - return DDS_IS_OK (is, 1) ? DDS_IS_GET1 (is) : 0; + memset (st, 0, sizeof (*st)); + st->m_index = 0; + dds_cdr_resize (st, size); } -uint16_t dds_stream_read_uint16 (dds_stream_t * is) +void dds_ostreamBE_init (dds_ostreamBE_t * __restrict st, uint32_t size) { - uint16_t val = 0; - DDS_CDR_ALIGN2 (is); - if (DDS_IS_OK (is, 2)) + dds_ostream_init (&st->x, size); +} + +void dds_ostream_fini (dds_ostream_t * __restrict st) +{ + if (st->m_size) + dds_free (st->m_buffer); +} + +void dds_ostreamBE_fini (dds_ostreamBE_t * __restrict st) +{ + dds_ostream_fini (&st->x); +} + +static void dds_cdr_alignto (dds_istream_t * __restrict s, uint32_t a) +{ + s->m_index = (s->m_index + a - 1) & ~(a - 1); + assert (s->m_index < s->m_size); +} + +static void dds_cdr_alignto_clear_and_resize (dds_ostream_t * __restrict s, uint32_t a, uint32_t extra) +{ + const uint32_t m = s->m_index % a; + if (m == 0) + dds_cdr_resize (s, extra); + else { - DDS_IS_GET2 (is, val); + uint32_t pad = a - m; + dds_cdr_resize (s, pad + extra); + while (pad--) + s->m_buffer[s->m_index++] = 0; } - return val; } -uint32_t dds_stream_read_uint32 (dds_stream_t * is) +static void dds_cdr_alignto_clear_and_resize_be (dds_ostreamBE_t * __restrict s, uint32_t a, uint32_t extra) { - uint32_t val = 0; - DDS_CDR_ALIGN4 (is); - if (DDS_IS_OK (is, 4)) - { - DDS_IS_GET4 (is, val, uint32_t); - } - return val; + dds_cdr_alignto_clear_and_resize (&s->x, a, extra); } -uint64_t dds_stream_read_uint64 (dds_stream_t * is) +static uint8_t dds_is_get1 (dds_istream_t * __restrict s) { - uint64_t val = 0; - DDS_CDR_ALIGN8 (is); - if (DDS_IS_OK (is, 8)) - { - DDS_IS_GET8 (is, val, uint64_t); - } - return val; + assert (s->m_index < s->m_size); + uint8_t v = *(s->m_buffer + s->m_index); + s->m_index++; + return v; } -extern inline char dds_stream_read_char (dds_stream_t *is); -extern inline int8_t dds_stream_read_int8 (dds_stream_t *is); -extern inline int16_t dds_stream_read_int16 (dds_stream_t *is); -extern inline int32_t dds_stream_read_int32 (dds_stream_t *is); -extern inline int64_t dds_stream_read_int64 (dds_stream_t *is); - -float dds_stream_read_float (dds_stream_t * is) +static uint16_t dds_is_get2 (dds_istream_t * __restrict s) { - float val = 0.0; - DDS_CDR_ALIGN4 (is); - if (DDS_IS_OK (is, 4)) - { - DDS_IS_GET4 (is, val, float); - } - return val; + dds_cdr_alignto (s, 2); + uint16_t v = * ((uint16_t *) (s->m_buffer + s->m_index)); + s->m_index += 2; + return v; } -double dds_stream_read_double (dds_stream_t * is) +static uint32_t dds_is_get4 (dds_istream_t * __restrict s) { - double val = 0.0; - DDS_CDR_ALIGN8 (is); - if (DDS_IS_OK (is, 8)) - { - DDS_IS_GET8 (is, val, double); - } - return val; + dds_cdr_alignto (s, 4); + uint32_t v = * ((uint32_t *) (s->m_buffer + s->m_index)); + s->m_index += 4; + return v; } -char * dds_stream_reuse_string - (dds_stream_t * is, char * str, const uint32_t bound) +static uint64_t dds_is_get8 (dds_istream_t * __restrict s) { - uint32_t length; - void * src; + dds_cdr_alignto (s, 8); + uint64_t v = * ((uint64_t *) (s->m_buffer + s->m_index)); + s->m_index += 8; + return v; +} - DDS_CDR_ALIGN4 (is); - if (DDS_IS_OK (is, 4)) +static void dds_is_get_bytes (dds_istream_t * __restrict s, void * __restrict b, uint32_t num, uint32_t elem_size) +{ + dds_cdr_alignto (s, elem_size); + memcpy (b, s->m_buffer + s->m_index, num * elem_size); + s->m_index += num * elem_size; +} + +static void dds_os_put1 (dds_ostream_t * __restrict s, uint8_t v) +{ + dds_cdr_resize (s, 1); + *((uint8_t *) (s->m_buffer + s->m_index)) = v; + s->m_index += 1; +} + +static void dds_os_put2 (dds_ostream_t * __restrict s, uint16_t v) +{ + dds_cdr_alignto_clear_and_resize (s, 2, 2); + *((uint16_t *) (s->m_buffer + s->m_index)) = v; + s->m_index += 2; +} + +static void dds_os_put4 (dds_ostream_t * __restrict s, uint32_t v) +{ + dds_cdr_alignto_clear_and_resize (s, 4, 4); + *((uint32_t *) (s->m_buffer + s->m_index)) = v; + s->m_index += 4; +} + +static void dds_os_put8 (dds_ostream_t * __restrict s, uint64_t v) +{ + dds_cdr_alignto_clear_and_resize (s, 8, 8); + *((uint64_t *) (s->m_buffer + s->m_index)) = v; + s->m_index += 8; +} + +static void dds_os_put1be (dds_ostreamBE_t * __restrict s, uint8_t v) +{ + dds_os_put1 (&s->x, v); +} + +static void dds_os_put2be (dds_ostreamBE_t * __restrict s, uint16_t v) +{ + dds_os_put2 (&s->x, toBE2u (v)); +} + +static void dds_os_put4be (dds_ostreamBE_t * __restrict s, uint32_t v) +{ + dds_os_put4 (&s->x, toBE4u (v)); +} + +static void dds_os_put8be (dds_ostreamBE_t * __restrict s, uint64_t v) +{ + dds_os_put8 (&s->x, toBE8u (v)); +} + +static void dds_os_put_bytes (dds_ostream_t * __restrict s, const void * __restrict b, uint32_t l) +{ + dds_cdr_resize (s, l); + memcpy (s->m_buffer + s->m_index, b, l); + s->m_index += l; +} + +static void dds_os_put_bytes_aligned (dds_ostream_t * __restrict s, const void * __restrict b, uint32_t n, uint32_t a) +{ + const uint32_t l = n * a; + dds_cdr_alignto_clear_and_resize (s, a, l); + memcpy (s->m_buffer + s->m_index, b, l); + s->m_index += l; +} + +static uint32_t get_type_size (enum dds_stream_typecode type) +{ + struct check { + char x[(DDS_OP_VAL_1BY == 1 && DDS_OP_VAL_2BY == 2 && DDS_OP_VAL_4BY == 3 && DDS_OP_VAL_8BY == 4) ? 1 : -1]; + }; + assert (type == DDS_OP_VAL_1BY || type == DDS_OP_VAL_2BY || type == DDS_OP_VAL_4BY || type == DDS_OP_VAL_8BY); + return (uint32_t)1 << ((uint32_t) type - 1); +} + +static size_t dds_stream_check_optimize1 (const dds_topic_descriptor_t * __restrict desc) +{ + const uint32_t *ops = desc->m_ops; + uint32_t insn; + while ((insn = *ops) != DDS_OP_RTS) { - DDS_IS_GET4 (is, length, uint32_t); - if (DDS_IS_OK (is, length)) + if (DDS_OP (insn) != DDS_OP_ADR) + return 0; + + switch (DDS_OP_TYPE (insn)) { - src = DDS_CDR_ADDRESS (is, void); - if (bound) - { - memcpy (str, src, length > bound ? bound : length); - } - else - { - if ((str == NULL) || (strlen (str) + 1 < length)) + case DDS_OP_VAL_1BY: + case DDS_OP_VAL_2BY: + case DDS_OP_VAL_4BY: + case DDS_OP_VAL_8BY: + if ((ops[1] % get_type_size (DDS_OP_TYPE (insn))) != 0) + return 0; + ops += 2; + break; + + case DDS_OP_VAL_ARR: + switch (DDS_OP_SUBTYPE (insn)) { - str = dds_realloc (str, length); + case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: + if ((ops[1] % get_type_size (DDS_OP_SUBTYPE (insn))) != 0) + return 0; + ops += 3; + break; + default: + return 0; } - memcpy (str, src, length); - } - is->m_index += length; + break; + + default: + return 0; } } - return str; + return desc->m_size; } -char * dds_stream_read_string (dds_stream_t * is) +size_t dds_stream_check_optimize (const dds_topic_descriptor_t * __restrict desc) { - return dds_stream_reuse_string (is, NULL, 0); + const size_t size = dds_stream_check_optimize1 (desc); + DDS_TRACE ("Marshalling for type: %s is %soptimised\n", desc->m_typename, size ? "" : "not "); + return size; } -void dds_stream_swap (void * buff, uint32_t size, uint32_t num) +static char *dds_stream_reuse_string (dds_istream_t * __restrict is, char * __restrict str, const uint32_t bound) { - assert (size == 2 || size == 4 || size == 8); - - switch (size) + const uint32_t length = dds_is_get4 (is); + const void *src = is->m_buffer + is->m_index; + if (bound) { - case 2: - { - uint16_t * ptr = (uint16_t*) buff; - while (num--) - { - *ptr = DDS_SWAP16 (*ptr); - ptr++; - } - break; - } - case 4: - { - uint32_t * ptr = (uint32_t*) buff; - while (num--) - { - *ptr = DDS_SWAP32 (*ptr); - ptr++; - } - break; - } - default: - { - uint64_t * ptr = (uint64_t*) buff; - while (num--) - { - *ptr = DDS_SWAP64 (*ptr); - ptr++; - } - break; - } - } -} - -static void dds_stream_read_fixed_buffer - (dds_stream_t * is, void * buff, uint32_t len, const uint32_t size, const bool swap) -{ - if (size && len) - { - DDS_CDR_ALIGNTO (is, size); - DDS_IS_GET_BYTES (is, buff, len * size); - if (swap && (size > 1)) - { - dds_stream_swap (buff, size, len); - } - } -} - -void dds_stream_read_buffer (dds_stream_t * is, uint8_t * buffer, uint32_t len) -{ - if (DDS_IS_OK (is, len)) - { - DDS_IS_GET_BYTES (is, buffer, len); - } -} - -void dds_stream_read_sample (dds_stream_t * is, void * data, const struct ddsi_sertopic_default * topic) -{ - const struct dds_topic_descriptor * desc = topic->type; - /* Check if can copy directly from stream buffer */ - if (topic->opt_size && DDS_IS_OK (is, desc->m_size) && (is->m_endian == DDS_ENDIAN)) - { - DDS_IS_GET_BYTES (is, data, desc->m_size); + /* FIXME: validation now rejects data containing an oversize bounded string, + so this check is superfluous, but perhaps rejecting such a sample is the + wrong thing to do */ + assert (str != NULL); + memcpy (str, src, length > bound ? bound : length); } else { - dds_stream_read (is, data, desc->m_ops); + if (str == NULL || strlen (str) + 1 < length) + str = dds_realloc (str, length); + memcpy (str, src, length); } + is->m_index += length; + return str; } -void dds_stream_write_bool (dds_stream_t * os, bool val) +static void dds_stream_skip_forward (dds_istream_t * __restrict is, uint32_t len, const uint32_t elem_size) { - dds_stream_write_uint8 (os, val ? 1 : 0); + if (elem_size && len) + is->m_index += len * elem_size; } -void dds_stream_write_uint8 (dds_stream_t * os, uint8_t val) +static void dds_stream_skip_string (dds_istream_t * __restrict is) { - DDS_OS_PUT1 (os, val); + const uint32_t length = dds_is_get4 (is); + dds_stream_skip_forward (is, length, 1); } -void dds_stream_write_uint16 (dds_stream_t * os, uint16_t val) -{ - DDS_OS_PUT2 (os, val); -} - -void dds_stream_write_uint32 (dds_stream_t * os, uint32_t val) -{ - DDS_OS_PUT4 (os, val, uint32_t); -} - -void dds_stream_write_uint64 (dds_stream_t * os, uint64_t val) -{ - DDS_OS_PUT8 (os, val, uint64_t); -} - -extern inline void dds_stream_write_char (dds_stream_t * os, char val); -extern inline void dds_stream_write_int8 (dds_stream_t * os, int8_t val); -extern inline void dds_stream_write_int16 (dds_stream_t * os, int16_t val); -extern inline void dds_stream_write_int32 (dds_stream_t * os, int32_t val); -extern inline void dds_stream_write_int64 (dds_stream_t * os, int64_t val); - -void dds_stream_write_float (dds_stream_t * os, float val) -{ - union { float f; uint32_t u; } u; - u.f = val; - dds_stream_write_uint32 (os, u.u); -} - -void dds_stream_write_double (dds_stream_t * os, double val) -{ - union { double f; uint64_t u; } u; - u.f = val; - dds_stream_write_uint64 (os, u.u); -} - -void dds_stream_write_string (dds_stream_t * os, const char * val) +static void dds_stream_write_string (dds_ostream_t * __restrict os, const char * __restrict val) { uint32_t size = 1; if (val) { - size += (uint32_t)strlen (val); /* Type casting is done for the warning of conversion from 'size_t' to 'uint32_t', which may cause possible loss of data */ + /* Type casting is done for the warning of conversion from 'size_t' to 'uint32_t', which may cause possible loss of data */ + size += (uint32_t) strlen (val); } - DDS_OS_PUT4 (os, size, uint32_t); + dds_os_put4 (os, size); if (val) { - DDS_OS_PUT_BYTES (os, (uint8_t*) val, size); + dds_os_put_bytes (os, val, size); } else { - DDS_OS_PUT1 (os, 0U); + dds_os_put1 (os, 0); } } -void dds_stream_write_buffer (dds_stream_t * os, uint32_t len, const uint8_t * buffer) +static void dds_streamBE_write_string (dds_ostreamBE_t * __restrict os, const char * __restrict val) { - DDS_OS_PUT_BYTES (os, buffer, len); -} + uint32_t size = 1; -void *dds_stream_address (dds_stream_t * s) -{ - return DDS_CDR_ADDRESS(s, void); -} - -void *dds_stream_alignto (dds_stream_t * s, uint32_t a) -{ - DDS_CDR_ALIGNTO (s, a); - return DDS_CDR_ADDRESS (s, void); -} - -static void dds_stream_write -( - dds_stream_t * os, - const char * data, - const uint32_t * ops -) -{ - uint32_t align; - uint32_t op; - uint32_t type; - uint32_t subtype; - uint32_t num; - const char * addr; - - while ((op = *ops) != DDS_OP_RTS) + if (val) { - switch (DDS_OP_MASK & op) - { - case DDS_OP_ADR: - { - type = DDS_OP_TYPE (op); -#ifdef OP_DEBUG_WRITE - DDS_TRACE("W-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: - { - DDS_OS_PUT1 (os, *(uint8_t*) addr); - break; - } - case DDS_OP_VAL_2BY: - { - DDS_OS_PUT2 (os, *(uint16_t*) addr); - break; - } - case DDS_OP_VAL_4BY: - { - DDS_OS_PUT4 (os, *(uint32_t*) addr, uint32_t); - break; - } - case DDS_OP_VAL_8BY: - { - DDS_OS_PUT8 (os, *(uint64_t*) addr, uint64_t); - break; - } - case DDS_OP_VAL_STR: - { -#ifdef OP_DEBUG_WRITE - DDS_TRACE("W-STR: %s\n", *((char**) addr)); -#endif - dds_stream_write_string (os, *((char**) addr)); - break; - } - case DDS_OP_VAL_SEQ: - { - dds_sequence_t * seq = (dds_sequence_t*) addr; - subtype = DDS_OP_SUBTYPE (op); - num = seq->_length; - -#ifdef OP_DEBUG_WRITE - DDS_TRACE("W-SEQ: %s <%d>\n", stream_op_type[subtype], num); -#endif - DDS_OS_PUT4 (os, num, uint32_t); - if (num || (subtype > DDS_OP_VAL_STR)) - { - switch (subtype) - { - case DDS_OP_VAL_1BY: - case DDS_OP_VAL_2BY: - case DDS_OP_VAL_4BY: - { - num = num * dds_op_size[subtype]; - DDS_OS_PUT_BYTES (os, seq->_buffer, num); - break; - } - case DDS_OP_VAL_8BY: - { - DDS_CDR_ALIGN8 (os); - DDS_OS_PUT_BYTES (os, seq->_buffer, num * 8u); - break; - } - case DDS_OP_VAL_STR: - { - char ** ptr = (char**) seq->_buffer; - while (num--) - { -#ifdef OP_DEBUG_WRITE - DDS_TRACE("W-SEQ STR: %s\n", *ptr); -#endif - dds_stream_write_string (os, *ptr); - ptr++; - } - break; - } - case DDS_OP_VAL_BST: - { - char * ptr = (char*) seq->_buffer; - align = *ops++; - while (num--) - { -#ifdef OP_DEBUG_WRITE - DDS_TRACE("W-SEQ BST[%d]: %s\n", align, ptr); -#endif - dds_stream_write_string (os, ptr); - ptr += align; - } - 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_write (os, ptr, jsr_ops); - ptr += elem_size; - } - ops += jmp ? (jmp - 3) : 1; - break; - } - } - } - break; - } - case DDS_OP_VAL_ARR: - { - subtype = DDS_OP_SUBTYPE (op); - num = *ops++; - -#ifdef OP_DEBUG_WRITE - DDS_TRACE("W-ARR: %s [%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: - { - align = dds_op_size[subtype]; - DDS_CDR_ALIGNTO (os, align); - DDS_OS_PUT_BYTES (os, addr, num * align); - break; - } - case DDS_OP_VAL_STR: - { - char ** ptr = (char**) addr; - while (num--) - { - dds_stream_write_string (os, *ptr); - ptr++; - } - break; - } - case DDS_OP_VAL_BST: - { - char * ptr = (char*) addr; - align = ops[1]; - while (num--) - { - dds_stream_write_string (os, ptr); - ptr += align; - } - 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_write (os, 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); - - /* Write discriminant */ - - switch (subtype) - { - case DDS_OP_VAL_1BY: - { - uint8_t d8 = *((uint8_t*) addr); - DDS_OS_PUT1 (os, d8); - disc = d8; - break; - } - case DDS_OP_VAL_2BY: - { - uint16_t d16 = *((uint16_t*) addr); - DDS_OS_PUT2 (os, d16); - disc = d16; - break; - } - case DDS_OP_VAL_4BY: - { - disc = *((uint32_t*) addr); - DDS_OS_PUT4 (os, disc, uint32_t); - break; - } - default: assert (0); - } -#ifdef OP_DEBUG_WRITE - DDS_TRACE("W-UNI: switch %s case %d/%d\n", stream_op_type[subtype], disc, num); -#endif - - /* Write case matching discriminant */ - - while (num--) - { - assert ((DDS_OP_MASK & jeq_op[0]) == DDS_OP_JEQ); - - /* Select matching or default case */ - - if ((jeq_op[1] == disc) || (has_default && (num == 0))) - { - subtype = DDS_JEQ_TYPE (jeq_op[0]); - addr = data + jeq_op[2]; - -#ifdef OP_DEBUG_WRITE - DDS_TRACE("W-UNI: case type %s\n", stream_op_type[subtype]); -#endif - switch (subtype) - { - case DDS_OP_VAL_1BY: - case DDS_OP_VAL_2BY: - case DDS_OP_VAL_4BY: - case DDS_OP_VAL_8BY: - { - align = dds_op_size[subtype]; - DDS_CDR_ALIGNTO (os, align); - DDS_OS_PUT_BYTES (os, addr, align); - break; - } - case DDS_OP_VAL_STR: - { - dds_stream_write_string (os, *(char**) addr); - break; - } - case DDS_OP_VAL_BST: - { - dds_stream_write_string (os, (char*) addr); - break; - } - default: - { - dds_stream_write (os, 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: - { -#ifdef OP_DEBUG_WRITE - DDS_TRACE("W-BST: %s\n", (char*) addr); -#endif - dds_stream_write_string (os, (char*) addr); - ops++; - break; - } - default: assert (0); - } - break; - } - case DDS_OP_JSR: /* Implies nested type */ - { -#ifdef OP_DEBUG_WRITE - DDS_TRACE("W-JSR: %d\n", DDS_OP_JUMP (op)); -#endif - dds_stream_write (os, data, ops + DDS_OP_JUMP (op)); - ops++; - break; - } - default: assert (0); - } + /* Type casting is done for the warning of conversion from 'size_t' to 'uint32_t', which may cause possible loss of data */ + size += (uint32_t) strlen (val); } -#ifdef OP_DEBUG_WRITE - DDS_TRACE("W-RTS:\n"); -#endif -} -static void dds_stream_read (dds_stream_t * is, char * data, const uint32_t * ops) -{ - uint32_t align; - uint32_t op; - uint32_t type; - uint32_t subtype; - uint32_t num; - char * addr; + dds_os_put4be (os, size); - while ((op = *ops) != DDS_OP_RTS) + if (val) { - switch (DDS_OP_MASK & op) - { - case DDS_OP_ADR: - { - type = DDS_OP_TYPE (op); -#ifdef OP_DEBUG_READ - DDS_TRACE("R-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: - { - *(uint8_t*) addr = dds_stream_read_uint8 (is); - break; - } - case DDS_OP_VAL_2BY: - { - *(uint16_t*) addr = dds_stream_read_uint16 (is); - break; - } - case DDS_OP_VAL_4BY: - { - *(uint32_t*) addr = dds_stream_read_uint32 (is); - break; - } - case DDS_OP_VAL_8BY: - { - *(uint64_t*) addr = dds_stream_read_uint64 (is); - break; - } - case DDS_OP_VAL_STR: - { -#ifdef OP_DEBUG_READ - DDS_TRACE("R-STR: @ %p\n", addr); -#endif - *(char**) addr = dds_stream_reuse_string (is, *((char**) addr), 0); - break; - } - case DDS_OP_VAL_SEQ: - { - dds_sequence_t * seq = (dds_sequence_t*) addr; - subtype = DDS_OP_SUBTYPE (op); - num = dds_stream_read_uint32 (is); - -#ifdef OP_DEBUG_READ - DDS_TRACE("R-SEQ: %s <%d>\n", stream_op_type[subtype], num); -#endif - /* Maintain max sequence length (may not have been set by caller) */ - - if (seq->_length > seq->_maximum) - { - seq->_maximum = seq->_length; - } - - switch (subtype) - { - case DDS_OP_VAL_1BY: - case DDS_OP_VAL_2BY: - case DDS_OP_VAL_4BY: - case DDS_OP_VAL_8BY: - { - align = dds_op_size[subtype]; - - /* Reuse sequence buffer if big enough */ - - if (num > seq->_length) - { - if (seq->_release && seq->_length) - { - seq->_buffer = dds_realloc_zero (seq->_buffer, num * align); - } - else - { - seq->_buffer = dds_alloc (num * align); - } - seq->_release = true; - seq->_maximum = num; - } - seq->_length = num; - dds_stream_read_fixed_buffer (is, seq->_buffer, seq->_length, align, is->m_endian != DDS_ENDIAN); - break; - } - case DDS_OP_VAL_STR: - { - char ** ptr; - - /* Reuse sequence buffer if big enough */ - - if (num > seq->_maximum) - { - if (seq->_release && seq->_maximum) - { - seq->_buffer = dds_realloc_zero (seq->_buffer, num * sizeof (char*)); - } - else - { - seq->_buffer = dds_alloc (num * sizeof (char*)); - } - seq->_release = true; - seq->_maximum = num; - } - seq->_length = num; - - ptr = (char**) seq->_buffer; - while (num--) - { - *ptr = dds_stream_reuse_string (is, *ptr, 0); - ptr++; - } - break; - } - case DDS_OP_VAL_BST: - { - char * ptr; - align = *ops++; - - /* Reuse sequence buffer if big enough */ - - if (num > seq->_maximum) - { - if (seq->_release && seq->_maximum) - { - seq->_buffer = dds_realloc_zero (seq->_buffer, num * align); - } - else - { - seq->_buffer = dds_alloc (num * align); - } - seq->_release = true; - seq->_maximum = num; - } - seq->_length = num; - - ptr = (char*) seq->_buffer; - while (num--) - { - dds_stream_reuse_string (is, ptr, align); - ptr += align; - } - 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); - uint32_t i; - char * ptr; - - /* Reuse sequence buffer if big enough */ - - if (num > seq->_maximum) - { - if (seq->_release && seq->_maximum) - { - if (seq->_buffer) - { - i = seq->_length; - ptr = (char*) seq->_buffer; - while (i--) - { - dds_sample_free_contents (ptr, jsr_ops); - ptr += elem_size; - } - } - seq->_buffer = dds_realloc_zero (seq->_buffer, num * elem_size); - } - else - { - seq->_buffer = dds_alloc (num * elem_size); - } - seq->_release = true; - seq->_maximum = num; - } - seq->_length = num; - - ptr = (char*) seq->_buffer; - while (num--) - { - dds_stream_read (is, ptr, jsr_ops); - ptr += elem_size; - } - ops += jmp ? (jmp - 3) : 1; - break; - } - } - break; - } - case DDS_OP_VAL_ARR: - { - subtype = DDS_OP_SUBTYPE (op); - num = *ops++; - -#ifdef OP_DEBUG_READ - DDS_TRACE("R-ARR: %s [%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: - { - align = dds_op_size[subtype]; - if (DDS_IS_OK (is, num * align)) - { - dds_stream_read_fixed_buffer (is, addr, num, align, is->m_endian != DDS_ENDIAN); - } - break; - } - case DDS_OP_VAL_STR: - { - char ** ptr = (char**) addr; - while (num--) - { - *ptr = dds_stream_reuse_string (is, *ptr, 0); - ptr++; - } - break; - } - case DDS_OP_VAL_BST: - { - char * ptr = (char*) addr; - align = ops[1]; - while (num--) - { - dds_stream_reuse_string (is, ptr, align); - ptr += align; - } - 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_read (is, 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); - - /* Read discriminant */ - - switch (subtype) - { - case DDS_OP_VAL_1BY: - { - uint8_t d8 = dds_stream_read_uint8 (is); - *(uint8_t*) addr = d8; - disc = d8; - break; - } - case DDS_OP_VAL_2BY: - { - uint16_t d16 = dds_stream_read_uint16 (is); - *(uint16_t*) addr = d16; - disc = d16; - break; - } - case DDS_OP_VAL_4BY: - { - disc = dds_stream_read_uint32 (is); - *(uint32_t*) addr = disc; - break; - } - default: assert (0); - } - -#ifdef OP_DEBUG_READ - DDS_TRACE("R-UNI: switch %s case %d/%d\n", stream_op_type[subtype], disc, num); -#endif - - /* Read 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]; - -#ifdef OP_DEBUG_READ - DDS_TRACE("R-UNI: case type %s\n", stream_op_type[subtype]); -#endif - switch (subtype) - { - case DDS_OP_VAL_1BY: - { - *(uint8_t*) addr = dds_stream_read_uint8 (is); - break; - } - case DDS_OP_VAL_2BY: - { - *(uint16_t*) addr = dds_stream_read_uint16 (is); - break; - } - case DDS_OP_VAL_4BY: - { - *(uint32_t*) addr = dds_stream_read_uint32 (is); - break; - } - case DDS_OP_VAL_8BY: - { - *(uint64_t*) addr = dds_stream_read_uint64 (is); - break; - } - case DDS_OP_VAL_STR: - { - *(char**) addr = dds_stream_reuse_string (is, *((char**) addr), 0); - break; - } - default: - { - dds_stream_read (is, 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: - { -#ifdef OP_DEBUG_READ - DDS_TRACE("R-BST: @ %p\n", addr); -#endif - dds_stream_reuse_string (is, (char*) addr, *ops); - ops++; - break; - } - default: assert (0); - } - break; - } - case DDS_OP_JSR: /* Implies nested type */ - { -#ifdef OP_DEBUG_READ - DDS_TRACE("R-JSR: %d\n", DDS_OP_JUMP (op)); -#endif - dds_stream_read (is, data, ops + DDS_OP_JUMP (op)); - ops++; - break; - } - default: assert (0); - } - } -#ifdef OP_DEBUG_READ - DDS_TRACE("R-RTS:\n"); -#endif -} - -void dds_stream_write_sample (dds_stream_t * os, const void * data, const struct ddsi_sertopic_default * topic) -{ - const struct dds_topic_descriptor * desc = topic->type; - - if (topic->opt_size && DDS_CDR_ALIGNED (os, desc->m_align)) - { - DDS_OS_PUT_BYTES (os, data, desc->m_size); + dds_os_put_bytes (&os->x, val, size); } else { - dds_stream_write (os, data, desc->m_ops); + dds_os_put1be (os, 0); } } -void dds_stream_from_serdata_default (dds_stream_t * s, const struct ddsi_serdata_default *d) +static bool insn_key_ok_p (uint32_t insn) { - s->m_failed = false; - s->m_buffer.p8 = (uint8_t*) d; - s->m_index = (uint32_t) offsetof (struct ddsi_serdata_default, data); - s->m_size = d->size + s->m_index; - assert (d->hdr.identifier == CDR_LE || d->hdr.identifier == CDR_BE); - s->m_endian = (d->hdr.identifier == CDR_LE); + return (DDS_OP (insn) == DDS_OP_ADR && (insn & DDS_OP_FLAG_KEY) && + (DDS_OP_TYPE (insn) <= DDS_OP_VAL_BST || + (DDS_OP_TYPE (insn) == DDS_OP_VAL_ARR && DDS_OP_SUBTYPE (insn) <= DDS_OP_VAL_8BY))); } -void dds_stream_add_to_serdata_default (dds_stream_t * s, struct ddsi_serdata_default **d) +static uint32_t read_union_discriminant (dds_istream_t * __restrict is, enum dds_stream_typecode type) { - /* DDSI requires 4 byte alignment */ - - DDS_CDR_ALIGN4 (s); - - /* Reset data pointer as stream may have reallocated */ - - (*d) = s->m_buffer.pv; - (*d)->pos = (s->m_index - (uint32_t)offsetof (struct ddsi_serdata_default, data)); - (*d)->size = (s->m_size - (uint32_t)offsetof (struct ddsi_serdata_default, data)); -} - -void dds_stream_write_key (dds_stream_t * os, const char * sample, const struct ddsi_sertopic_default * topic) -{ - const struct dds_topic_descriptor * desc = (const struct dds_topic_descriptor *) topic->type; - uint32_t i; - const char * src; - const uint32_t * op; - - for (i = 0; i < desc->m_nkeys; i++) + assert (type == DDS_OP_VAL_1BY || type == DDS_OP_VAL_2BY || type == DDS_OP_VAL_4BY); + switch (type) { - op = desc->m_ops + desc->m_keys[i].m_index; - src = sample + op[1]; - assert ((*op & DDS_OP_FLAG_KEY) && ((DDS_OP_MASK & *op) == DDS_OP_ADR)); + case DDS_OP_VAL_1BY: return dds_is_get1 (is); + case DDS_OP_VAL_2BY: return dds_is_get2 (is); + case DDS_OP_VAL_4BY: return dds_is_get4 (is); + default: return 0; + } +} + +static uint32_t write_union_discriminant (dds_ostream_t * __restrict os, enum dds_stream_typecode type, const void * __restrict addr) +{ + assert (type == DDS_OP_VAL_1BY || type == DDS_OP_VAL_2BY || type == DDS_OP_VAL_4BY); + switch (type) + { + case DDS_OP_VAL_1BY: { uint8_t d8 = *((const uint8_t *) addr); dds_os_put1 (os, d8); return d8; } + case DDS_OP_VAL_2BY: { uint16_t d16 = *((const uint16_t *) addr); dds_os_put2 (os, d16); return d16; } + case DDS_OP_VAL_4BY: { uint32_t d32 = *((const uint32_t *) addr); dds_os_put4 (os, d32); return d32; } + default: return 0; + } +} + +static const uint32_t *find_union_case (const uint32_t * __restrict union_ops, uint32_t disc) +{ + assert (DDS_OP_TYPE (*union_ops) == DDS_OP_VAL_UNI); + const bool has_default = *union_ops & DDS_OP_FLAG_DEF; + const uint32_t numcases = union_ops[2]; + const uint32_t *jeq_op = union_ops + DDS_OP_ADR_JSR (union_ops[3]); + /* Find union case; default case is always the last one */ + assert (numcases > 0); + uint32_t ci; +#ifndef NDEBUG + for (ci = 0; ci < numcases; ci++) + assert (DDS_OP (jeq_op[3 * ci]) == DDS_OP_JEQ); +#endif + for (ci = 0; ci < numcases - (has_default ? 1 : 0); ci++, jeq_op += 3) + if (jeq_op[1] == disc) + return jeq_op; + return (ci < numcases) ? jeq_op : NULL; +} + +static const uint32_t *skip_sequence_insns (const uint32_t * __restrict ops, uint32_t insn) +{ + switch (DDS_OP_SUBTYPE (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: + return ops + 2; + case DDS_OP_VAL_BST: + return ops + 3; /* bound */ + 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]); + return ops + (jmp ? jmp : 4); /* FIXME: why would jmp be 0? */ + } + } + return NULL; +} + +static const uint32_t *dds_stream_write_seq (dds_ostream_t * __restrict os, const char * __restrict addr, const uint32_t * __restrict ops, uint32_t insn) +{ + const dds_sequence_t * const seq = (const dds_sequence_t *) addr; + const uint32_t num = seq->_length; + + dds_os_put4 (os, num); + if (num == 0) + return skip_sequence_insns (ops, insn); + + const enum dds_stream_typecode subtype = DDS_OP_SUBTYPE (insn); + /* following length, stream is aligned to mod 4 */ + switch (subtype) + { + case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: + dds_os_put_bytes_aligned (os, seq->_buffer, num, get_type_size (subtype)); + return ops + 2; + case DDS_OP_VAL_STR: { + const char **ptr = (const char **) seq->_buffer; + for (uint32_t i = 0; i < num; i++) + dds_stream_write_string (os, ptr[i]); + return ops + 2; + } + case DDS_OP_VAL_BST: { + const char *ptr = (const char *) seq->_buffer; + const uint32_t elem_size = ops[2]; + for (uint32_t i = 0; i < num; i++) + dds_stream_write_string (os, ptr + i * elem_size); + return ops + 3; + } + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { + const uint32_t elem_size = ops[2]; + const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]); + uint32_t const * const jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]); + const char *ptr = (const char *) seq->_buffer; + for (uint32_t i = 0; i < num; i++) + dds_stream_write (os, ptr + i * elem_size, jsr_ops); + return ops + (jmp ? jmp : 4); /* FIXME: why would jmp be 0? */ + } + } + return NULL; +} + +static const uint32_t *dds_stream_write_arr (dds_ostream_t * __restrict os, const char * __restrict addr, const uint32_t * __restrict ops, uint32_t insn) +{ + const enum dds_stream_typecode subtype = DDS_OP_SUBTYPE (insn); + const uint32_t num = ops[2]; + switch (subtype) + { + case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: + dds_os_put_bytes_aligned (os, addr, num, get_type_size (subtype)); + return ops + 3; + case DDS_OP_VAL_STR: { + const char **ptr = (const char **) addr; + for (uint32_t i = 0; i < num; i++) + dds_stream_write_string (os, ptr[i]); + return ops + 3; + } + case DDS_OP_VAL_BST: { + const char *ptr = (const char *) addr; + const uint32_t elem_size = ops[4]; + for (uint32_t i = 0; i < num; i++) + dds_stream_write_string (os, ptr + i * elem_size); + return 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 * jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]); + const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]); + const uint32_t elem_size = ops[4]; + for (uint32_t i = 0; i < num; i++) + dds_stream_write (os, addr + i * elem_size, jsr_ops); + return ops + (jmp ? jmp : 5); + } + } + return NULL; +} + +static const uint32_t *dds_stream_write_uni (dds_ostream_t * __restrict os, const char * __restrict discaddr, const char * __restrict baseaddr, const uint32_t * __restrict ops, uint32_t insn) +{ + const uint32_t disc = write_union_discriminant (os, DDS_OP_SUBTYPE (insn), discaddr); + uint32_t const * const jeq_op = find_union_case (ops, disc); + ops += DDS_OP_ADR_JMP (ops[3]); + if (jeq_op) + { + const enum dds_stream_typecode valtype = DDS_JEQ_TYPE (jeq_op[0]); + const void *valaddr = baseaddr + jeq_op[2]; + switch (valtype) + { + case DDS_OP_VAL_1BY: dds_os_put1 (os, *(const uint8_t *) valaddr); break; + case DDS_OP_VAL_2BY: dds_os_put2 (os, *(const uint16_t *) valaddr); break; + case DDS_OP_VAL_4BY: dds_os_put4 (os, *(const uint32_t *) valaddr); break; + case DDS_OP_VAL_8BY: dds_os_put8 (os, *(const uint64_t *) valaddr); break; + case DDS_OP_VAL_STR: dds_stream_write_string (os, *(const char **) valaddr); break; + case DDS_OP_VAL_BST: dds_stream_write_string (os, (const char *) valaddr); break; + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: + dds_stream_write (os, valaddr, jeq_op + DDS_OP_ADR_JSR (jeq_op[0])); + break; + } + } + return ops; +} + +static void dds_stream_write (dds_ostream_t * __restrict os, const char * __restrict data, const uint32_t * __restrict ops) +{ + uint32_t insn; + while ((insn = *ops) != DDS_OP_RTS) + { + switch (DDS_OP (insn)) + { + case DDS_OP_ADR: { + const void *addr = data + ops[1]; + switch (DDS_OP_TYPE (insn)) + { + case DDS_OP_VAL_1BY: dds_os_put1 (os, *((const uint8_t *) addr)); ops += 2; break; + case DDS_OP_VAL_2BY: dds_os_put2 (os, *((const uint16_t *) addr)); ops += 2; break; + case DDS_OP_VAL_4BY: dds_os_put4 (os, *((const uint32_t *) addr)); ops += 2; break; + case DDS_OP_VAL_8BY: dds_os_put8 (os, *((const uint64_t *) addr)); ops += 2; break; + case DDS_OP_VAL_STR: dds_stream_write_string (os, *((const char **) addr)); ops += 2; break; + case DDS_OP_VAL_BST: dds_stream_write_string (os, (const char *) addr); ops += 3; break; + case DDS_OP_VAL_SEQ: ops = dds_stream_write_seq (os, addr, ops, insn); break; + case DDS_OP_VAL_ARR: ops = dds_stream_write_arr (os, addr, ops, insn); break; + case DDS_OP_VAL_UNI: ops = dds_stream_write_uni (os, addr, data, ops, insn); break; + case DDS_OP_VAL_STU: abort (); break; + } + break; + } + case DDS_OP_JSR: { + dds_stream_write (os, data, ops + DDS_OP_JUMP (insn)); + ops++; + break; + } + case DDS_OP_RTS: case DDS_OP_JEQ: { + abort (); + break; + } + } + } +} + +static void realloc_sequence_buffer_if_needed (dds_sequence_t * __restrict seq, uint32_t num, uint32_t elem_size, bool init) +{ + const uint32_t size = num * elem_size; + + /* maintain max sequence length (may not have been set by caller) */ + if (seq->_length > seq->_maximum) + seq->_maximum = seq->_length; + + if (num > seq->_maximum && seq->_release) + { + seq->_buffer = ddsrt_realloc (seq->_buffer, size); + if (init) + { + const uint32_t off = seq->_maximum * elem_size; + memset (seq->_buffer + off, 0, size - off); + } + seq->_maximum = num; + } + else if (num > 0 && seq->_maximum == 0) + { + seq->_buffer = ddsrt_malloc (size); + if (init) + memset (seq->_buffer, 0, size); + seq->_release = true; + seq->_maximum = num; + } +} + +static const uint32_t *dds_stream_read_seq (dds_istream_t * __restrict is, char * __restrict addr, const uint32_t * __restrict ops, uint32_t insn) +{ + dds_sequence_t * const seq = (dds_sequence_t *) addr; + const enum dds_stream_typecode subtype = DDS_OP_SUBTYPE (insn); + const uint32_t num = dds_is_get4 (is); + if (num == 0) + { + seq->_length = 0; + return skip_sequence_insns (ops, insn); + } + + switch (subtype) + { + case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: { + const uint32_t elem_size = get_type_size (subtype); + realloc_sequence_buffer_if_needed (seq, num, elem_size, false); + seq->_length = (num <= seq->_maximum) ? num : seq->_maximum; + dds_is_get_bytes (is, seq->_buffer, seq->_length, elem_size); + if (seq->_length < num) + dds_stream_skip_forward (is, num - seq->_length, elem_size); + return ops + 2; + } + case DDS_OP_VAL_STR: { + realloc_sequence_buffer_if_needed (seq, num, sizeof (char *), true); + seq->_length = (num <= seq->_maximum) ? num : seq->_maximum; + char **ptr = (char **) seq->_buffer; + for (uint32_t i = 0; i < seq->_length; i++) + ptr[i] = dds_stream_reuse_string (is, ptr[i], 0); + for (uint32_t i = seq->_length; i < num; i++) + dds_stream_skip_string (is); + return ops + 2; + } + case DDS_OP_VAL_BST: { + const uint32_t elem_size = ops[2]; + realloc_sequence_buffer_if_needed (seq, num, elem_size, false); + seq->_length = (num <= seq->_maximum) ? num : seq->_maximum; + char *ptr = (char *) seq->_buffer; + for (uint32_t i = 0; i < seq->_length; i++) + (void) dds_stream_reuse_string (is, ptr + i * elem_size, elem_size); + for (uint32_t i = seq->_length; i < num; i++) + dds_stream_skip_string (is); + return ops + 3; + } + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { + const uint32_t elem_size = ops[2]; + const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]); + uint32_t const * const jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]); + realloc_sequence_buffer_if_needed (seq, num, elem_size, true); + seq->_length = (num <= seq->_maximum) ? num : seq->_maximum; + char *ptr = (char *) seq->_buffer; + for (uint32_t i = 0; i < num; i++) + dds_stream_read (is, ptr + i * elem_size, jsr_ops); + return ops + (jmp ? jmp : 4); /* FIXME: why would jmp be 0? */ + } + } + return NULL; +} + +static const uint32_t *dds_stream_read_arr (dds_istream_t * __restrict is, char * __restrict addr, const uint32_t * __restrict ops, uint32_t insn) +{ + const enum dds_stream_typecode subtype = DDS_OP_SUBTYPE (insn); + const uint32_t num = ops[2]; + switch (subtype) + { + case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: { + const uint32_t elem_size = get_type_size (subtype); + dds_is_get_bytes (is, addr, num, elem_size); + return ops + 3; + } + case DDS_OP_VAL_STR: { + char **ptr = (char **) addr; + for (uint32_t i = 0; i < num; i++) + ptr[i] = dds_stream_reuse_string (is, ptr[i], 0); + return ops + 3; + } + case DDS_OP_VAL_BST: { + char *ptr = (char *) addr; + const uint32_t elem_size = ops[4]; + for (uint32_t i = 0; i < num; i++) + (void) dds_stream_reuse_string (is, ptr + i * elem_size, elem_size); + return ops + 5; + } + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { + const uint32_t *jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]); + const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]); + const uint32_t elem_size = ops[4]; + for (uint32_t i = 0; i < num; i++) + dds_stream_read (is, addr + i * elem_size, jsr_ops); + return ops + (jmp ? jmp : 5); + } + } + return NULL; +} + +static const uint32_t *dds_stream_read_uni (dds_istream_t * __restrict is, char * __restrict discaddr, char * __restrict baseaddr, const uint32_t * __restrict ops, uint32_t insn) +{ + const uint32_t disc = read_union_discriminant (is, DDS_OP_SUBTYPE (insn)); + switch (DDS_OP_SUBTYPE (insn)) + { + case DDS_OP_VAL_1BY: *((uint8_t *) discaddr) = (uint8_t) disc; break; + case DDS_OP_VAL_2BY: *((uint16_t *) discaddr) = (uint16_t) disc; break; + case DDS_OP_VAL_4BY: *((uint32_t *) discaddr) = disc; break; + default: break; + } + uint32_t const * const jeq_op = find_union_case (ops, disc); + ops += DDS_OP_ADR_JMP (ops[3]); + if (jeq_op) + { + const enum dds_stream_typecode valtype = DDS_JEQ_TYPE (jeq_op[0]); + void *valaddr = baseaddr + jeq_op[2]; + switch (valtype) + { + case DDS_OP_VAL_1BY: *((uint8_t *) valaddr) = dds_is_get1 (is); break; + case DDS_OP_VAL_2BY: *((uint16_t *) valaddr) = dds_is_get2 (is); break; + case DDS_OP_VAL_4BY: *((uint32_t *) valaddr) = dds_is_get4 (is); break; + case DDS_OP_VAL_8BY: *((uint64_t *) valaddr) = dds_is_get8 (is); break; + case DDS_OP_VAL_STR: *(char **) valaddr = dds_stream_reuse_string (is, *((char **) valaddr), 0); break; + case DDS_OP_VAL_BST: case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: + dds_stream_read (is, valaddr, jeq_op + DDS_OP_ADR_JSR (jeq_op[0])); + break; + } + } + return ops; +} + +static void dds_stream_read (dds_istream_t * __restrict is, char * __restrict data, const uint32_t * __restrict ops) +{ + uint32_t insn; + while ((insn = *ops) != DDS_OP_RTS) + { + switch (DDS_OP (insn)) + { + case DDS_OP_ADR: { + void *addr = data + ops[1]; + switch (DDS_OP_TYPE (insn)) + { + case DDS_OP_VAL_1BY: *((uint8_t *) addr) = dds_is_get1 (is); ops += 2; break; + case DDS_OP_VAL_2BY: *((uint16_t *) addr) = dds_is_get2 (is); ops += 2; break; + case DDS_OP_VAL_4BY: *((uint32_t *) addr) = dds_is_get4 (is); ops += 2; break; + case DDS_OP_VAL_8BY: *((uint64_t *) addr) = dds_is_get8 (is); ops += 2; break; + case DDS_OP_VAL_STR: *((char **) addr) = dds_stream_reuse_string (is, *((char **) addr), 0); ops += 2; break; + case DDS_OP_VAL_BST: dds_stream_reuse_string (is, (char *) addr, ops[2]); ops += 3; break; + case DDS_OP_VAL_SEQ: ops = dds_stream_read_seq (is, addr, ops, insn); break; + case DDS_OP_VAL_ARR: ops = dds_stream_read_arr (is, addr, ops, insn); break; + case DDS_OP_VAL_UNI: ops = dds_stream_read_uni (is, addr, data, ops, insn); break; + case DDS_OP_VAL_STU: abort (); break; + } + break; + } + case DDS_OP_JSR: { + dds_stream_read (is, data, ops + DDS_OP_JUMP (insn)); + ops++; + break; + } + case DDS_OP_RTS: case DDS_OP_JEQ: { + abort (); + break; + } + } + } +} + +/******************************************************************************************* + ** + ** Validation and conversion to native endian. + ** + *******************************************************************************************/ + +/* Limit the size of the input buffer so we don't need to worry about adding + padding and a primitive type overflowing our offset */ +#define CDR_SIZE_MAX ((uint32_t) 0xfffffff0) + +static bool stream_normalize (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap, const uint32_t * __restrict ops); + +static uint32_t check_align_prim (uint32_t off, uint32_t size, uint32_t a_lg2) +{ + assert (a_lg2 <= 3); + const uint32_t a = 1u << a_lg2; + assert (size <= CDR_SIZE_MAX); + assert (off <= size); + const uint32_t off1 = (off + a - 1) & ~(a - 1); + assert (off <= off1 && off1 <= CDR_SIZE_MAX); + if (size < off1 + a) + return UINT32_MAX; + return off1; +} + +static uint32_t check_align_prim_many (uint32_t off, uint32_t size, uint32_t a_lg2, uint32_t n) +{ + assert (a_lg2 <= 3); + const uint32_t a = 1u << a_lg2; + assert (size <= CDR_SIZE_MAX); + assert (off <= size); + const uint32_t off1 = (off + a - 1) & ~(a - 1); + assert (off <= off1 && off1 <= CDR_SIZE_MAX); + if (size < off1 || ((size - off1) >> a_lg2) < n) + return UINT32_MAX; + return off1; +} + +static bool normalize_uint8 (uint32_t *off, uint32_t size) +{ + if (*off == size) + return false; + (*off)++; + return true; +} + +static bool normalize_uint16 (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap) +{ + if ((*off = check_align_prim (*off, size, 1)) == UINT32_MAX) + return false; + if (bswap) + *((uint16_t *) (data + *off)) = bswap2u (*((uint16_t *) (data + *off))); + (*off) += 2; + return true; +} + +static bool normalize_uint32 (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap) +{ + if ((*off = check_align_prim (*off, size, 2)) == UINT32_MAX) + return false; + if (bswap) + *((uint32_t *) (data + *off)) = bswap4u (*((uint32_t *) (data + *off))); + (*off) += 4; + return true; +} + +static bool read_and_normalize_uint32 (uint32_t * __restrict val, char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap) +{ + if ((*off = check_align_prim (*off, size, 2)) == UINT32_MAX) + return false; + if (bswap) + *((uint32_t *) (data + *off)) = bswap4u (*((uint32_t *) (data + *off))); + *val = *((uint32_t *) (data + *off)); + (*off) += 4; + return true; +} + +static bool normalize_uint64 (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap) +{ + if ((*off = check_align_prim (*off, size, 3)) == UINT32_MAX) + return false; + if (bswap) + *((uint64_t *) (data + *off)) = bswap8u (*((uint64_t *) (data + *off))); + (*off) += 8; + return true; +} + +static bool normalize_string (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap, size_t maxsz) +{ + uint32_t sz; + if (!read_and_normalize_uint32 (&sz, data, off, size, bswap)) + return false; + if (sz == 0 || size - *off < sz || maxsz < sz) + return false; + if (data[*off + sz - 1] != 0) + return false; + *off += sz; + return true; +} + +static bool normalize_primarray (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap, uint32_t num, enum dds_stream_typecode type) +{ + switch (type) + { + case DDS_OP_VAL_1BY: + if ((*off = check_align_prim_many (*off, size, 0, num)) == UINT32_MAX) + return false; + *off += num; + return true; + case DDS_OP_VAL_2BY: + if ((*off = check_align_prim_many (*off, size, 1, num)) == UINT32_MAX) + return false; + if (bswap) + { + uint16_t *xs = (uint16_t *) (data + *off); + for (uint32_t i = 0; i < num; i++) + xs[i] = bswap2u (xs[i]); + } + *off += 2 * num; + return true; + case DDS_OP_VAL_4BY: + if ((*off = check_align_prim_many (*off, size, 2, num)) == UINT32_MAX) + return false; + if (bswap) + { + uint32_t *xs = (uint32_t *) (data + *off); + for (uint32_t i = 0; i < num; i++) + xs[i] = bswap4u (xs[i]); + } + *off += 4 * num; + return true; + case DDS_OP_VAL_8BY: + if ((*off = check_align_prim_many (*off, size, 3, num)) == UINT32_MAX) + return false; + if (bswap) + { + uint64_t *xs = (uint64_t *) (data + *off); + for (uint32_t i = 0; i < num; i++) + xs[i] = bswap8u (xs[i]); + } + *off += 8 * num; + return true; + default: + abort (); + break; + } + return false; +} + +static const uint32_t *normalize_seq (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap, const uint32_t * __restrict ops, uint32_t insn) +{ + const enum dds_stream_typecode subtype = DDS_OP_SUBTYPE (insn); + uint32_t num; + if (!read_and_normalize_uint32 (&num, data, off, size, bswap)) + return NULL; + if (num == 0) + return skip_sequence_insns (ops, insn); + switch (subtype) + { + case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: + if (!normalize_primarray (data, off, size, bswap, num, subtype)) + return NULL; + return ops + 2; + case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: { + const size_t maxsz = (subtype == DDS_OP_VAL_STR) ? SIZE_MAX : ops[2]; + for (uint32_t i = 0; i < num; i++) + if (!normalize_string (data, off, size, bswap, maxsz)) + return NULL; + return ops + (subtype == DDS_OP_VAL_STR ? 2 : 3); + } + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { + const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]); + uint32_t const * const jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]); + for (uint32_t i = 0; i < num; i++) + if (!stream_normalize (data, off, size, bswap, jsr_ops)) + return NULL; + return ops + (jmp ? jmp : 4); /* FIXME: why would jmp be 0? */ + } + } + return NULL; +} + +static const uint32_t *normalize_arr (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap, const uint32_t * __restrict ops, uint32_t insn) +{ + const enum dds_stream_typecode subtype = DDS_OP_SUBTYPE (insn); + const uint32_t num = ops[2]; + switch (subtype) + { + case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: + if (!normalize_primarray (data, off, size, bswap, num, subtype)) + return NULL; + return ops + 3; + case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: { + const size_t maxsz = (subtype == DDS_OP_VAL_STR) ? SIZE_MAX : ops[4]; + for (uint32_t i = 0; i < num; i++) + if (!normalize_string (data, off, size, bswap, maxsz)) + return NULL; + return ops + (subtype == DDS_OP_VAL_STR ? 3 : 5); + } + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { + const uint32_t *jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]); + const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]); + for (uint32_t i = 0; i < num; i++) + if (!stream_normalize (data, off, size, bswap, jsr_ops)) + return NULL; + return ops + (jmp ? jmp : 5); + } + } + return NULL; +} + +static bool normalize_uni_disc (uint32_t * __restrict val, char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap, enum dds_stream_typecode disctype) +{ + switch (disctype) + { + case DDS_OP_VAL_1BY: + if ((*off = check_align_prim (*off, size, 0)) == UINT32_MAX) + return false; + *val = *((uint8_t *) (data + *off)); + (*off) += 1; + return true; + case DDS_OP_VAL_2BY: + if ((*off = check_align_prim (*off, size, 1)) == UINT32_MAX) + return false; + if (bswap) + *((uint16_t *) (data + *off)) = bswap2u (*((uint16_t *) (data + *off))); + *val = *((uint16_t *) (data + *off)); + (*off) += 2; + return true; + case DDS_OP_VAL_4BY: + if ((*off = check_align_prim (*off, size, 2)) == UINT32_MAX) + return false; + if (bswap) + *((uint32_t *) (data + *off)) = bswap4u (*((uint32_t *) (data + *off))); + *val = *((uint32_t *) (data + *off)); + (*off) += 4; + return true; + default: + abort (); + } + return false; +} + +static const uint32_t *normalize_uni (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap, const uint32_t * __restrict ops, uint32_t insn) +{ + uint32_t disc; + if (!normalize_uni_disc (&disc, data, off, size, bswap, DDS_OP_SUBTYPE (insn))) + return NULL; + uint32_t const * const jeq_op = find_union_case (ops, disc); + ops += DDS_OP_ADR_JMP (ops[3]); + if (jeq_op) + { + const enum dds_stream_typecode valtype = DDS_JEQ_TYPE (jeq_op[0]); + switch (valtype) + { + case DDS_OP_VAL_1BY: if (!normalize_uint8 (off, size)) return NULL; break; + case DDS_OP_VAL_2BY: if (!normalize_uint16 (data, off, size, bswap)) return NULL; break; + case DDS_OP_VAL_4BY: if (!normalize_uint32 (data, off, size, bswap)) return NULL; break; + case DDS_OP_VAL_8BY: if (!normalize_uint64 (data, off, size, bswap)) return NULL; break; + case DDS_OP_VAL_STR: if (!normalize_string (data, off, size, bswap, SIZE_MAX)) return NULL; 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: + if (!stream_normalize (data, off, size, bswap, jeq_op + DDS_OP_ADR_JSR (jeq_op[0]))) + return NULL; + break; + } + } + return ops; +} + +static bool stream_normalize (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap, const uint32_t * __restrict ops) +{ + 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: if (!normalize_uint8 (off, size)) return false; ops += 2; break; + case DDS_OP_VAL_2BY: if (!normalize_uint16 (data, off, size, bswap)) return false; ops += 2; break; + case DDS_OP_VAL_4BY: if (!normalize_uint32 (data, off, size, bswap)) return false; ops += 2; break; + case DDS_OP_VAL_8BY: if (!normalize_uint64 (data, off, size, bswap)) return false; ops += 2; break; + case DDS_OP_VAL_STR: if (!normalize_string (data, off, size, bswap, SIZE_MAX)) return false; ops += 2; break; + case DDS_OP_VAL_BST: if (!normalize_string (data, off, size, bswap, ops[2])) return false; ops += 3; break; + case DDS_OP_VAL_SEQ: ops = normalize_seq (data, off, size, bswap, ops, insn); if (!ops) return false; break; + case DDS_OP_VAL_ARR: ops = normalize_arr (data, off, size, bswap, ops, insn); if (!ops) return false; break; + case DDS_OP_VAL_UNI: ops = normalize_uni (data, off, size, bswap, ops, insn); if (!ops) return false; break; + case DDS_OP_VAL_STU: abort (); break; + } + break; + } + case DDS_OP_JSR: { + if (!stream_normalize (data, off, size, bswap, ops + DDS_OP_JUMP (insn))) + return false; + ops++; + break; + } + case DDS_OP_RTS: case DDS_OP_JEQ: { + abort (); + break; + } + } + } + return true; +} + +static bool stream_normalize_key (void * __restrict data, uint32_t size, bool bswap, const struct dds_topic_descriptor * __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; + insn_key_ok_p (*op); switch (DDS_OP_TYPE (*op)) { - case DDS_OP_VAL_1BY: - DDS_OS_PUT1 (os, *((uint8_t*) src)); - break; - case DDS_OP_VAL_2BY: - DDS_OS_PUT2 (os, *((uint16_t*) src)); - break; - case DDS_OP_VAL_4BY: - DDS_OS_PUT4 (os, *((uint32_t*) src), uint32_t); - break; - case DDS_OP_VAL_8BY: - DDS_OS_PUT8 (os, *((uint64_t*) src), uint64_t); - break; - case DDS_OP_VAL_STR: - src = *(char**) src; - /* FALLS THROUGH */ - case DDS_OP_VAL_BST: - dds_stream_write_string (os, src); + case DDS_OP_VAL_1BY: if (!normalize_uint8 (&off, size)) return false; break; + case DDS_OP_VAL_2BY: if (!normalize_uint16 (data, &off, size, bswap)) return false; break; + case DDS_OP_VAL_4BY: if (!normalize_uint32 (data, &off, size, bswap)) return false; break; + case DDS_OP_VAL_8BY: if (!normalize_uint64 (data, &off, size, bswap)) return false; break; + case DDS_OP_VAL_STR: if (!normalize_string (data, &off, size, bswap, SIZE_MAX)) return false; break; + case DDS_OP_VAL_BST: if (!normalize_string (data, &off, size, bswap, op[2])) return false; break; + case DDS_OP_VAL_ARR: if (!normalize_arr (data, &off, size, bswap, op, *op)) return false; break; + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: + abort (); break; + } + } + return true; +} + +bool dds_stream_normalize (void * __restrict data, uint32_t size, bool bswap, const struct ddsi_sertopic_default * __restrict topic, bool just_key) +{ + if (size > CDR_SIZE_MAX) + return false; + if (just_key) + 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); + } +} + +/******************************************************************************************* + ** + ** Read/write of samples and keys -- i.e., DDSI payloads. + ** + *******************************************************************************************/ + +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; + if (topic->opt_size) + dds_is_get_bytes (is, data, desc->m_size, 1); + else + { + if (desc->m_flagset & DDS_TOPIC_CONTAINS_UNION) + { + /* Switching union cases causes big trouble if some cases have sequences or strings, + and other cases have other things mapped to those addresses. So, pretend to be + nice by freeing whatever was allocated, then clearing all memory. This will + 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); + memset (data, 0, desc->m_size); + } + dds_stream_read (is, data, desc->m_ops); + } +} + +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; + if (topic->opt_size && desc->m_align && (os->m_index % desc->m_align) == 0) + dds_os_put_bytes (os, data, desc->m_size); + else + dds_stream_write (os, data, desc->m_ops); +} + +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; + for (uint32_t i = 0; i < desc->m_nkeys; i++) + { + const uint32_t *op = desc->m_ops + desc->m_keys[i].m_index; + char *dst = sample + op[1]; + insn_key_ok_p (*op); + switch (DDS_OP_TYPE (*op)) + { + case DDS_OP_VAL_1BY: *((uint8_t *) dst) = dds_is_get1 (is); break; + case DDS_OP_VAL_2BY: *((uint16_t *) dst) = dds_is_get2 (is); break; + case DDS_OP_VAL_4BY: *((uint32_t *) dst) = dds_is_get4 (is); break; + case DDS_OP_VAL_8BY: *((uint64_t *) dst) = dds_is_get8 (is); break; + case DDS_OP_VAL_STR: *((char **) dst) = dds_stream_reuse_string (is, *((char **) dst), 0); break; + case DDS_OP_VAL_BST: dds_stream_reuse_string (is, dst, op[2]); break; case DDS_OP_VAL_ARR: - { - uint32_t subtype = DDS_OP_SUBTYPE (*op); - assert (subtype <= DDS_OP_VAL_8BY); - uint32_t align = dds_op_size[subtype]; - DDS_CDR_ALIGNTO (os, align); - DDS_OS_PUT_BYTES (os, src, op[2] * align); + dds_is_get_bytes (is, dst, op[2], get_type_size (DDS_OP_SUBTYPE (*op))); + break; + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: + abort (); break; - } - default: assert (0); } } } -/* - dds_stream_get_keyhash: Extract key values from a stream and generate - keyhash used for instance identification. Non key fields are skipped. - Key hash data is big endian CDR encoded with no padding. Returns length - of key hash. Input stream may contain full sample of just key data. -*/ - -uint32_t dds_stream_extract_key (dds_stream_t *is, dds_stream_t *os, const uint32_t *ops, const bool just_key) +void dds_stream_write_key (dds_ostream_t * __restrict os, const char * __restrict sample, const struct ddsi_sertopic_default * __restrict topic) { - uint32_t align; - uint32_t op; - uint32_t type; - uint32_t subtype; - uint32_t num; - uint32_t len; - const uint32_t origin = os->m_index; - bool is_key; - bool have_data; + const struct dds_topic_descriptor *desc = (const struct dds_topic_descriptor *) 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 void *src = sample + insnp[1]; + assert (insn_key_ok_p (*insnp)); + switch (DDS_OP_TYPE (*insnp)) + { + case DDS_OP_VAL_1BY: dds_os_put1 (os, *((uint8_t *) src)); break; + case DDS_OP_VAL_2BY: dds_os_put2 (os, *((uint16_t *) src)); break; + case DDS_OP_VAL_4BY: dds_os_put4 (os, *((uint32_t *) src)); break; + case DDS_OP_VAL_8BY: dds_os_put8 (os, *((uint64_t *) src)); break; + case DDS_OP_VAL_STR: dds_stream_write_string (os, *(char **) src); break; + case DDS_OP_VAL_BST: dds_stream_write_string (os, src); break; + case DDS_OP_VAL_ARR: { + const uint32_t elem_size = get_type_size (DDS_OP_SUBTYPE (*insnp)); + const uint32_t num = insnp[2]; + dds_cdr_alignto_clear_and_resize(os, elem_size, num * elem_size); + dds_os_put_bytes (os, src, num * elem_size); + break; + } + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { + abort (); + break; + } + } + } +} +#if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN +static void dds_stream_swap_insitu (void * __restrict vbuf, uint32_t size, uint32_t num) +{ + assert (size == 1 || size == 2 || size == 4 || size == 8); + switch (size) + { + case 1: + break; + case 2: { + uint16_t *buf = vbuf; + for (uint32_t i = 0; i < num; i++) + buf[i] = bswap2u (buf[i]); + break; + } + case 4: { + uint32_t *buf = vbuf; + for (uint32_t i = 0; i < num; i++) + buf[i] = bswap4u (buf[i]); + break; + } + case 8: { + uint64_t *buf = vbuf; + for (uint32_t i = 0; i < num; i++) + buf[i] = bswap8u (buf[i]); + break; + } + } +} + +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; + for (uint32_t i = 0; i < desc->m_nkeys; i++) + { + const uint32_t *insnp = desc->m_ops + desc->m_keys[i].m_index; + const void *src = sample + insnp[1]; + assert (insn_key_ok_p (*insnp)); + switch (DDS_OP_TYPE (*insnp)) + { + case DDS_OP_VAL_1BY: dds_os_put1be (os, *((uint8_t *) src)); break; + case DDS_OP_VAL_2BY: dds_os_put2be (os, *((uint16_t *) src)); break; + case DDS_OP_VAL_4BY: dds_os_put4be (os, *((uint32_t *) src)); break; + case DDS_OP_VAL_8BY: dds_os_put8be (os, *((uint64_t *) src)); break; + case DDS_OP_VAL_STR: dds_streamBE_write_string (os, *(char **) src); break; + case DDS_OP_VAL_BST: dds_streamBE_write_string (os, src); break; + case DDS_OP_VAL_ARR: { + const uint32_t elem_size = get_type_size (DDS_OP_SUBTYPE (*insnp)); + const uint32_t num = insnp[2]; + dds_cdr_alignto_clear_and_resize_be (os, elem_size, num * elem_size); + void * const dst = os->x.m_buffer + os->x.m_index; + dds_os_put_bytes (&os->x, src, num * elem_size); + dds_stream_swap_insitu (dst, elem_size, num); + break; + } + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { + abort (); + break; + } + } + } +} +#elif DDSRT_ENDIAN == DDSRT_BIG_ENDIAN +void dds_stream_write_keyBE (dds_ostreamBE_t * __restrict os, const char * __restrict sample, const struct ddsi_sertopic_default * __restrict topic) +{ + dds_stream_write_key (&os->x, sample, topic); +} +#else +#error "DDSRT_ENDIAN neither LITTLE nor BIG" +#endif + +/******************************************************************************************* + ** + ** Extracting key/keyhash (the only difference that a keyhash MUST be big-endian, + ** padding MUST be cleared, and that it may be necessary to run the value through + ** MD5. + ** + *******************************************************************************************/ + +static void dds_stream_extract_key_from_data1 (dds_istream_t * __restrict is, dds_ostream_t * __restrict os, const uint32_t * __restrict ops, uint32_t * __restrict keys_remaining); + +static void dds_stream_extract_key_from_key_prim_op (dds_istream_t * __restrict is, dds_ostream_t * __restrict os, const uint32_t * __restrict op) +{ + assert ((*op & DDS_OP_FLAG_KEY) && ((DDS_OP (*op)) == DDS_OP_ADR)); + switch (DDS_OP_TYPE (*op)) + { + case DDS_OP_VAL_1BY: dds_os_put1 (os, dds_is_get1 (is)); break; + case DDS_OP_VAL_2BY: dds_os_put2 (os, dds_is_get2 (is)); break; + case DDS_OP_VAL_4BY: dds_os_put4 (os, dds_is_get4 (is)); break; + case DDS_OP_VAL_8BY: dds_os_put8 (os, dds_is_get8 (is)); break; + case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: { + uint32_t sz = dds_is_get4 (is); + dds_os_put4 (os, sz); + dds_os_put_bytes (os, is->m_buffer + is->m_index, sz); + is->m_index += sz; + break; + } + case DDS_OP_VAL_ARR: { + const uint32_t subtype = DDS_OP_SUBTYPE (*op); + assert (subtype <= DDS_OP_VAL_8BY); + const uint32_t align = get_type_size (subtype); + const uint32_t num = op[2]; + dds_cdr_alignto_clear_and_resize (os, align, num * align); + void * const dst = os->m_buffer + os->m_index; + dds_is_get_bytes (is, dst, num, align); + os->m_index += num * align; + is->m_index += num * align; + break; + } + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { + abort (); + break; + } + } +} + +#if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN +static void dds_stream_swap_copy (void * __restrict vdst, const void * __restrict vsrc, uint32_t size, uint32_t num) +{ + assert (size == 2 || size == 4 || size == 8); + switch (size) + { + case 2: { + const uint16_t *src = vsrc; + uint16_t *dst = vdst; + for (uint32_t i = 0; i < num; i++) + dst[i] = bswap2u (src[i]); + break; + } + case 4: { + const uint32_t *src = vsrc; + uint32_t *dst = vdst; + for (uint32_t i = 0; i < num; i++) + dst[i] = bswap4u (src[i]); + break; + } + case 8: { + const uint64_t *src = vsrc; + uint64_t *dst = vdst; + for (uint32_t i = 0; i < num; i++) + dst[i] = bswap8u (src[i]); + break; + } + } +} +#endif + +static void dds_stream_extract_keyBE_from_key_prim_op (dds_istream_t * __restrict is, dds_ostreamBE_t * __restrict os, const uint32_t * __restrict op) +{ + assert ((*op & DDS_OP_FLAG_KEY) && ((DDS_OP (*op)) == DDS_OP_ADR)); + switch (DDS_OP_TYPE (*op)) + { + case DDS_OP_VAL_1BY: dds_os_put1be (os, dds_is_get1 (is)); break; + case DDS_OP_VAL_2BY: dds_os_put2be (os, dds_is_get2 (is)); break; + case DDS_OP_VAL_4BY: dds_os_put4be (os, dds_is_get4 (is)); break; + case DDS_OP_VAL_8BY: dds_os_put8be (os, dds_is_get8 (is)); break; + case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: { + uint32_t sz = dds_is_get4 (is); + dds_os_put4be (os, sz); + dds_os_put_bytes (&os->x, is->m_buffer + is->m_index, sz); + is->m_index += sz; + break; + } + case DDS_OP_VAL_ARR: { + const uint32_t subtype = DDS_OP_SUBTYPE (*op); + assert (subtype <= DDS_OP_VAL_8BY); + const uint32_t align = get_type_size (subtype); + const uint32_t num = op[2]; + dds_cdr_alignto (is, align); + dds_cdr_alignto_clear_and_resize_be (os, align, num * align); + void const * const src = is->m_buffer + is->m_index; + void * const dst = os->x.m_buffer + os->x.m_index; +#if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN + dds_stream_swap_copy (dst, src, num, align); +#else + dds_stream_read_fixed_buffer (is, dst, num, align); +#endif + os->x.m_index += num * align; + is->m_index += num * align; + break; + } + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { + abort (); + break; + } + } +} + +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; + for (uint32_t i = 0; i < desc->m_nkeys; i++) + { + uint32_t const * const op = desc->m_ops + desc->m_keys[i].m_index; + dds_stream_extract_keyBE_from_key_prim_op (is, os, op); + } +} + +static void dds_stream_extract_key_from_data_skip_subtype (dds_istream_t * __restrict is, uint32_t num, uint32_t subtype, const uint32_t * __restrict subops) +{ + switch (subtype) + { + case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: { + const uint32_t elem_size = get_type_size (subtype); + dds_cdr_alignto (is, elem_size); + is->m_index += num * elem_size; + break; + } + case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: { + for (uint32_t i = 0; i < num; i++) + { + const uint32_t len = dds_is_get4 (is); + is->m_index += len; + } + break; + } + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { + uint32_t remain = UINT32_MAX; + for (uint32_t i = 0; i < num; i++) + dds_stream_extract_key_from_data1 (is, NULL, subops, &remain); + break; + } + } +} + +static const uint32_t *dds_stream_extract_key_from_data_skip_array (dds_istream_t * __restrict is, const uint32_t * __restrict ops) +{ + const uint32_t op = *ops; + assert (DDS_OP_TYPE (op) == DDS_OP_VAL_ARR); + const uint32_t subtype = DDS_OP_SUBTYPE (op); + const uint32_t num = ops[2]; + if (subtype > DDS_OP_VAL_BST) + { + const uint32_t *jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]); + const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]); + dds_stream_extract_key_from_data_skip_subtype (is, num, subtype, jsr_ops); + return ops + (jmp ? jmp : 5); + } + else + { + dds_stream_extract_key_from_data_skip_subtype (is, num, subtype, NULL); + return ops + 3; + } +} + +static const uint32_t *dds_stream_extract_key_from_data_skip_sequence (dds_istream_t * __restrict is, const uint32_t * __restrict ops) +{ + const uint32_t op = *ops; + const enum dds_stream_typecode type = DDS_OP_TYPE (op); + assert (type == DDS_OP_VAL_SEQ); + const uint32_t subtype = DDS_OP_SUBTYPE (op); + const uint32_t num = dds_is_get4 (is); + if (num == 0) + return ops + 2 + (type == DDS_OP_VAL_BST || type == DDS_OP_VAL_ARR); + else if (subtype > DDS_OP_VAL_BST) + { + const uint32_t * jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]); + const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]); + dds_stream_extract_key_from_data_skip_subtype (is, num, subtype, jsr_ops); + return ops + (jmp ? jmp : 4); + } + else + { + dds_stream_extract_key_from_data_skip_subtype (is, num, subtype, NULL); + return ops + 2 + (type == DDS_OP_VAL_BST || type == DDS_OP_VAL_ARR); + } +} + +static const uint32_t *dds_stream_extract_key_from_data_skip_union (dds_istream_t * __restrict is, const uint32_t * __restrict ops) +{ + const uint32_t op = *ops; + assert (DDS_OP_TYPE (op) == DDS_OP_VAL_UNI); + const uint32_t disc = read_union_discriminant (is, DDS_OP_SUBTYPE (op)); + uint32_t const * const jeq_op = find_union_case (ops, disc); + if (jeq_op) + dds_stream_extract_key_from_data_skip_subtype (is, 1, DDS_JEQ_TYPE (jeq_op[0]), jeq_op + DDS_OP_ADR_JSR (jeq_op[0])); + return ops + DDS_OP_ADR_JMP (ops[3]); +} + +static void dds_stream_extract_key_from_data1 (dds_istream_t * __restrict is, dds_ostream_t * __restrict os, const uint32_t * __restrict ops, uint32_t * __restrict keys_remaining) +{ + uint32_t op; while ((op = *ops) != DDS_OP_RTS) { - switch (DDS_OP_MASK & op) + switch (DDS_OP (op)) { - case DDS_OP_ADR: - { - type = DDS_OP_TYPE (op); - is_key = (op & DDS_OP_FLAG_KEY) && (os != NULL); - have_data = is_key || !just_key; - ops += 2; - if (type <= DDS_OP_VAL_8BY) - { - if (have_data) - { - align = dds_op_size[type]; - DDS_CDR_ALIGNTO (is, align); - - /* Quick skip for basic types that are not keys */ - - if (! is_key) - { - is->m_index += align; - break; - } - } - else - { - break; - } - } -#ifdef OP_DEBUG_KEY + case DDS_OP_ADR: { + const uint32_t type = DDS_OP_TYPE (op); + const bool is_key = (op & DDS_OP_FLAG_KEY) && (os != NULL); if (is_key) { - DDS_TRACE("K-ADR: %s\n", stream_op_type[type]); + dds_stream_extract_key_from_key_prim_op (is, os, ops); + if (--(*keys_remaining) == 0) + return; + ops += 2 + (type == DDS_OP_VAL_BST || type == DDS_OP_VAL_ARR); } -#endif - switch (type) + else { - case DDS_OP_VAL_1BY: + switch (type) { - uint8_t v = DDS_IS_GET1 (is); - DDS_OS_PUT1 (os, v); - break; + case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: + dds_stream_extract_key_from_data_skip_subtype (is, 1, type, NULL); + ops += 2 + (type == DDS_OP_VAL_BST || type == DDS_OP_VAL_ARR); + break; + case DDS_OP_VAL_SEQ: + ops = dds_stream_extract_key_from_data_skip_sequence (is, ops); + break; + case DDS_OP_VAL_ARR: + ops = dds_stream_extract_key_from_data_skip_array (is, ops); + break; + case DDS_OP_VAL_UNI: + ops = dds_stream_extract_key_from_data_skip_union (is, ops); + break; + case DDS_OP_VAL_STU: + abort (); } - case DDS_OP_VAL_2BY: - { - uint16_t v; - DDS_IS_GET2 (is, v); - DDS_OS_PUT2 (os, v); - break; - } - case DDS_OP_VAL_4BY: - { - uint32_t v; - DDS_IS_GET4 (is, v, uint32_t); - DDS_OS_PUT4 (os, v, uint32_t); - break; - } - case DDS_OP_VAL_8BY: - { - uint64_t v; - DDS_IS_GET8 (is, v, uint64_t); - DDS_OS_PUT8 (os, v, uint64_t); - break; - } - case DDS_OP_VAL_STR: - case DDS_OP_VAL_BST: - { - if (have_data) - { - len = dds_stream_read_uint32 (is); - if (is_key) - { - DDS_OS_PUT4 (os, len, uint32_t); - DDS_OS_PUT_BYTES(os, DDS_CDR_ADDRESS (is, void), len); -#ifdef OP_DEBUG_KEY - DDS_TRACE("K-ADR: String/BString (%d)\n", len); -#endif - } - is->m_index += len; - } - if (type == DDS_OP_VAL_BST) - { - ops++; - } - break; - } - case DDS_OP_VAL_SEQ: - { - assert (! is_key); - subtype = DDS_OP_SUBTYPE (op); - num = have_data ? dds_stream_read_uint32 (is) : 0; - - if (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: - { - align = dds_op_size[subtype]; - DDS_CDR_ALIGNTO (is, align); - is->m_index += align * num; - break; - } - case DDS_OP_VAL_STR: - case DDS_OP_VAL_BST: - { - while (num--) - { - len = dds_stream_read_uint32 (is); - is->m_index += len; - } - if (subtype == DDS_OP_VAL_BST) - { - ops++; - } - break; - } - default: - { - const uint32_t * jsr_ops = ops + DDS_OP_ADR_JSR (ops[1]) - 2; - const uint32_t jmp = DDS_OP_ADR_JMP (ops[1]); - while (num--) - { - dds_stream_extract_key (is, NULL, jsr_ops, just_key); - } - ops += jmp ? (jmp - 2) : 2; - break; - } - } - } - break; - } - case DDS_OP_VAL_ARR: - { - subtype = DDS_OP_SUBTYPE (op); - assert (! is_key || subtype <= DDS_OP_VAL_8BY); - num = have_data ? *ops : 0; - ops++; - -#ifdef OP_DEBUG_KEY - if (is_key) - { - DDS_TRACE("K-ADR: %s[%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: - { - if (num) - { - align = dds_op_size[subtype]; - if (is_key) - { - char *dst; - DDS_CDR_ALIGNTO (os, align); - DDS_CDR_RESIZE (os, num * align); - dst = DDS_CDR_ADDRESS(os, char); - dds_stream_read_fixed_buffer (is, dst, num, align, is->m_endian); - os->m_index += num * align; - } - is->m_index += num * align; - } - break; - } - case DDS_OP_VAL_STR: - case DDS_OP_VAL_BST: - { - while (num--) - { - len = dds_stream_read_uint32 (is); - is->m_index += len; - } - break; - } - default: - { - const uint32_t * jsr_ops = ops + DDS_OP_ADR_JSR (*ops) - 3; - const uint32_t jmp = DDS_OP_ADR_JMP (*ops); - while (num--) - { - dds_stream_extract_key (is, NULL, jsr_ops, just_key); - } - 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); - assert (! is_key); - -#ifdef OP_DEBUG_KEY - DDS_TRACE("K-UNI: switch %s cases %d\n", stream_op_type[subtype], num); -#endif - /* Read discriminant */ - - if (have_data) - { - switch (subtype) - { - case DDS_OP_VAL_1BY: - { - disc = dds_stream_read_uint8 (is); - break; - } - case DDS_OP_VAL_2BY: - { - disc = dds_stream_read_uint16 (is); - break; - } - case DDS_OP_VAL_4BY: - { - disc = dds_stream_read_uint32 (is); - break; - } - default: assert (0); - } - - /* Skip union case */ - - 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]); - - switch (subtype) - { - case DDS_OP_VAL_1BY: - case DDS_OP_VAL_2BY: - case DDS_OP_VAL_4BY: - case DDS_OP_VAL_8BY: - { - align = dds_op_size[subtype]; - DDS_CDR_ALIGNTO (is, align); - is->m_index += align; - break; - } - case DDS_OP_VAL_STR: - case DDS_OP_VAL_BST: - { - len = dds_stream_read_uint32 (is); - is->m_index += len; - break; - } - default: - { - dds_stream_extract_key (is, NULL, jeq_op + DDS_OP_ADR_JSR (jeq_op[0]), just_key); - break; - } - } - break; - } - jeq_op += 3; - } - } - - /* Jump to next instruction */ - - ops += DDS_OP_ADR_JMP (ops[1]) - 2; - break; - } - default: assert (0); } break; } - case DDS_OP_JSR: /* Implies nested type */ - { - dds_stream_extract_key (is, os, ops + DDS_OP_JUMP (op), just_key); + case DDS_OP_JSR: { /* Implies nested type */ + ops += 2; + dds_stream_extract_key_from_data1 (is, os, ops + DDS_OP_JUMP (op), keys_remaining); + if (--(*keys_remaining) == 0) + return; ops++; break; } - default: assert (0); + case DDS_OP_RTS: case DDS_OP_JEQ: { + abort (); + break; + } } } - return os->m_index - origin; } -#ifndef NDEBUG -static bool keyhash_is_reset(const dds_key_hash_t *kh) +static void dds_stream_extract_keyBE_from_data1 (dds_istream_t * __restrict is, dds_ostreamBE_t * __restrict os, const uint32_t * __restrict ops, uint32_t * __restrict keys_remaining) { - static const char nullhash[sizeof(kh->m_hash)] = { 0 }; - return !kh->m_set && memcmp(kh->m_hash, nullhash, sizeof(nullhash)) == 0; + uint32_t op; + while ((op = *ops) != DDS_OP_RTS) + { + switch (DDS_OP (op)) + { + case DDS_OP_ADR: { + const uint32_t type = DDS_OP_TYPE (op); + const bool is_key = (op & DDS_OP_FLAG_KEY) && (os != NULL); + if (is_key) + { + dds_stream_extract_keyBE_from_key_prim_op (is, os, ops); + if (--(*keys_remaining) == 0) + return; + ops += 2 + (type == DDS_OP_VAL_BST || type == DDS_OP_VAL_ARR); + } + else + { + switch (type) + { + case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: + dds_stream_extract_key_from_data_skip_subtype (is, 1, type, NULL); + ops += 2 + (type == DDS_OP_VAL_BST || type == DDS_OP_VAL_ARR); + break; + case DDS_OP_VAL_SEQ: + ops = dds_stream_extract_key_from_data_skip_sequence (is, ops); + break; + case DDS_OP_VAL_ARR: + ops = dds_stream_extract_key_from_data_skip_array (is, ops); + break; + case DDS_OP_VAL_UNI: + ops = dds_stream_extract_key_from_data_skip_union (is, ops); + break; + case DDS_OP_VAL_STU: + abort (); + } + } + break; + } + case DDS_OP_JSR: { /* Implies nested type */ + ops += 2; + dds_stream_extract_keyBE_from_data1 (is, os, ops + DDS_OP_JUMP (op), keys_remaining); + if (--(*keys_remaining) == 0) + return; + ops++; + break; + } + case DDS_OP_RTS: case DDS_OP_JEQ: { + abort (); + break; + } + } + } } -#endif -void dds_stream_read_keyhash -( - dds_stream_t * is, - dds_key_hash_t * kh, - const dds_topic_descriptor_t * desc, - const bool just_key -) +void dds_stream_extract_key_from_data (dds_istream_t * __restrict is, dds_ostream_t * __restrict os, const struct ddsi_sertopic_default * __restrict topic) { - assert (keyhash_is_reset(kh)); + const dds_topic_descriptor_t *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; + 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; kh->m_set = 1; if (desc->m_nkeys == 0) kh->m_iskey = 1; else if (desc->m_flagset & DDS_TOPIC_FIXED_KEY) { - dds_stream_t os; - uint32_t ncheck; + dds_ostreamBE_t os; kh->m_iskey = 1; - dds_stream_init(&os, 0); - os.m_buffer.pv = kh->m_hash; - os.m_size = 16; - os.m_endian = 0; - ncheck = dds_stream_extract_key (is, &os, desc->m_ops, just_key); - assert(ncheck <= 16); - (void)ncheck; + dds_ostreamBE_init (&os, 0); + os.x.m_buffer = kh->m_hash; + os.x.m_size = 16; + if (just_key) + dds_stream_extract_keyBE_from_key (is, &os, topic); + else + dds_stream_extract_keyBE_from_data (is, &os, topic); + assert (os.x.m_index <= 16); } else { - dds_stream_t os; + dds_ostreamBE_t os; ddsrt_md5_state_t md5st; kh->m_iskey = 0; - dds_stream_init (&os, 0); - os.m_endian = 0; - dds_stream_extract_key (is, &os, desc->m_ops, just_key); + dds_ostreamBE_init (&os, 0); + if (just_key) + dds_stream_extract_keyBE_from_key (is, &os, topic); + else + dds_stream_extract_keyBE_from_data (is, &os, topic); ddsrt_md5_init (&md5st); - ddsrt_md5_append (&md5st, os.m_buffer.p8, os.m_index); - ddsrt_md5_finish (&md5st, (unsigned char *) kh->m_hash); - dds_stream_fini (&os); + ddsrt_md5_append (&md5st, os.x.m_buffer, os.x.m_index); + ddsrt_md5_finish (&md5st, kh->m_hash); + dds_ostreamBE_fini (&os); } } -void dds_stream_read_key -( - dds_stream_t * is, - char * sample, - const dds_topic_descriptor_t * desc -) +/******************************************************************************************* + ** + ** Stuff to make it possible to treat a ddsi_serdata_default as a stream + ** + *******************************************************************************************/ + +void dds_istream_from_serdata_default (dds_istream_t * __restrict s, const struct ddsi_serdata_default * __restrict d) { - uint32_t i; - char * dst; - const uint32_t * op; - - for (i = 0; i < desc->m_nkeys; i++) - { - op = desc->m_ops + desc->m_keys[i].m_index; - dst = sample + op[1]; - assert ((*op & DDS_OP_FLAG_KEY) && ((DDS_OP_MASK & *op) == DDS_OP_ADR)); - switch (DDS_OP_TYPE (*op)) - { - case DDS_OP_VAL_1BY: - *((uint8_t*) dst) = dds_stream_read_uint8 (is); - break; - case DDS_OP_VAL_2BY: - *((uint16_t*) dst) = dds_stream_read_uint16 (is); - break; - case DDS_OP_VAL_4BY: - *((uint32_t*) dst) = dds_stream_read_uint32 (is); - break; - case DDS_OP_VAL_8BY: - *((uint64_t*) dst) = dds_stream_read_uint64 (is); - break; - case DDS_OP_VAL_STR: - *((char**) dst) = dds_stream_reuse_string (is, *((char**) dst), 0); - break; - case DDS_OP_VAL_BST: - dds_stream_reuse_string (is, dst, op[2]); - break; - case DDS_OP_VAL_ARR: - { - uint32_t subtype = DDS_OP_SUBTYPE (*op); - assert (subtype <= DDS_OP_VAL_8BY); - dds_stream_read_fixed_buffer (is, dst, op[2], dds_op_size[subtype], is->m_endian != DDS_ENDIAN); - break; - } - default: assert (0); - } - } + s->m_buffer = (const unsigned char *) d; + s->m_index = (uint32_t) offsetof (struct ddsi_serdata_default, data); + s->m_size = d->size + s->m_index; +#if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN + assert (d->hdr.identifier == CDR_LE); +#elif DDSRT_ENDIAN == DDSRT_BIG_ENDIAN + assert (d->hdr.identifier == CDR_BE); +#else +#error "DDSRT_ENDIAN neither LITTLE nor BIG" +#endif +} + +void dds_ostream_from_serdata_default (dds_ostream_t * __restrict s, struct ddsi_serdata_default * __restrict d) +{ + s->m_buffer = (unsigned char *) d; + s->m_index = (uint32_t) offsetof (struct ddsi_serdata_default, data); + s->m_size = d->size + s->m_index; +#if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN + assert (d->hdr.identifier == CDR_LE); +#elif DDSRT_ENDIAN == DDSRT_BIG_ENDIAN + assert (d->hdr.identifier == CDR_BE); +#else +#error "DDSRT_ENDIAN neither LITTLE nor BIG" +#endif +} + +void dds_ostream_add_to_serdata_default (dds_ostream_t * __restrict s, struct ddsi_serdata_default ** __restrict d) +{ + /* DDSI requires 4 byte alignment */ + + dds_cdr_alignto_clear_and_resize (s, 4, 0); + + /* Reset data pointer as stream may have reallocated */ + + (*d) = (void *) s->m_buffer; + (*d)->pos = (s->m_index - (uint32_t) offsetof (struct ddsi_serdata_default, data)); + (*d)->size = (s->m_size - (uint32_t) offsetof (struct ddsi_serdata_default, data)); +} + +void dds_ostreamBE_from_serdata_default (dds_ostreamBE_t * __restrict s, struct ddsi_serdata_default * __restrict d) +{ + s->x.m_buffer = (unsigned char *) d; + s->x.m_index = (uint32_t) offsetof (struct ddsi_serdata_default, data); + s->x.m_size = d->size + s->x.m_index; + assert (d->hdr.identifier == CDR_BE); +} + +void dds_ostreamBE_add_to_serdata_default (dds_ostreamBE_t * __restrict s, struct ddsi_serdata_default ** __restrict d) +{ + /* DDSI requires 4 byte alignment */ + + dds_cdr_alignto_clear_and_resize_be (s, 4, 0); + + /* Reset data pointer as stream may have reallocated */ + + (*d) = (void *) s->x.m_buffer; + (*d)->pos = (s->x.m_index - (uint32_t) offsetof (struct ddsi_serdata_default, data)); + (*d)->size = (s->x.m_size - (uint32_t) offsetof (struct ddsi_serdata_default, data)); } 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 c61bb97..6c2bc29 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -43,12 +43,11 @@ struct serdatapool { struct nn_freelist freelist; }; -typedef struct dds_key_hash { - char m_hash [16]; /* Key hash value. Also possibly key. Suitably aligned for accessing as uint32_t's */ +typedef struct dds_keyhash { + unsigned char m_hash [16]; /* Key hash value. Also possibly key. Suitably aligned for accessing as uint32_t's */ unsigned m_set : 1; /* has it been initialised? */ unsigned m_iskey : 1; /* m_hash is key value */ -} -dds_key_hash_t; +} dds_keyhash_t; struct ddsi_serdata_default { struct ddsi_serdata c; @@ -57,7 +56,7 @@ struct ddsi_serdata_default { #ifndef NDEBUG bool fixed; #endif - dds_key_hash_t keyhash; + dds_keyhash_t keyhash; struct serdatapool *pool; struct ddsi_serdata_default *next; /* in pool->freelist */ diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 167cc8b..65ab5d4 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -20,20 +20,30 @@ #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" -#include "dds__key.h" #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_serdata_default.h" +#if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN +#define NATIVE_ENCODING CDR_LE +#define NATIVE_ENCODING_PL PL_CDR_LE +#elif DDSRT_ENDIAN == DDSRT_BIG_ENDIAN +#define NATIVE_ENCODING CDR_BE +#define NATIVE_ENCODING_PL PL_CDR_BE +#else +#error "DDSRT_ENDIAN neither LITTLE nor BIG" +#endif + /* 8k entries in the freelist seems to be roughly the amount needed to send minimum-size (well, 4 bytes) samples as fast as possible over loopback while using large messages -- actually, it stands to reason that this would be the same as the WHC node pool size */ #define MAX_POOL_SIZE 8192 #define MAX_SIZE_FOR_POOL 256 -#define CLEAR_PADDING 0 +#define DEFAULT_NEW_SIZE 128 +#define CHUNK_SIZE 128 #ifndef NDEBUG static int ispowerof2_size (size_t x) @@ -80,7 +90,7 @@ static void *serdata_default_append (struct ddsi_serdata_default **d, size_t n) char *p; if ((*d)->pos + n > (*d)->size) { - size_t size1 = alignup_size ((*d)->pos + n, 128); + size_t size1 = alignup_size ((*d)->pos + n, CHUNK_SIZE); *d = ddsrt_realloc (*d, offsetof (struct ddsi_serdata_default, data) + size1); (*d)->size = (uint32_t)size1; } @@ -228,36 +238,49 @@ static void serdata_default_init(struct ddsi_serdata_default *d, const struct dd d->keyhash.m_iskey = 0; } -static struct ddsi_serdata_default *serdata_default_allocnew(struct serdatapool *pool) +static struct ddsi_serdata_default *serdata_default_allocnew (struct serdatapool *pool, uint32_t init_size) { - const uint32_t init_size = 128; - struct ddsi_serdata_default *d = ddsrt_malloc(offsetof (struct ddsi_serdata_default, data) + init_size); + struct ddsi_serdata_default *d = ddsrt_malloc (offsetof (struct ddsi_serdata_default, data) + init_size); d->size = init_size; d->pool = pool; return d; } -static struct ddsi_serdata_default *serdata_default_new(const struct ddsi_sertopic_default *tp, enum ddsi_serdata_kind kind) +static struct ddsi_serdata_default *serdata_default_new_size (const struct ddsi_sertopic_default *tp, enum ddsi_serdata_kind kind, uint32_t size) { struct ddsi_serdata_default *d; - if ((d = nn_freelist_pop (&gv.serpool->freelist)) == NULL) - d = serdata_default_allocnew(gv.serpool); - else - ddsrt_atomic_st32(&d->c.refc, 1); - serdata_default_init(d, tp, kind); + if (size <= MAX_SIZE_FOR_POOL && (d = nn_freelist_pop (&gv.serpool->freelist)) != NULL) + ddsrt_atomic_st32 (&d->c.refc, 1); + else if ((d = serdata_default_allocnew (gv.serpool, size)) == NULL) + return NULL; + serdata_default_init (d, tp, kind); return d; } +static struct ddsi_serdata_default *serdata_default_new (const struct ddsi_sertopic_default *tp, enum ddsi_serdata_kind kind) +{ + return serdata_default_new_size (tp, kind, DEFAULT_NEW_SIZE); +} + /* Construct a serdata from a fragchain received over the network */ static struct ddsi_serdata_default *serdata_default_from_ser_common (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const struct nn_rdata *fragchain, size_t size) { const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn; - struct ddsi_serdata_default *d = serdata_default_new(tp, kind); + + /* 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; + struct ddsi_serdata_default *d = serdata_default_new_size (tp, kind, (uint32_t) size); + if (d == NULL) + return NULL; + uint32_t off = 4; /* must skip the CDR header */ assert (fragchain->min == 0); assert (fragchain->maxp1 >= off); /* CDR header must be in first fragment */ - (void)size; memcpy (&d->hdr, NN_RMSG_PAYLOADOFF (fragchain->rmsg, NN_RDATA_PAYLOAD_OFF (fragchain)), sizeof (d->hdr)); assert (d->hdr.identifier == CDR_LE || d->hdr.identifier == CDR_BE); @@ -276,20 +299,36 @@ static struct ddsi_serdata_default *serdata_default_from_ser_common (const struc fragchain = fragchain->nextfrag; } - dds_stream_t is; - dds_stream_from_serdata_default (&is, d); - dds_stream_read_keyhash (&is, &d->keyhash, (const dds_topic_descriptor_t *)tp->type, kind == SDK_KEY); - return d; + const bool needs_bswap = (d->hdr.identifier != NATIVE_ENCODING); + d->hdr.identifier = NATIVE_ENCODING; + if (!dds_stream_normalize (d->data, d->pos, 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) { - return fix_serdata_default (serdata_default_from_ser_common (tpcmn, kind, fragchain, size), tpcmn->serdata_basehash); + struct ddsi_serdata_default *d; + if ((d = serdata_default_from_ser_common (tpcmn, kind, fragchain, 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) { - return fix_serdata_default_nokey (serdata_default_from_ser_common (tpcmn, kind, fragchain, size), tpcmn->serdata_basehash); + struct ddsi_serdata_default *d; + if ((d = serdata_default_from_ser_common (tpcmn, kind, fragchain, size)) == NULL) + return NULL; + return fix_serdata_default_nokey (d, tpcmn->serdata_basehash); } struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash) @@ -304,8 +343,14 @@ struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr (const struct ddsi_sertopic * else { struct ddsi_serdata_default *d = serdata_default_new(tp, SDK_KEY); - d->hdr.identifier = CDR_BE; + if (d == NULL) + return NULL; serdata_default_append_blob (&d, 1, sizeof (keyhash->value), keyhash->value); + if (!dds_stream_normalize (d->data, d->pos, (NATIVE_ENCODING != CDR_BE), tp, true)) + { + ddsi_serdata_unref (&d->c); + return NULL; + } memcpy (d->keyhash.m_hash, keyhash->value, sizeof (d->keyhash.m_hash)); d->keyhash.m_set = 1; d->keyhash.m_iskey = 1; @@ -317,19 +362,52 @@ struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr_nokey (const struct ddsi_sert { const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn; struct ddsi_serdata_default *d = serdata_default_new(tp, SDK_KEY); + if (d == NULL) + return NULL; (void)keyhash; d->keyhash.m_set = 1; d->keyhash.m_iskey = 1; return fix_serdata_default_nokey(d, tp->c.serdata_basehash); } +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; + kh->m_set = 1; + if (desc->m_nkeys == 0) + kh->m_iskey = 1; + else if (desc->m_flagset & DDS_TOPIC_FIXED_KEY) + { + dds_ostreamBE_t os; + kh->m_iskey = 1; + dds_ostreamBE_init (&os, 0); + os.x.m_buffer = kh->m_hash; + os.x.m_size = 16; + dds_stream_write_keyBE (&os, sample, topic); + } + else + { + dds_ostreamBE_t os; + ddsrt_md5_state_t md5st; + kh->m_iskey = 0; + dds_ostreamBE_init (&os, 64); + dds_stream_write_keyBE (&os, sample, topic); + ddsrt_md5_init (&md5st); + ddsrt_md5_append (&md5st, os.x.m_buffer, os.x.m_index); + ddsrt_md5_finish (&md5st, kh->m_hash); + dds_ostreamBE_fini (&os); + } +} + static struct ddsi_serdata_default *serdata_default_from_sample_cdr_common (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const void *sample) { const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn; struct ddsi_serdata_default *d = serdata_default_new(tp, kind); - dds_stream_t os; - dds_key_gen ((const dds_topic_descriptor_t *)tp->type, &d->keyhash, (char*)sample); - dds_stream_from_serdata_default (&os, d); + if (d == NULL) + return NULL; + dds_ostream_t os; + gen_keyhash_from_sample (tp, &d->keyhash, sample); + dds_ostream_from_serdata_default (&os, d); switch (kind) { case SDK_EMPTY: @@ -341,18 +419,24 @@ static struct ddsi_serdata_default *serdata_default_from_sample_cdr_common (cons dds_stream_write_sample (&os, sample, tp); break; } - dds_stream_add_to_serdata_default (&os, &d); + dds_ostream_add_to_serdata_default (&os, &d); return d; } static struct ddsi_serdata *serdata_default_from_sample_cdr (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const void *sample) { - return fix_serdata_default (serdata_default_from_sample_cdr_common (tpcmn, kind, sample), tpcmn->serdata_basehash); + struct ddsi_serdata_default *d; + if ((d = serdata_default_from_sample_cdr_common (tpcmn, kind, sample)) == NULL) + return NULL; + return fix_serdata_default (d, tpcmn->serdata_basehash); } static struct ddsi_serdata *serdata_default_from_sample_cdr_nokey (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const void *sample) { - return fix_serdata_default_nokey (serdata_default_from_sample_cdr_common (tpcmn, kind, sample), tpcmn->serdata_basehash); + struct ddsi_serdata_default *d; + if ((d = serdata_default_from_sample_cdr_common (tpcmn, kind, sample)) == NULL) + return NULL; + return fix_serdata_default_nokey (d, tpcmn->serdata_basehash); } static struct ddsi_serdata *serdata_default_from_sample_plist (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const void *vsample) @@ -361,6 +445,8 @@ static struct ddsi_serdata *serdata_default_from_sample_plist (const struct ddsi const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn; const struct ddsi_plist_sample *sample = vsample; struct ddsi_serdata_default *d = serdata_default_new(tp, kind); + 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); #ifndef NDEBUG @@ -416,6 +502,8 @@ static struct ddsi_serdata *serdata_default_from_sample_rawcdr (const struct dds const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn; const struct ddsi_rawcdr_sample *sample = vsample; struct ddsi_serdata_default *d = serdata_default_new(tp, kind); + if (d == NULL) + return NULL; assert (sample->keysize <= 16); serdata_default_append_blob (&d, 1, sample->size, sample->blob); d->keyhash.m_set = 1; @@ -433,7 +521,10 @@ static struct ddsi_serdata *serdata_default_to_topicless (const struct ddsi_serd { const struct ddsi_serdata_default *d = (const struct ddsi_serdata_default *)serdata_common; const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)d->c.topic; + assert (d->hdr.identifier == NATIVE_ENCODING || d->hdr.identifier == NATIVE_ENCODING_PL); struct ddsi_serdata_default *d_tl = serdata_default_new(tp, SDK_KEY); + if (d_tl == NULL) + return NULL; d_tl->c.topic = NULL; d_tl->c.hash = d->c.hash; d_tl->c.timestamp.v = INT64_MIN; @@ -443,31 +534,31 @@ static struct ddsi_serdata *serdata_default_to_topicless (const struct ddsi_serd the payload is of interest. */ if (d->c.ops == &ddsi_serdata_ops_cdr) { + assert (d->hdr.identifier == NATIVE_ENCODING); if (d->c.kind == SDK_KEY) - { - d_tl->hdr.identifier = d->hdr.identifier; serdata_default_append_blob (&d_tl, 1, d->pos, d->data); - } else if (d->keyhash.m_iskey) { - d_tl->hdr.identifier = CDR_BE; serdata_default_append_blob (&d_tl, 1, sizeof (d->keyhash.m_hash), d->keyhash.m_hash); +#if NATIVE_ENCODING != CDR_BE + bool ok = dds_stream_normalize (d_tl->data, d_tl->pos, true, tp, true); + assert (ok); + (void) ok; +#endif } else { - const struct dds_topic_descriptor *desc = tp->type; - dds_stream_t is, os; - uint32_t nbytes; - dds_stream_from_serdata_default (&is, d); - dds_stream_from_serdata_default (&os, d_tl); - nbytes = dds_stream_extract_key (&is, &os, desc->m_ops, false); - os.m_index += nbytes; + dds_istream_t is; + dds_ostream_t os; + dds_istream_from_serdata_default (&is, d); + dds_ostream_from_serdata_default (&os, d_tl); + dds_stream_extract_key_from_data (&is, &os, tp); if (os.m_index < os.m_size) { - os.m_buffer.p8 = dds_realloc (os.m_buffer.p8, os.m_index); + os.m_buffer = dds_realloc (os.m_buffer, os.m_index); os.m_size = os.m_index; } - dds_stream_add_to_serdata_default (&os, &d_tl); + dds_ostream_add_to_serdata_default (&os, &d_tl); } } return (struct ddsi_serdata *)d_tl; @@ -501,26 +592,30 @@ static void serdata_default_to_ser_unref (struct ddsi_serdata *serdata_common, c static bool serdata_default_to_sample_cdr (const struct ddsi_serdata *serdata_common, void *sample, void **bufptr, void *buflim) { const struct ddsi_serdata_default *d = (const struct ddsi_serdata_default *)serdata_common; - dds_stream_t is; + const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *) d->c.topic; + dds_istream_t is; if (bufptr) abort(); else { (void)buflim; } /* FIXME: haven't implemented that bit yet! */ - dds_stream_from_serdata_default(&is, d); + assert (d->hdr.identifier == NATIVE_ENCODING); + dds_istream_from_serdata_default(&is, d); if (d->c.kind == SDK_KEY) - dds_stream_read_key (&is, sample, (const dds_topic_descriptor_t*) ((struct ddsi_sertopic_default *)d->c.topic)->type); + dds_stream_read_key (&is, sample, tp); else - dds_stream_read_sample (&is, sample, (const struct ddsi_sertopic_default *)d->c.topic); + dds_stream_read_sample (&is, sample, tp); return true; /* FIXME: can't conversion to sample fail? */ } static bool serdata_default_topicless_to_sample_cdr (const struct ddsi_sertopic *topic, const struct ddsi_serdata *serdata_common, void *sample, void **bufptr, void *buflim) { const struct ddsi_serdata_default *d = (const struct ddsi_serdata_default *)serdata_common; - dds_stream_t is; + const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *) topic; + dds_istream_t is; assert (d->c.topic == NULL); assert (d->c.kind == SDK_KEY); assert (d->c.ops == topic->serdata_ops); + assert (d->hdr.identifier == NATIVE_ENCODING); if (bufptr) abort(); else { (void)buflim; } /* FIXME: haven't implemented that bit yet! */ - dds_stream_from_serdata_default(&is, d); - dds_stream_read_key (&is, sample, (const dds_topic_descriptor_t*) ((struct ddsi_sertopic_default *)topic)->type); + dds_istream_from_serdata_default(&is, d); + dds_stream_read_key (&is, sample, tp); return true; /* FIXME: can't conversion to sample fail? */ } diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index a706067..842d372 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -1766,8 +1766,11 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm static struct ddsi_serdata *get_serdata (struct ddsi_sertopic const * const topic, const struct nn_rdata *fragchain, uint32_t sz, int justkey, unsigned statusinfo, nn_wctime_t tstamp) { struct ddsi_serdata *sd = ddsi_serdata_from_ser (topic, justkey ? SDK_KEY : SDK_DATA, fragchain, sz); - sd->statusinfo = statusinfo; - sd->timestamp = tstamp; + if (sd) + { + sd->statusinfo = statusinfo; + sd->timestamp = tstamp; + } return sd; } diff --git a/src/core/xtests/cdrtest/CMakeLists.txt b/src/core/xtests/cdrtest/CMakeLists.txt new file mode 100644 index 0000000..9566927 --- /dev/null +++ b/src/core/xtests/cdrtest/CMakeLists.txt @@ -0,0 +1,46 @@ +# +# Copyright(c) 2019 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# +cmake_minimum_required(VERSION 3.5) + +if (NOT TARGET CycloneDDS::ddsc) + # Find the CycloneDDS package. If it is not in a default location, try + # finding it relative to the example where it most likely resides. + find_package(CycloneDDS REQUIRED PATHS ../../) +endif() + +add_compile_options("-I${PROJECT_SOURCE_DIR}/ddsrt/include") +add_compile_options("-I${PROJECT_SOURCE_DIR}/core/ddsc/include") +add_compile_options("-I${PROJECT_SOURCE_DIR}/core/ddsc/src") +add_compile_options("-I${PROJECT_SOURCE_DIR}/core/ddsi/include") + +add_compile_options("-I$ENV{OSPL_HOME}/src/abstraction/os/include") +add_compile_options("-I$ENV{OSPL_HOME}/src/database/database/include") +add_compile_options("-I$ENV{OSPL_HOME}/src/database/serialization/include") +add_compile_options("-I$ENV{OSPL_HOME}/src/utilities/include") +add_compile_options("-I$ENV{OSPL_HOME}/src/kernel/include") +add_compile_options("-I$ENV{OSPL_HOME}/src/kernel/bld/$ENV{SPLICE_TARGET}") +add_compile_options("-I$ENV{OSPL_HOME}/src/user/include") +add_compile_options("-I$ENV{OSPL_HOME}/src/api/dcps/sac/include") +add_compile_options("-I$ENV{OSPL_HOME}/src/api/dcps/sac/code") + +# This is a convenience function, provided by the CycloneDDS package, +# that will supply a library target related the the given idl file. +# In short, it takes the idl file, generates the source files with +# the proper data types and compiles them into a library. +idlc_generate(xxx_lib "xxx.idl") + +# Both executables have only one related source file. +add_executable(xxx xxx-cyc.c) + +# Both executables need to be linked to the idl data type library and +# the ddsc API library. +target_link_libraries(xxx xxx_lib CycloneDDS::ddsc -L$ENV{OSPL_HOME}/lib/$ENV{SPLICE_TARGET} -Wl,-rpath,$ENV{OSPL_HOME}/lib/$ENV{SPLICE_TARGET} ddskernel dcpssac) diff --git a/src/core/xtests/cdrtest/cdrtest.pl b/src/core/xtests/cdrtest/cdrtest.pl new file mode 100644 index 0000000..e850927 --- /dev/null +++ b/src/core/xtests/cdrtest/cdrtest.pl @@ -0,0 +1,403 @@ +# +# Copyright(c) 2019 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# + +#use strict; + +use Data::Dumper; +$Data::Dumper::Terse = 1; +$Data::Dumper::Useqq = 1; + +my $outfn = "xxx"; +local $nextident = "a0000"; + +my @types = qw(u0 u1 u2 u3 u4 seq ary str uni); +my @idltype = ("octet", "unsigned short", "unsigned long", "unsigned long long", "string"); +# unions cannot have an octet as a discriminator ... +my @idltype_unidisc = ("char", "unsigned short", "unsigned long", "unsigned long long", "string"); +my @ctype = ("uint8_t", "uint16_t", "uint32_t", "uint64_t", "char *"); +my @probs = do { + my @ps = qw(0.3 0.3 0.3 0.3 0.3 1 1 1 1); + my (@xs, $sum); + for (@ps) { $sum += $_; push @xs, $sum; } + @xs; +}; +my @noaryprobs = do { + my @ps = qw(0.3 0.3 0.3 0.3 0.3 1 0 1 1); + my (@xs, $sum); + for (@ps) { $sum += $_; push @xs, $sum; } + @xs; +}; +my @unicaseprobs = do { + my @ps = qw(0.3 0.3 0.3 0.3 0.3 1 0 1 0); + my (@xs, $sum); + for (@ps) { $sum += $_; push @xs, $sum; } + @xs; +}; + +open IDL, ">${outfn}.idl" or die "can't open ${outfn}.idl"; +open CYC, ">${outfn}-cyc.c" or die "can't open ${outfn}-cyc.c"; +print CYC < +#include +#include +#include +#include "dds/dds.h" +#include "dds/ddsrt/random.h" +#include "dds/ddsrt/sockets.h" +#include "dds/ddsi/ddsi_serdata_default.h" +#include "dds__stream.h" + +#include "c_base.h" +#include "sd_cdr.h" +#include "sd_serializerXMLTypeinfo.h" +#include "v_copyIn.h" +#include "sac_genericCopyIn.h" + +#include "xxx.h" +int main() +{ + unsigned char garbage[1000]; + struct ddsi_sertopic_default ddd; + uint32_t deser_garbage = 0; + memset (&ddd, 0, sizeof (ddd)); + dds_istream_t is; + c_base base = c_create ("X", NULL, 0, 0); + dds_entity_t dp = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); + if (dp < 0) abort (); +EOF +; +for (1 .. 300) { + my $t = genstr (0); + my $idl = genidltd ($t); + print IDL $idl; + (my $idlcmt = $idl) =~ s,^,//,mg; + print CYC $idlcmt; + gencyc ($t); +} +print CYC <[1]_desc, \"$t->[1]\", NULL, NULL); + if (tp < 0) abort (); + dds_entity_t rd = dds_create_reader (dp, tp, NULL, NULL); + if (rd < 0) abort (); + dds_entity_t wr = dds_create_writer (dp, tp, NULL, NULL); + if (wr < 0) abort (); +EOF + ; + print CYC geninit ($t); + print CYC <[1]) < 0) abort (); + void *msg = NULL; + dds_sample_info_t info; + if (dds_take (rd, &msg, &info, 1, 1) != 1) abort (); + const $t->[1] *b = msg; +EOF + ; + print CYC gencmp ($t); + print CYC <[1]_desc; + for (uint32_t i = 0; i < 1000; i++) { + for (size_t j = 0; j < sizeof (garbage); j++) + garbage[j] = (unsigned char) ddsrt_random (); + if (dds_stream_normalize (garbage, (uint32_t) sizeof (garbage), false, &ddd, false)) { + is.m_buffer = garbage; + is.m_size = 1000; + is.m_index = 0; + dds_stream_read_sample (&is, msg, &ddd); + deser_garbage++; + } + } + sd_serializer serializer = sd_serializerXMLTypeinfoNew (base, 0); + sd_serializedData meta_data = sd_serializerFromString (serializer, $t->[1]_desc.m_meta); + if (sd_serializerDeserialize (serializer, meta_data) == NULL) abort (); + c_type type = c_resolve (base, "$t->[1]"); if (!type) abort (); + sd_serializedDataFree (meta_data); + sd_serializerFree (serializer); + struct sd_cdrInfo *ci = sd_cdrInfoNew (type); + if (sd_cdrCompile (ci) < 0) abort (); + DDS_copyCache cc = DDS_copyCacheNew ((c_metaObject) type); + struct DDS_srcInfo_s src = { .src = &v$t->[1], cc }; + void *samplecopy = c_new (type); + DDS_copyInStruct (base, &src, samplecopy); + struct sd_cdrSerdata *sd = sd_cdrSerializeBSwap (ci, samplecopy); + const void *blob; + uint32_t blobsz = sd_cdrSerdataBlob (&blob, sd); + /* hack alert: modifying read-only blob ...*/ + if (!dds_stream_normalize ((void *) blob, blobsz, true, &ddd, false)) abort (); + is.m_buffer = blob; + is.m_size = blobsz; + is.m_index = 0; + dds_stream_read_sample (&is, msg, &ddd); + sd_cdrSerdataFree (sd); + sd = sd_cdrSerialize (ci, samplecopy); + blobsz = sd_cdrSerdataBlob (&blob, sd); + if (!dds_stream_normalize ((void *) blob, blobsz, false, &ddd, false)) abort (); + for (uint32_t i = 1; i < blobsz && i <= 16; i++) { + if (dds_stream_normalize ((void *) blob, blobsz - i, false, &ddd, false)) abort (); + } + sd_cdrSerdataFree (sd); +EOF +; + print CYC gencmp ($t); + print CYC <[1] v$t->[1] = $res;\n"; +} + +sub gencmp { + my ($t) = @_; + my $res = gencmp1 ($t, "v$t->[1]", ""); + return $res; +} + +sub geninit1 { + my ($ind, $out, $t, $idxsuf) = @_; + if ($t->[0] =~ /^u([0-3])$/) { + return int (rand (10)); + } elsif ($t->[0] eq "u4") { + return "\"".("x"x(int (rand (8))))."\""; + } elsif ($t->[0] eq "seq") { + my $len = int (rand (10)); + my $bufref; + if ($len == 0) { + $bufref = "0"; + } else { + my $buf = "vb$t->[1]_$idxsuf"; + $bufref = "$buf"; + my $ctype = ($t->[2]->[0] =~ /^u(\d+)$/) ? $ctype[$1] : $t->[2]->[1]; + my $tmp = " $ctype $buf\[\] = {"; + for (1..$len) { + $tmp .= geninit1 ("$ind", $out, $t->[2], "${idxsuf}_$_"); + $tmp .= "," if $_ < $len; + } + $tmp .= "};\n"; + push @$out, $tmp; + } + return "{$len,$len,$bufref,0}"; + } elsif ($t->[0] eq "ary") { + my $len = $t->[3]; die unless $len > 0; + my $tmp = "{"; + for (1..$len) { + $tmp .= geninit1 ("$ind", $out, $t->[2], "${idxsuf}_$_"); + $tmp .= "," if $_ < $len; + } + $tmp .= "}"; + return $tmp; + } elsif ($t->[0] eq "str") { + my $tmp = "{"; + for (my $i = 2; $i < @$t; $i++) { + my ($name, $st) = @{$t->[$i]}; + $tmp .= geninit1 ("", $out, $st, "${idxsuf}_"); + $tmp .= "," if $i + 1 < @$t; + } + $tmp .= "}"; + return $tmp; + } elsif ($t->[0] eq "uni") { # uni name disctype hasdef case... + my $discval = int(rand(@$t - 3)); # -3 so we generate values outside label range as well + my $hasdef = $t->[3]; + my $case = (4 + $discval < @$t) ? $discval : $hasdef ? @$t-1 : 0; + $discval = ("'".chr ($discval + ord ("A"))."'") if $t->[2] eq "u0"; + # $case matches have a label or default; if no default generate an initializer for the + # first case to avoid compiler warnings + my ($name, $st) = @{$t->[4+$case]}; + my $tmp = "{$discval,{.$name="; + $tmp .= geninit1 ("", $out, $st, "${idxsuf}_"); + $tmp .= "}}"; + return $tmp; + } else { + die; + } +} + +sub gencmp1 { + my ($t, $toplevel, $path) = @_; + if ($t->[0] =~ /^u([0-3])$/) { + return " if ($toplevel.$path != b->$path) abort ();\n"; + } elsif ($t->[0] eq "u4") { + return " if (strcmp ($toplevel.$path, b->$path) != 0) abort ();\n"; + } elsif ($t->[0] eq "seq") { + my $idx = "i".length $path; + return ("if ($toplevel.$path._length != b->$path._length) abort ();\n" . + "for (uint32_t $idx = 0; $idx < $toplevel.$path._length; $idx++) {\n" . + gencmp1 ($t->[2], $toplevel, "$path._buffer[$idx]") . + "}\n"); + } elsif ($t->[0] eq "ary") { + my $len = $t->[3]; die unless $len > 0; + my $idx = "i".length $path; + return ("for (uint32_t $idx = 0; $idx < $len; $idx++) {\n" . + gencmp1 ($t->[2], $toplevel, "$path\[$idx]") . + "}\n"); + } elsif ($t->[0] eq "str") { + my $sep = length $path == 0 ? "" : "."; + my $tmp = ""; + for (my $i = 2; $i < @$t; $i++) { + my ($name, $st) = @{$t->[$i]}; + $tmp .= gencmp1 ($st, $toplevel, "$path$sep$name"); + } + return $tmp; + } elsif ($t->[0] eq "uni") { # uni name disctype hasdef case... + my $tmp = "if ($toplevel.$path._d != b->$path._d) abort ();\n"; + my $hasdef = $t->[3]; + $tmp .= "switch ($toplevel.$path._d) {\n"; + for (my $i = 4; $i < @$t; $i++) { + my ($name, $st) = @{$t->[$i]}; + my $discval = $i - 4; + $discval = "'".chr ($discval + ord ("A"))."'" if $t->[2] eq "u0"; + $tmp .= ($i == @$t && $hasdef) ? " default:\n" : " case $discval:\n"; + $tmp .= gencmp1 ($st, $toplevel, "$path._u.$name"); + $tmp .= "break;\n"; + } + $tmp .= "}\n"; + return $tmp; + } else { + die; + } +} + +sub genidltd { + my ($t) = @_; + my @out = (); + my $res = genidl1td ("", \@out, $t); + return (join "", @out) . $res . "#pragma keylist $t->[1]\n//------------\n"; +}; + +sub genidl1 { + my ($ind, $out, $name, $t) = @_; + my $res = ""; + if ($t->[0] =~ /^u(\d+)$/) { + $res = "${ind}$idltype[$1] $name;\n"; + } elsif ($t->[0] eq "seq") { + push @$out, genidl1td ("", $out, $t); + $res = "${ind}$t->[1] $name;\n"; + } elsif ($t->[0] eq "ary") { + if ($t->[2]->[0] =~ /^u(\d+)$/) { + $res = "${ind}$idltype[$1] ${name}[$t->[3]];\n"; + } else { + push @$out, genidl1td ("", $out, $t->[2]); + $res = "${ind}$t->[2]->[1] ${name}[$t->[3]];\n"; + } + } elsif ($t->[0] eq "str") { + push @$out, genidl1td ("", $out, $t); + $res = "${ind}$t->[1] $name;\n"; + } elsif ($t->[0] eq "uni") { + push @$out, genidl1td ("", $out, $t); + $res = "${ind}$t->[1] $name;\n"; + } else { + die; + } + return $res; +} + +sub genidl1td { + my ($ind, $out, $t) = @_; + if ($t->[0] eq "seq") { + if ($t->[2]->[0] =~ /^u(\d+)$/) { + return "${ind}typedef sequence<$idltype[$1]> $t->[1];\n"; + } else { + push @$out, genidl1td ("", $out, $t->[2]); + return "${ind}typedef sequence<$t->[2]->[1]> $t->[1];\n"; + } + } elsif ($t->[0] eq "ary") { + if ($t->[2]->[0] =~ /^u(\d+)$/) { + return "${ind}typedef ${idltype[$1]} $t->[1]"."[$t->[3]];\n"; + } else { + push @$out, genidl1td ("", $out, $t->[2]); + return "${ind}typedef $t->[2]->[1] $t->[1]"."[$t->[3]];\n"; + } + } elsif ($t->[0] eq "str") { + my $res = "struct $t->[1] {\n"; + for (my $i = 2; $i < @$t; $i++) { + $res .= genidl1 ($ind." ", $out, @{$t->[$i]}); + } + $res .= "};\n"; + return $res; + } elsif ($t->[0] eq "uni") { + my $hasdef = $t->[3]; + die unless $t->[2] =~ /^u([0-2])$/; + my $res = "${ind}union $t->[1] switch ($idltype_unidisc[$1]) {\n"; + for (my $i = 4; $i < @$t; $i++) { + my $discval = $i - 4; + $discval = "'".(chr ($discval + ord ("A")))."'" if $t->[2] eq "u0"; + $res .= ($i == @$t && $hasdef) ? "$ind default: " : "$ind case $discval: "; + $res .= genidl1 ($ind." ", $out, @{$t->[$i]}); + } + $res .= "};\n"; + return $res; + } else { + die; + } +}; + +sub genu0 { return ["u0"]; } +sub genu1 { return ["u1"]; } +sub genu2 { return ["u2"]; } +sub genu3 { return ["u3"]; } +sub genu4 { return ["u4"]; } +sub genseq { return ["seq", nextident (), gentype ($_[0] + 1, @probs)]; } +sub genary { return ["ary", nextident (), gentype ($_[0] + 1, @noaryprobs), 1 + int (rand (4))]; } +sub genstr { + my @ts = ("str", nextident ()); + my $n = 1 + int (rand (4)); + push @ts, [ nextident (), gentype ($_[0] + 1, @probs) ] while $n--; + return \@ts; +} +sub genuni { + my @ts = ("uni", nextident (), "u".(int (rand (2))), int (rand (1))); # uni name disctype hasdef case... + my $ncases = 1 + int (rand (4)); + push @ts, [ nextident (), gentype ($_[0] + 1, @unicaseprobs) ] while $ncases--; + return \@ts; +} + +sub gentype { + my $t = choosetype (@_); + my $f = "gen$t"; + return &$f (@_); +} + +sub choosetype { + my ($lev, @probs) = @_; + my $r = rand ($_[0] == 4 ? $probs[3] : $probs[$#probs]); + my $i; + for ($i = 0; $i < $#probs; $i++) { + last if $r < $probs[$i]; + } + return $types[$i]; +} + +sub nextident { + return $nextident++; +} diff --git a/src/idlc/src/org/eclipse/cyclonedds/generator/ArrayType.java b/src/idlc/src/org/eclipse/cyclonedds/generator/ArrayType.java index e25f88c..b418668 100644 --- a/src/idlc/src/org/eclipse/cyclonedds/generator/ArrayType.java +++ b/src/idlc/src/org/eclipse/cyclonedds/generator/ArrayType.java @@ -48,6 +48,16 @@ public class ArrayType extends AbstractType return new ArrayType (dimensions, subtype); } + public boolean containsUnion () + { + Type t = subtype; + while (t instanceof TypedefType) + { + t = ((TypedefType)t).getRef (); + } + return t.containsUnion (); + } + public ArrayList getMetaOp (String myname, String structname) { ArrayList result = new ArrayList (); diff --git a/src/idlc/src/org/eclipse/cyclonedds/generator/BasicType.java b/src/idlc/src/org/eclipse/cyclonedds/generator/BasicType.java index 7355b42..6ddb67b 100644 --- a/src/idlc/src/org/eclipse/cyclonedds/generator/BasicType.java +++ b/src/idlc/src/org/eclipse/cyclonedds/generator/BasicType.java @@ -57,6 +57,11 @@ public class BasicType extends AbstractType return new BasicType (type); } + public boolean containsUnion () + { + return false; + } + public ArrayList getMetaOp (String myname, String structname) { ArrayList result = new ArrayList (1); diff --git a/src/idlc/src/org/eclipse/cyclonedds/generator/BoundedStringType.java b/src/idlc/src/org/eclipse/cyclonedds/generator/BoundedStringType.java index 9e49eb5..62e04c1 100644 --- a/src/idlc/src/org/eclipse/cyclonedds/generator/BoundedStringType.java +++ b/src/idlc/src/org/eclipse/cyclonedds/generator/BoundedStringType.java @@ -36,6 +36,11 @@ public class BoundedStringType extends AbstractType return size; } + public boolean containsUnion () + { + return false; + } + public ArrayList getMetaOp (String myname, String structname) { ArrayList result = new ArrayList (); diff --git a/src/idlc/src/org/eclipse/cyclonedds/generator/EnumType.java b/src/idlc/src/org/eclipse/cyclonedds/generator/EnumType.java index 9313f94..739add7 100644 --- a/src/idlc/src/org/eclipse/cyclonedds/generator/EnumType.java +++ b/src/idlc/src/org/eclipse/cyclonedds/generator/EnumType.java @@ -40,6 +40,11 @@ public class EnumType extends BasicType implements NamedType return SN.toString ("_"); } + public boolean containsUnion () + { + return false; + } + public void addEnumerand (String val) { vals.add (val); diff --git a/src/idlc/src/org/eclipse/cyclonedds/generator/GenVisitor.java b/src/idlc/src/org/eclipse/cyclonedds/generator/GenVisitor.java index be9698c..d5152a4 100644 --- a/src/idlc/src/org/eclipse/cyclonedds/generator/GenVisitor.java +++ b/src/idlc/src/org/eclipse/cyclonedds/generator/GenVisitor.java @@ -1207,6 +1207,10 @@ public class GenVisitor extends org.eclipse.cyclonedds.parser.IDLBaseVisitor getMetaOp (String myname, String structname) { ArrayList result = new ArrayList (); diff --git a/src/idlc/src/org/eclipse/cyclonedds/generator/StructType.java b/src/idlc/src/org/eclipse/cyclonedds/generator/StructType.java index faeadc4..198f476 100644 --- a/src/idlc/src/org/eclipse/cyclonedds/generator/StructType.java +++ b/src/idlc/src/org/eclipse/cyclonedds/generator/StructType.java @@ -176,6 +176,23 @@ public class StructType extends AbstractType implements NamedType return false; } + public boolean containsUnion () + { + for (Member m : members) + { + Type mtype = m.type; + while (mtype instanceof TypedefType) + { + mtype = ((TypedefType)mtype).getRef (); + } + if (mtype.containsUnion ()) + { + return true; + } + } + return false; + } + public long getKeySize () { Type mtype; diff --git a/src/idlc/src/org/eclipse/cyclonedds/generator/Type.java b/src/idlc/src/org/eclipse/cyclonedds/generator/Type.java index 8cf0aac..b8a599d 100644 --- a/src/idlc/src/org/eclipse/cyclonedds/generator/Type.java +++ b/src/idlc/src/org/eclipse/cyclonedds/generator/Type.java @@ -29,5 +29,6 @@ public interface Type public int getMetaOpSize (); public Alignment getAlignment (); public Type dup (); + public boolean containsUnion (); } diff --git a/src/idlc/src/org/eclipse/cyclonedds/generator/TypedefType.java b/src/idlc/src/org/eclipse/cyclonedds/generator/TypedefType.java index 80c3bcb..f27b86a 100644 --- a/src/idlc/src/org/eclipse/cyclonedds/generator/TypedefType.java +++ b/src/idlc/src/org/eclipse/cyclonedds/generator/TypedefType.java @@ -27,6 +27,11 @@ public class TypedefType extends AbstractType implements NamedType return new TypedefType (name, ref); } + public boolean containsUnion () + { + return ref.containsUnion (); + } + public ArrayList getMetaOp (String myname, String structname) { return ref.getMetaOp (myname, structname); diff --git a/src/idlc/src/org/eclipse/cyclonedds/generator/UnionType.java b/src/idlc/src/org/eclipse/cyclonedds/generator/UnionType.java index da5dc53..5885c77 100644 --- a/src/idlc/src/org/eclipse/cyclonedds/generator/UnionType.java +++ b/src/idlc/src/org/eclipse/cyclonedds/generator/UnionType.java @@ -207,6 +207,11 @@ public class UnionType extends AbstractType implements NamedType less than the alignment of the members. */ } + public boolean containsUnion () + { + return true; + } + public Alignment getAlignment () { Alignment result = discriminant.getAlignment (); From ed9406f64254bf28a664ba4ded08ff7ee56ded28 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 10 May 2019 18:15:45 +0800 Subject: [PATCH 073/178] let final messages on shutdown go onto the network The discovery data is sent asynchronously (via the "tev" thread, i.e., via the "xeventq"), but any messages generated but not yet sent upon destruction of the event queue were discarded rather than sent out. Deleting the last participant triggers the shutdown of Cyclone, and the participant discovery message informing the world of its disappearance always got discarded. Consequently, all other nodes would not become aware of the disappearnce until the lease expired. This commit changes the behaviour to send out those last few messages and absent packet loss, all peers are now properly informed. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_xevent.c | 41 ++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index dc959c0..9eca691 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -158,6 +158,7 @@ static uint32_t xevent_thread (struct xeventq *xevq); static nn_mtime_t earliest_in_xeventq (struct xeventq *evq); static int msg_xevents_cmp (const void *a, const void *b); static int compare_xevent_tsched (const void *va, const void *vb); +static void handle_nontimed_xevent (struct xevent_nt *xev, struct nn_xpack *xp); static const ddsrt_avl_treedef_t msg_xevents_treedef = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct xevent_nt, u.msg_rexmit.msg_avlnode), offsetof (struct xevent_nt, u.msg_rexmit.msg), msg_xevents_cmp, 0); @@ -173,7 +174,7 @@ static int compare_xevent_tsched (const void *va, const void *vb) static void update_rexmit_counts (struct xeventq *evq, struct xevent_nt *ev) { #if 0 - DDS_TRACE(("ZZZ(%p,%"PA_PRIuSIZE")", (void *) ev, ev->u.msg_rexmit.queued_rexmit_bytes); + DDS_TRACE("ZZZ(%p,%"PRIuSIZE")", (void *) ev, ev->u.msg_rexmit.queued_rexmit_bytes); #endif assert (ev->kind == XEVK_MSG_REXMIT); assert (ev->u.msg_rexmit.queued_rexmit_bytes <= evq->queued_rexmit_bytes); @@ -315,26 +316,6 @@ static void free_xevent (struct xeventq *evq, struct xevent *ev) ddsrt_free (ev); } -static void free_xevent_nt (struct xeventq *evq, struct xevent_nt *ev) -{ - assert (!nontimed_xevent_in_queue (evq, ev)); - switch (ev->kind) - { - case XEVK_MSG: - nn_xmsg_free (ev->u.msg.msg); - break; - case XEVK_MSG_REXMIT: - assert (ddsrt_avl_lookup (&msg_xevents_treedef, &evq->msg_xevents, ev->u.msg_rexmit.msg) == NULL); - update_rexmit_counts (evq, ev); - nn_xmsg_free (ev->u.msg_rexmit.msg); - break; - case XEVK_ENTITYID: - nn_xmsg_free (ev->u.entityid.msg); - break; - } - ddsrt_free (ev); -} - void delete_xevent (struct xevent *ev) { struct xeventq *evq = ev->evq; @@ -551,8 +532,22 @@ void xeventq_free (struct xeventq *evq) } } } - while (!non_timed_xmit_list_is_empty(evq)) - free_xevent_nt (evq, getnext_from_non_timed_xmit_list (evq)); + + { + struct nn_xpack *xp = nn_xpack_new (evq->tev_conn, evq->auxiliary_bandwidth_limit, false); + thread_state_awake (lookup_thread_state ()); + ddsrt_mutex_lock (&evq->lock); + while (!non_timed_xmit_list_is_empty (evq)) + { + thread_state_awake_to_awake_no_nest (lookup_thread_state ()); + handle_nontimed_xevent (getnext_from_non_timed_xmit_list (evq), xp); + } + ddsrt_mutex_unlock (&evq->lock); + thread_state_asleep (lookup_thread_state ()); + nn_xpack_send (xp, false); + nn_xpack_free (xp); + } + assert (ddsrt_avl_is_empty (&evq->msg_xevents)); ddsrt_cond_destroy (&evq->cond); ddsrt_mutex_destroy (&evq->lock); From 35fcc013afc8fbc1aaf6e865e6068f14c0404012 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 12 May 2019 09:54:07 +0200 Subject: [PATCH 074/178] use clock_gettime on macOS >= 10.12 Since macOS 10.12, the POSIX clock_gettime interface with various different clocks is supported on macOS, so use those when building for 10.12 or newer. Signed-off-by: Erik Boasson --- src/ddsrt/src/time/darwin/time.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/ddsrt/src/time/darwin/time.c b/src/ddsrt/src/time/darwin/time.c index a8a35c4..71e2ccb 100644 --- a/src/ddsrt/src/time/darwin/time.c +++ b/src/ddsrt/src/time/darwin/time.c @@ -13,21 +13,29 @@ #include #include #include + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12 #include +#endif #include "dds/ddsrt/time.h" dds_time_t dds_time(void) { +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12 + return (int64_t) clock_gettime_nsec_np (CLOCK_REALTIME); +#else struct timeval tv; - (void)gettimeofday(&tv, NULL); - return ((tv.tv_sec * DDS_NSECS_IN_SEC) + (tv.tv_usec * DDS_NSECS_IN_USEC)); +#endif } dds_time_t ddsrt_time_monotonic(void) { +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12 + return (int64_t) clock_gettime_nsec_np (CLOCK_UPTIME_RAW); +#else static mach_timebase_info_data_t timeInfo; uint64_t mt; @@ -49,10 +57,15 @@ dds_time_t ddsrt_time_monotonic(void) } return (dds_time_t)(mt * timeInfo.numer / timeInfo.denom); +#endif } dds_time_t ddsrt_time_elapsed(void) { +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12 + return (int64_t) clock_gettime_nsec_np (CLOCK_MONOTONIC_RAW); +#else /* Elapsed time clock not (yet) supported on this platform. */ return ddsrt_time_monotonic(); +#endif } From 3574ac6903d544ca13df2960ec219af1eb0fa270 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 14 May 2019 17:46:32 +0200 Subject: [PATCH 075/178] set & use encoding options according to XTypes Two bits of the DDSI encoding "options" field are used by the XTypes spec to indicate the amount of padding that had to be added at the end to reach the nearest 4-byte boundary as required by the DDSI message format. These bits are now set in according with the spec, and for received samples, the padding is subtracted from the inferred size of the data so that, e.g., a struct T { octet x; } will never deserialise as a struct S { octet x, y; }. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_stream.c | 22 +++++++++++++++------- src/core/ddsi/src/ddsi_serdata_default.c | 8 +++++++- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/core/ddsc/src/dds_stream.c b/src/core/ddsc/src/dds_stream.c index 2c724a9..fc706d5 100644 --- a/src/core/ddsc/src/dds_stream.c +++ b/src/core/ddsc/src/dds_stream.c @@ -77,23 +77,27 @@ static void dds_cdr_alignto (dds_istream_t * __restrict s, uint32_t a) assert (s->m_index < s->m_size); } -static void dds_cdr_alignto_clear_and_resize (dds_ostream_t * __restrict s, uint32_t a, uint32_t extra) +static uint32_t dds_cdr_alignto_clear_and_resize (dds_ostream_t * __restrict s, uint32_t a, uint32_t extra) { const uint32_t m = s->m_index % a; if (m == 0) + { dds_cdr_resize (s, extra); + return 0; + } else { - uint32_t pad = a - m; + const uint32_t pad = a - m; dds_cdr_resize (s, pad + extra); - while (pad--) + for (uint32_t i = 0; i < pad; i++) s->m_buffer[s->m_index++] = 0; + return pad; } } -static void dds_cdr_alignto_clear_and_resize_be (dds_ostreamBE_t * __restrict s, uint32_t a, uint32_t extra) +static uint32_t dds_cdr_alignto_clear_and_resize_be (dds_ostreamBE_t * __restrict s, uint32_t a, uint32_t extra) { - dds_cdr_alignto_clear_and_resize (&s->x, a, extra); + return dds_cdr_alignto_clear_and_resize (&s->x, a, extra); } static uint8_t dds_is_get1 (dds_istream_t * __restrict s) @@ -1644,13 +1648,15 @@ void dds_ostream_add_to_serdata_default (dds_ostream_t * __restrict s, struct dd { /* DDSI requires 4 byte alignment */ - dds_cdr_alignto_clear_and_resize (s, 4, 0); + const uint32_t pad = dds_cdr_alignto_clear_and_resize (s, 4, 0); + assert (pad <= 3); /* Reset data pointer as stream may have reallocated */ (*d) = (void *) s->m_buffer; (*d)->pos = (s->m_index - (uint32_t) offsetof (struct ddsi_serdata_default, data)); (*d)->size = (s->m_size - (uint32_t) offsetof (struct ddsi_serdata_default, data)); + (*d)->hdr.options = toBE2u ((uint16_t) pad); } void dds_ostreamBE_from_serdata_default (dds_ostreamBE_t * __restrict s, struct ddsi_serdata_default * __restrict d) @@ -1665,11 +1671,13 @@ void dds_ostreamBE_add_to_serdata_default (dds_ostreamBE_t * __restrict s, struc { /* DDSI requires 4 byte alignment */ - dds_cdr_alignto_clear_and_resize_be (s, 4, 0); + const uint32_t pad = dds_cdr_alignto_clear_and_resize_be (s, 4, 0); + assert (pad <= 3); /* Reset data pointer as stream may have reallocated */ (*d) = (void *) s->x.m_buffer; (*d)->pos = (s->x.m_index - (uint32_t) offsetof (struct ddsi_serdata_default, data)); (*d)->size = (s->x.m_size - (uint32_t) offsetof (struct ddsi_serdata_default, data)); + (*d)->hdr.options = toBE2u ((uint16_t) pad); } diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 65ab5d4..630c6c0 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -301,7 +301,13 @@ static struct ddsi_serdata_default *serdata_default_from_ser_common (const struc const bool needs_bswap = (d->hdr.identifier != NATIVE_ENCODING); d->hdr.identifier = NATIVE_ENCODING; - if (!dds_stream_normalize (d->data, d->pos, needs_bswap, tp, kind == SDK_KEY)) + const uint32_t pad = 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; From 2c31e4aa4642b5bc2983a5844bf68b41f8300823 Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Mon, 27 May 2019 14:23:16 +0200 Subject: [PATCH 076/178] Moved thread_state_awake in dds_unregister_instance_ih_ts. Signed-off-by: Martin Bremmer --- src/core/ddsc/src/dds_instance.c | 3 +-- src/core/ddsc/tests/unregister.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index 903d7ee..7b8b93e 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -241,12 +241,11 @@ dds_unregister_instance_ih_ts( if (wr->m_entity.m_qos) { dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose); } + thread_state_awake (ts1); if (autodispose) { dds_instance_remove (wr->m_topic, NULL, handle); action |= DDS_WR_DISPOSE_BIT; } - - thread_state_awake (ts1); tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle); if (tk) { struct ddsi_sertopic *tp = wr->m_topic->m_stopic; diff --git a/src/core/ddsc/tests/unregister.c b/src/core/ddsc/tests/unregister.c index e27eb32..b7b03d5 100644 --- a/src/core/ddsc/tests/unregister.c +++ b/src/core/ddsc/tests/unregister.c @@ -609,6 +609,37 @@ CU_Test(ddsc_unregister_instance_ih_ts, unregistering_past_sample, .init=unregis } /*************************************************************************************************/ +/*************************************************************************************************/ +CU_Test(ddsc_unregister_instance_ih_ts, unregistering_instance) +{ + Space_Type1 testData = { 0, 22, 22 }; + dds_instance_handle_t ih = 0; + dds_return_t ret; + char name[100]; + + /* Create a writer that WILL automatically dispose unregistered samples. */ + g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); + CU_ASSERT_FATAL(g_participant > 0); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_unregistering_instance_test", name, 100), NULL, NULL); + CU_ASSERT_FATAL(g_topic > 0); + g_writer = dds_create_writer(g_participant, g_topic, NULL, NULL); + CU_ASSERT_FATAL(g_writer > 0); + + /* Register the instance. */ + ret = dds_register_instance(g_writer, &ih, &testData); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_NOT_EQUAL_FATAL(ih, DDS_HANDLE_NIL); + + /* Unregister the instance. */ + ret = dds_unregister_instance_ih_ts(g_writer, ih, dds_time()); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + dds_delete(g_writer); + dds_delete(g_topic); + dds_delete(g_participant); +} +/*************************************************************************************************/ + /*************************************************************************************************/ CU_Test(ddsc_unregister_instance, dispose_unregistered_sample, .init=unregistering_init, .fini=unregistering_fini) { From d723ab79adc84f5011fe6fb571f39dee26575ef2 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 16 May 2019 14:40:42 +0200 Subject: [PATCH 077/178] add option to prefer multicast for data Sometimes it can be useful to force all data transmissions to go out via multicasts, instead of using a unicast when a single unicast suffices. This commit adds a General/PreferMulticast setting that, when set to true, implements this behaviour. It is "PreferMulticast" because readers that only advertise unicast addresses will still receive the data via unicast. The default behaviour is unchanged. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_config.h | 1 + src/core/ddsi/src/q_config.c | 2 ++ src/core/ddsi/src/q_entity.c | 6 ++++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index b0e160c..d7cd25d 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -239,6 +239,7 @@ struct config int tracingTimestamps; int tracingAppendToFile; uint32_t allowMulticast; + int prefer_multicast; enum transport_selector transport_selector; enum boolean_default compat_use_ipv6; enum boolean_default compat_tcp_enable; diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index cde5e86..382d2c1 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -244,6 +244,8 @@ static const struct cfgelem general_cfgelems[] = {
    • ssm: enables the use of SSM (source-specific multicast) for all non-SPDP traffic (if supported)
    • \n\
    \n\

    When set to \"false\" all multicasting is disabled. The default, \"true\" enables full use of multicasts. Listening for multicasts can be controlled by General/MulticastRecvNetworkInterfaceAddresses.

    ") }, + { LEAF("PreferMulticast"), 1, "false", ABSOFF(prefer_multicast), 0, uf_boolean, 0, pf_boolean, + BLURB("

    When false (default) Cyclone DDS uses unicast for data whenever there a single unicast suffices. Setting this to true makes it prefer multicasting data, falling back to unicast only when no multicast address is available.

    ") }, { LEAF("MulticastTimeToLive"), 1, "32", ABSOFF(multicast_ttl), 0, uf_natint_255, 0, pf_int, BLURB("

    This element specifies the time-to-live setting for outgoing multicast packets.

    ") }, { LEAF("DontRoute"), 1, "false", ABSOFF(dontRoute), 0, uf_boolean, 0, pf_boolean, diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 53c0bc6..f7d3480 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -1107,7 +1107,7 @@ static void rebuild_trace_covered(int nreaders, int nlocs, const nn_locator_t *l { char buf[DDSI_LOCATORSTRLEN]; ddsi_locator_to_string(buf, sizeof(buf), &locs[i]); - DDS_LOG(DDS_LC_DISCOVERY, " loc %2d = %-20s %2d {", i, buf, locs_nrds[i]); + DDS_LOG(DDS_LC_DISCOVERY, " loc %2d = %-30s %2d {", i, buf, locs_nrds[i]); for (j = 0; j < nreaders; j++) if (covered[j * nlocs + i] >= 0) DDS_LOG(DDS_LC_DISCOVERY, " %d", covered[j * nlocs + i]); @@ -1123,7 +1123,9 @@ static int rebuild_select(int nlocs, const nn_locator_t *locs, const int *locs_n if (nlocs == 0) return -1; for (j = 0, i = 1; i < nlocs; i++) { - if (locs_nrds[i] > locs_nrds[j]) + if (config.prefer_multicast && locs_nrds[i] > 0 && ddsi_is_mcaddr(&locs[i]) && !ddsi_is_mcaddr(&locs[j])) + j = i; /* obviously first step must be to try and avoid unicast if configuration says so */ + else if (locs_nrds[i] > locs_nrds[j]) j = i; /* better coverage */ else if (locs_nrds[i] == locs_nrds[j]) { From 7fbe49c26738b5551abf764051bd27b49c191a4d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 24 May 2019 08:33:04 +0200 Subject: [PATCH 078/178] Fix broken check for multi-process support With the introduction of FreeRTOS support, the requirement that the underlying platform supports multiple processes became untenable, and therefore the code for dealing with multiple processes is now automatically detected via some CMake code and then effectuated in the sources via a macro (DDSRT_HAVE_MULTI_PROCESS). Unfortunately, a typo resulted in all platforms being treated as if without support for multiple processes. Fortunately, at this stage the only consequence was the disabling of the first few multi-process tests. Signed-off-by: Erik Boasson --- src/ddsrt/cmake/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ddsrt/cmake/process.c b/src/ddsrt/cmake/process.c index a1f3561..84e13f0 100644 --- a/src/ddsrt/cmake/process.c +++ b/src/ddsrt/cmake/process.c @@ -11,7 +11,7 @@ */ #include "dds/ddsrt/process.h" -#if DDSRT_HAVE_PROCESS +#if DDSRT_HAVE_MULTI_PROCESS # error "cmake_HAVE_MULTI_PROCESS=true" #else # error "cmake_HAVE_MULTI_PROCESS=false" From 4fc56c5cbea1725ba423dd3b173c09109c154c43 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 24 May 2019 08:37:19 +0200 Subject: [PATCH 079/178] MPT driver incorrectly reporting a waitpid error The multi-process test driver program waits until all its children have stopped (or timeout) by calling ddsrt_proc_waitpids in a loop. The way the loop is written, it can try once more when all children have already been waited for, in which case it reports a spurious error. This fixes that problem by checking whether the error code was to be expected. Signed-off-by: Erik Boasson --- src/mpt/mpt/src/main.c.in | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mpt/mpt/src/main.c.in b/src/mpt/mpt/src/main.c.in index 14ca113..b48f3a6 100644 --- a/src/mpt/mpt/src/main.c.in +++ b/src/mpt/mpt/src/main.c.in @@ -355,8 +355,14 @@ mpt_run_test(const char *exe, mpt_suite_t *suite, mpt_test_t *test) result = EXIT_FAILURE; } } else if (retcode != DDS_RETCODE_NOT_FOUND) { - printf("Wait for processes of %s::%s failed (%d)\n", suite->name, test->name, (int)retcode); - result = EXIT_FAILURE; + for (proc = test->procs; proc; proc = proc->next) { + if (proc->pid != 0) + break; + } + if (proc != NULL) { + printf("Wait for processes of %s::%s failed (%d)\n", suite->name, test->name, (int)retcode); + result = EXIT_FAILURE; + } } } From e822dba9c1bed9ca947eed9be24a0c26cef89cc7 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 24 May 2019 13:05:02 +0200 Subject: [PATCH 080/178] MPT basic: append config, don't hardcode network If a firewall blocks traffic over one network but not another, and the one happens to be the default pick of Cyclone, then the MPT basic tests won't work properly. With the recent changes to the configuration handling for supporting multiple sources of configuration, it makes far more sense to remove the hardcoded network interface selection in the test configurations and to append the test configuration file to the environment list rather than to replace it. Signed-off-by: Erik Boasson --- src/mpt/tests/basic/etc/config_any.xml | 1 - src/mpt/tests/basic/etc/config_specific.xml | 1 - src/mpt/tests/basic/helloworld.c | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mpt/tests/basic/etc/config_any.xml b/src/mpt/tests/basic/etc/config_any.xml index 71b410f..275eb4b 100644 --- a/src/mpt/tests/basic/etc/config_any.xml +++ b/src/mpt/tests/basic/etc/config_any.xml @@ -14,7 +14,6 @@ any - auto true true diff --git a/src/mpt/tests/basic/etc/config_specific.xml b/src/mpt/tests/basic/etc/config_specific.xml index c6ccf33..0532aa0 100644 --- a/src/mpt/tests/basic/etc/config_specific.xml +++ b/src/mpt/tests/basic/etc/config_specific.xml @@ -14,7 +14,6 @@ ${DOMAIN_ID} - auto true true diff --git a/src/mpt/tests/basic/helloworld.c b/src/mpt/tests/basic/helloworld.c index c959edb..934262a 100644 --- a/src/mpt/tests/basic/helloworld.c +++ b/src/mpt/tests/basic/helloworld.c @@ -13,13 +13,13 @@ /* Environments */ static mpt_env_t environment_any[] = { { "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/basic/etc" }, - { "CYCLONEDDS_URI", "file://${ETC_DIR}/config_any.xml" }, + { "CYCLONEDDS_URI", "${CYCLONEDDS_URI},file://${ETC_DIR}/config_any.xml" }, { NULL, NULL } }; static mpt_env_t environment_42[] = { { "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/basic/etc" }, { "DOMAIN_ID", "42" }, - { "CYCLONEDDS_URI", "file://${ETC_DIR}/config_specific.xml" }, + { "CYCLONEDDS_URI", "${CYCLONEDDS_URI},file://${ETC_DIR}/config_specific.xml" }, { NULL, NULL } }; From a652ecb78e145fa936b8fef2f58f27ab0411245a Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 22 May 2019 20:53:57 +0200 Subject: [PATCH 081/178] ensure delivery of writes immediately following pub match event (#165) A long-standing bug of Cyclone is that a sample written immediately after a publication-matched event may never arrive at the reader that was just matched. This happened because the reader need not have completed discovery of the writer by the time the writer discovers the reader, at which point the reader ignores the sample because it either doesn't know the writer at all, or it hasn't yet seen a Heartbeat from it. That Heartbeat arrives shortly after, but by then it is too late: the reader slaves decides to accept the next sample to be written by the writer. (It has no choice, really: either you risk losing some data, or you will be requesting all historical data, which is empathically not what a volatile reader is about ...) A related issue is the handling of historical data for transient-local readers: it used to deliver this out-of-order, but that is firstly against the specification, and secondly, against reasonable expectations of those who use DDS as a mere publish-subscribe messaging system. To add insult to injury, it didn't completely handle some reordering issues with disposes ... This commit changes the way writers respond to a request for retransmission from volatile proxy readers and the way the in-sync/out-of-sync setting of a reader with respect to a proxy-writer is used. The first makes it safe for a Cyclone reader to ask a Cyclone writer for all data (all these details not being covered in the specs it errs on the reasonable side for other vendors, but that may cause the data loss mentioned above): the writer simply send a Gap message to the reader for all the sequence numbers prior to the matching. The second changes the rule for switching from out-of-sync to in-sync: that transition is now simply once the next sequence number to be delivered to the reader equals the next sequence number that will be delivered directly from the proxy writer object to all readers. (I.e., a much more intuitive notion than reaching some seemingly arbitrary sequence number.) To avoid duplicates the rule for delivery straight from a proxy writer has changed: where samples were delivered from the proxy writer to all matching readers, they are now delivered only to the matching readers that are in-sync. To avoid ordering problems, the idea that historical data can be delivered through the asynchronous delivery path even when the regular data goes through the synchronous delivery path has been abandoned. All data now always follows the same path. As these same mechanisms are used for getting historical data into transient-local readers, the ordering problem for the historical data also disappeared. The test stuff in src/core/xtests/initsampledeliv covers a lot of the interesting cases: data published before the existene of a reader, after it, mixes of volatile and transient-local. Running them takes quite a bit of time, and they are not yet integrated in the CI builds (if ever, because of that time). Note: the "conservative built-in startup" option has been removed, because it really makes no sense to keep a vague compatibility option added a decade ago "just in case" that has never been used ... Note: the workaround in the src/mpt/tests/basic/procs/hello.c (use transient-local to ensure delivery of data) has been removed, as has been its workaround for the already-fixed #146. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_config.h | 1 - src/core/ddsi/include/dds/ddsi/q_entity.h | 4 +- src/core/ddsi/src/q_config.c | 7 +- src/core/ddsi/src/q_debmon.c | 2 +- src/core/ddsi/src/q_entity.c | 80 ++++-- src/core/ddsi/src/q_receive.c | 257 +++++++++--------- src/core/xtests/CMakeLists.txt | 17 +- .../xtests/initsampledeliv/CMakeLists.txt | 20 ++ .../initsampledeliv/InitSampleDelivData.idl | 19 ++ src/core/xtests/initsampledeliv/publisher.c | 163 +++++++++++ src/core/xtests/initsampledeliv/runtest | 46 ++++ src/core/xtests/initsampledeliv/subscriber.c | 198 ++++++++++++++ src/core/xtests/rhc_torture/CMakeLists.txt | 26 ++ .../xtests/{ => rhc_torture}/RhcTypes.idl | 0 .../xtests/{ => rhc_torture}/rhc_torture.c | 0 src/mpt/tests/basic/procs/hello.c | 9 +- 16 files changed, 677 insertions(+), 172 deletions(-) create mode 100644 src/core/xtests/initsampledeliv/CMakeLists.txt create mode 100644 src/core/xtests/initsampledeliv/InitSampleDelivData.idl create mode 100644 src/core/xtests/initsampledeliv/publisher.c create mode 100644 src/core/xtests/initsampledeliv/runtest create mode 100644 src/core/xtests/initsampledeliv/subscriber.c create mode 100644 src/core/xtests/rhc_torture/CMakeLists.txt rename src/core/xtests/{ => rhc_torture}/RhcTypes.idl (100%) rename src/core/xtests/{ => rhc_torture}/rhc_torture.c (100%) diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index d7cd25d..a83fbf8 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -330,7 +330,6 @@ struct config uint32_t rmsg_chunk_size; /**<< size of a chunk in the receive buffer */ uint32_t rbuf_size; /* << size of a single receiver buffer */ enum besmode besmode; - int conservative_builtin_reader_startup; int meas_hb_to_ack_latency; int unicast_response_to_spdp_messages; int synchronous_delivery_priority_threshold; diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 4c0c4bd..603b88f 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -123,7 +123,6 @@ struct pwr_rd_match { union { struct { seqno_t end_of_tl_seq; /* when seq >= end_of_tl_seq, it's in sync, =0 when not tl */ - seqno_t end_of_out_of_sync_seq; /* when seq >= end_of_tl_seq, it's in sync, =0 when not tl */ struct nn_reorder *reorder; /* can be done (mostly) per proxy writer, but that is harder; only when state=OUT_OF_SYNC */ } not_in_sync; } u; @@ -574,6 +573,9 @@ uint64_t writer_instance_id (const struct nn_guid *guid); rebuild them all (which only makes sense after previously having emptied them all). */ void rebuild_or_clear_writer_addrsets(int rebuild); + +void local_reader_ary_setfastpath_ok (struct local_reader_ary *x, bool fastpath_ok); + #if defined (__cplusplus) } #endif diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 382d2c1..98f030b 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -509,9 +509,9 @@ static const struct cfgelem unsupp_cfgelems[] = { { MOVED("FragmentSize", "CycloneDDS/General/FragmentSize") }, { LEAF("DeliveryQueueMaxSamples"), 1, "256", ABSOFF(delivery_queue_maxsamples), 0, uf_uint, 0, pf_uint, BLURB("

    This element controls the Maximum size of a delivery queue, expressed in samples. Once a delivery queue is full, incoming samples destined for that queue are dropped until space becomes available again.

    ") }, - { LEAF("PrimaryReorderMaxSamples"), 1, "64", ABSOFF(primary_reorder_maxsamples), 0, uf_uint, 0, pf_uint, + { LEAF("PrimaryReorderMaxSamples"), 1, "128", ABSOFF(primary_reorder_maxsamples), 0, uf_uint, 0, pf_uint, BLURB("

    This element sets the maximum size in samples of a primary re-order administration. Each proxy writer has one primary re-order administration to buffer the packet flow in case some packets arrive out of order. Old samples are forwarded to secondary re-order administrations associated with readers in need of historical data.

    ") }, - { LEAF("SecondaryReorderMaxSamples"), 1, "16", ABSOFF(secondary_reorder_maxsamples), 0, uf_uint, 0, pf_uint, + { LEAF("SecondaryReorderMaxSamples"), 1, "128", ABSOFF(secondary_reorder_maxsamples), 0, uf_uint, 0, pf_uint, BLURB("

    This element sets the maximum size in samples of a secondary re-order administration. The secondary re-order administration is per reader in need of historical data.

    ") }, { LEAF("DefragUnreliableMaxSamples"), 1, "4", ABSOFF(defrag_unreliable_maxsamples), 0, uf_uint, 0, pf_uint, BLURB("

    This element sets the maximum number of samples that can be defragmented simultaneously for a best-effort writers.

    ") }, @@ -523,9 +523,6 @@ static const struct cfgelem unsupp_cfgelems[] = {
  • writers: all participants have the writers, but just one has the readers;
  • \n\
  • minimal: only one participant has built-in endpoints.
  • \n\

    The default is writers, as this is thought to be compliant and reasonably efficient. Minimal may or may not be compliant but is most efficient, and full is inefficient but certain to be compliant. See also Internal/ConservativeBuiltinReaderStartup.

    ") }, - { LEAF("ConservativeBuiltinReaderStartup"), 1, "false", ABSOFF(conservative_builtin_reader_startup), 0, uf_boolean, 0, pf_boolean, - BLURB("

    This element forces all DDSI2E built-in discovery-related readers to request all historical data, instead of just one for each \"topic\". There is no indication that any of the current DDSI implementations requires changing of this setting, but it is conceivable that an implementation might track which participants have been informed of the existence of endpoints and which have not been, refusing communication with those that have \"can't\" know.

    \n\ -

    Should it be necessary to hide DDSI2E's shared discovery behaviour, set this to true and Internal/BuiltinEndpointSet to full.

    ") }, { LEAF("MeasureHbToAckLatency"), 1, "false", ABSOFF(meas_hb_to_ack_latency), 0, uf_boolean, 0, pf_boolean, BLURB("

    This element enables heartbeat-to-ack latency among DDSI2E services by prepending timestamps to Heartbeat and AckNack messages and calculating round trip times. This is non-standard behaviour. The measured latencies are quite noisy and are currently not used anywhere.

    ") }, { LEAF("UnicastResponseToSPDPMessages"), 1, "true", ABSOFF(unicast_response_to_spdp_messages), 0, uf_boolean, 0, pf_boolean, diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index 35ed218..9ea929f 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -286,7 +286,7 @@ static int print_proxy_participants (struct thread_state1 * const ts1, ddsi_tran x += cpf (conn, " tl-catchup end_of_tl_seq %lld\n", m->u.not_in_sync.end_of_tl_seq); break; case PRMSS_OUT_OF_SYNC: - x += cpf (conn, " out-of-sync end_of_tl_seq %lld end_of_out_of_sync_seq %lld\n", m->u.not_in_sync.end_of_tl_seq, m->u.not_in_sync.end_of_out_of_sync_seq); + x += cpf (conn, " out-of-sync end_of_tl_seq %lld\n", m->u.not_in_sync.end_of_tl_seq); break; } } diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index f7d3480..9dc0024 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -235,6 +235,14 @@ void local_reader_ary_remove (struct local_reader_ary *x, struct reader *rd) ddsrt_mutex_unlock (&x->rdary_lock); } +void local_reader_ary_setfastpath_ok (struct local_reader_ary *x, bool fastpath_ok) +{ + ddsrt_mutex_lock (&x->rdary_lock); + if (x->valid) + x->fastpath_ok = fastpath_ok; + ddsrt_mutex_unlock (&x->rdary_lock); +} + void local_reader_ary_setinvalid (struct local_reader_ary *x) { ddsrt_mutex_lock (&x->rdary_lock); @@ -1492,9 +1500,17 @@ static void proxy_writer_drop_connection (const struct nn_guid *pwr_guid, struct { ddsrt_avl_delete (&pwr_readers_treedef, &pwr->readers, m); if (m->in_sync != PRMSS_SYNC) - pwr->n_readers_out_of_sync--; + { + if (--pwr->n_readers_out_of_sync == 0) + local_reader_ary_setfastpath_ok (&pwr->rdary, true); + } if (rd->reliable) pwr->n_reliable_readers--; + /* If no reliable readers left, there is no reason to believe the heartbeats will keep + coming and therefore reset have_seen_heartbeat so the next reader to be created + doesn't get initialised based on stale data */ + if (pwr->n_reliable_readers == 0) + pwr->have_seen_heartbeat = 0; local_reader_ary_remove (&pwr->rdary, rd); } ddsrt_mutex_unlock (&pwr->e.lock); @@ -1775,7 +1791,6 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader { struct pwr_rd_match *m = ddsrt_malloc (sizeof (*m)); ddsrt_avl_ipath_t path; - seqno_t last_deliv_seq; ddsrt_mutex_lock (&pwr->e.lock); if (ddsrt_avl_lookup_ipath (&pwr_readers_treedef, &pwr->readers, &rd->e.guid, &path)) @@ -1794,7 +1809,6 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader m->rd_guid = rd->e.guid; m->tcreate = now_mt (); - /* We track the last heartbeat count value per reader--proxy-writer pair, so that we can correctly handle directed heartbeats. The only reason to bother is to prevent a directed heartbeat (with @@ -1813,34 +1827,61 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader /* These can change as a consequence of handling data and/or discovery activities. The safe way of dealing with them is to lock the proxy writer */ - last_deliv_seq = nn_reorder_next_seq (pwr->reorder) - 1; - if (!rd->handle_as_transient_local) + if (is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) && !ddsrt_avl_is_empty (&pwr->readers)) { + /* builtins really don't care about multiple copies or anything */ m->in_sync = PRMSS_SYNC; } - else if (!config.conservative_builtin_reader_startup && is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) && !ddsrt_avl_is_empty (&pwr->readers)) + else if (!pwr->have_seen_heartbeat) { - /* builtins really don't care about multiple copies */ + /* Proxy writer hasn't seen a heartbeat yet: means we have no + clue from what sequence number to start accepting data, nor + where historical data ends and live data begins. + + A transient-local reader should always get all historical + data, and so can always start-out as "out-of-sync". Cyclone + refuses to retransmit already ACK'd samples to a Cyclone + reader, so if the other side is Cyclone, we can always start + from sequence number 1. + + For non-Cyclone, if the reader is volatile, we have to just + start from the most recent sample, even though that means + the first samples written after matching the reader may be + lost. The alternative not only gets too much historical data + but may also result in "sample lost" notifications because the + writer is (may not be) retaining samples on behalf of this + reader for the oldest samples and so this reader may end up + with a partial set of old-ish samples. Even when both are + using KEEP_ALL and the connection doesn't fail ... */ + if (rd->handle_as_transient_local) + m->in_sync = PRMSS_OUT_OF_SYNC; + else if (vendor_is_eclipse (pwr->c.vendor)) + m->in_sync = PRMSS_OUT_OF_SYNC; + else + m->in_sync = PRMSS_SYNC; + m->u.not_in_sync.end_of_tl_seq = MAX_SEQ_NUMBER; + } + else if (!rd->handle_as_transient_local) + { + /* volatile reader, writer has seen a heartbeat: it's in sync + (there is a risk of it getting some historical data: that + happens to be cached in the writer's reorder admin at this + point) */ m->in_sync = PRMSS_SYNC; } else { - /* normal transient-local, reader is behind proxy writer */ + /* transient-local reader; range of sequence numbers is already + known */ m->in_sync = PRMSS_OUT_OF_SYNC; - if (last_deliv_seq == 0) - { - m->u.not_in_sync.end_of_out_of_sync_seq = MAX_SEQ_NUMBER; - m->u.not_in_sync.end_of_tl_seq = MAX_SEQ_NUMBER; - } - else - { - m->u.not_in_sync.end_of_tl_seq = pwr->last_seq; - m->u.not_in_sync.end_of_out_of_sync_seq = last_deliv_seq; - } - DDS_LOG(DDS_LC_DISCOVERY, " - out-of-sync %"PRId64, m->u.not_in_sync.end_of_out_of_sync_seq); + m->u.not_in_sync.end_of_tl_seq = pwr->last_seq; } if (m->in_sync != PRMSS_SYNC) + { + DDS_LOG(DDS_LC_DISCOVERY, " - out-of-sync"); pwr->n_readers_out_of_sync++; + local_reader_ary_setfastpath_ok (&pwr->rdary, false); + } m->count = init_count; /* Spec says we may send a pre-emptive AckNack (8.4.2.3.4), hence we schedule it for the configured delay * T_MILLISECOND. From then @@ -3510,7 +3551,6 @@ void new_proxy_participant proxypp->plist = nn_plist_dup (plist); ddsrt_avl_init (&proxypp_groups_treedef, &proxypp->groups); - if (custom_flags & CF_INC_KERNEL_SEQUENCE_NUMBERS) proxypp->kernel_sequence_numbers = 1; else diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 842d372..58ae5c3 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -74,7 +74,7 @@ Notes: */ -static void deliver_user_data_synchronously (struct nn_rsample_chain *sc); +static void deliver_user_data_synchronously (struct nn_rsample_chain *sc, const nn_guid_t *rdguid); static void maybe_set_reader_in_sync (struct proxy_writer *pwr, struct pwr_rd_match *wn, seqno_t last_deliv_seq) { @@ -87,11 +87,13 @@ static void maybe_set_reader_in_sync (struct proxy_writer *pwr, struct pwr_rd_ma if (last_deliv_seq >= wn->u.not_in_sync.end_of_tl_seq) { wn->in_sync = PRMSS_SYNC; - pwr->n_readers_out_of_sync--; + if (--pwr->n_readers_out_of_sync == 0) + local_reader_ary_setfastpath_ok (&pwr->rdary, true); } break; case PRMSS_OUT_OF_SYNC: - if (nn_reorder_next_seq (wn->u.not_in_sync.reorder) - 1 >= wn->u.not_in_sync.end_of_out_of_sync_seq) + assert (nn_reorder_next_seq (wn->u.not_in_sync.reorder) <= nn_reorder_next_seq (pwr->reorder)); + if (pwr->have_seen_heartbeat && nn_reorder_next_seq (wn->u.not_in_sync.reorder) == nn_reorder_next_seq (pwr->reorder)) { DDS_TRACE(" msr_in_sync("PGUIDFMT" out-of-sync to tlcatchup)", PGUID (wn->rd_guid)); wn->in_sync = PRMSS_TLCATCHUP; @@ -887,6 +889,8 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac a future request'll fix it. */ enqueued = 1; seq_xmit = READ_SEQ_XMIT(wr); + const bool gap_for_already_acked = vendor_is_eclipse (rst->vendor) && prd->c.xqos->durability.kind == NN_VOLATILE_DURABILITY_QOS && seqbase <= rn->seq; + const seqno_t min_seq_to_rexmit = gap_for_already_acked ? rn->seq + 1 : 0; for (i = 0; i < numbits && seqbase + i <= seq_xmit && enqueued; i++) { /* Accelerated schedule may run ahead of sequence number set @@ -897,7 +901,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac { seqno_t seq = seqbase + i; struct whc_borrowed_sample sample; - if (whc_borrow_sample (wr->whc, seq, &sample)) + if (seqbase + i >= min_seq_to_rexmit && whc_borrow_sample (wr->whc, seq, &sample)) { if (!wr->retransmitting && sample.unacked) writer_set_retransmitting (wr); @@ -1176,40 +1180,45 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct if (!rst->forme) { - DDS_TRACE(""PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst)); + DDS_TRACE(PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst)); return 1; } if ((pwr = ephash_lookup_proxy_writer_guid (&src)) == NULL) { - DDS_TRACE(""PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst)); + DDS_TRACE(PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst)); return 1; } - /* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */ + /* liveliness is still only implemented partially (with all set to AUTOMATIC, + BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */ if (pwr->assert_pp_lease) lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); - DDS_TRACE(""PGUIDFMT" -> "PGUIDFMT":", PGUID (src), PGUID (dst)); + DDS_TRACE(PGUIDFMT" -> "PGUIDFMT":", PGUID (src), PGUID (dst)); ddsrt_mutex_lock (&pwr->e.lock); + if (pwr->n_reliable_readers == 0) + { + DDS_TRACE(PGUIDFMT" -> "PGUIDFMT" no-reliable-readers)", PGUID (src), PGUID (dst)); + ddsrt_mutex_unlock (&pwr->e.lock); + return 1; + } + if (!pwr->have_seen_heartbeat) { struct nn_rdata *gap; struct nn_rsample_chain sc; int refc_adjust = 0; nn_reorder_result_t res; - nn_defrag_notegap (pwr->defrag, 1, lastseq + 1); gap = nn_rdata_newgap (rmsg); - if ((res = nn_reorder_gap (&sc, pwr->reorder, gap, 1, lastseq + 1, &refc_adjust)) > 0) - { - if (pwr->deliver_synchronously) - deliver_user_data_synchronously (&sc); - else - nn_dqueue_enqueue (pwr->dqueue, &sc, res); - } + res = nn_reorder_gap (&sc, pwr->reorder, gap, 1, lastseq + 1, &refc_adjust); + /* proxy writer is not accepting data until it has received a heartbeat, so + there can't be any data to deliver */ + assert (res <= 0); + (void) res; nn_fragchain_adjust_refcount (gap, refc_adjust); pwr->have_seen_heartbeat = 1; } @@ -1243,7 +1252,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct if ((res = nn_reorder_gap (&sc, pwr->reorder, gap, 1, firstseq, &refc_adjust)) > 0) { if (pwr->deliver_synchronously) - deliver_user_data_synchronously (&sc); + deliver_user_data_synchronously (&sc, NULL); else nn_dqueue_enqueue (pwr->dqueue, &sc, res); } @@ -1262,13 +1271,18 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct case PRMSS_OUT_OF_SYNC: { struct nn_reorder *ro = wn->u.not_in_sync.reorder; if ((res = nn_reorder_gap (&sc, ro, gap, 1, firstseq, &refc_adjust)) > 0) - nn_dqueue_enqueue1 (pwr->dqueue, &wn->rd_guid, &sc, res); + { + if (pwr->deliver_synchronously) + deliver_user_data_synchronously (&sc, &wn->rd_guid); + else + nn_dqueue_enqueue1 (pwr->dqueue, &wn->rd_guid, &sc, res); + } last_deliv_seq = nn_reorder_next_seq (wn->u.not_in_sync.reorder) - 1; } } if (wn->u.not_in_sync.end_of_tl_seq == MAX_SEQ_NUMBER) { - wn->u.not_in_sync.end_of_out_of_sync_seq = wn->u.not_in_sync.end_of_tl_seq = fromSN (msg->lastSN); + wn->u.not_in_sync.end_of_tl_seq = fromSN (msg->lastSN); DDS_TRACE(" end-of-tl-seq(rd "PGUIDFMT" #%"PRId64")", PGUID(wn->rd_guid), wn->u.not_in_sync.end_of_tl_seq); } maybe_set_reader_in_sync (pwr, wn, last_deliv_seq); @@ -1591,7 +1605,7 @@ static int handle_one_gap (struct proxy_writer *pwr, struct pwr_rd_match *wn, se if ((res = nn_reorder_gap (&sc, pwr->reorder, gap, a, b, refc_adjust)) > 0) { if (pwr->deliver_synchronously) - deliver_user_data_synchronously (&sc); + deliver_user_data_synchronously (&sc, NULL); else nn_dqueue_enqueue (pwr->dqueue, &sc, res); } @@ -1617,13 +1631,15 @@ static int handle_one_gap (struct proxy_writer *pwr, struct pwr_rd_match *wn, se case PRMSS_TLCATCHUP: break; case PRMSS_OUT_OF_SYNC: - if (a <= wn->u.not_in_sync.end_of_out_of_sync_seq) + if ((res = nn_reorder_gap (&sc, wn->u.not_in_sync.reorder, gap, a, b, refc_adjust)) > 0) { - if ((res = nn_reorder_gap (&sc, wn->u.not_in_sync.reorder, gap, a, b, refc_adjust)) > 0) + if (pwr->deliver_synchronously) + deliver_user_data_synchronously (&sc, &wn->rd_guid); + else nn_dqueue_enqueue1 (pwr->dqueue, &wn->rd_guid, &sc, res); - if (res >= 0) - gap_was_valuable = 1; } + if (res >= 0) + gap_was_valuable = 1; break; } @@ -1970,94 +1986,90 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st goto no_payload; } - /* Generate the DDS_SampleInfo (which is faked to some extent - because we don't actually have a data reader); also note that - the PRISMTECH_WRITER_INFO thing is completely meaningless to - us */ + because we don't actually have a data reader); also note that + the PRISMTECH_WRITER_INFO thing is completely meaningless to + us */ + struct ddsi_tkmap_instance * tk; + if ((tk = ddsi_tkmap_lookup_instance_ref(payload)) != NULL) { - struct ddsi_tkmap_instance * tk; - tk = ddsi_tkmap_lookup_instance_ref(payload); - if (tk) + struct proxy_writer_info pwr_info; + make_proxy_writer_info(&pwr_info, &pwr->e, pwr->c.xqos); + + if (rdguid == NULL) { - struct proxy_writer_info pwr_info; - make_proxy_writer_info(&pwr_info, &pwr->e, pwr->c.xqos); + DDS_TRACE(" %"PRId64"=>EVERYONE\n", sampleinfo->seq); - if (rdguid == NULL) + /* FIXME: pwr->rdary is an array of pointers to attached + readers. There's only one thread delivering data for the + proxy writer (as long as there is only one receive thread), + so could get away with not locking at all, and doing safe + updates + GC of rdary instead. */ + + /* Retry loop, for re-delivery of rejected reliable samples. Is a + temporary hack till throttling back of writer is implemented + (with late acknowledgement of sample and nack). */ + retry: + + ddsrt_mutex_lock (&pwr->rdary.rdary_lock); + if (pwr->rdary.fastpath_ok) { - DDS_TRACE(" %"PRId64"=>EVERYONE\n", sampleinfo->seq); - - /* FIXME: pwr->rdary is an array of pointers to attached - readers. There's only one thread delivering data for the - proxy writer (as long as there is only one receive thread), - so could get away with not locking at all, and doing safe - updates + GC of rdary instead. */ - - /* Retry loop, for re-delivery of rejected reliable samples. Is a - temporary hack till throttling back of writer is implemented - (with late acknowledgement of sample and nack). */ -retry: - - ddsrt_mutex_lock (&pwr->rdary.rdary_lock); - if (pwr->rdary.fastpath_ok) + struct reader ** const rdary = pwr->rdary.rdary; + unsigned i; + for (i = 0; rdary[i]; i++) { - struct reader ** const rdary = pwr->rdary.rdary; - unsigned i; - for (i = 0; rdary[i]; i++) + DDS_TRACE("reader "PGUIDFMT"\n", PGUID (rdary[i]->e.guid)); + if (! (ddsi_plugin.rhc_plugin.rhc_store_fn) (rdary[i]->rhc, &pwr_info, payload, tk)) { - DDS_TRACE("reader "PGUIDFMT"\n", PGUID (rdary[i]->e.guid)); - if (! (ddsi_plugin.rhc_plugin.rhc_store_fn) (rdary[i]->rhc, &pwr_info, payload, tk)) - { - if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock); - ddsrt_mutex_unlock (&pwr->rdary.rdary_lock); - dds_sleepfor (DDS_MSECS (10)); - if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock); - goto retry; - } + if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock); + ddsrt_mutex_unlock (&pwr->rdary.rdary_lock); + dds_sleepfor (DDS_MSECS (10)); + if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock); + goto retry; } - 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 pwr_rd_match *m; - ddsrt_mutex_unlock (&pwr->rdary.rdary_lock); - if (!pwr_locked) ddsrt_mutex_lock (&pwr->e.lock); - for (m = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); m != NULL; m = ddsrt_avl_iter_next (&it)) - { - struct reader *rd; - if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) - { - DDS_TRACE("reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid)); - (void) (ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk); - } - } - if (!pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock); - } - - ddsrt_atomic_st32 (&pwr->next_deliv_seq_lowword, (uint32_t) (sampleinfo->seq + 1)); + ddsrt_mutex_unlock (&pwr->rdary.rdary_lock); } else { - struct reader *rd = ephash_lookup_reader_guid (rdguid);; - DDS_TRACE(" %"PRId64"=>"PGUIDFMT"%s\n", sampleinfo->seq, PGUID (*rdguid), rd ? "" : "?"); - while (rd && ! (ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk) && ephash_lookup_proxy_writer_guid (&pwr->e.guid)) + /* 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; + ddsrt_mutex_unlock (&pwr->rdary.rdary_lock); + if (!pwr_locked) ddsrt_mutex_lock (&pwr->e.lock); + for (m = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); m != NULL; m = ddsrt_avl_iter_next (&it)) { - if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock); - dds_sleepfor (DDS_MSECS (1)); - if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock); + struct reader *rd; + if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL && m->in_sync == PRMSS_SYNC) + { + DDS_TRACE("reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid)); + (void) (ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk); + } } + if (!pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock); } - ddsi_tkmap_instance_unref (tk); + + ddsrt_atomic_st32 (&pwr->next_deliv_seq_lowword, (uint32_t) (sampleinfo->seq + 1)); } + else + { + struct reader *rd = ephash_lookup_reader_guid (rdguid);; + DDS_TRACE(" %"PRId64"=>"PGUIDFMT"%s\n", sampleinfo->seq, PGUID (*rdguid), rd ? "" : "?"); + while (rd && ! (ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk) && ephash_lookup_proxy_writer_guid (&pwr->e.guid)) + { + if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock); + dds_sleepfor (DDS_MSECS (1)); + if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock); + } + } + ddsi_tkmap_instance_unref (tk); } ddsi_serdata_unref (payload); no_payload: @@ -2072,7 +2084,7 @@ int user_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct return res; } -static void deliver_user_data_synchronously (struct nn_rsample_chain *sc) +static void deliver_user_data_synchronously (struct nn_rsample_chain *sc, const nn_guid_t *rdguid) { while (sc->first) { @@ -2084,7 +2096,7 @@ static void deliver_user_data_synchronously (struct nn_rsample_chain *sc) sample_lost events. Also note that the synchronous path is _never_ used for historical data, and therefore never has the GUID of a reader to deliver to */ - deliver_user_data (e->sampleinfo, e->fragchain, NULL, 1); + deliver_user_data (e->sampleinfo, e->fragchain, rdguid, 1); } nn_fragchain_unref (e->fragchain); } @@ -2215,7 +2227,7 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct by the current mishandling of resource limits */ if (*deferred_wakeup) dd_dqueue_enqueue_trigger (*deferred_wakeup); - deliver_user_data_synchronously (&sc); + deliver_user_data_synchronously (&sc, NULL); } else { @@ -2226,28 +2238,22 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct *deferred_wakeup = pwr->dqueue; } } - if (pwr->n_readers_out_of_sync > 0) - { - /* Those readers catching up with TL but in sync with the proxy - writer may have become in sync with the proxy writer and the - writer; those catching up with TL all by themselves go through - the "TOO_OLD" path below. */ - ddsrt_avl_iter_t it; - struct pwr_rd_match *wn; - for (wn = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); wn != NULL; wn = ddsrt_avl_iter_next (&it)) - if (wn->in_sync == PRMSS_TLCATCHUP) - maybe_set_reader_in_sync (pwr, wn, sampleinfo->seq); - } } - else if (rres == NN_REORDER_TOO_OLD) + + if (pwr->n_readers_out_of_sync > 0) { + /* Those readers catching up with TL but in sync with the proxy + writer may have become in sync with the proxy writer and the + writer; those catching up with TL all by themselves go through + the "TOO_OLD" path below. */ + ddsrt_avl_iter_t it; struct pwr_rd_match *wn; struct nn_rsample *rsample_dup = NULL; int reuse_rsample_dup = 0; - for (wn = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); wn != NULL; wn = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, wn)) + for (wn = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); wn != NULL; wn = ddsrt_avl_iter_next (&it)) { nn_reorder_result_t rres2; - if (wn->in_sync != PRMSS_OUT_OF_SYNC || sampleinfo->seq > wn->u.not_in_sync.end_of_out_of_sync_seq) + if (wn->in_sync == PRMSS_SYNC) continue; if (!reuse_rsample_dup) rsample_dup = nn_reorder_rsample_dup (rmsg, rsample); @@ -2273,17 +2279,26 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct in-order, and those few microseconds can't hurt in catching up on transient-local data. See also NN_REORDER_DELIVER case in outer switch. */ - nn_dqueue_enqueue1 (pwr->dqueue, &wn->rd_guid, &sc, rres2); + if (pwr->deliver_synchronously) + { + /* FIXME: just in case the synchronous delivery runs into a delay caused + by the current mishandling of resource limits */ + deliver_user_data_synchronously (&sc, &wn->rd_guid); + } + else + { + if (*deferred_wakeup && *deferred_wakeup != pwr->dqueue) + { + dd_dqueue_enqueue_trigger (*deferred_wakeup); + *deferred_wakeup = NULL; + } + nn_dqueue_enqueue1 (pwr->dqueue, &wn->rd_guid, &sc, rres2); + } break; } } } -#ifndef NDEBUG - else - { - assert (rres == NN_REORDER_ACCEPT || rres == NN_REORDER_REJECT); - } -#endif + nn_fragchain_adjust_refcount (fragchain, refc_adjust); } ddsrt_mutex_unlock (&pwr->e.lock); diff --git a/src/core/xtests/CMakeLists.txt b/src/core/xtests/CMakeLists.txt index 02b7bfd..72bdb94 100644 --- a/src/core/xtests/CMakeLists.txt +++ b/src/core/xtests/CMakeLists.txt @@ -9,18 +9,5 @@ # # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # -idlc_generate(RhcTypes RhcTypes.idl) - -add_executable(rhc_torture rhc_torture.c) - -target_include_directories( - rhc_torture PRIVATE - "$" - "$") - -target_link_libraries(rhc_torture RhcTypes ddsc) - -add_test( - NAME rhc_torture - COMMAND rhc_torture 314159265 0 5000 0) -set_property(TEST rhc_torture PROPERTY TIMEOUT 20) +add_subdirectory(rhc_torture) +add_subdirectory(initsampledeliv) diff --git a/src/core/xtests/initsampledeliv/CMakeLists.txt b/src/core/xtests/initsampledeliv/CMakeLists.txt new file mode 100644 index 0000000..e4804fa --- /dev/null +++ b/src/core/xtests/initsampledeliv/CMakeLists.txt @@ -0,0 +1,20 @@ +# +# Copyright(c) 2019 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# +cmake_minimum_required(VERSION 3.5) + +idlc_generate(InitSampleDeliv_lib InitSampleDelivData.idl) + +add_executable(InitSampleDelivPub publisher.c) +add_executable(InitSampleDelivSub subscriber.c) + +target_link_libraries(InitSampleDelivPub InitSampleDeliv_lib ddsc) +target_link_libraries(InitSampleDelivSub InitSampleDeliv_lib ddsc) diff --git a/src/core/xtests/initsampledeliv/InitSampleDelivData.idl b/src/core/xtests/initsampledeliv/InitSampleDelivData.idl new file mode 100644 index 0000000..1064232 --- /dev/null +++ b/src/core/xtests/initsampledeliv/InitSampleDelivData.idl @@ -0,0 +1,19 @@ +// Copyright(c) 2019 ADLINK Technology Limited and others +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +// v. 1.0 which is available at +// http://www.eclipse.org/org/documents/edl-v10.php. +// +// SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +struct Msg { + long keyval; + long seq; + long tldepth; + long final_seq; + long seq_at_match[2]; +}; + +#pragma keylist Msg keyval diff --git a/src/core/xtests/initsampledeliv/publisher.c b/src/core/xtests/initsampledeliv/publisher.c new file mode 100644 index 0000000..a690c16 --- /dev/null +++ b/src/core/xtests/initsampledeliv/publisher.c @@ -0,0 +1,163 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include "dds/dds.h" +#include "dds/ddsrt/atomics.h" +#include "InitSampleDelivData.h" +#include +#include +#include + +static void oops (const char *file, int line) +{ + fflush (stdout); + fprintf (stderr, "%s:%d\n", file, line); + abort (); +} + +#define oops() oops(__FILE__, __LINE__) + +static void on_pub_matched (dds_entity_t wr, const dds_publication_matched_status_t st, void *varg) +{ + ddsrt_atomic_uint32_t *new_readers = varg; + dds_sample_info_t info; + void *raw = NULL; + dds_entity_t rd; + printf ("pubmatched\n"); + if ((rd = dds_create_reader (dds_get_participant (wr), DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL)) < 0) + oops (); + if (dds_read_instance (rd, &raw, &info, 1, 1, st.last_subscription_handle) != 1) + oops (); + const dds_builtintopic_endpoint_t *sample = raw; + /* in our test the user data must be present */ + void *ud; + size_t udsz; + if (!dds_qget_userdata (sample->qos, &ud, &udsz)) + oops (); + int rdid = atoi (ud); + if (rdid < 0 || rdid > 31) + oops (); + printf ("pubmatched: %d\n", rdid); + fflush (stdout); + ddsrt_atomic_or32 (new_readers, UINT32_C (1) << rdid); + dds_free (ud); + dds_return_loan (rd, &raw, 1); +} + +static uint32_t get_publication_matched_count (dds_entity_t wr) +{ + dds_publication_matched_status_t status; + if (dds_get_publication_matched_status (wr, &status) < 0) + oops (); + return status.current_count; +} + +int main (int argc, char ** argv) +{ + dds_entity_t ppant; + dds_entity_t tp; + dds_entity_t wr; + dds_qos_t *qos; + ddsrt_atomic_uint32_t newreaders = DDSRT_ATOMIC_UINT32_INIT (0); + int opt; + bool flag_prewrite = false; + bool flag_translocal = false; + const int32_t tlhist = 10; + + while ((opt = getopt (argc, argv, "tp")) != EOF) + { + switch (opt) + { + case 't': + flag_translocal = true; + break; + case 'p': + flag_prewrite = true; + break; + default: + fprintf (stderr, "usage error: see source code\n"); + exit (2); + } + } + + if ((ppant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL)) < 0) + oops (); + + qos = dds_create_qos (); + dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_SECS (10)); + dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); + if ((tp = dds_create_topic (ppant, &Msg_desc, "Msg", qos, NULL)) < 0) + oops (); + + /* Writer has overrides for history, durability */ + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0); + dds_qset_durability (qos, flag_translocal ? DDS_DURABILITY_TRANSIENT_LOCAL : DDS_DURABILITY_VOLATILE); + dds_qset_durability_service (qos, 0, DDS_HISTORY_KEEP_LAST, tlhist, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED); + + dds_listener_t *list = dds_create_listener (&newreaders); + dds_lset_publication_matched (list, on_pub_matched); + if ((wr = dds_create_writer (ppant, tp, qos, list)) < 0) + oops (); + dds_delete_listener (list); + dds_delete_qos (qos); + + Msg sample = { + .keyval = 0, + .seq = 1, + .tldepth = tlhist, + .final_seq = 30, + .seq_at_match = { 0, 0 } + }; + dds_time_t tlast = 0, tnewrd = 0; + while (sample.seq <= sample.final_seq) + { + uint32_t newrd = ddsrt_atomic_and32_ov (&newreaders, 0); + for (uint32_t i = 0; i < 32; i++) + { + if (newrd & (UINT32_C (1) << i)) + { + if (i >= (uint32_t) (sizeof (sample.seq_at_match) / sizeof (sample.seq_at_match[0]))) + oops (); + if (sample.seq_at_match[i] != 0) + oops (); + sample.seq_at_match[i] = sample.seq; + tnewrd = dds_time (); + printf ("%d.%09d newreader %d: start seq %d\n", (int) (tnewrd / DDS_NSECS_IN_SEC), (int) (tnewrd % DDS_NSECS_IN_SEC), (int) i, (int) sample.seq_at_match[i]); + fflush (stdout); + } + } + + if (get_publication_matched_count (wr) || (flag_prewrite && sample.seq <= tlhist + 1)) + { + dds_time_t tnow = dds_time (); + if (tnow - tlast > DDS_MSECS (100) || newrd) + { + if (dds_write (wr, &sample) < 0) + oops (); + sample.seq++; + tlast = tnow; + if (sample.seq > sample.final_seq) + { + tnow = dds_time (); + printf ("%d.%09d done writing\n", (int) (tnow / DDS_NSECS_IN_SEC), (int) (tnow % DDS_NSECS_IN_SEC)); + fflush (stdout); + } + } + } + + dds_sleepfor (DDS_MSECS (1)); + } + + dds_sleepfor (DDS_MSECS (100)); + dds_wait_for_acks (wr, DDS_INFINITY); + dds_delete (ppant); + return 0; +} diff --git a/src/core/xtests/initsampledeliv/runtest b/src/core/xtests/initsampledeliv/runtest new file mode 100644 index 0000000..9ba03b8 --- /dev/null +++ b/src/core/xtests/initsampledeliv/runtest @@ -0,0 +1,46 @@ +#!/bin/bash +# +# Copyright(c) 2019 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# +ok=true +for sd in "" "-d1" "-d12" ; do + for st in "" "-t" ; do + for sT in "" "-T" ; do + if [ "$st" = "-t" -o "$sT" = "-T" ] ; then + maybeV=false + else + maybeV=true + fi + for sw in "" "-w" ; do + for pt in "" "-t" ; do + for pp in "" "-p" ; do + if [ "$sT" = "" -a "$sd" != "" -a \( "$pt" = "-t" -o $maybeV = true \) ] ; then + if $ok ; then + echo "bin/InitSampleDelivSub $sw $sd $st $sT & bin/InitSampleDelivPub $pt $pp" + bin/InitSampleDelivSub $sw $sd $st $sT & spid=$! + bin/InitSampleDelivPub $pt $pp + wait $spid || ok=false + fi + if $ok ; then + echo "bin/InitSampleDelivPub $pt $pp & sleep 2 ; bin/InitSampleDelivSub $sw $sd $st $sT " + bin/InitSampleDelivPub $pt $pp & ppid=$! + sleep 2 + bin/InitSampleDelivSub $sw $sd $st $sT & spid=$! + wait $spid || ok=false + wait + fi + fi + done + done + done + done + done +done diff --git a/src/core/xtests/initsampledeliv/subscriber.c b/src/core/xtests/initsampledeliv/subscriber.c new file mode 100644 index 0000000..1cb6ad6 --- /dev/null +++ b/src/core/xtests/initsampledeliv/subscriber.c @@ -0,0 +1,198 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include "dds/dds.h" +#include "InitSampleDelivData.h" +#include +#include +#include +#include +#include + +static void oops (const char *file, int line) +{ + fflush (stdout); + fprintf (stderr, "%s:%d\n", file, line); + abort (); +} + +#define oops() oops(__FILE__, __LINE__) + +static void wait_for_writer (dds_entity_t ppant) +{ + dds_entity_t rd; + dds_sample_info_t info; + void *raw = NULL; + int32_t n; + if ((rd = dds_create_reader (ppant, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, NULL, NULL)) < 0) + oops (); + bool done = false; + do { + dds_sleepfor (DDS_MSECS (100)); + while ((n = dds_take (rd, &raw, &info, 1, 1)) == 1) + { + const dds_builtintopic_endpoint_t *sample = raw; + if (strcmp (sample->topic_name, "Msg") == 0) + done = true; + dds_return_loan (rd, &raw, n); + } + if (n < 0) oops (); + } while (!done); + dds_delete (rd); +} + +static uint32_t get_subscription_matched_count (dds_entity_t rd) +{ + dds_subscription_matched_status_t status; + if (dds_get_subscription_matched_status (rd, &status) < 0) + oops (); + return status.current_count; +} + +int main (int argc, char ** argv) +{ + dds_entity_t ppant; + dds_entity_t tp; + dds_entity_t rd[2] = { 0, 0 }; + dds_qos_t *qos; + int opt; + bool flag_wait = false; + bool flag_translocal[sizeof (rd) / sizeof (rd[0])] = { false }; + int flag_create_2nd_rd = -1; + + while ((opt = getopt (argc, argv, "d:tTw")) != EOF) + { + switch (opt) + { + case 'd': + flag_create_2nd_rd = atoi (optarg); + break; + case 't': + flag_translocal[0] = true; + break; + case 'T': + flag_translocal[1] = true; + break; + case 'w': + flag_wait = true; + break; + default: + fprintf (stderr, "usage error: see source code\n"); + exit (2); + } + } + + if ((ppant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL)) < 0) + oops (); + + qos = dds_create_qos (); + dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_SECS (10)); + dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); + if ((tp = dds_create_topic (ppant, &Msg_desc, "Msg", qos, NULL)) < 0) + oops (); + + if (flag_wait) + { + printf ("waiting for writer ...\n"); + fflush (stdout); + wait_for_writer (ppant); + printf ("writer seen; giving it some time to discover us and publish data ...\n"); + fflush (stdout); + dds_sleepfor (DDS_SECS (1)); + printf ("continuing ...\n"); + fflush (stdout); + } + + /* Reader has overrides for history, durability */ + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0); + dds_qset_durability (qos, flag_translocal[0] ? DDS_DURABILITY_TRANSIENT_LOCAL : DDS_DURABILITY_VOLATILE); + dds_qset_userdata (qos, "0", 1); + if ((rd[0] = dds_create_reader (ppant, tp, qos, NULL)) < 0) + oops (); + + dds_qset_durability (qos, flag_translocal[1] ? DDS_DURABILITY_TRANSIENT_LOCAL : DDS_DURABILITY_VOLATILE); + dds_qset_userdata (qos, "1", 1); + + int32_t firstmsg[2] = { 0 }; + int32_t prevmsg[2] = { 0 }; + int32_t seqatmatch[2] = { 0 }; + int32_t tldepth = 0; + int32_t endmsg = 0; + while (prevmsg[0] == 0 || get_subscription_matched_count (rd[0]) > 0) + { + void *raw = NULL; + dds_sample_info_t info; + int32_t n; + for (int i = 0; i < 2 && rd[i]; i++) + { + if ((n = dds_take (rd[i], &raw, &info, 1, 1)) < 0) + oops (); + else if (n > 0 && info.valid_data) + { + const Msg *msg = raw; + if (prevmsg[i] == 0) + { + /* have to postpone first seq# check for transient-local data because the limit + t-l history means the first sample we read may have an arbitrary sequence + that antedated the matching */ + printf ("reader %d: first seq %d\n", i, (int) msg->seq); + fflush (stdout); + firstmsg[i] = msg->seq; + } + else if (msg->seq != prevmsg[i] + 1) + { + printf ("reader %d: received %d, previous %d\n", i, (int) msg->seq, (int) prevmsg[i]); + oops (); + } + prevmsg[i] = msg->seq; + endmsg = msg->final_seq; + tldepth = msg->tldepth; + if (seqatmatch[i] == 0) + seqatmatch[i] = msg->seq_at_match[i]; + dds_return_loan (rd[i], &raw, n); + } + } + if (rd[1] == 0 && prevmsg[0] == flag_create_2nd_rd) + { + if ((rd[1] = dds_create_reader (ppant, tp, qos, NULL)) < 0) + oops (); + } + dds_sleepfor (DDS_MSECS (10)); + } + if (tldepth == 0 || endmsg == 0) + oops (); + for (int i = 0; i < 2; i++) + { + if (rd[i] == 0) + continue; + if (prevmsg[i] != endmsg) + oops (); + int32_t refseq; + if (!flag_translocal[i]) + refseq = seqatmatch[i]; + else if (seqatmatch[i] <= tldepth) + refseq = 1; + else + refseq = seqatmatch[i] - tldepth; + if (flag_translocal[i] ? (firstmsg[i] > refseq + 1) : firstmsg[i] > refseq) + { + /* allow the rare cases where an additional sample was received for volatile data + (for t-l data, the publisher waits to give so the subscriber can get the data + in time */ + printf ("reader %d: first seq %d but refseq %d\n", i, (int) firstmsg[i], refseq); + oops (); + } + } + + dds_delete_qos (qos); + dds_delete (ppant); + return 0; +} diff --git a/src/core/xtests/rhc_torture/CMakeLists.txt b/src/core/xtests/rhc_torture/CMakeLists.txt new file mode 100644 index 0000000..4aa3a5f --- /dev/null +++ b/src/core/xtests/rhc_torture/CMakeLists.txt @@ -0,0 +1,26 @@ +# +# Copyright(c) 2019 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# +idlc_generate(RhcTypes RhcTypes.idl) + +add_executable(rhc_torture rhc_torture.c) + +target_include_directories( + rhc_torture PRIVATE + "$" + "$") + +target_link_libraries(rhc_torture RhcTypes ddsc) + +add_test( + NAME rhc_torture + COMMAND rhc_torture 314159265 0 5000 0) +set_property(TEST rhc_torture PROPERTY TIMEOUT 20) diff --git a/src/core/xtests/RhcTypes.idl b/src/core/xtests/rhc_torture/RhcTypes.idl similarity index 100% rename from src/core/xtests/RhcTypes.idl rename to src/core/xtests/rhc_torture/RhcTypes.idl diff --git a/src/core/xtests/rhc_torture.c b/src/core/xtests/rhc_torture/rhc_torture.c similarity index 100% rename from src/core/xtests/rhc_torture.c rename to src/core/xtests/rhc_torture/rhc_torture.c diff --git a/src/mpt/tests/basic/procs/hello.c b/src/mpt/tests/basic/procs/hello.c index 2c68a84..8623ac0 100644 --- a/src/mpt/tests/basic/procs/hello.c +++ b/src/mpt/tests/basic/procs/hello.c @@ -173,13 +173,7 @@ MPT_ProcessEntry(hello_subscriber, printf("--- [Subscriber(%d)] Start(%d) ...\n", id, domainid); - /* - * A reliable volatile sample, written after publication matched, can still - * be lost when the subscriber wasn't able to match its subscription yet. - * Use transient_local reliable to make sure the sample is received. - */ qos = dds_create_qos(); - dds_qset_durability(qos, DDS_DURABILITY_TRANSIENT_LOCAL); dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_SECS(10)); /* Use listener to get data available trigger. */ @@ -206,8 +200,7 @@ MPT_ProcessEntry(hello_subscriber, ddsrt_mutex_lock(&g_mutex); recv_cnt = 0; while (recv_cnt < sample_cnt) { - /* Use a take with mask to work around the #146 issue. */ - rc = dds_take_mask(reader, samples, infos, MAX_SAMPLES, MAX_SAMPLES, DDS_NEW_VIEW_STATE); + rc = dds_take(reader, samples, infos, MAX_SAMPLES, MAX_SAMPLES); MPT_ASSERT_GEQ(rc, 0, "Could not read: %s\n", dds_strretcode(-rc)); /* Check if we read some data and it is valid. */ From 19aec98b8a934ff3796c19c720f7d14b4134d6f0 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 23 May 2019 16:51:43 +0200 Subject: [PATCH 082/178] Clean up return code types * Remove dds_return_t / dds_retcode_t distinction (now there is only dds_return_t and all error codes are always negative) * Remove Q_ERR_... error codes and replace them by DDS_RETCODE_... ones so that there is only one set of error codes * Replace a whole bunch "int" return types that were used to return Q_ERR_... codes by "dds_return_t" return types Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/dds.h | 13 +- .../ddsc/include/dds/ddsc/dds_public_error.h | 8 +- .../ddsc/include/dds/ddsc/dds_public_status.h | 16 +- src/core/ddsc/src/dds__entity.h | 18 +- src/core/ddsc/src/dds__err.h | 28 -- src/core/ddsc/src/dds_builtin.c | 3 +- src/core/ddsc/src/dds_coherent.c | 1 - src/core/ddsc/src/dds_entity.c | 171 ++++----- src/core/ddsc/src/dds_guardcond.c | 21 +- src/core/ddsc/src/dds_handles.c | 3 +- src/core/ddsc/src/dds_init.c | 21 +- src/core/ddsc/src/dds_instance.c | 64 ++-- src/core/ddsc/src/dds_participant.c | 15 +- src/core/ddsc/src/dds_publisher.c | 30 +- src/core/ddsc/src/dds_qos.c | 19 +- src/core/ddsc/src/dds_querycond.c | 7 +- src/core/ddsc/src/dds_read.c | 56 ++- src/core/ddsc/src/dds_readcond.c | 19 +- src/core/ddsc/src/dds_reader.c | 100 ++--- src/core/ddsc/src/dds_rhc.c | 1 - src/core/ddsc/src/dds_subscriber.c | 34 +- src/core/ddsc/src/dds_topic.c | 69 ++-- src/core/ddsc/src/dds_waitset.c | 79 ++-- src/core/ddsc/src/dds_write.c | 49 ++- src/core/ddsc/src/dds_writer.c | 67 ++-- src/core/ddsc/tests/config.c | 2 +- src/core/ddsc/tests/dispose.c | 62 ++- src/core/ddsc/tests/entity_api.c | 112 +++--- src/core/ddsc/tests/entity_hierarchy.c | 95 +++-- src/core/ddsc/tests/entity_status.c | 171 ++++----- src/core/ddsc/tests/instance_get_key.c | 8 +- src/core/ddsc/tests/participant.c | 28 +- src/core/ddsc/tests/publisher.c | 54 ++- src/core/ddsc/tests/qos.c | 4 +- src/core/ddsc/tests/querycondition.c | 22 +- src/core/ddsc/tests/read_instance.c | 44 +-- src/core/ddsc/tests/readcondition.c | 22 +- src/core/ddsc/tests/reader.c | 78 ++-- src/core/ddsc/tests/reader_iterator.c | 36 +- src/core/ddsc/tests/register.c | 9 +- src/core/ddsc/tests/return_loan.c | 18 +- src/core/ddsc/tests/subscriber.c | 6 +- src/core/ddsc/tests/take_instance.c | 44 +-- src/core/ddsc/tests/topic.c | 36 +- src/core/ddsc/tests/types.c | 4 +- src/core/ddsc/tests/unregister.c | 36 +- src/core/ddsc/tests/unsupported.c | 14 +- src/core/ddsc/tests/waitset.c | 67 ++-- src/core/ddsc/tests/write.c | 18 +- src/core/ddsc/tests/writer.c | 12 +- src/core/ddsi/CMakeLists.txt | 1 - src/core/ddsi/include/dds/ddsi/ddsi_tcp.h | 4 +- .../ddsi/include/dds/ddsi/ddsi_threadmon.h | 2 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 104 ++++- src/core/ddsi/include/dds/ddsi/q_error.h | 27 -- src/core/ddsi/include/dds/ddsi/q_plist.h | 74 +++- src/core/ddsi/include/dds/ddsi/q_thread.h | 4 +- src/core/ddsi/include/dds/ddsi/q_transmit.h | 2 +- src/core/ddsi/include/dds/ddsi/q_xevent.h | 2 +- src/core/ddsi/include/dds/ddsi/q_xmsg.h | 4 +- src/core/ddsi/src/ddsi_raweth.c | 7 +- src/core/ddsi/src/ddsi_ssl.c | 4 +- src/core/ddsi/src/ddsi_tcp.c | 32 +- src/core/ddsi/src/ddsi_threadmon.c | 5 +- src/core/ddsi/src/ddsi_udp.c | 12 +- src/core/ddsi/src/q_config.c | 1 - src/core/ddsi/src/q_ddsi_discovery.c | 21 +- src/core/ddsi/src/q_debmon.c | 1 - src/core/ddsi/src/q_entity.c | 69 ++-- src/core/ddsi/src/q_init.c | 1 - src/core/ddsi/src/q_nwif.c | 12 +- src/core/ddsi/src/q_plist.c | 359 +++++++++--------- src/core/ddsi/src/q_receive.c | 5 +- src/core/ddsi/src/q_security.c | 3 +- src/core/ddsi/src/q_sockwaitset.c | 2 +- src/core/ddsi/src/q_thread.c | 12 +- src/core/ddsi/src/q_transmit.c | 26 +- src/core/ddsi/src/q_xevent.c | 7 +- src/core/ddsi/src/q_xmsg.c | 17 +- src/core/ddsi/src/sysdeps.c | 1 - src/ddsrt/CMakeLists.txt | 10 +- src/ddsrt/include/dds/ddsrt/environ.h | 12 +- src/ddsrt/include/dds/ddsrt/ifaddrs.h | 2 +- src/ddsrt/include/dds/ddsrt/process.h | 20 +- src/ddsrt/include/dds/ddsrt/retcode.h | 34 +- src/ddsrt/include/dds/ddsrt/rusage.h | 4 +- src/ddsrt/include/dds/ddsrt/sockets.h | 40 +- src/ddsrt/include/dds/ddsrt/string.h | 4 +- src/ddsrt/include/dds/ddsrt/strtod.h | 8 +- src/ddsrt/include/dds/ddsrt/strtol.h | 16 +- src/ddsrt/include/dds/ddsrt/thread_pool.h | 2 +- src/ddsrt/include/dds/ddsrt/threads.h | 12 +- src/ddsrt/src/environ/posix/environ.c | 6 +- src/ddsrt/src/environ/windows/environ.c | 6 +- src/ddsrt/src/ifaddrs/posix/ifaddrs.c | 8 +- src/ddsrt/src/ifaddrs/windows/ifaddrs.c | 12 +- src/ddsrt/src/process/posix/process.c | 16 +- src/ddsrt/src/process/windows/process.c | 42 +- src/ddsrt/src/retcode.c | 28 +- src/ddsrt/src/rusage/posix/rusage.c | 4 +- src/ddsrt/src/rusage/windows/rusage.c | 2 +- src/ddsrt/src/sockets.c | 6 +- src/ddsrt/src/sockets/posix/gethostname.c | 4 +- src/ddsrt/src/sockets/posix/socket.c | 34 +- src/ddsrt/src/sockets/windows/socket.c | 36 +- src/ddsrt/src/string/posix/strerror.c | 2 +- src/ddsrt/src/strtod.c | 8 +- src/ddsrt/src/strtol.c | 16 +- src/ddsrt/src/thread_pool.c | 8 +- src/ddsrt/src/threads/posix/threads.c | 8 +- src/ddsrt/src/threads/windows/threads.c | 8 +- src/ddsrt/tests/environ.c | 10 +- src/ddsrt/tests/ifaddrs.c | 10 +- src/ddsrt/tests/log.c | 2 +- src/ddsrt/tests/process.c | 20 +- src/ddsrt/tests/select.c | 10 +- src/ddsrt/tests/socket.c | 36 +- src/ddsrt/tests/strtoll.c | 8 +- src/ddsrt/tests/sync.c | 12 +- src/ddsrt/tests/thread.c | 4 +- src/ddsrt/tests/thread_cleanup.c | 2 +- src/examples/throughput/publisher.c | 4 +- src/mpt/mpt/src/main.c.in | 2 +- src/tools/ddsperf/ddsperf.c | 10 +- src/tools/pubsub/common.h | 2 +- src/tools/pubsub/pubsub.c | 2 +- 126 files changed, 1565 insertions(+), 1722 deletions(-) delete mode 100644 src/core/ddsc/src/dds__err.h delete mode 100644 src/core/ddsi/include/dds/ddsi/q_error.h diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index add219b..beff47b 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -26,17 +26,10 @@ #include "dds/export.h" -/* TODO: Move to appropriate location */ -/** - * Return code indicating success (DDS_RETCODE_OK) or failure. If a given - * operation failed the value will be a unique error code and dds_err_nr() must - * be used to extract the DDS_RETCODE_* value. - */ -typedef int32_t dds_return_t; /** * Handle to an entity. A valid entity handle will always have a positive - * integer value. Should the value be negative, the value represents a unique - * error code. dds_err_nr() can be used to extract the DDS_RETCODE_* value. + * integer value. Should the value be negative, it is one of the DDS_RETCODE_* + * error codes. */ typedef int32_t dds_entity_t; @@ -1223,7 +1216,7 @@ dds_create_reader( * @returns a status, 0 on success, TIMEOUT on timeout or a negative value to indicate error. */ /* TODO: Complete list of error codes */ -DDS_EXPORT int +DDS_EXPORT dds_return_t dds_reader_wait_for_historical_data( dds_entity_t reader, dds_duration_t max_wait); diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_error.h b/src/core/ddsc/include/dds/ddsc/dds_public_error.h index b574371..bc73a57 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_error.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_error.h @@ -28,6 +28,8 @@ extern "C" { #endif +/* ** DEPRECATED ** */ + /* Error masks for returned status values */ #define DDS_ERR_NR_MASK 0x000000ff @@ -37,13 +39,13 @@ extern "C" { /* Error code handling functions */ /** Macro to extract error number */ -#define dds_err_nr(e) ((-(e)) & DDS_ERR_NR_MASK) +#define dds_err_nr(e) (e)) /** Macro to extract line number */ -#define dds_err_line(e) (((-(e)) & DDS_ERR_LINE_MASK) >> 8) +#define dds_err_line(e) (0) /** Macro to extract file identifier */ -#define dds_err_file_id(e) (((-(e)) & DDS_ERR_FILE_ID_MASK) >> 22) +#define dds_err_file_id(e) (0) #if defined (__cplusplus) } diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_status.h b/src/core/ddsc/include/dds/ddsc/dds_public_status.h index ce9ae79..40df7d6 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_status.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_status.h @@ -185,7 +185,7 @@ dds_inconsistent_topic_status_t; * @param[out] status The pointer to \ref DCPS_Status_InconsistentTopic to get the status * * @returns 0 - Success - * @returns <0 - Failure (use dds_err_nr() to get error value). + * @returns <0 - Failure * * @retval DDS_RETCODE_ERROR * An internal error has occurred. @@ -212,7 +212,7 @@ dds_get_inconsistent_topic_status ( * @param[out] status The pointer to \ref DCPS_Status_PublicationMatched to get the status * * @returns 0 - Success - * @returns <0 - Failure (use dds_err_nr() to get error value). + * @returns <0 - Failure * * @retval DDS_RETCODE_ERROR * An internal error has occurred. @@ -239,7 +239,7 @@ dds_get_publication_matched_status ( * @param[out] status The pointer to \ref DCPS_Status_LivelinessLost to get the status * * @returns 0 - Success - * @returns <0 - Failure (use dds_err_nr() to get error value). + * @returns <0 - Failure * * @retval DDS_RETCODE_ERROR * An internal error has occurred. @@ -266,7 +266,7 @@ dds_get_liveliness_lost_status ( * @param[out] status The pointer to \ref DCPS_Status_OfferedDeadlineMissed to get the status * * @returns 0 - Success - * @returns <0 - Failure (use dds_err_nr() to get error value). + * @returns <0 - Failure * * @retval DDS_RETCODE_ERROR * An internal error has occurred. @@ -293,7 +293,7 @@ dds_get_offered_deadline_missed_status( * @param[out] status The pointer to \ref DCPS_Status_OfferedIncompatibleQoS to get the status * * @returns 0 - Success - * @returns <0 - Failure (use dds_err_nr() to get error value). + * @returns <0 - Failure * * @retval DDS_RETCODE_ERROR * An internal error has occurred. @@ -320,7 +320,7 @@ dds_get_offered_incompatible_qos_status ( * @param[out] status The pointer to \ref DCPS_Status_SubscriptionMatched to get the status * * @returns 0 - Success - * @returns <0 - Failure (use dds_err_nr() to get error value). + * @returns <0 - Failure * * @retval DDS_RETCODE_ERROR * An internal error has occurred. @@ -347,7 +347,7 @@ dds_get_subscription_matched_status ( * @param[out] status The pointer to \ref DCPS_Status_LivelinessChanged to get the status * * @returns 0 - Success - * @returns <0 - Failure (use dds_err_nr() to get error value). + * @returns <0 - Failure * * @retval DDS_RETCODE_ERROR * An internal error has occurred. @@ -374,7 +374,7 @@ dds_get_liveliness_changed_status ( * @param[out] status The pointer to \ref DCPS_Status_SampleRejected to get the status * * @returns 0 - Success - * @returns <0 - Failure (use dds_err_nr() to get error value). + * @returns <0 - Failure * * @retval DDS_RETCODE_ERROR * An internal error has occurred. diff --git a/src/core/ddsc/src/dds__entity.h b/src/core/ddsc/src/dds__entity.h index 34c13c5..f74b03e 100644 --- a/src/core/ddsc/src/dds__entity.h +++ b/src/core/ddsc/src/dds__entity.h @@ -35,9 +35,9 @@ DDS_EXPORT void dds_entity_add_ref_nolock(dds_entity *e); #define DEFINE_ENTITY_LOCK_UNLOCK(qualifier_, type_, kind_) \ - qualifier_ dds_retcode_t type_##_lock (dds_entity_t hdl, type_ **x) \ + qualifier_ dds_return_t type_##_lock (dds_entity_t hdl, type_ **x) \ { \ - dds_retcode_t rc; \ + dds_return_t rc; \ dds_entity *e; \ if ((rc = dds_entity_lock (hdl, kind_, &e)) != DDS_RETCODE_OK) \ return rc; \ @@ -50,7 +50,7 @@ dds_entity_add_ref_nolock(dds_entity *e); dds_entity_unlock (&x->m_entity); \ } #define DECL_ENTITY_LOCK_UNLOCK(qualifier_, type_) \ - qualifier_ dds_retcode_t type_##_lock (dds_entity_t hdl, type_ **x); \ + qualifier_ dds_return_t type_##_lock (dds_entity_t hdl, type_ **x); \ qualifier_ void type_##_unlock (type_ *x); DDS_EXPORT inline dds_entity *dds_entity_from_handle_link (struct dds_handle_link *hdllink) { @@ -79,7 +79,7 @@ DDS_EXPORT void dds_entity_status_signal (dds_entity *e); DDS_EXPORT void dds_entity_invoke_listener (const dds_entity *entity, enum dds_status_id which, const void *vst); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t dds_entity_claim ( dds_entity_t hdl, dds_entity **eptr); @@ -87,7 +87,7 @@ dds_entity_claim ( DDS_EXPORT void dds_entity_release ( dds_entity *e); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t dds_entity_lock( dds_entity_t hdl, dds_entity_kind_t kind, @@ -96,24 +96,24 @@ dds_entity_lock( DDS_EXPORT void dds_entity_unlock(dds_entity *e); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t dds_entity_observer_register_nl( dds_entity *observed, dds_entity_t observer, dds_entity_callback cb); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t dds_entity_observer_register( dds_entity_t observed, dds_entity_t observer, dds_entity_callback cb); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t dds_entity_observer_unregister_nl( dds_entity *observed, dds_entity_t observer); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t dds_entity_observer_unregister( dds_entity_t observed, dds_entity_t observer); diff --git a/src/core/ddsc/src/dds__err.h b/src/core/ddsc/src/dds__err.h deleted file mode 100644 index a54be27..0000000 --- a/src/core/ddsc/src/dds__err.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef _DDS_ERR_H_ -#define _DDS_ERR_H_ - -#include - -#include "dds/ddsrt/retcode.h" - -#if defined (__cplusplus) -extern "C" { -#endif - -#define DDS_ERRNO(err) (assert(err > DDS_RETCODE_OK), -(err)) - -#if defined (__cplusplus) -} -#endif -#endif diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index fff187a..01c98e5 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -18,7 +18,6 @@ #include "dds__qos.h" #include "dds__domain.h" #include "dds__participant.h" -#include "dds__err.h" #include "dds__types.h" #include "dds__builtin.h" #include "dds__subscriber.h" @@ -93,7 +92,7 @@ dds_entity_t dds__get_builtin_topic (dds_entity_t e, dds_entity_t topic) sertopic = builtin_reader_topic; } else { assert (0); - return DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; } dds_qos_t *qos = dds__create_builtin_qos (); diff --git a/src/core/ddsc/src/dds_coherent.c b/src/core/ddsc/src/dds_coherent.c index 6123a47..f2f1063 100644 --- a/src/core/ddsc/src/dds_coherent.c +++ b/src/core/ddsc/src/dds_coherent.c @@ -15,7 +15,6 @@ #include "dds__entity.h" #include "dds__subscriber.h" #include "dds__publisher.h" -#include "dds__err.h" dds_return_t dds_begin_coherent( diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index 7d62349..176a7eb 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -19,7 +19,6 @@ #include "dds__writer.h" #include "dds__reader.h" #include "dds__listener.h" -#include "dds__err.h" #include "dds/version.h" extern inline dds_entity *dds_entity_from_handle_link (struct dds_handle_link *hdllink); @@ -51,7 +50,7 @@ dds_domain *dds__entity_domain (dds_entity *e) static void dds_set_explicit (dds_entity_t entity) { dds_entity *e; - dds_retcode_t rc; + dds_return_t rc; if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) == DDS_RETCODE_OK) { e->m_flags &= ~DDS_ENTITY_IMPLICIT; @@ -142,13 +141,13 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) dds_entity *prev = NULL; dds_entity *next = NULL; dds_return_t ret; - dds_retcode_t rc; + dds_return_t rc; rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e); if (rc != DDS_RETCODE_OK) { DDS_TRACE ("dds_delete_impl: error on locking entity %"PRIu32" keep_if_explicit %d\n", entity, (int) keep_if_explicit); - return DDS_ERRNO (rc); + return rc; } if (keep_if_explicit == true && (e->m_flags & DDS_ENTITY_IMPLICIT) == 0) @@ -275,9 +274,9 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) dds_entity_t dds_get_parent (dds_entity_t entity) { dds_entity *e; - dds_retcode_t rc; + dds_return_t rc; if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + return rc; else { dds_entity *parent; @@ -297,9 +296,9 @@ dds_entity_t dds_get_parent (dds_entity_t entity) dds_entity_t dds_get_participant (dds_entity_t entity) { dds_entity *e; - dds_retcode_t rc; + dds_return_t rc; if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + return rc; else { dds_entity_t hdl = e->m_participant->m_hdllink.hdl; @@ -311,15 +310,15 @@ dds_entity_t dds_get_participant (dds_entity_t entity) dds_return_t dds_get_children (dds_entity_t entity, dds_entity_t *children, size_t size) { dds_entity *e; - dds_retcode_t rc; + dds_return_t rc; if (children != NULL && (size <= 0 || size >= INT32_MAX)) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; if (children == NULL && size != 0) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + return rc; else { dds_return_t n = 0; @@ -342,17 +341,16 @@ dds_return_t dds_get_children (dds_entity_t entity, dds_entity_t *children, size dds_return_t dds_get_qos (dds_entity_t entity, dds_qos_t *qos) { dds_entity *e; - dds_retcode_t rc; dds_return_t ret; if (qos == NULL) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; - if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return ret; if (e->m_deriver.set_qos == 0) - ret = DDS_ERRNO(DDS_RETCODE_ILLEGAL_OPERATION); + ret = DDS_RETCODE_ILLEGAL_OPERATION; else { dds_reset_qos (qos); @@ -365,25 +363,23 @@ dds_return_t dds_get_qos (dds_entity_t entity, dds_qos_t *qos) dds_return_t dds_set_qos (dds_entity_t entity, const dds_qos_t *qos) { dds_entity *e; - dds_retcode_t rc; dds_return_t ret; if (qos == NULL) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; - if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return ret; if (e->m_deriver.set_qos == 0) - ret = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + ret = DDS_RETCODE_ILLEGAL_OPERATION; else { if ((ret = e->m_deriver.set_qos (e, qos, e->m_flags & DDS_ENTITY_ENABLED)) == DDS_RETCODE_OK) { if (e->m_qos == NULL) e->m_qos = dds_create_qos (); - rc = dds_copy_qos (e->m_qos, qos); - ret = DDS_ERRNO (rc); + ret = dds_copy_qos (e->m_qos, qos); } } dds_entity_unlock (e); @@ -393,24 +389,19 @@ dds_return_t dds_set_qos (dds_entity_t entity, const dds_qos_t *qos) dds_return_t dds_get_listener (dds_entity_t entity, dds_listener_t *listener) { dds_entity *e; - dds_return_t ret = DDS_RETCODE_OK; - dds_retcode_t rc; - - if (listener != NULL) { - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc == DDS_RETCODE_OK) { - ddsrt_mutex_lock (&e->m_observers_lock); - dds_copy_listener (listener, &e->m_listener); - ddsrt_mutex_unlock (&e->m_observers_lock); - dds_entity_unlock(e); - } else { - ret = DDS_ERRNO(rc); - } - } else { - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + dds_return_t ret; + if (listener == NULL) + return DDS_RETCODE_BAD_PARAMETER; + else if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return ret; + else + { + ddsrt_mutex_lock (&e->m_observers_lock); + dds_copy_listener (listener, &e->m_listener); + ddsrt_mutex_unlock (&e->m_observers_lock); + dds_entity_unlock(e); + return DDS_RETCODE_OK; } - - return ret; } void dds_entity_invoke_listener (const dds_entity *entity, enum dds_status_id which, const void *vst) @@ -548,10 +539,10 @@ static void pushdown_listener (dds_entity_t entity) dds_return_t dds_set_listener (dds_entity_t entity, const dds_listener_t *listener) { dds_entity *e, *x; - dds_retcode_t rc; + dds_return_t rc; if ((rc = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + return rc; ddsrt_mutex_lock (&e->m_observers_lock); while (e->m_cb_count > 0) @@ -579,10 +570,10 @@ dds_return_t dds_set_listener (dds_entity_t entity, const dds_listener_t *listen dds_return_t dds_enable (dds_entity_t entity) { dds_entity *e; - dds_retcode_t rc; + dds_return_t rc; if ((rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + return rc; if ((e->m_flags & DDS_ENTITY_ENABLED) == 0) { @@ -597,17 +588,16 @@ dds_return_t dds_enable (dds_entity_t entity) dds_return_t dds_get_status_changes (dds_entity_t entity, uint32_t *status) { dds_entity *e; - dds_retcode_t rc; dds_return_t ret; if (status == NULL) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; - if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return ret; if (e->m_deriver.validate_status == 0) - ret = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + ret = DDS_RETCODE_ILLEGAL_OPERATION; else { ddsrt_mutex_lock (&e->m_observers_lock); @@ -622,17 +612,16 @@ dds_return_t dds_get_status_changes (dds_entity_t entity, uint32_t *status) dds_return_t dds_get_status_mask (dds_entity_t entity, uint32_t *mask) { dds_entity *e; - dds_retcode_t rc; dds_return_t ret; if (mask == NULL) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; - if ((rc = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + if ((ret = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) + return ret; if (e->m_deriver.validate_status == 0) - ret = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + ret = DDS_RETCODE_ILLEGAL_OPERATION; else { ddsrt_mutex_lock (&e->m_observers_lock); @@ -652,14 +641,13 @@ dds_return_t dds_get_enabled_status (dds_entity_t entity, uint32_t *status) dds_return_t dds_set_status_mask (dds_entity_t entity, uint32_t mask) { dds_entity *e; - dds_retcode_t rc; dds_return_t ret; - if ((rc = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + if ((ret = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) + return ret; if (e->m_deriver.validate_status == 0) - ret = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + ret = DDS_RETCODE_ILLEGAL_OPERATION; else if ((ret = e->m_deriver.validate_status (mask)) == DDS_RETCODE_OK) { ddsrt_mutex_lock (&e->m_observers_lock); @@ -684,17 +672,16 @@ dds_return_t dds_set_enabled_status(dds_entity_t entity, uint32_t mask) static dds_return_t dds_readtake_status (dds_entity_t entity, uint32_t *status, uint32_t mask, bool reset) { dds_entity *e; - dds_retcode_t rc; dds_return_t ret; if (status == NULL) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; - if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return ret; if (e->m_deriver.validate_status == 0) - ret = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + ret = DDS_RETCODE_ILLEGAL_OPERATION; else if ((ret = e->m_deriver.validate_status (mask)) == DDS_RETCODE_OK) { ddsrt_mutex_lock (&e->m_observers_lock); @@ -721,13 +708,13 @@ dds_return_t dds_take_status (dds_entity_t entity, uint32_t *status, uint32_t ma dds_return_t dds_get_domainid (dds_entity_t entity, dds_domainid_t *id) { dds_entity *e; - dds_retcode_t rc; + dds_return_t rc; if (id == NULL) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + return rc; *id = e->m_domainid; dds_entity_unlock(e); @@ -737,26 +724,25 @@ dds_return_t dds_get_domainid (dds_entity_t entity, dds_domainid_t *id) dds_return_t dds_get_instance_handle (dds_entity_t entity, dds_instance_handle_t *ihdl) { dds_entity *e; - dds_retcode_t rc; dds_return_t ret; if (ihdl == NULL) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; - if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return ret; if (e->m_deriver.get_instance_hdl) ret = e->m_deriver.get_instance_hdl (e, ihdl); else - ret = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + ret = DDS_RETCODE_ILLEGAL_OPERATION; dds_entity_unlock(e); return ret; } -dds_retcode_t dds_entity_claim (dds_entity_t hdl, dds_entity **eptr) +dds_return_t dds_entity_claim (dds_entity_t hdl, dds_entity **eptr) { - dds_retcode_t hres; + dds_return_t hres; struct dds_handle_link *hdllink; if ((hres = dds_handle_claim (hdl, &hdllink)) != DDS_RETCODE_OK) return hres; @@ -772,9 +758,9 @@ void dds_entity_release (dds_entity *e) dds_handle_release (&e->m_hdllink); } -dds_retcode_t dds_entity_lock (dds_entity_t hdl, dds_entity_kind_t kind, dds_entity **eptr) +dds_return_t dds_entity_lock (dds_entity_t hdl, dds_entity_kind_t kind, dds_entity **eptr) { - dds_retcode_t hres; + dds_return_t hres; dds_entity *e; /* When the given handle already contains an error, then return that @@ -817,10 +803,9 @@ dds_return_t dds_triggered (dds_entity_t entity) { dds_entity *e; dds_return_t ret; - dds_retcode_t rc; - if ((rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + if ((ret = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + return ret; ddsrt_mutex_lock (&e->m_observers_lock); ret = (e->m_trigger != 0); ddsrt_mutex_unlock (&e->m_observers_lock); @@ -837,9 +822,9 @@ static bool in_observer_list_p (const struct dds_entity *observed, const dds_ent return false; } -dds_retcode_t dds_entity_observer_register_nl (dds_entity *observed, dds_entity_t observer, dds_entity_callback cb) +dds_return_t dds_entity_observer_register_nl (dds_entity *observed, dds_entity_t observer, dds_entity_callback cb) { - dds_retcode_t rc; + dds_return_t rc; assert (observed); ddsrt_mutex_lock (&observed->m_observers_lock); if (in_observer_list_p (observed, observer)) @@ -857,9 +842,9 @@ dds_retcode_t dds_entity_observer_register_nl (dds_entity *observed, dds_entity_ return rc; } -dds_retcode_t dds_entity_observer_register (dds_entity_t observed, dds_entity_t observer, dds_entity_callback cb) +dds_return_t dds_entity_observer_register (dds_entity_t observed, dds_entity_t observer, dds_entity_callback cb) { - dds_retcode_t rc; + dds_return_t rc; dds_entity *e; assert (cb); if ((rc = dds_entity_lock (observed, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) @@ -869,9 +854,9 @@ dds_retcode_t dds_entity_observer_register (dds_entity_t observed, dds_entity_t return rc; } -dds_retcode_t dds_entity_observer_unregister_nl (dds_entity *observed, dds_entity_t observer) +dds_return_t dds_entity_observer_unregister_nl (dds_entity *observed, dds_entity_t observer) { - dds_retcode_t rc; + dds_return_t rc; dds_entity_observer *prev, *idx; ddsrt_mutex_lock (&observed->m_observers_lock); @@ -897,9 +882,9 @@ dds_retcode_t dds_entity_observer_unregister_nl (dds_entity *observed, dds_entit return rc; } -dds_retcode_t dds_entity_observer_unregister (dds_entity_t observed, dds_entity_t observer) +dds_return_t dds_entity_observer_unregister (dds_entity_t observed, dds_entity_t observer) { - dds_retcode_t rc; + dds_return_t rc; dds_entity *e; if ((rc = dds_entity_lock (observed, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) return rc; @@ -947,12 +932,12 @@ void dds_entity_status_set (dds_entity *e, uint32_t t) dds_entity_t dds_get_topic (dds_entity_t entity) { - dds_retcode_t rc; + dds_return_t rc; dds_entity_t hdl; dds_entity *e; if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + return rc; switch (dds_entity_kind (e)) { case DDS_KIND_READER: { @@ -973,7 +958,7 @@ dds_entity_t dds_get_topic (dds_entity_t entity) break; } default: { - hdl = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + hdl = DDS_RETCODE_ILLEGAL_OPERATION; break; } } @@ -984,9 +969,9 @@ dds_entity_t dds_get_topic (dds_entity_t entity) dds_return_t dds_generic_unimplemented_operation_manykinds (dds_entity_t handle, size_t nkinds, const dds_entity_kind_t *kinds) { dds_entity *e; - dds_retcode_t ret; + dds_return_t ret; if ((ret = dds_entity_claim (handle, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (ret); + return ret; else { const dds_entity_kind_t actual = dds_entity_kind (e); @@ -1001,7 +986,7 @@ dds_return_t dds_generic_unimplemented_operation_manykinds (dds_entity_t handle, } } dds_entity_release (e); - return DDS_ERRNO (ret); + return ret; } } diff --git a/src/core/ddsc/src/dds_guardcond.c b/src/core/ddsc/src/dds_guardcond.c index c4feee0..9b3b0ca 100644 --- a/src/core/ddsc/src/dds_guardcond.c +++ b/src/core/ddsc/src/dds_guardcond.c @@ -14,7 +14,6 @@ #include "dds__reader.h" #include "dds__guardcond.h" #include "dds__participant.h" -#include "dds__err.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" @@ -24,10 +23,10 @@ DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_guardcond) dds_entity_t dds_create_guardcondition (dds_entity_t participant) { dds_participant *pp; - dds_retcode_t rc; + dds_return_t rc; if ((rc = dds_participant_lock (participant, &pp)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + return rc; else { dds_guardcond * gcond = dds_alloc (sizeof (*gcond)); @@ -40,10 +39,10 @@ dds_entity_t dds_create_guardcondition (dds_entity_t participant) dds_return_t dds_set_guardcondition (dds_entity_t condition, bool triggered) { dds_guardcond *gcond; - dds_retcode_t rc; + dds_return_t rc; if ((rc = dds_guardcond_lock (condition, &gcond)) != DDS_RETCODE_OK) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return rc; else { ddsrt_mutex_lock (&gcond->m_entity.m_observers_lock); @@ -60,14 +59,14 @@ dds_return_t dds_set_guardcondition (dds_entity_t condition, bool triggered) dds_return_t dds_read_guardcondition (dds_entity_t condition, bool *triggered) { dds_guardcond *gcond; - dds_retcode_t rc; + dds_return_t rc; if (triggered == NULL) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; *triggered = false; if ((rc = dds_guardcond_lock (condition, &gcond)) != DDS_RETCODE_OK) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return rc; else { ddsrt_mutex_lock (&gcond->m_entity.m_observers_lock); @@ -81,14 +80,14 @@ dds_return_t dds_read_guardcondition (dds_entity_t condition, bool *triggered) dds_return_t dds_take_guardcondition (dds_entity_t condition, bool *triggered) { dds_guardcond *gcond; - dds_retcode_t rc; + dds_return_t rc; if (triggered == NULL) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; *triggered = false; if ((rc = dds_guardcond_lock (condition, &gcond)) != DDS_RETCODE_OK) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return rc; else { ddsrt_mutex_lock (&gcond->m_entity.m_observers_lock); diff --git a/src/core/ddsc/src/dds_handles.c b/src/core/ddsc/src/dds_handles.c index dd509dd..eff8005 100644 --- a/src/core/ddsc/src/dds_handles.c +++ b/src/core/ddsc/src/dds_handles.c @@ -19,7 +19,6 @@ #include "dds/ddsi/q_thread.h" #include "dds__handles.h" #include "dds__types.h" -#include "dds__err.h" /* FIXME: this code isn't really correct when USE_CHH is set: - the DDS entity code doesn't really play by the awake/asleep mechanism @@ -128,7 +127,7 @@ dds_handle_t dds_handle_create (struct dds_handle_link *link) if (handles.count == MAX_HANDLES) { ddsrt_mutex_unlock (&handles.lock); - ret = DDS_ERRNO (DDS_RETCODE_OUT_OF_RESOURCES); + ret = DDS_RETCODE_OUT_OF_RESOURCES; } else { diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 9db9187..ce068eb 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -20,7 +20,6 @@ #include "dds__init.h" #include "dds__rhc.h" #include "dds__domain.h" -#include "dds__err.h" #include "dds__builtin.h" #include "dds__whc_builtintopic.h" #include "dds/ddsi/ddsi_iid.h" @@ -87,7 +86,7 @@ dds_init(dds_domainid_t domain) if (dds_cfgst == NULL) { DDS_LOG(DDS_LC_CONFIG, "Failed to parse configuration XML file %s\n", uri); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; goto fail_config; } @@ -97,7 +96,7 @@ dds_init(dds_domainid_t domain) if (domain < 0 || domain > 230) { DDS_ERROR("requested domain id %"PRId32" is out of range\n", domain); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; goto fail_config_domainid; } else if (config.domainId.isdefault) @@ -107,7 +106,7 @@ dds_init(dds_domainid_t domain) else if (domain != config.domainId.value) { DDS_ERROR("requested domain id %"PRId32" is inconsistent with configured value %"PRId32"\n", domain, config.domainId.value); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; goto fail_config_domainid; } } @@ -119,7 +118,7 @@ dds_init(dds_domainid_t domain) if (rtps_config_prep(dds_cfgst) != 0) { DDS_LOG(DDS_LC_CONFIG, "Failed to configure RTPS\n"); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; goto fail_rtps_config; } @@ -135,7 +134,7 @@ dds_init(dds_domainid_t domain) if (gv.threadmon == NULL) { DDS_ERROR("Failed to create a thread monitor\n"); - ret = DDS_ERRNO(DDS_RETCODE_OUT_OF_RESOURCES); + ret = DDS_RETCODE_OUT_OF_RESOURCES; goto fail_threadmon_new; } } @@ -143,14 +142,14 @@ dds_init(dds_domainid_t domain) if (rtps_init () < 0) { DDS_LOG(DDS_LC_CONFIG, "Failed to initialize RTPS\n"); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; goto fail_rtps_init; } if (dds_handle_server_init (free_via_gc) != DDS_RETCODE_OK) { DDS_ERROR("Failed to initialize internal handle server\n"); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; goto fail_handleserver; } @@ -159,14 +158,14 @@ dds_init(dds_domainid_t domain) if (rtps_start () < 0) { DDS_LOG(DDS_LC_CONFIG, "Failed to start RTPS\n"); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; goto fail_rtps_start; } if (gv.threadmon && ddsi_threadmon_start(gv.threadmon) < 0) { DDS_ERROR("Failed to start the servicelease\n"); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; goto fail_threadmon_start; } @@ -299,7 +298,7 @@ dds__check_domain( { DDS_ERROR("Inconsistent domain configuration detected: domain on " "configuration: %"PRId32", domain %"PRId32"\n", dds_global.m_default_domain, domain); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; } } return ret; diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index 7b8b93e..cef2032 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -17,7 +17,6 @@ #include "dds__write.h" #include "dds__writer.h" #include "dds__rhc.h" -#include "dds__err.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/q_entity.h" @@ -104,7 +103,7 @@ static const dds_topic *dds_instance_info (dds_entity *e) static const dds_topic * dds_instance_info_by_hdl (dds_entity_t e) { const dds_topic * topic = NULL; - dds_retcode_t rc; + dds_return_t rc; dds_entity *w_or_r; rc = dds_entity_lock(e, DDS_KIND_WRITER, &w_or_r); @@ -131,19 +130,15 @@ dds_register_instance( struct ddsi_tkmap_instance * inst; dds_writer *wr; dds_return_t ret; - dds_retcode_t rc; if(data == NULL){ - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - goto err; + return DDS_RETCODE_BAD_PARAMETER; } if(handle == NULL){ - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - goto err; + return DDS_RETCODE_BAD_PARAMETER; } - rc = dds_writer_lock(writer, &wr); - if (rc != DDS_RETCODE_OK) { - ret = DDS_ERRNO(rc); + ret = dds_writer_lock(writer, &wr); + if (ret != DDS_RETCODE_OK) { goto err; } thread_state_awake (ts1); @@ -152,7 +147,7 @@ dds_register_instance( *handle = inst->m_iid; ret = DDS_RETCODE_OK; } else { - ret = DDS_ERRNO(DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; } thread_state_asleep (ts1); dds_writer_unlock(wr); @@ -184,22 +179,20 @@ dds_unregister_instance_ts( { struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; - dds_retcode_t rc; bool autodispose = true; dds_write_action action = DDS_WR_ACTION_UNREGISTER; dds_writer *wr; if (data == NULL){ - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto err; } if(timestamp < 0){ - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto err; } - rc = dds_writer_lock(writer, &wr); - if (rc != DDS_RETCODE_OK) { - ret = DDS_ERRNO(rc); + ret = dds_writer_lock(writer, &wr); + if (ret != DDS_RETCODE_OK) { goto err; } @@ -226,15 +219,13 @@ dds_unregister_instance_ih_ts( { struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; - dds_retcode_t rc; bool autodispose = true; dds_write_action action = DDS_WR_ACTION_UNREGISTER; dds_writer *wr; struct ddsi_tkmap_instance *tk; - rc = dds_writer_lock(writer, &wr); - if (rc != DDS_RETCODE_OK) { - ret = DDS_ERRNO(rc); + ret = dds_writer_lock(writer, &wr); + if (ret != DDS_RETCODE_OK) { goto err; } @@ -255,7 +246,7 @@ dds_unregister_instance_ih_ts( ret = dds_write_impl (wr, sample, timestamp, action); ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL); } else { - ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); + ret = DDS_RETCODE_PRECONDITION_NOT_MET; } thread_state_asleep (ts1); dds_writer_unlock(wr); @@ -271,11 +262,10 @@ dds_writedispose_ts( { struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret; - dds_retcode_t rc; dds_writer *wr; - rc = dds_writer_lock(writer, &wr); - if (rc == DDS_RETCODE_OK) { + ret = dds_writer_lock(writer, &wr); + if (ret == DDS_RETCODE_OK) { thread_state_awake (ts1); ret = dds_write_impl (wr, data, timestamp, DDS_WR_ACTION_WRITE_DISPOSE); if (ret == DDS_RETCODE_OK) { @@ -283,8 +273,6 @@ dds_writedispose_ts( } thread_state_asleep (ts1); dds_writer_unlock(wr); - } else { - ret = DDS_ERRNO(rc); } return ret; @@ -315,17 +303,14 @@ dds_dispose_ts( { struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret; - dds_retcode_t rc; dds_writer *wr; - rc = dds_writer_lock(writer, &wr); - if (rc == DDS_RETCODE_OK) { + ret = dds_writer_lock(writer, &wr); + if (ret == DDS_RETCODE_OK) { thread_state_awake (ts1); ret = dds_dispose_impl(wr, data, DDS_HANDLE_NIL, timestamp); thread_state_asleep (ts1); dds_writer_unlock(wr); - } else { - ret = DDS_ERRNO(rc); } return ret; @@ -339,11 +324,10 @@ dds_dispose_ih_ts( { struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret; - dds_retcode_t rc; dds_writer *wr; - rc = dds_writer_lock(writer, &wr); - if (rc == DDS_RETCODE_OK) { + ret = dds_writer_lock(writer, &wr); + if (ret == DDS_RETCODE_OK) { struct ddsi_tkmap_instance *tk; thread_state_awake (ts1); if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle)) != NULL) { @@ -354,12 +338,10 @@ dds_dispose_ih_ts( ret = dds_dispose_impl (wr, sample, handle, timestamp); ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL); } else { - ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); + ret = DDS_RETCODE_PRECONDITION_NOT_MET; } thread_state_asleep (ts1); dds_writer_unlock(wr); - } else { - ret = DDS_ERRNO(rc); } return ret; @@ -412,13 +394,13 @@ dds_instance_get_key( struct ddsi_tkmap_instance * tk; if(data == NULL){ - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto err; } topic = dds_instance_info_by_hdl (entity); if(topic == NULL){ - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto err; } thread_state_awake (ts1); @@ -428,7 +410,7 @@ dds_instance_get_key( ddsi_tkmap_instance_unref (tk); ret = DDS_RETCODE_OK; } else { - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; } thread_state_asleep (ts1); err: diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index a0c3c03..30f1330 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -19,7 +19,6 @@ #include "dds__qos.h" #include "dds__domain.h" #include "dds__participant.h" -#include "dds__err.h" #include "dds__builtin.h" DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_participant) @@ -37,7 +36,7 @@ dds_participant_status_validate( dds_return_t ret = DDS_RETCODE_OK; if (mask & ~(DDS_PARTICIPANT_STATUS_MASK)) { - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; } return ret; @@ -106,11 +105,11 @@ dds_participant_qos_validate( /* Check consistency. */ if ((qos->present & QP_USER_DATA) && !validate_octetseq(&qos->user_data)) { DDS_ERROR("User data QoS policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)) { DDS_ERROR("Prismtech entity factory QoS policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } return ret; } @@ -128,7 +127,7 @@ dds_participant_qos_set( if (enabled) { /* TODO: CHAM-95: DDSI does not support changing QoS policies. */ DDS_ERROR("Changing the participant QoS is not supported\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); + ret = DDS_RETCODE_UNSUPPORTED; } } return ret; @@ -188,7 +187,7 @@ dds_create_participant( nn_plist_fini (&plist); if (q_rc != 0) { DDS_ERROR("Internal error"); - e = DDS_ERRNO(DDS_RETCODE_ERROR); + e = DDS_RETCODE_ERROR; goto fail_new_participant; } @@ -241,12 +240,12 @@ dds_lookup_participant( if ((participants != NULL) && ((size <= 0) || (size >= INT32_MAX))) { DDS_ERROR("Array is given, but with invalid size\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto err; } if ((participants == NULL) && (size != 0)) { DDS_ERROR("Size is given, but no array\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto err; } diff --git a/src/core/ddsc/src/dds_publisher.c b/src/core/ddsc/src/dds_publisher.c index 47365c7..39ffc85 100644 --- a/src/core/ddsc/src/dds_publisher.c +++ b/src/core/ddsc/src/dds_publisher.c @@ -15,7 +15,6 @@ #include "dds__listener.h" #include "dds__publisher.h" #include "dds__qos.h" -#include "dds__err.h" #include "dds/ddsi/q_entity.h" #include "dds/version.h" @@ -32,7 +31,7 @@ dds_publisher_instance_hdl( (void)i; /* TODO: Get/generate proper handle. */ DDS_ERROR("Getting publisher instance handle is not supported\n"); - return DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); + return DDS_RETCODE_UNSUPPORTED; } static dds_return_t @@ -46,24 +45,24 @@ dds_publisher_qos_validate( /* Check consistency. */ if((qos->present & QP_GROUP_DATA) && !validate_octetseq(&qos->group_data)){ DDS_ERROR("Group data policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if((qos->present & QP_PRESENTATION) && (validate_presentation_qospolicy(&qos->presentation) != 0)){ DDS_ERROR("Presentation policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if((qos->present & QP_PARTITION) && !validate_stringseq(&qos->partition)){ DDS_ERROR("Partition policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)){ DDS_ERROR("Prismtech entity factory policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if(ret == DDS_RETCODE_OK && enabled && (qos->present & QP_PRESENTATION)){ /* TODO: Improve/check immutable check. */ DDS_ERROR("Presentation policy is immutable\n"); - ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY); + ret = DDS_RETCODE_IMMUTABLE_POLICY; } return ret; } @@ -80,7 +79,7 @@ dds_publisher_qos_set( if (enabled) { /* TODO: CHAM-95: DDSI does not support changing QoS policies. */ DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies yet\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); + ret = DDS_RETCODE_UNSUPPORTED; } } return ret; @@ -92,7 +91,7 @@ static dds_return_t dds_publisher_status_validate (uint32_t mask) if (mask & ~(DDS_PUBLISHER_STATUS_MASK)) { DDS_ERROR("Invalid status mask\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; } return ret; @@ -109,12 +108,11 @@ dds_create_publisher( dds_entity_t hdl; dds_qos_t * new_qos = NULL; dds_return_t ret; - dds_retcode_t rc; - rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); - if (rc != DDS_RETCODE_OK) { + ret = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking participant\n"); - hdl = DDS_ERRNO(rc); + hdl = ret; goto lock_err; } @@ -164,7 +162,7 @@ dds_wait_for_acks( dds_duration_t timeout) { if (timeout < 0) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + 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); } @@ -176,7 +174,7 @@ dds_publisher_begin_coherent( /* TODO: CHAM-124 Currently unsupported. */ (void)e; DDS_ERROR("Using coherency to get a coherent data set is not being supported yet\n"); - return DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); + return DDS_RETCODE_UNSUPPORTED; } dds_return_t @@ -186,6 +184,6 @@ dds_publisher_end_coherent( /* TODO: CHAM-124 Currently unsupported. */ (void)e; DDS_ERROR("Using coherency to get a coherent data set is not being supported yet\n"); - return DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); + return DDS_RETCODE_UNSUPPORTED; } diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index b53d046..24584be 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -12,7 +12,6 @@ #include #include #include "dds__qos.h" -#include "dds__err.h" #include "dds/ddsi/q_config.h" /* TODO: dd_duration_t is converted to nn_ddsi_time_t declared in q_time.h @@ -144,31 +143,31 @@ dds_qos_validate_mutable_common ( /* TODO: Check whether immutable QoS are changed should actually incorporate change to current QoS */ if (qos->present & QP_DEADLINE) { DDS_ERROR("Deadline QoS policy caused immutable error\n"); - ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY); + ret = DDS_RETCODE_IMMUTABLE_POLICY; } if (qos->present & QP_OWNERSHIP) { DDS_ERROR("Ownership QoS policy caused immutable error\n"); - ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY); + ret = DDS_RETCODE_IMMUTABLE_POLICY; } if (qos->present & QP_LIVELINESS) { DDS_ERROR("Liveliness QoS policy caused immutable error\n"); - ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY); + ret = DDS_RETCODE_IMMUTABLE_POLICY; } if (qos->present & QP_RELIABILITY) { DDS_ERROR("Reliability QoS policy caused immutable error\n"); - ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY); + ret = DDS_RETCODE_IMMUTABLE_POLICY; } if (qos->present & QP_DESTINATION_ORDER) { DDS_ERROR("Destination order QoS policy caused immutable error\n"); - ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY); + ret = DDS_RETCODE_IMMUTABLE_POLICY; } if (qos->present & QP_HISTORY) { DDS_ERROR("History QoS policy caused immutable error\n"); - ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY); + ret = DDS_RETCODE_IMMUTABLE_POLICY; } if (qos->present & QP_RESOURCE_LIMITS) { DDS_ERROR("Resource limits QoS policy caused immutable error\n"); - ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY); + ret = DDS_RETCODE_IMMUTABLE_POLICY; } return ret; @@ -263,11 +262,11 @@ dds_copy_qos ( { if(!src){ DDS_ERROR("Argument source(src) is NULL\n"); - return DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; } if(!dst){ DDS_ERROR("Argument destination(dst) is NULL\n"); - return DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; } nn_xqos_copy (dst, src); return DDS_RETCODE_OK; diff --git a/src/core/ddsc/src/dds_querycond.c b/src/core/ddsc/src/dds_querycond.c index 0a5e50d..ca972dd 100644 --- a/src/core/ddsc/src/dds_querycond.c +++ b/src/core/ddsc/src/dds_querycond.c @@ -18,7 +18,6 @@ #include "dds__topic.h" #include "dds__querycond.h" #include "dds__readcond.h" -#include "dds__err.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_sertopic.h" @@ -29,7 +28,7 @@ dds_create_querycondition( dds_querycondition_filter_fn filter) { dds_entity_t hdl; - dds_retcode_t rc; + dds_return_t rc; dds_reader *r; rc = dds_reader_lock(reader, &r); @@ -42,11 +41,11 @@ dds_create_querycondition( hdl = cond->m_entity.m_hdllink.hdl; } else { dds_delete (cond->m_entity.m_hdllink.hdl); - hdl = DDS_ERRNO(DDS_RETCODE_OUT_OF_RESOURCES); + hdl = DDS_RETCODE_OUT_OF_RESOURCES; } } else { DDS_ERROR("Error occurred on locking reader\n"); - hdl = DDS_ERRNO(rc); + hdl = rc; } return hdl; diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 1702a25..5d1c4e8 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -15,16 +15,15 @@ #include "dds__reader.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds__rhc.h" -#include "dds__err.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_globals.h" #include "dds/ddsi/ddsi_sertopic.h" -static dds_retcode_t dds_read_lock (dds_entity_t hdl, dds_reader **reader, dds_readcond **condition, bool only_reader) +static dds_return_t dds_read_lock (dds_entity_t hdl, dds_reader **reader, dds_readcond **condition, bool only_reader) { - dds_retcode_t rc; + dds_return_t rc; dds_entity *entity, *parent_entity; if ((rc = dds_entity_lock (hdl, DDS_KIND_DONTCARE, &entity)) != DDS_RETCODE_OK) { @@ -91,7 +90,6 @@ dds_read_impl( { struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; - dds_retcode_t rc; struct dds_reader * rd; struct dds_readcond * cond; unsigned nodata_cleanups = 0; @@ -101,40 +99,39 @@ dds_read_impl( if (buf == NULL) { DDS_ERROR("The provided buffer is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto fail; } if (si == NULL) { DDS_ERROR("Provided pointer to an array of dds_sample_info_t is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto fail; } if (maxs == 0) { DDS_ERROR("The maximum number of samples to read is zero\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto fail; } if (bufsz == 0) { DDS_ERROR("The size of buffer is zero\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto fail; } if (bufsz < maxs) { DDS_ERROR("The provided size of buffer is smaller than the maximum number of samples to read\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto fail; } thread_state_awake (ts1); - rc = dds_read_lock(reader_or_condition, &rd, &cond, only_reader); - if (rc != DDS_RETCODE_OK) { - ret = DDS_ERRNO(rc); + ret = dds_read_lock(reader_or_condition, &rd, &cond, only_reader); + if (ret != DDS_RETCODE_OK) { goto fail_awake; } if (hand != DDS_HANDLE_NIL) { if (ddsi_tkmap_find_by_id(gv.m_tkmap, hand) == NULL) { DDS_ERROR("Could not find instance\n"); - ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); + ret = DDS_RETCODE_PRECONDITION_NOT_MET; dds_read_unlock(rd, cond); goto fail_awake; } @@ -217,7 +214,6 @@ dds_readcdr_impl( { struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; - dds_retcode_t rc; struct dds_reader * rd; struct dds_readcond * cond; @@ -229,8 +225,8 @@ dds_readcdr_impl( (void)take; thread_state_awake (ts1); - rc = dds_read_lock(reader_or_condition, &rd, &cond, false); - if (rc == DDS_RETCODE_OK) { + ret = dds_read_lock(reader_or_condition, &rd, &cond, false); + if (ret == DDS_RETCODE_OK) { /* read/take resets data available status -- must reset before reading because the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); @@ -251,8 +247,6 @@ dds_readcdr_impl( ); dds_read_unlock(rd, cond); - } else { - ret = DDS_ERRNO(rc); } thread_state_asleep (ts1); @@ -349,7 +343,7 @@ dds_read_instance( if (handle == DDS_HANDLE_NIL) { DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); + ret = DDS_RETCODE_PRECONDITION_NOT_MET; goto fail; } @@ -377,7 +371,7 @@ dds_read_instance_wl( if (handle == DDS_HANDLE_NIL) { DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); + ret = DDS_RETCODE_PRECONDITION_NOT_MET; goto fail; } @@ -407,7 +401,7 @@ dds_read_instance_mask( if (handle == DDS_HANDLE_NIL) { DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); + ret = DDS_RETCODE_PRECONDITION_NOT_MET; goto fail; } @@ -436,7 +430,7 @@ dds_read_instance_mask_wl( if (handle == DDS_HANDLE_NIL) { DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); + ret = DDS_RETCODE_PRECONDITION_NOT_MET; goto fail; } if (maxs == DDS_READ_WITHOUT_LOCK) { @@ -579,7 +573,7 @@ dds_take_instance( if (handle == DDS_HANDLE_NIL) { DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); + ret = DDS_RETCODE_PRECONDITION_NOT_MET; goto fail; } @@ -607,7 +601,7 @@ dds_take_instance_wl( if (handle == DDS_HANDLE_NIL) { DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); + ret = DDS_RETCODE_PRECONDITION_NOT_MET; goto fail; } if (maxs == DDS_READ_WITHOUT_LOCK) { @@ -636,7 +630,7 @@ dds_take_instance_mask( if (handle == DDS_HANDLE_NIL) { DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); + ret = DDS_RETCODE_PRECONDITION_NOT_MET; goto fail; } if (maxs == DDS_READ_WITHOUT_LOCK) { @@ -664,7 +658,7 @@ dds_take_instance_mask_wl( if (handle == DDS_HANDLE_NIL) { DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); + ret = DDS_RETCODE_PRECONDITION_NOT_MET; goto fail; } if (maxs == DDS_READ_WITHOUT_LOCK) { @@ -704,7 +698,6 @@ dds_return_loan( void **buf, int32_t bufsz) { - dds_retcode_t rc; const struct ddsi_sertopic *st; dds_reader *rd; dds_readcond *cond; @@ -712,17 +705,16 @@ dds_return_loan( if (!buf) { DDS_ERROR("Argument buf is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto fail; } if (*buf == NULL && bufsz > 0) { - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto fail; } - rc = dds_read_lock(reader_or_condition, &rd, &cond, false); - if (rc != DDS_RETCODE_OK) { - ret = DDS_ERRNO(rc); + ret = dds_read_lock(reader_or_condition, &rd, &cond, false); + if (ret != DDS_RETCODE_OK) { goto fail; } st = rd->m_topic->m_stopic; diff --git a/src/core/ddsc/src/dds_readcond.c b/src/core/ddsc/src/dds_readcond.c index ee37521..ae889be 100644 --- a/src/core/ddsc/src/dds_readcond.c +++ b/src/core/ddsc/src/dds_readcond.c @@ -14,7 +14,6 @@ #include "dds__readcond.h" #include "dds__rhc.h" #include "dds__entity.h" -#include "dds__err.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" @@ -63,7 +62,7 @@ dds_create_readcondition( { dds_entity_t hdl; dds_reader * rd; - dds_retcode_t rc; + dds_return_t rc; rc = dds_reader_lock(reader, &rd); if (rc == DDS_RETCODE_OK) { @@ -74,7 +73,7 @@ dds_create_readcondition( dds_reader_unlock(rd); } else { DDS_ERROR("Error occurred on locking reader\n"); - hdl = DDS_ERRNO(rc); + hdl = rc; } return hdl; @@ -83,9 +82,9 @@ dds_create_readcondition( dds_entity_t dds_get_datareader (dds_entity_t condition) { struct dds_entity *e; - dds_retcode_t rc; + dds_return_t rc; if ((rc = dds_entity_claim (condition, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + return rc; else { dds_entity_t rdh; @@ -97,7 +96,7 @@ dds_entity_t dds_get_datareader (dds_entity_t condition) rdh = e->m_parent->m_hdllink.hdl; break; default: - rdh = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + rdh = DDS_RETCODE_ILLEGAL_OPERATION; break; } dds_entity_release (e); @@ -108,17 +107,17 @@ dds_entity_t dds_get_datareader (dds_entity_t condition) dds_return_t dds_get_mask (dds_entity_t condition, uint32_t *mask) { dds_entity *entity; - dds_retcode_t rc; + dds_return_t rc; if (mask == NULL) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; if ((rc = dds_entity_lock (condition, DDS_KIND_DONTCARE, &entity)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + return rc; else if (dds_entity_kind (entity) != DDS_KIND_COND_READ && dds_entity_kind (entity) != DDS_KIND_COND_QUERY) { dds_entity_unlock (entity); - return DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + return DDS_RETCODE_ILLEGAL_OPERATION; } else { diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index be86ed3..49a6c0c 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -19,7 +19,6 @@ #include "dds__qos.h" #include "dds__init.h" #include "dds__rhc.h" -#include "dds__err.h" #include "dds__topic.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" @@ -53,7 +52,6 @@ static dds_return_t dds_reader_close( dds_entity *e) { - dds_retcode_t rc; dds_return_t ret = DDS_RETCODE_OK; assert(e); @@ -61,8 +59,7 @@ dds_reader_close( thread_state_awake (lookup_thread_state ()); if (delete_reader(&e->m_guid) != 0) { DDS_ERROR("Internal error"); - rc = DDS_RETCODE_ERROR; - ret = DDS_ERRNO(rc); + ret = DDS_RETCODE_ERROR; } thread_state_asleep (lookup_thread_state ()); return ret; @@ -78,7 +75,7 @@ dds_reader_delete( ret = dds_delete(rd->m_topic->m_entity.m_hdllink.hdl); if(ret == DDS_RETCODE_OK){ ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true); - if(dds_err_nr(ret) == DDS_RETCODE_BAD_PARAMETER){ + if(ret == DDS_RETCODE_BAD_PARAMETER){ ret = DDS_RETCODE_OK; } } @@ -98,27 +95,27 @@ dds_reader_qos_validate( /* Check consistency. */ if(!dds_qos_validate_common(qos)) { DDS_ERROR("Argument Qos is not valid\n"); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; } if((qos->present & QP_USER_DATA) && !(validate_octetseq (&qos->user_data))) { DDS_ERROR("User data policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if((qos->present & QP_PRISMTECH_READER_DATA_LIFECYCLE) && (validate_reader_data_lifecycle (&qos->reader_data_lifecycle) != 0)) { DDS_ERROR("Prismtech reader data lifecycle policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if((qos->present & QP_TIME_BASED_FILTER) && (validate_duration (&qos->time_based_filter.minimum_separation) != 0)) { DDS_ERROR("Time based filter policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits (&qos->history, &qos->resource_limits) != 0)) { DDS_ERROR("History and resource limits policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if((qos->present & QP_TIME_BASED_FILTER) && (qos->present & QP_DEADLINE) && !(validate_deadline_and_timebased_filter (qos->deadline.deadline, qos->time_based_filter.minimum_separation))) { DDS_ERROR("Time based filter and deadline policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if(ret == DDS_RETCODE_OK && enabled) { ret = dds_qos_validate_mutable_common(qos); @@ -139,7 +136,7 @@ dds_reader_qos_set( if (enabled) { /* TODO: CHAM-95: DDSI does not support changing QoS policies. */ DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); + ret = DDS_RETCODE_UNSUPPORTED; } } return ret; @@ -150,7 +147,7 @@ dds_reader_status_validate( uint32_t mask) { return (mask & ~(DDS_READER_STATUS_MASK)) ? - DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER) : + DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK; } @@ -360,7 +357,6 @@ dds_create_reader( const dds_listener_t *listener) { dds_qos_t * rqos; - dds_retcode_t rc; dds_subscriber * sub = NULL; dds_entity_t subscriber; dds_reader * rd; @@ -383,8 +379,8 @@ dds_create_reader( default: { dds_entity *p_or_s; - if ((rc = dds_entity_claim (participant_or_subscriber, &p_or_s)) != DDS_RETCODE_OK) { - return DDS_ERRNO (rc); + if ((ret = dds_entity_claim (participant_or_subscriber, &p_or_s)) != DDS_RETCODE_OK) { + return ret; } if (dds_entity_kind (p_or_s) == DDS_KIND_PARTICIPANT) { subscriber = dds_create_subscriber(participant_or_subscriber, qos, NULL); @@ -398,8 +394,8 @@ dds_create_reader( } } - if ((rc = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK) { - reader = DDS_ERRNO (rc); + if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK) { + reader = ret; goto err_sub_lock; } @@ -408,10 +404,10 @@ dds_create_reader( sub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT; } - rc = dds_topic_lock(t, &tp); - if (rc != DDS_RETCODE_OK) { + ret = dds_topic_lock(t, &tp); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking topic\n"); - reader = DDS_ERRNO(rc); + reader = ret; goto err_tp_lock; } assert (tp->m_stopic); @@ -448,7 +444,7 @@ dds_create_reader( if (internal_topic && !dds__validate_builtin_reader_qos(topic, qos)) { dds_delete_qos(rqos); DDS_ERROR("Invalid QoS specified for built-in topic reader"); - reader = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + reader = DDS_RETCODE_INCONSISTENT_POLICY; goto err_bad_qos; } @@ -573,12 +569,12 @@ uint32_t dds_reader_lock_samples (dds_entity_t reader) return n; } -int dds_reader_wait_for_historical_data (dds_entity_t reader, dds_duration_t max_wait) +dds_return_t dds_reader_wait_for_historical_data (dds_entity_t reader, dds_duration_t max_wait) { dds_reader *rd; - int ret; + dds_return_t ret; if ((ret = dds_reader_lock (reader, &rd)) != DDS_RETCODE_OK) - return DDS_ERRNO (ret); + return ret; switch (rd->m_entity.m_qos->durability.kind) { case DDS_DURABILITY_VOLATILE: @@ -598,9 +594,9 @@ int dds_reader_wait_for_historical_data (dds_entity_t reader, dds_duration_t max dds_entity_t dds_get_subscriber (dds_entity_t entity) { dds_entity *e; - dds_retcode_t ret; + dds_return_t ret; if ((ret = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) - return (dds_entity_t) DDS_ERRNO (ret); + return ret; else { dds_entity_t subh; @@ -617,7 +613,7 @@ dds_entity_t dds_get_subscriber (dds_entity_t entity) subh = e->m_parent->m_parent->m_hdllink.hdl; break; default: - subh = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + subh = DDS_RETCODE_ILLEGAL_OPERATION; break; } dds_entity_release (e); @@ -630,14 +626,12 @@ dds_get_subscription_matched_status ( dds_entity_t reader, dds_subscription_matched_status_t * status) { - dds_retcode_t rc; dds_reader *rd; - dds_return_t ret = DDS_RETCODE_OK; + dds_return_t ret; - rc = dds_reader_lock(reader, &rd); - if (rc != DDS_RETCODE_OK) { + ret = dds_reader_lock(reader, &rd); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking reader\n"); - ret = DDS_ERRNO(rc); goto fail; } /* status = NULL, application do not need the status, but reset the counter & triggered bit */ @@ -661,14 +655,12 @@ dds_get_liveliness_changed_status ( dds_entity_t reader, dds_liveliness_changed_status_t * status) { - dds_retcode_t rc; dds_reader *rd; - dds_return_t ret = DDS_RETCODE_OK; + dds_return_t ret; - rc = dds_reader_lock(reader, &rd); - if (rc != DDS_RETCODE_OK) { + ret = dds_reader_lock(reader, &rd); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking reader\n"); - ret = DDS_ERRNO(rc); goto fail; } /* status = NULL, application do not need the status, but reset the counter & triggered bit */ @@ -691,14 +683,12 @@ dds_return_t dds_get_sample_rejected_status ( dds_entity_t reader, dds_sample_rejected_status_t * status) { - dds_retcode_t rc; dds_reader *rd; - dds_return_t ret = DDS_RETCODE_OK; + dds_return_t ret; - rc = dds_reader_lock(reader, &rd); - if (rc != DDS_RETCODE_OK) { + ret = dds_reader_lock(reader, &rd); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking reader\n"); - ret = DDS_ERRNO(rc); goto fail; } /* status = NULL, application do not need the status, but reset the counter & triggered bit */ @@ -721,14 +711,12 @@ dds_return_t dds_get_sample_lost_status ( dds_entity_t reader, dds_sample_lost_status_t * status) { - dds_retcode_t rc; dds_reader *rd; - dds_return_t ret = DDS_RETCODE_OK; + dds_return_t ret; - rc = dds_reader_lock(reader, &rd); - if (rc != DDS_RETCODE_OK) { + ret = dds_reader_lock(reader, &rd); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking reader\n"); - ret = DDS_ERRNO(rc); goto fail; } /* status = NULL, application do not need the status, but reset the counter & triggered bit */ @@ -750,14 +738,12 @@ dds_return_t dds_get_requested_deadline_missed_status ( dds_entity_t reader, dds_requested_deadline_missed_status_t * status) { - dds_retcode_t rc; dds_reader *rd; - dds_return_t ret = DDS_RETCODE_OK; + dds_return_t ret; - rc = dds_reader_lock(reader, &rd); - if (rc != DDS_RETCODE_OK) { + ret = dds_reader_lock(reader, &rd); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking reader\n"); - ret = DDS_ERRNO(rc); goto fail; } /* status = NULL, application do not need the status, but reset the counter & triggered bit */ @@ -779,14 +765,12 @@ dds_return_t dds_get_requested_incompatible_qos_status ( dds_entity_t reader, dds_requested_incompatible_qos_status_t * status) { - dds_retcode_t rc; dds_reader *rd; - dds_return_t ret = DDS_RETCODE_OK; + dds_return_t ret; - rc = dds_reader_lock(reader, &rd); - if (rc != DDS_RETCODE_OK) { + ret = dds_reader_lock(reader, &rd); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking reader\n"); - ret = DDS_ERRNO(rc); goto fail; } /* status = NULL, application do not need the status, but reset the counter & triggered bit */ diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 79a134a..99f4508 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -30,7 +30,6 @@ #include "dds/ddsrt/hopscotch.h" #include "dds/ddsrt/avl.h" #include "dds/ddsi/q_xqos.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_globals.h" diff --git a/src/core/ddsc/src/dds_subscriber.c b/src/core/ddsc/src/dds_subscriber.c index 1a51775..91efce6 100644 --- a/src/core/ddsc/src/dds_subscriber.c +++ b/src/core/ddsc/src/dds_subscriber.c @@ -12,7 +12,6 @@ #include #include "dds__listener.h" #include "dds__qos.h" -#include "dds__err.h" #include "dds__subscriber.h" #include "dds/ddsi/q_entity.h" #include "dds/version.h" @@ -31,7 +30,7 @@ dds_subscriber_instance_hdl( (void)i; /* TODO: Get/generate proper handle. */ DDS_ERROR("Generating subscriber instance handle is not supported"); - return DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); + return DDS_RETCODE_UNSUPPORTED; } static dds_return_t @@ -45,24 +44,24 @@ dds__subscriber_qos_validate( if((qos->present & QP_GROUP_DATA) && !validate_octetseq(&qos->group_data)) { DDS_ERROR("Group data policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if((qos->present & QP_PARTITION) && !validate_stringseq(&qos->partition)) { DDS_ERROR("Partition policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if((qos->present & QP_PRESENTATION) && validate_presentation_qospolicy(&qos->presentation)) { DDS_ERROR("Presentation policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)) { DDS_ERROR("Prismtech entity factory policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if(ret == DDS_RETCODE_OK && enabled && (qos->present & QP_PRESENTATION)) { /* TODO: Improve/check immutable check. */ DDS_ERROR("Presentation QoS policy is immutable\n"); - ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY); + ret = DDS_RETCODE_IMMUTABLE_POLICY; } return ret; @@ -80,7 +79,7 @@ dds_subscriber_qos_set( if (enabled) { /* TODO: CHAM-95: DDSI does not support changing QoS policies. */ DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies yet\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); + ret = DDS_RETCODE_UNSUPPORTED; } } return ret; @@ -94,7 +93,7 @@ dds_subscriber_status_validate( if (mask & ~(DDS_SUBSCRIBER_STATUS_MASK)) { DDS_ERROR("Invalid status mask\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; } return ret; @@ -146,12 +145,12 @@ dds_create_subscriber( { dds_entity * par; dds_entity_t hdl; - dds_retcode_t errnr; + dds_return_t errnr; errnr = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); if (errnr != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking participant\n"); - hdl = DDS_ERRNO(errnr); + hdl = errnr; return hdl; } @@ -167,14 +166,12 @@ dds_notify_readers( { dds_entity *iter; dds_entity *sub; - dds_retcode_t errnr; dds_return_t ret; - errnr = dds_entity_lock(subscriber, DDS_KIND_SUBSCRIBER, &sub); - if (errnr == DDS_RETCODE_OK) { - errnr = DDS_RETCODE_UNSUPPORTED; + ret = dds_entity_lock(subscriber, DDS_KIND_SUBSCRIBER, &sub); + if (ret == DDS_RETCODE_OK) { + ret = DDS_RETCODE_UNSUPPORTED; DDS_ERROR("Unsupported operation\n"); - ret = DDS_ERRNO(errnr); iter = sub->m_children; while (iter) { ddsrt_mutex_lock(&iter->m_mutex); @@ -185,7 +182,6 @@ dds_notify_readers( dds_entity_unlock(sub); } else { DDS_ERROR("Error occurred on locking subscriber\n"); - ret = DDS_ERRNO(errnr); } return ret; @@ -198,7 +194,7 @@ dds_subscriber_begin_coherent( /* TODO: CHAM-124 Currently unsupported. */ (void)e; DDS_ERROR("Using coherency to get a coherent data set is not currently being supported\n"); - return DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); + return DDS_RETCODE_UNSUPPORTED; } dds_return_t @@ -208,6 +204,6 @@ dds_subscriber_end_coherent( /* TODO: CHAM-124 Currently unsupported. */ (void)e; DDS_ERROR("Using coherency to get a coherent data set is not currently being supported\n"); - return DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); + return DDS_RETCODE_UNSUPPORTED; } diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index c0cb41d..384c250 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -20,7 +20,6 @@ #include "dds__stream.h" #include "dds__init.h" #include "dds__domain.h" -#include "dds__err.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/ddsi_sertopic.h" @@ -76,7 +75,7 @@ dds_topic_status_validate( if (mask & ~(DDS_TOPIC_STATUS_MASK)) { DDS_ERROR("Argument mask is invalid\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; } return ret; @@ -183,7 +182,7 @@ dds_find_topic( dds_entity_t tp; dds_entity *p = NULL; struct ddsi_sertopic *st; - dds_retcode_t rc; + dds_return_t rc; if (name) { rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &p); @@ -200,16 +199,16 @@ dds_find_topic( tp = st->status_cb_entity->m_entity.m_hdllink.hdl; } else { DDS_ERROR("Topic is not being created yet\n"); - tp = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); + tp = DDS_RETCODE_PRECONDITION_NOT_MET; } ddsrt_mutex_unlock (&dds_global.m_mutex); dds_entity_unlock(p); } else { - tp = DDS_ERRNO(rc); + tp = rc; } } else { DDS_ERROR("Argument name is not valid\n"); - tp = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + tp = DDS_RETCODE_BAD_PARAMETER; } return tp; @@ -234,23 +233,23 @@ dds_topic_qos_validate( /* Check consistency. */ if (!dds_qos_validate_common(qos)) { DDS_ERROR("Argument QoS is not valid\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; } if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data)) { DDS_ERROR("Group data QoS policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if ((qos->present & QP_DURABILITY_SERVICE) && (validate_durability_service_qospolicy(&qos->durability_service) != 0)) { DDS_ERROR("Durability service QoS policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if ((qos->present & QP_LIFESPAN) && (validate_duration(&qos->lifespan.duration) != 0)) { DDS_ERROR("Lifespan QoS policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if (qos->present & QP_HISTORY && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits(&qos->history, &qos->resource_limits) != 0)) { DDS_ERROR("Lifespan QoS policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if(ret == DDS_RETCODE_OK && enabled){ ret = dds_qos_validate_mutable_common(qos); @@ -271,7 +270,7 @@ dds_topic_qos_set( if (enabled) { /* TODO: CHAM-95: DDSI does not support changing QoS policies. */ DDS_ERROR("Changing the topic QoS is not supported\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); + ret = DDS_RETCODE_UNSUPPORTED; } } return ret; @@ -310,7 +309,7 @@ dds_create_topic_arbitrary ( const nn_plist_t *sedp_plist) { struct ddsi_sertopic *stgeneric; - dds_retcode_t rc; + dds_return_t rc; dds_entity *par; dds_topic *top; dds_qos_t *new_qos = NULL; @@ -319,13 +318,13 @@ dds_create_topic_arbitrary ( if (sertopic == NULL){ DDS_ERROR("Topic description is NULL\n"); - hdl = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + hdl = DDS_RETCODE_BAD_PARAMETER; goto bad_param_err; } rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); if (rc != DDS_RETCODE_OK) { - hdl = DDS_ERRNO(rc); + hdl = rc; goto lock_err; } @@ -345,11 +344,11 @@ dds_create_topic_arbitrary ( if (!sertopic_equivalent (stgeneric, sertopic)) { /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */ DDS_ERROR("Create topic with mismatching type\n"); - hdl = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); + hdl = DDS_RETCODE_PRECONDITION_NOT_MET; } else if (!dupdef_qos_ok(qos, stgeneric)) { /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */ DDS_ERROR("Create topic with mismatching qos\n"); - hdl = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + hdl = DDS_RETCODE_INCONSISTENT_POLICY; } else { /* FIXME: calling addref is wrong because the Cyclone library has no knowledge of the reference and hence simply deleting the participant @@ -417,19 +416,19 @@ dds_create_topic( if (desc == NULL){ DDS_ERROR("Topic description is NULL"); - hdl = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + hdl = DDS_RETCODE_BAD_PARAMETER; goto bad_param_err; } if (name == NULL) { DDS_ERROR("Topic name is NULL"); - hdl = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + hdl = DDS_RETCODE_BAD_PARAMETER; goto bad_param_err; } if (!is_valid_name(name)) { DDS_ERROR("Topic name contains characters that are not allowed."); - hdl = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + hdl = DDS_RETCODE_BAD_PARAMETER; goto bad_param_err; } @@ -586,27 +585,24 @@ dds_get_name( { dds_topic *t; dds_return_t ret; - dds_retcode_t rc; if(size <= 0){ DDS_ERROR("Argument size is smaller than 0\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto fail; } if(name == NULL){ DDS_ERROR("Argument name is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto fail; } name[0] = '\0'; - rc = dds_topic_lock(topic, &t); - if (rc == DDS_RETCODE_OK) { + ret = dds_topic_lock(topic, &t); + if (ret == DDS_RETCODE_OK) { (void)snprintf(name, size, "%s", t->m_stopic->name); dds_topic_unlock(t); - ret = DDS_RETCODE_OK; } else { DDS_ERROR("Error occurred on locking topic\n"); - ret = DDS_ERRNO(rc); goto fail; } fail: @@ -620,29 +616,26 @@ dds_get_type_name( size_t size) { dds_topic *t; - dds_retcode_t rc; dds_return_t ret; if(size <= 0){ DDS_ERROR("Argument size is smaller than 0\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto fail; } if(name == NULL){ DDS_ERROR("Argument name is NULL\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; goto fail; } name[0] = '\0'; - rc = dds_topic_lock(topic, &t); - if (rc != DDS_RETCODE_OK) { + ret = dds_topic_lock(topic, &t); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking topic\n"); - ret = DDS_ERRNO(rc); goto fail; } (void)snprintf(name, size, "%s", t->m_stopic->type_name); dds_topic_unlock(t); - ret = DDS_RETCODE_OK; fail: return ret; } @@ -652,14 +645,12 @@ dds_get_inconsistent_topic_status( dds_entity_t topic, dds_inconsistent_topic_status_t *status) { - dds_retcode_t rc; dds_topic *t; - dds_return_t ret = DDS_RETCODE_OK; + dds_return_t ret; - rc = dds_topic_lock(topic, &t); - if (rc != DDS_RETCODE_OK) { + ret = dds_topic_lock(topic, &t); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking topic\n"); - ret = DDS_ERRNO(rc); goto fail; } /* status = NULL, application do not need the status, but reset the counter & triggered bit */ diff --git a/src/core/ddsc/src/dds_waitset.c b/src/core/ddsc/src/dds_waitset.c index 4d5bd4b..357d8fb 100644 --- a/src/core/ddsc/src/dds_waitset.c +++ b/src/core/ddsc/src/dds_waitset.c @@ -17,7 +17,6 @@ #include "dds__querycond.h" #include "dds__readcond.h" #include "dds__rhc.h" -#include "dds__err.h" DEFINE_ENTITY_LOCK_UNLOCK(static, dds_waitset, DDS_KIND_WAITSET) @@ -50,24 +49,23 @@ dds_waitset_wait_impl( { dds_waitset *ws; dds_return_t ret; - dds_retcode_t rc; dds_attachment *idx; dds_attachment *next; dds_attachment *prev; if ((xs == NULL) && (nxs != 0)){ DDS_ERROR("A size was given, but no array\n"); - return DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; } if ((xs != NULL) && (nxs == 0)){ DDS_ERROR("Array is given with an invalid size\n"); - return DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; } /* Locking the waitset here will delay a possible deletion until it is * unlocked. Even when the related mutex is unlocked by a conditioned wait. */ - rc = dds_waitset_lock(waitset, &ws); - if (rc == DDS_RETCODE_OK) { + ret = dds_waitset_lock(waitset, &ws); + if (ret == DDS_RETCODE_OK) { /* Check if any of any previous triggered entities has changed there status * and thus it trigger value could be false now. */ idx = ws->triggered; @@ -97,12 +95,11 @@ dds_waitset_wait_impl( } /* Only wait/keep waiting when whe have something to observer and there aren't any triggers yet. */ - rc = DDS_RETCODE_OK; - while ((ws->observed != NULL) && (ws->triggered == NULL) && (rc == DDS_RETCODE_OK)) { + while ((ws->observed != NULL) && (ws->triggered == NULL) && (ret == DDS_RETCODE_OK)) { if (abstimeout == DDS_NEVER) { ddsrt_cond_wait(&ws->m_entity.m_cond, &ws->m_entity.m_mutex); } else if (abstimeout <= tnow) { - rc = DDS_RETCODE_TIMEOUT; + ret = DDS_RETCODE_TIMEOUT; } else { dds_duration_t dt = abstimeout - tnow; (void)ddsrt_cond_waitfor(&ws->m_entity.m_cond, &ws->m_entity.m_mutex, dt); @@ -113,7 +110,7 @@ dds_waitset_wait_impl( /* Get number of triggered entities * - set attach array when needed * - swap them back to observed */ - if (rc == DDS_RETCODE_OK) { + if (ret == DDS_RETCODE_OK) { ret = 0; idx = ws->triggered; while (idx != NULL) { @@ -127,17 +124,15 @@ dds_waitset_wait_impl( dds_waitset_swap(&(ws->observed), &(ws->triggered), NULL, idx); idx = next; } - } else if (rc == DDS_RETCODE_TIMEOUT) { + } else if (ret == DDS_RETCODE_TIMEOUT) { ret = 0; } else { DDS_ERROR("Internal error"); - ret = DDS_ERRNO(rc); } dds_waitset_unlock(ws); } else { DDS_ERROR("Error occurred on locking waitset\n"); - ret = DDS_ERRNO(rc); } return ret; @@ -206,7 +201,7 @@ dds_create_waitset( { dds_entity_t hdl; dds_entity *par; - dds_retcode_t rc; + dds_return_t rc; rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); if (rc == DDS_RETCODE_OK) { @@ -217,7 +212,7 @@ dds_create_waitset( waitset->triggered = NULL; dds_entity_unlock(par); } else { - hdl = DDS_ERRNO(rc); + hdl = rc; } return hdl; @@ -230,14 +225,14 @@ dds_waitset_get_entities( dds_entity_t *entities, size_t size) { - dds_return_t ret = 0; - dds_retcode_t rc; + dds_return_t ret; dds_waitset *ws; - rc = dds_waitset_lock(waitset, &ws); - if (rc == DDS_RETCODE_OK) { + ret = dds_waitset_lock(waitset, &ws); + if (ret == DDS_RETCODE_OK) { dds_attachment* iter; + ret = 0; iter = ws->observed; while (iter) { if (((size_t)ret < size) && (entities != NULL)) { @@ -258,7 +253,6 @@ dds_waitset_get_entities( dds_waitset_unlock(ws); } else { DDS_ERROR("Error occurred on locking waitset\n"); - ret = DDS_ERRNO(rc); } return ret; @@ -330,14 +324,13 @@ dds_waitset_attach( { dds_entity *e = NULL; dds_waitset *ws; - dds_retcode_t rc; dds_return_t ret; - rc = dds_waitset_lock(waitset, &ws); - if (rc == DDS_RETCODE_OK) { + ret = dds_waitset_lock(waitset, &ws); + if (ret == DDS_RETCODE_OK) { if (waitset != entity) { - rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (rc != DDS_RETCODE_OK) { + ret = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); + if (ret != DDS_RETCODE_OK) { e = NULL; } } else { @@ -345,11 +338,11 @@ dds_waitset_attach( } /* This will fail if given entity is already attached (or deleted). */ - if (rc == DDS_RETCODE_OK) { - rc = dds_entity_observer_register_nl(e, waitset, dds_waitset_observer); + if (ret == DDS_RETCODE_OK) { + ret = dds_entity_observer_register_nl(e, waitset, dds_waitset_observer); } - if (rc == DDS_RETCODE_OK) { + if (ret == DDS_RETCODE_OK) { dds_attachment *a = ddsrt_malloc(sizeof(dds_attachment)); a->arg = x; a->entity = e; @@ -361,12 +354,11 @@ dds_waitset_attach( ws->observed = a; } ret = DDS_RETCODE_OK; - } else if (rc != DDS_RETCODE_PRECONDITION_NOT_MET) { + } else if (ret != DDS_RETCODE_PRECONDITION_NOT_MET) { DDS_ERROR("Entity is not valid\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; } else { DDS_ERROR("Entity is already attached\n"); - ret = DDS_ERRNO(rc); } if ((e != NULL) && (waitset != entity)) { dds_entity_unlock(e); @@ -374,7 +366,6 @@ dds_waitset_attach( dds_waitset_unlock(ws); } else { DDS_ERROR("Error occurred on locking waitset\n"); - ret = DDS_ERRNO(rc); } return ret; @@ -386,31 +377,27 @@ dds_waitset_detach( dds_entity_t entity) { dds_waitset *ws; - dds_retcode_t rc; dds_return_t ret; - rc = dds_waitset_lock(waitset, &ws); - if (rc == DDS_RETCODE_OK) { + ret = dds_waitset_lock(waitset, &ws); + if (ret == DDS_RETCODE_OK) { /* Possibly fails when entity was not attached. */ if (waitset == entity) { - rc = dds_entity_observer_unregister_nl(&ws->m_entity, waitset); + ret = dds_entity_observer_unregister_nl(&ws->m_entity, waitset); } else { - rc = dds_entity_observer_unregister(entity, waitset); + ret = dds_entity_observer_unregister(entity, waitset); } - if (rc == DDS_RETCODE_OK) { + if (ret == DDS_RETCODE_OK) { dds_waitset_remove(ws, entity); - ret = DDS_RETCODE_OK; - } else if (rc != DDS_RETCODE_PRECONDITION_NOT_MET) { + } else if (ret != DDS_RETCODE_PRECONDITION_NOT_MET) { DDS_ERROR("The given entity to detach is invalid\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; } else { DDS_ERROR("The given entity to detach was not attached previously\n"); - ret = DDS_ERRNO(rc); } dds_waitset_unlock(ws); } else { DDS_ERROR("Error occurred on locking waitset\n"); - ret = DDS_ERRNO(rc); } return ret; @@ -441,7 +428,7 @@ dds_waitset_wait( ret = dds_waitset_wait_impl(waitset, xs, nxs, abstimeout, tnow); } else{ DDS_ERROR("Negative timeout\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; } return ret; @@ -450,10 +437,10 @@ dds_waitset_wait( dds_return_t dds_waitset_set_trigger (dds_entity_t waitset, bool trigger) { dds_waitset *ws; - dds_retcode_t rc; + dds_return_t rc; if ((rc = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + return rc; ddsrt_mutex_unlock (&ws->m_entity.m_mutex); diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 032141a..2ef7f1f 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -14,12 +14,10 @@ #include "dds__writer.h" #include "dds__write.h" #include "dds/ddsi/ddsi_tkmap.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds__stream.h" -#include "dds__err.h" #include "dds/ddsi/q_transmit.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_config.h" @@ -29,14 +27,13 @@ dds_return_t dds_write (dds_entity_t writer, const void *data) { dds_return_t ret; - dds_retcode_t rc; dds_writer *wr; if (data == NULL) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; - if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) + return ret; ret = dds_write_impl (wr, data, dds_time (), 0); dds_writer_unlock (wr); return ret; @@ -45,14 +42,13 @@ dds_return_t dds_write (dds_entity_t writer, const void *data) dds_return_t dds_writecdr (dds_entity_t writer, struct ddsi_serdata *serdata) { dds_return_t ret; - dds_retcode_t rc; dds_writer *wr; if (serdata == NULL) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; - if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) + return ret; ret = dds_writecdr_impl (wr, serdata, dds_time (), 0); dds_writer_unlock (wr); return ret; @@ -61,14 +57,13 @@ dds_return_t dds_writecdr (dds_entity_t writer, struct ddsi_serdata *serdata) dds_return_t dds_write_ts (dds_entity_t writer, const void *data, dds_time_t timestamp) { dds_return_t ret; - dds_retcode_t rc; dds_writer *wr; if (data == NULL || timestamp < 0) - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; - if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) + return ret; ret = dds_write_impl (wr, data, timestamp, 0); dds_writer_unlock (wr); return ret; @@ -86,7 +81,7 @@ static dds_return_t try_store (struct rhc *rhc, const struct proxy_writer_info * else { DDS_ERROR ("The writer could not deliver data on time, probably due to a local reader resources being full\n"); - return DDS_ERRNO (DDS_RETCODE_TIMEOUT); + return DDS_RETCODE_TIMEOUT; } } return DDS_RETCODE_OK; @@ -159,7 +154,7 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam if (data == NULL) { DDS_ERROR("No data buffer provided\n"); - return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + return DDS_RETCODE_BAD_PARAMETER; } /* Check for topic filter */ @@ -183,15 +178,15 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam if (!config.whc_batch) nn_xpack_send (wr->m_xp, false); ret = DDS_RETCODE_OK; - } else if (w_rc == Q_ERR_TIMEOUT) { + } else if (w_rc == DDS_RETCODE_TIMEOUT) { DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n"); - ret = DDS_ERRNO (DDS_RETCODE_TIMEOUT); - } else if (w_rc == Q_ERR_INVALID_DATA) { + ret = DDS_RETCODE_TIMEOUT; + } else if (w_rc == DDS_RETCODE_BAD_PARAMETER) { DDS_ERROR ("Invalid data provided\n"); - ret = DDS_ERRNO (DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; } else { DDS_ERROR ("Internal error\n"); - ret = DDS_ERRNO (DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; } if (ret == DDS_RETCODE_OK) ret = deliver_locally (ddsi_wr, d, tk); @@ -217,15 +212,15 @@ dds_return_t dds_writecdr_impl_lowlevel (struct writer *ddsi_wr, struct nn_xpack if (!config.whc_batch && xp != NULL) nn_xpack_send (xp, false); ret = DDS_RETCODE_OK; - } else if (w_rc == Q_ERR_TIMEOUT) { + } else if (w_rc == DDS_RETCODE_TIMEOUT) { DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n"); - ret = DDS_ERRNO(DDS_RETCODE_TIMEOUT); - } else if (w_rc == Q_ERR_INVALID_DATA) { + ret = DDS_RETCODE_TIMEOUT; + } else if (w_rc == DDS_RETCODE_BAD_PARAMETER) { DDS_ERROR ("Invalid data provided\n"); - ret = DDS_ERRNO (DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; } else { DDS_ERROR ("Internal error\n"); - ret = DDS_ERRNO (DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; } if (ret == DDS_RETCODE_OK) @@ -255,7 +250,7 @@ void dds_write_flush (dds_entity_t writer) { struct thread_state1 * const ts1 = lookup_thread_state (); dds_writer *wr; - dds_retcode_t rc; + dds_return_t rc; thread_state_awake (ts1); if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) DDS_ERROR ("Error occurred on locking writer\n"); diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index f144e35..534ba86 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -21,7 +21,6 @@ #include "dds__writer.h" #include "dds__listener.h" #include "dds__qos.h" -#include "dds__err.h" #include "dds__init.h" #include "dds__publisher.h" #include "dds__topic.h" @@ -55,7 +54,7 @@ dds_writer_status_validate( if (mask & ~(DDS_WRITER_STATUS_MASK)) { DDS_ERROR("Invalid status mask\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + ret = DDS_RETCODE_BAD_PARAMETER; } return ret; @@ -200,7 +199,7 @@ dds_writer_close( nn_xpack_send (wr->m_xp, false); if (delete_writer (&e->m_guid) != 0) { DDS_ERROR("Internal error"); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; } thread_state_asleep (lookup_thread_state ()); return ret; @@ -219,7 +218,7 @@ dds_writer_delete( ret = dds_delete(wr->m_topic->m_entity.m_hdllink.hdl); if(ret == DDS_RETCODE_OK){ ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true); - if(dds_err_nr(ret) == DDS_RETCODE_BAD_PARAMETER){ + if(ret == DDS_RETCODE_BAD_PARAMETER){ ret = DDS_RETCODE_OK; } } @@ -239,23 +238,23 @@ dds_writer_qos_validate( /* Check consistency. */ if(dds_qos_validate_common(qos) != true){ DDS_ERROR("Provided inconsistent QoS policy\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if((qos->present & QP_USER_DATA) && validate_octetseq(&qos->user_data) != true){ DDS_ERROR("User Data QoS policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy(&qos->durability_service) != 0){ DDS_ERROR("Durability service QoS policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if ((qos->present & QP_LIFESPAN) && validate_duration(&qos->lifespan.duration) != 0){ DDS_ERROR("Lifespan QoS policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits(&qos->history, &qos->resource_limits) != 0)){ DDS_ERROR("Resource limits QoS policy is inconsistent and caused an error\n"); - ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); + ret = DDS_RETCODE_INCONSISTENT_POLICY; } if(ret == DDS_RETCODE_OK && enabled) { ret = dds_qos_validate_mutable_common(qos); @@ -299,12 +298,12 @@ dds_writer_qos_set( thread_state_asleep (lookup_thread_state ()); } else { DDS_ERROR("Setting ownership strength doesn't make sense when the ownership is shared\n"); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); + ret = DDS_RETCODE_ERROR; } } else { if (enabled) { DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies yet\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); + ret = DDS_RETCODE_UNSUPPORTED; } } } @@ -342,7 +341,7 @@ dds_create_writer( const dds_qos_t *qos, const dds_listener_t *listener) { - dds_retcode_t rc; + dds_return_t rc; dds_qos_t * wqos; dds_writer * wr; dds_entity_t writer; @@ -355,7 +354,7 @@ dds_create_writer( { dds_entity *p_or_p; if ((rc = dds_entity_claim (participant_or_publisher, &p_or_p)) != DDS_RETCODE_OK) { - return DDS_ERRNO (rc); + return rc; } if (dds_entity_kind (p_or_p) == DDS_KIND_PARTICIPANT) { publisher = dds_create_publisher(participant_or_publisher, qos, NULL); @@ -366,7 +365,7 @@ dds_create_writer( } if ((rc = dds_publisher_lock(publisher, &pub)) != DDS_RETCODE_OK) { - writer = DDS_ERRNO(rc); + writer = rc; goto err_pub_lock; } @@ -377,7 +376,7 @@ dds_create_writer( rc = dds_topic_lock(topic, &tp); if (rc != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking topic\n"); - writer = DDS_ERRNO(rc); + writer = rc; goto err_tp_lock; } assert(tp->m_stopic); @@ -455,14 +454,14 @@ dds_get_publisher( dds_entity_t writer) { dds_entity *e; - dds_retcode_t rc; + dds_return_t rc; if ((rc = dds_entity_claim (writer, &e)) != DDS_RETCODE_OK) - return DDS_ERRNO (rc); + return rc; else { dds_entity_t pubh; if (dds_entity_kind (e) != DDS_KIND_WRITER) - pubh = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + pubh = DDS_RETCODE_ILLEGAL_OPERATION; else { assert (dds_entity_kind (e->m_parent) == DDS_KIND_PUBLISHER); @@ -478,14 +477,12 @@ dds_get_publication_matched_status ( dds_entity_t writer, dds_publication_matched_status_t * status) { - dds_retcode_t rc; dds_writer *wr; - dds_return_t ret = DDS_RETCODE_OK; + dds_return_t ret; - rc = dds_writer_lock(writer, &wr); - if (rc != DDS_RETCODE_OK) { + ret = dds_writer_lock(writer, &wr); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking writer\n"); - ret = DDS_ERRNO(rc); goto fail; } /* status = NULL, application do not need the status, but reset the counter & triggered bit */ @@ -509,14 +506,12 @@ dds_get_liveliness_lost_status ( dds_entity_t writer, dds_liveliness_lost_status_t * status) { - dds_retcode_t rc; dds_writer *wr; - dds_return_t ret = DDS_RETCODE_OK; + dds_return_t ret; - rc = dds_writer_lock(writer, &wr); - if (rc != DDS_RETCODE_OK) { + ret = dds_writer_lock(writer, &wr); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking writer\n"); - ret = DDS_ERRNO(rc); goto fail; } /* status = NULL, application do not need the status, but reset the counter & triggered bit */ @@ -539,14 +534,12 @@ dds_get_offered_deadline_missed_status( dds_entity_t writer, dds_offered_deadline_missed_status_t *status) { - dds_retcode_t rc; dds_writer *wr; - dds_return_t ret = DDS_RETCODE_OK; + dds_return_t ret; - rc = dds_writer_lock(writer, &wr); - if (rc != DDS_RETCODE_OK) { + ret = dds_writer_lock(writer, &wr); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking writer\n"); - ret = DDS_ERRNO(rc); goto fail; } /* status = NULL, application do not need the status, but reset the counter & triggered bit */ @@ -569,14 +562,12 @@ dds_get_offered_incompatible_qos_status ( dds_entity_t writer, dds_offered_incompatible_qos_status_t * status) { - dds_retcode_t rc; dds_writer *wr; - dds_return_t ret = DDS_RETCODE_OK; + dds_return_t ret; - rc = dds_writer_lock(writer, &wr); - if (rc != DDS_RETCODE_OK) { + ret = dds_writer_lock(writer, &wr); + if (ret != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking writer\n"); - ret = DDS_ERRNO(rc); goto fail; } /* status = NULL, application do not need the status, but reset the counter & triggered bit */ diff --git a/src/core/ddsc/tests/config.c b/src/core/ddsc/tests/config.c index b751a2c..76f92b0 100644 --- a/src/core/ddsc/tests/config.c +++ b/src/core/ddsc/tests/config.c @@ -49,7 +49,7 @@ static void config__check_env( } if ( !env_ok ) { - dds_retcode_t r; + dds_return_t r; r = ddsrt_setenv(env_variable, expected_value); CU_ASSERT_EQUAL_FATAL(r, DDS_RETCODE_OK); diff --git a/src/core/ddsc/tests/dispose.c b/src/core/ddsc/tests/dispose.c index 0e10c60..2df1714 100644 --- a/src/core/ddsc/tests/dispose.c +++ b/src/core/ddsc/tests/dispose.c @@ -153,7 +153,7 @@ CU_Test(ddsc_writedispose, deleted, .init=disposing_init, .fini=disposing_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_writedispose(g_writer, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -164,7 +164,7 @@ CU_Test(ddsc_writedispose, null, .init=disposing_init, .fini=disposing_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_writedispose(g_writer, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -174,13 +174,12 @@ CU_TheoryDataPoints(ddsc_writedispose, invalid_writers) = { }; CU_Theory((dds_entity_t writer), ddsc_writedispose, invalid_writers, .init=disposing_init, .fini=disposing_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_writedispose(writer, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -194,7 +193,7 @@ CU_Theory((dds_entity_t *writer), ddsc_writedispose, non_writers, .init=disposin DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_writedispose(*writer, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -290,7 +289,7 @@ CU_Test(ddsc_writedispose, timeout, .init=disposing_init, .fini=disposing_fini) ret = dds_writedispose(g_writer, &newInstance1); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_writedispose(g_writer, &newInstance2); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_TIMEOUT); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_TIMEOUT); } /*************************************************************************************************/ @@ -310,7 +309,7 @@ CU_Test(ddsc_writedispose_ts, deleted, .init=disposing_init, .fini=disposing_fin DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_writedispose_ts(g_writer, NULL, g_present); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -321,7 +320,7 @@ CU_Test(ddsc_writedispose_ts, null, .init=disposing_init, .fini=disposing_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_writedispose_ts(g_writer, NULL, g_present); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -335,7 +334,7 @@ CU_Test(ddsc_writedispose_ts, timeout, .init=disposing_init, .fini=disposing_fin ret = dds_writedispose_ts(g_writer, &newInstance1, g_present); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_writedispose_ts(g_writer, &newInstance2, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_TIMEOUT); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_TIMEOUT); } /*************************************************************************************************/ @@ -345,13 +344,12 @@ CU_TheoryDataPoints(ddsc_writedispose_ts, invalid_writers) = { }; CU_Theory((dds_entity_t writer), ddsc_writedispose_ts, invalid_writers, .init=disposing_init, .fini=disposing_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_writedispose_ts(writer, NULL, g_present); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -365,7 +363,7 @@ CU_Theory((dds_entity_t *writer), ddsc_writedispose_ts, non_writers, .init=dispo DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_writedispose_ts(*writer, NULL, g_present); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -510,7 +508,7 @@ CU_Test(ddsc_dispose, deleted, .init=disposing_init, .fini=disposing_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_dispose(g_writer, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -521,7 +519,7 @@ CU_Test(ddsc_dispose, null, .init=disposing_init, .fini=disposing_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_dispose(g_writer, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -535,7 +533,7 @@ CU_Test(ddsc_dispose, timeout, .init=disposing_init, .fini=disposing_fini) ret = dds_dispose(g_writer, &newInstance1); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_dispose(g_writer, &newInstance2); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_TIMEOUT); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_TIMEOUT); } /*************************************************************************************************/ @@ -545,13 +543,12 @@ CU_TheoryDataPoints(ddsc_dispose, invalid_writers) = { }; CU_Theory((dds_entity_t writer), ddsc_dispose, invalid_writers, .init=disposing_init, .fini=disposing_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_dispose(writer, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -565,7 +562,7 @@ CU_Theory((dds_entity_t *writer), ddsc_dispose, non_writers, .init=disposing_ini DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_dispose(*writer, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -665,7 +662,7 @@ CU_Test(ddsc_dispose_ts, deleted, .init=disposing_init, .fini=disposing_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_dispose_ts(g_writer, NULL, g_present); DDSRT_WARNING_MSVC_ON(6387); /* Disable SAL warning on intentional misuse of the API */ - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -676,7 +673,7 @@ CU_Test(ddsc_dispose_ts, null, .init=disposing_init, .fini=disposing_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_dispose_ts(g_writer, NULL, g_present); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -690,7 +687,7 @@ CU_Test(ddsc_dispose_ts, timeout, .init=disposing_init, .fini=disposing_fini) ret = dds_dispose_ts(g_writer, &newInstance1, g_present); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_dispose_ts(g_writer, &newInstance2, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_TIMEOUT); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_TIMEOUT); } /*************************************************************************************************/ @@ -700,13 +697,12 @@ CU_TheoryDataPoints(ddsc_dispose_ts, invalid_writers) = { }; CU_Theory((dds_entity_t writer), ddsc_dispose_ts, invalid_writers, .init=disposing_init, .fini=disposing_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_dispose_ts(writer, NULL, g_present); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -720,7 +716,7 @@ CU_Theory((dds_entity_t *writer), ddsc_dispose_ts, non_writers, .init=disposing_ DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_dispose_ts(*writer, NULL, g_present); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -861,7 +857,7 @@ CU_Test(ddsc_dispose_ih, deleted, .init=disposing_init, .fini=disposing_fini) dds_return_t ret; dds_delete(g_writer); ret = dds_dispose_ih(g_writer, DDS_HANDLE_NIL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -873,7 +869,7 @@ CU_Theory((dds_instance_handle_t handle), ddsc_dispose_ih, invalid_handles, .ini { dds_return_t ret; ret = dds_dispose_ih(g_writer, handle); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -883,11 +879,10 @@ CU_TheoryDataPoints(ddsc_dispose_ih, invalid_writers) = { }; CU_Theory((dds_entity_t writer), ddsc_dispose_ih, invalid_writers, .init=disposing_init, .fini=disposing_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_dispose_ih(writer, DDS_HANDLE_NIL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -899,7 +894,7 @@ CU_Theory((dds_entity_t *writer), ddsc_dispose_ih, non_writers, .init=disposing_ { dds_return_t ret; ret = dds_dispose_ih(*writer, DDS_HANDLE_NIL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -959,7 +954,7 @@ CU_Test(ddsc_dispose_ih_ts, deleted, .init=disposing_init, .fini=disposing_fini) dds_return_t ret; dds_delete(g_writer); ret = dds_dispose_ih_ts(g_writer, DDS_HANDLE_NIL, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -971,7 +966,7 @@ CU_Theory((dds_instance_handle_t handle), ddsc_dispose_ih_ts, invalid_handles, . { dds_return_t ret; ret = dds_dispose_ih_ts(g_writer, handle, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -981,11 +976,10 @@ CU_TheoryDataPoints(ddsc_dispose_ih_ts, invalid_writers) = { }; CU_Theory((dds_entity_t writer), ddsc_dispose_ih_ts, invalid_writers, .init=disposing_init, .fini=disposing_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_dispose_ih_ts(writer, DDS_HANDLE_NIL, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -997,7 +991,7 @@ CU_Theory((dds_entity_t *writer), ddsc_dispose_ih_ts, non_writers, .init=disposi { dds_return_t ret; ret = dds_dispose_ih_ts(*writer, DDS_HANDLE_NIL, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/entity_api.c b/src/core/ddsc/tests/entity_api.c index 8befa14..fa098b5 100644 --- a/src/core/ddsc/tests/entity_api.c +++ b/src/core/ddsc/tests/entity_api.c @@ -23,8 +23,6 @@ static dds_entity_t entity = -1; -#define cu_assert_status_eq(s1, s2) CU_ASSERT_FATAL(dds_err_nr(s1)== s2) - /* Fixture to create prerequisite entity */ void create_entity(void) { @@ -38,7 +36,7 @@ void delete_entity(void) { CU_ASSERT_FATAL(entity > 0); dds_return_t ret = dds_delete(entity); - cu_assert_status_eq(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); entity = -1; } @@ -55,17 +53,17 @@ CU_Test(ddsc_entity, enable, .init = create_entity, .fini = delete_entity) /* Check enabling with bad parameters. */ status = dds_enable(0); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); /* Check actual enabling. */ /* TODO: CHAM-96: Check enabling. status = dds_enable(&entity); - cu_assert_status_eq(status, dds_err_nr(DDS_RETCODE_OK), "dds_enable (delayed enable)"); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK, "dds_enable (delayed enable)"); */ /* Check re-enabling (should be a noop). */ status = dds_enable(entity); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); } void entity_qos_get_set(dds_entity_t e, const char* info) @@ -77,10 +75,10 @@ void entity_qos_get_set(dds_entity_t e, const char* info) /* Get QoS. */ status = dds_get_qos (e, qos); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); status = dds_set_qos (e, qos); /* Doesn't change anything, so no need to forbid. But we return NOT_SUPPORTED anyway for now*/ - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_UNSUPPORTED); dds_delete_qos(qos); } @@ -95,19 +93,19 @@ CU_Test(ddsc_entity, qos, .init = create_entity, .fini = delete_entity) /* Check getting QoS with bad parameters. */ status = dds_get_qos (0, NULL); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_get_qos (entity, NULL); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_get_qos (0, qos); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); /* Check setting QoS with bad parameters. */ status = dds_set_qos (0, NULL); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_set_qos (entity, NULL); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_set_qos (0, qos); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); /* Check set/get with entity without initial qos. */ entity_qos_get_set(entity, "{without initial qos}"); @@ -145,15 +143,15 @@ CU_Test(ddsc_entity, listener, .init = create_entity, .fini = delete_entity) /* Check getting Listener with bad parameters. */ status = dds_get_listener (0, NULL); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_get_listener (entity, NULL); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_get_listener (0, l1); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); /* Get Listener, which should be unset. */ status = dds_get_listener (entity, l1); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); dds_lget_liveliness_changed (l1, (dds_on_liveliness_changed_fn*)&cb1); CU_ASSERT_EQUAL_FATAL(cb1, DDS_LUNSET); dds_lget_requested_deadline_missed (l1, (dds_on_requested_deadline_missed_fn*)&cb1); @@ -165,15 +163,15 @@ CU_Test(ddsc_entity, listener, .init = create_entity, .fini = delete_entity) /* Check setting Listener with bad parameters. */ status = dds_set_listener (0, NULL); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_set_listener (0, l2); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); /* Getting after setting should return set listener. */ status = dds_set_listener (entity, l2); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); status = dds_get_listener (entity, l1); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); dds_lget_liveliness_changed (l1, (dds_on_liveliness_changed_fn*)&cb1); dds_lget_liveliness_changed (l2, (dds_on_liveliness_changed_fn*)&cb2); CU_ASSERT_EQUAL_FATAL(cb1, cb2); @@ -189,9 +187,9 @@ CU_Test(ddsc_entity, listener, .init = create_entity, .fini = delete_entity) /* Reset listener. */ status = dds_set_listener (entity, NULL); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); status = dds_get_listener (entity, l2); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); dds_lget_liveliness_changed (l2, (dds_on_liveliness_changed_fn*)&cb2); CU_ASSERT_EQUAL_FATAL(cb2, DDS_LUNSET); dds_lget_requested_deadline_missed (l2, (dds_on_requested_deadline_missed_fn*)&cb2); @@ -215,46 +213,46 @@ CU_Test(ddsc_entity, status, .init = create_entity, .fini = delete_entity) /* Check getting Status with bad parameters. */ status1 = dds_get_status_mask (0, NULL); - cu_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_BAD_PARAMETER); status1 = dds_get_status_mask (entity, NULL); - cu_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_BAD_PARAMETER); status1 = dds_get_status_mask (0, &s1); - cu_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_BAD_PARAMETER); /* Get Status, which should be 0 for a participant. */ status1 = dds_get_status_mask (entity, &s1); - cu_assert_status_eq(status1, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(s1, 0); /* Check setting Status with bad parameters. */ status1 = dds_set_status_mask (0, 0); - cu_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_BAD_PARAMETER); /* I shouldn't be able to set statuses on a participant. */ status1 = dds_set_status_mask (entity, 0); - cu_assert_status_eq(status1, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_OK); status1 = dds_set_status_mask (entity, DDS_DATA_AVAILABLE_STATUS); - cu_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_BAD_PARAMETER); /* Check getting Status changes with bad parameters. */ status1 = dds_get_status_changes (0, NULL); - cu_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_BAD_PARAMETER); status1 = dds_get_status_changes (entity, NULL); - cu_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_BAD_PARAMETER); status1 = dds_get_status_changes (0, &s1); - cu_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_BAD_PARAMETER); status1 = dds_get_status_changes (entity, &s1); - cu_assert_status_eq(status1, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_OK); /* Status read and take shouldn't work either. */ status1 = dds_read_status (0, &s1, 0); - cu_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_BAD_PARAMETER); status1 = dds_read_status (entity, &s1, 0); - cu_assert_status_eq(status1, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_OK); status1 = dds_take_status (0, &s1, 0); - cu_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_BAD_PARAMETER); status1 = dds_take_status (entity, &s1, 0); - cu_assert_status_eq(status1, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status1, DDS_RETCODE_OK); } @@ -268,15 +266,15 @@ CU_Test(ddsc_entity, instance_handle, .init = create_entity, .fini = delete_enti /* Check getting Handle with bad parameters. */ status = dds_get_instance_handle (0, NULL); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_get_instance_handle (entity, NULL); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_get_instance_handle (0, &hdl); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); /* Get Instance Handle, which should not be 0 for a participant. */ status = dds_get_instance_handle (entity, &hdl); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); CU_ASSERT_NOT_EQUAL_FATAL(hdl, 0); } @@ -290,17 +288,17 @@ CU_Test(ddsc_entity, get_entities, .init = create_entity, .fini = delete_entity) /* Check getting Parent with bad parameters. */ par = dds_get_parent (0); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(par), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(par, DDS_RETCODE_BAD_PARAMETER); /* Get Parent, a participant doesn't have a parent. */ par = dds_get_parent (entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(par), DDS_ENTITY_NIL); + CU_ASSERT_EQUAL_FATAL(par, DDS_ENTITY_NIL); /* ---------- Get Participant ------------ */ /* Check getting Participant with bad parameters. */ par = dds_get_participant (0); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(par), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(par, DDS_RETCODE_BAD_PARAMETER); /* Get Participant, a participants' participant is itself. */ par = dds_get_participant (entity); @@ -310,15 +308,15 @@ CU_Test(ddsc_entity, get_entities, .init = create_entity, .fini = delete_entity) /* Check getting Children with bad parameters. */ status = dds_get_children (0, &child, 1); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_get_children (entity, NULL, 1); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_get_children (entity, &child, 0); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_get_children (0, NULL, 1); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_get_children (0, &child, 0); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); /* Get Children, of which there are currently none. */ status = dds_get_children (entity, NULL, 0); @@ -342,15 +340,15 @@ CU_Test(ddsc_entity, get_domainid, .init = create_entity, .fini = delete_entity) /* Check getting ID with bad parameters. */ status = dds_get_domainid (0, NULL); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_get_domainid (entity, NULL); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_get_domainid (0, &id); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); /* Get and check the domain id. */ status = dds_get_domainid (entity, &id); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); CU_ASSERT_FATAL(id != -1); } @@ -358,10 +356,10 @@ CU_Test(ddsc_entity, delete, .init = create_entity) { dds_return_t status; status = dds_delete(0); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); status = dds_delete(entity); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); entity = 0; } diff --git a/src/core/ddsc/tests/entity_hierarchy.c b/src/core/ddsc/tests/entity_hierarchy.c index ec7e2dc..a54f3cd 100644 --- a/src/core/ddsc/tests/entity_hierarchy.c +++ b/src/core/ddsc/tests/entity_hierarchy.c @@ -125,43 +125,43 @@ CU_Test(ddsc_entity_delete, recursive, .init=hierarchy_init, .fini=hierarchy_fin /* First be sure that 'dds_get_domainid' returns ok. */ ret = dds_get_domainid(g_participant, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_get_domainid(g_topic, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_get_domainid(g_publisher, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_get_domainid(g_subscriber, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_get_domainid(g_writer, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_get_domainid(g_reader, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_get_domainid(g_readcond, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_get_domainid(g_querycond, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); /* Deleting the top dog (participant) should delete all children. */ ret = dds_delete(g_participant); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); /* Check if all the entities are deleted now. */ ret = dds_get_domainid(g_participant, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_topic, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_publisher, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_subscriber, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_writer, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_reader, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_readcond, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_querycond, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -190,22 +190,22 @@ CU_Test(ddsc_entity_delete, recursive_with_deleted_topic) * reference to the topic and thus will delete it when it itself is * deleted. */ ret = dds_delete(g_topic); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); /* Third, deleting the participant should delete all children of which * the writer with the last topic reference is one. */ ret = dds_delete(g_participant); /* Before the CHAM-424 fix, we would not get here because of a crash, * or it (incidentally) continued but returned an error. */ - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); /* Check if the entities are actually deleted. */ ret = dds_get_domainid(g_participant, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER ); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER ); ret = dds_get_domainid(g_topic, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_writer, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); dds_delete(g_keep); } @@ -240,7 +240,7 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_participant, deleted_entities, dds_entity_t participant; dds_delete(*entity); participant = dds_get_participant(*entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(participant), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -250,11 +250,10 @@ CU_TheoryDataPoints(ddsc_entity_get_participant, invalid_entities) = { }; CU_Theory((dds_entity_t entity), ddsc_entity_get_participant, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_entity_t participant; participant = dds_get_participant(entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(participant), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -314,7 +313,7 @@ CU_Test(ddsc_entity_get_parent, participant, .init=hierarchy_init, .fini=hierarc { dds_entity_t parent; parent = dds_get_parent(g_participant); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(parent), DDS_ENTITY_NIL); + CU_ASSERT_EQUAL_FATAL(parent, DDS_ENTITY_NIL); } /*************************************************************************************************/ @@ -327,7 +326,7 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_parent, deleted_entities, .ini dds_entity_t parent; dds_delete(*entity); parent = dds_get_parent(*entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(parent), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(parent, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -337,11 +336,10 @@ CU_TheoryDataPoints(ddsc_entity_get_parent, invalid_entities) = { }; CU_Theory((dds_entity_t entity), ddsc_entity_get_parent, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_entity_t parent; parent = dds_get_parent(entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(parent), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(parent, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -369,7 +367,7 @@ CU_Test(ddsc_entity_get_children, invalid_size, .init=hierarchy_init, .fini=hier dds_return_t ret; dds_entity_t child; ret = dds_get_children(g_participant, &child, INT32_MAX); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -478,7 +476,7 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_children, deleted_entities, .i dds_entity_t children[4]; dds_delete(*entity); ret = dds_get_children(*entity, children, 4); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -488,12 +486,11 @@ CU_TheoryDataPoints(ddsc_entity_get_children, invalid_entities) = { }; CU_Theory((dds_entity_t entity), ddsc_entity_get_children, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_entity_t children[4]; dds_return_t ret; ret = dds_get_children(entity, children, 4); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -527,7 +524,7 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_topic, deleted_entities, .init dds_entity_t topic; dds_delete(*entity); topic = dds_get_topic(*entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(topic, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -537,11 +534,10 @@ CU_TheoryDataPoints(ddsc_entity_get_topic, invalid_entities) = { }; CU_Theory((dds_entity_t entity), ddsc_entity_get_topic, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_entity_t topic; topic = dds_get_topic(entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(topic, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -553,7 +549,7 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_topic, non_data_entities, .ini { dds_entity_t topic; topic = dds_get_topic(*entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(topic, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -581,7 +577,7 @@ CU_Test(ddsc_entity_get_publisher, deleted_writer, .init=hierarchy_init, .fini=h dds_entity_t publisher; dds_delete(g_writer); publisher = dds_get_publisher(g_writer); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(publisher), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(publisher, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -591,11 +587,10 @@ CU_TheoryDataPoints(ddsc_entity_get_publisher, invalid_writers) = { }; CU_Theory((dds_entity_t entity), ddsc_entity_get_publisher, invalid_writers, .init=hierarchy_init, .fini=hierarchy_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_entity_t publisher; publisher = dds_get_publisher(entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(publisher), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(publisher, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -607,7 +602,7 @@ CU_Theory((dds_entity_t *cond), ddsc_entity_get_publisher, non_writers, .init=hi { dds_entity_t publisher; publisher = dds_get_publisher(*cond); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(publisher), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(publisher, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -640,7 +635,7 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_subscriber, deleted_readers, . dds_entity_t subscriber; dds_delete(*entity); subscriber = dds_get_subscriber(*entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(subscriber), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(subscriber, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -650,11 +645,10 @@ CU_TheoryDataPoints(ddsc_entity_get_subscriber, invalid_readers) = { }; CU_Theory((dds_entity_t entity), ddsc_entity_get_subscriber, invalid_readers, .init=hierarchy_init, .fini=hierarchy_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_entity_t subscriber; subscriber = dds_get_subscriber(entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(subscriber), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(subscriber, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -666,7 +660,7 @@ CU_Theory((dds_entity_t *cond), ddsc_entity_get_subscriber, non_readers, .init=h { dds_entity_t subscriber; subscriber = dds_get_subscriber(*cond); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(subscriber), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(subscriber, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -701,7 +695,7 @@ CU_Theory((dds_entity_t *cond), ddsc_entity_get_datareader, deleted_conds, .init dds_entity_t reader; dds_delete(*cond); reader = dds_get_datareader(*cond); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(reader), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(reader, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -711,11 +705,10 @@ CU_TheoryDataPoints(ddsc_entity_get_datareader, invalid_conds) = { }; CU_Theory((dds_entity_t cond), ddsc_entity_get_datareader, invalid_conds, .init=hierarchy_init, .fini=hierarchy_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_entity_t reader; reader = dds_get_datareader(cond); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(reader), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(reader, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -727,7 +720,7 @@ CU_Theory((dds_entity_t *cond), ddsc_entity_get_datareader, non_conds, .init=hie { dds_entity_t reader; reader = dds_get_datareader(*cond); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(reader), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(reader, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -954,7 +947,7 @@ CU_Test(ddsc_entity_get_parent, implicit_publisher) dds_delete(writer); ret = dds_delete(parent); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); dds_delete(participant); } /*************************************************************************************************/ @@ -985,7 +978,7 @@ CU_Test(ddsc_entity_get_parent, implicit_subscriber) dds_delete(reader); ret = dds_delete(parent); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); dds_delete(participant); } diff --git a/src/core/ddsc/tests/entity_status.c b/src/core/ddsc/tests/entity_status.c index 45883fe..737fbf7 100644 --- a/src/core/ddsc/tests/entity_status.c +++ b/src/core/ddsc/tests/entity_status.c @@ -141,7 +141,7 @@ CU_Test(ddsc_entity_status, publication_matched, .init=init_entity_status, .fini /* Getting the status should have reset the trigger, * meaning that the wait should timeout. */ ret = dds_waitset_wait(waitSetwr, wsresults, wsresultsize, shortTimeout); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); /* Un-match the publication by deleting the reader. */ dds_delete(rea); @@ -178,7 +178,7 @@ CU_Test(ddsc_entity_status, subscription_matched, .init=init_entity_status, .fin /* Getting the status should have reset the trigger, * meaning that the wait should timeout. */ ret = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); /* Un-match the subscription by deleting the writer. */ dds_delete(wri); @@ -233,7 +233,7 @@ CU_Test(ddsc_entity, incompatible_qos, .init=init_entity_status, .fini=fini_enti /*Getting the status should have reset the trigger, waitset should timeout */ ret = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); /* Wait for offered incompatible QoS status */ ret = dds_waitset_wait(waitSetwr, wsresults, wsresultsize, waitTimeout); @@ -246,7 +246,7 @@ CU_Test(ddsc_entity, incompatible_qos, .init=init_entity_status, .fini=fini_enti /*Getting the status should have reset the trigger, waitset should timeout */ ret = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); ret = dds_waitset_detach(waitSetrd, reader2); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); @@ -280,7 +280,7 @@ CU_Test(ddsc_entity, liveliness_changed, .init=init_entity_status, .fini=fini_en /*Getting the status should have reset the trigger, waitset should timeout */ ret = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); /* Reset writer */ ret = dds_waitset_detach(waitSetwr, wri); @@ -341,7 +341,7 @@ CU_Test(ddsc_entity, sample_rejected, .init=init_entity_status, .fini=fini_entit /*Getting the status should have reset the trigger, waitset should timeout */ ret = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); } #if 0 @@ -370,7 +370,7 @@ Test(ddsc_entity, inconsistent_topic) /*Getting the status should have reset the trigger, waitset should timeout */ status = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), 0, "returned %d", dds_err_nr(status)); + CU_ASSERT_EQUAL_FATAL(status, 0, "returned %d", status); /* Wait for sub inconsistent topic status callback */ ret = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, waitTimeout); @@ -381,7 +381,7 @@ Test(ddsc_entity, inconsistent_topic) /*Getting the status should have reset the trigger, waitset should timeout */ status = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), 0); + CU_ASSERT_EQUAL_FATAL(status, 0); dds_delete(top); } @@ -431,7 +431,7 @@ CU_Test(ddsc_entity, sample_lost, .init=init_entity_status, .fini=fini_entity_st /*Getting the status should have reset the trigger, waitset should timeout */ ret = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); } @@ -594,10 +594,9 @@ CU_TheoryDataPoints(ddsc_get_enabled_status, bad_param) = { CU_Theory((dds_entity_t e), ddsc_get_enabled_status, bad_param, .init=init_entity_status, .fini=fini_entity_status) { uint32_t mask; - dds_return_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_get_status_mask(e, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_get_enabled_status, deleted_reader, .init=init_entity_status, .fini=fini_entity_status) @@ -605,14 +604,14 @@ CU_Test(ddsc_get_enabled_status, deleted_reader, .init=init_entity_status, .fini uint32_t mask; dds_delete(rea); ret = dds_get_status_mask(rea, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_get_enabled_status, illegal, .init=init_entity_status, .fini=fini_entity_status) { uint32_t mask; ret = dds_get_status_mask(waitSetrd, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } CU_TheoryDataPoints(ddsc_get_enabled_status, status_ok) = { @@ -632,23 +631,21 @@ CU_TheoryDataPoints(ddsc_set_enabled_status, bad_param) = { }; CU_Theory((dds_entity_t e), ddsc_set_enabled_status, bad_param, .init=init_entity_status, .fini=fini_entity_status) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; - ret = dds_set_status_mask(e, 0 /*mask*/); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_set_enabled_status, deleted_reader, .init=init_entity_status, .fini=fini_entity_status) { dds_delete(rea); ret = dds_set_status_mask(rea, 0 /*mask*/); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_set_enabled_status, illegal, .init=init_entity_status, .fini=fini_entity_status) { ret = dds_set_status_mask(waitSetrd, 0); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } CU_TheoryDataPoints(ddsc_set_enabled_status, status_ok) = { @@ -668,10 +665,9 @@ CU_TheoryDataPoints(ddsc_read_status, bad_param) = { CU_Theory((dds_entity_t e), ddsc_read_status, bad_param, .init=init_entity_status, .fini=fini_entity_status) { uint32_t status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_read_status(e, &status, 0 /*mask*/); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_read_status, deleted_reader, .init=init_entity_status, .fini=fini_entity_status) @@ -679,14 +675,14 @@ CU_Test(ddsc_read_status, deleted_reader, .init=init_entity_status, .fini=fini_e uint32_t status; dds_delete(rea); ret = dds_read_status(rea, &status, 0 /*mask*/); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_read_status, illegal, .init=init_entity_status, .fini=fini_entity_status) { uint32_t status; ret = dds_read_status(waitSetrd, &status, 0); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } CU_TheoryDataPoints(ddsc_read_status, status_ok) = { CU_DataPoints(dds_entity_t *,&rea, &wri, &participant, &top, &publisher, &subscriber), @@ -702,14 +698,14 @@ CU_Test(ddsc_read_status, invalid_status_on_reader, .init=init_entity_status, .f { uint32_t status; ret = dds_read_status(rea, &status, DDS_PUBLICATION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_read_status, invalid_status_on_writer, .init=init_entity_status, .fini=fini_entity_status) { uint32_t status; ret = dds_read_status(wri, &status, DDS_SUBSCRIPTION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -720,10 +716,9 @@ CU_TheoryDataPoints(ddsc_take_status, bad_param) = { CU_Theory((dds_entity_t e), ddsc_take_status, bad_param, .init=init_entity_status, .fini=fini_entity_status) { uint32_t status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_take_status(e, &status, 0 /*mask*/); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_take_status, deleted_reader, .init=init_entity_status, .fini=fini_entity_status) @@ -731,13 +726,13 @@ CU_Test(ddsc_take_status, deleted_reader, .init=init_entity_status, .fini=fini_e uint32_t status; dds_delete(rea); ret = dds_take_status(rea, &status, 0 /*mask*/); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_take_status, illegal, .init=init_entity_status, .fini=fini_entity_status) { uint32_t status; ret = dds_take_status(waitSetrd, &status, 0); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } CU_TheoryDataPoints(ddsc_take_status, status_ok) = { @@ -759,10 +754,9 @@ CU_TheoryDataPoints(ddsc_get_status_changes, bad_param) = { CU_Theory((dds_entity_t e), ddsc_get_status_changes, bad_param, .init=init_entity_status, .fini=fini_entity_status) { uint32_t status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_get_status_changes(e, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_get_status_changes, deleted_reader, .init=init_entity_status, .fini=fini_entity_status) @@ -770,14 +764,14 @@ CU_Test(ddsc_get_status_changes, deleted_reader, .init=init_entity_status, .fini uint32_t status; dds_delete(rea); ret = dds_get_status_changes(rea, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_get_status_changes, illegal, .init=init_entity_status, .fini=fini_entity_status) { uint32_t status; ret = dds_get_status_changes(waitSetrd, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } CU_TheoryDataPoints(ddsc_get_status_changes, status_ok) = { @@ -797,17 +791,15 @@ CU_TheoryDataPoints(ddsc_triggered, bad_param) = { }; CU_Theory((dds_entity_t e), ddsc_triggered, bad_param, .init=init_entity_status, .fini=fini_entity_status) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; - ret = dds_triggered(e); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_triggered, deleted_reader, .init=init_entity_status, .fini=fini_entity_status) { dds_delete(rea); ret = dds_triggered(rea); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_TheoryDataPoints(ddsc_triggered, status_ok) = { @@ -825,7 +817,7 @@ CU_Test(ddsc_get_inconsistent_topic_status, inconsistent_topic_status, .init=ini { dds_inconsistent_topic_status_t inconsistent_topic_status; ret = dds_get_inconsistent_topic_status(top, &inconsistent_topic_status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(inconsistent_topic_status.total_count, 0); CU_ASSERT_EQUAL_FATAL(inconsistent_topic_status.total_count_change, 0); } @@ -838,10 +830,9 @@ CU_TheoryDataPoints(ddsc_get_inconsistent_topic_status, bad_params) = { CU_Theory((dds_entity_t topic), ddsc_get_inconsistent_topic_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_inconsistent_topic_status_t topic_status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_get_inconsistent_topic_status(topic, &topic_status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -850,7 +841,7 @@ CU_Test(ddsc_get_inconsistent_topic_status, null, .init=init_entity_status, .fin { dds_set_status_mask(top, 0); ret = dds_get_inconsistent_topic_status(top, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); } /*************************************************************************************************/ @@ -861,7 +852,7 @@ CU_TheoryDataPoints(ddsc_get_inconsistent_topic_status, non_topics) = { CU_Theory((dds_entity_t *topic), ddsc_get_inconsistent_topic_status, non_topics, .init=init_entity_status, .fini=fini_entity_status) { ret = dds_get_inconsistent_topic_status(*topic, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -870,7 +861,7 @@ CU_Test(ddsc_get_inconsistent_topic_status, deleted_topic, .init=init_entity_sta { dds_delete(top); ret = dds_get_inconsistent_topic_status(top, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); } /*************************************************************************************************/ @@ -881,10 +872,9 @@ CU_TheoryDataPoints(ddsc_get_publication_matched_status, bad_params) = { CU_Theory((dds_entity_t writer), ddsc_get_publication_matched_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_publication_matched_status_t status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_get_publication_matched_status(writer, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -893,7 +883,7 @@ CU_Test(ddsc_get_publication_matched_status, null, .init=init_entity_status, .fi { dds_set_status_mask(wri, 0); ret = dds_get_publication_matched_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); } /*************************************************************************************************/ @@ -904,7 +894,7 @@ CU_TheoryDataPoints(ddsc_get_publication_matched_status, non_writers) = { CU_Theory((dds_entity_t *writer), ddsc_get_publication_matched_status, non_writers, .init=init_entity_status, .fini=fini_entity_status) { ret = dds_get_publication_matched_status(*writer, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -913,7 +903,7 @@ CU_Test(ddsc_get_publication_matched_status, deleted_writer, .init=init_entity_s { dds_delete(wri); ret = dds_get_publication_matched_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -922,7 +912,7 @@ CU_Test(ddsc_get_liveliness_lost_status, liveliness_lost_status, .init=init_enti { dds_liveliness_lost_status_t liveliness_lost_status; ret = dds_get_liveliness_lost_status(wri, &liveliness_lost_status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(liveliness_lost_status.total_count, 0); CU_ASSERT_EQUAL_FATAL(liveliness_lost_status.total_count_change, 0); } @@ -935,10 +925,9 @@ CU_TheoryDataPoints(ddsc_get_liveliness_lost_status, bad_params) = { CU_Theory((dds_entity_t writer), ddsc_get_liveliness_lost_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_liveliness_lost_status_t status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_get_liveliness_lost_status(writer, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -947,7 +936,7 @@ CU_Test(ddsc_get_liveliness_lost_status, null, .init=init_entity_status, .fini=f { dds_set_status_mask(wri, 0); ret = dds_get_liveliness_lost_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); } /*************************************************************************************************/ @@ -958,7 +947,7 @@ CU_TheoryDataPoints(ddsc_get_liveliness_lost_status, non_writers) = { CU_Theory((dds_entity_t *writer), ddsc_get_liveliness_lost_status, non_writers, .init=init_entity_status, .fini=fini_entity_status) { ret = dds_get_liveliness_lost_status(*writer, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -967,7 +956,7 @@ CU_Test(ddsc_get_liveliness_lost_status, deleted_writer, .init=init_entity_statu { dds_delete(wri); ret = dds_get_liveliness_lost_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -976,7 +965,7 @@ CU_Test(ddsc_get_offered_deadline_missed_status, offered_deadline_missed_status, { dds_offered_deadline_missed_status_t offered_deadline_missed_status; ret = dds_get_offered_deadline_missed_status(wri, &offered_deadline_missed_status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(offered_deadline_missed_status.total_count, 0); CU_ASSERT_EQUAL_FATAL(offered_deadline_missed_status.total_count_change, 0); CU_ASSERT_EQUAL_FATAL(offered_deadline_missed_status.last_instance_handle, 0); @@ -990,10 +979,9 @@ CU_TheoryDataPoints(ddsc_get_offered_deadline_missed_status, bad_params) = { CU_Theory((dds_entity_t writer), ddsc_get_offered_deadline_missed_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_offered_deadline_missed_status_t status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_get_offered_deadline_missed_status(writer, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1002,7 +990,7 @@ CU_Test(ddsc_get_offered_deadline_missed_status, null, .init=init_entity_status, { dds_set_status_mask(wri, 0); ret = dds_get_offered_deadline_missed_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); } /*************************************************************************************************/ @@ -1013,7 +1001,7 @@ CU_TheoryDataPoints(ddsc_get_offered_deadline_missed_status, non_writers) = { CU_Theory((dds_entity_t *writer), ddsc_get_offered_deadline_missed_status, non_writers, .init=init_entity_status, .fini=fini_entity_status) { ret = dds_get_offered_deadline_missed_status(*writer, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -1022,7 +1010,7 @@ CU_Test(ddsc_get_offered_deadline_missed_status, deleted_writer, .init=init_enti { dds_delete(wri); ret = dds_get_offered_deadline_missed_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1033,10 +1021,9 @@ CU_TheoryDataPoints(ddsc_get_offered_incompatible_qos_status, bad_params) = { CU_Theory((dds_entity_t writer), ddsc_get_offered_incompatible_qos_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_offered_incompatible_qos_status_t status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_get_offered_incompatible_qos_status(writer, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1045,7 +1032,7 @@ CU_Test(ddsc_get_offered_incompatible_qos_status, null, .init=init_entity_status { dds_set_status_mask(wri, 0); ret = dds_get_offered_incompatible_qos_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); } /*************************************************************************************************/ @@ -1056,7 +1043,7 @@ CU_TheoryDataPoints(ddsc_get_offered_incompatible_qos_status, non_writers) = { CU_Theory((dds_entity_t *writer), ddsc_get_offered_incompatible_qos_status, non_writers, .init=init_entity_status, .fini=fini_entity_status) { ret = dds_get_offered_incompatible_qos_status(*writer, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -1065,7 +1052,7 @@ CU_Test(ddsc_get_offered_incompatible_qos_status, deleted_writer, .init=init_ent { dds_delete(wri); ret = dds_get_offered_incompatible_qos_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1076,10 +1063,9 @@ CU_TheoryDataPoints(ddsc_get_subscription_matched_status, bad_params) = { CU_Theory((dds_entity_t reader), ddsc_get_subscription_matched_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_subscription_matched_status_t status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_get_subscription_matched_status(reader, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1088,7 +1074,7 @@ CU_Test(ddsc_get_subscription_matched_status, null, .init=init_entity_status, .f { dds_set_status_mask(rea, 0); ret = dds_get_subscription_matched_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); } /*************************************************************************************************/ @@ -1099,7 +1085,7 @@ CU_TheoryDataPoints(ddsc_get_subscription_matched_status, non_readers) = { CU_Theory((dds_entity_t *reader), ddsc_get_subscription_matched_status, non_readers, .init=init_entity_status, .fini=fini_entity_status) { ret = dds_get_subscription_matched_status(*reader, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -1108,7 +1094,7 @@ CU_Test(ddsc_get_subscription_matched_status, deleted_reader, .init=init_entity_ { dds_delete(rea); ret = dds_get_subscription_matched_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1119,10 +1105,9 @@ CU_TheoryDataPoints(ddsc_get_liveliness_changed_status, bad_params) = { CU_Theory((dds_entity_t reader), ddsc_get_liveliness_changed_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_liveliness_changed_status_t status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_get_liveliness_changed_status(reader, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1131,7 +1116,7 @@ CU_Test(ddsc_get_liveliness_changed_status, null, .init=init_entity_status, .fin { dds_set_status_mask(rea, 0); ret = dds_get_liveliness_changed_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); } /*************************************************************************************************/ @@ -1142,7 +1127,7 @@ CU_TheoryDataPoints(ddsc_get_liveliness_changed_status, non_readers) = { CU_Theory((dds_entity_t *reader), ddsc_get_liveliness_changed_status, non_readers, .init=init_entity_status, .fini=fini_entity_status) { ret = dds_get_liveliness_changed_status(*reader, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -1151,7 +1136,7 @@ CU_Test(ddsc_get_liveliness_changed_status, deleted_reader, .init=init_entity_st { dds_delete(rea); ret = dds_get_liveliness_changed_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1162,10 +1147,9 @@ CU_TheoryDataPoints(ddsc_get_sample_rejected_status, bad_params) = { CU_Theory((dds_entity_t reader), ddsc_get_sample_rejected_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_sample_rejected_status_t status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_get_sample_rejected_status(reader, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1174,7 +1158,7 @@ CU_Test(ddsc_get_sample_rejected_status, null, .init=init_entity_status, .fini=f { dds_set_status_mask(rea, 0); ret = dds_get_sample_rejected_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); } /*************************************************************************************************/ @@ -1185,7 +1169,7 @@ CU_TheoryDataPoints(ddsc_get_sample_rejected_status, non_readers) = { CU_Theory((dds_entity_t *reader), ddsc_get_sample_rejected_status, non_readers, .init=init_entity_status, .fini=fini_entity_status) { ret = dds_get_sample_rejected_status(*reader, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -1194,7 +1178,7 @@ CU_Test(ddsc_get_sample_rejected_status, deleted_reader, .init=init_entity_statu { dds_delete(rea); ret = dds_get_sample_rejected_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1205,10 +1189,9 @@ CU_TheoryDataPoints(ddsc_get_sample_lost_status, bad_params) = { CU_Theory((dds_entity_t reader), ddsc_get_sample_lost_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_sample_lost_status_t status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_get_sample_lost_status(reader, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1217,7 +1200,7 @@ CU_Test(ddsc_get_sample_lost_status, null, .init=init_entity_status, .fini=fini_ { dds_set_status_mask(rea, 0); ret = dds_get_sample_lost_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); } /*************************************************************************************************/ @@ -1228,7 +1211,7 @@ CU_TheoryDataPoints(ddsc_get_sample_lost_status, non_readers) = { CU_Theory((dds_entity_t *reader), ddsc_get_sample_lost_status, non_readers, .init=init_entity_status, .fini=fini_entity_status) { ret = dds_get_sample_lost_status(*reader, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -1237,7 +1220,7 @@ CU_Test(ddsc_get_sample_lost_status, deleted_reader, .init=init_entity_status, . { dds_delete(rea); ret = dds_get_sample_lost_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1246,7 +1229,7 @@ CU_Test(ddsc_get_requested_deadline_missed_status, requested_deadline_missed_sta { dds_requested_deadline_missed_status_t requested_deadline_missed_status; ret = dds_get_requested_deadline_missed_status(rea, &requested_deadline_missed_status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(requested_deadline_missed_status.total_count, 0); CU_ASSERT_EQUAL_FATAL(requested_deadline_missed_status.total_count_change, 0); CU_ASSERT_EQUAL_FATAL(requested_deadline_missed_status.last_instance_handle, DDS_HANDLE_NIL); @@ -1260,10 +1243,9 @@ CU_TheoryDataPoints(ddsc_get_requested_deadline_missed_status, bad_params) = { CU_Theory((dds_entity_t reader), ddsc_get_requested_deadline_missed_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_requested_deadline_missed_status_t status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_get_requested_deadline_missed_status(reader, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1272,7 +1254,7 @@ CU_Test(ddsc_get_requested_deadline_missed_status, null, .init=init_entity_statu { dds_set_status_mask(rea, 0); ret = dds_get_requested_deadline_missed_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); } /*************************************************************************************************/ @@ -1283,7 +1265,7 @@ CU_TheoryDataPoints(ddsc_get_requested_deadline_missed_status, non_readers) = { CU_Theory((dds_entity_t *reader), ddsc_get_requested_deadline_missed_status, non_readers, .init=init_entity_status, .fini=fini_entity_status) { ret = dds_get_requested_deadline_missed_status(*reader, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -1292,7 +1274,7 @@ CU_Test(ddsc_get_requested_deadline_missed_status, deleted_reader, .init=init_en { dds_delete(rea); ret = dds_get_requested_deadline_missed_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1303,10 +1285,9 @@ CU_TheoryDataPoints(ddsc_get_requested_incompatible_qos_status, bad_params) = { CU_Theory((dds_entity_t reader), ddsc_get_requested_incompatible_qos_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_requested_incompatible_qos_status_t status; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; ret = dds_get_requested_incompatible_qos_status(reader, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1315,7 +1296,7 @@ CU_Test(ddsc_get_requested_incompatible_qos_status, null, .init=init_entity_stat { dds_set_status_mask(rea, 0); ret = dds_get_requested_incompatible_qos_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); } /*************************************************************************************************/ @@ -1326,7 +1307,7 @@ CU_TheoryDataPoints(ddsc_get_requested_incompatible_qos_status, non_readers) = { CU_Theory((dds_entity_t *reader), ddsc_get_requested_incompatible_qos_status, non_readers, .init=init_entity_status, .fini=fini_entity_status) { ret = dds_get_requested_incompatible_qos_status(*reader, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -1335,7 +1316,7 @@ CU_Test(ddsc_get_requested_incompatible_qos_status, deleted_reader, .init=init_e { dds_delete(rea); ret = dds_get_requested_incompatible_qos_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/instance_get_key.c b/src/core/ddsc/tests/instance_get_key.c index 48bd0d3..9c25d1a 100644 --- a/src/core/ddsc/tests/instance_get_key.c +++ b/src/core/ddsc/tests/instance_get_key.c @@ -63,7 +63,7 @@ CU_Test(ddsc_instance_get_key, bad_entity, .init=setup, .fini=teardown) dds_return_t ret; ret = dds_instance_get_key(participant, handle, &data); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_instance_get_key, null_data, .init=setup, .fini=teardown) @@ -71,7 +71,7 @@ CU_Test(ddsc_instance_get_key, null_data, .init=setup, .fini=teardown) dds_return_t ret; ret = dds_register_instance(writer, &handle, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_instance_get_key, null_handle, .init=setup, .fini=teardown) @@ -81,7 +81,7 @@ CU_Test(ddsc_instance_get_key, null_handle, .init=setup, .fini=teardown) CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_instance_get_key(writer, DDS_HANDLE_NIL, &data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_instance_get_key, registered_instance, .init=setup, .fini=teardown) @@ -99,7 +99,7 @@ CU_Test(ddsc_instance_get_key, registered_instance, .init=setup, .fini=teardown) CU_ASSERT_PTR_NOT_NULL_FATAL(key_data.ip); CU_ASSERT_STRING_EQUAL_FATAL(key_data.ip, data.ip); CU_ASSERT_EQUAL_FATAL(key_data.port, data.port); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); RoundTripModule_Address_free(&key_data, DDS_FREE_CONTENTS); } diff --git a/src/core/ddsc/tests/participant.c b/src/core/ddsc/tests/participant.c index 6b7155d..8225d2d 100644 --- a/src/core/ddsc/tests/participant.c +++ b/src/core/ddsc/tests/participant.c @@ -17,8 +17,6 @@ #include "dds/version.h" #include "dds/ddsrt/environ.h" -#define cu_assert_status_eq(s1, s2) CU_ASSERT_EQUAL_FATAL(dds_err_nr(s1), s2) - CU_Test(ddsc_participant, create_and_delete) { @@ -59,14 +57,14 @@ CU_Test(ddsc_participant, create_with_no_conf_no_env) participant2 = dds_create_participant (valid_domain, NULL, NULL); CU_ASSERT_FATAL(participant2 > 0); status = dds_get_domainid(participant2, &domain_id); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(domain_id, valid_domain); //DDS_DOMAIN_DEFAULT from user participant3 = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant3 > 0); status = dds_get_domainid(participant3, &domain_id); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(domain_id, valid_domain); dds_delete(participant2); @@ -98,7 +96,7 @@ CU_Test(ddsc_participant, create_with_conf_no_env) { participant2 = dds_create_participant (valid_domain, NULL, NULL); CU_ASSERT_FATAL(participant2 > 0); status = dds_get_domainid(participant2, &domain_id); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(domain_id, valid_domain); @@ -106,7 +104,7 @@ CU_Test(ddsc_participant, create_with_conf_no_env) { participant3 = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant3 > 0); status = dds_get_domainid(participant3, &domain_id); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(domain_id, valid_domain); dds_delete(participant2); @@ -127,7 +125,7 @@ CU_Test(ddsc_participant_lookup, one) { /* Get domain id */ status = dds_get_domainid(participant, &domain_id); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); num_of_found_pp = dds_lookup_participant( domain_id, participants, size); CU_ASSERT_EQUAL_FATAL(num_of_found_pp, 1); @@ -153,7 +151,7 @@ CU_Test(ddsc_participant_lookup, multiple) { /* Get domain id */ status = dds_get_domainid(participant, &domain_id); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); num_of_found_pp = dds_lookup_participant( domain_id, participants, size); CU_ASSERT_EQUAL_FATAL(num_of_found_pp, 2); @@ -185,7 +183,7 @@ CU_Test(ddsc_participant_lookup, array_too_small) { /* Get domain id */ status = dds_get_domainid(participant, &domain_id); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); num_of_found_pp = dds_lookup_participant( domain_id, participants, size); CU_ASSERT_EQUAL_FATAL(num_of_found_pp, 3); @@ -211,7 +209,7 @@ CU_Test(ddsc_participant_lookup, null_zero){ /* Get domain id */ status = dds_get_domainid(participant, &domain_id); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); num_of_found_pp = dds_lookup_participant( domain_id, NULL, size); CU_ASSERT_EQUAL_FATAL(num_of_found_pp, 1); @@ -232,10 +230,10 @@ CU_Test(ddsc_participant_lookup, null_nonzero){ /* Get domain id */ status = dds_get_domainid(participant, &domain_id); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); num_of_found_pp = dds_lookup_participant( domain_id, NULL, size); - cu_assert_status_eq(num_of_found_pp, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(num_of_found_pp, DDS_RETCODE_BAD_PARAMETER); dds_delete (participant); } @@ -254,7 +252,7 @@ CU_Test(ddsc_participant_lookup, unknown_id) { /* Get domain id */ status = dds_get_domainid(participant, &domain_id); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); domain_id ++; num_of_found_pp = dds_lookup_participant( domain_id, participants, size); @@ -287,7 +285,7 @@ CU_Test(ddsc_participant_lookup, no_more) { /* Get domain id */ status = dds_get_domainid(participant, &domain_id); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); dds_delete (participant); @@ -312,7 +310,7 @@ CU_Test(ddsc_participant_lookup, deleted) { /* Get domain id */ status = dds_get_domainid(participant, &domain_id); - cu_assert_status_eq(status, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); dds_delete (participant2); diff --git a/src/core/ddsc/tests/publisher.c b/src/core/ddsc/tests/publisher.c index 78c5bb1..2035e4a 100644 --- a/src/core/ddsc/tests/publisher.c +++ b/src/core/ddsc/tests/publisher.c @@ -19,8 +19,6 @@ #pragma warning(disable: 28020) #endif -#define cu_assert_status_eq(s1, s2) CU_ASSERT_EQUAL_FATAL(dds_err_nr(s1), s2) - /* Dummy callback */ static void data_available_cb(dds_entity_t reader, void* arg) { @@ -42,7 +40,7 @@ CU_Test(ddsc_publisher, create) /* Use NULL participant */ publisher = dds_create_publisher(0, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(publisher), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(publisher, DDS_RETCODE_PRECONDITION_NOT_MET); participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); @@ -53,7 +51,7 @@ CU_Test(ddsc_publisher, create) /* Use entity that is not a participant */ publisher1 = dds_create_publisher(publisher, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(publisher1), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(publisher1, DDS_RETCODE_ILLEGAL_OPERATION); dds_delete(publisher); /* Create a non-null qos */ @@ -143,35 +141,35 @@ CU_Test(ddsc_publisher, suspend_resume) /* Suspend a 0 publisher */ status = dds_suspend(0); - cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_PRECONDITION_NOT_MET); /* Resume a 0 publisher */ status = dds_resume(0); - cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_PRECONDITION_NOT_MET); /* Uae dds_suspend on something else than a publisher */ participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); status = dds_suspend(participant); - cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_ILLEGAL_OPERATION); /* Use dds_resume on something else than a publisher */ status = dds_resume(participant); - cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_ILLEGAL_OPERATION); /* Use dds_resume without calling dds_suspend */ publisher = dds_create_publisher(participant, NULL, NULL); CU_ASSERT_FATAL(publisher > 0); status = dds_resume(publisher); /* Should be precondition not met? */ - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_UNSUPPORTED); /* Use dds_suspend on non-null publisher */ status = dds_suspend(publisher); - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_UNSUPPORTED); /* Use dds_resume on non-null publisher */ status = dds_resume(publisher); - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_UNSUPPORTED); dds_delete(publisher); dds_delete(participant); @@ -189,38 +187,38 @@ CU_Test(ddsc_publisher, wait_for_acks) /* Wait_for_acks on 0 publisher or writer and minusOneSec timeout */ status = dds_wait_for_acks(0, minusOneSec); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); /* Wait_for_acks on NULL publisher or writer and zeroSec timeout */ status = dds_wait_for_acks(0, zeroSec); - cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_PRECONDITION_NOT_MET); /* wait_for_acks on NULL publisher or writer and oneSec timeout */ status = dds_wait_for_acks(0, oneSec); - cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_PRECONDITION_NOT_MET); /* wait_for_acks on NULL publisher or writer and DDS_INFINITE timeout */ status = dds_wait_for_acks(0, DDS_INFINITY); - cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_PRECONDITION_NOT_MET); participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); /* Wait_for_acks on participant and minusOneSec timeout */ status = dds_wait_for_acks(participant, minusOneSec); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); /* Wait_for_acks on participant and zeroSec timeout */ status = dds_wait_for_acks(participant, zeroSec); - cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_ILLEGAL_OPERATION); /* Wait_for_acks on participant and oneSec timeout */ status = dds_wait_for_acks(participant, oneSec); - cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_ILLEGAL_OPERATION); /* Wait_for_acks on participant and DDS_INFINITE timeout */ status = dds_wait_for_acks(participant, DDS_INFINITY); - cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_ILLEGAL_OPERATION); publisher = dds_create_publisher(participant, NULL, NULL); CU_ASSERT_FATAL(publisher > 0); @@ -228,40 +226,40 @@ CU_Test(ddsc_publisher, wait_for_acks) /* Wait_for_acks on publisher and minusOneSec timeout -- either BAD_PARAMETER or UNSUPPORTED would be both be ok, really */ status = dds_wait_for_acks(publisher, minusOneSec); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); /* Wait_for_acks on publisher and zeroSec timeout */ status = dds_wait_for_acks(publisher, zeroSec); - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_UNSUPPORTED); /* Wait_for_acks on publisher and oneSec timeout */ status = dds_wait_for_acks(publisher, oneSec); - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_UNSUPPORTED); /* Wait_for_acks on publisher and DDS_INFINITE timeout */ status = dds_wait_for_acks(publisher, DDS_INFINITY); - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_UNSUPPORTED); /* TODO: create tests by calling dds_qwait_for_acks on writers */ status = dds_suspend(publisher); - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_UNSUPPORTED); /* Wait_for_acks on suspended publisher and minusOneSec timeout */ status = dds_wait_for_acks(publisher, minusOneSec); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); /* Wait_for_acks on suspended publisher and zeroSec timeout */ status = dds_wait_for_acks(publisher, zeroSec); - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_UNSUPPORTED); /* Wait_for_acks on suspended publisher and oneSec timeout */ status = dds_wait_for_acks(publisher, oneSec); - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_UNSUPPORTED); /* Wait_for_acks on suspended publisher and DDS_INFINITE timeout */ status = dds_wait_for_acks(publisher, DDS_INFINITY); - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_UNSUPPORTED); dds_delete(publisher); dds_delete(participant); diff --git a/src/core/ddsc/tests/qos.c b/src/core/ddsc/tests/qos.c index a947390..88fe4e6 100644 --- a/src/core/ddsc/tests/qos.c +++ b/src/core/ddsc/tests/qos.c @@ -234,7 +234,7 @@ CU_Test(ddsc_qos, copy_bad_source, .init=qos_init, .fini=qos_fini) dds_return_t result; result = dds_copy_qos(g_qos, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(result), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(result, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_qos, copy_bad_destination, .init=qos_init, .fini=qos_fini) @@ -242,7 +242,7 @@ CU_Test(ddsc_qos, copy_bad_destination, .init=qos_init, .fini=qos_fini) dds_return_t result; result = dds_copy_qos(NULL, g_qos); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(result), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(result, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_qos, copy_with_partition, .init=qos_init, .fini=qos_fini) diff --git a/src/core/ddsc/tests/querycondition.c b/src/core/ddsc/tests/querycondition.c index 107fdd1..d1afbf5 100644 --- a/src/core/ddsc/tests/querycondition.c +++ b/src/core/ddsc/tests/querycondition.c @@ -245,7 +245,7 @@ CU_Test(ddsc_querycondition_create, deleted_reader, .init=querycondition_init, . dds_entity_t cond; dds_delete(g_reader); cond = dds_create_querycondition(g_reader, mask, filter_mod2); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(cond, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -256,11 +256,10 @@ CU_TheoryDataPoints(ddsc_querycondition_create, invalid_readers) = { CU_Theory((dds_entity_t rdr), ddsc_querycondition_create, invalid_readers, .init=querycondition_init, .fini=querycondition_fini) { uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_entity_t cond; cond = dds_create_querycondition(rdr, mask, filter_mod2); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(cond, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -273,7 +272,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_querycondition_create, non_readers, .init=qu uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_entity_t cond; cond = dds_create_querycondition(*rdr, mask, filter_mod2); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(cond, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -297,7 +296,7 @@ CU_Test(ddsc_querycondition_get_mask, deleted, .init=querycondition_init, .fini= dds_delete(condition); mask = 0; ret = dds_get_mask(condition, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -312,7 +311,7 @@ CU_Test(ddsc_querycondition_get_mask, null, .init=querycondition_init, .fini=que DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_get_mask(condition, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); dds_delete(condition); } /*************************************************************************************************/ @@ -323,12 +322,11 @@ CU_TheoryDataPoints(ddsc_querycondition_get_mask, invalid_conditions) = { }; CU_Theory((dds_entity_t cond), ddsc_querycondition_get_mask, invalid_conditions, .init=querycondition_init, .fini=querycondition_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; uint32_t mask; ret = dds_get_mask(cond, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -341,7 +339,7 @@ CU_Theory((dds_entity_t *cond), ddsc_querycondition_get_mask, non_conditions, .i dds_return_t ret; uint32_t mask; ret = dds_get_mask(*cond, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -362,7 +360,7 @@ CU_Theory((uint32_t ss, uint32_t vs, uint32_t is), ddsc_querycondition_get_mask, CU_ASSERT_FATAL(condition > 0); ret = dds_get_mask(condition, &maskOut); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(maskIn, maskOut); dds_delete(condition); @@ -924,7 +922,7 @@ CU_Test(ddsc_querycondition_read, already_deleted, .init=querycondition_init, .f /* Try to read with a deleted condition. */ ret = dds_read(condition, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1487,7 +1485,7 @@ CU_Test(ddsc_querycondition_take, already_deleted, .init=querycondition_init, .f /* Try to take with a deleted condition. */ ret = dds_take(condition, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/read_instance.c b/src/core/ddsc/tests/read_instance.c index 063d003..db46759 100644 --- a/src/core/ddsc/tests/read_instance.c +++ b/src/core/ddsc/tests/read_instance.c @@ -299,7 +299,7 @@ CU_Theory((dds_entity_t *ent, void **buf, dds_sample_info_t *si, size_t bufsz, u * However, that's not the case yet. So don't test it. */ if (buf != g_loans) { ret = dds_read_instance(*ent, buf, si, bufsz, maxs, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } else { CU_PASS("Skipped"); } @@ -320,7 +320,7 @@ CU_Theory((dds_entity_t *ent, void **buf, dds_sample_info_t *si, uint32_t maxs), * invalid and neither is the handle. So, don't test that. */ if ((buf != g_loans) || (si != g_info) || (maxs == 0)) { ret = dds_read_instance_wl(*ent, buf, si, maxs, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } else { CU_PASS("Skipped"); } @@ -350,7 +350,7 @@ CU_Theory((dds_entity_t *ent, void **buf, dds_sample_info_t *si, size_t bufsz, u * However, that's not the case yet. So don't test it. */ if (buf != g_loans) { ret = dds_read_instance_mask(*ent, buf, si, bufsz, maxs, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } else { CU_PASS("Skipped"); } @@ -372,7 +372,7 @@ CU_Theory((dds_entity_t *ent, void **buf, dds_sample_info_t *si, uint32_t maxs), * invalid and neither is the handle. So, don't test that. */ CU_ASSERT_FATAL((buf != g_loans) || (si != g_info) || (maxs == 0)); ret = dds_read_instance_mask_wl(*ent, buf, si, maxs, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -394,7 +394,7 @@ CU_Theory((dds_entity_t *rdr, dds_instance_handle_t hdl), ddsc_read_instance, in { dds_return_t ret; ret = dds_read_instance(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, hdl); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -407,7 +407,7 @@ CU_Theory((dds_entity_t *rdr, dds_instance_handle_t hdl), ddsc_read_instance_wl, { dds_return_t ret; ret = dds_read_instance_wl(*rdr, g_loans, g_info, MAX_SAMPLES, hdl); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -421,7 +421,7 @@ CU_Theory((dds_entity_t *rdr, dds_instance_handle_t hdl), ddsc_read_instance_mas uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_return_t ret; ret = dds_read_instance_mask(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, hdl, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -435,7 +435,7 @@ CU_Theory((dds_entity_t *rdr, dds_instance_handle_t hdl), ddsc_read_instance_mas uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_return_t ret; ret = dds_read_instance_mask_wl(*rdr, g_loans, g_info, MAX_SAMPLES, hdl, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -454,11 +454,10 @@ CU_TheoryDataPoints(ddsc_read_instance, invalid_readers) = { }; CU_Theory((dds_entity_t rdr), ddsc_read_instance, invalid_readers, .init=read_instance_init, .fini=read_instance_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_read_instance(rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -468,11 +467,10 @@ CU_TheoryDataPoints(ddsc_read_instance_wl, invalid_readers) = { }; CU_Theory((dds_entity_t rdr), ddsc_read_instance_wl, invalid_readers, .init=read_instance_init, .fini=read_instance_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_read_instance_wl(rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -483,11 +481,10 @@ CU_TheoryDataPoints(ddsc_read_instance_mask, invalid_readers) = { CU_Theory((dds_entity_t rdr), ddsc_read_instance_mask, invalid_readers, .init=read_instance_init, .fini=read_instance_fini) { uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_read_instance_mask(rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -498,11 +495,10 @@ CU_TheoryDataPoints(ddsc_read_instance_mask_wl, invalid_readers) = { CU_Theory((dds_entity_t rdr), ddsc_read_instance_mask_wl, invalid_readers, .init=read_instance_init, .fini=read_instance_fini) { uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_read_instance_mask_wl(rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -524,7 +520,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance, non_readers, .init=read_insta { dds_return_t ret; ret = dds_read_instance(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -536,7 +532,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance_wl, non_readers, .init=read_in { dds_return_t ret; ret = dds_read_instance_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -549,7 +545,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance_mask, non_readers, .init=read_ uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_return_t ret; ret = dds_read_instance_mask(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -562,7 +558,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance_mask_wl, non_readers, .init=re uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_return_t ret; ret = dds_read_instance_mask_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -586,7 +582,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance, already_deleted, .init=read_i ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_instance(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -600,7 +596,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance_wl, already_deleted, .init=rea ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_instance_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -615,7 +611,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance_mask, already_deleted, .init=r ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_instance_mask(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -630,7 +626,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance_mask_wl, already_deleted, .ini ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_instance_mask_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/readcondition.c b/src/core/ddsc/tests/readcondition.c index 694d463..4566d0c 100644 --- a/src/core/ddsc/tests/readcondition.c +++ b/src/core/ddsc/tests/readcondition.c @@ -227,7 +227,7 @@ CU_Test(ddsc_readcondition_create, deleted_reader, .init=readcondition_init, .fi dds_entity_t cond; dds_delete(g_reader); cond = dds_create_readcondition(g_reader, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(cond, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -238,11 +238,10 @@ CU_TheoryDataPoints(ddsc_readcondition_create, invalid_readers) = { CU_Theory((dds_entity_t rdr), ddsc_readcondition_create, invalid_readers, .init=readcondition_init, .fini=readcondition_fini) { uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_entity_t cond; cond = dds_create_readcondition(rdr, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(cond, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -255,7 +254,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_readcondition_create, non_readers, .init=rea uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_entity_t cond; cond = dds_create_readcondition(*rdr, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(cond, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -279,7 +278,7 @@ CU_Test(ddsc_readcondition_get_mask, deleted, .init=readcondition_init, .fini=re dds_delete(condition); mask = 0; ret = dds_get_mask(condition, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -294,7 +293,7 @@ CU_Test(ddsc_readcondition_get_mask, null, .init=readcondition_init, .fini=readc DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_get_mask(condition, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); dds_delete(condition); } /*************************************************************************************************/ @@ -305,12 +304,11 @@ CU_TheoryDataPoints(ddsc_readcondition_get_mask, invalid_conditions) = { }; CU_Theory((dds_entity_t cond), ddsc_readcondition_get_mask, invalid_conditions, .init=readcondition_init, .fini=readcondition_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; uint32_t mask; ret = dds_get_mask(cond, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -323,7 +321,7 @@ CU_Theory((dds_entity_t *cond), ddsc_readcondition_get_mask, non_conditions, .in dds_return_t ret; uint32_t mask; ret = dds_get_mask(*cond, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -344,7 +342,7 @@ CU_Theory((uint32_t ss, uint32_t vs, uint32_t is), ddsc_readcondition_get_mask, CU_ASSERT_FATAL(condition > 0); ret = dds_get_mask(condition, &maskOut); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(maskIn, maskOut); dds_delete(condition); @@ -906,7 +904,7 @@ CU_Test(ddsc_readcondition_read, already_deleted, .init=readcondition_init, .fin /* Try to read with a deleted condition. */ ret = dds_read(condition, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1462,7 +1460,7 @@ CU_Test(ddsc_readcondition_take, already_deleted, .init=readcondition_init, .fin /* Try to take with a deleted condition. */ ret = dds_take(condition, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/reader.c b/src/core/ddsc/tests/reader.c index ad80be7..bf8e9dc 100644 --- a/src/core/ddsc/tests/reader.c +++ b/src/core/ddsc/tests/reader.c @@ -241,7 +241,7 @@ CU_Test(ddsc_reader_create, invalid_qos_participant, .init=reader_init, .fini=re dds_qset_reader_data_lifecycle(qos, DDS_SECS(-1), DDS_SECS(-1)); DDSRT_WARNING_MSVC_ON(28020); rdr = dds_create_reader(g_participant, g_topic, qos, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(rdr), DDS_RETCODE_INCONSISTENT_POLICY); + CU_ASSERT_EQUAL_FATAL(rdr, DDS_RETCODE_INCONSISTENT_POLICY); dds_delete_qos(qos); } /*************************************************************************************************/ @@ -256,7 +256,7 @@ CU_Test(ddsc_reader_create, invalid_qos_subscriber, .init=reader_init, .fini=rea dds_qset_reader_data_lifecycle(qos, DDS_SECS(-1), DDS_SECS(-1)); DDSRT_WARNING_MSVC_ON(28020); rdr = dds_create_reader(g_subscriber, g_topic, qos, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(rdr), DDS_RETCODE_INCONSISTENT_POLICY); + CU_ASSERT_EQUAL_FATAL(rdr, DDS_RETCODE_INCONSISTENT_POLICY); dds_delete_qos(qos); } /*************************************************************************************************/ @@ -273,7 +273,7 @@ CU_Theory((dds_entity_t *par, dds_entity_t *top), ddsc_reader_create, non_partic * actually the topic. So, don't test that permutation. */ CU_ASSERT_FATAL((par != &g_participant) || (top != &g_topic)); rdr = dds_create_reader(*par, *top, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(rdr), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(rdr, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -307,7 +307,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs), ddsc * However, that's not the case yet. So don't test it. */ if (buf != g_loans) { ret = dds_read(g_reader, buf, si, bufsz, maxs); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } else { CU_PASS("Skipped"); } @@ -320,11 +320,10 @@ CU_TheoryDataPoints(ddsc_read, invalid_readers) = { }; CU_Theory((dds_entity_t rdr), ddsc_read, invalid_readers, .init=reader_init, .fini=reader_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_read(rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -336,7 +335,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read, non_readers, .init=reader_init, .fini= { dds_return_t ret; ret = dds_read(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -347,7 +346,7 @@ CU_Test(ddsc_read, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_read(g_reader, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -420,7 +419,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, uint32_t maxs), ddsc_read_wl, inva * invalid. So, don't test that. */ CU_ASSERT_FATAL((buf != g_loans) || (si != g_info) || (maxs == 0)); ret = dds_read_wl(g_reader, buf, si, maxs); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -430,11 +429,10 @@ CU_TheoryDataPoints(ddsc_read_wl, invalid_readers) = { }; CU_Theory((dds_entity_t rdr), ddsc_read_wl, invalid_readers, .init=reader_init, .fini=reader_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_read_wl(rdr, g_loans, g_info, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -446,7 +444,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_wl, non_readers, .init=reader_init, .fi { dds_return_t ret; ret = dds_read_wl(*rdr, g_loans, g_info, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -457,7 +455,7 @@ CU_Test(ddsc_read_wl, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_read_wl(g_reader, g_loans, g_info, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -541,7 +539,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs), ddsc * However, that's not the case yet. So don't test it. */ if (buf != g_loans) { ret = dds_read_mask(g_reader, buf, si, bufsz, maxs, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } else { CU_PASS("Skipped"); } @@ -555,11 +553,10 @@ CU_TheoryDataPoints(ddsc_read_mask, invalid_readers) = { CU_Theory((dds_entity_t rdr), ddsc_read_mask, invalid_readers, .init=reader_init, .fini=reader_fini) { uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_read_mask(rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -572,7 +569,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_mask, non_readers, .init=reader_init, . uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_return_t ret; ret = dds_read_mask(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -584,7 +581,7 @@ CU_Test(ddsc_read_mask, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_read_mask(g_reader, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1092,7 +1089,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, uint32_t maxs), ddsc_read_mask_wl, * invalid. So, don't test that. */ CU_ASSERT_FATAL((buf != g_loans) || (si != g_info) || (maxs == 0)); ret = dds_read_mask_wl(g_reader, buf, si, maxs, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1103,11 +1100,10 @@ CU_TheoryDataPoints(ddsc_read_mask_wl, invalid_readers) = { CU_Theory((dds_entity_t rdr), ddsc_read_mask_wl, invalid_readers, .init=reader_init, .fini=reader_fini) { uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_read_mask_wl(rdr, g_loans, g_info, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1120,7 +1116,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_mask_wl, non_readers, .init=reader_init uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_return_t ret; ret = dds_read_mask_wl(*rdr, g_loans, g_info, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -1132,7 +1128,7 @@ CU_Test(ddsc_read_mask_wl, already_deleted, .init=reader_init, .fini=reader_fini /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_read_mask_wl(g_reader, g_loans, g_info, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1677,7 +1673,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs), ddsc * However, that's not the case yet. So don't test it. */ if (buf != g_loans) { ret = dds_take(g_reader, buf, si, bufsz, maxs); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } else { CU_PASS("Skipped"); } @@ -1690,11 +1686,10 @@ CU_TheoryDataPoints(ddsc_take, invalid_readers) = { }; CU_Theory((dds_entity_t rdr), ddsc_take, invalid_readers, .init=reader_init, .fini=reader_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_take(rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1706,7 +1701,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take, non_readers, .init=reader_init, .fini= { dds_return_t ret; ret = dds_take(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -1717,7 +1712,7 @@ CU_Test(ddsc_take, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to take with a deleted reader. */ dds_delete(g_reader); ret = dds_take(g_reader, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1790,7 +1785,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, uint32_t maxs), ddsc_take_wl, inva * invalid. So, don't test that. */ CU_ASSERT_FATAL((buf != g_loans) || (si != g_info) || (maxs == 0)); ret = dds_take_wl(g_reader, buf, si, maxs); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1800,11 +1795,10 @@ CU_TheoryDataPoints(ddsc_take_wl, invalid_readers) = { }; CU_Theory((dds_entity_t rdr), ddsc_take_wl, invalid_readers, .init=reader_init, .fini=reader_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_take_wl(rdr, g_loans, g_info, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1816,7 +1810,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_wl, non_readers, .init=reader_init, .fi { dds_return_t ret; ret = dds_take_wl(*rdr, g_loans, g_info, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -1827,7 +1821,7 @@ CU_Test(ddsc_take_wl, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_take_wl(g_reader, g_loans, g_info, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1912,7 +1906,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs), ddsc * However, that's not the case yet. So don't test it. */ if (buf != g_loans) { ret = dds_take_mask(g_reader, buf, si, bufsz, maxs, mask); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_BAD_PARAMETER); } else { CU_PASS("Skipped"); } @@ -1926,11 +1920,10 @@ CU_TheoryDataPoints(ddsc_take_mask, invalid_readers) = { CU_Theory((dds_entity_t rdr), ddsc_take_mask, invalid_readers, .init=reader_init, .fini=reader_fini) { uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_take_mask(rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1943,7 +1936,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_mask, non_readers, .init=reader_init, . uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_return_t ret; ret = dds_take_mask(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -1955,7 +1948,7 @@ CU_Test(ddsc_take_mask, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_take_mask(g_reader, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -2596,7 +2589,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, uint32_t maxs), ddsc_take_mask_wl, * invalid. So, don't test that. */ CU_ASSERT_FATAL((buf != g_loans) || (si != g_info) || (maxs == 0)); ret = dds_take_mask_wl(g_reader, buf, si, maxs, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -2607,11 +2600,10 @@ CU_TheoryDataPoints(ddsc_take_mask_wl, invalid_readers) = { CU_Theory((dds_entity_t rdr), ddsc_take_mask_wl, invalid_readers, .init=reader_init, .fini=reader_fini) { uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_take_mask_wl(rdr, g_loans, g_info, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -2624,7 +2616,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_mask_wl, non_readers, .init=reader_init uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_return_t ret; ret = dds_take_mask_wl(*rdr, g_loans, g_info, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -2636,7 +2628,7 @@ CU_Test(ddsc_take_mask_wl, already_deleted, .init=reader_init, .fini=reader_fini /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_take_mask_wl(g_reader, g_loans, g_info, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/reader_iterator.c b/src/core/ddsc/tests/reader_iterator.c index c0dbe6a..a714a67 100644 --- a/src/core/ddsc/tests/reader_iterator.c +++ b/src/core/ddsc/tests/reader_iterator.c @@ -360,11 +360,10 @@ CU_TheoryDataPoints(ddsc_read_next, invalid_readers) = { }; CU_Theory((dds_entity_t rdr), ddsc_read_next, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_read_next(rdr, g_samples, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -376,7 +375,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_next, non_readers, .init=reader_iterato { dds_return_t ret; ret = dds_read_next(*rdr, g_samples, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -390,7 +389,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_next, already_deleted, .init=reader_ite ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_next(*rdr, g_samples, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -405,7 +404,7 @@ CU_Theory((void **buf, dds_sample_info_t *si), ddsc_read_next, invalid_buffers, dds_return_t ret; if ((buf != g_samples || si != g_info) && (buf != g_loans)) { ret = dds_read_next(g_reader, buf, si); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } else { CU_PASS("Skipped"); } @@ -476,11 +475,10 @@ CU_TheoryDataPoints(ddsc_read_next_wl, invalid_readers) = { }; CU_Theory((dds_entity_t rdr), ddsc_read_next_wl, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_read_next_wl(rdr, g_loans, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -492,7 +490,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_next_wl, non_readers, .init=reader_iter { dds_return_t ret; ret = dds_read_next_wl(*rdr, g_loans, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -506,7 +504,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_next_wl, already_deleted, .init=reader_ ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_next_wl(*rdr, g_loans, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -521,7 +519,7 @@ CU_Theory((void **buf, dds_sample_info_t *si), ddsc_read_next_wl, invalid_buffer dds_return_t ret; if (buf != g_loans || si != g_info) { ret = dds_read_next_wl(g_reader, buf, si); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } else { CU_PASS("Skipped"); } @@ -586,11 +584,10 @@ CU_TheoryDataPoints(ddsc_take_next, invalid_readers) = { }; CU_Theory((dds_entity_t rdr), ddsc_take_next, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_take_next(rdr, g_samples, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -602,7 +599,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_next, non_readers, .init=reader_iterato { dds_return_t ret; ret = dds_take_next(*rdr, g_samples, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -616,7 +613,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_next, already_deleted, .init=reader_ite ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_next(*rdr, g_samples, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -631,7 +628,7 @@ CU_Theory((void **buf, dds_sample_info_t *si), ddsc_take_next, invalid_buffers, dds_return_t ret; if ((buf != g_samples || si != g_info) && (buf != g_loans)) { ret = dds_take_next(g_reader, buf, si); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } else { CU_PASS("Skipped"); } @@ -699,11 +696,10 @@ CU_TheoryDataPoints(ddsc_take_next_wl, invalid_readers) = { }; CU_Theory((dds_entity_t rdr), ddsc_take_next_wl, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_take_next_wl(rdr, g_loans, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -715,7 +711,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_next_wl, non_readers, .init=reader_iter { dds_return_t ret; ret = dds_take_next_wl(*rdr, g_loans, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -729,7 +725,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_next_wl, already_deleted, .init=reader_ ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_next_wl(*rdr, g_loans, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -743,7 +739,7 @@ CU_Theory((void **buf, dds_sample_info_t *si), ddsc_take_next_wl, invalid_buffer dds_return_t ret; if (buf != g_loans || si != g_info) { ret = dds_take_next_wl(g_reader, buf, si); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } else { CU_PASS("Skipped"); } diff --git a/src/core/ddsc/tests/register.c b/src/core/ddsc/tests/register.c index 11249dd..b04d35f 100644 --- a/src/core/ddsc/tests/register.c +++ b/src/core/ddsc/tests/register.c @@ -150,7 +150,7 @@ CU_Test(ddsc_register_instance, deleted_entity, .init=registering_init, .fini=re dds_instance_handle_t handle; dds_delete(g_writer); ret = dds_register_instance(g_writer, &handle, g_data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } static dds_instance_handle_t hndle = 0; @@ -169,7 +169,7 @@ CU_Theory((dds_instance_handle_t *hndl2, void *datap), ddsc_register_instance, i DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_register_instance(g_writer, hndl2, datap); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_TheoryDataPoints(ddsc_register_instance, invalid_writers) = { @@ -177,12 +177,11 @@ CU_TheoryDataPoints(ddsc_register_instance, invalid_writers) = { }; CU_Theory((dds_entity_t writer), ddsc_register_instance, invalid_writers, .init=registering_init, .fini=registering_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; dds_instance_handle_t handle; ret = dds_register_instance(writer, &handle, g_data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } CU_TheoryDataPoints(ddsc_register_instance, non_writers) = { @@ -193,7 +192,7 @@ CU_Theory((dds_entity_t *writer), ddsc_register_instance, non_writers, .init=reg dds_return_t ret; dds_instance_handle_t handle; ret = dds_register_instance(*writer, &handle, g_data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } CU_Test(ddsc_register_instance, registering_new_instance, .init=registering_init, .fini=registering_fini) diff --git a/src/core/ddsc/tests/return_loan.c b/src/core/ddsc/tests/return_loan.c index 365ea76..4ff1fcc 100644 --- a/src/core/ddsc/tests/return_loan.c +++ b/src/core/ddsc/tests/return_loan.c @@ -36,7 +36,7 @@ void delete_entities(void) { dds_return_t result; result = dds_delete(participant); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(result), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(result, DDS_RETCODE_OK); dds_delete(read_condition); } @@ -86,7 +86,7 @@ CU_Test(ddsc_reader, return_loan_bad_params, .init = create_entities, .fini = de void **buf = NULL; result = dds_return_loan(reader, NULL, 0); - CU_ASSERT_EQUAL(dds_err_nr(result), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(result, DDS_RETCODE_BAD_PARAMETER); #ifdef _MSC_VER #pragma warning(push) @@ -96,7 +96,7 @@ CU_Test(ddsc_reader, return_loan_bad_params, .init = create_entities, .fini = de #ifdef _MSC_VER #pragma warning(pop) #endif - CU_ASSERT_EQUAL(dds_err_nr(result), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(result, DDS_RETCODE_BAD_PARAMETER); buf = create_loan_buf(10, false); #ifdef _MSC_VER @@ -107,10 +107,10 @@ CU_Test(ddsc_reader, return_loan_bad_params, .init = create_entities, .fini = de #ifdef _MSC_VER #pragma warning(pop) #endif - CU_ASSERT_EQUAL(dds_err_nr(result), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(result, DDS_RETCODE_BAD_PARAMETER); result = dds_return_loan(participant, buf, 0); - CU_ASSERT_EQUAL(dds_err_nr(result), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL(result, DDS_RETCODE_ILLEGAL_OPERATION); delete_loan_buf(buf, 10, false); } @@ -124,17 +124,17 @@ CU_Test(ddsc_reader, return_loan_success, .init = create_entities, .fini = delet buf = create_loan_buf(10, false); result = dds_return_loan(reader, buf, 10); - CU_ASSERT_EQUAL(dds_err_nr(result), DDS_RETCODE_OK); + CU_ASSERT_EQUAL(result, DDS_RETCODE_OK); result = dds_return_loan(reader, &buf2, 0); - CU_ASSERT_EQUAL(dds_err_nr(result), DDS_RETCODE_OK); + CU_ASSERT_EQUAL(result, DDS_RETCODE_OK); delete_loan_buf(buf, 10, true); buf = create_loan_buf(10, false); result = dds_return_loan(read_condition, buf, 10); - CU_ASSERT_EQUAL(dds_err_nr(result), DDS_RETCODE_OK); + CU_ASSERT_EQUAL(result, DDS_RETCODE_OK); result = dds_return_loan(read_condition, &buf2, 0); - CU_ASSERT_EQUAL(dds_err_nr(result), DDS_RETCODE_OK); + CU_ASSERT_EQUAL(result, DDS_RETCODE_OK); delete_loan_buf(buf, 10, true); } diff --git a/src/core/ddsc/tests/subscriber.c b/src/core/ddsc/tests/subscriber.c index 7e881d1..cc9144a 100644 --- a/src/core/ddsc/tests/subscriber.c +++ b/src/core/ddsc/tests/subscriber.c @@ -48,7 +48,7 @@ CU_Test(ddsc_subscriber, notify_readers) { /* todo implement tests */ ret = dds_notify_readers(subscriber); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_UNSUPPORTED); dds_delete(subscriber); dds_delete(participant); @@ -67,7 +67,7 @@ CU_Test(ddsc_subscriber, create) { /*** Verify participant parameter ***/ subscriber = dds_create_subscriber(0, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(subscriber), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(subscriber, DDS_RETCODE_BAD_PARAMETER); subscriber = dds_create_subscriber(participant, NULL, NULL); CU_ASSERT_FATAL(subscriber > 0); @@ -91,7 +91,7 @@ CU_Test(ddsc_subscriber, create) { sqos = dds_create_qos(); dds_qset_presentation(sqos, 123, 1, 1); /* Set invalid presentation policy */ subscriber = dds_create_subscriber(participant, sqos, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(subscriber), DDS_RETCODE_INCONSISTENT_POLICY); + CU_ASSERT_EQUAL_FATAL(subscriber, DDS_RETCODE_INCONSISTENT_POLICY); dds_delete_qos(sqos); /*** Verify listener parameter ***/ diff --git a/src/core/ddsc/tests/take_instance.c b/src/core/ddsc/tests/take_instance.c index 6fba4a6..e8cba48 100644 --- a/src/core/ddsc/tests/take_instance.c +++ b/src/core/ddsc/tests/take_instance.c @@ -299,7 +299,7 @@ CU_Theory((dds_entity_t *ent, void **buf, dds_sample_info_t *si, size_t bufsz, u * However, that's not the case yet. So don't test it. */ if (buf != g_loans) { ret = dds_take_instance(*ent, buf, si, bufsz, maxs, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } else { CU_PASS("Skipped"); } @@ -320,7 +320,7 @@ CU_Theory((dds_entity_t *ent, void **buf, dds_sample_info_t *si, uint32_t maxs), * invalid and neither is the handle. So, don't test that. */ CU_ASSERT_FATAL((buf != g_loans) || (si != g_info) || (maxs == 0)); ret = dds_take_instance_wl(*ent, buf, si, maxs, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -347,7 +347,7 @@ CU_Theory((dds_entity_t *ent, void **buf, dds_sample_info_t *si, size_t bufsz, u * However, that's not the case yet. So don't test it. */ if (buf != g_loans) { ret = dds_take_instance_mask(*ent, buf, si, bufsz, maxs, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } else { CU_PASS("Skipped"); } @@ -369,7 +369,7 @@ CU_Theory((dds_entity_t *ent, void **buf, dds_sample_info_t *si, uint32_t maxs), * invalid and neither is the handle. So, don't test that. */ CU_ASSERT_FATAL((buf != g_loans) || (si != g_info) || (maxs == 0)); ret = dds_take_instance_mask_wl(*ent, buf, si, maxs, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -391,7 +391,7 @@ CU_Theory((dds_entity_t *rdr, dds_instance_handle_t hdl), ddsc_take_instance, in { dds_return_t ret; ret = dds_take_instance(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, hdl); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -404,7 +404,7 @@ CU_Theory((dds_entity_t *rdr, dds_instance_handle_t hdl), ddsc_take_instance_wl, { dds_return_t ret; ret = dds_take_instance_wl(*rdr, g_loans, g_info, MAX_SAMPLES, hdl); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -418,7 +418,7 @@ CU_Theory((dds_entity_t *rdr, dds_instance_handle_t hdl), ddsc_take_instance_mas uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_return_t ret; ret = dds_take_instance_mask(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, hdl, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -432,7 +432,7 @@ CU_Theory((dds_entity_t *rdr, dds_instance_handle_t hdl), ddsc_take_instance_mas uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_return_t ret; ret = dds_take_instance_mask_wl(*rdr, g_loans, g_info, MAX_SAMPLES, hdl, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -451,11 +451,10 @@ CU_TheoryDataPoints(ddsc_take_instance, invalid_readers) = { }; CU_Theory((dds_entity_t rdr), ddsc_take_instance, invalid_readers, .init=take_instance_init, .fini=take_instance_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_take_instance(rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -465,11 +464,10 @@ CU_TheoryDataPoints(ddsc_take_instance_wl, invalid_readers) = { }; CU_Theory((dds_entity_t rdr), ddsc_take_instance_wl, invalid_readers, .init=take_instance_init, .fini=take_instance_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_take_instance_wl(rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -480,11 +478,10 @@ CU_TheoryDataPoints(ddsc_take_instance_mask, invalid_readers) = { CU_Theory((dds_entity_t rdr), ddsc_take_instance_mask, invalid_readers, .init=take_instance_init, .fini=take_instance_fini) { uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_take_instance_mask(rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -495,11 +492,10 @@ CU_TheoryDataPoints(ddsc_take_instance_mask_wl, invalid_readers) = { CU_Theory((dds_entity_t rdr), ddsc_take_instance_mask_wl, invalid_readers, .init=take_instance_init, .fini=take_instance_fini) { uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_take_instance_mask_wl(rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -521,7 +517,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance, non_readers, .init=take_insta { dds_return_t ret; ret = dds_take_instance(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -533,7 +529,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance_wl, non_readers, .init=take_in { dds_return_t ret; ret = dds_take_instance_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -546,7 +542,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance_mask, non_readers, .init=take_ uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_return_t ret; ret = dds_take_instance_mask(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -559,7 +555,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance_mask_wl, non_readers, .init=ta uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; dds_return_t ret; ret = dds_take_instance_mask_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -583,7 +579,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance, already_deleted, .init=take_i ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_instance(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -597,7 +593,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance_wl, already_deleted, .init=tak ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_instance_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -612,7 +608,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance_mask, already_deleted, .init=t ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_instance_mask(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -627,7 +623,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance_mask_wl, already_deleted, .ini ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_instance_mask_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/topic.c b/src/core/ddsc/tests/topic.c index 43dde13..085926b 100644 --- a/src/core/ddsc/tests/topic.c +++ b/src/core/ddsc/tests/topic.c @@ -108,7 +108,7 @@ CU_Test(ddsc_topic_create, invalid_qos, .init=ddsc_topic_init, .fini=ddsc_topic_ dds_qset_lifespan(qos, DDS_SECS(-1)); DDSRT_WARNING_MSVC_OFF(28020); topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, "inconsistent", qos, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_INCONSISTENT_POLICY); + CU_ASSERT_EQUAL_FATAL(topic, DDS_RETCODE_INCONSISTENT_POLICY); dds_delete_qos(qos); } /*************************************************************************************************/ @@ -118,7 +118,7 @@ CU_Test(ddsc_topic_create, non_participants, .init=ddsc_topic_init, .fini=ddsc_t { dds_entity_t topic; topic = dds_create_topic(g_topicRtmDataType, &RoundTripModule_DataType_desc, "non_participant", NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(topic, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -141,7 +141,7 @@ CU_Test(ddsc_topic_create, same_name, .init=ddsc_topic_init, .fini=ddsc_topic_fi dds_entity_t topic; /* Creating the different topic with same name should fail. */ topic = dds_create_topic(g_participant, &RoundTripModule_Address_desc, g_topicRtmDataTypeName, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(topic, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -169,7 +169,7 @@ CU_Test(ddsc_topic_create, desc_null, .init=ddsc_topic_init, .fini=ddsc_topic_fi DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ topic = dds_create_topic (g_participant, NULL, "desc_null", NULL, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(topic, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -183,7 +183,7 @@ CU_Theory((char *name), ddsc_topic_create, invalid_names, .init=ddsc_topic_init, { dds_entity_t topic; topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, name, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(topic, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -213,7 +213,7 @@ CU_Test(ddsc_topic_find, non_participants, .init=ddsc_topic_init, .fini=ddsc_top { dds_entity_t topic; topic = dds_find_topic(g_topicRtmDataType, "non_participant"); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(topic, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -224,7 +224,7 @@ CU_Test(ddsc_topic_find, null, .init=ddsc_topic_init, .fini=ddsc_topic_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ topic = dds_find_topic(g_participant, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(topic, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -233,7 +233,7 @@ CU_Test(ddsc_topic_find, unknown, .init=ddsc_topic_init, .fini=ddsc_topic_fini) { dds_entity_t topic; topic = dds_find_topic(g_participant, "unknown"); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(topic, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -243,7 +243,7 @@ CU_Test(ddsc_topic_find, deleted, .init=ddsc_topic_init, .fini=ddsc_topic_fini) dds_entity_t topic; dds_delete(g_topicRtmDataType); topic = dds_find_topic(g_participant, g_topicRtmDataTypeName); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(topic, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -289,7 +289,7 @@ CU_Test(ddsc_topic_get_name, non_topic, .init=ddsc_topic_init, .fini=ddsc_topic_ char name[MAX_NAME_SIZE]; dds_return_t ret; ret = dds_get_name(g_participant, name, MAX_NAME_SIZE); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -303,7 +303,7 @@ CU_Theory((char *name, size_t size), ddsc_topic_get_name, invalid_params, .init= dds_return_t ret; CU_ASSERT_FATAL((name != g_nameBuffer) || (size != MAX_NAME_SIZE)); ret = dds_get_name(g_topicRtmDataType, name, size); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -314,7 +314,7 @@ CU_Test(ddsc_topic_get_name, deleted, .init=ddsc_topic_init, .fini=ddsc_topic_fi dds_return_t ret; dds_delete(g_topicRtmDataType); ret = dds_get_name(g_topicRtmDataType, name, MAX_NAME_SIZE); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -362,7 +362,7 @@ CU_Test(ddsc_topic_get_type_name, non_topic, .init=ddsc_topic_init, .fini=ddsc_t char name[MAX_NAME_SIZE]; dds_return_t ret; ret = dds_get_type_name(g_participant, name, MAX_NAME_SIZE); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -376,7 +376,7 @@ CU_Theory((char *name, size_t size), ddsc_topic_get_type_name, invalid_params, . dds_return_t ret; CU_ASSERT_FATAL((name != g_nameBuffer) || (size != MAX_NAME_SIZE)); ret = dds_get_type_name(g_topicRtmDataType, name, size); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -387,7 +387,7 @@ CU_Test(ddsc_topic_get_type_name, deleted, .init=ddsc_topic_init, .fini=ddsc_top dds_return_t ret; dds_delete(g_topicRtmDataType); ret = dds_get_type_name(g_topicRtmDataType, name, MAX_NAME_SIZE); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -405,7 +405,7 @@ CU_Test(ddsc_topic_set_qos, valid, .init=ddsc_topic_init, .fini=ddsc_topic_fini) /* Latency is the only one allowed to change. */ dds_qset_latency_budget(g_qos, DDS_SECS(1)); ret = dds_set_qos(g_topicRtmDataType, g_qos); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_UNSUPPORTED); } /*************************************************************************************************/ @@ -417,7 +417,7 @@ CU_Test(ddsc_topic_set_qos, inconsistent, .init=ddsc_topic_init, .fini=ddsc_topi dds_qset_lifespan(g_qos, DDS_SECS(-1)); DDSRT_WARNING_MSVC_ON(28020); ret = dds_set_qos(g_topicRtmDataType, g_qos); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_INCONSISTENT_POLICY); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_INCONSISTENT_POLICY); } /*************************************************************************************************/ @@ -427,6 +427,6 @@ CU_Test(ddsc_topic_set_qos, immutable, .init=ddsc_topic_init, .fini=ddsc_topic_f dds_return_t ret; dds_qset_destination_order(g_qos, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP); /* Immutable */ ret = dds_set_qos(g_topicRtmDataType, g_qos); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_IMMUTABLE_POLICY); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_IMMUTABLE_POLICY); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/types.c b/src/core/ddsc/tests/types.c index a2f6c28..427fe53 100644 --- a/src/core/ddsc/tests/types.c +++ b/src/core/ddsc/tests/types.c @@ -30,7 +30,7 @@ CU_ASSERT_FATAL(wri > 0); \ \ status = dds_write(wri, &data); \ - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_OK); \ + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); \ \ dds_delete(wri); \ dds_delete(top); \ @@ -114,7 +114,7 @@ CU_Test(ddsc_types, alltypeskey) CU_ASSERT_FATAL(wri > 0); status = dds_write(wri, &atk_data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); dds_delete(wri); dds_delete(top); diff --git a/src/core/ddsc/tests/unregister.c b/src/core/ddsc/tests/unregister.c index b7b03d5..538c661 100644 --- a/src/core/ddsc/tests/unregister.c +++ b/src/core/ddsc/tests/unregister.c @@ -152,7 +152,7 @@ CU_Test(ddsc_unregister_instance, deleted, .init=unregistering_init, .fini=unreg dds_delete(g_writer); ret = dds_unregister_instance(g_writer, g_data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -161,7 +161,7 @@ CU_Test(ddsc_unregister_instance, null, .init=unregistering_init, .fini=unregist { dds_return_t ret; ret = dds_unregister_instance(g_writer, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -171,11 +171,10 @@ CU_TheoryDataPoints(ddsc_unregister_instance, invalid_writers) = { }; CU_Theory((dds_entity_t writer), ddsc_unregister_instance, invalid_writers, .init=unregistering_init, .fini=unregistering_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_unregister_instance(writer, g_data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -187,7 +186,7 @@ CU_Theory((dds_entity_t *writer), ddsc_unregister_instance, non_writers, .init=u { dds_return_t ret; ret = dds_unregister_instance(*writer, g_data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -246,7 +245,7 @@ CU_Test(ddsc_unregister_instance_ts, deleted, .init=unregistering_init, .fini=un dds_return_t ret; dds_delete(g_writer); ret = dds_unregister_instance_ts(g_writer, g_data, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -255,7 +254,7 @@ CU_Test(ddsc_unregister_instance_ts, null, .init=unregistering_init, .fini=unreg { dds_return_t ret; ret = dds_unregister_instance_ts(g_writer, NULL, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -265,11 +264,10 @@ CU_TheoryDataPoints(ddsc_unregister_instance_ts, invalid_writers) = { }; CU_Theory((dds_entity_t writer), ddsc_unregister_instance_ts, invalid_writers, .init=unregistering_init, .fini=unregistering_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_unregister_instance_ts(writer, g_data, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -281,7 +279,7 @@ CU_Theory((dds_entity_t *writer), ddsc_unregister_instance_ts, non_writers, .ini { dds_return_t ret; ret = dds_unregister_instance_ts(*writer, g_data, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -383,7 +381,7 @@ CU_Test(ddsc_unregister_instance_ih, deleted, .init=unregistering_init, .fini=un dds_return_t ret; dds_delete(g_writer); ret = dds_unregister_instance_ih(g_writer, DDS_HANDLE_NIL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -395,7 +393,7 @@ CU_Theory((dds_instance_handle_t handle), ddsc_unregister_instance_ih, invalid_h { dds_return_t ret; ret = dds_unregister_instance_ih(g_writer, handle); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -405,11 +403,10 @@ CU_TheoryDataPoints(ddsc_unregister_instance_ih, invalid_writers) = { }; CU_Theory((dds_entity_t writer), ddsc_unregister_instance_ih, invalid_writers, .init=unregistering_init, .fini=unregistering_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_unregister_instance_ih(writer, DDS_HANDLE_NIL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -421,7 +418,7 @@ CU_Theory((dds_entity_t *writer), ddsc_unregister_instance_ih, non_writers, .ini { dds_return_t ret; ret = dds_unregister_instance_ih(*writer, DDS_HANDLE_NIL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -481,7 +478,7 @@ CU_Test(ddsc_unregister_instance_ih_ts, deleted, .init=unregistering_init, .fini dds_return_t ret; dds_delete(g_writer); ret = dds_unregister_instance_ih_ts(g_writer, DDS_HANDLE_NIL, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -493,7 +490,7 @@ CU_Theory((dds_instance_handle_t handle), ddsc_unregister_instance_ih_ts, invali { dds_return_t ret; ret = dds_unregister_instance_ih_ts(g_writer, handle, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -503,11 +500,10 @@ CU_TheoryDataPoints(ddsc_unregister_instance_ih_ts, invalid_writers) = { }; CU_Theory((dds_entity_t writer), ddsc_unregister_instance_ih_ts, invalid_writers, .init=unregistering_init, .fini=unregistering_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_unregister_instance_ih_ts(writer, DDS_HANDLE_NIL, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -519,7 +515,7 @@ CU_Theory((dds_entity_t *writer), ddsc_unregister_instance_ih_ts, non_writers, . { dds_return_t ret; ret = dds_unregister_instance_ih_ts(*writer, DDS_HANDLE_NIL, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/unsupported.c b/src/core/ddsc/tests/unsupported.c index 68bf4a5..279e8cd 100644 --- a/src/core/ddsc/tests/unsupported.c +++ b/src/core/ddsc/tests/unsupported.c @@ -78,9 +78,9 @@ CU_Test(ddsc_unsupported, dds_begin_end_coherent, .init = setup, .fini = teardow for (int i=0; i < 5; i++) { result = dds_begin_coherent(e[pars[i].index]); - CU_ASSERT_EQUAL(dds_err_nr(result), pars[i].exp_res); + CU_ASSERT_EQUAL(result, pars[i].exp_res); result = dds_end_coherent(e[pars[i].index]); - CU_ASSERT_EQUAL(dds_err_nr(result), pars[i].exp_res); + CU_ASSERT_EQUAL(result, pars[i].exp_res); } } @@ -95,7 +95,7 @@ CU_Test(ddsc_unsupported, dds_wait_for_acks, .init = setup, .fini = teardown) for (int i=0; i< 3; i++) { result = dds_wait_for_acks(e[pars[i].index], 0); - CU_ASSERT_EQUAL(dds_err_nr(result), pars[i].exp_res); + CU_ASSERT_EQUAL(result, pars[i].exp_res); } } @@ -110,9 +110,9 @@ CU_Test(ddsc_unsupported, dds_suspend_resume, .init = setup, .fini = teardown) for (int i=0; i< 3; i++) { result = dds_suspend(e[pars[i].index]); - CU_ASSERT_EQUAL(dds_err_nr(result), pars[i].exp_res); + CU_ASSERT_EQUAL(result, pars[i].exp_res); result = dds_resume(e[pars[i].index]); - CU_ASSERT_EQUAL(dds_err_nr(result), pars[i].exp_res); + CU_ASSERT_EQUAL(result, pars[i].exp_res); } } @@ -130,7 +130,7 @@ CU_Test(ddsc_unsupported, dds_get_instance_handle, .init = setup, .fini = teardo for (int i=0; i < 5; i++) { result = dds_get_instance_handle(e[pars[i].index], &ih); - CU_ASSERT_EQUAL(dds_err_nr(result), pars[i].exp_res); + CU_ASSERT_EQUAL(result, pars[i].exp_res); } } @@ -152,7 +152,7 @@ CU_Test(ddsc_unsupported, dds_set_qos, .init = setup, .fini = teardown) qos = dds_create_qos(); for (int i=0; i < 8;i++) { result = dds_set_qos(e[pars[i].index], qos); - CU_ASSERT_EQUAL(dds_err_nr(result), pars[i].exp_res); + CU_ASSERT_EQUAL(result, pars[i].exp_res); } dds_delete_qos(qos); } diff --git a/src/core/ddsc/tests/waitset.c b/src/core/ddsc/tests/waitset.c index 9c401cb..cffa069 100644 --- a/src/core/ddsc/tests/waitset.c +++ b/src/core/ddsc/tests/waitset.c @@ -226,7 +226,7 @@ CU_Test(ddsc_waitset_create, deleted_participant, .init=ddsc_waitset_basic_init, deleted = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); dds_delete(deleted); ws = dds_create_waitset(deleted); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ws), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ws, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -236,11 +236,10 @@ CU_TheoryDataPoints(ddsc_waitset_create, invalid_params) = { }; CU_Theory((dds_entity_t par), ddsc_waitset_create, invalid_params, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { - dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_entity_t ws; ws = dds_create_waitset(par); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ws), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ws, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -252,7 +251,7 @@ CU_Theory((dds_entity_t *par), ddsc_waitset_create, non_participants, .init=ddsc { dds_entity_t ws; ws = dds_create_waitset(*par); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ws), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ws, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -276,7 +275,7 @@ CU_Theory((dds_entity_t e, dds_attach_t a), ddsc_waitset_attach, invalid_params, { dds_return_t ret; ret = dds_waitset_attach(waitset, e, a); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -287,11 +286,10 @@ CU_TheoryDataPoints(ddsc_waitset_attach, invalid_waitsets) = { }; CU_Theory((dds_entity_t ws, dds_attach_t a), ddsc_waitset_attach, invalid_waitsets, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { - dds_return_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_waitset_attach(ws, participant, a); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -305,7 +303,7 @@ CU_Theory((dds_entity_t *ws, dds_entity_t *e, dds_attach_t a), ddsc_waitset_atta { dds_return_t ret; ret = dds_waitset_attach(*ws, *e, a); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -315,7 +313,7 @@ CU_Test(ddsc_waitset_attach, deleted_waitset, .init=ddsc_waitset_basic_init, .fi dds_return_t ret; dds_delete(waitset); ret = dds_waitset_attach(waitset, participant, 0); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -347,7 +345,7 @@ CU_Theory((dds_entity_t *ws, dds_entity_t *e, dds_attach_t a), ddsc_waitset_atta /* Try to attach. */ ret = dds_waitset_attach(*ws, *e, a); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), exp); + CU_ASSERT_EQUAL_FATAL(ret, exp); /* Detach when needed. */ if (ret == DDS_RETCODE_OK) { @@ -366,13 +364,13 @@ CU_Test(ddsc_waitset_attach_detach, second, .init=ddsc_waitset_basic_init, .fini CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_waitset_attach(waitset, waitset, 0); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); ret = dds_waitset_detach(waitset, waitset); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_waitset_detach(waitset, waitset); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_PRECONDITION_NOT_MET); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); } /*************************************************************************************************/ @@ -399,7 +397,7 @@ CU_Theory((dds_entity_t e), ddsc_waitset_detach, invalid_params, .init=ddsc_wait { dds_return_t ret; ret = dds_waitset_detach(waitset, e); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -409,11 +407,10 @@ CU_TheoryDataPoints(ddsc_waitset_detach, invalid_waitsets) = { }; CU_Theory((dds_entity_t ws), ddsc_waitset_detach, invalid_waitsets, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { - dds_return_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_waitset_detach(ws, participant); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -436,7 +433,7 @@ CU_Theory((dds_entity_t *ws, dds_entity_t *e), ddsc_waitset_detach, valid_entiti } ret = dds_waitset_detach(*ws, *e); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), exp); + CU_ASSERT_EQUAL_FATAL(ret, exp); } /*************************************************************************************************/ @@ -580,7 +577,7 @@ CU_Test(ddsc_waitset_set_trigger, deleted_waitset, .init=ddsc_waitset_basic_init dds_return_t ret; dds_delete(waitset); ret = dds_waitset_set_trigger(waitset, true); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -590,11 +587,10 @@ CU_TheoryDataPoints(ddsc_waitset_set_trigger, invalid_params) = { }; CU_Theory((dds_entity_t ws), ddsc_waitset_set_trigger, invalid_params, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { - dds_return_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_waitset_set_trigger(ws, true); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -606,7 +602,7 @@ CU_Theory((dds_entity_t *ws), ddsc_waitset_set_trigger, non_waitsets, .init=ddsc { dds_return_t ret; ret = dds_waitset_set_trigger(*ws, true); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -625,7 +621,7 @@ CU_Test(ddsc_waitset_wait, deleted_waitset, .init=ddsc_waitset_attached_init, .f dds_return_t ret; dds_delete(waitset); ret = dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(1)); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -636,11 +632,10 @@ CU_TheoryDataPoints(ddsc_waitset_wait, invalid_waitsets) = { CU_Theory((dds_entity_t ws), ddsc_waitset_wait, invalid_waitsets, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { dds_attach_t triggered; - dds_return_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_waitset_wait(ws, &triggered, 1, DDS_SECS(1)); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -653,7 +648,7 @@ CU_Theory((dds_entity_t *ws), ddsc_waitset_wait, non_waitsets, .init=ddsc_waitse dds_attach_t triggered; dds_return_t ret; ret = dds_waitset_wait(*ws, &triggered, 1, DDS_SECS(1)); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -672,7 +667,7 @@ CU_Theory((dds_attach_t *a, size_t size, int msec), ddsc_waitset_wait, invalid_p CU_ASSERT_FATAL(((a == NULL) && (size != 0)) || ((a != NULL) && (size == 0)) || (msec < 0)); ret = dds_waitset_wait(waitset, a, size, DDS_MSECS(msec)); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -683,7 +678,7 @@ CU_Test(ddsc_waitset_wait_until, deleted_waitset, .init=ddsc_waitset_attached_in dds_return_t ret; dds_delete(waitset); ret = dds_waitset_wait_until(waitset, &triggered, 1, dds_time()); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -694,11 +689,10 @@ CU_TheoryDataPoints(ddsc_waitset_wait_until, invalid_waitsets) = { CU_Theory((dds_entity_t ws), ddsc_waitset_wait_until, invalid_waitsets, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { dds_attach_t triggered; - dds_return_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_return_t ret; ret = dds_waitset_wait_until(ws, &triggered, 1, dds_time()); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -711,7 +705,7 @@ CU_Theory((dds_entity_t *ws), ddsc_waitset_wait_until, non_waitsets, .init=ddsc_ dds_attach_t triggered; dds_return_t ret; ret = dds_waitset_wait_until(*ws, &triggered, 1, dds_time()); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -729,7 +723,7 @@ CU_Theory((dds_attach_t *a, size_t size), ddsc_waitset_wait_until, invalid_param CU_ASSERT_FATAL(((a == NULL) && (size != 0)) || ((a != NULL) && (size == 0))); ret = dds_waitset_wait_until(waitset, a, size, dds_time()); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -843,7 +837,7 @@ CU_Test(ddsc_waitset_get_entities, deleted_waitset, .init=ddsc_waitset_attached_ dds_entity_t entities[MAX_ENTITIES_CNT]; dds_delete(waitset); ret = dds_waitset_get_entities(waitset, entities, MAX_ENTITIES_CNT); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -853,12 +847,11 @@ CU_TheoryDataPoints(ddsc_waitset_get_entities, invalid_params) = { }; CU_Theory((dds_entity_t ws), ddsc_waitset_get_entities, invalid_params, .init=ddsc_waitset_attached_init, .fini=ddsc_waitset_attached_fini) { - dds_return_t exp = DDS_RETCODE_BAD_PARAMETER * -1; dds_entity_t entities[MAX_ENTITIES_CNT]; dds_return_t ret; ret = dds_waitset_get_entities(ws, entities, MAX_ENTITIES_CNT); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), dds_err_nr(exp)); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -871,7 +864,7 @@ CU_Theory((dds_entity_t *ws), ddsc_waitset_get_entities, non_waitsets, .init=dds dds_entity_t entities[MAX_ENTITIES_CNT]; dds_return_t ret; ret = dds_waitset_get_entities(*ws, entities, MAX_ENTITIES_CNT); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } /*************************************************************************************************/ @@ -1073,7 +1066,7 @@ waiting_thread(void *a) return 0; } -static dds_retcode_t +static dds_return_t thread_reached_state(thread_state_t *actual, thread_state_t expected, int32_t msec) { /* Convenience function. */ @@ -1090,7 +1083,7 @@ waiting_thread_start(struct thread_arg_t *arg, dds_entity_t expected) { ddsrt_thread_t thread_id; ddsrt_threadattr_t thread_attr; - dds_retcode_t rc; + dds_return_t rc; assert(arg); @@ -1115,7 +1108,7 @@ waiting_thread_start(struct thread_arg_t *arg, dds_entity_t expected) static dds_return_t waiting_thread_expect_exit(struct thread_arg_t *arg) { - dds_retcode_t rc; + dds_return_t rc; assert(arg); rc = thread_reached_state(&(arg->state), STOPPED, 5000); if (rc == DDS_RETCODE_OK) { diff --git a/src/core/ddsc/tests/write.c b/src/core/ddsc/tests/write.c index 2cd3f15..b5523ce 100644 --- a/src/core/ddsc/tests/write.c +++ b/src/core/ddsc/tests/write.c @@ -65,7 +65,7 @@ CU_Test(ddsc_write, basic, .init = setup, .fini = teardown) dds_return_t status; status = dds_write(writer, &data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); } CU_Test(ddsc_write, null_writer, .init = setup, .fini = teardown) @@ -76,7 +76,7 @@ CU_Test(ddsc_write, null_writer, .init = setup, .fini = teardown) DDSRT_WARNING_MSVC_OFF(28020); status = dds_write(0, &data); DDSRT_WARNING_MSVC_ON(28020); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_write, bad_writer, .init = setup, .fini = teardown) @@ -84,7 +84,7 @@ CU_Test(ddsc_write, bad_writer, .init = setup, .fini = teardown) dds_return_t status; status = dds_write(publisher, &data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_ILLEGAL_OPERATION); } CU_Test(ddsc_write, closed_writer, .init = setup, .fini = teardown) @@ -92,10 +92,10 @@ CU_Test(ddsc_write, closed_writer, .init = setup, .fini = teardown) dds_return_t status; status = dds_delete(writer); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); status = dds_write(writer, &data); writer = 0; - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_write, null_sample, .init = setup, .fini = teardown) @@ -107,7 +107,7 @@ CU_Test(ddsc_write, null_sample, .init = setup, .fini = teardown) status = dds_write(writer, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_write_ts, basic, .init = setup, .fini = teardown) @@ -115,7 +115,7 @@ CU_Test(ddsc_write_ts, basic, .init = setup, .fini = teardown) dds_return_t status; status = dds_write_ts(writer, &data, dds_time()); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); } CU_Test(ddsc_write_ts, bad_timestamp, .init = setup, .fini = teardown) @@ -123,7 +123,7 @@ CU_Test(ddsc_write_ts, bad_timestamp, .init = setup, .fini = teardown) dds_return_t status; status = dds_write_ts(writer, &data, -1); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_write, simpletypes) @@ -152,7 +152,7 @@ CU_Test(ddsc_write, simpletypes) CU_ASSERT_FATAL(wri > 0); status = dds_write(wri, &st_data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); dds_delete(wri); dds_delete(top); diff --git a/src/core/ddsc/tests/writer.c b/src/core/ddsc/tests/writer.c index 66ce1ea..4a9a8c2 100644 --- a/src/core/ddsc/tests/writer.c +++ b/src/core/ddsc/tests/writer.c @@ -57,13 +57,13 @@ CU_Test(ddsc_create_writer, null_parent, .init = setup, .fini = teardown) DDSRT_WARNING_MSVC_OFF(28020); /* Disable SAL warning on intentional misuse of the API */ writer = dds_create_writer(0, topic, NULL, NULL); DDSRT_WARNING_MSVC_ON(28020); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(writer, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_create_writer, bad_parent, .init = setup, .fini = teardown) { writer = dds_create_writer(topic, topic, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(writer, DDS_RETCODE_ILLEGAL_OPERATION); } CU_Test(ddsc_create_writer, participant, .init = setup, .fini = teardown) @@ -83,7 +83,7 @@ CU_Test(ddsc_create_writer, deleted_publisher, .init = setup, .fini = teardown) dds_delete(publisher); writer = dds_create_writer(publisher, topic, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(writer, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_create_writer, null_topic, .init = setup, .fini = teardown) @@ -91,13 +91,13 @@ CU_Test(ddsc_create_writer, null_topic, .init = setup, .fini = teardown) DDSRT_WARNING_MSVC_OFF(28020); /* Disable SAL warning on intentional misuse of the API */ writer = dds_create_writer(publisher, 0, NULL, NULL); DDSRT_WARNING_MSVC_ON(28020); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(writer, DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_create_writer, bad_topic, .init = setup, .fini = teardown) { writer = dds_create_writer(publisher, publisher, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_ILLEGAL_OPERATION); + CU_ASSERT_EQUAL_FATAL(writer, DDS_RETCODE_ILLEGAL_OPERATION); } CU_Test(ddsc_create_writer, deleted_topic, .init = setup, .fini = teardown) @@ -105,5 +105,5 @@ CU_Test(ddsc_create_writer, deleted_topic, .init = setup, .fini = teardown) dds_delete(topic); writer = dds_create_writer(publisher, topic, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(writer, DDS_RETCODE_BAD_PARAMETER); } diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 4a6bb0f..70c2837 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -86,7 +86,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" q_debmon.h q_entity.h q_ephash.h - q_error.h q_feature_check.h q_freelist.h q_gc.h diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h b/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h index 380dac3..c1b8f42 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h @@ -28,8 +28,8 @@ struct ddsi_ssl_plugins void (*fini) (void); void (*ssl_free) (SSL *ssl); void (*bio_vfree) (BIO *bio); - ssize_t (*read) (SSL *ssl, void *buf, size_t len, dds_retcode_t *err); - ssize_t (*write) (SSL *ssl, const void *msg, size_t len, dds_retcode_t *err); + 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) (ddsrt_socket_t sock); BIO * (*listen) (ddsrt_socket_t sock); SSL * (*accept) (BIO *bio, ddsrt_socket_t *sock); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h b/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h index 7d9d346..4a967f5 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h @@ -19,7 +19,7 @@ extern "C" { struct ddsi_threadmon; struct ddsi_threadmon *ddsi_threadmon_new (void); -int ddsi_threadmon_start (struct ddsi_threadmon *sl); +dds_return_t ddsi_threadmon_start (struct ddsi_threadmon *sl); void ddsi_threadmon_stop (struct ddsi_threadmon *sl); void ddsi_threadmon_free (struct ddsi_threadmon *sl); void ddsi_threadmon_statechange_barrier (struct ddsi_threadmon *sl); diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 603b88f..5836165 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -400,9 +400,6 @@ int is_writer_entityid (nn_entityid_t id); int is_reader_entityid (nn_entityid_t id); nn_vendorid_t get_entity_vendorid (const struct entity_common *e); -int pp_allocate_entityid (nn_entityid_t *id, unsigned kind, struct participant *pp); -void pp_release_entityid(struct participant *pp, nn_entityid_t id); - /* Interface for glue code between the OpenSplice kernel and the DDSI entities. These all return 0 iff successful. All GIDs supplied __MUST_BE_UNIQUE__. All hell may break loose if they aren't. @@ -456,20 +453,93 @@ void pp_release_entityid(struct participant *pp, nn_entityid_t id); /* Set this flag to mark the participant as an local entity only. */ #define RTPS_PF_ONLY_LOCAL 16u -/* To create a DDSI participant given a GUID. May return ERR_OUT_OF_IDS - (a.o.) */ -int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const struct nn_plist *plist); +/** + * @brief Create a new participant with a given GUID in the domain. + * + * @param[in] ppguid + * The GUID of the new participant. + * @param[in] flags + * Zero or more of: + * - RTPS_PF_NO_BUILTIN_READERS do not create discovery readers in new ppant + * - RTPS_PF_NO_BUILTIN_WRITERS do not create discvoery writers in new ppant + * - RTPS_PF_PRIVILEGED_PP FIXME: figure out how to describe this ... + * - RTPS_PF_IS_DDSI2_PP FIXME: OSPL holdover - there is no DDSI2E here + * - RTPS_PF_ONLY_LOCAL FIXME: not used, it seems + * @param[in] plist + * Parameters/QoS for this participant + * @param[out] dest + * Filled with the recognized parameters in the input if successful, otherwise + * initialized to an empty parameter list. Where possible, pointers alias the + * 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. + * @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 + * + * @returns A dds_return_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * All parameters valid (or ignored), dest and *nextafterplist have been set + * accordingly. + * @retval DDS_RETCODE_PRECONDITION_NOT_MET + * A participant with GUID *ppguid already exists. + * @retval DDS_RETCODE_OUT_OF_RESOURCES + * The configured maximum number of participants has been reached. + */ +dds_return_t new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const struct nn_plist *plist); -int new_participant (struct nn_guid *ppguid, unsigned flags, const struct nn_plist *plist); +/** + * @brief Create a new participant in the domain. See also new_participant_guid. + * + * @param[out] ppguid + * On successful return: the GUID of the new participant; + * Undefined on error. + * @param[in] flags + * See new_participant_guid + * @param[in] plist + * See new_participant_guid + * + * @returns A dds_return_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * Success, there is now a local participant with the GUID stored in + * *ppguid + * @retval DDS_RETCODE_OUT_OF_RESOURCES + * Failed to allocate a new GUID (note: currently this will always + * happen after 2**24-1 successful calls to new_participant ...). + * @retval DDS_RETCODE_OUT_OF_RESOURCES + * The configured maximum number of participants has been reached. +*/ +dds_return_t new_participant (struct nn_guid *ppguid, unsigned flags, const struct nn_plist *plist); -/* To delete a DDSI participant: this only removes the participant - from the hash tables and schedules the actual delete operation, - which will start doing scary things once all but the DDSI built-in - endpoints are gone. It is acceptable to call delete_participant() - before all its readers and writers have been deleted (which also - fits nicely with model where the glue calls merely schedules - garbage-collection). */ -int delete_participant (const struct nn_guid *ppguid); +/** + * @brief Initiate the deletion of the participant: + * - dispose/unregister built-in topic + * - list it as one of the recently deleted participants + * - remote it from the GUID hash tables + * - schedule the scare stuff to really delete it via the GC + * + * It is ok to call delete_participant without deleting all DDSI-level + * readers/writers: those will simply be deleted. (New ones can't be + * created anymore because the participant can no longer be located via + * the hash tables). + * + * @param[in] ppguid + * GUID of the participant to be deleted. + * + * @returns A dds_return_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * Success, it is no longer visible and GC events have + * been scheduled for eventual deleting of all remaining + * readers and writers and freeing of memory + * @retval DDS_RETCODE_BAD_PARAMETER + * ppguid lookup failed. +*/ +dds_return_t delete_participant (const struct nn_guid *ppguid); /* To obtain the builtin writer to be used for publishing SPDP, SEDP, PMD stuff for PP and its endpoints, given the entityid. If PP has @@ -480,9 +550,9 @@ struct writer *get_builtin_writer (const struct participant *pp, unsigned entity GUID "ppguid". May return NULL if participant unknown or writer/reader already known. */ -dds_retcode_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg); +dds_return_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg); -dds_retcode_t new_reader (struct reader **rd_out, struct nn_guid *rdguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc * rhc, status_cb_t status_cb, void *status_cb_arg); +dds_return_t new_reader (struct reader **rd_out, struct nn_guid *rdguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc * rhc, status_cb_t status_cb, void *status_cb_arg); struct whc_node; struct whc_state; diff --git a/src/core/ddsi/include/dds/ddsi/q_error.h b/src/core/ddsi/include/dds/ddsi/q_error.h deleted file mode 100644 index 8c4f840..0000000 --- a/src/core/ddsi/include/dds/ddsi/q_error.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef NN_ERROR_H -#define NN_ERROR_H - -#define Q_ERR_UNSPECIFIED -1 -#define Q_ERR_INVALID -2 -#define Q_ERR_OUT_OF_MEMORY -3 -#define Q_ERR_ENTITY_EXISTS -4 -#define Q_ERR_UNKNOWN_ENTITY -5 -#define Q_ERR_OUT_OF_IDS -6 -#define Q_ERR_INVALID_DATA -7 -#define Q_ERR_BUSY -8 -#define Q_ERR_NO_ADDRESS -9 -#define Q_ERR_TIMEOUT -10 -#define Q_ERR_INCOMPATIBLE -11 - -#endif /* NN_ERROR_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_plist.h b/src/core/ddsi/include/dds/ddsi/q_plist.h index 6481caa..639401f 100644 --- a/src/core/ddsi/include/dds/ddsi/q_plist.h +++ b/src/core/ddsi/include/dds/ddsi/q_plist.h @@ -196,24 +196,68 @@ 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); 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); -DDS_EXPORT int nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uint64_t pwanted, uint64_t qwanted, const nn_plist_src_t *src); + +/** + * @brief Initialize an nn_plist_t from a PL_CDR_{LE,BE} paylaod. + * + * @param[in] pwanted + * PP_... flags indicating which non-QoS parameters are of interest, treated as + * a hint. Parameters in the input that are outside the mask may or may not be + * ignored. + * @param[in] qwanted + * QP_... flags indicating which QoS settings are of interest, and is treated as + * a hint. Parameters in the input that are outside the mask may or may not be + * ignored. + * @param[in] src + * Serialized payload to be parsed, validated and copied into dest + * - protocol_version is the version protocol version according to which the list + * should be parsed + * - vendorid is the vendor id code for the source of the parameter list (for + * handling vendor-specific parameters and compatibility workarounds) + * - encoding is PL_CDR_LE or PL_CDR_BE + * - buf is a pointer to the first parameter header + * - bufsz is the size in bytes of the input buffer + * @param[out] dest + * Filled with the recognized parameters in the input if successful, otherwise + * initialized to an empty parameter list. Where possible, pointers alias the + * 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. + * @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 + * + * @returns A dds_return_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * All parameters valid (or ignored), dest and *nextafterplist have been set + * accordingly. + * @retval DDS_RETCODE_BAD_PARAMETER + * Input contained invalid data; dest is cleared, *nextafterplist is NULL. + * @retval DDS_RETCODE_UNSUPPORTED + * 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_addtomsg (struct nn_xmsg *m, const nn_plist_t *ps, uint64_t pwanted, uint64_t qwanted); -DDS_EXPORT int nn_plist_init_default_participant (nn_plist_t *plist); +DDS_EXPORT void nn_plist_init_default_participant (nn_plist_t *plist); -DDS_EXPORT int validate_history_qospolicy (const nn_history_qospolicy_t *q); -DDS_EXPORT int validate_durability_qospolicy (const nn_durability_qospolicy_t *q); -DDS_EXPORT int validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q); -DDS_EXPORT int validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, const nn_resource_limits_qospolicy_t *qr); -DDS_EXPORT int validate_durability_service_qospolicy (const nn_durability_service_qospolicy_t *q); -DDS_EXPORT int validate_liveliness_qospolicy (const nn_liveliness_qospolicy_t *q); -DDS_EXPORT int validate_destination_order_qospolicy (const nn_destination_order_qospolicy_t *q); -DDS_EXPORT int validate_ownership_qospolicy (const nn_ownership_qospolicy_t *q); -DDS_EXPORT int validate_ownership_strength_qospolicy (const nn_ownership_strength_qospolicy_t *q); -DDS_EXPORT int validate_presentation_qospolicy (const nn_presentation_qospolicy_t *q); -DDS_EXPORT int validate_transport_priority_qospolicy (const nn_transport_priority_qospolicy_t *q); -DDS_EXPORT int validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t *q); -DDS_EXPORT int validate_duration (const nn_duration_t *d); +DDS_EXPORT dds_return_t validate_history_qospolicy (const nn_history_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_durability_qospolicy (const nn_durability_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, const nn_resource_limits_qospolicy_t *qr); +DDS_EXPORT dds_return_t validate_durability_service_qospolicy (const nn_durability_service_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_liveliness_qospolicy (const nn_liveliness_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_destination_order_qospolicy (const nn_destination_order_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_ownership_qospolicy (const nn_ownership_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_ownership_strength_qospolicy (const nn_ownership_strength_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_presentation_qospolicy (const nn_presentation_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_transport_priority_qospolicy (const nn_transport_priority_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_duration (const nn_duration_t *d); struct nn_rmsg; diff --git a/src/core/ddsi/include/dds/ddsi/q_thread.h b/src/core/ddsi/include/dds/ddsi/q_thread.h index 4d572d2..230e625 100644 --- a/src/core/ddsi/include/dds/ddsi/q_thread.h +++ b/src/core/ddsi/include/dds/ddsi/q_thread.h @@ -98,9 +98,9 @@ DDS_EXPORT void thread_states_fini (void); DDS_EXPORT void upgrade_main_thread (void); DDS_EXPORT void downgrade_main_thread (void); DDS_EXPORT const struct config_thread_properties_listelem *lookup_thread_properties (const char *name); -DDS_EXPORT dds_retcode_t create_thread (struct thread_state1 **ts, const char *name, uint32_t (*f) (void *arg), void *arg); +DDS_EXPORT dds_return_t create_thread (struct thread_state1 **ts, const char *name, uint32_t (*f) (void *arg), void *arg); DDS_EXPORT struct thread_state1 *lookup_thread_state_real (void); -DDS_EXPORT int join_thread (struct thread_state1 *ts1); +DDS_EXPORT dds_return_t join_thread (struct thread_state1 *ts1); DDS_EXPORT void log_stack_traces (void); DDS_EXPORT void reset_thread_state (struct thread_state1 *ts1); DDS_EXPORT int thread_exists (const char *name); diff --git a/src/core/ddsi/include/dds/ddsi/q_transmit.h b/src/core/ddsi/include/dds/ddsi/q_transmit.h index 19cc947..9fc3f2d 100644 --- a/src/core/ddsi/include/dds/ddsi/q_transmit.h +++ b/src/core/ddsi/include/dds/ddsi/q_transmit.h @@ -40,7 +40,7 @@ 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 */ -int 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); +dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, unsigned fragnum, struct proxy_reader *prd,struct nn_xmsg **msg, int isnew); int enqueue_sample_wrlock_held (struct writer *wr, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew); void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_state *whcst, int hbansreq, nn_entityid_t dst, int issync); diff --git a/src/core/ddsi/include/dds/ddsi/q_xevent.h b/src/core/ddsi/include/dds/ddsi/q_xevent.h index ef356f4..4e1513c 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xevent.h +++ b/src/core/ddsi/include/dds/ddsi/q_xevent.h @@ -42,7 +42,7 @@ struct xeventq *xeventq_new /* xeventq_free calls callback handlers with t = T_NEVER, at which point they are required to free whatever memory is claimed for the argument and call delete_xevent. */ DDS_EXPORT void xeventq_free (struct xeventq *evq); -DDS_EXPORT int xeventq_start (struct xeventq *evq, const char *name); /* <0 => error, =0 => ok */ +DDS_EXPORT dds_return_t xeventq_start (struct xeventq *evq, const char *name); /* <0 => error, =0 => ok */ DDS_EXPORT void xeventq_stop (struct xeventq *evq); DDS_EXPORT void qxev_msg (struct xeventq *evq, struct nn_xmsg *msg); diff --git a/src/core/ddsi/include/dds/ddsi/q_xmsg.h b/src/core/ddsi/include/dds/ddsi/q_xmsg.h index ef634a9..f9abcfa 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xmsg.h +++ b/src/core/ddsi/include/dds/ddsi/q_xmsg.h @@ -64,8 +64,8 @@ void nn_xmsg_setdst1 (struct nn_xmsg *m, const nn_guid_prefix_t *gp, const nn_lo /* For sending to a particular proxy reader; this is a convenience routine that extracts a suitable address from the proxy reader's address sets and calls setdst1. */ -int nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd); -int nn_xmsg_setdstPWR (struct nn_xmsg *m, const struct proxy_writer *pwr); +dds_return_t nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd); +dds_return_t nn_xmsg_setdstPWR (struct nn_xmsg *m, const struct proxy_writer *pwr); /* For sending to all in the address set AS -- typically, the writer's address set to multicast to all matched readers */ diff --git a/src/core/ddsi/src/ddsi_raweth.c b/src/core/ddsi/src/ddsi_raweth.c index dc409c7..ef63a73 100644 --- a/src/core/ddsi/src/ddsi_raweth.c +++ b/src/core/ddsi/src/ddsi_raweth.c @@ -16,7 +16,6 @@ #include "dds/ddsi/q_nwif.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/q_pcap.h" #include "dds/ddsi/q_globals.h" #include "dds/ddsrt/atomics.h" @@ -69,7 +68,7 @@ static char *ddsi_raweth_to_string (ddsi_tran_factory_t tran, char *dst, size_t static ssize_t ddsi_raweth_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, bool allow_spurious, nn_locator_t *srcloc) { - dds_retcode_t rc; + dds_return_t rc; ssize_t ret = 0; struct msghdr msghdr; struct sockaddr_ll src; @@ -127,7 +126,7 @@ static ssize_t ddsi_raweth_conn_read (ddsi_tran_conn_t conn, unsigned char * buf static ssize_t ddsi_raweth_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const ddsrt_iovec_t *iov, uint32_t flags) { ddsi_raweth_conn_t uc = (ddsi_raweth_conn_t) conn; - dds_retcode_t rc; + dds_return_t rc; ssize_t ret; unsigned retry = 2; int sendflags = 0; @@ -191,7 +190,7 @@ static int ddsi_raweth_conn_locator (ddsi_tran_base_t base, nn_locator_t *loc) static ddsi_tran_conn_t ddsi_raweth_create_conn (uint32_t port, ddsi_tran_qos_t qos) { ddsrt_socket_t sock; - dds_retcode_t rc; + dds_return_t rc; ddsi_raweth_conn_t uc = NULL; struct sockaddr_ll addr; bool mcast = (bool) (qos ? qos->m_multicast : 0); diff --git a/src/core/ddsi/src/ddsi_ssl.c b/src/core/ddsi/src/ddsi_ssl.c index 2d85f0e..64f8051 100644 --- a/src/core/ddsi/src/ddsi_ssl.c +++ b/src/core/ddsi/src/ddsi_ssl.c @@ -63,7 +63,7 @@ static int ddsi_ssl_verify (int ok, X509_STORE_CTX *store) return ok; } -static ssize_t ddsi_ssl_read (SSL *ssl, void *buf, size_t len, dds_retcode_t *rc) +static ssize_t ddsi_ssl_read (SSL *ssl, void *buf, size_t len, dds_return_t *rc) { assert (len <= INT32_MAX); if (SSL_get_shutdown (ssl) != 0) @@ -95,7 +95,7 @@ static ssize_t ddsi_ssl_read (SSL *ssl, void *buf, size_t len, dds_retcode_t *rc return rcvd; } -static ssize_t ddsi_ssl_write (SSL *ssl, const void *buf, size_t len, dds_retcode_t *rc) +static ssize_t ddsi_ssl_write (SSL *ssl, const void *buf, size_t len, dds_return_t *rc) { assert(len <= INT32_MAX); diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 676099c..bc65a40 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -150,7 +150,7 @@ static unsigned short get_socket_port (ddsrt_socket_t socket) { struct sockaddr_storage addr; socklen_t addrlen = sizeof (addr); - dds_retcode_t ret; + dds_return_t ret; ret = ddsrt_getsockname(socket, (struct sockaddr *)&addr, &addrlen); if (ret != DDS_RETCODE_OK) { @@ -197,7 +197,7 @@ static void ddsi_tcp_conn_connect (ddsi_tcp_conn_t conn, const ddsrt_msghdr_t * { char buff[DDSI_LOCSTRLEN]; ddsrt_socket_t sock; - dds_retcode_t ret; + dds_return_t ret; ddsi_tcp_sock_new (&sock, 0); if (sock != DDSRT_INVALID_SOCKET) @@ -341,7 +341,7 @@ static ddsi_tcp_conn_t ddsi_tcp_cache_find (const ddsrt_msghdr_t * msg) return ret; } -static ssize_t ddsi_tcp_conn_read_plain (ddsi_tcp_conn_t tcp, void * buf, size_t len, dds_retcode_t *rc) +static ssize_t ddsi_tcp_conn_read_plain (ddsi_tcp_conn_t tcp, void * buf, size_t len, dds_return_t *rc) { ssize_t rcvd = -1; @@ -352,7 +352,7 @@ static ssize_t ddsi_tcp_conn_read_plain (ddsi_tcp_conn_t tcp, void * buf, size_t } #ifdef DDSI_INCLUDE_SSL -static ssize_t ddsi_tcp_conn_read_ssl (ddsi_tcp_conn_t tcp, void * buf, size_t len, dds_retcode_t *rc) +static ssize_t ddsi_tcp_conn_read_ssl (ddsi_tcp_conn_t tcp, void * buf, size_t len, dds_return_t *rc) { return (ddsi_tcp_ssl_plugin.read) (tcp->m_ssl, buf, len, rc); } @@ -360,7 +360,7 @@ static ssize_t ddsi_tcp_conn_read_ssl (ddsi_tcp_conn_t tcp, void * buf, size_t l static bool ddsi_tcp_select (ddsrt_socket_t sock, bool read, size_t pos) { - dds_retcode_t rc; + dds_return_t rc; fd_set fds; fd_set * rdset = read ? &fds : NULL; fd_set * wrset = read ? NULL : &fds; @@ -395,9 +395,9 @@ static bool ddsi_tcp_select (ddsrt_socket_t sock, bool read, size_t pos) 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) { - dds_retcode_t rc; + 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_retcode_t * err) = ddsi_tcp_conn_read_plain; + ssize_t (*rd) (ddsi_tcp_conn_t, void *, size_t, dds_return_t * err) = ddsi_tcp_conn_read_plain; size_t pos = 0; ssize_t n; @@ -452,7 +452,7 @@ static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s return -1; } -static ssize_t ddsi_tcp_conn_write_plain (ddsi_tcp_conn_t conn, const void * buf, size_t len, dds_retcode_t *rc) +static ssize_t ddsi_tcp_conn_write_plain (ddsi_tcp_conn_t conn, const void * buf, size_t len, dds_return_t *rc) { ssize_t sent = -1; int sendflags = 0; @@ -466,7 +466,7 @@ static ssize_t ddsi_tcp_conn_write_plain (ddsi_tcp_conn_t conn, const void * buf } #ifdef DDSI_INCLUDE_SSL -static ssize_t ddsi_tcp_conn_write_ssl (ddsi_tcp_conn_t conn, const void * buf, size_t len, dds_retcode_t *rc) +static ssize_t ddsi_tcp_conn_write_ssl (ddsi_tcp_conn_t conn, const void * buf, size_t len, dds_return_t *rc) { return (ddsi_tcp_ssl_plugin.write) (conn->m_ssl, buf, len, rc); } @@ -474,7 +474,7 @@ static ssize_t ddsi_tcp_conn_write_ssl (ddsi_tcp_conn_t conn, const void * buf, static ssize_t ddsi_tcp_block_write ( - ssize_t (*wr) (ddsi_tcp_conn_t, const void *, size_t, dds_retcode_t *), + ssize_t (*wr) (ddsi_tcp_conn_t, const void *, size_t, dds_return_t *), ddsi_tcp_conn_t conn, const void * buf, size_t sz @@ -482,7 +482,7 @@ static ssize_t ddsi_tcp_block_write { /* Write all bytes of buf even in the presence of signals, partial writes and blocking (typically write buffer full) */ - dds_retcode_t rc; + dds_return_t rc; size_t pos = 0; ssize_t n = -1; @@ -615,7 +615,7 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const nn_locator_t *d #endif { int sendflags = 0; - dds_retcode_t rc; + dds_return_t rc; #ifdef MSG_NOSIGNAL sendflags |= MSG_NOSIGNAL; #endif @@ -661,7 +661,7 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const nn_locator_t *d if (piecewise) { - ssize_t (*wr) (ddsi_tcp_conn_t, const void *, size_t, dds_retcode_t *) = ddsi_tcp_conn_write_plain; + ssize_t (*wr) (ddsi_tcp_conn_t, const void *, size_t, dds_return_t *) = ddsi_tcp_conn_write_plain; int i = 0; #ifdef DDSI_INCLUDE_SSL if (ddsi_tcp_ssl_plugin.write) @@ -749,7 +749,7 @@ static ddsi_tran_conn_t ddsi_tcp_accept (ddsi_tran_listener_t listener) struct sockaddr_storage addr; socklen_t addrlen = sizeof (addr); char buff[DDSI_LOCSTRLEN]; - dds_retcode_t rc = DDS_RETCODE_OK; + dds_return_t rc = DDS_RETCODE_OK; #ifdef DDSI_INCLUDE_SSL SSL * ssl = NULL; #endif @@ -875,7 +875,7 @@ static ddsi_tran_listener_t ddsi_tcp_create_listener (int port, ddsi_tran_qos_t if (sock != DDSRT_INVALID_SOCKET) { - dds_retcode_t ret; + dds_return_t ret; tl = (ddsi_tcp_listener_t) ddsrt_malloc (sizeof (*tl)); memset (tl, 0, sizeof (*tl)); @@ -953,7 +953,7 @@ static void ddsi_tcp_unblock_listener (ddsi_tran_listener_t listener) { ddsi_tcp_listener_t tl = (ddsi_tcp_listener_t) listener; ddsrt_socket_t sock; - dds_retcode_t ret; + dds_return_t ret; /* Connect to own listener socket to wake listener from blocking 'accept()' */ ddsi_tcp_sock_new (&sock, 0); diff --git a/src/core/ddsi/src/ddsi_threadmon.c b/src/core/ddsi/src/ddsi_threadmon.c index 1f9d4af..d687b9f 100644 --- a/src/core/ddsi/src/ddsi_threadmon.c +++ b/src/core/ddsi/src/ddsi_threadmon.c @@ -21,7 +21,6 @@ #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_unused.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/q_globals.h" /* for mattr, cattr */ #include "dds/ddsi/q_receive.h" @@ -166,7 +165,7 @@ struct ddsi_threadmon *ddsi_threadmon_new (void) return NULL; } -int ddsi_threadmon_start (struct ddsi_threadmon *sl) +dds_return_t ddsi_threadmon_start (struct ddsi_threadmon *sl) { ddsrt_mutex_lock (&sl->lock); assert (sl->keepgoing == -1); @@ -179,7 +178,7 @@ int ddsi_threadmon_start (struct ddsi_threadmon *sl) fail_thread: sl->keepgoing = -1; - return Q_ERR_UNSPECIFIED; + return DDS_RETCODE_ERROR; } void ddsi_threadmon_statechange_barrier (struct ddsi_threadmon *sl) diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index e2e1576..85fde82 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -54,7 +54,7 @@ static ddsrt_atomic_uint32_t ddsi_udp_init_g = DDSRT_ATOMIC_UINT32_INIT(0); static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, bool allow_spurious, nn_locator_t *srcloc) { - dds_retcode_t rc; + dds_return_t rc; ssize_t ret = 0; ddsrt_msghdr_t msghdr; struct sockaddr_storage src; @@ -117,7 +117,7 @@ static void set_msghdr_iov (ddsrt_msghdr_t *mhdr, ddsrt_iovec_t *iov, size_t iov static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const ddsrt_iovec_t *iov, uint32_t flags) { - dds_retcode_t rc; + dds_return_t rc; ssize_t ret = -1; unsigned retry = 2; int sendflags = 0; @@ -214,7 +214,7 @@ static int ddsi_udp_conn_locator (ddsi_tran_base_t base, nn_locator_t *loc) static unsigned short get_socket_port (ddsrt_socket_t socket) { - dds_retcode_t ret; + dds_return_t ret; struct sockaddr_storage addr; socklen_t addrlen = sizeof (addr); @@ -282,7 +282,7 @@ static ddsi_tran_conn_t ddsi_udp_create_conn #ifdef DDSI_INCLUDE_NETWORK_CHANNELS if ((uc->m_diffserv != 0) && (ddsi_udp_factory_g.m_kind == NN_LOCATOR_KIND_UDPv4)) { - dds_retcode_t rc; + dds_return_t rc; rc = ddsrt_setsockopt(sock, IPPROTO_IP, IP_TOS, (char *)&uc->m_diffserv, sizeof(uc->m_diffserv)); if (rc != DDS_RETCODE_OK) DDS_ERROR("ddsi_udp_create_conn: set diffserv retcode %"PRId32"\n", rc); @@ -307,7 +307,7 @@ static ddsi_tran_conn_t ddsi_udp_create_conn static int joinleave_asm_mcgroup (ddsrt_socket_t socket, int join, const nn_locator_t *mcloc, const struct nn_interface *interf) { - dds_retcode_t rc; + dds_return_t rc; struct sockaddr_storage mcip; ddsi_ipaddr_from_loc(&mcip, mcloc); #if DDSRT_HAVE_IPV6 @@ -336,7 +336,7 @@ static int joinleave_asm_mcgroup (ddsrt_socket_t socket, int join, const nn_loca #ifdef DDSI_INCLUDE_SSM static int joinleave_ssm_mcgroup (ddsrt_socket_t socket, int join, const nn_locator_t *srcloc, const nn_locator_t *mcloc, const struct nn_interface *interf) { - dds_retcode_t rc; + dds_return_t rc; struct sockaddr_storage mcip, srcip; ddsi_ipaddr_from_loc(&mcip, mcloc); ddsi_ipaddr_from_loc(&srcip, srcloc); diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 98f030b..383534c 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -31,7 +31,6 @@ #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_addrset.h" #include "dds/ddsi/q_nwif.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsrt/xmlparser.h" diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 8a75416..654ce2c 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -40,7 +40,6 @@ #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_transmit.h" #include "dds/ddsi/q_lease.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/ddsi_serdata_default.h" #include "dds/ddsi/q_feature_check.h" @@ -793,7 +792,7 @@ static void handle_SPDP (const struct receiver_state *rst, nn_wctime_t timestamp nn_plist_t decoded_data; nn_plist_src_t src; int interesting = 0; - int plist_ret; + dds_return_t plist_ret; src.protocol_version = rst->protocol_version; src.vendorid = rst->vendor; src.encoding = data->identifier; @@ -801,7 +800,7 @@ static void handle_SPDP (const struct receiver_state *rst, nn_wctime_t timestamp src.bufsz = len - 4; if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { - if (plist_ret != Q_ERR_INCOMPATIBLE) + if (plist_ret != DDS_RETCODE_UNSUPPORTED) DDS_WARNING("SPDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); return; } @@ -1335,7 +1334,7 @@ static void handle_SEDP (const struct receiver_state *rst, nn_wctime_t timestamp { nn_plist_t decoded_data; nn_plist_src_t src; - int plist_ret; + dds_return_t plist_ret; src.protocol_version = rst->protocol_version; src.vendorid = rst->vendor; src.encoding = data->identifier; @@ -1343,7 +1342,7 @@ static void handle_SEDP (const struct receiver_state *rst, nn_wctime_t timestamp src.bufsz = len - 4; if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { - if (plist_ret != Q_ERR_INCOMPATIBLE) + if (plist_ret != DDS_RETCODE_UNSUPPORTED) DDS_WARNING("SEDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); return; } @@ -1463,7 +1462,7 @@ static void handle_SEDP_CM (const struct receiver_state *rst, nn_entityid_t wr_e { nn_plist_t decoded_data; nn_plist_src_t src; - int plist_ret; + dds_return_t plist_ret; src.protocol_version = rst->protocol_version; src.vendorid = rst->vendor; src.encoding = data->identifier; @@ -1471,7 +1470,7 @@ static void handle_SEDP_CM (const struct receiver_state *rst, nn_entityid_t wr_e src.bufsz = len - 4; if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { - if (plist_ret != Q_ERR_INCOMPATIBLE) + if (plist_ret != DDS_RETCODE_UNSUPPORTED) DDS_WARNING("SEDP_CM (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); return; } @@ -1625,7 +1624,7 @@ static void handle_SEDP_GROUP (const struct receiver_state *rst, nn_wctime_t tim { nn_plist_t decoded_data; nn_plist_src_t src; - int plist_ret; + dds_return_t plist_ret; src.protocol_version = rst->protocol_version; src.vendorid = rst->vendor; src.encoding = data->identifier; @@ -1633,7 +1632,7 @@ static void handle_SEDP_GROUP (const struct receiver_state *rst, nn_wctime_t tim src.bufsz = len - 4; if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { - if (plist_ret != Q_ERR_INCOMPATIBLE) + if (plist_ret != DDS_RETCODE_UNSUPPORTED) DDS_WARNING("SEDP_GROUP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); return; } @@ -1748,7 +1747,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str { nn_plist_src_t src; size_t qos_offset = NN_RDATA_SUBMSG_OFF (fragchain) + offsetof (Data_DataFrag_common_t, octetsToInlineQos) + sizeof (msg->octetsToInlineQos) + msg->octetsToInlineQos; - int plist_ret; + dds_return_t plist_ret; src.protocol_version = sampleinfo->rst->protocol_version; src.vendorid = sampleinfo->rst->vendor; src.encoding = (msg->smhdr.flags & SMFLAG_ENDIANNESS) ? PL_CDR_LE : PL_CDR_BE; @@ -1756,7 +1755,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str src.bufsz = NN_RDATA_PAYLOAD_OFF (fragchain) - qos_offset; if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH, 0, &src)) < 0) { - if (plist_ret != Q_ERR_INCOMPATIBLE) + if (plist_ret != DDS_RETCODE_UNSUPPORTED) DDS_WARNING("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n", src.vendorid.id[0], src.vendorid.id[1], PGUID (srcguid), sampleinfo->seq); goto done_upd_deliv; diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index 9ea929f..a3362cb 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -33,7 +33,6 @@ #include "dds/ddsi/q_ddsi_discovery.h" #include "dds/ddsi/q_protocol.h" /* NN_ENTITYID_... */ #include "dds/ddsi/q_unused.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/q_debmon.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_tran.h" diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 9dc0024..18d2895 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -38,7 +38,6 @@ #include "dds/ddsi/q_radmin.h" #include "dds/ddsi/q_protocol.h" /* NN_ENTITYID_... */ #include "dds/ddsi/q_unused.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/ddsi_serdata_default.h" #include "dds/ddsi/ddsi_mcgroup.h" #include "dds/ddsi/q_receive.h" @@ -88,8 +87,8 @@ static const unsigned prismtech_builtin_writers_besmask = NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER | NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER; -static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_cbarg); -static dds_retcode_t new_reader_guid (struct reader **rd_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc *rhc, status_cb_t status_cb, void *status_cbarg); +static dds_return_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_cbarg); +static dds_return_t new_reader_guid (struct reader **rd_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc *rhc, status_cb_t status_cb, void *status_cbarg); static struct participant *ref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity); static void unref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity); static void delete_proxy_group_locked (struct proxy_group *pgroup, nn_wctime_t timestamp, int isimplicit); @@ -376,7 +375,7 @@ static void remove_deleted_participant_guid (const struct nn_guid *guid, unsigne /* PARTICIPANT ------------------------------------------------------ */ -int pp_allocate_entityid(nn_entityid_t *id, unsigned kind, struct participant *pp) +static dds_return_t pp_allocate_entityid(nn_entityid_t *id, unsigned kind, struct participant *pp) { uint32_t id1; int ret = 0; @@ -389,20 +388,20 @@ int pp_allocate_entityid(nn_entityid_t *id, unsigned kind, struct participant *p else { DDS_ERROR("pp_allocate_entityid("PGUIDFMT"): all ids in use\n", PGUID(pp->e.guid)); - ret = Q_ERR_OUT_OF_IDS; + ret = DDS_RETCODE_OUT_OF_RESOURCES; } ddsrt_mutex_unlock (&pp->e.lock); return ret; } -void pp_release_entityid(struct participant *pp, nn_entityid_t id) +static void pp_release_entityid(struct participant *pp, nn_entityid_t id) { ddsrt_mutex_lock (&pp->e.lock); inverse_uint32_set_free(&pp->avail_entityids.x, id.u / NN_ENTITYID_ALLOCSTEP); ddsrt_mutex_unlock (&pp->e.lock); } -int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plist_t *plist) +dds_return_t new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plist_t *plist) { struct participant *pp; nn_guid_t subguid, group_guid; @@ -420,7 +419,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis used to exist, but is currently being deleted and we're trying to recreate it. */ if (ephash_lookup_participant_guid (ppguid) != NULL) - return Q_ERR_ENTITY_EXISTS; + return DDS_RETCODE_PRECONDITION_NOT_MET; if (config.max_participants == 0) { @@ -440,7 +439,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis { ddsrt_mutex_unlock (&gv.participant_set_lock); DDS_ERROR("new_participant("PGUIDFMT", %x) failed: max participants reached\n", PGUID (*ppguid), flags); - return Q_ERR_OUT_OF_IDS; + return DDS_RETCODE_OUT_OF_RESOURCES; } } @@ -658,7 +657,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis return 0; } -int new_participant (nn_guid_t *p_ppguid, unsigned flags, const nn_plist_t *plist) +dds_return_t new_participant (nn_guid_t *p_ppguid, unsigned flags, const nn_plist_t *plist) { nn_guid_t ppguid; @@ -667,7 +666,7 @@ int new_participant (nn_guid_t *p_ppguid, unsigned flags, const nn_plist_t *plis if (gv.next_ppguid.prefix.u[2]++ == ~0u) { ddsrt_mutex_unlock (&gv.privileged_pp_lock); - return Q_ERR_OUT_OF_IDS; + return DDS_RETCODE_OUT_OF_RESOURCES; } ddsrt_mutex_unlock (&gv.privileged_pp_lock); *p_ppguid = ppguid; @@ -858,11 +857,11 @@ static void gc_delete_participant (struct gcreq *gcreq) unref_participant (pp, NULL); } -int delete_participant (const struct nn_guid *ppguid) +dds_return_t delete_participant (const struct nn_guid *ppguid) { struct participant *pp; if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) - return Q_ERR_UNKNOWN_ENTITY; + return DDS_RETCODE_BAD_PARAMETER; ddsi_plugin.builtintopic_write (&pp->e, now(), false); remember_deleted_participant_guid (&pp->e.guid); ephash_remove_participant_guid (pp); @@ -2821,7 +2820,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se local_reader_ary_init (&wr->rdary); } -static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_entity) +static dds_return_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_entity) { struct writer *wr; nn_mtime_t tnow = now_mt (); @@ -2868,24 +2867,25 @@ static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_gu resched_xevent_if_earlier (pp->pmd_update_xevent, tsched); } - return DDS_RETCODE_OK; + return 0; } -dds_retcode_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg) +dds_return_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg) { struct participant *pp; + dds_return_t rc; if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "new_writer - participant "PGUIDFMT" not found\n", PGUID (*ppguid)); - return DDS_RETCODE_NOT_FOUND; + return DDS_RETCODE_BAD_PARAMETER; } /* participant can't be freed while we're mucking around cos we are awake and do not touch the thread's vtime (ephash_lookup already verifies we're awake) */ wrguid->prefix = pp->e.guid.prefix; - if (pp_allocate_entityid (&wrguid->entityid, NN_ENTITYID_KIND_WRITER_WITH_KEY, pp) < 0) - return DDS_RETCODE_OUT_OF_RESOURCES; + if ((rc = pp_allocate_entityid (&wrguid->entityid, NN_ENTITYID_KIND_WRITER_WITH_KEY, pp)) < 0) + return rc; return new_writer_guid (wr_out, wrguid, group_guid, pp, topic, xqos, whc, status_cb, status_cb_arg); } @@ -3027,7 +3027,7 @@ int delete_writer_nolinger (const struct nn_guid *guid) if ((wr = ephash_lookup_writer_guid (guid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid)); - return Q_ERR_UNKNOWN_ENTITY; + return DDS_RETCODE_BAD_PARAMETER; } DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (*guid)); ddsrt_mutex_lock (&wr->e.lock); @@ -3050,7 +3050,7 @@ int delete_writer (const struct nn_guid *guid) if ((wr = ephash_lookup_writer_guid (guid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid)); - return Q_ERR_UNKNOWN_ENTITY; + return DDS_RETCODE_BAD_PARAMETER; } DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") ...\n", PGUID (*guid)); ddsrt_mutex_lock (&wr->e.lock); @@ -3196,7 +3196,7 @@ static void leave_mcast_helper (const nn_locator_t *n, void * varg) } #endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */ -static dds_retcode_t new_reader_guid +static dds_return_t new_reader_guid ( struct reader **rd_out, const struct nn_guid *guid, @@ -3332,10 +3332,10 @@ static dds_retcode_t new_reader_guid match_reader_with_proxy_writers (rd, tnow); match_reader_with_local_writers (rd, tnow); sedp_write_reader (rd); - return DDS_RETCODE_OK; + return 0; } -dds_retcode_t new_reader +dds_return_t new_reader ( struct reader **rd_out, struct nn_guid *rdguid, @@ -3349,15 +3349,16 @@ dds_retcode_t new_reader ) { struct participant * pp; + dds_return_t rc; if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "new_reader - participant "PGUIDFMT" not found\n", PGUID (*ppguid)); - return DDS_RETCODE_NOT_FOUND; + return DDS_RETCODE_BAD_PARAMETER; } rdguid->prefix = pp->e.guid.prefix; - if (pp_allocate_entityid (&rdguid->entityid, NN_ENTITYID_KIND_READER_WITH_KEY, pp) < 0) - return DDS_RETCODE_OUT_OF_RESOURCES; + if ((rc = pp_allocate_entityid (&rdguid->entityid, NN_ENTITYID_KIND_READER_WITH_KEY, pp)) < 0) + return rc; return new_reader_guid (rd_out, rdguid, group_guid, pp, topic, xqos, rhc, status_cb, status_cbarg); } @@ -3415,7 +3416,7 @@ int delete_reader (const struct nn_guid *guid) if ((rd = ephash_lookup_reader_guid (guid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid)); - return Q_ERR_UNKNOWN_ENTITY; + return DDS_RETCODE_BAD_PARAMETER; } DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid "PGUIDFMT") ...\n", PGUID (*guid)); ddsi_plugin.builtintopic_write (&rd->e, now(), false); @@ -3918,7 +3919,7 @@ int delete_proxy_participant_by_guid (const struct nn_guid * guid, nn_wctime_t t { ddsrt_mutex_unlock (&gv.lock); DDS_LOG(DDS_LC_DISCOVERY, "- unknown\n"); - return Q_ERR_UNKNOWN_ENTITY; + return DDS_RETCODE_BAD_PARAMETER; } DDS_LOG(DDS_LC_DISCOVERY, "- deleting\n"); ddsi_plugin.builtintopic_write (&ppt->e, timestamp, false); @@ -3973,7 +3974,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct break; default: DDS_WARNING("new_proxy_group: unrecognised entityid: %"PRIx32"\n", guid->entityid.u); - return Q_ERR_INVALID_DATA; + return DDS_RETCODE_BAD_PARAMETER; } ddsrt_mutex_lock (&proxypp->e.lock); if ((pgroup = ddsrt_avl_lookup_ipath (&proxypp_groups_treedef, &proxypp->groups, guid, &ipath)) != NULL) @@ -4102,7 +4103,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, if ((proxypp = ephash_lookup_proxy_participant_guid (ppguid)) == NULL) { DDS_WARNING("new_proxy_writer("PGUIDFMT"): proxy participant unknown\n", PGUID (*guid)); - return Q_ERR_UNKNOWN_ENTITY; + return DDS_RETCODE_BAD_PARAMETER; } pwr = ddsrt_malloc (sizeof (*pwr)); @@ -4301,7 +4302,7 @@ int delete_proxy_writer (const struct nn_guid *guid, nn_wctime_t timestamp, int { ddsrt_mutex_unlock (&gv.lock); DDS_LOG(DDS_LC_DISCOVERY, "- unknown\n"); - return Q_ERR_UNKNOWN_ENTITY; + return DDS_RETCODE_BAD_PARAMETER; } /* Set "deleting" flag in particular for Lite, to signal to the receive path it can't trust rdary[] anymore, which is because removing the proxy writer from the hash @@ -4334,7 +4335,7 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, if ((proxypp = ephash_lookup_proxy_participant_guid (ppguid)) == NULL) { DDS_WARNING("new_proxy_reader("PGUIDFMT"): proxy participant unknown\n", PGUID (*guid)); - return Q_ERR_UNKNOWN_ENTITY; + return DDS_RETCODE_BAD_PARAMETER; } prd = ddsrt_malloc (sizeof (*prd)); @@ -4437,7 +4438,7 @@ int delete_proxy_reader (const struct nn_guid *guid, nn_wctime_t timestamp, int { ddsrt_mutex_unlock (&gv.lock); DDS_LOG(DDS_LC_DISCOVERY, "- unknown\n"); - return Q_ERR_UNKNOWN_ENTITY; + return DDS_RETCODE_BAD_PARAMETER; } ddsi_plugin.builtintopic_write (&prd->e, timestamp, false); ephash_remove_proxy_reader_guid (prd); diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index df26b1d..f224960 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -36,7 +36,6 @@ #include "dds/ddsi/q_addrset.h" #include "dds/ddsi/q_ddsi_discovery.h" #include "dds/ddsi/q_radmin.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_lease.h" diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index f15f9dd..839eacf 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -96,7 +96,7 @@ static int set_rcvbuf (ddsrt_socket_t socket) uint32_t ReceiveBufferSize; socklen_t optlen = (socklen_t) sizeof (ReceiveBufferSize); uint32_t socket_min_rcvbuf_size; - dds_retcode_t rc; + dds_return_t rc; if (config.socket_min_rcvbuf_size.isdefault) socket_min_rcvbuf_size = 1048576; else @@ -145,7 +145,7 @@ static int set_sndbuf (ddsrt_socket_t socket) { unsigned SendBufferSize; socklen_t optlen = (socklen_t) sizeof(SendBufferSize); - dds_retcode_t rc; + dds_return_t rc; rc = ddsrt_getsockopt( socket, SOL_SOCKET, SO_SNDBUF,(char *)&SendBufferSize, &optlen); if (rc == DDS_RETCODE_BAD_PARAMETER) { @@ -202,7 +202,7 @@ static int set_reuse_options (ddsrt_socket_t socket) /* Set REUSEADDR (if available on platform) for multicast sockets, leave unicast sockets alone. */ int one = 1; - dds_retcode_t rc = ddsrt_setsockopt ( + dds_return_t rc = ddsrt_setsockopt ( socket, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof (one)); if (rc == DDS_RETCODE_BAD_PARAMETER) { DDS_LOG(DDS_LC_CONFIG, "cannot enable address reuse on socket\n"); @@ -217,7 +217,7 @@ static int set_reuse_options (ddsrt_socket_t socket) static int bind_socket (ddsrt_socket_t socket, unsigned short port) { - dds_retcode_t rc = DDS_RETCODE_ERROR; + dds_return_t rc = DDS_RETCODE_ERROR; #if DDSRT_HAVE_IPV6 if (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6) @@ -279,7 +279,7 @@ static int set_mc_options_transmit_ipv4 (ddsrt_socket_t socket) { unsigned char ttl = (unsigned char) config.multicast_ttl; unsigned char loop; - dds_retcode_t ret; + dds_return_t ret; #if (defined(__linux) || defined(__APPLE__)) && !LWIP_SOCKET if (config.use_multicast_if_mreqn) @@ -348,7 +348,7 @@ int make_socket ) { int rc = -2; - dds_retcode_t ret; + dds_return_t ret; #if DDSRT_HAVE_IPV6 if (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6) diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index a83f9f9..bae275b 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -22,7 +22,6 @@ #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_unused.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/q_plist.h" #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_xmsg.h" @@ -87,31 +86,31 @@ static int protocol_version_is_newer (nn_protocol_version_t pv) return (pv.major < RTPS_MAJOR) ? 0 : (pv.major > RTPS_MAJOR) ? 1 : (pv.minor > RTPS_MINOR); } -static int validate_string (const struct dd *dd, size_t *len) +static dds_return_t validate_string (const struct dd *dd, size_t *len) { const struct cdrstring *x = (const struct cdrstring *) dd->buf; if (dd->bufsz < sizeof (struct cdrstring)) { DDS_TRACE("plist/validate_string: buffer too small (header)\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } *len = dd->bswap ? bswap4u (x->length) : x->length; if (*len < 1 || *len > dd->bufsz - offsetof (struct cdrstring, contents)) { DDS_TRACE("plist/validate_string: length %" PRIuSIZE " out of range\n", *len); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if (x->contents[*len-1] != 0) { DDS_TRACE("plist/validate_string: terminator missing\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } return 0; } -static int alias_string (const unsigned char **ptr, const struct dd *dd, size_t *len) +static dds_return_t alias_string (const unsigned char **ptr, const struct dd *dd, size_t *len) { - int rc; + dds_return_t rc; if ((rc = validate_string (dd, len)) < 0) return rc; else @@ -139,21 +138,21 @@ static void unalias_string (char **str, int bswap) memcpy (*str, alias, len); } -static int validate_octetseq (const struct dd *dd, size_t *len) +static dds_return_t validate_octetseq (const struct dd *dd, size_t *len) { const struct cdroctetseq *x = (const struct cdroctetseq *) dd->buf; if (dd->bufsz < offsetof (struct cdroctetseq, value)) - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; *len = dd->bswap ? bswap4u (x->len) : x->len; if (*len > dd->bufsz - offsetof (struct cdroctetseq, value) || *len >= UINT32_MAX) - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; return 0; } -static int alias_octetseq (nn_octetseq_t *oseq, const struct dd *dd) +static dds_return_t alias_octetseq (nn_octetseq_t *oseq, const struct dd *dd) { size_t len; - int rc; + dds_return_t rc; if ((rc = validate_octetseq (dd, &len)) < 0) return rc; else @@ -166,7 +165,7 @@ static int alias_octetseq (nn_octetseq_t *oseq, const struct dd *dd) } } -static int alias_blob (nn_octetseq_t *oseq, const struct dd *dd) +static dds_return_t alias_blob (nn_octetseq_t *oseq, const struct dd *dd) { assert (dd->bufsz < UINT32_MAX); oseq->length = (uint32_t)dd->bufsz; @@ -185,7 +184,7 @@ static void unalias_octetseq (nn_octetseq_t *oseq, UNUSED_ARG (int bswap)) } } -static int validate_stringseq (const struct dd *dd) +static dds_return_t validate_stringseq (const struct dd *dd) { const unsigned char *seq = dd->buf; const unsigned char *seqend = seq + dd->bufsz; @@ -194,7 +193,7 @@ static int validate_stringseq (const struct dd *dd) if (dd->bufsz < sizeof (int)) { DDS_TRACE("plist/validate_stringseq: buffer too small (header)\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } memcpy (&n, seq, sizeof (n)); if (dd->bswap) @@ -203,7 +202,7 @@ static int validate_stringseq (const struct dd *dd) if (n < 0) { DDS_TRACE("plist/validate_stringseq: length %d out of range\n", n); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else if (n == 0) { @@ -227,7 +226,7 @@ static int validate_stringseq (const struct dd *dd) if (i < n) { DDS_TRACE("plist/validate_stringseq: buffer too small (contents)\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } /* Should I worry about junk between the last string & the end of @@ -235,7 +234,7 @@ static int validate_stringseq (const struct dd *dd) return 0; } -static int alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) +static dds_return_t alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) { /* Not truly an alias: it allocates an array of pointers that alias the individual null-terminated strings. Also: see @@ -245,11 +244,11 @@ static int alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) struct dd dd1 = *dd; char **strs; unsigned i; - int result; + dds_return_t result; if (dd->bufsz < sizeof (int)) { DDS_TRACE("plist/alias_stringseq: buffer too small (header)\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } memcpy (&strseq->n, seq, sizeof (strseq->n)); if (dd->bswap) @@ -258,7 +257,7 @@ static int alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) if (strseq->n >= UINT_MAX / sizeof(*strs)) { DDS_TRACE("plist/alias_stringseq: length %"PRIu32" out of range\n", strseq->n); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else if (strseq->n == 0) { @@ -285,7 +284,7 @@ static int alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) if (i != strseq->n) { DDS_TRACE("plist/validate_stringseq: buffer too small (contents)\n"); - result = Q_ERR_INVALID; + result = DDS_RETCODE_BAD_PARAMETER; goto fail; } strseq->strs = strs; @@ -300,16 +299,12 @@ static void free_stringseq (nn_stringseq_t *strseq) { unsigned i; for (i = 0; i < strseq->n; i++) - { if (strseq->strs[i]) - { ddsrt_free (strseq->strs[i]); - } - } ddsrt_free (strseq->strs); } -static int unalias_stringseq (nn_stringseq_t *strseq, int bswap) +static dds_return_t unalias_stringseq (nn_stringseq_t *strseq, int bswap) { unsigned i; char **strs; @@ -465,9 +460,9 @@ void nn_plist_unalias (nn_plist_t *ps) } #endif -static int do_octetseq (nn_octetseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) +static dds_return_t do_octetseq (nn_octetseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) { - int res; + dds_return_t res; size_t len; if (!(wanted & fl)) return NN_STRICT_P ? validate_octetseq (dd, &len) : 0; @@ -479,9 +474,9 @@ static int do_octetseq (nn_octetseq_t *dst, uint64_t *present, uint64_t *aliased return res; } -static int do_blob (nn_octetseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) +static dds_return_t do_blob (nn_octetseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) { - int res; + dds_return_t res; if (!(wanted & fl)) return 0; if ((res = alias_blob (dst, dd)) >= 0) @@ -492,9 +487,9 @@ static int do_blob (nn_octetseq_t *dst, uint64_t *present, uint64_t *aliased, ui return res; } -static int do_string (char **dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) +static dds_return_t do_string (char **dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) { - int res; + dds_return_t res; size_t len; if (!(wanted & fl)) return NN_STRICT_P ? validate_string (dd, &len) : 0; @@ -506,9 +501,9 @@ static int do_string (char **dst, uint64_t *present, uint64_t *aliased, uint64_t return res; } -static int do_stringseq (nn_stringseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) +static dds_return_t do_stringseq (nn_stringseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) { - int res; + dds_return_t res; if (!(wanted & fl)) return NN_STRICT_P ? validate_stringseq (dd) : 0; if ((res = alias_stringseq (dst, dd)) >= 0) @@ -525,9 +520,9 @@ static void bswap_time (nn_ddsi_time_t *t) t->fraction = bswap4u (t->fraction); } -static int validate_time (const nn_ddsi_time_t *t) +static dds_return_t validate_time (const nn_ddsi_time_t *t) { - /* Accepter are zero, positive, infinite or invalid as defined in + /* Accepted are zero, positive, infinite or invalid as defined in the DDS 2.1 spec, table 9.4. */ if (t->seconds >= 0) return 0; @@ -536,7 +531,7 @@ static int validate_time (const nn_ddsi_time_t *t) else { DDS_TRACE("plist/validate_time: invalid timestamp (%08x.%08x)\n", t->seconds, t->fraction); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } @@ -545,18 +540,18 @@ static void bswap_duration (nn_duration_t *d) bswap_time (d); } -int validate_duration (const nn_duration_t *d) +dds_return_t validate_duration (const nn_duration_t *d) { return validate_time (d); } -static int do_duration (nn_duration_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) +static dds_return_t do_duration (nn_duration_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) { - int res; + dds_return_t res; if (dd->bufsz < sizeof (*q)) { DDS_TRACE("plist/do_duration: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } memcpy (q, dd->buf, sizeof (*q)); if (dd->bswap) @@ -572,7 +567,7 @@ static void bswap_durability_qospolicy (nn_durability_qospolicy_t *q) q->kind = bswap4u (q->kind); } -int validate_durability_qospolicy (const nn_durability_qospolicy_t *q) +dds_return_t validate_durability_qospolicy (const nn_durability_qospolicy_t *q) { switch (q->kind) { @@ -583,7 +578,7 @@ int validate_durability_qospolicy (const nn_durability_qospolicy_t *q) break; default: DDS_TRACE("plist/validate_durability_qospolicy: invalid kind (%d)\n", (int) q->kind); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } return 0; } @@ -599,7 +594,7 @@ static int history_qospolicy_allzero (const nn_history_qospolicy_t *q) return q->kind == NN_KEEP_LAST_HISTORY_QOS && q->depth == 0; } -int validate_history_qospolicy (const nn_history_qospolicy_t *q) +dds_return_t validate_history_qospolicy (const nn_history_qospolicy_t *q) { /* Validity of history setting and of resource limits are dependent, but we don't have access to the resource limits here ... the @@ -615,7 +610,7 @@ int validate_history_qospolicy (const nn_history_qospolicy_t *q) break; default: DDS_TRACE("plist/validate_history_qospolicy: invalid kind (%d)\n", (int) q->kind); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } /* Accept all values for depth if kind = ALL */ if (q->kind == NN_KEEP_LAST_HISTORY_QOS) @@ -623,7 +618,7 @@ int validate_history_qospolicy (const nn_history_qospolicy_t *q) if (q->depth < 1) { DDS_TRACE("plist/validate_history_qospolicy: invalid depth (%d)\n", (int) q->depth); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } return 0; @@ -641,7 +636,7 @@ static int resource_limits_qospolicy_allzero (const nn_resource_limits_qospolicy return q->max_samples == 0 && q->max_instances == 0 && q->max_samples_per_instance == 0; } -int validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q) +dds_return_t validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q) { const int unlimited = NN_DDS_LENGTH_UNLIMITED; /* Note: dependent on history setting as well (see @@ -650,17 +645,17 @@ int validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q) if (q->max_samples < 1 && q->max_samples != unlimited) { DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples invalid (%d)\n", (int) q->max_samples); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if (q->max_instances < 1 && q->max_instances != unlimited) { DDS_TRACE("plist/validate_resource_limits_qospolicy: max_instances invalid (%d)\n", (int) q->max_instances); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if (q->max_samples_per_instance < 1 && q->max_samples_per_instance != unlimited) { DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples_per_instance invalid (%d)\n", (int) q->max_samples_per_instance); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if (q->max_samples != unlimited && q->max_samples_per_instance != unlimited) { @@ -669,16 +664,16 @@ int validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q) if (q->max_samples < q->max_samples_per_instance) { DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples (%d) and max_samples_per_instance (%d) incompatible\n", (int) q->max_samples, (int) q->max_samples_per_instance); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } return 0; } -int validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, const nn_resource_limits_qospolicy_t *qr) +dds_return_t validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, const nn_resource_limits_qospolicy_t *qr) { const int unlimited = NN_DDS_LENGTH_UNLIMITED; - int res; + dds_return_t res; if ((res = validate_history_qospolicy (qh)) < 0) { DDS_TRACE("plist/validate_history_and_resource_limits: history policy invalid\n"); @@ -696,7 +691,7 @@ int validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, cons if (qr->max_samples_per_instance != unlimited) { DDS_TRACE("plist/validate_history_and_resource_limits: max_samples_per_instance (%d) incompatible with KEEP_ALL policy\n", (int) qr->max_samples_per_instance); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } #endif break; @@ -704,7 +699,7 @@ int validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, cons if (qr->max_samples_per_instance != unlimited && qh->depth > qr->max_samples_per_instance) { DDS_TRACE("plist/validate_history_and_resource_limits: depth (%d) and max_samples_per_instance (%d) incompatible with KEEP_LAST policy\n", (int) qh->depth, (int) qr->max_samples_per_instance); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } break; } @@ -725,9 +720,9 @@ static int durability_service_qospolicy_allzero (const nn_durability_service_qos q->service_cleanup_delay.seconds == 0 && q->service_cleanup_delay.fraction == 0); } -static int validate_durability_service_qospolicy_acceptzero (const nn_durability_service_qospolicy_t *q, bool acceptzero) +static dds_return_t validate_durability_service_qospolicy_acceptzero (const nn_durability_service_qospolicy_t *q, bool acceptzero) { - int res; + dds_return_t res; if (acceptzero && durability_service_qospolicy_allzero (q)) return 0; if ((res = validate_duration (&q->service_cleanup_delay)) < 0) @@ -743,7 +738,7 @@ static int validate_durability_service_qospolicy_acceptzero (const nn_durability return 0; } -int validate_durability_service_qospolicy (const nn_durability_service_qospolicy_t *q) +dds_return_t validate_durability_service_qospolicy (const nn_durability_service_qospolicy_t *q) { return validate_durability_service_qospolicy_acceptzero (q, false); } @@ -754,9 +749,9 @@ static void bswap_liveliness_qospolicy (nn_liveliness_qospolicy_t *q) bswap_duration (&q->lease_duration); } -int validate_liveliness_qospolicy (const nn_liveliness_qospolicy_t *q) +dds_return_t validate_liveliness_qospolicy (const nn_liveliness_qospolicy_t *q) { - int res; + dds_return_t res; switch (q->kind) { case NN_AUTOMATIC_LIVELINESS_QOS: @@ -767,7 +762,7 @@ int validate_liveliness_qospolicy (const nn_liveliness_qospolicy_t *q) return res; default: DDS_TRACE("plist/validate_liveliness_qospolicy: invalid kind (%d)\n", (int) q->kind); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } @@ -777,9 +772,9 @@ static void bswap_external_reliability_qospolicy (nn_external_reliability_qospol bswap_duration (&qext->max_blocking_time); } -static int validate_xform_reliability_qospolicy (nn_reliability_qospolicy_t *qdst, const nn_external_reliability_qospolicy_t *qext) +static dds_return_t validate_xform_reliability_qospolicy (nn_reliability_qospolicy_t *qdst, const nn_external_reliability_qospolicy_t *qext) { - int res; + dds_return_t res; qdst->max_blocking_time = qext->max_blocking_time; if (NN_PEDANTIC_P) { @@ -795,7 +790,7 @@ static int validate_xform_reliability_qospolicy (nn_reliability_qospolicy_t *qds return res; default: DDS_TRACE("plist/validate_xform_reliability_qospolicy[pedantic]: invalid kind (%d)\n", (int) qext->kind); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } else @@ -812,7 +807,7 @@ static int validate_xform_reliability_qospolicy (nn_reliability_qospolicy_t *qds return res; default: DDS_TRACE("plist/validate_xform_reliability_qospolicy[!pedantic]: invalid kind (%d)\n", (int) qext->kind); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } } @@ -822,7 +817,7 @@ static void bswap_destination_order_qospolicy (nn_destination_order_qospolicy_t q->kind = bswap4u (q->kind); } -int validate_destination_order_qospolicy (const nn_destination_order_qospolicy_t *q) +dds_return_t validate_destination_order_qospolicy (const nn_destination_order_qospolicy_t *q) { switch (q->kind) { @@ -831,7 +826,7 @@ int validate_destination_order_qospolicy (const nn_destination_order_qospolicy_t return 0; default: DDS_TRACE("plist/validate_destination_order_qospolicy: invalid kind (%d)\n", (int) q->kind); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } @@ -840,7 +835,7 @@ static void bswap_ownership_qospolicy (nn_ownership_qospolicy_t *q) q->kind = bswap4u (q->kind); } -int validate_ownership_qospolicy (const nn_ownership_qospolicy_t *q) +dds_return_t validate_ownership_qospolicy (const nn_ownership_qospolicy_t *q) { switch (q->kind) { @@ -849,7 +844,7 @@ int validate_ownership_qospolicy (const nn_ownership_qospolicy_t *q) return 0; default: DDS_TRACE("plist/validate_ownership_qospolicy: invalid kind (%d)\n", (int) q->kind); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } @@ -858,9 +853,9 @@ static void bswap_ownership_strength_qospolicy (nn_ownership_strength_qospolicy_ q->value = bswap4 (q->value); } -int validate_ownership_strength_qospolicy (UNUSED_ARG (const nn_ownership_strength_qospolicy_t *q)) +dds_return_t validate_ownership_strength_qospolicy (UNUSED_ARG (const nn_ownership_strength_qospolicy_t *q)) { - return 1; + return 0; } static void bswap_presentation_qospolicy (nn_presentation_qospolicy_t *q) @@ -868,7 +863,7 @@ static void bswap_presentation_qospolicy (nn_presentation_qospolicy_t *q) q->access_scope = bswap4u (q->access_scope); } -int validate_presentation_qospolicy (const nn_presentation_qospolicy_t *q) +dds_return_t validate_presentation_qospolicy (const nn_presentation_qospolicy_t *q) { switch (q->access_scope) { @@ -878,18 +873,18 @@ int validate_presentation_qospolicy (const nn_presentation_qospolicy_t *q) break; default: DDS_TRACE("plist/validate_presentation_qospolicy: invalid access_scope (%d)\n", (int) q->access_scope); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } /* Bools must be 0 or 1, i.e., only the lsb may be set */ if (q->coherent_access & ~1) { DDS_TRACE("plist/validate_presentation_qospolicy: coherent_access invalid (%d)\n", (int) q->coherent_access); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if (q->ordered_access & ~1) { DDS_TRACE("plist/validate_presentation_qospolicy: ordered_access invalid (%d)\n", (int) q->ordered_access); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } /* coherent_access & ordered_access are a bit irrelevant for instance presentation qos, but it appears as if their values are @@ -902,12 +897,12 @@ static void bswap_transport_priority_qospolicy (nn_transport_priority_qospolicy_ q->value = bswap4 (q->value); } -int validate_transport_priority_qospolicy (UNUSED_ARG (const nn_transport_priority_qospolicy_t *q)) +dds_return_t validate_transport_priority_qospolicy (UNUSED_ARG (const nn_transport_priority_qospolicy_t *q)) { - return 1; + return 0; } -static int add_locator (nn_locators_t *ls, uint64_t *present, uint64_t wanted, uint64_t fl, const nn_locator_t *loc) +static dds_return_t add_locator (nn_locators_t *ls, uint64_t *present, uint64_t wanted, uint64_t fl, const nn_locator_t *loc) { if (wanted & fl) { @@ -951,7 +946,7 @@ static int locator_address_zero (const nn_locator_t *loc) return (u[0] == 0 && u[1] == 0 && u[2] == 0 && u[3] == 0); } -static int do_locator +static dds_return_t do_locator ( nn_locators_t *ls, uint64_t *present, @@ -965,7 +960,7 @@ static int do_locator if (dd->bufsz < sizeof (loc)) { DDS_TRACE("plist/do_locator: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } memcpy (&loc, dd->buf, sizeof (loc)); if (dd->bswap) @@ -980,12 +975,12 @@ static int do_locator if (loc.port <= 0 || loc.port > 65535) { DDS_TRACE("plist/do_locator[kind=IPv4]: invalid port (%d)\n", (int) loc.port); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if (!locator_address_prefix12_zero (&loc)) { DDS_TRACE("plist/do_locator[kind=IPv4]: junk in address prefix\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } break; case NN_LOCATOR_KIND_UDPv6: @@ -993,7 +988,7 @@ static int do_locator if (loc.port <= 0 || loc.port > 65535) { DDS_TRACE("plist/do_locator[kind=IPv6]: invalid port (%d)\n", (int) loc.port); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } break; case NN_LOCATOR_KIND_UDPv4MCGEN: { @@ -1003,12 +998,12 @@ static int do_locator if (loc.port <= 0 || loc.port > 65536) { DDS_TRACE("plist/do_locator[kind=IPv4MCGEN]: invalid port (%d)\n", (int) loc.port); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if ((int)x->base + x->count >= 28 || x->count == 0 || x->idx >= x->count) { DDS_TRACE("plist/do_locator[kind=IPv4MCGEN]: invalid base/count/idx (%u,%u,%u)\n", x->base, x->count, x->idx); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } break; } @@ -1016,12 +1011,12 @@ static int do_locator if (!locator_address_zero (&loc)) { DDS_TRACE("plist/do_locator[kind=INVALID]: junk in address\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if (loc.port != 0) { DDS_TRACE("plist/do_locator[kind=INVALID]: junk in port\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } /* silently dropped correctly formatted "invalid" locators. */ return 0; @@ -1030,7 +1025,7 @@ static int do_locator return 0; default: DDS_TRACE("plist/do_locator: invalid kind (%d)\n", (int) loc.kind); - return NN_PEDANTIC_P ? Q_ERR_INVALID : 0; + return NN_PEDANTIC_P ? DDS_RETCODE_BAD_PARAMETER : 0; } return add_locator (ls, present, wanted, fl, &loc); } @@ -1043,7 +1038,7 @@ static void locator_from_ipv4address_port (nn_locator_t *loc, const nn_ipv4addre memcpy (loc->address + 12, a, 4); } -static int do_ipv4address (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t wanted, unsigned fl_tmp, const struct dd *dd) +static dds_return_t do_ipv4address (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t wanted, unsigned fl_tmp, const struct dd *dd) { nn_ipv4address_t *a; nn_port_t *p; @@ -1053,7 +1048,7 @@ static int do_ipv4address (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp if (dd->bufsz < sizeof (*a)) { DDS_TRACE("plist/do_ipv4address: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } switch (fl_tmp) { @@ -1113,7 +1108,7 @@ static int do_ipv4address (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp } } -static int do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t wanted, unsigned fl_tmp, const struct dd *dd) +static dds_return_t do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t wanted, unsigned fl_tmp, const struct dd *dd) { nn_ipv4address_t *a; nn_port_t *p; @@ -1123,7 +1118,7 @@ static int do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint6 if (dd->bufsz < sizeof (*p)) { DDS_TRACE("plist/do_port: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } switch (fl_tmp) { @@ -1157,7 +1152,7 @@ static int do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint6 if (*p <= 0 || *p > 65535) { DDS_TRACE("plist/do_port: invalid port (%d)\n", (int) *p); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } dest_tmp->present |= fl_tmp; if ((dest_tmp->present & (fl_tmp | fl1_tmp)) == (fl_tmp | fl1_tmp)) @@ -1176,7 +1171,7 @@ static int do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint6 } } -static int valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd)) +static dds_return_t valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd)) { /* All 0 is GUID_UNKNOWN, which is a defined GUID */ if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0) @@ -1186,7 +1181,7 @@ static int valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct else { DDS_TRACE("plist/valid_participant_guid: prefix is 0 but entityid is not (%"PRIu32")\n", g->entityid.u); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } else if (g->entityid.u == NN_ENTITYID_PARTICIPANT) @@ -1196,11 +1191,11 @@ static int valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct else { DDS_TRACE("plist/valid_participant_guid: entityid not a participant entityid (%"PRIu32")\n", g->entityid.u); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } -static int valid_group_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd)) +static dds_return_t valid_group_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd)) { /* All 0 is GUID_UNKNOWN, which is a defined GUID */ if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0) @@ -1210,7 +1205,7 @@ static int valid_group_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd else { DDS_TRACE("plist/valid_group_guid: prefix is 0 but entityid is not (%"PRIu32")\n", g->entityid.u); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } else if (g->entityid.u != 0) @@ -1221,11 +1216,11 @@ static int valid_group_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd else { DDS_TRACE("plist/valid_group_guid: entityid is 0\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } -static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) +static dds_return_t valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) { /* All 0 is GUID_UNKNOWN, which is a defined GUID */ if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0) @@ -1235,7 +1230,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) else { DDS_TRACE("plist/valid_endpoint_guid: prefix is 0 but entityid is not (%"PRIx32")\n", g->entityid.u); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } switch (g->entityid.u & NN_ENTITYID_SOURCE_MASK) @@ -1256,7 +1251,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) DDS_TRACE("plist/valid_endpoint_guid[src=USER,proto=%u.%u]: invalid kind (%"PRIx32")\n", dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u & NN_ENTITYID_KIND_MASK); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } case NN_ENTITYID_SOURCE_BUILTIN: @@ -1280,7 +1275,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) { DDS_TRACE("plist/valid_endpoint_guid[src=BUILTIN,proto=%u.%u]: invalid entityid (%"PRIx32")\n", dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } case NN_ENTITYID_SOURCE_VENDOR: @@ -1310,16 +1305,16 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) } default: DDS_TRACE("plist/valid_endpoint_guid: invalid source (%"PRIx32")\n", g->entityid.u); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } -static int do_guid (nn_guid_t *dst, uint64_t *present, uint64_t fl, int (*valid) (const nn_guid_t *g, const struct dd *dd), const struct dd *dd) +static dds_return_t do_guid (nn_guid_t *dst, uint64_t *present, uint64_t fl, int (*valid) (const nn_guid_t *g, const struct dd *dd), const struct dd *dd) { if (dd->bufsz < sizeof (*dst)) { DDS_TRACE("plist/do_guid: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } memcpy (dst, dd->buf, sizeof (*dst)); *dst = nn_ntoh_guid (*dst); @@ -1335,7 +1330,7 @@ static int do_guid (nn_guid_t *dst, uint64_t *present, uint64_t fl, int (*valid) } else { - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } } *present |= fl; @@ -1352,18 +1347,18 @@ static void bswap_prismtech_participant_version_info (nn_prismtech_participant_v pvi->unused[i] = bswap4u (pvi->unused[i]); } -static int do_prismtech_participant_version_info (nn_prismtech_participant_version_info_t *pvi, uint64_t *present, uint64_t *aliased, const struct dd *dd) +static dds_return_t do_prismtech_participant_version_info (nn_prismtech_participant_version_info_t *pvi, uint64_t *present, uint64_t *aliased, const struct dd *dd) { if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) return 0; else if (dd->bufsz < NN_PRISMTECH_PARTICIPANT_VERSION_INFO_FIXED_CDRSIZE) { DDS_TRACE("plist/do_prismtech_participant_version_info[pid=PRISMTECH_PARTICIPANT_VERSION_INFO]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else { - int res; + dds_return_t res; unsigned sz = NN_PRISMTECH_PARTICIPANT_VERSION_INFO_FIXED_CDRSIZE - sizeof(uint32_t); uint32_t *pu = (uint32_t *)dd->buf; size_t len; @@ -1385,22 +1380,20 @@ static int do_prismtech_participant_version_info (nn_prismtech_participant_versi } } - - -static int do_subscription_keys_qospolicy (nn_subscription_keys_qospolicy_t *q, uint64_t *present, uint64_t *aliased, uint64_t fl, const struct dd *dd) +static dds_return_t do_subscription_keys_qospolicy (nn_subscription_keys_qospolicy_t *q, uint64_t *present, uint64_t *aliased, uint64_t fl, const struct dd *dd) { struct dd dd1; - int res; + dds_return_t res; if (dd->bufsz < 4) { DDS_TRACE("plist/do_subscription_keys: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } q->use_key_list = (unsigned char) dd->buf[0]; if (q->use_key_list != 0 && q->use_key_list != 1) { DDS_TRACE("plist/do_subscription_keys: invalid use_key_list (%d)\n", (int) q->use_key_list); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } dd1 = *dd; dd1.buf += 4; @@ -1413,18 +1406,18 @@ static int do_subscription_keys_qospolicy (nn_subscription_keys_qospolicy_t *q, return res; } -static int unalias_subscription_keys_qospolicy (nn_subscription_keys_qospolicy_t *q, int bswap) +static dds_return_t unalias_subscription_keys_qospolicy (nn_subscription_keys_qospolicy_t *q, int bswap) { return unalias_stringseq (&q->key_list, bswap); } -static int do_reader_lifespan_qospolicy (nn_reader_lifespan_qospolicy_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) +static dds_return_t do_reader_lifespan_qospolicy (nn_reader_lifespan_qospolicy_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) { - int res; + dds_return_t res; if (dd->bufsz < sizeof (*q)) { DDS_TRACE("plist/do_reader_lifespan: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } *q = *((nn_reader_lifespan_qospolicy_t *) dd->buf); if (dd->bswap) @@ -1432,47 +1425,47 @@ static int do_reader_lifespan_qospolicy (nn_reader_lifespan_qospolicy_t *q, uint if (q->use_lifespan != 0 && q->use_lifespan != 1) { DDS_TRACE("plist/do_reader_lifespan: invalid use_lifespan (%d)\n", (int) q->use_lifespan); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if ((res = validate_duration (&q->duration)) >= 0) *present |= fl; return res; } -static int do_entity_factory_qospolicy (nn_entity_factory_qospolicy_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) +static dds_return_t do_entity_factory_qospolicy (nn_entity_factory_qospolicy_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) { if (dd->bufsz < sizeof (*q)) { DDS_TRACE("plist/do_entity_factory: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } q->autoenable_created_entities = dd->buf[0]; if (q->autoenable_created_entities != 0 && q->autoenable_created_entities != 1) { DDS_TRACE("plist/do_entity_factory: invalid autoenable_created_entities (%d)\n", (int) q->autoenable_created_entities); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } *present |= fl; return 0; } -int validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t *q) +dds_return_t validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t *q) { if (validate_duration (&q->autopurge_nowriter_samples_delay) < 0 || validate_duration (&q->autopurge_disposed_samples_delay) < 0) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid autopurge_nowriter_sample_delay or autopurge_disposed_samples_delay\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if (q->autopurge_dispose_all != 0 && q->autopurge_dispose_all != 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid autopurge_dispose_all\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if (q->enable_invalid_samples != 0 && q->enable_invalid_samples != 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid enable_invalid_samples\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } /* Don't check consistency between enable_invalid_samples and invalid_samples_mode (yet) */ switch (q->invalid_sample_visibility) @@ -1483,12 +1476,12 @@ int validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t * break; default: DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid invalid_sample_visibility\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } return 0; } -static int do_reader_data_lifecycle_v0 (nn_reader_data_lifecycle_qospolicy_t *q, const struct dd *dd) +static dds_return_t do_reader_data_lifecycle_v0 (nn_reader_data_lifecycle_qospolicy_t *q, const struct dd *dd) { memcpy (q, dd->buf, 2 * sizeof (nn_duration_t)); q->autopurge_dispose_all = 0; @@ -1502,7 +1495,7 @@ static int do_reader_data_lifecycle_v0 (nn_reader_data_lifecycle_qospolicy_t *q, return validate_reader_data_lifecycle (q); } -static int do_reader_data_lifecycle_v1 (nn_reader_data_lifecycle_qospolicy_t *q, const struct dd *dd) +static dds_return_t do_reader_data_lifecycle_v1 (nn_reader_data_lifecycle_qospolicy_t *q, const struct dd *dd) { memcpy (q, dd->buf, sizeof (*q)); if (dd->bswap) @@ -1514,7 +1507,7 @@ static int do_reader_data_lifecycle_v1 (nn_reader_data_lifecycle_qospolicy_t *q, return validate_reader_data_lifecycle (q); } -static int init_one_parameter +static dds_return_t init_one_parameter ( nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, @@ -1524,7 +1517,7 @@ static int init_one_parameter const struct dd *dd ) { - int res; + dds_return_t res; switch (pid) { case PID_PAD: @@ -1536,7 +1529,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (nn_##name_##_qospolicy_t)) \ { \ DDS_TRACE("plist/init_one_parameter[pid=%s]: buffer too small\n", #NAME_); \ - return Q_ERR_INVALID; \ + return DDS_RETCODE_BAD_PARAMETER; \ } \ else \ { \ @@ -1563,7 +1556,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (nn_durability_service_qospolicy_t)) { DDS_TRACE("plist/init_one_parameter[pid=DURABILITY_SERVICE]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else { @@ -1590,7 +1583,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (nn_external_reliability_qospolicy_t)) { DDS_TRACE("plist/init_one_parameter[pid=RELIABILITY]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else { @@ -1631,7 +1624,7 @@ static int init_one_parameter case PID_PRISMTECH_READER_DATA_LIFECYCLE: /* PrismTech specific */ { - int ret; + dds_return_t ret; if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) return 0; if (dd->bufsz >= sizeof (nn_reader_data_lifecycle_qospolicy_t)) @@ -1641,7 +1634,7 @@ static int init_one_parameter else { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: buffer too small\n"); - ret = Q_ERR_INVALID; + ret = DDS_RETCODE_BAD_PARAMETER; } if (ret >= 0) dest->qos.present |= QP_PRISMTECH_READER_DATA_LIFECYCLE; @@ -1656,7 +1649,7 @@ static int init_one_parameter if (dd->bufsz < 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else if (dd->bufsz < sizeof (*q)) { @@ -1677,13 +1670,13 @@ static int init_one_parameter if (q->autodispose_unregistered_instances & ~1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: invalid autodispose_unregistered_instances (%d)\n", (int) q->autodispose_unregistered_instances); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if (validate_duration (&q->autounregister_instance_delay) < 0 || validate_duration (&q->autopurge_suspended_samples_delay) < 0) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: invalid autounregister_instance_delay or autopurge_suspended_samples_delay\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } dest->qos.present |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE; return 0; @@ -1695,7 +1688,7 @@ static int init_one_parameter else if (dd->bufsz < sizeof (dest->qos.relaxed_qos_matching)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_RELAXED_QOS_MATCHING]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else { @@ -1704,7 +1697,7 @@ static int init_one_parameter if (rqm->value != 0 && rqm->value != 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_RELAXED_QOS_MATCHING]: invalid\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } dest->qos.present |= QP_PRISMTECH_RELAXED_QOS_MATCHING; return 0; @@ -1716,7 +1709,7 @@ static int init_one_parameter else if (dd->bufsz < sizeof (dest->qos.synchronous_endpoint)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SYNCHRONOUS_ENDPOINT]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else { @@ -1725,7 +1718,7 @@ static int init_one_parameter if (q->value != 0 && q->value != 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SYNCHRONOUS_ENDPOINT]: invalid value for synchronous flag\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } dest->qos.present |= QP_PRISMTECH_SYNCHRONOUS_ENDPOINT; return 0; @@ -1736,7 +1729,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (nn_protocol_version_t)) { DDS_TRACE("plist/init_one_parameter[pid=PROTOCOL_VERSION]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } memcpy (&dest->protocol_version, dd->buf, sizeof (dest->protocol_version)); if (NN_STRICT_P && @@ -1749,14 +1742,14 @@ static int init_one_parameter DDS_TRACE("plist/init_one_parameter[pid=PROTOCOL_VERSION,mode=STRICT]: version (%u.%u) mismatch with message (%u.%u)\n", dest->protocol_version.major, dest->protocol_version.minor, dd->protocol_version.major, dd->protocol_version.minor); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } dest->present |= PP_PROTOCOL_VERSION; return 0; case PID_VENDORID: if (dd->bufsz < sizeof (nn_vendorid_t)) - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; memcpy (&dest->vendorid, dd->buf, sizeof (dest->vendorid)); if (NN_STRICT_P && (dest->vendorid.id[0] != dd->vendorid.id[0] || @@ -1765,7 +1758,7 @@ static int init_one_parameter /* see PROTOCOL_VERSION */ DDS_TRACE("plist/init_one_parameter[pid=VENDORID,mode=STRICT]: vendor (%u.%u) mismatch with message (%u.%u)\n", dest->vendorid.id[0], dest->vendorid.id[1], dd->vendorid.id[0], dd->vendorid.id[1]); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } dest->present |= PP_VENDORID; return 0; @@ -1809,7 +1802,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->expects_inline_qos)) { DDS_TRACE("plist/init_one_parameter[pid=EXPECTS_INLINE_QOS]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } dest->expects_inline_qos = dd->buf[0]; /* boolean: only lsb may be set */ @@ -1817,7 +1810,7 @@ static int init_one_parameter { DDS_TRACE("plist/init_one_parameter[pid=EXPECTS_INLINE_QOS]: invalid expects_inline_qos (%d)\n", (int) dest->expects_inline_qos); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } dest->present |= PP_EXPECTS_INLINE_QOS; return 0; @@ -1829,7 +1822,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->participant_manual_liveliness_count)) { DDS_TRACE("plist/init_one_parameter[pid=PARTICIPANT_MANUAL_LIVELINESS_COUNT]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } memcpy (&dest->participant_manual_liveliness_count, dd->buf, sizeof (dest->participant_manual_liveliness_count)); if (dd->bswap) @@ -1863,7 +1856,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->builtin_endpoint_set)) { DDS_TRACE("plist/init_one_parameter[pid=BUILTIN_ENDPOINT_SET(%u)]: buffer too small\n", pid); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } memcpy (&dest->builtin_endpoint_set, dd->buf, sizeof (dest->builtin_endpoint_set)); if (dd->bswap) @@ -1888,7 +1881,7 @@ static int init_one_parameter { DDS_TRACE("plist/init_one_parameter[pid=BUILTIN_ENDPOINT_SET(%u),mode=STRICT,proto=%u.%u]: invalid set (0x%x)\n", pid, dd->protocol_version.major, dd->protocol_version.minor, dest->builtin_endpoint_set); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } dest->present |= PP_BUILTIN_ENDPOINT_SET; return 0; @@ -1899,7 +1892,7 @@ static int init_one_parameter else if (dd->bufsz < sizeof (dest->prismtech_builtin_endpoint_set)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_BUILTIN_ENDPOINT_SET(%u)]: buffer too small\n", pid); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else { @@ -1922,7 +1915,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->keyhash)) { DDS_TRACE("plist/init_one_parameter[pid=KEYHASH]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } memcpy (&dest->keyhash, dd->buf, sizeof (dest->keyhash)); dest->present |= PP_KEYHASH; @@ -1932,7 +1925,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->statusinfo)) { DDS_TRACE("plist/init_one_parameter[pid=STATUSINFO]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } memcpy (&dest->statusinfo, dd->buf, sizeof (dest->statusinfo)); dest->statusinfo = fromBE4u (dest->statusinfo); @@ -1943,7 +1936,7 @@ static int init_one_parameter may use them in this version of the specification */ DDS_TRACE("plist/init_one_parameter[pid=STATUSINFO,mode=STRICT,proto=%u.%u]: invalid statusinfo (0x%x)\n", dd->protocol_version.major, dd->protocol_version.minor, dest->statusinfo); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } /* Clear all bits we don't understand, then add the extended bits if present */ dest->statusinfo &= NN_STATUSINFO_STANDARDIZED; @@ -1963,7 +1956,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->coherent_set_seqno)) { DDS_TRACE("plist/init_one_parameter[pid=COHERENT_SET]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else { @@ -1979,7 +1972,7 @@ static int init_one_parameter if (seqno <= 0 && seqno != NN_SEQUENCE_NUMBER_UNKNOWN) { DDS_TRACE("plist/init_one_parameter[pid=COHERENT_SET]: invalid sequence number (%" PRId64 ")\n", seqno); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } dest->present |= PP_COHERENT_SET; return 0; @@ -2000,7 +1993,7 @@ static int init_one_parameter ignore it. */ DDS_TRACE("plist/init_one_parameter[pid=ENDPOINT_GUID,mode=PEDANTIC,proto=%u.%u]: undefined pid\n", dd->protocol_version.major, dd->protocol_version.minor); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } return do_guid (&dest->endpoint_guid, &dest->present, PP_ENDPOINT_GUID, valid_endpoint_guid, dd); @@ -2021,7 +2014,6 @@ static int init_one_parameter return 0; } - case PID_PRISMTECH_PARTICIPANT_VERSION_INFO: return do_prismtech_participant_version_info(&dest->prismtech_participant_version_info, &dest->present, &dest->aliased, dd); @@ -2035,7 +2027,6 @@ static int init_one_parameter return 0; return do_reader_lifespan_qospolicy (&dest->qos.reader_lifespan, &dest->qos.present, QP_PRISMTECH_READER_LIFESPAN, dd); - case PID_PRISMTECH_ENTITY_FACTORY: if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) return 0; @@ -2057,7 +2048,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->service_type)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SERVICE_TYPE]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } memcpy (&dest->service_type, dd->buf, sizeof (dest->service_type)); if (dd->bswap) @@ -2071,7 +2062,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->process_id)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_PROCESS_ID]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } memcpy (&dest->process_id, dd->buf, sizeof (dest->process_id)); if (dd->bswap) @@ -2090,7 +2081,7 @@ static int init_one_parameter else if (dd->bufsz < 2*sizeof (uint32_t)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_EOTINFO]: buffer too small (1)\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else { @@ -2106,7 +2097,7 @@ static int init_one_parameter if (q->n > (dd->bufsz - 2*sizeof (uint32_t)) / sizeof (nn_prismtech_eotgroup_tid_t)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_EOTINFO]: buffer too small (2)\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if (q->n == 0) q->tids = NULL; @@ -2135,7 +2126,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->reader_favours_ssm)) { DDS_TRACE("plist/init_one_parameter[pid=READER_FAVOURS_SSM]: buffer too small\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else { @@ -2175,13 +2166,13 @@ static int init_one_parameter bugs & the buffer overflows originate! */ if (pid & PID_UNRECOGNIZED_INCOMPATIBLE_FLAG) { dest->present |= PP_INCOMPATIBLE; - return Q_ERR_INCOMPATIBLE; + return DDS_RETCODE_UNSUPPORTED; } else if (pid & PID_VENDORSPECIFIC_FLAG) { return 0; } else if (!protocol_version_is_newer (dd->protocol_version) && NN_STRICT_P) { DDS_TRACE("plist/init_one_parameter[pid=%u,mode=STRICT,proto=%u.%u]: undefined paramter id\n", pid, dd->protocol_version.major, dd->protocol_version.minor); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else { return 0; } @@ -2189,7 +2180,7 @@ static int init_one_parameter assert (0); DDS_TRACE("plist/init_one_parameter: can't happen\n"); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } static void default_resource_limits (nn_resource_limits_qospolicy_t *q) @@ -2299,7 +2290,7 @@ nn_plist_t *nn_plist_dup (const nn_plist_t *src) return dst; } -static int final_validation (nn_plist_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid) +static dds_return_t final_validation (nn_plist_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid) { /* Resource limits & history are related, so if only one is given, set the other to the default, claim it has been provided & @@ -2317,7 +2308,7 @@ static int final_validation (nn_plist_t *dest, nn_protocol_version_t protocol_ve } if (dest->qos.present & (QP_HISTORY | QP_RESOURCE_LIMITS)) { - int res; + dds_return_t res; assert ((dest->qos.present & (QP_HISTORY | QP_RESOURCE_LIMITS)) == (QP_HISTORY | QP_RESOURCE_LIMITS)); if ((res = validate_history_and_resource_limits (&dest->qos.history, &dest->qos.resource_limits)) < 0) return res; @@ -2357,7 +2348,7 @@ static int final_validation (nn_plist_t *dest, nn_protocol_version_t protocol_ve /* if it is still present, it must be valid */ if (dest->qos.present & QP_DURABILITY_SERVICE) { - int res; + dds_return_t res; if ((res = validate_durability_service_qospolicy (&dest->qos.durability_service)) < 0) return res; } @@ -2365,7 +2356,7 @@ static int final_validation (nn_plist_t *dest, nn_protocol_version_t protocol_ve return 0; } -int nn_plist_init_frommsg +dds_return_t nn_plist_init_frommsg ( nn_plist_t *dest, char **nextafterplist, @@ -2405,7 +2396,7 @@ int nn_plist_init_frommsg default: DDS_WARNING ("plist(vendor %u.%u): unknown encoding (%d)\n", src->vendorid.id[0], src->vendorid.id[1], src->encoding); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } nn_plist_init_empty (dest); dest->unalias_needs_bswap = dd.bswap; @@ -2419,7 +2410,7 @@ int nn_plist_init_frommsg nn_parameter_t *par = (nn_parameter_t *) pl; nn_parameterid_t pid; unsigned short length; - int res; + dds_return_t res; /* swapping header partially based on wireshark dissector output, partially on intuition, and in a small part based on the spec */ @@ -2432,7 +2423,7 @@ int nn_plist_init_frommsg if ((res = final_validation (dest, src->protocol_version, src->vendorid)) < 0) { nn_plist_fini (dest); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } else { @@ -2447,14 +2438,14 @@ int nn_plist_init_frommsg DDS_WARNING("plist(vendor %u.%u): parameter length %u out of bounds\n", src->vendorid.id[0], src->vendorid.id[1], length); nn_plist_fini (dest); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if ((length % 4) != 0) /* DDSI 9.4.2.11 */ { DDS_WARNING("plist(vendor %u.%u): parameter length %u mod 4 != 0\n", src->vendorid.id[0], src->vendorid.id[1], length); nn_plist_fini (dest); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } if (dds_get_log_mask() & DDS_LC_PLIST) @@ -2480,7 +2471,7 @@ int nn_plist_init_frommsg DDS_WARNING("plist(vendor %u.%u): invalid parameter list: sentinel missing\n", src->vendorid.id[0], src->vendorid.id[1]); nn_plist_fini (dest); - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } const unsigned char *nn_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid) @@ -2591,7 +2582,6 @@ unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn return NULL; } - void nn_xqos_init_empty (nn_xqos_t *dest) { #ifndef NDEBUG @@ -2600,12 +2590,11 @@ void nn_xqos_init_empty (nn_xqos_t *dest) dest->present = dest->aliased = 0; } -int nn_plist_init_default_participant (nn_plist_t *plist) +void nn_plist_init_default_participant (nn_plist_t *plist) { nn_plist_init_empty (plist); plist->qos.present |= QP_PRISMTECH_ENTITY_FACTORY; plist->qos.entity_factory.autoenable_created_entities = 0; - return 0; } static void xqos_init_default_common (nn_xqos_t *xqos) diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 58ae5c3..9923a91 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -36,7 +36,6 @@ #include "dds/ddsi/q_addrset.h" #include "dds/ddsi/q_ddsi_discovery.h" #include "dds/ddsi/q_radmin.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_lease.h" @@ -1953,7 +1952,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st { nn_plist_src_t src; size_t qos_offset = NN_RDATA_SUBMSG_OFF (fragchain) + offsetof (Data_DataFrag_common_t, octetsToInlineQos) + sizeof (msg->octetsToInlineQos) + msg->octetsToInlineQos; - int plist_ret; + dds_return_t plist_ret; src.protocol_version = rst->protocol_version; src.vendorid = rst->vendor; src.encoding = (msg->smhdr.flags & SMFLAG_ENDIANNESS) ? PL_CDR_LE : PL_CDR_BE; @@ -1961,7 +1960,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st src.bufsz = NN_RDATA_PAYLOAD_OFF (fragchain) - qos_offset; if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH | PP_COHERENT_SET | PP_PRISMTECH_EOTINFO, 0, &src)) < 0) { - if (plist_ret != Q_ERR_INCOMPATIBLE) + if (plist_ret != DDS_RETCODE_UNSUPPORTED) DDS_WARNING ("data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n", src.vendorid.id[0], src.vendorid.id[1], PGUID (pwr->e.guid), sampleinfo->seq); return 0; diff --git a/src/core/ddsi/src/q_security.c b/src/core/ddsi/src/q_security.c index 408c077..000ba0d 100644 --- a/src/core/ddsi/src/q_security.c +++ b/src/core/ddsi/src/q_security.c @@ -14,7 +14,6 @@ #include "dds/ddsi/q_security.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" -#include "dds/ddsi/q_error.h" #include "os/os_stdlib.h" #include "os/os_process.h" #include "os/os_thread.h" @@ -1657,7 +1656,7 @@ static os_ssize_t q_security_sendmsg char stbuf[2048], *buf; size_t sz, data_size; uint32_t sz32, data_size32; - ssize_t ret = Q_ERR_UNSPECIFIED; + ssize_t ret = DDS_RETCODE_ERROR; PT_InfoContainer_t * securityHeader; unsigned i; diff --git a/src/core/ddsi/src/q_sockwaitset.c b/src/core/ddsi/src/q_sockwaitset.c index 833312d..c1876d5 100644 --- a/src/core/ddsi/src/q_sockwaitset.c +++ b/src/core/ddsi/src/q_sockwaitset.c @@ -893,7 +893,7 @@ os_sockWaitsetCtx os_sockWaitsetWait (os_sockWaitset ws) do { - dds_retcode_t rc = ddsrt_select (fdmax, rdset, NULL, NULL, DDS_INFINITY, &n); + dds_return_t rc = ddsrt_select (fdmax, rdset, NULL, NULL, DDS_INFINITY, &n); if (rc != DDS_RETCODE_OK && rc != DDS_RETCODE_INTERRUPTED && rc != DDS_RETCODE_TRY_AGAIN) { DDS_WARNING("os_sockWaitsetWait: select failed, retcode = %"PRId32, rc); diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index 6cf4a47..5518176 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -23,7 +23,6 @@ #include "dds/ddsi/q_thread.h" #include "dds/ddsi/ddsi_threadmon.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_globals.h" @@ -245,7 +244,7 @@ static struct thread_state1 *init_thread_state (const char *tname, enum thread_s return ts; } -dds_retcode_t create_thread (struct thread_state1 **ts1, const char *name, uint32_t (*f) (void *arg), void *arg) +dds_return_t create_thread (struct thread_state1 **ts1, const char *name, uint32_t (*f) (void *arg), void *arg) { struct config_thread_properties_listelem const * const tprops = lookup_thread_properties (name); ddsrt_threadattr_t tattr; @@ -300,14 +299,11 @@ static void reap_thread_state (struct thread_state1 *ts1, int sync_with_servicel ddsrt_mutex_unlock (&thread_states.lock); } -int join_thread (struct thread_state1 *ts1) +dds_return_t join_thread (struct thread_state1 *ts1) { - int ret; + dds_return_t ret; assert (ts1->state == THREAD_STATE_ALIVE); - if (ddsrt_thread_join (ts1->extTid, NULL) == DDS_RETCODE_OK) - ret = 0; - else - ret = Q_ERR_UNSPECIFIED; + ret = ddsrt_thread_join (ts1->extTid, NULL); assert (vtime_asleep_p (ts1->vtime)); reap_thread_state (ts1, 1); return ret; diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index cc086a6..499b6f0 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -26,7 +26,6 @@ #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_globals.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/q_transmit.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_unused.h" @@ -387,7 +386,7 @@ void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_sta nn_xmsg_submsg_setnext (msg, sm_marker); } -static int create_fragment_message_simple (struct writer *wr, seqno_t seq, struct ddsi_serdata *serdata, struct nn_xmsg **pmsg) +static dds_return_t create_fragment_message_simple (struct writer *wr, seqno_t seq, struct ddsi_serdata *serdata, struct nn_xmsg **pmsg) { #define TEST_KEYHASH 0 /* actual expected_inline_qos_size is typically 0, but always claiming 32 bytes won't make @@ -417,7 +416,7 @@ static int create_fragment_message_simple (struct writer *wr, seqno_t seq, struc /* INFO_TS: 12 bytes, Data_t: 24 bytes, expected inline QoS: 32 => should be single chunk */ if ((*pmsg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (Data_t) + expected_inline_qos_size, NN_XMSG_KIND_DATA)) == NULL) - return Q_ERR_OUT_OF_MEMORY; + return DDS_RETCODE_OUT_OF_RESOURCES; #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS /* use the partition_id from the writer to select the proper encoder */ @@ -461,7 +460,7 @@ static int create_fragment_message_simple (struct writer *wr, seqno_t seq, struc return 0; } -int 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 nn_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 @@ -484,7 +483,7 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli uint32_t fragstart, fraglen; enum nn_xmsg_kind xmsg_kind = isnew ? NN_XMSG_KIND_DATA : NN_XMSG_KIND_DATA_REXMIT; const uint32_t size = ddsi_serdata_size (serdata); - int ret = 0; + dds_return_t ret = 0; (void)plist; ASSERT_MUTEX_HELD (&wr->e.lock); @@ -495,14 +494,14 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli an non-existent fragment, which a malicious (or buggy) remote reader can trigger. So we return an error instead of asserting as we used to. */ - return Q_ERR_INVALID; + return DDS_RETCODE_BAD_PARAMETER; } fragging = (config.fragment_size < size); /* INFO_TS: 12 bytes, DataFrag_t: 36 bytes, expected inline QoS: 32 => should be single chunk */ if ((*pmsg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (DataFrag_t) + expected_inline_qos_size, xmsg_kind)) == NULL) - return Q_ERR_OUT_OF_MEMORY; + return DDS_RETCODE_OUT_OF_RESOURCES; #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS /* use the partition_id from the writer to select the proper encoder */ @@ -515,7 +514,7 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli { nn_xmsg_free (*pmsg); *pmsg = NULL; - return Q_ERR_NO_ADDRESS; + return DDS_RETCODE_PRECONDITION_NOT_MET; } /* retransmits: latency budget doesn't apply */ } @@ -901,7 +900,7 @@ static int writer_may_continue (const struct writer *wr, const struct whc_state } -static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr) +static dds_return_t throttle_writer (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr) { /* Sleep (cond_wait) without updating the thread's vtime: the garbage collector won't free the writer while we leave it @@ -937,7 +936,7 @@ static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct n reader. This implicitly clears the whc and unblocks the writer. */ - dds_retcode_t result = DDS_RETCODE_OK; + dds_return_t result = DDS_RETCODE_OK; nn_mtime_t tnow = now_mt (); const nn_mtime_t abstimeout = add_duration_to_mtime (tnow, nn_from_ddsi_duration (wr->xqos->reliability.max_blocking_time)); struct whc_state whcst; @@ -1040,7 +1039,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * ddsi_serdata_size (serdata), config.max_sample_size, PGUID (wr->e.guid), tname, ttname, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)"); - r = Q_ERR_INVALID_DATA; + r = DDS_RETCODE_BAD_PARAMETER; goto drop; } @@ -1057,7 +1056,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * whc_get_state(wr->whc, &whcst); if (whcst.unacked_bytes > wr->whc_high) { - dds_retcode_t ores; + dds_return_t ores; assert(gc_allowed); /* also see beginning of the function */ if (config.prioritize_retransmit && wr->retransmitting) ores = throttle_writer (ts1, xp, wr); @@ -1072,7 +1071,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * if (ores == DDS_RETCODE_TIMEOUT) { ddsrt_mutex_unlock (&wr->e.lock); - r = Q_ERR_TIMEOUT; + r = DDS_RETCODE_TIMEOUT; goto drop; } } @@ -1189,4 +1188,3 @@ int write_sample_nogc_notk (struct thread_state1 * const ts1, struct nn_xpack *x ddsi_tkmap_instance_unref (tk); return res; } - diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index 9eca691..baaf10f 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -30,7 +30,6 @@ #include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_transmit.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_misc.h" @@ -477,9 +476,9 @@ struct xeventq * xeventq_new return evq; } -int xeventq_start (struct xeventq *evq, const char *name) +dds_return_t xeventq_start (struct xeventq *evq, const char *name) { - dds_retcode_t rc; + dds_return_t rc; char * evqname = "tev"; assert (evq->ts == NULL); @@ -497,7 +496,7 @@ int xeventq_start (struct xeventq *evq, const char *name) { ddsrt_free (evqname); } - return (rc != DDS_RETCODE_OK) ? Q_ERR_UNSPECIFIED : 0; + return rc; } void xeventq_stop (struct xeventq *evq) diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 3c0eae0..b443e25 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -31,7 +31,6 @@ #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_addrset.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_unused.h" @@ -148,7 +147,7 @@ typedef struct { ddsrt_cond_t cv; } ddsi_sem_t; -dds_retcode_t +dds_return_t ddsi_sem_init (ddsi_sem_t *sem, uint32_t value) { sem->value = value; @@ -157,7 +156,7 @@ ddsi_sem_init (ddsi_sem_t *sem, uint32_t value) return DDS_RETCODE_OK; } -dds_retcode_t +dds_return_t ddsi_sem_destroy (ddsi_sem_t *sem) { ddsrt_cond_destroy (&sem->cv); @@ -165,7 +164,7 @@ ddsi_sem_destroy (ddsi_sem_t *sem) return DDS_RETCODE_OK; } -dds_retcode_t +dds_return_t ddsi_sem_post (ddsi_sem_t *sem) { ddsrt_mutex_lock (&sem->mtx); @@ -175,7 +174,7 @@ ddsi_sem_post (ddsi_sem_t *sem) return DDS_RETCODE_OK; } -dds_retcode_t +dds_return_t ddsi_sem_wait (ddsi_sem_t *sem) { ddsrt_mutex_lock (&sem->mtx); @@ -586,7 +585,7 @@ void nn_xmsg_setdst1 (struct nn_xmsg *m, const nn_guid_prefix_t *gp, const nn_lo m->data->dst.guid_prefix = nn_hton_guid_prefix (*gp); } -int nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd) +dds_return_t nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd) { nn_locator_t loc; if (addrset_any_uc (prd->c.as, &loc) || addrset_any_mc (prd->c.as, &loc)) @@ -597,11 +596,11 @@ int nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd) else { DDS_WARNING("nn_xmsg_setdstPRD: no address for "PGUIDFMT"", PGUID (prd->e.guid)); - return Q_ERR_NO_ADDRESS; + return DDS_RETCODE_PRECONDITION_NOT_MET; } } -int nn_xmsg_setdstPWR (struct nn_xmsg *m, const struct proxy_writer *pwr) +dds_return_t nn_xmsg_setdstPWR (struct nn_xmsg *m, const struct proxy_writer *pwr) { nn_locator_t loc; if (addrset_any_uc (pwr->c.as, &loc) || addrset_any_mc (pwr->c.as, &loc)) @@ -610,7 +609,7 @@ int nn_xmsg_setdstPWR (struct nn_xmsg *m, const struct proxy_writer *pwr) return 0; } DDS_WARNING("nn_xmsg_setdstPRD: no address for "PGUIDFMT, PGUID (pwr->e.guid)); - return Q_ERR_NO_ADDRESS; + return DDS_RETCODE_PRECONDITION_NOT_MET; } void nn_xmsg_setdstN (struct nn_xmsg *m, struct addrset *as, struct addrset *as_group) diff --git a/src/core/ddsi/src/sysdeps.c b/src/core/ddsi/src/sysdeps.c index c233f16..73262f6 100644 --- a/src/core/ddsi/src/sysdeps.c +++ b/src/core/ddsi/src/sysdeps.c @@ -15,7 +15,6 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/misc.h" -#include "dds/ddsi/q_error.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/sysdeps.h" diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 28069d0..4a2f5b1 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -121,10 +121,10 @@ list(APPEND sources "${source_path}/strtol.c") list(APPEND headers - "${source_path}/dds/ddsrt/avl.h" - "${source_path}/dds/ddsrt/fibheap.h" - "${source_path}/dds/ddsrt/hopscotch.h" - "${source_path}/dds/ddsrt/thread_pool.h") + "${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}/avl.c" @@ -221,7 +221,7 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage endif() endforeach() -target_sources(ddsrt INTERFACE ${sources}) +target_sources(ddsrt INTERFACE ${sources} ${headers}) set(HAVE_MULTI_PROCESS ${HAVE_MULTI_PROCESS} PARENT_SCOPE) diff --git a/src/ddsrt/include/dds/ddsrt/environ.h b/src/ddsrt/include/dds/ddsrt/environ.h index 67a8c29..ddc4167 100644 --- a/src/ddsrt/include/dds/ddsrt/environ.h +++ b/src/ddsrt/include/dds/ddsrt/environ.h @@ -30,7 +30,7 @@ extern "C" { * byte), or would have been written would @buf have been * sufficiently large enough. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * Environment variable written to @buf. @@ -43,7 +43,7 @@ extern "C" { * @retval DDS_RETCODE_ERROR * Unspecified error. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_getenv( const char *name, char **value) @@ -58,7 +58,7 @@ ddsrt_nonnull_all; * @param[in] name Environment variable name. * @param[in] value Value to set environment variable to. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * Environment variable successfully set to @value. @@ -69,7 +69,7 @@ ddsrt_nonnull_all; * @retval DDS_RETCODE_ERROR * Unspecified system error. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_setenv( const char *name, const char *value) @@ -80,7 +80,7 @@ ddsrt_nonnull_all; * * @param[in] name Environment variable name. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * Environment variable successfully unset. @@ -91,7 +91,7 @@ ddsrt_nonnull_all; * @retval DDS_RETCODE_ERROR * Unspecified system error. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_unsetenv( const char *name) ddsrt_nonnull_all; diff --git a/src/ddsrt/include/dds/ddsrt/ifaddrs.h b/src/ddsrt/include/dds/ddsrt/ifaddrs.h index b98d5b8..389356e 100644 --- a/src/ddsrt/include/dds/ddsrt/ifaddrs.h +++ b/src/ddsrt/include/dds/ddsrt/ifaddrs.h @@ -30,7 +30,7 @@ struct ddsrt_ifaddrs { typedef struct ddsrt_ifaddrs ddsrt_ifaddrs_t; -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_getifaddrs( ddsrt_ifaddrs_t **ifap, const int *afs); diff --git a/src/ddsrt/include/dds/ddsrt/process.h b/src/ddsrt/include/dds/ddsrt/process.h index 592508c..6a39c4a 100644 --- a/src/ddsrt/include/dds/ddsrt/process.h +++ b/src/ddsrt/include/dds/ddsrt/process.h @@ -72,7 +72,7 @@ ddsrt_getpid(void); * @param[in] argv Arguments array. * @param[out] pid ID of the created process. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * Process successfully created. @@ -85,7 +85,7 @@ ddsrt_getpid(void); * @retval DDS_RETCODE_ERROR * Process could not be created. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_proc_create( const char *executable, char *const argv[], @@ -109,7 +109,7 @@ ddsrt_proc_create( * @param[in] timemout Time within the process is expected to finish. * @param[out] code The exit code of the process. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * Process has terminated and its exit code has been captured. @@ -124,7 +124,7 @@ ddsrt_proc_create( * @retval DDS_RETCODE_ERROR * Getting the exit code failed for an unknown reason. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_proc_waitpid( ddsrt_pid_t pid, dds_duration_t timeout, @@ -149,7 +149,7 @@ ddsrt_proc_waitpid( * @param[out] pid Process ID (PID) of the finished process. * @param[out] code The exit code of the process. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * A process has terminated. @@ -165,7 +165,7 @@ ddsrt_proc_waitpid( * @retval DDS_RETCODE_ERROR * Getting the exit code failed for an unknown reason. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_proc_waitpids( dds_duration_t timeout, ddsrt_pid_t *pid, @@ -176,7 +176,7 @@ ddsrt_proc_waitpids( * * @param[in] pid Process ID (PID) to check if it exists. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * The process exists. @@ -185,7 +185,7 @@ ddsrt_proc_waitpids( * @retval DDS_RETCODE_ERROR * Determining if a process exists or not, failed. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_proc_exists( ddsrt_pid_t pid); @@ -202,7 +202,7 @@ ddsrt_proc_exists( * * @param[in] pid Process ID (PID) of the process to terminate. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * Kill attempt has been started. @@ -213,7 +213,7 @@ ddsrt_proc_exists( * @retval DDS_RETCODE_ERROR * Kill failed for an unknown reason. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_proc_kill( ddsrt_pid_t pid); diff --git a/src/ddsrt/include/dds/ddsrt/retcode.h b/src/ddsrt/include/dds/ddsrt/retcode.h index f57626d..ca2cc8a 100644 --- a/src/ddsrt/include/dds/ddsrt/retcode.h +++ b/src/ddsrt/include/dds/ddsrt/retcode.h @@ -9,7 +9,7 @@ extern "C" { #endif -typedef int32_t dds_retcode_t; +typedef int32_t dds_return_t; /* State is unchanged following a function call returning an error @@ -29,25 +29,25 @@ typedef int32_t dds_retcode_t; * @{ */ #define DDS_RETCODE_OK 0 /**< Success */ -#define DDS_RETCODE_ERROR 1 /**< Non specific error */ -#define DDS_RETCODE_UNSUPPORTED 2 /**< Feature unsupported */ -#define DDS_RETCODE_BAD_PARAMETER 3 /**< Bad parameter value */ -#define DDS_RETCODE_PRECONDITION_NOT_MET 4 /**< Precondition for operation not met */ -#define DDS_RETCODE_OUT_OF_RESOURCES 5 /**< When an operation fails because of a lack of resources */ -#define DDS_RETCODE_NOT_ENABLED 6 /**< When a configurable feature is not enabled */ -#define DDS_RETCODE_IMMUTABLE_POLICY 7 /**< When an attempt is made to modify an immutable policy */ -#define DDS_RETCODE_INCONSISTENT_POLICY 8 /**< When a policy is used with inconsistent values */ -#define DDS_RETCODE_ALREADY_DELETED 9 /**< When an attempt is made to delete something more than once */ -#define DDS_RETCODE_TIMEOUT 10 /**< When a timeout has occurred */ -#define DDS_RETCODE_NO_DATA 11 /**< When expected data is not provided */ -#define DDS_RETCODE_ILLEGAL_OPERATION 12 /**< When a function is called when it should not be */ -#define DDS_RETCODE_NOT_ALLOWED_BY_SECURITY 13 /**< When credentials are not enough to use the function */ +#define DDS_RETCODE_ERROR -1 /**< Non specific error */ +#define DDS_RETCODE_UNSUPPORTED -2 /**< Feature unsupported */ +#define DDS_RETCODE_BAD_PARAMETER -3 /**< Bad parameter value */ +#define DDS_RETCODE_PRECONDITION_NOT_MET -4 /**< Precondition for operation not met */ +#define DDS_RETCODE_OUT_OF_RESOURCES -5 /**< When an operation fails because of a lack of resources */ +#define DDS_RETCODE_NOT_ENABLED -6 /**< When a configurable feature is not enabled */ +#define DDS_RETCODE_IMMUTABLE_POLICY -7 /**< When an attempt is made to modify an immutable policy */ +#define DDS_RETCODE_INCONSISTENT_POLICY -8 /**< When a policy is used with inconsistent values */ +#define DDS_RETCODE_ALREADY_DELETED -9 /**< When an attempt is made to delete something more than once */ +#define DDS_RETCODE_TIMEOUT -10 /**< When a timeout has occurred */ +#define DDS_RETCODE_NO_DATA -11 /**< When expected data is not provided */ +#define DDS_RETCODE_ILLEGAL_OPERATION -12 /**< When a function is called when it should not be */ +#define DDS_RETCODE_NOT_ALLOWED_BY_SECURITY -13 /**< When credentials are not enough to use the function */ /* Extended return codes are not in the DDS specification and are meant exclusively for internal use and must not be returned by the C API. */ -#define DDS_XRETCODE_BASE (50) -#define DDS_XRETCODE(x) (DDS_XRETCODE_BASE + (x)) +#define DDS_XRETCODE_BASE (-50) +#define DDS_XRETCODE(x) (DDS_XRETCODE_BASE - (x)) /** Requested resource is busy */ #define DDS_RETCODE_IN_PROGRESS DDS_XRETCODE(1) @@ -88,7 +88,7 @@ typedef int32_t dds_retcode_t; * * @returns String corresponding to the error value */ -DDS_EXPORT const char *dds_strretcode(dds_retcode_t ret); +DDS_EXPORT const char *dds_strretcode(dds_return_t ret); #if defined (__cplusplus) } diff --git a/src/ddsrt/include/dds/ddsrt/rusage.h b/src/ddsrt/include/dds/ddsrt/rusage.h index a58de6b..8150df3 100644 --- a/src/ddsrt/include/dds/ddsrt/rusage.h +++ b/src/ddsrt/include/dds/ddsrt/rusage.h @@ -52,7 +52,7 @@ typedef struct { * @param[in] who DDSRT_RUSAGE_SELF or DDSRT_RUSAGE_THREAD. * @param[in] usage Structure where resource usage is returned. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * Resource usage successfully returned in @usage. @@ -61,7 +61,7 @@ typedef struct { * @retval DDS_RETCODE_ERROR * An unidentified error occurred. */ -DDS_EXPORT dds_retcode_t ddsrt_getrusage(int who, ddsrt_rusage_t *usage); +DDS_EXPORT dds_return_t ddsrt_getrusage(int who, ddsrt_rusage_t *usage); #if defined (__cplusplus) } diff --git a/src/ddsrt/include/dds/ddsrt/sockets.h b/src/ddsrt/include/dds/ddsrt/sockets.h index 3876320..e783b89 100644 --- a/src/ddsrt/include/dds/ddsrt/sockets.h +++ b/src/ddsrt/include/dds/ddsrt/sockets.h @@ -32,53 +32,53 @@ extern const struct in6_addr ddsrt_in6addr_loopback; #define DDSRT_AF_TERM (-1) -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_gethostname( char *hostname, size_t buffersize); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_socket( ddsrt_socket_t *sockptr, int domain, int type, int protocol); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_close( ddsrt_socket_t sock); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_connect( ddsrt_socket_t sock, const struct sockaddr *addr, socklen_t addrlen); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_accept( ddsrt_socket_t sock, struct sockaddr *addr, socklen_t *addrlen, ddsrt_socket_t *connptr); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_listen( ddsrt_socket_t sock, int backlog); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_bind( ddsrt_socket_t sock, const struct sockaddr *addr, socklen_t addrlen); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_getsockname( ddsrt_socket_t sock, struct sockaddr *addr, socklen_t *addrlen); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_send( ddsrt_socket_t sock, const void *buf, @@ -86,14 +86,14 @@ ddsrt_send( int flags, ssize_t *sent); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_sendmsg( ddsrt_socket_t sock, const ddsrt_msghdr_t *msg, int flags, ssize_t *sent); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_recv( ddsrt_socket_t sock, void *buf, @@ -101,14 +101,14 @@ ddsrt_recv( int flags, ssize_t *rcvd); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_recvmsg( ddsrt_socket_t sock, ddsrt_msghdr_t *msg, int flags, ssize_t *rcvd); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_getsockopt( ddsrt_socket_t sock, int32_t level, /* SOL_SOCKET */ @@ -116,7 +116,7 @@ ddsrt_getsockopt( void *optval, socklen_t *optlen); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_setsockopt( ddsrt_socket_t sock, int32_t level, /* SOL_SOCKET */ @@ -130,7 +130,7 @@ ddsrt_setsockopt( * @param[in] sock Socket to set I/O mode for. * @param[in] nonblock true for nonblocking, or false for blocking I/O. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * I/O mode successfully set to (non)blocking. @@ -141,7 +141,7 @@ ddsrt_setsockopt( * @retval DDS_RETCODE_ERROR * An unknown error error occurred. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_setsocknonblocking( ddsrt_socket_t sock, bool nonblock); @@ -228,11 +228,11 @@ ddsrt_sockaddr_insamesubnet( const struct sockaddr *mask) ddsrt_nonnull_all; -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_sockaddrfromstr( int af, const char *str, void *sa); -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_sockaddrtostr( const void *sa, char *buf, size_t size); @@ -249,7 +249,7 @@ typedef struct { * @param[in] af Address family, either AF_INET, AF_INET6 or AF_UNSPEC. * @param[out] hent Structure of type ddsrt_hostent_t. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * Host name successfully resolved to address(es). @@ -262,7 +262,7 @@ typedef struct { * @retval DDS_RETCODE_TRY_AGAIN * Nonauthoratitative host not found. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_gethostbyname( const char *name, int af, diff --git a/src/ddsrt/include/dds/ddsrt/string.h b/src/ddsrt/include/dds/ddsrt/string.h index 0023d12..68d3181 100644 --- a/src/ddsrt/include/dds/ddsrt/string.h +++ b/src/ddsrt/include/dds/ddsrt/string.h @@ -176,7 +176,7 @@ ddsrt_nonnull((1,2)); * @param[in] buf Buffer where description is copied to. * @param[in] buflen Number of bytes available in @buf. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * Description for @errnum was successfully copied to @buf. @@ -185,7 +185,7 @@ ddsrt_nonnull((1,2)); * @retval DDS_RETCODE_NOT_ENOUGH_SPACE * Buffer was not large enough to hold the description. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_strerror_r( int errnum, char *buf, diff --git a/src/ddsrt/include/dds/ddsrt/strtod.h b/src/ddsrt/include/dds/ddsrt/strtod.h index f8bb511..4db08e7 100644 --- a/src/ddsrt/include/dds/ddsrt/strtod.h +++ b/src/ddsrt/include/dds/ddsrt/strtod.h @@ -34,9 +34,9 @@ extern "C" { * character is stored. * @param[out] dblptr A double where the result is stored. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_strtod(const char *nptr, char **endptr, double *dblptr); /** @@ -47,9 +47,9 @@ ddsrt_strtod(const char *nptr, char **endptr, double *dblptr); * character is stored. * @param[out] fltptr A float where the floating-point number is stored. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_strtof(const char *nptr, char **endptr, float *fltptr); /** diff --git a/src/ddsrt/include/dds/ddsrt/strtol.h b/src/ddsrt/include/dds/ddsrt/strtol.h index a862c06..c4cb059 100644 --- a/src/ddsrt/include/dds/ddsrt/strtol.h +++ b/src/ddsrt/include/dds/ddsrt/strtol.h @@ -37,7 +37,7 @@ extern "C" { * determine from @str. * @param[out] llng A long long integer where the number is stored. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * String successfully converted to an integer. @@ -46,7 +46,7 @@ extern "C" { * @retval DDS_RETCODE_OUT_OF_RANGE * String converted to an integer, but was out of range. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_strtoll( const char *str, char **endptr, @@ -69,7 +69,7 @@ ddsrt_strtoll( * determine from @str. * @param[out] ullng A long long integer where the number is stored. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * String successfully converted to an integer. @@ -78,7 +78,7 @@ ddsrt_strtoll( * @retval DDS_RETCODE_OUT_OF_RANGE * String converted to an integer, but was out of range. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_strtoull( const char *str, char **endptr, @@ -91,7 +91,7 @@ ddsrt_strtoull( * @param[in] str String to convert into a long long integer. * @param[in] llng A long long integer where the number is stored. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * String successfully converted to an integer. @@ -100,7 +100,7 @@ ddsrt_strtoull( * @retval DDS_RETCODE_OUT_OF_RANGE * String converted to an integer, but was out of range. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_atoll( const char *str, long long *llng); @@ -111,7 +111,7 @@ ddsrt_atoll( * @param[in] str String to conver into an unsigned long long integer. * @param[out] ullng An unsigned long long integer where the number is stored. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * String successfully converted to an integer. @@ -120,7 +120,7 @@ ddsrt_atoll( * @retval DDS_RETCODE_OUT_OF_RANGE * String converted to an integer, but was out of range. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_atoull( const char *str, unsigned long long *ullng); diff --git a/src/ddsrt/include/dds/ddsrt/thread_pool.h b/src/ddsrt/include/dds/ddsrt/thread_pool.h index f03fe46..4bcdc77 100644 --- a/src/ddsrt/include/dds/ddsrt/thread_pool.h +++ b/src/ddsrt/include/dds/ddsrt/thread_pool.h @@ -55,7 +55,7 @@ DDS_EXPORT void ddsrt_thread_pool_purge (ddsrt_thread_pool pool); Note that if the pool queue has reached it's maximum DDS_RETCODE_TRY_AGAIN is returned. */ -DDS_EXPORT dds_retcode_t ddsrt_thread_pool_submit +DDS_EXPORT dds_return_t ddsrt_thread_pool_submit ( ddsrt_thread_pool pool, /* Thread pool instance */ void (*fn) (void *arg), /* Function to be invoked by thread from pool */ diff --git a/src/ddsrt/include/dds/ddsrt/threads.h b/src/ddsrt/include/dds/ddsrt/threads.h index 32f49bd..ce8ee30 100644 --- a/src/ddsrt/include/dds/ddsrt/threads.h +++ b/src/ddsrt/include/dds/ddsrt/threads.h @@ -121,14 +121,14 @@ ddsrt_nonnull_all; * @param[in] start_routine Function to execute in created thread. * @param[in] arg Argument passed to @start_routine. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * Thread successfully created. * @retval DDS_RETCODE_ERROR * Thread could not be created. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_thread_create( ddsrt_thread_t *thread, const char *name, @@ -172,14 +172,14 @@ ddsrt_thread_equal(ddsrt_thread_t t1, ddsrt_thread_t t2); * @param[in] thread Id of thread to wait for. * @param[out] thread_result Location where thread result is stored. * - * @returns A dds_retcode_t indicating success or failure. + * @returns A dds_return_t indicating success or failure. * * @retval DDS_RETCODE_OK * Target thread terminated. * @retval DDS_RETCODE_ERROR * An error occurred while waiting for the thread to terminate. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_thread_join( ddsrt_thread_t thread, uint32_t *thread_result); @@ -224,7 +224,7 @@ ddsrt_thread_setname( * @param[in] routine Cleanup handler to push onto the thread cleanup stack. * @param[in] arg Argument that will be passed to the cleanup handler. */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_thread_cleanup_push( void (*routine)(void*), void *arg); @@ -235,7 +235,7 @@ ddsrt_thread_cleanup_push( * Remove routine at the top of the calling thread's cleanup stack and * optionally invoke it (if execute is non-zero). */ -DDS_EXPORT dds_retcode_t +DDS_EXPORT dds_return_t ddsrt_thread_cleanup_pop( int execute); diff --git a/src/ddsrt/src/environ/posix/environ.c b/src/ddsrt/src/environ/posix/environ.c index b05769c..1f8b84f 100644 --- a/src/ddsrt/src/environ/posix/environ.c +++ b/src/ddsrt/src/environ/posix/environ.c @@ -23,7 +23,7 @@ isenvvar(const char *name) return (*name == '\0' || strchr(name, '=') != NULL) == 0; } -dds_retcode_t +dds_return_t ddsrt_getenv(const char *name, char **value) { char *env; @@ -40,7 +40,7 @@ ddsrt_getenv(const char *name, char **value) return DDS_RETCODE_NOT_FOUND; } -dds_retcode_t +dds_return_t ddsrt_setenv(const char *name, const char *value) { assert(name != NULL); @@ -65,7 +65,7 @@ ddsrt_setenv(const char *name, const char *value) return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_unsetenv(const char *name) { assert(name != NULL); diff --git a/src/ddsrt/src/environ/windows/environ.c b/src/ddsrt/src/environ/windows/environ.c index 076aea1..a5b2f90 100644 --- a/src/ddsrt/src/environ/windows/environ.c +++ b/src/ddsrt/src/environ/windows/environ.c @@ -25,7 +25,7 @@ isenvvar(const char *name) } DDSRT_WARNING_MSVC_OFF(4996) -dds_retcode_t +dds_return_t ddsrt_getenv(const char *name, char **value) { char *env; @@ -43,7 +43,7 @@ ddsrt_getenv(const char *name, char **value) } DDSRT_WARNING_MSVC_ON(4996) -dds_retcode_t +dds_return_t ddsrt_setenv(const char *name, const char *value) { assert(name != NULL); @@ -65,7 +65,7 @@ ddsrt_setenv(const char *name, const char *value) return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_unsetenv(const char *name) { assert(name != NULL); diff --git a/src/ddsrt/src/ifaddrs/posix/ifaddrs.c b/src/ddsrt/src/ifaddrs/posix/ifaddrs.c index 88606b1..208c4e0 100644 --- a/src/ddsrt/src/ifaddrs/posix/ifaddrs.c +++ b/src/ddsrt/src/ifaddrs/posix/ifaddrs.c @@ -21,10 +21,10 @@ extern const int *const os_supp_afs; -static dds_retcode_t +static dds_return_t copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) { - dds_retcode_t err = DDS_RETCODE_OK; + dds_return_t err = DDS_RETCODE_OK; ddsrt_ifaddrs_t *ifa; size_t sz; @@ -64,12 +64,12 @@ copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) return err; } -dds_retcode_t +dds_return_t ddsrt_getifaddrs( ddsrt_ifaddrs_t **ifap, const int *afs) { - dds_retcode_t err = DDS_RETCODE_OK; + dds_return_t err = DDS_RETCODE_OK; int use; ddsrt_ifaddrs_t *ifa, *ifa_root, *ifa_next; struct ifaddrs *sys_ifa, *sys_ifa_root; diff --git a/src/ddsrt/src/ifaddrs/windows/ifaddrs.c b/src/ddsrt/src/ifaddrs/windows/ifaddrs.c index 1bd41da..7dcb8aa 100644 --- a/src/ddsrt/src/ifaddrs/windows/ifaddrs.c +++ b/src/ddsrt/src/ifaddrs/windows/ifaddrs.c @@ -23,10 +23,10 @@ extern const int *const os_supp_afs; -static dds_retcode_t +static dds_return_t getifaces(PIP_ADAPTER_ADDRESSES *ptr) { - dds_retcode_t err = DDS_RETCODE_NOT_ENOUGH_SPACE; + dds_return_t err = DDS_RETCODE_NOT_ENOUGH_SPACE; PIP_ADAPTER_ADDRESSES buf = NULL; ULONG bufsz = 0; /* Size is determined on first iteration. */ ULONG ret; @@ -72,10 +72,10 @@ getifaces(PIP_ADAPTER_ADDRESSES *ptr) return err; } -static dds_retcode_t +static dds_return_t getaddrtable(PMIB_IPADDRTABLE *ptr) { - dds_retcode_t err = DDS_RETCODE_NOT_ENOUGH_SPACE; + dds_return_t err = DDS_RETCODE_NOT_ENOUGH_SPACE; PMIB_IPADDRTABLE buf = NULL; ULONG bufsz = 0; DWORD ret; @@ -159,7 +159,7 @@ copyaddr( const PMIB_IPADDRTABLE addrtable, const PIP_ADAPTER_UNICAST_ADDRESS addr) { - dds_retcode_t err = DDS_RETCODE_OK; + dds_return_t err = DDS_RETCODE_OK; ddsrt_ifaddrs_t *ifa; struct sockaddr *sa; size_t sz; @@ -220,7 +220,7 @@ copyaddr( return err; } -dds_retcode_t +dds_return_t ddsrt_getifaddrs( ddsrt_ifaddrs_t **ifap, const int *afs) diff --git a/src/ddsrt/src/process/posix/process.c b/src/ddsrt/src/process/posix/process.c index d42877f..f8de0fc 100644 --- a/src/ddsrt/src/process/posix/process.c +++ b/src/ddsrt/src/process/posix/process.c @@ -72,7 +72,7 @@ static void no_op(int sig) } -static dds_retcode_t +static dds_return_t waitpids( ddsrt_pid_t request_pid, dds_duration_t timeout, @@ -81,7 +81,7 @@ waitpids( { struct sigaction sigactold; struct sigaction sigact; - dds_retcode_t rv; + dds_return_t rv; int options = 0; int ret; int s; @@ -148,13 +148,13 @@ waitpids( -dds_retcode_t +dds_return_t ddsrt_proc_create( const char *executable, char *const argv[], ddsrt_pid_t *pid) { - dds_retcode_t rv; + dds_return_t rv; char **exec_argv; int exec_fds[2]; int exec_err; @@ -253,7 +253,7 @@ fail_pipe: -dds_retcode_t +dds_return_t ddsrt_proc_waitpid( ddsrt_pid_t pid, dds_duration_t timeout, @@ -267,7 +267,7 @@ ddsrt_proc_waitpid( -dds_retcode_t +dds_return_t ddsrt_proc_waitpids( dds_duration_t timeout, ddsrt_pid_t *pid, @@ -278,7 +278,7 @@ ddsrt_proc_waitpids( -dds_retcode_t +dds_return_t ddsrt_proc_exists( ddsrt_pid_t pid) { @@ -294,7 +294,7 @@ ddsrt_proc_exists( -dds_retcode_t +dds_return_t ddsrt_proc_kill( ddsrt_pid_t pid) { diff --git a/src/ddsrt/src/process/windows/process.c b/src/ddsrt/src/process/windows/process.c index 91cebec..65c5125 100644 --- a/src/ddsrt/src/process/windows/process.c +++ b/src/ddsrt/src/process/windows/process.c @@ -29,24 +29,24 @@ ddsrt_getpid(void) -static HANDLE pid_to_phdl (ddsrt_pid_t pid); -static dds_retcode_t process_get_exit_code(HANDLE phdl, int32_t *code); -static dds_retcode_t process_kill (HANDLE phdl); -static char* commandline (const char *exe, char *const argv_in[]); -static BOOL child_add (HANDLE phdl); -static void child_remove (HANDLE phdl); -static DWORD child_list (HANDLE *list, DWORD max); -static HANDLE child_handle (ddsrt_pid_t pid); +static HANDLE pid_to_phdl (ddsrt_pid_t pid); +static dds_return_t process_get_exit_code(HANDLE phdl, int32_t *code); +static dds_return_t process_kill (HANDLE phdl); +static char* commandline (const char *exe, char *const argv_in[]); +static BOOL child_add (HANDLE phdl); +static void child_remove (HANDLE phdl); +static DWORD child_list (HANDLE *list, DWORD max); +static HANDLE child_handle (ddsrt_pid_t pid); -dds_retcode_t +dds_return_t ddsrt_proc_create( const char *executable, char *const argv[], ddsrt_pid_t *pid) { - dds_retcode_t rv = DDS_RETCODE_ERROR; + dds_return_t rv = DDS_RETCODE_ERROR; PROCESS_INFORMATION process_info; STARTUPINFO si; char *cmd; @@ -111,13 +111,13 @@ ddsrt_proc_create( -dds_retcode_t +dds_return_t ddsrt_proc_waitpid( ddsrt_pid_t pid, dds_duration_t timeout, int32_t *code) { - dds_retcode_t rv = DDS_RETCODE_OK; + dds_return_t rv = DDS_RETCODE_OK; HANDLE phdl; DWORD ret; @@ -155,13 +155,13 @@ ddsrt_proc_waitpid( -dds_retcode_t +dds_return_t ddsrt_proc_waitpids( dds_duration_t timeout, ddsrt_pid_t *pid, int32_t *code) { - dds_retcode_t rv = DDS_RETCODE_OK; + dds_return_t rv = DDS_RETCODE_OK; HANDLE hdls[MAXIMUM_WAIT_OBJECTS]; HANDLE phdl; DWORD cnt; @@ -208,11 +208,11 @@ ddsrt_proc_waitpids( -dds_retcode_t +dds_return_t ddsrt_proc_exists( ddsrt_pid_t pid) { - dds_retcode_t rv = DDS_RETCODE_NOT_FOUND; + dds_return_t rv = DDS_RETCODE_NOT_FOUND; HANDLE phdl; phdl = pid_to_phdl(pid); @@ -235,11 +235,11 @@ ddsrt_proc_exists( -dds_retcode_t +dds_return_t ddsrt_proc_kill( ddsrt_pid_t pid) { - dds_retcode_t rv = DDS_RETCODE_BAD_PARAMETER; + dds_return_t rv = DDS_RETCODE_BAD_PARAMETER; HANDLE phdl; phdl = pid_to_phdl(pid); @@ -262,12 +262,12 @@ pid_to_phdl(ddsrt_pid_t pid) -static dds_retcode_t +static dds_return_t process_get_exit_code( HANDLE phdl, int32_t *code) { - dds_retcode_t rv = DDS_RETCODE_ERROR; + dds_return_t rv = DDS_RETCODE_ERROR; DWORD tr; assert(phdl != 0); @@ -289,7 +289,7 @@ process_get_exit_code( /* Forcefully kill the given process. */ -static dds_retcode_t +static dds_return_t process_kill(HANDLE phdl) { assert(phdl != 0); diff --git a/src/ddsrt/src/retcode.c b/src/ddsrt/src/retcode.c index 6484f23..930a327 100644 --- a/src/ddsrt/src/retcode.c +++ b/src/ddsrt/src/retcode.c @@ -11,8 +11,7 @@ */ #include "dds/ddsrt/retcode.h" -static const char *retcodes[] = -{ +static const char *retcodes[] = { "Success", "Error", "Unsupported", @@ -42,19 +41,20 @@ static const char *xretcodes[] = { "Not found" }; -const char * -dds_strretcode (dds_retcode_t rc) +const char *dds_strretcode (dds_return_t rc) { - if (rc >= 0 && - rc < (dds_retcode_t)(sizeof(retcodes) / sizeof(retcodes[0]))) - { + const dds_return_t nretcodes = (dds_return_t) (sizeof (retcodes) / sizeof (retcodes[0])); + const dds_return_t nxretcodes = (dds_return_t) (sizeof (xretcodes) / sizeof (xretcodes[0])); + /* Retcodes used to be positive, but return values from the API would be a negative + and so there are/were/may be places outside the core library where dds_strretcode + is called with a -N for N a API return value, so ... play it safe and use the + magnitude */ + if (rc < 0) + rc = -rc; + if (rc >= 0 && rc < nretcodes) return retcodes[rc]; - } else if (rc >= (DDS_XRETCODE_BASE) && - rc < (dds_retcode_t)(DDS_XRETCODE_BASE + (sizeof(xretcodes) / sizeof(xretcodes[0])))) - { + else if (rc >= DDS_XRETCODE_BASE && rc < DDS_XRETCODE_BASE + nxretcodes) return xretcodes[rc - DDS_XRETCODE_BASE]; - } - - return "Unknown return code"; + else + return "Unknown return code"; } - diff --git a/src/ddsrt/src/rusage/posix/rusage.c b/src/ddsrt/src/rusage/posix/rusage.c index 878bd1d..d200007 100644 --- a/src/ddsrt/src/rusage/posix/rusage.c +++ b/src/ddsrt/src/rusage/posix/rusage.c @@ -23,12 +23,12 @@ #include "dds/ddsrt/rusage.h" -dds_retcode_t +dds_return_t ddsrt_getrusage(int who, ddsrt_rusage_t *usage) { int err = 0; struct rusage buf; - dds_retcode_t rc; + dds_return_t rc; assert(who == DDSRT_RUSAGE_SELF || who == DDSRT_RUSAGE_THREAD); assert(usage != NULL); diff --git a/src/ddsrt/src/rusage/windows/rusage.c b/src/ddsrt/src/rusage/windows/rusage.c index 71d763d..ca83658 100644 --- a/src/ddsrt/src/rusage/windows/rusage.c +++ b/src/ddsrt/src/rusage/windows/rusage.c @@ -24,7 +24,7 @@ filetime_to_time(const FILETIME *ft) return ((ft->dwHighDateTime << 31) + (ft->dwLowDateTime)) * 100; } -dds_retcode_t +dds_return_t ddsrt_getrusage(int who, ddsrt_rusage_t *usage) { FILETIME stime, utime, ctime, etime; diff --git a/src/ddsrt/src/sockets.c b/src/ddsrt/src/sockets.c index 48e3282..2aaffb8 100644 --- a/src/ddsrt/src/sockets.c +++ b/src/ddsrt/src/sockets.c @@ -177,7 +177,7 @@ ddsrt_sockaddr_insamesubnet( return eq; } -dds_retcode_t +dds_return_t ddsrt_sockaddrfromstr(int af, const char *str, void *sa) { assert(str != NULL); @@ -213,7 +213,7 @@ ddsrt_sockaddrfromstr(int af, const char *str, void *sa) return DDS_RETCODE_OK; } -dds_retcode_t ddsrt_sockaddrtostr(const void *sa, char *buf, size_t size) +dds_return_t ddsrt_sockaddrtostr(const void *sa, char *buf, size_t size) { const char *ptr; @@ -249,7 +249,7 @@ DDSRT_WARNING_GNUC_ON(sign-conversion) } #if DDSRT_HAVE_DNS -dds_retcode_t +dds_return_t ddsrt_gethostbyname(const char *name, int af, ddsrt_hostent_t **hentp) { int gai_err = 0; diff --git a/src/ddsrt/src/sockets/posix/gethostname.c b/src/ddsrt/src/sockets/posix/gethostname.c index fbdd7c4..fcf7618 100644 --- a/src/ddsrt/src/sockets/posix/gethostname.c +++ b/src/ddsrt/src/sockets/posix/gethostname.c @@ -34,7 +34,7 @@ #if LWIP_SOCKET -dds_retcode_t +dds_return_t ddsrt_gethostname( char *name, size_t len) @@ -45,7 +45,7 @@ ddsrt_gethostname( return DDS_RETCODE_OK; } #else -dds_retcode_t +dds_return_t ddsrt_gethostname( char *name, size_t len) diff --git a/src/ddsrt/src/sockets/posix/socket.c b/src/ddsrt/src/sockets/posix/socket.c index 7334483..e3fa47e 100644 --- a/src/ddsrt/src/sockets/posix/socket.c +++ b/src/ddsrt/src/sockets/posix/socket.c @@ -37,7 +37,7 @@ #endif /* __APPLE__ */ #endif /* LWIP_SOCKET */ -dds_retcode_t +dds_return_t ddsrt_socket(ddsrt_socket_t *sockptr, int domain, int type, int protocol) { ddsrt_socket_t sock; @@ -68,7 +68,7 @@ ddsrt_socket(ddsrt_socket_t *sockptr, int domain, int type, int protocol) return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_close( ddsrt_socket_t sock) { @@ -87,7 +87,7 @@ ddsrt_close( return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_bind( ddsrt_socket_t sock, const struct sockaddr *addr, @@ -112,7 +112,7 @@ ddsrt_bind( return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_listen( ddsrt_socket_t sock, int backlog) @@ -135,7 +135,7 @@ ddsrt_listen( return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_connect( ddsrt_socket_t sock, const struct sockaddr *addr, @@ -177,7 +177,7 @@ ddsrt_connect( return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_accept( ddsrt_socket_t sock, struct sockaddr *addr, @@ -224,7 +224,7 @@ ddsrt_accept( return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_getsockname( ddsrt_socket_t sock, struct sockaddr *addr, @@ -248,7 +248,7 @@ ddsrt_getsockname( return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_getsockopt( ddsrt_socket_t sock, int32_t level, @@ -282,7 +282,7 @@ ddsrt_getsockopt( return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_setsockopt( ddsrt_socket_t sock, int32_t level, @@ -339,7 +339,7 @@ err_setsockopt: return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_setsocknonblocking( ddsrt_socket_t sock, bool nonblock) @@ -377,7 +377,7 @@ err_fcntl: return DDS_RETCODE_ERROR; } -static inline dds_retcode_t +static inline dds_return_t recv_error_to_retcode(int errnum) { switch (errnum) { @@ -406,7 +406,7 @@ recv_error_to_retcode(int errnum) return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_recv( ddsrt_socket_t sock, void *buf, @@ -443,7 +443,7 @@ static ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) } #endif /* LWIP_SOCKET */ -dds_retcode_t +dds_return_t ddsrt_recvmsg( ddsrt_socket_t sock, ddsrt_msghdr_t *msg, @@ -461,7 +461,7 @@ ddsrt_recvmsg( return recv_error_to_retcode(errno); } -static inline dds_retcode_t +static inline dds_return_t send_error_to_retcode(int errnum) { switch (errnum) { @@ -503,7 +503,7 @@ send_error_to_retcode(int errnum) return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_send( ddsrt_socket_t sock, const void *buf, @@ -522,7 +522,7 @@ ddsrt_send( return send_error_to_retcode(errno); } -dds_retcode_t +dds_return_t ddsrt_sendmsg( ddsrt_socket_t sock, const ddsrt_msghdr_t *msg, @@ -540,7 +540,7 @@ ddsrt_sendmsg( return send_error_to_retcode(errno); } -dds_retcode_t +dds_return_t ddsrt_select( int32_t nfds, fd_set *readfds, diff --git a/src/ddsrt/src/sockets/windows/socket.c b/src/ddsrt/src/sockets/windows/socket.c index bc96301..d2b3221 100644 --- a/src/ddsrt/src/sockets/windows/socket.c +++ b/src/ddsrt/src/sockets/windows/socket.c @@ -52,11 +52,11 @@ ddsrt_winsock_fini(void) WSACleanup(); } -dds_retcode_t +dds_return_t ddsrt_socket(ddsrt_socket_t *sockptr, int domain, int type, int protocol) { int err; - dds_retcode_t ret = DDS_RETCODE_OK; + dds_return_t ret = DDS_RETCODE_OK; ddsrt_socket_t sock = DDSRT_INVALID_SOCKET; assert(sockptr != NULL); @@ -93,7 +93,7 @@ ddsrt_socket(ddsrt_socket_t *sockptr, int domain, int type, int protocol) return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_close(ddsrt_socket_t sock) { int err; @@ -120,7 +120,7 @@ ddsrt_close(ddsrt_socket_t sock) return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_accept( ddsrt_socket_t sock, struct sockaddr *addr, @@ -162,7 +162,7 @@ ddsrt_accept( return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_bind(ddsrt_socket_t sock, const struct sockaddr *addr, socklen_t addrlen) { int err; @@ -195,7 +195,7 @@ ddsrt_bind(ddsrt_socket_t sock, const struct sockaddr *addr, socklen_t addrlen) return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_listen( ddsrt_socket_t sock, int backlog) @@ -227,7 +227,7 @@ ddsrt_listen( return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_connect( ddsrt_socket_t sock, const struct sockaddr *addr, @@ -275,7 +275,7 @@ ddsrt_connect( return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_getsockname( ddsrt_socket_t sock, struct sockaddr *addr, @@ -309,7 +309,7 @@ ddsrt_getsockname( return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_getsockopt( ddsrt_socket_t sock, int32_t level, @@ -358,7 +358,7 @@ ddsrt_getsockopt( return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_setsockopt( ddsrt_socket_t sock, int32_t level, @@ -404,7 +404,7 @@ ddsrt_setsockopt( return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_setsocknonblocking( ddsrt_socket_t sock, bool nonblock) @@ -435,7 +435,7 @@ ddsrt_setsocknonblocking( return DDS_RETCODE_ERROR; } -static dds_retcode_t recv_error_to_retcode(int errnum) +static dds_return_t recv_error_to_retcode(int errnum) { assert(errnum != WSANOTINITIALISED); switch (errnum) { @@ -470,7 +470,7 @@ static dds_retcode_t recv_error_to_retcode(int errnum) return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_recv( ddsrt_socket_t sock, void *buf, @@ -490,7 +490,7 @@ ddsrt_recv( return recv_error_to_retcode(WSAGetLastError()); } -dds_retcode_t +dds_return_t ddsrt_recvmsg( ddsrt_socket_t sock, ddsrt_msghdr_t *msg, @@ -531,7 +531,7 @@ ddsrt_recvmsg( return recv_error_to_retcode(err); } -static dds_retcode_t +static dds_return_t send_error_to_retcode(int errnum) { assert(errnum != WSANOTINITIALISED); @@ -577,7 +577,7 @@ send_error_to_retcode(int errnum) return DDS_RETCODE_ERROR; } -dds_retcode_t +dds_return_t ddsrt_send( ddsrt_socket_t sock, const void *buf, @@ -608,7 +608,7 @@ struct iovec_matches_WSABUF { char len_size_matches[sizeof(((ddsrt_iovec_t *)8)->iov_len) == sizeof(((WSABUF *)8)->len) ? 1 : -1]; }; -dds_retcode_t +dds_return_t ddsrt_sendmsg( ddsrt_socket_t sock, const ddsrt_msghdr_t *msg, @@ -639,7 +639,7 @@ ddsrt_sendmsg( return send_error_to_retcode(WSAGetLastError()); } -dds_retcode_t +dds_return_t ddsrt_select( int32_t nfds, fd_set *readfds, diff --git a/src/ddsrt/src/string/posix/strerror.c b/src/ddsrt/src/string/posix/strerror.c index f467e30..cbd1009 100644 --- a/src/ddsrt/src/string/posix/strerror.c +++ b/src/ddsrt/src/string/posix/strerror.c @@ -21,7 +21,7 @@ #include "dds/ddsrt/string.h" -dds_retcode_t +dds_return_t ddsrt_strerror_r(int errnum, char *buf, size_t buflen) { assert(buf != NULL); diff --git a/src/ddsrt/src/strtod.c b/src/ddsrt/src/strtod.c index 99e4f05..7d0c0ba 100644 --- a/src/ddsrt/src/strtod.c +++ b/src/ddsrt/src/strtod.c @@ -96,12 +96,12 @@ os_lcNumericReplace(char *str) { } } -dds_retcode_t +dds_return_t ddsrt_strtod(const char *nptr, char **endptr, double *dblptr) { double dbl; int orig_errno; - dds_retcode_t ret = DDS_RETCODE_OK; + dds_return_t ret = DDS_RETCODE_OK; assert(nptr != NULL); assert(dblptr != NULL); @@ -161,7 +161,7 @@ ddsrt_strtod(const char *nptr, char **endptr, double *dblptr) return ret; } -dds_retcode_t +dds_return_t ddsrt_strtof(const char *nptr, char **endptr, float *fltptr) { /* Just use os_strtod(). */ @@ -169,7 +169,7 @@ ddsrt_strtof(const char *nptr, char **endptr, float *fltptr) point number is definitely not a double-precision floating point number. */ double dbl = 0.0; - dds_retcode_t ret; + dds_return_t ret; assert(nptr != NULL); assert(fltptr != NULL); diff --git a/src/ddsrt/src/strtol.c b/src/ddsrt/src/strtol.c index c6b6a5f..009c012 100644 --- a/src/ddsrt/src/strtol.c +++ b/src/ddsrt/src/strtol.c @@ -29,7 +29,7 @@ int ddsrt_todigit(const int chr) return -1; } -static dds_retcode_t +static dds_return_t ullfstr( const char *str, char **endptr, @@ -37,7 +37,7 @@ ullfstr( unsigned long long *ullng, unsigned long long max) { - dds_retcode_t rc = DDS_RETCODE_OK; + dds_return_t rc = DDS_RETCODE_OK; int num; size_t cnt = 0; unsigned long long tot = 0; @@ -86,14 +86,14 @@ ullfstr( return rc; } -dds_retcode_t +dds_return_t ddsrt_strtoll( const char *str, char **endptr, int32_t base, long long *llng) { - dds_retcode_t rc = DDS_RETCODE_OK; + dds_return_t rc = DDS_RETCODE_OK; size_t cnt = 0; long long tot = 1; unsigned long long ullng = 0, max = INT64_MAX; @@ -122,14 +122,14 @@ ddsrt_strtoll( return rc; } -dds_retcode_t +dds_return_t ddsrt_strtoull( const char *str, char **endptr, int32_t base, unsigned long long *ullng) { - dds_retcode_t rc = DDS_RETCODE_OK; + dds_return_t rc = DDS_RETCODE_OK; size_t cnt = 0; unsigned long long tot = 1; unsigned long long max = UINT64_MAX; @@ -157,7 +157,7 @@ ddsrt_strtoull( return rc; } -dds_retcode_t +dds_return_t ddsrt_atoll( const char *str, long long *llng) @@ -165,7 +165,7 @@ ddsrt_atoll( return ddsrt_strtoll(str, NULL, 10, llng); } -dds_retcode_t +dds_return_t ddsrt_atoull( const char *str, unsigned long long *ullng) diff --git a/src/ddsrt/src/thread_pool.c b/src/ddsrt/src/thread_pool.c index 48cba27..bc240e4 100644 --- a/src/ddsrt/src/thread_pool.c +++ b/src/ddsrt/src/thread_pool.c @@ -88,13 +88,13 @@ static uint32_t ddsrt_thread_start_fn (void * arg) return 0; } -static dds_retcode_t ddsrt_thread_pool_new_thread (ddsrt_thread_pool pool) +static dds_return_t ddsrt_thread_pool_new_thread (ddsrt_thread_pool pool) { static unsigned char pools = 0; /* Pool counter - TODO make atomic */ char name [64]; ddsrt_thread_t id; - dds_retcode_t res; + dds_return_t res; (void) snprintf (name, sizeof (name), "OSPL-%u-%u", pools++, pool->m_count++); res = ddsrt_thread_create (&id, name, &pool->m_attr, &ddsrt_thread_start_fn, pool); @@ -205,9 +205,9 @@ void ddsrt_thread_pool_free (ddsrt_thread_pool pool) ddsrt_free (pool); } -dds_retcode_t ddsrt_thread_pool_submit (ddsrt_thread_pool pool, void (*fn) (void *arg), void * arg) +dds_return_t ddsrt_thread_pool_submit (ddsrt_thread_pool pool, void (*fn) (void *arg), void * arg) { - dds_retcode_t res = DDS_RETCODE_OK; + dds_return_t res = DDS_RETCODE_OK; ddsi_work_queue_job_t job; ddsrt_mutex_lock (&pool->m_mutex); diff --git a/src/ddsrt/src/threads/posix/threads.c b/src/ddsrt/src/threads/posix/threads.c index 92eec22..bca8e36 100644 --- a/src/ddsrt/src/threads/posix/threads.c +++ b/src/ddsrt/src/threads/posix/threads.c @@ -187,7 +187,7 @@ static void *os_startRoutineWrapper (void *threadContext) return (void *)resultValue; } -dds_retcode_t +dds_return_t ddsrt_thread_create ( ddsrt_thread_t *threadptr, const char *name, @@ -346,7 +346,7 @@ bool ddsrt_thread_equal(ddsrt_thread_t a, ddsrt_thread_t b) return (pthread_equal(a.v, b.v) != 0); } -dds_retcode_t +dds_return_t ddsrt_thread_join(ddsrt_thread_t thread, uint32_t *thread_result) { int err; @@ -386,7 +386,7 @@ static void thread_init(void) (void)pthread_once(&thread_once, &thread_init_once); } -dds_retcode_t ddsrt_thread_cleanup_push (void (*routine) (void *), void *arg) +dds_return_t ddsrt_thread_cleanup_push (void (*routine) (void *), void *arg) { int err; thread_cleanup_t *prev, *tail; @@ -408,7 +408,7 @@ dds_retcode_t ddsrt_thread_cleanup_push (void (*routine) (void *), void *arg) return DDS_RETCODE_OUT_OF_RESOURCES; } -dds_retcode_t ddsrt_thread_cleanup_pop (int execute) +dds_return_t ddsrt_thread_cleanup_pop (int execute) { int err; thread_cleanup_t *tail; diff --git a/src/ddsrt/src/threads/windows/threads.c b/src/ddsrt/src/threads/windows/threads.c index 23830ab..97615ab 100644 --- a/src/ddsrt/src/threads/windows/threads.c +++ b/src/ddsrt/src/threads/windows/threads.c @@ -43,7 +43,7 @@ os_startRoutineWrapper( return resultValue; } -dds_retcode_t +dds_return_t ddsrt_thread_create( ddsrt_thread_t *thrptr, const char *name, @@ -139,7 +139,7 @@ bool ddsrt_thread_equal(ddsrt_thread_t a, ddsrt_thread_t b) * should not be closed until the os_threadWaitExit(...) call is called. * CloseHandle (threadHandle); */ -dds_retcode_t +dds_return_t ddsrt_thread_join( ddsrt_thread_t thread, uint32_t *thread_result) @@ -248,7 +248,7 @@ ddsrt_thread_setname( static ddsrt_thread_local thread_cleanup_t *thread_cleanup = NULL; -dds_retcode_t ddsrt_thread_cleanup_push(void (*routine)(void *), void *arg) +dds_return_t ddsrt_thread_cleanup_push(void (*routine)(void *), void *arg) { thread_cleanup_t *tail; @@ -265,7 +265,7 @@ dds_retcode_t ddsrt_thread_cleanup_push(void (*routine)(void *), void *arg) return DDS_RETCODE_OUT_OF_RESOURCES; } -dds_retcode_t ddsrt_thread_cleanup_pop(int execute) +dds_return_t ddsrt_thread_cleanup_pop(int execute) { thread_cleanup_t *tail; diff --git a/src/ddsrt/tests/environ.c b/src/ddsrt/tests/environ.c index b69acf4..0700546 100644 --- a/src/ddsrt/tests/environ.c +++ b/src/ddsrt/tests/environ.c @@ -22,7 +22,7 @@ CU_TheoryDataPoints(ddsrt_environ, bad_name) = { CU_Theory((const char *name), ddsrt_environ, bad_name) { - dds_retcode_t rc; + dds_return_t rc; static const char value[] = "bar"; static char dummy[] = "foobar"; char *ptr; @@ -40,7 +40,7 @@ CU_Theory((const char *name), ddsrt_environ, bad_name) DDSRT_WARNING_MSVC_OFF(4996) CU_Test(ddsrt_environ, setenv) { - dds_retcode_t rc; + dds_return_t rc; static const char name[] = "foo"; static char value[] = "bar"; char *ptr; @@ -64,7 +64,7 @@ DDSRT_WARNING_MSVC_ON(4996) CU_Test(ddsrt_environ, getenv) { - dds_retcode_t rc; + dds_return_t rc; static const char name[] = "foo"; static const char value[] = "bar"; static char dummy[] = "foobar"; @@ -111,7 +111,7 @@ CU_TheoryDataPoints(ddsrt_environ, expand) = { }; CU_Theory((const char *var, const char *expect), ddsrt_environ, expand) { - dds_retcode_t rc; + dds_return_t rc; static const char x_name[] = "X"; static const char x_value[] = "TEST"; static const char y_name[] = "Y"; @@ -163,7 +163,7 @@ CU_TheoryDataPoints(ddsrt_environ, expand_sh) = { }; CU_Theory((const char *var, const char *expect), ddsrt_environ, expand_sh) { - dds_retcode_t rc; + dds_return_t rc; static const char x_name[] = "X"; static const char x_value[] = "TEST"; static const char y_name[] = "Y"; diff --git a/src/ddsrt/tests/ifaddrs.c b/src/ddsrt/tests/ifaddrs.c index 50166da..6035724 100644 --- a/src/ddsrt/tests/ifaddrs.c +++ b/src/ddsrt/tests/ifaddrs.c @@ -64,7 +64,7 @@ CU_Clean(ddsrt_getifaddrs) IFF_LOOPBACK flags are properly set. */ CU_Test(ddsrt_getifaddrs, ipv4) { - dds_retcode_t ret; + dds_return_t ret; int seen = 0; ddsrt_ifaddrs_t *ifa_root, *ifa; const int afs[] = { AF_INET, DDSRT_AF_TERM }; @@ -90,7 +90,7 @@ CU_Test(ddsrt_getifaddrs, ipv4) CU_Test(ddsrt_getifaddrs, null_filter) { - dds_retcode_t ret; + dds_return_t ret; int cnt = 0; ddsrt_ifaddrs_t *ifa_root, *ifa; @@ -107,7 +107,7 @@ CU_Test(ddsrt_getifaddrs, null_filter) CU_Test(ddsrt_getifaddrs, empty_filter) { - dds_retcode_t ret; + dds_return_t ret; ddsrt_ifaddrs_t *ifa_root; const int afs[] = { DDSRT_AF_TERM }; @@ -121,7 +121,7 @@ CU_Test(ddsrt_getifaddrs, ipv6) { #ifdef DDSRT_HAVE_IPV6 if (ipv6_enabled == 1) { - dds_retcode_t ret; + dds_return_t ret; int have_ipv6 = 0; ddsrt_ifaddrs_t *ifa_root, *ifa; const int afs[] = { AF_INET6, DDSRT_AF_TERM }; @@ -160,7 +160,7 @@ CU_Test(ddsrt_getifaddrs, ipv4_n_ipv6) { #if DDSRT_HAVE_IPV6 if (ipv6_enabled == 1) { - dds_retcode_t ret; + dds_return_t ret; int have_ipv4 = 0; int have_ipv6 = 0; ddsrt_ifaddrs_t *ifa_root, *ifa; diff --git a/src/ddsrt/tests/log.c b/src/ddsrt/tests/log.c index a5e66cf..63c0438 100644 --- a/src/ddsrt/tests/log.c +++ b/src/ddsrt/tests/log.c @@ -349,7 +349,7 @@ CU_Test(dds_log, synchronous_sink_changes, .fini=reset) struct arg arg; ddsrt_thread_t tid; ddsrt_threadattr_t tattr; - dds_retcode_t ret; + dds_return_t ret; ddsrt_mutex_init(&mutex); ddsrt_cond_init(&cond); diff --git a/src/ddsrt/tests/process.c b/src/ddsrt/tests/process.c index c000cf7..90ac385 100644 --- a/src/ddsrt/tests/process.c +++ b/src/ddsrt/tests/process.c @@ -26,7 +26,7 @@ */ static void create_and_test_exit(const char *arg, int code) { - dds_retcode_t ret; + dds_return_t ret; ddsrt_pid_t pid; int32_t status; char *argv[] = { NULL, NULL }; @@ -64,7 +64,7 @@ CU_Test(ddsrt_process, create) */ CU_Test(ddsrt_process, kill) { - dds_retcode_t ret; + dds_return_t ret; ddsrt_pid_t pid; /* Sleep for 20 seconds. It should be killed before then. */ @@ -98,7 +98,7 @@ CU_Test(ddsrt_process, kill) */ CU_Test(ddsrt_process, pid) { - dds_retcode_t ret; + dds_return_t ret; ddsrt_pid_t pid; int32_t status; char *argv[] = { TEST_PID_ARG, NULL }; @@ -126,7 +126,7 @@ CU_Test(ddsrt_process, pid) */ CU_Test(ddsrt_process, env) { - dds_retcode_t ret; + dds_return_t ret; ret = ddsrt_setenv(TEST_ENV_VAR_NAME, TEST_ENV_VAR_VALUE); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); @@ -141,7 +141,7 @@ CU_Test(ddsrt_process, env) */ CU_Test(ddsrt_process, invalid) { - dds_retcode_t ret; + dds_return_t ret; ddsrt_pid_t pid; ret = ddsrt_proc_create("ProbablyNotAnValidExecutable", NULL, &pid); @@ -177,7 +177,7 @@ CU_Test(ddsrt_process, arg_dquote) */ CU_Test(ddsrt_process, waitpids) { - dds_retcode_t ret; + dds_return_t ret; ddsrt_pid_t child; ddsrt_pid_t pid1 = 0; ddsrt_pid_t pid2 = 0; @@ -225,7 +225,7 @@ CU_Test(ddsrt_process, waitpids) */ CU_Test(ddsrt_process, waitpid_timeout) { - dds_retcode_t ret; + dds_return_t ret; ddsrt_pid_t pid; /* Sleep for 20 seconds. We should have a timeout before then. */ @@ -238,7 +238,7 @@ CU_Test(ddsrt_process, waitpid_timeout) ret = ddsrt_proc_waitpid(pid, 0, NULL); CU_ASSERT_EQUAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); - /* Valid timeout should return DDS_RETCODE_TIMEOUT when alive. */ + /* Valid timeout should return DDS_RETURN_TIMEOUT when alive. */ ret = ddsrt_proc_waitpid(pid, DDS_SECS(1), NULL); CU_ASSERT_EQUAL(ret, DDS_RETCODE_TIMEOUT); @@ -257,7 +257,7 @@ CU_Test(ddsrt_process, waitpid_timeout) */ CU_Test(ddsrt_process, waitpids_timeout) { - dds_retcode_t ret; + dds_return_t ret; ddsrt_pid_t pid; /* Sleep for 20 seconds. We should have a timeout before then. */ @@ -270,7 +270,7 @@ CU_Test(ddsrt_process, waitpids_timeout) ret = ddsrt_proc_waitpids(0, NULL, NULL); CU_ASSERT_EQUAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); - /* Valid timeout should return DDS_RETCODE_TIMEOUT when alive. */ + /* Valid timeout should return DDS_RETURN_TIMEOUT when alive. */ ret = ddsrt_proc_waitpids(DDS_SECS(1), NULL, NULL); CU_ASSERT_EQUAL(ret, DDS_RETCODE_TIMEOUT); diff --git a/src/ddsrt/tests/select.c b/src/ddsrt/tests/select.c index 7d99096..e23b261 100644 --- a/src/ddsrt/tests/select.c +++ b/src/ddsrt/tests/select.c @@ -107,7 +107,7 @@ typedef struct { static void sockets_pipe(ddsrt_socket_t socks[2]) { - dds_retcode_t rc; + dds_return_t rc; ddsrt_socket_t sock; int reuseaddr = 1; @@ -140,7 +140,7 @@ static const char mesg[] = "foobar"; static uint32_t select_timeout_routine(void *ptr) { int32_t cnt = -1; - dds_retcode_t rc; + dds_return_t rc; dds_time_t before, after; dds_duration_t delay; fd_set rdset; @@ -179,7 +179,7 @@ static uint32_t select_timeout_routine(void *ptr) CU_Test(ddsrt_select, timeout) { - dds_retcode_t rc; + dds_return_t rc; ddsrt_socket_t socks[2]; ddsrt_thread_t thr; ddsrt_threadattr_t attr; @@ -242,7 +242,7 @@ static uint32_t recv_routine(void *ptr) CU_Test(ddsrt_select, send_recv) { - dds_retcode_t rc; + dds_return_t rc; ddsrt_socket_t socks[2]; ddsrt_thread_t thr; ddsrt_threadattr_t attr; @@ -309,7 +309,7 @@ static uint32_t recvmsg_routine(void *ptr) CU_Test(ddsrt_select, sendmsg_recvmsg) { - dds_retcode_t rc; + dds_return_t rc; ddsrt_socket_t socks[2]; ddsrt_thread_t thr; ddsrt_threadattr_t attr; diff --git a/src/ddsrt/tests/socket.c b/src/ddsrt/tests/socket.c index 366c4b2..411524b 100644 --- a/src/ddsrt/tests/socket.c +++ b/src/ddsrt/tests/socket.c @@ -48,15 +48,15 @@ static void teardown(void) CU_Test(ddsrt_sockaddrfromstr, bad_family) { - dds_retcode_t rc; + dds_return_t rc; struct sockaddr_storage sa; rc = ddsrt_sockaddrfromstr(AF_UNSPEC, "127.0.0.1", &sa); CU_ASSERT_EQUAL(rc, DDS_RETCODE_BAD_PARAMETER); } -static void sockaddrfromstr_test(char *str, int af, dds_retcode_t exp) +static void sockaddrfromstr_test(char *str, int af, dds_return_t exp) { - dds_retcode_t rc; + dds_return_t rc; struct sockaddr_storage ss; rc = ddsrt_sockaddrfromstr(af, str, &ss); CU_ASSERT_EQUAL(rc, exp); @@ -70,11 +70,11 @@ CU_TheoryDataPoints(ddsrt_sockaddrfromstr, ipv4) = { "nip"), CU_DataPoints(int, AF_INET, AF_INET, AF_INET), - CU_DataPoints(dds_retcode_t, DDS_RETCODE_OK, DDS_RETCODE_OK, + CU_DataPoints(dds_return_t, DDS_RETCODE_OK, DDS_RETCODE_OK, DDS_RETCODE_BAD_PARAMETER) }; -CU_Theory((char *str, int af, dds_retcode_t exp), ddsrt_sockaddrfromstr, ipv4, .init=setup, .fini=teardown) +CU_Theory((char *str, int af, dds_return_t exp), ddsrt_sockaddrfromstr, ipv4, .init=setup, .fini=teardown) { sockaddrfromstr_test(str, af, exp); } @@ -87,13 +87,13 @@ CU_TheoryDataPoints(ddsrt_sockaddrfromstr, ipv6) = { CU_DataPoints(int, AF_INET6, AF_INET6, AF_INET, AF_INET6, AF_INET6), - CU_DataPoints(dds_retcode_t, DDS_RETCODE_BAD_PARAMETER, DDS_RETCODE_OK, + CU_DataPoints(dds_return_t, DDS_RETCODE_BAD_PARAMETER, DDS_RETCODE_OK, DDS_RETCODE_BAD_PARAMETER, DDS_RETCODE_OK, DDS_RETCODE_BAD_PARAMETER) #endif /* DDSRT_HAVE_IPV6 */ }; -CU_Theory((char *str, int af, dds_retcode_t exp), ddsrt_sockaddrfromstr, ipv6, .init=setup, .fini=teardown) +CU_Theory((char *str, int af, dds_return_t exp), ddsrt_sockaddrfromstr, ipv6, .init=setup, .fini=teardown) { #if DDSRT_HAVE_IPV6 sockaddrfromstr_test(str, af, exp); @@ -107,7 +107,7 @@ CU_Theory((char *str, int af, dds_retcode_t exp), ddsrt_sockaddrfromstr, ipv6, . CU_Test(ddsrt_sockaddrtostr, bad_sockaddr, .init=setup, .fini=teardown) { - dds_retcode_t rc; + dds_return_t rc; char buf[128] = { 0 }; struct sockaddr_in sa; memcpy(&sa, &ipv4_loopback, sizeof(ipv4_loopback)); @@ -118,7 +118,7 @@ CU_Test(ddsrt_sockaddrtostr, bad_sockaddr, .init=setup, .fini=teardown) CU_Test(ddsrt_sockaddrtostr, no_space, .init=setup, .fini=teardown) { - dds_retcode_t rc; + dds_return_t rc; char buf[1] = { 0 }; rc = ddsrt_sockaddrtostr(&ipv4_loopback, buf, sizeof(buf)); CU_ASSERT_EQUAL(rc, DDS_RETCODE_NOT_ENOUGH_SPACE); @@ -126,7 +126,7 @@ CU_Test(ddsrt_sockaddrtostr, no_space, .init=setup, .fini=teardown) CU_Test(ddsrt_sockaddrtostr, ipv4) { - dds_retcode_t rc; + dds_return_t rc; char buf[128] = { 0 }; rc = ddsrt_sockaddrtostr(&ipv4_loopback, buf, sizeof(buf)); CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); @@ -136,7 +136,7 @@ CU_Test(ddsrt_sockaddrtostr, ipv4) CU_Test(ddsrt_sockaddrtostr, ipv6) { #if DDSRT_HAVE_IPV6 - dds_retcode_t rc; + dds_return_t rc; char buf[128] = { 0 }; rc = ddsrt_sockaddrtostr(&ipv6_loopback, buf, sizeof(buf)); CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); @@ -148,7 +148,7 @@ CU_Test(ddsrt_sockaddrtostr, ipv6) CU_Test(ddsrt_sockets, gethostname) { - dds_retcode_t rc; + dds_return_t rc; char sysbuf[200], buf[200]; buf[0] = '\0'; @@ -169,9 +169,9 @@ CU_Test(ddsrt_sockets, gethostname) } #if DDSRT_HAVE_DNS -static void gethostbyname_test(char *name, int af, dds_retcode_t exp) +static void gethostbyname_test(char *name, int af, dds_return_t exp) { - dds_retcode_t rc; + dds_return_t rc; ddsrt_hostent_t *hent = NULL; rc = ddsrt_gethostbyname(name, af, &hent); CU_ASSERT_EQUAL(rc, exp); @@ -188,10 +188,10 @@ static void gethostbyname_test(char *name, int af, dds_retcode_t exp) CU_TheoryDataPoints(ddsrt_gethostbyname, ipv4) = { CU_DataPoints(char *, "", "127.0.0.1", "127.0.0.1"), CU_DataPoints(int, AF_UNSPEC, AF_INET, AF_UNSPEC), - CU_DataPoints(dds_retcode_t, DDS_RETCODE_HOST_NOT_FOUND, DDS_RETCODE_OK, DDS_RETCODE_OK) + CU_DataPoints(dds_return_t, DDS_RETCODE_HOST_NOT_FOUND, DDS_RETCODE_OK, DDS_RETCODE_OK) }; -CU_Theory((char *name, int af, dds_retcode_t exp), ddsrt_gethostbyname, ipv4, .init=setup, .fini=teardown) +CU_Theory((char *name, int af, dds_return_t exp), ddsrt_gethostbyname, ipv4, .init=setup, .fini=teardown) { #if DDSRT_HAVE_DNS gethostbyname_test(name, af, exp); @@ -209,11 +209,11 @@ CU_TheoryDataPoints(ddsrt_gethostbyname, ipv6) = { #if DDSRT_HAVE_IPV6 && DDSRT_HAVE_DNS CU_DataPoints(char *, "::1", "::1", "::1"), CU_DataPoints(int, AF_INET, AF_INET6, AF_UNSPEC), - CU_DataPoints(dds_retcode_t, DDS_RETCODE_HOST_NOT_FOUND, DDS_RETCODE_OK, DDS_RETCODE_OK) + CU_DataPoints(dds_return_t, DDS_RETCODE_HOST_NOT_FOUND, DDS_RETCODE_OK, DDS_RETCODE_OK) #endif /* DDSRT_HAVE_IPV6 */ }; -CU_Theory((char *name, int af, dds_retcode_t exp), ddsrt_gethostbyname, ipv6, .init=setup, .fini=teardown) +CU_Theory((char *name, int af, dds_return_t exp), ddsrt_gethostbyname, ipv6, .init=setup, .fini=teardown) { #if DDSRT_HAVE_IPV6 && DDSRT_HAVE_DNS gethostbyname_test(name, af, exp); diff --git a/src/ddsrt/tests/strtoll.c b/src/ddsrt/tests/strtoll.c index d22e813..525ddf1 100644 --- a/src/ddsrt/tests/strtoll.c +++ b/src/ddsrt/tests/strtoll.c @@ -52,7 +52,7 @@ CU_Clean(ddstr_strtoll) CU_Test(ddsrt_strtoll, strtoll) { - dds_retcode_t rc; + dds_return_t rc; long long ll; static char dummy[] = "dummy"; @@ -248,7 +248,7 @@ CU_Test(ddsrt_strtoll, strtoll) CU_Test(ddsrt_strtoll, strtoull) { - dds_retcode_t rc; + dds_return_t rc; unsigned long long ull; str = "0xffffffffffffffff"; @@ -272,7 +272,7 @@ CU_Test(ddsrt_strtoll, strtoull) CU_Test(ddsrt_strtoll, atoll) { - dds_retcode_t rc; + dds_return_t rc; long long ll; str = "10"; @@ -284,7 +284,7 @@ CU_Test(ddsrt_strtoll, atoll) CU_Test(ddsrt_strtoll, atoull) { - dds_retcode_t rc; + dds_return_t rc; unsigned long long ull; str = "10"; diff --git a/src/ddsrt/tests/sync.c b/src/ddsrt/tests/sync.c index d009353..e2b2cda 100644 --- a/src/ddsrt/tests/sync.c +++ b/src/ddsrt/tests/sync.c @@ -55,7 +55,7 @@ static uint32_t mutex_lock_routine(void *ptr) main thread before a lock operation is attempted by the second thread. */ CU_Test(ddsrt_sync, mutex_lock_conc) { - dds_retcode_t ret; + dds_return_t ret; ddsrt_thread_t thr; ddsrt_threadattr_t attr; thread_arg_t arg = { .cnt = DDSRT_ATOMIC_UINT32_INIT(0) }; @@ -133,7 +133,7 @@ static uint32_t rwlock_trywrite_routine(void *ptr) CU_Test(ddsrt_sync, mutex_trylock_conc) { - dds_retcode_t ret; + dds_return_t ret; ddsrt_thread_t thr; ddsrt_threadattr_t attr; thread_arg_t arg = { .cnt = DDSRT_ATOMIC_UINT32_INIT(1) }; @@ -164,7 +164,7 @@ CU_TheoryDataPoints(ddsrt_sync, rwlock_trylock_conc) = { CU_Theory((uint32_t lock, uint32_t trylock, uint32_t exp), ddsrt_sync, rwlock_trylock_conc) { - dds_retcode_t ret; + dds_return_t ret; ddsrt_thread_t thr; ddsrt_threadattr_t attr; ddsrt_thread_routine_t func; @@ -219,7 +219,7 @@ static uint32_t once_routine(void *ptr) CU_Test(ddsrt_sync, once_conc) { - dds_retcode_t ret; + dds_return_t ret; ddsrt_thread_t thrs[ONCE_THREADS]; ddsrt_threadattr_t attr; uint32_t res; @@ -284,7 +284,7 @@ static uint32_t waitfor_routine(void *ptr) CU_Test(ddsrt_sync, cond_waitfor) { - dds_retcode_t rc; + dds_return_t rc; ddsrt_thread_t thr; ddsrt_threadattr_t attr; thread_arg_t arg = { .cnt = DDSRT_ATOMIC_UINT32_INIT(0), .reltime = DDS_MSECS(100) }; @@ -333,7 +333,7 @@ static uint32_t waituntil_routine(void *ptr) CU_Test(ddsrt_sync, cond_waituntil) { - dds_retcode_t rc; + dds_return_t rc; dds_duration_t delay = DDS_MSECS(100); ddsrt_thread_t thr; ddsrt_threadattr_t attr; diff --git a/src/ddsrt/tests/thread.c b/src/ddsrt/tests/thread.c index 8814440..2e6b5d6 100644 --- a/src/ddsrt/tests/thread.c +++ b/src/ddsrt/tests/thread.c @@ -119,7 +119,7 @@ CU_Theory((ddsrt_sched_t sched, int32_t *prio, uint32_t exp), ddsrt_thread, crea { int skip = 0; uint32_t res = 50505; - dds_retcode_t ret; + dds_return_t ret; ddsrt_thread_t thr; ddsrt_threadattr_t attr; thread_arg_t arg; @@ -215,7 +215,7 @@ uint32_t thread_main_waitforit(void *ptr) CU_Test(ddsrt_thread, stacked_join) { - dds_retcode_t ret; + dds_return_t ret; ddsrt_thread_t thrs[2]; ddsrt_threadattr_t attr; uint32_t res = 0; diff --git a/src/ddsrt/tests/thread_cleanup.c b/src/ddsrt/tests/thread_cleanup.c index 4e9bf24..795819c 100644 --- a/src/ddsrt/tests/thread_cleanup.c +++ b/src/ddsrt/tests/thread_cleanup.c @@ -122,7 +122,7 @@ static void setup( struct thread_argument *arg) { - dds_retcode_t rc; + dds_return_t rc; ddsrt_thread_t thr; ddsrt_threadattr_t attr; diff --git a/src/examples/throughput/publisher.c b/src/examples/throughput/publisher.c index 5109d6b..bf1d20c 100644 --- a/src/examples/throughput/publisher.c +++ b/src/examples/throughput/publisher.c @@ -232,7 +232,7 @@ static void start_writing( if (burstCount < burstSize) { status = dds_write (writer, sample); - if (dds_err_nr(status) == DDS_RETCODE_TIMEOUT) + if (status == DDS_RETCODE_TIMEOUT) { timedOut = true; } @@ -285,7 +285,7 @@ static void start_writing( static void finalize_dds(dds_entity_t participant, dds_entity_t writer, ThroughputModule_DataType sample) { dds_return_t status = dds_dispose (writer, &sample); - if (dds_err_nr (status) != DDS_RETCODE_TIMEOUT && status < 0) + if (status != DDS_RETCODE_TIMEOUT && status < 0) DDS_FATAL("dds_dispose: %s\n", dds_strretcode(-status)); dds_free (sample.payload._buffer); diff --git a/src/mpt/mpt/src/main.c.in b/src/mpt/mpt/src/main.c.in index b48f3a6..5aa3580 100644 --- a/src/mpt/mpt/src/main.c.in +++ b/src/mpt/mpt/src/main.c.in @@ -298,7 +298,7 @@ mpt_run_test(const char *exe, mpt_suite_t *suite, mpt_test_t *test) { int result = EXIT_SUCCESS; mpt_process_t *proc; - dds_retcode_t retcode; + dds_return_t retcode; char *argv[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; argv[0] = "-s"; diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index d270095..eaaefc9 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -564,7 +564,7 @@ static uint32_t pubthread (void *varg) { printf ("write error: %d\n", result); fflush (stdout); - if (dds_err_nr (result) != DDS_RETCODE_TIMEOUT) + if (result != DDS_RETCODE_TIMEOUT) exit (2); timeouts++; /* retry with original timestamp, it really is just a way of reporting @@ -800,7 +800,7 @@ static bool process_data (dds_entity_t rd, struct subthread_arg *arg) if ((wr_pong = get_pong_writer (iseq[i].publication_handle)) != 0) { dds_return_t rc; - if ((rc = dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp - 1)) < 0 && dds_err_nr(rc) != DDS_RETCODE_TIMEOUT) + if ((rc = dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp - 1)) < 0 && rc != DDS_RETCODE_TIMEOUT) error2 ("dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp): %d\n", (int) rc); dds_write_flush (wr_pong); } @@ -828,7 +828,7 @@ static bool process_ping (dds_entity_t rd, struct subthread_arg *arg) if ((wr_pong = get_pong_writer (iseq[i].publication_handle)) != 0) { dds_return_t rc; - if ((rc = dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp | 1)) < 0 && dds_err_nr(rc) != DDS_RETCODE_TIMEOUT) + if ((rc = dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp | 1)) < 0 && rc != DDS_RETCODE_TIMEOUT) error2 ("dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp): %d\n", (int) rc); dds_write_flush (wr_pong); } @@ -863,7 +863,7 @@ static bool process_pong (dds_entity_t rd, struct subthread_arg *arg) cur_ping_time = dds_time (); cur_ping_seq = ++(*seq); ddsrt_mutex_unlock (&pongwr_lock); - if ((rc = dds_write_ts (wr_ping, mseq[i], dds_time () | 1)) < 0 && dds_err_nr(rc) != DDS_RETCODE_TIMEOUT) + if ((rc = dds_write_ts (wr_ping, mseq[i], dds_time () | 1)) < 0 && rc != DDS_RETCODE_TIMEOUT) error2 ("dds_write (wr_ping, mseq[i]): %d\n", (int) rc); dds_write_flush (wr_ping); } @@ -916,7 +916,7 @@ static void maybe_send_new_ping (dds_time_t tnow, dds_time_t *tnextping) cur_ping_seq++; baggage = init_sample (&data, cur_ping_seq); ddsrt_mutex_unlock (&pongwr_lock); - if ((rc = dds_write_ts (wr_ping, &data, dds_time () | 1)) < 0 && dds_err_nr (rc) != DDS_RETCODE_TIMEOUT) + if ((rc = dds_write_ts (wr_ping, &data, dds_time () | 1)) < 0 && rc != DDS_RETCODE_TIMEOUT) error2 ("send_new_ping: dds_write (wr_ping, &data): %d\n", (int) rc); dds_write_flush (wr_ping); if (baggage) diff --git a/src/tools/pubsub/common.h b/src/tools/pubsub/common.h index e4a0b5f..1beca88 100644 --- a/src/tools/pubsub/common.h +++ b/src/tools/pubsub/common.h @@ -119,7 +119,7 @@ bool dds_err_check (dds_return_t err, unsigned flags, const char *where); #define DDS_CHECK_FAIL 0x02 #define DDS_CHECK_EXIT 0x04 -#define dds_err_str(x) (dds_strretcode(dds_err_nr(x))) +#define dds_err_str(x) (dds_strretcode(x)) #define DDS_TO_STRING(n) #n #define DDS_INT_TO_STRING(n) DDS_TO_STRING(n) diff --git a/src/tools/pubsub/pubsub.c b/src/tools/pubsub/pubsub.c index e775f10..60f9fc6 100644 --- a/src/tools/pubsub/pubsub.c +++ b/src/tools/pubsub/pubsub.c @@ -2792,7 +2792,7 @@ int main(int argc, char *argv[]) { ddsrt_threadattr_t attr; ddsrt_threadattr_init(&attr); - dds_retcode_t osres; + dds_return_t osres; if (want_writer) { for (i = 0; i <= specidx; i++) { From 13480616e0c464a2eec226719f193791ec9ed2c5 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 23 May 2019 20:40:51 +0200 Subject: [PATCH 083/178] Consistent code formatting for the core code Code formatting was quite a mess (different indentation, completely different ideas on where opening braces should go, spacing in various places, early out versus single return or goto-based error handling, &c.). This commit cleans it up. A few doxygen comment fixes allowed turning on Clang's warnings for doxygen comments, so those are no enabled by default as least on Xcode-based builds. Signed-off-by: Erik Boasson --- src/CMakeLists.txt | 1 + src/core/ddsc/CMakeLists.txt | 1 + src/core/ddsc/include/dds/dds.h | 17 +- .../ddsc/include/dds/ddsc/dds_public_qos.h | 8 +- src/core/ddsc/src/dds__get_status.h | 56 + src/core/ddsc/src/dds__subscriber.h | 2 +- src/core/ddsc/src/dds__topic.h | 4 +- src/core/ddsc/src/dds__types.h | 8 +- src/core/ddsc/src/dds_builtin.c | 4 +- src/core/ddsc/src/dds_coherent.c | 8 +- src/core/ddsc/src/dds_domain.c | 21 +- src/core/ddsc/src/dds_guardcond.c | 2 +- src/core/ddsc/src/dds_instance.c | 559 ++++---- src/core/ddsc/src/dds_listener.c | 285 +--- src/core/ddsc/src/dds_participant.c | 405 +++--- src/core/ddsc/src/dds_publisher.c | 210 ++- src/core/ddsc/src/dds_qos.c | 1150 +++++++---------- src/core/ddsc/src/dds_querycond.c | 43 +- src/core/ddsc/src/dds_read.c | 991 ++++++-------- src/core/ddsc/src/dds_readcond.c | 91 +- src/core/ddsc/src/dds_reader.c | 616 +++------ src/core/ddsc/src/dds_stream.c | 4 +- src/core/ddsc/src/dds_subscriber.c | 247 ++-- src/core/ddsc/src/dds_topic.c | 805 +++++------- src/core/ddsc/src/dds_waitset.c | 593 ++++----- src/core/ddsc/src/dds_whc.c | 349 +++-- src/core/ddsc/src/dds_whc_builtintopic.c | 4 +- src/core/ddsc/src/dds_write.c | 42 +- src/core/ddsc/src/dds_writer.c | 549 +++----- src/core/ddsi/CMakeLists.txt | 1 - src/core/ddsi/include/dds/ddsi/q_entity.h | 19 +- src/core/ddsi/include/dds/ddsi/q_qosmatch.h | 2 - src/core/ddsi/include/dds/ddsi/q_thread.h | 4 +- src/core/ddsi/src/ddsi_raweth.c | 5 +- src/core/ddsi/src/q_addrset.c | 4 +- src/core/ddsi/src/q_config.c | 18 +- src/core/ddsi/src/q_entity.c | 14 +- src/core/ddsi/src/q_freelist.c | 8 +- src/core/ddsi/src/q_init.c | 68 +- src/core/ddsi/src/q_pcap.c | 4 +- src/core/ddsi/src/q_plist.c | 10 +- src/core/ddsi/src/q_qosmatch.c | 42 +- src/core/ddsi/src/q_receive.c | 6 +- src/core/ddsi/src/q_thread.c | 6 +- src/core/ddsi/src/q_transmit.c | 4 +- src/ddsrt/CMakeLists.txt | 4 +- src/ddsrt/include/dds/ddsrt/atomics/msvc.h | 28 +- src/ddsrt/include/dds/ddsrt/countargs.h | 20 + src/ddsrt/include/dds/ddsrt/environ.h | 6 +- src/ddsrt/include/dds/ddsrt/process.h | 4 +- src/ddsrt/include/dds/ddsrt/retcode.h | 2 +- src/ddsrt/include/dds/ddsrt/sockets.h | 2 +- .../include/dds/ddsrt/static_assert.h} | 27 +- src/ddsrt/include/dds/ddsrt/string.h | 6 +- src/ddsrt/src/random.c | 5 +- src/ddsrt/src/xmlparser.c | 4 +- 56 files changed, 2856 insertions(+), 4542 deletions(-) create mode 100644 src/core/ddsc/src/dds__get_status.h create mode 100644 src/ddsrt/include/dds/ddsrt/countargs.h rename src/{core/ddsi/include/dds/ddsi/q_static_assert.h => ddsrt/include/dds/ddsrt/static_assert.h} (58%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba9fb57..491da54 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -130,6 +130,7 @@ if(${CMAKE_GENERATOR} STREQUAL "Xcode") set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_PARAMETER YES) set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VALUE YES) set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VARIABLE YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_DOCUMENTATION_COMMENTS YES) endif() # Make it easy to enable one of Clang's/gcc's analyzers, and default to using diff --git a/src/core/ddsc/CMakeLists.txt b/src/core/ddsc/CMakeLists.txt index 4af6cb5..3475af6 100644 --- a/src/core/ddsc/CMakeLists.txt +++ b/src/core/ddsc/CMakeLists.txt @@ -74,6 +74,7 @@ PREPEND(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src" dds__whc.h dds__whc_builtintopic.h dds__serdata_builtintopic.h + dds__get_status.h ) generate_export_header( diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index beff47b..ec2e321 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -313,7 +313,7 @@ dds_delete(dds_entity_t entity); * For instance, it will return the Publisher that was used when * creating a DataWriter (when that DataWriter was provided here). * - * @param[in] entity Entity from which to get its publisher. + * @param[in] writer Entity from which to get its publisher. * * @returns A valid entity or an error code. * @@ -361,7 +361,7 @@ dds_get_subscriber(dds_entity_t entity); * For instance, it will return the DataReader that was used when * creating a ReadCondition (when that ReadCondition was provided here). * - * @param[in] entity Entity from which to get its datareader. + * @param[in] condition Entity from which to get its datareader. * * @returns A valid reader handle or an error code. * @@ -502,7 +502,7 @@ dds_get_status_changes(dds_entity_t entity, uint32_t *status); * This operation returns the status enabled on the entity * * @param[in] entity Entity to get the status. - * @param[out] status Status set on the entity. + * @param[out] mask Mask of enabled statuses set on the entity. * * @returns A dds_return_t indicating success or failure. * @@ -952,6 +952,8 @@ 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. * @@ -972,8 +974,6 @@ dds_create_topic( * Either participant, descriptor, name or qos is invalid. */ /* TODO: Check list of retcodes is complete. */ -struct ddsi_sertopic; -struct nn_plist; DDS_EXPORT dds_entity_t dds_create_topic_arbitrary ( dds_entity_t participant, @@ -1650,8 +1650,7 @@ dds_write_flush(dds_entity_t writer); * @brief Write a CDR serialized value of a data instance * * @param[in] writer The writer entity. - * @param[in] cdr CDR serialized value to be written. - * @param[in] size Size (in bytes) of CDR encoded data to be written. + * @param[in] serdata CDR serialized value to be written. * * @returns A dds_return_t indicating success or failure. */ @@ -2604,7 +2603,7 @@ dds_take_mask_wl( uint32_t maxs, uint32_t mask); -DDS_EXPORT int +DDS_EXPORT dds_return_t dds_takecdr( dds_entity_t reader_or_condition, struct ddsi_serdata **buf, @@ -2898,7 +2897,7 @@ dds_read_next_wl( * the memory is released so that the buffer can be reused during a successive read/take operation. * When a condition is provided, the reader to which the condition belongs is looked up. * - * @param[in] rd_or_cnd Reader or condition that belongs to a reader. + * @param[in] reader_or_condition Reader or condition that belongs to a reader. * @param[in] buf An array of (pointers to) samples. * @param[in] bufsz The number of (pointers to) samples stored in buf. * 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 b8fc7fa..29cb38c 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h @@ -212,8 +212,8 @@ dds_qos_merge (dds_qos_t * __restrict dst, const dds_qos_t * __restrict src); * * Policies are copied from src to dst, unless src already has the policy set to a non-default value. * - * @param[in,out] dst - Pointer to the destination qos structure - * @param[in] src - Pointer to the source qos structure + * @param[in,out] a - Pointer to the destination qos structure + * @param[in] b - Pointer to the source qos structure */ DDS_EXPORT bool dds_qos_equal (const dds_qos_t * __restrict a, const dds_qos_t * __restrict b); @@ -448,7 +448,7 @@ dds_qset_destination_order ( * @brief Set the writer data-lifecycle policy of a qos structure * * @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy - * @param[in] autodispose_unregistered_instances - Automatic disposal of unregistered instances + * @param[in] autodispose - Automatic disposal of unregistered instances */ DDS_EXPORT void dds_qset_writer_data_lifecycle (dds_qos_t * __restrict qos, bool autodispose); @@ -738,7 +738,7 @@ dds_qget_destination_order ( * @brief Get the writer data-lifecycle qos policy * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy - * @param[in,out] autodispose_unregistered_instances - Pointer that will store the autodispose unregistered instances enable value + * @param[in,out] autodispose - Pointer that will store the autodispose unregistered instances enable value * * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ diff --git a/src/core/ddsc/src/dds__get_status.h b/src/core/ddsc/src/dds__get_status.h new file mode 100644 index 0000000..881b7d1 --- /dev/null +++ b/src/core/ddsc/src/dds__get_status.h @@ -0,0 +1,56 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef _DDS_GET_STATUS_H_ +#define _DDS_GET_STATUS_H_ + +#include "dds/ddsrt/countargs.h" + +#define DDS_GET_STATUS_LOCKED_RESET_1(status_, reset0_) \ + (ent->m_##status_##_status.reset0_ = 0); +#define DDS_GET_STATUS_LOCKED_RESET_2(status_, reset0_, reset1_) \ + (ent->m_##status_##_status.reset0_ = 0); \ + (ent->m_##status_##_status.reset1_ = 0); +#define DDS_GET_STATUS_LOCKED_RESET_MSVC_WORKAROUND(x) x +#define DDS_GET_STATUS_LOCKED_RESET_N1(n_, status_, ...) \ + DDS_GET_STATUS_LOCKED_RESET_MSVC_WORKAROUND (DDS_GET_STATUS_LOCKED_RESET_##n_ (status_, __VA_ARGS__)) +#define DDS_GET_STATUS_LOCKED_RESET_N(n_, status_, ...) DDS_GET_STATUS_LOCKED_RESET_N1 (n_, status_, __VA_ARGS__) + +#define DDS_GET_STATUS_LOCKED(ent_type_, status_, STATUS_, ...) \ + static void dds_get_##status_##_status_locked (dds_##ent_type_ *ent, dds_##status_##_status_t *status) \ + { \ + if (status) \ + *status = ent->m_##status_##_status; \ + if (ent->m_entity.m_status_enable & DDS_##STATUS_##_STATUS) { \ + do { DDS_GET_STATUS_LOCKED_RESET_N (DDSRT_COUNT_ARGS (__VA_ARGS__), status_, __VA_ARGS__) } while (0); \ + dds_entity_status_reset (&ent->m_entity, DDS_##STATUS_##_STATUS); \ + } \ + } + +#define DDS_GET_STATUS_COMMON(ent_type_, status_) \ + dds_return_t dds_get_##status_##_status (dds_entity_t entity, dds_##status_##_status_t *status) \ + { \ + dds_##ent_type_ *ent; \ + dds_return_t ret; \ + if ((ret = dds_##ent_type_##_lock (entity, &ent)) != DDS_RETCODE_OK) \ + return ret; \ + ddsrt_mutex_lock (&ent->m_entity.m_observers_lock); \ + dds_get_##status_##_status_locked (ent, status); \ + ddsrt_mutex_unlock (&ent->m_entity.m_observers_lock); \ + dds_##ent_type_##_unlock (ent); \ + return DDS_RETCODE_OK; \ + } + +#define DDS_GET_STATUS(ent_type_, status_, STATUS_, ...) \ + DDS_GET_STATUS_LOCKED (ent_type_, status_, STATUS_, __VA_ARGS__) \ + DDS_GET_STATUS_COMMON (ent_type_, status_) + +#endif diff --git a/src/core/ddsc/src/dds__subscriber.h b/src/core/ddsc/src/dds__subscriber.h index c104255..966f43e 100644 --- a/src/core/ddsc/src/dds__subscriber.h +++ b/src/core/ddsc/src/dds__subscriber.h @@ -23,7 +23,7 @@ DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_subscriber, DDS_KIND_SUBSCRIBER) dds_entity_t dds__create_subscriber_l( - struct dds_entity *participant, /* entity-lock must be held */ + struct dds_participant *participant, /* entity-lock must be held */ const dds_qos_t *qos, const dds_listener_t *listener); diff --git a/src/core/ddsc/src/dds__topic.h b/src/core/ddsc/src/dds__topic.h index 7cba5a5..d59dc1f 100644 --- a/src/core/ddsc/src/dds__topic.h +++ b/src/core/ddsc/src/dds__topic.h @@ -21,8 +21,8 @@ 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); -DDS_EXPORT void dds_topic_free (dds_domainid_t domainid, struct ddsi_sertopic * st); +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; #ifndef DDS_TOPIC_INTERN_FILTER_FN_DEFINED #define DDS_TOPIC_INTERN_FILTER_FN_DEFINED diff --git a/src/core/ddsc/src/dds__types.h b/src/core/ddsc/src/dds__types.h index 61c7c57..ba2319a 100644 --- a/src/core/ddsc/src/dds__types.h +++ b/src/core/ddsc/src/dds__types.h @@ -104,12 +104,12 @@ dds_domain; struct dds_entity; typedef struct dds_entity_deriver { /* Close can be used to terminate (blocking) actions on a entity before actually deleting it. */ - dds_return_t (*close)(struct dds_entity *e); + dds_return_t (*close)(struct dds_entity *e) ddsrt_nonnull_all; /* Delete is used to actually free the entity. */ - dds_return_t (*delete)(struct dds_entity *e); - dds_return_t (*set_qos)(struct dds_entity *e, const dds_qos_t *qos, bool enabled); + dds_return_t (*delete)(struct dds_entity *e) ddsrt_nonnull_all; + dds_return_t (*set_qos)(struct dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; dds_return_t (*validate_status)(uint32_t mask); - dds_return_t (*get_instance_hdl)(struct dds_entity *e, dds_instance_handle_t *i); + dds_return_t (*get_instance_hdl)(struct dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all; } dds_entity_deriver; diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index 01c98e5..12648d6 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -132,7 +132,7 @@ bool dds__validate_builtin_reader_qos (dds_entity_t topic, const dds_qos_t *qos) } } -static dds_entity_t dds__create_builtin_subscriber (dds_entity *participant) +static dds_entity_t dds__create_builtin_subscriber (dds_participant *participant) { dds_qos_t *qos = dds__create_builtin_qos (); dds_entity_t sub = dds__create_subscriber_l (participant, qos, NULL); @@ -153,7 +153,7 @@ dds_entity_t dds__get_builtin_subscriber (dds_entity_t e) return ret; if (p->m_builtin_subscriber <= 0) { - p->m_builtin_subscriber = dds__create_builtin_subscriber (&p->m_entity); + p->m_builtin_subscriber = dds__create_builtin_subscriber (p); } sub = p->m_builtin_subscriber; dds_participant_unlock(p); diff --git a/src/core/ddsc/src/dds_coherent.c b/src/core/ddsc/src/dds_coherent.c index f2f1063..68bf384 100644 --- a/src/core/ddsc/src/dds_coherent.c +++ b/src/core/ddsc/src/dds_coherent.c @@ -16,17 +16,13 @@ #include "dds__subscriber.h" #include "dds__publisher.h" -dds_return_t -dds_begin_coherent( - dds_entity_t entity) +dds_return_t dds_begin_coherent (dds_entity_t entity) { static const dds_entity_kind_t kinds[] = { DDS_KIND_READER, DDS_KIND_WRITER, DDS_KIND_PUBLISHER, DDS_KIND_SUBSCRIBER }; return dds_generic_unimplemented_operation_manykinds (entity, sizeof (kinds) / sizeof (kinds[0]), kinds); } -dds_return_t -dds_end_coherent( - dds_entity_t entity) +dds_return_t dds_end_coherent (dds_entity_t entity) { static const dds_entity_kind_t kinds[] = { DDS_KIND_READER, DDS_KIND_WRITER, DDS_KIND_PUBLISHER, DDS_KIND_SUBSCRIBER }; return dds_generic_unimplemented_operation_manykinds (entity, sizeof (kinds) / sizeof (kinds[0]), kinds); diff --git a/src/core/ddsc/src/dds_domain.c b/src/core/ddsc/src/dds_domain.c index b8c12d8..2c83a22 100644 --- a/src/core/ddsc/src/dds_domain.c +++ b/src/core/ddsc/src/dds_domain.c @@ -12,27 +12,24 @@ #include "dds__domain.h" #include "dds/ddsi/ddsi_tkmap.h" -static int dds_domain_compare (const int32_t * a, const int32_t * b) +static int dds_domain_compare (const void *va, const void *vb) { + const int32_t *a = va; + const int32_t *b = vb; return (*a == *b) ? 0 : (*a < *b) ? -1 : 1; } -const ddsrt_avl_treedef_t dds_domaintree_def = DDSRT_AVL_TREEDEF_INITIALIZER -( - offsetof (dds_domain, m_node), - offsetof (dds_domain, m_id), - (int (*) (const void *, const void *)) dds_domain_compare, - 0 -); +const ddsrt_avl_treedef_t dds_domaintree_def = DDSRT_AVL_TREEDEF_INITIALIZER ( + offsetof (dds_domain, m_node), offsetof (dds_domain, m_id), dds_domain_compare, 0); -dds_domain * dds_domain_find_locked (dds_domainid_t id) +dds_domain *dds_domain_find_locked (dds_domainid_t id) { return ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &id); } -dds_domain * dds_domain_create (dds_domainid_t id) +dds_domain *dds_domain_create (dds_domainid_t id) { - dds_domain * domain; + dds_domain *domain; ddsrt_mutex_lock (&dds_global.m_mutex); domain = dds_domain_find_locked (id); if (domain == NULL) @@ -47,7 +44,7 @@ dds_domain * dds_domain_create (dds_domainid_t id) return domain; } -void dds_domain_free (dds_domain * domain) +void dds_domain_free (dds_domain *domain) { ddsrt_mutex_lock (&dds_global.m_mutex); if (--domain->m_refc == 0) diff --git a/src/core/ddsc/src/dds_guardcond.c b/src/core/ddsc/src/dds_guardcond.c index 9b3b0ca..8dcb956 100644 --- a/src/core/ddsc/src/dds_guardcond.c +++ b/src/core/ddsc/src/dds_guardcond.c @@ -18,7 +18,7 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" -DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_guardcond) +DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_guardcond) dds_entity_t dds_create_guardcondition (dds_entity_t participant) { diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index cef2032..5631a1c 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -23,396 +23,307 @@ #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_globals.h" -dds_return_t -dds_writedispose( - dds_entity_t writer, - const void *data) +dds_return_t dds_writedispose (dds_entity_t writer, const void *data) { - return dds_writedispose_ts(writer, data, dds_time()); + return dds_writedispose_ts (writer, data, dds_time ()); } -dds_return_t -dds_dispose( - dds_entity_t writer, - const void *data) +dds_return_t dds_dispose (dds_entity_t writer, const void *data) { - return dds_dispose_ts(writer, data, dds_time()); + return dds_dispose_ts (writer, data, dds_time ()); } -dds_return_t -dds_dispose_ih( - dds_entity_t writer, - dds_instance_handle_t handle) +dds_return_t dds_dispose_ih (dds_entity_t writer, dds_instance_handle_t handle) { - return dds_dispose_ih_ts(writer, handle, dds_time()); + return dds_dispose_ih_ts (writer, handle, dds_time ()); } -static struct ddsi_tkmap_instance* -dds_instance_find( - const dds_topic *topic, - const void *data, - const bool create) +static struct ddsi_tkmap_instance *dds_instance_find (const dds_topic *topic, const void *data, const bool create) { - struct ddsi_serdata *sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data); - struct ddsi_tkmap_instance * inst = ddsi_tkmap_find (sd, false, create); - ddsi_serdata_unref (sd); - return inst; + struct ddsi_serdata *sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data); + struct ddsi_tkmap_instance *inst = ddsi_tkmap_find (sd, false, create); + ddsi_serdata_unref (sd); + return inst; } -static void -dds_instance_remove( - const dds_topic *topic, - const void *data, - dds_instance_handle_t handle) +static void dds_instance_remove (const dds_topic *topic, const void *data, dds_instance_handle_t handle) { - struct ddsi_tkmap_instance * inst; - - if (handle != DDS_HANDLE_NIL) - { - inst = ddsi_tkmap_find_by_id (gv.m_tkmap, handle); - } - else - { - assert (data); - inst = dds_instance_find (topic, data, false); - } - if (inst) - { - ddsi_tkmap_instance_unref (inst); - } + struct ddsi_tkmap_instance *inst; + if (handle != DDS_HANDLE_NIL) + inst = ddsi_tkmap_find_by_id (gv.m_tkmap, handle); + else + { + assert (data); + inst = dds_instance_find (topic, data, false); + } + if (inst) + { + ddsi_tkmap_instance_unref (inst); + } } static const dds_topic *dds_instance_info (dds_entity *e) { - const dds_topic *topic; - switch (dds_entity_kind (e)) - { - case DDS_KIND_READER: - topic = ((dds_reader*) e)->m_topic; - break; - case DDS_KIND_WRITER: - topic = ((dds_writer*) e)->m_topic; - break; - default: - assert (0); - topic = NULL; - } - return topic; + const dds_topic *topic; + switch (dds_entity_kind (e)) + { + case DDS_KIND_READER: + topic = ((dds_reader*) e)->m_topic; + break; + case DDS_KIND_WRITER: + topic = ((dds_writer*) e)->m_topic; + break; + default: + assert (0); + topic = NULL; + } + return topic; } -static const dds_topic * dds_instance_info_by_hdl (dds_entity_t e) +static const dds_topic *dds_instance_info_by_hdl (dds_entity_t e) { - const dds_topic * topic = NULL; - dds_return_t rc; - dds_entity *w_or_r; + const dds_topic *topic; + dds_entity *w_or_r; - rc = dds_entity_lock(e, DDS_KIND_WRITER, &w_or_r); - if (rc == DDS_RETCODE_ILLEGAL_OPERATION) - { - rc = dds_entity_lock(e, DDS_KIND_READER, &w_or_r); - } - if (rc != DDS_RETCODE_OK) - { - return NULL; - } - topic = dds_instance_info(w_or_r); - dds_entity_unlock(w_or_r); - return topic; + if (dds_entity_lock (e, DDS_KIND_DONTCARE, &w_or_r) != DDS_RETCODE_OK) + return NULL; + + switch (dds_entity_kind (w_or_r)) + { + case DDS_KIND_WRITER: + case DDS_KIND_READER: + topic = dds_instance_info (w_or_r); + break; + default: + topic = NULL; + break; + } + dds_entity_unlock (w_or_r); + return topic; } -dds_return_t -dds_register_instance( - dds_entity_t writer, - dds_instance_handle_t *handle, - const void *data) +dds_return_t dds_register_instance (dds_entity_t writer, dds_instance_handle_t *handle, const void *data) { - struct thread_state1 * const ts1 = lookup_thread_state (); - struct ddsi_tkmap_instance * inst; - dds_writer *wr; - dds_return_t ret; + struct thread_state1 * const ts1 = lookup_thread_state (); + dds_writer *wr; + dds_return_t ret; - if(data == NULL){ - return DDS_RETCODE_BAD_PARAMETER; - } - if(handle == NULL){ - return DDS_RETCODE_BAD_PARAMETER; - } - ret = dds_writer_lock(writer, &wr); - if (ret != DDS_RETCODE_OK) { - goto err; - } - thread_state_awake (ts1); - inst = dds_instance_find (wr->m_topic, data, true); - if(inst != NULL){ - *handle = inst->m_iid; - ret = DDS_RETCODE_OK; - } else { - ret = DDS_RETCODE_ERROR; - } - thread_state_asleep (ts1); - dds_writer_unlock(wr); -err: + if (data == NULL || handle == NULL) + return DDS_RETCODE_BAD_PARAMETER; + + if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) return ret; + + thread_state_awake (ts1); + struct ddsi_tkmap_instance * const inst = dds_instance_find (wr->m_topic, data, true); + if (inst == NULL) + ret = DDS_RETCODE_ERROR; + else + { + *handle = inst->m_iid; + ret = DDS_RETCODE_OK; + } + thread_state_asleep (ts1); + dds_writer_unlock (wr); + return ret; } -dds_return_t -dds_unregister_instance( - dds_entity_t writer, - const void *data) +dds_return_t dds_unregister_instance (dds_entity_t writer, const void *data) { - return dds_unregister_instance_ts (writer, data, dds_time()); + return dds_unregister_instance_ts (writer, data, dds_time ()); } -dds_return_t -dds_unregister_instance_ih( - dds_entity_t writer, - dds_instance_handle_t handle) +dds_return_t dds_unregister_instance_ih (dds_entity_t writer, dds_instance_handle_t handle) { - return dds_unregister_instance_ih_ts(writer, handle, dds_time()); + return dds_unregister_instance_ih_ts (writer, handle, dds_time ()); } -dds_return_t -dds_unregister_instance_ts( - dds_entity_t writer, - const void *data, - dds_time_t timestamp) +dds_return_t dds_unregister_instance_ts (dds_entity_t writer, const void *data, dds_time_t timestamp) { - struct thread_state1 * const ts1 = lookup_thread_state (); - dds_return_t ret = DDS_RETCODE_OK; - bool autodispose = true; - dds_write_action action = DDS_WR_ACTION_UNREGISTER; - dds_writer *wr; + struct thread_state1 * const ts1 = lookup_thread_state (); + dds_return_t ret; + bool autodispose = true; + dds_write_action action = DDS_WR_ACTION_UNREGISTER; + dds_writer *wr; - if (data == NULL){ - ret = DDS_RETCODE_BAD_PARAMETER; - goto err; - } - if(timestamp < 0){ - ret = DDS_RETCODE_BAD_PARAMETER; - goto err; - } - ret = dds_writer_lock(writer, &wr); - if (ret != DDS_RETCODE_OK) { - goto err; - } + if (data == NULL || timestamp < 0) + return DDS_RETCODE_BAD_PARAMETER; - if (wr->m_entity.m_qos) { - dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose); - } - thread_state_awake (ts1); - if (autodispose) { - dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL); - action |= DDS_WR_DISPOSE_BIT; - } - ret = dds_write_impl (wr, data, timestamp, action); - thread_state_asleep (ts1); - dds_writer_unlock(wr); -err: + if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) return ret; + + if (wr->m_entity.m_qos) + dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose); + + thread_state_awake (ts1); + if (autodispose) + { + dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL); + action |= DDS_WR_DISPOSE_BIT; + } + ret = dds_write_impl (wr, data, timestamp, action); + thread_state_asleep (ts1); + dds_writer_unlock (wr); + return ret; } -dds_return_t -dds_unregister_instance_ih_ts( - dds_entity_t writer, - dds_instance_handle_t handle, - dds_time_t timestamp) +dds_return_t dds_unregister_instance_ih_ts (dds_entity_t writer, dds_instance_handle_t handle, dds_time_t timestamp) { - struct thread_state1 * const ts1 = lookup_thread_state (); - dds_return_t ret = DDS_RETCODE_OK; - bool autodispose = true; - dds_write_action action = DDS_WR_ACTION_UNREGISTER; - dds_writer *wr; - struct ddsi_tkmap_instance *tk; + struct thread_state1 * const ts1 = lookup_thread_state (); + dds_return_t ret = DDS_RETCODE_OK; + bool autodispose = true; + dds_write_action action = DDS_WR_ACTION_UNREGISTER; + dds_writer *wr; + struct ddsi_tkmap_instance *tk; - ret = dds_writer_lock(writer, &wr); - if (ret != DDS_RETCODE_OK) { - goto err; - } - - if (wr->m_entity.m_qos) { - dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose); - } - thread_state_awake (ts1); - if (autodispose) { - dds_instance_remove (wr->m_topic, NULL, handle); - action |= DDS_WR_DISPOSE_BIT; - } - tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle); - if (tk) { - struct ddsi_sertopic *tp = wr->m_topic->m_stopic; - void *sample = ddsi_sertopic_alloc_sample (tp); - ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL); - ddsi_tkmap_instance_unref (tk); - ret = dds_write_impl (wr, sample, timestamp, action); - ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL); - } else { - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - } - thread_state_asleep (ts1); - dds_writer_unlock(wr); -err: + if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) return ret; + + if (wr->m_entity.m_qos) + dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose); + + thread_state_awake (ts1); + if (autodispose) + { + dds_instance_remove (wr->m_topic, NULL, handle); + action |= DDS_WR_DISPOSE_BIT; + } + if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle)) == NULL) + ret = DDS_RETCODE_PRECONDITION_NOT_MET; + else + { + struct ddsi_sertopic *tp = wr->m_topic->m_stopic; + void *sample = ddsi_sertopic_alloc_sample (tp); + ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL); + ddsi_tkmap_instance_unref (tk); + ret = dds_write_impl (wr, sample, timestamp, action); + ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL); + } + thread_state_asleep (ts1); + dds_writer_unlock (wr); + return ret; } -dds_return_t -dds_writedispose_ts( - dds_entity_t writer, - const void *data, - dds_time_t timestamp) +dds_return_t dds_writedispose_ts (dds_entity_t writer, const void *data, dds_time_t timestamp) { - struct thread_state1 * const ts1 = lookup_thread_state (); - dds_return_t ret; - dds_writer *wr; - - ret = dds_writer_lock(writer, &wr); - if (ret == DDS_RETCODE_OK) { - thread_state_awake (ts1); - ret = dds_write_impl (wr, data, timestamp, DDS_WR_ACTION_WRITE_DISPOSE); - if (ret == DDS_RETCODE_OK) { - dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL); - } - thread_state_asleep (ts1); - dds_writer_unlock(wr); - } + struct thread_state1 * const ts1 = lookup_thread_state (); + dds_return_t ret; + dds_writer *wr; + if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) return ret; + + thread_state_awake (ts1); + if ((ret = dds_write_impl (wr, data, timestamp, DDS_WR_ACTION_WRITE_DISPOSE)) == DDS_RETCODE_OK) + dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL); + thread_state_asleep (ts1); + dds_writer_unlock (wr); + return ret; } -static dds_return_t -dds_dispose_impl( - dds_writer *wr, - const void *data, - dds_instance_handle_t handle, - dds_time_t timestamp) +static dds_return_t dds_dispose_impl (dds_writer *wr, const void *data, dds_instance_handle_t handle, dds_time_t timestamp) ddsrt_nonnull_all; + +static dds_return_t dds_dispose_impl (dds_writer *wr, const void *data, dds_instance_handle_t handle, dds_time_t timestamp) { - dds_return_t ret; - assert(thread_is_awake ()); - assert(wr); - ret = dds_write_impl(wr, data, timestamp, DDS_WR_ACTION_DISPOSE); - if (ret == DDS_RETCODE_OK) { - dds_instance_remove (wr->m_topic, data, handle); - } + dds_return_t ret; + assert (thread_is_awake ()); + if ((ret = dds_write_impl (wr, data, timestamp, DDS_WR_ACTION_DISPOSE)) == DDS_RETCODE_OK) + dds_instance_remove (wr->m_topic, data, handle); + return ret; +} + +dds_return_t dds_dispose_ts (dds_entity_t writer, const void *data, dds_time_t timestamp) +{ + struct thread_state1 * const ts1 = lookup_thread_state (); + dds_return_t ret; + dds_writer *wr; + + if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) return ret; + + thread_state_awake (ts1); + ret = dds_dispose_impl (wr, data, DDS_HANDLE_NIL, timestamp); + thread_state_asleep (ts1); + dds_writer_unlock(wr); + return ret; } -dds_return_t -dds_dispose_ts( - dds_entity_t writer, - const void *data, - dds_time_t timestamp) +dds_return_t dds_dispose_ih_ts (dds_entity_t writer, dds_instance_handle_t handle, dds_time_t timestamp) { - struct thread_state1 * const ts1 = lookup_thread_state (); - dds_return_t ret; - dds_writer *wr; - - ret = dds_writer_lock(writer, &wr); - if (ret == DDS_RETCODE_OK) { - thread_state_awake (ts1); - ret = dds_dispose_impl(wr, data, DDS_HANDLE_NIL, timestamp); - thread_state_asleep (ts1); - dds_writer_unlock(wr); - } + struct thread_state1 * const ts1 = lookup_thread_state (); + dds_return_t ret; + dds_writer *wr; + if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) return ret; + + struct ddsi_tkmap_instance *tk; + thread_state_awake (ts1); + if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle)) == NULL) + ret = DDS_RETCODE_PRECONDITION_NOT_MET; + else + { + struct ddsi_sertopic *tp = wr->m_topic->m_stopic; + void *sample = ddsi_sertopic_alloc_sample (tp); + ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL); + ddsi_tkmap_instance_unref (tk); + ret = dds_dispose_impl (wr, sample, handle, timestamp); + ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL); + } + thread_state_asleep (ts1); + dds_writer_unlock (wr); + return ret; } -dds_return_t -dds_dispose_ih_ts( - dds_entity_t writer, - dds_instance_handle_t handle, - dds_time_t timestamp) +dds_instance_handle_t dds_lookup_instance (dds_entity_t entity, const void *data) { - struct thread_state1 * const ts1 = lookup_thread_state (); - dds_return_t ret; - dds_writer *wr; + struct thread_state1 * const ts1 = lookup_thread_state (); + dds_instance_handle_t ih = DDS_HANDLE_NIL; + const dds_topic *topic; + struct ddsi_serdata *sd; - ret = dds_writer_lock(writer, &wr); - if (ret == DDS_RETCODE_OK) { - struct ddsi_tkmap_instance *tk; - thread_state_awake (ts1); - if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle)) != NULL) { - struct ddsi_sertopic *tp = wr->m_topic->m_stopic; - void *sample = ddsi_sertopic_alloc_sample (tp); - ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL); - ddsi_tkmap_instance_unref (tk); - ret = dds_dispose_impl (wr, sample, handle, timestamp); - ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL); - } else { - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - } - thread_state_asleep (ts1); - dds_writer_unlock(wr); - } + if (data == NULL) + return DDS_HANDLE_NIL; - return ret; + if ((topic = dds_instance_info_by_hdl (entity)) == NULL) + return DDS_HANDLE_NIL; + + thread_state_awake (ts1); + sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data); + ih = ddsi_tkmap_lookup (gv.m_tkmap, sd); + ddsi_serdata_unref (sd); + thread_state_asleep (ts1); + return ih; } -dds_instance_handle_t -dds_lookup_instance( - dds_entity_t entity, - const void *data) +dds_instance_handle_t dds_instance_lookup (dds_entity_t entity, const void *data) { - struct thread_state1 * const ts1 = lookup_thread_state (); - dds_instance_handle_t ih = DDS_HANDLE_NIL; - const dds_topic * topic; - struct ddsi_tkmap * map = gv.m_tkmap; - struct ddsi_serdata *sd; - - if(data == NULL){ - goto err; - } - - topic = dds_instance_info_by_hdl (entity); - if (topic) { - thread_state_awake (ts1); - sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data); - ih = ddsi_tkmap_lookup (map, sd); - ddsi_serdata_unref (sd); - thread_state_asleep (ts1); - } -err: - return ih; + return dds_lookup_instance (entity, data); } -dds_instance_handle_t -dds_instance_lookup ( - dds_entity_t entity, - const void *data) +dds_return_t dds_instance_get_key (dds_entity_t entity, dds_instance_handle_t ih, void *data) { - return dds_lookup_instance(entity, data); -} - -dds_return_t -dds_instance_get_key( - dds_entity_t entity, - dds_instance_handle_t ih, - void *data) -{ - struct thread_state1 * const ts1 = lookup_thread_state (); - dds_return_t ret; - const dds_topic * topic; - struct ddsi_tkmap_instance * tk; - - if(data == NULL){ - ret = DDS_RETCODE_BAD_PARAMETER; - goto err; - } - - topic = dds_instance_info_by_hdl (entity); - if(topic == NULL){ - ret = DDS_RETCODE_BAD_PARAMETER; - goto err; - } - thread_state_awake (ts1); - if ((tk = ddsi_tkmap_find_by_id(gv.m_tkmap, ih)) != NULL) { - ddsi_sertopic_zero_sample (topic->m_stopic, data); - ddsi_serdata_topicless_to_sample (topic->m_stopic, tk->m_sample, data, NULL, NULL); - ddsi_tkmap_instance_unref (tk); - ret = DDS_RETCODE_OK; - } else { - ret = DDS_RETCODE_BAD_PARAMETER; - } - thread_state_asleep (ts1); -err: - return ret; + struct thread_state1 * const ts1 = lookup_thread_state (); + dds_return_t ret; + const dds_topic *topic; + struct ddsi_tkmap_instance *tk; + + if (data == NULL) + return DDS_RETCODE_BAD_PARAMETER; + + if ((topic = dds_instance_info_by_hdl (entity)) == NULL) + return DDS_RETCODE_BAD_PARAMETER; + + thread_state_awake (ts1); + if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, ih)) == NULL) + ret = DDS_RETCODE_BAD_PARAMETER; + else + { + ddsi_sertopic_zero_sample (topic->m_stopic, data); + ddsi_serdata_topicless_to_sample (topic->m_stopic, tk->m_sample, data, NULL, NULL); + ddsi_tkmap_instance_unref (tk); + ret = DDS_RETCODE_OK; + } + thread_state_asleep (ts1); + return ret; } diff --git a/src/core/ddsc/src/dds_listener.c b/src/core/ddsc/src/dds_listener.c index a325753..ddfc5ca 100644 --- a/src/core/ddsc/src/dds_listener.c +++ b/src/core/ddsc/src/dds_listener.c @@ -207,324 +207,169 @@ void dds_merge_listener (dds_listener_t * __restrict dst, const dds_listener_t * void dds_listener_merge (dds_listener_t * __restrict dst, const dds_listener_t * __restrict src) { - dds_merge_listener(dst, src); + dds_merge_listener (dst, src); } /************************************************************************************************ * Setters ************************************************************************************************/ -void -dds_lset_data_available (dds_listener_t * __restrict listener, dds_on_data_available_fn callback) +void dds_lset_data_available (dds_listener_t * __restrict listener, dds_on_data_available_fn callback) { - if (listener) { - listener->on_data_available = callback; - } else { - DDS_ERROR("Argument listener is NULL\n"); - } + if (listener) + listener->on_data_available = callback; } -void -dds_lset_data_on_readers (dds_listener_t * __restrict listener, dds_on_data_on_readers_fn callback) +void dds_lset_data_on_readers (dds_listener_t * __restrict listener, dds_on_data_on_readers_fn callback) { - if (listener) { - listener->on_data_on_readers = callback; - } else { - DDS_ERROR("Argument listener is NULL\n"); - } + if (listener) + listener->on_data_on_readers = callback; } -void -dds_lset_inconsistent_topic (dds_listener_t * __restrict listener, dds_on_inconsistent_topic_fn callback) +void dds_lset_inconsistent_topic (dds_listener_t * __restrict listener, dds_on_inconsistent_topic_fn callback) { - if (listener) { - listener->on_inconsistent_topic = callback; - } else { - DDS_ERROR("Argument listener is NULL\n"); - } + if (listener) + listener->on_inconsistent_topic = callback; } -void -dds_lset_liveliness_changed (dds_listener_t * __restrict listener, dds_on_liveliness_changed_fn callback) +void dds_lset_liveliness_changed (dds_listener_t * __restrict listener, dds_on_liveliness_changed_fn callback) { - if (listener) { - listener->on_liveliness_changed = callback; - } else { - DDS_ERROR("Argument listener is NULL\n"); - } + if (listener) + listener->on_liveliness_changed = callback; } -void -dds_lset_liveliness_lost (dds_listener_t * __restrict listener, dds_on_liveliness_lost_fn callback) +void dds_lset_liveliness_lost (dds_listener_t * __restrict listener, dds_on_liveliness_lost_fn callback) { - if (listener) { - listener->on_liveliness_lost = callback; - } else { - DDS_ERROR("Argument listener is NULL\n"); - } + if (listener) + listener->on_liveliness_lost = callback; } -void -dds_lset_offered_deadline_missed (dds_listener_t * __restrict listener, dds_on_offered_deadline_missed_fn callback) +void dds_lset_offered_deadline_missed (dds_listener_t * __restrict listener, dds_on_offered_deadline_missed_fn callback) { - if (listener) { - listener->on_offered_deadline_missed = callback; - } else { - DDS_ERROR("Argument listener is NULL\n"); - } + if (listener) + listener->on_offered_deadline_missed = callback; } -void -dds_lset_offered_incompatible_qos (dds_listener_t * __restrict listener, dds_on_offered_incompatible_qos_fn callback) +void dds_lset_offered_incompatible_qos (dds_listener_t * __restrict listener, dds_on_offered_incompatible_qos_fn callback) { - if (listener) { - listener->on_offered_incompatible_qos = callback; - } else { - DDS_ERROR("Argument listener is NULL\n"); - } + if (listener) + listener->on_offered_incompatible_qos = callback; } -void -dds_lset_publication_matched (dds_listener_t * __restrict listener, dds_on_publication_matched_fn callback) +void dds_lset_publication_matched (dds_listener_t * __restrict listener, dds_on_publication_matched_fn callback) { - if (listener) { - listener->on_publication_matched = callback; - } else { - DDS_ERROR("Argument listener is NULL"); - } + if (listener) + listener->on_publication_matched = callback; } -void -dds_lset_requested_deadline_missed (dds_listener_t * __restrict listener, dds_on_requested_deadline_missed_fn callback) +void dds_lset_requested_deadline_missed (dds_listener_t * __restrict listener, dds_on_requested_deadline_missed_fn callback) { - if (listener) { - listener->on_requested_deadline_missed = callback; - } else { - DDS_ERROR("Argument listener is NULL\n"); - } + if (listener) + listener->on_requested_deadline_missed = callback; } -void -dds_lset_requested_incompatible_qos (dds_listener_t * __restrict listener, dds_on_requested_incompatible_qos_fn callback) +void dds_lset_requested_incompatible_qos (dds_listener_t * __restrict listener, dds_on_requested_incompatible_qos_fn callback) { - if (listener) { - listener->on_requested_incompatible_qos = callback; - } else { - DDS_ERROR("Argument listener is NULL\n"); - } + if (listener) + listener->on_requested_incompatible_qos = callback; } -void -dds_lset_sample_lost (dds_listener_t * __restrict listener, dds_on_sample_lost_fn callback) +void dds_lset_sample_lost (dds_listener_t * __restrict listener, dds_on_sample_lost_fn callback) { - if (listener) { - listener->on_sample_lost = callback; - } else { - DDS_ERROR("Argument listener is NULL\n"); - } + if (listener) + listener->on_sample_lost = callback; } -void -dds_lset_sample_rejected (dds_listener_t * __restrict listener, dds_on_sample_rejected_fn callback) +void dds_lset_sample_rejected (dds_listener_t * __restrict listener, dds_on_sample_rejected_fn callback) { - if (listener) { - listener->on_sample_rejected = callback; - } else { - DDS_ERROR("Argument listener is NULL\n"); - } + if (listener) + listener->on_sample_rejected = callback; } -void -dds_lset_subscription_matched (dds_listener_t * __restrict listener, dds_on_subscription_matched_fn callback) +void dds_lset_subscription_matched (dds_listener_t * __restrict listener, dds_on_subscription_matched_fn callback) { - if (listener) { - listener->on_subscription_matched = callback; - } else { - DDS_ERROR("Argument listener is NULL\n"); - } + if (listener) + listener->on_subscription_matched = callback; } /************************************************************************************************ * Getters ************************************************************************************************/ -void -dds_lget_data_available (const dds_listener_t * __restrict listener, dds_on_data_available_fn *callback) +void dds_lget_data_available (const dds_listener_t * __restrict listener, dds_on_data_available_fn *callback) { - if(!callback){ - DDS_ERROR("Argument callback is NULL\n"); - return ; - } - if (!listener) { - DDS_ERROR("Argument listener is NULL\n"); - return ; - } + if (callback && listener) *callback = listener->on_data_available; } -void -dds_lget_data_on_readers (const dds_listener_t * __restrict listener, dds_on_data_on_readers_fn *callback) +void dds_lget_data_on_readers (const dds_listener_t * __restrict listener, dds_on_data_on_readers_fn *callback) { - if(!callback){ - DDS_ERROR("Argument callback is NULL\n"); - return ; - } - if (!listener) { - DDS_ERROR("Argument listener is NULL\n"); - return ; - } + if (callback && listener) *callback = listener->on_data_on_readers; } void dds_lget_inconsistent_topic (const dds_listener_t * __restrict listener, dds_on_inconsistent_topic_fn *callback) { - if(!callback){ - DDS_ERROR("Argument callback is NULL\n"); - return ; - } - if (!listener) { - DDS_ERROR("Argument listener is NULL\n"); - return ; - } + if (callback && listener) *callback = listener->on_inconsistent_topic; } -void -dds_lget_liveliness_changed (const dds_listener_t * __restrict listener, dds_on_liveliness_changed_fn *callback) +void dds_lget_liveliness_changed (const dds_listener_t * __restrict listener, dds_on_liveliness_changed_fn *callback) { - if(!callback){ - DDS_ERROR("Argument callback is NULL\n"); - return ; - } - if (!listener) { - DDS_ERROR("Argument listener is NULL\n"); - return ; - } + if (callback && listener) *callback = listener->on_liveliness_changed; } -void -dds_lget_liveliness_lost (const dds_listener_t * __restrict listener, dds_on_liveliness_lost_fn *callback) +void dds_lget_liveliness_lost (const dds_listener_t * __restrict listener, dds_on_liveliness_lost_fn *callback) { - if(!callback){ - DDS_ERROR("Argument callback is NULL\n"); - return ; - } - if (!listener) { - DDS_ERROR("Argument listener is NULL\n"); - return ; - } + if (callback && listener) *callback = listener->on_liveliness_lost; } -void -dds_lget_offered_deadline_missed (const dds_listener_t * __restrict listener, dds_on_offered_deadline_missed_fn *callback) +void dds_lget_offered_deadline_missed (const dds_listener_t * __restrict listener, dds_on_offered_deadline_missed_fn *callback) { - if(!callback){ - DDS_ERROR("Argument callback is NULL\n"); - return ; - } - if (!listener) { - DDS_ERROR("Argument listener is NULL\n"); - return ; - } + if (callback && listener) *callback = listener->on_offered_deadline_missed; } -void -dds_lget_offered_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_offered_incompatible_qos_fn *callback) +void dds_lget_offered_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_offered_incompatible_qos_fn *callback) { - if(!callback){ - DDS_ERROR("Argument callback is NULL\n"); - return ; - } - if (!listener) { - DDS_ERROR("Argument listener is NULL\n"); - return ; - } + if (callback && listener) *callback = listener->on_offered_incompatible_qos; } -void -dds_lget_publication_matched (const dds_listener_t * __restrict listener, dds_on_publication_matched_fn *callback) +void dds_lget_publication_matched (const dds_listener_t * __restrict listener, dds_on_publication_matched_fn *callback) { - if(!callback){ - DDS_ERROR("Argument callback is NULL\n"); - return ; - } - if (!listener) { - DDS_ERROR("Argument listener is NULL\n"); - return ; - } + if (callback && listener) *callback = listener->on_publication_matched; } -void -dds_lget_requested_deadline_missed (const dds_listener_t * __restrict listener, dds_on_requested_deadline_missed_fn *callback) +void dds_lget_requested_deadline_missed (const dds_listener_t * __restrict listener, dds_on_requested_deadline_missed_fn *callback) { - if(!callback) { - DDS_ERROR("Argument callback is NULL\n"); - return ; - } - if (!listener) { - DDS_ERROR("Argument listener is NULL\n"); - return ; - } + if (callback && listener) *callback = listener->on_requested_deadline_missed; } -void -dds_lget_requested_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_requested_incompatible_qos_fn *callback) +void dds_lget_requested_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_requested_incompatible_qos_fn *callback) { - if(!callback) { - DDS_ERROR("Argument callback is NULL\n"); - return ; - } - if (!listener) { - DDS_ERROR("Argument listener is NULL\n"); - return ; - } + if (callback && listener) *callback = listener->on_requested_incompatible_qos; } -void -dds_lget_sample_lost (const dds_listener_t *__restrict listener, dds_on_sample_lost_fn *callback) +void dds_lget_sample_lost (const dds_listener_t *__restrict listener, dds_on_sample_lost_fn *callback) { - if(!callback) { - DDS_ERROR("Argument callback is NULL\n"); - return ; - } - if (!listener) { - DDS_ERROR("Argument listener is NULL\n"); - return ; - } + if (callback && listener) *callback = listener->on_sample_lost; } -void -dds_lget_sample_rejected (const dds_listener_t *__restrict listener, dds_on_sample_rejected_fn *callback) +void dds_lget_sample_rejected (const dds_listener_t *__restrict listener, dds_on_sample_rejected_fn *callback) { - if(!callback) { - DDS_ERROR("Argument callback is NULL\n"); - return ; - } - if (!listener) { - DDS_ERROR("Argument listener is NULL\n"); - return ; - } + if (callback && listener) *callback = listener->on_sample_rejected; } -void -dds_lget_subscription_matched (const dds_listener_t * __restrict listener, dds_on_subscription_matched_fn *callback) +void dds_lget_subscription_matched (const dds_listener_t * __restrict listener, dds_on_subscription_matched_fn *callback) { - if(!callback) { - DDS_ERROR("Argument callback is NULL\n"); - return ; - } - if (!listener) { - DDS_ERROR("Argument listener is NULL\n"); - return ; - } + if (callback && listener) *callback = listener->on_subscription_matched; } diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 30f1330..b1269d6 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -21,260 +21,183 @@ #include "dds__participant.h" #include "dds__builtin.h" -DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_participant) +DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_participant) -#define DDS_PARTICIPANT_STATUS_MASK 0u +#define DDS_PARTICIPANT_STATUS_MASK (0u) /* List of created participants */ +static dds_entity *dds_pp_head = NULL; -static dds_entity * dds_pp_head = NULL; - -static dds_return_t -dds_participant_status_validate( - uint32_t mask) +static dds_return_t dds_participant_status_validate (uint32_t mask) { - dds_return_t ret = DDS_RETCODE_OK; - - if (mask & ~(DDS_PARTICIPANT_STATUS_MASK)) { - ret = DDS_RETCODE_BAD_PARAMETER; - } - - return ret; + return (mask & ~DDS_PARTICIPANT_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK; } -static dds_return_t -dds_participant_delete( - dds_entity *e) +static dds_return_t dds_participant_delete (dds_entity *e) ddsrt_nonnull_all; + +static dds_return_t dds_participant_delete (dds_entity *e) { - dds_entity *prev = NULL; - dds_entity *iter; + assert (dds_entity_kind (e) == DDS_KIND_PARTICIPANT); - assert(e); - assert(dds_entity_kind(e) == DDS_KIND_PARTICIPANT); + thread_state_awake (lookup_thread_state ()); + dds_domain_free (e->m_domain); + ddsrt_mutex_lock (&dds_global.m_mutex); + dds_entity *prev, *iter; + for (iter = dds_pp_head, prev = NULL; iter; prev = iter, iter = iter->m_next) + { + if (iter == e) + break; + } + assert (iter); + if (prev) + prev->m_next = iter->m_next; + else + dds_pp_head = iter->m_next; + ddsrt_mutex_unlock (&dds_global.m_mutex); + thread_state_asleep (lookup_thread_state ()); - thread_state_awake (lookup_thread_state ()); + /* Every dds_init needs a dds_fini. */ + dds_fini (); + return DDS_RETCODE_OK; +} - dds_domain_free (e->m_domain); +static dds_return_t dds_participant_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all; +static dds_return_t dds_participant_instance_hdl (dds_entity *e, dds_instance_handle_t *i) +{ + *i = participant_instance_id (&e->m_guid); + return DDS_RETCODE_OK; +} + +static dds_return_t dds_participant_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; + +static dds_return_t dds_participant_qos_validate (const dds_qos_t *qos, bool enabled) +{ + (void)enabled; + + if ((qos->present & QP_USER_DATA) && !validate_octetseq (&qos->user_data)) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy (&qos->entity_factory)) + return DDS_RETCODE_INCONSISTENT_POLICY; + + return DDS_RETCODE_OK; +} + +static dds_return_t dds_participant_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; + +static dds_return_t dds_participant_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) +{ + dds_return_t ret; + (void)e; + if ((ret = dds_participant_qos_validate (qos, enabled)) != DDS_RETCODE_OK) + return ret; + if (enabled) /* FIXME: changing QoS */ + return DDS_RETCODE_UNSUPPORTED; + return ret; +} + +dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_t *qos, const dds_listener_t *listener) +{ + dds_entity_t ret; + nn_guid_t guid; + dds_participant * pp; + nn_plist_t plist; + dds_qos_t *new_qos = NULL; + + /* Make sure DDS instance is initialized. */ + if ((ret = dds_init (domain)) != DDS_RETCODE_OK) + goto err_dds_init; + + /* Check domain id */ + if ((ret = dds__check_domain (domain)) != DDS_RETCODE_OK) + goto err_domain_check; + + /* Validate qos or use default if NULL */ + if (qos && (ret = dds_participant_qos_validate (qos, false)) != DDS_RETCODE_OK) + goto err_qos_validation; + + new_qos = dds_create_qos (); + if (qos != NULL) + (void) dds_copy_qos (new_qos, qos); + + /* Translate qos */ + nn_plist_init_empty (&plist); + dds_merge_qos (&plist.qos, new_qos); + + thread_state_awake (lookup_thread_state ()); + ret = new_participant (&guid, 0, &plist); + thread_state_asleep (lookup_thread_state ()); + nn_plist_fini (&plist); + if (ret < 0) + { + ret = DDS_RETCODE_ERROR; + goto err_new_participant; + } + + pp = dds_alloc (sizeof (*pp)); + if ((ret = dds_entity_init (&pp->m_entity, NULL, DDS_KIND_PARTICIPANT, new_qos, listener, DDS_PARTICIPANT_STATUS_MASK)) < 0) + goto err_entity_init; + + pp->m_entity.m_guid = guid; + pp->m_entity.m_domain = dds_domain_create (dds_domain_default ()); + pp->m_entity.m_domainid = dds_domain_default (); + pp->m_entity.m_deriver.delete = dds_participant_delete; + pp->m_entity.m_deriver.set_qos = dds_participant_qos_set; + pp->m_entity.m_deriver.get_instance_hdl = dds_participant_instance_hdl; + pp->m_entity.m_deriver.validate_status = dds_participant_status_validate; + pp->m_builtin_subscriber = 0; + + /* Add participant to extent */ + ddsrt_mutex_lock (&dds_global.m_mutex); + pp->m_entity.m_next = dds_pp_head; + dds_pp_head = &pp->m_entity; + ddsrt_mutex_unlock (&dds_global.m_mutex); + return ret; + +err_entity_init: + dds_free (pp); +err_new_participant: + dds_delete_qos (new_qos); +err_qos_validation: +err_domain_check: + dds_fini (); +err_dds_init: + return ret; +} + +dds_entity_t dds_lookup_participant (dds_domainid_t domain_id, dds_entity_t *participants, size_t size) +{ + ddsrt_mutex_t *init_mutex; + + ddsrt_init (); + init_mutex = ddsrt_get_singleton_mutex (); + + if ((participants != NULL && (size <= 0 || size >= INT32_MAX)) || (participants == NULL && size != 0)) + { + ddsrt_fini (); + return DDS_RETCODE_BAD_PARAMETER; + } + + if (participants) + participants[0] = 0; + + dds_return_t ret = 0; + ddsrt_mutex_lock (init_mutex); + if (dds_global.m_init_count > 0) + { ddsrt_mutex_lock (&dds_global.m_mutex); - iter = dds_pp_head; - while (iter) { - if (iter == e) { - if (prev) { - prev->m_next = iter->m_next; - } else { - dds_pp_head = iter->m_next; - } - break; - } - prev = iter; - iter = iter->m_next; + for (dds_entity *iter = dds_pp_head; iter; iter = iter->m_next) + { + if (iter->m_domainid == domain_id) + { + if ((size_t) ret < size) + participants[ret] = iter->m_hdllink.hdl; + ret++; + } } ddsrt_mutex_unlock (&dds_global.m_mutex); - - assert (iter); - - thread_state_asleep (lookup_thread_state ()); - - /* Every dds_init needs a dds_fini. */ - dds_fini(); - - return DDS_RETCODE_OK; -} - -static dds_return_t -dds_participant_instance_hdl( - dds_entity *e, - dds_instance_handle_t *i) -{ - assert(e); - assert(i); - *i = (dds_instance_handle_t)participant_instance_id(&e->m_guid); - return DDS_RETCODE_OK; -} - -static dds_return_t -dds_participant_qos_validate( - const dds_qos_t *qos, - bool enabled) -{ - dds_return_t ret = DDS_RETCODE_OK; - assert(qos); - (void)enabled; - - /* Check consistency. */ - if ((qos->present & QP_USER_DATA) && !validate_octetseq(&qos->user_data)) { - DDS_ERROR("User data QoS policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)) { - DDS_ERROR("Prismtech entity factory QoS policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - return ret; -} - - -static dds_return_t -dds_participant_qos_set( - dds_entity *e, - const dds_qos_t *qos, - bool enabled) -{ - dds_return_t ret = dds_participant_qos_validate(qos, enabled); - (void)e; - if (ret == DDS_RETCODE_OK) { - if (enabled) { - /* TODO: CHAM-95: DDSI does not support changing QoS policies. */ - DDS_ERROR("Changing the participant QoS is not supported\n"); - ret = DDS_RETCODE_UNSUPPORTED; - } - } - return ret; -} - -dds_entity_t -dds_create_participant( - const dds_domainid_t domain, - const dds_qos_t *qos, - const dds_listener_t *listener) -{ - int q_rc; - dds_return_t ret; - dds_entity_t e; - nn_guid_t guid; - dds_participant * pp; - nn_plist_t plist; - dds_qos_t * new_qos = NULL; - - /* Make sure DDS instance is initialized. */ - ret = dds_init(domain); - if (ret != DDS_RETCODE_OK) { - e = (dds_entity_t)ret; - goto fail_dds_init; - } - - /* Check domain id */ - ret = dds__check_domain (domain); - if (ret != DDS_RETCODE_OK) { - e = (dds_entity_t)ret; - goto fail_domain_check; - } - - /* Validate qos */ - if (qos) { - ret = dds_participant_qos_validate (qos, false); - if (ret != DDS_RETCODE_OK) { - e = (dds_entity_t)ret; - goto fail_qos_validation; - } - new_qos = dds_create_qos (); - /* Only returns failure when one of the qos args is NULL, which - * is not the case here. */ - (void)dds_copy_qos(new_qos, qos); - } else { - /* Use default qos. */ - new_qos = dds_create_qos (); - } - - /* Translate qos */ - nn_plist_init_empty(&plist); - dds_merge_qos (&plist.qos, new_qos); - - thread_state_awake (lookup_thread_state ()); - q_rc = new_participant (&guid, 0, &plist); - thread_state_asleep (lookup_thread_state ()); - nn_plist_fini (&plist); - if (q_rc != 0) { - DDS_ERROR("Internal error"); - e = DDS_RETCODE_ERROR; - goto fail_new_participant; - } - - pp = dds_alloc (sizeof (*pp)); - e = dds_entity_init (&pp->m_entity, NULL, DDS_KIND_PARTICIPANT, new_qos, listener, DDS_PARTICIPANT_STATUS_MASK); - if (e < 0) { - goto fail_entity_init; - } - - pp->m_entity.m_guid = guid; - pp->m_entity.m_domain = dds_domain_create (dds_domain_default()); - pp->m_entity.m_domainid = dds_domain_default(); - pp->m_entity.m_deriver.delete = dds_participant_delete; - pp->m_entity.m_deriver.set_qos = dds_participant_qos_set; - pp->m_entity.m_deriver.get_instance_hdl = dds_participant_instance_hdl; - pp->m_entity.m_deriver.validate_status = dds_participant_status_validate; - pp->m_builtin_subscriber = 0; - - /* Add participant to extent */ - ddsrt_mutex_lock (&dds_global.m_mutex); - pp->m_entity.m_next = dds_pp_head; - dds_pp_head = &pp->m_entity; - ddsrt_mutex_unlock (&dds_global.m_mutex); - - return e; - -fail_entity_init: - dds_free(pp); -fail_new_participant: - dds_delete_qos(new_qos); -fail_qos_validation: -fail_domain_check: - dds_fini(); -fail_dds_init: - return e; -} - -dds_entity_t -dds_lookup_participant( - dds_domainid_t domain_id, - dds_entity_t *participants, - size_t size) -{ - dds_return_t ret = 0; - ddsrt_mutex_t *init_mutex; - - /* Be sure the DDS lifecycle resources are initialized. */ - ddsrt_init(); - init_mutex = ddsrt_get_singleton_mutex(); - - if ((participants != NULL) && ((size <= 0) || (size >= INT32_MAX))) { - DDS_ERROR("Array is given, but with invalid size\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - goto err; - } - if ((participants == NULL) && (size != 0)) { - DDS_ERROR("Size is given, but no array\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - goto err; - } - - if(participants){ - participants[0] = 0; - } - - ddsrt_mutex_lock (init_mutex); - - /* Check if dds is intialized. */ - if (dds_global.m_init_count > 0) { - dds_entity* iter; - ddsrt_mutex_lock (&dds_global.m_mutex); - iter = dds_pp_head; - while (iter) { - if (iter->m_domainid == domain_id) { - if ((size_t)ret < size) { - participants[ret] = iter->m_hdllink.hdl; - } - ret++; - } - iter = iter->m_next; - } - ddsrt_mutex_unlock (&dds_global.m_mutex); - } - - ddsrt_mutex_unlock (init_mutex); - -err: - ddsrt_fini(); - return ret; + } + ddsrt_mutex_unlock (init_mutex); + ddsrt_fini (); + return ret; } diff --git a/src/core/ddsc/src/dds_publisher.c b/src/core/ddsc/src/dds_publisher.c index 39ffc85..8f68e12 100644 --- a/src/core/ddsc/src/dds_publisher.c +++ b/src/core/ddsc/src/dds_publisher.c @@ -13,153 +13,102 @@ #include #include "dds/ddsrt/misc.h" #include "dds__listener.h" +#include "dds__participant.h" #include "dds__publisher.h" #include "dds__qos.h" #include "dds/ddsi/q_entity.h" #include "dds/version.h" -DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_publisher) +DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_publisher) -#define DDS_PUBLISHER_STATUS_MASK 0u +#define DDS_PUBLISHER_STATUS_MASK (0u) -static dds_return_t -dds_publisher_instance_hdl( - dds_entity *e, - dds_instance_handle_t *i) +static dds_return_t dds_publisher_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all; + +static dds_return_t dds_publisher_instance_hdl (dds_entity *e, dds_instance_handle_t *i) { - (void)e; - (void)i; - /* TODO: Get/generate proper handle. */ - DDS_ERROR("Getting publisher instance handle is not supported\n"); + /* FIXME: Get/generate proper handle. */ + (void) e; + (void) i; + return DDS_RETCODE_UNSUPPORTED; +} + +static dds_return_t dds_publisher_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; + +static dds_return_t dds_publisher_qos_validate (const dds_qos_t *qos, bool enabled) +{ + if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data)) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_PRESENTATION) && validate_presentation_qospolicy (&qos->presentation) < 0) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_PARTITION) && !validate_stringseq (&qos->partition)) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy (&qos->entity_factory)) + return DDS_RETCODE_INCONSISTENT_POLICY; + /* FIXME: Improve/check immutable check. */ + if (enabled && (qos->present & QP_PRESENTATION)) + return DDS_RETCODE_IMMUTABLE_POLICY; + return DDS_RETCODE_OK; +} + +static dds_return_t dds_publisher_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; + +static dds_return_t dds_publisher_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) +{ + dds_return_t ret; + (void)e; + if ((ret = dds_publisher_qos_validate (qos, enabled)) != DDS_RETCODE_OK) + return ret; + if (enabled) /* FIXME: QoS changes. */ return DDS_RETCODE_UNSUPPORTED; -} - -static dds_return_t -dds_publisher_qos_validate( - const dds_qos_t *qos, - bool enabled) -{ - dds_return_t ret = DDS_RETCODE_OK; - assert(qos); - - /* Check consistency. */ - if((qos->present & QP_GROUP_DATA) && !validate_octetseq(&qos->group_data)){ - DDS_ERROR("Group data policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if((qos->present & QP_PRESENTATION) && (validate_presentation_qospolicy(&qos->presentation) != 0)){ - DDS_ERROR("Presentation policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if((qos->present & QP_PARTITION) && !validate_stringseq(&qos->partition)){ - DDS_ERROR("Partition policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)){ - DDS_ERROR("Prismtech entity factory policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if(ret == DDS_RETCODE_OK && enabled && (qos->present & QP_PRESENTATION)){ - /* TODO: Improve/check immutable check. */ - DDS_ERROR("Presentation policy is immutable\n"); - ret = DDS_RETCODE_IMMUTABLE_POLICY; - } - return ret; -} - -static dds_return_t -dds_publisher_qos_set( - dds_entity *e, - const dds_qos_t *qos, - bool enabled) -{ - dds_return_t ret = dds_publisher_qos_validate(qos, enabled); - (void)e; - if (ret == DDS_RETCODE_OK) { - if (enabled) { - /* TODO: CHAM-95: DDSI does not support changing QoS policies. */ - DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies yet\n"); - ret = DDS_RETCODE_UNSUPPORTED; - } - } - return ret; + return DDS_RETCODE_OK; } static dds_return_t dds_publisher_status_validate (uint32_t mask) { - dds_return_t ret = DDS_RETCODE_OK; + return (mask & ~DDS_PUBLISHER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK; +} - if (mask & ~(DDS_PUBLISHER_STATUS_MASK)) { - DDS_ERROR("Invalid status mask\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - } +dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qos, const dds_listener_t *listener) +{ + dds_participant *par; + dds_publisher *pub; + dds_entity_t hdl; + dds_qos_t *new_qos = NULL; + dds_return_t ret; + if (qos && (ret = dds_publisher_qos_validate (qos, false)) != DDS_RETCODE_OK) return ret; + + if ((ret = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK) + return ret; + + if (qos) + { + new_qos = dds_create_qos (); + (void) dds_copy_qos (new_qos, qos); + } + + pub = dds_alloc (sizeof (*pub)); + hdl = dds_entity_init (&pub->m_entity, &par->m_entity, DDS_KIND_PUBLISHER, new_qos, listener, DDS_PUBLISHER_STATUS_MASK); + pub->m_entity.m_deriver.set_qos = dds_publisher_qos_set; + pub->m_entity.m_deriver.get_instance_hdl = dds_publisher_instance_hdl; + pub->m_entity.m_deriver.validate_status = dds_publisher_status_validate; + dds_participant_unlock (par); + return hdl; } -dds_entity_t -dds_create_publisher( - dds_entity_t participant, - const dds_qos_t *qos, - const dds_listener_t *listener) -{ - dds_entity * par; - dds_publisher * pub; - dds_entity_t hdl; - dds_qos_t * new_qos = NULL; - dds_return_t ret; - - ret = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking participant\n"); - hdl = ret; - goto lock_err; - } - - /* Validate qos */ - if (qos) { - ret = dds_publisher_qos_validate(qos, false); - if (ret != DDS_RETCODE_OK) { - hdl = ret; - goto qos_err; - } - new_qos = dds_create_qos (); - /* Only returns failure when one of the qos args is NULL, which - * is not the case here. */ - (void)dds_copy_qos(new_qos, qos); - } - - /* Create publisher */ - pub = dds_alloc (sizeof (*pub)); - hdl = dds_entity_init (&pub->m_entity, par, DDS_KIND_PUBLISHER, new_qos, listener, DDS_PUBLISHER_STATUS_MASK); - pub->m_entity.m_deriver.set_qos = dds_publisher_qos_set; - pub->m_entity.m_deriver.get_instance_hdl = dds_publisher_instance_hdl; - pub->m_entity.m_deriver.validate_status = dds_publisher_status_validate; - -qos_err: - dds_entity_unlock(par); -lock_err: - return hdl; -} - -DDS_EXPORT dds_return_t -dds_suspend( - dds_entity_t publisher) +dds_return_t dds_suspend (dds_entity_t publisher) { return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER); } -dds_return_t -dds_resume( - dds_entity_t publisher) +dds_return_t dds_resume (dds_entity_t publisher) { return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER); } -dds_return_t -dds_wait_for_acks( - dds_entity_t publisher_or_writer, - dds_duration_t timeout) +dds_return_t dds_wait_for_acks (dds_entity_t publisher_or_writer, dds_duration_t timeout) { if (timeout < 0) return DDS_RETCODE_BAD_PARAMETER; @@ -167,23 +116,12 @@ dds_wait_for_acks( return dds_generic_unimplemented_operation_manykinds (publisher_or_writer, sizeof (kinds) / sizeof (kinds[0]), kinds); } -dds_return_t -dds_publisher_begin_coherent( - dds_entity_t e) +dds_return_t dds_publisher_begin_coherent (dds_entity_t publisher) { - /* TODO: CHAM-124 Currently unsupported. */ - (void)e; - DDS_ERROR("Using coherency to get a coherent data set is not being supported yet\n"); - return DDS_RETCODE_UNSUPPORTED; + return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER); } -dds_return_t -dds_publisher_end_coherent( - dds_entity_t e) +dds_return_t dds_publisher_end_coherent (dds_entity_t publisher) { - /* TODO: CHAM-124 Currently unsupported. */ - (void)e; - DDS_ERROR("Using coherency to get a coherent data set is not being supported yet\n"); - return DDS_RETCODE_UNSUPPORTED; + return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER); } - diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index 24584be..a1771f8 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -19,544 +19,378 @@ Revisit on the conversion as default values are { 0x7fffffff, 0xffffffff } */ -static void -dds_qos_data_copy_in( - nn_octetseq_t * data, - const void * __restrict value, - size_t sz) +static void dds_qos_data_copy_in (nn_octetseq_t *data, const void * __restrict value, size_t sz) { - if (data->value) { - dds_free (data->value); - data->value = NULL; - } - data->length = (uint32_t) sz; - if (sz && value) { - data->value = dds_alloc (sz); - memcpy (data->value, value, sz); - } + if (data->value) + { + dds_free (data->value); + data->value = NULL; + } + data->length = (uint32_t) sz; + if (sz && value) + { + data->value = dds_alloc (sz); + memcpy (data->value, value, sz); + } } -static bool -dds_qos_data_copy_out( - const nn_octetseq_t * data, - void ** value, - size_t * sz) +static bool dds_qos_data_copy_out (const nn_octetseq_t *data, void **value, size_t *sz) { - assert (data->length < UINT32_MAX); - if (sz == NULL && value != NULL) { + assert (data->length < UINT32_MAX); + if (sz == NULL && value != NULL) + return false; + + if (sz) + *sz = data->length; + if (value) + { + if (data->length == 0) + *value = NULL; + else + { + assert (data->value); + *value = dds_alloc (data->length + 1); + memcpy (*value, data->value, data->length); + ((char *) (*value))[data->length] = 0; + } + } + return true; +} + +bool validate_octetseq (const nn_octetseq_t *seq) +{ + /* default value is NULL with length 0 */ + return ((seq->length == 0 && seq->value == NULL) || (seq->length > 0 && seq->length < UINT32_MAX)); +} + +bool validate_stringseq (const nn_stringseq_t *seq) +{ + if (seq->n == 0) + return (seq->strs == NULL); + else + { + for (uint32_t i = 0; i < seq->n; i++) + if (seq->strs[i] == NULL) return false; - } - if (sz) { - *sz = data->length; - } - if (value) { - if (data->length != 0) { - assert (data->value); - *value = dds_alloc (data->length + 1); - memcpy (*value, data->value, data->length); - ((char *) (*value))[data->length] = 0; - } else { - *value = NULL; - } - } return true; + } } -bool -validate_octetseq( - const nn_octetseq_t* seq) +bool validate_entityfactory_qospolicy (const nn_entity_factory_qospolicy_t *entityfactory) { - /* default value is NULL with length 0 */ - return (((seq->length == 0) && (seq->value == NULL)) || (seq->length > 0 && seq->length < UINT32_MAX)); + /* Bools must be 0 or 1, i.e., only the lsb may be set */ + return !(entityfactory->autoenable_created_entities & ~1); } -bool -validate_stringseq( - const nn_stringseq_t* seq) +bool validate_reliability_qospolicy (const nn_reliability_qospolicy_t *reliability) { - if (seq->n != 0) { - unsigned i; - for (i = 0; i < seq->n; i++) { - if (!seq->strs[i]) { - break; - } - } - return (seq->n == i); - } else { - return (seq->strs == NULL); - } + return ((reliability->kind == NN_BEST_EFFORT_RELIABILITY_QOS || reliability->kind == NN_RELIABLE_RELIABILITY_QOS) && + (validate_duration (&reliability->max_blocking_time) == 0)); } -bool -validate_entityfactory_qospolicy( - const nn_entity_factory_qospolicy_t * entityfactory) +bool validate_deadline_and_timebased_filter (const nn_duration_t deadline, const nn_duration_t minimum_separation) { - /* Bools must be 0 or 1, i.e., only the lsb may be set */ - return !(entityfactory->autoenable_created_entities & ~1); + return (validate_duration (&deadline) == DDS_RETCODE_OK && + validate_duration (&minimum_separation) == DDS_RETCODE_OK && + nn_from_ddsi_duration (minimum_separation) <= nn_from_ddsi_duration (deadline)); } -bool -validate_reliability_qospolicy( - const nn_reliability_qospolicy_t * reliability) +bool dds_qos_validate_common (const dds_qos_t *qos) { - return ( - (reliability->kind == NN_BEST_EFFORT_RELIABILITY_QOS || reliability->kind == NN_RELIABLE_RELIABILITY_QOS) && - (validate_duration(&reliability->max_blocking_time) == 0) - ); + return !(((qos->present & QP_DURABILITY) && validate_durability_qospolicy (&qos->durability) != DDS_RETCODE_OK) || + ((qos->present & QP_DEADLINE) && validate_duration (&qos->deadline.deadline) != DDS_RETCODE_OK) || + ((qos->present & QP_LATENCY_BUDGET) && validate_duration (&qos->latency_budget.duration) != DDS_RETCODE_OK) || + ((qos->present & QP_OWNERSHIP) && validate_ownership_qospolicy (&qos->ownership) != DDS_RETCODE_OK) || + ((qos->present & QP_LIVELINESS) && validate_liveliness_qospolicy (&qos->liveliness) != DDS_RETCODE_OK) || + ((qos->present & QP_RELIABILITY) && ! validate_reliability_qospolicy (&qos->reliability)) || + ((qos->present & QP_DESTINATION_ORDER) && validate_destination_order_qospolicy (&qos->destination_order) != DDS_RETCODE_OK) || + ((qos->present & QP_HISTORY) && validate_history_qospolicy (&qos->history) != DDS_RETCODE_OK) || + ((qos->present & QP_RESOURCE_LIMITS) && validate_resource_limits_qospolicy (&qos->resource_limits) != DDS_RETCODE_OK)); } -bool -validate_deadline_and_timebased_filter( - const nn_duration_t deadline, - const nn_duration_t minimum_separation) +dds_return_t dds_qos_validate_mutable_common (const dds_qos_t *qos) { - return ( - (validate_duration(&deadline) == 0) && - (validate_duration(&minimum_separation) == 0) && - (nn_from_ddsi_duration(minimum_separation) <= nn_from_ddsi_duration(deadline)) - ); + /* FIXME: Check whether immutable QoS are changed should actually incorporate change to current QoS */ + if (qos->present & QP_DEADLINE) + return DDS_RETCODE_IMMUTABLE_POLICY; + if (qos->present & QP_OWNERSHIP) + return DDS_RETCODE_IMMUTABLE_POLICY; + if (qos->present & QP_LIVELINESS) + return DDS_RETCODE_IMMUTABLE_POLICY; + if (qos->present & QP_RELIABILITY) + return DDS_RETCODE_IMMUTABLE_POLICY; + if (qos->present & QP_DESTINATION_ORDER) + return DDS_RETCODE_IMMUTABLE_POLICY; + if (qos->present & QP_HISTORY) + return DDS_RETCODE_IMMUTABLE_POLICY; + if (qos->present & QP_RESOURCE_LIMITS) + return DDS_RETCODE_IMMUTABLE_POLICY; + return DDS_RETCODE_OK; } -bool -dds_qos_validate_common ( - const dds_qos_t *qos) +static void dds_qos_init_defaults (dds_qos_t * __restrict qos) ddsrt_nonnull_all; + +static void dds_qos_init_defaults (dds_qos_t * __restrict qos) { - return !( - ((qos->present & QP_DURABILITY) && (validate_durability_qospolicy (&qos->durability) != 0)) || - ((qos->present & QP_DEADLINE) && (validate_duration (&qos->deadline.deadline) != 0)) || - ((qos->present & QP_LATENCY_BUDGET) && (validate_duration (&qos->latency_budget.duration) != 0)) || - ((qos->present & QP_OWNERSHIP) && (validate_ownership_qospolicy (&qos->ownership) != 0)) || - ((qos->present & QP_LIVELINESS) && (validate_liveliness_qospolicy (&qos->liveliness) != 0)) || - ((qos->present & QP_RELIABILITY) && ! validate_reliability_qospolicy (&qos->reliability)) || - ((qos->present & QP_DESTINATION_ORDER) && (validate_destination_order_qospolicy (&qos->destination_order) != 0)) || - ((qos->present & QP_HISTORY) && (validate_history_qospolicy (&qos->history) != 0)) || - ((qos->present & QP_RESOURCE_LIMITS) && (validate_resource_limits_qospolicy (&qos->resource_limits) != 0)) - ); + assert (qos); + memset (qos, 0, sizeof (*qos)); + qos->durability.kind = (nn_durability_kind_t) DDS_DURABILITY_VOLATILE; + qos->deadline.deadline = nn_to_ddsi_duration (DDS_INFINITY); + qos->durability_service.service_cleanup_delay = nn_to_ddsi_duration (0); + qos->durability_service.history.kind = (nn_history_kind_t) DDS_HISTORY_KEEP_LAST; + qos->durability_service.history.depth = 1; + qos->durability_service.resource_limits.max_samples = DDS_LENGTH_UNLIMITED; + qos->durability_service.resource_limits.max_instances = DDS_LENGTH_UNLIMITED; + qos->durability_service.resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED; + qos->presentation.access_scope = (nn_presentation_access_scope_kind_t) DDS_PRESENTATION_INSTANCE; + qos->latency_budget.duration = nn_to_ddsi_duration (0); + qos->ownership.kind = (nn_ownership_kind_t) DDS_OWNERSHIP_SHARED; + qos->liveliness.kind = (nn_liveliness_kind_t) DDS_LIVELINESS_AUTOMATIC; + qos->liveliness.lease_duration = nn_to_ddsi_duration (DDS_INFINITY); + qos->time_based_filter.minimum_separation = nn_to_ddsi_duration (0); + qos->reliability.kind = (nn_reliability_kind_t) DDS_RELIABILITY_BEST_EFFORT; + qos->reliability.max_blocking_time = nn_to_ddsi_duration (DDS_MSECS (100)); + qos->lifespan.duration = nn_to_ddsi_duration (DDS_INFINITY); + qos->destination_order.kind = (nn_destination_order_kind_t) DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP; + qos->history.kind = (nn_history_kind_t) DDS_HISTORY_KEEP_LAST; + qos->history.depth = 1; + qos->resource_limits.max_samples = DDS_LENGTH_UNLIMITED; + qos->resource_limits.max_instances = DDS_LENGTH_UNLIMITED; + qos->resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED; + qos->writer_data_lifecycle.autodispose_unregistered_instances = true; + qos->reader_data_lifecycle.autopurge_nowriter_samples_delay = nn_to_ddsi_duration (DDS_INFINITY); + qos->reader_data_lifecycle.autopurge_disposed_samples_delay = nn_to_ddsi_duration (DDS_INFINITY); } -dds_return_t -dds_qos_validate_mutable_common ( - const dds_qos_t *qos) +dds_qos_t *dds_create_qos (void) { - dds_return_t ret = DDS_RETCODE_OK; - - /* TODO: Check whether immutable QoS are changed should actually incorporate change to current QoS */ - if (qos->present & QP_DEADLINE) { - DDS_ERROR("Deadline QoS policy caused immutable error\n"); - ret = DDS_RETCODE_IMMUTABLE_POLICY; - } - if (qos->present & QP_OWNERSHIP) { - DDS_ERROR("Ownership QoS policy caused immutable error\n"); - ret = DDS_RETCODE_IMMUTABLE_POLICY; - } - if (qos->present & QP_LIVELINESS) { - DDS_ERROR("Liveliness QoS policy caused immutable error\n"); - ret = DDS_RETCODE_IMMUTABLE_POLICY; - } - if (qos->present & QP_RELIABILITY) { - DDS_ERROR("Reliability QoS policy caused immutable error\n"); - ret = DDS_RETCODE_IMMUTABLE_POLICY; - } - if (qos->present & QP_DESTINATION_ORDER) { - DDS_ERROR("Destination order QoS policy caused immutable error\n"); - ret = DDS_RETCODE_IMMUTABLE_POLICY; - } - if (qos->present & QP_HISTORY) { - DDS_ERROR("History QoS policy caused immutable error\n"); - ret = DDS_RETCODE_IMMUTABLE_POLICY; - } - if (qos->present & QP_RESOURCE_LIMITS) { - DDS_ERROR("Resource limits QoS policy caused immutable error\n"); - ret = DDS_RETCODE_IMMUTABLE_POLICY; - } - - return ret; + dds_qos_t *qos = dds_alloc (sizeof (dds_qos_t)); + dds_qos_init_defaults (qos); + return qos; } -static void -dds_qos_init_defaults ( - dds_qos_t * __restrict qos) +dds_qos_t *dds_qos_create (void) { - assert (qos); - memset (qos, 0, sizeof (*qos)); - qos->durability.kind = (nn_durability_kind_t) DDS_DURABILITY_VOLATILE; - qos->deadline.deadline = nn_to_ddsi_duration (DDS_INFINITY); - qos->durability_service.service_cleanup_delay = nn_to_ddsi_duration (0); - qos->durability_service.history.kind = (nn_history_kind_t) DDS_HISTORY_KEEP_LAST; - qos->durability_service.history.depth = 1; - qos->durability_service.resource_limits.max_samples = DDS_LENGTH_UNLIMITED; - qos->durability_service.resource_limits.max_instances = DDS_LENGTH_UNLIMITED; - qos->durability_service.resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED; - qos->presentation.access_scope = (nn_presentation_access_scope_kind_t) DDS_PRESENTATION_INSTANCE; - qos->latency_budget.duration = nn_to_ddsi_duration (0); - qos->ownership.kind = (nn_ownership_kind_t) DDS_OWNERSHIP_SHARED; - qos->liveliness.kind = (nn_liveliness_kind_t) DDS_LIVELINESS_AUTOMATIC; - qos->liveliness.lease_duration = nn_to_ddsi_duration (DDS_INFINITY); - qos->time_based_filter.minimum_separation = nn_to_ddsi_duration (0); - qos->reliability.kind = (nn_reliability_kind_t) DDS_RELIABILITY_BEST_EFFORT; - qos->reliability.max_blocking_time = nn_to_ddsi_duration (DDS_MSECS (100)); - qos->lifespan.duration = nn_to_ddsi_duration (DDS_INFINITY); - qos->destination_order.kind = (nn_destination_order_kind_t) DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP; - qos->history.kind = (nn_history_kind_t) DDS_HISTORY_KEEP_LAST; - qos->history.depth = 1; - qos->resource_limits.max_samples = DDS_LENGTH_UNLIMITED; - qos->resource_limits.max_instances = DDS_LENGTH_UNLIMITED; - qos->resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED; - qos->writer_data_lifecycle.autodispose_unregistered_instances = true; - qos->reader_data_lifecycle.autopurge_nowriter_samples_delay = nn_to_ddsi_duration (DDS_INFINITY); - qos->reader_data_lifecycle.autopurge_disposed_samples_delay = nn_to_ddsi_duration (DDS_INFINITY); + return dds_create_qos (); } -dds_qos_t * dds_create_qos (void) +void dds_reset_qos (dds_qos_t * __restrict qos) { - dds_qos_t *qos = dds_alloc (sizeof (dds_qos_t)); + if (qos) + { + nn_xqos_fini (qos); dds_qos_init_defaults (qos); - return qos; + } } -dds_qos_t * dds_qos_create (void) +void dds_qos_reset (dds_qos_t * __restrict qos) { - return dds_create_qos (); + dds_reset_qos (qos); } -void -dds_reset_qos( - dds_qos_t * __restrict qos) +void dds_delete_qos (dds_qos_t * __restrict qos) { - if (qos) { - nn_xqos_fini (qos); - dds_qos_init_defaults (qos); - } else { - DDS_WARNING("Argument QoS is NULL\n"); - } + if (qos) + { + dds_reset_qos(qos); + dds_free(qos); + } } -void -dds_qos_reset( - dds_qos_t * __restrict qos) +void dds_qos_delete (dds_qos_t * __restrict qos) { - dds_reset_qos (qos); + dds_delete_qos (qos); } -void -dds_delete_qos( - dds_qos_t * __restrict qos) +dds_return_t dds_copy_qos (dds_qos_t * __restrict dst, const dds_qos_t * __restrict src) { - if (qos) { - dds_reset_qos(qos); - dds_free(qos); - } + if (src == NULL || dst == NULL) + return DDS_RETCODE_BAD_PARAMETER; + nn_xqos_copy (dst, src); + return DDS_RETCODE_OK; } -void -dds_qos_delete( - dds_qos_t * __restrict qos) +dds_return_t dds_qos_copy (dds_qos_t * __restrict dst, const dds_qos_t * __restrict src) { - dds_delete_qos (qos); + return dds_copy_qos (dst, src); } -dds_return_t -dds_copy_qos ( - dds_qos_t * __restrict dst, - const dds_qos_t * __restrict src) +void dds_merge_qos (dds_qos_t * __restrict dst, const dds_qos_t * __restrict src) { - if(!src){ - DDS_ERROR("Argument source(src) is NULL\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - if(!dst){ - DDS_ERROR("Argument destination(dst) is NULL\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - nn_xqos_copy (dst, src); - return DDS_RETCODE_OK; -} - -dds_return_t -dds_qos_copy ( - dds_qos_t * __restrict dst, - const dds_qos_t * __restrict src) -{ - return dds_copy_qos (dst, src); -} - -void dds_merge_qos ( - dds_qos_t * __restrict dst, - const dds_qos_t * __restrict src) -{ - if(!src){ - DDS_ERROR("Argument source(src) is NULL\n"); - return; - } - if(!dst){ - DDS_ERROR("Argument destination(dst) is NULL\n"); - return; - } - /* Copy qos from source to destination unless already set */ + /* Copy qos from source to destination unless already set */ + if (src != NULL && dst != NULL) nn_xqos_mergein_missing (dst, src); } -void dds_qos_merge ( - dds_qos_t * __restrict dst, - const dds_qos_t * __restrict src) +void dds_qos_merge (dds_qos_t * __restrict dst, const dds_qos_t * __restrict src) { - dds_merge_qos (dst, src); + dds_merge_qos (dst, src); } -bool dds_qos_equal ( - const dds_qos_t * __restrict a, - const dds_qos_t * __restrict b) +bool dds_qos_equal (const dds_qos_t * __restrict a, const dds_qos_t * __restrict b) { - /* FIXME: a bit of a hack - and I am not so sure I like accepting null pointers here anyway */ - if (a == NULL && b == NULL) { - return true; - } else if (a == NULL || b == NULL) { - return false; - } else { - return nn_xqos_delta(a, b, ~(uint64_t)0) == 0; - } + /* FIXME: a bit of a hack - and I am not so sure I like accepting null pointers here anyway */ + if (a == NULL && b == NULL) + return true; + else if (a == NULL || b == NULL) + return false; + else + return nn_xqos_delta (a, b, ~(uint64_t)0) == 0; } -void dds_qset_userdata( - dds_qos_t * __restrict qos, - const void * __restrict value, - size_t sz) +void dds_qset_userdata (dds_qos_t * __restrict qos, const void * __restrict value, size_t sz) { - if (!qos) { - DDS_ERROR("Argument qos is NULL\n"); - return ; - } - dds_qos_data_copy_in(&qos->user_data, value, sz); + if (qos != NULL) + { + dds_qos_data_copy_in (&qos->user_data, value, sz); qos->present |= QP_USER_DATA; + } } -void dds_qset_topicdata( - dds_qos_t * __restrict qos, - const void * __restrict value, - size_t sz) +void dds_qset_topicdata (dds_qos_t * __restrict qos, const void * __restrict value, size_t sz) { - if (!qos) { - DDS_ERROR("Argument qos is NULL\n"); - return ; - } + if (qos != NULL) + { dds_qos_data_copy_in (&qos->topic_data, value, sz); qos->present |= QP_TOPIC_DATA; + } } -void dds_qset_groupdata( - dds_qos_t * __restrict qos, - const void * __restrict value, - size_t sz) +void dds_qset_groupdata (dds_qos_t * __restrict qos, const void * __restrict value, size_t sz) { - if (!qos) { - DDS_ERROR("Argument qos is NULL\n"); - return ; - } + if (qos != NULL) + { dds_qos_data_copy_in (&qos->group_data, value, sz); qos->present |= QP_GROUP_DATA; + } } -void dds_qset_durability -( - dds_qos_t * __restrict qos, - dds_durability_kind_t kind -) +void dds_qset_durability (dds_qos_t * __restrict qos, dds_durability_kind_t kind) { - if (qos) { - qos->durability.kind = (nn_durability_kind_t) kind; - qos->present |= QP_DURABILITY; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->durability.kind = (nn_durability_kind_t) kind; + qos->present |= QP_DURABILITY; + } } -void dds_qset_history -( - dds_qos_t * __restrict qos, - dds_history_kind_t kind, - int32_t depth -) +void dds_qset_history (dds_qos_t * __restrict qos, dds_history_kind_t kind, int32_t depth) { - if (qos) { - qos->history.kind = (nn_history_kind_t) kind; - qos->history.depth = depth; - qos->present |= QP_HISTORY; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->history.kind = (nn_history_kind_t) kind; + qos->history.depth = depth; + qos->present |= QP_HISTORY; + } } -void dds_qset_resource_limits -( - dds_qos_t * __restrict qos, - int32_t max_samples, - int32_t max_instances, - int32_t max_samples_per_instance -) +void dds_qset_resource_limits (dds_qos_t * __restrict qos, int32_t max_samples, int32_t max_instances, int32_t max_samples_per_instance) { - if (qos) { - qos->resource_limits.max_samples = max_samples; - qos->resource_limits.max_instances = max_instances; - qos->resource_limits.max_samples_per_instance = max_samples_per_instance; - qos->present |= QP_RESOURCE_LIMITS; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->resource_limits.max_samples = max_samples; + qos->resource_limits.max_instances = max_instances; + qos->resource_limits.max_samples_per_instance = max_samples_per_instance; + qos->present |= QP_RESOURCE_LIMITS; + } } -void dds_qset_presentation -( - dds_qos_t * __restrict qos, - dds_presentation_access_scope_kind_t access_scope, - bool coherent_access, - bool ordered_access -) +void dds_qset_presentation (dds_qos_t * __restrict qos, dds_presentation_access_scope_kind_t access_scope, bool coherent_access, bool ordered_access) { - if (qos) { - qos->presentation.access_scope = (nn_presentation_access_scope_kind_t) access_scope; - qos->presentation.coherent_access = coherent_access; - qos->presentation.ordered_access = ordered_access; - qos->present |= QP_PRESENTATION; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->presentation.access_scope = (nn_presentation_access_scope_kind_t) access_scope; + qos->presentation.coherent_access = coherent_access; + qos->presentation.ordered_access = ordered_access; + qos->present |= QP_PRESENTATION; + } } -void dds_qset_lifespan -( - dds_qos_t * __restrict qos, - dds_duration_t lifespan -) +void dds_qset_lifespan (dds_qos_t * __restrict qos, dds_duration_t lifespan) { - if (qos) { - qos->lifespan.duration = nn_to_ddsi_duration (lifespan); - qos->present |= QP_LIFESPAN; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->lifespan.duration = nn_to_ddsi_duration (lifespan); + qos->present |= QP_LIFESPAN; + } } -void dds_qset_deadline -( - dds_qos_t * __restrict qos, - dds_duration_t deadline -) +void dds_qset_deadline (dds_qos_t * __restrict qos, dds_duration_t deadline) { - if (qos) { - qos->deadline.deadline = nn_to_ddsi_duration (deadline); - qos->present |= QP_DEADLINE; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->deadline.deadline = nn_to_ddsi_duration (deadline); + qos->present |= QP_DEADLINE; + } } -void dds_qset_latency_budget -( - dds_qos_t * __restrict qos, - dds_duration_t duration -) +void dds_qset_latency_budget (dds_qos_t * __restrict qos, dds_duration_t duration) { - if (qos) { - qos->latency_budget.duration = nn_to_ddsi_duration (duration); - qos->present |= QP_LATENCY_BUDGET; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->latency_budget.duration = nn_to_ddsi_duration (duration); + qos->present |= QP_LATENCY_BUDGET; + } } -void dds_qset_ownership -( - dds_qos_t * __restrict qos, - dds_ownership_kind_t kind -) +void dds_qset_ownership (dds_qos_t * __restrict qos, dds_ownership_kind_t kind) { - if (qos) { - qos->ownership.kind = (nn_ownership_kind_t) kind; - qos->present |= QP_OWNERSHIP; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->ownership.kind = (nn_ownership_kind_t) kind; + qos->present |= QP_OWNERSHIP; + } } -void dds_qset_ownership_strength -( - dds_qos_t * __restrict qos, - int32_t value -) +void dds_qset_ownership_strength (dds_qos_t * __restrict qos, int32_t value) { - if (qos) { - qos->ownership_strength.value = value; - qos->present |= QP_OWNERSHIP_STRENGTH; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->ownership_strength.value = value; + qos->present |= QP_OWNERSHIP_STRENGTH; + } } -void dds_qset_liveliness -( - dds_qos_t * __restrict qos, - dds_liveliness_kind_t kind, - dds_duration_t lease_duration -) +void dds_qset_liveliness (dds_qos_t * __restrict qos, dds_liveliness_kind_t kind, dds_duration_t lease_duration) { - if (qos) { - qos->liveliness.kind = (nn_liveliness_kind_t) kind; - qos->liveliness.lease_duration = nn_to_ddsi_duration (lease_duration); - qos->present |= QP_LIVELINESS; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->liveliness.kind = (nn_liveliness_kind_t) kind; + qos->liveliness.lease_duration = nn_to_ddsi_duration (lease_duration); + qos->present |= QP_LIVELINESS; + } } -void dds_qset_time_based_filter -( - dds_qos_t * __restrict qos, - dds_duration_t minimum_separation -) +void dds_qset_time_based_filter (dds_qos_t * __restrict qos, dds_duration_t minimum_separation) { - if (qos) { - qos->time_based_filter.minimum_separation = nn_to_ddsi_duration (minimum_separation); - qos->present |= QP_TIME_BASED_FILTER; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->time_based_filter.minimum_separation = nn_to_ddsi_duration (minimum_separation); + qos->present |= QP_TIME_BASED_FILTER; + } } -void dds_qset_partition -( - dds_qos_t * __restrict qos, - uint32_t n, - const char ** __restrict ps -) +void dds_qset_partition (dds_qos_t * __restrict qos, uint32_t n, const char ** __restrict ps) { - uint32_t i; + if (qos == NULL || (n && ps == NULL)) + return; - if(!qos) { - DDS_ERROR("Argument qos may not be NULL\n"); - return ; - } - if(n && !ps) { - DDS_ERROR("Argument ps is NULL, but n (%"PRIu32") > 0", n); - return ; - } + if (qos->partition.strs != NULL) + { + for (uint32_t i = 0; i < qos->partition.n; i++) + dds_free (qos->partition.strs[i]); + dds_free (qos->partition.strs); + qos->partition.strs = NULL; + } - if (qos->partition.strs != NULL){ - for (i = 0; i < qos->partition.n; i++) { - dds_free(qos->partition.strs[i]); - } - dds_free(qos->partition.strs); - qos->partition.strs = NULL; - } - - qos->partition.n = n; - if(n){ - qos->partition.strs = dds_alloc (sizeof (char*) * n); - } - - for (i = 0; i < n; i++) { - qos->partition.strs[i] = dds_string_dup (ps[i]); - } - qos->present |= QP_PARTITION; + qos->partition.n = n; + if (n > 0) + { + qos->partition.strs = dds_alloc (sizeof (char*) * n); + for (uint32_t i = 0; i < n; i++) + qos->partition.strs[i] = dds_string_dup (ps[i]); + } + qos->present |= QP_PARTITION; } void dds_qset_partition1 (dds_qos_t * __restrict qos, const char * __restrict name) @@ -567,397 +401,303 @@ void dds_qset_partition1 (dds_qos_t * __restrict qos, const char * __restrict na dds_qset_partition (qos, 1, (const char **) &name); } -void dds_qset_reliability -( - dds_qos_t * __restrict qos, - dds_reliability_kind_t kind, - dds_duration_t max_blocking_time -) +void dds_qset_reliability (dds_qos_t * __restrict qos, dds_reliability_kind_t kind, dds_duration_t max_blocking_time) { - if (qos) { - qos->reliability.kind = (nn_reliability_kind_t) kind; - qos->reliability.max_blocking_time = nn_to_ddsi_duration (max_blocking_time); - qos->present |= QP_RELIABILITY; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->reliability.kind = (nn_reliability_kind_t) kind; + qos->reliability.max_blocking_time = nn_to_ddsi_duration (max_blocking_time); + qos->present |= QP_RELIABILITY; + } } -void dds_qset_transport_priority -( - dds_qos_t * __restrict qos, - int32_t value -) +void dds_qset_transport_priority (dds_qos_t * __restrict qos, int32_t value) { - if (qos) { - qos->transport_priority.value = value; - qos->present |= QP_TRANSPORT_PRIORITY; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->transport_priority.value = value; + qos->present |= QP_TRANSPORT_PRIORITY; + } } -void dds_qset_destination_order -( - dds_qos_t * __restrict qos, - dds_destination_order_kind_t kind -) +void dds_qset_destination_order (dds_qos_t * __restrict qos, dds_destination_order_kind_t kind) { - if (qos) { - qos->destination_order.kind = (nn_destination_order_kind_t) kind; - qos->present |= QP_DESTINATION_ORDER; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->destination_order.kind = (nn_destination_order_kind_t) kind; + qos->present |= QP_DESTINATION_ORDER; + } } -void dds_qset_writer_data_lifecycle -( - dds_qos_t * __restrict qos, - bool autodispose -) +void dds_qset_writer_data_lifecycle (dds_qos_t * __restrict qos, bool autodispose) { - if(qos) { - qos->writer_data_lifecycle.autodispose_unregistered_instances = autodispose; - qos->present |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->writer_data_lifecycle.autodispose_unregistered_instances = autodispose; + qos->present |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE; + } } -void dds_qset_reader_data_lifecycle -( - dds_qos_t * __restrict qos, - dds_duration_t autopurge_nowriter_samples_delay, - dds_duration_t autopurge_disposed_samples_delay -) +void dds_qset_reader_data_lifecycle (dds_qos_t * __restrict qos, dds_duration_t autopurge_nowriter_samples_delay, dds_duration_t autopurge_disposed_samples_delay) { - if (qos) { - qos->reader_data_lifecycle.autopurge_nowriter_samples_delay = \ - nn_to_ddsi_duration (autopurge_nowriter_samples_delay); - qos->reader_data_lifecycle.autopurge_disposed_samples_delay = \ - nn_to_ddsi_duration (autopurge_disposed_samples_delay); - qos->present |= QP_PRISMTECH_READER_DATA_LIFECYCLE; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->reader_data_lifecycle.autopurge_nowriter_samples_delay = nn_to_ddsi_duration (autopurge_nowriter_samples_delay); + qos->reader_data_lifecycle.autopurge_disposed_samples_delay = nn_to_ddsi_duration (autopurge_disposed_samples_delay); + qos->present |= QP_PRISMTECH_READER_DATA_LIFECYCLE; + } } -void dds_qset_durability_service -( - dds_qos_t * __restrict qos, - dds_duration_t service_cleanup_delay, - dds_history_kind_t history_kind, - int32_t history_depth, - int32_t max_samples, - int32_t max_instances, - int32_t max_samples_per_instance -) +void dds_qset_durability_service (dds_qos_t * __restrict qos, dds_duration_t service_cleanup_delay, dds_history_kind_t history_kind, int32_t history_depth, int32_t max_samples, int32_t max_instances, int32_t max_samples_per_instance) { - if (qos) { - qos->durability_service.service_cleanup_delay = nn_to_ddsi_duration (service_cleanup_delay); - qos->durability_service.history.kind = (nn_history_kind_t) history_kind; - qos->durability_service.history.depth = history_depth; - qos->durability_service.resource_limits.max_samples = max_samples; - qos->durability_service.resource_limits.max_instances = max_instances; - qos->durability_service.resource_limits.max_samples_per_instance = max_samples_per_instance; - qos->present |= QP_DURABILITY_SERVICE; - } else { - DDS_ERROR("Argument QoS is NULL\n"); - } + if (qos != NULL) + { + qos->durability_service.service_cleanup_delay = nn_to_ddsi_duration (service_cleanup_delay); + qos->durability_service.history.kind = (nn_history_kind_t) history_kind; + qos->durability_service.history.depth = history_depth; + qos->durability_service.resource_limits.max_samples = max_samples; + qos->durability_service.resource_limits.max_instances = max_instances; + qos->durability_service.resource_limits.max_samples_per_instance = max_samples_per_instance; + qos->present |= QP_DURABILITY_SERVICE; + } } void dds_qset_ignorelocal (dds_qos_t * __restrict qos, dds_ignorelocal_kind_t ignore) { - if (qos) { + if (qos != NULL) + { qos->ignorelocal.value = (nn_ignorelocal_kind_t) ignore; qos->present |= QP_CYCLONE_IGNORELOCAL; - } else { - DDS_ERROR("Argument QoS is NULL\n"); } } bool dds_qget_userdata (const dds_qos_t * __restrict qos, void **value, size_t *sz) { - if (!qos || !(qos->present & QP_USER_DATA)) { - return false; - } - return dds_qos_data_copy_out (&qos->user_data, value, sz); + if (qos == NULL || !(qos->present & QP_USER_DATA)) + return false; + return dds_qos_data_copy_out (&qos->user_data, value, sz); } bool dds_qget_topicdata (const dds_qos_t * __restrict qos, void **value, size_t *sz) { - if (!qos || !(qos->present & QP_TOPIC_DATA)) { - return false; - } - return dds_qos_data_copy_out (&qos->topic_data, value, sz); + if (qos == NULL || !(qos->present & QP_TOPIC_DATA)) + return false; + return dds_qos_data_copy_out (&qos->topic_data, value, sz); } bool dds_qget_groupdata (const dds_qos_t * __restrict qos, void **value, size_t *sz) { - if (!qos || !(qos->present & QP_GROUP_DATA)) { - return false; - } - return dds_qos_data_copy_out (&qos->group_data, value, sz); + if (qos == NULL || !(qos->present & QP_GROUP_DATA)) + return false; + return dds_qos_data_copy_out (&qos->group_data, value, sz); } bool dds_qget_durability (const dds_qos_t * __restrict qos, dds_durability_kind_t *kind) { - if (!qos || !(qos->present & QP_DURABILITY)) { - return false; - } - if (kind) { - *kind = (dds_durability_kind_t) qos->durability.kind; - } - return true; + if (qos == NULL || !(qos->present & QP_DURABILITY)) + return false; + if (kind) + *kind = (dds_durability_kind_t) qos->durability.kind; + return true; } bool dds_qget_history (const dds_qos_t * __restrict qos, dds_history_kind_t *kind, int32_t *depth) { - if (!qos || !(qos->present & QP_HISTORY)) { - return false; - } - if (kind) { - *kind = (dds_history_kind_t) qos->history.kind; - } - if (depth) { - *depth = qos->history.depth; - } - return true; + if (qos == NULL || !(qos->present & QP_HISTORY)) + return false; + if (kind) + *kind = (dds_history_kind_t) qos->history.kind; + if (depth) + *depth = qos->history.depth; + return true; } bool dds_qget_resource_limits (const dds_qos_t * __restrict qos, int32_t *max_samples, int32_t *max_instances, int32_t *max_samples_per_instance) { - if (!qos || !(qos->present & QP_RESOURCE_LIMITS)) { - return false; - } - if (max_samples) { - *max_samples = qos->resource_limits.max_samples; - } - if (max_instances) { - *max_instances = qos->resource_limits.max_instances; - } - if (max_samples_per_instance) { - *max_samples_per_instance = qos->resource_limits.max_samples_per_instance; - } - return true; + if (qos == NULL || !(qos->present & QP_RESOURCE_LIMITS)) + return false; + if (max_samples) + *max_samples = qos->resource_limits.max_samples; + if (max_instances) + *max_instances = qos->resource_limits.max_instances; + if (max_samples_per_instance) + *max_samples_per_instance = qos->resource_limits.max_samples_per_instance; + return true; } bool dds_qget_presentation (const dds_qos_t * __restrict qos, dds_presentation_access_scope_kind_t *access_scope, bool *coherent_access, bool *ordered_access) { - if (!qos || !(qos->present & QP_PRESENTATION)) { - return false; - } - if (access_scope) { - *access_scope = (dds_presentation_access_scope_kind_t) qos->presentation.access_scope; - } - if (coherent_access) { - *coherent_access = qos->presentation.coherent_access; - } - if (ordered_access) { - *ordered_access = qos->presentation.ordered_access; - } - return true; + if (qos == NULL || !(qos->present & QP_PRESENTATION)) + return false; + if (access_scope) + *access_scope = (dds_presentation_access_scope_kind_t) qos->presentation.access_scope; + if (coherent_access) + *coherent_access = qos->presentation.coherent_access; + if (ordered_access) + *ordered_access = qos->presentation.ordered_access; + return true; } bool dds_qget_lifespan (const dds_qos_t * __restrict qos, dds_duration_t *lifespan) { - if (!qos || !(qos->present & QP_LIFESPAN)) { - return false; - } - if (lifespan) { - *lifespan = nn_from_ddsi_duration (qos->lifespan.duration); - } - return true; + if (qos == NULL || !(qos->present & QP_LIFESPAN)) + return false; + if (lifespan) + *lifespan = nn_from_ddsi_duration (qos->lifespan.duration); + return true; } bool dds_qget_deadline (const dds_qos_t * __restrict qos, dds_duration_t *deadline) { - if (!qos || !(qos->present & QP_DEADLINE)) { - return false; - } - if (deadline) { - *deadline = nn_from_ddsi_duration (qos->deadline.deadline); - } - return true; + if (qos == NULL || !(qos->present & QP_DEADLINE)) + return false; + if (deadline) + *deadline = nn_from_ddsi_duration (qos->deadline.deadline); + return true; } bool dds_qget_latency_budget (const dds_qos_t * __restrict qos, dds_duration_t *duration) { - if (!qos || !(qos->present & QP_LATENCY_BUDGET)) { - return false; - } - if (duration) { - *duration = nn_from_ddsi_duration (qos->latency_budget.duration); - } - return true; + if (qos == NULL || !(qos->present & QP_LATENCY_BUDGET)) + return false; + if (duration) + *duration = nn_from_ddsi_duration (qos->latency_budget.duration); + return true; } bool dds_qget_ownership (const dds_qos_t * __restrict qos, dds_ownership_kind_t *kind) { - if (!qos || !(qos->present & QP_OWNERSHIP)) { - return false; - } - if (kind) { - *kind = (dds_ownership_kind_t) qos->ownership.kind; - } - return true; + if (qos == NULL || !(qos->present & QP_OWNERSHIP)) + return false; + if (kind) + *kind = (dds_ownership_kind_t) qos->ownership.kind; + return true; } bool dds_qget_ownership_strength (const dds_qos_t * __restrict qos, int32_t *value) { - if (!qos || !(qos->present & QP_OWNERSHIP_STRENGTH)) { - return false; - } - if (value) { - *value = qos->ownership_strength.value; - } - return true; + if (qos == NULL || !(qos->present & QP_OWNERSHIP_STRENGTH)) + return false; + if (value) + *value = qos->ownership_strength.value; + return true; } bool dds_qget_liveliness (const dds_qos_t * __restrict qos, dds_liveliness_kind_t *kind, dds_duration_t *lease_duration) { - if (!qos || !(qos->present & QP_LIVELINESS)) { - return false; - } - if (kind) { - *kind = (dds_liveliness_kind_t) qos->liveliness.kind; - } - if (lease_duration) { - *lease_duration = nn_from_ddsi_duration (qos->liveliness.lease_duration); - } - return true; + if (qos == NULL || !(qos->present & QP_LIVELINESS)) + return false; + if (kind) + *kind = (dds_liveliness_kind_t) qos->liveliness.kind; + if (lease_duration) + *lease_duration = nn_from_ddsi_duration (qos->liveliness.lease_duration); + return true; } bool dds_qget_time_based_filter (const dds_qos_t * __restrict qos, dds_duration_t *minimum_separation) { - if (!qos || !(qos->present & QP_TIME_BASED_FILTER)) { - return false; - } - if (minimum_separation) { - *minimum_separation = nn_from_ddsi_duration (qos->time_based_filter.minimum_separation); - } - return true; + if (qos == NULL || !(qos->present & QP_TIME_BASED_FILTER)) + return false; + if (minimum_separation) + *minimum_separation = nn_from_ddsi_duration (qos->time_based_filter.minimum_separation); + return true; } bool dds_qget_partition (const dds_qos_t * __restrict qos, uint32_t *n, char ***ps) { - if (!qos || !(qos->present & QP_PARTITION)) { - return false; + if (qos == NULL || !(qos->present & QP_PARTITION)) + return false; + if (n == NULL && ps != NULL) + return false; + if (n) + *n = qos->partition.n; + if (ps) + { + if (qos->partition.n == 0) + *ps = NULL; + else + { + *ps = dds_alloc (sizeof (char*) * qos->partition.n); + for (uint32_t i = 0; i < qos->partition.n; i++) + (*ps)[i] = dds_string_dup (qos->partition.strs[i]); } - if (n == NULL && ps != NULL) { - return false; - } - if (n) { - *n = qos->partition.n; - } - if (ps) { - if (qos->partition.n != 0) { - *ps = dds_alloc(sizeof(char*) * qos->partition.n); - for (uint32_t i = 0; i < qos->partition.n; i++) { - (*ps)[i] = dds_string_dup(qos->partition.strs[i]); - } - } else { - *ps = NULL; - } - } - return true; + } + return true; } bool dds_qget_reliability (const dds_qos_t * __restrict qos, dds_reliability_kind_t *kind, dds_duration_t *max_blocking_time) { - if (!qos || !(qos->present & QP_RELIABILITY)) { - return false; - } - if (kind) { - *kind = (dds_reliability_kind_t) qos->reliability.kind; - } - if (max_blocking_time) { - *max_blocking_time = nn_from_ddsi_duration (qos->reliability.max_blocking_time); - } - return true; + if (qos == NULL || !(qos->present & QP_RELIABILITY)) + return false; + if (kind) + *kind = (dds_reliability_kind_t) qos->reliability.kind; + if (max_blocking_time) + *max_blocking_time = nn_from_ddsi_duration (qos->reliability.max_blocking_time); + return true; } bool dds_qget_transport_priority (const dds_qos_t * __restrict qos, int32_t *value) { - if (!qos || !(qos->present & QP_TRANSPORT_PRIORITY)) { - return false; - } - if (value) { - *value = qos->transport_priority.value; - } - return true; + if (qos == NULL || !(qos->present & QP_TRANSPORT_PRIORITY)) + return false; + if (value) + *value = qos->transport_priority.value; + return true; } bool dds_qget_destination_order (const dds_qos_t * __restrict qos, dds_destination_order_kind_t *kind) { - if (!qos || !(qos->present & QP_DESTINATION_ORDER)) { - return false; - } - if (kind) { - *kind = (dds_destination_order_kind_t) qos->destination_order.kind; - } - return true; + if (qos == NULL || !(qos->present & QP_DESTINATION_ORDER)) + return false; + if (kind) + *kind = (dds_destination_order_kind_t) qos->destination_order.kind; + return true; } bool dds_qget_writer_data_lifecycle (const dds_qos_t * __restrict qos, bool *autodispose) { - if (!qos || !(qos->present & QP_PRISMTECH_WRITER_DATA_LIFECYCLE)) { - return false; - } - if (autodispose) { - *autodispose = qos->writer_data_lifecycle.autodispose_unregistered_instances; - } - return true; + if (qos == NULL || !(qos->present & QP_PRISMTECH_WRITER_DATA_LIFECYCLE)) + return false; + if (autodispose) + *autodispose = qos->writer_data_lifecycle.autodispose_unregistered_instances; + return true; } bool dds_qget_reader_data_lifecycle (const dds_qos_t * __restrict qos, dds_duration_t *autopurge_nowriter_samples_delay, dds_duration_t *autopurge_disposed_samples_delay) { - if (!qos || !(qos->present & QP_PRISMTECH_READER_DATA_LIFECYCLE)) { - return false; - } - if (autopurge_nowriter_samples_delay) { - *autopurge_nowriter_samples_delay = nn_from_ddsi_duration (qos->reader_data_lifecycle.autopurge_nowriter_samples_delay); - } - if (autopurge_disposed_samples_delay) { - *autopurge_disposed_samples_delay = nn_from_ddsi_duration (qos->reader_data_lifecycle.autopurge_disposed_samples_delay); - } - return true; + if (qos == NULL || !(qos->present & QP_PRISMTECH_READER_DATA_LIFECYCLE)) + return false; + if (autopurge_nowriter_samples_delay) + *autopurge_nowriter_samples_delay = nn_from_ddsi_duration (qos->reader_data_lifecycle.autopurge_nowriter_samples_delay); + if (autopurge_disposed_samples_delay) + *autopurge_disposed_samples_delay = nn_from_ddsi_duration (qos->reader_data_lifecycle.autopurge_disposed_samples_delay); + return true; } bool dds_qget_durability_service (const dds_qos_t * __restrict qos, dds_duration_t *service_cleanup_delay, dds_history_kind_t *history_kind, int32_t *history_depth, int32_t *max_samples, int32_t *max_instances, int32_t *max_samples_per_instance) { - if (!qos || !(qos->present & QP_DURABILITY_SERVICE)) { - return false; - } - if (service_cleanup_delay) { - *service_cleanup_delay = nn_from_ddsi_duration (qos->durability_service.service_cleanup_delay); - } - if (history_kind) { - *history_kind = (dds_history_kind_t) qos->durability_service.history.kind; - } - if (history_depth) { - *history_depth = qos->durability_service.history.depth; - } - if (max_samples) { - *max_samples = qos->durability_service.resource_limits.max_samples; - } - if (max_instances) { - *max_instances = qos->durability_service.resource_limits.max_instances; - } - if (max_samples_per_instance) { - *max_samples_per_instance = qos->durability_service.resource_limits.max_samples_per_instance; - } - return true; + if (qos == NULL || !(qos->present & QP_DURABILITY_SERVICE)) + return false; + if (service_cleanup_delay) + *service_cleanup_delay = nn_from_ddsi_duration (qos->durability_service.service_cleanup_delay); + if (history_kind) + *history_kind = (dds_history_kind_t) qos->durability_service.history.kind; + if (history_depth) + *history_depth = qos->durability_service.history.depth; + if (max_samples) + *max_samples = qos->durability_service.resource_limits.max_samples; + if (max_instances) + *max_instances = qos->durability_service.resource_limits.max_instances; + if (max_samples_per_instance) + *max_samples_per_instance = qos->durability_service.resource_limits.max_samples_per_instance; + return true; } bool dds_qget_ignorelocal (const dds_qos_t * __restrict qos, dds_ignorelocal_kind_t *ignore) { - if (!qos || !(qos->present & QP_CYCLONE_IGNORELOCAL)) { + if (qos == NULL || !(qos->present & QP_CYCLONE_IGNORELOCAL)) return false; - } - if (ignore) { + if (ignore) *ignore = (dds_ignorelocal_kind_t) qos->ignorelocal.value; - } return true; } diff --git a/src/core/ddsc/src/dds_querycond.c b/src/core/ddsc/src/dds_querycond.c index ca972dd..fc5b0ea 100644 --- a/src/core/ddsc/src/dds_querycond.c +++ b/src/core/ddsc/src/dds_querycond.c @@ -21,32 +21,27 @@ #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_sertopic.h" -DDS_EXPORT dds_entity_t -dds_create_querycondition( - dds_entity_t reader, - uint32_t mask, - dds_querycondition_filter_fn filter) +dds_entity_t dds_create_querycondition (dds_entity_t reader, uint32_t mask, dds_querycondition_filter_fn filter) { + dds_return_t rc; + dds_reader *r; + + if ((rc = dds_reader_lock (reader, &r)) != DDS_RETCODE_OK) + return rc; + else + { dds_entity_t hdl; - dds_return_t rc; - dds_reader *r; - - rc = dds_reader_lock(reader, &r); - if (rc == DDS_RETCODE_OK) { - dds_readcond *cond = dds_create_readcond(r, DDS_KIND_COND_QUERY, mask, filter); - assert(cond); - const bool success = (cond->m_entity.m_deriver.delete != 0); - dds_reader_unlock(r); - if (success) { - hdl = cond->m_entity.m_hdllink.hdl; - } else { - dds_delete (cond->m_entity.m_hdllink.hdl); - hdl = DDS_RETCODE_OUT_OF_RESOURCES; - } - } else { - DDS_ERROR("Error occurred on locking reader\n"); - hdl = rc; + dds_readcond *cond = dds_create_readcond (r, DDS_KIND_COND_QUERY, mask, filter); + assert (cond); + const bool success = (cond->m_entity.m_deriver.delete != 0); + dds_reader_unlock (r); + if (success) + hdl = cond->m_entity.m_hdllink.hdl; + else + { + dds_delete (cond->m_entity.m_hdllink.hdl); + hdl = DDS_RETCODE_OUT_OF_RESOURCES; } - return hdl; + } } diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 5d1c4e8..ca5e839 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -38,19 +38,16 @@ static dds_return_t dds_read_lock (dds_entity_t hdl, dds_reader **reader, dds_re else if (only_reader) { dds_entity_unlock (entity); - DDS_ERROR ("Given entity is not a reader\n"); return DDS_RETCODE_ILLEGAL_OPERATION; } else if (dds_entity_kind (entity) != DDS_KIND_COND_READ && dds_entity_kind (entity) != DDS_KIND_COND_QUERY) { dds_entity_unlock (entity); - DDS_ERROR ("Given entity is a reader nor a condition\n"); return DDS_RETCODE_ILLEGAL_OPERATION; } else if ((rc = dds_entity_lock (entity->m_parent->m_hdllink.hdl, DDS_KIND_READER, &parent_entity)) != DDS_RETCODE_OK) { dds_entity_unlock (entity); - DDS_ERROR ("Failed to lock condition's reader\n"); return rc; } else @@ -63,9 +60,9 @@ static dds_return_t dds_read_lock (dds_entity_t hdl, dds_reader **reader, dds_re static void dds_read_unlock (dds_reader *reader, dds_readcond *condition) { - dds_entity_unlock (&reader->m_entity); - if (condition) - dds_entity_unlock (&condition->m_entity); + dds_entity_unlock (&reader->m_entity); + if (condition) + dds_entity_unlock (&condition->m_entity); } /* @@ -75,147 +72,113 @@ static void dds_read_unlock (dds_reader *reader, dds_readcond *condition) has been locked. This is used to support C++ API reading length unlimited which is interpreted as "all relevant samples in cache". */ -static dds_return_t -dds_read_impl( - bool take, - dds_entity_t reader_or_condition, - void **buf, - size_t bufsz, - uint32_t maxs, - dds_sample_info_t *si, - uint32_t mask, - dds_instance_handle_t hand, - bool lock, - bool only_reader) +static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, void **buf, size_t bufsz, uint32_t maxs, dds_sample_info_t *si, uint32_t mask, dds_instance_handle_t hand, bool lock, bool only_reader) { - struct thread_state1 * const ts1 = lookup_thread_state (); - dds_return_t ret = DDS_RETCODE_OK; - struct dds_reader * rd; - struct dds_readcond * cond; - unsigned nodata_cleanups = 0; + struct thread_state1 * const ts1 = lookup_thread_state (); + dds_return_t ret = DDS_RETCODE_OK; + struct dds_reader *rd; + struct dds_readcond *cond; + unsigned nodata_cleanups = 0; #define NC_CLEAR_LOAN_OUT 1u #define NC_FREE_BUF 2u #define NC_RESET_BUF 4u - if (buf == NULL) { - DDS_ERROR("The provided buffer is NULL\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - goto fail; - } - if (si == NULL) { - DDS_ERROR("Provided pointer to an array of dds_sample_info_t is NULL\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - goto fail; - } - if (maxs == 0) { - DDS_ERROR("The maximum number of samples to read is zero\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - goto fail; - } - if (bufsz == 0) { - DDS_ERROR("The size of buffer is zero\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - goto fail; - } - if (bufsz < maxs) { - DDS_ERROR("The provided size of buffer is smaller than the maximum number of samples to read\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - goto fail; - } + if (buf == NULL || si == NULL || maxs == 0 || bufsz == 0 || bufsz < maxs) + return DDS_RETCODE_BAD_PARAMETER; - thread_state_awake (ts1); - ret = dds_read_lock(reader_or_condition, &rd, &cond, only_reader); - if (ret != DDS_RETCODE_OK) { - goto fail_awake; - } - if (hand != DDS_HANDLE_NIL) { - if (ddsi_tkmap_find_by_id(gv.m_tkmap, hand) == NULL) { - DDS_ERROR("Could not find instance\n"); - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - dds_read_unlock(rd, cond); - goto fail_awake; - } - } - /* Allocate samples if not provided (assuming all or none provided) */ - if (buf[0] == NULL) { - /* Allocate, use or reallocate loan cached on reader */ - if (rd->m_loan_out) { - ddsi_sertopic_realloc_samples (buf, rd->m_topic->m_stopic, NULL, 0, maxs); - nodata_cleanups = NC_FREE_BUF | NC_RESET_BUF; - } else { - if (rd->m_loan) { - if (rd->m_loan_size < maxs) { - ddsi_sertopic_realloc_samples (buf, rd->m_topic->m_stopic, rd->m_loan, rd->m_loan_size, maxs); - rd->m_loan = buf[0]; - rd->m_loan_size = maxs; - nodata_cleanups = NC_RESET_BUF; - } else { - buf[0] = rd->m_loan; - nodata_cleanups = NC_RESET_BUF; - } - } else { - ddsi_sertopic_realloc_samples (buf, rd->m_topic->m_stopic, NULL, 0, maxs); - rd->m_loan = buf[0]; - rd->m_loan_size = maxs; - } - rd->m_loan_out = true; - nodata_cleanups |= NC_CLEAR_LOAN_OUT; - } - } + thread_state_awake (ts1); + if ((ret = dds_read_lock (reader_or_condition, &rd, &cond, only_reader)) != DDS_RETCODE_OK) + goto fail_awake; - /* read/take resets data available status -- must reset before reading because - the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ - ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); - dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); - /* reset DATA_ON_READERS status on subscriber after successful read/take */ - if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { - dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); + if (hand != DDS_HANDLE_NIL) + { + if (ddsi_tkmap_find_by_id (gv.m_tkmap, hand) == NULL) { + ret = DDS_RETCODE_PRECONDITION_NOT_MET; + goto fail_awake_lock; } - ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); + } - if (take) { - ret = (dds_return_t) dds_rhc_take (rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); - } else { - ret = (dds_return_t) dds_rhc_read (rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); + /* Allocate samples if not provided (assuming all or none provided) */ + if (buf[0] == NULL) + { + /* Allocate, use or reallocate loan cached on reader */ + if (rd->m_loan_out) + { + ddsi_sertopic_realloc_samples (buf, rd->m_topic->m_stopic, NULL, 0, maxs); + nodata_cleanups = NC_FREE_BUF | NC_RESET_BUF; } - - /* if no data read, restore the state to what it was before the call, with the sole - exception of holding on to a buffer we just allocated and that is pointed to by - rd->m_loan */ - if (ret <= 0 && nodata_cleanups) { - if (nodata_cleanups & NC_CLEAR_LOAN_OUT) { - rd->m_loan_out = false; - } - if (nodata_cleanups & NC_FREE_BUF) { - ddsi_sertopic_free_samples (rd->m_topic->m_stopic, buf[0], maxs, DDS_FREE_ALL); - } - if (nodata_cleanups & NC_RESET_BUF) { - buf[0] = NULL; + else + { + if (rd->m_loan) + { + if (rd->m_loan_size >= maxs) + buf[0] = rd->m_loan; + else + { + ddsi_sertopic_realloc_samples (buf, rd->m_topic->m_stopic, rd->m_loan, rd->m_loan_size, maxs); + rd->m_loan = buf[0]; + rd->m_loan_size = maxs; } + nodata_cleanups = NC_RESET_BUF; + } + else + { + ddsi_sertopic_realloc_samples (buf, rd->m_topic->m_stopic, NULL, 0, maxs); + rd->m_loan = buf[0]; + rd->m_loan_size = maxs; + } + rd->m_loan_out = true; + nodata_cleanups |= NC_CLEAR_LOAN_OUT; } - dds_read_unlock(rd, cond); + } + /* read/take resets data available status -- must reset before reading because + the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); + dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); + /* reset DATA_ON_READERS status on subscriber after successful read/take */ + if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) + dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); + + if (take) + ret = dds_rhc_take (rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); + else + ret = dds_rhc_read (rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); + + /* if no data read, restore the state to what it was before the call, with the sole + exception of holding on to a buffer we just allocated and that is pointed to by + rd->m_loan */ + if (ret <= 0 && nodata_cleanups) + { + if (nodata_cleanups & NC_CLEAR_LOAN_OUT) + rd->m_loan_out = false; + if (nodata_cleanups & NC_FREE_BUF) + ddsi_sertopic_free_samples (rd->m_topic->m_stopic, buf[0], maxs, DDS_FREE_ALL); + if (nodata_cleanups & NC_RESET_BUF) + buf[0] = NULL; + } + dds_read_unlock(rd, cond); + thread_state_asleep (ts1); + return ret; + +#undef NC_CLEAR_LOAN_OUT +#undef NC_FREE_BUF +#undef NC_RESET_BUF + +fail_awake_lock: + dds_read_unlock (rd, cond); fail_awake: - thread_state_asleep (ts1); -fail: - return ret; + thread_state_asleep (ts1); + return ret; } -static dds_return_t -dds_readcdr_impl( - bool take, - dds_entity_t reader_or_condition, - struct ddsi_serdata ** buf, - uint32_t maxs, - dds_sample_info_t * si, - uint32_t mask, - dds_instance_handle_t hand, - bool lock) +static dds_return_t dds_readcdr_impl (bool take, dds_entity_t reader_or_condition, struct ddsi_serdata **buf, uint32_t maxs, dds_sample_info_t *si, uint32_t mask, dds_instance_handle_t hand, bool lock) { struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; - struct dds_reader * rd; - struct dds_readcond * cond; + struct dds_reader *rd; + struct dds_readcond *cond; assert (take); assert (buf); @@ -225,512 +188,312 @@ dds_readcdr_impl( (void)take; thread_state_awake (ts1); - ret = dds_read_lock(reader_or_condition, &rd, &cond, false); - if (ret == DDS_RETCODE_OK) { - /* read/take resets data available status -- must reset before reading because - the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ - ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); - dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); - /* reset DATA_ON_READERS status on subscriber after successful read/take */ - if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { - dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); - } - ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); + if ((ret = dds_read_lock (reader_or_condition, &rd, &cond, false)) == DDS_RETCODE_OK) + { + /* read/take resets data available status -- must reset before reading because + the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); + dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); + /* reset DATA_ON_READERS status on subscriber after successful read/take */ + if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) + dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); - ret = dds_rhc_takecdr - ( - rd->m_rd->rhc, lock, buf, si, maxs, - mask & DDS_ANY_SAMPLE_STATE, - mask & DDS_ANY_VIEW_STATE, - mask & DDS_ANY_INSTANCE_STATE, - hand - ); - - dds_read_unlock(rd, cond); + ret = dds_rhc_takecdr (rd->m_rd->rhc, lock, buf, si, maxs, mask & DDS_ANY_SAMPLE_STATE, mask & DDS_ANY_VIEW_STATE, mask & DDS_ANY_INSTANCE_STATE, hand); + dds_read_unlock (rd, cond); } - thread_state_asleep (ts1); return ret; } -dds_return_t -dds_read( - dds_entity_t rd_or_cnd, - void ** buf, - dds_sample_info_t * si, - size_t bufsz, - uint32_t maxs) +dds_return_t dds_read (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs) { - bool lock = true; - - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs, so use bufsz instead. - * CHAM-306 will remove this ugly piece of code. */ - maxs = (uint32_t)bufsz; - } - return dds_read_impl (false, rd_or_cnd, buf, bufsz, maxs, si, NO_STATE_MASK_SET, DDS_HANDLE_NIL, lock, false); + bool lock = true; + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = (uint32_t) bufsz; + } + return dds_read_impl (false, rd_or_cnd, buf, bufsz, maxs, si, NO_STATE_MASK_SET, DDS_HANDLE_NIL, lock, false); } -dds_return_t -dds_read_wl( - dds_entity_t rd_or_cnd, - void ** buf, - dds_sample_info_t * si, - uint32_t maxs) +dds_return_t dds_read_wl (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, uint32_t maxs) { - bool lock = true; - - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs. Just an arbitrarily number. - * CHAM-306 will remove this ugly piece of code. */ - maxs = 100; - } - return dds_read_impl (false, rd_or_cnd, buf, maxs, maxs, si, NO_STATE_MASK_SET, DDS_HANDLE_NIL, lock, false); + bool lock = true; + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_read_impl (false, rd_or_cnd, buf, maxs, maxs, si, NO_STATE_MASK_SET, DDS_HANDLE_NIL, lock, false); } -dds_return_t -dds_read_mask( - dds_entity_t rd_or_cnd, - void ** buf, - dds_sample_info_t * si, - size_t bufsz, - uint32_t maxs, - uint32_t mask) +dds_return_t dds_read_mask (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs, uint32_t mask) { - bool lock = true; - - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs, so use bufsz instead. - * CHAM-306 will remove this ugly piece of code. */ - maxs = (uint32_t)bufsz; - } - return dds_read_impl (false, rd_or_cnd, buf, bufsz, maxs, si, mask, DDS_HANDLE_NIL, lock, false); + bool lock = true; + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = (uint32_t)bufsz; + } + return dds_read_impl (false, rd_or_cnd, buf, bufsz, maxs, si, mask, DDS_HANDLE_NIL, lock, false); } -dds_return_t -dds_read_mask_wl( - dds_entity_t rd_or_cnd, - void ** buf, - dds_sample_info_t * si, - uint32_t maxs, - uint32_t mask) +dds_return_t dds_read_mask_wl (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, uint32_t maxs, uint32_t mask) { - bool lock = true; - - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs. Just an arbitrarily number. - * CHAM-306 will remove this ugly piece of code. */ - maxs = 100; - } - return dds_read_impl (false, rd_or_cnd, buf, maxs, maxs, si, mask, DDS_HANDLE_NIL, lock, false); + bool lock = true; + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_read_impl (false, rd_or_cnd, buf, maxs, maxs, si, mask, DDS_HANDLE_NIL, lock, false); } -dds_return_t -dds_read_instance( - dds_entity_t rd_or_cnd, - void **buf, - dds_sample_info_t *si, - size_t bufsz, - uint32_t maxs, - dds_instance_handle_t handle) +dds_return_t dds_read_instance (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs, dds_instance_handle_t handle) { - dds_return_t ret = DDS_RETCODE_OK; - bool lock = true; + bool lock = true; - if (handle == DDS_HANDLE_NIL) { - DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - goto fail; - } + if (handle == DDS_HANDLE_NIL) + return DDS_RETCODE_PRECONDITION_NOT_MET; - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs. Just an arbitrarily number. - * CHAM-306 will remove this ugly piece of code. */ - maxs = 100; - } - ret = dds_read_impl(false, rd_or_cnd, buf, bufsz, maxs, si, NO_STATE_MASK_SET, handle, lock, false); -fail: - return ret; -} - -dds_return_t -dds_read_instance_wl( - dds_entity_t rd_or_cnd, - void **buf, - dds_sample_info_t *si, - uint32_t maxs, - dds_instance_handle_t handle) -{ - dds_return_t ret = DDS_RETCODE_OK; - bool lock = true; - - if (handle == DDS_HANDLE_NIL) { - DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - goto fail; - } - - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs. Just an arbitrarily number. - * CHAM-306 will remove this ugly piece of code. */ - maxs = 100; - } - ret = dds_read_impl(false, rd_or_cnd, buf, maxs, maxs, si, NO_STATE_MASK_SET, handle, lock, false); -fail: - return ret; -} - -dds_return_t -dds_read_instance_mask( - dds_entity_t rd_or_cnd, - void **buf, - dds_sample_info_t *si, - size_t bufsz, - uint32_t maxs, - dds_instance_handle_t handle, - uint32_t mask) -{ - dds_return_t ret = DDS_RETCODE_OK; - bool lock = true; - - if (handle == DDS_HANDLE_NIL) { - DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - goto fail; - } - - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs. Just an arbitrarily number. - * CHAM-306 will remove this ugly piece of code. */ - maxs = 100; - } - ret = dds_read_impl(false, rd_or_cnd, buf, bufsz, maxs, si, mask, handle, lock, false); -fail: - return ret; -} - -dds_return_t -dds_read_instance_mask_wl( - dds_entity_t rd_or_cnd, - void **buf, - dds_sample_info_t *si, - uint32_t maxs, - dds_instance_handle_t handle, - uint32_t mask) -{ - dds_return_t ret = DDS_RETCODE_OK; - bool lock = true; - - if (handle == DDS_HANDLE_NIL) { - DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - goto fail; - } - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs. Just an arbitrarily number. - * CHAM-306 will remove this ugly piece of code. */ - maxs = 100; - } - ret = dds_read_impl(false, rd_or_cnd, buf, maxs, maxs, si, mask, handle, lock, false); -fail: - return ret; -} - -dds_return_t -dds_read_next( - dds_entity_t reader, - void **buf, - dds_sample_info_t *si) -{ - uint32_t mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - return dds_read_impl (false, reader, buf, 1u, 1u, si, mask, DDS_HANDLE_NIL, true, true); -} - -dds_return_t -dds_read_next_wl( - dds_entity_t reader, - void **buf, - dds_sample_info_t *si) -{ - uint32_t mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - return dds_read_impl (false, reader, buf, 1u, 1u, si, mask, DDS_HANDLE_NIL, true, true); -} - -dds_return_t -dds_take( - dds_entity_t rd_or_cnd, - void ** buf, - dds_sample_info_t * si, - size_t bufsz, - uint32_t maxs) -{ - bool lock = true; - - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs, so use bufsz instead. - * CHAM-306 will remove this ugly piece of code. */ - maxs = (uint32_t)bufsz; - } - return dds_read_impl (true, rd_or_cnd, buf, bufsz, maxs, si, NO_STATE_MASK_SET, DDS_HANDLE_NIL, lock, false); -} - -dds_return_t -dds_take_wl( - dds_entity_t rd_or_cnd, - void ** buf, - dds_sample_info_t * si, - uint32_t maxs) -{ - bool lock = true; - - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs. Just an arbitrarily number. - * CHAM-306 will remove this ugly piece of code. */ - maxs = 100; - } - return dds_read_impl (true, rd_or_cnd, buf, maxs, maxs, si, NO_STATE_MASK_SET, DDS_HANDLE_NIL, lock, false); -} - -dds_return_t -dds_take_mask( - dds_entity_t rd_or_cnd, - void ** buf, - dds_sample_info_t * si, - size_t bufsz, - uint32_t maxs, - uint32_t mask) -{ - bool lock = true; - - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs, so use bufsz instead. - * CHAM-306 will remove this ugly piece of code. */ - maxs = (uint32_t)bufsz; - } - return dds_read_impl (true, rd_or_cnd, buf, bufsz, maxs, si, mask, DDS_HANDLE_NIL, lock, false); -} - -dds_return_t -dds_take_mask_wl( - dds_entity_t rd_or_cnd, - void ** buf, - dds_sample_info_t * si, - uint32_t maxs, - uint32_t mask) -{ - bool lock = true; - - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs. Just an arbitrarily number. - * CHAM-306 will remove this ugly piece of code. */ - maxs = 100; - } - return dds_read_impl (true, rd_or_cnd, buf, maxs, maxs, si, mask, DDS_HANDLE_NIL, lock, false); -} - -int -dds_takecdr( - dds_entity_t rd_or_cnd, - struct ddsi_serdata **buf, - uint32_t maxs, - dds_sample_info_t *si, - uint32_t mask) -{ - bool lock = true; - - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs. Just an arbitrarily number. - * CHAM-306 will remove this ugly piece of code. */ - maxs = 100; - } - return dds_readcdr_impl (true, rd_or_cnd, buf, maxs, si, mask, DDS_HANDLE_NIL, lock); -} - -dds_return_t -dds_take_instance( - dds_entity_t rd_or_cnd, - void **buf, - dds_sample_info_t *si, - size_t bufsz, - uint32_t maxs, - dds_instance_handle_t handle) -{ - dds_return_t ret = DDS_RETCODE_OK; - bool lock = true; - - if (handle == DDS_HANDLE_NIL) { - DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - goto fail; - } - - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs. Just an arbitrarily number. - * CHAM-306 will remove this ugly piece of code. */ - maxs = 100; - } - ret = dds_read_impl(true, rd_or_cnd, buf, bufsz, maxs, si, NO_STATE_MASK_SET, handle, lock, false); -fail: - return ret; -} - -dds_return_t -dds_take_instance_wl( - dds_entity_t rd_or_cnd, - void **buf, - dds_sample_info_t *si, - uint32_t maxs, - dds_instance_handle_t handle) -{ - dds_return_t ret = DDS_RETCODE_OK; - bool lock = true; - - if (handle == DDS_HANDLE_NIL) { - DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - goto fail; - } - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs. Just an arbitrarily number. - * CHAM-306 will remove this ugly piece of code. */ - maxs = 100; - } - ret = dds_read_impl(true, rd_or_cnd, buf, maxs, maxs, si, NO_STATE_MASK_SET, handle, lock, false); -fail: - return ret; -} - -dds_return_t -dds_take_instance_mask( - dds_entity_t rd_or_cnd, - void **buf, - dds_sample_info_t *si, - size_t bufsz, - uint32_t maxs, - dds_instance_handle_t handle, - uint32_t mask) -{ - dds_return_t ret = DDS_RETCODE_OK; - bool lock = true; - - if (handle == DDS_HANDLE_NIL) { - DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - goto fail; - } - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs. Just an arbitrarily number. - * CHAM-306 will remove this ugly piece of code. */ - maxs = 100; - } - ret = dds_read_impl(true, rd_or_cnd, buf, bufsz, maxs, si, mask, handle, lock, false); -fail: - return ret; -} - -dds_return_t -dds_take_instance_mask_wl( - dds_entity_t rd_or_cnd, - void **buf, - dds_sample_info_t *si, - uint32_t maxs, - dds_instance_handle_t handle, - uint32_t mask) -{ - dds_return_t ret = DDS_RETCODE_OK; - bool lock = true; - - if (handle == DDS_HANDLE_NIL) { - DDS_ERROR("DDS_HANDLE_NIL was provided\n"); - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - goto fail; - } - if (maxs == DDS_READ_WITHOUT_LOCK) { - lock = false; - /* Use a more sensible maxs. Just an arbitrarily number. - * CHAM-306 will remove this ugly piece of code. */ - maxs = 100; - } - ret = dds_read_impl(true, rd_or_cnd, buf, maxs, maxs, si, mask, handle, lock, false); -fail: - return ret; -} - -dds_return_t -dds_take_next( - dds_entity_t reader, - void **buf, - dds_sample_info_t *si) -{ - uint32_t mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - return dds_read_impl (true, reader, buf, 1u, 1u, si, mask, DDS_HANDLE_NIL, true, true); -} - -dds_return_t -dds_take_next_wl( - dds_entity_t reader, - void **buf, - dds_sample_info_t *si) -{ - uint32_t mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; - return dds_read_impl (true, reader, buf, 1u, 1u, si, mask, DDS_HANDLE_NIL, true, true); -} - -dds_return_t -dds_return_loan( - dds_entity_t reader_or_condition, - void **buf, - int32_t bufsz) -{ - const struct ddsi_sertopic *st; - dds_reader *rd; - dds_readcond *cond; - dds_return_t ret = DDS_RETCODE_OK; - - if (!buf) { - DDS_ERROR("Argument buf is NULL\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - goto fail; - } - if (*buf == NULL && bufsz > 0) { - ret = DDS_RETCODE_BAD_PARAMETER; - goto fail; - } - - ret = dds_read_lock(reader_or_condition, &rd, &cond, false); - if (ret != DDS_RETCODE_OK) { - goto fail; - } - st = rd->m_topic->m_stopic; - - for (int32_t i = 0; i < bufsz; i++) { - ddsi_sertopic_free_sample (st, buf[i], DDS_FREE_CONTENTS); - } - - /* If possible return loan buffer to reader */ - if (rd->m_loan != 0 && (buf[0] == rd->m_loan)) { - rd->m_loan_out = false; - ddsi_sertopic_zero_samples (st, rd->m_loan, rd->m_loan_size); - buf[0] = NULL; - } - - dds_read_unlock(rd, cond); -fail: + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_read_impl (false, rd_or_cnd, buf, bufsz, maxs, si, NO_STATE_MASK_SET, handle, lock, false); +} + +dds_return_t dds_read_instance_wl (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, uint32_t maxs, dds_instance_handle_t handle) +{ + bool lock = true; + + if (handle == DDS_HANDLE_NIL) + return DDS_RETCODE_PRECONDITION_NOT_MET; + + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_read_impl (false, rd_or_cnd, buf, maxs, maxs, si, NO_STATE_MASK_SET, handle, lock, false); +} + +dds_return_t dds_read_instance_mask (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs, dds_instance_handle_t handle, uint32_t mask) +{ + bool lock = true; + + if (handle == DDS_HANDLE_NIL) + return DDS_RETCODE_PRECONDITION_NOT_MET; + + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_read_impl (false, rd_or_cnd, buf, bufsz, maxs, si, mask, handle, lock, false); +} + +dds_return_t dds_read_instance_mask_wl (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, uint32_t maxs, dds_instance_handle_t handle, uint32_t mask) +{ + bool lock = true; + + if (handle == DDS_HANDLE_NIL) + return DDS_RETCODE_PRECONDITION_NOT_MET; + + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_read_impl (false, rd_or_cnd, buf, maxs, maxs, si, mask, handle, lock, false); +} + +dds_return_t dds_read_next (dds_entity_t reader, void **buf, dds_sample_info_t *si) +{ + uint32_t mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; + return dds_read_impl (false, reader, buf, 1u, 1u, si, mask, DDS_HANDLE_NIL, true, true); +} + +dds_return_t dds_read_next_wl ( + dds_entity_t reader, + void **buf, + dds_sample_info_t *si) +{ + uint32_t mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; + return dds_read_impl (false, reader, buf, 1u, 1u, si, mask, DDS_HANDLE_NIL, true, true); +} + +dds_return_t dds_take (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs) +{ + bool lock = true; + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = (uint32_t)bufsz; + } + return dds_read_impl (true, rd_or_cnd, buf, bufsz, maxs, si, NO_STATE_MASK_SET, DDS_HANDLE_NIL, lock, false); +} + +dds_return_t dds_take_wl (dds_entity_t rd_or_cnd, void ** buf, dds_sample_info_t * si, uint32_t maxs) +{ + bool lock = true; + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_read_impl (true, rd_or_cnd, buf, maxs, maxs, si, NO_STATE_MASK_SET, DDS_HANDLE_NIL, lock, false); +} + +dds_return_t dds_take_mask (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs, uint32_t mask) +{ + bool lock = true; + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = (uint32_t) bufsz; + } + return dds_read_impl (true, rd_or_cnd, buf, bufsz, maxs, si, mask, DDS_HANDLE_NIL, lock, false); +} + +dds_return_t dds_take_mask_wl (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, uint32_t maxs, uint32_t mask) +{ + bool lock = true; + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_read_impl (true, rd_or_cnd, buf, maxs, maxs, si, mask, DDS_HANDLE_NIL, lock, false); +} + +dds_return_t dds_takecdr (dds_entity_t rd_or_cnd, struct ddsi_serdata **buf, uint32_t maxs, dds_sample_info_t *si, uint32_t mask) +{ + bool lock = true; + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_readcdr_impl (true, rd_or_cnd, buf, maxs, si, mask, DDS_HANDLE_NIL, lock); +} + +dds_return_t dds_take_instance (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs, dds_instance_handle_t handle) +{ + bool lock = true; + + if (handle == DDS_HANDLE_NIL) + return DDS_RETCODE_PRECONDITION_NOT_MET; + + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_read_impl(true, rd_or_cnd, buf, bufsz, maxs, si, NO_STATE_MASK_SET, handle, lock, false); +} + +dds_return_t dds_take_instance_wl (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, uint32_t maxs, dds_instance_handle_t handle) +{ + bool lock = true; + + if (handle == DDS_HANDLE_NIL) + return DDS_RETCODE_PRECONDITION_NOT_MET; + + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_read_impl(true, rd_or_cnd, buf, maxs, maxs, si, NO_STATE_MASK_SET, handle, lock, false); +} + +dds_return_t dds_take_instance_mask (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs, dds_instance_handle_t handle, uint32_t mask) +{ + bool lock = true; + + if (handle == DDS_HANDLE_NIL) + return DDS_RETCODE_PRECONDITION_NOT_MET; + + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_read_impl(true, rd_or_cnd, buf, bufsz, maxs, si, mask, handle, lock, false); +} + +dds_return_t dds_take_instance_mask_wl (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, uint32_t maxs, dds_instance_handle_t handle, uint32_t mask) +{ + bool lock = true; + + if (handle == DDS_HANDLE_NIL) + return DDS_RETCODE_PRECONDITION_NOT_MET; + + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_read_impl(true, rd_or_cnd, buf, maxs, maxs, si, mask, handle, lock, false); +} + +dds_return_t dds_take_next (dds_entity_t reader, void **buf, dds_sample_info_t *si) +{ + uint32_t mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; + return dds_read_impl (true, reader, buf, 1u, 1u, si, mask, DDS_HANDLE_NIL, true, true); +} + +dds_return_t dds_take_next_wl (dds_entity_t reader, void **buf, dds_sample_info_t *si) +{ + uint32_t mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; + return dds_read_impl (true, reader, buf, 1u, 1u, si, mask, DDS_HANDLE_NIL, true, true); +} + +dds_return_t dds_return_loan (dds_entity_t reader_or_condition, void **buf, int32_t bufsz) +{ + const struct ddsi_sertopic *st; + dds_reader *rd; + dds_readcond *cond; + dds_return_t ret = DDS_RETCODE_OK; + + if (buf == NULL || (*buf == NULL && bufsz > 0)) + return DDS_RETCODE_BAD_PARAMETER; + + if ((ret = dds_read_lock(reader_or_condition, &rd, &cond, false)) != DDS_RETCODE_OK) return ret; + + st = rd->m_topic->m_stopic; + for (int32_t i = 0; i < bufsz; i++) + ddsi_sertopic_free_sample (st, buf[i], DDS_FREE_CONTENTS); + + /* If possible return loan buffer to reader */ + if (rd->m_loan != 0 && (buf[0] == rd->m_loan)) + { + rd->m_loan_out = false; + ddsi_sertopic_zero_samples (st, rd->m_loan, rd->m_loan_size); + buf[0] = NULL; + } + + dds_read_unlock(rd, cond); + return DDS_RETCODE_OK; } diff --git a/src/core/ddsc/src/dds_readcond.c b/src/core/ddsc/src/dds_readcond.c index ae889be..c5b0ace 100644 --- a/src/core/ddsc/src/dds_readcond.c +++ b/src/core/ddsc/src/dds_readcond.c @@ -18,65 +18,56 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" -static dds_return_t -dds_readcond_delete( - dds_entity *e) +static dds_return_t dds_readcond_delete (dds_entity *e) ddsrt_nonnull_all; + +static dds_return_t dds_readcond_delete (dds_entity *e) { - dds_rhc_remove_readcondition((dds_readcond*)e); - return DDS_RETCODE_OK; + dds_rhc_remove_readcondition ((dds_readcond *) e); + return DDS_RETCODE_OK; } -dds_readcond* -dds_create_readcond( - dds_reader *rd, - dds_entity_kind_t kind, - uint32_t mask, - dds_querycondition_filter_fn filter) +dds_readcond *dds_create_readcond (dds_reader *rd, dds_entity_kind_t kind, uint32_t mask, dds_querycondition_filter_fn filter) { - dds_readcond * cond = dds_alloc(sizeof(*cond)); - assert((kind == DDS_KIND_COND_READ && filter == 0) || (kind == DDS_KIND_COND_QUERY && filter != 0)); - (void) dds_entity_init(&cond->m_entity, (dds_entity*)rd, kind, NULL, NULL, 0); - cond->m_entity.m_deriver.delete = dds_readcond_delete; - cond->m_rhc = rd->m_rd->rhc; - cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE; - cond->m_view_states = mask & DDS_ANY_VIEW_STATE; - cond->m_instance_states = mask & DDS_ANY_INSTANCE_STATE; - cond->m_rd_guid = rd->m_entity.m_guid; - if (kind == DDS_KIND_COND_QUERY) { - cond->m_query.m_filter = filter; - cond->m_query.m_qcmask = 0; - } - if (!dds_rhc_add_readcondition (cond)) { - /* FIXME: current entity management code can't deal with an error late in the creation of the - entity because it doesn't allow deleting it again ... instead use a hack to signal a problem - to the caller and let that one handle it. */ - cond->m_entity.m_deriver.delete = 0; - } - return cond; + dds_readcond *cond = dds_alloc (sizeof (*cond)); + assert ((kind == DDS_KIND_COND_READ && filter == 0) || (kind == DDS_KIND_COND_QUERY && filter != 0)); + (void) dds_entity_init (&cond->m_entity, &rd->m_entity, kind, NULL, NULL, 0); + cond->m_entity.m_deriver.delete = dds_readcond_delete; + cond->m_rhc = rd->m_rd->rhc; + cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE; + cond->m_view_states = mask & DDS_ANY_VIEW_STATE; + cond->m_instance_states = mask & DDS_ANY_INSTANCE_STATE; + cond->m_rd_guid = rd->m_entity.m_guid; + if (kind == DDS_KIND_COND_QUERY) + { + cond->m_query.m_filter = filter; + cond->m_query.m_qcmask = 0; + } + if (!dds_rhc_add_readcondition (cond)) + { + /* FIXME: current entity management code can't deal with an error late in the creation of the + entity because it doesn't allow deleting it again ... instead use a hack to signal a problem + to the caller and let that one handle it. */ + cond->m_entity.m_deriver.delete = 0; + } + return cond; } -dds_entity_t -dds_create_readcondition( - dds_entity_t reader, - uint32_t mask) +dds_entity_t dds_create_readcondition (dds_entity_t reader, uint32_t mask) { + dds_reader *rd; + dds_return_t rc; + if ((rc = dds_reader_lock (reader, &rd)) != DDS_RETCODE_OK) + return rc; + else + { dds_entity_t hdl; - dds_reader * rd; - dds_return_t rc; - - rc = dds_reader_lock(reader, &rd); - if (rc == DDS_RETCODE_OK) { - dds_readcond *cond = dds_create_readcond(rd, DDS_KIND_COND_READ, mask, 0); - assert(cond); - assert(cond->m_entity.m_deriver.delete); - hdl = cond->m_entity.m_hdllink.hdl; - dds_reader_unlock(rd); - } else { - DDS_ERROR("Error occurred on locking reader\n"); - hdl = rc; - } - + dds_readcond *cond = dds_create_readcond(rd, DDS_KIND_COND_READ, mask, 0); + assert (cond); + assert (cond->m_entity.m_deriver.delete); + hdl = cond->m_entity.m_hdllink.hdl; + dds_reader_unlock (rd); return hdl; + } } dds_entity_t dds_get_datareader (dds_entity_t condition) diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 49a6c0c..8638251 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -13,6 +13,7 @@ #include #include "dds/dds.h" #include "dds/version.h" +#include "dds/ddsrt/static_assert.h" #include "dds__subscriber.h" #include "dds__reader.h" #include "dds__listener.h" @@ -20,135 +21,96 @@ #include "dds__init.h" #include "dds__rhc.h" #include "dds__topic.h" +#include "dds__get_status.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_globals.h" #include "dds__builtin.h" #include "dds/ddsi/ddsi_sertopic.h" -DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_reader) +DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_reader) #define DDS_READER_STATUS_MASK \ - DDS_SAMPLE_REJECTED_STATUS |\ - DDS_LIVELINESS_CHANGED_STATUS |\ - DDS_REQUESTED_DEADLINE_MISSED_STATUS |\ - DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS |\ - DDS_DATA_AVAILABLE_STATUS |\ - DDS_SAMPLE_LOST_STATUS |\ - DDS_SUBSCRIPTION_MATCHED_STATUS + (DDS_SAMPLE_REJECTED_STATUS |\ + DDS_LIVELINESS_CHANGED_STATUS |\ + DDS_REQUESTED_DEADLINE_MISSED_STATUS |\ + DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS |\ + DDS_DATA_AVAILABLE_STATUS |\ + DDS_SAMPLE_LOST_STATUS |\ + DDS_SUBSCRIPTION_MATCHED_STATUS) -static dds_return_t -dds_reader_instance_hdl( - dds_entity *e, - dds_instance_handle_t *i) +static dds_return_t dds_reader_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all; + +static dds_return_t dds_reader_instance_hdl (dds_entity *e, dds_instance_handle_t *i) { - assert(e); - assert(i); - *i = (dds_instance_handle_t)reader_instance_id(&e->m_guid); - return DDS_RETCODE_OK; + *i = reader_instance_id (&e->m_guid); + return DDS_RETCODE_OK; } -static dds_return_t -dds_reader_close( - dds_entity *e) +static dds_return_t dds_reader_close (dds_entity *e) ddsrt_nonnull_all; + +static dds_return_t dds_reader_close (dds_entity *e) { - dds_return_t ret = DDS_RETCODE_OK; + dds_return_t ret = DDS_RETCODE_OK; + thread_state_awake (lookup_thread_state ()); + if (delete_reader (&e->m_guid) != 0) + ret = DDS_RETCODE_ERROR; + thread_state_asleep (lookup_thread_state ()); + return ret; +} - assert(e); +static dds_return_t dds_reader_delete (dds_entity *e) ddsrt_nonnull_all; - thread_state_awake (lookup_thread_state ()); - if (delete_reader(&e->m_guid) != 0) { - DDS_ERROR("Internal error"); - ret = DDS_RETCODE_ERROR; - } - thread_state_asleep (lookup_thread_state ()); +static dds_return_t dds_reader_delete (dds_entity *e) +{ + dds_reader * const rd = (dds_reader *) e; + dds_return_t ret; + if ((ret = dds_delete (rd->m_topic->m_entity.m_hdllink.hdl)) == DDS_RETCODE_OK) + { + /* Delete an implicitly created parent; for normal ones, this is expected + to fail with BAD_PARAMETER - FIXME: there must be a cleaner way */ + ret = dds_delete_impl (e->m_parent->m_hdllink.hdl, true); + if (ret == DDS_RETCODE_BAD_PARAMETER) + ret = DDS_RETCODE_OK; + } + dds_free (rd->m_loan); + return ret; +} + +static dds_return_t dds_reader_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; + +static dds_return_t dds_reader_qos_validate (const dds_qos_t *qos, bool enabled) +{ + if (!dds_qos_validate_common (qos)) + return DDS_RETCODE_ERROR; + if ((qos->present & QP_USER_DATA) && !validate_octetseq (&qos->user_data)) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_PRISMTECH_READER_DATA_LIFECYCLE) && validate_reader_data_lifecycle (&qos->reader_data_lifecycle) < 0) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_TIME_BASED_FILTER) && validate_duration (&qos->time_based_filter.minimum_separation) < 0) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits (&qos->history, &qos->resource_limits) < 0) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_TIME_BASED_FILTER) && (qos->present & QP_DEADLINE) && !validate_deadline_and_timebased_filter (qos->deadline.deadline, qos->time_based_filter.minimum_separation)) + return DDS_RETCODE_INCONSISTENT_POLICY; + return (enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK); +} + +static dds_return_t dds_reader_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; + +static dds_return_t dds_reader_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) +{ + dds_return_t ret; + (void) e; + if ((ret = dds_reader_qos_validate (qos, enabled)) != DDS_RETCODE_OK) return ret; + /* FIXME: QoS changes. */ + return (enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK); } -static dds_return_t -dds_reader_delete( - dds_entity *e) +static dds_return_t dds_reader_status_validate (uint32_t mask) { - dds_reader *rd = (dds_reader*)e; - dds_return_t ret; - assert(e); - ret = dds_delete(rd->m_topic->m_entity.m_hdllink.hdl); - if(ret == DDS_RETCODE_OK){ - ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true); - if(ret == DDS_RETCODE_BAD_PARAMETER){ - ret = DDS_RETCODE_OK; - } - } - dds_free(rd->m_loan); - return ret; -} - -static dds_return_t -dds_reader_qos_validate( - const dds_qos_t *qos, - bool enabled) -{ - dds_return_t ret = DDS_RETCODE_OK; - - assert(qos); - - /* Check consistency. */ - if(!dds_qos_validate_common(qos)) { - DDS_ERROR("Argument Qos is not valid\n"); - ret = DDS_RETCODE_ERROR; - } - if((qos->present & QP_USER_DATA) && !(validate_octetseq (&qos->user_data))) { - DDS_ERROR("User data policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if((qos->present & QP_PRISMTECH_READER_DATA_LIFECYCLE) && (validate_reader_data_lifecycle (&qos->reader_data_lifecycle) != 0)) { - DDS_ERROR("Prismtech reader data lifecycle policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if((qos->present & QP_TIME_BASED_FILTER) && (validate_duration (&qos->time_based_filter.minimum_separation) != 0)) { - DDS_ERROR("Time based filter policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits (&qos->history, &qos->resource_limits) != 0)) { - DDS_ERROR("History and resource limits policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if((qos->present & QP_TIME_BASED_FILTER) && (qos->present & QP_DEADLINE) && !(validate_deadline_and_timebased_filter (qos->deadline.deadline, qos->time_based_filter.minimum_separation))) { - DDS_ERROR("Time based filter and deadline policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if(ret == DDS_RETCODE_OK && enabled) { - ret = dds_qos_validate_mutable_common(qos); - } - - return ret; -} - -static dds_return_t -dds_reader_qos_set( - dds_entity *e, - const dds_qos_t *qos, - bool enabled) -{ - dds_return_t ret = dds_reader_qos_validate(qos, enabled); - (void)e; - if (ret == DDS_RETCODE_OK) { - if (enabled) { - /* TODO: CHAM-95: DDSI does not support changing QoS policies. */ - DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies\n"); - ret = DDS_RETCODE_UNSUPPORTED; - } - } - return ret; -} - -static dds_return_t -dds_reader_status_validate( - uint32_t mask) -{ - return (mask & ~(DDS_READER_STATUS_MASK)) ? - DDS_RETCODE_BAD_PARAMETER : - DDS_RETCODE_OK; + return (mask & ~DDS_READER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK; } void dds_reader_data_available_cb (struct dds_reader *rd) @@ -349,170 +311,157 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) ddsrt_mutex_unlock (&entity->m_observers_lock); } -dds_entity_t -dds_create_reader( - dds_entity_t participant_or_subscriber, - dds_entity_t topic, - const dds_qos_t *qos, - const dds_listener_t *listener) +dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_entity_t topic, const dds_qos_t *qos, const dds_listener_t *listener) { - dds_qos_t * rqos; - dds_subscriber * sub = NULL; - dds_entity_t subscriber; - dds_reader * rd; - struct rhc * rhc; - dds_topic * tp; - dds_entity_t reader; - dds_entity_t t; - dds_return_t ret = DDS_RETCODE_OK; - bool internal_topic; + dds_qos_t *rqos; + dds_subscriber *sub = NULL; + dds_entity_t subscriber; + dds_reader *rd; + struct rhc *rhc; + dds_topic *tp; + dds_entity_t reader; + dds_entity_t t; + dds_return_t ret = DDS_RETCODE_OK; + bool internal_topic; - switch (topic) { - case DDS_BUILTIN_TOPIC_DCPSPARTICIPANT: - case DDS_BUILTIN_TOPIC_DCPSTOPIC: - case DDS_BUILTIN_TOPIC_DCPSPUBLICATION: - case DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION: - internal_topic = true; - subscriber = dds__get_builtin_subscriber(participant_or_subscriber); - t = dds__get_builtin_topic (subscriber, topic); - break; + switch (topic) + { + case DDS_BUILTIN_TOPIC_DCPSPARTICIPANT: + case DDS_BUILTIN_TOPIC_DCPSTOPIC: + case DDS_BUILTIN_TOPIC_DCPSPUBLICATION: + case DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION: + internal_topic = true; + subscriber = dds__get_builtin_subscriber (participant_or_subscriber); + t = dds__get_builtin_topic (subscriber, topic); + break; - default: { - dds_entity *p_or_s; - if ((ret = dds_entity_claim (participant_or_subscriber, &p_or_s)) != DDS_RETCODE_OK) { - return ret; - } - if (dds_entity_kind (p_or_s) == DDS_KIND_PARTICIPANT) { - subscriber = dds_create_subscriber(participant_or_subscriber, qos, NULL); - } else { - subscriber = participant_or_subscriber; - } - dds_entity_release (p_or_s); - internal_topic = false; - t = topic; - break; - } + default: { + dds_entity *p_or_s; + if ((ret = dds_entity_claim (participant_or_subscriber, &p_or_s)) != DDS_RETCODE_OK) + return ret; + if (dds_entity_kind (p_or_s) == DDS_KIND_PARTICIPANT) + subscriber = dds_create_subscriber (participant_or_subscriber, qos, NULL); + else + subscriber = participant_or_subscriber; + dds_entity_release (p_or_s); + internal_topic = false; + t = topic; + break; } + } - if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK) { - reader = ret; - goto err_sub_lock; - } + if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK) + { + reader = ret; + goto err_sub_lock; + } - if ((subscriber != participant_or_subscriber) && !internal_topic) { - /* Delete implicit subscriber if reader creation fails */ - sub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT; - } + if (subscriber != participant_or_subscriber && !internal_topic) + { + /* Delete implicit subscriber if reader creation fails */ + sub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT; + } - ret = dds_topic_lock(t, &tp); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking topic\n"); - reader = ret; - goto err_tp_lock; - } - assert (tp->m_stopic); - assert (sub->m_entity.m_domain == tp->m_entity.m_domain); + if ((ret = dds_topic_lock (t, &tp)) != DDS_RETCODE_OK) + { + reader = ret; + goto err_tp_lock; + } + assert (tp->m_stopic); + assert (sub->m_entity.m_domain == tp->m_entity.m_domain); - /* Merge qos from topic and subscriber */ - rqos = dds_create_qos (); - if (qos) { - /* Only returns failure when one of the qos args is NULL, which - * is not the case here. */ - (void)dds_copy_qos(rqos, qos); - } + /* 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 (); + if (qos) + (void) dds_copy_qos (rqos, qos); - if(sub->m_entity.m_qos){ - dds_merge_qos (rqos, sub->m_entity.m_qos); - } + if (sub->m_entity.m_qos) + dds_merge_qos (rqos, sub->m_entity.m_qos); - if (tp->m_entity.m_qos) { - dds_merge_qos (rqos, tp->m_entity.m_qos); + if (tp->m_entity.m_qos) + { + dds_merge_qos (rqos, tp->m_entity.m_qos); + /* reset the following qos policies if set during topic qos merge as they aren't applicable for reader */ + rqos->present &= ~(QP_DURABILITY_SERVICE | QP_TRANSPORT_PRIORITY | QP_LIFESPAN); + } + nn_xqos_mergein_missing (rqos, &gv.default_xqos_rd); - /* reset the following qos policies if set during topic qos merge as they aren't applicable for reader */ - rqos->present &= ~(QP_DURABILITY_SERVICE | QP_TRANSPORT_PRIORITY | QP_LIFESPAN); - } - nn_xqos_mergein_missing (rqos, &gv.default_xqos_rd); + if ((ret = dds_reader_qos_validate (rqos, false)) != DDS_RETCODE_OK) + { + dds_delete_qos (rqos); + reader = ret; + goto err_bad_qos; + } - ret = dds_reader_qos_validate (rqos, false); - if (ret != 0) { - 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 (topic, qos)) + { + dds_delete_qos (rqos); + reader = DDS_RETCODE_INCONSISTENT_POLICY; + goto err_bad_qos; + } - /* Additional checks required for built-in topics */ - if (internal_topic && !dds__validate_builtin_reader_qos(topic, qos)) { - dds_delete_qos(rqos); - DDS_ERROR("Invalid QoS specified for built-in topic reader"); - reader = DDS_RETCODE_INCONSISTENT_POLICY; - goto err_bad_qos; - } + /* Create reader and associated read cache */ + rd = dds_alloc (sizeof (*rd)); + reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, rqos, listener, DDS_READER_STATUS_MASK); + rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED; + rd->m_topic = tp; + rhc = dds_rhc_new (rd, tp->m_stopic); + dds_entity_add_ref_nolock (&tp->m_entity); + rd->m_entity.m_deriver.close = dds_reader_close; + rd->m_entity.m_deriver.delete = dds_reader_delete; + rd->m_entity.m_deriver.set_qos = dds_reader_qos_set; + rd->m_entity.m_deriver.validate_status = dds_reader_status_validate; + rd->m_entity.m_deriver.get_instance_hdl = dds_reader_instance_hdl; - /* Create reader and associated read cache */ - rd = dds_alloc (sizeof (*rd)); - reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, rqos, listener, DDS_READER_STATUS_MASK); - rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED; - rd->m_topic = tp; - rhc = dds_rhc_new (rd, tp->m_stopic); - dds_entity_add_ref_nolock (&tp->m_entity); - rd->m_entity.m_deriver.close = dds_reader_close; - rd->m_entity.m_deriver.delete = dds_reader_delete; - rd->m_entity.m_deriver.set_qos = dds_reader_qos_set; - rd->m_entity.m_deriver.validate_status = dds_reader_status_validate; - rd->m_entity.m_deriver.get_instance_hdl = dds_reader_instance_hdl; + /* Extra claim of this reader to make sure that the delete waits until DDSI + has deleted its reader as well. This can be known through the callback. */ + dds_handle_claim_inc (&rd->m_entity.m_hdllink); - /* Extra claim of this reader to make sure that the delete waits until DDSI - * has deleted its reader as well. This can be known through the callback. */ - dds_handle_claim_inc (&rd->m_entity.m_hdllink); + ddsrt_mutex_unlock (&tp->m_entity.m_mutex); + ddsrt_mutex_unlock (&sub->m_entity.m_mutex); - ddsrt_mutex_unlock(&tp->m_entity.m_mutex); - ddsrt_mutex_unlock(&sub->m_entity.m_mutex); + thread_state_awake (lookup_thread_state ()); + ret = new_reader (&rd->m_rd, &rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, rqos, rhc, dds_reader_status_cb, rd); + ddsrt_mutex_lock (&sub->m_entity.m_mutex); + ddsrt_mutex_lock (&tp->m_entity.m_mutex); + assert (ret == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */ + thread_state_asleep (lookup_thread_state ()); - thread_state_awake (lookup_thread_state ()); - ret = new_reader(&rd->m_rd, &rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, - rqos, rhc, dds_reader_status_cb, rd); - ddsrt_mutex_lock(&sub->m_entity.m_mutex); - ddsrt_mutex_lock(&tp->m_entity.m_mutex); - assert (ret == DDS_RETCODE_OK); - thread_state_asleep (lookup_thread_state ()); + /* For persistent data register reader with durability */ + if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > NN_TRANSIENT_LOCAL_DURABILITY_QOS)) { + (dds_global.m_dur_reader) (rd, rhc); + } + dds_topic_unlock (tp); + dds_subscriber_unlock (sub); - /* For persistent data register reader with durability */ - if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > NN_TRANSIENT_LOCAL_DURABILITY_QOS)) { - (dds_global.m_dur_reader) (rd, rhc); - } - dds_topic_unlock(tp); - dds_subscriber_unlock(sub); - - if (internal_topic) { - /* If topic is builtin, then the topic entity is local and should - * be deleted because the application won't. */ - dds_delete(t); - } - - return reader; + if (internal_topic) + { + /* If topic is builtin, then the topic entity is local and should be deleted because the application won't. */ + dds_delete (t); + } + return reader; err_bad_qos: - dds_topic_unlock(tp); + dds_topic_unlock (tp); err_tp_lock: - dds_subscriber_unlock(sub); - if((sub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){ - (void)dds_delete(subscriber); - } + dds_subscriber_unlock (sub); + if ((sub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0) + (void) dds_delete (subscriber); err_sub_lock: - if (internal_topic) { - /* If topic is builtin, then the topic entity is local and should - * be deleted because the application won't. */ - dds_delete(t); - } - return reader; + if (internal_topic) + dds_delete (t); + return reader; } void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb, void *cbarg) { dds_entity *dds_entity; - if (dds_entity_claim(entity, &dds_entity) != DDS_RETCODE_OK) + if (dds_entity_claim (entity, &dds_entity) != DDS_RETCODE_OK) return; - if (dds_entity_kind (dds_entity) != DDS_KIND_READER) { dds_entity_release (dds_entity); @@ -532,7 +481,7 @@ void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb while ((m = ddsrt_avl_lookup_succ_eq (&rd_writers_treedef, &rd->writers, &pwrguid)) != NULL) { /* have to be careful walking the tree -- pretty is different, but - I want to check this before I write a lookup_succ function. */ + I want to check this before I write a lookup_succ function. */ struct rd_pwr_match *m_next; nn_guid_t pwrguid_next; pwrguid = m->pwr_guid; @@ -621,169 +570,12 @@ dds_entity_t dds_get_subscriber (dds_entity_t entity) } } -dds_return_t -dds_get_subscription_matched_status ( - dds_entity_t reader, - dds_subscription_matched_status_t * status) -{ - dds_reader *rd; - dds_return_t ret; +/* Reset sets everything (type) 0, including the reason field, verify that 0 is correct */ +DDSRT_STATIC_ASSERT ((int) DDS_NOT_REJECTED == 0); - ret = dds_reader_lock(reader, &rd); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking reader\n"); - goto fail; - } - /* status = NULL, application do not need the status, but reset the counter & triggered bit */ - if (status) { - *status = rd->m_subscription_matched_status; - } - ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); - if (rd->m_entity.m_status_enable & DDS_SUBSCRIPTION_MATCHED_STATUS) { - rd->m_subscription_matched_status.total_count_change = 0; - rd->m_subscription_matched_status.current_count_change = 0; - dds_entity_status_reset(&rd->m_entity, DDS_SUBSCRIPTION_MATCHED_STATUS); - } - ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); - dds_reader_unlock(rd); -fail: - return ret; -} - -dds_return_t -dds_get_liveliness_changed_status ( - dds_entity_t reader, - dds_liveliness_changed_status_t * status) -{ - dds_reader *rd; - dds_return_t ret; - - ret = dds_reader_lock(reader, &rd); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking reader\n"); - goto fail; - } - /* status = NULL, application do not need the status, but reset the counter & triggered bit */ - if (status) { - *status = rd->m_liveliness_changed_status; - } - ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); - if (rd->m_entity.m_status_enable & DDS_LIVELINESS_CHANGED_STATUS) { - rd->m_liveliness_changed_status.alive_count_change = 0; - rd->m_liveliness_changed_status.not_alive_count_change = 0; - dds_entity_status_reset(&rd->m_entity, DDS_LIVELINESS_CHANGED_STATUS); - } - ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); - dds_reader_unlock(rd); -fail: - return ret; -} - -dds_return_t dds_get_sample_rejected_status ( - dds_entity_t reader, - dds_sample_rejected_status_t * status) -{ - dds_reader *rd; - dds_return_t ret; - - ret = dds_reader_lock(reader, &rd); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking reader\n"); - goto fail; - } - /* status = NULL, application do not need the status, but reset the counter & triggered bit */ - if (status) { - *status = rd->m_sample_rejected_status; - } - ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); - if (rd->m_entity.m_status_enable & DDS_SAMPLE_REJECTED_STATUS) { - rd->m_sample_rejected_status.total_count_change = 0; - rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED; - dds_entity_status_reset(&rd->m_entity, DDS_SAMPLE_REJECTED_STATUS); - } - ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); - dds_reader_unlock(rd); -fail: - return ret; -} - -dds_return_t dds_get_sample_lost_status ( - dds_entity_t reader, - dds_sample_lost_status_t * status) -{ - dds_reader *rd; - dds_return_t ret; - - ret = dds_reader_lock(reader, &rd); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking reader\n"); - goto fail; - } - /* status = NULL, application do not need the status, but reset the counter & triggered bit */ - if (status) { - *status = rd->m_sample_lost_status; - } - ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); - if (rd->m_entity.m_status_enable & DDS_SAMPLE_LOST_STATUS) { - rd->m_sample_lost_status.total_count_change = 0; - dds_entity_status_reset(&rd->m_entity, DDS_SAMPLE_LOST_STATUS); - } - ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); - dds_reader_unlock(rd); -fail: - return ret; -} - -dds_return_t dds_get_requested_deadline_missed_status ( - dds_entity_t reader, - dds_requested_deadline_missed_status_t * status) -{ - dds_reader *rd; - dds_return_t ret; - - ret = dds_reader_lock(reader, &rd); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking reader\n"); - goto fail; - } - /* status = NULL, application do not need the status, but reset the counter & triggered bit */ - if (status) { - *status = rd->m_requested_deadline_missed_status; - } - ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); - if (rd->m_entity.m_status_enable & DDS_REQUESTED_DEADLINE_MISSED_STATUS) { - rd->m_requested_deadline_missed_status.total_count_change = 0; - dds_entity_status_reset(&rd->m_entity, DDS_REQUESTED_DEADLINE_MISSED_STATUS); - } - ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); - dds_reader_unlock(rd); -fail: - return ret; -} - -dds_return_t dds_get_requested_incompatible_qos_status ( - dds_entity_t reader, - dds_requested_incompatible_qos_status_t * status) -{ - dds_reader *rd; - dds_return_t ret; - - ret = dds_reader_lock(reader, &rd); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking reader\n"); - goto fail; - } - /* status = NULL, application do not need the status, but reset the counter & triggered bit */ - if (status) { - *status = rd->m_requested_incompatible_qos_status; - } - ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); - if (rd->m_entity.m_status_enable & DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS) { - rd->m_requested_incompatible_qos_status.total_count_change = 0; - dds_entity_status_reset(&rd->m_entity, DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS); - } - ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); - dds_reader_unlock(rd); -fail: - return ret; -} +DDS_GET_STATUS (reader, subscription_matched, SUBSCRIPTION_MATCHED, total_count_change, current_count_change) +DDS_GET_STATUS (reader, liveliness_changed, LIVELINESS_CHANGED, alive_count_change, not_alive_count_change) +DDS_GET_STATUS (reader, sample_rejected, SAMPLE_REJECTED, total_count_change, last_reason) +DDS_GET_STATUS (reader, sample_lost, SAMPLE_LOST, total_count_change) +DDS_GET_STATUS (reader, requested_deadline_missed, REQUESTED_DEADLINE_MISSED, total_count_change) +DDS_GET_STATUS (reader, requested_incompatible_qos, REQUESTED_INCOMPATIBLE_QOS, total_count_change) diff --git a/src/core/ddsc/src/dds_stream.c b/src/core/ddsc/src/dds_stream.c index fc706d5..9593e4c 100644 --- a/src/core/ddsc/src/dds_stream.c +++ b/src/core/ddsc/src/dds_stream.c @@ -204,9 +204,7 @@ static void dds_os_put_bytes_aligned (dds_ostream_t * __restrict s, const void * static uint32_t get_type_size (enum dds_stream_typecode type) { - struct check { - char x[(DDS_OP_VAL_1BY == 1 && DDS_OP_VAL_2BY == 2 && DDS_OP_VAL_4BY == 3 && DDS_OP_VAL_8BY == 4) ? 1 : -1]; - }; + DDSRT_STATIC_ASSERT (DDS_OP_VAL_1BY == 1 && DDS_OP_VAL_2BY == 2 && DDS_OP_VAL_4BY == 3 && DDS_OP_VAL_8BY == 4); assert (type == DDS_OP_VAL_1BY || type == DDS_OP_VAL_2BY || type == DDS_OP_VAL_4BY || type == DDS_OP_VAL_8BY); return (uint32_t)1 << ((uint32_t) type - 1); } diff --git a/src/core/ddsc/src/dds_subscriber.c b/src/core/ddsc/src/dds_subscriber.c index 91efce6..907f413 100644 --- a/src/core/ddsc/src/dds_subscriber.c +++ b/src/core/ddsc/src/dds_subscriber.c @@ -11,199 +11,126 @@ */ #include #include "dds__listener.h" +#include "dds__participant.h" #include "dds__qos.h" #include "dds__subscriber.h" #include "dds/ddsi/q_entity.h" #include "dds/version.h" -DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_subscriber) +DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_subscriber) #define DDS_SUBSCRIBER_STATUS_MASK \ - DDS_DATA_ON_READERS_STATUS + (DDS_DATA_ON_READERS_STATUS) -static dds_return_t -dds_subscriber_instance_hdl( - dds_entity *e, - dds_instance_handle_t *i) +static dds_return_t dds_subscriber_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all; + +static dds_return_t dds_subscriber_instance_hdl (dds_entity *e, dds_instance_handle_t *i) { - (void)e; - (void)i; - /* TODO: Get/generate proper handle. */ - DDS_ERROR("Generating subscriber instance handle is not supported"); - return DDS_RETCODE_UNSUPPORTED; + (void) e; + (void) i; + /* FIXME: Get/generate proper handle. */ + return DDS_RETCODE_UNSUPPORTED; } -static dds_return_t -dds__subscriber_qos_validate( - const dds_qos_t *qos, - bool enabled) +static dds_return_t dds__subscriber_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; + +static dds_return_t dds__subscriber_qos_validate (const dds_qos_t *qos, bool enabled) { - dds_return_t ret = DDS_RETCODE_OK; + if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data)) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_PARTITION) && !validate_stringseq (&qos->partition)) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_PRESENTATION) && validate_presentation_qospolicy (&qos->presentation) < 0) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy (&qos->entity_factory)) + return DDS_RETCODE_INCONSISTENT_POLICY; + /* FIXME: Improve/check immutable check. */ + return (enabled && (qos->present & QP_PRESENTATION)) ? DDS_RETCODE_IMMUTABLE_POLICY : DDS_RETCODE_OK; +} - assert(qos); - - if((qos->present & QP_GROUP_DATA) && !validate_octetseq(&qos->group_data)) { - DDS_ERROR("Group data policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if((qos->present & QP_PARTITION) && !validate_stringseq(&qos->partition)) { - DDS_ERROR("Partition policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if((qos->present & QP_PRESENTATION) && validate_presentation_qospolicy(&qos->presentation)) { - DDS_ERROR("Presentation policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)) { - DDS_ERROR("Prismtech entity factory policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if(ret == DDS_RETCODE_OK && enabled && (qos->present & QP_PRESENTATION)) { - /* TODO: Improve/check immutable check. */ - DDS_ERROR("Presentation QoS policy is immutable\n"); - ret = DDS_RETCODE_IMMUTABLE_POLICY; - } +static dds_return_t dds_subscriber_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; +static dds_return_t dds_subscriber_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) +{ + /* FIXME: QoS changes. */ + dds_return_t ret; + (void) e; + if ((ret = dds__subscriber_qos_validate (qos, enabled)) != DDS_RETCODE_OK) return ret; + return (enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK); } -static dds_return_t -dds_subscriber_qos_set( - dds_entity *e, - const dds_qos_t *qos, - bool enabled) +static dds_return_t dds_subscriber_status_validate (uint32_t mask) { - dds_return_t ret = dds__subscriber_qos_validate(qos, enabled); - (void)e; - if (ret == DDS_RETCODE_OK) { - if (enabled) { - /* TODO: CHAM-95: DDSI does not support changing QoS policies. */ - DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies yet\n"); - ret = DDS_RETCODE_UNSUPPORTED; - } - } + return (mask & ~DDS_SUBSCRIBER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK; +} + +dds_entity_t dds__create_subscriber_l (dds_participant *participant, const dds_qos_t *qos, const dds_listener_t *listener) +{ + /* participant entity lock must be held */ + dds_subscriber *sub; + dds_entity_t subscriber; + dds_return_t ret; + dds_qos_t *new_qos; + + /* Validate qos */ + if (qos && (ret = dds__subscriber_qos_validate (qos, false)) != DDS_RETCODE_OK) return ret; + + if (qos == NULL) + new_qos = NULL; + else + { + new_qos = dds_create_qos (); + (void) dds_copy_qos (new_qos, qos); + } + + sub = dds_alloc (sizeof (*sub)); + subscriber = dds_entity_init (&sub->m_entity, &participant->m_entity, DDS_KIND_SUBSCRIBER, new_qos, listener, DDS_SUBSCRIBER_STATUS_MASK); + sub->m_entity.m_deriver.set_qos = dds_subscriber_qos_set; + sub->m_entity.m_deriver.validate_status = dds_subscriber_status_validate; + sub->m_entity.m_deriver.get_instance_hdl = dds_subscriber_instance_hdl; + return subscriber; } -static dds_return_t -dds_subscriber_status_validate( - uint32_t mask) +dds_entity_t dds_create_subscriber (dds_entity_t participant, const dds_qos_t *qos, const dds_listener_t *listener) { - dds_return_t ret = DDS_RETCODE_OK; - - if (mask & ~(DDS_SUBSCRIBER_STATUS_MASK)) { - DDS_ERROR("Invalid status mask\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - } - + dds_participant *par; + dds_entity_t hdl; + dds_return_t ret; + if ((ret = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK) return ret; + hdl = dds__create_subscriber_l (par, qos, listener); + dds_participant_unlock (par); + return hdl; } -dds_entity_t -dds__create_subscriber_l( - dds_entity *participant, /* entity-lock must be held */ - const dds_qos_t *qos, - const dds_listener_t *listener) +dds_return_t dds_notify_readers (dds_entity_t subscriber) { - dds_subscriber * sub; - dds_entity_t subscriber; - dds_return_t ret; - dds_qos_t * new_qos; + dds_subscriber *sub; + dds_return_t ret; - /* Validate qos */ - if (qos) { - if ((ret = dds__subscriber_qos_validate(qos, false)) != DDS_RETCODE_OK) { - goto err_param; - } - new_qos = dds_create_qos(); - /* Only returns failure when one of the qos args is NULL, which - * is not the case here. */ - (void)dds_copy_qos(new_qos, qos); - } else { - new_qos = NULL; - } - - /* Create subscriber */ - sub = dds_alloc(sizeof(*sub)); - subscriber = dds_entity_init(&sub->m_entity, participant, DDS_KIND_SUBSCRIBER, new_qos, listener, DDS_SUBSCRIBER_STATUS_MASK); - sub->m_entity.m_deriver.set_qos = dds_subscriber_qos_set; - sub->m_entity.m_deriver.validate_status = dds_subscriber_status_validate; - sub->m_entity.m_deriver.get_instance_hdl = dds_subscriber_instance_hdl; - - return subscriber; - - /* Error handling */ -err_param: + if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK) return ret; + + ret = DDS_RETCODE_UNSUPPORTED; + for (dds_entity *iter = sub->m_entity.m_children; iter; iter = iter->m_next) + { + ddsrt_mutex_lock (&iter->m_mutex); + // FIXME: check if reader has data available, call listener + ddsrt_mutex_unlock(&iter->m_mutex); + } + dds_subscriber_unlock (sub); + return ret; } -dds_entity_t -dds_create_subscriber( - dds_entity_t participant, - const dds_qos_t *qos, - const dds_listener_t *listener) +dds_return_t dds_subscriber_begin_coherent (dds_entity_t e) { - dds_entity * par; - dds_entity_t hdl; - dds_return_t errnr; - - errnr = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); - if (errnr != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking participant\n"); - hdl = errnr; - return hdl; - } - - hdl = dds__create_subscriber_l(par, qos, listener); - dds_entity_unlock(par); - - return hdl; + return dds_generic_unimplemented_operation (e, DDS_KIND_SUBSCRIBER); } -dds_return_t -dds_notify_readers( - dds_entity_t subscriber) +dds_return_t dds_subscriber_end_coherent (dds_entity_t e) { - dds_entity *iter; - dds_entity *sub; - dds_return_t ret; - - ret = dds_entity_lock(subscriber, DDS_KIND_SUBSCRIBER, &sub); - if (ret == DDS_RETCODE_OK) { - ret = DDS_RETCODE_UNSUPPORTED; - DDS_ERROR("Unsupported operation\n"); - iter = sub->m_children; - while (iter) { - ddsrt_mutex_lock(&iter->m_mutex); - // TODO: check if reader has data available, call listener - ddsrt_mutex_unlock(&iter->m_mutex); - iter = iter->m_next; - } - dds_entity_unlock(sub); - } else { - DDS_ERROR("Error occurred on locking subscriber\n"); - } - - return ret; -} - -dds_return_t -dds_subscriber_begin_coherent( - dds_entity_t e) -{ - /* TODO: CHAM-124 Currently unsupported. */ - (void)e; - DDS_ERROR("Using coherency to get a coherent data set is not currently being supported\n"); - return DDS_RETCODE_UNSUPPORTED; -} - -dds_return_t -dds_subscriber_end_coherent( - dds_entity_t e) -{ - /* TODO: CHAM-124 Currently unsupported. */ - (void)e; - DDS_ERROR("Using coherency to get a coherent data set is not currently being supported\n"); - return DDS_RETCODE_UNSUPPORTED; + return dds_generic_unimplemented_operation (e, DDS_KIND_SUBSCRIBER); } diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 384c250..13a6680 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -17,68 +17,53 @@ #include "dds__topic.h" #include "dds__listener.h" #include "dds__qos.h" +#include "dds__participant.h" #include "dds__stream.h" #include "dds__init.h" #include "dds__domain.h" +#include "dds__get_status.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/q_ddsi_discovery.h" #include "dds/ddsi/ddsi_iid.h" -DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_topic) +DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_topic) #define DDS_TOPIC_STATUS_MASK \ - DDS_INCONSISTENT_TOPIC_STATUS + (DDS_INCONSISTENT_TOPIC_STATUS) -const ddsrt_avl_treedef_t dds_topictree_def = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY -( - offsetof (struct ddsi_sertopic, avlnode), - offsetof (struct ddsi_sertopic, name_type_name), - (int (*) (const void *, const void *)) strcmp, - 0 -); - -static bool -is_valid_name( - const char *name) +static int strcmp_wrapper (const void *va, const void *vb) { - bool valid = false; - /* DDS Spec: - * | TOPICNAME - A topic name is an identifier for a topic, and is defined as any series of characters - * | 'a', ..., 'z', - * | 'A', ..., 'Z', - * | '0', ..., '9', - * | '-' but may not start with a digit. - * It is considered that '-' is an error in the spec and should say '_'. So, that's what we'll check for. - * | '/' got added for ROS2 - */ - assert(name); - if ((name[0] != '\0') && (!isdigit((unsigned char)name[0]))) { - while (isalnum((unsigned char)*name) || (*name == '_') || (*name == '/')) { - name++; - } - if (*name == '\0') { - valid = true; - } - } - - return valid; + return strcmp (va, vb); } +const ddsrt_avl_treedef_t dds_topictree_def = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct ddsi_sertopic, avlnode), offsetof (struct ddsi_sertopic, name_type_name), strcmp_wrapper, 0); -static dds_return_t -dds_topic_status_validate( - uint32_t mask) +static bool is_valid_name (const char *name) ddsrt_nonnull_all; + +static bool is_valid_name (const char *name) { - dds_return_t ret = DDS_RETCODE_OK; + /* DDS Spec: + * | TOPICNAME - A topic name is an identifier for a topic, and is defined as any series of characters + * | 'a', ..., 'z', + * | 'A', ..., 'Z', + * | '0', ..., '9', + * | '-' but may not start with a digit. + * It is considered that '-' is an error in the spec and should say '_'. So, that's what we'll check for. + * | '/' got added for ROS2 + */ + if (name[0] == '\0' || isdigit ((unsigned char) name[0])) + return false; + for (size_t i = 0; name[i]; i++) + if (!(isalnum ((unsigned char) name[i]) || name[i] == '_' || name[i] == '/')) + return false; + return true; +} - if (mask & ~(DDS_TOPIC_STATUS_MASK)) { - DDS_ERROR("Argument mask is invalid\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - } - - return ret; +static dds_return_t dds_topic_status_validate (uint32_t mask) +{ + return (mask & ~DDS_TOPIC_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK; } /* @@ -100,191 +85,135 @@ static void dds_topic_status_cb (struct dds_topic *tp) if (lst->on_inconsistent_topic) { ddsrt_mutex_unlock (&tp->m_entity.m_observers_lock); - dds_entity_invoke_listener(&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS_ID, &tp->m_inconsistent_topic_status); + dds_entity_invoke_listener (&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS_ID, &tp->m_inconsistent_topic_status); ddsrt_mutex_lock (&tp->m_entity.m_observers_lock); tp->m_inconsistent_topic_status.total_count_change = 0; } - dds_entity_status_set(&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS); + dds_entity_status_set (&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS); tp->m_entity.m_cb_count--; ddsrt_cond_broadcast (&tp->m_entity.m_observers_cond); ddsrt_mutex_unlock (&tp->m_entity.m_observers_lock); } -struct ddsi_sertopic * -dds_topic_lookup_locked( - dds_domain *domain, - const char *name) +struct ddsi_sertopic *dds_topic_lookup_locked (dds_domain *domain, const char *name) ddsrt_nonnull_all; + +struct ddsi_sertopic *dds_topic_lookup_locked (dds_domain *domain, const char *name) { - struct ddsi_sertopic *st = NULL; - ddsrt_avl_iter_t iter; - - assert (domain); - assert (name); - - st = ddsrt_avl_iter_first (&dds_topictree_def, &domain->m_topics, &iter); - while (st) { - if (strcmp (st->name, name) == 0) { - break; - } - st = ddsrt_avl_iter_next (&iter); - } - return st; + ddsrt_avl_iter_t iter; + for (struct ddsi_sertopic *st = ddsrt_avl_iter_first (&dds_topictree_def, &domain->m_topics, &iter); st; st = ddsrt_avl_iter_next (&iter)) + if (strcmp (st->name, name) == 0) + return st; + return NULL; } -struct ddsi_sertopic * -dds_topic_lookup( - dds_domain *domain, - const char *name) +struct ddsi_sertopic *dds_topic_lookup (dds_domain *domain, const char *name) { - struct ddsi_sertopic *st; - ddsrt_mutex_lock (&dds_global.m_mutex); - st = dds_topic_lookup_locked(domain, name); - ddsrt_mutex_unlock (&dds_global.m_mutex); - return st; + struct ddsi_sertopic *st; + ddsrt_mutex_lock (&dds_global.m_mutex); + st = dds_topic_lookup_locked (domain, name); + ddsrt_mutex_unlock (&dds_global.m_mutex); + return st; } -void -dds_topic_free( - dds_domainid_t domainid, - struct ddsi_sertopic *st) +void dds_topic_free (dds_domainid_t domainid, struct ddsi_sertopic *st) { - dds_domain *domain; - - assert (st); - - ddsrt_mutex_lock (&dds_global.m_mutex); - domain = ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &domainid); - if (domain != NULL) { - ddsrt_avl_delete (&dds_topictree_def, &domain->m_topics, st); - } - ddsrt_mutex_unlock (&dds_global.m_mutex); - st->status_cb_entity = NULL; - ddsi_sertopic_unref (st); + dds_domain *domain; + ddsrt_mutex_lock (&dds_global.m_mutex); + domain = ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &domainid); + if (domain != NULL) + { + assert (ddsrt_avl_lookup (&dds_topictree_def, &domain->m_topics, st->name_type_name) != NULL); + ddsrt_avl_delete (&dds_topictree_def, &domain->m_topics, st); + } + ddsrt_mutex_unlock (&dds_global.m_mutex); + st->status_cb_entity = NULL; + ddsi_sertopic_unref (st); } -static void -dds_topic_add_locked( - dds_domainid_t id, - struct ddsi_sertopic *st) +static void dds_topic_add_locked (dds_domainid_t id, struct ddsi_sertopic *st) { - dds_domain * dom; - dom = dds_domain_find_locked (id); - assert (dom); - ddsrt_avl_insert (&dds_topictree_def, &dom->m_topics, st); + dds_domain *dom = dds_domain_find_locked (id); + assert (dom); + assert (ddsrt_avl_lookup (&dds_topictree_def, &dom->m_topics, st->name_type_name) == NULL); + ddsrt_avl_insert (&dds_topictree_def, &dom->m_topics, st); } -DDS_EXPORT dds_entity_t -dds_find_topic( - dds_entity_t participant, - const char *name) +dds_entity_t dds_find_topic (dds_entity_t participant, const char *name) { - dds_entity_t tp; - dds_entity *p = NULL; - struct ddsi_sertopic *st; - dds_return_t rc; + dds_entity_t tp; + dds_participant *p; + struct ddsi_sertopic *st; + dds_return_t rc; - if (name) { - rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &p); - if (rc == DDS_RETCODE_OK) { - ddsrt_mutex_lock (&dds_global.m_mutex); - st = dds_topic_lookup_locked (p->m_domain, name); - if (st) { - /* FIXME: calling addref is wrong because the Cyclone library has no - knowledge of the reference and hence simply deleting the participant - won't make the ref count drop to 0. On the other hand, the DDS spec - says find_topic (and a second call to create_topic) return a new - proxy that must separately be deleted. */ - dds_entity_add_ref (&st->status_cb_entity->m_entity); - tp = st->status_cb_entity->m_entity.m_hdllink.hdl; - } else { - DDS_ERROR("Topic is not being created yet\n"); - tp = DDS_RETCODE_PRECONDITION_NOT_MET; - } - ddsrt_mutex_unlock (&dds_global.m_mutex); - dds_entity_unlock(p); - } else { - tp = rc; - } - } else { - DDS_ERROR("Argument name is not valid\n"); - tp = DDS_RETCODE_BAD_PARAMETER; - } + if (name == NULL) + return DDS_RETCODE_BAD_PARAMETER; - return tp; + if ((rc = dds_participant_lock (participant, &p)) != DDS_RETCODE_OK) + return rc; + + ddsrt_mutex_lock (&dds_global.m_mutex); + if ((st = dds_topic_lookup_locked (p->m_entity.m_domain, name)) == NULL) + tp = DDS_RETCODE_PRECONDITION_NOT_MET; + else + { + /* FIXME: calling addref is wrong because the Cyclone library has no + knowledge of the reference and hence simply deleting the participant + won't make the ref count drop to 0. On the other hand, the DDS spec + says find_topic (and a second call to create_topic) return a new + proxy that must separately be deleted. */ + dds_entity_add_ref (&st->status_cb_entity->m_entity); + tp = st->status_cb_entity->m_entity.m_hdllink.hdl; + } + ddsrt_mutex_unlock (&dds_global.m_mutex); + dds_participant_unlock (p); + return tp; } -static dds_return_t -dds_topic_delete( - dds_entity *e) +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_free(e->m_domainid, ((dds_topic*) e)->m_stopic); - return DDS_RETCODE_OK; + dds_topic_free (e->m_domainid, ((dds_topic *) e)->m_stopic); + return DDS_RETCODE_OK; } -static dds_return_t -dds_topic_qos_validate( - const dds_qos_t *qos, - bool enabled) -{ - dds_return_t ret = DDS_RETCODE_OK; - assert(qos); +static dds_return_t dds_topic_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; - /* Check consistency. */ - if (!dds_qos_validate_common(qos)) { - DDS_ERROR("Argument QoS is not valid\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - } - if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data)) { - DDS_ERROR("Group data QoS policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if ((qos->present & QP_DURABILITY_SERVICE) && (validate_durability_service_qospolicy(&qos->durability_service) != 0)) { - DDS_ERROR("Durability service QoS policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if ((qos->present & QP_LIFESPAN) && (validate_duration(&qos->lifespan.duration) != 0)) { - DDS_ERROR("Lifespan QoS policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if (qos->present & QP_HISTORY && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits(&qos->history, &qos->resource_limits) != 0)) { - DDS_ERROR("Lifespan QoS policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if(ret == DDS_RETCODE_OK && enabled){ - ret = dds_qos_validate_mutable_common(qos); - } +static dds_return_t dds_topic_qos_validate (const dds_qos_t *qos, bool enabled) +{ + if (!dds_qos_validate_common (qos)) + return DDS_RETCODE_BAD_PARAMETER; + if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data)) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy(&qos->durability_service) < 0) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_LIFESPAN) && validate_duration(&qos->lifespan.duration) < 0) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits(&qos->history, &qos->resource_limits) < 0) + return DDS_RETCODE_INCONSISTENT_POLICY; + return enabled ? dds_qos_validate_mutable_common(qos) : DDS_RETCODE_OK; +} + + +static dds_return_t dds_topic_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) +{ + /* FIXME: QoS changes */ + dds_return_t ret; + (void) e; + if ((ret = dds_topic_qos_validate (qos, enabled)) != DDS_RETCODE_OK) return ret; + return enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK; } - -static dds_return_t -dds_topic_qos_set( - dds_entity *e, - const dds_qos_t *qos, - bool enabled) +static bool dupdef_qos_ok (const dds_qos_t *qos, const struct ddsi_sertopic *st) { - dds_return_t ret = dds_topic_qos_validate(qos, enabled); - (void)e; - if (ret == DDS_RETCODE_OK) { - if (enabled) { - /* TODO: CHAM-95: DDSI does not support changing QoS policies. */ - DDS_ERROR("Changing the topic QoS is not supported\n"); - ret = DDS_RETCODE_UNSUPPORTED; - } - } - return ret; -} - -static bool dupdef_qos_ok(const dds_qos_t *qos, const struct ddsi_sertopic *st) -{ - if ((qos == NULL) != (st->status_cb_entity->m_entity.m_qos == NULL)) { - return false; - } else if (qos == NULL) { - return true; - } else { - return dds_qos_equal(st->status_cb_entity->m_entity.m_qos, qos); - } + if ((qos == NULL) != (st->status_cb_entity->m_entity.m_qos == NULL)) + return false; + else if (qos == NULL) + return true; + else + return dds_qos_equal (st->status_cb_entity->m_entity.m_qos, qos); } static bool sertopic_equivalent (const struct ddsi_sertopic *a, const struct ddsi_sertopic *b) @@ -300,276 +229,213 @@ static bool sertopic_equivalent (const struct ddsi_sertopic *a, const struct dds return true; } -DDS_EXPORT 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 nn_plist_t *sedp_plist) { - struct ddsi_sertopic *stgeneric; - dds_return_t rc; - dds_entity *par; - dds_topic *top; - dds_qos_t *new_qos = NULL; - dds_entity_t hdl; - struct participant *ddsi_pp; + struct ddsi_sertopic *stgeneric; + dds_return_t rc; + dds_participant *par; + dds_topic *top; + dds_qos_t *new_qos = NULL; + dds_entity_t hdl; + struct participant *ddsi_pp; - if (sertopic == NULL){ - DDS_ERROR("Topic description is NULL\n"); - hdl = DDS_RETCODE_BAD_PARAMETER; - goto bad_param_err; - } + if (sertopic == NULL) + return DDS_RETCODE_BAD_PARAMETER; - rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); - if (rc != DDS_RETCODE_OK) { - hdl = rc; - goto lock_err; - } + if (qos && (rc = dds_topic_qos_validate (qos, false)) != DDS_RETCODE_OK) + return rc; - /* Validate qos */ - if (qos) { - hdl = dds_topic_qos_validate (qos, false); - if (hdl != DDS_RETCODE_OK) { - goto qos_err; - } - } + if ((rc = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK) + return rc; - /* FIXME: I find it weird that qos may be NULL in the entity */ + /* FIXME: I find it weird that qos may be NULL in the entity */ - /* Check if topic already exists with same name */ - ddsrt_mutex_lock (&dds_global.m_mutex); - if ((stgeneric = dds_topic_lookup_locked (par->m_domain, sertopic->name)) != NULL) { - if (!sertopic_equivalent (stgeneric, sertopic)) { - /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */ - DDS_ERROR("Create topic with mismatching type\n"); - hdl = DDS_RETCODE_PRECONDITION_NOT_MET; - } else if (!dupdef_qos_ok(qos, stgeneric)) { - /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */ - DDS_ERROR("Create topic with mismatching qos\n"); - hdl = DDS_RETCODE_INCONSISTENT_POLICY; - } else { - /* FIXME: calling addref is wrong because the Cyclone library has no - knowledge of the reference and hence simply deleting the participant - won't make the ref count drop to 0. On the other hand, the DDS spec - says find_topic (and a second call to create_topic) return a new - proxy that must separately be deleted. */ - dds_entity_add_ref (&stgeneric->status_cb_entity->m_entity); - hdl = stgeneric->status_cb_entity->m_entity.m_hdllink.hdl; - } - ddsrt_mutex_unlock (&dds_global.m_mutex); + /* Check if topic already exists with same name */ + ddsrt_mutex_lock (&dds_global.m_mutex); + if ((stgeneric = dds_topic_lookup_locked (par->m_entity.m_domain, sertopic->name)) != NULL) { + if (!sertopic_equivalent (stgeneric, sertopic)) { + /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */ + rc = DDS_RETCODE_PRECONDITION_NOT_MET; + goto err_mismatch; + } else if (!dupdef_qos_ok(qos, stgeneric)) { + /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */ + rc = DDS_RETCODE_INCONSISTENT_POLICY; + goto err_mismatch; } else { - if (qos) { - new_qos = dds_create_qos(); - /* Only returns failure when one of the qos args is NULL, which - * is not the case here. */ - (void)dds_copy_qos(new_qos, qos); - } - - /* Create topic */ - top = dds_alloc (sizeof (*top)); - hdl = dds_entity_init (&top->m_entity, par, DDS_KIND_TOPIC, new_qos, listener, DDS_TOPIC_STATUS_MASK); - top->m_entity.m_deriver.delete = dds_topic_delete; - top->m_entity.m_deriver.set_qos = dds_topic_qos_set; - top->m_entity.m_deriver.validate_status = dds_topic_status_validate; - top->m_stopic = ddsi_sertopic_ref (sertopic); - sertopic->status_cb_entity = top; - - /* Add topic to extent */ - dds_topic_add_locked (par->m_domainid, sertopic); - ddsrt_mutex_unlock (&dds_global.m_mutex); - - /* Publish Topic */ - thread_state_awake (lookup_thread_state ()); - ddsi_pp = ephash_lookup_participant_guid (&par->m_guid); - assert (ddsi_pp); - if (sedp_plist) { - sedp_write_topic (ddsi_pp, sedp_plist); - } - thread_state_asleep (lookup_thread_state ()); + /* FIXME: calling addref is wrong because the Cyclone library has no + knowledge of the reference and hence simply deleting the participant + won't make the ref count drop to 0. On the other hand, the DDS spec + says find_topic (and a second call to create_topic) return a new + proxy that must separately be deleted. */ + dds_entity_add_ref (&stgeneric->status_cb_entity->m_entity); + hdl = stgeneric->status_cb_entity->m_entity.m_hdllink.hdl; + } + ddsrt_mutex_unlock (&dds_global.m_mutex); + } else { + if (qos) + { + new_qos = dds_create_qos (); + (void)dds_copy_qos (new_qos, qos); } -qos_err: - dds_entity_unlock(par); -lock_err: -bad_param_err: - return hdl; + /* Create topic */ + top = dds_alloc (sizeof (*top)); + hdl = dds_entity_init (&top->m_entity, &par->m_entity, DDS_KIND_TOPIC, new_qos, listener, DDS_TOPIC_STATUS_MASK); + top->m_entity.m_deriver.delete = dds_topic_delete; + top->m_entity.m_deriver.set_qos = dds_topic_qos_set; + top->m_entity.m_deriver.validate_status = dds_topic_status_validate; + top->m_stopic = ddsi_sertopic_ref (sertopic); + sertopic->status_cb_entity = top; + + /* Add topic to extent */ + dds_topic_add_locked (par->m_entity.m_domainid, sertopic); + ddsrt_mutex_unlock (&dds_global.m_mutex); + + /* Publish Topic */ + thread_state_awake (lookup_thread_state ()); + ddsi_pp = ephash_lookup_participant_guid (&par->m_entity.m_guid); + assert (ddsi_pp); + if (sedp_plist) + sedp_write_topic (ddsi_pp, sedp_plist); + thread_state_asleep (lookup_thread_state ()); + } + dds_participant_unlock (par); + return hdl; + +err_mismatch: + ddsrt_mutex_unlock (&dds_global.m_mutex); + dds_participant_unlock (par); + return rc; } -DDS_EXPORT 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) +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) { - char *key = NULL; - struct ddsi_sertopic_default *st; - const char *typename; - dds_qos_t *new_qos = NULL; - nn_plist_t plist; - dds_entity_t hdl; - uint32_t index; - size_t keysz; + char *key = NULL; + struct ddsi_sertopic_default *st; + const char *typename; + dds_qos_t *new_qos = NULL; + nn_plist_t plist; + dds_entity_t hdl; + size_t keysz; - if (desc == NULL){ - DDS_ERROR("Topic description is NULL"); - hdl = DDS_RETCODE_BAD_PARAMETER; - goto bad_param_err; - } + if (desc == NULL || name == NULL || !is_valid_name (name)) + return DDS_RETCODE_BAD_PARAMETER; - if (name == NULL) { - DDS_ERROR("Topic name is NULL"); - hdl = DDS_RETCODE_BAD_PARAMETER; - goto bad_param_err; - } + typename = desc->m_typename; + keysz = strlen (name) + strlen (typename) + 2; + key = dds_alloc (keysz); + (void) snprintf (key, keysz, "%s/%s", name, typename); - if (!is_valid_name(name)) { - DDS_ERROR("Topic name contains characters that are not allowed."); - hdl = DDS_RETCODE_BAD_PARAMETER; - goto bad_param_err; - } + st = dds_alloc (sizeof (*st)); - typename = desc->m_typename; - keysz = strlen (name) + strlen (typename) + 2; - key = (char*) dds_alloc (keysz); - (void) snprintf(key, keysz, "%s/%s", name, typename); + ddsrt_atomic_st32 (&st->c.refc, 1); + st->c.iid = ddsi_iid_gen (); + st->c.status_cb = dds_topic_status_cb; + st->c.status_cb_entity = NULL; /* set by dds_create_topic_arbitrary */ + st->c.name_type_name = key; + st->c.name = dds_string_dup (name); + st->c.type_name = dds_string_dup (typename); + st->c.ops = &ddsi_sertopic_ops_default; + st->c.serdata_ops = desc->m_nkeys ? &ddsi_serdata_ops_cdr : &ddsi_serdata_ops_cdr_nokey; + st->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (st->c.serdata_ops); + st->native_encoding_identifier = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE); - st = dds_alloc (sizeof (*st)); + st->type = (void*) desc; + st->nkeys = desc->m_nkeys; + st->keys = desc->m_keys; - ddsrt_atomic_st32 (&st->c.refc, 1); - st->c.iid = ddsi_iid_gen (); - st->c.status_cb = dds_topic_status_cb; - st->c.status_cb_entity = NULL; /* set by dds_create_topic_arbitrary */ - st->c.name_type_name = key; - st->c.name = dds_string_dup (name); - st->c.type_name = dds_string_dup (typename); - st->c.ops = &ddsi_sertopic_ops_default; - st->c.serdata_ops = desc->m_nkeys ? &ddsi_serdata_ops_cdr : &ddsi_serdata_ops_cdr_nokey; - st->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (st->c.serdata_ops); - st->native_encoding_identifier = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE); + /* Check if topic cannot be optimised (memcpy marshal) */ + if (!(desc->m_flagset & DDS_TOPIC_NO_OPTIMIZE)) { + st->opt_size = dds_stream_check_optimize (desc); + } - st->type = (void*) desc; - st->nkeys = desc->m_nkeys; - st->keys = desc->m_keys; + nn_plist_init_empty (&plist); + if (new_qos) + dds_merge_qos (&plist.qos, new_qos); - /* Check if topic cannot be optimised (memcpy marshal) */ - if ((desc->m_flagset & DDS_TOPIC_NO_OPTIMIZE) == 0) { - st->opt_size = dds_stream_check_optimize (desc); - } + /* Set Topic meta data (for SEDP publication) */ + plist.qos.topic_name = dds_string_dup (st->c.name); + plist.qos.type_name = dds_string_dup (st->c.type_name); + plist.qos.present |= (QP_TOPIC_NAME | QP_TYPE_NAME); + if (desc->m_meta) + { + plist.type_description = dds_string_dup (desc->m_meta); + plist.present |= PP_PRISMTECH_TYPE_DESCRIPTION; + } + if (desc->m_nkeys) + { + plist.qos.present |= QP_PRISMTECH_SUBSCRIPTION_KEYS; + plist.qos.subscription_keys.use_key_list = 1; + plist.qos.subscription_keys.key_list.n = desc->m_nkeys; + plist.qos.subscription_keys.key_list.strs = dds_alloc (desc->m_nkeys * sizeof (char*)); + for (uint32_t index = 0; index < desc->m_nkeys; index++) + plist.qos.subscription_keys.key_list.strs[index] = dds_string_dup (desc->m_keys[index].m_name); + } - nn_plist_init_empty (&plist); - if (new_qos) { - dds_merge_qos (&plist.qos, new_qos); - } - - /* Set Topic meta data (for SEDP publication) */ - plist.qos.topic_name = dds_string_dup (st->c.name); - plist.qos.type_name = dds_string_dup (st->c.type_name); - plist.qos.present |= (QP_TOPIC_NAME | QP_TYPE_NAME); - if (desc->m_meta) { - plist.type_description = dds_string_dup (desc->m_meta); - plist.present |= PP_PRISMTECH_TYPE_DESCRIPTION; - } - if (desc->m_nkeys) { - plist.qos.present |= QP_PRISMTECH_SUBSCRIPTION_KEYS; - plist.qos.subscription_keys.use_key_list = 1; - plist.qos.subscription_keys.key_list.n = desc->m_nkeys; - plist.qos.subscription_keys.key_list.strs = dds_alloc (desc->m_nkeys * sizeof (char*)); - for (index = 0; index < desc->m_nkeys; index++) { - plist.qos.subscription_keys.key_list.strs[index] = dds_string_dup (desc->m_keys[index].m_name); - } - } - - hdl = dds_create_topic_arbitrary(participant, &st->c, qos, listener, &plist); - ddsi_sertopic_unref (&st->c); - nn_plist_fini (&plist); - -bad_param_err: - return hdl; + hdl = dds_create_topic_arbitrary (participant, &st->c, qos, listener, &plist); + ddsi_sertopic_unref (&st->c); + nn_plist_fini (&plist); + return hdl; } -static bool -dds_topic_chaining_filter( - const void *sample, - void *ctx) +static bool dds_topic_chaining_filter (const void *sample, void *ctx) { - dds_topic_filter_fn realf = (dds_topic_filter_fn)ctx; - return realf (sample); + dds_topic_filter_fn realf = (dds_topic_filter_fn) ctx; + return realf (sample); } -static void -dds_topic_mod_filter( - dds_entity_t topic, - dds_topic_intern_filter_fn *filter, - void **ctx, - bool set) +static void dds_topic_mod_filter (dds_entity_t topic, dds_topic_intern_filter_fn *filter, void **ctx, bool set) { - dds_topic *t; - if (dds_topic_lock(topic, &t) == DDS_RETCODE_OK) { - if (set) { - t->filter_fn = *filter; - t->filter_ctx = *ctx; - } else { - *filter = t->filter_fn; - *ctx = t->filter_ctx; - } - dds_topic_unlock(t); + dds_topic *t; + if (dds_topic_lock (topic, &t) == DDS_RETCODE_OK) + { + if (set) { + t->filter_fn = *filter; + t->filter_ctx = *ctx; } else { - *filter = 0; - *ctx = NULL; + *filter = t->filter_fn; + *ctx = t->filter_ctx; } + dds_topic_unlock (t); + } + else + { + *filter = 0; + *ctx = NULL; + } } -void -dds_set_topic_filter( - dds_entity_t topic, - dds_topic_filter_fn filter) +void dds_set_topic_filter (dds_entity_t topic, dds_topic_filter_fn filter) { - dds_topic_intern_filter_fn chaining = dds_topic_chaining_filter; - void *realf = (void *)filter; - dds_topic_mod_filter (topic, &chaining, &realf, true); + dds_topic_intern_filter_fn chaining = dds_topic_chaining_filter; + void *realf = (void *) filter; + dds_topic_mod_filter (topic, &chaining, &realf, true); } -void -dds_topic_set_filter( - dds_entity_t topic, - dds_topic_filter_fn filter) +void dds_topic_set_filter (dds_entity_t topic, dds_topic_filter_fn filter) { - dds_set_topic_filter(topic, filter); + dds_set_topic_filter (topic, filter); } -dds_topic_filter_fn -dds_get_topic_filter( - dds_entity_t topic) +dds_topic_filter_fn dds_get_topic_filter (dds_entity_t topic) { - dds_topic_intern_filter_fn filter; - void *ctx; - dds_topic_mod_filter (topic, &filter, &ctx, false); - return (filter == dds_topic_chaining_filter) ? (dds_topic_filter_fn)ctx : 0; + dds_topic_intern_filter_fn filter; + void *ctx; + dds_topic_mod_filter (topic, &filter, &ctx, false); + return (filter == dds_topic_chaining_filter) ? (dds_topic_filter_fn) ctx : 0; } -dds_topic_filter_fn -dds_topic_get_filter( - dds_entity_t topic) +dds_topic_filter_fn dds_topic_get_filter (dds_entity_t topic) { - return dds_get_topic_filter(topic); + return dds_get_topic_filter (topic); } -void -dds_topic_set_filter_with_ctx( - dds_entity_t topic, - dds_topic_intern_filter_fn filter, - void *ctx) +void dds_topic_set_filter_with_ctx (dds_entity_t topic, dds_topic_intern_filter_fn filter, void *ctx) { dds_topic_mod_filter (topic, &filter, &ctx, true); } -dds_topic_intern_filter_fn -dds_topic_get_filter_with_ctx( - dds_entity_t topic) +dds_topic_intern_filter_fn dds_topic_get_filter_with_ctx (dds_entity_t topic) { dds_topic_intern_filter_fn filter; void *ctx; @@ -577,93 +443,32 @@ dds_topic_get_filter_with_ctx( return (filter == dds_topic_chaining_filter) ? 0 : filter; } -DDS_EXPORT dds_return_t -dds_get_name( - dds_entity_t topic, - char *name, - size_t size) +dds_return_t dds_get_name (dds_entity_t topic, char *name, size_t size) { - dds_topic *t; - dds_return_t ret; - - if(size <= 0){ - DDS_ERROR("Argument size is smaller than 0\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - goto fail; - } - if(name == NULL){ - DDS_ERROR("Argument name is NULL\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - goto fail; - } - name[0] = '\0'; - ret = dds_topic_lock(topic, &t); - if (ret == DDS_RETCODE_OK) { - (void)snprintf(name, size, "%s", t->m_stopic->name); - dds_topic_unlock(t); - } else { - DDS_ERROR("Error occurred on locking topic\n"); - goto fail; - } -fail: + dds_topic *t; + dds_return_t ret; + if (size <= 0 || name == NULL) + return DDS_RETCODE_BAD_PARAMETER; + name[0] = '\0'; + if ((ret = dds_topic_lock (topic, &t)) != DDS_RETCODE_OK) return ret; + (void) snprintf (name, size, "%s", t->m_stopic->name); + dds_topic_unlock (t); + return DDS_RETCODE_OK; } -DDS_EXPORT dds_return_t -dds_get_type_name( - dds_entity_t topic, - char *name, - size_t size) +dds_return_t dds_get_type_name (dds_entity_t topic, char *name, size_t size) { - dds_topic *t; - dds_return_t ret; - - if(size <= 0){ - DDS_ERROR("Argument size is smaller than 0\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - goto fail; - } - if(name == NULL){ - DDS_ERROR("Argument name is NULL\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - goto fail; - } - name[0] = '\0'; - ret = dds_topic_lock(topic, &t); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking topic\n"); - goto fail; - } - (void)snprintf(name, size, "%s", t->m_stopic->type_name); - dds_topic_unlock(t); -fail: + dds_topic *t; + dds_return_t ret; + if (size <= 0 || name == NULL) + return DDS_RETCODE_BAD_PARAMETER; + name[0] = '\0'; + if ((ret = dds_topic_lock (topic, &t)) != DDS_RETCODE_OK) return ret; + (void) snprintf (name, size, "%s", t->m_stopic->type_name); + dds_topic_unlock (t); + return DDS_RETCODE_OK; } -dds_return_t -dds_get_inconsistent_topic_status( - dds_entity_t topic, - dds_inconsistent_topic_status_t *status) -{ - dds_topic *t; - dds_return_t ret; - - ret = dds_topic_lock(topic, &t); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking topic\n"); - goto fail; - } - /* status = NULL, application do not need the status, but reset the counter & triggered bit */ - if (status) { - *status = t->m_inconsistent_topic_status; - } - ddsrt_mutex_lock (&t->m_entity.m_observers_lock); - if (t->m_entity.m_status_enable & DDS_INCONSISTENT_TOPIC_STATUS) { - t->m_inconsistent_topic_status.total_count_change = 0; - dds_entity_status_reset(&t->m_entity, DDS_INCONSISTENT_TOPIC_STATUS); - } - ddsrt_mutex_unlock (&t->m_entity.m_observers_lock); - dds_topic_unlock(t); -fail: - return ret; -} +DDS_GET_STATUS(topic, inconsistent_topic, INCONSISTENT_TOPIC, total_count_change) diff --git a/src/core/ddsc/src/dds_waitset.c b/src/core/ddsc/src/dds_waitset.c index 357d8fb..08cd290 100644 --- a/src/core/ddsc/src/dds_waitset.c +++ b/src/core/ddsc/src/dds_waitset.c @@ -14,424 +14,296 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" #include "dds__entity.h" +#include "dds__participant.h" #include "dds__querycond.h" #include "dds__readcond.h" #include "dds__rhc.h" -DEFINE_ENTITY_LOCK_UNLOCK(static, dds_waitset, DDS_KIND_WAITSET) +DEFINE_ENTITY_LOCK_UNLOCK (static, dds_waitset, DDS_KIND_WAITSET) -static void -dds_waitset_swap( - dds_attachment **dst, - dds_attachment **src, - dds_attachment *prev, - dds_attachment *idx) +static void dds_waitset_swap (dds_attachment **dst, dds_attachment **src, dds_attachment *prev, dds_attachment *idx) { - /* Remove from source. */ - if (prev == NULL) { - *src = idx->next; - } else { - prev->next = idx->next; - } + /* Remove from source. */ + if (prev == NULL) + *src = idx->next; + else + prev->next = idx->next; - /* Add to destination. */ - idx->next = *dst; - *dst = idx; + /* Add to destination. */ + idx->next = *dst; + *dst = idx; } -static dds_return_t -dds_waitset_wait_impl( - dds_entity_t waitset, - dds_attach_t *xs, - size_t nxs, - dds_time_t abstimeout, - dds_time_t tnow) +static dds_return_t dds_waitset_wait_impl (dds_entity_t waitset, dds_attach_t *xs, size_t nxs, dds_time_t abstimeout) { - dds_waitset *ws; - dds_return_t ret; - dds_attachment *idx; - dds_attachment *next; - dds_attachment *prev; + dds_waitset *ws; + dds_return_t ret; + dds_attachment *idx; + dds_attachment *prev; - if ((xs == NULL) && (nxs != 0)){ - DDS_ERROR("A size was given, but no array\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - if ((xs != NULL) && (nxs == 0)){ - DDS_ERROR("Array is given with an invalid size\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - - /* Locking the waitset here will delay a possible deletion until it is - * unlocked. Even when the related mutex is unlocked by a conditioned wait. */ - ret = dds_waitset_lock(waitset, &ws); - if (ret == DDS_RETCODE_OK) { - /* Check if any of any previous triggered entities has changed there status - * and thus it trigger value could be false now. */ - idx = ws->triggered; - prev = NULL; - while (idx != NULL) { - next = idx->next; - if (idx->entity->m_trigger == 0) { - /* Move observed entity to triggered list. */ - dds_waitset_swap(&(ws->observed), &(ws->triggered), prev, idx); - } else { - prev = idx; - } - idx = next; - } - /* Check if any of the entities have been triggered. */ - idx = ws->observed; - prev = NULL; - while (idx != NULL) { - next = idx->next; - if (idx->entity->m_trigger > 0) { - /* Move observed entity to triggered list. */ - dds_waitset_swap(&(ws->triggered), &(ws->observed), prev, idx); - } else { - prev = idx; - } - idx = next; - } - - /* Only wait/keep waiting when whe have something to observer and there aren't any triggers yet. */ - while ((ws->observed != NULL) && (ws->triggered == NULL) && (ret == DDS_RETCODE_OK)) { - if (abstimeout == DDS_NEVER) { - ddsrt_cond_wait(&ws->m_entity.m_cond, &ws->m_entity.m_mutex); - } else if (abstimeout <= tnow) { - ret = DDS_RETCODE_TIMEOUT; - } else { - dds_duration_t dt = abstimeout - tnow; - (void)ddsrt_cond_waitfor(&ws->m_entity.m_cond, &ws->m_entity.m_mutex, dt); - tnow = dds_time(); - } - } - - /* Get number of triggered entities - * - set attach array when needed - * - swap them back to observed */ - if (ret == DDS_RETCODE_OK) { - ret = 0; - idx = ws->triggered; - while (idx != NULL) { - if ((uint32_t)ret < (uint32_t)nxs) { - xs[ret] = idx->arg; - } - ret++; - - next = idx->next; - /* The idx is always the first in triggered, so no prev. */ - dds_waitset_swap(&(ws->observed), &(ws->triggered), NULL, idx); - idx = next; - } - } else if (ret == DDS_RETCODE_TIMEOUT) { - ret = 0; - } else { - DDS_ERROR("Internal error"); - } - - dds_waitset_unlock(ws); - } else { - DDS_ERROR("Error occurred on locking waitset\n"); - } + if (xs == NULL && nxs != 0) + return DDS_RETCODE_BAD_PARAMETER; + if (xs != NULL && nxs == 0) + return DDS_RETCODE_BAD_PARAMETER; + /* Locking the waitset here will delay a possible deletion until it is + * unlocked. Even when the related mutex is unlocked by a conditioned wait. */ + if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK) return ret; + + /* Move any previously but no longer triggering entities back to the observed list */ + idx = ws->triggered; + prev = NULL; + while (idx != NULL) + { + dds_attachment *next = idx->next; + if (idx->entity->m_trigger == 0) + dds_waitset_swap (&ws->observed, &ws->triggered, prev, idx); + else + prev = idx; + idx = next; + } + /* Check if any of the observed entities are currently triggered, moving them + to the triggered list */ + idx = ws->observed; + prev = NULL; + while (idx != NULL) + { + dds_attachment *next = idx->next; + if (idx->entity->m_trigger > 0) + dds_waitset_swap (&ws->triggered, &ws->observed, prev, idx); + else + prev = idx; + idx = next; + } + + /* Only wait/keep waiting when we have something to observe and there aren't any triggers yet. */ + while (ws->observed != NULL && ws->triggered == NULL) + if (!ddsrt_cond_waituntil (&ws->m_entity.m_cond, &ws->m_entity.m_mutex, abstimeout)) + break; + + /* Get number of triggered entities + * - set attach array when needed + * - swap them back to observed */ + ret = 0; + idx = ws->triggered; + while (idx != NULL) + { + if ((uint32_t) ret < (uint32_t) nxs) + xs[ret] = idx->arg; + ret++; + + /* The idx is always the first in triggered, so no prev. */ + dds_attachment *next = idx->next; + dds_waitset_swap (&ws->observed, &ws->triggered, NULL, idx); + idx = next; + } + dds_waitset_unlock (ws); + return ret; } -static void -dds_waitset_close_list( - dds_attachment **list, - dds_entity_t waitset) +static void dds_waitset_close_list (dds_attachment **list, dds_entity_t waitset) { - dds_attachment *idx = *list; - dds_attachment *next; - while (idx != NULL) { - next = idx->next; - (void)dds_entity_observer_unregister(idx->entity->m_hdllink.hdl, waitset); - ddsrt_free(idx); - idx = next; - } - *list = NULL; + dds_attachment *idx = *list; + dds_attachment *next; + while (idx != NULL) + { + next = idx->next; + (void) dds_entity_observer_unregister (idx->entity->m_hdllink.hdl, waitset); + ddsrt_free (idx); + idx = next; + } + *list = NULL; } -static bool -dds_waitset_remove_from_list( - dds_attachment **list, - dds_entity_t observed) +static bool dds_waitset_remove_from_list (dds_attachment **list, dds_entity_t observed) { - dds_attachment *idx = *list; - dds_attachment *prev = NULL; - - while (idx != NULL) { - if (idx->entity->m_hdllink.hdl == observed) { - if (prev == NULL) { - *list = idx->next; - } else { - prev->next = idx->next; - } - ddsrt_free(idx); - - /* We're done. */ - return true; - } - prev = idx; - idx = idx->next; - } + dds_attachment *idx, *prev; + for (idx = *list, prev = NULL; idx != NULL; prev = idx, idx = idx->next) + if (idx->entity->m_hdllink.hdl == observed) + break; + if (idx == NULL) return false; + + if (prev == NULL) + *list = idx->next; + else + prev->next = idx->next; + ddsrt_free (idx); + return true; } -dds_return_t -dds_waitset_close( - struct dds_entity *e) +dds_return_t dds_waitset_close (struct dds_entity *e) { - dds_waitset *ws = (dds_waitset*)e; - - dds_waitset_close_list(&ws->observed, e->m_hdllink.hdl); - dds_waitset_close_list(&ws->triggered, e->m_hdllink.hdl); - - /* Trigger waitset to wake up. */ - ddsrt_cond_broadcast(&e->m_cond); - - return DDS_RETCODE_OK; + dds_waitset *ws = (dds_waitset *) e; + dds_waitset_close_list (&ws->observed, e->m_hdllink.hdl); + dds_waitset_close_list (&ws->triggered, e->m_hdllink.hdl); + ddsrt_cond_broadcast (&e->m_cond); + return DDS_RETCODE_OK; } -DDS_EXPORT dds_entity_t -dds_create_waitset( - dds_entity_t participant) +dds_entity_t dds_create_waitset (dds_entity_t participant) { - dds_entity_t hdl; - dds_entity *par; - dds_return_t rc; + dds_entity_t hdl; + dds_participant *par; + dds_return_t rc; - rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); - if (rc == DDS_RETCODE_OK) { - dds_waitset *waitset = dds_alloc(sizeof(*waitset)); - hdl = dds_entity_init(&waitset->m_entity, par, DDS_KIND_WAITSET, NULL, NULL, 0); - waitset->m_entity.m_deriver.close = dds_waitset_close; - waitset->observed = NULL; - waitset->triggered = NULL; - dds_entity_unlock(par); - } else { - hdl = rc; - } + if ((rc = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK) + return rc; - return hdl; + dds_waitset *waitset = dds_alloc (sizeof (*waitset)); + hdl = dds_entity_init (&waitset->m_entity, &par->m_entity, DDS_KIND_WAITSET, NULL, NULL, 0); + waitset->m_entity.m_deriver.close = dds_waitset_close; + waitset->observed = NULL; + waitset->triggered = NULL; + dds_participant_unlock (par); + return hdl; } -DDS_EXPORT dds_return_t -dds_waitset_get_entities( - dds_entity_t waitset, - dds_entity_t *entities, - size_t size) +dds_return_t dds_waitset_get_entities (dds_entity_t waitset, dds_entity_t *entities, size_t size) { - dds_return_t ret; - dds_waitset *ws; - - ret = dds_waitset_lock(waitset, &ws); - if (ret == DDS_RETCODE_OK) { - dds_attachment* iter; - - ret = 0; - iter = ws->observed; - while (iter) { - if (((size_t)ret < size) && (entities != NULL)) { - entities[ret] = iter->entity->m_hdllink.hdl; - } - ret++; - iter = iter->next; - } - - iter = ws->triggered; - while (iter) { - if (((size_t)ret < size) && (entities != NULL)) { - entities[ret] = iter->entity->m_hdllink.hdl; - } - ret++; - iter = iter->next; - } - dds_waitset_unlock(ws); - } else { - DDS_ERROR("Error occurred on locking waitset\n"); - } + dds_return_t ret; + dds_waitset *ws; + if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK) return ret; + + ret = 0; + for (dds_attachment *iter = ws->observed; iter != NULL; iter = iter->next) + { + if ((size_t) ret < size && entities != NULL) + entities[ret] = iter->entity->m_hdllink.hdl; + ret++; + } + for (dds_attachment *iter = ws->triggered; iter != NULL; iter = iter->next) + { + if ((size_t) ret < size && entities != NULL) + entities[ret] = iter->entity->m_hdllink.hdl; + ret++; + } + dds_waitset_unlock(ws); + return ret; } - -static void -dds_waitset_move( - dds_attachment **src, - dds_attachment **dst, - dds_entity_t entity) +static void dds_waitset_move (dds_attachment **src, dds_attachment **dst, dds_entity_t entity) { - dds_attachment *idx = *src; - dds_attachment *prev = NULL; - while (idx != NULL) { - if (idx->entity->m_hdllink.hdl == entity) { - /* Swap idx from src to dst. */ - dds_waitset_swap(dst, src, prev, idx); - - /* We're done. */ - return; - } - prev = idx; - idx = idx->next; - } + dds_attachment *idx, *prev; + for (idx = *src, prev = NULL; idx != NULL; prev = idx, idx = idx->next) + if (idx->entity->m_hdllink.hdl == entity) + break; + if (idx != NULL) + { + /* Swap idx from src to dst. */ + dds_waitset_swap (dst, src, prev, idx); + } } -static void -dds_waitset_remove( - dds_waitset *ws, - dds_entity_t observed) +static void dds_waitset_remove (dds_waitset *ws, dds_entity_t observed) { - if (!dds_waitset_remove_from_list(&(ws->observed), observed)) { - (void)dds_waitset_remove_from_list(&(ws->triggered), observed); - } + if (!dds_waitset_remove_from_list (&ws->observed, observed)) + (void) dds_waitset_remove_from_list (&ws->triggered, observed); } /* This is called when the observed entity signals a status change. */ -void -dds_waitset_observer( - dds_entity_t observer, - dds_entity_t observed, - uint32_t status) +void dds_waitset_observer (dds_entity_t observer, dds_entity_t observed, uint32_t status) { - dds_waitset *ws; - if (dds_waitset_lock(observer, &ws) == DDS_RETCODE_OK) { - if (status & DDS_DELETING_STATUS) { - /* Remove this observed entity, which is being deleted, from the waitset. */ - dds_waitset_remove(ws, observed); - /* Our registration to this observed entity will be removed automatically. */ - } else if (status != 0) { - /* Move observed entity to triggered list. */ - dds_waitset_move(&(ws->observed), &(ws->triggered), observed); - } else { - /* Remove observed entity from triggered list (which it possibly resides in). */ - dds_waitset_move(&(ws->triggered), &(ws->observed), observed); - } - /* Trigger waitset to wake up. */ - ddsrt_cond_broadcast(&ws->m_entity.m_cond); - dds_waitset_unlock(ws); - } -} - -DDS_EXPORT dds_return_t -dds_waitset_attach( - dds_entity_t waitset, - dds_entity_t entity, - dds_attach_t x) -{ - dds_entity *e = NULL; - dds_waitset *ws; - dds_return_t ret; - - ret = dds_waitset_lock(waitset, &ws); - if (ret == DDS_RETCODE_OK) { - if (waitset != entity) { - ret = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e); - if (ret != DDS_RETCODE_OK) { - e = NULL; - } - } else { - e = &ws->m_entity; - } - - /* This will fail if given entity is already attached (or deleted). */ - if (ret == DDS_RETCODE_OK) { - ret = dds_entity_observer_register_nl(e, waitset, dds_waitset_observer); - } - - if (ret == DDS_RETCODE_OK) { - dds_attachment *a = ddsrt_malloc(sizeof(dds_attachment)); - a->arg = x; - a->entity = e; - if (e->m_trigger > 0) { - a->next = ws->triggered; - ws->triggered = a; - } else { - a->next = ws->observed; - ws->observed = a; - } - ret = DDS_RETCODE_OK; - } else if (ret != DDS_RETCODE_PRECONDITION_NOT_MET) { - DDS_ERROR("Entity is not valid\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - } else { - DDS_ERROR("Entity is already attached\n"); - } - if ((e != NULL) && (waitset != entity)) { - dds_entity_unlock(e); - } - dds_waitset_unlock(ws); + dds_waitset *ws; + if (dds_waitset_lock (observer, &ws) == DDS_RETCODE_OK) { + if (status & DDS_DELETING_STATUS) { + /* Remove this observed entity, which is being deleted, from the waitset. */ + dds_waitset_remove (ws, observed); + /* Our registration to this observed entity will be removed automatically. */ + } else if (status != 0) { + /* Move observed entity to triggered list. */ + dds_waitset_move (&ws->observed, &ws->triggered, observed); } else { - DDS_ERROR("Error occurred on locking waitset\n"); + /* Remove observed entity from triggered list (which it possibly resides in). */ + dds_waitset_move (&ws->triggered, &ws->observed, observed); } - - return ret; + /* Trigger waitset to wake up. */ + ddsrt_cond_broadcast (&ws->m_entity.m_cond); + dds_waitset_unlock (ws); + } } -DDS_EXPORT dds_return_t -dds_waitset_detach( - dds_entity_t waitset, - dds_entity_t entity) +dds_return_t dds_waitset_attach (dds_entity_t waitset, dds_entity_t entity, dds_attach_t x) { - dds_waitset *ws; - dds_return_t ret; - - ret = dds_waitset_lock(waitset, &ws); - if (ret == DDS_RETCODE_OK) { - /* Possibly fails when entity was not attached. */ - if (waitset == entity) { - ret = dds_entity_observer_unregister_nl(&ws->m_entity, waitset); - } else { - ret = dds_entity_observer_unregister(entity, waitset); - } - if (ret == DDS_RETCODE_OK) { - dds_waitset_remove(ws, entity); - } else if (ret != DDS_RETCODE_PRECONDITION_NOT_MET) { - DDS_ERROR("The given entity to detach is invalid\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - } else { - DDS_ERROR("The given entity to detach was not attached previously\n"); - } - dds_waitset_unlock(ws); - } else { - DDS_ERROR("Error occurred on locking waitset\n"); - } + dds_entity *e; + dds_waitset *ws; + dds_return_t ret; + if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK) return ret; + + if (waitset == entity) + e = &ws->m_entity; + else if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + { + ret = DDS_RETCODE_BAD_PARAMETER; + goto err_waitset; + } + + /* This will fail if given entity is already attached (or deleted). */ + if ((ret = dds_entity_observer_register_nl (e, waitset, dds_waitset_observer)) != DDS_RETCODE_OK) + goto err_entity; + + dds_attachment *a = ddsrt_malloc (sizeof (*a)); + a->arg = x; + a->entity = e; + if (e->m_trigger > 0) { + a->next = ws->triggered; + ws->triggered = a; + } else { + a->next = ws->observed; + ws->observed = a; + } + +err_entity: + if (e != &ws->m_entity) + dds_entity_unlock (e); +err_waitset: + dds_waitset_unlock (ws); + return ret; } -dds_return_t -dds_waitset_wait_until( - dds_entity_t waitset, - dds_attach_t *xs, - size_t nxs, - dds_time_t abstimeout) +dds_return_t dds_waitset_detach (dds_entity_t waitset, dds_entity_t entity) { - return dds_waitset_wait_impl(waitset, xs, nxs, abstimeout, dds_time()); + dds_waitset *ws; + dds_return_t ret; + + if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK) + return ret; + + /* Possibly fails when entity was not attached. */ + if (waitset == entity) + ret = dds_entity_observer_unregister_nl (&ws->m_entity, waitset); + else + ret = dds_entity_observer_unregister (entity, waitset); + + if (ret == DDS_RETCODE_OK) + dds_waitset_remove (ws, entity); + else + { + if (ret != DDS_RETCODE_PRECONDITION_NOT_MET) + ret = DDS_RETCODE_BAD_PARAMETER; + } + dds_waitset_unlock (ws); + return ret; } -dds_return_t -dds_waitset_wait( - dds_entity_t waitset, - dds_attach_t *xs, - size_t nxs, - dds_duration_t reltimeout) +dds_return_t dds_waitset_wait_until (dds_entity_t waitset, dds_attach_t *xs, size_t nxs, dds_time_t abstimeout) { - dds_entity_t ret; + return dds_waitset_wait_impl(waitset, xs, nxs, abstimeout); +} - if (reltimeout >= 0) { - dds_time_t tnow = dds_time(); - dds_time_t abstimeout = (DDS_INFINITY - reltimeout <= tnow) ? DDS_NEVER : (tnow + reltimeout); - ret = dds_waitset_wait_impl(waitset, xs, nxs, abstimeout, tnow); - } else{ - DDS_ERROR("Negative timeout\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - } - - return ret; +dds_return_t dds_waitset_wait (dds_entity_t waitset, dds_attach_t *xs, size_t nxs, dds_duration_t reltimeout) +{ + if (reltimeout < 0) + return DDS_RETCODE_BAD_PARAMETER; + const dds_time_t tnow = dds_time (); + const dds_time_t abstimeout = (DDS_INFINITY - reltimeout <= tnow) ? DDS_NEVER : (tnow + reltimeout); + return dds_waitset_wait_impl (waitset, xs, nxs, abstimeout); } dds_return_t dds_waitset_set_trigger (dds_entity_t waitset, bool trigger) @@ -455,4 +327,3 @@ dds_return_t dds_waitset_set_trigger (dds_entity_t waitset, bool trigger) dds_waitset_unlock (ws); return DDS_RETCODE_OK; } - diff --git a/src/core/ddsc/src/dds_whc.c b/src/core/ddsc/src/dds_whc.c index 2992990..1c29649 100644 --- a/src/core/ddsc/src/dds_whc.c +++ b/src/core/ddsc/src/dds_whc.c @@ -35,7 +35,7 @@ struct whc_node { struct whc_node *next_seq; /* next in this interval */ struct whc_node *prev_seq; /* prev in this interval */ struct whc_idxnode *idxnode; /* NULL if not in index */ - unsigned idxnode_pos; /* index in idxnode.hist */ + uint32_t idxnode_pos; /* index in idxnode.hist */ seqno_t seq; uint64_t total_bytes; /* cumulative number of bytes up to and including this node */ size_t size; @@ -43,7 +43,7 @@ struct whc_node { 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; - unsigned rexmit_count; + uint32_t rexmit_count; struct ddsi_serdata *serdata; }; @@ -59,7 +59,7 @@ struct whc_idxnode { uint64_t iid; seqno_t prune_seq; struct ddsi_tkmap_instance *tk; - unsigned headidx; + uint32_t headidx; #if __STDC_VERSION__ >= 199901L struct whc_node *hist[]; #else @@ -77,14 +77,14 @@ struct whc_seq_entry { struct whc_impl { struct whc common; ddsrt_mutex_t lock; - unsigned seq_size; + uint32_t seq_size; size_t unacked_bytes; size_t sample_overhead; uint64_t total_bytes; /* total number of bytes pushed in */ unsigned is_transient_local: 1; - unsigned hdepth; /* 0 = unlimited */ - unsigned tldepth; /* 0 = disabled/unlimited (no need to maintain an index if KEEP_ALL <=> is_transient_local + tldepth=0) */ - unsigned idxdepth; /* = max(hdepth, tldepth) */ + 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) */ 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 */ @@ -103,14 +103,12 @@ struct whc_sample_iter_impl { }; /* check that our definition of whc_sample_iter fits in the type that callers allocate */ -struct whc_sample_iter_sizecheck { - char fits_in_generic_type[sizeof(struct whc_sample_iter_impl) <= sizeof(struct whc_sample_iter) ? 1 : -1]; -}; +DDSRT_STATIC_ASSERT (sizeof (struct whc_sample_iter_impl) <= sizeof (struct whc_sample_iter)); /* Hash + interval tree adminitration of samples-by-sequence number * - by definition contains all samples in WHC (unchanged from older versions) * Circular array of samples per instance, inited to all 0 - * - length is max(durability_service.history_depth, history.depth), KEEP_ALL => as-if 0 + * - length is max (durability_service.history_depth, history.depth), KEEP_ALL => as-if 0 * - no instance index if above length 0 * - each sample (i.e., whc_node): backpointer into index * - maintain index of latest sample, end of history then trivially follows from index arithmetic @@ -124,24 +122,24 @@ static void insert_whcn_in_hash (struct whc_impl *whc, struct whc_node *whcn); static void whc_delete_one (struct whc_impl *whc, struct whc_node *whcn); static int compare_seq (const void *va, const void *vb); static void free_deferred_free_list (struct whc_node *deferred_free_list); -static void get_state_locked(const struct whc_impl *whc, struct whc_state *st); +static void get_state_locked (const struct whc_impl *whc, struct whc_state *st); -static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list); -static unsigned whc_default_remove_acked_messages (struct whc *whc, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list); +static uint32_t whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list); +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 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, struct nn_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); static void whc_default_return_sample (struct whc *whc, struct whc_borrowed_sample *sample, bool update_retransmit_info); -static unsigned whc_default_downgrade_to_volatile (struct whc *whc, struct whc_state *st); +static uint32_t whc_default_downgrade_to_volatile (struct whc *whc, struct whc_state *st); static void whc_default_sample_iter_init (const struct whc *whc, struct whc_sample_iter *opaque_it); static bool whc_default_sample_iter_borrow_next (struct whc_sample_iter *opaque_it, struct whc_borrowed_sample *sample); static void whc_default_free (struct whc *whc); static const ddsrt_avl_treedef_t whc_seq_treedef = - DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct whc_intvnode, avlnode), offsetof (struct whc_intvnode, min), compare_seq, 0); +DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct whc_intvnode, avlnode), offsetof (struct whc_intvnode, min), compare_seq, 0); static const struct whc_ops whc_ops = { .insert = whc_default_insert, @@ -159,12 +157,12 @@ static const struct whc_ops whc_ops = { }; /* Number of instantiated WHCs and a global freelist for WHC nodes that gets - initialized lazily and cleaned up automatically when the last WHC is freed. - Protected by dds_global.m_mutex. + initialized lazily and cleaned up automatically when the last WHC is freed. + Protected by dds_global.m_mutex. - sizeof (whc_node) on 64-bit machines ~ 100 bytes, so this is ~1MB - 8k entries seems to be roughly the amount needed for minimum samples, - maximum message size and a short round-trip time */ + sizeof (whc_node) on 64-bit machines ~ 100 bytes, so this is ~1MB + 8k entries seems to be roughly the amount needed for minimum samples, + maximum message size and a short round-trip time */ #define MAX_FREELIST_SIZE 8192 static uint32_t whc_count; static struct nn_freelist whc_node_freelist; @@ -175,9 +173,9 @@ static uint32_t whc_seq_entry_hash (const void *vn) const struct whc_seq_entry *n = vn; /* we hash the lower 32 bits, on the assumption that with 4 billion samples in between there won't be significant correlation */ - const uint64_t c = UINT64_C(16292676669999574021); + const uint64_t c = UINT64_C (16292676669999574021); const uint32_t x = (uint32_t) n->seq; - return (unsigned) ((x * c) >> 32); + return (uint32_t) ((x * c) >> 32); } static int whc_seq_entry_eq (const void *va, const void *vb) @@ -192,9 +190,9 @@ static uint32_t whc_node_hash (const void *vn) const struct whc_node *n = vn; /* we hash the lower 32 bits, on the assumption that with 4 billion samples in between there won't be significant correlation */ - const uint64_t c = UINT64_C(16292676669999574021); + const uint64_t c = UINT64_C (16292676669999574021); const uint32_t x = (uint32_t) n->seq; - return (unsigned) ((x * c) >> 32); + return (uint32_t) ((x * c) >> 32); } static int whc_node_eq (const void *va, const void *vb) @@ -245,10 +243,10 @@ static struct whc_node *whc_findmax_procedurally (const struct whc_impl *whc) static void check_whc (const struct whc_impl *whc) { /* there's much more we can check, but it gets expensive quite - quickly: all nodes but open_intv non-empty, non-overlapping and - non-contiguous; min & maxp1 of intervals correct; each interval - contiguous; all samples in seq & in seqhash; tlidx \subseteq seq; - seq-number ordered list correct; &c. */ + quickly: all nodes but open_intv non-empty, non-overlapping and + non-contiguous; min & maxp1 of intervals correct; each interval + contiguous; all samples in seq & in seqhash; tlidx \subseteq seq; + seq-number ordered list correct; &c. */ assert (whc->open_intv != NULL); assert (whc->open_intv == ddsrt_avl_find_max (&whc_seq_treedef, &whc->seq)); assert (ddsrt_avl_find_succ (&whc_seq_treedef, &whc->seq, whc->open_intv) == NULL); @@ -269,7 +267,7 @@ static void check_whc (const struct whc_impl *whc) } assert (whc->maxseq_node == whc_findmax_procedurally (whc)); -#if !defined(NDEBUG) +#if !defined (NDEBUG) if (config.enabled_xchecks & DDS_XCHECK_WHC) { struct whc_intvnode *firstintv; @@ -295,10 +293,10 @@ static void insert_whcn_in_hash (struct whc_impl *whc, struct whc_node *whcn) #if USE_EHH struct whc_seq_entry e = { .seq = whcn->seq, .whcn = whcn }; if (!ddsrt_ehh_add (whc->seq_hash, &e)) - assert(0); + assert (0); #else if (!ddsrt_hh_add (whc->seq_hash, whcn)) - assert(0); + assert (0); #endif } @@ -307,11 +305,11 @@ static void remove_whcn_from_hash (struct whc_impl *whc, struct whc_node *whcn) /* precondition: whcn is in hash */ #if USE_EHH struct whc_seq_entry e = { .seq = whcn->seq }; - if (!ddsrt_ehh_remove(whc->seq_hash, &e)) - assert(0); + if (!ddsrt_ehh_remove (whc->seq_hash, &e)) + assert (0); #else - if (!ddsrt_hh_remove(whc->seq_hash, whcn)) - assert(0); + if (!ddsrt_hh_remove (whc->seq_hash, whcn)) + assert (0); #endif } @@ -319,14 +317,14 @@ static struct whc_node *whc_findseq (const struct whc_impl *whc, seqno_t seq) { #if USE_EHH struct whc_seq_entry e = { .seq = seq }, *r; - if ((r = ddsrt_ehh_lookup(whc->seq_hash, &e)) != NULL) + if ((r = ddsrt_ehh_lookup (whc->seq_hash, &e)) != NULL) return r->whcn; else return NULL; #else struct whc_node template; template.seq = seq; - return ddsrt_hh_lookup(whc->seq_hash, &template); + return ddsrt_hh_lookup (whc->seq_hash, &template); #endif } @@ -334,11 +332,11 @@ static struct whc_node *whc_findkey (const struct whc_impl *whc, const struct dd { union { struct whc_idxnode idxn; - char pad[sizeof(struct whc_idxnode) + sizeof(struct whc_node *)]; + char pad[sizeof (struct whc_idxnode) + sizeof (struct whc_node *)]; } template; struct whc_idxnode *n; check_whc (whc); - template.idxn.iid = ddsi_tkmap_lookup(gv.m_tkmap, serdata_key); + template.idxn.iid = ddsi_tkmap_lookup (gv.m_tkmap, serdata_key); n = ddsrt_hh_lookup (whc->idx_hash, &template.idxn); if (n == NULL) return NULL; @@ -349,13 +347,13 @@ static struct whc_node *whc_findkey (const struct whc_impl *whc, const struct dd } } -struct whc *whc_new (int is_transient_local, unsigned hdepth, unsigned tldepth) +struct whc *whc_new (int is_transient_local, uint32_t hdepth, uint32_t tldepth) { 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 ((hdepth == 0 || tldepth <= hdepth) || is_transient_local); whc = ddsrt_malloc (sizeof (*whc)); whc->common.ops = &whc_ops; @@ -372,11 +370,11 @@ struct whc *whc_new (int is_transient_local, unsigned hdepth, unsigned tldepth) #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(32, whc_node_hash, whc_node_eq); + whc->seq_hash = ddsrt_hh_new (32, whc_node_hash, whc_node_eq); #endif if (whc->idxdepth > 0) - whc->idx_hash = ddsrt_hh_new(32, whc_idxnode_hash_key, whc_idxnode_eq_key); + whc->idx_hash = ddsrt_hh_new (32, whc_idxnode_hash_key, whc_idxnode_eq_key); else whc->idx_hash = NULL; @@ -417,9 +415,9 @@ void whc_default_free (struct whc *whc_generic) { 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); + 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); } { @@ -427,10 +425,10 @@ void whc_default_free (struct whc *whc_generic) while (whcn) { struct whc_node *tmp = whcn; -/* The compiler doesn't realize that whcn->prev_seq is always initialized. */ -DDSRT_WARNING_MSVC_OFF(6001); + /* The compiler doesn't realize that whcn->prev_seq is always initialized. */ + DDSRT_WARNING_MSVC_OFF (6001); whcn = whcn->prev_seq; -DDSRT_WARNING_MSVC_ON(6001); + DDSRT_WARNING_MSVC_ON (6001); free_whc_node_contents (tmp); ddsrt_free (tmp); } @@ -452,7 +450,7 @@ DDSRT_WARNING_MSVC_ON(6001); ddsrt_free (whc); } -static void get_state_locked(const struct whc_impl *whc, struct whc_state *st) +static void get_state_locked (const struct whc_impl *whc, struct whc_state *st) { if (whc->seq_size == 0) { @@ -473,12 +471,12 @@ static void get_state_locked(const struct whc_impl *whc, struct whc_state *st) } } -static void whc_default_get_state(const struct whc *whc_generic, struct whc_state *st) +static void whc_default_get_state (const struct whc *whc_generic, struct whc_state *st) { const struct whc_impl * const whc = (const struct whc_impl *)whc_generic; ddsrt_mutex_lock ((ddsrt_mutex_t *)&whc->lock); check_whc (whc); - get_state_locked(whc, st); + get_state_locked (whc, st); ddsrt_mutex_unlock ((ddsrt_mutex_t *)&whc->lock); } @@ -489,8 +487,8 @@ static struct whc_node *find_nextseq_intv (struct whc_intvnode **p_intv, const s if ((n = whc_findseq (whc, seq)) == NULL) { /* don't know seq => lookup interval with min > seq (intervals are - contiguous, so if we don't know seq, an interval [X,Y) with X < - SEQ < Y can't exist */ + contiguous, so if we don't know seq, an interval [X,Y) with X < + SEQ < Y can't exist */ #ifndef NDEBUG { struct whc_intvnode *predintv = ddsrt_avl_lookup_pred_eq (&whc_seq_treedef, &whc->seq, &seq); @@ -551,13 +549,12 @@ static void delete_one_sample_from_idx (struct whc_impl *whc, struct whc_node *w else { #ifndef NDEBUG - unsigned i; - for (i = 0; i < whc->idxdepth; i++) + 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(idxn->tk); + ddsi_tkmap_instance_unref (idxn->tk); ddsrt_free (idxn); } whcn->idxnode = NULL; @@ -565,8 +562,7 @@ static void delete_one_sample_from_idx (struct whc_impl *whc, struct whc_node *w static void free_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_idxnode *idxn) { - unsigned i; - for (i = 0; i < whc->idxdepth; i++) + for (uint32_t i = 0; i < whc->idxdepth; i++) { if (idxn->hist[i]) { @@ -574,13 +570,13 @@ static void free_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_s oldn->idxnode = NULL; if (oldn->seq <= max_drop_seq) { - DDS_LOG(DDS_LC_WHC, " prune tl whcn %p\n", (void *)oldn); - assert(oldn != whc->maxseq_node); + DDS_LOG (DDS_LC_WHC, " prune tl whcn %p\n", (void *)oldn); + assert (oldn != whc->maxseq_node); whc_delete_one (whc, oldn); } } } - ddsrt_free(idxn); + ddsrt_free (idxn); } static void delete_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_idxnode *idxn) @@ -590,34 +586,34 @@ static void delete_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop free_one_instance_from_idx (whc, max_drop_seq, idxn); } -static int whcn_in_tlidx (const struct whc_impl *whc, const struct whc_idxnode *idxn, unsigned pos) +static int whcn_in_tlidx (const struct whc_impl *whc, const struct whc_idxnode *idxn, uint32_t pos) { if (idxn == NULL) return 0; else { - unsigned d = (idxn->headidx + (pos > idxn->headidx ? whc->idxdepth : 0)) - pos; + uint32_t d = (idxn->headidx + (pos > idxn->headidx ? whc->idxdepth : 0)) - pos; assert (d < whc->idxdepth); return d < whc->tldepth; } } -static unsigned whc_default_downgrade_to_volatile (struct whc *whc_generic, struct whc_state *st) +static uint32_t whc_default_downgrade_to_volatile (struct whc *whc_generic, struct whc_state *st) { struct whc_impl * const whc = (struct whc_impl *)whc_generic; seqno_t old_max_drop_seq; struct whc_node *deferred_free_list; - unsigned cnt; + uint32_t cnt; /* We only remove them from whc->tlidx: we don't remove them from - whc->seq yet. That'll happen eventually. */ + whc->seq yet. That'll happen eventually. */ ddsrt_mutex_lock (&whc->lock); check_whc (whc); if (whc->idxdepth == 0) { /* if not maintaining an index at all, this is nonsense */ - get_state_locked(whc, st); + get_state_locked (whc, st); ddsrt_mutex_unlock (&whc->lock); return 0; } @@ -625,29 +621,29 @@ static unsigned whc_default_downgrade_to_volatile (struct whc *whc_generic, stru assert (!whc->is_transient_local); if (whc->tldepth > 0) { - assert(whc->hdepth == 0 || whc->tldepth <= whc->hdepth); + assert (whc->hdepth == 0 || whc->tldepth <= whc->hdepth); whc->tldepth = 0; if (whc->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)) + 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); - ddsrt_hh_free(whc->idx_hash); + ddsrt_hh_free (whc->idx_hash); whc->idxdepth = 0; whc->idx_hash = NULL; } } /* Immediately drop them from the WHC (used to delay it until the - next ack); but need to make sure remove_acked_messages processes - them all. */ + next ack); but need to make sure remove_acked_messages processes + them all. */ old_max_drop_seq = whc->max_drop_seq; whc->max_drop_seq = 0; cnt = whc_default_remove_acked_messages_full (whc, old_max_drop_seq, &deferred_free_list); whc_default_free_deferred_free_list (whc_generic, deferred_free_list); assert (whc->max_drop_seq == old_max_drop_seq); - get_state_locked(whc, st); + get_state_locked (whc, st); ddsrt_mutex_unlock (&whc->lock); return cnt; } @@ -661,14 +657,14 @@ static size_t whcn_size (const struct whc_impl *whc, const struct whc_node *whcn static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_intv, struct whc_node **p_whcn) { /* Removes *p_whcn, possibly deleting or splitting *p_intv, as the - case may be. Does *NOT* update whc->seq_size. *p_intv must be - the interval containing *p_whcn (&& both must actually exist). + case may be. Does *NOT* update whc->seq_size. *p_intv must be + the interval containing *p_whcn (&& both must actually exist). - Returns: - - 0 if delete failed (only possible cause is memory exhaustion), - in which case *p_intv & *p_whcn are undefined; - - 1 if successful, in which case *p_intv & *p_whcn are set - correctly for the next sample in sequence number order */ + Returns: + - 0 if delete failed (only possible cause is memory exhaustion), + in which case *p_intv & *p_whcn are undefined; + - 1 if successful, in which case *p_intv & *p_whcn are set + correctly for the next sample in sequence number order */ struct whc_intvnode *intv = *p_intv; struct whc_node *whcn = *p_whcn; assert (whcn->seq >= intv->min && whcn->seq < intv->maxp1); @@ -685,13 +681,13 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i } /* Take it out of seqhash; deleting it from the list ordered on - sequence numbers is left to the caller (it has to be done unconditionally, - but remove_acked_messages defers it until the end or a skipped node). */ + sequence numbers is left to the caller (it has to be done unconditionally, + but remove_acked_messages defers it until the end or a skipped node). */ remove_whcn_from_hash (whc, whcn); /* We may have introduced a hole & have to split the interval - node, or we may have nibbled of the first one, or even the - last one. */ + node, or we may have nibbled of the first one, or even the + last one. */ if (whcn == intv->first) { if (whcn == intv->last && intv != whc->open_intv) @@ -714,7 +710,7 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i else if (whcn == intv->last) { /* well, at least it isn't the first one & so the interval is - still non-empty and we don't have to drop the interval */ + still non-empty and we don't have to drop the interval */ assert (intv->min < whcn->seq); assert (whcn->prev_seq); assert (whcn->prev_seq->seq + 1 == whcn->seq); @@ -725,9 +721,9 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i else { /* somewhere in the middle => split the interval (ideally, - would split it lazily, but it really is a transient-local - issue only, and so we can (for now) get away with splitting - it greedily */ + would split it lazily, but it really is a transient-local + issue only, and so we can (for now) get away with splitting + it greedily */ struct whc_intvnode *new_intv; ddsrt_avl_ipath_t path; @@ -746,7 +742,7 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i assert (new_intv->min < new_intv->maxp1); /* insert new node & continue the loop with intv set to the - new interval */ + new interval */ if (ddsrt_avl_lookup_ipath (&whc_seq_treedef, &whc->seq, &new_intv->min, &path) != NULL) assert (0); ddsrt_avl_insert_ipath (&whc_seq_treedef, &whc->seq, new_intv, &path); @@ -801,11 +797,11 @@ static void whc_default_free_deferred_free_list (struct whc *whc_generic, struct free_deferred_free_list (deferred_free_list); } -static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list) +static uint32_t whc_default_remove_acked_messages_noidx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list) { struct whc_intvnode *intv; struct whc_node *whcn; - unsigned ndropped = 0; + uint32_t ndropped = 0; /* In the trivial case of an empty WHC, get out quickly */ if (max_drop_seq <= whc->max_drop_seq || whc->maxseq_node == NULL) @@ -817,7 +813,7 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s } /* If simple, we have always dropped everything up to whc->max_drop_seq, - and there can only be a single interval */ + and there can only be a single interval */ #ifndef NDEBUG whcn = find_nextseq_intv (&intv, whc, whc->max_drop_seq); assert (whcn == NULL || whcn->prev_seq == NULL); @@ -826,14 +822,14 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s intv = whc->open_intv; /* Drop everything up to and including max_drop_seq, or absent that one, - the highest available sequence number (which then must be less) */ + the highest available sequence number (which then must be less) */ if ((whcn = whc_findseq (whc, max_drop_seq)) == NULL) { if (max_drop_seq < intv->min) { /* at startup, whc->max_drop_seq = 0 and reader states have max ack'd seq taken from wr->seq; - so if multiple readers are matched and the writer runs ahead of the readers, for the first - ack, whc->max_drop_seq < max_drop_seq = MIN(readers max ack) < intv->min */ + so if multiple readers are matched and the writer runs ahead of the readers, for the first + ack, whc->max_drop_seq < max_drop_seq = MIN (readers max ack) < intv->min */ if (max_drop_seq > whc->max_drop_seq) whc->max_drop_seq = max_drop_seq; *deferred_free_list = NULL; @@ -847,7 +843,7 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s } *deferred_free_list = intv->first; - ndropped = (unsigned) (whcn->seq - intv->min + 1); + ndropped = (uint32_t) (whcn->seq - intv->min + 1); intv->first = whcn->next_seq; intv->min = max_drop_seq + 1; @@ -877,18 +873,18 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s return ndropped; } -static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list) +static uint32_t whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list) { struct whc_intvnode *intv; struct whc_node *whcn; struct whc_node *prev_seq; struct whc_node deferred_list_head, *last_to_free = &deferred_list_head; - unsigned ndropped = 0; + uint32_t ndropped = 0; if (whc->is_transient_local && whc->tldepth == 0) { /* KEEP_ALL on transient local, so we can never ever delete anything */ - DDS_LOG(DDS_LC_WHC, " KEEP_ALL transient-local: do nothing\n"); + DDS_LOG (DDS_LC_WHC, " KEEP_ALL transient-local: do nothing\n"); *deferred_free_list = NULL; return 0; } @@ -898,11 +894,11 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se prev_seq = whcn ? whcn->prev_seq : NULL; while (whcn && whcn->seq <= max_drop_seq) { - DDS_LOG(DDS_LC_WHC, " whcn %p %"PRId64, (void *) whcn, whcn->seq); - if (whcn_in_tlidx(whc, whcn->idxnode, whcn->idxnode_pos)) + DDS_LOG (DDS_LC_WHC, " whcn %p %"PRId64, (void *) whcn, whcn->seq); + if (whcn_in_tlidx (whc, whcn->idxnode, whcn->idxnode_pos)) { /* quickly skip over samples in tlidx */ - DDS_LOG(DDS_LC_WHC, " tl:keep"); + DDS_LOG (DDS_LC_WHC, " tl:keep"); if (whcn->unacked) { assert (whc->unacked_bytes >= whcn->size); @@ -920,13 +916,13 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se } else { - DDS_LOG(DDS_LC_WHC, " delete"); + DDS_LOG (DDS_LC_WHC, " delete"); last_to_free->next_seq = whcn; last_to_free = last_to_free->next_seq; whc_delete_one_intv (whc, &intv, &whcn); ndropped++; } - DDS_LOG(DDS_LC_WHC, "\n"); + DDS_LOG (DDS_LC_WHC, "\n"); } if (prev_seq) prev_seq->next_seq = whcn; @@ -936,32 +932,32 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se *deferred_free_list = deferred_list_head.next_seq; /* If the history is deeper than durability_service.history (but not KEEP_ALL), then there - may be old samples in this instance, samples that were retained because they were within - 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. */ + may be old samples in this instance, samples that were retained because they were within + 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) { - assert(whc->hdepth == whc->idxdepth); - DDS_LOG(DDS_LC_WHC, " idxdepth %u > tldepth %u > 0 -- must prune\n", whc->idxdepth, whc->tldepth); + assert (whc->hdepth == whc->idxdepth); + DDS_LOG (DDS_LC_WHC, " idxdepth %"PRIu32" > tldepth %"PRIu32" > 0 -- must prune\n", whc->idxdepth, whc->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 - (the rest has been dropped already) and we prune old samples in the instance */ + encounter samples that were retained because of the transient-local durability setting + (the rest has been dropped already) and we prune old samples in the instance */ whcn = find_nextseq_intv (&intv, whc, whc->max_drop_seq); while (whcn && whcn->seq <= max_drop_seq) { struct whc_idxnode * const idxn = whcn->idxnode; - unsigned cnt, idx; + uint32_t cnt, idx; - DDS_LOG(DDS_LC_WHC, " whcn %p %"PRId64" idxn %p prune_seq %"PRId64":", (void *)whcn, whcn->seq, (void *)idxn, idxn->prune_seq); + DDS_LOG (DDS_LC_WHC, " whcn %p %"PRId64" idxn %p prune_seq %"PRId64":", (void *) whcn, whcn->seq, (void *) idxn, idxn->prune_seq); - assert(whcn_in_tlidx(whc, idxn, whcn->idxnode_pos)); + assert (whcn_in_tlidx (whc, idxn, whcn->idxnode_pos)); assert (idxn->prune_seq <= max_drop_seq); if (idxn->prune_seq == max_drop_seq) { - DDS_LOG(DDS_LC_WHC, " already pruned\n"); + DDS_LOG (DDS_LC_WHC, " already pruned\n"); whcn = whcn->next_seq; continue; } @@ -977,27 +973,27 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se if ((oldn = idxn->hist[idx]) != NULL) { /* Delete it - but this may not result in deleting the index node as - there must still be a more recent one available */ + there must still be a more recent one available */ #ifndef NDEBUG struct whc_node whcn_template; union { struct whc_idxnode idxn; - char pad[sizeof(struct whc_idxnode) + sizeof(struct whc_node *)]; + char pad[sizeof (struct whc_idxnode) + sizeof (struct whc_node *)]; } template; template.idxn.headidx = 0; template.idxn.hist[0] = &whcn_template; - whcn_template.serdata = ddsi_serdata_ref(oldn->serdata); - assert(oldn->seq < whcn->seq); + whcn_template.serdata = ddsi_serdata_ref (oldn->serdata); + assert (oldn->seq < whcn->seq); #endif - DDS_LOG(DDS_LC_WHC, " del %p %"PRId64, (void *) oldn, oldn->seq); + DDS_LOG (DDS_LC_WHC, " del %p %"PRId64, (void *) oldn, oldn->seq); whc_delete_one (whc, oldn); #ifndef NDEBUG - assert(ddsrt_hh_lookup(whc->idx_hash, &template) == idxn); - ddsi_serdata_unref(whcn_template.serdata); + assert (ddsrt_hh_lookup (whc->idx_hash, &template) == idxn); + ddsi_serdata_unref (whcn_template.serdata); #endif } } - DDS_LOG(DDS_LC_WHC, "\n"); + DDS_LOG (DDS_LC_WHC, "\n"); whcn = whcn->next_seq; } } @@ -1011,22 +1007,22 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se return ndropped; } -static unsigned whc_default_remove_acked_messages (struct whc *whc_generic, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list) +static uint32_t whc_default_remove_acked_messages (struct whc *whc_generic, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list) { struct whc_impl * const whc = (struct whc_impl *)whc_generic; - unsigned cnt; + uint32_t cnt; ddsrt_mutex_lock (&whc->lock); assert (max_drop_seq < MAX_SEQ_NUMBER); assert (max_drop_seq >= whc->max_drop_seq); - if (dds_get_log_mask() & DDS_LC_WHC) + if (dds_get_log_mask () & DDS_LC_WHC) { struct whc_state tmp; - get_state_locked(whc, &tmp); - DDS_LOG(DDS_LC_WHC, "whc_default_remove_acked_messages(%p max_drop_seq %"PRId64")\n", (void *)whc, max_drop_seq); - DDS_LOG(DDS_LC_WHC, " whc: [%"PRId64",%"PRId64"] max_drop_seq %"PRId64" h %u tl %u\n", - tmp.min_seq, tmp.max_seq, whc->max_drop_seq, whc->hdepth, whc->tldepth); + get_state_locked (whc, &tmp); + DDS_LOG (DDS_LC_WHC, "whc_default_remove_acked_messages(%p max_drop_seq %"PRId64")\n", (void *)whc, max_drop_seq); + DDS_LOG (DDS_LC_WHC, " 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); } check_whc (whc); @@ -1035,7 +1031,7 @@ static unsigned whc_default_remove_acked_messages (struct whc *whc_generic, seqn 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); - get_state_locked(whc, whcst); + get_state_locked (whc, whcst); ddsrt_mutex_unlock (&whc->lock); return cnt; } @@ -1108,38 +1104,39 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se struct whc_idxnode *idxn; union { struct whc_idxnode idxn; - char pad[sizeof(struct whc_idxnode) + sizeof(struct whc_node *)]; + char pad[sizeof (struct whc_idxnode) + sizeof (struct whc_node *)]; } template; ddsrt_mutex_lock (&whc->lock); check_whc (whc); - if (dds_get_log_mask() & DDS_LC_WHC) + if (dds_get_log_mask () & DDS_LC_WHC) { struct whc_state whcst; - get_state_locked(whc, &whcst); - DDS_LOG(DDS_LC_WHC, "whc_default_insert(%p max_drop_seq %"PRId64" seq %"PRId64" plist %p serdata %p:%"PRIx32")\n", (void *)whc, max_drop_seq, seq, (void*)plist, (void*)serdata, serdata->hash); - DDS_LOG(DDS_LC_WHC, " whc: [%"PRId64",%"PRId64"] max_drop_seq %"PRId64" h %u tl %u\n", - whcst.min_seq, whcst.max_seq, whc->max_drop_seq, whc->hdepth, whc->tldepth); + get_state_locked (whc, &whcst); + DDS_LOG (DDS_LC_WHC, "whc_default_insert(%p max_drop_seq %"PRId64" seq %"PRId64" plist %p serdata %p:%"PRIx32")\n", + (void *)whc, max_drop_seq, seq, (void*)plist, (void*)serdata, serdata->hash); + DDS_LOG (DDS_LC_WHC, " 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); } assert (max_drop_seq < MAX_SEQ_NUMBER); assert (max_drop_seq >= whc->max_drop_seq); /* Seq must be greater than what is currently stored. Usually it'll - be the next sequence number, but if there are no readers - temporarily, a gap may be among the possibilities */ + be the next sequence number, but if there are no readers + temporarily, a gap may be among the possibilities */ assert (whc->seq_size == 0 || seq > whc->maxseq_node->seq); /* Always insert in seq admin */ newn = whc_default_insert_seq (whc, max_drop_seq, seq, plist, serdata); - DDS_LOG(DDS_LC_WHC, " whcn %p:", (void*)newn); + DDS_LOG (DDS_LC_WHC, " 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) { - DDS_LOG(DDS_LC_WHC, " empty or no hist\n"); + DDS_LOG (DDS_LC_WHC, " empty or no hist\n"); ddsrt_mutex_unlock (&whc->lock); return 0; } @@ -1148,15 +1145,15 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se if ((idxn = ddsrt_hh_lookup (whc->idx_hash, &template)) != NULL) { /* Unregisters cause deleting of index entry, non-unregister of adding/overwriting in history */ - DDS_LOG(DDS_LC_WHC, " idxn %p", (void *)idxn); + DDS_LOG (DDS_LC_WHC, " idxn %p", (void *)idxn); if (serdata->statusinfo & NN_STATUSINFO_UNREGISTER) { - DDS_LOG(DDS_LC_WHC, " unreg:delete\n"); + DDS_LOG (DDS_LC_WHC, " unreg:delete\n"); delete_one_instance_from_idx (whc, max_drop_seq, idxn); if (newn->seq <= max_drop_seq) { struct whc_node *prev_seq = newn->prev_seq; - DDS_LOG(DDS_LC_WHC, " unreg:seq <= max_drop_seq: delete newn\n"); + DDS_LOG (DDS_LC_WHC, " unreg:seq <= max_drop_seq: delete newn\n"); whc_delete_one (whc, newn); whc->maxseq_node = prev_seq; } @@ -1168,7 +1165,7 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se idxn->headidx = 0; if ((oldn = idxn->hist[idxn->headidx]) != NULL) { - DDS_LOG(DDS_LC_WHC, " overwrite whcn %p", (void *)oldn); + DDS_LOG (DDS_LC_WHC, " overwrite whcn %p", (void *)oldn); oldn->idxnode = NULL; } idxn->hist[idxn->headidx] = newn; @@ -1177,46 +1174,45 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se if (oldn && (whc->hdepth > 0 || oldn->seq <= max_drop_seq)) { - DDS_LOG(DDS_LC_WHC, " prune whcn %p", (void *)oldn); - assert(oldn != whc->maxseq_node); + DDS_LOG (DDS_LC_WHC, " 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). */ + 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) { - unsigned pos = idxn->headidx + 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) { - DDS_LOG(DDS_LC_WHC, " prune tl whcn %p", (void *)oldn); - assert(oldn != whc->maxseq_node); + DDS_LOG (DDS_LC_WHC, " prune tl whcn %p", (void *)oldn); + assert (oldn != whc->maxseq_node); whc_delete_one (whc, oldn); } } - DDS_LOG(DDS_LC_WHC, "\n"); + DDS_LOG (DDS_LC_WHC, "\n"); } } else { - DDS_LOG(DDS_LC_WHC, " newkey"); + DDS_LOG (DDS_LC_WHC, " newkey"); /* Ignore unregisters, but insert everything else */ if (!(serdata->statusinfo & NN_STATUSINFO_UNREGISTER)) { - unsigned i; idxn = ddsrt_malloc (sizeof (*idxn) + whc->idxdepth * sizeof (idxn->hist[0])); - DDS_LOG(DDS_LC_WHC, " idxn %p", (void *)idxn); - ddsi_tkmap_instance_ref(tk); + DDS_LOG (DDS_LC_WHC, " 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 (i = 1; i < whc->idxdepth; i++) + for (uint32_t i = 1; i < whc->idxdepth; i++) idxn->hist[i] = NULL; newn->idxnode = idxn; newn->idxnode_pos = 0; @@ -1225,24 +1221,24 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se } else { - DDS_LOG(DDS_LC_WHC, " unreg:skip"); + DDS_LOG (DDS_LC_WHC, " unreg:skip"); if (newn->seq <= max_drop_seq) { struct whc_node *prev_seq = newn->prev_seq; - DDS_LOG(DDS_LC_WHC, " unreg:seq <= max_drop_seq: delete newn\n"); + DDS_LOG (DDS_LC_WHC, " unreg:seq <= max_drop_seq: delete newn\n"); whc_delete_one (whc, newn); whc->maxseq_node = prev_seq; } } - DDS_LOG(DDS_LC_WHC, "\n"); + DDS_LOG (DDS_LC_WHC, "\n"); } ddsrt_mutex_unlock (&whc->lock); return 0; } -static void make_borrowed_sample(struct whc_borrowed_sample *sample, struct whc_node *whcn) +static void make_borrowed_sample (struct whc_borrowed_sample *sample, struct whc_node *whcn) { - assert(!whcn->borrowed); + assert (!whcn->borrowed); whcn->borrowed = 1; sample->seq = whcn->seq; sample->plist = whcn->plist; @@ -1258,11 +1254,11 @@ static bool whc_default_borrow_sample (const struct whc *whc_generic, seqno_t se struct whc_node *whcn; bool found; ddsrt_mutex_lock ((ddsrt_mutex_t *)&whc->lock); - if ((whcn = whc_findseq(whc, seq)) == NULL) + if ((whcn = whc_findseq (whc, seq)) == NULL) found = false; else { - make_borrowed_sample(sample, whcn); + make_borrowed_sample (sample, whcn); found = true; } ddsrt_mutex_unlock ((ddsrt_mutex_t *)&whc->lock); @@ -1275,11 +1271,11 @@ static bool whc_default_borrow_sample_key (const struct whc *whc_generic, const struct whc_node *whcn; bool found; ddsrt_mutex_lock ((ddsrt_mutex_t *)&whc->lock); - if ((whcn = whc_findkey(whc, serdata_key)) == NULL) + if ((whcn = whc_findkey (whc, serdata_key)) == NULL) found = false; else { - make_borrowed_sample(sample, whcn); + make_borrowed_sample (sample, whcn); found = true; } ddsrt_mutex_unlock ((ddsrt_mutex_t *)&whc->lock); @@ -1293,14 +1289,15 @@ static void return_sample_locked (struct whc_impl *whc, struct whc_borrowed_samp { /* data no longer present in WHC - that means ownership for serdata, plist shifted to the borrowed copy and "returning" it really becomes "destroying" it */ ddsi_serdata_unref (sample->serdata); - if (sample->plist) { + if (sample->plist) + { nn_plist_fini (sample->plist); ddsrt_free (sample->plist); } } else { - assert(whcn->borrowed); + assert (whcn->borrowed); whcn->borrowed = 0; if (update_retransmit_info) { @@ -1338,7 +1335,7 @@ static bool whc_default_sample_iter_borrow_next (struct whc_sample_iter *opaque_ if (!it->first) { seq = sample->seq; - return_sample_locked(whc, sample, false); + return_sample_locked (whc, sample, false); } else { @@ -1349,7 +1346,7 @@ static bool whc_default_sample_iter_borrow_next (struct whc_sample_iter *opaque_ valid = false; else { - make_borrowed_sample(sample, whcn); + make_borrowed_sample (sample, whcn); valid = true; } ddsrt_mutex_unlock (&whc->lock); diff --git a/src/core/ddsc/src/dds_whc_builtintopic.c b/src/core/ddsc/src/dds_whc_builtintopic.c index ded5cf3..58ac495 100644 --- a/src/core/ddsc/src/dds_whc_builtintopic.c +++ b/src/core/ddsc/src/dds_whc_builtintopic.c @@ -44,9 +44,7 @@ struct bwhc_iter { }; /* check that our definition of whc_sample_iter fits in the type that callers allocate */ -struct bwhc_sample_iter_sizecheck { - char fits_in_generic_type[sizeof(struct bwhc_iter) <= sizeof(struct whc_sample_iter) ? 1 : -1]; -}; +DDSRT_STATIC_ASSERT (sizeof (struct bwhc_iter) <= sizeof (struct whc_sample_iter)); static void bwhc_free (struct whc *whc_generic) { diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 2ef7f1f..70cd6c7 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -111,13 +111,13 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay 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. */ + 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 proxy_writer_info pwr_info; @@ -130,8 +130,8 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay struct reader *rd; if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) { - DDS_TRACE("reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid)); - /* Copied the return value ignore from DDSI deliver_user_data() function. */ + DDS_TRACE ("reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid)); + /* Copied the return value ignore from DDSI deliver_user_data () function. */ if ((ret = try_store (rd->rhc, &pwr_info, payload, tk, &max_block_ms)) != DDS_RETCODE_OK) break; } @@ -152,40 +152,34 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam int w_rc; if (data == NULL) - { - DDS_ERROR("No data buffer provided\n"); return DDS_RETCODE_BAD_PARAMETER; - } /* Check for topic filter */ if (wr->m_topic->filter_fn && !writekey) - if (!(wr->m_topic->filter_fn) (data, wr->m_topic->filter_ctx)) + if (! wr->m_topic->filter_fn (data, wr->m_topic->filter_ctx)) return DDS_RETCODE_OK; thread_state_awake (ts1); /* Serialize and write data or key */ d = ddsi_serdata_from_sample (ddsi_wr->topic, writekey ? SDK_KEY : SDK_DATA, data); - d->statusinfo = ((action & DDS_WR_DISPOSE_BIT) ? NN_STATUSINFO_DISPOSE : 0) | ((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0); + d->statusinfo = (((action & DDS_WR_DISPOSE_BIT) ? NN_STATUSINFO_DISPOSE : 0) | + ((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0)); d->timestamp.v = tstamp; ddsi_serdata_ref (d); tk = ddsi_tkmap_lookup_instance_ref (d); w_rc = write_sample_gc (ts1, wr->m_xp, ddsi_wr, d, tk); - if (w_rc >= 0) - { + if (w_rc >= 0) { /* Flush out write unless configured to batch */ if (!config.whc_batch) nn_xpack_send (wr->m_xp, false); ret = DDS_RETCODE_OK; } else if (w_rc == DDS_RETCODE_TIMEOUT) { - DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n"); ret = DDS_RETCODE_TIMEOUT; } else if (w_rc == DDS_RETCODE_BAD_PARAMETER) { - DDS_ERROR ("Invalid data provided\n"); ret = DDS_RETCODE_ERROR; } else { - DDS_ERROR ("Internal error\n"); ret = DDS_RETCODE_ERROR; } if (ret == DDS_RETCODE_OK) @@ -213,13 +207,10 @@ dds_return_t dds_writecdr_impl_lowlevel (struct writer *ddsi_wr, struct nn_xpack nn_xpack_send (xp, false); ret = DDS_RETCODE_OK; } else if (w_rc == DDS_RETCODE_TIMEOUT) { - DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n"); ret = DDS_RETCODE_TIMEOUT; } else if (w_rc == DDS_RETCODE_BAD_PARAMETER) { - DDS_ERROR ("Invalid data provided\n"); ret = DDS_RETCODE_ERROR; } else { - DDS_ERROR ("Internal error\n"); ret = DDS_RETCODE_ERROR; } @@ -236,7 +227,8 @@ dds_return_t dds_writecdr_impl (dds_writer *wr, struct ddsi_serdata *d, dds_time if (wr->m_topic->filter_fn) abort (); /* Set if disposing or unregistering */ - d->statusinfo = ((action & DDS_WR_DISPOSE_BIT) ? NN_STATUSINFO_DISPOSE : 0) | ((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0); + d->statusinfo = (((action & DDS_WR_DISPOSE_BIT) ? NN_STATUSINFO_DISPOSE : 0) | + ((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0)); d->timestamp.v = tstamp; return dds_writecdr_impl_lowlevel (wr->m_wr, wr->m_xp, d); } @@ -252,9 +244,7 @@ void dds_write_flush (dds_entity_t writer) dds_writer *wr; dds_return_t rc; thread_state_awake (ts1); - if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) - DDS_ERROR ("Error occurred on locking writer\n"); - else + if ((rc = dds_writer_lock (writer, &wr)) == DDS_RETCODE_OK) { nn_xpack_send (wr->m_xp, true); dds_writer_unlock (wr); diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 534ba86..e8749fc 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -24,40 +24,29 @@ #include "dds__init.h" #include "dds__publisher.h" #include "dds__topic.h" +#include "dds__get_status.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds__whc.h" -DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_writer) +DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_writer) #define DDS_WRITER_STATUS_MASK \ - DDS_LIVELINESS_LOST_STATUS |\ - DDS_OFFERED_DEADLINE_MISSED_STATUS |\ - DDS_OFFERED_INCOMPATIBLE_QOS_STATUS |\ - DDS_PUBLICATION_MATCHED_STATUS + (DDS_LIVELINESS_LOST_STATUS |\ + DDS_OFFERED_DEADLINE_MISSED_STATUS |\ + DDS_OFFERED_INCOMPATIBLE_QOS_STATUS |\ + DDS_PUBLICATION_MATCHED_STATUS) -static dds_return_t -dds_writer_instance_hdl( - dds_entity *e, - dds_instance_handle_t *i) +static dds_return_t dds_writer_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all; + +static dds_return_t dds_writer_instance_hdl (dds_entity *e, dds_instance_handle_t *i) { - assert(e); - assert(i); - *i = (dds_instance_handle_t)writer_instance_id(&e->m_guid); - return DDS_RETCODE_OK; + *i = writer_instance_id(&e->m_guid); + return DDS_RETCODE_OK; } -static dds_return_t -dds_writer_status_validate( - uint32_t mask) +static dds_return_t dds_writer_status_validate (uint32_t mask) { - dds_return_t ret = DDS_RETCODE_OK; - - if (mask & ~(DDS_WRITER_STATUS_MASK)) { - DDS_ERROR("Invalid status mask\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - } - - return ret; + return (mask & ~DDS_WRITER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK; } /* @@ -173,285 +162,217 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) ddsrt_mutex_unlock (&entity->m_observers_lock); } -static uint32_t -get_bandwidth_limit( - nn_transport_priority_qospolicy_t transport_priority) +static uint32_t get_bandwidth_limit (nn_transport_priority_qospolicy_t transport_priority) { #ifdef DDSI_INCLUDE_NETWORK_CHANNELS struct config_channel_listelem *channel = find_channel (transport_priority); return channel->data_bandwidth_limit; #else - (void)transport_priority; + (void) transport_priority; return 0; #endif } -static dds_return_t -dds_writer_close( - dds_entity *e) -{ - dds_return_t ret = DDS_RETCODE_OK; - dds_writer *wr = (dds_writer*)e; +static dds_return_t dds_writer_close (dds_entity *e) ddsrt_nonnull_all; - assert(e); +static dds_return_t dds_writer_close (dds_entity *e) +{ + dds_writer * const wr = (dds_writer *) e; + dds_return_t ret; + thread_state_awake (lookup_thread_state ()); + nn_xpack_send (wr->m_xp, false); + if ((ret = delete_writer (&e->m_guid)) < 0) + ret = DDS_RETCODE_ERROR; + thread_state_asleep (lookup_thread_state ()); + return ret; +} + +static dds_return_t dds_writer_delete (dds_entity *e) ddsrt_nonnull_all; + +static dds_return_t dds_writer_delete (dds_entity *e) +{ + dds_writer * const wr = (dds_writer *) e; + dds_return_t ret; + /* FIXME: not freeing WHC here because it is owned by the DDSI entity */ + thread_state_awake (lookup_thread_state ()); + nn_xpack_free (wr->m_xp); + thread_state_asleep (lookup_thread_state ()); + if ((ret = dds_delete (wr->m_topic->m_entity.m_hdllink.hdl)) == DDS_RETCODE_OK) + { + ret = dds_delete_impl (e->m_parent->m_hdllink.hdl, true); + if (ret == DDS_RETCODE_BAD_PARAMETER) + ret = DDS_RETCODE_OK; + } + return ret; +} + +static dds_return_t dds_writer_qos_validate (const dds_qos_t *qos, bool enabled) +{ + if (!dds_qos_validate_common(qos)) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_USER_DATA) && !validate_octetseq (&qos->user_data)) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy (&qos->durability_service) < 0) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_LIFESPAN) && validate_duration (&qos->lifespan.duration) < 0) + return DDS_RETCODE_INCONSISTENT_POLICY; + if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits(&qos->history, &qos->resource_limits) < 0) + return DDS_RETCODE_INCONSISTENT_POLICY; + return enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK; +} + +static dds_return_t dds_writer_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) +{ + /* FIXME: QoS changes */ + dds_return_t ret; + + if ((ret = dds_writer_qos_validate (qos, enabled)) != DDS_RETCODE_OK) + return ret; + + /* Sort-of support updating ownership strength */ + if ((qos->present & QP_OWNERSHIP_STRENGTH) && (qos->present & ~QP_OWNERSHIP_STRENGTH) == 0) + { + dds_ownership_kind_t kind; + dds_qget_ownership (e->m_qos, &kind); + + if (kind != DDS_OWNERSHIP_EXCLUSIVE) + return DDS_RETCODE_ERROR; + + struct writer *ddsi_wr = ((dds_writer *) e)->m_wr; + dds_qset_ownership_strength (e->m_qos, qos->ownership_strength.value); thread_state_awake (lookup_thread_state ()); - nn_xpack_send (wr->m_xp, false); - if (delete_writer (&e->m_guid) != 0) { - DDS_ERROR("Internal error"); - ret = DDS_RETCODE_ERROR; - } + + /* FIXME: with QoS changes being unsupported by the underlying stack I wonder what will happen; locking the underlying DDSI writer is of doubtful value as well */ + ddsrt_mutex_lock (&ddsi_wr->e.lock); + ddsi_wr->xqos->ownership_strength.value = qos->ownership_strength.value; + ddsrt_mutex_unlock (&ddsi_wr->e.lock); thread_state_asleep (lookup_thread_state ()); - return ret; + } + else + { + if (enabled) + ret = DDS_RETCODE_UNSUPPORTED; + } + return ret; } -static dds_return_t -dds_writer_delete( - dds_entity *e) -{ - dds_writer *wr = (dds_writer*)e; - dds_return_t ret; - /* FIXME: not freeing WHC here because it is owned by the DDSI entity */ - thread_state_awake (lookup_thread_state ()); - nn_xpack_free(wr->m_xp); - thread_state_asleep (lookup_thread_state ()); - ret = dds_delete(wr->m_topic->m_entity.m_hdllink.hdl); - if(ret == DDS_RETCODE_OK){ - ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true); - if(ret == DDS_RETCODE_BAD_PARAMETER){ - ret = DDS_RETCODE_OK; - } - } - return ret; -} - - -static dds_return_t -dds_writer_qos_validate( - const dds_qos_t *qos, - bool enabled) -{ - dds_return_t ret = DDS_RETCODE_OK; - - assert(qos); - - /* Check consistency. */ - if(dds_qos_validate_common(qos) != true){ - DDS_ERROR("Provided inconsistent QoS policy\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if((qos->present & QP_USER_DATA) && validate_octetseq(&qos->user_data) != true){ - DDS_ERROR("User Data QoS policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy(&qos->durability_service) != 0){ - DDS_ERROR("Durability service QoS policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if ((qos->present & QP_LIFESPAN) && validate_duration(&qos->lifespan.duration) != 0){ - DDS_ERROR("Lifespan QoS policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits(&qos->history, &qos->resource_limits) != 0)){ - DDS_ERROR("Resource limits QoS policy is inconsistent and caused an error\n"); - ret = DDS_RETCODE_INCONSISTENT_POLICY; - } - if(ret == DDS_RETCODE_OK && enabled) { - ret = dds_qos_validate_mutable_common(qos); - } - return ret; -} - -static dds_return_t -dds_writer_qos_set( - dds_entity *e, - const dds_qos_t *qos, - bool enabled) -{ - dds_return_t ret = dds_writer_qos_validate(qos, enabled); - if (ret == DDS_RETCODE_OK) { - /* - * TODO: CHAM-95: DDSI does not support changing QoS policies. - * - * Only Ownership is required for the minimum viable product. This seems - * to be the only QoS policy that DDSI supports changes on. - */ - if (qos->present & QP_OWNERSHIP_STRENGTH) { - dds_ownership_kind_t kind; - /* check for ownership before updating, ownership strength is applicable only if - * writer is exclusive */ - dds_qget_ownership (e->m_qos, &kind); - - if (kind == DDS_OWNERSHIP_EXCLUSIVE) { - struct writer * ddsi_wr = ((dds_writer*)e)->m_wr; - - dds_qset_ownership_strength (e->m_qos, qos->ownership_strength.value); - - thread_state_awake (lookup_thread_state ()); - - /* FIXME: with QoS changes being unsupported by the underlying stack I wonder what will happen; locking the underlying DDSI writer is of doubtful value as well */ - ddsrt_mutex_lock (&ddsi_wr->e.lock); - if (qos->ownership_strength.value != ddsi_wr->xqos->ownership_strength.value) { - ddsi_wr->xqos->ownership_strength.value = qos->ownership_strength.value; - } - ddsrt_mutex_unlock (&ddsi_wr->e.lock); - thread_state_asleep (lookup_thread_state ()); - } else { - DDS_ERROR("Setting ownership strength doesn't make sense when the ownership is shared\n"); - ret = DDS_RETCODE_ERROR; - } - } else { - if (enabled) { - DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies yet\n"); - ret = DDS_RETCODE_UNSUPPORTED; - } - } - } - return ret; -} - -static struct whc *make_whc(const dds_qos_t *qos) +static struct whc *make_whc (const dds_qos_t *qos) { bool handle_as_transient_local; - unsigned hdepth, tldepth; + 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. */ + drop all samples for which a later update is available. This + forces it to maintain a tlidx. */ handle_as_transient_local = (qos->durability.kind == NN_TRANSIENT_LOCAL_DURABILITY_QOS); if (qos->history.kind == NN_KEEP_ALL_HISTORY_QOS) hdepth = 0; else - hdepth = (unsigned)qos->history.depth; - if (handle_as_transient_local) { + hdepth = (unsigned) qos->history.depth; + if (!handle_as_transient_local) + tldepth = 0; + else + { if (qos->durability_service.history.kind == NN_KEEP_ALL_HISTORY_QOS) tldepth = 0; else - tldepth = (unsigned)qos->durability_service.history.depth; - } else { - tldepth = 0; + tldepth = (unsigned) qos->durability_service.history.depth; } return whc_new (handle_as_transient_local, hdepth, tldepth); } - -dds_entity_t -dds_create_writer( - dds_entity_t participant_or_publisher, - dds_entity_t topic, - const dds_qos_t *qos, - const dds_listener_t *listener) +dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entity_t topic, const dds_qos_t *qos, const dds_listener_t *listener) { - dds_return_t rc; - dds_qos_t * wqos; - dds_writer * wr; - dds_entity_t writer; - dds_publisher * pub = NULL; - dds_topic * tp; - dds_entity_t publisher; - ddsi_tran_conn_t conn = gv.data_conn_uc; - dds_return_t ret; + dds_return_t rc; + dds_qos_t *wqos; + dds_writer *wr; + dds_entity_t writer; + dds_publisher *pub = NULL; + dds_topic *tp; + dds_entity_t publisher; + ddsi_tran_conn_t conn = gv.data_conn_uc; - { - dds_entity *p_or_p; - if ((rc = dds_entity_claim (participant_or_publisher, &p_or_p)) != DDS_RETCODE_OK) { - return rc; - } - if (dds_entity_kind (p_or_p) == DDS_KIND_PARTICIPANT) { - publisher = dds_create_publisher(participant_or_publisher, qos, NULL); - } else { - publisher = participant_or_publisher; - } - dds_entity_release (p_or_p); - } + { + dds_entity *p_or_p; + if ((rc = dds_entity_claim (participant_or_publisher, &p_or_p)) != DDS_RETCODE_OK) + return rc; + if (dds_entity_kind (p_or_p) == DDS_KIND_PARTICIPANT) + publisher = dds_create_publisher(participant_or_publisher, qos, NULL); + else + publisher = participant_or_publisher; + dds_entity_release (p_or_p); + } - if ((rc = dds_publisher_lock(publisher, &pub)) != DDS_RETCODE_OK) { - writer = rc; - goto err_pub_lock; - } + if ((rc = dds_publisher_lock (publisher, &pub)) != DDS_RETCODE_OK) + return rc; - if (publisher != participant_or_publisher) { - pub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT; - } + if (publisher != participant_or_publisher) + pub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT; - rc = dds_topic_lock(topic, &tp); - if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking topic\n"); - writer = rc; - goto err_tp_lock; - } - assert(tp->m_stopic); - assert(pub->m_entity.m_domain == tp->m_entity.m_domain); + if ((rc = dds_topic_lock (topic, &tp)) != DDS_RETCODE_OK) + goto err_tp_lock; - /* Merge Topic & Publisher qos */ - wqos = dds_create_qos(); - if (qos) { - /* Only returns failure when one of the qos args is NULL, which - * is not the case here. */ - (void)dds_copy_qos(wqos, qos); - } + assert (tp->m_stopic); + assert (pub->m_entity.m_domain == tp->m_entity.m_domain); - if (pub->m_entity.m_qos) { - dds_merge_qos(wqos, pub->m_entity.m_qos); - } + /* Merge Topic & Publisher qos */ + wqos = dds_create_qos (); + if (qos) + (void) dds_copy_qos (wqos, qos); + if (pub->m_entity.m_qos) + dds_merge_qos (wqos, pub->m_entity.m_qos); + if (tp->m_entity.m_qos) + dds_merge_qos (wqos, tp->m_entity.m_qos); + nn_xqos_mergein_missing (wqos, &gv.default_xqos_wr); - if (tp->m_entity.m_qos) { - /* merge topic qos data to writer qos */ - dds_merge_qos(wqos, tp->m_entity.m_qos); - } - nn_xqos_mergein_missing(wqos, &gv.default_xqos_wr); + if ((rc = dds_writer_qos_validate (wqos, false)) != DDS_RETCODE_OK) + { + dds_delete_qos(wqos); + goto err_bad_qos; + } - ret = dds_writer_qos_validate(wqos, false); - if (ret != 0) { - dds_delete_qos(wqos); - writer = ret; - goto err_bad_qos; - } + /* Create writer */ + wr = dds_alloc (sizeof (*wr)); + writer = dds_entity_init (&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK); - /* Create writer */ - wr = dds_alloc(sizeof (*wr)); - writer = dds_entity_init(&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK); + wr->m_topic = tp; + dds_entity_add_ref_nolock (&tp->m_entity); + wr->m_xp = nn_xpack_new (conn, get_bandwidth_limit (wqos->transport_priority), config.xpack_send_async); + wr->m_entity.m_deriver.close = dds_writer_close; + wr->m_entity.m_deriver.delete = dds_writer_delete; + wr->m_entity.m_deriver.set_qos = dds_writer_qos_set; + wr->m_entity.m_deriver.validate_status = dds_writer_status_validate; + wr->m_entity.m_deriver.get_instance_hdl = dds_writer_instance_hdl; + wr->m_whc = make_whc (wqos); - wr->m_topic = tp; - dds_entity_add_ref_nolock(&tp->m_entity); - wr->m_xp = nn_xpack_new(conn, get_bandwidth_limit(wqos->transport_priority), config.xpack_send_async); - wr->m_entity.m_deriver.close = dds_writer_close; - wr->m_entity.m_deriver.delete = dds_writer_delete; - wr->m_entity.m_deriver.set_qos = dds_writer_qos_set; - wr->m_entity.m_deriver.validate_status = dds_writer_status_validate; - wr->m_entity.m_deriver.get_instance_hdl = dds_writer_instance_hdl; - wr->m_whc = make_whc (wqos); + /* Extra claim of this writer to make sure that the delete waits until DDSI + * has deleted its writer as well. This can be known through the callback. */ + dds_handle_claim_inc (&wr->m_entity.m_hdllink); - /* Extra claim of this writer to make sure that the delete waits until DDSI - * has deleted its writer as well. This can be known through the callback. */ - dds_handle_claim_inc (&wr->m_entity.m_hdllink); + ddsrt_mutex_unlock (&tp->m_entity.m_mutex); + ddsrt_mutex_unlock (&pub->m_entity.m_mutex); - ddsrt_mutex_unlock (&tp->m_entity.m_mutex); - ddsrt_mutex_unlock (&pub->m_entity.m_mutex); - - thread_state_awake (lookup_thread_state ()); - ret = new_writer(&wr->m_wr, &wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); - ddsrt_mutex_lock (&pub->m_entity.m_mutex); - ddsrt_mutex_lock (&tp->m_entity.m_mutex); - assert(ret == DDS_RETCODE_OK); - thread_state_asleep (lookup_thread_state ()); - dds_topic_unlock(tp); - dds_publisher_unlock(pub); - return writer; + thread_state_awake (lookup_thread_state ()); + rc = new_writer (&wr->m_wr, &wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); + ddsrt_mutex_lock (&pub->m_entity.m_mutex); + ddsrt_mutex_lock (&tp->m_entity.m_mutex); + assert(rc == DDS_RETCODE_OK); + thread_state_asleep (lookup_thread_state ()); + dds_topic_unlock (tp); + dds_publisher_unlock (pub); + return writer; err_bad_qos: - dds_topic_unlock(tp); + dds_topic_unlock (tp); err_tp_lock: - dds_publisher_unlock(pub); - if((pub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){ - (void)dds_delete(publisher); - } -err_pub_lock: - return writer; + dds_publisher_unlock (pub); + if ((pub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){ + (void )dds_delete (publisher); + } + return rc; } -dds_entity_t -dds_get_publisher( - dds_entity_t writer) +dds_entity_t dds_get_publisher (dds_entity_t writer) { dds_entity *e; dds_return_t rc; @@ -472,115 +393,7 @@ dds_get_publisher( } } -dds_return_t -dds_get_publication_matched_status ( - dds_entity_t writer, - dds_publication_matched_status_t * status) -{ - dds_writer *wr; - dds_return_t ret; - - ret = dds_writer_lock(writer, &wr); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking writer\n"); - goto fail; - } - /* status = NULL, application do not need the status, but reset the counter & triggered bit */ - if (status) { - *status = wr->m_publication_matched_status; - } - ddsrt_mutex_lock (&wr->m_entity.m_observers_lock); - if (wr->m_entity.m_status_enable & DDS_PUBLICATION_MATCHED_STATUS) { - wr->m_publication_matched_status.total_count_change = 0; - wr->m_publication_matched_status.current_count_change = 0; - dds_entity_status_reset(&wr->m_entity, DDS_PUBLICATION_MATCHED_STATUS); - } - ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock); - dds_writer_unlock(wr); -fail: - return ret; -} - -dds_return_t -dds_get_liveliness_lost_status ( - dds_entity_t writer, - dds_liveliness_lost_status_t * status) -{ - dds_writer *wr; - dds_return_t ret; - - ret = dds_writer_lock(writer, &wr); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking writer\n"); - goto fail; - } - /* status = NULL, application do not need the status, but reset the counter & triggered bit */ - if (status) { - *status = wr->m_liveliness_lost_status; - } - ddsrt_mutex_lock (&wr->m_entity.m_observers_lock); - if (wr->m_entity.m_status_enable & DDS_LIVELINESS_LOST_STATUS) { - wr->m_liveliness_lost_status.total_count_change = 0; - dds_entity_status_reset(&wr->m_entity, DDS_LIVELINESS_LOST_STATUS); - } - ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock); - dds_writer_unlock(wr); -fail: - return ret; -} - -dds_return_t -dds_get_offered_deadline_missed_status( - dds_entity_t writer, - dds_offered_deadline_missed_status_t *status) -{ - dds_writer *wr; - dds_return_t ret; - - ret = dds_writer_lock(writer, &wr); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking writer\n"); - goto fail; - } - /* status = NULL, application do not need the status, but reset the counter & triggered bit */ - if (status) { - *status = wr->m_offered_deadline_missed_status; - } - ddsrt_mutex_lock (&wr->m_entity.m_observers_lock); - if (wr->m_entity.m_status_enable & DDS_OFFERED_DEADLINE_MISSED_STATUS) { - wr->m_offered_deadline_missed_status.total_count_change = 0; - dds_entity_status_reset(&wr->m_entity, DDS_OFFERED_DEADLINE_MISSED_STATUS); - } - ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock); - dds_writer_unlock(wr); -fail: - return ret; -} - -dds_return_t -dds_get_offered_incompatible_qos_status ( - dds_entity_t writer, - dds_offered_incompatible_qos_status_t * status) -{ - dds_writer *wr; - dds_return_t ret; - - ret = dds_writer_lock(writer, &wr); - if (ret != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking writer\n"); - goto fail; - } - /* status = NULL, application do not need the status, but reset the counter & triggered bit */ - if (status) { - *status = wr->m_offered_incompatible_qos_status; - } - ddsrt_mutex_lock (&wr->m_entity.m_observers_lock); - if (wr->m_entity.m_status_enable & DDS_OFFERED_INCOMPATIBLE_QOS_STATUS) { - wr->m_offered_incompatible_qos_status.total_count_change = 0; - dds_entity_status_reset(&wr->m_entity, DDS_OFFERED_INCOMPATIBLE_QOS_STATUS); - } - ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock); - dds_writer_unlock(wr); -fail: - return ret; -} +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) +DDS_GET_STATUS(writer, offered_incompatible_qos, OFFERED_INCOMPATIBLE_QOS, total_count_change) diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 70c2837..ccfe592 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -105,7 +105,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" q_rtps.h q_security.h q_sockwaitset.h - q_static_assert.h q_thread.h q_time.h q_transmit.h diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 5836165..0312e6d 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -467,17 +467,6 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e); * - RTPS_PF_ONLY_LOCAL FIXME: not used, it seems * @param[in] plist * Parameters/QoS for this participant - * @param[out] dest - * Filled with the recognized parameters in the input if successful, otherwise - * initialized to an empty parameter list. Where possible, pointers alias the - * 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. - * @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 * * @returns A dds_return_t indicating success or failure. * @@ -562,11 +551,11 @@ int writer_must_have_hb_scheduled (const struct writer *wr, const struct whc_sta void writer_set_retransmitting (struct writer *wr); void writer_clear_retransmitting (struct writer *wr); -int delete_writer (const struct nn_guid *guid); -int delete_writer_nolinger (const struct nn_guid *guid); -int delete_writer_nolinger_locked (struct writer *wr); +dds_return_t delete_writer (const struct nn_guid *guid); +dds_return_t delete_writer_nolinger (const struct nn_guid *guid); +dds_return_t delete_writer_nolinger_locked (struct writer *wr); -int delete_reader (const struct nn_guid *guid); +dds_return_t delete_reader (const struct nn_guid *guid); uint64_t reader_instance_id (const struct nn_guid *guid); struct local_orphan_writer { diff --git a/src/core/ddsi/include/dds/ddsi/q_qosmatch.h b/src/core/ddsi/include/dds/ddsi/q_qosmatch.h index df224ed..d70c24c 100644 --- a/src/core/ddsi/include/dds/ddsi/q_qosmatch.h +++ b/src/core/ddsi/include/dds/ddsi/q_qosmatch.h @@ -18,9 +18,7 @@ extern "C" { struct nn_xqos; -int partition_match_based_on_wildcard_in_left_operand (const struct nn_xqos *a, const struct nn_xqos *b, const char **realname); int partitions_match_p (const struct nn_xqos *a, const struct nn_xqos *b); -int is_wildcard_partition (const char *str); /* Returns -1 on success, or QoS id of first mismatch (>=0) */ diff --git a/src/core/ddsi/include/dds/ddsi/q_thread.h b/src/core/ddsi/include/dds/ddsi/q_thread.h index 230e625..1377ae9 100644 --- a/src/core/ddsi/include/dds/ddsi/q_thread.h +++ b/src/core/ddsi/include/dds/ddsi/q_thread.h @@ -17,7 +17,7 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/threads.h" -#include "dds/ddsi/q_static_assert.h" +#include "dds/ddsrt/static_assert.h" #if defined (__cplusplus) extern "C" { @@ -125,7 +125,7 @@ DDS_EXPORT inline bool vtime_asleep_p (vtime_t vtime) DDS_EXPORT inline bool vtime_gt (vtime_t vtime1, vtime_t vtime0) { - Q_STATIC_ASSERT_CODE (sizeof (vtime_t) == sizeof (svtime_t)); + DDSRT_STATIC_ASSERT_CODE (sizeof (vtime_t) == sizeof (svtime_t)); return (svtime_t) ((vtime1 & VTIME_TIME_MASK) - (vtime0 & VTIME_TIME_MASK)) > 0; } diff --git a/src/core/ddsi/src/ddsi_raweth.c b/src/core/ddsi/src/ddsi_raweth.c index ef63a73..a8f350b 100644 --- a/src/core/ddsi/src/ddsi_raweth.c +++ b/src/core/ddsi/src/ddsi_raweth.c @@ -332,8 +332,9 @@ static enum ddsi_locator_from_string_result ddsi_raweth_address_from_string (dds memset (loc->address, 0, sizeof (loc->address)); while (i < 6 && *str != 0) { - int o, p; - if (sscanf (str, "%x%n", &o, &p) != 1 || o < 0 || o > 255) + unsigned o; + int p; + if (sscanf (str, "%x%n", &o, &p) != 1 || o > 255) return AFSR_INVALID; loc->address[10 + i++] = (unsigned char) o; str += p; diff --git a/src/core/ddsi/src/q_addrset.c b/src/core/ddsi/src/q_addrset.c index f8694d8..1eeda78 100644 --- a/src/core/ddsi/src/q_addrset.c +++ b/src/core/ddsi/src/q_addrset.c @@ -127,12 +127,12 @@ static int add_addresses_to_addrset_1 (struct addrset *as, const char *ip, int p return 0; } -DDSRT_WARNING_MSVC_OFF(4996); int add_addresses_to_addrset (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 */ + DDSRT_WARNING_MSVC_OFF(4996); char *addrs_copy, *ip, *cursor, *a; int retval = -1; addrs_copy = ddsrt_strdup (addrs); @@ -179,8 +179,8 @@ int add_addresses_to_addrset (struct addrset *as, const char *addrs, int port_mo ddsrt_free (ip); ddsrt_free (addrs_copy); return retval; + DDSRT_WARNING_MSVC_ON(4996); } -DDSRT_WARNING_MSVC_ON(4996); int compare_locators (const nn_locator_t *a, const nn_locator_t *b) { diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 383534c..60145a9 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -1335,9 +1335,9 @@ static void do_print_uint32_bitset (struct cfgst *cfgst, uint32_t mask, size_t n cfg_logelem (cfgst, sources, "%s%s", res, suffix); } -DDSRT_WARNING_MSVC_OFF(4996); static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *value, const struct unit *unittab, int64_t def_mult, int64_t min, int64_t max) { + DDSRT_WARNING_MSVC_OFF(4996); int pos; double v_dbl; int64_t v_int; @@ -1364,8 +1364,8 @@ static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *valu *elem = 0; /* some static analyzers don't "get it" */ return cfg_error (cfgst, "%s: invalid value", value); } + DDSRT_WARNING_MSVC_ON(4996); } -DDSRT_WARNING_MSVC_ON(4996); static void pf_int64_unit (struct cfgst *cfgst, int64_t value, uint32_t sources, const struct unit *unittab, const char *zero_unit) { @@ -1393,10 +1393,8 @@ static void pf_int64_unit (struct cfgst *cfgst, int64_t value, uint32_t sources, } #define GENERIC_ENUM_CTYPE_UF(type_, c_type_) \ - struct en_##type_##_vs_ms_check { \ - char length_eq[(sizeof (en_##type_##_vs) / sizeof (*en_##type_##_vs) == \ - sizeof (en_##type_##_ms) / sizeof (*en_##type_##_ms)) ? 1 : -1]; \ - }; \ + DDSRT_STATIC_ASSERT (sizeof (en_##type_##_vs) / sizeof (*en_##type_##_vs) == \ + sizeof (en_##type_##_ms) / sizeof (*en_##type_##_ms)); \ \ static int uf_##type_ (struct cfgst *cfgst, void *parent, UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value) \ { \ @@ -1773,9 +1771,9 @@ static void pf_allow_multicast(struct cfgst *cfgst, void *parent, struct cfgelem do_print_uint32_bitset (cfgst, *p, sizeof (allow_multicast_codes) / sizeof (*allow_multicast_codes), allow_multicast_names, allow_multicast_codes, sources, ""); } -DDSRT_WARNING_MSVC_OFF(4996); static int uf_maybe_int32 (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) { + DDSRT_WARNING_MSVC_OFF(4996); struct config_maybe_int32 * const elem = cfg_address (cfgst, parent, cfgelem); int pos; if (ddsrt_strcasecmp (value, "default") == 0) { @@ -1788,8 +1786,8 @@ static int uf_maybe_int32 (struct cfgst *cfgst, void *parent, struct cfgelem con } else { return cfg_error (cfgst, "'%s': neither 'default' nor a decimal integer\n", value); } + DDSRT_WARNING_MSVC_ON(4996); } -DDSRT_WARNING_MSVC_ON(4996); static void pf_maybe_int32 (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) { @@ -1940,9 +1938,9 @@ static void pf_duration (struct cfgst *cfgst, void *parent, struct cfgelem const pf_int64_unit (cfgst, *elem, sources, unittab_duration, "s"); } -DDSRT_WARNING_MSVC_OFF(4996); static int uf_domainId (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) { + DDSRT_WARNING_MSVC_OFF(4996); struct config_maybe_int32 * const elem = cfg_address (cfgst, parent, cfgelem); int pos; if (ddsrt_strcasecmp (value, "any") == 0) { @@ -1955,8 +1953,8 @@ static int uf_domainId (struct cfgst *cfgst, void *parent, struct cfgelem const } else { return cfg_error (cfgst, "'%s': neither 'any' nor a decimal integer in 0 .. 230\n", value); } + DDSRT_WARNING_MSVC_ON(4996); } -DDSRT_WARNING_MSVC_ON(4996); static void pf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) { diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 18d2895..6cfca79 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -1099,10 +1099,10 @@ static void rebuild_make_locs_nrds(int **locs_nrds, int nreaders, int nlocs, con if (covered[j * nlocs + i] >= 0) n++; -/* The compiler doesn't realize that ln is large enough. */ -DDSRT_WARNING_MSVC_OFF(6386); + /* The compiler doesn't realize that ln is large enough. */ + DDSRT_WARNING_MSVC_OFF(6386); ln[i] = n; -DDSRT_WARNING_MSVC_ON(6386); + DDSRT_WARNING_MSVC_ON(6386); } *locs_nrds = ln; } @@ -3002,7 +3002,7 @@ static void writer_set_state (struct writer *wr, enum writer_state newstate) wr->state = newstate; } -int delete_writer_nolinger_locked (struct writer *wr) +dds_return_t delete_writer_nolinger_locked (struct writer *wr) { DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (wr->e.guid)); ASSERT_MUTEX_HELD (&wr->e.lock); @@ -3014,7 +3014,7 @@ int delete_writer_nolinger_locked (struct writer *wr) return 0; } -int delete_writer_nolinger (const struct nn_guid *guid) +dds_return_t delete_writer_nolinger (const struct nn_guid *guid) { struct writer *wr; /* We take no care to ensure application writers are not deleted @@ -3043,7 +3043,7 @@ void delete_local_orphan_writer (struct local_orphan_writer *lowr) ddsrt_mutex_unlock (&lowr->wr.e.lock); } -int delete_writer (const struct nn_guid *guid) +dds_return_t delete_writer (const struct nn_guid *guid) { struct writer *wr; struct whc_state whcst; @@ -3409,7 +3409,7 @@ static void gc_delete_reader (struct gcreq *gcreq) ddsrt_free (rd); } -int delete_reader (const struct nn_guid *guid) +dds_return_t delete_reader (const struct nn_guid *guid) { struct reader *rd; assert (!is_writer_entityid (guid->entityid)); diff --git a/src/core/ddsi/src/q_freelist.c b/src/core/ddsi/src/q_freelist.c index fd7aef7..9d1a1bc 100644 --- a/src/core/ddsi/src/q_freelist.c +++ b/src/core/ddsi/src/q_freelist.c @@ -140,9 +140,9 @@ void nn_freelist_fini (struct nn_freelist *fl, void (*xfree) (void *)) xfree (fl->inner[i].m->x[j]); ddsrt_free(fl->inner[i].m); } -/* The compiler can't make sense of all these linked lists and doesn't - * realize that the next pointers are always initialized here. */ -DDSRT_WARNING_MSVC_OFF(6001); + /* The compiler can't make sense of all these linked lists and doesn't + * realize that the next pointers are always initialized here. */ + DDSRT_WARNING_MSVC_OFF(6001); while ((m = fl->mlist) != NULL) { fl->mlist = m->next; @@ -155,7 +155,7 @@ DDSRT_WARNING_MSVC_OFF(6001); fl->emlist = m->next; ddsrt_free (m); } -DDSRT_WARNING_MSVC_ON(6001); + DDSRT_WARNING_MSVC_ON(6001); } static ddsrt_atomic_uint32_t freelist_inner_idx_off = DDSRT_ATOMIC_UINT32_INIT(0); diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index f224960..c20b06c 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -415,43 +415,43 @@ static int check_thread_properties (void) return ok; } -DDSRT_WARNING_MSVC_OFF(4996); int rtps_config_open (void) { - int status; + DDSRT_WARNING_MSVC_OFF(4996); + int status; - if (config.tracingOutputFileName == NULL || *config.tracingOutputFileName == 0 || config.enabled_logcats == 0) - { - config.enabled_logcats = 0; - config.tracingOutputFile = NULL; - status = 1; - } - else if (ddsrt_strcasecmp (config.tracingOutputFileName, "stdout") == 0) - { - config.tracingOutputFile = stdout; - status = 1; - } - else if (ddsrt_strcasecmp (config.tracingOutputFileName, "stderr") == 0) - { - config.tracingOutputFile = stderr; - status = 1; - } - else if ((config.tracingOutputFile = fopen (config.tracingOutputFileName, config.tracingAppendToFile ? "a" : "w")) == NULL) - { - DDS_ERROR("%s: cannot open for writing\n", config.tracingOutputFileName); - status = 0; - } - else - { - status = 1; - } + if (config.tracingOutputFileName == NULL || *config.tracingOutputFileName == 0 || config.enabled_logcats == 0) + { + config.enabled_logcats = 0; + config.tracingOutputFile = NULL; + status = 1; + } + else if (ddsrt_strcasecmp (config.tracingOutputFileName, "stdout") == 0) + { + config.tracingOutputFile = stdout; + status = 1; + } + else if (ddsrt_strcasecmp (config.tracingOutputFileName, "stderr") == 0) + { + config.tracingOutputFile = stderr; + status = 1; + } + else if ((config.tracingOutputFile = fopen (config.tracingOutputFileName, config.tracingAppendToFile ? "a" : "w")) == NULL) + { + DDS_ERROR("%s: cannot open for writing\n", config.tracingOutputFileName); + status = 0; + } + else + { + status = 1; + } - dds_set_log_mask(config.enabled_logcats); - dds_set_trace_file(config.tracingOutputFile); + dds_set_log_mask(config.enabled_logcats); + dds_set_trace_file(config.tracingOutputFile); - return status; + return status; + DDSRT_WARNING_MSVC_ON(4996); } -DDSRT_WARNING_MSVC_ON(4996); int rtps_config_prep (struct cfgst *cfgst) { @@ -1654,10 +1654,10 @@ void rtps_fini (void) while (gv.recvips) { struct config_in_addr_node *n = gv.recvips; -/* The compiler doesn't realize that n->next is always initialized. */ -DDSRT_WARNING_MSVC_OFF(6001); + /* The compiler doesn't realize that n->next is always initialized. */ + DDSRT_WARNING_MSVC_OFF(6001); gv.recvips = n->next; -DDSRT_WARNING_MSVC_ON(6001); + DDSRT_WARNING_MSVC_ON(6001); ddsrt_free (n); } diff --git a/src/core/ddsi/src/q_pcap.c b/src/core/ddsi/src/q_pcap.c index c48e636..f625b96 100644 --- a/src/core/ddsi/src/q_pcap.c +++ b/src/core/ddsi/src/q_pcap.c @@ -77,9 +77,9 @@ static const ipv4_hdr_t ipv4_hdr_template = { #define IPV4_HDR_SIZE 20 #define UDP_HDR_SIZE 8 -DDSRT_WARNING_MSVC_OFF(4996); FILE *new_pcap_file (const char *name) { + DDSRT_WARNING_MSVC_OFF(4996); FILE *fp; pcap_hdr_t hdr; @@ -99,8 +99,8 @@ FILE *new_pcap_file (const char *name) fwrite (&hdr, sizeof (hdr), 1, fp); return fp; + DDSRT_WARNING_MSVC_ON(4996); } -DDSRT_WARNING_MSVC_ON(4996); static void write_data (FILE *fp, const ddsrt_msghdr_t *msghdr, size_t sz) { diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index bae275b..e930218 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -17,6 +17,7 @@ #include "dds/ddsrt/log.h" #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/static_assert.h" #include "dds/ddsi/q_log.h" @@ -30,7 +31,6 @@ #include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_protocol.h" /* for NN_STATUSINFO_... */ #include "dds/ddsi/q_radmin.h" /* for nn_plist_quickscan */ -#include "dds/ddsi/q_static_assert.h" #include "dds/ddsrt/avl.h" #include "dds/ddsi/q_misc.h" /* for vendor_is_... */ @@ -407,8 +407,8 @@ void nn_plist_fini (nn_plist_t *ps) int i; nn_xqos_fini (&ps->qos); -/* The compiler doesn't understand how offsetof is used in the arrays. */ -DDSRT_WARNING_MSVC_OFF(6001); + /* The compiler doesn't understand how offsetof is used in the arrays. */ + DDSRT_WARNING_MSVC_OFF(6001); for (i = 0; i < (int) (sizeof (simple) / sizeof (*simple)); i++) { if ((ps->present & simple[i].fl) && !(ps->aliased & simple[i].fl)) @@ -422,7 +422,7 @@ DDSRT_WARNING_MSVC_OFF(6001); if ((ps->present & locs[i].fl) && !(ps->aliased & locs[i].fl)) free_locators ((nn_locators_t *) ((char *) ps + locs[i].off)); } -DDSRT_WARNING_MSVC_ON(6001); + DDSRT_WARNING_MSVC_ON(6001); ps->present = 0; } @@ -1943,7 +1943,7 @@ static dds_return_t init_one_parameter if (dd->bufsz >= 2 * sizeof (dest->statusinfo) && vendor_is_eclipse_or_opensplice(dd->vendorid)) { uint32_t statusinfox; - Q_STATIC_ASSERT_CODE (sizeof(statusinfox) == sizeof(dest->statusinfo)); + DDSRT_STATIC_ASSERT_CODE (sizeof(statusinfox) == sizeof(dest->statusinfo)); memcpy (&statusinfox, dd->buf + sizeof (dest->statusinfo), sizeof (statusinfox)); statusinfox = fromBE4u (statusinfox); if (statusinfox & NN_STATUSINFOX_OSPL_AUTO) diff --git a/src/core/ddsi/src/q_qosmatch.c b/src/core/ddsi/src/q_qosmatch.c index abac093..f7ee363 100644 --- a/src/core/ddsi/src/q_qosmatch.c +++ b/src/core/ddsi/src/q_qosmatch.c @@ -17,7 +17,7 @@ #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_qosmatch.h" -int is_wildcard_partition (const char *str) +static int is_wildcard_partition (const char *str) { return strchr (str, '*') || strchr (str, '?'); } @@ -66,46 +66,6 @@ int partitions_match_p (const nn_xqos_t *a, const nn_xqos_t *b) } } -int partition_match_based_on_wildcard_in_left_operand (const nn_xqos_t *a, const nn_xqos_t *b, const char **realname) -{ - assert (partitions_match_p (a, b)); - if (!(a->present & QP_PARTITION) || a->partition.n == 0) - { - return 0; - } - else if (!(b->present & QP_PARTITION) || b->partition.n == 0) - { - /* Either A explicitly includes the default partition, or it is a - wildcard that matches it */ - unsigned i; - for (i = 0; i < a->partition.n; i++) - if (strcmp (a->partition.strs[i], "") == 0) - return 0; - *realname = ""; - return 1; - } - else - { - unsigned i, j; - int maybe_yes = 0; - for (i = 0; i < a->partition.n; i++) - for (j = 0; j < b->partition.n; j++) - { - if (partition_patmatch_p (a->partition.strs[i], b->partition.strs[j])) - { - if (!is_wildcard_partition (a->partition.strs[i])) - return 0; - else - { - *realname = b->partition.strs[j]; - maybe_yes = 1; - } - } - } - return maybe_yes; - } -} - static int ddsi_duration_is_lt (nn_duration_t a0, nn_duration_t b0) { /* inf counts as <= inf */ diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 9923a91..aff4669 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -19,6 +19,7 @@ #include "dds/ddsrt/md5.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/string.h" +#include "dds/ddsrt/static_assert.h" #include "dds/ddsrt/avl.h" #include "dds__stream.h" @@ -46,7 +47,6 @@ #include "dds/ddsi/q_transmit.h" #include "dds/ddsi/q_globals.h" -#include "dds/ddsi/q_static_assert.h" #include "dds/ddsi/q_init.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_mcgroup.h" @@ -1613,7 +1613,7 @@ static int handle_one_gap (struct proxy_writer *pwr, struct pwr_rd_match *wn, se anything useful, or there was insufficient memory to store it. When the result is either ACCEPT or a sample chain, it clearly meant something. */ - Q_STATIC_ASSERT_CODE (NN_REORDER_ACCEPT == 0); + DDSRT_STATIC_ASSERT_CODE (NN_REORDER_ACCEPT == 0); if (res >= 0) gap_was_valuable = 1; @@ -1877,7 +1877,7 @@ unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr) case SMID_DATA_FRAG: { unsigned char common = smhdr->flags & DATA_FLAG_INLINE_QOS; - Q_STATIC_ASSERT_CODE (DATA_FLAG_INLINE_QOS == DATAFRAG_FLAG_INLINE_QOS); + DDSRT_STATIC_ASSERT_CODE (DATA_FLAG_INLINE_QOS == DATAFRAG_FLAG_INLINE_QOS); if (smhdr->flags & DATAFRAG_FLAG_KEYFLAG) return common | DATA_FLAG_KEYFLAG; else diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index 5518176..ca0ae3f 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -89,15 +89,15 @@ void thread_states_init (unsigned maxthreads) thread_states.ts = ddsrt_malloc_aligned_cacheline (maxthreads * sizeof (*thread_states.ts)); memset (thread_states.ts, 0, maxthreads * sizeof (*thread_states.ts)); -/* The compiler doesn't realize that ts is large enough. */ -DDSRT_WARNING_MSVC_OFF(6386); + /* The compiler doesn't realize that ts is large enough. */ + DDSRT_WARNING_MSVC_OFF(6386); for (i = 0; i < thread_states.nthreads; i++) { thread_states.ts[i].state = THREAD_STATE_ZERO; thread_states.ts[i].vtime = 0u; thread_states.ts[i].name = NULL; } -DDSRT_WARNING_MSVC_ON(6386); + DDSRT_WARNING_MSVC_ON(6386); } void thread_states_fini (void) diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 499b6f0..a47c12c 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -14,6 +14,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" +#include "dds/ddsrt/static_assert.h" #include "dds/ddsrt/avl.h" #include "dds/ddsi/q_entity.h" @@ -30,7 +31,6 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_hbcontrol.h" -#include "dds/ddsi/q_static_assert.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_sertopic.h" @@ -598,7 +598,7 @@ dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const stru if (xmsg_kind == NN_XMSG_KIND_DATA_REXMIT) nn_xmsg_set_data_readerId (*pmsg, &ddcmn->readerId); - Q_STATIC_ASSERT_CODE (DATA_FLAG_INLINE_QOS == DATAFRAG_FLAG_INLINE_QOS); + DDSRT_STATIC_ASSERT_CODE (DATA_FLAG_INLINE_QOS == DATAFRAG_FLAG_INLINE_QOS); assert (!(ddcmn->smhdr.flags & DATAFRAG_FLAG_INLINE_QOS)); if (fragnum == 0) diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 4a2f5b1..ca286ed 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -111,7 +111,9 @@ list(APPEND headers "${include_path}/dds/ddsrt/process.h" "${include_path}/dds/ddsrt/strtod.h" "${include_path}/dds/ddsrt/strtol.h" - "${include_path}/dds/ddsrt/types.h") + "${include_path}/dds/ddsrt/types.h" + "${include_path}/dds/ddsrt/countargs.h" + "${include_path}/dds/ddsrt/static_assert.h") list(APPEND sources "${source_path}/io.c" diff --git a/src/ddsrt/include/dds/ddsrt/atomics/msvc.h b/src/ddsrt/include/dds/ddsrt/atomics/msvc.h index e4418e1..f7f2218 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/msvc.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/msvc.h @@ -157,46 +157,46 @@ inline void *ddsrt_atomic_addvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff inline void ddsrt_atomic_sub32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { /* disable unary minus applied to unsigned type, result still unsigned */ -DDSRT_WARNING_MSVC_OFF(4146) + DDSRT_WARNING_MSVC_OFF(4146) InterlockedExchangeAdd (&x->v, -v); -DDSRT_WARNING_MSVC_ON(4146) + DDSRT_WARNING_MSVC_ON(4146) } #if DDSRT_HAVE_ATOMIC64 inline void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) { /* disable unary minus applied to unsigned type, result still unsigned */ -DDSRT_WARNING_MSVC_OFF(4146) + DDSRT_WARNING_MSVC_OFF(4146) InterlockedExchangeAdd64 (&x->v, -v); -DDSRT_WARNING_MSVC_ON(4146) + DDSRT_WARNING_MSVC_ON(4146) } #endif inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) { /* disable unary minus applied to unsigned type, result still unsigned */ -DDSRT_WARNING_MSVC_OFF(4146) + DDSRT_WARNING_MSVC_OFF(4146) DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, -v); -DDSRT_WARNING_MSVC_ON(4146) + DDSRT_WARNING_MSVC_ON(4146) } inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) { ddsrt_atomic_subptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v); } inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { /* disable unary minus applied to unsigned type, result still unsigned */ -DDSRT_WARNING_MSVC_OFF(4146) + DDSRT_WARNING_MSVC_OFF(4146) return InterlockedExchangeAdd (&x->v, -v) - v; -DDSRT_WARNING_MSVC_ON(4146) + DDSRT_WARNING_MSVC_ON(4146) } #if DDSRT_HAVE_ATOMIC64 inline uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) { /* disable unary minus applied to unsigned type, result still unsigned */ -DDSRT_WARNING_MSVC_OFF(4146) + DDSRT_WARNING_MSVC_OFF(4146) return InterlockedExchangeAdd64 (&x->v, -v) - v; -DDSRT_WARNING_MSVC_ON(4146) + DDSRT_WARNING_MSVC_ON(4146) } #endif inline uintptr_t ddsrt_atomic_subptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) { /* disable unary minus applied to unsigned type, result still unsigned */ -DDSRT_WARNING_MSVC_OFF(4146) + DDSRT_WARNING_MSVC_OFF(4146) return DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, -v) - v; -DDSRT_WARNING_MSVC_ON(4146) + DDSRT_WARNING_MSVC_ON(4146) } inline void *ddsrt_atomic_subvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) { return (void *) ddsrt_atomic_subptr_nv ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v); @@ -280,10 +280,10 @@ inline void ddsrt_atomic_fence (void) { /* 28113: accessing a local variable tmp via an Interlocked function: This is an unusual usage which could be reconsidered. It is too heavyweight, true, but it does the trick. */ -DDSRT_WARNING_MSVC_OFF(28113) + DDSRT_WARNING_MSVC_OFF(28113) volatile LONG tmp = 0; InterlockedExchange (&tmp, 0); -DDSRT_WARNING_MSVC_ON(28113) + DDSRT_WARNING_MSVC_ON(28113) } inline void ddsrt_atomic_fence_ldld (void) { #if !(defined _M_IX86 || defined _M_X64) diff --git a/src/ddsrt/include/dds/ddsrt/countargs.h b/src/ddsrt/include/dds/ddsrt/countargs.h new file mode 100644 index 0000000..69e6773 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/countargs.h @@ -0,0 +1,20 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSRT_COUNTARGS_H +#define DDSRT_COUNTARGS_H + +#define DDSRT_COUNT_ARGS_MSVC_WORKAROUND(x) x +#define DDSRT_COUNT_ARGS(...) DDSRT_COUNT_ARGS1 (__VA_ARGS__, 10,9,8,7,6,5,4,3,2,1,0) +#define DDSRT_COUNT_ARGS1(...) DDSRT_COUNT_ARGS_MSVC_WORKAROUND (DDSRT_COUNT_ARGS_ARGN (__VA_ARGS__)) +#define DDSRT_COUNT_ARGS_ARGN(a,b,c,d,e,f,g,h,i,j,n,...) n + +#endif diff --git a/src/ddsrt/include/dds/ddsrt/environ.h b/src/ddsrt/include/dds/ddsrt/environ.h index ddc4167..950d3ce 100644 --- a/src/ddsrt/include/dds/ddsrt/environ.h +++ b/src/ddsrt/include/dds/ddsrt/environ.h @@ -24,11 +24,7 @@ extern "C" { * @brief Get value for environment variable. * * @param[in] name Environment variable name. - * @param[in] buf Buffer to write value to. - * @param[in] sz Size of buffer. - * @param[out] reqsz Number of bytes written (excluding the terminating null - * byte), or would have been written would @buf have been - * sufficiently large enough. + * @param[out] value Alias to value of environment variable - must not be modified * * @returns A dds_return_t indicating success or failure. * diff --git a/src/ddsrt/include/dds/ddsrt/process.h b/src/ddsrt/include/dds/ddsrt/process.h index 6a39c4a..2d59130 100644 --- a/src/ddsrt/include/dds/ddsrt/process.h +++ b/src/ddsrt/include/dds/ddsrt/process.h @@ -106,7 +106,7 @@ ddsrt_proc_create( * See ddsrt_proc_waitpids() for waiting on all child processes. * * @param[in] pid Process ID (PID) to get the exit code from. - * @param[in] timemout Time within the process is expected to finish. + * @param[in] timeout Time within the process is expected to finish. * @param[out] code The exit code of the process. * * @returns A dds_return_t indicating success or failure. @@ -145,7 +145,7 @@ ddsrt_proc_waitpid( * * See ddsrt_proc_waitpid() for waiting on a specific child process. * - * @param[in] timemout Time within a process is expected to finish. + * @param[in] timeout Time within a process is expected to finish. * @param[out] pid Process ID (PID) of the finished process. * @param[out] code The exit code of the process. * diff --git a/src/ddsrt/include/dds/ddsrt/retcode.h b/src/ddsrt/include/dds/ddsrt/retcode.h index ca2cc8a..20b106f 100644 --- a/src/ddsrt/include/dds/ddsrt/retcode.h +++ b/src/ddsrt/include/dds/ddsrt/retcode.h @@ -84,7 +84,7 @@ typedef int32_t dds_return_t; /** * @brief Takes the error value and outputs a string corresponding to it. * - * @param[in] err Error value to be converted to a string + * @param[in] ret Error value to be converted to a string * * @returns String corresponding to the error value */ diff --git a/src/ddsrt/include/dds/ddsrt/sockets.h b/src/ddsrt/include/dds/ddsrt/sockets.h index e783b89..0f55e2b 100644 --- a/src/ddsrt/include/dds/ddsrt/sockets.h +++ b/src/ddsrt/include/dds/ddsrt/sockets.h @@ -247,7 +247,7 @@ typedef struct { * * @param[in] name Host name to resolve. * @param[in] af Address family, either AF_INET, AF_INET6 or AF_UNSPEC. - * @param[out] hent Structure of type ddsrt_hostent_t. + * @param[out] hentp Structure of type ddsrt_hostent_t. * * @returns A dds_return_t indicating success or failure. * diff --git a/src/core/ddsi/include/dds/ddsi/q_static_assert.h b/src/ddsrt/include/dds/ddsrt/static_assert.h similarity index 58% rename from src/core/ddsi/include/dds/ddsi/q_static_assert.h rename to src/ddsrt/include/dds/ddsrt/static_assert.h index 078ed62..f21d44f 100644 --- a/src/core/ddsi/include/dds/ddsi/q_static_assert.h +++ b/src/ddsrt/include/dds/ddsrt/static_assert.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * Copyright(c) 2019 ADLINK Technology Limited and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -9,29 +9,34 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef Q_STATIC_ASSERT_H -#define Q_STATIC_ASSERT_H +#ifndef DDSRT_STATIC_ASSERT_H +#define DDSRT_STATIC_ASSERT_H /* There are many tricks to use a constant expression to yield an illegal type or expression at compile time, such as zero-sized arrays and duplicate case or enum labels. So this is but one of the many tricks. */ +#define DDSRT_STATIC_ASSERT2(line, pred) \ + struct static_assert_##line { \ + char cond[(pred) ? 1 : -1]; \ + } +#define DDSRT_STATIC_ASSERT1(line, pred) \ + DDSRT_STATIC_ASSERT2 (line, pred) +#define DDSRT_STATIC_ASSERT(pred) \ + DDSRT_STATIC_ASSERT1 (__LINE__, pred) + #ifndef _MSC_VER - -#define Q_STATIC_ASSERT_CODE(pred) do { switch(0) { case 0: case pred: ; } } while (0) - +#define DDSRT_STATIC_ASSERT_CODE(pred) do { switch(0) { case 0: case (pred): ; } } while (0) #else - /* Temporarily disabling warning C6326: Potential comparison of a constant with another constant. */ -#define Q_STATIC_ASSERT_CODE(pred) do { \ +#define DDSRT_STATIC_ASSERT_CODE(pred) do { \ __pragma (warning (push)) \ __pragma (warning (disable : 6326)) \ - switch(0) { case 0: case pred: ; } \ + switch(0) { case 0: case (pred): ; } \ __pragma (warning (pop)) \ } while (0) - #endif -#endif /* Q_STATIC_ASSERT_H */ +#endif diff --git a/src/ddsrt/include/dds/ddsrt/string.h b/src/ddsrt/include/dds/ddsrt/string.h index 68d3181..1d449b7 100644 --- a/src/ddsrt/include/dds/ddsrt/string.h +++ b/src/ddsrt/include/dds/ddsrt/string.h @@ -57,7 +57,7 @@ ddsrt_nonnull((1,2)); * * @param[in] str String to split into tokens. * @param[in] delim Characters that delimit a token. - * @param[inout] saveptr Pointer to a char * used internally. + * @param[in,out] saveptr Pointer to a char * used internally. * * @returns The next token or NULL if there are no more tokens. */ @@ -74,7 +74,7 @@ ddsrt_strtok_r( * @delim. The delimiter is overwritten with a null byte, terminating the * token and @stringp is updated to point past the delimiter. * - * @param[inout] stringp String to extract token from. + * @param[in,out] stringp String to extract token from. * @param[in] delim Characters that delimit a token. * * @returns The original value of @stringp. @@ -153,7 +153,7 @@ ddsrt_nonnull((1,2)); * string is truncated if there is not enough space. The resulting string * guaranteed to be null terminated if there is space. * - * @param[inout] dest Destination buffer. + * @param[in,out] dest Destination buffer. * @param[in] src Null terminated string to append to dest. * @param[in] size Number of bytes available in dest. * diff --git a/src/ddsrt/src/random.c b/src/ddsrt/src/random.c index 7f2943a..b5b2ac6 100644 --- a/src/ddsrt/src/random.c +++ b/src/ddsrt/src/random.c @@ -61,6 +61,7 @@ #include "dds/ddsrt/sync.h" #include "dds/ddsrt/time.h" #include "dds/ddsrt/process.h" +#include "dds/ddsrt/static_assert.h" #define N DDSRT_MT19937_N #define M 397 @@ -186,9 +187,7 @@ void ddsrt_random_init (void) if (!ddsrt_prng_makeseed (&seed)) { /* Poor man's initialisation */ - struct lengthof_seed_large_enough { - char ok[sizeof (seed.key) / sizeof (seed.key[0]) >= 3 ? 1 : -1]; - }; + DDSRT_STATIC_ASSERT (sizeof (seed.key) / sizeof (seed.key[0]) >= 3); memset (&seed, 0, sizeof (seed)); dds_time_t now = dds_time (); seed.key[0] = (uint32_t) ddsrt_getpid (); diff --git a/src/ddsrt/src/xmlparser.c b/src/ddsrt/src/xmlparser.c index 193522b..4b4bb4b 100644 --- a/src/ddsrt/src/xmlparser.c +++ b/src/ddsrt/src/xmlparser.c @@ -305,9 +305,9 @@ static char *unescape_into_utf8 (char *dst, unsigned cp) return dst; } -DDSRT_WARNING_MSVC_OFF(4996); static int unescape_insitu (char *buffer, size_t *n) { + DDSRT_WARNING_MSVC_OFF(4996); const char *src = buffer; char const * const srcend = buffer + *n; char *dst = buffer; @@ -361,8 +361,8 @@ static int unescape_insitu (char *buffer, size_t *n) } *n = (size_t) (dst - buffer); return 0; + DDSRT_WARNING_MSVC_ON(4996); } -DDSRT_WARNING_MSVC_ON(4996); static void discard_payload (struct ddsrt_xmlp_state *st) { From 12e69461633a71c15230ffe5150e020cbea0edd8 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 26 May 2019 12:12:00 +0200 Subject: [PATCH 084/178] Remove QoS duplication between DDS and DDSI All this duplication was rather useless: the values are standardized anyway and the conversion was a simple type cast without any check. This commit unifies the definitions. * DDSI now uses the definitions of the various QoS "kind" values from the header file; * The durations in the QoS objects are no longer in wire-format representation, the conversions now happen only in conversion to/from wire format; * The core DDSI stack no longer uses DDSI time representations for time stamps, instead using the "native" one; * QoS policy ids duplication has been eliminated, again using the IDs visible in the API -- the actual values are meaningless to the DDSI stack anyway. Signed-off-by: Erik Boasson --- src/core/ddsc/CMakeLists.txt | 1 + .../ddsc/include/dds/ddsc/dds_public_impl.h | 2 - .../ddsc/include/dds/ddsc/dds_public_qos.h | 121 +-- .../include/dds/ddsc/dds_public_qosdefs.h | 132 +++ src/core/ddsc/src/dds__qos.h | 12 +- src/core/ddsc/src/dds__rhc.h | 4 +- src/core/ddsc/src/dds__serdata_builtintopic.h | 2 +- src/core/ddsc/src/dds_builtin.c | 2 +- src/core/ddsc/src/dds_qos.c | 139 ++- src/core/ddsc/src/dds_reader.c | 4 +- src/core/ddsc/src/dds_rhc.c | 12 +- src/core/ddsc/src/dds_serdata_builtintopic.c | 2 +- src/core/ddsc/src/dds_topic.c | 2 +- src/core/ddsc/src/dds_write.c | 4 +- src/core/ddsc/src/dds_writer.c | 10 +- src/core/ddsc/tests/entity_status.c | 9 +- .../ddsi/include/dds/ddsi/ddsi_rhc_plugin.h | 6 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 18 +- src/core/ddsi/include/dds/ddsi/q_globals.h | 18 +- src/core/ddsi/include/dds/ddsi/q_plist.h | 31 +- src/core/ddsi/include/dds/ddsi/q_protocol.h | 6 +- src/core/ddsi/include/dds/ddsi/q_qosmatch.h | 6 +- src/core/ddsi/include/dds/ddsi/q_radmin.h | 2 +- src/core/ddsi/include/dds/ddsi/q_time.h | 24 +- src/core/ddsi/include/dds/ddsi/q_xmsg.h | 30 +- src/core/ddsi/include/dds/ddsi/q_xqos.h | 350 ++++---- src/core/ddsi/src/ddsi_rhc_plugin.c | 2 +- src/core/ddsi/src/q_ddsi_discovery.c | 32 +- src/core/ddsi/src/q_debmon.c | 4 +- src/core/ddsi/src/q_entity.c | 94 +- src/core/ddsi/src/q_init.c | 10 +- src/core/ddsi/src/q_plist.c | 844 ++++++++---------- src/core/ddsi/src/q_qosmatch.c | 161 ++-- src/core/ddsi/src/q_receive.c | 42 +- src/core/ddsi/src/q_time.c | 26 +- src/core/ddsi/src/q_transmit.c | 8 +- src/core/ddsi/src/q_xmsg.c | 134 ++- src/core/xtests/rhc_torture/rhc_torture.c | 10 +- 38 files changed, 1074 insertions(+), 1242 deletions(-) create mode 100644 src/core/ddsc/include/dds/ddsc/dds_public_qosdefs.h diff --git a/src/core/ddsc/CMakeLists.txt b/src/core/ddsc/CMakeLists.txt index 3475af6..9c0d16d 100644 --- a/src/core/ddsc/CMakeLists.txt +++ b/src/core/ddsc/CMakeLists.txt @@ -46,6 +46,7 @@ PREPEND(hdrs_public_ddsc "$wr.xqos) && !qos_has_resource_limits (qos); + return !qos_match_p (qos, bwr->wr.xqos, NULL) && !qos_has_resource_limits (qos); } } diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index a1771f8..3d2ccb1 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -14,12 +14,7 @@ #include "dds__qos.h" #include "dds/ddsi/q_config.h" -/* TODO: dd_duration_t is converted to nn_ddsi_time_t declared in q_time.h - This structure contain seconds and fractions. - Revisit on the conversion as default values are { 0x7fffffff, 0xffffffff } -*/ - -static void dds_qos_data_copy_in (nn_octetseq_t *data, const void * __restrict value, size_t sz) +static void dds_qos_data_copy_in (ddsi_octetseq_t *data, const void * __restrict value, size_t sz) { if (data->value) { @@ -34,7 +29,7 @@ static void dds_qos_data_copy_in (nn_octetseq_t *data, const void * __restrict v } } -static bool dds_qos_data_copy_out (const nn_octetseq_t *data, void **value, size_t *sz) +static bool dds_qos_data_copy_out (const ddsi_octetseq_t *data, void **value, size_t *sz) { assert (data->length < UINT32_MAX); if (sz == NULL && value != NULL) @@ -57,13 +52,13 @@ static bool dds_qos_data_copy_out (const nn_octetseq_t *data, void **value, size return true; } -bool validate_octetseq (const nn_octetseq_t *seq) +bool validate_octetseq (const ddsi_octetseq_t *seq) { /* default value is NULL with length 0 */ return ((seq->length == 0 && seq->value == NULL) || (seq->length > 0 && seq->length < UINT32_MAX)); } -bool validate_stringseq (const nn_stringseq_t *seq) +bool validate_stringseq (const ddsi_stringseq_t *seq) { if (seq->n == 0) return (seq->strs == NULL); @@ -76,30 +71,30 @@ bool validate_stringseq (const nn_stringseq_t *seq) } } -bool validate_entityfactory_qospolicy (const nn_entity_factory_qospolicy_t *entityfactory) +bool validate_entityfactory_qospolicy (const dds_entity_factory_qospolicy_t *entityfactory) { /* Bools must be 0 or 1, i.e., only the lsb may be set */ return !(entityfactory->autoenable_created_entities & ~1); } -bool validate_reliability_qospolicy (const nn_reliability_qospolicy_t *reliability) +bool validate_reliability_qospolicy (const dds_reliability_qospolicy_t *reliability) { - return ((reliability->kind == NN_BEST_EFFORT_RELIABILITY_QOS || reliability->kind == NN_RELIABLE_RELIABILITY_QOS) && - (validate_duration (&reliability->max_blocking_time) == 0)); + return ((reliability->kind == DDS_RELIABILITY_BEST_EFFORT || reliability->kind == DDS_RELIABILITY_RELIABLE) && + (validate_duration (reliability->max_blocking_time) == 0)); } -bool validate_deadline_and_timebased_filter (const nn_duration_t deadline, const nn_duration_t minimum_separation) +bool validate_deadline_and_timebased_filter (const dds_duration_t deadline, const dds_duration_t minimum_separation) { - return (validate_duration (&deadline) == DDS_RETCODE_OK && - validate_duration (&minimum_separation) == DDS_RETCODE_OK && - nn_from_ddsi_duration (minimum_separation) <= nn_from_ddsi_duration (deadline)); + return (validate_duration (deadline) == DDS_RETCODE_OK && + validate_duration (minimum_separation) == DDS_RETCODE_OK && + minimum_separation <= deadline); } bool dds_qos_validate_common (const dds_qos_t *qos) { return !(((qos->present & QP_DURABILITY) && validate_durability_qospolicy (&qos->durability) != DDS_RETCODE_OK) || - ((qos->present & QP_DEADLINE) && validate_duration (&qos->deadline.deadline) != DDS_RETCODE_OK) || - ((qos->present & QP_LATENCY_BUDGET) && validate_duration (&qos->latency_budget.duration) != DDS_RETCODE_OK) || + ((qos->present & QP_DEADLINE) && validate_duration (qos->deadline.deadline) != DDS_RETCODE_OK) || + ((qos->present & QP_LATENCY_BUDGET) && validate_duration (qos->latency_budget.duration) != DDS_RETCODE_OK) || ((qos->present & QP_OWNERSHIP) && validate_ownership_qospolicy (&qos->ownership) != DDS_RETCODE_OK) || ((qos->present & QP_LIVELINESS) && validate_liveliness_qospolicy (&qos->liveliness) != DDS_RETCODE_OK) || ((qos->present & QP_RELIABILITY) && ! validate_reliability_qospolicy (&qos->reliability)) || @@ -134,32 +129,32 @@ static void dds_qos_init_defaults (dds_qos_t * __restrict qos) { assert (qos); memset (qos, 0, sizeof (*qos)); - qos->durability.kind = (nn_durability_kind_t) DDS_DURABILITY_VOLATILE; - qos->deadline.deadline = nn_to_ddsi_duration (DDS_INFINITY); - qos->durability_service.service_cleanup_delay = nn_to_ddsi_duration (0); - qos->durability_service.history.kind = (nn_history_kind_t) DDS_HISTORY_KEEP_LAST; + qos->durability.kind = DDS_DURABILITY_VOLATILE; + qos->deadline.deadline = DDS_INFINITY; + qos->durability_service.service_cleanup_delay = 0; + qos->durability_service.history.kind = DDS_HISTORY_KEEP_LAST; qos->durability_service.history.depth = 1; qos->durability_service.resource_limits.max_samples = DDS_LENGTH_UNLIMITED; qos->durability_service.resource_limits.max_instances = DDS_LENGTH_UNLIMITED; qos->durability_service.resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED; - qos->presentation.access_scope = (nn_presentation_access_scope_kind_t) DDS_PRESENTATION_INSTANCE; - qos->latency_budget.duration = nn_to_ddsi_duration (0); - qos->ownership.kind = (nn_ownership_kind_t) DDS_OWNERSHIP_SHARED; - qos->liveliness.kind = (nn_liveliness_kind_t) DDS_LIVELINESS_AUTOMATIC; - qos->liveliness.lease_duration = nn_to_ddsi_duration (DDS_INFINITY); - qos->time_based_filter.minimum_separation = nn_to_ddsi_duration (0); - qos->reliability.kind = (nn_reliability_kind_t) DDS_RELIABILITY_BEST_EFFORT; - qos->reliability.max_blocking_time = nn_to_ddsi_duration (DDS_MSECS (100)); - qos->lifespan.duration = nn_to_ddsi_duration (DDS_INFINITY); - qos->destination_order.kind = (nn_destination_order_kind_t) DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP; - qos->history.kind = (nn_history_kind_t) DDS_HISTORY_KEEP_LAST; + qos->presentation.access_scope = DDS_PRESENTATION_INSTANCE; + qos->latency_budget.duration = 0; + qos->ownership.kind = DDS_OWNERSHIP_SHARED; + qos->liveliness.kind = DDS_LIVELINESS_AUTOMATIC; + qos->liveliness.lease_duration = DDS_INFINITY; + qos->time_based_filter.minimum_separation = 0; + qos->reliability.kind = DDS_RELIABILITY_BEST_EFFORT; + qos->reliability.max_blocking_time = DDS_MSECS (100); + qos->lifespan.duration = DDS_INFINITY; + qos->destination_order.kind = DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP; + qos->history.kind = DDS_HISTORY_KEEP_LAST; qos->history.depth = 1; qos->resource_limits.max_samples = DDS_LENGTH_UNLIMITED; qos->resource_limits.max_instances = DDS_LENGTH_UNLIMITED; qos->resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED; qos->writer_data_lifecycle.autodispose_unregistered_instances = true; - qos->reader_data_lifecycle.autopurge_nowriter_samples_delay = nn_to_ddsi_duration (DDS_INFINITY); - qos->reader_data_lifecycle.autopurge_disposed_samples_delay = nn_to_ddsi_duration (DDS_INFINITY); + qos->reader_data_lifecycle.autopurge_nowriter_samples_delay = DDS_INFINITY; + qos->reader_data_lifecycle.autopurge_disposed_samples_delay = DDS_INFINITY; } dds_qos_t *dds_create_qos (void) @@ -269,7 +264,7 @@ void dds_qset_durability (dds_qos_t * __restrict qos, dds_durability_kind_t kind { if (qos != NULL) { - qos->durability.kind = (nn_durability_kind_t) kind; + qos->durability.kind = kind; qos->present |= QP_DURABILITY; } } @@ -278,7 +273,7 @@ void dds_qset_history (dds_qos_t * __restrict qos, dds_history_kind_t kind, int3 { if (qos != NULL) { - qos->history.kind = (nn_history_kind_t) kind; + qos->history.kind = kind; qos->history.depth = depth; qos->present |= QP_HISTORY; } @@ -299,7 +294,7 @@ void dds_qset_presentation (dds_qos_t * __restrict qos, dds_presentation_access_ { if (qos != NULL) { - qos->presentation.access_scope = (nn_presentation_access_scope_kind_t) access_scope; + qos->presentation.access_scope = access_scope; qos->presentation.coherent_access = coherent_access; qos->presentation.ordered_access = ordered_access; qos->present |= QP_PRESENTATION; @@ -310,7 +305,7 @@ void dds_qset_lifespan (dds_qos_t * __restrict qos, dds_duration_t lifespan) { if (qos != NULL) { - qos->lifespan.duration = nn_to_ddsi_duration (lifespan); + qos->lifespan.duration = lifespan; qos->present |= QP_LIFESPAN; } } @@ -319,7 +314,7 @@ void dds_qset_deadline (dds_qos_t * __restrict qos, dds_duration_t deadline) { if (qos != NULL) { - qos->deadline.deadline = nn_to_ddsi_duration (deadline); + qos->deadline.deadline = deadline; qos->present |= QP_DEADLINE; } } @@ -328,7 +323,7 @@ void dds_qset_latency_budget (dds_qos_t * __restrict qos, dds_duration_t duratio { if (qos != NULL) { - qos->latency_budget.duration = nn_to_ddsi_duration (duration); + qos->latency_budget.duration = duration; qos->present |= QP_LATENCY_BUDGET; } } @@ -337,7 +332,7 @@ void dds_qset_ownership (dds_qos_t * __restrict qos, dds_ownership_kind_t kind) { if (qos != NULL) { - qos->ownership.kind = (nn_ownership_kind_t) kind; + qos->ownership.kind = kind; qos->present |= QP_OWNERSHIP; } } @@ -355,8 +350,8 @@ void dds_qset_liveliness (dds_qos_t * __restrict qos, dds_liveliness_kind_t kind { if (qos != NULL) { - qos->liveliness.kind = (nn_liveliness_kind_t) kind; - qos->liveliness.lease_duration = nn_to_ddsi_duration (lease_duration); + qos->liveliness.kind = kind; + qos->liveliness.lease_duration = lease_duration; qos->present |= QP_LIVELINESS; } } @@ -365,7 +360,7 @@ void dds_qset_time_based_filter (dds_qos_t * __restrict qos, dds_duration_t mini { if (qos != NULL) { - qos->time_based_filter.minimum_separation = nn_to_ddsi_duration (minimum_separation); + qos->time_based_filter.minimum_separation = minimum_separation; qos->present |= QP_TIME_BASED_FILTER; } } @@ -405,8 +400,8 @@ void dds_qset_reliability (dds_qos_t * __restrict qos, dds_reliability_kind_t ki { if (qos != NULL) { - qos->reliability.kind = (nn_reliability_kind_t) kind; - qos->reliability.max_blocking_time = nn_to_ddsi_duration (max_blocking_time); + qos->reliability.kind = kind; + qos->reliability.max_blocking_time = max_blocking_time; qos->present |= QP_RELIABILITY; } } @@ -424,7 +419,7 @@ void dds_qset_destination_order (dds_qos_t * __restrict qos, dds_destination_ord { if (qos != NULL) { - qos->destination_order.kind = (nn_destination_order_kind_t) kind; + qos->destination_order.kind = kind; qos->present |= QP_DESTINATION_ORDER; } } @@ -442,8 +437,8 @@ void dds_qset_reader_data_lifecycle (dds_qos_t * __restrict qos, dds_duration_t { if (qos != NULL) { - qos->reader_data_lifecycle.autopurge_nowriter_samples_delay = nn_to_ddsi_duration (autopurge_nowriter_samples_delay); - qos->reader_data_lifecycle.autopurge_disposed_samples_delay = nn_to_ddsi_duration (autopurge_disposed_samples_delay); + qos->reader_data_lifecycle.autopurge_nowriter_samples_delay = autopurge_nowriter_samples_delay; + qos->reader_data_lifecycle.autopurge_disposed_samples_delay = autopurge_disposed_samples_delay; qos->present |= QP_PRISMTECH_READER_DATA_LIFECYCLE; } } @@ -452,8 +447,8 @@ void dds_qset_durability_service (dds_qos_t * __restrict qos, dds_duration_t ser { if (qos != NULL) { - qos->durability_service.service_cleanup_delay = nn_to_ddsi_duration (service_cleanup_delay); - qos->durability_service.history.kind = (nn_history_kind_t) history_kind; + qos->durability_service.service_cleanup_delay = service_cleanup_delay; + qos->durability_service.history.kind = history_kind; qos->durability_service.history.depth = history_depth; qos->durability_service.resource_limits.max_samples = max_samples; qos->durability_service.resource_limits.max_instances = max_instances; @@ -466,7 +461,7 @@ void dds_qset_ignorelocal (dds_qos_t * __restrict qos, dds_ignorelocal_kind_t ig { if (qos != NULL) { - qos->ignorelocal.value = (nn_ignorelocal_kind_t) ignore; + qos->ignorelocal.value = ignore; qos->present |= QP_CYCLONE_IGNORELOCAL; } } @@ -497,7 +492,7 @@ bool dds_qget_durability (const dds_qos_t * __restrict qos, dds_durability_kind_ if (qos == NULL || !(qos->present & QP_DURABILITY)) return false; if (kind) - *kind = (dds_durability_kind_t) qos->durability.kind; + *kind = qos->durability.kind; return true; } @@ -506,7 +501,7 @@ bool dds_qget_history (const dds_qos_t * __restrict qos, dds_history_kind_t *kin if (qos == NULL || !(qos->present & QP_HISTORY)) return false; if (kind) - *kind = (dds_history_kind_t) qos->history.kind; + *kind = qos->history.kind; if (depth) *depth = qos->history.depth; return true; @@ -530,7 +525,7 @@ bool dds_qget_presentation (const dds_qos_t * __restrict qos, dds_presentation_a if (qos == NULL || !(qos->present & QP_PRESENTATION)) return false; if (access_scope) - *access_scope = (dds_presentation_access_scope_kind_t) qos->presentation.access_scope; + *access_scope = qos->presentation.access_scope; if (coherent_access) *coherent_access = qos->presentation.coherent_access; if (ordered_access) @@ -543,7 +538,7 @@ bool dds_qget_lifespan (const dds_qos_t * __restrict qos, dds_duration_t *lifesp if (qos == NULL || !(qos->present & QP_LIFESPAN)) return false; if (lifespan) - *lifespan = nn_from_ddsi_duration (qos->lifespan.duration); + *lifespan = qos->lifespan.duration; return true; } @@ -552,7 +547,7 @@ bool dds_qget_deadline (const dds_qos_t * __restrict qos, dds_duration_t *deadli if (qos == NULL || !(qos->present & QP_DEADLINE)) return false; if (deadline) - *deadline = nn_from_ddsi_duration (qos->deadline.deadline); + *deadline = qos->deadline.deadline; return true; } @@ -561,7 +556,7 @@ bool dds_qget_latency_budget (const dds_qos_t * __restrict qos, dds_duration_t * if (qos == NULL || !(qos->present & QP_LATENCY_BUDGET)) return false; if (duration) - *duration = nn_from_ddsi_duration (qos->latency_budget.duration); + *duration = qos->latency_budget.duration; return true; } @@ -570,7 +565,7 @@ bool dds_qget_ownership (const dds_qos_t * __restrict qos, dds_ownership_kind_t if (qos == NULL || !(qos->present & QP_OWNERSHIP)) return false; if (kind) - *kind = (dds_ownership_kind_t) qos->ownership.kind; + *kind = qos->ownership.kind; return true; } @@ -588,9 +583,9 @@ bool dds_qget_liveliness (const dds_qos_t * __restrict qos, dds_liveliness_kind_ if (qos == NULL || !(qos->present & QP_LIVELINESS)) return false; if (kind) - *kind = (dds_liveliness_kind_t) qos->liveliness.kind; + *kind = qos->liveliness.kind; if (lease_duration) - *lease_duration = nn_from_ddsi_duration (qos->liveliness.lease_duration); + *lease_duration = qos->liveliness.lease_duration; return true; } @@ -599,7 +594,7 @@ bool dds_qget_time_based_filter (const dds_qos_t * __restrict qos, dds_duration_ if (qos == NULL || !(qos->present & QP_TIME_BASED_FILTER)) return false; if (minimum_separation) - *minimum_separation = nn_from_ddsi_duration (qos->time_based_filter.minimum_separation); + *minimum_separation = qos->time_based_filter.minimum_separation; return true; } @@ -630,9 +625,9 @@ bool dds_qget_reliability (const dds_qos_t * __restrict qos, dds_reliability_kin if (qos == NULL || !(qos->present & QP_RELIABILITY)) return false; if (kind) - *kind = (dds_reliability_kind_t) qos->reliability.kind; + *kind = qos->reliability.kind; if (max_blocking_time) - *max_blocking_time = nn_from_ddsi_duration (qos->reliability.max_blocking_time); + *max_blocking_time = qos->reliability.max_blocking_time; return true; } @@ -650,7 +645,7 @@ bool dds_qget_destination_order (const dds_qos_t * __restrict qos, dds_destinati if (qos == NULL || !(qos->present & QP_DESTINATION_ORDER)) return false; if (kind) - *kind = (dds_destination_order_kind_t) qos->destination_order.kind; + *kind = qos->destination_order.kind; return true; } @@ -668,9 +663,9 @@ bool dds_qget_reader_data_lifecycle (const dds_qos_t * __restrict qos, dds_durat if (qos == NULL || !(qos->present & QP_PRISMTECH_READER_DATA_LIFECYCLE)) return false; if (autopurge_nowriter_samples_delay) - *autopurge_nowriter_samples_delay = nn_from_ddsi_duration (qos->reader_data_lifecycle.autopurge_nowriter_samples_delay); + *autopurge_nowriter_samples_delay = qos->reader_data_lifecycle.autopurge_nowriter_samples_delay; if (autopurge_disposed_samples_delay) - *autopurge_disposed_samples_delay = nn_from_ddsi_duration (qos->reader_data_lifecycle.autopurge_disposed_samples_delay); + *autopurge_disposed_samples_delay = qos->reader_data_lifecycle.autopurge_disposed_samples_delay; return true; } @@ -679,9 +674,9 @@ bool dds_qget_durability_service (const dds_qos_t * __restrict qos, dds_duration if (qos == NULL || !(qos->present & QP_DURABILITY_SERVICE)) return false; if (service_cleanup_delay) - *service_cleanup_delay = nn_from_ddsi_duration (qos->durability_service.service_cleanup_delay); + *service_cleanup_delay = qos->durability_service.service_cleanup_delay; if (history_kind) - *history_kind = (dds_history_kind_t) qos->durability_service.history.kind; + *history_kind = qos->durability_service.history.kind; if (history_depth) *history_depth = qos->durability_service.history.depth; if (max_samples) @@ -698,6 +693,6 @@ bool dds_qget_ignorelocal (const dds_qos_t * __restrict qos, dds_ignorelocal_kin if (qos == NULL || !(qos->present & QP_CYCLONE_IGNORELOCAL)) return false; if (ignore) - *ignore = (dds_ignorelocal_kind_t) qos->ignorelocal.value; + *ignore = qos->ignorelocal.value; return true; } diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 8638251..6392124 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -87,7 +87,7 @@ static dds_return_t dds_reader_qos_validate (const dds_qos_t *qos, bool enabled) return DDS_RETCODE_INCONSISTENT_POLICY; if ((qos->present & QP_PRISMTECH_READER_DATA_LIFECYCLE) && validate_reader_data_lifecycle (&qos->reader_data_lifecycle) < 0) return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_TIME_BASED_FILTER) && validate_duration (&qos->time_based_filter.minimum_separation) < 0) + if ((qos->present & QP_TIME_BASED_FILTER) && validate_duration (qos->time_based_filter.minimum_separation) < 0) return DDS_RETCODE_INCONSISTENT_POLICY; if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits (&qos->history, &qos->resource_limits) < 0) return DDS_RETCODE_INCONSISTENT_POLICY; @@ -432,7 +432,7 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti thread_state_asleep (lookup_thread_state ()); /* For persistent data register reader with durability */ - if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > NN_TRANSIENT_LOCAL_DURABILITY_QOS)) { + if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > DDS_DURABILITY_TRANSIENT_LOCAL)) { (dds_global.m_dur_reader) (rd, rhc); } dds_topic_unlock (tp); diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 99f4508..e2c9f2b 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -464,18 +464,18 @@ struct rhc * dds_rhc_new (dds_reader * reader, const struct ddsi_sertopic * topi return rhc; } -void dds_rhc_set_qos (struct rhc * rhc, const nn_xqos_t * qos) +void dds_rhc_set_qos (struct rhc * rhc, const dds_qos_t * qos) { /* Set read related QoS */ rhc->max_samples = qos->resource_limits.max_samples; rhc->max_instances = qos->resource_limits.max_instances; rhc->max_samples_per_instance = qos->resource_limits.max_samples_per_instance; - rhc->by_source_ordering = (qos->destination_order.kind == NN_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS); - rhc->exclusive_ownership = (qos->ownership.kind == NN_EXCLUSIVE_OWNERSHIP_QOS); - rhc->reliable = (qos->reliability.kind == NN_RELIABLE_RELIABILITY_QOS); - assert(qos->history.kind != NN_KEEP_LAST_HISTORY_QOS || qos->history.depth > 0); - rhc->history_depth = (qos->history.kind == NN_KEEP_LAST_HISTORY_QOS) ? (uint32_t)qos->history.depth : ~0u; + rhc->by_source_ordering = (qos->destination_order.kind == DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP); + rhc->exclusive_ownership = (qos->ownership.kind == DDS_OWNERSHIP_EXCLUSIVE); + 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; } static bool eval_predicate_sample (const struct rhc *rhc, const struct ddsi_serdata *sample, bool (*pred) (const void *sample)) diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index f043783..03b6409 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -186,7 +186,7 @@ static char *dds_string_dup_reuse (char *old, const char *src) return memcpy (new, src, size); } -static dds_qos_t *dds_qos_from_xqos_reuse (dds_qos_t *old, const nn_xqos_t *src) +static dds_qos_t *dds_qos_from_xqos_reuse (dds_qos_t *old, const dds_qos_t *src) { if (old == NULL) { diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 13a6680..31390cf 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -188,7 +188,7 @@ static dds_return_t dds_topic_qos_validate (const dds_qos_t *qos, bool enabled) return DDS_RETCODE_INCONSISTENT_POLICY; if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy(&qos->durability_service) < 0) return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_LIFESPAN) && validate_duration(&qos->lifespan.duration) < 0) + if ((qos->present & QP_LIFESPAN) && validate_duration(qos->lifespan.duration) < 0) return DDS_RETCODE_INCONSISTENT_POLICY; if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits(&qos->history, &qos->resource_limits) < 0) return DDS_RETCODE_INCONSISTENT_POLICY; diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 70cd6c7..d399e80 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -96,7 +96,7 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay struct reader ** const rdary = wr->rdary.rdary; if (rdary[0]) { - dds_duration_t max_block_ms = nn_from_ddsi_duration (wr->xqos->reliability.max_blocking_time); + dds_duration_t max_block_ms = wr->xqos->reliability.max_blocking_time; struct proxy_writer_info pwr_info; unsigned i; make_proxy_writer_info (&pwr_info, &wr->e, wr->xqos); @@ -121,7 +121,7 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay ddsrt_avl_iter_t it; struct pwr_rd_match *m; struct proxy_writer_info pwr_info; - dds_duration_t max_block_ms = nn_from_ddsi_duration (wr->xqos->reliability.max_blocking_time); + dds_duration_t max_block_ms = wr->xqos->reliability.max_blocking_time; ddsrt_mutex_unlock (&wr->rdary.rdary_lock); make_proxy_writer_info (&pwr_info, &wr->e, wr->xqos); ddsrt_mutex_lock (&wr->e.lock); diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index e8749fc..542be62 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -162,7 +162,7 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) ddsrt_mutex_unlock (&entity->m_observers_lock); } -static uint32_t get_bandwidth_limit (nn_transport_priority_qospolicy_t transport_priority) +static uint32_t get_bandwidth_limit (dds_transport_priority_qospolicy_t transport_priority) { #ifdef DDSI_INCLUDE_NETWORK_CHANNELS struct config_channel_listelem *channel = find_channel (transport_priority); @@ -214,7 +214,7 @@ static dds_return_t dds_writer_qos_validate (const dds_qos_t *qos, bool enabled) return DDS_RETCODE_INCONSISTENT_POLICY; if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy (&qos->durability_service) < 0) return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_LIFESPAN) && validate_duration (&qos->lifespan.duration) < 0) + if ((qos->present & QP_LIFESPAN) && validate_duration (qos->lifespan.duration) < 0) return DDS_RETCODE_INCONSISTENT_POLICY; if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits(&qos->history, &qos->resource_limits) < 0) return DDS_RETCODE_INCONSISTENT_POLICY; @@ -264,8 +264,8 @@ static struct whc *make_whc (const dds_qos_t *qos) /* 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 == NN_TRANSIENT_LOCAL_DURABILITY_QOS); - if (qos->history.kind == NN_KEEP_ALL_HISTORY_QOS) + 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; @@ -273,7 +273,7 @@ static struct whc *make_whc (const dds_qos_t *qos) tldepth = 0; else { - if (qos->durability_service.history.kind == NN_KEEP_ALL_HISTORY_QOS) + if (qos->durability_service.history.kind == DDS_HISTORY_KEEP_ALL) tldepth = 0; else tldepth = (unsigned) qos->durability_service.history.depth; diff --git a/src/core/ddsc/tests/entity_status.c b/src/core/ddsc/tests/entity_status.c index 737fbf7..662d3ae 100644 --- a/src/core/ddsc/tests/entity_status.c +++ b/src/core/ddsc/tests/entity_status.c @@ -41,7 +41,14 @@ static dds_time_t waitTimeout = DDS_SECS (2); static dds_time_t shortTimeout = DDS_MSECS (10); static dds_publication_matched_status_t publication_matched; static dds_subscription_matched_status_t subscription_matched; -static dds_resource_limits_qospolicy_t resource_limits = {1,1,1}; + +struct reslimits { + int32_t max_samples; + int32_t max_instances; + int32_t max_samples_per_instance; +}; + +static struct reslimits resource_limits = {1,1,1}; static dds_instance_handle_t reader_i_hdl = 0; static dds_instance_handle_t writer_i_hdl = 0; diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h b/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h index 1d37ecf..20754fd 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h @@ -17,7 +17,7 @@ extern "C" { #endif struct rhc; -struct nn_xqos; +struct dds_qos; struct ddsi_tkmap_instance; struct ddsi_serdata; struct ddsi_sertopic; @@ -41,10 +41,10 @@ struct ddsi_rhc_plugin (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info); void (*rhc_relinquish_ownership_fn) (struct rhc * __restrict rhc, const uint64_t wr_iid); - void (*rhc_set_qos_fn) (struct rhc * rhc, const struct nn_xqos * qos); + void (*rhc_set_qos_fn) (struct rhc * rhc, const struct dds_qos * qos); }; -DDS_EXPORT void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct nn_xqos *xqos); +DDS_EXPORT void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct dds_qos *xqos); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 0312e6d..709ad36 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -38,7 +38,7 @@ struct nn_rdata; struct addrset; struct ddsi_sertopic; struct whc; -struct nn_xqos; +struct dds_qos; struct nn_plist; struct lease; @@ -228,7 +228,7 @@ struct writer nn_count_t hbfragcount; /* last hb frag seq number */ int throttling; /* non-zero when some thread is waiting for the WHC to shrink */ struct hbcontrol hbcontrol; /* controls heartbeat timing, piggybacking */ - struct nn_xqos *xqos; + struct dds_qos *xqos; enum writer_state state; unsigned reliable: 1; /* iff 1, writer is reliable <=> heartbeat_xevent != NULL */ unsigned handle_as_transient_local: 1; /* controls whether data is retained in WHC */ @@ -270,7 +270,7 @@ struct reader status_cb_t status_cb; void * status_cb_entity; struct rhc * rhc; /* reader history, tracks registrations and data */ - struct nn_xqos *xqos; + struct dds_qos *xqos; unsigned reliable: 1; /* 1 iff reader is reliable */ unsigned handle_as_transient_local: 1; /* 1 iff reader wants historical data from proxy writers */ #ifdef DDSI_INCLUDE_SSM @@ -323,7 +323,7 @@ struct proxy_group { nn_guid_t guid; char *name; struct proxy_participant *proxypp; /* uncounted backref to proxy participant */ - struct nn_xqos *xqos; /* publisher/subscriber QoS */ + struct dds_qos *xqos; /* publisher/subscriber QoS */ }; struct proxy_endpoint_common @@ -331,7 +331,7 @@ struct proxy_endpoint_common struct proxy_participant *proxypp; /* counted backref to proxy participant */ struct proxy_endpoint_common *next_ep; /* next \ endpoint belonging to this proxy participant */ struct proxy_endpoint_common *prev_ep; /* prev / -- this is in arbitrary ordering */ - struct nn_xqos *xqos; /* proxy endpoint QoS lives here; FIXME: local ones should have it moved to common as well */ + struct dds_qos *xqos; /* proxy endpoint QoS lives here; FIXME: local ones should have it moved to common as well */ struct ddsi_sertopic * topic; /* topic may be NULL: for built-ins, but also for never-yet matched proxies (so we don't have to know the topic; when we match, we certainly do know) */ struct addrset *as; /* address set to use for communicating with this endpoint */ nn_guid_t group_guid; /* 0:0:0:0 if not available */ @@ -539,9 +539,9 @@ struct writer *get_builtin_writer (const struct participant *pp, unsigned entity GUID "ppguid". May return NULL if participant unknown or writer/reader already known. */ -dds_return_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg); +dds_return_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg); -dds_return_t new_reader (struct reader **rd_out, struct nn_guid *rdguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc * rhc, status_cb_t status_cb, void *status_cb_arg); +dds_return_t new_reader (struct reader **rd_out, struct nn_guid *rdguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct rhc * rhc, status_cb_t status_cb, void *status_cb_arg); struct whc_node; struct whc_state; @@ -561,7 +561,7 @@ uint64_t reader_instance_id (const struct nn_guid *guid); struct local_orphan_writer { struct writer wr; }; -struct local_orphan_writer *new_local_orphan_writer (nn_entityid_t entityid, struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc); +struct local_orphan_writer *new_local_orphan_writer (nn_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc); void delete_local_orphan_writer (struct local_orphan_writer *wr); /* To create or delete a new proxy participant: "guid" MUST have the @@ -623,7 +623,7 @@ int delete_proxy_reader (const struct nn_guid *guid, nn_wctime_t timestamp, int void update_proxy_reader (struct proxy_reader * prd, struct addrset *as); void update_proxy_writer (struct proxy_writer * pwr, struct addrset *as); -int new_proxy_group (const struct nn_guid *guid, const char *name, const struct nn_xqos *xqos, nn_wctime_t timestamp); +int new_proxy_group (const struct nn_guid *guid, const char *name, const struct dds_qos *xqos, nn_wctime_t timestamp); void delete_proxy_group (const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit); uint64_t writer_instance_id (const struct nn_guid *guid); diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/q_globals.h index 857bd4c..418fd88 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/q_globals.h @@ -233,15 +233,15 @@ struct q_globals { packets); plus the actual QoSs needed for the builtin endpoints. */ nn_plist_t default_plist_pp; - nn_xqos_t default_xqos_rd; - nn_xqos_t default_xqos_wr; - nn_xqos_t default_xqos_wr_nad; - nn_xqos_t default_xqos_tp; - nn_xqos_t default_xqos_sub; - nn_xqos_t default_xqos_pub; - nn_xqos_t spdp_endpoint_xqos; - nn_xqos_t builtin_endpoint_xqos_rd; - nn_xqos_t builtin_endpoint_xqos_wr; + dds_qos_t default_xqos_rd; + dds_qos_t default_xqos_wr; + dds_qos_t default_xqos_wr_nad; + dds_qos_t default_xqos_tp; + dds_qos_t default_xqos_sub; + dds_qos_t default_xqos_pub; + dds_qos_t spdp_endpoint_xqos; + dds_qos_t builtin_endpoint_xqos_rd; + dds_qos_t builtin_endpoint_xqos_wr; /* SPDP packets get very special treatment (they're the only packets we accept from writers we don't know) and have their very own diff --git a/src/core/ddsi/include/dds/ddsi/q_plist.h b/src/core/ddsi/include/dds/ddsi/q_plist.h index 639401f..98b9466 100644 --- a/src/core/ddsi/include/dds/ddsi/q_plist.h +++ b/src/core/ddsi/include/dds/ddsi/q_plist.h @@ -137,7 +137,7 @@ typedef struct nn_plist { uint64_t aliased; int unalias_needs_bswap; - nn_xqos_t qos; + dds_qos_t qos; nn_protocol_version_t protocol_version; nn_vendorid_t vendorid; @@ -151,7 +151,7 @@ typedef struct nn_plist { unsigned char expects_inline_qos; nn_count_t participant_manual_liveliness_count; unsigned participant_builtin_endpoints; - nn_duration_t participant_lease_duration; + dds_duration_t participant_lease_duration; /* nn_content_filter_property_t content_filter_property; */ nn_guid_t participant_guid; nn_guid_t endpoint_guid; @@ -245,20 +245,19 @@ DDS_EXPORT void nn_plist_fini (nn_plist_t *ps); 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 dds_return_t validate_history_qospolicy (const nn_history_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_durability_qospolicy (const nn_durability_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, const nn_resource_limits_qospolicy_t *qr); -DDS_EXPORT dds_return_t validate_durability_service_qospolicy (const nn_durability_service_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_liveliness_qospolicy (const nn_liveliness_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_destination_order_qospolicy (const nn_destination_order_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_ownership_qospolicy (const nn_ownership_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_ownership_strength_qospolicy (const nn_ownership_strength_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_presentation_qospolicy (const nn_presentation_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_transport_priority_qospolicy (const nn_transport_priority_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_duration (const nn_duration_t *d); - +DDS_EXPORT dds_return_t validate_history_qospolicy (const dds_history_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_durability_qospolicy (const dds_durability_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_resource_limits_qospolicy (const dds_resource_limits_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_history_and_resource_limits (const dds_history_qospolicy_t *qh, const dds_resource_limits_qospolicy_t *qr); +DDS_EXPORT dds_return_t validate_durability_service_qospolicy (const dds_durability_service_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_liveliness_qospolicy (const dds_liveliness_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_destination_order_qospolicy (const dds_destination_order_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_ownership_qospolicy (const dds_ownership_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_ownership_strength_qospolicy (const dds_ownership_strength_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_presentation_qospolicy (const dds_presentation_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_transport_priority_qospolicy (const dds_transport_priority_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_reader_data_lifecycle (const dds_reader_data_lifecycle_qospolicy_t *q); +DDS_EXPORT dds_return_t validate_duration (const dds_duration_t d); 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 d0a3de2..f8f65d6 100644 --- a/src/core/ddsi/include/dds/ddsi/q_protocol.h +++ b/src/core/ddsi/include/dds/ddsi/q_protocol.h @@ -167,7 +167,7 @@ typedef enum SubmessageKind { typedef struct InfoTimestamp { SubmessageHeader_t smhdr; - nn_ddsi_time_t time; + ddsi_time_t time; } InfoTimestamp_t; typedef struct EntityId { @@ -196,7 +196,7 @@ typedef struct InfoSRC { #define PL_CDR_LE 0x0003u #endif -typedef unsigned short nn_parameterid_t; /* spec says short */ +typedef uint16_t nn_parameterid_t; /* spec says short */ typedef struct nn_parameter { nn_parameterid_t parameterid; uint16_t length; /* spec says signed short */ @@ -257,7 +257,7 @@ typedef struct Gap { typedef struct InfoTS { SubmessageHeader_t smhdr; - nn_ddsi_time_t time; + ddsi_time_t time; } InfoTS_t; #define INFOTS_INVALIDATE_FLAG 0x2u diff --git a/src/core/ddsi/include/dds/ddsi/q_qosmatch.h b/src/core/ddsi/include/dds/ddsi/q_qosmatch.h index d70c24c..7cfd371 100644 --- a/src/core/ddsi/include/dds/ddsi/q_qosmatch.h +++ b/src/core/ddsi/include/dds/ddsi/q_qosmatch.h @@ -16,13 +16,13 @@ extern "C" { #endif -struct nn_xqos; +struct dds_qos; -int partitions_match_p (const struct nn_xqos *a, const struct nn_xqos *b); +int partitions_match_p (const struct dds_qos *a, const struct dds_qos *b); /* Returns -1 on success, or QoS id of first mismatch (>=0) */ -int32_t qos_match_p (const struct nn_xqos *rd, const struct nn_xqos *wr); +bool qos_match_p (const struct dds_qos *rd, const struct dds_qos *wr, dds_qos_policy_id_t *reason) ddsrt_nonnull ((1, 2)); #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 95df0a7..bfba76c 100644 --- a/src/core/ddsi/include/dds/ddsi/q_radmin.h +++ b/src/core/ddsi/include/dds/ddsi/q_radmin.h @@ -115,7 +115,7 @@ struct nn_rsample_info { struct proxy_writer *pwr; uint32_t size; uint32_t fragsize; - nn_ddsi_time_t timestamp; + nn_wctime_t timestamp; nn_wctime_t reception_timestamp; /* OpenSplice extension -- but we get it essentially for free, so why not? */ unsigned statusinfo: 2; /* just the two defined bits from the status info */ unsigned pt_wr_info_zoff: 16; /* PrismTech writer info offset */ diff --git a/src/core/ddsi/include/dds/ddsi/q_time.h b/src/core/ddsi/include/dds/ddsi/q_time.h index 5c89cfa..7bdd5b0 100644 --- a/src/core/ddsi/include/dds/ddsi/q_time.h +++ b/src/core/ddsi/include/dds/ddsi/q_time.h @@ -26,11 +26,13 @@ extern "C" { #define T_MICROSECOND (T_MILLISECOND/1000) typedef struct { - int seconds; - unsigned fraction; -} nn_ddsi_time_t; + int32_t seconds; + uint32_t fraction; +} ddsi_time_t; +#define DDSI_TIME_INFINITE ((ddsi_time_t) { INT32_MAX, UINT32_MAX }) +#define DDSI_TIME_INVALID ((ddsi_time_t) { -1, UINT32_MAX }) -typedef nn_ddsi_time_t nn_duration_t; +typedef ddsi_time_t ddsi_duration_t; typedef struct { int64_t v; @@ -44,11 +46,9 @@ typedef struct { int64_t v; } nn_etime_t; -extern const nn_ddsi_time_t invalid_ddsi_timestamp; -extern const nn_ddsi_time_t ddsi_time_infinite; -extern const nn_duration_t duration_infinite; +#define NN_WCTIME_INVALID ((nn_wctime_t) { INT64_MIN }) -int valid_ddsi_timestamp (nn_ddsi_time_t t); +int valid_ddsi_timestamp (ddsi_time_t t); DDS_EXPORT nn_wctime_t now (void); /* wall clock time */ DDS_EXPORT nn_mtime_t now_mt (void); /* monotonic time */ @@ -61,10 +61,10 @@ DDS_EXPORT nn_mtime_t add_duration_to_mtime (nn_mtime_t t, int64_t d); DDS_EXPORT nn_wctime_t add_duration_to_wctime (nn_wctime_t t, int64_t d); DDS_EXPORT nn_etime_t add_duration_to_etime (nn_etime_t t, int64_t d); -DDS_EXPORT nn_ddsi_time_t nn_wctime_to_ddsi_time (nn_wctime_t t); -DDS_EXPORT nn_wctime_t nn_wctime_from_ddsi_time (nn_ddsi_time_t x); -DDS_EXPORT nn_duration_t nn_to_ddsi_duration (int64_t t); -DDS_EXPORT int64_t nn_from_ddsi_duration (nn_duration_t x); +DDS_EXPORT ddsi_time_t nn_wctime_to_ddsi_time (nn_wctime_t t); +DDS_EXPORT nn_wctime_t nn_wctime_from_ddsi_time (ddsi_time_t x); +DDS_EXPORT ddsi_duration_t nn_to_ddsi_duration (int64_t t); +DDS_EXPORT int64_t nn_from_ddsi_duration (ddsi_duration_t x); #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 f9abcfa..9b7e1eb 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xmsg.h +++ b/src/core/ddsi/include/dds/ddsi/q_xmsg.h @@ -121,21 +121,25 @@ void nn_xmsg_submsg_setnext (struct nn_xmsg *msg, struct nn_xmsg_marker marker); void nn_xmsg_submsg_init (struct nn_xmsg *msg, struct nn_xmsg_marker marker, SubmessageKind_t smkind); void nn_xmsg_add_timestamp (struct nn_xmsg *m, nn_wctime_t t); void nn_xmsg_add_entityid (struct nn_xmsg * m); -void *nn_xmsg_addpar (struct nn_xmsg *m, unsigned pid, size_t len); -void nn_xmsg_addpar_string (struct nn_xmsg *m, unsigned pid, const char *str); -void nn_xmsg_addpar_octetseq (struct nn_xmsg *m, unsigned pid, const nn_octetseq_t *oseq); -void nn_xmsg_addpar_stringseq (struct nn_xmsg *m, unsigned pid, const nn_stringseq_t *sseq); -void nn_xmsg_addpar_guid (struct nn_xmsg *m, unsigned pid, const nn_guid_t *guid); -void nn_xmsg_addpar_BE4u (struct nn_xmsg *m, unsigned pid, unsigned x); -void nn_xmsg_addpar_4u (struct nn_xmsg *m, unsigned pid, unsigned x); +void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len); +void nn_xmsg_addpar_string (struct nn_xmsg *m, nn_parameterid_t pid, const char *str); +void nn_xmsg_addpar_octetseq (struct nn_xmsg *m, nn_parameterid_t pid, const ddsi_octetseq_t *oseq); +void nn_xmsg_addpar_stringseq (struct nn_xmsg *m, nn_parameterid_t pid, const ddsi_stringseq_t *sseq); +void nn_xmsg_addpar_guid (struct nn_xmsg *m, nn_parameterid_t pid, const nn_guid_t *guid); +void nn_xmsg_addpar_BE4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x); +void nn_xmsg_addpar_4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x); void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata); -void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, unsigned statusinfo); -void nn_xmsg_addpar_reliability (struct nn_xmsg *m, unsigned pid, const struct nn_reliability_qospolicy *rq); -void nn_xmsg_addpar_share (struct nn_xmsg *m, unsigned pid, const struct nn_share_qospolicy *rq); -void nn_xmsg_addpar_subscription_keys (struct nn_xmsg *m, unsigned pid, const struct nn_subscription_keys_qospolicy *rq); +void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, uint32_t statusinfo); +void nn_xmsg_addpar_reliability (struct nn_xmsg *m, nn_parameterid_t pid, const struct dds_reliability_qospolicy *rq); +void nn_xmsg_addpar_duration (struct nn_xmsg *m, nn_parameterid_t pid, const dds_duration_t dur); +void nn_xmsg_addpar_subscription_keys (struct nn_xmsg *m, nn_parameterid_t pid, const struct dds_subscription_keys_qospolicy *rq); +void nn_xmsg_addpar_durability_service (struct nn_xmsg *m, nn_parameterid_t pid, const dds_durability_service_qospolicy_t *rq); +void nn_xmsg_addpar_reader_lifespan (struct nn_xmsg *m, nn_parameterid_t pid, const dds_reader_lifespan_qospolicy_t *rq); +void nn_xmsg_addpar_reader_data_lifecycle (struct nn_xmsg *m, nn_parameterid_t pid, const dds_reader_data_lifecycle_qospolicy_t *rq); +void nn_xmsg_addpar_liveliness (struct nn_xmsg *m, nn_parameterid_t pid, const dds_liveliness_qospolicy_t *rq); -void nn_xmsg_addpar_parvinfo (struct nn_xmsg *m, unsigned pid, const struct nn_prismtech_participant_version_info *pvi); -void nn_xmsg_addpar_eotinfo (struct nn_xmsg *m, unsigned pid, const struct nn_prismtech_eotinfo *txnid); +void nn_xmsg_addpar_parvinfo (struct nn_xmsg *m, nn_parameterid_t pid, const struct nn_prismtech_participant_version_info *pvi); +void nn_xmsg_addpar_eotinfo (struct nn_xmsg *m, nn_parameterid_t pid, const struct nn_prismtech_eotinfo *txnid); void nn_xmsg_addpar_sentinel (struct nn_xmsg *m); int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg *m); diff --git a/src/core/ddsi/include/dds/ddsi/q_xqos.h b/src/core/ddsi/include/dds/ddsi/q_xqos.h index d13207d..225e280 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xqos.h +++ b/src/core/ddsi/include/dds/ddsi/q_xqos.h @@ -12,6 +12,7 @@ #ifndef NN_XQOS_H #define NN_XQOS_H +#include "dds/ddsc/dds_public_qosdefs.h" /*XXX*/ #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_rtps.h" @@ -22,198 +23,164 @@ extern "C" { #endif -#define NN_DDS_LENGTH_UNLIMITED -1 - -typedef struct nn_octetseq { +typedef struct ddsi_octetseq { uint32_t length; unsigned char *value; -} nn_octetseq_t; +} ddsi_octetseq_t; -typedef nn_octetseq_t nn_userdata_qospolicy_t; -typedef nn_octetseq_t nn_topicdata_qospolicy_t; -typedef nn_octetseq_t nn_groupdata_qospolicy_t; +typedef ddsi_octetseq_t dds_userdata_qospolicy_t; +typedef ddsi_octetseq_t dds_topicdata_qospolicy_t; +typedef ddsi_octetseq_t dds_groupdata_qospolicy_t; -typedef enum nn_durability_kind { - NN_VOLATILE_DURABILITY_QOS, - NN_TRANSIENT_LOCAL_DURABILITY_QOS, - NN_TRANSIENT_DURABILITY_QOS, - NN_PERSISTENT_DURABILITY_QOS -} nn_durability_kind_t; +typedef struct dds_durability_qospolicy { + dds_durability_kind_t kind; +} dds_durability_qospolicy_t; -typedef struct nn_durability_qospolicy { - nn_durability_kind_t kind; -} nn_durability_qospolicy_t; - -typedef enum nn_history_kind { - NN_KEEP_LAST_HISTORY_QOS, - NN_KEEP_ALL_HISTORY_QOS -} nn_history_kind_t; - -typedef struct nn_history_qospolicy { - nn_history_kind_t kind; +typedef struct dds_history_qospolicy { + dds_history_kind_t kind; int32_t depth; -} nn_history_qospolicy_t; +} dds_history_qospolicy_t; -typedef struct nn_resource_limits_qospolicy { +typedef struct dds_resource_limits_qospolicy { int32_t max_samples; int32_t max_instances; int32_t max_samples_per_instance; -} nn_resource_limits_qospolicy_t; +} dds_resource_limits_qospolicy_t; -typedef struct nn_durability_service_qospolicy { - nn_duration_t service_cleanup_delay; - nn_history_qospolicy_t history; - nn_resource_limits_qospolicy_t resource_limits; -} nn_durability_service_qospolicy_t; +typedef struct dds_durability_service_qospolicy { + dds_duration_t service_cleanup_delay; + dds_history_qospolicy_t history; + dds_resource_limits_qospolicy_t resource_limits; +} dds_durability_service_qospolicy_t; -typedef enum nn_presentation_access_scope_kind { - NN_INSTANCE_PRESENTATION_QOS, - NN_TOPIC_PRESENTATION_QOS, - NN_GROUP_PRESENTATION_QOS -} nn_presentation_access_scope_kind_t; +typedef struct dds_external_durability_service_qospolicy { + ddsi_duration_t service_cleanup_delay; + dds_history_qospolicy_t history; + dds_resource_limits_qospolicy_t resource_limits; +} dds_external_durability_service_qospolicy_t; -typedef struct nn_presentation_qospolicy { - nn_presentation_access_scope_kind_t access_scope; +typedef struct dds_presentation_qospolicy { + dds_presentation_access_scope_kind_t access_scope; unsigned char coherent_access; unsigned char ordered_access; -} nn_presentation_qospolicy_t; +} dds_presentation_qospolicy_t; -typedef struct nn_deadline_qospolicy { - nn_duration_t deadline; -} nn_deadline_qospolicy_t; +typedef struct dds_deadline_qospolicy { + dds_duration_t deadline; +} dds_deadline_qospolicy_t; -typedef struct nn_latency_budget_qospolicy { - nn_duration_t duration; -} nn_latency_budget_qospolicy_t; +typedef struct dds_external_deadline_qospolicy { + ddsi_duration_t deadline; +} dds_external_deadline_qospolicy_t; -typedef enum nn_ownership_kind { - NN_SHARED_OWNERSHIP_QOS, - NN_EXCLUSIVE_OWNERSHIP_QOS -} nn_ownership_kind_t; +typedef struct dds_latency_budget_qospolicy { + dds_duration_t duration; +} dds_latency_budget_qospolicy_t; -typedef struct nn_ownership_qospolicy { - nn_ownership_kind_t kind; -} nn_ownership_qospolicy_t; +typedef struct dds_external_latency_budget_qospolicy { + ddsi_duration_t duration; +} dds_external_latency_budget_qospolicy_t; -typedef struct nn_ownership_strength_qospolicy { +typedef struct dds_ownership_qospolicy { + dds_ownership_kind_t kind; +} dds_ownership_qospolicy_t; + +typedef struct dds_ownership_strength_qospolicy { int32_t value; -} nn_ownership_strength_qospolicy_t; +} dds_ownership_strength_qospolicy_t; -typedef enum nn_liveliness_kind { - NN_AUTOMATIC_LIVELINESS_QOS, - NN_MANUAL_BY_PARTICIPANT_LIVELINESS_QOS, - NN_MANUAL_BY_TOPIC_LIVELINESS_QOS -} nn_liveliness_kind_t; +typedef struct dds_liveliness_qospolicy { + dds_liveliness_kind_t kind; + dds_duration_t lease_duration; +} dds_liveliness_qospolicy_t; -typedef struct nn_liveliness_qospolicy { - nn_liveliness_kind_t kind; - nn_duration_t lease_duration; -} nn_liveliness_qospolicy_t; +typedef struct dds_external_liveliness_qospolicy { + dds_liveliness_kind_t kind; + ddsi_duration_t lease_duration; +} dds_external_liveliness_qospolicy_t; -typedef struct nn_time_based_filter_qospolicy { - nn_duration_t minimum_separation; -} nn_time_based_filter_qospolicy_t; +typedef struct dds_time_based_filter_qospolicy { + dds_duration_t minimum_separation; +} dds_time_based_filter_qospolicy_t; -typedef struct nn_stringseq { +typedef struct dds_external_time_based_filter_qospolicy { + ddsi_duration_t minimum_separation; +} dds_external_time_based_filter_qospolicy_t; + +typedef struct ddsi_stringseq { uint32_t n; char **strs; -} nn_stringseq_t; +} ddsi_stringseq_t; -typedef nn_stringseq_t nn_partition_qospolicy_t; +typedef ddsi_stringseq_t dds_partition_qospolicy_t; -typedef enum nn_reliability_kind { - NN_BEST_EFFORT_RELIABILITY_QOS, - NN_RELIABLE_RELIABILITY_QOS -} nn_reliability_kind_t; +typedef struct dds_reliability_qospolicy { + dds_reliability_kind_t kind; + dds_duration_t max_blocking_time; +} dds_reliability_qospolicy_t; -typedef struct nn_reliability_qospolicy { - nn_reliability_kind_t kind; - nn_duration_t max_blocking_time; -} nn_reliability_qospolicy_t; +typedef enum dds_external_reliability_kind { + DDS_EXTERNAL_RELIABILITY_BEST_EFFORT = 1, + DDS_EXTERNAL_RELIABILITY_RELIABLE = 2 +} dds_external_reliability_kind_t; -typedef struct nn_external_reliability_qospolicy { - uint32_t kind; - nn_duration_t max_blocking_time; -} nn_external_reliability_qospolicy_t; +typedef struct dds_external_reliability_qospolicy { + dds_external_reliability_kind_t kind; + ddsi_duration_t max_blocking_time; +} dds_external_reliability_qospolicy_t; -#define NN_PEDANTIC_BEST_EFFORT_RELIABILITY_QOS 1 -#define NN_PEDANTIC_RELIABLE_RELIABILITY_QOS 3 /* <= see DDSI 2.1, table 9.4 */ -#define NN_INTEROP_BEST_EFFORT_RELIABILITY_QOS 1 -#define NN_INTEROP_RELIABLE_RELIABILITY_QOS 2 - -typedef struct nn_transport_priority_qospolicy { +typedef struct dds_transport_priority_qospolicy { int32_t value; -} nn_transport_priority_qospolicy_t; +} dds_transport_priority_qospolicy_t; -typedef struct nn_lifespan_qospolicy { - nn_duration_t duration; -} nn_lifespan_qospolicy_t; +typedef struct dds_lifespan_qospolicy { + dds_duration_t duration; +} dds_lifespan_qospolicy_t; -typedef enum nn_destination_order_kind { - NN_BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS, - NN_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS -} nn_destination_order_kind_t; +typedef struct dds_external_lifespan_qospolicy { + ddsi_duration_t duration; +} dds_external_lifespan_qospolicy_t; -typedef struct nn_destination_order_qospolicy { - nn_destination_order_kind_t kind; -} nn_destination_order_qospolicy_t; +typedef struct dds_destination_order_qospolicy { + dds_destination_order_kind_t kind; +} dds_destination_order_qospolicy_t; -typedef struct nn_entity_factory_qospolicy { +typedef struct dds_entity_factory_qospolicy { unsigned char autoenable_created_entities; -} nn_entity_factory_qospolicy_t; +} dds_entity_factory_qospolicy_t; -typedef struct nn_writer_data_lifecycle_qospolicy { +typedef struct dds_writer_data_lifecycle_qospolicy { unsigned char autodispose_unregistered_instances; - nn_duration_t autopurge_suspended_samples_delay; /* OpenSplice extension */ - nn_duration_t autounregister_instance_delay; /* OpenSplice extension */ -} nn_writer_data_lifecycle_qospolicy_t; +} dds_writer_data_lifecycle_qospolicy_t; -typedef enum nn_invalid_sample_visibility_kind { - NN_NO_INVALID_SAMPLE_VISIBILITY_QOS, - NN_MINIMUM_INVALID_SAMPLE_VISIBILITY_QOS, - NN_ALL_INVALID_SAMPLE_VISIBILITY_QOS -} nn_invalid_sample_visibility_kind_t; +typedef struct dds_reader_data_lifecycle_qospolicy { + dds_duration_t autopurge_nowriter_samples_delay; + dds_duration_t autopurge_disposed_samples_delay; +} dds_reader_data_lifecycle_qospolicy_t; -typedef struct nn_reader_data_lifecycle_qospolicy { - nn_duration_t autopurge_nowriter_samples_delay; - nn_duration_t autopurge_disposed_samples_delay; - unsigned char autopurge_dispose_all; /* OpenSplice extension */ - unsigned char enable_invalid_samples; /* OpenSplice extension */ - nn_invalid_sample_visibility_kind_t invalid_sample_visibility; /* OpenSplice extension */ -} nn_reader_data_lifecycle_qospolicy_t; +typedef struct dds_external_reader_data_lifecycle_qospolicy { + ddsi_duration_t autopurge_nowriter_samples_delay; + ddsi_duration_t autopurge_disposed_samples_delay; +} dds_external_reader_data_lifecycle_qospolicy_t; -typedef struct nn_synchronous_endpoint_qospolicy { - unsigned char value; -} nn_synchronous_endpoint_qospolicy_t; - -typedef struct nn_relaxed_qos_matching_qospolicy { - unsigned char value; -} nn_relaxed_qos_matching_qospolicy_t; - -typedef struct nn_subscription_keys_qospolicy { +typedef struct dds_subscription_keys_qospolicy { unsigned char use_key_list; - nn_stringseq_t key_list; -} nn_subscription_keys_qospolicy_t; + ddsi_stringseq_t key_list; +} dds_subscription_keys_qospolicy_t; -typedef struct nn_reader_lifespan_qospolicy { +typedef struct dds_reader_lifespan_qospolicy { unsigned char use_lifespan; - nn_duration_t duration; -} nn_reader_lifespan_qospolicy_t; + dds_duration_t duration; +} dds_reader_lifespan_qospolicy_t; -typedef struct nn_share_qospolicy { - unsigned char enable; - char *name; -} nn_share_qospolicy_t; +typedef struct dds_external_reader_lifespan_qospolicy { + unsigned char use_lifespan; + ddsi_duration_t duration; +} dds_external_reader_lifespan_qospolicy_t; -typedef enum nn_ignorelocal_kind { - NN_NONE_IGNORELOCAL_QOS, - NN_PARTICIPANT_IGNORELOCAL_QOS, - NN_PROCESS_IGNORELOCAL_QOS -} nn_ignorelocal_kind_t; - -typedef struct nn_ignorelocal_qospolicy { - nn_ignorelocal_kind_t value; -} nn_ignorelocal_qospolicy_t; +typedef struct dds_ignorelocal_qospolicy { + dds_ignorelocal_kind_t value; +} dds_ignorelocal_qospolicy_t; /***/ @@ -241,11 +208,9 @@ typedef struct nn_ignorelocal_qospolicy { #define QP_TIME_BASED_FILTER ((uint64_t)1 << 20) #define QP_PRISMTECH_WRITER_DATA_LIFECYCLE ((uint64_t)1 << 21) #define QP_PRISMTECH_READER_DATA_LIFECYCLE ((uint64_t)1 << 22) -#define QP_PRISMTECH_RELAXED_QOS_MATCHING ((uint64_t)1 << 23) #define QP_PRISMTECH_READER_LIFESPAN ((uint64_t)1 << 24) #define QP_PRISMTECH_SUBSCRIPTION_KEYS ((uint64_t)1 << 25) #define QP_PRISMTECH_ENTITY_FACTORY ((uint64_t)1 << 27) -#define QP_PRISMTECH_SYNCHRONOUS_ENDPOINT ((uint64_t)1 << 28) #define QP_RTI_TYPECODE ((uint64_t)1 << 29) #define QP_CYCLONE_IGNORELOCAL ((uint64_t)1 << 30) @@ -253,13 +218,13 @@ typedef struct nn_ignorelocal_qospolicy { section 7.1.3), but communication will not take place unless it matches. Same for topic and type. Relaxed qos matching is a bit of a weird one, but it affects matching, so ... */ -#define QP_RXO_MASK (QP_DURABILITY | QP_PRESENTATION | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_LIVELINESS | QP_RELIABILITY | QP_DESTINATION_ORDER | QP_PRISMTECH_RELAXED_QOS_MATCHING | QP_PRISMTECH_SYNCHRONOUS_ENDPOINT) +#define QP_RXO_MASK (QP_DURABILITY | QP_PRESENTATION | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_LIVELINESS | QP_RELIABILITY | QP_DESTINATION_ORDER) #define QP_CHANGEABLE_MASK (QP_USER_DATA | QP_TOPIC_DATA | QP_GROUP_DATA | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP_STRENGTH | QP_TIME_BASED_FILTER | QP_PARTITION | QP_TRANSPORT_PRIORITY | QP_LIFESPAN | QP_PRISMTECH_ENTITY_FACTORY | QP_PRISMTECH_WRITER_DATA_LIFECYCLE | QP_PRISMTECH_READER_DATA_LIFECYCLE) -#define QP_UNRECOGNIZED_INCOMPATIBLE_MASK (QP_PRISMTECH_RELAXED_QOS_MATCHING) +#define QP_UNRECOGNIZED_INCOMPATIBLE_MASK ((uint64_t) 0) /* readers & writers have an extended qos, hence why it is a separate type */ -typedef struct nn_xqos { +struct dds_qos { /* Entries present, for sparse QoS */ uint64_t present; uint64_t aliased; @@ -272,57 +237,54 @@ typedef struct nn_xqos { /* xx */char *topic_name; /* xx */char *type_name; /* PublisherQos, SubscriberQos: */ - /*xxx */nn_presentation_qospolicy_t presentation; - /*xxx */nn_partition_qospolicy_t partition; - /*xxx */nn_groupdata_qospolicy_t group_data; - /*x xX*/nn_entity_factory_qospolicy_t entity_factory; + /*xxx */dds_presentation_qospolicy_t presentation; + /*xxx */dds_partition_qospolicy_t partition; + /*xxx */dds_groupdata_qospolicy_t group_data; + /*x xX*/dds_entity_factory_qospolicy_t entity_factory; /* TopicQos: */ - /*xxx */nn_topicdata_qospolicy_t topic_data; + /*xxx */dds_topicdata_qospolicy_t topic_data; /* DataWriterQos, DataReaderQos: */ - /*xxx */nn_durability_qospolicy_t durability; - /*xxx */nn_durability_service_qospolicy_t durability_service; - /*xxx */nn_deadline_qospolicy_t deadline; - /*xxx */nn_latency_budget_qospolicy_t latency_budget; - /*xxx */nn_liveliness_qospolicy_t liveliness; - /*xxx */nn_reliability_qospolicy_t reliability; - /*xxx */nn_destination_order_qospolicy_t destination_order; - /*x x */nn_history_qospolicy_t history; - /*x x */nn_resource_limits_qospolicy_t resource_limits; - /*x x */nn_transport_priority_qospolicy_t transport_priority; - /*xxx */nn_lifespan_qospolicy_t lifespan; - /*xxx */nn_userdata_qospolicy_t user_data; - /*xxx */nn_ownership_qospolicy_t ownership; - /*xxxW*/nn_ownership_strength_qospolicy_t ownership_strength; - /*xxxR*/nn_time_based_filter_qospolicy_t time_based_filter; - /*x W*/nn_writer_data_lifecycle_qospolicy_t writer_data_lifecycle; - /*x xR*/nn_reader_data_lifecycle_qospolicy_t reader_data_lifecycle; - /*x x */nn_relaxed_qos_matching_qospolicy_t relaxed_qos_matching; - /*x xR*/nn_subscription_keys_qospolicy_t subscription_keys; - /*x xR*/nn_reader_lifespan_qospolicy_t reader_lifespan; - /*x xR*/nn_share_qospolicy_t share; - /*xxx */nn_synchronous_endpoint_qospolicy_t synchronous_endpoint; - /* x */nn_ignorelocal_qospolicy_t ignorelocal; + /*xxx */dds_durability_qospolicy_t durability; + /*xxx */dds_durability_service_qospolicy_t durability_service; + /*xxx */dds_deadline_qospolicy_t deadline; + /*xxx */dds_latency_budget_qospolicy_t latency_budget; + /*xxx */dds_liveliness_qospolicy_t liveliness; + /*xxx */dds_reliability_qospolicy_t reliability; + /*xxx */dds_destination_order_qospolicy_t destination_order; + /*x x */dds_history_qospolicy_t history; + /*x x */dds_resource_limits_qospolicy_t resource_limits; + /*x x */dds_transport_priority_qospolicy_t transport_priority; + /*xxx */dds_lifespan_qospolicy_t lifespan; + /*xxx */dds_userdata_qospolicy_t user_data; + /*xxx */dds_ownership_qospolicy_t ownership; + /*xxxW*/dds_ownership_strength_qospolicy_t ownership_strength; + /*xxxR*/dds_time_based_filter_qospolicy_t time_based_filter; + /*x W*/dds_writer_data_lifecycle_qospolicy_t writer_data_lifecycle; + /*x xR*/dds_reader_data_lifecycle_qospolicy_t reader_data_lifecycle; + /*x xR*/dds_subscription_keys_qospolicy_t subscription_keys; + /*x xR*/dds_reader_lifespan_qospolicy_t reader_lifespan; + /* x */dds_ignorelocal_qospolicy_t ignorelocal; - /* X*/nn_octetseq_t rti_typecode; -} nn_xqos_t; + /* X*/ddsi_octetseq_t rti_typecode; +}; struct nn_xmsg; -DDS_EXPORT void nn_xqos_init_empty (nn_xqos_t *xqos); -DDS_EXPORT void nn_xqos_init_default_reader (nn_xqos_t *xqos); -DDS_EXPORT void nn_xqos_init_default_writer (nn_xqos_t *xqos); -DDS_EXPORT void nn_xqos_init_default_writer_noautodispose (nn_xqos_t *xqos); -DDS_EXPORT void nn_xqos_init_default_subscriber (nn_xqos_t *xqos); -DDS_EXPORT void nn_xqos_init_default_publisher (nn_xqos_t *xqos); -DDS_EXPORT void nn_xqos_init_default_topic (nn_xqos_t *xqos); -DDS_EXPORT void nn_xqos_copy (nn_xqos_t *dst, const nn_xqos_t *src); -DDS_EXPORT void nn_xqos_unalias (nn_xqos_t *xqos); -DDS_EXPORT void nn_xqos_fini (nn_xqos_t *xqos); -DDS_EXPORT void nn_xqos_mergein_missing (nn_xqos_t *a, const nn_xqos_t *b); -DDS_EXPORT uint64_t nn_xqos_delta (const nn_xqos_t *a, const nn_xqos_t *b, uint64_t mask); -DDS_EXPORT void nn_xqos_addtomsg (struct nn_xmsg *m, const nn_xqos_t *xqos, uint64_t wanted); -DDS_EXPORT void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos); -DDS_EXPORT nn_xqos_t *nn_xqos_dup (const nn_xqos_t *src); +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_mergein_missing (dds_qos_t *a, const dds_qos_t *b); +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 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_rhc_plugin.c b/src/core/ddsi/src/ddsi_rhc_plugin.c index 969c753..be1caa3 100644 --- a/src/core/ddsi/src/ddsi_rhc_plugin.c +++ b/src/core/ddsi/src/ddsi_rhc_plugin.c @@ -13,7 +13,7 @@ #include "dds/ddsi/q_xqos.h" #include "dds/ddsi/ddsi_rhc_plugin.h" -DDS_EXPORT void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct nn_xqos *xqos) +DDS_EXPORT void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct dds_qos *xqos) { pwr_info->guid = e->guid; pwr_info->ownership_strength = xqos->ownership_strength.value; diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 654ce2c..9e5b1a8 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -284,7 +284,7 @@ int spdp_write (struct participant *pp) meta_multi_loc_one.loc = gv.loc_meta_mc; } } - ps.participant_lease_duration = nn_to_ddsi_duration (pp->lease_duration); + ps.participant_lease_duration = pp->lease_duration; /* Add PrismTech specific version information */ { @@ -515,7 +515,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time unsigned builtin_endpoint_set; unsigned prismtech_builtin_endpoint_set; nn_guid_t privileged_pp_guid; - nn_duration_t lease_duration; + dds_duration_t lease_duration; unsigned custom_flags = 0; if (!(datap->present & PP_PARTICIPANT_GUID) || !(datap->present & PP_BUILTIN_ENDPOINT_SET)) @@ -611,7 +611,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time else { DDS_LOG(DDS_LC_DISCOVERY, " (PARTICIPANT_LEASE_DURATION defaulting to 100s)"); - lease_duration = nn_to_ddsi_duration (100 * T_SECOND); + lease_duration = 100 * T_SECOND; } if (datap->present & PP_PRISMTECH_PARTICIPANT_VERSION_INFO) { @@ -645,7 +645,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time DDS_LOG(DDS_LC_DISCOVERY, " (depends on "PGUIDFMT")", PGUID (privileged_pp_guid)); /* never expire lease for this proxy: it won't actually expire until the "privileged" one expires anyway */ - lease_duration = nn_to_ddsi_duration (T_NEVER); + lease_duration = T_NEVER; } else if (vendor_is_eclipse_or_opensplice (rst->vendor) && !(custom_flags & CF_PARTICIPANT_IS_DDSI2)) { @@ -657,7 +657,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time else { privileged_pp_guid.prefix = ddsi2->e.guid.prefix; - lease_duration = nn_to_ddsi_duration (T_NEVER); + lease_duration = T_NEVER; DDS_LOG(DDS_LC_DISCOVERY, " (depends on "PGUIDFMT")", PGUID (privileged_pp_guid)); } } @@ -735,7 +735,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time as_default, as_meta, datap, - nn_from_ddsi_duration (lease_duration), + lease_duration, rst->vendor, custom_flags, timestamp @@ -865,9 +865,9 @@ static int sedp_write_endpoint ( struct writer *wr, int alive, const nn_guid_t *epguid, const struct entity_common *common, const struct endpoint_common *epcommon, - const nn_xqos_t *xqos, struct addrset *as) + const dds_qos_t *xqos, struct addrset *as) { - const nn_xqos_t *defqos = is_writer_entityid (epguid->entityid) ? &gv.default_xqos_wr : &gv.default_xqos_rd; + 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; @@ -1006,14 +1006,14 @@ int sedp_dispose_unregister_reader (struct reader *rd) return 0; } -static const char *durability_to_string (nn_durability_kind_t k) +static const char *durability_to_string (dds_durability_kind_t k) { switch (k) { - case NN_VOLATILE_DURABILITY_QOS: return "volatile"; - case NN_TRANSIENT_LOCAL_DURABILITY_QOS: return "transient-local"; - case NN_TRANSIENT_DURABILITY_QOS: return "transient"; - case NN_PERSISTENT_DURABILITY_QOS: return "persistent"; + case DDS_DURABILITY_VOLATILE: return "volatile"; + case DDS_DURABILITY_TRANSIENT_LOCAL: return "transient-local"; + case DDS_DURABILITY_TRANSIENT: return "transient"; + case DDS_DURABILITY_PERSISTENT: return "persistent"; } return "undefined-durability"; } @@ -1105,7 +1105,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat struct proxy_writer * pwr = NULL; struct proxy_reader * prd = NULL; nn_guid_t ppguid; - nn_xqos_t *xqos; + dds_qos_t *xqos; int reliable; struct addrset *as; int is_writer; @@ -1158,7 +1158,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat assert ((xqos->present & datap->qos.present) == datap->qos.present); assert (xqos->present & QP_RELIABILITY); assert (xqos->present & QP_DURABILITY); - reliable = (xqos->reliability.kind == NN_RELIABLE_RELIABILITY_QOS); + reliable = (xqos->reliability.kind == DDS_RELIABILITY_RELIABLE); DDS_LOG(DDS_LC_DISCOVERY, " %s %s %s: %s%s.%s/%s", reliable ? "reliable" : "best-effort", @@ -1860,7 +1860,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str goto done_upd_deliv; } - timestamp = valid_ddsi_timestamp(sampleinfo->timestamp) ? nn_wctime_from_ddsi_time(sampleinfo->timestamp): now(); + timestamp = (sampleinfo->timestamp.v != NN_WCTIME_INVALID.v) ? sampleinfo->timestamp : now (); switch (srcguid.entityid.u) { case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER: diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index a3362cb..c555bc2 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -107,7 +107,7 @@ static int print_addrset_if_notempty (ddsi_tran_conn_t conn, const char *prefix, } static int print_any_endpoint_common (ddsi_tran_conn_t conn, const char *label, const struct entity_common *e, - const struct nn_xqos *xqos, const struct ddsi_sertopic *topic) + const struct dds_qos *xqos, const struct ddsi_sertopic *topic) { int x = 0; x += cpf (conn, " %s %x:%x:%x:%x ", label, PGUID (e->guid)); @@ -126,7 +126,7 @@ static int print_any_endpoint_common (ddsi_tran_conn_t conn, const char *label, return x; } -static int print_endpoint_common (ddsi_tran_conn_t conn, const char *label, const struct entity_common *e, const struct endpoint_common *c, const struct nn_xqos *xqos, const struct ddsi_sertopic *topic) +static int print_endpoint_common (ddsi_tran_conn_t conn, const char *label, const struct entity_common *e, const struct endpoint_common *c, const struct dds_qos *xqos, const struct ddsi_sertopic *topic) { DDSRT_UNUSED_ARG (c); return print_any_endpoint_common (conn, label, e, xqos, topic); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 6cfca79..b34e167 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -87,8 +87,8 @@ static const unsigned prismtech_builtin_writers_besmask = NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER | NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER; -static dds_return_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_cbarg); -static dds_return_t new_reader_guid (struct reader **rd_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc *rhc, status_cb_t status_cb, void *status_cbarg); +static dds_return_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc, status_cb_t status_cb, void *status_cbarg); +static dds_return_t new_reader_guid (struct reader **rd_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct rhc *rhc, status_cb_t status_cb, void *status_cbarg); static struct participant *ref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity); static void unref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity); static void delete_proxy_group_locked (struct proxy_group *pgroup, nn_wctime_t timestamp, int isimplicit); @@ -1545,7 +1545,7 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) ddsrt_avl_ipath_t path; int pretend_everything_acked; m->prd_guid = prd->e.guid; - m->is_reliable = (prd->c.xqos->reliability.kind > NN_BEST_EFFORT_RELIABILITY_QOS); + m->is_reliable = (prd->c.xqos->reliability.kind > DDS_RELIABILITY_BEST_EFFORT); m->assumed_in_sync = (config.retransmit_merging == REXMIT_MERGE_ALWAYS); m->has_replied_to_hb = !m->is_reliable; m->all_have_replied_to_hb = 0; @@ -1655,7 +1655,7 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd) historical data for best-effort data over the wire, so also not locally). FIXME: should limit ourselves to what it is available because of durability history, not writer history */ - if (rd->xqos->reliability.kind > NN_BEST_EFFORT_RELIABILITY_QOS && rd->xqos->durability.kind > NN_VOLATILE_DURABILITY_QOS) + if (rd->xqos->reliability.kind > DDS_RELIABILITY_BEST_EFFORT && rd->xqos->durability.kind > DDS_DURABILITY_VOLATILE) { struct whc_sample_iter it; struct whc_borrowed_sample sample; @@ -2021,7 +2021,7 @@ static nn_entityid_t builtin_entityid_match (nn_entityid_t x) return res; } -static void writer_qos_mismatch (struct writer * wr, uint32_t reason) +static void writer_qos_mismatch (struct writer * wr, dds_qos_policy_id_t reason) { /* When the reason is DDS_INVALID_QOS_POLICY_ID, it means that we compared * readers/writers from different topics: ignore that. */ @@ -2041,7 +2041,7 @@ static void writer_qos_mismatch (struct writer * wr, uint32_t reason) } } -static void reader_qos_mismatch (struct reader * rd, uint32_t reason) +static void reader_qos_mismatch (struct reader * rd, dds_qos_policy_id_t reason) { /* When the reason is DDS_INVALID_QOS_POLICY_ID, it means that we compared * readers/writers from different topics: ignore that. */ @@ -2066,15 +2066,15 @@ static void connect_writer_with_proxy_reader (struct writer *wr, struct proxy_re { const int isb0 = (is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE) != 0); const int isb1 = (is_builtin_entityid (prd->e.guid.entityid, prd->c.vendor) != 0); - int32_t reason; + dds_qos_policy_id_t reason; DDSRT_UNUSED_ARG(tnow); if (isb0 != isb1) return; if (wr->e.onlylocal) return; - if (!isb0 && (reason = qos_match_p (prd->c.xqos, wr->xqos)) >= 0) + if (!isb0 && !qos_match_p (prd->c.xqos, wr->xqos, &reason)) { - writer_qos_mismatch (wr, (uint32_t)reason); + writer_qos_mismatch (wr, reason); return; } proxy_reader_add_connection (prd, wr); @@ -2085,41 +2085,41 @@ static void connect_proxy_writer_with_reader (struct proxy_writer *pwr, struct r { const int isb0 = (is_builtin_entityid (pwr->e.guid.entityid, pwr->c.vendor) != 0); const int isb1 = (is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) != 0); - int32_t reason; + dds_qos_policy_id_t reason; nn_count_t init_count; if (isb0 != isb1) return; if (rd->e.onlylocal) return; - if (!isb0 && (reason = qos_match_p (rd->xqos, pwr->c.xqos)) >= 0) + if (!isb0 && !qos_match_p (rd->xqos, pwr->c.xqos, &reason)) { - reader_qos_mismatch (rd, (uint32_t)reason); + reader_qos_mismatch (rd, reason); return; } reader_add_connection (rd, pwr, &init_count); proxy_writer_add_connection (pwr, rd, tnow, init_count); } -static bool ignore_local_p (const nn_guid_t *guid1, const nn_guid_t *guid2, const struct nn_xqos *xqos1, const struct nn_xqos *xqos2) +static bool ignore_local_p (const nn_guid_t *guid1, const nn_guid_t *guid2, const struct dds_qos *xqos1, const struct dds_qos *xqos2) { assert (xqos1->present & QP_CYCLONE_IGNORELOCAL); assert (xqos2->present & QP_CYCLONE_IGNORELOCAL); switch (xqos1->ignorelocal.value) { - case NN_NONE_IGNORELOCAL_QOS: + case DDS_IGNORELOCAL_NONE: break; - case NN_PARTICIPANT_IGNORELOCAL_QOS: + case DDS_IGNORELOCAL_PARTICIPANT: return memcmp (&guid1->prefix, &guid2->prefix, sizeof (guid1->prefix)) == 0; - case NN_PROCESS_IGNORELOCAL_QOS: + case DDS_IGNORELOCAL_PROCESS: return true; } switch (xqos2->ignorelocal.value) { - case NN_NONE_IGNORELOCAL_QOS: + case DDS_IGNORELOCAL_NONE: break; - case NN_PARTICIPANT_IGNORELOCAL_QOS: + case DDS_IGNORELOCAL_PARTICIPANT: return memcmp (&guid1->prefix, &guid2->prefix, sizeof (guid1->prefix)) == 0; - case NN_PROCESS_IGNORELOCAL_QOS: + case DDS_IGNORELOCAL_PROCESS: return true; } return false; @@ -2127,16 +2127,16 @@ static bool ignore_local_p (const nn_guid_t *guid1, const nn_guid_t *guid2, cons static void connect_writer_with_reader (struct writer *wr, struct reader *rd, nn_mtime_t tnow) { - int32_t reason; + dds_qos_policy_id_t reason; (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; if (ignore_local_p (&wr->e.guid, &rd->e.guid, wr->xqos, rd->xqos)) return; - if ((reason = qos_match_p (rd->xqos, wr->xqos)) >= 0) + if (!qos_match_p (rd->xqos, wr->xqos, &reason)) { - writer_qos_mismatch (wr, (uint32_t)reason); - reader_qos_mismatch (rd, (uint32_t)reason); + writer_qos_mismatch (wr, reason); + reader_qos_mismatch (rd, reason); return; } reader_add_local_connection (rd, wr); @@ -2402,7 +2402,7 @@ static void match_proxy_reader_with_writers (struct proxy_reader *prd, nn_mtime_ /* ENDPOINT --------------------------------------------------------- */ -static void new_reader_writer_common (const struct nn_guid *guid, const struct ddsi_sertopic * topic, const struct nn_xqos *xqos) +static void new_reader_writer_common (const struct nn_guid *guid, const struct ddsi_sertopic * topic, const struct dds_qos *xqos) { const char *partition = "(default)"; const char *partition_suffix = ""; @@ -2452,7 +2452,7 @@ static void endpoint_common_fini (struct entity_common *e, struct endpoint_commo entity_common_fini (e); } -static int set_topic_type_name (nn_xqos_t *xqos, const struct ddsi_sertopic * topic) +static int set_topic_type_name (dds_qos_t *xqos, const struct ddsi_sertopic * topic) { if (!(xqos->present & QP_TYPE_NAME) && topic) { @@ -2655,7 +2655,7 @@ unsigned remove_acked_messages (struct writer *wr, struct whc_state *whcst, stru return n; } -static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void * status_entity) +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); wr->seq = 0; @@ -2693,14 +2693,14 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se DDS_LOG(DDS_LC_DISCOVERY, "}\n"); assert (wr->xqos->present & QP_RELIABILITY); - wr->reliable = (wr->xqos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS); + wr->reliable = (wr->xqos->reliability.kind != DDS_RELIABILITY_BEST_EFFORT); assert (wr->xqos->present & QP_DURABILITY); if (is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE)) { - assert (wr->xqos->history.kind == NN_KEEP_LAST_HISTORY_QOS); - assert (wr->xqos->durability.kind == NN_TRANSIENT_LOCAL_DURABILITY_QOS); + assert (wr->xqos->history.kind == DDS_HISTORY_KEEP_LAST); + assert (wr->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL); } - wr->handle_as_transient_local = (wr->xqos->durability.kind == NN_TRANSIENT_LOCAL_DURABILITY_QOS); + wr->handle_as_transient_local = (wr->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL); wr->include_keyhash = config.generate_keyhash && ((wr->e.guid.entityid.u & NN_ENTITYID_KIND_MASK) == NN_ENTITYID_KIND_WRITER_WITH_KEY); @@ -2790,15 +2790,14 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se wr->heartbeat_xevent = NULL; } assert (wr->xqos->present & QP_LIVELINESS); - if (wr->xqos->liveliness.kind != NN_AUTOMATIC_LIVELINESS_QOS || - nn_from_ddsi_duration (wr->xqos->liveliness.lease_duration) != T_NEVER) + if (wr->xqos->liveliness.kind != DDS_LIVELINESS_AUTOMATIC || wr->xqos->liveliness.lease_duration != T_NEVER) { - DDS_LOG(DDS_LC_DISCOVERY, "writer "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (wr->e.guid), (int) wr->xqos->liveliness.kind, nn_from_ddsi_duration (wr->xqos->liveliness.lease_duration)); + DDS_LOG(DDS_LC_DISCOVERY, "writer "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (wr->e.guid), (int) wr->xqos->liveliness.kind, wr->xqos->liveliness.lease_duration); } wr->lease_duration = T_NEVER; /* FIXME */ wr->whc = whc; - if (wr->xqos->history.kind == NN_KEEP_LAST_HISTORY_QOS) + if (wr->xqos->history.kind == DDS_HISTORY_KEEP_LAST) { /* hdepth > 0 => "aggressive keep last", and in that case: why bother blocking for a slow receiver when the entire point of @@ -2820,7 +2819,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se local_reader_ary_init (&wr->rdary); } -static dds_return_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_entity) +static dds_return_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc, status_cb_t status_cb, void *status_entity) { struct writer *wr; nn_mtime_t tnow = now_mt (); @@ -2870,7 +2869,7 @@ static dds_return_t new_writer_guid (struct writer **wr_out, const struct nn_gui return 0; } -dds_return_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg) +dds_return_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg) { struct participant *pp; dds_return_t rc; @@ -2889,7 +2888,7 @@ dds_return_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const s 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 (nn_entityid_t entityid, struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc) +struct local_orphan_writer *new_local_orphan_writer (nn_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc) { nn_guid_t guid; struct local_orphan_writer *lowr; @@ -3203,7 +3202,7 @@ static dds_return_t new_reader_guid const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, - const struct nn_xqos *xqos, + const struct dds_qos *xqos, struct rhc *rhc, status_cb_t status_cb, void * status_entity @@ -3239,9 +3238,9 @@ static dds_return_t new_reader_guid DDS_LOG(DDS_LC_DISCOVERY, "}\n"); } assert (rd->xqos->present & QP_RELIABILITY); - rd->reliable = (rd->xqos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS); + rd->reliable = (rd->xqos->reliability.kind != DDS_RELIABILITY_BEST_EFFORT); assert (rd->xqos->present & QP_DURABILITY); - rd->handle_as_transient_local = (rd->xqos->durability.kind == NN_TRANSIENT_LOCAL_DURABILITY_QOS); + rd->handle_as_transient_local = (rd->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL); rd->topic = ddsi_sertopic_ref (topic); rd->ddsi2direct_cb = 0; rd->ddsi2direct_cbarg = 0; @@ -3262,10 +3261,9 @@ static dds_return_t new_reader_guid (ddsi_plugin.rhc_plugin.rhc_set_qos_fn) (rd->rhc, rd->xqos); } assert (rd->xqos->present & QP_LIVELINESS); - if (rd->xqos->liveliness.kind != NN_AUTOMATIC_LIVELINESS_QOS || - nn_from_ddsi_duration (rd->xqos->liveliness.lease_duration) != T_NEVER) + if (rd->xqos->liveliness.kind != DDS_LIVELINESS_AUTOMATIC || rd->xqos->liveliness.lease_duration != T_NEVER) { - DDS_LOG(DDS_LC_DISCOVERY, "reader "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (rd->e.guid), (int) rd->xqos->liveliness.kind, nn_from_ddsi_duration (rd->xqos->liveliness.lease_duration)); + DDS_LOG(DDS_LC_DISCOVERY, "reader "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (rd->e.guid), (int) rd->xqos->liveliness.kind, rd->xqos->liveliness.lease_duration); } #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS @@ -3342,7 +3340,7 @@ dds_return_t new_reader const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, - const struct nn_xqos *xqos, + const struct dds_qos *xqos, struct rhc * rhc, status_cb_t status_cb, void * status_cbarg @@ -3947,7 +3945,7 @@ uint64_t participant_instance_id (const struct nn_guid *guid) /* PROXY-GROUP --------------------------------------------------- */ -int new_proxy_group (const struct nn_guid *guid, const char *name, const struct nn_xqos *xqos, nn_wctime_t timestamp) +int new_proxy_group (const struct nn_guid *guid, const char *name, const struct dds_qos *xqos, nn_wctime_t timestamp) { struct proxy_participant *proxypp; nn_guid_t ppguid; @@ -4121,7 +4119,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, /* The DDSI built-in proxy writers always deliver asynchronously */ pwr->deliver_synchronously = 0; - } else if (nn_from_ddsi_duration (pwr->c.xqos->latency_budget.duration) <= config.synchronous_delivery_latency_bound && + } else if (pwr->c.xqos->latency_budget.duration <= config.synchronous_delivery_latency_bound && pwr->c.xqos->transport_priority.value >= config.synchronous_delivery_priority_threshold) { /* Regular proxy-writers with a sufficiently low latency_budget and a sufficiently high transport_priority deliver @@ -4131,7 +4129,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, pwr->deliver_synchronously = 0; } /* Pretend we have seen a heartbeat if the proxy writer is a best-effort one */ - isreliable = (pwr->c.xqos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS); + isreliable = (pwr->c.xqos->reliability.kind != DDS_RELIABILITY_BEST_EFFORT); pwr->have_seen_heartbeat = !isreliable; pwr->local_matching_inprogress = 1; #ifdef DDSI_INCLUDE_SSM @@ -4144,7 +4142,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, (unsigned) !!config.arrival_of_data_asserts_pp_and_ep_liveliness; assert (pwr->c.xqos->present & QP_LIVELINESS); - if (pwr->c.xqos->liveliness.kind != NN_AUTOMATIC_LIVELINESS_QOS) + if (pwr->c.xqos->liveliness.kind != DDS_LIVELINESS_AUTOMATIC) DDS_LOG(DDS_LC_DISCOVERY, " FIXME: only AUTOMATIC liveliness supported"); #if 0 pwr->tlease_dur = nn_from_ddsi_duration (pwr->c.xqos->liveliness.lease_duration); diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index c20b06c..9abc779 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -131,12 +131,12 @@ static int make_uc_sockets (uint32_t * pdisc, uint32_t * pdata, int ppid) return gv.data_conn_uc ? 0 : -1; } -static void make_builtin_endpoint_xqos (nn_xqos_t *q, const nn_xqos_t *template) +static void make_builtin_endpoint_xqos (dds_qos_t *q, const dds_qos_t *template) { nn_xqos_copy (q, template); - q->reliability.kind = NN_RELIABLE_RELIABILITY_QOS; - q->reliability.max_blocking_time = nn_to_ddsi_duration (100 * T_MILLISECOND); - q->durability.kind = NN_TRANSIENT_LOCAL_DURABILITY_QOS; + q->reliability.kind = DDS_RELIABILITY_RELIABLE; + q->reliability.max_blocking_time = 100 * T_MILLISECOND; + q->durability.kind = DDS_DURABILITY_TRANSIENT_LOCAL; } static int set_recvips (void) @@ -1006,7 +1006,7 @@ int rtps_init (void) 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); - gv.spdp_endpoint_xqos.durability.kind = NN_TRANSIENT_LOCAL_DURABILITY_QOS; + 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); diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index e930218..1e65ee5 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -35,6 +35,11 @@ #include "dds/ddsrt/avl.h" #include "dds/ddsi/q_misc.h" /* for vendor_is_... */ +/* I am tempted to change LENGTH_UNLIMITED to 0 in the API (with -1 + supported for backwards compatibility) ... on the wire however + it must be -1 */ +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 @@ -50,7 +55,7 @@ #define PPTMP_METATRAFFIC_MULTICAST_PORT (1 << 6) typedef struct nn_ipaddress_params_tmp { - unsigned present; + uint32_t present; nn_ipv4address_t multicast_ipaddress; nn_ipv4address_t default_unicast_ipaddress; @@ -70,11 +75,11 @@ struct dd { }; struct cdroctetseq { - unsigned len; + uint32_t len; unsigned char value[1]; }; -static void log_octetseq (uint32_t cat, unsigned n, const unsigned char *xs); +static void log_octetseq (uint32_t cat, uint32_t n, const unsigned char *xs); static size_t align4u (size_t x) { @@ -124,15 +129,15 @@ static dds_return_t alias_string (const unsigned char **ptr, const struct dd *dd static void unalias_string (char **str, int bswap) { const char *alias = *str; - unsigned len; + uint32_t len; if (bswap == 0 || bswap == 1) { - const unsigned *plen = (const unsigned *) alias - 1; + const uint32_t *plen = (const uint32_t *) alias - 1; len = bswap ? bswap4u (*plen) : *plen; } else { - len = (unsigned) strlen (alias) + 1; + len = (uint32_t) strlen (alias) + 1; } *str = ddsrt_malloc (len); memcpy (*str, alias, len); @@ -149,7 +154,7 @@ static dds_return_t validate_octetseq (const struct dd *dd, size_t *len) return 0; } -static dds_return_t alias_octetseq (nn_octetseq_t *oseq, const struct dd *dd) +static dds_return_t alias_octetseq (ddsi_octetseq_t *oseq, const struct dd *dd) { size_t len; dds_return_t rc; @@ -165,7 +170,7 @@ static dds_return_t alias_octetseq (nn_octetseq_t *oseq, const struct dd *dd) } } -static dds_return_t alias_blob (nn_octetseq_t *oseq, const struct dd *dd) +static dds_return_t alias_blob (ddsi_octetseq_t *oseq, const struct dd *dd) { assert (dd->bufsz < UINT32_MAX); oseq->length = (uint32_t)dd->bufsz; @@ -173,7 +178,7 @@ static dds_return_t alias_blob (nn_octetseq_t *oseq, const struct dd *dd) return 0; } -static void unalias_octetseq (nn_octetseq_t *oseq, UNUSED_ARG (int bswap)) +static void unalias_octetseq (ddsi_octetseq_t *oseq, UNUSED_ARG (int bswap)) { if (oseq->length != 0) { @@ -234,7 +239,7 @@ static dds_return_t validate_stringseq (const struct dd *dd) return 0; } -static dds_return_t alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) +static dds_return_t alias_stringseq (ddsi_stringseq_t *strseq, const struct dd *dd) { /* Not truly an alias: it allocates an array of pointers that alias the individual null-terminated strings. Also: see @@ -243,7 +248,7 @@ static dds_return_t alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd const unsigned char *seqend = seq + dd->bufsz; struct dd dd1 = *dd; char **strs; - unsigned i; + uint32_t i; dds_return_t result; if (dd->bufsz < sizeof (int)) { @@ -295,18 +300,18 @@ static dds_return_t alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd return result; } -static void free_stringseq (nn_stringseq_t *strseq) +static void free_stringseq (ddsi_stringseq_t *strseq) { - unsigned i; + uint32_t i; for (i = 0; i < strseq->n; i++) if (strseq->strs[i]) ddsrt_free (strseq->strs[i]); ddsrt_free (strseq->strs); } -static dds_return_t unalias_stringseq (nn_stringseq_t *strseq, int bswap) +static dds_return_t unalias_stringseq (ddsi_stringseq_t *strseq, int bswap) { - unsigned i; + uint32_t i; char **strs; if (strseq->n != 0) { @@ -322,9 +327,9 @@ static dds_return_t unalias_stringseq (nn_stringseq_t *strseq, int bswap) return 0; } -static void duplicate_stringseq (nn_stringseq_t *dest, const nn_stringseq_t *src) +static void duplicate_stringseq (ddsi_stringseq_t *dest, const ddsi_stringseq_t *src) { - unsigned i; + uint32_t i; dest->n = src->n; assert (dest->strs == NULL); if (dest->n == 0) @@ -460,7 +465,7 @@ void nn_plist_unalias (nn_plist_t *ps) } #endif -static dds_return_t do_octetseq (nn_octetseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) +static dds_return_t do_octetseq (ddsi_octetseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) { dds_return_t res; size_t len; @@ -474,7 +479,7 @@ static dds_return_t do_octetseq (nn_octetseq_t *dst, uint64_t *present, uint64_t return res; } -static dds_return_t do_blob (nn_octetseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) +static dds_return_t do_blob (ddsi_octetseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) { dds_return_t res; if (!(wanted & fl)) @@ -501,7 +506,7 @@ static dds_return_t do_string (char **dst, uint64_t *present, uint64_t *aliased, return res; } -static dds_return_t do_stringseq (nn_stringseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) +static dds_return_t do_stringseq (ddsi_stringseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) { dds_return_t res; if (!(wanted & fl)) @@ -514,13 +519,13 @@ static dds_return_t do_stringseq (nn_stringseq_t *dst, uint64_t *present, uint64 return res; } -static void bswap_time (nn_ddsi_time_t *t) +static void bswap_time (ddsi_time_t *t) { t->seconds = bswap4 (t->seconds); t->fraction = bswap4u (t->fraction); } -static dds_return_t validate_time (const nn_ddsi_time_t *t) +static dds_return_t validate_time (const ddsi_time_t *t) { /* Accepted are zero, positive, infinite or invalid as defined in the DDS 2.1 spec, table 9.4. */ @@ -535,46 +540,53 @@ static dds_return_t validate_time (const nn_ddsi_time_t *t) } } -static void bswap_duration (nn_duration_t *d) +static void bswap_external_duration (ddsi_duration_t *d) { bswap_time (d); } -dds_return_t validate_duration (const nn_duration_t *d) +static dds_return_t validate_external_duration (const ddsi_duration_t *d) { return validate_time (d); } -static dds_return_t do_duration (nn_duration_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) +dds_return_t validate_duration (const dds_duration_t d) { + return (d >= 0 && d <= DDS_INFINITY) ? DDS_RETCODE_OK : DDS_RETCODE_BAD_PARAMETER; +} + +static dds_return_t do_duration (dds_duration_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) +{ + ddsi_duration_t extq; dds_return_t res; - if (dd->bufsz < sizeof (*q)) + if (dd->bufsz < sizeof (extq)) { DDS_TRACE("plist/do_duration: buffer too small\n"); return DDS_RETCODE_BAD_PARAMETER; } - memcpy (q, dd->buf, sizeof (*q)); + memcpy (&extq, dd->buf, sizeof (extq)); if (dd->bswap) - bswap_duration (q); - if ((res = validate_duration (q)) < 0) + bswap_external_duration (&extq); + if ((res = validate_external_duration (&extq)) < 0) return res; + *q = nn_from_ddsi_duration (extq); *present |= fl; return 0; } -static void bswap_durability_qospolicy (nn_durability_qospolicy_t *q) +static void bswap_durability_qospolicy (dds_durability_qospolicy_t *q) { q->kind = bswap4u (q->kind); } -dds_return_t validate_durability_qospolicy (const nn_durability_qospolicy_t *q) +dds_return_t validate_durability_qospolicy (const dds_durability_qospolicy_t *q) { switch (q->kind) { - case NN_VOLATILE_DURABILITY_QOS: - case NN_TRANSIENT_LOCAL_DURABILITY_QOS: - case NN_TRANSIENT_DURABILITY_QOS: - case NN_PERSISTENT_DURABILITY_QOS: + case DDS_DURABILITY_VOLATILE: + case DDS_DURABILITY_TRANSIENT_LOCAL: + case DDS_DURABILITY_TRANSIENT: + case DDS_DURABILITY_PERSISTENT: break; default: DDS_TRACE("plist/validate_durability_qospolicy: invalid kind (%d)\n", (int) q->kind); @@ -583,18 +595,18 @@ dds_return_t validate_durability_qospolicy (const nn_durability_qospolicy_t *q) return 0; } -static void bswap_history_qospolicy (nn_history_qospolicy_t *q) +static void bswap_history_qospolicy (dds_history_qospolicy_t *q) { q->kind = bswap4u (q->kind); q->depth = bswap4 (q->depth); } -static int history_qospolicy_allzero (const nn_history_qospolicy_t *q) +static int history_qospolicy_allzero (const dds_history_qospolicy_t *q) { - return q->kind == NN_KEEP_LAST_HISTORY_QOS && q->depth == 0; + return q->kind == DDS_HISTORY_KEEP_LAST && q->depth == 0; } -dds_return_t validate_history_qospolicy (const nn_history_qospolicy_t *q) +dds_return_t validate_history_qospolicy (const dds_history_qospolicy_t *q) { /* Validity of history setting and of resource limits are dependent, but we don't have access to the resource limits here ... the @@ -605,15 +617,15 @@ dds_return_t validate_history_qospolicy (const nn_history_qospolicy_t *q) n possibly unlimited. */ switch (q->kind) { - case NN_KEEP_LAST_HISTORY_QOS: - case NN_KEEP_ALL_HISTORY_QOS: + case DDS_HISTORY_KEEP_LAST: + case DDS_HISTORY_KEEP_ALL: break; default: DDS_TRACE("plist/validate_history_qospolicy: invalid kind (%d)\n", (int) q->kind); return DDS_RETCODE_BAD_PARAMETER; } /* Accept all values for depth if kind = ALL */ - if (q->kind == NN_KEEP_LAST_HISTORY_QOS) + if (q->kind == DDS_HISTORY_KEEP_LAST) { if (q->depth < 1) { @@ -624,21 +636,21 @@ dds_return_t validate_history_qospolicy (const nn_history_qospolicy_t *q) return 0; } -static void bswap_resource_limits_qospolicy (nn_resource_limits_qospolicy_t *q) +static void bswap_resource_limits_qospolicy (dds_resource_limits_qospolicy_t *q) { q->max_samples = bswap4 (q->max_samples); q->max_instances = bswap4 (q->max_instances); q->max_samples_per_instance = bswap4 (q->max_samples_per_instance); } -static int resource_limits_qospolicy_allzero (const nn_resource_limits_qospolicy_t *q) +static int resource_limits_qospolicy_allzero (const dds_resource_limits_qospolicy_t *q) { return q->max_samples == 0 && q->max_instances == 0 && q->max_samples_per_instance == 0; } -dds_return_t validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q) +dds_return_t validate_resource_limits_qospolicy (const dds_resource_limits_qospolicy_t *q) { - const int unlimited = NN_DDS_LENGTH_UNLIMITED; + const int unlimited = DDS_LENGTH_UNLIMITED; /* Note: dependent on history setting as well (see validate_history_qospolicy). Verifying only the internal consistency of the resource limits. */ @@ -670,9 +682,9 @@ dds_return_t validate_resource_limits_qospolicy (const nn_resource_limits_qospol return 0; } -dds_return_t validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, const nn_resource_limits_qospolicy_t *qr) +dds_return_t validate_history_and_resource_limits (const dds_history_qospolicy_t *qh, const dds_resource_limits_qospolicy_t *qr) { - const int unlimited = NN_DDS_LENGTH_UNLIMITED; + const int unlimited = DDS_LENGTH_UNLIMITED; dds_return_t res; if ((res = validate_history_qospolicy (qh)) < 0) { @@ -686,7 +698,7 @@ dds_return_t validate_history_and_resource_limits (const nn_history_qospolicy_t } switch (qh->kind) { - case NN_KEEP_ALL_HISTORY_QOS: + case DDS_HISTORY_KEEP_ALL: #if 0 /* See comment in validate_resource_limits, ref'ing 7.1.3.19 */ if (qr->max_samples_per_instance != unlimited) { @@ -695,7 +707,7 @@ dds_return_t validate_history_and_resource_limits (const nn_history_qospolicy_t } #endif break; - case NN_KEEP_LAST_HISTORY_QOS: + case DDS_HISTORY_KEEP_LAST: if (qr->max_samples_per_instance != unlimited && qh->depth > qr->max_samples_per_instance) { DDS_TRACE("plist/validate_history_and_resource_limits: depth (%d) and max_samples_per_instance (%d) incompatible with KEEP_LAST policy\n", (int) qh->depth, (int) qr->max_samples_per_instance); @@ -706,26 +718,33 @@ dds_return_t validate_history_and_resource_limits (const nn_history_qospolicy_t return 0; } -static void bswap_durability_service_qospolicy (nn_durability_service_qospolicy_t *q) +static void bswap_external_durability_service_qospolicy (dds_external_durability_service_qospolicy_t *q) { - bswap_duration (&q->service_cleanup_delay); + bswap_external_duration (&q->service_cleanup_delay); bswap_history_qospolicy (&q->history); bswap_resource_limits_qospolicy (&q->resource_limits); } -static int durability_service_qospolicy_allzero (const nn_durability_service_qospolicy_t *q) +static int durability_service_qospolicy_allzero (const dds_durability_service_qospolicy_t *q) +{ + return (history_qospolicy_allzero (&q->history) && + resource_limits_qospolicy_allzero (&q->resource_limits) && + q->service_cleanup_delay == 0); +} + +static int external_durability_service_qospolicy_allzero (const dds_external_durability_service_qospolicy_t *q) { return (history_qospolicy_allzero (&q->history) && resource_limits_qospolicy_allzero (&q->resource_limits) && q->service_cleanup_delay.seconds == 0 && q->service_cleanup_delay.fraction == 0); } -static dds_return_t validate_durability_service_qospolicy_acceptzero (const nn_durability_service_qospolicy_t *q, bool acceptzero) +static dds_return_t validate_external_durability_service_qospolicy_acceptzero (const dds_external_durability_service_qospolicy_t *q, bool acceptzero) { dds_return_t res; - if (acceptzero && durability_service_qospolicy_allzero (q)) + if (acceptzero && external_durability_service_qospolicy_allzero (q)) return 0; - if ((res = validate_duration (&q->service_cleanup_delay)) < 0) + if ((res = validate_external_duration (&q->service_cleanup_delay)) < 0) { DDS_TRACE("plist/validate_durability_service_qospolicy: duration invalid\n"); return res; @@ -738,26 +757,30 @@ static dds_return_t validate_durability_service_qospolicy_acceptzero (const nn_d return 0; } -dds_return_t validate_durability_service_qospolicy (const nn_durability_service_qospolicy_t *q) +dds_return_t validate_durability_service_qospolicy (const dds_durability_service_qospolicy_t *q) { - return validate_durability_service_qospolicy_acceptzero (q, false); + dds_external_durability_service_qospolicy_t qext; + qext.history = q->history; + qext.resource_limits = q->resource_limits; + qext.service_cleanup_delay = nn_to_ddsi_duration (q->service_cleanup_delay); + return validate_external_durability_service_qospolicy_acceptzero (&qext, false); } -static void bswap_liveliness_qospolicy (nn_liveliness_qospolicy_t *q) +static void bswap_external_liveliness_qospolicy (dds_external_liveliness_qospolicy_t *q) { q->kind = bswap4u (q->kind); - bswap_duration (&q->lease_duration); + bswap_external_duration (&q->lease_duration); } -dds_return_t validate_liveliness_qospolicy (const nn_liveliness_qospolicy_t *q) +static dds_return_t validate_external_liveliness_qospolicy (const dds_external_liveliness_qospolicy_t *q) { dds_return_t res; switch (q->kind) { - case NN_AUTOMATIC_LIVELINESS_QOS: - case NN_MANUAL_BY_PARTICIPANT_LIVELINESS_QOS: - case NN_MANUAL_BY_TOPIC_LIVELINESS_QOS: - if ((res = validate_duration (&q->lease_duration)) < 0) + case DDS_LIVELINESS_AUTOMATIC: + case DDS_LIVELINESS_MANUAL_BY_PARTICIPANT: + case DDS_LIVELINESS_MANUAL_BY_TOPIC: + if ((res = validate_external_duration (&q->lease_duration)) < 0) DDS_TRACE("plist/validate_liveliness_qospolicy: invalid lease duration\n"); return res; default: @@ -766,63 +789,51 @@ dds_return_t validate_liveliness_qospolicy (const nn_liveliness_qospolicy_t *q) } } -static void bswap_external_reliability_qospolicy (nn_external_reliability_qospolicy_t *qext) +dds_return_t validate_liveliness_qospolicy (const dds_liveliness_qospolicy_t *q) +{ + dds_external_liveliness_qospolicy_t qext; + qext.kind = q->kind; + qext.lease_duration = nn_to_ddsi_duration (q->lease_duration); + return validate_external_liveliness_qospolicy (&qext); +} + +static void bswap_external_reliability_qospolicy (dds_external_reliability_qospolicy_t *qext) { qext->kind = bswap4u (qext->kind); - bswap_duration (&qext->max_blocking_time); + bswap_external_duration (&qext->max_blocking_time); } -static dds_return_t validate_xform_reliability_qospolicy (nn_reliability_qospolicy_t *qdst, const nn_external_reliability_qospolicy_t *qext) +static dds_return_t validate_xform_reliability_qospolicy (dds_reliability_qospolicy_t *qdst, const dds_external_reliability_qospolicy_t *qext) { dds_return_t res; - qdst->max_blocking_time = qext->max_blocking_time; - if (NN_PEDANTIC_P) + qdst->max_blocking_time = nn_from_ddsi_duration (qext->max_blocking_time); + switch (qext->kind) { - switch (qext->kind) - { - case NN_PEDANTIC_BEST_EFFORT_RELIABILITY_QOS: - qdst->kind = NN_BEST_EFFORT_RELIABILITY_QOS; - return 0; - case NN_PEDANTIC_RELIABLE_RELIABILITY_QOS: - qdst->kind = NN_RELIABLE_RELIABILITY_QOS; - if ((res = validate_duration (&qdst->max_blocking_time)) < 0) - DDS_TRACE("plist/validate_xform_reliability_qospolicy[pedantic]: max_blocking_time invalid\n"); - return res; - default: - DDS_TRACE("plist/validate_xform_reliability_qospolicy[pedantic]: invalid kind (%d)\n", (int) qext->kind); - return DDS_RETCODE_BAD_PARAMETER; - } - } - else - { - switch (qext->kind) - { - case NN_INTEROP_BEST_EFFORT_RELIABILITY_QOS: - qdst->kind = NN_BEST_EFFORT_RELIABILITY_QOS; - return 0; - case NN_INTEROP_RELIABLE_RELIABILITY_QOS: - qdst->kind = NN_RELIABLE_RELIABILITY_QOS; - if ((res = validate_duration (&qdst->max_blocking_time)) < 0) - DDS_TRACE("plist/validate_xform_reliability_qospolicy[!pedantic]: max_blocking time invalid\n"); - return res; - default: - DDS_TRACE("plist/validate_xform_reliability_qospolicy[!pedantic]: invalid kind (%d)\n", (int) qext->kind); - return DDS_RETCODE_BAD_PARAMETER; - } + case DDS_EXTERNAL_RELIABILITY_BEST_EFFORT: + qdst->kind = DDS_RELIABILITY_BEST_EFFORT; + return 0; + case DDS_EXTERNAL_RELIABILITY_RELIABLE: + qdst->kind = DDS_RELIABILITY_RELIABLE; + if ((res = validate_external_duration (&qext->max_blocking_time)) < 0) + DDS_TRACE("plist/validate_xform_reliability_qospolicy[!pedantic]: max_blocking time invalid\n"); + return res; + default: + DDS_TRACE("plist/validate_xform_reliability_qospolicy[!pedantic]: invalid kind (%d)\n", (int) qext->kind); + return DDS_RETCODE_BAD_PARAMETER; } } -static void bswap_destination_order_qospolicy (nn_destination_order_qospolicy_t *q) +static void bswap_destination_order_qospolicy (dds_destination_order_qospolicy_t *q) { q->kind = bswap4u (q->kind); } -dds_return_t validate_destination_order_qospolicy (const nn_destination_order_qospolicy_t *q) +dds_return_t validate_destination_order_qospolicy (const dds_destination_order_qospolicy_t *q) { switch (q->kind) { - case NN_BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS: - case NN_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS: + case DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP: + case DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP: return 0; default: DDS_TRACE("plist/validate_destination_order_qospolicy: invalid kind (%d)\n", (int) q->kind); @@ -830,17 +841,17 @@ dds_return_t validate_destination_order_qospolicy (const nn_destination_order_qo } } -static void bswap_ownership_qospolicy (nn_ownership_qospolicy_t *q) +static void bswap_ownership_qospolicy (dds_ownership_qospolicy_t *q) { q->kind = bswap4u (q->kind); } -dds_return_t validate_ownership_qospolicy (const nn_ownership_qospolicy_t *q) +dds_return_t validate_ownership_qospolicy (const dds_ownership_qospolicy_t *q) { switch (q->kind) { - case NN_SHARED_OWNERSHIP_QOS: - case NN_EXCLUSIVE_OWNERSHIP_QOS: + case DDS_OWNERSHIP_SHARED: + case DDS_OWNERSHIP_EXCLUSIVE: return 0; default: DDS_TRACE("plist/validate_ownership_qospolicy: invalid kind (%d)\n", (int) q->kind); @@ -848,28 +859,28 @@ dds_return_t validate_ownership_qospolicy (const nn_ownership_qospolicy_t *q) } } -static void bswap_ownership_strength_qospolicy (nn_ownership_strength_qospolicy_t *q) +static void bswap_ownership_strength_qospolicy (dds_ownership_strength_qospolicy_t *q) { q->value = bswap4 (q->value); } -dds_return_t validate_ownership_strength_qospolicy (UNUSED_ARG (const nn_ownership_strength_qospolicy_t *q)) +dds_return_t validate_ownership_strength_qospolicy (UNUSED_ARG (const dds_ownership_strength_qospolicy_t *q)) { return 0; } -static void bswap_presentation_qospolicy (nn_presentation_qospolicy_t *q) +static void bswap_presentation_qospolicy (dds_presentation_qospolicy_t *q) { q->access_scope = bswap4u (q->access_scope); } -dds_return_t validate_presentation_qospolicy (const nn_presentation_qospolicy_t *q) +dds_return_t validate_presentation_qospolicy (const dds_presentation_qospolicy_t *q) { switch (q->access_scope) { - case NN_INSTANCE_PRESENTATION_QOS: - case NN_TOPIC_PRESENTATION_QOS: - case NN_GROUP_PRESENTATION_QOS: + case DDS_PRESENTATION_INSTANCE: + case DDS_PRESENTATION_TOPIC: + case DDS_PRESENTATION_GROUP: break; default: DDS_TRACE("plist/validate_presentation_qospolicy: invalid access_scope (%d)\n", (int) q->access_scope); @@ -892,12 +903,12 @@ dds_return_t validate_presentation_qospolicy (const nn_presentation_qospolicy_t return 0; } -static void bswap_transport_priority_qospolicy (nn_transport_priority_qospolicy_t *q) +static void bswap_transport_priority_qospolicy (dds_transport_priority_qospolicy_t *q) { q->value = bswap4 (q->value); } -dds_return_t validate_transport_priority_qospolicy (UNUSED_ARG (const nn_transport_priority_qospolicy_t *q)) +dds_return_t validate_transport_priority_qospolicy (UNUSED_ARG (const dds_transport_priority_qospolicy_t *q)) { return 0; } @@ -935,14 +946,14 @@ static int locator_address_prefix12_zero (const nn_locator_t *loc) /* loc has has 32 bit ints preceding the address, hence address is 4-byte aligned; reading char* as unsigneds isn't illegal type punning */ - const unsigned *u = (const unsigned *) loc->address; + const uint32_t *u = (const uint32_t *) loc->address; return (u[0] == 0 && u[1] == 0 && u[2] == 0); } static int locator_address_zero (const nn_locator_t *loc) { /* see locator_address_prefix12_zero */ - const unsigned *u = (const unsigned *) loc->address; + const uint32_t *u = (const uint32_t *) loc->address; return (u[0] == 0 && u[1] == 0 && u[2] == 0 && u[3] == 0); } @@ -1038,12 +1049,12 @@ 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, unsigned fl_tmp, const struct dd *dd) +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) { nn_ipv4address_t *a; nn_port_t *p; nn_locators_t *ls; - unsigned fl1_tmp; + uint32_t fl1_tmp; uint64_t fldest; if (dd->bufsz < sizeof (*a)) { @@ -1108,13 +1119,13 @@ 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, unsigned fl_tmp, const struct dd *dd) +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) { nn_ipv4address_t *a; nn_port_t *p; nn_locators_t *ls; uint64_t fldest; - unsigned fl1_tmp; + uint32_t fl1_tmp; if (dd->bufsz < sizeof (*p)) { DDS_TRACE("plist/do_port: buffer too small\n"); @@ -1359,7 +1370,7 @@ static dds_return_t do_prismtech_participant_version_info (nn_prismtech_particip else { dds_return_t res; - unsigned sz = NN_PRISMTECH_PARTICIPANT_VERSION_INFO_FIXED_CDRSIZE - sizeof(uint32_t); + uint32_t sz = NN_PRISMTECH_PARTICIPANT_VERSION_INFO_FIXED_CDRSIZE - sizeof(uint32_t); uint32_t *pu = (uint32_t *)dd->buf; size_t len; struct dd dd1 = *dd; @@ -1380,7 +1391,7 @@ static dds_return_t do_prismtech_participant_version_info (nn_prismtech_particip } } -static dds_return_t do_subscription_keys_qospolicy (nn_subscription_keys_qospolicy_t *q, uint64_t *present, uint64_t *aliased, uint64_t fl, const struct dd *dd) +static dds_return_t do_subscription_keys_qospolicy (dds_subscription_keys_qospolicy_t *q, uint64_t *present, uint64_t *aliased, uint64_t fl, const struct dd *dd) { struct dd dd1; dds_return_t res; @@ -1406,33 +1417,37 @@ static dds_return_t do_subscription_keys_qospolicy (nn_subscription_keys_qospoli return res; } -static dds_return_t unalias_subscription_keys_qospolicy (nn_subscription_keys_qospolicy_t *q, int bswap) +static dds_return_t unalias_subscription_keys_qospolicy (dds_subscription_keys_qospolicy_t *q, int bswap) { return unalias_stringseq (&q->key_list, bswap); } -static dds_return_t do_reader_lifespan_qospolicy (nn_reader_lifespan_qospolicy_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) +static dds_return_t do_reader_lifespan_qospolicy (dds_reader_lifespan_qospolicy_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) { + dds_external_reader_lifespan_qospolicy_t qext; dds_return_t res; - if (dd->bufsz < sizeof (*q)) + if (dd->bufsz < sizeof (qext)) { DDS_TRACE("plist/do_reader_lifespan: buffer too small\n"); return DDS_RETCODE_BAD_PARAMETER; } - *q = *((nn_reader_lifespan_qospolicy_t *) dd->buf); + memcpy (&qext, dd->buf, sizeof (qext)); if (dd->bswap) - bswap_duration (&q->duration); - if (q->use_lifespan != 0 && q->use_lifespan != 1) + bswap_external_duration (&qext.duration); + if (qext.use_lifespan != 0 && qext.use_lifespan != 1) { - DDS_TRACE("plist/do_reader_lifespan: invalid use_lifespan (%d)\n", (int) q->use_lifespan); + DDS_TRACE("plist/do_reader_lifespan: invalid use_lifespan (%d)\n", (int) qext.use_lifespan); return DDS_RETCODE_BAD_PARAMETER; } - if ((res = validate_duration (&q->duration)) >= 0) - *present |= fl; - return res; + if ((res = validate_external_duration (&qext.duration)) < 0) + return res; + q->use_lifespan = qext.use_lifespan; + q->duration = nn_from_ddsi_duration (qext.duration); + *present |= fl; + return 0; } -static dds_return_t do_entity_factory_qospolicy (nn_entity_factory_qospolicy_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) +static dds_return_t do_entity_factory_qospolicy (dds_entity_factory_qospolicy_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) { if (dd->bufsz < sizeof (*q)) { @@ -1449,62 +1464,40 @@ static dds_return_t do_entity_factory_qospolicy (nn_entity_factory_qospolicy_t * return 0; } -dds_return_t validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t *q) +static dds_return_t validate_external_reader_data_lifecycle (const dds_external_reader_data_lifecycle_qospolicy_t *q) { - if (validate_duration (&q->autopurge_nowriter_samples_delay) < 0 || - validate_duration (&q->autopurge_disposed_samples_delay) < 0) + if (validate_external_duration (&q->autopurge_nowriter_samples_delay) < 0 || + validate_external_duration (&q->autopurge_disposed_samples_delay) < 0) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid autopurge_nowriter_sample_delay or autopurge_disposed_samples_delay\n"); return DDS_RETCODE_BAD_PARAMETER; } - if (q->autopurge_dispose_all != 0 && q->autopurge_dispose_all != 1) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid autopurge_dispose_all\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - if (q->enable_invalid_samples != 0 && q->enable_invalid_samples != 1) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid enable_invalid_samples\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - /* Don't check consistency between enable_invalid_samples and invalid_samples_mode (yet) */ - switch (q->invalid_sample_visibility) - { - case NN_NO_INVALID_SAMPLE_VISIBILITY_QOS: - case NN_MINIMUM_INVALID_SAMPLE_VISIBILITY_QOS: - case NN_ALL_INVALID_SAMPLE_VISIBILITY_QOS: - break; - default: - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid invalid_sample_visibility\n"); - return DDS_RETCODE_BAD_PARAMETER; - } return 0; } -static dds_return_t do_reader_data_lifecycle_v0 (nn_reader_data_lifecycle_qospolicy_t *q, const struct dd *dd) +dds_return_t validate_reader_data_lifecycle (const dds_reader_data_lifecycle_qospolicy_t *q) { - memcpy (q, dd->buf, 2 * sizeof (nn_duration_t)); - q->autopurge_dispose_all = 0; - q->enable_invalid_samples = 1; - q->invalid_sample_visibility = NN_MINIMUM_INVALID_SAMPLE_VISIBILITY_QOS; - if (dd->bswap) - { - bswap_duration (&q->autopurge_nowriter_samples_delay); - bswap_duration (&q->autopurge_disposed_samples_delay); - } - return validate_reader_data_lifecycle (q); + dds_external_reader_data_lifecycle_qospolicy_t qext; + qext.autopurge_disposed_samples_delay = nn_to_ddsi_duration (q->autopurge_disposed_samples_delay); + qext.autopurge_nowriter_samples_delay = nn_to_ddsi_duration (q->autopurge_nowriter_samples_delay); + return validate_external_reader_data_lifecycle (&qext); } -static dds_return_t do_reader_data_lifecycle_v1 (nn_reader_data_lifecycle_qospolicy_t *q, const struct dd *dd) +static dds_return_t do_reader_data_lifecycle (dds_reader_data_lifecycle_qospolicy_t *q, const struct dd *dd) { - memcpy (q, dd->buf, sizeof (*q)); + dds_external_reader_data_lifecycle_qospolicy_t qext; + dds_return_t ret; + memcpy (&qext, dd->buf, sizeof (qext)); if (dd->bswap) { - bswap_duration (&q->autopurge_nowriter_samples_delay); - bswap_duration (&q->autopurge_disposed_samples_delay); - q->invalid_sample_visibility = (nn_invalid_sample_visibility_kind_t) bswap4u ((unsigned) q->invalid_sample_visibility); + bswap_external_duration (&qext.autopurge_nowriter_samples_delay); + bswap_external_duration (&qext.autopurge_disposed_samples_delay); } - return validate_reader_data_lifecycle (q); + if ((ret = validate_external_reader_data_lifecycle (&qext)) < 0) + return ret; + q->autopurge_disposed_samples_delay = nn_from_ddsi_duration (qext.autopurge_disposed_samples_delay); + q->autopurge_nowriter_samples_delay = nn_from_ddsi_duration (qext.autopurge_nowriter_samples_delay); + return 0; } static dds_return_t init_one_parameter @@ -1513,7 +1506,7 @@ static dds_return_t init_one_parameter nn_ipaddress_params_tmp_t *dest_tmp, uint64_t pwanted, uint64_t qwanted, - unsigned short pid, + uint16_t pid, const struct dd *dd ) { @@ -1525,15 +1518,15 @@ static dds_return_t init_one_parameter return 0; /* Extended QoS data: */ -#define Q(NAME_, name_) case PID_##NAME_: \ - if (dd->bufsz < sizeof (nn_##name_##_qospolicy_t)) \ +#define Q(NAME_, prefix_, name_) case PID_##NAME_: \ + if (dd->bufsz < sizeof (prefix_##_##name_##_qospolicy_t)) \ { \ DDS_TRACE("plist/init_one_parameter[pid=%s]: buffer too small\n", #NAME_); \ - return DDS_RETCODE_BAD_PARAMETER; \ + return DDS_RETCODE_BAD_PARAMETER; \ } \ else \ { \ - nn_##name_##_qospolicy_t *q = &dest->qos.name_; \ + prefix_##_##name_##_qospolicy_t *q = &dest->qos.name_; \ memcpy (q, dd->buf, sizeof (*q)); \ if (dd->bswap) bswap_##name_##_qospolicy (q); \ if ((res = validate_##name_##_qospolicy (q)) < 0) \ @@ -1541,34 +1534,58 @@ static dds_return_t init_one_parameter dest->qos.present |= QP_##NAME_; \ } \ return 0 - Q (DURABILITY, durability); - Q (LIVELINESS, liveliness); - Q (DESTINATION_ORDER, destination_order); - Q (HISTORY, history); - Q (RESOURCE_LIMITS, resource_limits); - Q (OWNERSHIP, ownership); - Q (OWNERSHIP_STRENGTH, ownership_strength); - Q (PRESENTATION, presentation); - Q (TRANSPORT_PRIORITY, transport_priority); + Q (DURABILITY, dds, durability); + Q (DESTINATION_ORDER, dds, destination_order); + Q (HISTORY, dds, history); + Q (RESOURCE_LIMITS, dds, resource_limits); + Q (OWNERSHIP, dds, ownership); + Q (OWNERSHIP_STRENGTH, dds, ownership_strength); + Q (PRESENTATION, dds, presentation); + Q (TRANSPORT_PRIORITY, dds, transport_priority); #undef Q + case PID_LIVELINESS: + if (dd->bufsz < sizeof (dds_external_liveliness_qospolicy_t)) + { + DDS_TRACE("plist/init_one_parameter[pid=LIVELINESS]: buffer too small\n"); + return DDS_RETCODE_BAD_PARAMETER; + } + else + { + dds_external_liveliness_qospolicy_t qext; + dds_liveliness_qospolicy_t *q = &dest->qos.liveliness; + memcpy (&qext, dd->buf, sizeof (qext)); + if (dd->bswap) + bswap_external_liveliness_qospolicy (&qext); + if ((res = validate_external_liveliness_qospolicy (&qext)) < 0) + return res; + q->kind = qext.kind; + q->lease_duration = nn_from_ddsi_duration (qext.lease_duration); + dest->qos.present |= QP_LIVELINESS; + } + return 0; + case PID_DURABILITY_SERVICE: - if (dd->bufsz < sizeof (nn_durability_service_qospolicy_t)) + if (dd->bufsz < sizeof (dds_external_durability_service_qospolicy_t)) { DDS_TRACE("plist/init_one_parameter[pid=DURABILITY_SERVICE]: buffer too small\n"); return DDS_RETCODE_BAD_PARAMETER; } else { - nn_durability_service_qospolicy_t *q = &dest->qos.durability_service; + dds_external_durability_service_qospolicy_t qext; + dds_durability_service_qospolicy_t *q = &dest->qos.durability_service; /* All-zero durability service is illegal, but at least CoreDX sometimes advertises it in some harmless cases. So accept all-zero durability service, then handle it in final_validation, where we can determine whether it really is harmless or not */ - memcpy (q, dd->buf, sizeof (*q)); + memcpy (&qext, dd->buf, sizeof (qext)); if (dd->bswap) - bswap_durability_service_qospolicy (q); - if ((res = validate_durability_service_qospolicy_acceptzero (q, true)) < 0) + bswap_external_durability_service_qospolicy (&qext); + if ((res = validate_external_durability_service_qospolicy_acceptzero (&qext, true)) < 0) return res; + q->history = qext.history; + q->resource_limits = qext.resource_limits; + q->service_cleanup_delay = nn_from_ddsi_duration (qext.service_cleanup_delay); dest->qos.present |= QP_DURABILITY_SERVICE; } return 0; @@ -1580,15 +1597,15 @@ static dds_return_t init_one_parameter the case, it would've been an ordinary Q (RELIABILITY, reliability). */ case PID_RELIABILITY: - if (dd->bufsz < sizeof (nn_external_reliability_qospolicy_t)) + if (dd->bufsz < sizeof (dds_external_reliability_qospolicy_t)) { DDS_TRACE("plist/init_one_parameter[pid=RELIABILITY]: buffer too small\n"); return DDS_RETCODE_BAD_PARAMETER; } else { - nn_reliability_qospolicy_t *q = &dest->qos.reliability; - nn_external_reliability_qospolicy_t qext; + dds_reliability_qospolicy_t *q = &dest->qos.reliability; + dds_external_reliability_qospolicy_t qext; memcpy (&qext, dd->buf, sizeof (qext)); if (dd->bswap) bswap_external_reliability_qospolicy (&qext); @@ -1627,10 +1644,8 @@ static dds_return_t init_one_parameter dds_return_t ret; if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) return 0; - if (dd->bufsz >= sizeof (nn_reader_data_lifecycle_qospolicy_t)) - ret = do_reader_data_lifecycle_v1 (&dest->qos.reader_data_lifecycle, dd); - else if (dd->bufsz >= 2 * sizeof (nn_duration_t)) - ret = do_reader_data_lifecycle_v0 (&dest->qos.reader_data_lifecycle, dd); + if (dd->bufsz >= sizeof (dds_external_reader_data_lifecycle_qospolicy_t)) + ret = do_reader_data_lifecycle (&dest->qos.reader_data_lifecycle, dd); else { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: buffer too small\n"); @@ -1645,85 +1660,22 @@ static dds_return_t init_one_parameter return 0; else { - nn_writer_data_lifecycle_qospolicy_t *q = &dest->qos.writer_data_lifecycle; - if (dd->bufsz < 1) + dds_writer_data_lifecycle_qospolicy_t *q = &dest->qos.writer_data_lifecycle; + if (dd->bufsz < sizeof (*q)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: buffer too small\n"); return DDS_RETCODE_BAD_PARAMETER; } - else if (dd->bufsz < sizeof (*q)) - { - /* Spec form, with just autodispose_unregistered_instances */ - q->autodispose_unregistered_instances = dd->buf[0]; - q->autounregister_instance_delay = nn_to_ddsi_duration (T_NEVER); - q->autopurge_suspended_samples_delay = nn_to_ddsi_duration (T_NEVER); - } - else - { - memcpy (q, dd->buf, sizeof (*q)); - if (dd->bswap) - { - bswap_duration (&q->autounregister_instance_delay); - bswap_duration (&q->autopurge_suspended_samples_delay); - } - } + q->autodispose_unregistered_instances = dd->buf[0]; if (q->autodispose_unregistered_instances & ~1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: invalid autodispose_unregistered_instances (%d)\n", (int) q->autodispose_unregistered_instances); return DDS_RETCODE_BAD_PARAMETER; } - if (validate_duration (&q->autounregister_instance_delay) < 0 || - validate_duration (&q->autopurge_suspended_samples_delay) < 0) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: invalid autounregister_instance_delay or autopurge_suspended_samples_delay\n"); - return DDS_RETCODE_BAD_PARAMETER; - } dest->qos.present |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE; return 0; } - case PID_PRISMTECH_RELAXED_QOS_MATCHING: - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - else if (dd->bufsz < sizeof (dest->qos.relaxed_qos_matching)) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_RELAXED_QOS_MATCHING]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - else - { - nn_relaxed_qos_matching_qospolicy_t *rqm = &dest->qos.relaxed_qos_matching; - memcpy (rqm, dd->buf, sizeof (*rqm)); - if (rqm->value != 0 && rqm->value != 1) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_RELAXED_QOS_MATCHING]: invalid\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - dest->qos.present |= QP_PRISMTECH_RELAXED_QOS_MATCHING; - return 0; - } - - case PID_PRISMTECH_SYNCHRONOUS_ENDPOINT: /* PrismTech specific */ - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - else if (dd->bufsz < sizeof (dest->qos.synchronous_endpoint)) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SYNCHRONOUS_ENDPOINT]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - else - { - nn_synchronous_endpoint_qospolicy_t *q = &dest->qos.synchronous_endpoint; - memcpy (q, dd->buf, sizeof (*q)); - if (q->value != 0 && q->value != 1) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SYNCHRONOUS_ENDPOINT]: invalid value for synchronous flag\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - dest->qos.present |= QP_PRISMTECH_SYNCHRONOUS_ENDPOINT; - return 0; - } - /* Other plist */ case PID_PROTOCOL_VERSION: if (dd->bufsz < sizeof (nn_protocol_version_t)) @@ -2183,16 +2135,16 @@ static dds_return_t init_one_parameter return DDS_RETCODE_BAD_PARAMETER; } -static void default_resource_limits (nn_resource_limits_qospolicy_t *q) +static void default_resource_limits (dds_resource_limits_qospolicy_t *q) { - q->max_instances = NN_DDS_LENGTH_UNLIMITED; - q->max_samples = NN_DDS_LENGTH_UNLIMITED; - q->max_samples_per_instance = NN_DDS_LENGTH_UNLIMITED; + q->max_instances = DDS_LENGTH_UNLIMITED; + q->max_samples = DDS_LENGTH_UNLIMITED; + q->max_samples_per_instance = DDS_LENGTH_UNLIMITED; } -static void default_history (nn_history_qospolicy_t *q) +static void default_history (dds_history_qospolicy_t *q) { - q->kind = NN_KEEP_LAST_HISTORY_QOS; + q->kind = DDS_HISTORY_KEEP_LAST; q->depth = 1; } @@ -2322,7 +2274,7 @@ static dds_return_t final_validation (nn_plist_t *dest, nn_protocol_version_t pr is valid or delete it if irrelevant. */ if (dest->qos.present & QP_DURABILITY_SERVICE) { - const nn_durability_kind_t durkind = (dest->qos.present & QP_DURABILITY) ? dest->qos.durability.kind : NN_VOLATILE_DURABILITY_QOS; + const dds_durability_kind_t durkind = (dest->qos.present & QP_DURABILITY) ? dest->qos.durability.kind : DDS_DURABILITY_VOLATILE; bool acceptzero; /* Use a somewhat convoluted rule to decide whether or not to "accept" an all-zero durability service setting, to find a @@ -2335,14 +2287,14 @@ static dds_return_t final_validation (nn_plist_t *dest, nn_protocol_version_t pr acceptzero = !vendor_is_eclipse (vendorid); switch (durkind) { - case NN_VOLATILE_DURABILITY_QOS: - case NN_TRANSIENT_LOCAL_DURABILITY_QOS: + case DDS_DURABILITY_VOLATILE: + case DDS_DURABILITY_TRANSIENT_LOCAL: /* pretend we never saw it if it is all zero */ if (acceptzero && durability_service_qospolicy_allzero (&dest->qos.durability_service)) dest->qos.present &= ~QP_DURABILITY_SERVICE; break; - case NN_TRANSIENT_DURABILITY_QOS: - case NN_PERSISTENT_DURABILITY_QOS: + case DDS_DURABILITY_TRANSIENT: + case DDS_DURABILITY_PERSISTENT: break; } /* if it is still present, it must be valid */ @@ -2409,17 +2361,17 @@ dds_return_t nn_plist_init_frommsg { nn_parameter_t *par = (nn_parameter_t *) pl; nn_parameterid_t pid; - unsigned short length; + uint16_t length; dds_return_t res; /* swapping header partially based on wireshark dissector output, partially on intuition, and in a small part based on the spec */ pid = (nn_parameterid_t) (dd.bswap ? bswap2u (par->parameterid) : par->parameterid); - length = (unsigned short) (dd.bswap ? bswap2u (par->length) : par->length); + length = (uint16_t) (dd.bswap ? bswap2u (par->length) : par->length); if (pid == PID_SENTINEL) { /* Sentinel terminates list, the length is ignored, DDSI 9.4.2.11. */ - DDS_LOG(DDS_LC_PLIST, "%4x PID %x\n", (unsigned) (pl - src->buf), pid); + DDS_LOG(DDS_LC_PLIST, "%4"PRIx32" PID %"PRIx16"\n", (uint32_t) (pl - src->buf), pid); if ((res = final_validation (dest, src->protocol_version, src->vendorid)) < 0) { nn_plist_fini (dest); @@ -2433,16 +2385,16 @@ dds_return_t nn_plist_init_frommsg return 0; } } - if (length > src->bufsz - sizeof (*par) - (unsigned) (pl - src->buf)) + if (length > src->bufsz - sizeof (*par) - (uint32_t) (pl - src->buf)) { - DDS_WARNING("plist(vendor %u.%u): parameter length %u out of bounds\n", + DDS_WARNING("plist(vendor %u.%u): parameter length %"PRIu16" out of bounds\n", src->vendorid.id[0], src->vendorid.id[1], length); nn_plist_fini (dest); return DDS_RETCODE_BAD_PARAMETER; } if ((length % 4) != 0) /* DDSI 9.4.2.11 */ { - DDS_WARNING("plist(vendor %u.%u): parameter length %u mod 4 != 0\n", + DDS_WARNING("plist(vendor %u.%u): parameter length %"PRIu16" mod 4 != 0\n", src->vendorid.id[0], src->vendorid.id[1], length); nn_plist_fini (dest); return DDS_RETCODE_BAD_PARAMETER; @@ -2450,7 +2402,7 @@ dds_return_t nn_plist_init_frommsg if (dds_get_log_mask() & DDS_LC_PLIST) { - DDS_LOG(DDS_LC_PLIST, "%4x PID %x len %u ", (unsigned) (pl - src->buf), pid, length); + DDS_LOG(DDS_LC_PLIST, "%4"PRIx32" PID %"PRIx16" len %"PRIu16" ", (uint32_t) (pl - src->buf), pid, length); log_octetseq(DDS_LC_PLIST, length, (const unsigned char *) (par + 1)); DDS_LOG(DDS_LC_PLIST, "\n"); } @@ -2460,7 +2412,7 @@ dds_return_t nn_plist_init_frommsg if ((res = init_one_parameter (dest, &dest_tmp, pwanted, qwanted, pid, &dd)) < 0) { /* make sure we print a trace message on error */ - DDS_TRACE("plist(vendor %u.%u): failed at pid=%u\n", src->vendorid.id[0], src->vendorid.id[1], pid); + DDS_TRACE("plist(vendor %u.%u): failed at pid=%"PRIx16"\n", src->vendorid.id[0], src->vendorid.id[1], pid); nn_plist_fini (dest); return res; } @@ -2535,13 +2487,13 @@ unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn return (unsigned char *) pl; if (length > src->bufsz - (size_t)(pl - src->buf)) { - DDS_WARNING("plist(vendor %u.%u): quickscan: parameter length %u out of bounds\n", + DDS_WARNING("plist(vendor %u.%u): quickscan: parameter length %"PRIu16" out of bounds\n", src->vendorid.id[0], src->vendorid.id[1], length); return NULL; } if ((length % 4) != 0) /* DDSI 9.4.2.11 */ { - DDS_WARNING("plist(vendor %u.%u): quickscan: parameter length %u mod 4 != 0\n", + DDS_WARNING("plist(vendor %u.%u): quickscan: parameter length %"PRIu16" mod 4 != 0\n", src->vendorid.id[0], src->vendorid.id[1], length); return NULL; } @@ -2558,8 +2510,8 @@ unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn } else { - unsigned stinfo = fromBE4u (*((unsigned *) pl)); - unsigned stinfox = (length < 8 || !vendor_is_eclipse_or_opensplice(src->vendorid)) ? 0 : fromBE4u (*((unsigned *) pl + 1)); + uint32_t stinfo = fromBE4u (*((uint32_t *) pl)); + uint32_t stinfox = (length < 8 || !vendor_is_eclipse_or_opensplice(src->vendorid)) ? 0 : fromBE4u (*((uint32_t *) pl + 1)); #if (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER) != 3 #error "expected dispose/unregister to be in lowest 2 bits" #endif @@ -2569,7 +2521,7 @@ unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn } break; default: - DDS_LOG(DDS_LC_PLIST, "(pid=%x complex_qos=1)", pid); + DDS_LOG(DDS_LC_PLIST, "(pid=%"PRIx16" complex_qos=1)", pid); dest->complex_qos = 1; break; } @@ -2582,7 +2534,7 @@ unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn return NULL; } -void nn_xqos_init_empty (nn_xqos_t *dest) +void nn_xqos_init_empty (dds_qos_t *dest) { #ifndef NDEBUG memset (dest, 0, sizeof (*dest)); @@ -2597,7 +2549,7 @@ void nn_plist_init_default_participant (nn_plist_t *plist) plist->qos.entity_factory.autoenable_created_entities = 0; } -static void xqos_init_default_common (nn_xqos_t *xqos) +static void xqos_init_default_common (dds_qos_t *xqos) { nn_xqos_init_empty (xqos); @@ -2606,72 +2558,62 @@ static void xqos_init_default_common (nn_xqos_t *xqos) xqos->partition.strs = NULL; xqos->present |= QP_PRESENTATION; - xqos->presentation.access_scope = NN_INSTANCE_PRESENTATION_QOS; + xqos->presentation.access_scope = DDS_PRESENTATION_INSTANCE; xqos->presentation.coherent_access = 0; xqos->presentation.ordered_access = 0; xqos->present |= QP_DURABILITY; - xqos->durability.kind = NN_VOLATILE_DURABILITY_QOS; + xqos->durability.kind = DDS_DURABILITY_VOLATILE; xqos->present |= QP_DEADLINE; - xqos->deadline.deadline = nn_to_ddsi_duration (T_NEVER); + xqos->deadline.deadline = T_NEVER; xqos->present |= QP_LATENCY_BUDGET; - xqos->latency_budget.duration = nn_to_ddsi_duration (0); + xqos->latency_budget.duration = 0; xqos->present |= QP_LIVELINESS; - xqos->liveliness.kind = NN_AUTOMATIC_LIVELINESS_QOS; - xqos->liveliness.lease_duration = nn_to_ddsi_duration (T_NEVER); + xqos->liveliness.kind = DDS_LIVELINESS_AUTOMATIC; + xqos->liveliness.lease_duration = T_NEVER; xqos->present |= QP_DESTINATION_ORDER; - xqos->destination_order.kind = NN_BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS; + xqos->destination_order.kind = DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP; xqos->present |= QP_HISTORY; - xqos->history.kind = NN_KEEP_LAST_HISTORY_QOS; + xqos->history.kind = DDS_HISTORY_KEEP_LAST; xqos->history.depth = 1; xqos->present |= QP_RESOURCE_LIMITS; - xqos->resource_limits.max_samples = NN_DDS_LENGTH_UNLIMITED; - xqos->resource_limits.max_instances = NN_DDS_LENGTH_UNLIMITED; - xqos->resource_limits.max_samples_per_instance = NN_DDS_LENGTH_UNLIMITED; + xqos->resource_limits.max_samples = DDS_LENGTH_UNLIMITED; + xqos->resource_limits.max_instances = DDS_LENGTH_UNLIMITED; + xqos->resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED; xqos->present |= QP_TRANSPORT_PRIORITY; xqos->transport_priority.value = 0; xqos->present |= QP_OWNERSHIP; - xqos->ownership.kind = NN_SHARED_OWNERSHIP_QOS; - - xqos->present |= QP_PRISMTECH_RELAXED_QOS_MATCHING; - xqos->relaxed_qos_matching.value = 0; - - xqos->present |= QP_PRISMTECH_SYNCHRONOUS_ENDPOINT; - xqos->synchronous_endpoint.value = 0; + xqos->ownership.kind = DDS_OWNERSHIP_SHARED; xqos->present |= QP_CYCLONE_IGNORELOCAL; - xqos->ignorelocal.value = NN_NONE_IGNORELOCAL_QOS; + xqos->ignorelocal.value = DDS_IGNORELOCAL_NONE; } -void nn_xqos_init_default_reader (nn_xqos_t *xqos) +void nn_xqos_init_default_reader (dds_qos_t *xqos) { xqos_init_default_common (xqos); xqos->present |= QP_RELIABILITY; - xqos->reliability.kind = NN_BEST_EFFORT_RELIABILITY_QOS; + xqos->reliability.kind = DDS_RELIABILITY_BEST_EFFORT; xqos->present |= QP_TIME_BASED_FILTER; - xqos->time_based_filter.minimum_separation = nn_to_ddsi_duration (0); + xqos->time_based_filter.minimum_separation = 0; xqos->present |= QP_PRISMTECH_READER_DATA_LIFECYCLE; - xqos->reader_data_lifecycle.autopurge_nowriter_samples_delay = nn_to_ddsi_duration (T_NEVER); - xqos->reader_data_lifecycle.autopurge_disposed_samples_delay = nn_to_ddsi_duration (T_NEVER); - xqos->reader_data_lifecycle.autopurge_dispose_all = 0; - xqos->reader_data_lifecycle.enable_invalid_samples = 1; - xqos->reader_data_lifecycle.invalid_sample_visibility = NN_MINIMUM_INVALID_SAMPLE_VISIBILITY_QOS; + xqos->reader_data_lifecycle.autopurge_nowriter_samples_delay = T_NEVER; + xqos->reader_data_lifecycle.autopurge_disposed_samples_delay = T_NEVER; xqos->present |= QP_PRISMTECH_READER_LIFESPAN; xqos->reader_lifespan.use_lifespan = 0; - xqos->reader_lifespan.duration = nn_to_ddsi_duration (T_NEVER); - + xqos->reader_lifespan.duration = T_NEVER; xqos->present |= QP_PRISMTECH_SUBSCRIPTION_KEYS; xqos->subscription_keys.use_key_list = 0; @@ -2679,21 +2621,21 @@ void nn_xqos_init_default_reader (nn_xqos_t *xqos) xqos->subscription_keys.key_list.strs = NULL; } -void nn_xqos_init_default_writer (nn_xqos_t *xqos) +void nn_xqos_init_default_writer (dds_qos_t *xqos) { xqos_init_default_common (xqos); xqos->present |= QP_DURABILITY_SERVICE; - xqos->durability_service.service_cleanup_delay = nn_to_ddsi_duration (0); - xqos->durability_service.history.kind = NN_KEEP_LAST_HISTORY_QOS; + xqos->durability_service.service_cleanup_delay = 0; + xqos->durability_service.history.kind = DDS_HISTORY_KEEP_LAST; xqos->durability_service.history.depth = 1; - xqos->durability_service.resource_limits.max_samples = NN_DDS_LENGTH_UNLIMITED; - xqos->durability_service.resource_limits.max_instances = NN_DDS_LENGTH_UNLIMITED; - xqos->durability_service.resource_limits.max_samples_per_instance = NN_DDS_LENGTH_UNLIMITED; + xqos->durability_service.resource_limits.max_samples = DDS_LENGTH_UNLIMITED; + xqos->durability_service.resource_limits.max_instances = DDS_LENGTH_UNLIMITED; + xqos->durability_service.resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED; xqos->present |= QP_RELIABILITY; - xqos->reliability.kind = NN_RELIABLE_RELIABILITY_QOS; - xqos->reliability.max_blocking_time = nn_to_ddsi_duration (100 * T_MILLISECOND); + xqos->reliability.kind = DDS_RELIABILITY_RELIABLE; + xqos->reliability.max_blocking_time = 100 * T_MILLISECOND; xqos->present |= QP_OWNERSHIP_STRENGTH; xqos->ownership_strength.value = 0; @@ -2702,41 +2644,39 @@ void nn_xqos_init_default_writer (nn_xqos_t *xqos) xqos->transport_priority.value = 0; xqos->present |= QP_LIFESPAN; - xqos->lifespan.duration = nn_to_ddsi_duration (T_NEVER); + xqos->lifespan.duration = T_NEVER; xqos->present |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE; xqos->writer_data_lifecycle.autodispose_unregistered_instances = 1; - xqos->writer_data_lifecycle.autounregister_instance_delay = nn_to_ddsi_duration (T_NEVER); - xqos->writer_data_lifecycle.autopurge_suspended_samples_delay = nn_to_ddsi_duration (T_NEVER); } -void nn_xqos_init_default_writer_noautodispose (nn_xqos_t *xqos) +void nn_xqos_init_default_writer_noautodispose (dds_qos_t *xqos) { nn_xqos_init_default_writer (xqos); xqos->writer_data_lifecycle.autodispose_unregistered_instances = 0; } -void nn_xqos_init_default_topic (nn_xqos_t *xqos) +void nn_xqos_init_default_topic (dds_qos_t *xqos) { xqos_init_default_common (xqos); xqos->present |= QP_DURABILITY_SERVICE; - xqos->durability_service.service_cleanup_delay = nn_to_ddsi_duration (0); - xqos->durability_service.history.kind = NN_KEEP_LAST_HISTORY_QOS; + xqos->durability_service.service_cleanup_delay = 0; + xqos->durability_service.history.kind = DDS_HISTORY_KEEP_LAST; xqos->durability_service.history.depth = 1; - xqos->durability_service.resource_limits.max_samples = NN_DDS_LENGTH_UNLIMITED; - xqos->durability_service.resource_limits.max_instances = NN_DDS_LENGTH_UNLIMITED; - xqos->durability_service.resource_limits.max_samples_per_instance = NN_DDS_LENGTH_UNLIMITED; + xqos->durability_service.resource_limits.max_samples = DDS_LENGTH_UNLIMITED; + xqos->durability_service.resource_limits.max_instances = DDS_LENGTH_UNLIMITED; + xqos->durability_service.resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED; xqos->present |= QP_RELIABILITY; - xqos->reliability.kind = NN_BEST_EFFORT_RELIABILITY_QOS; - xqos->reliability.max_blocking_time = nn_to_ddsi_duration (100 * T_MILLISECOND); + xqos->reliability.kind = DDS_RELIABILITY_BEST_EFFORT; + xqos->reliability.max_blocking_time = 100 * T_MILLISECOND; xqos->present |= QP_TRANSPORT_PRIORITY; xqos->transport_priority.value = 0; xqos->present |= QP_LIFESPAN; - xqos->lifespan.duration = nn_to_ddsi_duration (T_NEVER); + xqos->lifespan.duration = T_NEVER; xqos->present |= QP_PRISMTECH_SUBSCRIPTION_KEYS; xqos->subscription_keys.use_key_list = 0; @@ -2744,7 +2684,7 @@ void nn_xqos_init_default_topic (nn_xqos_t *xqos) xqos->subscription_keys.key_list.strs = NULL; } -void nn_xqos_init_default_subscriber (nn_xqos_t *xqos) +void nn_xqos_init_default_subscriber (dds_qos_t *xqos) { nn_xqos_init_empty (xqos); @@ -2757,7 +2697,7 @@ void nn_xqos_init_default_subscriber (nn_xqos_t *xqos) xqos->partition.strs = NULL; } -void nn_xqos_init_default_publisher (nn_xqos_t *xqos) +void nn_xqos_init_default_publisher (dds_qos_t *xqos) { nn_xqos_init_empty (xqos); @@ -2769,7 +2709,7 @@ void nn_xqos_init_default_publisher (nn_xqos_t *xqos) xqos->partition.strs = NULL; } -void nn_xqos_mergein_missing (nn_xqos_t *a, const nn_xqos_t *b) +void nn_xqos_mergein_missing (dds_qos_t *a, const dds_qos_t *b) { /* Adds QoS's from B to A (duplicating memory) (only those not present in A, obviously) */ @@ -2799,10 +2739,8 @@ void nn_xqos_mergein_missing (nn_xqos_t *a, const nn_xqos_t *b) CQ (TIME_BASED_FILTER, time_based_filter); CQ (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle); CQ (PRISMTECH_WRITER_DATA_LIFECYCLE, writer_data_lifecycle); - CQ (PRISMTECH_RELAXED_QOS_MATCHING, relaxed_qos_matching); CQ (PRISMTECH_READER_LIFESPAN, reader_lifespan); CQ (PRISMTECH_ENTITY_FACTORY, entity_factory); - CQ (PRISMTECH_SYNCHRONOUS_ENDPOINT, synchronous_endpoint); CQ (CYCLONE_IGNORELOCAL, ignorelocal); #undef CQ @@ -2818,12 +2756,12 @@ void nn_xqos_mergein_missing (nn_xqos_t *a, const nn_xqos_t *b) a->present |= QP_##fl_; \ } \ } while (0) - CQ (GROUP_DATA, group_data, octetseq, nn_octetseq_t); - CQ (TOPIC_DATA, topic_data, octetseq, nn_octetseq_t); - CQ (USER_DATA, user_data, octetseq, nn_octetseq_t); + CQ (GROUP_DATA, group_data, octetseq, ddsi_octetseq_t); + CQ (TOPIC_DATA, topic_data, octetseq, ddsi_octetseq_t); + CQ (USER_DATA, user_data, octetseq, ddsi_octetseq_t); CQ (TOPIC_NAME, topic_name, string, char *); CQ (TYPE_NAME, type_name, string, char *); - CQ (RTI_TYPECODE, rti_typecode, octetseq, nn_octetseq_t); + CQ (RTI_TYPECODE, rti_typecode, octetseq, ddsi_octetseq_t); #undef CQ if (!(a->present & QP_PRISMTECH_SUBSCRIPTION_KEYS) && (b->present & QP_PRISMTECH_SUBSCRIPTION_KEYS)) { @@ -2838,13 +2776,13 @@ void nn_xqos_mergein_missing (nn_xqos_t *a, const nn_xqos_t *b) } } -void nn_xqos_copy (nn_xqos_t *dst, const nn_xqos_t *src) +void nn_xqos_copy (dds_qos_t *dst, const dds_qos_t *src) { nn_xqos_init_empty (dst); nn_xqos_mergein_missing (dst, src); } -void nn_xqos_unalias (nn_xqos_t *xqos) +void nn_xqos_unalias (dds_qos_t *xqos) { DDS_LOG(DDS_LC_PLIST, "NN_XQOS_UNALIAS\n"); #define Q(name_, func_, field_) do { \ @@ -2865,20 +2803,19 @@ void nn_xqos_unalias (nn_xqos_t *xqos) assert (xqos->aliased == 0); } -void nn_xqos_fini (nn_xqos_t *xqos) +void nn_xqos_fini (dds_qos_t *xqos) { struct t { uint64_t fl; size_t off; }; static const struct t qos_simple[] = { - { QP_GROUP_DATA, offsetof (nn_xqos_t, group_data.value) }, - { QP_TOPIC_DATA, offsetof (nn_xqos_t, topic_data.value) }, - { QP_USER_DATA, offsetof (nn_xqos_t, user_data.value) }, - { QP_TOPIC_NAME, offsetof (nn_xqos_t, topic_name) }, - { QP_TYPE_NAME, offsetof (nn_xqos_t, type_name) }, - { QP_RTI_TYPECODE, offsetof (nn_xqos_t, rti_typecode.value) } + { QP_GROUP_DATA, offsetof (dds_qos_t, group_data.value) }, + { QP_TOPIC_DATA, offsetof (dds_qos_t, topic_data.value) }, + { QP_USER_DATA, offsetof (dds_qos_t, user_data.value) }, + { QP_TOPIC_NAME, offsetof (dds_qos_t, topic_name) }, + { QP_TYPE_NAME, offsetof (dds_qos_t, type_name) }, + { QP_RTI_TYPECODE, offsetof (dds_qos_t, rti_typecode.value) } }; - int i; DDS_LOG(DDS_LC_PLIST, "NN_XQOS_FINI\n"); - for (i = 0; i < (int) (sizeof (qos_simple) / sizeof (*qos_simple)); i++) + for (size_t i = 0; i < sizeof (qos_simple) / sizeof (*qos_simple); i++) { if ((xqos->present & qos_simple[i].fl) && !(xqos->aliased & qos_simple[i].fl)) { @@ -2914,27 +2851,22 @@ void nn_xqos_fini (nn_xqos_t *xqos) xqos->present = 0; } -nn_xqos_t * nn_xqos_dup (const nn_xqos_t *src) +dds_qos_t * nn_xqos_dup (const dds_qos_t *src) { - nn_xqos_t *dst = ddsrt_malloc (sizeof (*dst)); + dds_qos_t *dst = ddsrt_malloc (sizeof (*dst)); nn_xqos_copy (dst, src); assert (dst->aliased == 0); return dst; } -static int octetseqs_differ (const nn_octetseq_t *a, const nn_octetseq_t *b) +static int octetseqs_differ (const ddsi_octetseq_t *a, const ddsi_octetseq_t *b) { return (a->length != b->length || memcmp (a->value, b->value, a->length) != 0); } -static int durations_differ (const nn_duration_t *a, const nn_duration_t *b) +static int stringseqs_differ (const ddsi_stringseq_t *a, const ddsi_stringseq_t *b) { - return (a->seconds != b->seconds || a->fraction != b->fraction); -} - -static int stringseqs_differ (const nn_stringseq_t *a, const nn_stringseq_t *b) -{ - unsigned i; + uint32_t i; if (a->n != b->n) return 1; for (i = 0; i < a->n; i++) @@ -2943,29 +2875,29 @@ static int stringseqs_differ (const nn_stringseq_t *a, const nn_stringseq_t *b) return 0; } -static int histories_differ (const nn_history_qospolicy_t *a, const nn_history_qospolicy_t *b) +static int histories_differ (const dds_history_qospolicy_t *a, const dds_history_qospolicy_t *b) { - return (a->kind != b->kind || (a->kind == NN_KEEP_LAST_HISTORY_QOS && a->depth != b->depth)); + return (a->kind != b->kind || (a->kind == DDS_HISTORY_KEEP_LAST && a->depth != b->depth)); } -static int resource_limits_differ (const nn_resource_limits_qospolicy_t *a, const nn_resource_limits_qospolicy_t *b) +static int resource_limits_differ (const dds_resource_limits_qospolicy_t *a, const dds_resource_limits_qospolicy_t *b) { return (a->max_samples != b->max_samples || a->max_instances != b->max_instances || a->max_samples_per_instance != b->max_samples_per_instance); } -static int partition_is_default (const nn_partition_qospolicy_t *a) +static int partition_is_default (const dds_partition_qospolicy_t *a) { - unsigned i; + uint32_t i; for (i = 0; i < a->n; i++) if (strcmp (a->strs[i], "") != 0) return 0; return 1; } -static int partitions_equal_n2 (const nn_partition_qospolicy_t *a, const nn_partition_qospolicy_t *b) +static int partitions_equal_n2 (const dds_partition_qospolicy_t *a, const dds_partition_qospolicy_t *b) { - unsigned i, j; + uint32_t i, j; for (i = 0; i < a->n; i++) { for (j = 0; j < b->n; j++) @@ -2977,22 +2909,27 @@ static int partitions_equal_n2 (const nn_partition_qospolicy_t *a, const nn_part return 1; } -static int partitions_equal_nlogn (const nn_partition_qospolicy_t *a, const nn_partition_qospolicy_t *b) +static int strcmp_wrapper (const void *a, const void *b) +{ + return strcmp (a, b); +} + +static int partitions_equal_nlogn (const dds_partition_qospolicy_t *a, const dds_partition_qospolicy_t *b) { char *statictab[8], **tab; int equal = 1; - unsigned i; + uint32_t i; - if (a->n <= (int) (sizeof (statictab) / sizeof (*statictab))) + if (a->n <= sizeof (statictab) / sizeof (*statictab)) tab = statictab; else tab = ddsrt_malloc (a->n * sizeof (*tab)); for (i = 0; i < a->n; i++) tab[i] = a->strs[i]; - qsort (tab, a->n, sizeof (*tab), (int (*) (const void *, const void *)) strcmp); + qsort (tab, a->n, sizeof (*tab), strcmp_wrapper); for (i = 0; i < b->n; i++) - if (bsearch (b->strs[i], tab, a->n, sizeof (*tab), (int (*) (const void *, const void *)) strcmp) == NULL) + if (bsearch (b->strs[i], tab, a->n, sizeof (*tab), strcmp_wrapper) == NULL) { equal = 0; break; @@ -3002,7 +2939,7 @@ static int partitions_equal_nlogn (const nn_partition_qospolicy_t *a, const nn_p return equal; } -static int partitions_equal (const nn_partition_qospolicy_t *a, const nn_partition_qospolicy_t *b) +static int partitions_equal (const dds_partition_qospolicy_t *a, const dds_partition_qospolicy_t *b) { /* Return true iff (the set a->strs) equals (the set b->strs); that is, order doesn't matter. One could argue that "**" and "*" are @@ -3023,7 +2960,7 @@ static int partitions_equal (const nn_partition_qospolicy_t *a, const nn_partiti assuming that |A| >= |B|. */ if (a->n < b->n) { - const nn_partition_qospolicy_t *x = a; + const dds_partition_qospolicy_t *x = a; a = b; b = x; } @@ -3040,7 +2977,7 @@ static int partitions_equal (const nn_partition_qospolicy_t *a, const nn_partiti } } -uint64_t nn_xqos_delta (const nn_xqos_t *a, const nn_xqos_t *b, uint64_t mask) +uint64_t nn_xqos_delta (const dds_qos_t *a, const dds_qos_t *b, uint64_t mask) { /* Returns QP_... set for RxO settings where a differs from b; if present in a but not in b (or in b but not in a) it counts as a @@ -3079,29 +3016,27 @@ uint64_t nn_xqos_delta (const nn_xqos_t *a, const nn_xqos_t *b, uint64_t mask) } if (check & QP_DURABILITY_SERVICE) { - const nn_durability_service_qospolicy_t *qa = &a->durability_service; - const nn_durability_service_qospolicy_t *qb = &b->durability_service; - if (durations_differ (&qa->service_cleanup_delay, &qb->service_cleanup_delay) || + const dds_durability_service_qospolicy_t *qa = &a->durability_service; + const dds_durability_service_qospolicy_t *qb = &b->durability_service; + if (qa->service_cleanup_delay != qb->service_cleanup_delay || histories_differ (&qa->history, &qb->history) || resource_limits_differ (&qa->resource_limits, &qb->resource_limits)) delta |= QP_DURABILITY_SERVICE; } if (check & QP_DEADLINE) { - if (durations_differ (&a->deadline.deadline, &b->deadline.deadline)) + if (a->deadline.deadline != b->deadline.deadline) delta |= QP_DEADLINE; } if (check & QP_LATENCY_BUDGET) { - if (durations_differ (&a->latency_budget.duration, &b->latency_budget.duration)) + if (a->latency_budget.duration != b->latency_budget.duration) delta |= QP_LATENCY_BUDGET; } if (check & QP_LIVELINESS) { - if (a->liveliness.kind != b->liveliness.kind || - durations_differ (&a->liveliness.lease_duration, &b->liveliness.lease_duration)) + if (a->liveliness.kind != b->liveliness.kind || a->liveliness.lease_duration != b->liveliness.lease_duration) delta |= QP_LIVELINESS; } if (check & QP_RELIABILITY) { - if (a->reliability.kind != b->reliability.kind || - durations_differ (&a->reliability.max_blocking_time, &b->reliability.max_blocking_time)) + if (a->reliability.kind != b->reliability.kind || a->reliability.max_blocking_time != b->reliability.max_blocking_time) delta |= QP_RELIABILITY; } if (check & QP_DESTINATION_ORDER) { @@ -3121,7 +3056,7 @@ uint64_t nn_xqos_delta (const nn_xqos_t *a, const nn_xqos_t *b, uint64_t mask) delta |= QP_TRANSPORT_PRIORITY; } if (check & QP_LIFESPAN) { - if (durations_differ (&a->lifespan.duration, &b->lifespan.duration)) + if (a->lifespan.duration != b->lifespan.duration) delta |= QP_LIFESPAN; } if (check & QP_USER_DATA) { @@ -3137,38 +3072,24 @@ uint64_t nn_xqos_delta (const nn_xqos_t *a, const nn_xqos_t *b, uint64_t mask) delta |= QP_OWNERSHIP_STRENGTH; } if (check & QP_TIME_BASED_FILTER) { - if (durations_differ (&a->time_based_filter.minimum_separation, &b->time_based_filter.minimum_separation)) + if (a->time_based_filter.minimum_separation != b->time_based_filter.minimum_separation) delta |= QP_TIME_BASED_FILTER; } if (check & QP_PRISMTECH_READER_DATA_LIFECYCLE) { - if (durations_differ (&a->reader_data_lifecycle.autopurge_disposed_samples_delay, - &b->reader_data_lifecycle.autopurge_disposed_samples_delay) || - durations_differ (&a->reader_data_lifecycle.autopurge_nowriter_samples_delay, - &b->reader_data_lifecycle.autopurge_nowriter_samples_delay) || - a->reader_data_lifecycle.autopurge_dispose_all != b->reader_data_lifecycle.autopurge_dispose_all || - a->reader_data_lifecycle.enable_invalid_samples != b->reader_data_lifecycle.enable_invalid_samples || - a->reader_data_lifecycle.invalid_sample_visibility != b->reader_data_lifecycle.invalid_sample_visibility) + if (a->reader_data_lifecycle.autopurge_disposed_samples_delay != b->reader_data_lifecycle.autopurge_disposed_samples_delay || + a->reader_data_lifecycle.autopurge_nowriter_samples_delay != b->reader_data_lifecycle.autopurge_nowriter_samples_delay) delta |= QP_PRISMTECH_READER_DATA_LIFECYCLE; } if (check & QP_PRISMTECH_WRITER_DATA_LIFECYCLE) { if (a->writer_data_lifecycle.autodispose_unregistered_instances != - b->writer_data_lifecycle.autodispose_unregistered_instances || - durations_differ (&a->writer_data_lifecycle.autopurge_suspended_samples_delay, - &b->writer_data_lifecycle.autopurge_suspended_samples_delay) || - durations_differ (&a->writer_data_lifecycle.autounregister_instance_delay, - &b->writer_data_lifecycle.autounregister_instance_delay)) + b->writer_data_lifecycle.autodispose_unregistered_instances) delta |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE; } - if (check & QP_PRISMTECH_RELAXED_QOS_MATCHING) { - if (a->relaxed_qos_matching.value != - b->relaxed_qos_matching.value) - delta |= QP_PRISMTECH_RELAXED_QOS_MATCHING; - } if (check & QP_PRISMTECH_READER_LIFESPAN) { /* Note: the conjunction need not test both a & b for having use_lifespan set */ if (a->reader_lifespan.use_lifespan != b->reader_lifespan.use_lifespan || (a->reader_lifespan.use_lifespan && b->reader_lifespan.use_lifespan && - durations_differ (&a->reader_lifespan.duration, &b->reader_lifespan.duration))) + a->reader_lifespan.duration != b->reader_lifespan.duration)) delta |= QP_PRISMTECH_READER_LIFESPAN; } if (check & QP_PRISMTECH_SUBSCRIPTION_KEYS) { @@ -3183,10 +3104,6 @@ uint64_t nn_xqos_delta (const nn_xqos_t *a, const nn_xqos_t *b, uint64_t mask) b->entity_factory.autoenable_created_entities) delta |= QP_PRISMTECH_ENTITY_FACTORY; } - if (check & QP_PRISMTECH_SYNCHRONOUS_ENDPOINT) { - if (a->synchronous_endpoint.value != b->synchronous_endpoint.value) - delta |= QP_PRISMTECH_SYNCHRONOUS_ENDPOINT; - } if (check & QP_RTI_TYPECODE) { if (octetseqs_differ (&a->rti_typecode, &b->rti_typecode)) delta |= QP_RTI_TYPECODE; @@ -3200,17 +3117,17 @@ uint64_t nn_xqos_delta (const nn_xqos_t *a, const nn_xqos_t *b, uint64_t mask) /*************************/ -void nn_xqos_addtomsg (struct nn_xmsg *m, const nn_xqos_t *xqos, uint64_t wanted) +void nn_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, uint64_t wanted) { /* Returns new nn_xmsg pointer (currently, reallocs may happen) */ uint64_t w = xqos->present & wanted; char *tmp; -#define SIMPLE(name_, field_) \ +#define SIMPLE(name_, prefix_, field_) \ do { \ if (w & QP_##name_) { \ tmp = nn_xmsg_addpar (m, PID_##name_, sizeof (xqos->field_)); \ - *((nn_##field_##_qospolicy_t *) tmp) = xqos->field_; \ + *((prefix_##_##field_##_qospolicy_t *) tmp) = xqos->field_; \ } \ } while (0) #define FUNC_BY_REF(name_, field_, func_) \ @@ -3228,32 +3145,30 @@ void nn_xqos_addtomsg (struct nn_xmsg *m, const nn_xqos_t *xqos, uint64_t wanted FUNC_BY_VAL (TOPIC_NAME, topic_name, string); FUNC_BY_VAL (TYPE_NAME, type_name, string); - SIMPLE (PRESENTATION, presentation); + SIMPLE (PRESENTATION, dds, presentation); FUNC_BY_REF (PARTITION, partition, stringseq); FUNC_BY_REF (GROUP_DATA, group_data, octetseq); FUNC_BY_REF (TOPIC_DATA, topic_data, octetseq); - SIMPLE (DURABILITY, durability); - SIMPLE (DURABILITY_SERVICE, durability_service); - SIMPLE (DEADLINE, deadline); - SIMPLE (LATENCY_BUDGET, latency_budget); - SIMPLE (LIVELINESS, liveliness); + SIMPLE (DURABILITY, dds, durability); + FUNC_BY_REF (DURABILITY_SERVICE, durability_service, durability_service); + FUNC_BY_VAL (DEADLINE, deadline.deadline, duration); + FUNC_BY_VAL (LATENCY_BUDGET, latency_budget.duration, duration); + FUNC_BY_REF (LIVELINESS, liveliness, liveliness); FUNC_BY_REF (RELIABILITY, reliability, reliability); - SIMPLE (DESTINATION_ORDER, destination_order); - SIMPLE (HISTORY, history); - SIMPLE (RESOURCE_LIMITS, resource_limits); - SIMPLE (TRANSPORT_PRIORITY, transport_priority); - SIMPLE (LIFESPAN, lifespan); + SIMPLE (DESTINATION_ORDER, dds, destination_order); + SIMPLE (HISTORY, dds, history); + SIMPLE (RESOURCE_LIMITS, dds, resource_limits); + SIMPLE (TRANSPORT_PRIORITY, dds, transport_priority); + FUNC_BY_VAL (LIFESPAN, lifespan.duration, duration); FUNC_BY_REF (USER_DATA, user_data, octetseq); - SIMPLE (OWNERSHIP, ownership); - SIMPLE (OWNERSHIP_STRENGTH, ownership_strength); - SIMPLE (TIME_BASED_FILTER, time_based_filter); - SIMPLE (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle); - SIMPLE (PRISMTECH_WRITER_DATA_LIFECYCLE, writer_data_lifecycle); - SIMPLE (PRISMTECH_RELAXED_QOS_MATCHING, relaxed_qos_matching); - SIMPLE (PRISMTECH_READER_LIFESPAN, reader_lifespan); + SIMPLE (OWNERSHIP, dds, ownership); + SIMPLE (OWNERSHIP_STRENGTH, dds, ownership_strength); + FUNC_BY_VAL (TIME_BASED_FILTER, time_based_filter.minimum_separation, duration); + FUNC_BY_REF (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle, reader_data_lifecycle); + SIMPLE (PRISMTECH_WRITER_DATA_LIFECYCLE, dds, writer_data_lifecycle); + FUNC_BY_REF (PRISMTECH_READER_LIFESPAN, reader_lifespan, reader_lifespan); FUNC_BY_REF (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys, subscription_keys); - SIMPLE (PRISMTECH_ENTITY_FACTORY, entity_factory); - SIMPLE (PRISMTECH_SYNCHRONOUS_ENDPOINT, synchronous_endpoint); + SIMPLE (PRISMTECH_ENTITY_FACTORY, dds, entity_factory); FUNC_BY_REF (RTI_TYPECODE, rti_typecode, octetseq); /* CYCLONE_IGNORELOCAL is not visible on the wire */ #undef FUNC_BY_REF @@ -3261,7 +3176,7 @@ void nn_xqos_addtomsg (struct nn_xmsg *m, const nn_xqos_t *xqos, uint64_t wanted #undef SIMPLE } -static void add_locators (struct nn_xmsg *m, uint64_t present, uint64_t flag, const nn_locators_t *ls, unsigned pid) +static void add_locators (struct nn_xmsg *m, uint64_t present, uint64_t flag, const nn_locators_t *ls, nn_parameterid_t pid) { const struct nn_locators_one *l; if (present & flag) @@ -3313,7 +3228,7 @@ void nn_plist_addtomsg (struct nn_xmsg *m, const nn_plist_t *ps, uint64_t pwante add_locators (m, ps->present, PP_METATRAFFIC_MULTICAST_LOCATOR, &ps->metatraffic_multicast_locators, PID_METATRAFFIC_MULTICAST_LOCATOR); SIMPLE_TYPE (EXPECTS_INLINE_QOS, expects_inline_qos, unsigned char); - SIMPLE_TYPE (PARTICIPANT_LEASE_DURATION, participant_lease_duration, nn_duration_t); + FUNC_BY_VAL (PARTICIPANT_LEASE_DURATION, participant_lease_duration, duration); FUNC_BY_REF (PARTICIPANT_GUID, participant_guid, guid); SIMPLE_TYPE (BUILTIN_ENDPOINT_SET, builtin_endpoint_set, unsigned); SIMPLE_TYPE (KEYHASH, keyhash, nn_keyhash_t); @@ -3349,21 +3264,21 @@ void nn_plist_addtomsg (struct nn_xmsg *m, const nn_plist_t *ps, uint64_t pwante /*************************/ -static unsigned isprint_runlen (unsigned n, const unsigned char *xs) +static uint32_t isprint_runlen (uint32_t n, const unsigned char *xs) { - unsigned m; + uint32_t m; for (m = 0; m < n && xs[m] != '"' && isprint (xs[m]); m++) ; return m; } -static void log_octetseq (uint32_t cat, unsigned n, const unsigned char *xs) +static void log_octetseq (uint32_t cat, uint32_t n, const unsigned char *xs) { - unsigned i = 0; + uint32_t i = 0; while (i < n) { - unsigned m = isprint_runlen(n - i, xs); + uint32_t m = isprint_runlen(n - i, xs); if (m >= 4) { DDS_LOG(cat, "%s\"%*.*s\"", i == 0 ? "" : ",", m, m, xs); @@ -3383,7 +3298,7 @@ static void log_octetseq (uint32_t cat, unsigned n, const unsigned char *xs) } } -void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos) +void nn_log_xqos (uint32_t cat, const dds_qos_t *xqos) { uint64_t p = xqos->present; const char *prefix = ""; @@ -3395,16 +3310,15 @@ void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos) #define LOGB5(fmt_, arg0_, arg1_, arg2_, arg3_, arg4_) DDS_LOG(cat, "%s" fmt_, prefix, arg0_, arg1_, arg2_, arg3_, arg4_) #define DO(name_, body_) do { if (p & QP_##name_) { { body_ } prefix = ","; } } while (0) -#define FMT_DUR "%d.%09d" -#define PRINTARG_DUR(d) (d).seconds, (int) ((d).fraction/4.294967296) +#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, { LOGB3 ("presentation=%d:%u:%u", xqos->presentation.access_scope, xqos->presentation.coherent_access, xqos->presentation.ordered_access); }); DO (PARTITION, { - unsigned i; LOGB0 ("partition={"); - for (i = 0; i < xqos->partition.n; i++) { + for (uint32_t i = 0; i < xqos->partition.n; i++) { DDS_LOG(cat, "%s%s", (i == 0) ? "" : ",", xqos->partition.strs[i]); } DDS_LOG(cat, "}"); @@ -3443,24 +3357,18 @@ void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos) 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, { LOGB5 ("reader_data_lifecycle="FMT_DUR":"FMT_DUR":%u:%u:%d", PRINTARG_DUR (xqos->reader_data_lifecycle.autopurge_nowriter_samples_delay), PRINTARG_DUR (xqos->reader_data_lifecycle.autopurge_disposed_samples_delay), xqos->reader_data_lifecycle.autopurge_dispose_all, xqos->reader_data_lifecycle.enable_invalid_samples, (int) xqos->reader_data_lifecycle.invalid_sample_visibility); }); + DO (PRISMTECH_READER_DATA_LIFECYCLE, { LOGB2 ("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, { - LOGB3 ("writer_data_lifecycle={%u,"FMT_DUR","FMT_DUR"}", - xqos->writer_data_lifecycle.autodispose_unregistered_instances, - PRINTARG_DUR (xqos->writer_data_lifecycle.autounregister_instance_delay), - PRINTARG_DUR (xqos->writer_data_lifecycle.autopurge_suspended_samples_delay)); }); - DO (PRISMTECH_RELAXED_QOS_MATCHING, { LOGB1 ("relaxed_qos_matching=%u", xqos->relaxed_qos_matching.value); }); + LOGB1 ("writer_data_lifecycle={%u}", xqos->writer_data_lifecycle.autodispose_unregistered_instances); }); DO (PRISMTECH_READER_LIFESPAN, { LOGB2 ("reader_lifespan={%u,"FMT_DUR"}", xqos->reader_lifespan.use_lifespan, PRINTARG_DUR (xqos->reader_lifespan.duration)); }); DO (PRISMTECH_SUBSCRIPTION_KEYS, { - unsigned i; LOGB1 ("subscription_keys={%u,{", xqos->subscription_keys.use_key_list); - for (i = 0; i < xqos->subscription_keys.key_list.n; i++) { + for (uint32_t i = 0; i < xqos->subscription_keys.key_list.n; i++) { DDS_LOG(cat, "%s%s", (i == 0) ? "" : ",", xqos->subscription_keys.key_list.strs[i]); } DDS_LOG(cat, "}}"); }); DO (PRISMTECH_ENTITY_FACTORY, { LOGB1 ("entity_factory=%u", xqos->entity_factory.autoenable_created_entities); }); - DO (PRISMTECH_SYNCHRONOUS_ENDPOINT, { LOGB1 ("synchronous_endpoint=%u", xqos->synchronous_endpoint.value); }); DO (RTI_TYPECODE, { LOGB1 ("rti_typecode=%"PRIu32"<", xqos->rti_typecode.length); log_octetseq (cat, xqos->rti_typecode.length, xqos->rti_typecode.value); diff --git a/src/core/ddsi/src/q_qosmatch.c b/src/core/ddsi/src/q_qosmatch.c index f7ee363..ec2afd1 100644 --- a/src/core/ddsi/src/q_qosmatch.c +++ b/src/core/ddsi/src/q_qosmatch.c @@ -35,7 +35,7 @@ static int partition_patmatch_p (const char *pat, const char *name) return ddsi2_patmatch (pat, name); } -static int partitions_match_default (const nn_xqos_t *x) +static int partitions_match_default (const dds_qos_t *x) { unsigned i; if (!(x->present & QP_PARTITION) || x->partition.n == 0) @@ -46,7 +46,7 @@ static int partitions_match_default (const nn_xqos_t *x) return 0; } -int partitions_match_p (const nn_xqos_t *a, const nn_xqos_t *b) +int partitions_match_p (const dds_qos_t *a, const dds_qos_t *b) { if (!(a->present & QP_PARTITION) || a->partition.n == 0) return partitions_match_default (b); @@ -66,117 +66,74 @@ int partitions_match_p (const nn_xqos_t *a, const nn_xqos_t *b) } } -static int ddsi_duration_is_lt (nn_duration_t a0, nn_duration_t b0) -{ - /* inf counts as <= inf */ - const int64_t a = nn_from_ddsi_duration (a0); - const int64_t b = nn_from_ddsi_duration (b0); - if (a == T_NEVER) - return 0; - else if (b == T_NEVER) - return 1; - else - return a < b; -} +static bool qos_match_internal_p (const dds_qos_t *rd, const dds_qos_t *wr, dds_qos_policy_id_t *reason) ddsrt_nonnull_all; -/* Duplicates of DDS policy ids to avoid inclusion of actual definitions */ - -#define Q_INVALID_QOS_POLICY_ID 0 -#define Q_USERDATA_QOS_POLICY_ID 1 -#define Q_DURABILITY_QOS_POLICY_ID 2 -#define Q_PRESENTATION_QOS_POLICY_ID 3 -#define Q_DEADLINE_QOS_POLICY_ID 4 -#define Q_LATENCYBUDGET_QOS_POLICY_ID 5 -#define Q_OWNERSHIP_QOS_POLICY_ID 6 -#define Q_OWNERSHIPSTRENGTH_QOS_POLICY_ID 7 -#define Q_LIVELINESS_QOS_POLICY_ID 8 -#define Q_TIMEBASEDFILTER_QOS_POLICY_ID 9 -#define Q_PARTITION_QOS_POLICY_ID 10 -#define Q_RELIABILITY_QOS_POLICY_ID 11 -#define Q_DESTINATIONORDER_QOS_POLICY_ID 12 -#define Q_HISTORY_QOS_POLICY_ID 13 -#define Q_RESOURCELIMITS_QOS_POLICY_ID 14 -#define Q_ENTITYFACTORY_QOS_POLICY_ID 15 -#define Q_WRITERDATALIFECYCLE_QOS_POLICY_ID 16 -#define Q_READERDATALIFECYCLE_QOS_POLICY_ID 17 -#define Q_TOPICDATA_QOS_POLICY_ID 18 -#define Q_GROUPDATA_QOS_POLICY_ID 19 -#define Q_TRANSPORTPRIORITY_QOS_POLICY_ID 20 -#define Q_LIFESPAN_QOS_POLICY_ID 21 -#define Q_DURABILITYSERVICE_QOS_POLICY_ID 22 - -int32_t qos_match_p (const nn_xqos_t *rd, const nn_xqos_t *wr) +static bool qos_match_internal_p (const dds_qos_t *rd, const dds_qos_t *wr, dds_qos_policy_id_t *reason) { #ifndef NDEBUG unsigned musthave = (QP_RXO_MASK | QP_PARTITION | QP_TOPIC_NAME | QP_TYPE_NAME); assert ((rd->present & musthave) == musthave); assert ((wr->present & musthave) == musthave); #endif + *reason = DDS_INVALID_QOS_POLICY_ID; if (strcmp (rd->topic_name, wr->topic_name) != 0) - { - return Q_INVALID_QOS_POLICY_ID; - } + return false; if (strcmp (rd->type_name, wr->type_name) != 0) - { - return Q_INVALID_QOS_POLICY_ID; + return false; + + if (rd->reliability.kind > wr->reliability.kind) { + *reason = DDS_RELIABILITY_QOS_POLICY_ID; + return false; } - if (rd->relaxed_qos_matching.value || wr->relaxed_qos_matching.value) - { - if (rd->reliability.kind != wr->reliability.kind) - { - return Q_RELIABILITY_QOS_POLICY_ID; - } + if (rd->durability.kind > wr->durability.kind) { + *reason = DDS_DURABILITY_QOS_POLICY_ID; + return false; } - else - { - if (rd->reliability.kind > wr->reliability.kind) - { - return Q_RELIABILITY_QOS_POLICY_ID; - } - if (rd->durability.kind > wr->durability.kind) - { - return Q_DURABILITY_QOS_POLICY_ID; - } - if (rd->presentation.access_scope > wr->presentation.access_scope) - { - return Q_PRESENTATION_QOS_POLICY_ID; - } - if (rd->presentation.coherent_access > wr->presentation.coherent_access) - { - return Q_PRESENTATION_QOS_POLICY_ID; - } - if (rd->presentation.ordered_access > wr->presentation.ordered_access) - { - return Q_PRESENTATION_QOS_POLICY_ID; - } - if (ddsi_duration_is_lt (rd->deadline.deadline, wr->deadline.deadline)) - { - return Q_DEADLINE_QOS_POLICY_ID; - } - if (ddsi_duration_is_lt (rd->latency_budget.duration, wr->latency_budget.duration)) - { - return Q_LATENCYBUDGET_QOS_POLICY_ID; - } - if (rd->ownership.kind != wr->ownership.kind) - { - return Q_OWNERSHIP_QOS_POLICY_ID; - } - if (rd->liveliness.kind > wr->liveliness.kind) - { - return Q_LIVELINESS_QOS_POLICY_ID; - } - if (ddsi_duration_is_lt (rd->liveliness.lease_duration, wr->liveliness.lease_duration)) - { - return Q_LIVELINESS_QOS_POLICY_ID; - } - if (rd->destination_order.kind > wr->destination_order.kind) - { - return Q_DESTINATIONORDER_QOS_POLICY_ID; - } + if (rd->presentation.access_scope > wr->presentation.access_scope) { + *reason = DDS_PRESENTATION_QOS_POLICY_ID; + return false; } - if (!partitions_match_p (rd, wr)) - { - return Q_PARTITION_QOS_POLICY_ID; + if (rd->presentation.coherent_access > wr->presentation.coherent_access) { + *reason = DDS_PRESENTATION_QOS_POLICY_ID; + return false; } - return -1; + if (rd->presentation.ordered_access > wr->presentation.ordered_access) { + *reason = DDS_PRESENTATION_QOS_POLICY_ID; + return false; + } + if (rd->deadline.deadline < wr->deadline.deadline) { + *reason = DDS_DEADLINE_QOS_POLICY_ID; + return false; + } + if (rd->latency_budget.duration < wr->latency_budget.duration) { + *reason = DDS_LATENCYBUDGET_QOS_POLICY_ID; + return false; + } + if (rd->ownership.kind != wr->ownership.kind) { + *reason = DDS_OWNERSHIP_QOS_POLICY_ID; + return false; + } + if (rd->liveliness.kind > wr->liveliness.kind) { + *reason = DDS_LIVELINESS_QOS_POLICY_ID; + return false; + } + if (rd->liveliness.lease_duration < wr->liveliness.lease_duration) { + *reason = DDS_LIVELINESS_QOS_POLICY_ID; + return false; + } + if (rd->destination_order.kind > wr->destination_order.kind) { + *reason = DDS_DESTINATIONORDER_QOS_POLICY_ID; + return false; + } + if (!partitions_match_p (rd, wr)) { + *reason = DDS_PARTITION_QOS_POLICY_ID; + return false; + } + return true; +} + +bool qos_match_p (const dds_qos_t *rd, const dds_qos_t *wr, dds_qos_policy_id_t *reason) +{ + dds_qos_policy_id_t dummy; + return qos_match_internal_p (rd, wr, reason ? reason : &dummy); } diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index aff4669..b4f5176 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -657,7 +657,7 @@ static int accept_ack_or_hb_w_timeout (nn_count_t new_count, nn_count_t *exp_cou return 1; } -static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const AckNack_t *msg, nn_ddsi_time_t timestamp) +static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const AckNack_t *msg, nn_wctime_t timestamp) { struct proxy_reader *prd; struct wr_prd_match *rn; @@ -757,11 +757,10 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac work so well if the timestamp can be a left over from some other submessage -- but then, it is no more than a quick hack at the moment. */ - if (config.meas_hb_to_ack_latency && valid_ddsi_timestamp (timestamp)) + if (config.meas_hb_to_ack_latency && timestamp.v) { nn_wctime_t tstamp_now = now (); - nn_wctime_t tstamp_msg = nn_wctime_from_ddsi_time (timestamp); - nn_lat_estim_update (&rn->hb_to_ack_latency, tstamp_now.v - tstamp_msg.v); + nn_lat_estim_update (&rn->hb_to_ack_latency, tstamp_now.v - timestamp.v); if ((dds_get_log_mask() & DDS_LC_TRACE) && tstamp_now.v > rn->hb_to_ack_latency_tlastlog.v + 10 * T_SECOND) { nn_lat_estim_log (DDS_LC_TRACE, NULL, &rn->hb_to_ack_latency); @@ -794,7 +793,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac /* If this reader was marked as "non-responsive" in the past, it's now responding again, so update its status */ - if (rn->seq == MAX_SEQ_NUMBER && prd->c.xqos->reliability.kind == NN_RELIABLE_RELIABILITY_QOS) + if (rn->seq == MAX_SEQ_NUMBER && prd->c.xqos->reliability.kind == DDS_RELIABILITY_RELIABLE) { seqno_t oldest_seq; oldest_seq = WHCST_ISEMPTY(&whcst) ? wr->seq : whcst.max_seq; @@ -888,7 +887,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac a future request'll fix it. */ enqueued = 1; seq_xmit = READ_SEQ_XMIT(wr); - const bool gap_for_already_acked = vendor_is_eclipse (rst->vendor) && prd->c.xqos->durability.kind == NN_VOLATILE_DURABILITY_QOS && seqbase <= rn->seq; + const bool gap_for_already_acked = vendor_is_eclipse (rst->vendor) && prd->c.xqos->durability.kind == DDS_DURABILITY_VOLATILE && seqbase <= rn->seq; const seqno_t min_seq_to_rexmit = gap_for_already_acked ? rn->seq + 1 : 0; for (i = 0; i < numbits && seqbase + i <= seq_xmit && enqueued; i++) { @@ -1088,7 +1087,7 @@ struct handle_Heartbeat_helper_arg { struct receiver_state *rst; const Heartbeat_t *msg; struct proxy_writer *pwr; - nn_ddsi_time_t timestamp; + nn_wctime_t timestamp; nn_etime_t tnow; nn_mtime_t tnow_mt; }; @@ -1145,13 +1144,13 @@ static void handle_Heartbeat_helper (struct pwr_rd_match * const wn, struct hand } if (resched_xevent_if_earlier (wn->acknack_xevent, tsched)) { - if (config.meas_hb_to_ack_latency && valid_ddsi_timestamp (arg->timestamp)) - wn->hb_timestamp = nn_wctime_from_ddsi_time (arg->timestamp); + if (config.meas_hb_to_ack_latency && arg->timestamp.v) + wn->hb_timestamp = arg->timestamp; } } } -static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Heartbeat_t *msg, nn_ddsi_time_t timestamp) +static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Heartbeat_t *msg, nn_wctime_t timestamp) { /* We now cheat: and process the heartbeat for _all_ readers, always, regardless of the destination address in the Heartbeat @@ -1567,22 +1566,19 @@ static int handle_InfoSRC (struct receiver_state *rst, const InfoSRC_t *msg) return 1; } -static int handle_InfoTS (const InfoTS_t *msg, nn_ddsi_time_t *timestamp) +static int handle_InfoTS (const InfoTS_t *msg, nn_wctime_t *timestamp) { DDS_TRACE("INFOTS("); if (msg->smhdr.flags & INFOTS_INVALIDATE_FLAG) { - *timestamp = invalid_ddsi_timestamp; + *timestamp = NN_WCTIME_INVALID; DDS_TRACE("invalidate"); } else { - *timestamp = msg->time; + *timestamp = nn_wctime_from_ddsi_time (msg->time); if (dds_get_log_mask() & DDS_LC_TRACE) - { - nn_wctime_t t = nn_wctime_from_ddsi_time (* timestamp); - DDS_TRACE("%d.%09d", (int) (t.v / 1000000000), (int) (t.v % 1000000000)); - } + DDS_TRACE("%d.%09d", (int) (timestamp->v / 1000000000), (int) (timestamp->v % 1000000000)); } DDS_TRACE(")"); return 1; @@ -1974,8 +1970,8 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st worry about it. */ { nn_wctime_t tstamp; - if (valid_ddsi_timestamp (sampleinfo->timestamp)) - tstamp = nn_wctime_from_ddsi_time (sampleinfo->timestamp); + if (sampleinfo->timestamp.v != NN_WCTIME_INVALID.v) + tstamp = sampleinfo->timestamp; else tstamp.v = 0; payload = extract_sample_from_data (sampleinfo, data_smhdr_flags, &qos, fragchain, statusinfo, tstamp, topic); @@ -2663,7 +2659,7 @@ static int handle_submsg_sequence Header_t * hdr = (Header_t *) msg; struct receiver_state *rst; int rst_live, ts_for_latmeas; - nn_ddsi_time_t timestamp; + nn_wctime_t timestamp; size_t submsg_size = 0; unsigned char * end = msg + len; struct nn_dqueue *deferred_wakeup = NULL; @@ -2693,7 +2689,7 @@ static int handle_submsg_sequence rst->srcloc = *srcloc; rst_live = 0; ts_for_latmeas = 0; - timestamp = invalid_ddsi_timestamp; + timestamp = NN_WCTIME_INVALID; assert (thread_is_asleep ()); thread_state_awake (ts1); @@ -2748,14 +2744,14 @@ static int handle_submsg_sequence state = "parse:acknack"; if (!valid_AckNack (&sm->acknack, submsg_size, byteswap)) goto malformed; - handle_AckNack (rst, tnowE, &sm->acknack, ts_for_latmeas ? timestamp : invalid_ddsi_timestamp); + handle_AckNack (rst, tnowE, &sm->acknack, ts_for_latmeas ? timestamp : NN_WCTIME_INVALID); ts_for_latmeas = 0; break; case SMID_HEARTBEAT: state = "parse:heartbeat"; if (!valid_Heartbeat (&sm->heartbeat, submsg_size, byteswap)) goto malformed; - handle_Heartbeat (rst, tnowE, rmsg, &sm->heartbeat, ts_for_latmeas ? timestamp : invalid_ddsi_timestamp); + handle_Heartbeat (rst, tnowE, rmsg, &sm->heartbeat, ts_for_latmeas ? timestamp : NN_WCTIME_INVALID); ts_for_latmeas = 0; break; case SMID_GAP: diff --git a/src/core/ddsi/src/q_time.c b/src/core/ddsi/src/q_time.c index 05878b3..79cfcf3 100644 --- a/src/core/ddsi/src/q_time.c +++ b/src/core/ddsi/src/q_time.c @@ -14,10 +14,6 @@ #include "dds/ddsrt/time.h" #include "dds/ddsi/q_time.h" -const nn_ddsi_time_t invalid_ddsi_timestamp = { -1, UINT32_MAX }; -const nn_ddsi_time_t ddsi_time_infinite = { INT32_MAX, UINT32_MAX }; -const nn_duration_t duration_infinite = { INT32_MAX, UINT32_MAX }; - nn_wctime_t now (void) { /* This function uses the wall clock. @@ -131,21 +127,21 @@ nn_etime_t add_duration_to_etime (nn_etime_t t, int64_t d) return u; } -int valid_ddsi_timestamp (nn_ddsi_time_t t) +int valid_ddsi_timestamp (ddsi_time_t t) { - return t.seconds != invalid_ddsi_timestamp.seconds && t.fraction != invalid_ddsi_timestamp.fraction; + return t.seconds != DDSI_TIME_INVALID.seconds && t.fraction != DDSI_TIME_INVALID.fraction; } -static nn_ddsi_time_t nn_to_ddsi_time (int64_t t) +static ddsi_time_t nn_to_ddsi_time (int64_t t) { if (t == T_NEVER) - return ddsi_time_infinite; + return DDSI_TIME_INFINITE; else { /* ceiling(ns * 2^32/10^9) -- can't change the ceiling to round-to-nearest because that would break backwards compatibility, but round-to-nearest of the inverse is correctly rounded anyway, so it shouldn't ever matter. */ - nn_ddsi_time_t x; + ddsi_time_t x; int ns = (int) (t % T_SECOND); x.seconds = (int) (t / T_SECOND); x.fraction = (unsigned) (((T_SECOND-1) + ((int64_t) ns << 32)) / T_SECOND); @@ -153,14 +149,14 @@ static nn_ddsi_time_t nn_to_ddsi_time (int64_t t) } } -nn_ddsi_time_t nn_wctime_to_ddsi_time (nn_wctime_t t) +ddsi_time_t nn_wctime_to_ddsi_time (nn_wctime_t t) { return nn_to_ddsi_time (t.v); } -static int64_t nn_from_ddsi_time (nn_ddsi_time_t x) +static int64_t nn_from_ddsi_time (ddsi_time_t x) { - if (x.seconds == ddsi_time_infinite.seconds && x.fraction == ddsi_time_infinite.fraction) + if (x.seconds == DDSI_TIME_INFINITE.seconds && x.fraction == DDSI_TIME_INFINITE.fraction) return T_NEVER; else { @@ -170,19 +166,19 @@ static int64_t nn_from_ddsi_time (nn_ddsi_time_t x) } } -nn_wctime_t nn_wctime_from_ddsi_time (nn_ddsi_time_t x) +nn_wctime_t nn_wctime_from_ddsi_time (ddsi_time_t x) { nn_wctime_t t; t.v = nn_from_ddsi_time (x); return t; } -nn_duration_t nn_to_ddsi_duration (int64_t x) +ddsi_duration_t nn_to_ddsi_duration (int64_t x) { return nn_to_ddsi_time (x); } -int64_t nn_from_ddsi_duration (nn_duration_t x) +int64_t nn_from_ddsi_duration (ddsi_duration_t x) { return nn_from_ddsi_time (x); } diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index a47c12c..c6f85aa 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -424,7 +424,7 @@ static dds_return_t create_fragment_message_simple (struct writer *wr, seqno_t s #endif nn_xmsg_setdstN (*pmsg, wr->as, wr->as_group); - nn_xmsg_setmaxdelay (*pmsg, nn_from_ddsi_duration (wr->xqos->latency_budget.duration)); + nn_xmsg_setmaxdelay (*pmsg, wr->xqos->latency_budget.duration); nn_xmsg_add_timestamp (*pmsg, serdata->timestamp); data = nn_xmsg_append (*pmsg, &sm_marker, sizeof (Data_t)); @@ -521,7 +521,7 @@ dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const stru else { nn_xmsg_setdstN (*pmsg, wr->as, wr->as_group); - nn_xmsg_setmaxdelay (*pmsg, nn_from_ddsi_duration (wr->xqos->latency_budget.duration)); + nn_xmsg_setmaxdelay (*pmsg, wr->xqos->latency_budget.duration); } /* Timestamp only needed once, for the first fragment */ @@ -938,7 +938,7 @@ static dds_return_t throttle_writer (struct thread_state1 * const ts1, struct nn dds_return_t result = DDS_RETCODE_OK; nn_mtime_t tnow = now_mt (); - const nn_mtime_t abstimeout = add_duration_to_mtime (tnow, nn_from_ddsi_duration (wr->xqos->reliability.max_blocking_time)); + const nn_mtime_t abstimeout = add_duration_to_mtime (tnow, wr->xqos->reliability.max_blocking_time); struct whc_state whcst; whc_get_state (wr->whc, &whcst); @@ -1024,7 +1024,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * nn_mtime_t tnow; /* 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 == NN_KEEP_LAST_HISTORY_QOS && wr->whc_low == INT32_MAX)); + assert(gc_allowed || (wr->xqos->history.kind == DDS_HISTORY_KEEP_LAST && wr->whc_low == INT32_MAX)); (void)gc_allowed; if (ddsi_serdata_size (serdata) > config.max_sample_size) diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index b443e25..924c663 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -782,7 +782,7 @@ size_t nn_xmsg_add_string_padded(unsigned char *buf, char *str) return len; } -size_t nn_xmsg_add_octseq_padded(unsigned char *buf, nn_octetseq_t *seq) +size_t nn_xmsg_add_octseq_padded(unsigned char *buf, ddsi_octetseq_t *seq) { unsigned len = seq->length; if (buf) { @@ -799,15 +799,16 @@ size_t nn_xmsg_add_octseq_padded(unsigned char *buf, nn_octetseq_t *seq) align4u(len); /* seqlen + possible padding */ } -void * nn_xmsg_addpar (struct nn_xmsg *m, unsigned pid, size_t len) +void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len) { - const size_t len4 = (len + 3) & (size_t)-4; /* must alloc a multiple of 4 */ + const size_t len4 = (len + 3) & ~(size_t)3; /* must alloc a multiple of 4 */ nn_parameter_t *phdr; char *p; + assert (len4 < UINT16_MAX); /* FIXME: return error */ m->have_params = 1; phdr = nn_xmsg_append (m, NULL, sizeof (nn_parameter_t) + len4); - phdr->parameterid = (nn_parameterid_t) pid; - phdr->length = (unsigned short) len4; + phdr->parameterid = pid; + phdr->length = (uint16_t) len4; p = (char *) (phdr + 1); if (len4 > len) { @@ -819,23 +820,23 @@ void * nn_xmsg_addpar (struct nn_xmsg *m, unsigned pid, size_t len) return p; } -void nn_xmsg_addpar_string (struct nn_xmsg *m, unsigned pid, const char *str) +void nn_xmsg_addpar_string (struct nn_xmsg *m, nn_parameterid_t pid, const char *str) { struct cdrstring *p; - unsigned len = (unsigned) strlen (str) + 1; + size_t len = strlen (str) + 1; p = nn_xmsg_addpar (m, pid, 4 + len); - p->length = len; + p->length = (uint32_t) len; memcpy (p->contents, str, len); } -void nn_xmsg_addpar_octetseq (struct nn_xmsg *m, unsigned pid, const nn_octetseq_t *oseq) +void nn_xmsg_addpar_octetseq (struct nn_xmsg *m, nn_parameterid_t pid, const ddsi_octetseq_t *oseq) { char *p = nn_xmsg_addpar (m, pid, 4 + oseq->length); *((unsigned *) p) = oseq->length; memcpy (p + sizeof (int), oseq->value, oseq->length); } -void nn_xmsg_addpar_stringseq (struct nn_xmsg *m, unsigned pid, const nn_stringseq_t *sseq) +void nn_xmsg_addpar_stringseq (struct nn_xmsg *m, nn_parameterid_t pid, const ddsi_stringseq_t *sseq) { unsigned char *tmp; uint32_t i; @@ -866,7 +867,7 @@ void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serda } } -void nn_xmsg_addpar_guid (struct nn_xmsg *m, unsigned pid, const nn_guid_t *guid) +void nn_xmsg_addpar_guid (struct nn_xmsg *m, nn_parameterid_t pid, const nn_guid_t *guid) { unsigned *pu; int i; @@ -878,50 +879,68 @@ void nn_xmsg_addpar_guid (struct nn_xmsg *m, unsigned pid, const nn_guid_t *guid pu[i] = toBE4u (guid->entityid.u); } -void nn_xmsg_addpar_reliability (struct nn_xmsg *m, unsigned pid, const struct nn_reliability_qospolicy *rq) +void nn_xmsg_addpar_reliability (struct nn_xmsg *m, nn_parameterid_t pid, const struct dds_reliability_qospolicy *rq) { - struct nn_external_reliability_qospolicy *p; + struct dds_external_reliability_qospolicy *p; p = nn_xmsg_addpar (m, pid, sizeof (*p)); - if (NN_PEDANTIC_P) + switch (rq->kind) { - switch (rq->kind) - { - case NN_BEST_EFFORT_RELIABILITY_QOS: - p->kind = NN_PEDANTIC_BEST_EFFORT_RELIABILITY_QOS; - break; - case NN_RELIABLE_RELIABILITY_QOS: - p->kind = NN_PEDANTIC_RELIABLE_RELIABILITY_QOS; - break; - default: - assert (0); - } + case DDS_RELIABILITY_BEST_EFFORT: + p->kind = DDS_EXTERNAL_RELIABILITY_BEST_EFFORT; + break; + case DDS_RELIABILITY_RELIABLE: + p->kind = DDS_EXTERNAL_RELIABILITY_RELIABLE; + break; + default: + assert (0); } - else - { - switch (rq->kind) - { - case NN_BEST_EFFORT_RELIABILITY_QOS: - p->kind = NN_INTEROP_BEST_EFFORT_RELIABILITY_QOS; - break; - case NN_RELIABLE_RELIABILITY_QOS: - p->kind = NN_INTEROP_RELIABLE_RELIABILITY_QOS; - break; - default: - assert (0); - } - } - p->max_blocking_time = rq->max_blocking_time; + p->max_blocking_time = nn_to_ddsi_duration (rq->max_blocking_time); } -void nn_xmsg_addpar_4u (struct nn_xmsg *m, unsigned pid, unsigned x) +void nn_xmsg_addpar_duration (struct nn_xmsg *m, nn_parameterid_t pid, const dds_duration_t rq) { - unsigned *p = nn_xmsg_addpar (m, pid, 4); + ddsi_duration_t *p = nn_xmsg_addpar (m, pid, sizeof (*p)); + *p = nn_to_ddsi_duration (rq); +} + +void nn_xmsg_addpar_durability_service (struct nn_xmsg *m, nn_parameterid_t pid, const dds_durability_service_qospolicy_t *rq) +{ + dds_external_durability_service_qospolicy_t *p = nn_xmsg_addpar (m, pid, sizeof (*p)); + p->history = rq->history; + p->resource_limits = rq->resource_limits; + p->service_cleanup_delay = nn_to_ddsi_duration (rq->service_cleanup_delay); +} + +void nn_xmsg_addpar_reader_lifespan (struct nn_xmsg *m, nn_parameterid_t pid, const dds_reader_lifespan_qospolicy_t *rq) +{ + dds_external_reader_lifespan_qospolicy_t *p = nn_xmsg_addpar (m, pid, sizeof (*p)); + p->use_lifespan = rq->use_lifespan; + p->duration = nn_to_ddsi_duration (rq->duration); +} + +void nn_xmsg_addpar_reader_data_lifecycle (struct nn_xmsg *m, nn_parameterid_t pid, const dds_reader_data_lifecycle_qospolicy_t *rq) +{ + dds_external_reader_data_lifecycle_qospolicy_t *p = nn_xmsg_addpar (m, pid, sizeof (*p)); + p->autopurge_disposed_samples_delay = nn_to_ddsi_duration (rq->autopurge_disposed_samples_delay); + p->autopurge_nowriter_samples_delay = nn_to_ddsi_duration (rq->autopurge_nowriter_samples_delay); +} + +void nn_xmsg_addpar_liveliness (struct nn_xmsg *m, nn_parameterid_t pid, const dds_liveliness_qospolicy_t *rq) +{ + dds_external_liveliness_qospolicy_t *p = nn_xmsg_addpar (m, pid, sizeof (*p)); + p->kind = rq->kind; + p->lease_duration = nn_to_ddsi_duration (rq->lease_duration); +} + +void nn_xmsg_addpar_4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x) +{ + unsigned *p = nn_xmsg_addpar (m, pid, sizeof (x)); *p = x; } -void nn_xmsg_addpar_BE4u (struct nn_xmsg *m, unsigned pid, unsigned x) +void nn_xmsg_addpar_BE4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x) { - unsigned *p = nn_xmsg_addpar (m, pid, 4); + unsigned *p = nn_xmsg_addpar (m, pid, sizeof (x)); *p = toBE4u (x); } @@ -941,28 +960,7 @@ void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, unsigned statusinfo) } } - -void nn_xmsg_addpar_share (struct nn_xmsg *m, unsigned pid, const struct nn_share_qospolicy *q) -{ - /* Written thus to allow q->name to be a null pointer if enable = false */ - const unsigned fixed_len = 4 + 4; - const unsigned len = (q->enable ? (unsigned) strlen (q->name) : 0) + 1; - unsigned char *p; - struct cdrstring *ps; - p = nn_xmsg_addpar (m, pid, fixed_len + len); - p[0] = q->enable; - p[1] = 0; - p[2] = 0; - p[3] = 0; - ps = (struct cdrstring *) (p + 4); - ps->length = len; - if (q->enable) - memcpy (ps->contents, q->name, len); - else - ps->contents[0] = 0; -} - -void nn_xmsg_addpar_subscription_keys (struct nn_xmsg *m, unsigned pid, const struct nn_subscription_keys_qospolicy *q) +void nn_xmsg_addpar_subscription_keys (struct nn_xmsg *m, nn_parameterid_t pid, const struct dds_subscription_keys_qospolicy *q) { unsigned char *tmp; size_t len = 8; /* use_key_list, length of key_list */ @@ -1012,7 +1010,7 @@ int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg * m) return 0; } -void nn_xmsg_addpar_parvinfo (struct nn_xmsg *m, unsigned pid, const struct nn_prismtech_participant_version_info *pvi) +void nn_xmsg_addpar_parvinfo (struct nn_xmsg *m, nn_parameterid_t pid, const struct nn_prismtech_participant_version_info *pvi) { int i; unsigned slen; @@ -1033,7 +1031,7 @@ void nn_xmsg_addpar_parvinfo (struct nn_xmsg *m, unsigned pid, const struct nn_p memcpy(ps->contents, pvi->internals, slen); } -void nn_xmsg_addpar_eotinfo (struct nn_xmsg *m, unsigned pid, const struct nn_prismtech_eotinfo *txnid) +void nn_xmsg_addpar_eotinfo (struct nn_xmsg *m, nn_parameterid_t pid, const struct nn_prismtech_eotinfo *txnid) { uint32_t *pu, i; pu = nn_xmsg_addpar (m, pid, 2 * sizeof (uint32_t) + txnid->n * sizeof (txnid->tids[0])); diff --git a/src/core/xtests/rhc_torture/rhc_torture.c b/src/core/xtests/rhc_torture/rhc_torture.c index 245d057..f743c12 100644 --- a/src/core/xtests/rhc_torture/rhc_torture.c +++ b/src/core/xtests/rhc_torture/rhc_torture.c @@ -140,7 +140,7 @@ static uint64_t store (struct rhc *rhc, struct proxy_writer *wr, struct ddsi_ser static struct proxy_writer *mkwr (bool auto_dispose) { struct proxy_writer *pwr; - struct nn_xqos *xqos; + struct dds_qos *xqos; uint64_t wr_iid; pwr = ddsrt_malloc (sizeof (*pwr)); xqos = ddsrt_malloc (sizeof (*xqos)); @@ -161,10 +161,10 @@ static void fwr (struct proxy_writer *wr) free (wr); } -static struct rhc *mkrhc (dds_reader *rd, nn_history_kind_t hk, int32_t hdepth, nn_destination_order_kind_t dok) +static struct rhc *mkrhc (dds_reader *rd, dds_history_kind_t hk, int32_t hdepth, dds_destination_order_kind_t dok) { struct rhc *rhc; - nn_xqos_t rqos; + dds_qos_t rqos; nn_xqos_init_empty (&rqos); rqos.present |= QP_HISTORY | QP_DESTINATION_ORDER; rqos.history.kind = hk; @@ -848,7 +848,7 @@ int main (int argc, char **argv) { if (print) printf ("************* 0 *************\n"); - struct rhc *rhc = mkrhc (NULL, NN_KEEP_LAST_HISTORY_QOS, 1, NN_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS); + struct rhc *rhc = mkrhc (NULL, DDS_HISTORY_KEEP_LAST, 1, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP); struct proxy_writer *wr0 = mkwr (1); uint64_t iid0, iid1, iid_t; iid0 = store (rhc, wr0, mksample (0, 0), print); @@ -894,7 +894,7 @@ int main (int argc, char **argv) { if (print) printf ("************* 1 *************\n"); - struct rhc *rhc = mkrhc (NULL, NN_KEEP_LAST_HISTORY_QOS, 4, NN_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS); + struct rhc *rhc = mkrhc (NULL, DDS_HISTORY_KEEP_LAST, 4, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP); struct proxy_writer *wr[] = { mkwr (0), mkwr (0), mkwr (0) }; uint64_t iid0, iid_t; int nregs = 3, isreg[] = { 1, 1, 1 }; From f9219bb5fa2b49f9e6ba491b1277842fe51a0d3e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 30 May 2019 10:31:10 +0200 Subject: [PATCH 085/178] Listener getters: set callback to 0 if listener is NULL The functions did not touch the callback pointer if a null pointer was passed in for the listener. That means one would have to initialize the out parameter before the call or manually check the listener pointer to know whether the callback point has a defined value following the call. That's asking for trouble. Thus, the decision to return a callback of 0 when no listener object is passed in. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_listener.c | 52 ++++++++++++++++---------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/core/ddsc/src/dds_listener.c b/src/core/ddsc/src/dds_listener.c index ddfc5ca..eee9ef6 100644 --- a/src/core/ddsc/src/dds_listener.c +++ b/src/core/ddsc/src/dds_listener.c @@ -298,78 +298,78 @@ void dds_lset_subscription_matched (dds_listener_t * __restrict listener, dds_on void dds_lget_data_available (const dds_listener_t * __restrict listener, dds_on_data_available_fn *callback) { - if (callback && listener) - *callback = listener->on_data_available; + if (callback != NULL) + *callback = listener ? listener->on_data_available : 0; } void dds_lget_data_on_readers (const dds_listener_t * __restrict listener, dds_on_data_on_readers_fn *callback) { - if (callback && listener) - *callback = listener->on_data_on_readers; + if (callback) + *callback = listener ? listener->on_data_on_readers : 0; } void dds_lget_inconsistent_topic (const dds_listener_t * __restrict listener, dds_on_inconsistent_topic_fn *callback) { - if (callback && listener) - *callback = listener->on_inconsistent_topic; + if (callback) + *callback = listener ? listener->on_inconsistent_topic : 0; } void dds_lget_liveliness_changed (const dds_listener_t * __restrict listener, dds_on_liveliness_changed_fn *callback) { - if (callback && listener) - *callback = listener->on_liveliness_changed; + if (callback) + *callback = listener ? listener->on_liveliness_changed : 0; } void dds_lget_liveliness_lost (const dds_listener_t * __restrict listener, dds_on_liveliness_lost_fn *callback) { - if (callback && listener) - *callback = listener->on_liveliness_lost; + if (callback) + *callback = listener ? listener->on_liveliness_lost : 0; } void dds_lget_offered_deadline_missed (const dds_listener_t * __restrict listener, dds_on_offered_deadline_missed_fn *callback) { - if (callback && listener) - *callback = listener->on_offered_deadline_missed; + if (callback) + *callback = listener ? listener->on_offered_deadline_missed : 0; } void dds_lget_offered_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_offered_incompatible_qos_fn *callback) { - if (callback && listener) - *callback = listener->on_offered_incompatible_qos; + if (callback) + *callback = listener ? listener->on_offered_incompatible_qos : 0; } void dds_lget_publication_matched (const dds_listener_t * __restrict listener, dds_on_publication_matched_fn *callback) { - if (callback && listener) - *callback = listener->on_publication_matched; + if (callback) + *callback = listener ? listener->on_publication_matched : 0; } void dds_lget_requested_deadline_missed (const dds_listener_t * __restrict listener, dds_on_requested_deadline_missed_fn *callback) { - if (callback && listener) - *callback = listener->on_requested_deadline_missed; + if (callback) + *callback = listener ? listener->on_requested_deadline_missed : 0; } void dds_lget_requested_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_requested_incompatible_qos_fn *callback) { - if (callback && listener) - *callback = listener->on_requested_incompatible_qos; + if (callback) + *callback = listener ? listener->on_requested_incompatible_qos : 0; } void dds_lget_sample_lost (const dds_listener_t *__restrict listener, dds_on_sample_lost_fn *callback) { - if (callback && listener) - *callback = listener->on_sample_lost; + if (callback) + *callback = listener ? listener->on_sample_lost : 0; } void dds_lget_sample_rejected (const dds_listener_t *__restrict listener, dds_on_sample_rejected_fn *callback) { - if (callback && listener) - *callback = listener->on_sample_rejected; + if (callback) + *callback = listener ? listener->on_sample_rejected : 0; } void dds_lget_subscription_matched (const dds_listener_t * __restrict listener, dds_on_subscription_matched_fn *callback) { - if (callback && listener) - *callback = listener->on_subscription_matched; + if (callback) + *callback = listener ? listener->on_subscription_matched : 0; } From ffbf3d78439746854556de8b1775dfff9a4f4f09 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 30 May 2019 12:33:23 +0200 Subject: [PATCH 086/178] Avoid implementation defined types, e.g. unsigned There are some cases where "int" or "unsigend" actually makes sense, but in a large number of cases it is really supposed to be either a 32-bit integer, or, in some cases, at least a 32-bit integer. It is much to be preferred to be clear about this. Another reason is that at least some embedded platforms define, e.g., int32_t as "long" instead of "int". For the ones I am aware of the "int" and "long" are actually the same 32-bit integer, but that distinction can cause trouble with printf format specifications. So again a good reason to be consistent in avoiding the implementation-defined ones. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds__rhc.h | 4 +- src/core/ddsc/src/dds_rhc.c | 53 ++++++-------------- src/core/ddsc/src/dds_write.c | 3 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 12 ++--- src/core/ddsi/include/dds/ddsi/q_gc.h | 6 +-- src/core/ddsi/include/dds/ddsi/q_globals.h | 2 +- src/core/ddsi/include/dds/ddsi/q_hbcontrol.h | 6 +-- src/core/ddsi/include/dds/ddsi/q_lease.h | 2 +- src/core/ddsi/include/dds/ddsi/q_nwif.h | 6 +-- src/core/ddsi/include/dds/ddsi/q_thread.h | 2 +- src/core/ddsi/src/ddsi_threadmon.c | 5 +- src/core/ddsi/src/ddsi_tran.c | 3 +- src/core/ddsi/src/q_addrset.c | 4 +- src/core/ddsi/src/q_bswap.c | 8 +-- src/core/ddsi/src/q_config.c | 8 +-- src/core/ddsi/src/q_ddsi_discovery.c | 8 +-- src/core/ddsi/src/q_debmon.c | 3 +- src/core/ddsi/src/q_entity.c | 33 +++++------- src/core/ddsi/src/q_gc.c | 8 +-- src/core/ddsi/src/q_init.c | 21 +++----- src/core/ddsi/src/q_lease.c | 14 +++--- src/core/ddsi/src/q_nwif.c | 6 +-- src/core/ddsi/src/q_qosmatch.c | 8 ++- src/core/ddsi/src/q_receive.c | 40 +++++++-------- src/core/ddsi/src/q_security.c | 5 +- src/core/ddsi/src/q_sockwaitset.c | 18 ++----- src/core/ddsi/src/q_thread.c | 23 +++------ src/core/ddsi/src/q_transmit.c | 9 ++-- src/core/ddsi/src/q_xevent.c | 13 +++-- src/core/ddsi/src/q_xmsg.c | 16 +++--- src/ddsrt/src/fibheap.c | 2 +- 31 files changed, 141 insertions(+), 210 deletions(-) diff --git a/src/core/ddsc/src/dds__rhc.h b/src/core/ddsc/src/dds__rhc.h index e0ede81..2a420d8 100644 --- a/src/core/ddsc/src/dds__rhc.h +++ b/src/core/ddsc/src/dds__rhc.h @@ -62,8 +62,8 @@ DDS_EXPORT void dds_rhc_remove_readcondition (dds_readcond * cond); DDS_EXPORT int dds_rhc_takecdr ( struct rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, - uint32_t max_samples, unsigned sample_states, - unsigned view_states, unsigned instance_states, + uint32_t max_samples, uint32_t sample_states, + uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle ); diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index e2c9f2b..4c160c1 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -234,16 +234,16 @@ struct rhc_sample { uint64_t wr_iid; /* unique id for writer of this sample (perhaps better in serdata) */ dds_querycond_mask_t conds; /* matching query conditions */ bool isread; /* READ or NOT_READ sample state */ - unsigned disposed_gen; /* snapshot of instance counter at time of insertion */ - unsigned no_writers_gen; /* __/ */ + uint32_t disposed_gen; /* snapshot of instance counter at time of insertion */ + uint32_t no_writers_gen; /* __/ */ }; struct rhc_instance { uint64_t iid; /* unique instance id, key of table, also serves as instance handle */ uint64_t wr_iid; /* unique of id of writer of latest sample or 0; if wrcount = 0 it is the wr_iid that caused */ struct rhc_sample *latest; /* latest received sample; circular list old->new; null if no sample */ - unsigned nvsamples; /* number of "valid" samples in instance */ - unsigned nvread; /* number of READ "valid" samples in instance (0 <= nvread <= nvsamples) */ + uint32_t nvsamples; /* number of "valid" samples in instance */ + uint32_t nvread; /* number of READ "valid" samples in instance (0 <= nvread <= nvsamples) */ dds_querycond_mask_t conds; /* matching query conditions */ uint32_t wrcount; /* number of live writers */ unsigned isnew : 1; /* NEW or NOT_NEW view state */ @@ -252,8 +252,8 @@ struct rhc_instance { unsigned wr_iid_islive : 1; /* whether wr_iid is of a live writer */ unsigned inv_exists : 1; /* whether or not state change occurred since last sample (i.e., must return invalid sample) */ unsigned inv_isread : 1; /* whether or not that state change has been read before */ - unsigned disposed_gen; /* bloody generation counters - worst invention of mankind */ - unsigned no_writers_gen; /* __/ */ + uint32_t disposed_gen; /* bloody generation counters - worst invention of mankind */ + uint32_t no_writers_gen; /* __/ */ int32_t strength; /* "current" ownership strength */ nn_guid_t wr_guid; /* guid of last writer (if wr_iid != 0 then wr_guid is the corresponding guid, else undef) */ nn_wctime_t tstamp; /* source time stamp of last update */ @@ -296,7 +296,7 @@ struct rhc { dds_reader *reader; /* reader */ const struct ddsi_sertopic *topic; /* topic description */ - unsigned history_depth; /* depth, 1 for KEEP_LAST_1, 2**32-1 for KEEP_ALL */ + uint32_t history_depth; /* depth, 1 for KEEP_LAST_1, 2**32-1 for KEEP_ALL */ ddsrt_mutex_t lock; dds_readcond * conds; /* List of associated read conditions */ @@ -1593,9 +1593,9 @@ static unsigned qmask_of_inst (const struct rhc_instance *inst) return qm; } -static unsigned qmask_from_dcpsquery (unsigned sample_states, unsigned view_states, unsigned instance_states) +static uint32_t qmask_from_dcpsquery (uint32_t sample_states, uint32_t view_states, uint32_t instance_states) { - unsigned qminv = 0; + uint32_t qminv = 0; switch ((dds_sample_state_t) sample_states) { @@ -1639,7 +1639,7 @@ static unsigned qmask_from_dcpsquery (unsigned sample_states, unsigned view_stat return qminv; } -static unsigned qmask_from_mask_n_cond(uint32_t mask, dds_readcond* cond) +static unsigned qmask_from_mask_n_cond (uint32_t mask, dds_readcond* cond) { unsigned qminv; if (mask == NO_STATE_MASK_SET) { @@ -2553,40 +2553,19 @@ static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, ****** READ/TAKE ****** *************************/ -int -dds_rhc_read( - struct rhc *rhc, - bool lock, - void ** values, - dds_sample_info_t *info_seq, - uint32_t max_samples, - uint32_t mask, - dds_instance_handle_t handle, - dds_readcond *cond) +int dds_rhc_read (struct rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) { - unsigned qminv = qmask_from_mask_n_cond(mask, cond); - return dds_rhc_read_w_qminv(rhc, lock, values, info_seq, max_samples, qminv, handle, cond); + unsigned qminv = qmask_from_mask_n_cond (mask, cond); + return dds_rhc_read_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, cond); } -int -dds_rhc_take( - struct rhc *rhc, - bool lock, - void ** values, - dds_sample_info_t *info_seq, - uint32_t max_samples, - uint32_t mask, - dds_instance_handle_t handle, - dds_readcond *cond) +int dds_rhc_take (struct rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) { unsigned qminv = qmask_from_mask_n_cond(mask, cond); - return dds_rhc_take_w_qminv(rhc, lock, values, info_seq, max_samples, qminv, handle, cond); + return dds_rhc_take_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, cond); } -int dds_rhc_takecdr -( - struct rhc *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, - unsigned sample_states, unsigned view_states, unsigned instance_states, dds_instance_handle_t handle) +int dds_rhc_takecdr (struct rhc *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { unsigned qminv = qmask_from_dcpsquery (sample_states, view_states, instance_states); return dds_rhc_takecdr_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, NULL); diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index d399e80..0156c1a 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -98,9 +98,8 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay { dds_duration_t max_block_ms = wr->xqos->reliability.max_blocking_time; struct proxy_writer_info pwr_info; - unsigned i; make_proxy_writer_info (&pwr_info, &wr->e, wr->xqos); - for (i = 0; rdary[i]; i++) { + for (uint32_t i = 0; rdary[i]; i++) { DDS_TRACE ("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; diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 709ad36..f809489 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -147,7 +147,7 @@ struct local_reader_ary { ddsrt_mutex_t rdary_lock; 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") */ - unsigned n_readers; + uint32_t n_readers; struct reader **rdary; /* for efficient delivery, null-pointer terminated */ }; @@ -158,9 +158,9 @@ struct avail_entityid_set { struct participant { struct entity_common e; - long long lease_duration; /* constant */ - unsigned bes; /* built-in endpoint set */ - unsigned prismtech_bes; /* prismtech-specific extension of built-in endpoints set */ + 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 */ @@ -242,7 +242,7 @@ struct writer struct addrset *as; /* set of addresses to publish to */ struct addrset *as_group; /* alternate case, used for SPDP, when using Cloud with multiple bootstrap locators */ struct xevent *heartbeat_xevent; /* timed event for "periodically" publishing heartbeats when unack'd data present, NULL <=> unreliable */ - long long lease_duration; + dds_duration_t lease_duration; struct whc *whc; /* WHC tracking history, T-L durability service history + samples by sequence number for retransmit */ uint32_t whc_low, whc_high; /* watermarks for WHC in bytes (counting only unack'd data) */ nn_etime_t t_rexmit_end; /* time of last 1->0 transition of "retransmitting" */ @@ -588,7 +588,7 @@ 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 (const struct nn_guid *guid, unsigned bes, unsigned prismtech_bes, const struct nn_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct nn_plist *plist, int64_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp); +void new_proxy_participant (const struct nn_guid *guid, unsigned bes, unsigned prismtech_bes, const struct nn_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct nn_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp); int delete_proxy_participant_by_guid (const struct nn_guid * guid, nn_wctime_t timestamp, int isimplicit); uint64_t participant_instance_id (const struct nn_guid *guid); diff --git a/src/core/ddsi/include/dds/ddsi/q_gc.h b/src/core/ddsi/include/dds/ddsi/q_gc.h index 6a155fd..1ea3fc4 100644 --- a/src/core/ddsi/include/dds/ddsi/q_gc.h +++ b/src/core/ddsi/include/dds/ddsi/q_gc.h @@ -30,7 +30,7 @@ struct proxy_reader; typedef void (*gcreq_cb_t) (struct gcreq *gcreq); struct idx_vtime { - unsigned idx; + uint32_t idx; vtime_t vtime; }; @@ -39,8 +39,8 @@ struct gcreq { struct gcreq_queue *queue; gcreq_cb_t cb; void *arg; - unsigned nvtimes; - struct idx_vtime vtimes[1 /* really a flex ary */]; + uint32_t nvtimes; + struct idx_vtime vtimes[]; }; DDS_EXPORT struct gcreq_queue *gcreq_queue_new (void); diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/q_globals.h index 418fd88..46cafab 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/q_globals.h @@ -210,7 +210,7 @@ struct q_globals { it is only a global variable because it needs to be freed way later than the receive thread itself terminates */ #define MAX_RECV_THREADS 3 - unsigned n_recv_threads; + uint32_t n_recv_threads; struct recv_thread { const char *name; struct thread_state1 *ts; diff --git a/src/core/ddsi/include/dds/ddsi/q_hbcontrol.h b/src/core/ddsi/include/dds/ddsi/q_hbcontrol.h index d4d29ed..ca6a56f 100644 --- a/src/core/ddsi/include/dds/ddsi/q_hbcontrol.h +++ b/src/core/ddsi/include/dds/ddsi/q_hbcontrol.h @@ -24,15 +24,15 @@ struct hbcontrol { nn_mtime_t t_of_last_hb; nn_mtime_t t_of_last_ackhb; nn_mtime_t tsched; - unsigned hbs_since_last_write; - unsigned last_packetid; + uint32_t hbs_since_last_write; + uint32_t last_packetid; }; void writer_hbcontrol_init (struct hbcontrol *hbc); int64_t writer_hbcontrol_intv (const struct writer *wr, const struct whc_state *whcst, nn_mtime_t tnow); void writer_hbcontrol_note_asyncwrite (struct writer *wr, nn_mtime_t tnow); int writer_hbcontrol_ack_required (const struct writer *wr, const struct whc_state *whcst, nn_mtime_t tnow); -struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_state *whcst, nn_mtime_t tnow, unsigned packetid, int *hbansreq); +struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_state *whcst, nn_mtime_t tnow, uint32_t packetid, int *hbansreq); int writer_hbcontrol_must_send (const struct writer *wr, const struct whc_state *whcst, nn_mtime_t tnow); struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const struct whc_state *whcst, nn_mtime_t tnow, int hbansreq, int issync); diff --git a/src/core/ddsi/include/dds/ddsi/q_lease.h b/src/core/ddsi/include/dds/ddsi/q_lease.h index a139075..fab3aaa 100644 --- a/src/core/ddsi/include/dds/ddsi/q_lease.h +++ b/src/core/ddsi/include/dds/ddsi/q_lease.h @@ -32,7 +32,7 @@ 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 (nn_etime_t tnow); -void handle_PMD (const struct receiver_state *rst, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len); +void handle_PMD (const struct receiver_state *rst, nn_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len); #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 90777d2..5fa789b 100644 --- a/src/core/ddsi/include/dds/ddsi/q_nwif.h +++ b/src/core/ddsi/include/dds/ddsi/q_nwif.h @@ -26,15 +26,15 @@ extern "C" { struct nn_interface { nn_locator_t loc; nn_locator_t netmask; - unsigned if_index; + uint32_t if_index; unsigned mc_capable: 1; unsigned point_to_point: 1; char *name; }; -int make_socket (ddsrt_socket_t *socket, unsigned short port, bool stream, bool reuse); +int make_socket (ddsrt_socket_t *socket, uint16_t port, bool stream, bool reuse); int find_own_ip (const char *requested_address); -unsigned locator_to_hopefully_unique_uint32 (const nn_locator_t *src); +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_thread.h b/src/core/ddsi/include/dds/ddsi/q_thread.h index 1377ae9..79c4c48 100644 --- a/src/core/ddsi/include/dds/ddsi/q_thread.h +++ b/src/core/ddsi/include/dds/ddsi/q_thread.h @@ -84,7 +84,7 @@ struct thread_state1 { struct thread_states { ddsrt_mutex_t lock; - unsigned nthreads; + uint32_t nthreads; struct thread_state1 *ts; /* [nthreads] */ }; diff --git a/src/core/ddsi/src/ddsi_threadmon.c b/src/core/ddsi/src/ddsi_threadmon.c index d687b9f..9af19c9 100644 --- a/src/core/ddsi/src/ddsi_threadmon.c +++ b/src/core/ddsi/src/ddsi_threadmon.c @@ -49,8 +49,7 @@ static uint32_t threadmon_thread (struct ddsi_threadmon *sl) nn_mtime_t next_thread_cputime = { 0 }; nn_mtime_t tlast = { 0 }; bool was_alive = true; - unsigned i; - for (i = 0; i < thread_states.nthreads; i++) + for (uint32_t i = 0; i < thread_states.nthreads; i++) { sl->av_ary[i].alive = true; } @@ -78,7 +77,7 @@ static uint32_t threadmon_thread (struct ddsi_threadmon *sl) else { tlast = tnow; - for (i = 0; i < thread_states.nthreads; i++) + for (uint32_t i = 0; i < thread_states.nthreads; i++) { if (thread_states.ts[i].state == THREAD_STATE_ZERO) n_unused++; diff --git a/src/core/ddsi/src/ddsi_tran.c b/src/core/ddsi/src/ddsi_tran.c index c1ef648..ceb2256 100644 --- a/src/core/ddsi/src/ddsi_tran.c +++ b/src/core/ddsi/src/ddsi_tran.c @@ -121,8 +121,7 @@ void ddsi_conn_free (ddsi_tran_conn_t conn) /* FIXME: rethink the socket waitset & the deleting of entries; the biggest issue is TCP handling that can open & close sockets at will and yet expects the waitset to wake up at the apprioriate times. (This pretty much works with the select-based version, but not the kqueue-based one.) TCP code can also have connections without a socket ... Calling sockWaitsetRemove here (where there shouldn't be any knowledge of it) at least ensures that it is removed in time and that there can't be aliasing of connections and sockets. */ if (ddsi_conn_handle (conn) != DDSRT_INVALID_SOCKET) { - unsigned i; - for (i = 0; i < gv.n_recv_threads; i++) + for (uint32_t i = 0; i < gv.n_recv_threads; i++) { if (!gv.recv_threads[i].ts) assert (!gv.rtps_keepgoing); diff --git a/src/core/ddsi/src/q_addrset.c b/src/core/ddsi/src/q_addrset.c index 1eeda78..ffd1d76 100644 --- a/src/core/ddsi/src/q_addrset.c +++ b/src/core/ddsi/src/q_addrset.c @@ -541,15 +541,13 @@ void addrset_forall (struct addrset *as, addrset_forall_fun_t f, void *arg) int addrset_forone (struct addrset *as, addrset_forone_fun_t f, void *arg) { - unsigned i; addrset_node_t n; ddsrt_avl_ctree_t *trees[2]; ddsrt_avl_citer_t iter; trees[0] = &as->mcaddrs; trees[1] = &as->ucaddrs; - - for (i = 0; i < 2u; i++) + for (int i = 0; i < 2; i++) { n = (addrset_node_t) ddsrt_avl_citer_first (&addrset_treedef, trees[i], &iter); while (n) diff --git a/src/core/ddsi/src/q_bswap.c b/src/core/ddsi/src/q_bswap.c index 2899b69..512c310 100644 --- a/src/core/ddsi/src/q_bswap.c +++ b/src/core/ddsi/src/q_bswap.c @@ -61,8 +61,8 @@ void bswap_sequence_number_set_hdr (nn_sequence_number_set_t *snset) void bswap_sequence_number_set_bitmap (nn_sequence_number_set_t *snset) { - unsigned i, n = (snset->numbits + 31) / 32; - for (i = 0; i < n; i++) + const uint32_t n = (snset->numbits + 31) / 32; + for (uint32_t i = 0; i < n; i++) snset->bits[i] = bswap4u (snset->bits[i]); } @@ -74,7 +74,7 @@ void bswap_fragment_number_set_hdr (nn_fragment_number_set_t *fnset) void bswap_fragment_number_set_bitmap (nn_fragment_number_set_t *fnset) { - unsigned i, n = (fnset->numbits + 31) / 32; - for (i = 0; i < n; i++) + const uint32_t n = (fnset->numbits + 31) / 32; + for (uint32_t i = 0; i < n; i++) fnset->bits[i] = bswap4u (fnset->bits[i]); } diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 60145a9..1fb1155 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -1703,7 +1703,7 @@ static int uf_networkAddresses (struct cfgst *cfgst, void *parent, struct cfgele { char *** const elem = cfg_address (cfgst, parent, cfgelem); char *copy; - unsigned count; + uint32_t count; /* First count how many addresses we have - but do it stupidly by counting commas and adding one (so two commas in a row are both @@ -1723,7 +1723,7 @@ static int uf_networkAddresses (struct cfgst *cfgst, void *parent, struct cfgele { char *cursor = copy, *tok; - unsigned idx = 0; + uint32_t idx = 0; while ((tok = ddsrt_strsep (&cursor, ",")) != NULL) { assert (idx < count); (*elem)[idx] = ddsrt_strdup (tok); @@ -2458,7 +2458,7 @@ static int sort_channels_check_nodups (struct config *cfg) structure, sorting is much easier in an array, and hence we convert back and forth. */ struct config_channel_listelem **ary, *c; - unsigned i, n; + uint32_t i, n; int result; n = 0; @@ -2469,7 +2469,7 @@ static int sort_channels_check_nodups (struct config *cfg) ary = ddsrt_malloc (n * sizeof (*ary)); i = 0; - for (c = cfg->channels; c; c = c->next) + for (c = cfg->channels; c; c = c->next) ary[i++] = c; qsort (ary, n, sizeof (*ary), sort_channels_cmp); diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 9e5b1a8..e9b6476 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -778,7 +778,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time return 1; } -static void handle_SPDP (const struct receiver_state *rst, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len) +static void handle_SPDP (const struct receiver_state *rst, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len) { const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ DDS_TRACE("SPDP ST%x", statusinfo); @@ -1321,7 +1321,7 @@ static void handle_SEDP_dead (nn_plist_t *datap, nn_wctime_t timestamp) DDS_LOG(DDS_LC_DISCOVERY, " %s\n", (res < 0) ? " unknown" : " delete"); } -static void handle_SEDP (const struct receiver_state *rst, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len) +static void handle_SEDP (const struct receiver_state *rst, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len) { const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ DDS_LOG(DDS_LC_DISCOVERY, "SEDP ST%x", statusinfo); @@ -1447,7 +1447,7 @@ int sedp_write_cm_participant (struct participant *pp, int alive) return ret; } -static void handle_SEDP_CM (const struct receiver_state *rst, nn_entityid_t wr_entity_id, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len) +static void handle_SEDP_CM (const struct receiver_state *rst, nn_entityid_t wr_entity_id, nn_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len) { const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ DDS_LOG(DDS_LC_DISCOVERY, "SEDP_CM ST%x", statusinfo); @@ -1611,7 +1611,7 @@ static void handle_SEDP_GROUP_dead (nn_plist_t *datap, nn_wctime_t timestamp) delete_proxy_group (&datap->group_guid, timestamp, 0); } -static void handle_SEDP_GROUP (const struct receiver_state *rst, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len) +static void handle_SEDP_GROUP (const struct receiver_state *rst, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len) { const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ DDS_LOG(DDS_LC_DISCOVERY, "SEDP_GROUP ST%x", statusinfo); diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index c555bc2..e5b87be 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -113,9 +113,8 @@ static int print_any_endpoint_common (ddsi_tran_conn_t conn, const char *label, x += cpf (conn, " %s %x:%x:%x:%x ", label, PGUID (e->guid)); if (xqos->present & QP_PARTITION) { - unsigned i; if (xqos->partition.n > 1) cpf (conn, "{"); - for (i = 0; i < xqos->partition.n; i++) + for (uint32_t i = 0; i < xqos->partition.n; i++) x += cpf (conn, "%s%s", i == 0 ? "" : ",", xqos->partition.strs[i]); if (xqos->partition.n > 1) cpf (conn, "}"); x += cpf (conn, ".%s/%s", diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index b34e167..a8eca66 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -218,7 +218,7 @@ void local_reader_ary_insert (struct local_reader_ary *x, struct reader *rd) void local_reader_ary_remove (struct local_reader_ary *x, struct reader *rd) { - unsigned i; + uint32_t i; ddsrt_mutex_lock (&x->rdary_lock); for (i = 0; i < x->n_readers; i++) { @@ -2709,16 +2709,13 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se wr->as_group = NULL; #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS - { - unsigned i; - /* This is an open issue how to encrypt mesages send for various - partitions that match multiple network partitions. From a safety - point of view a wierd configuration. Here we chose the first one - that we find */ - wr->partition_id = 0; - for (i = 0; i < wr->xqos->partition.n && wr->partition_id == 0; i++) - wr->partition_id = get_partitionid_from_mapping (wr->xqos->partition.strs[i], wr->xqos->topic_name); - } + /* This is an open issue how to encrypt mesages send for various + partitions that match multiple network partitions. From a safety + point of view a wierd configuration. Here we chose the first one + that we find */ + wr->partition_id = 0; + for (uint32_t i = 0; i < wr->xqos->partition.n && wr->partition_id == 0; i++) + wr->partition_id = get_partitionid_from_mapping (wr->xqos->partition.strs[i], wr->xqos->topic_name); #endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */ #ifdef DDSI_INCLUDE_SSM @@ -3128,12 +3125,11 @@ static void join_mcast_helper (const nn_locator_t *n, void * varg) nn_locator_t l = *n; nn_udpv4mcgen_address_t l1; uint32_t iph; - unsigned i; memcpy(&l1, l.address, sizeof(l1)); l.kind = NN_LOCATOR_KIND_UDPv4; memset(l.address, 0, 12); iph = ntohl(l1.ipv4.s_addr); - for (i = 1; i < (1u << l1.count); i++) + for (uint32_t i = 1; i < ((uint32_t)1 << l1.count); i++) { uint32_t ipn, iph1 = iph; if (i & (1u << l1.idx)) @@ -3170,12 +3166,11 @@ static void leave_mcast_helper (const nn_locator_t *n, void * varg) nn_locator_t l = *n; nn_udpv4mcgen_address_t l1; uint32_t iph; - unsigned i; memcpy(&l1, l.address, sizeof(l1)); l.kind = NN_LOCATOR_KIND_UDPv4; memset(l.address, 0, 12); iph = ntohl(l1.ipv4.s_addr); - for (i = 1; i < (1u << l1.count); i++) + for (uint32_t i = 1; i < ((uint32_t)1 << l1.count); i++) { uint32_t ipn, iph1 = iph; if (i & (1u << l1.idx)) @@ -3270,10 +3265,8 @@ static dds_return_t new_reader_guid rd->as = new_addrset (); if (config.allowMulticast & ~AMC_SPDP) { - unsigned i; - /* compile address set from the mapped network partitions */ - for (i = 0; i < rd->xqos->partition.n; i++) + for (uint32_t i = 0; i < rd->xqos->partition.n; i++) { struct addrset *pas = get_as_from_mapping (rd->xqos->partition.strs[i], rd->xqos->topic_name); if (pas) @@ -3483,7 +3476,7 @@ void new_proxy_participant struct addrset *as_default, struct addrset *as_meta, const nn_plist_t *plist, - int64_t tlease_dur, + dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp @@ -3538,7 +3531,7 @@ void new_proxy_participant { /* Lease duration is meaningless when the lease never expires, but when proxy participants are created implicitly because of endpoint discovery from a cloud service, we do want the lease to expire eventually when the cloud discovery service disappears and never reappears. The normal data path renews the lease, so if the lease expiry is changed after the DS disappears but data continues to flow (even if it is only a single sample) the proxy participant would immediately go back to a non-expiring lease with no further triggers for deleting it. Instead, we take tlease_dur == NEVER as a special value meaning a lease that doesn't expire now and that has a "reasonable" lease duration. That way the lease renewal in the data path is fine, and we only need to do something special in SEDP handling. */ nn_etime_t texp = add_duration_to_etime (now_et(), tlease_dur); - int64_t dur = (tlease_dur == T_NEVER) ? config.lease_duration : tlease_dur; + dds_duration_t dur = (tlease_dur == T_NEVER) ? config.lease_duration : tlease_dur; ddsrt_atomic_stvoidp (&proxypp->lease, lease_new (texp, dur, &proxypp->e)); proxypp->owns_lease = 1; } diff --git a/src/core/ddsi/src/q_gc.c b/src/core/ddsi/src/q_gc.c index 42fc0ef..0aff75b 100644 --- a/src/core/ddsi/src/q_gc.c +++ b/src/core/ddsi/src/q_gc.c @@ -41,7 +41,7 @@ struct gcreq_queue { static void threads_vtime_gather_for_wait (unsigned *nivs, struct idx_vtime *ivs) { /* copy vtimes of threads, skipping those that are sleeping */ - unsigned i, j; + uint32_t i, j; for (i = j = 0; i < thread_states.nthreads; i++) { vtime_t vtime = thread_states.ts[i].vtime; @@ -55,14 +55,14 @@ static void threads_vtime_gather_for_wait (unsigned *nivs, struct idx_vtime *ivs *nivs = j; } -static int threads_vtime_check (unsigned *nivs, struct idx_vtime *ivs) +static int threads_vtime_check (uint32_t *nivs, struct idx_vtime *ivs) { /* check all threads in ts have made progress those that have are removed from the set */ - unsigned i = 0; + uint32_t i = 0; while (i < *nivs) { - unsigned thridx = ivs[i].idx; + uint32_t thridx = ivs[i].idx; vtime_t vtime = thread_states.ts[thridx].vtime; assert (vtime_awake_p (ivs[i].vtime)); if (!vtime_gt (vtime, ivs[i].vtime)) diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 9abc779..e551bd0 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -705,7 +705,6 @@ static void wait_for_receive_threads_helper (struct xevent *xev, void *varg, nn_ static void wait_for_receive_threads (void) { struct xevent *trigev; - unsigned i; struct wait_for_receive_threads_helper_arg cbarg; cbarg.count = 0; if ((trigev = qxev_callback (add_duration_to_mtime (now_mt (), T_SECOND), wait_for_receive_threads_helper, &cbarg)) == NULL) @@ -715,7 +714,7 @@ static void wait_for_receive_threads (void) dropping the packets until the user approves. */ DDS_WARNING("wait_for_receive_threads: failed to schedule periodic triggering of the receive threads to deal with packet loss\n"); } - for (i = 0; i < gv.n_recv_threads; i++) + for (uint32_t i = 0; i < gv.n_recv_threads; i++) { if (gv.recv_threads[i].ts) { @@ -766,8 +765,7 @@ static void free_special_topics (void) static int setup_and_start_recv_threads (void) { - unsigned i; - for (i = 0; i < MAX_RECV_THREADS; i++) + for (uint32_t i = 0; i < MAX_RECV_THREADS; i++) { gv.recv_threads[i].ts = NULL; gv.recv_threads[i].arg.mode = RTM_SINGLE; @@ -806,7 +804,7 @@ static int setup_and_start_recv_threads (void) assert (gv.n_recv_threads <= MAX_RECV_THREADS); /* For each thread, create rbufpool and waitset if needed, then start it */ - for (i = 0; i < gv.n_recv_threads; i++) + for (uint32_t i = 0; i < gv.n_recv_threads; i++) { /* We create the rbufpool for the receive thread, and so we'll become the initial owner thread. The receive thread will change @@ -836,7 +834,7 @@ fail: /* to trigger any threads we already started to stop - xevent thread has already been started */ rtps_term_prep (); wait_for_receive_threads (); - for (i = 0; i < gv.n_recv_threads; i++) + for (uint32_t i = 0; i < gv.n_recv_threads; i++) { if (gv.recv_threads[i].arg.mode == RTM_MANY && gv.recv_threads[i].arg.u.many.ws) os_sockWaitsetFree (gv.recv_threads[i].arg.u.many.ws); @@ -1617,14 +1615,11 @@ void rtps_fini (void) been dropped, which only happens once all receive threads have stopped, defrags and reorders have been freed, and all delivery queues been drained. I.e., until very late in the game. */ + for (uint32_t i = 0; i < gv.n_recv_threads; i++) { - unsigned i; - for (i = 0; i < gv.n_recv_threads; i++) - { - if (gv.recv_threads[i].arg.mode == RTM_MANY) - os_sockWaitsetFree (gv.recv_threads[i].arg.u.many.ws); - nn_rbufpool_free (gv.recv_threads[i].arg.rbpool); - } + if (gv.recv_threads[i].arg.mode == RTM_MANY) + os_sockWaitsetFree (gv.recv_threads[i].arg.u.many.ws); + nn_rbufpool_free (gv.recv_threads[i].arg.rbpool); } ddsi_tkmap_free (gv.m_tkmap); diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index 4ec8892..d0dc03b 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -47,7 +47,7 @@ struct lease { ddsrt_fibheap_node_t heapnode; nn_etime_t tsched; /* access guarded by leaseheap_lock */ nn_etime_t tend; /* access guarded by lock_lease/unlock_lease */ - int64_t tdur; /* constant (renew depends on it) */ + dds_duration_t tdur; /* constant (renew depends on it) */ struct entity_common *entity; /* constant */ }; @@ -89,7 +89,7 @@ static ddsrt_mutex_t *lock_lease_addr (struct lease const * const l) { uint32_t u = (uint16_t) ((uintptr_t) l >> 3); uint32_t v = u * 0xb4817365; - unsigned idx = v >> (32 - N_LEASE_LOCKS_LG2); + uint32_t idx = v >> (32 - N_LEASE_LOCKS_LG2); return &gv.lease_locks[idx]; } @@ -103,7 +103,7 @@ static void unlock_lease (const struct lease *l) ddsrt_mutex_unlock (lock_lease_addr (l)); } -struct lease *lease_new (nn_etime_t texpire, int64_t tdur, struct entity_common *e) +struct lease *lease_new (nn_etime_t texpire, dds_duration_t tdur, struct entity_common *e) { struct lease *l; if ((l = ddsrt_malloc (sizeof (*l))) == NULL) @@ -327,7 +327,7 @@ static void debug_print_rawdata (const char *msg, const void *data, size_t len) DDS_TRACE(">"); } -void handle_PMD (UNUSED_ARG (const struct receiver_state *rst), nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len) +void handle_PMD (UNUSED_ARG (const struct receiver_state *rst), nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len) { const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ const int bswap = (data->identifier == CDR_LE) ^ (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN); @@ -348,8 +348,8 @@ void handle_PMD (UNUSED_ARG (const struct receiver_state *rst), nn_wctime_t time { const ParticipantMessageData_t *pmd = (ParticipantMessageData_t *) (data + 1); nn_guid_prefix_t p = nn_ntoh_guid_prefix (pmd->participantGuidPrefix); - unsigned kind = ntohl (pmd->kind); - unsigned length = bswap ? bswap4u (pmd->length) : pmd->length; + uint32_t kind = ntohl (pmd->kind); + uint32_t length = bswap ? bswap4u (pmd->length) : pmd->length; DDS_TRACE(" pp %"PRIx32":%"PRIx32":%"PRIx32" kind %u data %u", p.u[0], p.u[1], p.u[2], kind, length); if (len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value) < length) debug_print_rawdata (" SHORT2", pmd->value, len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value)); @@ -374,7 +374,7 @@ void handle_PMD (UNUSED_ARG (const struct receiver_state *rst), nn_wctime_t time case NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER: /* Serialized key; BE or LE doesn't matter as both fields are defined as octets. */ - if (len < (int) (sizeof (struct CDRHeader) + sizeof (nn_guid_prefix_t))) + if (len < sizeof (struct CDRHeader) + sizeof (nn_guid_prefix_t)) debug_print_rawdata (" SHORT3", data, len); else { diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index 839eacf..87b2acd 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -38,9 +38,9 @@ static void print_sockerror (const char *msg) DDS_ERROR("SOCKET %s\n", msg); } -unsigned locator_to_hopefully_unique_uint32 (const nn_locator_t *src) +uint32_t locator_to_hopefully_unique_uint32 (const nn_locator_t *src) { - unsigned id = 0; + uint32_t id = 0; if (src->kind == NN_LOCATOR_KIND_UDPv4 || src->kind == NN_LOCATOR_KIND_TCPv4) memcpy (&id, src->address + 12, sizeof (id)); else @@ -342,7 +342,7 @@ static int set_mc_options_transmit (ddsrt_socket_t socket) int make_socket ( ddsrt_socket_t * sock, - unsigned short port, + uint16_t port, bool stream, bool reuse ) diff --git a/src/core/ddsi/src/q_qosmatch.c b/src/core/ddsi/src/q_qosmatch.c index ec2afd1..70b02fe 100644 --- a/src/core/ddsi/src/q_qosmatch.c +++ b/src/core/ddsi/src/q_qosmatch.c @@ -37,10 +37,9 @@ static int partition_patmatch_p (const char *pat, const char *name) static int partitions_match_default (const dds_qos_t *x) { - unsigned i; if (!(x->present & QP_PARTITION) || x->partition.n == 0) return 1; - for (i = 0; i < x->partition.n; i++) + for (uint32_t i = 0; i < x->partition.n; i++) if (partition_patmatch_p (x->partition.strs[i], "")) return 1; return 0; @@ -54,9 +53,8 @@ int partitions_match_p (const dds_qos_t *a, const dds_qos_t *b) return partitions_match_default (a); else { - unsigned i, j; - for (i = 0; i < a->partition.n; i++) - for (j = 0; j < b->partition.n; j++) + for (uint32_t i = 0; i < a->partition.n; i++) + for (uint32_t j = 0; j < b->partition.n; j++) { if (partition_patmatch_p (a->partition.strs[i], b->partition.strs[j]) || partition_patmatch_p (b->partition.strs[j], a->partition.strs[i])) diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index b4f5176..60bdab7 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -679,7 +679,6 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac seqno_t max_seq_in_reply; struct whc_node *deferred_free_list = NULL; struct whc_state whcst; - unsigned i; int hb_sent_in_response = 0; memset (gapbits, 0, sizeof (gapbits)); countp = (nn_count_t *) ((char *) msg + offsetof (AckNack_t, readerSNState) + @@ -690,7 +689,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac dst.entityid = msg->writerId; DDS_TRACE("ACKNACK(%s#%"PRId32":%"PRId64"/%"PRIu32":", msg->smhdr.flags & ACKNACK_FLAG_FINAL ? "F" : "", *countp, fromSN (msg->readerSNState.bitmap_base), msg->readerSNState.numbits); - for (i = 0; i < msg->readerSNState.numbits; i++) + for (uint32_t i = 0; i < msg->readerSNState.numbits; i++) DDS_TRACE("%c", nn_bitset_isset (msg->readerSNState.numbits, msg->readerSNState.bits, i) ? '1' : '0'); seqbase = fromSN (msg->readerSNState.bitmap_base); @@ -889,7 +888,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac seq_xmit = READ_SEQ_XMIT(wr); const bool gap_for_already_acked = vendor_is_eclipse (rst->vendor) && prd->c.xqos->durability.kind == DDS_DURABILITY_VOLATILE && seqbase <= rn->seq; const seqno_t min_seq_to_rexmit = gap_for_already_acked ? rn->seq + 1 : 0; - for (i = 0; i < numbits && seqbase + i <= seq_xmit && enqueued; i++) + for (uint32_t i = 0; i < numbits && seqbase + i <= seq_xmit && enqueued; i++) { /* Accelerated schedule may run ahead of sequence number set contained in the acknack, and assumes all messages beyond the @@ -954,7 +953,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac } else if (seqbase + i - gapend < 256) { - unsigned idx = (unsigned) (seqbase + i - gapend); + uint32_t idx = (uint32_t) (seqbase + i - gapend); DDS_TRACE(" M%"PRId64, seqbase + i); gapnumbits = idx + 1; nn_bitset_set (gapnumbits, gapbits, idx); @@ -989,7 +988,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac if (gapend-1 + gapnumbits > max_seq_in_reply) max_seq_in_reply = gapend-1 + gapnumbits; DDS_TRACE(" XGAP%"PRId64"..%"PRId64"/%u:", gapstart, gapend, gapnumbits); - for (i = 0; i < gapnumbits; i++) + for (uint32_t i = 0; i < gapnumbits; i++) DDS_TRACE("%c", nn_bitset_isset (gapnumbits, gapbits, i) ? '1' : '0'); m = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_CONTROL); #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS @@ -1421,7 +1420,6 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N nn_guid_t src, dst; nn_count_t *countp; seqno_t seq = fromSN (msg->writerSN); - unsigned i; countp = (nn_count_t *) ((char *) msg + offsetof (NackFrag_t, fragmentNumberState) + NN_FRAGMENT_NUMBER_SET_SIZE (msg->fragmentNumberState.numbits)); src.prefix = rst->src_guid_prefix; @@ -1430,7 +1428,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N dst.entityid = msg->writerId; DDS_TRACE("NACKFRAG(#%"PRId32":%"PRId64"/%u/%"PRIu32":", *countp, seq, msg->fragmentNumberState.bitmap_base, msg->fragmentNumberState.numbits); - for (i = 0; i < msg->fragmentNumberState.numbits; i++) + for (uint32_t i = 0; i < msg->fragmentNumberState.numbits; i++) DDS_TRACE("%c", nn_bitset_isset (msg->fragmentNumberState.numbits, msg->fragmentNumberState.bits, i) ? '1' : '0'); if (!rst->forme) @@ -1487,7 +1485,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N const unsigned base = msg->fragmentNumberState.bitmap_base - 1; int enqueued = 1; DDS_TRACE(" scheduling requested frags ...\n"); - for (i = 0; i < msg->fragmentNumberState.numbits && enqueued; i++) + for (uint32_t i = 0; i < msg->fragmentNumberState.numbits && enqueued; i++) { if (nn_bitset_isset (msg->fragmentNumberState.numbits, msg->fragmentNumberState.bits, i)) { @@ -1670,8 +1668,8 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm struct pwr_rd_match *wn; nn_guid_t src, dst; seqno_t gapstart, listbase; - int64_t last_included_rel; - unsigned listidx; + int32_t last_included_rel; + uint32_t listidx; src.prefix = rst->src_guid_prefix; src.entityid = msg->writerId; @@ -1687,7 +1685,7 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm for (listidx = 0; listidx < msg->gapList.numbits; listidx++) if (!nn_bitset_isset (msg->gapList.numbits, msg->gapList.bits, listidx)) break; - last_included_rel = (int)listidx - 1; + last_included_rel = (int32_t) listidx - 1; if (!rst->forme) { @@ -1741,8 +1739,8 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm listidx++; else { - unsigned j; - for (j = listidx+1; j < msg->gapList.numbits; j++) + uint32_t j; + for (j = listidx + 1; j < msg->gapList.numbits; j++) if (!nn_bitset_isset (msg->gapList.numbits, msg->gapList.bits, j)) break; /* spec says gapList (2) identifies an additional list of sequence numbers that @@ -1750,7 +1748,7 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm initial interval is to be ignored and the bitmap to be applied */ (void) handle_one_gap (pwr, wn, listbase + listidx, listbase + j, gap, &refc_adjust); assert(j >= 1); - last_included_rel = j - 1; + last_included_rel = (int32_t) j - 1; listidx = j; } } @@ -2010,8 +2008,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st if (pwr->rdary.fastpath_ok) { struct reader ** const rdary = pwr->rdary.rdary; - unsigned i; - for (i = 0; rdary[i]; i++) + for (uint32_t i = 0; rdary[i]; i++) { DDS_TRACE("reader "PGUIDFMT"\n", PGUID (rdary[i]->e.guid)); if (! (ddsi_plugin.rhc_plugin.rhc_store_fn) (rdary[i]->rhc, &pwr_info, payload, tk)) @@ -3120,7 +3117,7 @@ static size_t dedup_sorted_array (void *base, size_t nel, size_t width, int (*co struct local_participant_set { struct local_participant_desc *ps; - unsigned nps; + uint32_t nps; uint32_t gen; }; @@ -3222,10 +3219,9 @@ uint32_t listen_thread (struct ddsi_tran_listener * listener) static int recv_thread_waitset_add_conn (os_sockWaitset ws, ddsi_tran_conn_t conn) { - unsigned i; if (conn == NULL) return 0; - for (i = 0; i < gv.n_recv_threads; i++) + 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; return os_sockWaitsetAdd (ws, conn); @@ -3324,8 +3320,7 @@ static int check_and_handle_deafness(struct local_deaf_state *st, unsigned num_f void trigger_recv_threads (void) { - unsigned i; - for (i = 0; i < gv.n_recv_threads; i++) + for (uint32_t i = 0; i < gv.n_recv_threads; i++) { if (gv.recv_threads[i].ts == NULL) continue; @@ -3373,7 +3368,6 @@ uint32_t recv_thread (void *vrecv_thread_arg) struct local_participant_set lps; unsigned num_fixed = 0, num_fixed_uc = 0; os_sockWaitsetCtx ctx; - unsigned i; struct local_deaf_state lds; lds.state = gv.deaf ? LDSR_DEAF : LDSR_NORMAL; lds.tnext = now_mt(); @@ -3416,7 +3410,7 @@ uint32_t recv_thread (void *vrecv_thread_arg) only happens when the participant set has changed, so might as well rebuild it */ rebuild_local_participant_set (ts1, &lps); os_sockWaitsetPurge (waitset, num_fixed); - for (i = 0; i < lps.nps; i++) + for (uint32_t i = 0; i < lps.nps; i++) { if (lps.ps[i].m_conn) os_sockWaitsetAdd (waitset, lps.ps[i].m_conn); diff --git a/src/core/ddsi/src/q_security.c b/src/core/ddsi/src/q_security.c index 000ba0d..0a94204 100644 --- a/src/core/ddsi/src/q_security.c +++ b/src/core/ddsi/src/q_security.c @@ -1658,14 +1658,13 @@ static os_ssize_t q_security_sendmsg uint32_t sz32, data_size32; ssize_t ret = DDS_RETCODE_ERROR; PT_InfoContainer_t * securityHeader; - unsigned i; assert (niov > 2); securityHeader = iov[1].iov_base; /* first determine the size of the message, then select the on-stack buffer or allocate one on the heap ... */ sz = q_securityEncoderSetHeaderSize (*codec); /* reserve appropriate headersize */ - for (i = 2; i < niov; i++) + for (uint32_t i = 2; i < niov; i++) { sz += iov[i].iov_len; } @@ -1679,7 +1678,7 @@ static os_ssize_t q_security_sendmsg } /* ... then copy data into buffer */ data_size = 0; - for (i = 2; i < niov; i++) + for (uint32_t i = 2; i < niov; i++) { memcpy (buf + data_size, iov[i].iov_base, iov[i].iov_len); data_size += iov[i].iov_len; diff --git a/src/core/ddsi/src/q_sockwaitset.c b/src/core/ddsi/src/q_sockwaitset.c index c1876d5..4284b0b 100644 --- a/src/core/ddsi/src/q_sockwaitset.c +++ b/src/core/ddsi/src/q_sockwaitset.c @@ -311,9 +311,7 @@ os_sockWaitset os_sockWaitsetNew (void) void os_sockWaitsetFree (os_sockWaitset ws) { - unsigned i; - - for (i = 0; i < ws->ctx.n; i++) + for (unsigned i = 0; i < ws->ctx.n; i++) { WSACloseEvent (ws->ctx.events[i]); } @@ -323,10 +321,8 @@ void os_sockWaitsetFree (os_sockWaitset ws) void os_sockWaitsetPurge (os_sockWaitset ws, unsigned index) { - unsigned i; - ddsrt_mutex_lock (&ws->mutex); - for (i = index + 1; i < ws->ctx.n; i++) + for (unsigned i = index + 1; i < ws->ctx.n; i++) { ws->ctx.conns[i] = NULL; if (!WSACloseEvent (ws->ctx.events[i])) @@ -340,10 +336,8 @@ void os_sockWaitsetPurge (os_sockWaitset ws, unsigned index) void os_sockWaitsetRemove (os_sockWaitset ws, ddsi_tran_conn_t conn) { - unsigned i; - ddsrt_mutex_lock (&ws->mutex); - for (i = 0; i < ws->ctx.n; i++) + for (unsigned i = 0; i < ws->ctx.n; i++) { if (conn == ws->ctx.conns[i]) { @@ -805,13 +799,12 @@ int os_sockWaitsetAdd (os_sockWaitset ws, ddsi_tran_conn_t conn) void os_sockWaitsetPurge (os_sockWaitset ws, unsigned index) { - unsigned i; os_sockWaitsetSet * set = &ws->set; ddsrt_mutex_lock (&ws->mutex); if (index + 1 <= set->n) { - for (i = index + 1; i < set->n; i++) + for (unsigned i = index + 1; i < set->n; i++) { set->conns[i] = NULL; set->fds[i] = 0; @@ -823,11 +816,10 @@ void os_sockWaitsetPurge (os_sockWaitset ws, unsigned index) void os_sockWaitsetRemove (os_sockWaitset ws, ddsi_tran_conn_t conn) { - unsigned i; os_sockWaitsetSet * set = &ws->set; ddsrt_mutex_lock (&ws->mutex); - for (i = 0; i < set->n; i++) + for (unsigned i = 0; i < set->n; i++) { if (conn == set->conns[i]) { diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index ca0ae3f..08b5de1 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -82,8 +82,6 @@ void thread_states_init_static (void) void thread_states_init (unsigned maxthreads) { - unsigned i; - ddsrt_mutex_init (&thread_states.lock); thread_states.nthreads = maxthreads; thread_states.ts = @@ -91,7 +89,7 @@ void thread_states_init (unsigned maxthreads) memset (thread_states.ts, 0, maxthreads * sizeof (*thread_states.ts)); /* The compiler doesn't realize that ts is large enough. */ DDSRT_WARNING_MSVC_OFF(6386); - for (i = 0; i < thread_states.nthreads; i++) + for (uint32_t i = 0; i < thread_states.nthreads; i++) { thread_states.ts[i].state = THREAD_STATE_ZERO; thread_states.ts[i].vtime = 0u; @@ -102,8 +100,7 @@ void thread_states_init (unsigned maxthreads) void thread_states_fini (void) { - unsigned i; - for (i = 0; i < thread_states.nthreads; i++) + for (uint32_t i = 0; i < thread_states.nthreads; i++) assert (thread_states.ts[i].state != THREAD_STATE_ALIVE); ddsrt_mutex_destroy (&thread_states.lock); ddsrt_free_aligned (thread_states.ts); @@ -119,11 +116,10 @@ void thread_states_fini (void) static struct thread_state1 *find_thread_state (ddsrt_thread_t tid) { if (thread_states.ts) { - unsigned i; - for (i = 0; i < thread_states.nthreads; i++) { - if (ddsrt_thread_equal (thread_states.ts[i].tid, tid)) { + for (uint32_t i = 0; i < thread_states.nthreads; i++) + { + if (ddsrt_thread_equal (thread_states.ts[i].tid, tid)) return &thread_states.ts[i]; - } } } return NULL; @@ -195,7 +191,7 @@ static uint32_t create_thread_wrapper (void *ptr) static int find_free_slot (const char *name) { - for (unsigned i = 0; i < thread_states.nthreads; i++) + for (uint32_t i = 0; i < thread_states.nthreads; i++) if (thread_states.ts[i].state == THREAD_STATE_ZERO) return (int) i; DDS_FATAL("create_thread: %s: no free slot\n", name ? name : "(anon)"); @@ -329,13 +325,8 @@ void downgrade_main_thread (void) void log_stack_traces (void) { - unsigned i; - for (i = 0; i < thread_states.nthreads; i++) - { + for (uint32_t i = 0; i < thread_states.nthreads; i++) if (thread_states.ts[i].state != THREAD_STATE_ZERO) - { log_stacktrace (thread_states.ts[i].name, thread_states.ts[i].tid); - } - } } diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index c6f85aa..8ecedf8 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -270,10 +270,10 @@ int writer_hbcontrol_ack_required (const struct writer *wr, const struct whc_sta return writer_hbcontrol_ack_required_generic (wr, whcst, hbc->t_of_last_write, tnow, 0); } -struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_state *whcst, nn_mtime_t tnow, unsigned packetid, int *hbansreq) +struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_state *whcst, nn_mtime_t tnow, uint32_t packetid, int *hbansreq) { struct hbcontrol * const hbc = &wr->hbcontrol; - unsigned last_packetid; + uint32_t last_packetid; nn_mtime_t tlast; struct nn_xmsg *msg; @@ -691,16 +691,15 @@ 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, unsigned nfrags) +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) { - unsigned i; #if 0 const char *frags_to_skip = getenv ("SKIPFRAGS"); #endif assert(xp); assert((wr->heartbeat_xevent != NULL) == (whcst != NULL)); - for (i = 0; i < nfrags; i++) + for (uint32_t i = 0; i < nfrags; i++) { struct nn_xmsg *fmsg = NULL; struct nn_xmsg *hmsg = NULL; diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index baaf10f..7698d12 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -703,9 +703,8 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p struct nn_reorder *reorder; AckNack_t *an; struct nn_xmsg_marker sm_marker; - unsigned i, numbits; + uint32_t i, numbits; seqno_t base; - unsigned ui; union { struct nn_fragment_number_set set; @@ -808,7 +807,7 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p DDS_TRACE("acknack "PGUIDFMT" -> "PGUIDFMT": #%"PRId32":%"PRId64"/%"PRIu32":", PGUID (rwn->rd_guid), PGUID (pwr->e.guid), rwn->count, base, an->readerSNState.numbits); - for (ui = 0; ui != an->readerSNState.numbits; ui++) + for (uint32_t ui = 0; ui != an->readerSNState.numbits; ui++) DDS_TRACE("%c", nn_bitset_isset (numbits, an->readerSNState.bits, ui) ? '1' : '0'); } @@ -837,7 +836,7 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p nn_xmsg_submsg_setnext (msg, sm_marker); DDS_TRACE(" + nackfrag #%"PRId32":%"PRId64"/%u/%"PRIu32":", *countp, fromSN (nf->writerSN), nf->fragmentNumberState.bitmap_base, nf->fragmentNumberState.numbits); - for (ui = 0; ui != nf->fragmentNumberState.numbits; ui++) + for (uint32_t ui = 0; ui != nf->fragmentNumberState.numbits; ui++) DDS_TRACE("%c", nn_bitset_isset (nf->fragmentNumberState.numbits, nf->fragmentNumberState.bits, ui) ? '1' : '0'); } } @@ -1071,8 +1070,8 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e /* schedule next when 80% of the interval has elapsed, or 2s before the lease ends, whichever comes first (similar to PMD), but never wait longer than spdp_interval */ - const int64_t mindelta = 10 * T_MILLISECOND; - const int64_t ldur = pp->lease_duration; + const dds_duration_t mindelta = 10 * T_MILLISECOND; + const dds_duration_t ldur = pp->lease_duration; nn_mtime_t tnext; int64_t intv; @@ -1134,7 +1133,7 @@ static void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_xpack *xp, struct xevent *ev, nn_mtime_t tnow) { struct participant *pp; - int64_t intv; + dds_duration_t intv; nn_mtime_t tnext; if ((pp = ephash_lookup_participant_guid (&ev->u.pmd_update.pp_guid)) == NULL) diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 924c663..7e8d77d 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -784,19 +784,18 @@ size_t nn_xmsg_add_string_padded(unsigned char *buf, char *str) size_t nn_xmsg_add_octseq_padded(unsigned char *buf, ddsi_octetseq_t *seq) { - unsigned len = seq->length; + uint32_t len = seq->length; if (buf) { /* Add cdr octet seq */ - *((unsigned *)buf) = len; - buf += sizeof (int); + *((uint32_t *) buf) = len; + buf += sizeof (uint32_t); memcpy (buf, seq->value, len); /* clear padding */ if (len < align4u (len)) { memset (buf + len, 0, align4u (len) - len); } } - return 4 + /* cdr sequence len arg + */ - align4u(len); /* seqlen + possible padding */ + return 4 + align4u (len); } void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len) @@ -964,9 +963,8 @@ void nn_xmsg_addpar_subscription_keys (struct nn_xmsg *m, nn_parameterid_t pid, { unsigned char *tmp; size_t len = 8; /* use_key_list, length of key_list */ - unsigned i; - for (i = 0; i < q->key_list.n; i++) + for (uint32_t i = 0; i < q->key_list.n; i++) { size_t len1 = strlen (q->key_list.strs[i]) + 1; len += 4 + align4u (len1); @@ -975,14 +973,14 @@ void nn_xmsg_addpar_subscription_keys (struct nn_xmsg *m, nn_parameterid_t pid, tmp = nn_xmsg_addpar (m, pid, len); tmp[0] = q->use_key_list; - for (i = 1; i < sizeof (int); i++) + for (uint32_t i = 1; i < sizeof (int); i++) { tmp[i] = 0; } tmp += sizeof (int); *((uint32_t *) tmp) = q->key_list.n; tmp += sizeof (uint32_t); - for (i = 0; i < q->key_list.n; i++) + for (uint32_t i = 0; i < q->key_list.n; i++) { struct cdrstring *p = (struct cdrstring *) tmp; size_t len1 = strlen (q->key_list.strs[i]) + 1; diff --git a/src/ddsrt/src/fibheap.c b/src/ddsrt/src/fibheap.c index 2e3bcf8..e9b122b 100644 --- a/src/ddsrt/src/fibheap.c +++ b/src/ddsrt/src/fibheap.c @@ -207,7 +207,7 @@ void *ddsrt_fibheap_extract_min (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap keys anyway to find the minimum */ { ddsrt_fibheap_node_t *mark, *cursor, *newmin; - unsigned i; + uint32_t i; for (i = 0; roots[i] == NULL; i++) { assert (i+1 < min_degree_noninit); } From 8ae81db490f5502eb98e009db1fe46a42bdd1828 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 2 Jun 2019 21:11:50 +0200 Subject: [PATCH 087/178] Add get_matched_{publication,subscription}_... The implementation is provisional (too inefficient), but it works. Signed-off-by: Erik Boasson --- src/core/ddsc/CMakeLists.txt | 1 + src/core/ddsc/include/dds/dds.h | 134 +++++++++++++++++++ src/core/ddsc/src/dds_matched.c | 220 ++++++++++++++++++++++++++++++++ 3 files changed, 355 insertions(+) create mode 100644 src/core/ddsc/src/dds_matched.c diff --git a/src/core/ddsc/CMakeLists.txt b/src/core/ddsc/CMakeLists.txt index 9c0d16d..084d4c9 100644 --- a/src/core/ddsc/CMakeLists.txt +++ b/src/core/ddsc/CMakeLists.txt @@ -24,6 +24,7 @@ PREPEND(srcs_ddsc "${CMAKE_CURRENT_LIST_DIR}/src" dds_qos.c dds_handles.c dds_entity.c + dds_matched.c dds_querycond.c dds_topic.c dds_listener.c diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index ec2e321..4e3233f 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -3061,6 +3061,140 @@ dds_triggered(dds_entity_t entity); DDS_EXPORT dds_entity_t dds_get_topic(dds_entity_t entity); +/** + * @brief Get instance handles of the data readers matching a writer + * + * This operation fills the provided array with the instance handles + * of the data readers that match the writer. On successful output, + * the number of entries of "rds" set is the minimum of the return + * value and the value of "nrds". + * + * @param[in] writer The writer. + * @param[in] rds The array to be filled. + * @param[in] nrds The size of the rds array, at most the first + * nrds entries will be filled. rds = NULL and nrds = 0 + * is a valid way of determining the number of matched + * readers, but inefficient compared to relying on the + * matched publication status. + * + * @returns A dds_return_t indicating the number of matched readers + * or failure. The return value may be larger than nrds + * if there are more matching readers than the array can + * hold. + * + * @retval >=0 + * The number of matching readers. + * @retval DDS_RETCODE_BAD_PARAMETER + * The entity parameter is not valid or rds = NULL and + * nrds > 0. + * @retval DDS_RETCODE_ILLEGAL_OPERATION + * The operation is invoked on an inappropriate object. + */ +DDS_EXPORT dds_return_t +dds_get_matched_subscriptions ( + dds_entity_t writer, + dds_instance_handle_t *rds, + size_t nrds); + +/** + * @brief Get a description of a reader matched with the provided + * writer + * + * This operation looks up the reader instance handle in the set of + * readers matched with the specified writer, returning a freshly + * allocated sample of the DCPSSubscription built-in topic if found, + * and NULL if not. The caller is responsible for freeing the + * memory allocated. + * + * This operation is similar to performing a read of the given + * instance handle on a reader of the DCPSSubscription built-in + * topic, but this operation additionally filters on whether the + * reader is matched by the provided writer. + * + * @param[in] writer The writer. + * @param[in] ih The instance handle of a reader. + * + * @returns A newly allocated sample containing the information on the + * reader, or a NULL pointer for any kind of failure. + * + * @retval != NULL + * The requested data + * @retval NULL + * The writer is not valid or ih is not an instance handle + * of a matched reader. + */ +DDS_EXPORT dds_builtintopic_endpoint_t * +dds_get_matched_subscription_data ( + dds_entity_t writer, + dds_instance_handle_t ih); + +/** + * @brief Get instance handles of the data writers matching a reader + * + * This operation fills the provided array with the instance handles + * of the data writers that match the reader. On successful output, + * the number of entries of "wrs" set is the minimum of the return + * value and the value of "nwrs". + * + * @param[in] reader The reader. + * @param[in] wrs The array to be filled. + * @param[in] nwrs The size of the wrs array, at most the first + * nwrs entries will be filled. wrs = NULL and wrds = 0 + * is a valid way of determining the number of matched + * readers, but inefficient compared to relying on the + * matched publication status. + * + * @returns A dds_return_t indicating the number of matched writers + * or failure. The return value may be larger than nwrs + * if there are more matching writers than the array can + * hold. + * + * @retval >=0 + * The number of matching writers. + * @retval DDS_RETCODE_BAD_PARAMETER + * The entity parameter is not valid or wrs = NULL and + * nwrs > 0. + * @retval DDS_RETCODE_ILLEGAL_OPERATION + * The operation is invoked on an inappropriate object. + */ +DDS_EXPORT dds_return_t +dds_get_matched_publications ( + dds_entity_t reader, + dds_instance_handle_t *wrs, + size_t nwrs); + +/** + * @brief Get a description of a writer matched with the provided + * reader + * + * This operation looks up the writer instance handle in the set of + * writers matched with the specified reader, returning a freshly + * allocated sample of the DCPSPublication built-in topic if found, + * and NULL if not. The caller is responsible for freeing the + * memory allocated. + * + * This operation is similar to performing a read of the given + * instance handle on a reader of the DCPSPublication built-in + * topic, but this operation additionally filters on whether the + * writer is matched by the provided reader. + * + * @param[in] reader The reader. + * @param[in] ih The instance handle of a writer. + * + * @returns A newly allocated sample containing the information on the + * writer, or a NULL pointer for any kind of failure. + * + * @retval != NULL + * The requested data + * @retval NULL + * The reader is not valid or ih is not an instance handle + * of a matched writer. + */ +DDS_EXPORT dds_builtintopic_endpoint_t * +dds_get_matched_publication_data ( + dds_entity_t reader, + dds_instance_handle_t ih); + #if defined (__cplusplus) } #endif diff --git a/src/core/ddsc/src/dds_matched.c b/src/core/ddsc/src/dds_matched.c new file mode 100644 index 0000000..327ec56 --- /dev/null +++ b/src/core/ddsc/src/dds_matched.c @@ -0,0 +1,220 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include + +#include "dds/dds.h" +#include "dds/version.h" +#include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_globals.h" +#include "dds/ddsi/q_entity.h" +#include "dds/ddsi/q_thread.h" +#include "dds/ddsi/q_bswap.h" +#include "dds__writer.h" +#include "dds__reader.h" +#include "dds__qos.h" +#include "dds__topic.h" + +dds_return_t dds_get_matched_subscriptions (dds_entity_t writer, dds_instance_handle_t *rds, size_t nrds) +{ + dds_writer *wr; + dds_return_t rc; + if (rds == NULL && nrds > 0) + return DDS_RETCODE_BAD_PARAMETER; + if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) + return rc; + else + { + const int32_t nrds_max = (nrds > INT32_MAX) ? INT32_MAX : (int32_t) nrds; + int32_t nrds_act = 0; + ddsrt_avl_iter_t it; + /* FIXME: this ought not be so tightly coupled to the lower layer */ + thread_state_awake (lookup_thread_state ()); + ddsrt_mutex_lock (&wr->m_wr->e.lock); + for (const struct wr_prd_match *m = ddsrt_avl_iter_first (&wr_readers_treedef, &wr->m_wr->readers, &it); + m != NULL; + m = ddsrt_avl_iter_next (&it)) + { + struct proxy_reader *prd; + if ((prd = ephash_lookup_proxy_reader_guid (&m->prd_guid)) != NULL) + { + if (nrds_act < nrds_max) + rds[nrds_act] = prd->e.iid; + nrds_act++; + } + } + for (const struct wr_rd_match *m = ddsrt_avl_iter_first (&wr_local_readers_treedef, &wr->m_wr->local_readers, &it); + m != NULL; + m = ddsrt_avl_iter_next (&it)) + { + struct reader *rd; + if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) + { + if (nrds_act < nrds_max) + rds[nrds_act] = rd->e.iid; + nrds_act++; + } + } + ddsrt_mutex_unlock (&wr->m_wr->e.lock); + thread_state_asleep (lookup_thread_state ()); + dds_writer_unlock (wr); + return nrds_act; + } +} + +dds_return_t dds_get_matched_publications (dds_entity_t reader, dds_instance_handle_t *wrs, size_t nwrs) +{ + dds_reader *rd; + dds_return_t rc; + if (wrs == NULL && nwrs > 0) + return DDS_RETCODE_BAD_PARAMETER; + if ((rc = dds_reader_lock (reader, &rd)) != DDS_RETCODE_OK) + return rc; + else + { + const int32_t nwrs_max = (nwrs > INT32_MAX) ? INT32_MAX : (int32_t) nwrs; + int32_t nwrs_act = 0; + ddsrt_avl_iter_t it; + /* FIXME: this ought not be so tightly coupled to the lower layer */ + thread_state_awake (lookup_thread_state ()); + ddsrt_mutex_lock (&rd->m_rd->e.lock); + for (const struct rd_pwr_match *m = ddsrt_avl_iter_first (&rd_writers_treedef, &rd->m_rd->writers, &it); + m != NULL; + m = ddsrt_avl_iter_next (&it)) + { + struct proxy_writer *pwr; + if ((pwr = ephash_lookup_proxy_writer_guid (&m->pwr_guid)) != NULL) + { + if (nwrs_act < nwrs_max) + wrs[nwrs_act] = pwr->e.iid; + nwrs_act++; + } + } + for (const struct rd_wr_match *m = ddsrt_avl_iter_first (&rd_local_writers_treedef, &rd->m_rd->local_writers, &it); + m != NULL; + m = ddsrt_avl_iter_next (&it)) + { + struct writer *wr; + if ((wr = ephash_lookup_writer_guid (&m->wr_guid)) != NULL) + { + if (nwrs_act < nwrs_max) + wrs[nwrs_act] = wr->e.iid; + nwrs_act++; + } + } + ddsrt_mutex_unlock (&rd->m_rd->e.lock); + thread_state_asleep (lookup_thread_state ()); + dds_reader_unlock (rd); + return nwrs_act; + } +} + +static dds_builtintopic_endpoint_t *make_builtintopic_endpoint (const nn_guid_t *guid, const nn_guid_t *ppguid, dds_instance_handle_t ppiid, const dds_qos_t *qos) +{ + dds_builtintopic_endpoint_t *ep; + nn_guid_t tmp; + ep = dds_alloc (sizeof (*ep)); + tmp = nn_hton_guid (*guid); + memcpy (&ep->key, &tmp, sizeof (ep->key)); + ep->participant_instance_handle = ppiid; + 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)); + ep->topic_name = dds_string_dup (qos->topic_name); + ep->type_name = dds_string_dup (qos->type_name); + return ep; +} + +dds_builtintopic_endpoint_t *dds_get_matched_subscription_data (dds_entity_t writer, dds_instance_handle_t ih) +{ + dds_writer *wr; + dds_return_t rc; + if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) + return NULL; + else + { + dds_builtintopic_endpoint_t *ret = NULL; + ddsrt_avl_iter_t it; + /* FIXME: this ought not be so tightly coupled to the lower layer, and not be so inefficient besides */ + thread_state_awake (lookup_thread_state ()); + ddsrt_mutex_lock (&wr->m_wr->e.lock); + for (const struct wr_prd_match *m = ddsrt_avl_iter_first (&wr_readers_treedef, &wr->m_wr->readers, &it); + m != NULL && ret == NULL; + m = ddsrt_avl_iter_next (&it)) + { + struct proxy_reader *prd; + if ((prd = ephash_lookup_proxy_reader_guid (&m->prd_guid)) != NULL) + { + if (prd->e.iid == ih) + ret = make_builtintopic_endpoint (&prd->e.guid, &prd->c.proxypp->e.guid, prd->c.proxypp->e.iid, prd->c.xqos); + } + } + for (const struct wr_rd_match *m = ddsrt_avl_iter_first (&wr_local_readers_treedef, &wr->m_wr->local_readers, &it); + m != NULL && ret == NULL; + m = ddsrt_avl_iter_next (&it)) + { + struct reader *rd; + if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) + { + if (rd->e.iid == ih) + ret = make_builtintopic_endpoint (&rd->e.guid, &rd->c.pp->e.guid, rd->c.pp->e.iid, rd->xqos); + } + } + ddsrt_mutex_unlock (&wr->m_wr->e.lock); + thread_state_asleep (lookup_thread_state ()); + dds_writer_unlock (wr); + return ret; + } +} + +dds_builtintopic_endpoint_t *dds_get_matched_publication_data (dds_entity_t reader, dds_instance_handle_t ih) +{ + dds_reader *rd; + dds_return_t rc; + if ((rc = dds_reader_lock (reader, &rd)) != DDS_RETCODE_OK) + return NULL; + else + { + dds_builtintopic_endpoint_t *ret = NULL; + ddsrt_avl_iter_t it; + /* FIXME: this ought not be so tightly coupled to the lower layer, and not be so inefficient besides */ + thread_state_awake (lookup_thread_state ()); + ddsrt_mutex_lock (&rd->m_rd->e.lock); + for (const struct rd_pwr_match *m = ddsrt_avl_iter_first (&rd_writers_treedef, &rd->m_rd->writers, &it); + m != NULL && ret == NULL; + m = ddsrt_avl_iter_next (&it)) + { + struct proxy_writer *pwr; + if ((pwr = ephash_lookup_proxy_writer_guid (&m->pwr_guid)) != NULL) + { + if (pwr->e.iid == ih) + ret = make_builtintopic_endpoint (&pwr->e.guid, &pwr->c.proxypp->e.guid, pwr->c.proxypp->e.iid, pwr->c.xqos); + } + } + for (const struct rd_wr_match *m = ddsrt_avl_iter_first (&rd_local_writers_treedef, &rd->m_rd->local_writers, &it); + m != NULL && ret == NULL; + m = ddsrt_avl_iter_next (&it)) + { + struct writer *wr; + if ((wr = ephash_lookup_writer_guid (&m->wr_guid)) != NULL) + { + if (wr->e.iid == ih) + ret = make_builtintopic_endpoint (&wr->e.guid, &wr->c.pp->e.guid, wr->c.pp->e.iid, wr->xqos); + } + } + ddsrt_mutex_unlock (&rd->m_rd->e.lock); + thread_state_asleep (lookup_thread_state ()); + dds_reader_unlock (rd); + return ret; + } +} From 3322fc086d1e4bf9ae34686cf7d3ad94e41f10fd Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 29 May 2019 14:03:53 +0200 Subject: [PATCH 088/178] Table-driven parameter list handling The old parameter list parsing was a mess of custom code with tons of duplicated checks, even though parameter list parsing really is a fairly straightforward affair. This commit changes it to a mostly table-driven implementation, where the vast majority of the settings are handled by a generic deserializer and the irregular ones (like reliability, locators) are handled by custom functions. The crazy ones (IPv4 address and port rely on additional state and are completely special-cased). Given these tables, the serialization, finalisation, validation, merging, unalias'ing can all be handled by a very small amount of custom code and an appropriately defined generic function for the common cases. This also makes it possible to have all QoS validation in place, and so removes the need for the specialized implementations for the various entity kinds in the upper layer. QoS inapplicable to an entity were previously ignored, allowing one to have invalid values set in a QoS object when creating an entity, provided that the invalid values are irrelevant to that entity. Whether this is a good thing or not is debatable, but certainly it is a good thing to avoid copying in inapplicable QoS settings. That in turn means the behaviour of the API can remain the same. It does turn out that the code used to return "inconsistent QoS" also for invalid values. That has now been rectified, and it returns "inconsistent QoS" or "bad parameter" as appropriate. Tests have been updated accordingly. Signed-off-by: Erik Boasson --- .../ddsc/include/dds/ddsc/dds_public_qos.h | 3 +- src/core/ddsc/src/dds__qos.h | 10 - src/core/ddsc/src/dds_builtin.c | 18 +- src/core/ddsc/src/dds_entity.c | 4 +- src/core/ddsc/src/dds_participant.c | 21 +- src/core/ddsc/src/dds_publisher.c | 34 +- src/core/ddsc/src/dds_qos.c | 348 +- src/core/ddsc/src/dds_reader.c | 32 +- src/core/ddsc/src/dds_serdata_builtintopic.c | 5 +- src/core/ddsc/src/dds_subscriber.c | 30 +- src/core/ddsc/src/dds_topic.c | 31 +- src/core/ddsc/src/dds_writer.c | 22 +- src/core/ddsc/tests/reader.c | 4 +- src/core/ddsc/tests/subscriber.c | 2 +- src/core/ddsc/tests/topic.c | 4 +- .../include/dds/ddsi/ddsi_serdata_default.h | 2 +- src/core/ddsi/include/dds/ddsi/q_plist.h | 60 +- src/core/ddsi/include/dds/ddsi/q_protocol.h | 8 - src/core/ddsi/include/dds/ddsi/q_qosmatch.h | 8 +- src/core/ddsi/include/dds/ddsi/q_xmsg.h | 3 - src/core/ddsi/include/dds/ddsi/q_xqos.h | 6 +- src/core/ddsi/src/q_ddsi_discovery.c | 11 +- src/core/ddsi/src/q_entity.c | 13 +- src/core/ddsi/src/q_init.c | 5 +- src/core/ddsi/src/q_plist.c | 3882 +++++++---------- src/core/ddsi/src/q_qosmatch.c | 37 +- src/core/ddsi/src/q_receive.c | 6 +- src/core/ddsi/src/q_xmsg.c | 13 - src/core/xtests/rhc_torture/rhc_torture.c | 4 +- src/ddsrt/include/dds/ddsrt/attributes.h | 6 + src/mpt/tests/CMakeLists.txt | 2 +- src/mpt/tests/qosmatch/CMakeLists.txt | 23 + src/mpt/tests/qosmatch/procs/rw.c | 376 ++ src/mpt/tests/qosmatch/procs/rw.h | 41 + src/mpt/tests/qosmatch/procs/rwdata.idl | 8 + src/mpt/tests/qosmatch/qosmatch.c | 20 + 36 files changed, 2367 insertions(+), 2735 deletions(-) create mode 100644 src/mpt/tests/qosmatch/CMakeLists.txt create mode 100644 src/mpt/tests/qosmatch/procs/rw.c create mode 100644 src/mpt/tests/qosmatch/procs/rw.h create mode 100644 src/mpt/tests/qosmatch/procs/rwdata.idl create mode 100644 src/mpt/tests/qosmatch/qosmatch.c 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 a699d34..503a567 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h @@ -374,7 +374,8 @@ dds_qset_durability_service ( * @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy * @param[in] ignore - True if readers and writers owned by the same participant should be ignored */ -DDS_EXPORT void dds_qset_ignorelocal ( +DDS_EXPORT void +dds_qset_ignorelocal ( dds_qos_t * __restrict qos, dds_ignorelocal_kind_t ignore); diff --git a/src/core/ddsc/src/dds__qos.h b/src/core/ddsc/src/dds__qos.h index 545d38e..4d66c67 100644 --- a/src/core/ddsc/src/dds__qos.h +++ b/src/core/ddsc/src/dds__qos.h @@ -14,21 +14,11 @@ #include "dds__entity.h" #include "dds/ddsi/q_xqos.h" -#include "dds/ddsi/q_time.h" -#include "dds/ddsi/q_plist.h" #if defined (__cplusplus) extern "C" { #endif -bool validate_deadline_and_timebased_filter (const dds_duration_t deadline, const dds_duration_t minimum_separation); -bool validate_entityfactory_qospolicy (const dds_entity_factory_qospolicy_t * entityfactory); -bool validate_octetseq (const ddsi_octetseq_t* seq); -bool validate_partition_qospolicy (const dds_partition_qospolicy_t * partition); -bool validate_reliability_qospolicy (const dds_reliability_qospolicy_t * reliability); -bool validate_stringseq (const ddsi_stringseq_t* seq); - -bool dds_qos_validate_common (const dds_qos_t *qos); dds_return_t dds_qos_validate_mutable_common (const dds_qos_t *qos); #if defined (__cplusplus) diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index 2f195a4..ba9c31d 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -11,9 +11,11 @@ */ #include #include +#include "dds/ddsrt/string.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_plist.h" /* for nn_keyhash */ #include "dds__init.h" #include "dds__qos.h" #include "dds__domain.h" @@ -103,6 +105,7 @@ dds_entity_t dds__get_builtin_topic (dds_entity_t e, dds_entity_t topic) static bool qos_has_resource_limits (const dds_qos_t *qos) { + assert (qos->present & QP_RESOURCE_LIMITS); return (qos->resource_limits.max_samples != DDS_LENGTH_UNLIMITED || qos->resource_limits.max_instances != DDS_LENGTH_UNLIMITED || qos->resource_limits.max_samples_per_instance != DDS_LENGTH_UNLIMITED); @@ -115,8 +118,9 @@ bool dds__validate_builtin_reader_qos (dds_entity_t topic, const dds_qos_t *qos) return true; else { - /* failing writes on built-in topics are unwelcome complications, so we simply forbid the creation of - a reader matching a built-in topics writer that has resource limits */ + /* failing writes on built-in topics are unwelcome complications, so we simply + forbid the creation of a reader matching a built-in topics writer that has + resource limits */ struct local_orphan_writer *bwr; if (topic == DDS_BUILTIN_TOPIC_DCPSPARTICIPANT) { bwr = builtintopic_writer_participant; @@ -128,7 +132,15 @@ bool dds__validate_builtin_reader_qos (dds_entity_t topic, const dds_qos_t *qos) assert (0); return false; } - return !qos_match_p (qos, bwr->wr.xqos, NULL) && !qos_has_resource_limits (qos); + + /* FIXME: DDSI-level readers, writers have topic, type name in their QoS, but + DDSC-level ones don't and that gives an automatic mismatch when comparing + the full QoS object ... Here the two have the same topic by construction + so ignoring them in the comparison makes things work. The discrepancy + should be addressed one day. */ + const uint64_t qmask = ~(QP_TOPIC_NAME | QP_TYPE_NAME); + dds_qos_policy_id_t dummy; + return qos_match_mask_p (qos, bwr->wr.xqos, qmask, &dummy) && !qos_has_resource_limits (qos); } } diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index 176a7eb..368f40c 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -20,6 +20,7 @@ #include "dds__reader.h" #include "dds__listener.h" #include "dds/version.h" +#include "dds/ddsi/q_xqos.h" extern inline dds_entity *dds_entity_from_handle_link (struct dds_handle_link *hdllink); extern inline bool dds_entity_is_enabled (const dds_entity *e); @@ -354,7 +355,8 @@ dds_return_t dds_get_qos (dds_entity_t entity, dds_qos_t *qos) else { dds_reset_qos (qos); - ret = dds_copy_qos (qos, e->m_qos); + nn_xqos_mergein_missing (qos, e->m_qos, ~(QP_TOPIC_NAME | QP_TYPE_NAME)); + ret = DDS_RETCODE_OK; } dds_entity_unlock(e); return ret; diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index b1269d6..614ec59 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -15,6 +15,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__init.h" #include "dds__qos.h" #include "dds__domain.h" @@ -73,13 +74,10 @@ static dds_return_t dds_participant_qos_validate (const dds_qos_t *qos, bool ena static dds_return_t dds_participant_qos_validate (const dds_qos_t *qos, bool enabled) { + dds_return_t ret; (void)enabled; - - if ((qos->present & QP_USER_DATA) && !validate_octetseq (&qos->user_data)) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy (&qos->entity_factory)) - return DDS_RETCODE_INCONSISTENT_POLICY; - + if ((ret = nn_xqos_valid (qos)) < 0) + return ret; return DDS_RETCODE_OK; } @@ -112,13 +110,14 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_ if ((ret = dds__check_domain (domain)) != DDS_RETCODE_OK) goto err_domain_check; - /* Validate qos or use default if NULL */ - if (qos && (ret = dds_participant_qos_validate (qos, false)) != DDS_RETCODE_OK) - goto err_qos_validation; +#define DDS_QOSMASK_PARTICIPANT (QP_USER_DATA | QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL) new_qos = dds_create_qos (); if (qos != NULL) - (void) dds_copy_qos (new_qos, qos); + nn_xqos_mergein_missing (new_qos, qos, DDS_QOSMASK_PARTICIPANT); + /* Validate qos or use default if NULL */ + if ((ret = dds_participant_qos_validate (new_qos, false)) != DDS_RETCODE_OK) + goto err_qos_validation; /* Translate qos */ nn_plist_init_empty (&plist); @@ -157,8 +156,8 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_ err_entity_init: dds_free (pp); err_new_participant: - dds_delete_qos (new_qos); err_qos_validation: + dds_delete_qos (new_qos); err_domain_check: dds_fini (); err_dds_init: diff --git a/src/core/ddsc/src/dds_publisher.c b/src/core/ddsc/src/dds_publisher.c index 8f68e12..bbaa4c5 100644 --- a/src/core/ddsc/src/dds_publisher.c +++ b/src/core/ddsc/src/dds_publisher.c @@ -17,6 +17,7 @@ #include "dds__publisher.h" #include "dds__qos.h" #include "dds/ddsi/q_entity.h" +#include "dds/ddsi/q_globals.h" #include "dds/version.h" DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_publisher) @@ -37,14 +38,9 @@ static dds_return_t dds_publisher_qos_validate (const dds_qos_t *qos, bool enabl static dds_return_t dds_publisher_qos_validate (const dds_qos_t *qos, bool enabled) { - if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data)) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_PRESENTATION) && validate_presentation_qospolicy (&qos->presentation) < 0) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_PARTITION) && !validate_stringseq (&qos->partition)) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy (&qos->entity_factory)) - return DDS_RETCODE_INCONSISTENT_POLICY; + dds_return_t ret; + if ((ret = nn_xqos_valid (qos)) < 0) + return ret; /* FIXME: Improve/check immutable check. */ if (enabled && (qos->present & QP_PRESENTATION)) return DDS_RETCODE_IMMUTABLE_POLICY; @@ -74,21 +70,25 @@ dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qo dds_participant *par; dds_publisher *pub; dds_entity_t hdl; - dds_qos_t *new_qos = NULL; + dds_qos_t *new_qos; dds_return_t ret; - if (qos && (ret = dds_publisher_qos_validate (qos, false)) != DDS_RETCODE_OK) - return ret; - - if ((ret = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK) - return ret; - +#define DDS_QOSMASK_PUBLISHER (QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL) + new_qos = dds_create_qos (); if (qos) + nn_xqos_mergein_missing (new_qos, qos, DDS_QOSMASK_PUBLISHER); + nn_xqos_mergein_missing (new_qos, &gv.default_xqos_pub, ~(uint64_t)0); + if ((ret = dds_publisher_qos_validate (new_qos, false)) != DDS_RETCODE_OK) { - new_qos = dds_create_qos (); - (void) dds_copy_qos (new_qos, qos); + dds_delete_qos (new_qos); + return ret; } + if ((ret = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK) + { + dds_delete_qos (new_qos); + return ret; + } pub = dds_alloc (sizeof (*pub)); hdl = dds_entity_init (&pub->m_entity, &par->m_entity, DDS_KIND_PUBLISHER, new_qos, listener, DDS_PUBLISHER_STATUS_MASK); pub->m_entity.m_deriver.set_qos = dds_publisher_qos_set; diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index 3d2ccb1..a67329e 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -12,21 +12,16 @@ #include #include #include "dds__qos.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" #include "dds/ddsi/q_config.h" -static void dds_qos_data_copy_in (ddsi_octetseq_t *data, const void * __restrict value, size_t sz) +static void dds_qos_data_copy_in (ddsi_octetseq_t *data, const void * __restrict value, size_t sz, bool overwrite) { - if (data->value) - { - dds_free (data->value); - data->value = NULL; - } + if (overwrite && data->value) + ddsrt_free (data->value); data->length = (uint32_t) sz; - if (sz && value) - { - data->value = dds_alloc (sz); - memcpy (data->value, value, sz); - } + data->value = ddsrt_memdup (value, sz); } static bool dds_qos_data_copy_out (const ddsi_octetseq_t *data, void **value, size_t *sz) @@ -52,57 +47,6 @@ static bool dds_qos_data_copy_out (const ddsi_octetseq_t *data, void **value, si return true; } -bool validate_octetseq (const ddsi_octetseq_t *seq) -{ - /* default value is NULL with length 0 */ - return ((seq->length == 0 && seq->value == NULL) || (seq->length > 0 && seq->length < UINT32_MAX)); -} - -bool validate_stringseq (const ddsi_stringseq_t *seq) -{ - if (seq->n == 0) - return (seq->strs == NULL); - else - { - for (uint32_t i = 0; i < seq->n; i++) - if (seq->strs[i] == NULL) - return false; - return true; - } -} - -bool validate_entityfactory_qospolicy (const dds_entity_factory_qospolicy_t *entityfactory) -{ - /* Bools must be 0 or 1, i.e., only the lsb may be set */ - return !(entityfactory->autoenable_created_entities & ~1); -} - -bool validate_reliability_qospolicy (const dds_reliability_qospolicy_t *reliability) -{ - return ((reliability->kind == DDS_RELIABILITY_BEST_EFFORT || reliability->kind == DDS_RELIABILITY_RELIABLE) && - (validate_duration (reliability->max_blocking_time) == 0)); -} - -bool validate_deadline_and_timebased_filter (const dds_duration_t deadline, const dds_duration_t minimum_separation) -{ - return (validate_duration (deadline) == DDS_RETCODE_OK && - validate_duration (minimum_separation) == DDS_RETCODE_OK && - minimum_separation <= deadline); -} - -bool dds_qos_validate_common (const dds_qos_t *qos) -{ - return !(((qos->present & QP_DURABILITY) && validate_durability_qospolicy (&qos->durability) != DDS_RETCODE_OK) || - ((qos->present & QP_DEADLINE) && validate_duration (qos->deadline.deadline) != DDS_RETCODE_OK) || - ((qos->present & QP_LATENCY_BUDGET) && validate_duration (qos->latency_budget.duration) != DDS_RETCODE_OK) || - ((qos->present & QP_OWNERSHIP) && validate_ownership_qospolicy (&qos->ownership) != DDS_RETCODE_OK) || - ((qos->present & QP_LIVELINESS) && validate_liveliness_qospolicy (&qos->liveliness) != DDS_RETCODE_OK) || - ((qos->present & QP_RELIABILITY) && ! validate_reliability_qospolicy (&qos->reliability)) || - ((qos->present & QP_DESTINATION_ORDER) && validate_destination_order_qospolicy (&qos->destination_order) != DDS_RETCODE_OK) || - ((qos->present & QP_HISTORY) && validate_history_qospolicy (&qos->history) != DDS_RETCODE_OK) || - ((qos->present & QP_RESOURCE_LIMITS) && validate_resource_limits_qospolicy (&qos->resource_limits) != DDS_RETCODE_OK)); -} - dds_return_t dds_qos_validate_mutable_common (const dds_qos_t *qos) { /* FIXME: Check whether immutable QoS are changed should actually incorporate change to current QoS */ @@ -123,44 +67,10 @@ dds_return_t dds_qos_validate_mutable_common (const dds_qos_t *qos) return DDS_RETCODE_OK; } -static void dds_qos_init_defaults (dds_qos_t * __restrict qos) ddsrt_nonnull_all; - -static void dds_qos_init_defaults (dds_qos_t * __restrict qos) -{ - assert (qos); - memset (qos, 0, sizeof (*qos)); - qos->durability.kind = DDS_DURABILITY_VOLATILE; - qos->deadline.deadline = DDS_INFINITY; - qos->durability_service.service_cleanup_delay = 0; - qos->durability_service.history.kind = DDS_HISTORY_KEEP_LAST; - qos->durability_service.history.depth = 1; - qos->durability_service.resource_limits.max_samples = DDS_LENGTH_UNLIMITED; - qos->durability_service.resource_limits.max_instances = DDS_LENGTH_UNLIMITED; - qos->durability_service.resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED; - qos->presentation.access_scope = DDS_PRESENTATION_INSTANCE; - qos->latency_budget.duration = 0; - qos->ownership.kind = DDS_OWNERSHIP_SHARED; - qos->liveliness.kind = DDS_LIVELINESS_AUTOMATIC; - qos->liveliness.lease_duration = DDS_INFINITY; - qos->time_based_filter.minimum_separation = 0; - qos->reliability.kind = DDS_RELIABILITY_BEST_EFFORT; - qos->reliability.max_blocking_time = DDS_MSECS (100); - qos->lifespan.duration = DDS_INFINITY; - qos->destination_order.kind = DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP; - qos->history.kind = DDS_HISTORY_KEEP_LAST; - qos->history.depth = 1; - qos->resource_limits.max_samples = DDS_LENGTH_UNLIMITED; - qos->resource_limits.max_instances = DDS_LENGTH_UNLIMITED; - qos->resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED; - qos->writer_data_lifecycle.autodispose_unregistered_instances = true; - qos->reader_data_lifecycle.autopurge_nowriter_samples_delay = DDS_INFINITY; - qos->reader_data_lifecycle.autopurge_disposed_samples_delay = DDS_INFINITY; -} - dds_qos_t *dds_create_qos (void) { - dds_qos_t *qos = dds_alloc (sizeof (dds_qos_t)); - dds_qos_init_defaults (qos); + dds_qos_t *qos = ddsrt_malloc (sizeof (dds_qos_t)); + nn_xqos_init_empty (qos); return qos; } @@ -174,7 +84,7 @@ void dds_reset_qos (dds_qos_t * __restrict qos) if (qos) { nn_xqos_fini (qos); - dds_qos_init_defaults (qos); + nn_xqos_init_empty (qos); } } @@ -187,8 +97,8 @@ void dds_delete_qos (dds_qos_t * __restrict qos) { if (qos) { - dds_reset_qos(qos); - dds_free(qos); + nn_xqos_fini (qos); + ddsrt_free (qos); } } @@ -214,7 +124,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); + nn_xqos_mergein_missing (dst, src, ~(uint64_t)0); } void dds_qos_merge (dds_qos_t * __restrict dst, const dds_qos_t * __restrict src) @@ -235,155 +145,140 @@ bool dds_qos_equal (const dds_qos_t * __restrict a, const dds_qos_t * __restrict void dds_qset_userdata (dds_qos_t * __restrict qos, const void * __restrict value, size_t sz) { - if (qos != NULL) - { - dds_qos_data_copy_in (&qos->user_data, value, sz); - qos->present |= QP_USER_DATA; - } + if (qos == NULL || (sz > 0 && value == NULL)) + return; + dds_qos_data_copy_in (&qos->user_data, value, sz, qos->present & QP_USER_DATA); + qos->present |= QP_USER_DATA; } void dds_qset_topicdata (dds_qos_t * __restrict qos, const void * __restrict value, size_t sz) { - if (qos != NULL) - { - dds_qos_data_copy_in (&qos->topic_data, value, sz); - qos->present |= QP_TOPIC_DATA; - } + if (qos == NULL || (sz > 0 && value == NULL)) + return; + dds_qos_data_copy_in (&qos->topic_data, value, sz, qos->present & QP_TOPIC_DATA); + qos->present |= QP_TOPIC_DATA; } void dds_qset_groupdata (dds_qos_t * __restrict qos, const void * __restrict value, size_t sz) { - if (qos != NULL) - { - dds_qos_data_copy_in (&qos->group_data, value, sz); - qos->present |= QP_GROUP_DATA; - } + if (qos == NULL || (sz > 0 && value == NULL)) + return; + dds_qos_data_copy_in (&qos->group_data, value, sz, qos->present & QP_GROUP_DATA); + qos->present |= QP_GROUP_DATA; } void dds_qset_durability (dds_qos_t * __restrict qos, dds_durability_kind_t kind) { - if (qos != NULL) - { - qos->durability.kind = kind; - qos->present |= QP_DURABILITY; - } + if (qos == NULL) + return; + qos->durability.kind = kind; + qos->present |= QP_DURABILITY; } void dds_qset_history (dds_qos_t * __restrict qos, dds_history_kind_t kind, int32_t depth) { - if (qos != NULL) - { - qos->history.kind = kind; - qos->history.depth = depth; - qos->present |= QP_HISTORY; - } + if (qos == NULL) + return; + qos->history.kind = kind; + qos->history.depth = depth; + qos->present |= QP_HISTORY; } void dds_qset_resource_limits (dds_qos_t * __restrict qos, int32_t max_samples, int32_t max_instances, int32_t max_samples_per_instance) { - if (qos != NULL) - { - qos->resource_limits.max_samples = max_samples; - qos->resource_limits.max_instances = max_instances; - qos->resource_limits.max_samples_per_instance = max_samples_per_instance; - qos->present |= QP_RESOURCE_LIMITS; - } + if (qos == NULL) + return; + qos->resource_limits.max_samples = max_samples; + qos->resource_limits.max_instances = max_instances; + qos->resource_limits.max_samples_per_instance = max_samples_per_instance; + qos->present |= QP_RESOURCE_LIMITS; } void dds_qset_presentation (dds_qos_t * __restrict qos, dds_presentation_access_scope_kind_t access_scope, bool coherent_access, bool ordered_access) { - if (qos != NULL) - { - qos->presentation.access_scope = access_scope; - qos->presentation.coherent_access = coherent_access; - qos->presentation.ordered_access = ordered_access; - qos->present |= QP_PRESENTATION; - } + if (qos == NULL) + return; + qos->presentation.access_scope = access_scope; + qos->presentation.coherent_access = coherent_access; + qos->presentation.ordered_access = ordered_access; + qos->present |= QP_PRESENTATION; } void dds_qset_lifespan (dds_qos_t * __restrict qos, dds_duration_t lifespan) { - if (qos != NULL) - { - qos->lifespan.duration = lifespan; - qos->present |= QP_LIFESPAN; - } + if (qos == NULL) + return; + qos->lifespan.duration = lifespan; + qos->present |= QP_LIFESPAN; } void dds_qset_deadline (dds_qos_t * __restrict qos, dds_duration_t deadline) { - if (qos != NULL) - { - qos->deadline.deadline = deadline; - qos->present |= QP_DEADLINE; - } + if (qos == NULL) + return; + qos->deadline.deadline = deadline; + qos->present |= QP_DEADLINE; } void dds_qset_latency_budget (dds_qos_t * __restrict qos, dds_duration_t duration) { - if (qos != NULL) - { - qos->latency_budget.duration = duration; - qos->present |= QP_LATENCY_BUDGET; - } + if (qos == NULL) + return; + qos->latency_budget.duration = duration; + qos->present |= QP_LATENCY_BUDGET; } void dds_qset_ownership (dds_qos_t * __restrict qos, dds_ownership_kind_t kind) { - if (qos != NULL) - { - qos->ownership.kind = kind; - qos->present |= QP_OWNERSHIP; - } + if (qos == NULL) + return; + qos->ownership.kind = kind; + qos->present |= QP_OWNERSHIP; } void dds_qset_ownership_strength (dds_qos_t * __restrict qos, int32_t value) { - if (qos != NULL) - { - qos->ownership_strength.value = value; - qos->present |= QP_OWNERSHIP_STRENGTH; - } + if (qos == NULL) + return; + qos->ownership_strength.value = value; + qos->present |= QP_OWNERSHIP_STRENGTH; } void dds_qset_liveliness (dds_qos_t * __restrict qos, dds_liveliness_kind_t kind, dds_duration_t lease_duration) { - if (qos != NULL) - { - qos->liveliness.kind = kind; - qos->liveliness.lease_duration = lease_duration; - qos->present |= QP_LIVELINESS; - } + if (qos == NULL) + return; + qos->liveliness.kind = kind; + qos->liveliness.lease_duration = lease_duration; + qos->present |= QP_LIVELINESS; } void dds_qset_time_based_filter (dds_qos_t * __restrict qos, dds_duration_t minimum_separation) { - if (qos != NULL) - { - qos->time_based_filter.minimum_separation = minimum_separation; - qos->present |= QP_TIME_BASED_FILTER; - } + if (qos == NULL) + return; + qos->time_based_filter.minimum_separation = minimum_separation; + qos->present |= QP_TIME_BASED_FILTER; } void dds_qset_partition (dds_qos_t * __restrict qos, uint32_t n, const char ** __restrict ps) { - if (qos == NULL || (n && ps == NULL)) + if (qos == NULL || (n > 0 && ps == NULL)) return; - - if (qos->partition.strs != NULL) + if (qos->present & QP_PARTITION) { for (uint32_t i = 0; i < qos->partition.n; i++) - dds_free (qos->partition.strs[i]); - dds_free (qos->partition.strs); - qos->partition.strs = NULL; + ddsrt_free (qos->partition.strs[i]); + ddsrt_free (qos->partition.strs); } - qos->partition.n = n; - if (n > 0) + if (qos->partition.n == 0) + qos->partition.strs = NULL; + else { - qos->partition.strs = dds_alloc (sizeof (char*) * n); + qos->partition.strs = ddsrt_malloc (n * sizeof (*qos->partition.strs)); for (uint32_t i = 0; i < n; i++) - qos->partition.strs[i] = dds_string_dup (ps[i]); + qos->partition.strs[i] = ddsrt_strdup (ps[i]); } qos->present |= QP_PARTITION; } @@ -398,72 +293,65 @@ void dds_qset_partition1 (dds_qos_t * __restrict qos, const char * __restrict na void dds_qset_reliability (dds_qos_t * __restrict qos, dds_reliability_kind_t kind, dds_duration_t max_blocking_time) { - if (qos != NULL) - { - qos->reliability.kind = kind; - qos->reliability.max_blocking_time = max_blocking_time; - qos->present |= QP_RELIABILITY; - } + if (qos == NULL) + return; + qos->reliability.kind = kind; + qos->reliability.max_blocking_time = max_blocking_time; + qos->present |= QP_RELIABILITY; } void dds_qset_transport_priority (dds_qos_t * __restrict qos, int32_t value) { - if (qos != NULL) - { - qos->transport_priority.value = value; - qos->present |= QP_TRANSPORT_PRIORITY; - } + if (qos == NULL) + return; + qos->transport_priority.value = value; + qos->present |= QP_TRANSPORT_PRIORITY; } void dds_qset_destination_order (dds_qos_t * __restrict qos, dds_destination_order_kind_t kind) { - if (qos != NULL) - { - qos->destination_order.kind = kind; - qos->present |= QP_DESTINATION_ORDER; - } + if (qos == NULL) + return; + qos->destination_order.kind = kind; + qos->present |= QP_DESTINATION_ORDER; } void dds_qset_writer_data_lifecycle (dds_qos_t * __restrict qos, bool autodispose) { - if (qos != NULL) - { - qos->writer_data_lifecycle.autodispose_unregistered_instances = autodispose; - qos->present |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE; - } + if (qos == NULL) + return; + qos->writer_data_lifecycle.autodispose_unregistered_instances = autodispose; + qos->present |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE; } void dds_qset_reader_data_lifecycle (dds_qos_t * __restrict qos, dds_duration_t autopurge_nowriter_samples_delay, dds_duration_t autopurge_disposed_samples_delay) { - if (qos != NULL) - { - qos->reader_data_lifecycle.autopurge_nowriter_samples_delay = autopurge_nowriter_samples_delay; - qos->reader_data_lifecycle.autopurge_disposed_samples_delay = autopurge_disposed_samples_delay; - qos->present |= QP_PRISMTECH_READER_DATA_LIFECYCLE; - } + if (qos == NULL) + return; + qos->reader_data_lifecycle.autopurge_nowriter_samples_delay = autopurge_nowriter_samples_delay; + qos->reader_data_lifecycle.autopurge_disposed_samples_delay = autopurge_disposed_samples_delay; + qos->present |= QP_PRISMTECH_READER_DATA_LIFECYCLE; } void dds_qset_durability_service (dds_qos_t * __restrict qos, dds_duration_t service_cleanup_delay, dds_history_kind_t history_kind, int32_t history_depth, int32_t max_samples, int32_t max_instances, int32_t max_samples_per_instance) { - if (qos != NULL) - { - qos->durability_service.service_cleanup_delay = service_cleanup_delay; - qos->durability_service.history.kind = history_kind; - qos->durability_service.history.depth = history_depth; - qos->durability_service.resource_limits.max_samples = max_samples; - qos->durability_service.resource_limits.max_instances = max_instances; - qos->durability_service.resource_limits.max_samples_per_instance = max_samples_per_instance; - qos->present |= QP_DURABILITY_SERVICE; - } + if (qos == NULL) + return; + qos->durability_service.service_cleanup_delay = service_cleanup_delay; + qos->durability_service.history.kind = history_kind; + qos->durability_service.history.depth = history_depth; + qos->durability_service.resource_limits.max_samples = max_samples; + qos->durability_service.resource_limits.max_instances = max_instances; + qos->durability_service.resource_limits.max_samples_per_instance = max_samples_per_instance; + qos->present |= QP_DURABILITY_SERVICE; } void dds_qset_ignorelocal (dds_qos_t * __restrict qos, dds_ignorelocal_kind_t ignore) { - if (qos != NULL) - { - qos->ignorelocal.value = ignore; - qos->present |= QP_CYCLONE_IGNORELOCAL; - } + if (qos == NULL) + return; + qos->ignorelocal.value = ignore; + qos->present |= QP_CYCLONE_IGNORELOCAL; } bool dds_qget_userdata (const dds_qos_t * __restrict qos, void **value, size_t *sz) diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 6392124..f40dfe1 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -81,18 +81,9 @@ static dds_return_t dds_reader_qos_validate (const dds_qos_t *qos, bool enabled) static dds_return_t dds_reader_qos_validate (const dds_qos_t *qos, bool enabled) { - if (!dds_qos_validate_common (qos)) - return DDS_RETCODE_ERROR; - if ((qos->present & QP_USER_DATA) && !validate_octetseq (&qos->user_data)) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_PRISMTECH_READER_DATA_LIFECYCLE) && validate_reader_data_lifecycle (&qos->reader_data_lifecycle) < 0) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_TIME_BASED_FILTER) && validate_duration (qos->time_based_filter.minimum_separation) < 0) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits (&qos->history, &qos->resource_limits) < 0) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_TIME_BASED_FILTER) && (qos->present & QP_DEADLINE) && !validate_deadline_and_timebased_filter (qos->deadline.deadline, qos->time_based_filter.minimum_separation)) - return DDS_RETCODE_INCONSISTENT_POLICY; + dds_return_t ret; + if ((ret = nn_xqos_valid (qos)) < 0) + return ret; return (enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK); } @@ -372,20 +363,15 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti /* 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 */ +#define DDS_QOSMASK_READER (QP_USER_DATA | QP_DURABILITY | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_LIVELINESS | QP_TIME_BASED_FILTER | QP_RELIABILITY | QP_DESTINATION_ORDER | QP_HISTORY | QP_RESOURCE_LIMITS | QP_PRISMTECH_READER_DATA_LIFECYCLE | QP_CYCLONE_IGNORELOCAL) rqos = dds_create_qos (); if (qos) - (void) dds_copy_qos (rqos, qos); - + nn_xqos_mergein_missing (rqos, qos, DDS_QOSMASK_READER); if (sub->m_entity.m_qos) - dds_merge_qos (rqos, sub->m_entity.m_qos); - + nn_xqos_mergein_missing (rqos, sub->m_entity.m_qos, ~(uint64_t)0); if (tp->m_entity.m_qos) - { - dds_merge_qos (rqos, tp->m_entity.m_qos); - /* reset the following qos policies if set during topic qos merge as they aren't applicable for reader */ - rqos->present &= ~(QP_DURABILITY_SERVICE | QP_TRANSPORT_PRIORITY | QP_LIFESPAN); - } - nn_xqos_mergein_missing (rqos, &gv.default_xqos_rd); + nn_xqos_mergein_missing (rqos, tp->m_entity.m_qos, ~(uint64_t)0); + nn_xqos_mergein_missing (rqos, &gv.default_xqos_rd, ~(uint64_t)0); if ((ret = dds_reader_qos_validate (rqos, false)) != DDS_RETCODE_OK) { @@ -397,7 +383,7 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti /* 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 (topic, qos)) + if (internal_topic && !dds__validate_builtin_reader_qos (topic, rqos)) { dds_delete_qos (rqos); reader = DDS_RETCODE_INCONSISTENT_POLICY; diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index 03b6409..b95df6e 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -19,6 +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__stream.h" #include "dds__serdata_builtintopic.h" #include "dds/ddsi/ddsi_tkmap.h" @@ -193,7 +194,7 @@ static dds_qos_t *dds_qos_from_xqos_reuse (dds_qos_t *old, const dds_qos_t *src) old = ddsrt_malloc (sizeof (*old)); nn_xqos_init_empty (old); old->present |= QP_TOPIC_NAME | QP_TYPE_NAME; - nn_xqos_mergein_missing (old, src); + nn_xqos_mergein_missing (old, src, ~(uint64_t)0); old->present &= ~(QP_TOPIC_NAME | QP_TYPE_NAME); } else @@ -201,7 +202,7 @@ static dds_qos_t *dds_qos_from_xqos_reuse (dds_qos_t *old, const dds_qos_t *src) nn_xqos_fini (old); nn_xqos_init_empty (old); old->present |= QP_TOPIC_NAME | QP_TYPE_NAME; - nn_xqos_mergein_missing (old, src); + nn_xqos_mergein_missing (old, src, ~(uint64_t)0); old->present &= ~(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 907f413..1054ef6 100644 --- a/src/core/ddsc/src/dds_subscriber.c +++ b/src/core/ddsc/src/dds_subscriber.c @@ -15,6 +15,7 @@ #include "dds__qos.h" #include "dds__subscriber.h" #include "dds/ddsi/q_entity.h" +#include "dds/ddsi/q_globals.h" #include "dds/version.h" DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_subscriber) @@ -36,15 +37,9 @@ static dds_return_t dds__subscriber_qos_validate (const dds_qos_t *qos, bool ena static dds_return_t dds__subscriber_qos_validate (const dds_qos_t *qos, bool enabled) { - if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data)) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_PARTITION) && !validate_stringseq (&qos->partition)) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_PRESENTATION) && validate_presentation_qospolicy (&qos->presentation) < 0) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy (&qos->entity_factory)) - return DDS_RETCODE_INCONSISTENT_POLICY; - /* FIXME: Improve/check immutable check. */ + dds_return_t ret; + if ((ret = nn_xqos_valid (qos)) < 0) + return ret; return (enabled && (qos->present & QP_PRESENTATION)) ? DDS_RETCODE_IMMUTABLE_POLICY : DDS_RETCODE_OK; } @@ -73,16 +68,15 @@ dds_entity_t dds__create_subscriber_l (dds_participant *participant, const dds_q dds_return_t ret; dds_qos_t *new_qos; - /* Validate qos */ - if (qos && (ret = dds__subscriber_qos_validate (qos, false)) != DDS_RETCODE_OK) - return ret; - - if (qos == NULL) - new_qos = NULL; - else +#define DDS_QOSMASK_SUBSCRIBER (QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL) + new_qos = dds_create_qos (); + if (qos) + nn_xqos_mergein_missing (new_qos, qos, DDS_QOSMASK_SUBSCRIBER); + nn_xqos_mergein_missing (new_qos, &gv.default_xqos_sub, ~(uint64_t)0); + if ((ret = dds__subscriber_qos_validate (new_qos, false)) != DDS_RETCODE_OK) { - new_qos = dds_create_qos (); - (void) dds_copy_qos (new_qos, qos); + dds_delete_qos (new_qos); + return ret; } sub = dds_alloc (sizeof (*sub)); diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 31390cf..7804a67 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -14,6 +14,8 @@ #include #include "dds/ddsrt/atomics.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" #include "dds__topic.h" #include "dds__listener.h" #include "dds__qos.h" @@ -27,6 +29,8 @@ #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/q_globals.h" DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_topic) @@ -182,17 +186,10 @@ static dds_return_t dds_topic_qos_validate (const dds_qos_t *qos, bool enabled) static dds_return_t dds_topic_qos_validate (const dds_qos_t *qos, bool enabled) { - if (!dds_qos_validate_common (qos)) - return DDS_RETCODE_BAD_PARAMETER; - if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data)) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy(&qos->durability_service) < 0) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_LIFESPAN) && validate_duration(qos->lifespan.duration) < 0) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits(&qos->history, &qos->resource_limits) < 0) - return DDS_RETCODE_INCONSISTENT_POLICY; - return enabled ? dds_qos_validate_mutable_common(qos) : DDS_RETCODE_OK; + dds_return_t ret; + if ((ret = nn_xqos_valid (qos)) < 0) + return ret; + return enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK; } @@ -333,8 +330,8 @@ dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descrip st->c.status_cb = dds_topic_status_cb; st->c.status_cb_entity = NULL; /* set by dds_create_topic_arbitrary */ st->c.name_type_name = key; - st->c.name = dds_string_dup (name); - st->c.type_name = dds_string_dup (typename); + st->c.name = ddsrt_strdup (name); + st->c.type_name = ddsrt_strdup (typename); st->c.ops = &ddsi_sertopic_ops_default; st->c.serdata_ops = desc->m_nkeys ? &ddsi_serdata_ops_cdr : &ddsi_serdata_ops_cdr_nokey; st->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (st->c.serdata_ops); @@ -349,13 +346,15 @@ dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descrip st->opt_size = dds_stream_check_optimize (desc); } +#define DDS_QOSMASK_TOPIC (QP_TOPIC_DATA | QP_DURABILITY | QP_DURABILITY_SERVICE | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_LIVELINESS | QP_RELIABILITY | QP_TRANSPORT_PRIORITY | QP_LIFESPAN | QP_DESTINATION_ORDER | QP_HISTORY | QP_RESOURCE_LIMITS) nn_plist_init_empty (&plist); if (new_qos) - dds_merge_qos (&plist.qos, new_qos); + nn_xqos_mergein_missing (&plist.qos, new_qos, DDS_QOSMASK_TOPIC); + nn_xqos_mergein_missing (&plist.qos, &gv.default_xqos_tp, DDS_QOSMASK_TOPIC); /* Set Topic meta data (for SEDP publication) */ - plist.qos.topic_name = dds_string_dup (st->c.name); - plist.qos.type_name = dds_string_dup (st->c.type_name); + plist.qos.topic_name = ddsrt_strdup (st->c.name); + plist.qos.type_name = ddsrt_strdup (st->c.type_name); plist.qos.present |= (QP_TOPIC_NAME | QP_TYPE_NAME); if (desc->m_meta) { diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 542be62..847e85a 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -208,16 +208,9 @@ static dds_return_t dds_writer_delete (dds_entity *e) static dds_return_t dds_writer_qos_validate (const dds_qos_t *qos, bool enabled) { - if (!dds_qos_validate_common(qos)) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_USER_DATA) && !validate_octetseq (&qos->user_data)) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy (&qos->durability_service) < 0) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_LIFESPAN) && validate_duration (qos->lifespan.duration) < 0) - return DDS_RETCODE_INCONSISTENT_POLICY; - if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits(&qos->history, &qos->resource_limits) < 0) - return DDS_RETCODE_INCONSISTENT_POLICY; + dds_return_t ret; + if ((ret = nn_xqos_valid (qos)) < 0) + return ret; return enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK; } @@ -316,14 +309,15 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit assert (pub->m_entity.m_domain == tp->m_entity.m_domain); /* Merge Topic & Publisher qos */ +#define DDS_QOSMASK_WRITER (QP_USER_DATA | QP_DURABILITY | QP_DURABILITY_SERVICE | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_OWNERSHIP_STRENGTH | QP_LIVELINESS | QP_RELIABILITY | QP_TRANSPORT_PRIORITY | QP_LIFESPAN | QP_DESTINATION_ORDER | QP_HISTORY | QP_RESOURCE_LIMITS | QP_PRISMTECH_WRITER_DATA_LIFECYCLE | QP_CYCLONE_IGNORELOCAL) wqos = dds_create_qos (); if (qos) - (void) dds_copy_qos (wqos, qos); + nn_xqos_mergein_missing (wqos, qos, DDS_QOSMASK_WRITER); if (pub->m_entity.m_qos) - dds_merge_qos (wqos, pub->m_entity.m_qos); + nn_xqos_mergein_missing (wqos, pub->m_entity.m_qos, ~(uint64_t)0); if (tp->m_entity.m_qos) - dds_merge_qos (wqos, tp->m_entity.m_qos); - nn_xqos_mergein_missing (wqos, &gv.default_xqos_wr); + nn_xqos_mergein_missing (wqos, tp->m_entity.m_qos, ~(uint64_t)0); + nn_xqos_mergein_missing (wqos, &gv.default_xqos_wr, ~(uint64_t)0); if ((rc = dds_writer_qos_validate (wqos, false)) != DDS_RETCODE_OK) { diff --git a/src/core/ddsc/tests/reader.c b/src/core/ddsc/tests/reader.c index bf8e9dc..2b53b99 100644 --- a/src/core/ddsc/tests/reader.c +++ b/src/core/ddsc/tests/reader.c @@ -241,7 +241,7 @@ CU_Test(ddsc_reader_create, invalid_qos_participant, .init=reader_init, .fini=re dds_qset_reader_data_lifecycle(qos, DDS_SECS(-1), DDS_SECS(-1)); DDSRT_WARNING_MSVC_ON(28020); rdr = dds_create_reader(g_participant, g_topic, qos, NULL); - CU_ASSERT_EQUAL_FATAL(rdr, DDS_RETCODE_INCONSISTENT_POLICY); + CU_ASSERT_EQUAL_FATAL(rdr, DDS_RETCODE_BAD_PARAMETER); dds_delete_qos(qos); } /*************************************************************************************************/ @@ -256,7 +256,7 @@ CU_Test(ddsc_reader_create, invalid_qos_subscriber, .init=reader_init, .fini=rea dds_qset_reader_data_lifecycle(qos, DDS_SECS(-1), DDS_SECS(-1)); DDSRT_WARNING_MSVC_ON(28020); rdr = dds_create_reader(g_subscriber, g_topic, qos, NULL); - CU_ASSERT_EQUAL_FATAL(rdr, DDS_RETCODE_INCONSISTENT_POLICY); + CU_ASSERT_EQUAL_FATAL(rdr, DDS_RETCODE_BAD_PARAMETER); dds_delete_qos(qos); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/subscriber.c b/src/core/ddsc/tests/subscriber.c index cc9144a..02a8625 100644 --- a/src/core/ddsc/tests/subscriber.c +++ b/src/core/ddsc/tests/subscriber.c @@ -91,7 +91,7 @@ CU_Test(ddsc_subscriber, create) { sqos = dds_create_qos(); dds_qset_presentation(sqos, 123, 1, 1); /* Set invalid presentation policy */ subscriber = dds_create_subscriber(participant, sqos, NULL); - CU_ASSERT_EQUAL_FATAL(subscriber, DDS_RETCODE_INCONSISTENT_POLICY); + CU_ASSERT_EQUAL_FATAL(subscriber, DDS_RETCODE_BAD_PARAMETER); dds_delete_qos(sqos); /*** Verify listener parameter ***/ diff --git a/src/core/ddsc/tests/topic.c b/src/core/ddsc/tests/topic.c index 085926b..d71c8d5 100644 --- a/src/core/ddsc/tests/topic.c +++ b/src/core/ddsc/tests/topic.c @@ -105,7 +105,7 @@ CU_Test(ddsc_topic_create, invalid_qos, .init=ddsc_topic_init, .fini=ddsc_topic_ dds_entity_t topic; dds_qos_t *qos = dds_create_qos(); DDSRT_WARNING_MSVC_OFF(28020); /* Disable SAL warning on intentional misuse of the API */ - dds_qset_lifespan(qos, DDS_SECS(-1)); + dds_qset_resource_limits(qos, 1, 1, 2); DDSRT_WARNING_MSVC_OFF(28020); topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, "inconsistent", qos, NULL); CU_ASSERT_EQUAL_FATAL(topic, DDS_RETCODE_INCONSISTENT_POLICY); @@ -417,7 +417,7 @@ CU_Test(ddsc_topic_set_qos, inconsistent, .init=ddsc_topic_init, .fini=ddsc_topi dds_qset_lifespan(g_qos, DDS_SECS(-1)); DDSRT_WARNING_MSVC_ON(28020); ret = dds_set_qos(g_topicRtmDataType, g_qos); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_INCONSISTENT_POLICY); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ 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 6c2bc29..e6e2f56 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -13,7 +13,7 @@ #define DDSI_SERDATA_DEFAULT_H #include "dds/ddsrt/endian.h" -#include "dds/ddsi/q_plist.h" /* for nn_prismtech_writer_info */ +#include "dds/ddsi/q_protocol.h" /* for nn_parameterid_t */ #include "dds/ddsi/q_freelist.h" #include "dds/ddsrt/avl.h" #include "dds/ddsi/ddsi_serdata.h" diff --git a/src/core/ddsi/include/dds/ddsi/q_plist.h b/src/core/ddsi/include/dds/ddsi/q_plist.h index 98b9466..6028da8 100644 --- a/src/core/ddsi/include/dds/ddsi/q_plist.h +++ b/src/core/ddsi/include/dds/ddsi/q_plist.h @@ -46,22 +46,16 @@ extern "C" { #define PP_STATUSINFO ((uint64_t)1 << 22) #define PP_ORIGINAL_WRITER_INFO ((uint64_t)1 << 23) #define PP_ENDPOINT_GUID ((uint64_t)1 << 24) -#define PP_PRISMTECH_WRITER_INFO ((uint64_t)1 << 25) #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_SERVICE_TYPE ((uint64_t)1 << 30) -#define PP_PRISMTECH_WATCHDOG_SCHEDULING ((uint64_t)1 << 31) -#define PP_PRISMTECH_LISTENER_SCHEDULING ((uint64_t)1 << 32) #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_EOTINFO ((uint64_t)1 << 38) #ifdef DDSI_INCLUDE_SSM #define PP_READER_FAVOURS_SSM ((uint64_t)1 << 39) #endif -#define PP_RTI_TYPECODE ((uint64_t)1 << 40) /* Security extensions. */ #define PP_IDENTITY_TOKEN ((uint64_t)1 << 41) #define PP_PERMISSIONS_TOKEN ((uint64_t)1 << 42) @@ -93,14 +87,14 @@ struct nn_locators_one { }; typedef struct nn_locators { - int n; + uint32_t n; struct nn_locators_one *first; struct nn_locators_one *last; } nn_locators_t; -typedef unsigned nn_ipv4address_t; +typedef uint32_t nn_ipv4address_t; -typedef unsigned nn_port_t; +typedef uint32_t nn_port_t; typedef struct nn_keyhash { unsigned char value[16]; @@ -109,15 +103,15 @@ typedef struct nn_keyhash { #ifdef DDSI_INCLUDE_SSM typedef struct nn_reader_favours_ssm { - unsigned state; /* default is false */ + uint32_t state; /* default is false */ } nn_reader_favours_ssm_t; #endif typedef struct nn_prismtech_participant_version_info { - unsigned version; - unsigned flags; - unsigned unused[3]; + uint32_t version; + uint32_t flags; + uint32_t unused[3]; char *internals; } nn_prismtech_participant_version_info_t; @@ -126,16 +120,9 @@ typedef struct nn_prismtech_eotgroup_tid { uint32_t transactionId; } nn_prismtech_eotgroup_tid_t; -typedef struct nn_prismtech_eotinfo { - uint32_t transactionId; - uint32_t n; - nn_prismtech_eotgroup_tid_t *tids; -} nn_prismtech_eotinfo_t; - typedef struct nn_plist { uint64_t present; uint64_t aliased; - int unalias_needs_bswap; dds_qos_t qos; @@ -150,7 +137,7 @@ typedef struct nn_plist { unsigned char expects_inline_qos; nn_count_t participant_manual_liveliness_count; - unsigned participant_builtin_endpoints; + uint32_t participant_builtin_endpoints; dds_duration_t participant_lease_duration; /* nn_content_filter_property_t content_filter_property; */ nn_guid_t participant_guid; @@ -160,21 +147,18 @@ typedef struct nn_plist { nn_entityid_t participant_entityid; nn_entityid_t group_entityid; #endif - unsigned builtin_endpoint_set; - unsigned prismtech_builtin_endpoint_set; + uint32_t builtin_endpoint_set; + uint32_t prismtech_builtin_endpoint_set; /* int type_max_size_serialized; */ char *entity_name; nn_keyhash_t keyhash; - unsigned statusinfo; + uint32_t statusinfo; nn_prismtech_participant_version_info_t prismtech_participant_version_info; char *node_name; char *exec_name; - unsigned char is_service; - unsigned service_type; - unsigned process_id; + uint32_t process_id; char *type_description; nn_sequence_number_t coherent_set_seqno; - nn_prismtech_eotinfo_t eotinfo; #ifdef DDSI_INCLUDE_SSM nn_reader_favours_ssm_t reader_favours_ssm; #endif @@ -192,8 +176,9 @@ typedef struct nn_plist_src { size_t bufsz; } nn_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); +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); @@ -234,6 +219,9 @@ DDS_EXPORT nn_plist_t *nn_plist_dup (const nn_plist_t *src); * @retval DDS_RETCODE_OK * All parameters valid (or ignored), dest and *nextafterplist have been set * accordingly. + * @retval DDS_INCONSISTENT_POLICY + * All individual settings are valid, but there are inconsistencies between + * dependent settings. * @retval DDS_RETCODE_BAD_PARAMETER * Input contained invalid data; dest is cleared, *nextafterplist is NULL. * @retval DDS_RETCODE_UNSUPPORTED @@ -245,20 +233,6 @@ DDS_EXPORT void nn_plist_fini (nn_plist_t *ps); 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 dds_return_t validate_history_qospolicy (const dds_history_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_durability_qospolicy (const dds_durability_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_resource_limits_qospolicy (const dds_resource_limits_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_history_and_resource_limits (const dds_history_qospolicy_t *qh, const dds_resource_limits_qospolicy_t *qr); -DDS_EXPORT dds_return_t validate_durability_service_qospolicy (const dds_durability_service_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_liveliness_qospolicy (const dds_liveliness_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_destination_order_qospolicy (const dds_destination_order_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_ownership_qospolicy (const dds_ownership_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_ownership_strength_qospolicy (const dds_ownership_strength_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_presentation_qospolicy (const dds_presentation_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_transport_priority_qospolicy (const dds_transport_priority_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_reader_data_lifecycle (const dds_reader_data_lifecycle_qospolicy_t *q); -DDS_EXPORT dds_return_t validate_duration (const dds_duration_t d); - struct nn_rmsg; struct nn_rsample_info; struct nn_rdata; diff --git a/src/core/ddsi/include/dds/ddsi/q_protocol.h b/src/core/ddsi/include/dds/ddsi/q_protocol.h index f8f65d6..e120f59 100644 --- a/src/core/ddsi/include/dds/ddsi/q_protocol.h +++ b/src/core/ddsi/include/dds/ddsi/q_protocol.h @@ -390,14 +390,6 @@ typedef struct ParticipantMessageData { #define PID_IDENTITY_TOKEN 0x1001u #define PID_PERMISSIONS_TOKEN 0x1002u -#define PID_RTI_TYPECODE (PID_VENDORSPECIFIC_FLAG | 0x4u) - -#ifdef DDSI_INCLUDE_SSM -/* To indicate whether a reader favours the use of SSM. Iff the - reader favours SSM, it will use SSM if available. */ -#define PID_READER_FAVOURS_SSM 0x72u -#endif - #ifdef DDSI_INCLUDE_SSM /* To indicate whether a reader favours the use of SSM. Iff the reader favours SSM, it will use SSM if available. */ diff --git a/src/core/ddsi/include/dds/ddsi/q_qosmatch.h b/src/core/ddsi/include/dds/ddsi/q_qosmatch.h index 7cfd371..bbf9b07 100644 --- a/src/core/ddsi/include/dds/ddsi/q_qosmatch.h +++ b/src/core/ddsi/include/dds/ddsi/q_qosmatch.h @@ -20,8 +20,14 @@ struct dds_qos; int partitions_match_p (const struct dds_qos *a, const struct dds_qos *b); -/* Returns -1 on success, or QoS id of first mismatch (>=0) */ +/* perform reader/writer QoS (and topic name, type name, partition) matching; + mask can be used to exclude some of these (including topic name and type + name, so be careful!) + reason will be set to the policy id of one of the mismatching QoS, or to + DDS_INVALID_QOS_POLICY_ID if there is no mismatch or if the mismatch is + in topic or type name (those are not really QoS and don't have a policy id) */ +bool qos_match_mask_p (const dds_qos_t *rd, const dds_qos_t *wr, uint64_t mask, dds_qos_policy_id_t *reason) ddsrt_nonnull_all; bool qos_match_p (const struct dds_qos *rd, const struct dds_qos *wr, dds_qos_policy_id_t *reason) ddsrt_nonnull ((1, 2)); #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 9b7e1eb..b70a5c4 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xmsg.h +++ b/src/core/ddsi/include/dds/ddsi/q_xmsg.h @@ -28,8 +28,6 @@ struct proxy_reader; struct proxy_writer; struct nn_prismtech_participant_version_info; -struct nn_prismtech_writer_info; -struct nn_prismtech_eotinfo; struct nn_xmsgpool; struct nn_xmsg_data; struct nn_xmsg; @@ -139,7 +137,6 @@ void nn_xmsg_addpar_reader_data_lifecycle (struct nn_xmsg *m, nn_parameterid_t p void nn_xmsg_addpar_liveliness (struct nn_xmsg *m, nn_parameterid_t pid, const dds_liveliness_qospolicy_t *rq); void nn_xmsg_addpar_parvinfo (struct nn_xmsg *m, nn_parameterid_t pid, const struct nn_prismtech_participant_version_info *pvi); -void nn_xmsg_addpar_eotinfo (struct nn_xmsg *m, nn_parameterid_t pid, const struct nn_prismtech_eotinfo *txnid); void nn_xmsg_addpar_sentinel (struct nn_xmsg *m); int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg *m); diff --git a/src/core/ddsi/include/dds/ddsi/q_xqos.h b/src/core/ddsi/include/dds/ddsi/q_xqos.h index 225e280..7b5e8ea 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xqos.h +++ b/src/core/ddsi/include/dds/ddsi/q_xqos.h @@ -211,7 +211,6 @@ typedef struct dds_ignorelocal_qospolicy { #define QP_PRISMTECH_READER_LIFESPAN ((uint64_t)1 << 24) #define QP_PRISMTECH_SUBSCRIPTION_KEYS ((uint64_t)1 << 25) #define QP_PRISMTECH_ENTITY_FACTORY ((uint64_t)1 << 27) -#define QP_RTI_TYPECODE ((uint64_t)1 << 29) #define QP_CYCLONE_IGNORELOCAL ((uint64_t)1 << 30) /* Partition QoS is not RxO according to the specification (DDS 1.2, @@ -264,8 +263,6 @@ struct dds_qos { /*x xR*/dds_subscription_keys_qospolicy_t subscription_keys; /*x xR*/dds_reader_lifespan_qospolicy_t reader_lifespan; /* x */dds_ignorelocal_qospolicy_t ignorelocal; - - /* X*/ddsi_octetseq_t rti_typecode; }; struct nn_xmsg; @@ -280,7 +277,8 @@ 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_mergein_missing (dds_qos_t *a, const dds_qos_t *b); +DDS_EXPORT dds_return_t nn_xqos_valid (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_log_xqos (uint32_t cat, const dds_qos_t *xqos); diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index e9b6476..3973840 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -1085,7 +1085,7 @@ static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppg 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); + nn_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; @@ -1146,11 +1146,11 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat xqos = &datap->qos; is_writer = is_writer_entityid (datap->endpoint_guid.entityid); if (!is_writer) - nn_xqos_mergein_missing (xqos, &gv.default_xqos_rd); + nn_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); + nn_xqos_mergein_missing (xqos, &gv.default_xqos_wr, ~(uint64_t)0); else - nn_xqos_mergein_missing (xqos, &gv.default_xqos_wr_nad); + nn_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, @@ -1434,8 +1434,7 @@ int sedp_write_cm_participant (struct participant *pp, int alive) { nn_plist_addtomsg (mpayload, pp->plist, PP_PRISMTECH_NODE_NAME | PP_PRISMTECH_EXEC_NAME | PP_PRISMTECH_PROCESS_ID | - PP_PRISMTECH_WATCHDOG_SCHEDULING | PP_PRISMTECH_LISTENER_SCHEDULING | - PP_PRISMTECH_SERVICE_TYPE | PP_ENTITY_NAME, + PP_ENTITY_NAME, QP_PRISMTECH_ENTITY_FACTORY); } nn_xmsg_addpar_sentinel (mpayload); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index a8eca66..d8e66fc 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -457,7 +457,7 @@ dds_return_t new_participant_guid (const nn_guid_t *ppguid, unsigned flags, cons pp->lease_duration = config.lease_duration; pp->plist = ddsrt_malloc (sizeof (*pp->plist)); nn_plist_copy (pp->plist, plist); - nn_plist_mergein_missing (pp->plist, &gv.default_plist_pp); + nn_plist_mergein_missing (pp->plist, &gv.default_plist_pp, ~(uint64_t)0, ~(uint64_t)0); if (dds_get_log_mask() & DDS_LC_DISCOVERY) { @@ -2684,7 +2684,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se wr->xqos = ddsrt_malloc (sizeof (*wr->xqos)); nn_xqos_copy (wr->xqos, xqos); - nn_xqos_mergein_missing (wr->xqos, &gv.default_xqos_wr); + nn_xqos_mergein_missing (wr->xqos, &gv.default_xqos_wr, ~(uint64_t)0); assert (wr->xqos->aliased == 0); set_topic_type_name (wr->xqos, topic); @@ -3222,7 +3222,7 @@ 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, &gv.default_xqos_rd); + nn_xqos_mergein_missing (rd->xqos, &gv.default_xqos_rd, ~(uint64_t)0); assert (rd->xqos->aliased == 0); set_topic_type_name (rd->xqos, topic); @@ -3660,7 +3660,7 @@ int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, co nn_plist_t *new_plist; new_plist = nn_plist_dup (datap); - nn_plist_mergein_missing (new_plist, proxypp->plist); + nn_plist_mergein_missing (new_plist, proxypp->plist, ~(uint64_t)0, ~(uint64_t)0); nn_plist_fini (proxypp->plist); ddsrt_free (proxypp->plist); proxypp->plist = new_plist; @@ -3694,8 +3694,7 @@ int update_proxy_participant_plist (struct proxy_participant *proxypp, const str tmp = *datap; tmp.present &= PP_PRISMTECH_NODE_NAME | PP_PRISMTECH_EXEC_NAME | PP_PRISMTECH_PROCESS_ID | - PP_PRISMTECH_WATCHDOG_SCHEDULING | PP_PRISMTECH_LISTENER_SCHEDULING | - PP_PRISMTECH_SERVICE_TYPE | PP_ENTITY_NAME; + PP_ENTITY_NAME; tmp.qos.present &= QP_PRISMTECH_ENTITY_FACTORY; update_proxy_participant_plist_locked (proxypp, &tmp, source, timestamp); break; @@ -3993,7 +3992,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group("PGUIDFMT"): setting name (%s) and qos\n", PGUID (*guid), name); pgroup->name = ddsrt_strdup (name); pgroup->xqos = nn_xqos_dup (xqos); - nn_xqos_mergein_missing (pgroup->xqos, is_sub ? &gv.default_xqos_sub : &gv.default_xqos_pub); + nn_xqos_mergein_missing (pgroup->xqos, is_sub ? &gv.default_xqos_sub : &gv.default_xqos_pub, ~(uint64_t)0); } out: ddsrt_mutex_unlock (&proxypp->e.lock); diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index e551bd0..e04b7fb 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -850,10 +850,11 @@ int rtps_init (void) uint32_t port_data_uc = 0; bool mc_available = true; + gv.tstart = now (); /* wall clock time, used in logs */ + ddsi_plugin_init (); ddsi_iid_init (); - - gv.tstart = now (); /* wall clock time, used in logs */ + nn_plist_init_tables (); gv.disc_conn_uc = NULL; gv.data_conn_uc = NULL; diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 1e65ee5..7d396c3 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -17,6 +17,7 @@ #include "dds/ddsrt/log.h" #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" #include "dds/ddsrt/static_assert.h" #include "dds/ddsi/q_log.h" @@ -26,6 +27,7 @@ #include "dds/ddsi/q_plist.h" #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_xmsg.h" +#include "dds/ddsi/ddsi_vendor.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_globals.h" @@ -74,531 +76,1457 @@ struct dd { nn_vendorid_t vendorid; }; -struct cdroctetseq { - uint32_t len; - unsigned char value[1]; +#define PDF_QOS 1 /* part of dds_qos_t */ +#define PDF_FUNCTION 2 /* use special functions */ +#define PDF_ALLOWMULTI 4 /* allow multiple copies -- do not use with Z or memory will leak */ + +struct flagset { + uint64_t *present; + uint64_t *aliased; + uint64_t wanted; +}; + +/* Instructions for the generic serializer (&c) that handles most parameters. + The "packed" attribute means single-byte instructions on GCC and Clang. */ +enum pserop { + XSTOP, + XO, /* octet sequence */ + XS, /* string */ + XZ, /* string sequence */ + XE1, XE2, XE3, /* enum 0..1, 0..2, 0..3 */ + Xl, /* length, int32_t, -1 or >= 1 */ + Xi, Xix2, Xix3, Xix4, /* int32_t, 1 .. 4 in a row */ + Xu, Xux2, Xux3, Xux4, Xux5, /* uint32_t, 1 .. 5 in a row */ + XD, XDx2, /* duration, 1 .. 2 in a row */ + Xo, Xox2, /* octet, 1 .. 2 in a row */ + Xb, Xbx2, /* boolean, 1 .. 2 in a row */ + XbCOND, /* boolean: compare to ignore remainder if false (for use_... flags) */ + XG, /* GUID */ + XK /* keyhash */ +} ddsrt_attribute_packed; + +struct piddesc { + nn_parameterid_t pid; /* parameter id or PID_PAD if strictly local */ + uint16_t flags; /* see PDF_xxx flags */ + 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 size; /* in-memory size for copying */ + union { + /* descriptor for generic code: 4 is enough for the current set of + parameters, compiler will warn if one ever tries to use more than + will fit; on non-GCC/Clang and 32-bits machines */ + const enum pserop desc[4]; + struct { + dds_return_t (*deser) (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff); + dds_return_t (*ser) (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff); + dds_return_t (*unalias) (void * __restrict dst, size_t * __restrict dstoff); + 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); + } f; + } op; + dds_return_t (*deser_validate_xform) (void * __restrict dst, const struct dd * __restrict dd); }; static void log_octetseq (uint32_t cat, 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); +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); +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); +static int partitions_equal (const dds_partition_qospolicy_t *a, const dds_partition_qospolicy_t *b); -static size_t align4u (size_t x) +static size_t align4size (size_t x) { - return (x + 3u) & ~(size_t)3; + return (x + 3) & ~(size_t)3; } +static void *deser_generic_dst (void * __restrict dst, size_t *dstoff, size_t align) +{ + *dstoff = (*dstoff + align - 1) & ~(align - 1); + return (char *) dst + *dstoff; +} + +static const void *deser_generic_src (const void * __restrict src, size_t *srcoff, size_t align) +{ + *srcoff = (*srcoff + align - 1) & ~(align - 1); + return (const char *) src + *srcoff; +} + +static void *ser_generic_align4 (char * __restrict p, size_t * __restrict off) +{ + *off = align4size (*off); + return p + *off; +} + +static dds_return_t deser_uint32 (uint32_t *dst, const struct dd * __restrict dd, size_t * __restrict off) +{ + size_t off1 = (*off + 3) & ~(size_t)3; + uint32_t tmp; + if (off1 + 4 > dd->bufsz) + return DDS_RETCODE_BAD_PARAMETER; + tmp = *((uint32_t *) (dd->buf + off1)); + if (dd->bswap) + tmp = bswap4u (tmp); + *dst = tmp; + *off = off1 + 4; + return 0; +} + +#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) +{ + DDSRT_STATIC_ASSERT (DDS_EXTERNAL_RELIABILITY_BEST_EFFORT == 1 && DDS_EXTERNAL_RELIABILITY_RELIABLE == 2 && + DDS_RELIABILITY_BEST_EFFORT == 0 && DDS_RELIABILITY_RELIABLE == 1); + dds_reliability_qospolicy_t * const x = deser_generic_dst (dst, dstoff, alignof (dds_reliability_qospolicy_t)); + uint32_t kind, mbtsec, mbtfrac; + ddsi_duration_t mbt; + if (deser_uint32 (&kind, dd, srcoff) < 0 || deser_uint32 (&mbtsec, dd, srcoff) < 0 || deser_uint32 (&mbtfrac, dd, srcoff) < 0) + return DDS_RETCODE_BAD_PARAMETER; + if (kind < 1 || kind > 2) + return DDS_RETCODE_BAD_PARAMETER; + mbt.seconds = (int32_t) mbtsec; + mbt.fraction = mbtfrac; + if (validate_external_duration (&mbt) < 0) + return DDS_RETCODE_BAD_PARAMETER; + x->kind = (enum dds_reliability_kind) (kind - 1); + x->max_blocking_time = nn_from_ddsi_duration (mbt); + *dstoff += sizeof (*x); + *flagset->present |= flag; + return 0; +} + +static dds_return_t ser_reliability (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff) +{ + DDSRT_STATIC_ASSERT (DDS_EXTERNAL_RELIABILITY_BEST_EFFORT == 1 && DDS_EXTERNAL_RELIABILITY_RELIABLE == 2 && + DDS_RELIABILITY_BEST_EFFORT == 0 && DDS_RELIABILITY_RELIABLE == 1); + dds_reliability_qospolicy_t const * const x = deser_generic_src (src, &srcoff, alignof (dds_reliability_qospolicy_t)); + ddsi_duration_t mbt = nn_to_ddsi_duration (x->max_blocking_time); + uint32_t * const p = nn_xmsg_addpar (xmsg, pid, 3 * sizeof (uint32_t)); + p[0] = 1 + (uint32_t) x->kind; + p[1] = (uint32_t) mbt.seconds; + p[2] = mbt.fraction; + return 0; +} + +static dds_return_t valid_reliability (const void *src, size_t srcoff) +{ + dds_reliability_qospolicy_t const * const x = deser_generic_src (src, &srcoff, alignof (dds_reliability_qospolicy_t)); + if ((x->kind == DDS_RELIABILITY_BEST_EFFORT || x->kind == DDS_RELIABILITY_RELIABLE) && x->max_blocking_time >= 0) + return 0; + else + return DDS_RETCODE_BAD_PARAMETER; +} + +static bool equal_reliability (const void *srcx, const void *srcy, size_t srcoff) +{ + dds_reliability_qospolicy_t const * const x = deser_generic_src (srcx, &srcoff, alignof (dds_reliability_qospolicy_t)); + dds_reliability_qospolicy_t const * const y = deser_generic_src (srcy, &srcoff, alignof (dds_reliability_qospolicy_t)); + return x->kind == y->kind && x->max_blocking_time == y->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)); + size_t srcoff1 = (*srcoff + 3) & ~(size_t)3; + if (srcoff1 + 4 > dd->bufsz) + return DDS_RETCODE_BAD_PARAMETER; + /* status info is always in BE format (it is an array of 4 octets according to the spec) -- + fortunately we have 4 byte alignment anyway -- and can have bits set we don't grok + (which we discard) */ + *x = fromBE4u (*((uint32_t *) (dd->buf + srcoff1))) & NN_STATUSINFO_STANDARDIZED; + *dstoff += sizeof (*x); + *srcoff = srcoff1 + 4; + *flagset->present |= flag; + return 0; +} + +static dds_return_t ser_statusinfo (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff) +{ + uint32_t const * const x = deser_generic_src (src, &srcoff, alignof (uint32_t)); + uint32_t * const p = nn_xmsg_addpar (xmsg, pid, sizeof (uint32_t)); + *p = toBE4u (*x); + return 0; +} + +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)); + /* FIXME: don't want to modify do_locator just yet, and don't want to require that a + locator is the only thing in the descriptor string (even though it actually always is), + so do alignment explicitly, fake a temporary input buffer and advance the source buffer */ + *srcoff = (*srcoff + 3) & ~(size_t)3; + if (*srcoff > dd->bufsz || dd->bufsz - *srcoff < 24) + return DDS_RETCODE_BAD_PARAMETER; + struct dd tmpdd = *dd; + tmpdd.buf += *srcoff; + tmpdd.bufsz -= *srcoff; + if (do_locator (x, flagset->present, flagset->wanted, flag, &tmpdd) < 0) + return DDS_RETCODE_BAD_PARAMETER; + *srcoff += 24; + *dstoff += sizeof (*x); + *flagset->present |= flag; + return 0; +} + +static dds_return_t ser_locator (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff) +{ + 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)); + } + return 0; +} + +static dds_return_t unalias_locator (void * __restrict dst, size_t * __restrict dstoff) +{ + nn_locators_t * const x = deser_generic_dst (dst, dstoff, alignof (nn_locators_t)); + nn_locators_t newlocs = { .n = x->n, .first = NULL, .last = NULL }; + struct nn_locators_one **pnext = &newlocs.first; + for (const struct nn_locators_one *lold = x->first; lold != NULL; lold = lold->next) + { + struct nn_locators_one *n = ddsrt_memdup (lold, sizeof (*n)); + *pnext = n; + pnext = &n->next; + } + newlocs.last = *pnext; + *pnext = NULL; + *x = newlocs; + *dstoff += sizeof (*x); + return 0; +} + +static dds_return_t fini_locator (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag) +{ + nn_locators_t * const x = deser_generic_dst (dst, dstoff, alignof (nn_locators_t)); + if (!(*flagset->aliased &flag)) + { + while (x->first) + { + struct nn_locators_one *l = x->first; + x->first = l->next; + ddsrt_free (l); + } + } + return 0; +} + +static void fini_generic_partial (void * __restrict dst, size_t * __restrict dstoff, const enum pserop *desc, const enum pserop * const desc_end, bool aliased) +{ +#define COMPLEX(basecase_, type_, cleanup_unaliased_, cleanup_always_) do { \ + type_ *x = deser_generic_dst (dst, dstoff, alignof (type_)); \ + const uint32_t cnt = 1 + (uint32_t) (*desc - (basecase_)); \ + for (uint32_t xi = 0; xi < cnt; xi++, x++) { \ + if (!aliased) do { cleanup_unaliased_; } while (0); \ + do { cleanup_always_; } while (0); \ + } \ + *dstoff += cnt * sizeof (*x); \ + } while (0) +#define SIMPLE(basecase_, type_) COMPLEX (basecase_, type_, (void) 0, (void) 0) + while (desc != desc_end) + { + switch (*desc) + { + case XSTOP: return; + case XO: COMPLEX (XO, ddsi_octetseq_t, ddsrt_free (x->value), (void) 0); break; + case XS: COMPLEX (XS, char *, ddsrt_free (*x), (void) 0); break; + case XZ: COMPLEX (XZ, ddsi_stringseq_t, { for (uint32_t i = 0; i < x->n; i++) ddsrt_free (x->strs[i]); }, ddsrt_free (x->strs)); break; + case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, (void) 0, (void) 0); break; + case Xi: case Xix2: case Xix3: case Xix4: SIMPLE (Xi, int32_t); break; + case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE (Xu, uint32_t); break; + case Xl: SIMPLE (Xl, int32_t); break; + case XD: case XDx2: SIMPLE (XD, dds_duration_t); break; + case Xo: case Xox2: SIMPLE (Xo, unsigned char); break; + case Xb: case Xbx2: SIMPLE (Xb, unsigned char); break; + case XbCOND: SIMPLE (XbCOND, unsigned char); break; + case XG: SIMPLE (XG, nn_guid_t); break; + case XK: SIMPLE (XK, nn_keyhash_t); break; + } + desc++; + } +#undef SIMPLE +#undef COMPLEX +} + +static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff, const enum pserop * __restrict desc) +{ + enum pserop const * const desc_in = desc; + size_t dstoff_in = *dstoff; + /* very large buffers run a risk with alignment calculations; such buffers basically + do not occur for discovery data, so checking makes sense */ + if (dd->bufsz >= SIZE_MAX - 8) + return DDS_RETCODE_BAD_PARAMETER; + while (true) + { + assert (*srcoff <= dd->bufsz); + switch (*desc) + { + case XSTOP: + *flagset->present |= flag; + return 0; + case XO: { /* octet sequence */ + ddsi_octetseq_t * const x = deser_generic_dst (dst, dstoff, alignof (ddsi_octetseq_t)); + if (deser_uint32 (&x->length, dd, srcoff) < 0 || dd->bufsz - *srcoff < x->length) + goto fail; + x->value = x->length ? (unsigned char *) (dd->buf + *srcoff) : NULL; + *srcoff += x->length; + *dstoff += sizeof (*x); + *flagset->aliased |= flag; + break; + } + case XS: { /* string: alias as-if octet sequence, do additional checks and store as string */ + char ** const x = deser_generic_dst (dst, dstoff, alignof (char *)); + ddsi_octetseq_t tmp; + size_t tmpoff = 0; + if (deser_generic (&tmp, &tmpoff, flagset, flag, dd, srcoff, (enum pserop []) { XO, XSTOP }) < 0) + goto fail; + if (tmp.length < 1 || tmp.value[tmp.length - 1] != 0) + goto fail; + *x = (char *) tmp.value; + *dstoff += sizeof (*x); + break; + } + case XZ: { /* string sequence: repeatedly read a string */ + ddsi_stringseq_t * const x = deser_generic_dst (dst, dstoff, alignof (ddsi_stringseq_t)); + /* sequence of string: length length ..., where each length is aligned + to a multiple of 4 bytes and the lengths are all at least 1, therefore all but the + last entry need 8 bytes and the final one at least 5; checking this protects us + against allocating large amount of memory */ + if (deser_uint32 (&x->n, dd, srcoff) < 0 || x->n > (dd->bufsz - *srcoff + 7) / 8) + goto fail; + x->strs = x->n ? ddsrt_malloc (x->n * sizeof (*x->strs)) : NULL; + size_t tmpoff = 0; + for (uint32_t i = 0; i < x->n; i++) + if (deser_generic (x->strs, &tmpoff, flagset, flag, dd, srcoff, (enum pserop []) { XS, XSTOP }) < 0) + goto fail; + *dstoff += sizeof (*x); + break; + } + case XE1: case XE2: case XE3: { /* enum with max allowed value */ + unsigned * const x = deser_generic_dst (dst, dstoff, alignof (int)); + const uint32_t maxval = 1 + (uint32_t) (*desc - XE1); + uint32_t tmp; + if (deser_uint32 (&tmp, dd, srcoff) < 0 || tmp > maxval) + goto fail; + *x = (unsigned) tmp; + *dstoff += sizeof (*x); + break; + } + case Xi: case Xix2: case Xix3: case Xix4: { /* int32_t(s) */ + uint32_t * const x = deser_generic_dst (dst, dstoff, alignof (uint32_t)); + const uint32_t cnt = 1 + (uint32_t) (*desc - Xi); + for (uint32_t i = 0; i < cnt; i++) + if (deser_uint32 (&x[i], dd, srcoff) < 0) + goto fail; + *dstoff += cnt * sizeof (*x); + break; + } + case Xu: case Xux2: case Xux3: case Xux4: case Xux5: { /* uint32_t(s): treated the same */ + uint32_t * const x = deser_generic_dst (dst, dstoff, alignof (uint32_t)); + const uint32_t cnt = 1 + (uint32_t) (*desc - Xu); + for (uint32_t i = 0; i < cnt; i++) + if (deser_uint32 (&x[i], dd, srcoff) < 0) + goto fail; + *dstoff += cnt * sizeof (*x); + break; + } + case Xl: { /* length(s): int32_t, -1 or >= 1 */ + int32_t * const x = deser_generic_dst (dst, dstoff, alignof (uint32_t)); + const uint32_t cnt = 1 + (uint32_t) (*desc - Xl); + for (uint32_t i = 0; i < cnt; i++) + if (deser_uint32 ((uint32_t *) &x[i], dd, srcoff) < 0 || (x[i] < 1 && x[i] != DDS_LENGTH_UNLIMITED)) + goto fail; + *dstoff += cnt * sizeof (*x); + break; + } + case XD: case XDx2: { /* duration(s): int64_t <=> int32_t.uint32_t (seconds.fraction) */ + dds_duration_t * const x = deser_generic_dst (dst, dstoff, alignof (dds_duration_t)); + const uint32_t cnt = 1 + (uint32_t) (*desc - XD); + for (uint32_t i = 0; i < cnt; i++) + { + ddsi_duration_t tmp; + if (deser_uint32 ((uint32_t *) &tmp.seconds, dd, srcoff) < 0 || deser_uint32 (&tmp.fraction, dd, srcoff) < 0) + goto fail; + if (validate_external_duration (&tmp)) + goto fail; + x[i] = nn_from_ddsi_duration (tmp); + } + *dstoff += cnt * sizeof (*x); + break; + } + case Xo: case Xox2: { /* octet(s) */ + unsigned char * const x = deser_generic_dst (dst, dstoff, alignof (unsigned char)); + const uint32_t cnt = 1 + (uint32_t) (*desc - Xo); + if (dd->bufsz - *srcoff < cnt) + goto fail; + memcpy (x, dd->buf + *srcoff, cnt); + *srcoff += cnt; + *dstoff += cnt * sizeof (*x); + break; + } + case Xb: case Xbx2: case XbCOND: { /* boolean(s) */ + unsigned char * const x = deser_generic_dst (dst, dstoff, alignof (unsigned char)); + const uint32_t cnt = (*desc == Xbx2) ? 2 : 1; /* <<<< beware! */ + if (dd->bufsz - *srcoff < cnt) + goto fail; + memcpy (x, dd->buf + *srcoff, cnt); + for (uint32_t i = 0; i < cnt; i++) + if (x[i] > 1) + goto fail; + *srcoff += cnt; + *dstoff += cnt * sizeof (*x); + break; + } + case XG: { /* GUID */ + nn_guid_t * const x = deser_generic_dst (dst, dstoff, alignof (nn_guid_t)); + if (dd->bufsz - *srcoff < sizeof (*x)) + goto fail; + memcpy (x, dd->buf + *srcoff, sizeof (*x)); + *x = nn_ntoh_guid (*x); + *srcoff += sizeof (*x); + *dstoff += sizeof (*x); + break; + } + case XK: { /* keyhash */ + nn_keyhash_t * const x = deser_generic_dst (dst, dstoff, alignof (nn_keyhash_t)); + if (dd->bufsz - *srcoff < sizeof (*x)) + goto fail; + memcpy (x, dd->buf + *srcoff, sizeof (*x)); + *srcoff += sizeof (*x); + *dstoff += sizeof (*x); + break; + } + } + desc++; + } + +fail: + fini_generic_partial (dst, &dstoff_in, desc_in, desc, *flagset->aliased & flag); + *flagset->present &= ~flag; + *flagset->aliased &= ~flag; + return DDS_RETCODE_BAD_PARAMETER; +} + +static size_t ser_generic_size (const void *src, size_t srcoff, const enum pserop * __restrict desc) +{ + size_t dstoff = 0; +#define COMPLEX(basecase_, type_, dstoff_update_) do { \ + type_ const *x = deser_generic_src (src, &srcoff, alignof (type_)); \ + const uint32_t cnt = 1 + (uint32_t) (*desc - (basecase_)); \ + for (uint32_t xi = 0; xi < cnt; xi++, x++) { dstoff_update_; } \ + srcoff += cnt * sizeof (*x); \ + } while (0) +#define SIMPLE1(basecase_, type_) COMPLEX (basecase_, type_, dstoff = dstoff + sizeof (*x)) +#define SIMPLE4(basecase_, type_) COMPLEX (basecase_, type_, dstoff = align4size (dstoff) + sizeof (*x)) + while (true) + { + switch (*desc) + { + case XSTOP: return dstoff; + case XO: COMPLEX (XO, ddsi_octetseq_t, dstoff = align4size (dstoff) + 4 + x->length); break; + case XS: COMPLEX (XS, const char *, dstoff = align4size (dstoff) + 4 + strlen (*x) + 1); break; + case XZ: COMPLEX (XZ, ddsi_stringseq_t, { + dstoff = align4size (dstoff) + 4; + for (uint32_t i = 0; i < x->n; i++) + dstoff = align4size (dstoff) + 4 + strlen (x->strs[i]) + 1; + }); break; + case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, dstoff = align4size (dstoff) + 4); break; + case Xi: case Xix2: case Xix3: case Xix4: SIMPLE4 (Xi, int32_t); break; + case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE4 (Xu, uint32_t); break; + case Xl: SIMPLE4 (Xl, int32_t); break; + case XD: case XDx2: SIMPLE4 (XD, dds_duration_t); break; + case Xo: case Xox2: SIMPLE1 (Xo, unsigned char); break; + case Xb: case Xbx2: SIMPLE1 (Xb, unsigned char); break; + case XbCOND: SIMPLE1 (XbCOND, unsigned char); break; + case XG: SIMPLE1 (XG, nn_guid_t); break; + case XK: SIMPLE1 (XK, nn_keyhash_t); break; + } + desc++; + } +#undef SIMPLE +#undef COMPLEX +} + +static dds_return_t ser_generic (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff, const enum pserop * __restrict desc) +{ + char * const data = nn_xmsg_addpar (xmsg, pid, ser_generic_size (src, srcoff, desc)); + size_t dstoff = 0; + while (true) + { + switch (*desc) + { + case XSTOP: + return 0; + case XO: { /* octet sequence */ + ddsi_octetseq_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_octetseq_t)); + char * const p = ser_generic_align4 (data, &dstoff); + *((uint32_t *) p) = x->length; + if (x->length) memcpy (p + 4, x->value, x->length); + dstoff += 4 + x->length; + srcoff += sizeof (*x); + break; + } + case XS: { /* string */ + char const * const * const x = deser_generic_src (src, &srcoff, alignof (char *)); + const uint32_t size = (uint32_t) (strlen (*x) + 1); + char * const p = ser_generic_align4 (data, &dstoff); + *((uint32_t *) p) = size; + memcpy (p + 4, *x, size); + dstoff += 4 + size; + srcoff += sizeof (*x); + break; + } + case XZ: { /* string sequence */ + ddsi_stringseq_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_stringseq_t)); + char * const p = ser_generic_align4 (data, &dstoff); + *((uint32_t *) p) = x->n; + dstoff += 4; + for (uint32_t i = 0; i < x->n; i++) + { + char * const q = ser_generic_align4 (data, &dstoff); + const uint32_t size = (uint32_t) (strlen (x->strs[i]) + 1); + *((uint32_t *) q) = size; + memcpy (q + 4, x->strs[i], size); + dstoff += 4 + size; + } + srcoff += sizeof (*x); + break; + } + case XE1: case XE2: case XE3: { /* enum */ + unsigned const * const x = deser_generic_src (src, &srcoff, alignof (unsigned)); + uint32_t * const p = ser_generic_align4 (data, &dstoff); + *p = (uint32_t) *x; + dstoff += 4; + srcoff += sizeof (*x); + break; + } + case Xi: case Xix2: case Xix3: case Xix4: { /* int32_t(s) */ + int32_t const * const x = deser_generic_src (src, &srcoff, alignof (int32_t)); + const uint32_t cnt = 1 + (uint32_t) (*desc - Xi); + int32_t * const p = ser_generic_align4 (data, &dstoff); + for (uint32_t i = 0; i < cnt; i++) + p[i] = x[i]; + dstoff += cnt * sizeof (*x); + srcoff += cnt * sizeof (*x); + break; + } + + case Xu: case Xux2: case Xux3: case Xux4: case Xux5: { /* uint32_t(s) */ + uint32_t const * const x = deser_generic_src (src, &srcoff, alignof (uint32_t)); + const uint32_t cnt = 1 + (uint32_t) (*desc - Xu); + uint32_t * const p = ser_generic_align4 (data, &dstoff); + for (uint32_t i = 0; i < cnt; i++) + p[i] = x[i]; + dstoff += cnt * sizeof (*x); + srcoff += cnt * sizeof (*x); + break; + } + + case Xl: { /* int32_t(s) */ + int32_t const * const x = deser_generic_src (src, &srcoff, alignof (uint32_t)); + const uint32_t cnt = 1 + (uint32_t) (*desc - Xu); + int32_t * const p = ser_generic_align4 (data, &dstoff); + for (uint32_t i = 0; i < cnt; i++) + p[i] = x[i]; + dstoff += cnt * sizeof (*x); + srcoff += cnt * sizeof (*x); + break; + } + case XD: case XDx2: { /* duration(s): int64_t <=> int32_t.uint32_t (seconds.fraction) */ + dds_duration_t const * const x = deser_generic_src (src, &srcoff, alignof (dds_duration_t)); + const uint32_t cnt = 1 + (uint32_t) (*desc - XD); + uint32_t * const p = ser_generic_align4 (data, &dstoff); + for (uint32_t i = 0; i < cnt; i++) + { + ddsi_duration_t tmp = nn_to_ddsi_duration (x[i]); + p[2 * i + 0] = (uint32_t) tmp.seconds; + p[2 * i + 1] = tmp.fraction; + } + dstoff += 2 * cnt * sizeof (uint32_t); + srcoff += cnt * sizeof (*x); + break; + } + case Xo: case Xox2: { /* octet(s) */ + unsigned char const * const x = deser_generic_src (src, &srcoff, alignof (unsigned char)); + const uint32_t cnt = 1 + (uint32_t) (*desc - Xo); + char * const p = data + dstoff; + memcpy (p, x, cnt); + dstoff += cnt; + srcoff += cnt * sizeof (*x); + break; + } + case Xb: case Xbx2: case XbCOND: { /* boolean(s) */ + unsigned char const * const x = deser_generic_src (src, &srcoff, alignof (unsigned char)); + const uint32_t cnt = (*desc == Xbx2) ? 2 : 1; /* <<<< beware! */ + char * const p = data + dstoff; + memcpy (p, x, cnt); + dstoff += cnt; + srcoff += cnt * sizeof (*x); + break; + } + case XG: { /* GUID */ + nn_guid_t const * const x = deser_generic_src (src, &srcoff, alignof (nn_guid_t)); + const nn_guid_t xn = nn_hton_guid (*x); + char * const p = data + dstoff; + memcpy (p, &xn, sizeof (xn)); + dstoff += sizeof (xn); + srcoff += sizeof (*x); + break; + } + case XK: { /* keyhash */ + nn_keyhash_t const * const x = deser_generic_src (src, &srcoff, alignof (nn_keyhash_t)); + char * const p = data + dstoff; + memcpy (p, x, sizeof (*x)); + dstoff += sizeof (*x); + srcoff += sizeof (*x); + break; + } + } + desc++; + } +} + +static dds_return_t unalias_generic (void * __restrict dst, size_t * __restrict dstoff, const enum pserop * __restrict desc) +{ +#define COMPLEX(basecase_, type_, ...) do { \ + type_ *x = deser_generic_dst (dst, dstoff, alignof (type_)); \ + const uint32_t cnt = 1 + (uint32_t) (*desc - basecase_); \ + for (uint32_t xi = 0; xi < cnt; xi++, x++) { __VA_ARGS__; } \ + *dstoff += cnt * sizeof (*x); \ + } while (0) +#define SIMPLE(basecase_, type_) COMPLEX (basecase_, type_, (void) 0) + while (true) + { + switch (*desc) + { + case XSTOP: + return 0; + case XO: COMPLEX (XO, ddsi_octetseq_t, x->value = ddsrt_memdup (x->value, x->length)); break; + case XS: COMPLEX (XS, char *, *x = ddsrt_strdup (*x)); break; + case XZ: COMPLEX (XZ, ddsi_stringseq_t, { + x->strs = ddsrt_memdup (x->strs, x->n * sizeof (*x->strs)); + for (uint32_t i = 0; i < x->n; i++) + x->strs[i] = ddsrt_strdup (x->strs[i]); + }); break; + case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, (void) 0); break; + case Xi: case Xix2: case Xix3: case Xix4: SIMPLE (Xi, int32_t); break; + case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE (Xu, uint32_t); break; + case Xl: SIMPLE (Xl, int32_t); break; + case XD: case XDx2: SIMPLE (XD, dds_duration_t); break; + case Xo: case Xox2: SIMPLE (Xo, unsigned char); break; + case Xb: case Xbx2: SIMPLE (Xb, unsigned char); break; + case XbCOND: SIMPLE (XbCOND, unsigned char); break; + case XG: SIMPLE (XG, nn_guid_t); break; + case XK: SIMPLE (XK, nn_keyhash_t); break; + } + desc++; + } +#undef SIMPLE +#undef COMPLEX +} + +static bool unalias_generic_required (const enum pserop * __restrict desc) +{ + while (*desc != XSTOP) + { + switch (*desc++) + { + case XO: case XS: case XZ: + return true; + default: + break; + } + } + return false; +} + +static bool fini_generic_required (const enum pserop * __restrict desc) +{ + /* the two happen to be the same */ + return unalias_generic_required (desc); +} + +static dds_return_t fini_generic (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const enum pserop * __restrict desc) +{ + fini_generic_partial (dst, dstoff, desc, NULL, *flagset->aliased & flag); + return 0; +} + +static dds_return_t valid_generic (const void *src, size_t srcoff, const enum pserop * __restrict desc) +{ +#define COMPLEX(basecase_, type_, cond_stmts_) do { \ + type_ const *x = deser_generic_src (src, &srcoff, alignof (type_)); \ + const uint32_t cnt = 1 + (uint32_t) (*desc - (basecase_)); \ + for (uint32_t xi = 0; xi < cnt; xi++, x++) { cond_stmts_; } \ + srcoff += cnt * sizeof (*x); \ + } while (0) +#define SIMPLE(basecase_, type_, cond_) COMPLEX (basecase_, type_, if (!(cond_)) return DDS_RETCODE_BAD_PARAMETER) +#define TRIVIAL(basecase_, type_) COMPLEX (basecase_, type_, (void) 0) + while (true) + { + switch (*desc) + { + case XSTOP: return 0; + case XO: SIMPLE (XO, ddsi_octetseq_t, (x->length == 0) == (x->value == NULL)); break; + case XS: SIMPLE (XS, const char *, *x != NULL); break; + case XZ: COMPLEX (XZ, ddsi_stringseq_t, { + if ((x->n == 0) != (x->strs == NULL)) + return DDS_RETCODE_BAD_PARAMETER; + for (uint32_t i = 0; i < x->n; i++) + if (x->strs[i] == NULL) + return DDS_RETCODE_BAD_PARAMETER; + }); break; + case XE1: case XE2: case XE3: SIMPLE (*desc, unsigned, *x <= 1 + (unsigned) *desc - XE1); break; + case Xi: case Xix2: case Xix3: case Xix4: TRIVIAL (Xi, int32_t); break; + case Xu: case Xux2: case Xux3: case Xux4: case Xux5: TRIVIAL (Xu, uint32_t); break; + case Xl: SIMPLE (Xl, int32_t, *x == DDS_LENGTH_UNLIMITED || *x > 1); break; + case XD: case XDx2: SIMPLE (XD, dds_duration_t, *x >= 0); break; + case Xo: case Xox2: TRIVIAL (Xo, unsigned char); break; + case Xb: case Xbx2: SIMPLE (Xb, unsigned char, *x == 0 || *x == 1); break; + case XbCOND: SIMPLE (XbCOND, unsigned char, *x == 0 || *x == 1); break; + case XG: TRIVIAL (XG, nn_guid_t); break; + case XK: TRIVIAL (XK, nn_keyhash_t); break; + } + desc++; + } +#undef TRIVIAL +#undef SIMPLE +#undef COMPLEX +} + +static bool equal_generic (const void *srcx, const void *srcy, size_t srcoff, const enum pserop * __restrict desc) +{ +#define COMPLEX(basecase_, type_, cond_stmts_) do { \ + type_ const *x = deser_generic_src (srcx, &srcoff, alignof (type_)); \ + type_ const *y = deser_generic_src (srcy, &srcoff, alignof (type_)); \ + const uint32_t cnt = 1 + (uint32_t) (*desc - (basecase_)); \ + for (uint32_t xi = 0; xi < cnt; xi++, x++, y++) { cond_stmts_; } \ + srcoff += cnt * sizeof (*x); \ + } while (0) +#define SIMPLE(basecase_, type_, cond_) COMPLEX (basecase_, type_, if (!(cond_)) return false) +#define TRIVIAL(basecase_, type_) SIMPLE (basecase_, type_, *x == *y) + while (true) + { + switch (*desc) + { + case XSTOP: + return true; + case XO: + SIMPLE (XO, ddsi_octetseq_t, + (x->length == y->length) && + (x->length == 0 || memcmp (x->value, y->value, x->length) == 0)); + break; + case XS: + SIMPLE (XS, const char *, strcmp (*x, *y) == 0); + break; + case XZ: + COMPLEX (XZ, ddsi_stringseq_t, { + if (x->n != y->n) + return false; + for (uint32_t i = 0; i < x->n; i++) + if (strcmp (x->strs[i], y->strs[i]) != 0) + return false; + }); + break; + case XE1: case XE2: case XE3: TRIVIAL (*desc, unsigned); break; + case Xi: case Xix2: case Xix3: case Xix4: TRIVIAL (Xi, int32_t); break; + case Xu: case Xux2: case Xux3: case Xux4: case Xux5: TRIVIAL (Xu, uint32_t); break; + case Xl: TRIVIAL (Xl, int32_t); break; + case XD: case XDx2: TRIVIAL (XD, dds_duration_t); break; + case Xo: case Xox2: TRIVIAL (Xo, unsigned char); break; + case Xb: case Xbx2: TRIVIAL (Xb, unsigned char); break; + case XbCOND: + COMPLEX (XbCOND, unsigned char, { + if (*x != *y) + return false; + if (*x == false) + return true; + }); + break; + case XG: SIMPLE (XG, nn_guid_t, memcmp (x, y, sizeof (*x))); break; + case XK: SIMPLE (XK, nn_keyhash_t, memcmp (x, y, sizeof (*x))); break; + } + desc++; + } +#undef TRIVIAL +#undef SIMPLE +#undef COMPLEX +} + +#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 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__) +#define QP(NAME_, name_, ...) ENTRY(QP, NAME_, qos.name_, PDF_QOS, 0, __VA_ARGS__) +#define PP(NAME_, name_, ...) ENTRY(PP, NAME_, name_, 0, 0, __VA_ARGS__) +#define PPM(NAME_, name_, ...) ENTRY(PP, NAME_, name_, PDF_ALLOWMULTI, 0, __VA_ARGS__) + static int protocol_version_is_newer (nn_protocol_version_t pv) { return (pv.major < RTPS_MAJOR) ? 0 : (pv.major > RTPS_MAJOR) ? 1 : (pv.minor > RTPS_MINOR); } -static dds_return_t validate_string (const struct dd *dd, size_t *len) +static dds_return_t dvx_durability_service (void * __restrict dst, const struct dd * __restrict dd) { - const struct cdrstring *x = (const struct cdrstring *) dd->buf; - if (dd->bufsz < sizeof (struct cdrstring)) - { - DDS_TRACE("plist/validate_string: buffer too small (header)\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - *len = dd->bswap ? bswap4u (x->length) : x->length; - if (*len < 1 || *len > dd->bufsz - offsetof (struct cdrstring, contents)) - { - DDS_TRACE("plist/validate_string: length %" PRIuSIZE " out of range\n", *len); - return DDS_RETCODE_BAD_PARAMETER; - } - if (x->contents[*len-1] != 0) - { - DDS_TRACE("plist/validate_string: terminator missing\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - return 0; + /* Accept all zero durability because of CoreDX, final_validation is more strict */ + (void) dd; + return validate_durability_service_qospolicy_acceptzero (dst, true); } -static dds_return_t alias_string (const unsigned char **ptr, const struct dd *dd, size_t *len) +static dds_return_t dvx_history (void * __restrict dst, const struct dd * __restrict dd) { - dds_return_t rc; - if ((rc = validate_string (dd, len)) < 0) - return rc; + (void) dd; + return validate_history_qospolicy (dst); +} + +static dds_return_t dvx_resource_limits (void * __restrict dst, const struct dd * __restrict dd) +{ + (void) dd; + return validate_resource_limits_qospolicy (dst); +} + +static dds_return_t dvx_participant_guid (void * __restrict dst, const struct dd * __restrict dd) +{ + const nn_guid_t *g = dst; + (void) dd; + if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0) + return (g->entityid.u == 0) ? 0 : DDS_RETCODE_BAD_PARAMETER; else - { - const struct cdrstring *x = (const struct cdrstring *) dd->buf; - *ptr = x->contents; - return 0; - } + return (g->entityid.u == NN_ENTITYID_PARTICIPANT) ? 0 : DDS_RETCODE_BAD_PARAMETER; } -static void unalias_string (char **str, int bswap) +static dds_return_t dvx_group_guid (void * __restrict dst, const struct dd * __restrict dd) { - const char *alias = *str; - uint32_t len; - if (bswap == 0 || bswap == 1) - { - const uint32_t *plen = (const uint32_t *) alias - 1; - len = bswap ? bswap4u (*plen) : *plen; - } + const nn_guid_t *g = dst; + (void) dd; + if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0) + return (g->entityid.u == 0) ? 0 : DDS_RETCODE_BAD_PARAMETER; else - { - len = (uint32_t) strlen (alias) + 1; - } - *str = ddsrt_malloc (len); - memcpy (*str, alias, len); + return (g->entityid.u != 0) ? 0 : DDS_RETCODE_BAD_PARAMETER; } -static dds_return_t validate_octetseq (const struct dd *dd, size_t *len) +static dds_return_t dvx_endpoint_guid (void * __restrict dst, const struct dd * __restrict dd) { - const struct cdroctetseq *x = (const struct cdroctetseq *) dd->buf; - if (dd->bufsz < offsetof (struct cdroctetseq, value)) - return DDS_RETCODE_BAD_PARAMETER; - *len = dd->bswap ? bswap4u (x->len) : x->len; - if (*len > dd->bufsz - offsetof (struct cdroctetseq, value) || *len >= UINT32_MAX) - return DDS_RETCODE_BAD_PARAMETER; + nn_guid_t *g = dst; + if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0) + return (g->entityid.u == 0) ? 0 : DDS_RETCODE_BAD_PARAMETER; + switch (g->entityid.u & NN_ENTITYID_KIND_MASK) + { + case NN_ENTITYID_KIND_WRITER_WITH_KEY: + case NN_ENTITYID_KIND_WRITER_NO_KEY: + case NN_ENTITYID_KIND_READER_NO_KEY: + case NN_ENTITYID_KIND_READER_WITH_KEY: + return 0; + default: + return (protocol_version_is_newer (dd->protocol_version) ? 0 : DDS_RETCODE_BAD_PARAMETER); + } +} + +#ifdef DDSI_INCLUDE_SSM +static dds_return_t dvx_reader_favours_ssm (void * __restrict dst, const struct dd * __restrict dd) +{ + uint32_t * const favours_ssm = dst; + (void) dd; + /* any unrecognized state: avoid SSM */ + if (*favours_ssm != 0 && *favours_ssm != 1) + *favours_ssm = 0; return 0; } - -static dds_return_t alias_octetseq (ddsi_octetseq_t *oseq, const struct dd *dd) -{ - size_t len; - dds_return_t rc; - if ((rc = validate_octetseq (dd, &len)) < 0) - return rc; - else - { - const struct cdroctetseq *x = (const struct cdroctetseq *) dd->buf; - assert(len < UINT32_MAX); /* it really is an uint32_t on the wire */ - oseq->length = (uint32_t)len; - oseq->value = (len == 0) ? NULL : (unsigned char *) x->value; - return 0; - } -} - -static dds_return_t alias_blob (ddsi_octetseq_t *oseq, const struct dd *dd) -{ - assert (dd->bufsz < UINT32_MAX); - oseq->length = (uint32_t)dd->bufsz; - oseq->value = (oseq->length == 0) ? NULL : (unsigned char *) dd->buf; - return 0; -} - -static void unalias_octetseq (ddsi_octetseq_t *oseq, UNUSED_ARG (int bswap)) -{ - if (oseq->length != 0) - { - unsigned char *vs; - vs = ddsrt_malloc (oseq->length); - memcpy (vs, oseq->value, oseq->length); - oseq->value = vs; - } -} - -static dds_return_t validate_stringseq (const struct dd *dd) -{ - const unsigned char *seq = dd->buf; - const unsigned char *seqend = seq + dd->bufsz; - struct dd dd1 = *dd; - int i, n; - if (dd->bufsz < sizeof (int)) - { - DDS_TRACE("plist/validate_stringseq: buffer too small (header)\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - memcpy (&n, seq, sizeof (n)); - if (dd->bswap) - n = bswap4 (n); - seq += sizeof (int); - if (n < 0) - { - DDS_TRACE("plist/validate_stringseq: length %d out of range\n", n); - return DDS_RETCODE_BAD_PARAMETER; - } - else if (n == 0) - { - return 0; - } - else - { - for (i = 0; i < n && seq <= seqend; i++) - { - size_t len1; - int rc; - dd1.buf = seq; - dd1.bufsz = (size_t) (seqend - seq); - if ((rc = validate_string (&dd1, &len1)) < 0) - { - DDS_TRACE("plist/validate_stringseq: invalid string\n"); - return rc; - } - seq += sizeof (uint32_t) + align4u (len1); - } - if (i < n) - { - DDS_TRACE("plist/validate_stringseq: buffer too small (contents)\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - } - /* Should I worry about junk between the last string & the end of - the parameter? */ - return 0; -} - -static dds_return_t alias_stringseq (ddsi_stringseq_t *strseq, const struct dd *dd) -{ - /* Not truly an alias: it allocates an array of pointers that alias - the individual null-terminated strings. Also: see - validate_stringseq */ - const unsigned char *seq = dd->buf; - const unsigned char *seqend = seq + dd->bufsz; - struct dd dd1 = *dd; - char **strs; - uint32_t i; - dds_return_t result; - if (dd->bufsz < sizeof (int)) - { - DDS_TRACE("plist/alias_stringseq: buffer too small (header)\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - memcpy (&strseq->n, seq, sizeof (strseq->n)); - if (dd->bswap) - strseq->n = bswap4u (strseq->n); - seq += sizeof (uint32_t); - if (strseq->n >= UINT_MAX / sizeof(*strs)) - { - DDS_TRACE("plist/alias_stringseq: length %"PRIu32" out of range\n", strseq->n); - return DDS_RETCODE_BAD_PARAMETER; - } - else if (strseq->n == 0) - { - strseq->strs = NULL; - } - else - { - strs = ddsrt_malloc (strseq->n * sizeof (*strs)); - for (i = 0; i < strseq->n && seq <= seqend; i++) - { - size_t len1; - dd1.buf = seq; - dd1.bufsz = (size_t)(seqend - seq); - /* (const char **) to silence the compiler, unfortunately strseq - can't have a const char **strs, that would require a const - and a non-const version of it. */ - if ((result = alias_string ((const unsigned char **) &strs[i], &dd1, &len1)) < 0) - { - DDS_TRACE("plist/alias_stringseq: invalid string\n"); - goto fail; - } - seq += sizeof (uint32_t) + align4u (len1); - } - if (i != strseq->n) - { - DDS_TRACE("plist/validate_stringseq: buffer too small (contents)\n"); - result = DDS_RETCODE_BAD_PARAMETER; - goto fail; - } - strseq->strs = strs; - } - return 0; - fail: - ddsrt_free (strs); - return result; -} - -static void free_stringseq (ddsi_stringseq_t *strseq) -{ - uint32_t i; - for (i = 0; i < strseq->n; i++) - if (strseq->strs[i]) - ddsrt_free (strseq->strs[i]); - ddsrt_free (strseq->strs); -} - -static dds_return_t unalias_stringseq (ddsi_stringseq_t *strseq, int bswap) -{ - uint32_t i; - char **strs; - if (strseq->n != 0) - { - strs = ddsrt_malloc (strseq->n * sizeof (*strs)); - for (i = 0; i < strseq->n; i++) - { - strs[i] = strseq->strs[i]; - unalias_string (&strs[i], bswap); - } - ddsrt_free (strseq->strs); - strseq->strs = strs; - } - return 0; -} - -static void duplicate_stringseq (ddsi_stringseq_t *dest, const ddsi_stringseq_t *src) -{ - uint32_t i; - dest->n = src->n; -assert (dest->strs == NULL); - if (dest->n == 0) - { - dest->strs = NULL; - return; - } - dest->strs = ddsrt_malloc (dest->n * sizeof (*dest->strs)); - for (i = 0; i < dest->n; i++) - { - dest->strs[i] = src->strs[i]; - unalias_string (&dest->strs[i], -1); - } -} - -static void free_locators (nn_locators_t *locs) -{ - while (locs->first) - { - struct nn_locators_one *l = locs->first; - locs->first = l->next; - ddsrt_free (l); - } -} - -static void unalias_locators (nn_locators_t *locs, UNUSED_ARG (int bswap)) -{ - nn_locators_t newlocs; - struct nn_locators_one *lold; - /* Copy it, without reversing the order. On failure, free the copy, - on success overwrite *locs. */ - newlocs.n = locs->n; - newlocs.first = NULL; - newlocs.last = NULL; - for (lold = locs->first; lold != NULL; lold = lold->next) - { - struct nn_locators_one *n; - n = ddsrt_malloc (sizeof (*n)); - n->next = NULL; - n->loc = lold->loc; - if (newlocs.first == NULL) - newlocs.first = n; - else - newlocs.last->next = n; - newlocs.last = n; - } - *locs = newlocs; -} - -static void unalias_eotinfo (nn_prismtech_eotinfo_t *txnid, UNUSED_ARG (int bswap)) -{ - if (txnid->n > 0) - { - nn_prismtech_eotgroup_tid_t *vs; - vs = ddsrt_malloc (txnid->n * sizeof (*vs)); - memcpy (vs, txnid->tids, txnid->n * sizeof (*vs)); - txnid->tids = vs; - } -} - -void nn_plist_fini (nn_plist_t *ps) -{ - struct t { uint64_t fl; size_t off; }; - static const struct t simple[] = { - { PP_ENTITY_NAME, offsetof (nn_plist_t, entity_name) }, - { PP_PRISMTECH_NODE_NAME, offsetof (nn_plist_t, node_name) }, - { PP_PRISMTECH_EXEC_NAME, offsetof (nn_plist_t, exec_name) }, - { PP_PRISMTECH_PARTICIPANT_VERSION_INFO, offsetof (nn_plist_t, prismtech_participant_version_info.internals) }, - { PP_PRISMTECH_TYPE_DESCRIPTION, offsetof (nn_plist_t, type_description) }, - { PP_PRISMTECH_EOTINFO, offsetof (nn_plist_t, eotinfo.tids) } - }; - static const struct t locs[] = { - { PP_UNICAST_LOCATOR, offsetof (nn_plist_t, unicast_locators) }, - { PP_MULTICAST_LOCATOR, offsetof (nn_plist_t, multicast_locators) }, - { PP_DEFAULT_UNICAST_LOCATOR, offsetof (nn_plist_t, default_unicast_locators) }, - { PP_DEFAULT_MULTICAST_LOCATOR, offsetof (nn_plist_t, default_multicast_locators) }, - { PP_METATRAFFIC_UNICAST_LOCATOR, offsetof (nn_plist_t, metatraffic_unicast_locators) }, - { PP_METATRAFFIC_MULTICAST_LOCATOR, offsetof (nn_plist_t, metatraffic_multicast_locators) } - }; - int i; - nn_xqos_fini (&ps->qos); - - /* The compiler doesn't understand how offsetof is used in the arrays. */ - DDSRT_WARNING_MSVC_OFF(6001); - for (i = 0; i < (int) (sizeof (simple) / sizeof (*simple)); i++) - { - if ((ps->present & simple[i].fl) && !(ps->aliased & simple[i].fl)) - { - void **pp = (void **) ((char *) ps + simple[i].off); - ddsrt_free (*pp); - } - } - for (i = 0; i < (int) (sizeof (locs) / sizeof (*locs)); i++) - { - if ((ps->present & locs[i].fl) && !(ps->aliased & locs[i].fl)) - free_locators ((nn_locators_t *) ((char *) ps + locs[i].off)); - } - DDSRT_WARNING_MSVC_ON(6001); - - ps->present = 0; -} - -#if 0 /* not currently needed */ -void nn_plist_unalias (nn_plist_t *ps) -{ -#define P(name_, func_, field_) do { \ - if ((ps->present & PP_##name_) && (ps->aliased & PP_##name_)) { \ - unalias_##func_ (&ps->field_, -1); \ - ps->aliased &= ~PP_##name_; \ - } \ - } while (0) - nn_xqos_unalias (&ps->qos); - P (ENTITY_NAME, string, entity_name); - P (UNICAST_LOCATOR, locators, unicast_locators); - P (MULTICAST_LOCATOR, locators, multicast_locators); - P (DEFAULT_UNICAST_LOCATOR, locators, default_unicast_locators); - P (DEFAULT_MULTICAST_LOCATOR, locators, default_multicast_locators); - P (METATRAFFIC_UNICAST_LOCATOR, locators, metatraffic_unicast_locators); - P (METATRAFFIC_MULTICAST_LOCATOR, locators, metatraffic_multicast_locators); - P (PRISMTECH_NODE_NAME, string, node_name); - P (PRISMTECH_EXEC_NAME, string, exec_name); - P (PRISMTECH_TYPE_DESCRIPTION, string, type_description); - P (PRISMTECH_EOTINFO, eotinfo, eotinfo); -#undef P - if ((ps->present & PP_PRISMTECH_PARTICIPANT_VERSION_INFO) && - (ps->aliased & PP_PRISMTECH_PARTICIPANT_VERSION_INFO)) - { - unalias_string (&ps->prismtech_participant_version_info.internals, -1); - ps->aliased &= ~PP_PRISMTECH_PARTICIPANT_VERSION_INFO; - } - - assert (ps->aliased == 0); -} #endif -static dds_return_t do_octetseq (ddsi_octetseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) +/* 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[] = { + QP (USER_DATA, user_data, XO), + QP (TOPIC_NAME, topic_name, XS), + QP (TYPE_NAME, type_name, XS), + QP (TOPIC_DATA, topic_data, XO), + QP (GROUP_DATA, group_data, XO), + QP (DURABILITY, durability, XE3), + /* CoreDX's use of all-zero durability service QoS means we can't use l; interdependencies between QoS + values means we must validate the combination anyway */ + QPV (DURABILITY_SERVICE, durability_service, XD, XE1, Xix4), + QP (DEADLINE, deadline, XD), + QP (LATENCY_BUDGET, latency_budget, XD), + QP (LIVELINESS, liveliness, XE2, XD), + /* 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 }, + 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" */ + QPV (HISTORY, history, XE1, Xi), + QPV (RESOURCE_LIMITS, resource_limits, Xix3), + QP (OWNERSHIP, ownership, XE1), + QP (OWNERSHIP_STRENGTH, ownership_strength, Xi), + QP (PRESENTATION, presentation, XE2, Xbx2), + QP (PARTITION, partition, XZ), + QP (TIME_BASED_FILTER, time_based_filter, XD), + QP (TRANSPORT_PRIORITY, transport_priority, Xi), + PP (PROTOCOL_VERSION, protocol_version, Xox2), + PP (VENDORID, vendorid, Xox2), + PP (EXPECTS_INLINE_QOS, expects_inline_qos, Xb), + PP (PARTICIPANT_MANUAL_LIVELINESS_COUNT, participant_manual_liveliness_count, Xi), + PP (PARTICIPANT_BUILTIN_ENDPOINTS, participant_builtin_endpoints, Xu), + PP (PARTICIPANT_LEASE_DURATION, participant_lease_duration, XD), + PPV (PARTICIPANT_GUID, participant_guid, XG), + PPV (GROUP_GUID, group_guid, XG), + PP (BUILTIN_ENDPOINT_SET, builtin_endpoint_set, Xu), + PP (ENTITY_NAME, entity_name, XS), + PP (KEYHASH, keyhash, XK), + PPV (ENDPOINT_GUID, endpoint_guid, XG), +#ifdef DDSI_INCLUDE_SSM + PPV (READER_FAVOURS_SSM, reader_favours_ssm, Xu), +#endif + { 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 }, + /* 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + /* 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 */ + { PID_SENTINEL, 0, 0, NULL, 0, 0, { .desc = { XSTOP } }, 0 } +}; + +/* Understood parameters for Eclipse Foundation (Cyclone DDS) vendor code */ +static const struct piddesc piddesc_eclipse[] = { + QP (PRISMTECH_ENTITY_FACTORY, entity_factory, Xb), + QP (PRISMTECH_READER_LIFESPAN, reader_lifespan, Xb, XD), + QP (PRISMTECH_WRITER_DATA_LIFECYCLE, writer_data_lifecycle, Xb), + QP (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle, XDx2), + QP (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys, XbCOND, XZ), + { 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 } +}; + +/* Understood parameters for PrismTech vendor code */ +static const struct piddesc piddesc_prismtech[] = { + QP (PRISMTECH_ENTITY_FACTORY, entity_factory, Xb), + QP (PRISMTECH_READER_LIFESPAN, reader_lifespan, Xb, XD), + QP (PRISMTECH_WRITER_DATA_LIFECYCLE, writer_data_lifecycle, Xb), + QP (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle, XDx2), + QP (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys, XbCOND, XZ), + 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 } +}; + +#undef PPM +#undef PP +#undef QP +#undef PPV +#undef QPV +#undef ENTRY +#undef membersize + +/* Parameters to be included in messages we generate */ +static const struct piddesc *piddesc_tables_output[] = { + piddesc_omg, + piddesc_eclipse +}; + +/* All known parameters -- this can potentially include + parameters from other vendors that we never generate + but that we do recognize on input and store for some + purpose other than the internal workings of Cyclone, + and that require fini/unalias processing */ +static const struct piddesc *piddesc_tables_all[] = { + piddesc_omg, + piddesc_eclipse +}; + +struct piddesc_index { + size_t index_max; + const struct piddesc **index; + /* include source table for generating the index -- + it's easier to generate the index at startup then + to maintain in the source */ + const struct piddesc *table; +}; + +/* Vendor code to vendor-specific table mapping, with index + vendor codes are currently of the form 1.x with x a small + number > 0 (and that's not likely to change) so we have + a table for major = 1 and use index 0 for the standard + ones. + + Sizes are such that the highest PID (without flags) in + table are the last entry in the array. Checked by + nn_plist_init_tables. */ +static const struct piddesc *piddesc_omg_index[115]; +static const struct piddesc *piddesc_eclipse_index[19]; +static const struct piddesc *piddesc_prismtech_index[19]; + +#define INDEX_ANY(vendorid_, tab_) [vendorid_] = { \ + .index_max = sizeof (piddesc_##tab_##_index) / sizeof (piddesc_##tab_##_index[0]) - 1, \ + .index = (const struct piddesc **) piddesc_##tab_##_index, \ + .table = piddesc_##tab_ } +#define INDEX(VENDOR_, tab_) INDEX_ANY (NN_VENDORID_MINOR_##VENDOR_, tab_) + +static const struct piddesc_index piddesc_vendor_index[] = { + INDEX_ANY (0, omg), + INDEX (ECLIPSE, eclipse), + INDEX (PRISMTECH_OSPL, prismtech), + INDEX (PRISMTECH_JAVA, prismtech), + INDEX (PRISMTECH_LITE, prismtech), + INDEX (PRISMTECH_GATEWAY, prismtech), + INDEX (PRISMTECH_CLOUD, prismtech) +}; + +#undef INDEX +#undef INDEX_ANY + +/* List of entries that require unalias, fini processing; + initialized by nn_plist_init_tables; will assert when + table too small or too large */ +static const struct piddesc *piddesc_unalias[18]; +static const struct piddesc *piddesc_fini[18]; +static ddsrt_once_t table_init_control = DDSRT_ONCE_INIT; + +static nn_parameterid_t pid_without_flags (nn_parameterid_t pid) { - dds_return_t res; - size_t len; - if (!(wanted & fl)) - return NN_STRICT_P ? validate_octetseq (dd, &len) : 0; - if ((res = alias_octetseq (dst, dd)) >= 0) + return (nn_parameterid_t) (pid & ~(PID_VENDORSPECIFIC_FLAG | PID_UNRECOGNIZED_INCOMPATIBLE_FLAG)); +} + +static int piddesc_cmp_qos_addr (const void *va, const void *vb) +{ + struct piddesc const * const *a = (struct piddesc const * const *) va; + struct piddesc const * const *b = (struct piddesc const * const *) vb; + /* QoS go first, then address */ + if (((*a)->flags & PDF_QOS) != ((*b)->flags & PDF_QOS)) + return ((*a)->flags & PDF_QOS) ? -1 : 1; + else + return ((uintptr_t) *a == (uintptr_t) *b) ? 0 : ((uintptr_t) *a < (uintptr_t) *b) ? -1 : 1; +} + +static void nn_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++) { - *present |= fl; - *aliased |= fl; + const struct piddesc *table = piddesc_vendor_index[i].table; + if (table == NULL) + continue; + struct piddesc const **index = piddesc_vendor_index[i].index; +#ifndef NDEBUG + nn_parameterid_t maxpid = 0; + bool only_qos_seen = true; +#endif + for (size_t j = 0; table[j].pid != PID_SENTINEL; j++) + { + nn_parameterid_t pid = pid_without_flags (table[j].pid); +#ifndef NDEBUG + /* Table must first list QoS, then other parameters */ + assert (only_qos_seen || !(table[j].flags & PDF_QOS)); + if (!(table[j].flags & PDF_QOS)) + only_qos_seen = false; + /* Track max PID so we can verify the table is no larger + than necessary */ + if (pid > maxpid) + maxpid = pid; +#endif + /* PAD is used for entries that are never visible on the wire + and the decoder assumes the PAD entries will be skipped + because they don't map to an entry */ + if (pid == PID_PAD) + continue; + assert (pid <= piddesc_vendor_index[i].index_max); + assert (index[pid] == NULL || index[pid] == &table[j]); + index[pid] = &table[j]; + } + assert (maxpid == piddesc_vendor_index[i].index_max); } - return res; -} -static dds_return_t do_blob (ddsi_octetseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) -{ - dds_return_t res; - if (!(wanted & fl)) - return 0; - if ((res = alias_blob (dst, dd)) >= 0) + /* PIDs requiring unalias; there is overlap between the tables + (because of different vendor codes mapping to the same entry + in qos/plist). Use the "present" flags to filter out + duplicates. */ + uint64_t pf = 0, qf = 0; + size_t unalias_index = 0; + size_t fini_index = 0; + for (size_t i = 0; i < sizeof (piddesc_vendor_index) / sizeof (piddesc_vendor_index[0]); i++) { - *present |= fl; - *aliased |= fl; + const struct piddesc *table = piddesc_vendor_index[i].table; + if (table == NULL) + continue; + for (size_t j = 0; table[j].pid != PID_SENTINEL; j++) + { + uint64_t * const f = (table[j].flags & PDF_QOS) ? &qf : &pf; + if (*f & table[j].present_flag) + continue; + *f |= table[j].present_flag; + if (((table[j].flags & PDF_FUNCTION) && table[j].op.f.unalias) || + (!(table[j].flags & PDF_FUNCTION) && unalias_generic_required (table[j].op.desc))) + { + assert (unalias_index < sizeof (piddesc_unalias) / sizeof (piddesc_unalias[0])); + piddesc_unalias[unalias_index++] = &table[j]; + } + if (((table[j].flags & PDF_FUNCTION) && table[j].op.f.fini) || + (!(table[j].flags & PDF_FUNCTION) && fini_generic_required (table[j].op.desc))) + { + assert (fini_index < sizeof (piddesc_fini) / sizeof (piddesc_fini[0])); + piddesc_fini[fini_index++] = &table[j]; + } + } } - return res; -} - -static dds_return_t do_string (char **dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) -{ - dds_return_t res; - size_t len; - if (!(wanted & fl)) - return NN_STRICT_P ? validate_string (dd, &len) : 0; - if ((res = alias_string ((const unsigned char **) dst, dd, &len)) >= 0) + assert (unalias_index == sizeof (piddesc_unalias) / sizeof (piddesc_unalias[0]) && + fini_index == sizeof (piddesc_fini) / sizeof (piddesc_fini[0])); + qsort ((void *) piddesc_unalias, unalias_index, sizeof (piddesc_unalias[0]), piddesc_cmp_qos_addr); + qsort ((void *) piddesc_fini, fini_index, sizeof (piddesc_fini[0]), piddesc_cmp_qos_addr); +#ifndef NDEBUG { - *present |= fl; - *aliased |= fl; + size_t i; + for (i = 0; i < unalias_index; i++) + if (!(piddesc_unalias[i]->flags & PDF_QOS)) + break; + for (; i < unalias_index; i++) + assert (!(piddesc_unalias[i]->flags & PDF_QOS)); + for (i = 0; i < fini_index; i++) + if (!(piddesc_fini[i]->flags & PDF_QOS)) + break; + for (; i < fini_index; i++) + assert (!(piddesc_fini[i]->flags & PDF_QOS)); } - return res; +#endif } -static dds_return_t do_stringseq (ddsi_stringseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd) +void nn_plist_init_tables (void) { - dds_return_t res; - if (!(wanted & fl)) - return NN_STRICT_P ? validate_stringseq (dd) : 0; - if ((res = alias_stringseq (dst, dd)) >= 0) + ddsrt_once (&table_init_control, nn_plist_init_tables_real); +} + +static void plist_or_xqos_fini (void * __restrict dst, size_t shift) +{ + /* shift == 0: plist, shift > 0: just qos */ + struct flagset pfs, qfs; + /* 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 (); + if (shift > 0) { - *present |= fl; - *aliased |= fl; + dds_qos_t *qos = dst; + pfs = (struct flagset) { 0 }; + qfs = (struct flagset) { .present = &qos->present, .aliased = &qos->aliased }; } - return res; -} - -static void bswap_time (ddsi_time_t *t) -{ - t->seconds = bswap4 (t->seconds); - t->fraction = bswap4u (t->fraction); -} - -static dds_return_t validate_time (const ddsi_time_t *t) -{ - /* Accepted are zero, positive, infinite or invalid as defined in - the DDS 2.1 spec, table 9.4. */ - if (t->seconds >= 0) - return 0; - else if (t->seconds == -1 && t->fraction == UINT32_MAX) - return 0; else { - DDS_TRACE("plist/validate_time: invalid timestamp (%08x.%08x)\n", t->seconds, t->fraction); - return DDS_RETCODE_BAD_PARAMETER; + nn_plist_t *plist = dst; + pfs = (struct flagset) { .present = &plist->present, .aliased = &plist->aliased }; + qfs = (struct flagset) { .present = &plist->qos.present, .aliased = &plist->qos.aliased }; + } + for (size_t i = 0; i < sizeof (piddesc_fini) / sizeof (piddesc_fini[0]); i++) + { + struct piddesc const * const entry = piddesc_fini[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)); + size_t dstoff = entry->plist_offset - shift; + struct flagset * const fs = (entry->flags & PDF_QOS) ? &qfs : &pfs; + if ((*fs->present & entry->present_flag)) + { + if (!(entry->flags & PDF_FUNCTION)) + fini_generic (dst, &dstoff, fs, entry->present_flag, entry->op.desc); + else if (entry->op.f.fini) + entry->op.f.fini (dst, &dstoff, fs, entry->present_flag); + } + } + if (pfs.present) { *pfs.present = *pfs.aliased = 0; } + *qfs.present = *qfs.aliased = 0; +} + +static void plist_or_xqos_unalias (void * __restrict dst, size_t shift) +{ + /* shift == 0: plist, shift > 0: just qos */ + struct flagset pfs, qfs; + /* 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 (); + if (shift > 0) + { + dds_qos_t *qos = dst; + pfs = (struct flagset) { 0 }; + qfs = (struct flagset) { .present = &qos->present, .aliased = &qos->aliased }; + } + else + { + nn_plist_t *plist = dst; + pfs = (struct flagset) { .present = &plist->present, .aliased = &plist->aliased }; + qfs = (struct flagset) { .present = &plist->qos.present, .aliased = &plist->qos.aliased }; + } + for (size_t i = 0; i < sizeof (piddesc_unalias) / sizeof (piddesc_unalias[0]); i++) + { + struct piddesc const * const entry = piddesc_unalias[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)); + size_t dstoff = entry->plist_offset - shift; + struct flagset * const fs = (entry->flags & PDF_QOS) ? &qfs : &pfs; + if ((*fs->present & entry->present_flag) && (*fs->aliased & entry->present_flag)) + { + if (!(entry->flags & PDF_FUNCTION)) + unalias_generic (dst, &dstoff, entry->op.desc); + else if (entry->op.f.unalias) + entry->op.f.unalias (dst, &dstoff); + *fs->aliased &= ~entry->present_flag; + } + } + assert (pfs.aliased == NULL || *pfs.aliased == 0); + assert (*qfs.aliased == 0); +} + +static void plist_or_xqos_mergein_missing (void * __restrict dst, const void * __restrict src, size_t shift, uint64_t pmask, uint64_t qmask) +{ + /* shift == 0: plist, shift > 0: just qos */ + 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; +#endif + if (shift > 0) + { + dds_qos_t *qos_dst = dst; + const dds_qos_t *qos_src = src; + pfs_dst = (struct flagset) { 0 }; + qfs_dst = (struct flagset) { .present = &qos_dst->present, .aliased = &qos_dst->aliased }; + pfs_src = (struct flagset) { 0 }; + qfs_src = (struct flagset) { .present = (uint64_t *) &qos_src->present, .aliased = (uint64_t *) &qos_src->aliased }; + } + else + { + nn_plist_t *plist_dst = dst; + const nn_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 }; + qfs_src = (struct flagset) { .present = (uint64_t *) &plist_src->qos.present, .aliased = (uint64_t *) &plist_src->qos.aliased }; + } + /* aliased may never have any bits set that are clear in present */ + assert (pfs_dst.present == NULL || (aliased_dst_inp & ~ *pfs_dst.present) == 0); + assert ((aliased_dst_inq & ~ *qfs_dst.present) == 0); + 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)); + size_t dstoff = entry->plist_offset - shift; + struct flagset * const fs_dst = (entry->flags & PDF_QOS) ? &qfs_dst : &pfs_dst; + struct flagset * const fs_src = (entry->flags & PDF_QOS) ? &qfs_src : &pfs_src; + uint64_t const mask = (entry->flags & PDF_QOS) ? qmask : pmask; + /* skip if already present in dst or absent in src */ + if (!(*fs_dst->present & entry->present_flag) && (*fs_src->present & mask & entry->present_flag)) + { + /* bitwise copy, mark as aliased & unalias; have to unalias fields one-by-one rather than + do this for all fields and call "unalias" on the entire object because fields that are + already present may be aliased, and it would be somewhat impolite to change that. + + Note: dst & src have the same type, so offset in src is the same; + Note: unalias may have to look at */ + memcpy ((char *) dst + dstoff, (const char *) src + dstoff, entry->size); + *fs_dst->present |= entry->present_flag; + if (!(entry->flags & PDF_FUNCTION)) + unalias_generic (dst, &dstoff, entry->op.desc); + else if (entry->op.f.unalias) + entry->op.f.unalias (dst, &dstoff); + } + } + } + /* all entries in src should be present in dst (but there may be more) */ + assert (pfs_dst.present == NULL || (*pfs_src.present & pmask & ~ *pfs_dst.present) == 0); + assert ((*qfs_src.present & qmask & ~ *qfs_dst.present) == 0); + /* the only aliased entries in dst may be ones that were aliased on input */ + assert (pfs_dst.aliased == NULL || (*pfs_dst.aliased & ~ aliased_dst_inp) == 0); + assert ((*qfs_dst.aliased & ~ aliased_dst_inq) == 0); +} + +static void plist_or_xqos_addtomsg (struct nn_xmsg *xmsg, const void * __restrict src, size_t shift, uint64_t pwanted, uint64_t qwanted) +{ + /* shift == 0: plist, shift > 0: just qos */ + uint64_t pw, qw; + if (shift > 0) + { + 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++) + { + struct piddesc const * const entry = &table[i]; + if (entry->pid == PID_PAD) + continue; + if (((entry->flags & PDF_QOS) ? qw : pw) & entry->present_flag) + { + assert (entry->plist_offset >= shift); + assert (shift == 0 || entry->plist_offset - shift < sizeof (dds_qos_t)); + size_t srcoff = entry->plist_offset - shift; + if (!(entry->flags & PDF_FUNCTION)) + ser_generic (xmsg, entry->pid, src, srcoff, entry->op.desc); + else + entry->op.f.ser (xmsg, entry->pid, src, srcoff); + } + } } } -static void bswap_external_duration (ddsi_duration_t *d) +void nn_plist_fini (nn_plist_t *plist) { - bswap_time (d); + plist_or_xqos_fini (plist, 0); +} + +void nn_plist_unalias (nn_plist_t *plist) +{ + plist_or_xqos_unalias (plist, 0); +} + +dds_return_t nn_xqos_valid (const dds_qos_t *xqos) +{ + dds_return_t ret; + if (piddesc_unalias[0] == NULL) + nn_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]; + 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 (xqos->present & entry->present_flag) + { + const size_t srcoff = entry->plist_offset - offsetof (nn_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_LOG (DDS_LC_PLIST, "nn_xqos_valid: %s invalid\n", entry->name); + return ret; + } + } + } + } + if ((ret = final_validation_qos (xqos, (nn_protocol_version_t) { RTPS_MAJOR, RTPS_MINOR }, NN_VENDORID_ECLIPSE, NULL)) < 0) + { + DDS_LOG (DDS_LC_PLIST, "nn_xqos_valid: final validation failed\n"); + } + return ret; +} + +uint64_t nn_xqos_delta (const dds_qos_t *x, const dds_qos_t *y, uint64_t mask) +{ + 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; } static dds_return_t validate_external_duration (const ddsi_duration_t *d) { - return validate_time (d); -} - -dds_return_t validate_duration (const dds_duration_t d) -{ - return (d >= 0 && d <= DDS_INFINITY) ? DDS_RETCODE_OK : DDS_RETCODE_BAD_PARAMETER; -} - -static dds_return_t do_duration (dds_duration_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) -{ - ddsi_duration_t extq; - dds_return_t res; - if (dd->bufsz < sizeof (extq)) - { - DDS_TRACE("plist/do_duration: buffer too small\n"); + /* Accepted are zero, positive, infinite or invalid as defined in + the DDS 2.1 spec, table 9.4. */ + if (d->seconds >= 0) + return 0; + else if (d->seconds == -1 && d->fraction == UINT32_MAX) + return 0; + else return DDS_RETCODE_BAD_PARAMETER; - } - memcpy (&extq, dd->buf, sizeof (extq)); - if (dd->bswap) - bswap_external_duration (&extq); - if ((res = validate_external_duration (&extq)) < 0) - return res; - *q = nn_from_ddsi_duration (extq); - *present |= fl; - return 0; -} - -static void bswap_durability_qospolicy (dds_durability_qospolicy_t *q) -{ - q->kind = bswap4u (q->kind); -} - -dds_return_t validate_durability_qospolicy (const dds_durability_qospolicy_t *q) -{ - switch (q->kind) - { - case DDS_DURABILITY_VOLATILE: - case DDS_DURABILITY_TRANSIENT_LOCAL: - case DDS_DURABILITY_TRANSIENT: - case DDS_DURABILITY_PERSISTENT: - break; - default: - DDS_TRACE("plist/validate_durability_qospolicy: invalid kind (%d)\n", (int) q->kind); - return DDS_RETCODE_BAD_PARAMETER; - } - return 0; -} - -static void bswap_history_qospolicy (dds_history_qospolicy_t *q) -{ - q->kind = bswap4u (q->kind); - q->depth = bswap4 (q->depth); } static int history_qospolicy_allzero (const dds_history_qospolicy_t *q) @@ -606,7 +1534,7 @@ static int history_qospolicy_allzero (const dds_history_qospolicy_t *q) return q->kind == DDS_HISTORY_KEEP_LAST && q->depth == 0; } -dds_return_t validate_history_qospolicy (const dds_history_qospolicy_t *q) +static dds_return_t validate_history_qospolicy (const dds_history_qospolicy_t *q) { /* Validity of history setting and of resource limits are dependent, but we don't have access to the resource limits here ... the @@ -621,110 +1549,63 @@ dds_return_t validate_history_qospolicy (const dds_history_qospolicy_t *q) case DDS_HISTORY_KEEP_ALL: break; default: - DDS_TRACE("plist/validate_history_qospolicy: invalid kind (%d)\n", (int) q->kind); return DDS_RETCODE_BAD_PARAMETER; } /* Accept all values for depth if kind = ALL */ - if (q->kind == DDS_HISTORY_KEEP_LAST) - { - if (q->depth < 1) - { - DDS_TRACE("plist/validate_history_qospolicy: invalid depth (%d)\n", (int) q->depth); - return DDS_RETCODE_BAD_PARAMETER; - } - } + if (q->kind == DDS_HISTORY_KEEP_LAST && q->depth < 1) + return DDS_RETCODE_BAD_PARAMETER; return 0; } -static void bswap_resource_limits_qospolicy (dds_resource_limits_qospolicy_t *q) -{ - q->max_samples = bswap4 (q->max_samples); - q->max_instances = bswap4 (q->max_instances); - q->max_samples_per_instance = bswap4 (q->max_samples_per_instance); -} - static int resource_limits_qospolicy_allzero (const dds_resource_limits_qospolicy_t *q) { return q->max_samples == 0 && q->max_instances == 0 && q->max_samples_per_instance == 0; } -dds_return_t validate_resource_limits_qospolicy (const dds_resource_limits_qospolicy_t *q) +static dds_return_t validate_resource_limits_qospolicy (const dds_resource_limits_qospolicy_t *q) { - const int unlimited = DDS_LENGTH_UNLIMITED; /* Note: dependent on history setting as well (see validate_history_qospolicy). Verifying only the internal consistency of the resource limits. */ - if (q->max_samples < 1 && q->max_samples != unlimited) - { - DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples invalid (%d)\n", (int) q->max_samples); + if (q->max_samples < 1 && q->max_samples != DDS_LENGTH_UNLIMITED) return DDS_RETCODE_BAD_PARAMETER; - } - if (q->max_instances < 1 && q->max_instances != unlimited) - { - DDS_TRACE("plist/validate_resource_limits_qospolicy: max_instances invalid (%d)\n", (int) q->max_instances); + if (q->max_instances < 1 && q->max_instances != DDS_LENGTH_UNLIMITED) return DDS_RETCODE_BAD_PARAMETER; - } - if (q->max_samples_per_instance < 1 && q->max_samples_per_instance != unlimited) - { - DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples_per_instance invalid (%d)\n", (int) q->max_samples_per_instance); + if (q->max_samples_per_instance < 1 && q->max_samples_per_instance != DDS_LENGTH_UNLIMITED) return DDS_RETCODE_BAD_PARAMETER; - } - if (q->max_samples != unlimited && q->max_samples_per_instance != unlimited) + if (q->max_samples != DDS_LENGTH_UNLIMITED && q->max_samples_per_instance != DDS_LENGTH_UNLIMITED) { /* Interpreting 7.1.3.19 as if "unlimited" is meant to mean "don't care" and any conditions related to it must be ignored. */ if (q->max_samples < q->max_samples_per_instance) - { - DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples (%d) and max_samples_per_instance (%d) incompatible\n", (int) q->max_samples, (int) q->max_samples_per_instance); - return DDS_RETCODE_BAD_PARAMETER; - } + return DDS_RETCODE_INCONSISTENT_POLICY; } return 0; } -dds_return_t validate_history_and_resource_limits (const dds_history_qospolicy_t *qh, const dds_resource_limits_qospolicy_t *qr) +static dds_return_t validate_history_and_resource_limits (const dds_history_qospolicy_t *qh, const dds_resource_limits_qospolicy_t *qr) { - const int unlimited = DDS_LENGTH_UNLIMITED; dds_return_t res; if ((res = validate_history_qospolicy (qh)) < 0) - { - DDS_TRACE("plist/validate_history_and_resource_limits: history policy invalid\n"); return res; - } if ((res = validate_resource_limits_qospolicy (qr)) < 0) - { - DDS_TRACE("plist/validate_history_and_resource_limits: resource_limits policy invalid\n"); return res; - } switch (qh->kind) { case DDS_HISTORY_KEEP_ALL: #if 0 /* See comment in validate_resource_limits, ref'ing 7.1.3.19 */ - if (qr->max_samples_per_instance != unlimited) - { - DDS_TRACE("plist/validate_history_and_resource_limits: max_samples_per_instance (%d) incompatible with KEEP_ALL policy\n", (int) qr->max_samples_per_instance); + if (qr->max_samples_per_instance != DDS_LENGTH_UNLIMITED) return DDS_RETCODE_BAD_PARAMETER; - } #endif break; case DDS_HISTORY_KEEP_LAST: - if (qr->max_samples_per_instance != unlimited && qh->depth > qr->max_samples_per_instance) - { - DDS_TRACE("plist/validate_history_and_resource_limits: depth (%d) and max_samples_per_instance (%d) incompatible with KEEP_LAST policy\n", (int) qh->depth, (int) qr->max_samples_per_instance); - return DDS_RETCODE_BAD_PARAMETER; - } + if (qr->max_samples_per_instance != DDS_LENGTH_UNLIMITED && qh->depth > qr->max_samples_per_instance) + return DDS_RETCODE_INCONSISTENT_POLICY; break; } return 0; } -static void bswap_external_durability_service_qospolicy (dds_external_durability_service_qospolicy_t *q) -{ - bswap_external_duration (&q->service_cleanup_delay); - bswap_history_qospolicy (&q->history); - bswap_resource_limits_qospolicy (&q->resource_limits); -} - static int durability_service_qospolicy_allzero (const dds_durability_service_qospolicy_t *q) { return (history_qospolicy_allzero (&q->history) && @@ -732,184 +1613,15 @@ static int durability_service_qospolicy_allzero (const dds_durability_service_qo q->service_cleanup_delay == 0); } -static int external_durability_service_qospolicy_allzero (const dds_external_durability_service_qospolicy_t *q) -{ - return (history_qospolicy_allzero (&q->history) && - resource_limits_qospolicy_allzero (&q->resource_limits) && - q->service_cleanup_delay.seconds == 0 && q->service_cleanup_delay.fraction == 0); -} - -static dds_return_t validate_external_durability_service_qospolicy_acceptzero (const dds_external_durability_service_qospolicy_t *q, bool acceptzero) +static dds_return_t validate_durability_service_qospolicy_acceptzero (const dds_durability_service_qospolicy_t *q, bool acceptzero) { dds_return_t res; - if (acceptzero && external_durability_service_qospolicy_allzero (q)) + if (acceptzero && durability_service_qospolicy_allzero (q)) return 0; - if ((res = validate_external_duration (&q->service_cleanup_delay)) < 0) - { - DDS_TRACE("plist/validate_durability_service_qospolicy: duration invalid\n"); - return res; - } + if (q->service_cleanup_delay < 0) + return DDS_RETCODE_BAD_PARAMETER; if ((res = validate_history_and_resource_limits (&q->history, &q->resource_limits)) < 0) - { - DDS_TRACE("plist/validate_durability_service_qospolicy: invalid history and/or resource limits\n"); return res; - } - return 0; -} - -dds_return_t validate_durability_service_qospolicy (const dds_durability_service_qospolicy_t *q) -{ - dds_external_durability_service_qospolicy_t qext; - qext.history = q->history; - qext.resource_limits = q->resource_limits; - qext.service_cleanup_delay = nn_to_ddsi_duration (q->service_cleanup_delay); - return validate_external_durability_service_qospolicy_acceptzero (&qext, false); -} - -static void bswap_external_liveliness_qospolicy (dds_external_liveliness_qospolicy_t *q) -{ - q->kind = bswap4u (q->kind); - bswap_external_duration (&q->lease_duration); -} - -static dds_return_t validate_external_liveliness_qospolicy (const dds_external_liveliness_qospolicy_t *q) -{ - dds_return_t res; - switch (q->kind) - { - case DDS_LIVELINESS_AUTOMATIC: - case DDS_LIVELINESS_MANUAL_BY_PARTICIPANT: - case DDS_LIVELINESS_MANUAL_BY_TOPIC: - if ((res = validate_external_duration (&q->lease_duration)) < 0) - DDS_TRACE("plist/validate_liveliness_qospolicy: invalid lease duration\n"); - return res; - default: - DDS_TRACE("plist/validate_liveliness_qospolicy: invalid kind (%d)\n", (int) q->kind); - return DDS_RETCODE_BAD_PARAMETER; - } -} - -dds_return_t validate_liveliness_qospolicy (const dds_liveliness_qospolicy_t *q) -{ - dds_external_liveliness_qospolicy_t qext; - qext.kind = q->kind; - qext.lease_duration = nn_to_ddsi_duration (q->lease_duration); - return validate_external_liveliness_qospolicy (&qext); -} - -static void bswap_external_reliability_qospolicy (dds_external_reliability_qospolicy_t *qext) -{ - qext->kind = bswap4u (qext->kind); - bswap_external_duration (&qext->max_blocking_time); -} - -static dds_return_t validate_xform_reliability_qospolicy (dds_reliability_qospolicy_t *qdst, const dds_external_reliability_qospolicy_t *qext) -{ - dds_return_t res; - qdst->max_blocking_time = nn_from_ddsi_duration (qext->max_blocking_time); - switch (qext->kind) - { - case DDS_EXTERNAL_RELIABILITY_BEST_EFFORT: - qdst->kind = DDS_RELIABILITY_BEST_EFFORT; - return 0; - case DDS_EXTERNAL_RELIABILITY_RELIABLE: - qdst->kind = DDS_RELIABILITY_RELIABLE; - if ((res = validate_external_duration (&qext->max_blocking_time)) < 0) - DDS_TRACE("plist/validate_xform_reliability_qospolicy[!pedantic]: max_blocking time invalid\n"); - return res; - default: - DDS_TRACE("plist/validate_xform_reliability_qospolicy[!pedantic]: invalid kind (%d)\n", (int) qext->kind); - return DDS_RETCODE_BAD_PARAMETER; - } -} - -static void bswap_destination_order_qospolicy (dds_destination_order_qospolicy_t *q) -{ - q->kind = bswap4u (q->kind); -} - -dds_return_t validate_destination_order_qospolicy (const dds_destination_order_qospolicy_t *q) -{ - switch (q->kind) - { - case DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP: - case DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP: - return 0; - default: - DDS_TRACE("plist/validate_destination_order_qospolicy: invalid kind (%d)\n", (int) q->kind); - return DDS_RETCODE_BAD_PARAMETER; - } -} - -static void bswap_ownership_qospolicy (dds_ownership_qospolicy_t *q) -{ - q->kind = bswap4u (q->kind); -} - -dds_return_t validate_ownership_qospolicy (const dds_ownership_qospolicy_t *q) -{ - switch (q->kind) - { - case DDS_OWNERSHIP_SHARED: - case DDS_OWNERSHIP_EXCLUSIVE: - return 0; - default: - DDS_TRACE("plist/validate_ownership_qospolicy: invalid kind (%d)\n", (int) q->kind); - return DDS_RETCODE_BAD_PARAMETER; - } -} - -static void bswap_ownership_strength_qospolicy (dds_ownership_strength_qospolicy_t *q) -{ - q->value = bswap4 (q->value); -} - -dds_return_t validate_ownership_strength_qospolicy (UNUSED_ARG (const dds_ownership_strength_qospolicy_t *q)) -{ - return 0; -} - -static void bswap_presentation_qospolicy (dds_presentation_qospolicy_t *q) -{ - q->access_scope = bswap4u (q->access_scope); -} - -dds_return_t validate_presentation_qospolicy (const dds_presentation_qospolicy_t *q) -{ - switch (q->access_scope) - { - case DDS_PRESENTATION_INSTANCE: - case DDS_PRESENTATION_TOPIC: - case DDS_PRESENTATION_GROUP: - break; - default: - DDS_TRACE("plist/validate_presentation_qospolicy: invalid access_scope (%d)\n", (int) q->access_scope); - return DDS_RETCODE_BAD_PARAMETER; - } - /* Bools must be 0 or 1, i.e., only the lsb may be set */ - if (q->coherent_access & ~1) - { - DDS_TRACE("plist/validate_presentation_qospolicy: coherent_access invalid (%d)\n", (int) q->coherent_access); - return DDS_RETCODE_BAD_PARAMETER; - } - if (q->ordered_access & ~1) - { - DDS_TRACE("plist/validate_presentation_qospolicy: ordered_access invalid (%d)\n", (int) q->ordered_access); - return DDS_RETCODE_BAD_PARAMETER; - } - /* coherent_access & ordered_access are a bit irrelevant for - instance presentation qos, but it appears as if their values are - not prescribed in that case. */ - return 0; -} - -static void bswap_transport_priority_qospolicy (dds_transport_priority_qospolicy_t *q) -{ - q->value = bswap4 (q->value); -} - -dds_return_t validate_transport_priority_qospolicy (UNUSED_ARG (const dds_transport_priority_qospolicy_t *q)) -{ return 0; } @@ -957,22 +1669,13 @@ static int locator_address_zero (const nn_locator_t *loc) return (u[0] == 0 && u[1] == 0 && u[2] == 0 && u[3] == 0); } -static dds_return_t do_locator -( - nn_locators_t *ls, - uint64_t *present, - uint64_t wanted, - uint64_t fl, - const struct dd *dd -) +static dds_return_t do_locator (nn_locators_t *ls, uint64_t *present, uint64_t wanted, uint64_t fl, const struct dd *dd) { nn_locator_t loc; if (dd->bufsz < sizeof (loc)) - { - DDS_TRACE("plist/do_locator: buffer too small\n"); return DDS_RETCODE_BAD_PARAMETER; - } + memcpy (&loc, dd->buf, sizeof (loc)); if (dd->bswap) { @@ -984,58 +1687,36 @@ static dds_return_t do_locator case NN_LOCATOR_KIND_UDPv4: case NN_LOCATOR_KIND_TCPv4: if (loc.port <= 0 || loc.port > 65535) - { - DDS_TRACE("plist/do_locator[kind=IPv4]: invalid port (%d)\n", (int) loc.port); return DDS_RETCODE_BAD_PARAMETER; - } if (!locator_address_prefix12_zero (&loc)) - { - DDS_TRACE("plist/do_locator[kind=IPv4]: junk in address prefix\n"); return DDS_RETCODE_BAD_PARAMETER; - } break; case NN_LOCATOR_KIND_UDPv6: case NN_LOCATOR_KIND_TCPv6: if (loc.port <= 0 || loc.port > 65535) - { - DDS_TRACE("plist/do_locator[kind=IPv6]: invalid port (%d)\n", (int) loc.port); return DDS_RETCODE_BAD_PARAMETER; - } break; case NN_LOCATOR_KIND_UDPv4MCGEN: { const nn_udpv4mcgen_address_t *x = (const nn_udpv4mcgen_address_t *) loc.address; - if (!ddsi_factory_supports(gv.m_factory, NN_LOCATOR_KIND_UDPv4)) + if (!ddsi_factory_supports (gv.m_factory, NN_LOCATOR_KIND_UDPv4)) return 0; if (loc.port <= 0 || loc.port > 65536) - { - DDS_TRACE("plist/do_locator[kind=IPv4MCGEN]: invalid port (%d)\n", (int) loc.port); return DDS_RETCODE_BAD_PARAMETER; - } - if ((int)x->base + x->count >= 28 || x->count == 0 || x->idx >= x->count) - { - DDS_TRACE("plist/do_locator[kind=IPv4MCGEN]: invalid base/count/idx (%u,%u,%u)\n", x->base, x->count, x->idx); + if ((uint32_t) x->base + x->count >= 28 || x->count == 0 || x->idx >= x->count) return DDS_RETCODE_BAD_PARAMETER; - } break; } case NN_LOCATOR_KIND_INVALID: if (!locator_address_zero (&loc)) - { - DDS_TRACE("plist/do_locator[kind=INVALID]: junk in address\n"); return DDS_RETCODE_BAD_PARAMETER; - } if (loc.port != 0) - { - DDS_TRACE("plist/do_locator[kind=INVALID]: junk in port\n"); return DDS_RETCODE_BAD_PARAMETER; - } /* silently dropped correctly formatted "invalid" locators. */ return 0; case NN_LOCATOR_KIND_RESERVED: /* silently dropped "reserved" locators. */ return 0; default: - DDS_TRACE("plist/do_locator: invalid kind (%d)\n", (int) loc.kind); return NN_PEDANTIC_P ? DDS_RETCODE_BAD_PARAMETER : 0; } return add_locator (ls, present, wanted, fl, &loc); @@ -1057,10 +1738,7 @@ static dds_return_t do_ipv4address (nn_plist_t *dest, nn_ipaddress_params_tmp_t uint32_t fl1_tmp; uint64_t fldest; if (dd->bufsz < sizeof (*a)) - { - DDS_TRACE("plist/do_ipv4address: buffer too small\n"); return DDS_RETCODE_BAD_PARAMETER; - } switch (fl_tmp) { case PPTMP_MULTICAST_IPADDRESS: @@ -1127,10 +1805,7 @@ static dds_return_t do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_t uint64_t fldest; uint32_t fl1_tmp; if (dd->bufsz < sizeof (*p)) - { - DDS_TRACE("plist/do_port: buffer too small\n"); return DDS_RETCODE_BAD_PARAMETER; - } switch (fl_tmp) { case PPTMP_DEFAULT_UNICAST_PORT: @@ -1161,10 +1836,7 @@ static dds_return_t do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_t if (dd->bswap) *p = bswap4u (*p); if (*p <= 0 || *p > 65535) - { - DDS_TRACE("plist/do_port: invalid port (%d)\n", (int) *p); return DDS_RETCODE_BAD_PARAMETER; - } dest_tmp->present |= fl_tmp; if ((dest_tmp->present & (fl_tmp | fl1_tmp)) == (fl_tmp | fl1_tmp)) { @@ -1182,1055 +1854,133 @@ static dds_return_t do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_t } } -static dds_return_t valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd)) +static dds_return_t return_unrecognized_pid (nn_plist_t *plist, nn_parameterid_t pid) { - /* All 0 is GUID_UNKNOWN, which is a defined GUID */ - if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0) - { - if (g->entityid.u == 0) - return 0; - else - { - DDS_TRACE("plist/valid_participant_guid: prefix is 0 but entityid is not (%"PRIu32")\n", g->entityid.u); - return DDS_RETCODE_BAD_PARAMETER; - } - } - else if (g->entityid.u == NN_ENTITYID_PARTICIPANT) - { + if (!(pid & PID_UNRECOGNIZED_INCOMPATIBLE_FLAG)) return 0; - } else { - DDS_TRACE("plist/valid_participant_guid: entityid not a participant entityid (%"PRIu32")\n", g->entityid.u); - return DDS_RETCODE_BAD_PARAMETER; + plist->present |= PP_INCOMPATIBLE; + return DDS_RETCODE_UNSUPPORTED; } } -static dds_return_t valid_group_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd)) +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) { - /* All 0 is GUID_UNKNOWN, which is a defined GUID */ - if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0) - { - if (g->entityid.u == 0) - return 0; - else - { - DDS_TRACE("plist/valid_group_guid: prefix is 0 but entityid is not (%"PRIu32")\n", g->entityid.u); - return DDS_RETCODE_BAD_PARAMETER; - } - } - else if (g->entityid.u != 0) - { - /* accept any entity id */ - return 0; - } - else - { - DDS_TRACE("plist/valid_group_guid: entityid is 0\n"); - return DDS_RETCODE_BAD_PARAMETER; - } -} - -static dds_return_t valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) -{ - /* All 0 is GUID_UNKNOWN, which is a defined GUID */ - if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0) - { - if (g->entityid.u == 0) - return 0; - else - { - DDS_TRACE("plist/valid_endpoint_guid: prefix is 0 but entityid is not (%"PRIx32")\n", g->entityid.u); - return DDS_RETCODE_BAD_PARAMETER; - } - } - switch (g->entityid.u & NN_ENTITYID_SOURCE_MASK) - { - case NN_ENTITYID_SOURCE_USER: - switch (g->entityid.u & NN_ENTITYID_KIND_MASK) - { - case NN_ENTITYID_KIND_WRITER_WITH_KEY: - case NN_ENTITYID_KIND_WRITER_NO_KEY: - case NN_ENTITYID_KIND_READER_NO_KEY: - case NN_ENTITYID_KIND_READER_WITH_KEY: - return 0; - default: - if (protocol_version_is_newer (dd->protocol_version)) - return 0; - else - { - DDS_TRACE("plist/valid_endpoint_guid[src=USER,proto=%u.%u]: invalid kind (%"PRIx32")\n", - dd->protocol_version.major, dd->protocol_version.minor, - g->entityid.u & NN_ENTITYID_KIND_MASK); - return DDS_RETCODE_BAD_PARAMETER; - } - } - case NN_ENTITYID_SOURCE_BUILTIN: - switch (g->entityid.u) - { - case NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_TOPIC_READER: - case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER: - case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER: - case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER: - case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER: - case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER: - case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER: - return 0; - default: - if (protocol_version_is_newer (dd->protocol_version)) - return 0; - else - { - DDS_TRACE("plist/valid_endpoint_guid[src=BUILTIN,proto=%u.%u]: invalid entityid (%"PRIx32")\n", - dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u); - return DDS_RETCODE_BAD_PARAMETER; - } - } - case NN_ENTITYID_SOURCE_VENDOR: - if (!vendor_is_eclipse (dd->vendorid)) - return 0; - else - { - switch (g->entityid.u) - { - case NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_READER: - case NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_READER: - case NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_READER: - return 0; - default: - if (protocol_version_is_newer (dd->protocol_version)) - return 0; - else - { - DDS_TRACE("plist/valid_endpoint_guid[src=VENDOR,proto=%u.%u]: unexpected entityid (%"PRIx32")\n", - dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u); - return 0; - } - } - } - default: - DDS_TRACE("plist/valid_endpoint_guid: invalid source (%"PRIx32")\n", g->entityid.u); - return DDS_RETCODE_BAD_PARAMETER; - } -} - -static dds_return_t do_guid (nn_guid_t *dst, uint64_t *present, uint64_t fl, int (*valid) (const nn_guid_t *g, const struct dd *dd), const struct dd *dd) -{ - if (dd->bufsz < sizeof (*dst)) - { - DDS_TRACE("plist/do_guid: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - memcpy (dst, dd->buf, sizeof (*dst)); - *dst = nn_ntoh_guid (*dst); - if (valid (dst, dd) < 0) - { - /* CoreDX once upon a time used to send out PARTICIPANT_GUID parameters with a 0 entity id, but it - that has long since changed (even if I don't know exactly when) */ - if (fl == PP_PARTICIPANT_GUID && vendor_is_twinoaks (dd->vendorid) && dst->entityid.u == 0 && ! NN_STRICT_P) - { - DDS_LOG(DDS_LC_DISCOVERY, "plist(vendor %u.%u): rewriting invalid participant guid "PGUIDFMT, - dd->vendorid.id[0], dd->vendorid.id[1], PGUID (*dst)); - dst->entityid.u = NN_ENTITYID_PARTICIPANT; - } - else - { - return DDS_RETCODE_BAD_PARAMETER; - } - } - *present |= fl; - return 0; -} - - -static void bswap_prismtech_participant_version_info (nn_prismtech_participant_version_info_t *pvi) -{ - int i; - pvi->version = bswap4u (pvi->version); - pvi->flags = bswap4u (pvi->flags); - for (i = 0; i < 3; i++) - pvi->unused[i] = bswap4u (pvi->unused[i]); -} - -static dds_return_t do_prismtech_participant_version_info (nn_prismtech_participant_version_info_t *pvi, uint64_t *present, uint64_t *aliased, const struct dd *dd) -{ - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - else if (dd->bufsz < NN_PRISMTECH_PARTICIPANT_VERSION_INFO_FIXED_CDRSIZE) - { - DDS_TRACE("plist/do_prismtech_participant_version_info[pid=PRISMTECH_PARTICIPANT_VERSION_INFO]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - else - { - dds_return_t res; - uint32_t sz = NN_PRISMTECH_PARTICIPANT_VERSION_INFO_FIXED_CDRSIZE - sizeof(uint32_t); - uint32_t *pu = (uint32_t *)dd->buf; - size_t len; - struct dd dd1 = *dd; - - memcpy (pvi, dd->buf, sz); - if (dd->bswap) - bswap_prismtech_participant_version_info(pvi); - - dd1.buf = (unsigned char *) &pu[5]; - dd1.bufsz = dd->bufsz - sz; - if ((res = alias_string ((const unsigned char **) &pvi->internals, &dd1, &len)) >= 0) { - *present |= PP_PRISMTECH_PARTICIPANT_VERSION_INFO; - *aliased |= PP_PRISMTECH_PARTICIPANT_VERSION_INFO; - res = 0; - } - - return res; - } -} - -static dds_return_t do_subscription_keys_qospolicy (dds_subscription_keys_qospolicy_t *q, uint64_t *present, uint64_t *aliased, uint64_t fl, const struct dd *dd) -{ - struct dd dd1; - dds_return_t res; - if (dd->bufsz < 4) - { - DDS_TRACE("plist/do_subscription_keys: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - q->use_key_list = (unsigned char) dd->buf[0]; - if (q->use_key_list != 0 && q->use_key_list != 1) - { - DDS_TRACE("plist/do_subscription_keys: invalid use_key_list (%d)\n", (int) q->use_key_list); - return DDS_RETCODE_BAD_PARAMETER; - } - dd1 = *dd; - dd1.buf += 4; - dd1.bufsz -= 4; - if ((res = alias_stringseq (&q->key_list, &dd1)) >= 0) - { - *present |= fl; - *aliased |= fl; - } - return res; -} - -static dds_return_t unalias_subscription_keys_qospolicy (dds_subscription_keys_qospolicy_t *q, int bswap) -{ - return unalias_stringseq (&q->key_list, bswap); -} - -static dds_return_t do_reader_lifespan_qospolicy (dds_reader_lifespan_qospolicy_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) -{ - dds_external_reader_lifespan_qospolicy_t qext; - dds_return_t res; - if (dd->bufsz < sizeof (qext)) - { - DDS_TRACE("plist/do_reader_lifespan: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - memcpy (&qext, dd->buf, sizeof (qext)); - if (dd->bswap) - bswap_external_duration (&qext.duration); - if (qext.use_lifespan != 0 && qext.use_lifespan != 1) - { - DDS_TRACE("plist/do_reader_lifespan: invalid use_lifespan (%d)\n", (int) qext.use_lifespan); - return DDS_RETCODE_BAD_PARAMETER; - } - if ((res = validate_external_duration (&qext.duration)) < 0) - return res; - q->use_lifespan = qext.use_lifespan; - q->duration = nn_from_ddsi_duration (qext.duration); - *present |= fl; - return 0; -} - -static dds_return_t do_entity_factory_qospolicy (dds_entity_factory_qospolicy_t *q, uint64_t *present, uint64_t fl, const struct dd *dd) -{ - if (dd->bufsz < sizeof (*q)) - { - DDS_TRACE("plist/do_entity_factory: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - q->autoenable_created_entities = dd->buf[0]; - if (q->autoenable_created_entities != 0 && q->autoenable_created_entities != 1) - { - DDS_TRACE("plist/do_entity_factory: invalid autoenable_created_entities (%d)\n", (int) q->autoenable_created_entities); - return DDS_RETCODE_BAD_PARAMETER; - } - *present |= fl; - return 0; -} - -static dds_return_t validate_external_reader_data_lifecycle (const dds_external_reader_data_lifecycle_qospolicy_t *q) -{ - if (validate_external_duration (&q->autopurge_nowriter_samples_delay) < 0 || - validate_external_duration (&q->autopurge_disposed_samples_delay) < 0) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid autopurge_nowriter_sample_delay or autopurge_disposed_samples_delay\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - return 0; -} - -dds_return_t validate_reader_data_lifecycle (const dds_reader_data_lifecycle_qospolicy_t *q) -{ - dds_external_reader_data_lifecycle_qospolicy_t qext; - qext.autopurge_disposed_samples_delay = nn_to_ddsi_duration (q->autopurge_disposed_samples_delay); - qext.autopurge_nowriter_samples_delay = nn_to_ddsi_duration (q->autopurge_nowriter_samples_delay); - return validate_external_reader_data_lifecycle (&qext); -} - -static dds_return_t do_reader_data_lifecycle (dds_reader_data_lifecycle_qospolicy_t *q, const struct dd *dd) -{ - dds_external_reader_data_lifecycle_qospolicy_t qext; - dds_return_t ret; - memcpy (&qext, dd->buf, sizeof (qext)); - if (dd->bswap) - { - bswap_external_duration (&qext.autopurge_nowriter_samples_delay); - bswap_external_duration (&qext.autopurge_disposed_samples_delay); - } - if ((ret = validate_external_reader_data_lifecycle (&qext)) < 0) - return ret; - q->autopurge_disposed_samples_delay = nn_from_ddsi_duration (qext.autopurge_disposed_samples_delay); - q->autopurge_nowriter_samples_delay = nn_from_ddsi_duration (qext.autopurge_nowriter_samples_delay); - return 0; -} - -static dds_return_t init_one_parameter -( - nn_plist_t *dest, - nn_ipaddress_params_tmp_t *dest_tmp, - uint64_t pwanted, - uint64_t qwanted, - uint16_t pid, - const struct dd *dd -) -{ - dds_return_t res; + /* special-cased ipv4address and port, because they have state beyond that what gets + passed into the generic code */ switch (pid) { - case PID_PAD: - case PID_SENTINEL: - return 0; - - /* Extended QoS data: */ -#define Q(NAME_, prefix_, name_) case PID_##NAME_: \ - if (dd->bufsz < sizeof (prefix_##_##name_##_qospolicy_t)) \ - { \ - DDS_TRACE("plist/init_one_parameter[pid=%s]: buffer too small\n", #NAME_); \ - return DDS_RETCODE_BAD_PARAMETER; \ - } \ - else \ - { \ - prefix_##_##name_##_qospolicy_t *q = &dest->qos.name_; \ - memcpy (q, dd->buf, sizeof (*q)); \ - if (dd->bswap) bswap_##name_##_qospolicy (q); \ - if ((res = validate_##name_##_qospolicy (q)) < 0) \ - return res; \ - dest->qos.present |= QP_##NAME_; \ - } \ - return 0 - Q (DURABILITY, dds, durability); - Q (DESTINATION_ORDER, dds, destination_order); - Q (HISTORY, dds, history); - Q (RESOURCE_LIMITS, dds, resource_limits); - Q (OWNERSHIP, dds, ownership); - Q (OWNERSHIP_STRENGTH, dds, ownership_strength); - Q (PRESENTATION, dds, presentation); - Q (TRANSPORT_PRIORITY, dds, transport_priority); -#undef Q - - case PID_LIVELINESS: - if (dd->bufsz < sizeof (dds_external_liveliness_qospolicy_t)) - { - DDS_TRACE("plist/init_one_parameter[pid=LIVELINESS]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - else - { - dds_external_liveliness_qospolicy_t qext; - dds_liveliness_qospolicy_t *q = &dest->qos.liveliness; - memcpy (&qext, dd->buf, sizeof (qext)); - if (dd->bswap) - bswap_external_liveliness_qospolicy (&qext); - if ((res = validate_external_liveliness_qospolicy (&qext)) < 0) - return res; - q->kind = qext.kind; - q->lease_duration = nn_from_ddsi_duration (qext.lease_duration); - dest->qos.present |= QP_LIVELINESS; - } - return 0; - - case PID_DURABILITY_SERVICE: - if (dd->bufsz < sizeof (dds_external_durability_service_qospolicy_t)) - { - DDS_TRACE("plist/init_one_parameter[pid=DURABILITY_SERVICE]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - else - { - dds_external_durability_service_qospolicy_t qext; - dds_durability_service_qospolicy_t *q = &dest->qos.durability_service; - /* All-zero durability service is illegal, but at least CoreDX sometimes advertises - it in some harmless cases. So accept all-zero durability service, then handle it - in final_validation, where we can determine whether it really is harmless or not */ - memcpy (&qext, dd->buf, sizeof (qext)); - if (dd->bswap) - bswap_external_durability_service_qospolicy (&qext); - if ((res = validate_external_durability_service_qospolicy_acceptzero (&qext, true)) < 0) - return res; - q->history = qext.history; - q->resource_limits = qext.resource_limits; - q->service_cleanup_delay = nn_from_ddsi_duration (qext.service_cleanup_delay); - dest->qos.present |= QP_DURABILITY_SERVICE; - } - return 0; - - /* PID_RELIABILITY handled differently because it (formally, for - static typing reasons) has a different type on the network - than internally, with the transformation between the two - dependent on wheter we are being pedantic. If that weren't - the case, it would've been an ordinary Q (RELIABILITY, - reliability). */ - case PID_RELIABILITY: - if (dd->bufsz < sizeof (dds_external_reliability_qospolicy_t)) - { - DDS_TRACE("plist/init_one_parameter[pid=RELIABILITY]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - else - { - dds_reliability_qospolicy_t *q = &dest->qos.reliability; - dds_external_reliability_qospolicy_t qext; - memcpy (&qext, dd->buf, sizeof (qext)); - if (dd->bswap) - bswap_external_reliability_qospolicy (&qext); - if ((res = validate_xform_reliability_qospolicy (q, &qext)) < 0) - return res; - dest->qos.present |= QP_RELIABILITY; - } - return 0; - - case PID_TOPIC_NAME: - return do_string (&dest->qos.topic_name, &dest->qos.present, &dest->qos.aliased, qwanted, QP_TOPIC_NAME, dd); - case PID_TYPE_NAME: - return do_string (&dest->qos.type_name, &dest->qos.present, &dest->qos.aliased, qwanted, QP_TYPE_NAME, dd); - - case PID_USER_DATA: - return do_octetseq (&dest->qos.user_data, &dest->qos.present, &dest->qos.aliased, qwanted, QP_USER_DATA, dd); - case PID_GROUP_DATA: - return do_octetseq (&dest->qos.group_data, &dest->qos.present, &dest->qos.aliased, qwanted, QP_GROUP_DATA, dd); - case PID_TOPIC_DATA: - return do_octetseq (&dest->qos.topic_data, &dest->qos.present, &dest->qos.aliased, qwanted, QP_TOPIC_DATA, dd); - - case PID_DEADLINE: - return do_duration (&dest->qos.deadline.deadline, &dest->qos.present, QP_DEADLINE, dd); - case PID_LATENCY_BUDGET: - return do_duration (&dest->qos.latency_budget.duration, &dest->qos.present, QP_LATENCY_BUDGET, dd); - case PID_LIFESPAN: - return do_duration (&dest->qos.lifespan.duration, &dest->qos.present, QP_LIFESPAN, dd); - case PID_TIME_BASED_FILTER: - return do_duration (&dest->qos.time_based_filter.minimum_separation, &dest->qos.present, QP_TIME_BASED_FILTER, dd); - - case PID_PARTITION: - return do_stringseq (&dest->qos.partition, &dest->qos.present, &dest->qos.aliased, qwanted, QP_PARTITION, dd); - - case PID_PRISMTECH_READER_DATA_LIFECYCLE: /* PrismTech specific */ - { - dds_return_t ret; - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - if (dd->bufsz >= sizeof (dds_external_reader_data_lifecycle_qospolicy_t)) - ret = do_reader_data_lifecycle (&dest->qos.reader_data_lifecycle, dd); - else - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: buffer too small\n"); - ret = DDS_RETCODE_BAD_PARAMETER; - } - if (ret >= 0) - dest->qos.present |= QP_PRISMTECH_READER_DATA_LIFECYCLE; - return ret; - } - case PID_PRISMTECH_WRITER_DATA_LIFECYCLE: /* PrismTech specific */ - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - else - { - dds_writer_data_lifecycle_qospolicy_t *q = &dest->qos.writer_data_lifecycle; - if (dd->bufsz < sizeof (*q)) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - q->autodispose_unregistered_instances = dd->buf[0]; - if (q->autodispose_unregistered_instances & ~1) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: invalid autodispose_unregistered_instances (%d)\n", (int) q->autodispose_unregistered_instances); - return DDS_RETCODE_BAD_PARAMETER; - } - dest->qos.present |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE; - return 0; - } - - /* Other plist */ - case PID_PROTOCOL_VERSION: - if (dd->bufsz < sizeof (nn_protocol_version_t)) - { - DDS_TRACE("plist/init_one_parameter[pid=PROTOCOL_VERSION]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - memcpy (&dest->protocol_version, dd->buf, sizeof (dest->protocol_version)); - if (NN_STRICT_P && - (dest->protocol_version.major != dd->protocol_version.major || - dest->protocol_version.minor != dd->protocol_version.minor)) - { - /* Not accepting a submessage advertising a protocol version - other than that advertised by the message header, unless I - have good reason to, at least not when being strict. */ - DDS_TRACE("plist/init_one_parameter[pid=PROTOCOL_VERSION,mode=STRICT]: version (%u.%u) mismatch with message (%u.%u)\n", - dest->protocol_version.major, dest->protocol_version.minor, - dd->protocol_version.major, dd->protocol_version.minor); - return DDS_RETCODE_BAD_PARAMETER; - } - dest->present |= PP_PROTOCOL_VERSION; - return 0; - - case PID_VENDORID: - if (dd->bufsz < sizeof (nn_vendorid_t)) - return DDS_RETCODE_BAD_PARAMETER; - memcpy (&dest->vendorid, dd->buf, sizeof (dest->vendorid)); - if (NN_STRICT_P && - (dest->vendorid.id[0] != dd->vendorid.id[0] || - dest->vendorid.id[1] != dd->vendorid.id[1])) - { - /* see PROTOCOL_VERSION */ - DDS_TRACE("plist/init_one_parameter[pid=VENDORID,mode=STRICT]: vendor (%u.%u) mismatch with message (%u.%u)\n", - dest->vendorid.id[0], dest->vendorid.id[1], dd->vendorid.id[0], dd->vendorid.id[1]); - return DDS_RETCODE_BAD_PARAMETER; - } - dest->present |= PP_VENDORID; - return 0; - - /* Locators: there may be lists, so we have to allocate memory for them */ -#define XL(NAME_, name_) case PID_##NAME_##_LOCATOR: return do_locator (&dest->name_##_locators, &dest->present, pwanted, PP_##NAME_##_LOCATOR, dd) - XL (UNICAST, unicast); - XL (MULTICAST, multicast); - XL (DEFAULT_UNICAST, default_unicast); - XL (DEFAULT_MULTICAST, default_multicast); - XL (METATRAFFIC_UNICAST, metatraffic_unicast); - XL (METATRAFFIC_MULTICAST, metatraffic_multicast); -#undef XL - - /* IPADDRESS + PORT entries are a nuisance ... I'd prefer - converting them to locators right away, so that the rest of - the code only has to deal with locators, but that is - impossible because the locators require both the address & - the port to be known. - - The wireshark dissector suggests IPvAdress_t is just the 32 - bits of the IP address but it doesn't say so anywhere - ... Similarly for ports, but contrary to the expections they - seem to be 32-bits, too. Apparently in host-endianness. - - And, to be honest, I have no idea what port to use for - MULTICAST_IPADDRESS ... */ -#define XA(NAME_) case PID_##NAME_##_IPADDRESS: return do_ipv4address (dest, dest_tmp, pwanted, PPTMP_##NAME_##_IPADDRESS, dd) -#define XP(NAME_) case PID_##NAME_##_PORT: return do_port (dest, dest_tmp, pwanted, PPTMP_##NAME_##_PORT, dd) - XA (MULTICAST); - XA (DEFAULT_UNICAST); - XP (DEFAULT_UNICAST); - XA (METATRAFFIC_UNICAST); - XP (METATRAFFIC_UNICAST); - XA (METATRAFFIC_MULTICAST); - XP (METATRAFFIC_MULTICAST); +#define XA(NAME_) case PID_##NAME_##_IPADDRESS: return do_ipv4address (plist, dest_tmp, pwanted, PPTMP_##NAME_##_IPADDRESS, dd) +#define XP(NAME_) case PID_##NAME_##_PORT: return do_port (plist, dest_tmp, pwanted, PPTMP_##NAME_##_PORT, dd) + XA (MULTICAST); + XA (DEFAULT_UNICAST); + XP (DEFAULT_UNICAST); + XA (METATRAFFIC_UNICAST); + XP (METATRAFFIC_UNICAST); + XA (METATRAFFIC_MULTICAST); + XP (METATRAFFIC_MULTICAST); #undef XP #undef XA - - case PID_EXPECTS_INLINE_QOS: - if (dd->bufsz < sizeof (dest->expects_inline_qos)) - { - DDS_TRACE("plist/init_one_parameter[pid=EXPECTS_INLINE_QOS]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - dest->expects_inline_qos = dd->buf[0]; - /* boolean: only lsb may be set */ - if (dest->expects_inline_qos & ~1) - { - DDS_TRACE("plist/init_one_parameter[pid=EXPECTS_INLINE_QOS]: invalid expects_inline_qos (%d)\n", - (int) dest->expects_inline_qos); - return DDS_RETCODE_BAD_PARAMETER; - } - dest->present |= PP_EXPECTS_INLINE_QOS; - return 0; - - case PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT: - /* Spec'd as "incremented monotonically" (DDSI 2.1, table 8.13), - but 32 bits signed is not such a smart choice for that. We'll - simply accept any value. */ - if (dd->bufsz < sizeof (dest->participant_manual_liveliness_count)) - { - DDS_TRACE("plist/init_one_parameter[pid=PARTICIPANT_MANUAL_LIVELINESS_COUNT]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - memcpy (&dest->participant_manual_liveliness_count, dd->buf, sizeof (dest->participant_manual_liveliness_count)); - if (dd->bswap) - dest->participant_manual_liveliness_count = bswap4 (dest->participant_manual_liveliness_count); - dest->present |= PP_PARTICIPANT_MANUAL_LIVELINESS_COUNT; - return 0; - - case PID_PARTICIPANT_LEASE_DURATION: - return do_duration (&dest->participant_lease_duration, &dest->present, PP_PARTICIPANT_LEASE_DURATION, dd); - - case PID_CONTENT_FILTER_PROPERTY: - /* FIXME */ - return 0; - - case PID_PARTICIPANT_GUID: - return do_guid (&dest->participant_guid, &dest->present, PP_PARTICIPANT_GUID, valid_participant_guid, dd); - - case PID_GROUP_GUID: - return do_guid (&dest->group_guid, &dest->present, PP_GROUP_GUID, valid_group_guid, dd); - - case PID_PARTICIPANT_ENTITYID: - case PID_GROUP_ENTITYID: - /* DDSI 2.1 table 9.13: reserved for future use */ - return 0; - - case PID_PARTICIPANT_BUILTIN_ENDPOINTS: - /* FIXME: I assume it is the same as the BUILTIN_ENDPOINT_SET, - which is the set that DDSI2 has been using so far. */ - /* FALLS THROUGH */ - case PID_BUILTIN_ENDPOINT_SET: - if (dd->bufsz < sizeof (dest->builtin_endpoint_set)) - { - DDS_TRACE("plist/init_one_parameter[pid=BUILTIN_ENDPOINT_SET(%u)]: buffer too small\n", pid); - return DDS_RETCODE_BAD_PARAMETER; - } - memcpy (&dest->builtin_endpoint_set, dd->buf, sizeof (dest->builtin_endpoint_set)); - if (dd->bswap) - dest->builtin_endpoint_set = bswap4u (dest->builtin_endpoint_set); - if (NN_STRICT_P && !protocol_version_is_newer (dd->protocol_version) && - (dest->builtin_endpoint_set & ~(NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER | - NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR | - NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER | - NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_DETECTOR | - NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER | - NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_DETECTOR | - NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER | - NN_DISC_BUILTIN_ENDPOINT_TOPIC_DETECTOR | - /* undefined ones: */ - NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_PROXY_ANNOUNCER | - NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_PROXY_DETECTOR | - NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_STATE_ANNOUNCER | - NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_STATE_DETECTOR | - /* defined ones again: */ - NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER | - NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER)) != 0) - { - DDS_TRACE("plist/init_one_parameter[pid=BUILTIN_ENDPOINT_SET(%u),mode=STRICT,proto=%u.%u]: invalid set (0x%x)\n", - pid, dd->protocol_version.major, dd->protocol_version.minor, dest->builtin_endpoint_set); - return DDS_RETCODE_BAD_PARAMETER; - } - dest->present |= PP_BUILTIN_ENDPOINT_SET; - return 0; - - case PID_PRISMTECH_BUILTIN_ENDPOINT_SET: - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - else if (dd->bufsz < sizeof (dest->prismtech_builtin_endpoint_set)) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_BUILTIN_ENDPOINT_SET(%u)]: buffer too small\n", pid); - return DDS_RETCODE_BAD_PARAMETER; - } - else - { - memcpy (&dest->prismtech_builtin_endpoint_set, dd->buf, sizeof (dest->prismtech_builtin_endpoint_set)); - if (dd->bswap) - dest->prismtech_builtin_endpoint_set = bswap4u (dest->prismtech_builtin_endpoint_set); - dest->present |= PP_PRISMTECH_BUILTIN_ENDPOINT_SET; - } - return 0; - - case PID_PROPERTY_LIST: - case PID_TYPE_MAX_SIZE_SERIALIZED: - /* FIXME */ - return 0; - - case PID_ENTITY_NAME: - return do_string (&dest->entity_name, &dest->present, &dest->aliased, pwanted, PP_ENTITY_NAME, dd); - - case PID_KEYHASH: - if (dd->bufsz < sizeof (dest->keyhash)) - { - DDS_TRACE("plist/init_one_parameter[pid=KEYHASH]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - memcpy (&dest->keyhash, dd->buf, sizeof (dest->keyhash)); - dest->present |= PP_KEYHASH; - return 0; - - case PID_STATUSINFO: - if (dd->bufsz < sizeof (dest->statusinfo)) - { - DDS_TRACE("plist/init_one_parameter[pid=STATUSINFO]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - memcpy (&dest->statusinfo, dd->buf, sizeof (dest->statusinfo)); - dest->statusinfo = fromBE4u (dest->statusinfo); - if (NN_STRICT_P && !protocol_version_is_newer (dd->protocol_version) && - (dest->statusinfo & ~NN_STATUSINFO_STANDARDIZED)) - { - /* Spec says I may not interpret the reserved bits. But no-one - may use them in this version of the specification */ - DDS_TRACE("plist/init_one_parameter[pid=STATUSINFO,mode=STRICT,proto=%u.%u]: invalid statusinfo (0x%x)\n", - dd->protocol_version.major, dd->protocol_version.minor, dest->statusinfo); - return DDS_RETCODE_BAD_PARAMETER; - } - /* Clear all bits we don't understand, then add the extended bits if present */ - dest->statusinfo &= NN_STATUSINFO_STANDARDIZED; - if (dd->bufsz >= 2 * sizeof (dest->statusinfo) && vendor_is_eclipse_or_opensplice(dd->vendorid)) - { - uint32_t statusinfox; - DDSRT_STATIC_ASSERT_CODE (sizeof(statusinfox) == sizeof(dest->statusinfo)); - memcpy (&statusinfox, dd->buf + sizeof (dest->statusinfo), sizeof (statusinfox)); - statusinfox = fromBE4u (statusinfox); - if (statusinfox & NN_STATUSINFOX_OSPL_AUTO) - dest->statusinfo |= NN_STATUSINFO_OSPL_AUTO; - } - dest->present |= PP_STATUSINFO; - return 0; - - case PID_COHERENT_SET: - if (dd->bufsz < sizeof (dest->coherent_set_seqno)) - { - DDS_TRACE("plist/init_one_parameter[pid=COHERENT_SET]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - else - { - nn_sequence_number_t *q = &dest->coherent_set_seqno; - seqno_t seqno; - memcpy (q, dd->buf, sizeof (*q)); - if (dd->bswap) - { - q->high = bswap4 (q->high); - q->low = bswap4u (q->low); - } - seqno = fromSN(dest->coherent_set_seqno); - if (seqno <= 0 && seqno != NN_SEQUENCE_NUMBER_UNKNOWN) - { - DDS_TRACE("plist/init_one_parameter[pid=COHERENT_SET]: invalid sequence number (%" PRId64 ")\n", seqno); - return DDS_RETCODE_BAD_PARAMETER; - } - dest->present |= PP_COHERENT_SET; - return 0; - } - - case PID_CONTENT_FILTER_INFO: - case PID_DIRECTED_WRITE: - case PID_ORIGINAL_WRITER_INFO: - /* FIXME */ - return 0; - - case PID_ENDPOINT_GUID: - if (NN_PEDANTIC_P && !protocol_version_is_newer (dd->protocol_version)) - { - /* ENDPOINT_GUID is not specified in the 2.1 standard, so - reject it: in (really) strict mode we do not accept - undefined things, even though we are -arguably- supposed to - ignore it. */ - DDS_TRACE("plist/init_one_parameter[pid=ENDPOINT_GUID,mode=PEDANTIC,proto=%u.%u]: undefined pid\n", - dd->protocol_version.major, dd->protocol_version.minor); - return DDS_RETCODE_BAD_PARAMETER; - } - return do_guid (&dest->endpoint_guid, &dest->present, PP_ENDPOINT_GUID, valid_endpoint_guid, dd); - - case PID_PRISMTECH_ENDPOINT_GUID: /* case PID_RTI_TYPECODE: */ - if (vendor_is_eclipse_or_prismtech (dd->vendorid)) - { - /* PrismTech specific variant of ENDPOINT_GUID, for strict compliancy */ - return do_guid (&dest->endpoint_guid, &dest->present, PP_ENDPOINT_GUID, valid_endpoint_guid, dd); - } - else if (vendor_is_rti (dd->vendorid)) - { - /* For RTI it is a typecode */ - return do_blob (&dest->qos.rti_typecode, &dest->qos.present, &dest->qos.aliased, qwanted, QP_RTI_TYPECODE, dd); - - } - else - { - return 0; - } - - case PID_PRISMTECH_PARTICIPANT_VERSION_INFO: - return do_prismtech_participant_version_info(&dest->prismtech_participant_version_info, &dest->present, &dest->aliased, dd); - - case PID_PRISMTECH_SUBSCRIPTION_KEYS: - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - return do_subscription_keys_qospolicy (&dest->qos.subscription_keys, &dest->qos.present, &dest->qos.aliased, QP_PRISMTECH_SUBSCRIPTION_KEYS, dd); - - case PID_PRISMTECH_READER_LIFESPAN: - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - return do_reader_lifespan_qospolicy (&dest->qos.reader_lifespan, &dest->qos.present, QP_PRISMTECH_READER_LIFESPAN, dd); - - case PID_PRISMTECH_ENTITY_FACTORY: - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - return do_entity_factory_qospolicy (&dest->qos.entity_factory, &dest->qos.present, QP_PRISMTECH_ENTITY_FACTORY, dd); - - case PID_PRISMTECH_NODE_NAME: - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - return do_string (&dest->node_name, &dest->present, &dest->aliased, pwanted, PP_PRISMTECH_NODE_NAME, dd); - - case PID_PRISMTECH_EXEC_NAME: - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - return do_string (&dest->exec_name, &dest->present, &dest->aliased, pwanted, PP_PRISMTECH_EXEC_NAME, dd); - - case PID_PRISMTECH_SERVICE_TYPE: - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - if (dd->bufsz < sizeof (dest->service_type)) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SERVICE_TYPE]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - memcpy (&dest->service_type, dd->buf, sizeof (dest->service_type)); - if (dd->bswap) - dest->service_type = bswap4u (dest->service_type); - dest->present |= PP_PRISMTECH_SERVICE_TYPE; - return 0; - - case PID_PRISMTECH_PROCESS_ID: - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - if (dd->bufsz < sizeof (dest->process_id)) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_PROCESS_ID]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - memcpy (&dest->process_id, dd->buf, sizeof (dest->process_id)); - if (dd->bswap) - dest->process_id = bswap4u (dest->process_id); - dest->present |= PP_PRISMTECH_PROCESS_ID; - return 0; - - case PID_PRISMTECH_TYPE_DESCRIPTION: - if (!vendor_is_eclipse_or_prismtech (dd->vendorid)) - return 0; - return do_string (&dest->type_description, &dest->present, &dest->aliased, pwanted, PP_PRISMTECH_TYPE_DESCRIPTION, dd); - - case PID_PRISMTECH_EOTINFO: - if (!vendor_is_eclipse_or_opensplice (dd->vendorid)) - return 0; - else if (dd->bufsz < 2*sizeof (uint32_t)) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_EOTINFO]: buffer too small (1)\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - else - { - nn_prismtech_eotinfo_t *q = &dest->eotinfo; - uint32_t i; - q->transactionId = ((const uint32_t *) dd->buf)[0]; - q->n = ((const uint32_t *) dd->buf)[1]; - if (dd->bswap) - { - q->n = bswap4u (q->n); - q->transactionId = bswap4u (q->transactionId); - } - if (q->n > (dd->bufsz - 2*sizeof (uint32_t)) / sizeof (nn_prismtech_eotgroup_tid_t)) - { - DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_EOTINFO]: buffer too small (2)\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - if (q->n == 0) - q->tids = NULL; - else - q->tids = (nn_prismtech_eotgroup_tid_t *) (dd->buf + 2*sizeof (uint32_t)); - for (i = 0; i < q->n; i++) - { - q->tids[i].writer_entityid.u = fromBE4u (q->tids[i].writer_entityid.u); - if (dd->bswap) - q->tids[i].transactionId = bswap4u (q->tids[i].transactionId); - } - dest->present |= PP_PRISMTECH_EOTINFO; - dest->aliased |= PP_PRISMTECH_EOTINFO; - if (dds_get_log_mask() & DDS_LC_PLIST) - { - DDS_LOG(DDS_LC_PLIST, "eotinfo: txn %"PRIu32" {", q->transactionId); - for (i = 0; i < q->n; i++) - DDS_LOG(DDS_LC_PLIST, " %"PRIx32":%"PRIu32, q->tids[i].writer_entityid.u, q->tids[i].transactionId); - DDS_LOG(DDS_LC_PLIST, " }\n"); - } - return 0; - } - -#ifdef DDSI_INCLUDE_SSM - case PID_READER_FAVOURS_SSM: - if (dd->bufsz < sizeof (dest->reader_favours_ssm)) - { - DDS_TRACE("plist/init_one_parameter[pid=READER_FAVOURS_SSM]: buffer too small\n"); - return DDS_RETCODE_BAD_PARAMETER; - } - else - { - nn_reader_favours_ssm_t *rfssm = &dest->reader_favours_ssm; - memcpy (rfssm, dd->buf, sizeof (*rfssm)); - if (dd->bswap) - rfssm->state = bswap4u (rfssm->state); - if (rfssm->state != 0 && rfssm->state != 1) - { - DDS_TRACE("plist/init_one_parameter[pid=READER_FAVOURS_SSM]: unsupported value: %u\n", rfssm->state); - rfssm->state = 0; - } - dest->present |= PP_READER_FAVOURS_SSM; - return 0; - } -#endif - - /* Deprecated ones (used by RTI, but not relevant to DDSI) */ - case PID_PERSISTENCE: - case PID_TYPE_CHECKSUM: - case PID_TYPE2_NAME: - case PID_TYPE2_CHECKSUM: - case PID_EXPECTS_ACK: - case PID_MANAGER_KEY: - case PID_SEND_QUEUE_SIZE: - case PID_RELIABILITY_ENABLED: - case PID_VARGAPPS_SEQUENCE_NUMBER_LAST: - case PID_RECV_QUEUE_SIZE: - case PID_RELIABILITY_OFFERED: - return 0; - - default: - /* Ignore unrecognised parameters (disregarding vendor-specific - ones, of course) if the protocol version is newer than the - one implemented, and fail it if it isn't. I know all RFPs say - to be tolerant in what is accepted, but that is where the - bugs & the buffer overflows originate! */ - if (pid & PID_UNRECOGNIZED_INCOMPATIBLE_FLAG) { - dest->present |= PP_INCOMPATIBLE; - return DDS_RETCODE_UNSUPPORTED; - } else if (pid & PID_VENDORSPECIFIC_FLAG) { - return 0; - } else if (!protocol_version_is_newer (dd->protocol_version) && NN_STRICT_P) { - DDS_TRACE("plist/init_one_parameter[pid=%u,mode=STRICT,proto=%u.%u]: undefined paramter id\n", - pid, dd->protocol_version.major, dd->protocol_version.minor); - return DDS_RETCODE_BAD_PARAMETER; - } else { - return 0; - } } - assert (0); - DDS_TRACE("plist/init_one_parameter: can't happen\n"); - return DDS_RETCODE_BAD_PARAMETER; -} + const struct piddesc_index *index; + if (!(pid & PID_VENDORSPECIFIC_FLAG)) + index = &piddesc_vendor_index[0]; + else if (dd->vendorid.id[0] != 1 || dd->vendorid.id[1] < 1) + return return_unrecognized_pid (plist, pid); + else if (dd->vendorid.id[1] >= sizeof (piddesc_vendor_index) / sizeof (piddesc_vendor_index[0])) + return return_unrecognized_pid (plist, pid); + else if (piddesc_vendor_index[dd->vendorid.id[1]].index == NULL) + return return_unrecognized_pid (plist, pid); + else + index = &piddesc_vendor_index[dd->vendorid.id[1]]; -static void default_resource_limits (dds_resource_limits_qospolicy_t *q) -{ - q->max_instances = DDS_LENGTH_UNLIMITED; - q->max_samples = DDS_LENGTH_UNLIMITED; - q->max_samples_per_instance = DDS_LENGTH_UNLIMITED; -} - -static void default_history (dds_history_qospolicy_t *q) -{ - q->kind = DDS_HISTORY_KEEP_LAST; - q->depth = 1; -} - -void nn_plist_init_empty (nn_plist_t *dest) -{ -#ifndef NDEBUG - memset (dest, 0, sizeof (*dest)); -#endif - dest->present = dest->aliased = 0; - nn_xqos_init_empty (&dest->qos); -} - -void nn_plist_mergein_missing (nn_plist_t *a, const nn_plist_t *b) -{ - /* Adds entries's from B to A (duplicating memory) (only those not - present in A, obviously) */ - - /* Simple ones (that don't need memory): everything but topic, type, - partition, {group,topic|user} data */ -#define CQ(fl_, name_) do { \ - if (!(a->present & PP_##fl_) && (b->present & PP_##fl_)) { \ - a->name_ = b->name_; \ - a->present |= PP_##fl_; \ - } \ - } while (0) - CQ (PROTOCOL_VERSION, protocol_version); - CQ (VENDORID, vendorid); - CQ (EXPECTS_INLINE_QOS, expects_inline_qos); - CQ (PARTICIPANT_MANUAL_LIVELINESS_COUNT, participant_manual_liveliness_count); - CQ (PARTICIPANT_BUILTIN_ENDPOINTS, participant_builtin_endpoints); - CQ (PARTICIPANT_LEASE_DURATION, participant_lease_duration); - CQ (PARTICIPANT_GUID, participant_guid); - CQ (ENDPOINT_GUID, endpoint_guid); - CQ (GROUP_GUID, group_guid); - CQ (BUILTIN_ENDPOINT_SET, builtin_endpoint_set); - CQ (KEYHASH, keyhash); - CQ (STATUSINFO, statusinfo); - CQ (COHERENT_SET, coherent_set_seqno); - CQ (PRISMTECH_SERVICE_TYPE, service_type); - CQ (PRISMTECH_PROCESS_ID, process_id); - CQ (PRISMTECH_BUILTIN_ENDPOINT_SET, prismtech_builtin_endpoint_set); -#ifdef DDSI_INCLUDE_SSM - CQ (READER_FAVOURS_SSM, reader_favours_ssm); -#endif -#undef CQ - - /* For allocated ones it is Not strictly necessary to use tmp, as - a->name_ may only be interpreted if the present flag is set, but - this keeps a clean on failure and may thereby save us from a - nasty surprise. */ -#define CQ(fl_, name_, type_, tmp_type_) do { \ - if (!(a->present & PP_##fl_) && (b->present & PP_##fl_)) { \ - tmp_type_ tmp = b->name_; \ - unalias_##type_ (&tmp, -1); \ - a->name_ = tmp; \ - a->present |= PP_##fl_; \ - } \ - } while (0) - CQ (UNICAST_LOCATOR, unicast_locators, locators, nn_locators_t); - CQ (MULTICAST_LOCATOR, unicast_locators, locators, nn_locators_t); - CQ (DEFAULT_UNICAST_LOCATOR, default_unicast_locators, locators, nn_locators_t); - CQ (DEFAULT_MULTICAST_LOCATOR, default_multicast_locators, locators, nn_locators_t); - CQ (METATRAFFIC_UNICAST_LOCATOR, metatraffic_unicast_locators, locators, nn_locators_t); - CQ (METATRAFFIC_MULTICAST_LOCATOR, metatraffic_multicast_locators, locators, nn_locators_t); - CQ (ENTITY_NAME, entity_name, string, char *); - CQ (PRISMTECH_NODE_NAME, node_name, string, char *); - CQ (PRISMTECH_EXEC_NAME, exec_name, string, char *); - CQ (PRISMTECH_TYPE_DESCRIPTION, type_description, string, char *); - CQ (PRISMTECH_EOTINFO, eotinfo, eotinfo, nn_prismtech_eotinfo_t); -#undef CQ - if (!(a->present & PP_PRISMTECH_PARTICIPANT_VERSION_INFO) && - (b->present & PP_PRISMTECH_PARTICIPANT_VERSION_INFO)) + const struct piddesc *entry; + if (pid_without_flags (pid) > index->index_max || (entry = index->index[pid_without_flags (pid)]) == NULL) + return return_unrecognized_pid (plist, pid); + assert (pid_without_flags (pid) == pid_without_flags (entry->pid)); + if (pid != entry->pid) { - nn_prismtech_participant_version_info_t tmp = b->prismtech_participant_version_info; - unalias_string (&tmp.internals, -1); - a->prismtech_participant_version_info = tmp; - a->present |= PP_PRISMTECH_PARTICIPANT_VERSION_INFO; + DDS_LOG (DDS_LC_ERROR, "error processing parameter list (vendor %u.%u, version %u.%u): pid %"PRIx16" mapped to pid %"PRIx16"\n", + dd->vendorid.id[0], dd->vendorid.id[1], + dd->protocol_version.major, dd->protocol_version.minor, + pid, entry->pid); + return return_unrecognized_pid (plist, pid); + } + assert (pid != PID_PAD); + + struct flagset flagset; + if (entry->flags & PDF_QOS) + { + flagset.present = &plist->qos.present; + flagset.aliased = &plist->qos.aliased; + flagset.wanted = qwanted; + } + else + { + flagset.present = &plist->present; + flagset.aliased = &plist->aliased; + flagset.wanted = pwanted; } - nn_xqos_mergein_missing (&a->qos, &b->qos); + /* Disallow multiple copies of the same parameter unless explicit allowed + (which is needed for handling locators). String sequences will leak + memory if deserialized repeatedly */ + if ((*flagset.present & entry->present_flag) && !(entry->flags & PDF_ALLOWMULTI)) + { + DDS_LOG (DDS_LC_WARNING, "invalid parameter list (vendor %u.%u, version %u.%u): pid %"PRIx16" (%s) multiply defined\n", + dd->vendorid.id[0], dd->vendorid.id[1], + dd->protocol_version.major, dd->protocol_version.minor, + pid, entry->name); + return DDS_RETCODE_BAD_PARAMETER; + } + if (!(flagset.wanted & entry->present_flag)) + { + /* skip don't cares -- the point of skipping them is performance and + avoiding unnecessary allocations, so validating them would be silly */ + return 0; + } + + /* String sequences are not allowed in parameters that may occur multiple + times because they will leak the arrays of pointers. Fixing this is + not worth the bother as long as such parameters don't exist. */ + dds_return_t ret; + void * const dst = (char *) plist + entry->plist_offset; + size_t dstoff = 0; + size_t srcoff = 0; + if (entry->flags & PDF_FUNCTION) + ret = entry->op.f.deser (dst, &dstoff, &flagset, entry->present_flag, dd, &srcoff); + else + ret = deser_generic (dst, &dstoff, &flagset, entry->present_flag, dd, &srcoff, entry->op.desc); + if (ret == 0 && entry->deser_validate_xform) + ret = entry->deser_validate_xform (dst, dd); + if (ret < 0) + { + DDS_LOG (DDS_LC_WARNING, "invalid parameter list (vendor %u.%u, version %u.%u): pid %"PRIx16" (%s) invalid, input = ", + dd->vendorid.id[0], dd->vendorid.id[1], + dd->protocol_version.major, dd->protocol_version.minor, + pid, entry->name); + log_octetseq (DDS_LC_WARNING, (uint32_t) dd->bufsz, dd->buf); + DDS_LOG (DDS_LC_WARNING, "\n"); + } + return ret; +} + +void nn_plist_mergein_missing (nn_plist_t *a, const nn_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) +{ + plist_or_xqos_mergein_missing (a, b, offsetof (nn_plist_t, qos), 0, mask); } void nn_plist_copy (nn_plist_t *dst, const nn_plist_t *src) { nn_plist_init_empty (dst); - nn_plist_mergein_missing (dst, src); + nn_plist_mergein_missing (dst, src, ~(uint64_t)0, ~(uint64_t)0); } nn_plist_t *nn_plist_dup (const nn_plist_t *src) @@ -2242,28 +1992,45 @@ nn_plist_t *nn_plist_dup (const nn_plist_t *src) return dst; } -static dds_return_t final_validation (nn_plist_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid) +void nn_plist_init_empty (nn_plist_t *dest) { +#ifndef NDEBUG + memset (dest, 0, sizeof (*dest)); +#endif + dest->present = dest->aliased = 0; + nn_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) +{ + /* input is const, but we need to validate the combination of + history & resource limits: so use a copy of those two policies */ + dds_history_qospolicy_t tmphist = { + .kind = DDS_HISTORY_KEEP_LAST, + .depth = 1 + }; + dds_resource_limits_qospolicy_t tmpreslim = { + .max_samples = DDS_LENGTH_UNLIMITED, + .max_instances = DDS_LENGTH_UNLIMITED, + .max_samples_per_instance = DDS_LENGTH_UNLIMITED + }; + dds_return_t res; + /* Resource limits & history are related, so if only one is given, set the other to the default, claim it has been provided & validate the combination. They can't be changed afterward, so this is a reasonable interpretation. */ - if ((dest->qos.present & QP_HISTORY) && !(dest->qos.present & QP_RESOURCE_LIMITS)) + if (dest->present & QP_HISTORY) + tmphist = dest->history; + if (dest->present & QP_RESOURCE_LIMITS) + tmpreslim = dest->resource_limits; + if ((res = validate_history_and_resource_limits (&tmphist, &tmpreslim)) < 0) + return res; + + if ((dest->present & QP_DEADLINE) && (dest->present & QP_TIME_BASED_FILTER)) { - default_resource_limits (&dest->qos.resource_limits); - dest->qos.present |= QP_RESOURCE_LIMITS; - } - if (!(dest->qos.present & QP_HISTORY) && (dest->qos.present & QP_RESOURCE_LIMITS)) - { - default_history (&dest->qos.history); - dest->qos.present |= QP_HISTORY; - } - if (dest->qos.present & (QP_HISTORY | QP_RESOURCE_LIMITS)) - { - dds_return_t res; - assert ((dest->qos.present & (QP_HISTORY | QP_RESOURCE_LIMITS)) == (QP_HISTORY | QP_RESOURCE_LIMITS)); - if ((res = validate_history_and_resource_limits (&dest->qos.history, &dest->qos.resource_limits)) < 0) - return res; + if (dest->deadline.deadline < dest->time_based_filter.minimum_separation) + return DDS_RETCODE_INCONSISTENT_POLICY; } /* Durability service is sort-of accepted if all zeros, but only @@ -2272,14 +2039,19 @@ static dds_return_t final_validation (nn_plist_t *dest, nn_protocol_version_t pr parsed we know the setting of the durability QoS (the default is always VOLATILE), and hence we can verify that the setting is valid or delete it if irrelevant. */ - if (dest->qos.present & QP_DURABILITY_SERVICE) + if (dursvc_accepted_allzero) + *dursvc_accepted_allzero = false; + if (dest->present & QP_DURABILITY_SERVICE) { - const dds_durability_kind_t durkind = (dest->qos.present & QP_DURABILITY) ? dest->qos.durability.kind : DDS_DURABILITY_VOLATILE; + const dds_durability_kind_t durkind = (dest->present & QP_DURABILITY) ? dest->durability.kind : DDS_DURABILITY_VOLATILE; bool acceptzero; + bool check_dursvc = true; /* Use a somewhat convoluted rule to decide whether or not to "accept" an all-zero durability service setting, to find a reasonable mix of strictness and compatibility */ - if (protocol_version_is_newer (protocol_version)) + if (dursvc_accepted_allzero == NULL) + acceptzero = false; + else if (protocol_version_is_newer (protocol_version)) acceptzero = true; else if (NN_STRICT_P) acceptzero = vendor_is_twinoaks (vendorid); @@ -2289,33 +2061,29 @@ static dds_return_t final_validation (nn_plist_t *dest, nn_protocol_version_t pr { case DDS_DURABILITY_VOLATILE: case DDS_DURABILITY_TRANSIENT_LOCAL: - /* pretend we never saw it if it is all zero */ - if (acceptzero && durability_service_qospolicy_allzero (&dest->qos.durability_service)) - dest->qos.present &= ~QP_DURABILITY_SERVICE; + /* let caller now if we accepted all-zero: our input is const and we can't patch it out */ + if (acceptzero && durability_service_qospolicy_allzero (&dest->durability_service) && dursvc_accepted_allzero) + { + *dursvc_accepted_allzero = true; + check_dursvc = false; + } break; case DDS_DURABILITY_TRANSIENT: case DDS_DURABILITY_PERSISTENT: break; } - /* if it is still present, it must be valid */ - if (dest->qos.present & QP_DURABILITY_SERVICE) - { - dds_return_t res; - if ((res = validate_durability_service_qospolicy (&dest->qos.durability_service)) < 0) - return res; - } + if (check_dursvc && (res = validate_durability_service_qospolicy_acceptzero (&dest->durability_service, false)) < 0) + return res; } return 0; } -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 -) +static dds_return_t final_validation (nn_plist_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid, bool *dursvc_accepted_allzero) +{ + return final_validation_qos (&dest->qos, protocol_version, vendorid, dursvc_accepted_allzero); +} + +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) { const unsigned char *pl; struct dd dd; @@ -2351,7 +2119,6 @@ dds_return_t nn_plist_init_frommsg return DDS_RETCODE_BAD_PARAMETER; } nn_plist_init_empty (dest); - dest->unalias_needs_bswap = dd.bswap; dest_tmp.present = 0; DDS_LOG(DDS_LC_PLIST, "NN_PLIST_INIT (bswap %d)\n", dd.bswap); @@ -2371,14 +2138,19 @@ dds_return_t nn_plist_init_frommsg if (pid == PID_SENTINEL) { /* Sentinel terminates list, the length is ignored, DDSI 9.4.2.11. */ + bool dursvc_accepted_allzero; DDS_LOG(DDS_LC_PLIST, "%4"PRIx32" PID %"PRIx16"\n", (uint32_t) (pl - src->buf), pid); - if ((res = final_validation (dest, src->protocol_version, src->vendorid)) < 0) + if ((res = final_validation (dest, src->protocol_version, src->vendorid, &dursvc_accepted_allzero)) < 0) { nn_plist_fini (dest); - return DDS_RETCODE_BAD_PARAMETER; + return res; } else { + /* If we accepted an all-zero durability service, that's awfully friendly of ours, + but we'll pretend we never saw it */ + if (dursvc_accepted_allzero) + dest->qos.present &= ~QP_DURABILITY_SERVICE; pl += sizeof (*par); if (nextafterplist) *nextafterplist = (char *) pl; @@ -2510,16 +2282,16 @@ unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn } else { + /* can only represent 2 LSBs of statusinfo in "dest", so if others are set, + mark it as a "complex_qos" and accept the hit of parsing the data completely. */ uint32_t stinfo = fromBE4u (*((uint32_t *) pl)); - uint32_t stinfox = (length < 8 || !vendor_is_eclipse_or_opensplice(src->vendorid)) ? 0 : fromBE4u (*((uint32_t *) pl + 1)); -#if (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER) != 3 -#error "expected dispose/unregister to be in lowest 2 bits" -#endif dest->statusinfo = stinfo & 3u; - if ((stinfo & ~3u) || stinfox) + if ((stinfo & ~3u)) dest->complex_qos = 1; } break; + case PID_KEYHASH: + break; default: DDS_LOG(DDS_LC_PLIST, "(pid=%"PRIx16" complex_qos=1)", pid); dest->complex_qos = 1; @@ -2691,7 +2463,6 @@ void nn_xqos_init_default_subscriber (dds_qos_t *xqos) xqos->present |= QP_PRISMTECH_ENTITY_FACTORY; xqos->entity_factory.autoenable_created_entities = 1; - xqos->present |= QP_PARTITION; xqos->partition.n = 0; xqos->partition.strs = NULL; @@ -2709,146 +2480,20 @@ void nn_xqos_init_default_publisher (dds_qos_t *xqos) xqos->partition.strs = NULL; } -void nn_xqos_mergein_missing (dds_qos_t *a, const dds_qos_t *b) -{ - /* Adds QoS's from B to A (duplicating memory) (only those not - present in A, obviously) */ - - /* Simple ones (that don't need memory): everything but topic, type, - partition, {group,topic|user} data */ -#define CQ(fl_, name_) do { \ - if (!(a->present & QP_##fl_) && (b->present & QP_##fl_)) { \ - a->name_ = b->name_; \ - a->present |= QP_##fl_; \ - } \ - } while (0) - CQ (PRESENTATION, presentation); - CQ (DURABILITY, durability); - CQ (DURABILITY_SERVICE, durability_service); - CQ (DEADLINE, deadline); - CQ (LATENCY_BUDGET, latency_budget); - CQ (LIVELINESS, liveliness); - CQ (RELIABILITY, reliability); - CQ (DESTINATION_ORDER, destination_order); - CQ (HISTORY, history); - CQ (RESOURCE_LIMITS, resource_limits); - CQ (TRANSPORT_PRIORITY, transport_priority); - CQ (LIFESPAN, lifespan); - CQ (OWNERSHIP, ownership); - CQ (OWNERSHIP_STRENGTH, ownership_strength); - CQ (TIME_BASED_FILTER, time_based_filter); - CQ (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle); - CQ (PRISMTECH_WRITER_DATA_LIFECYCLE, writer_data_lifecycle); - CQ (PRISMTECH_READER_LIFESPAN, reader_lifespan); - CQ (PRISMTECH_ENTITY_FACTORY, entity_factory); - CQ (CYCLONE_IGNORELOCAL, ignorelocal); -#undef CQ - - /* For allocated ones it is Not strictly necessary to use tmp, as - a->name_ may only be interpreted if the present flag is set, but - this keeps a clean on failure and may thereby save us from a - nasty surprise. */ -#define CQ(fl_, name_, type_, tmp_type_) do { \ - if (!(a->present & QP_##fl_) && (b->present & QP_##fl_)) { \ - tmp_type_ tmp = b->name_; \ - unalias_##type_ (&tmp, -1); \ - a->name_ = tmp; \ - a->present |= QP_##fl_; \ - } \ - } while (0) - CQ (GROUP_DATA, group_data, octetseq, ddsi_octetseq_t); - CQ (TOPIC_DATA, topic_data, octetseq, ddsi_octetseq_t); - CQ (USER_DATA, user_data, octetseq, ddsi_octetseq_t); - CQ (TOPIC_NAME, topic_name, string, char *); - CQ (TYPE_NAME, type_name, string, char *); - CQ (RTI_TYPECODE, rti_typecode, octetseq, ddsi_octetseq_t); -#undef CQ - if (!(a->present & QP_PRISMTECH_SUBSCRIPTION_KEYS) && (b->present & QP_PRISMTECH_SUBSCRIPTION_KEYS)) - { - a->subscription_keys.use_key_list = b->subscription_keys.use_key_list; - duplicate_stringseq (&a->subscription_keys.key_list, &b->subscription_keys.key_list); - a->present |= QP_PRISMTECH_SUBSCRIPTION_KEYS; - } - if (!(a->present & QP_PARTITION) && (b->present & QP_PARTITION)) - { - duplicate_stringseq (&a->partition, &b->partition); - a->present |= QP_PARTITION; - } -} - void nn_xqos_copy (dds_qos_t *dst, const dds_qos_t *src) { nn_xqos_init_empty (dst); - nn_xqos_mergein_missing (dst, src); -} - -void nn_xqos_unalias (dds_qos_t *xqos) -{ - DDS_LOG(DDS_LC_PLIST, "NN_XQOS_UNALIAS\n"); -#define Q(name_, func_, field_) do { \ - if ((xqos->present & QP_##name_) && (xqos->aliased & QP_##name_)) { \ - unalias_##func_ (&xqos->field_, -1); \ - xqos->aliased &= ~QP_##name_; \ - } \ - } while (0) - Q (GROUP_DATA, octetseq, group_data); - Q (TOPIC_DATA, octetseq, topic_data); - Q (USER_DATA, octetseq, user_data); - Q (TOPIC_NAME, string, topic_name); - Q (TYPE_NAME, string, type_name); - Q (PARTITION, stringseq, partition); - Q (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys_qospolicy, subscription_keys); - Q (RTI_TYPECODE, octetseq, rti_typecode); -#undef Q - assert (xqos->aliased == 0); + nn_xqos_mergein_missing (dst, src, ~(uint64_t)0); } void nn_xqos_fini (dds_qos_t *xqos) { - struct t { uint64_t fl; size_t off; }; - static const struct t qos_simple[] = { - { QP_GROUP_DATA, offsetof (dds_qos_t, group_data.value) }, - { QP_TOPIC_DATA, offsetof (dds_qos_t, topic_data.value) }, - { QP_USER_DATA, offsetof (dds_qos_t, user_data.value) }, - { QP_TOPIC_NAME, offsetof (dds_qos_t, topic_name) }, - { QP_TYPE_NAME, offsetof (dds_qos_t, type_name) }, - { QP_RTI_TYPECODE, offsetof (dds_qos_t, rti_typecode.value) } - }; - DDS_LOG(DDS_LC_PLIST, "NN_XQOS_FINI\n"); - for (size_t i = 0; i < sizeof (qos_simple) / sizeof (*qos_simple); i++) - { - if ((xqos->present & qos_simple[i].fl) && !(xqos->aliased & qos_simple[i].fl)) - { - void **pp = (void **) ((char *) xqos + qos_simple[i].off); - DDS_LOG(DDS_LC_PLIST, "NN_XQOS_FINI free %p\n", *pp); - ddsrt_free (*pp); - } - } - if (xqos->present & QP_PARTITION) - { - if (!(xqos->aliased & QP_PARTITION)) - { - free_stringseq (&xqos->partition); - } - else - { - /* until proper message buffers arrive */ - DDS_LOG(DDS_LC_PLIST, "NN_XQOS_FINI free %p\n", (void *) xqos->partition.strs); - ddsrt_free (xqos->partition.strs); - } - } - if (xqos->present & QP_PRISMTECH_SUBSCRIPTION_KEYS) - { - if (!(xqos->aliased & QP_PRISMTECH_SUBSCRIPTION_KEYS)) - free_stringseq (&xqos->subscription_keys.key_list); - else - { - /* until proper message buffers arrive */ - DDS_LOG(DDS_LC_PLIST, "NN_XQOS_FINI free %p\n", (void *) xqos->subscription_keys.key_list.strs); - ddsrt_free (xqos->subscription_keys.key_list.strs); - } - } - xqos->present = 0; + plist_or_xqos_fini (xqos, offsetof (nn_plist_t, qos)); +} + +void nn_xqos_unalias (dds_qos_t *xqos) +{ + plist_or_xqos_unalias (xqos, offsetof (nn_plist_t, qos)); } dds_qos_t * nn_xqos_dup (const dds_qos_t *src) @@ -2859,33 +2504,6 @@ dds_qos_t * nn_xqos_dup (const dds_qos_t *src) return dst; } -static int octetseqs_differ (const ddsi_octetseq_t *a, const ddsi_octetseq_t *b) -{ - return (a->length != b->length || memcmp (a->value, b->value, a->length) != 0); -} - -static int stringseqs_differ (const ddsi_stringseq_t *a, const ddsi_stringseq_t *b) -{ - uint32_t i; - if (a->n != b->n) - return 1; - for (i = 0; i < a->n; i++) - if (strcmp (a->strs[i], b->strs[i])) - return 1; - return 0; -} - -static int histories_differ (const dds_history_qospolicy_t *a, const dds_history_qospolicy_t *b) -{ - return (a->kind != b->kind || (a->kind == DDS_HISTORY_KEEP_LAST && a->depth != b->depth)); -} - -static int resource_limits_differ (const dds_resource_limits_qospolicy_t *a, const dds_resource_limits_qospolicy_t *b) -{ - return (a->max_samples != b->max_samples || a->max_instances != b->max_instances || - a->max_samples_per_instance != b->max_samples_per_instance); -} - static int partition_is_default (const dds_partition_qospolicy_t *a) { uint32_t i; @@ -2909,9 +2527,11 @@ static int partitions_equal_n2 (const dds_partition_qospolicy_t *a, const dds_pa return 1; } -static int strcmp_wrapper (const void *a, const void *b) +static int strcmp_wrapper (const void *va, const void *vb) { - return strcmp (a, b); + char const * const *a = va; + char const * const *b = vb; + return strcmp (*a, *b); } static int partitions_equal_nlogn (const dds_partition_qospolicy_t *a, const dds_partition_qospolicy_t *b) @@ -2929,7 +2549,7 @@ static int partitions_equal_nlogn (const dds_partition_qospolicy_t *a, const dds tab[i] = a->strs[i]; qsort (tab, a->n, sizeof (*tab), strcmp_wrapper); for (i = 0; i < b->n; i++) - if (bsearch (b->strs[i], tab, a->n, sizeof (*tab), strcmp_wrapper) == NULL) + if (bsearch (&b->strs[i], tab, a->n, sizeof (*tab), strcmp_wrapper) == NULL) { equal = 0; break; @@ -2977,289 +2597,16 @@ static int partitions_equal (const dds_partition_qospolicy_t *a, const dds_parti } } -uint64_t nn_xqos_delta (const dds_qos_t *a, const dds_qos_t *b, uint64_t mask) -{ - /* Returns QP_... set for RxO settings where a differs from b; if - present in a but not in b (or in b but not in a) it counts as a - difference. */ - uint64_t delta = (a->present ^ b->present) & mask; - uint64_t check = (a->present & b->present) & mask; - if (check & QP_TOPIC_NAME) { - if (strcmp (a->topic_name, b->topic_name)) - delta |= QP_TOPIC_NAME; - } - if (check & QP_TYPE_NAME) { - if (strcmp (a->type_name, b->type_name)) - delta |= QP_TYPE_NAME; - } - if (check & QP_PRESENTATION) { - if (a->presentation.access_scope != b->presentation.access_scope || - a->presentation.coherent_access != b->presentation.coherent_access || - a->presentation.ordered_access != b->presentation.ordered_access) - delta |= QP_PRESENTATION; - } - if (check & QP_PARTITION) { - if (!partitions_equal (&a->partition, &b->partition)) - delta |= QP_PARTITION; - } - if (check & QP_GROUP_DATA) { - if (octetseqs_differ (&a->group_data, &b->group_data)) - delta |= QP_GROUP_DATA; - } - if (check & QP_TOPIC_DATA) { - if (octetseqs_differ (&a->topic_data, &b->topic_data)) - delta |= QP_TOPIC_DATA; - } - if (check & QP_DURABILITY) { - if (a->durability.kind != b->durability.kind) - delta |= QP_DURABILITY; - } - if (check & QP_DURABILITY_SERVICE) - { - const dds_durability_service_qospolicy_t *qa = &a->durability_service; - const dds_durability_service_qospolicy_t *qb = &b->durability_service; - if (qa->service_cleanup_delay != qb->service_cleanup_delay || - histories_differ (&qa->history, &qb->history) || - resource_limits_differ (&qa->resource_limits, &qb->resource_limits)) - delta |= QP_DURABILITY_SERVICE; - } - if (check & QP_DEADLINE) { - if (a->deadline.deadline != b->deadline.deadline) - delta |= QP_DEADLINE; - } - if (check & QP_LATENCY_BUDGET) { - if (a->latency_budget.duration != b->latency_budget.duration) - delta |= QP_LATENCY_BUDGET; - } - if (check & QP_LIVELINESS) { - if (a->liveliness.kind != b->liveliness.kind || a->liveliness.lease_duration != b->liveliness.lease_duration) - delta |= QP_LIVELINESS; - } - if (check & QP_RELIABILITY) { - if (a->reliability.kind != b->reliability.kind || a->reliability.max_blocking_time != b->reliability.max_blocking_time) - delta |= QP_RELIABILITY; - } - if (check & QP_DESTINATION_ORDER) { - if (a->destination_order.kind != b->destination_order.kind) - delta |= QP_DESTINATION_ORDER; - } - if (check & QP_HISTORY) { - if (histories_differ (&a->history, &b->history)) - delta |= QP_HISTORY; - } - if (check & QP_RESOURCE_LIMITS) { - if (resource_limits_differ (&a->resource_limits, &b->resource_limits)) - delta |= QP_RESOURCE_LIMITS; - } - if (check & QP_TRANSPORT_PRIORITY) { - if (a->transport_priority.value != b->transport_priority.value) - delta |= QP_TRANSPORT_PRIORITY; - } - if (check & QP_LIFESPAN) { - if (a->lifespan.duration != b->lifespan.duration) - delta |= QP_LIFESPAN; - } - if (check & QP_USER_DATA) { - if (octetseqs_differ (&a->user_data, &b->user_data)) - delta |= QP_USER_DATA; - } - if (check & QP_OWNERSHIP) { - if (a->ownership.kind != b->ownership.kind) - delta |= QP_OWNERSHIP; - } - if (check & QP_OWNERSHIP_STRENGTH) { - if (a->ownership_strength.value != b->ownership_strength.value) - delta |= QP_OWNERSHIP_STRENGTH; - } - if (check & QP_TIME_BASED_FILTER) { - if (a->time_based_filter.minimum_separation != b->time_based_filter.minimum_separation) - delta |= QP_TIME_BASED_FILTER; - } - if (check & QP_PRISMTECH_READER_DATA_LIFECYCLE) { - if (a->reader_data_lifecycle.autopurge_disposed_samples_delay != b->reader_data_lifecycle.autopurge_disposed_samples_delay || - a->reader_data_lifecycle.autopurge_nowriter_samples_delay != b->reader_data_lifecycle.autopurge_nowriter_samples_delay) - delta |= QP_PRISMTECH_READER_DATA_LIFECYCLE; - } - if (check & QP_PRISMTECH_WRITER_DATA_LIFECYCLE) { - if (a->writer_data_lifecycle.autodispose_unregistered_instances != - b->writer_data_lifecycle.autodispose_unregistered_instances) - delta |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE; - } - if (check & QP_PRISMTECH_READER_LIFESPAN) { - /* Note: the conjunction need not test both a & b for having use_lifespan set */ - if (a->reader_lifespan.use_lifespan != b->reader_lifespan.use_lifespan || - (a->reader_lifespan.use_lifespan && b->reader_lifespan.use_lifespan && - a->reader_lifespan.duration != b->reader_lifespan.duration)) - delta |= QP_PRISMTECH_READER_LIFESPAN; - } - if (check & QP_PRISMTECH_SUBSCRIPTION_KEYS) { - /* Note: the conjunction need not test both a & b for having use_lifespan set */ - if (a->subscription_keys.use_key_list != b->subscription_keys.use_key_list || - (a->subscription_keys.use_key_list && b->subscription_keys.use_key_list && - stringseqs_differ (&a->subscription_keys.key_list, &b->subscription_keys.key_list))) - delta |= QP_PRISMTECH_SUBSCRIPTION_KEYS; - } - if (check & QP_PRISMTECH_ENTITY_FACTORY) { - if (a->entity_factory.autoenable_created_entities != - b->entity_factory.autoenable_created_entities) - delta |= QP_PRISMTECH_ENTITY_FACTORY; - } - if (check & QP_RTI_TYPECODE) { - if (octetseqs_differ (&a->rti_typecode, &b->rti_typecode)) - delta |= QP_RTI_TYPECODE; - } - if (check & QP_CYCLONE_IGNORELOCAL) { - if (a->ignorelocal.value != b->ignorelocal.value) - delta |= QP_CYCLONE_IGNORELOCAL; - } - return delta; -} - /*************************/ void nn_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, uint64_t wanted) { - /* Returns new nn_xmsg pointer (currently, reallocs may happen) */ - - uint64_t w = xqos->present & wanted; - char *tmp; -#define SIMPLE(name_, prefix_, field_) \ - do { \ - if (w & QP_##name_) { \ - tmp = nn_xmsg_addpar (m, PID_##name_, sizeof (xqos->field_)); \ - *((prefix_##_##field_##_qospolicy_t *) tmp) = xqos->field_; \ - } \ - } while (0) -#define FUNC_BY_REF(name_, field_, func_) \ - do { \ - if (w & QP_##name_) { \ - nn_xmsg_addpar_##func_ (m, PID_##name_, &xqos->field_); \ - } \ - } while (0) -#define FUNC_BY_VAL(name_, field_, func_) \ - do { \ - if (w & QP_##name_) { \ - nn_xmsg_addpar_##func_ (m, PID_##name_, xqos->field_); \ - } \ - } while (0) - - FUNC_BY_VAL (TOPIC_NAME, topic_name, string); - FUNC_BY_VAL (TYPE_NAME, type_name, string); - SIMPLE (PRESENTATION, dds, presentation); - FUNC_BY_REF (PARTITION, partition, stringseq); - FUNC_BY_REF (GROUP_DATA, group_data, octetseq); - FUNC_BY_REF (TOPIC_DATA, topic_data, octetseq); - SIMPLE (DURABILITY, dds, durability); - FUNC_BY_REF (DURABILITY_SERVICE, durability_service, durability_service); - FUNC_BY_VAL (DEADLINE, deadline.deadline, duration); - FUNC_BY_VAL (LATENCY_BUDGET, latency_budget.duration, duration); - FUNC_BY_REF (LIVELINESS, liveliness, liveliness); - FUNC_BY_REF (RELIABILITY, reliability, reliability); - SIMPLE (DESTINATION_ORDER, dds, destination_order); - SIMPLE (HISTORY, dds, history); - SIMPLE (RESOURCE_LIMITS, dds, resource_limits); - SIMPLE (TRANSPORT_PRIORITY, dds, transport_priority); - FUNC_BY_VAL (LIFESPAN, lifespan.duration, duration); - FUNC_BY_REF (USER_DATA, user_data, octetseq); - SIMPLE (OWNERSHIP, dds, ownership); - SIMPLE (OWNERSHIP_STRENGTH, dds, ownership_strength); - FUNC_BY_VAL (TIME_BASED_FILTER, time_based_filter.minimum_separation, duration); - FUNC_BY_REF (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle, reader_data_lifecycle); - SIMPLE (PRISMTECH_WRITER_DATA_LIFECYCLE, dds, writer_data_lifecycle); - FUNC_BY_REF (PRISMTECH_READER_LIFESPAN, reader_lifespan, reader_lifespan); - FUNC_BY_REF (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys, subscription_keys); - SIMPLE (PRISMTECH_ENTITY_FACTORY, dds, entity_factory); - FUNC_BY_REF (RTI_TYPECODE, rti_typecode, octetseq); - /* CYCLONE_IGNORELOCAL is not visible on the wire */ -#undef FUNC_BY_REF -#undef FUNC_BY_VAL -#undef SIMPLE -} - -static void add_locators (struct nn_xmsg *m, uint64_t present, uint64_t flag, const nn_locators_t *ls, nn_parameterid_t pid) -{ - const struct nn_locators_one *l; - if (present & flag) - { - for (l = ls->first; l != NULL; l = l->next) - { - char *tmp = nn_xmsg_addpar (m, pid, sizeof (nn_locator_t)); - memcpy (tmp, &l->loc, sizeof (nn_locator_t)); - } - } + plist_or_xqos_addtomsg (m, xqos, offsetof (struct nn_plist, qos), 0, wanted); } void nn_plist_addtomsg (struct nn_xmsg *m, const nn_plist_t *ps, uint64_t pwanted, uint64_t qwanted) { - /* Returns new nn_xmsg pointer (currently, reallocs may happen), or NULL - on out-of-memory. (In which case the original nn_xmsg is freed, cos - that is then required anyway */ - uint64_t w = ps->present & pwanted; - char *tmp; -#define SIMPLE_TYPE(name_, field_, type_) \ - do { \ - if (w & PP_##name_) { \ - tmp = nn_xmsg_addpar (m, PID_##name_, sizeof (ps->field_)); \ - *((type_ *) tmp) = ps->field_; \ - } \ - } while (0) -#define FUNC_BY_VAL(name_, field_, func_) \ - do { \ - if (w & PP_##name_) { \ - nn_xmsg_addpar_##func_ (m, PID_##name_, ps->field_); \ - } \ - } while (0) -#define FUNC_BY_REF(name_, field_, func_) \ - do { \ - if (w & PP_##name_) { \ - nn_xmsg_addpar_##func_ (m, PID_##name_, &ps->field_); \ - } \ - } while (0) - - nn_xqos_addtomsg (m, &ps->qos, qwanted); - SIMPLE_TYPE (PROTOCOL_VERSION, protocol_version, nn_protocol_version_t); - SIMPLE_TYPE (VENDORID, vendorid, nn_vendorid_t); - - add_locators (m, ps->present, PP_UNICAST_LOCATOR, &ps->unicast_locators, PID_UNICAST_LOCATOR); - add_locators (m, ps->present, PP_MULTICAST_LOCATOR, &ps->multicast_locators, PID_MULTICAST_LOCATOR); - add_locators (m, ps->present, PP_DEFAULT_UNICAST_LOCATOR, &ps->default_unicast_locators, PID_DEFAULT_UNICAST_LOCATOR); - add_locators (m, ps->present, PP_DEFAULT_MULTICAST_LOCATOR, &ps->default_multicast_locators, PID_DEFAULT_MULTICAST_LOCATOR); - add_locators (m, ps->present, PP_METATRAFFIC_UNICAST_LOCATOR, &ps->metatraffic_unicast_locators, PID_METATRAFFIC_UNICAST_LOCATOR); - add_locators (m, ps->present, PP_METATRAFFIC_MULTICAST_LOCATOR, &ps->metatraffic_multicast_locators, PID_METATRAFFIC_MULTICAST_LOCATOR); - - SIMPLE_TYPE (EXPECTS_INLINE_QOS, expects_inline_qos, unsigned char); - FUNC_BY_VAL (PARTICIPANT_LEASE_DURATION, participant_lease_duration, duration); - FUNC_BY_REF (PARTICIPANT_GUID, participant_guid, guid); - SIMPLE_TYPE (BUILTIN_ENDPOINT_SET, builtin_endpoint_set, unsigned); - SIMPLE_TYPE (KEYHASH, keyhash, nn_keyhash_t); - if (w & PP_STATUSINFO) - nn_xmsg_addpar_statusinfo (m, ps->statusinfo); - SIMPLE_TYPE (COHERENT_SET, coherent_set_seqno, nn_sequence_number_t); - if (! NN_PEDANTIC_P) - FUNC_BY_REF (ENDPOINT_GUID, endpoint_guid, guid); - else - { - if (w & PP_ENDPOINT_GUID) - { - nn_xmsg_addpar_guid (m, PID_PRISMTECH_ENDPOINT_GUID, &ps->endpoint_guid); - } - } - FUNC_BY_REF (GROUP_GUID, group_guid, guid); - SIMPLE_TYPE (PRISMTECH_BUILTIN_ENDPOINT_SET, prismtech_builtin_endpoint_set, unsigned); - FUNC_BY_REF (PRISMTECH_PARTICIPANT_VERSION_INFO, prismtech_participant_version_info, parvinfo); - FUNC_BY_VAL (ENTITY_NAME, entity_name, string); - FUNC_BY_VAL (PRISMTECH_NODE_NAME, node_name, string); - FUNC_BY_VAL (PRISMTECH_EXEC_NAME, exec_name, string); - SIMPLE_TYPE (PRISMTECH_PROCESS_ID, process_id, unsigned); - SIMPLE_TYPE (PRISMTECH_SERVICE_TYPE, service_type, unsigned); - FUNC_BY_VAL (PRISMTECH_TYPE_DESCRIPTION, type_description, string); - FUNC_BY_REF (PRISMTECH_EOTINFO, eotinfo, eotinfo); -#ifdef DDSI_INCLUDE_SSM - SIMPLE_TYPE (READER_FAVOURS_SSM, reader_favours_ssm, nn_reader_favours_ssm_t); -#endif -#undef FUNC_BY_REF -#undef FUNC_BY_VAL -#undef SIMPLE + plist_or_xqos_addtomsg (m, ps, 0, pwanted, qwanted); } /*************************/ @@ -3267,7 +2614,7 @@ 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) { uint32_t m; - for (m = 0; m < n && xs[m] != '"' && isprint (xs[m]); m++) + for (m = 0; m < n && xs[m] != '"' && isprint (xs[m]) && xs[m] < 127; m++) ; return m; } @@ -3278,10 +2625,10 @@ static void log_octetseq (uint32_t cat, 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) + uint32_t m = isprint_runlen (n - i, xs); + if (m >= 4 || (i == 0 && m == n)) { - DDS_LOG(cat, "%s\"%*.*s\"", i == 0 ? "" : ",", m, m, xs); + DDS_LOG (cat, "%s\"%*.*s\"", i == 0 ? "" : ",", m, m, xs); xs += m; i += m; } @@ -3291,7 +2638,7 @@ static void log_octetseq (uint32_t cat, uint32_t n, const unsigned char *xs) m = 1; while (m--) { - DDS_LOG(cat, "%s%u", i == 0 ? "" : ",", *xs++); + DDS_LOG (cat, "%s%u", i == 0 ? "" : ",", *xs++); i++; } } @@ -3369,11 +2716,6 @@ void nn_log_xqos (uint32_t cat, const dds_qos_t *xqos) DDS_LOG(cat, "}}"); }); DO (PRISMTECH_ENTITY_FACTORY, { LOGB1 ("entity_factory=%u", xqos->entity_factory.autoenable_created_entities); }); - DO (RTI_TYPECODE, { - LOGB1 ("rti_typecode=%"PRIu32"<", xqos->rti_typecode.length); - log_octetseq (cat, xqos->rti_typecode.length, xqos->rti_typecode.value); - DDS_LOG(cat, ">"); - }); DO (CYCLONE_IGNORELOCAL, { LOGB1 ("ignorelocal=%u", xqos->ignorelocal.value); }); #undef PRINTARG_DUR diff --git a/src/core/ddsi/src/q_qosmatch.c b/src/core/ddsi/src/q_qosmatch.c index 70b02fe..721a010 100644 --- a/src/core/ddsi/src/q_qosmatch.c +++ b/src/core/ddsi/src/q_qosmatch.c @@ -64,66 +64,65 @@ int partitions_match_p (const dds_qos_t *a, const dds_qos_t *b) } } -static bool qos_match_internal_p (const dds_qos_t *rd, const dds_qos_t *wr, dds_qos_policy_id_t *reason) ddsrt_nonnull_all; - -static bool qos_match_internal_p (const dds_qos_t *rd, const dds_qos_t *wr, dds_qos_policy_id_t *reason) +bool qos_match_mask_p (const dds_qos_t *rd, const dds_qos_t *wr, uint64_t mask, dds_qos_policy_id_t *reason) { #ifndef NDEBUG - unsigned musthave = (QP_RXO_MASK | QP_PARTITION | QP_TOPIC_NAME | QP_TYPE_NAME); + unsigned musthave = (QP_RXO_MASK | QP_PARTITION | QP_TOPIC_NAME | QP_TYPE_NAME) & mask; assert ((rd->present & musthave) == musthave); assert ((wr->present & musthave) == musthave); #endif + mask &= rd->present & wr->present; *reason = DDS_INVALID_QOS_POLICY_ID; - if (strcmp (rd->topic_name, wr->topic_name) != 0) + if ((mask & QP_TOPIC_NAME) && strcmp (rd->topic_name, wr->topic_name) != 0) return false; - if (strcmp (rd->type_name, wr->type_name) != 0) + if ((mask & QP_TYPE_NAME) && strcmp (rd->type_name, wr->type_name) != 0) return false; - if (rd->reliability.kind > wr->reliability.kind) { + if ((mask & QP_RELIABILITY) && rd->reliability.kind > wr->reliability.kind) { *reason = DDS_RELIABILITY_QOS_POLICY_ID; return false; } - if (rd->durability.kind > wr->durability.kind) { + if ((mask & QP_DURABILITY) && rd->durability.kind > wr->durability.kind) { *reason = DDS_DURABILITY_QOS_POLICY_ID; return false; } - if (rd->presentation.access_scope > wr->presentation.access_scope) { + if ((mask & QP_PRESENTATION) && rd->presentation.access_scope > wr->presentation.access_scope) { *reason = DDS_PRESENTATION_QOS_POLICY_ID; return false; } - if (rd->presentation.coherent_access > wr->presentation.coherent_access) { + if ((mask & QP_PRESENTATION) && rd->presentation.coherent_access > wr->presentation.coherent_access) { *reason = DDS_PRESENTATION_QOS_POLICY_ID; return false; } - if (rd->presentation.ordered_access > wr->presentation.ordered_access) { + if ((mask & QP_PRESENTATION) && rd->presentation.ordered_access > wr->presentation.ordered_access) { *reason = DDS_PRESENTATION_QOS_POLICY_ID; return false; } - if (rd->deadline.deadline < wr->deadline.deadline) { + if ((mask & QP_DEADLINE) && rd->deadline.deadline < wr->deadline.deadline) { *reason = DDS_DEADLINE_QOS_POLICY_ID; return false; } - if (rd->latency_budget.duration < wr->latency_budget.duration) { + if ((mask & QP_LATENCY_BUDGET) && rd->latency_budget.duration < wr->latency_budget.duration) { *reason = DDS_LATENCYBUDGET_QOS_POLICY_ID; return false; } - if (rd->ownership.kind != wr->ownership.kind) { + if ((mask & QP_OWNERSHIP) && rd->ownership.kind != wr->ownership.kind) { *reason = DDS_OWNERSHIP_QOS_POLICY_ID; return false; } - if (rd->liveliness.kind > wr->liveliness.kind) { + if ((mask & QP_LIVELINESS) && rd->liveliness.kind > wr->liveliness.kind) { *reason = DDS_LIVELINESS_QOS_POLICY_ID; return false; } - if (rd->liveliness.lease_duration < wr->liveliness.lease_duration) { + if ((mask & QP_LIVELINESS) && rd->liveliness.lease_duration < wr->liveliness.lease_duration) { *reason = DDS_LIVELINESS_QOS_POLICY_ID; return false; } - if (rd->destination_order.kind > wr->destination_order.kind) { + if ((mask & QP_DESTINATION_ORDER) && rd->destination_order.kind > wr->destination_order.kind) { *reason = DDS_DESTINATIONORDER_QOS_POLICY_ID; return false; } - if (!partitions_match_p (rd, wr)) { + if ((mask & QP_PARTITION) && !partitions_match_p (rd, wr)) { *reason = DDS_PARTITION_QOS_POLICY_ID; return false; } @@ -133,5 +132,5 @@ static bool qos_match_internal_p (const dds_qos_t *rd, const dds_qos_t *wr, dds_ bool qos_match_p (const dds_qos_t *rd, const dds_qos_t *wr, dds_qos_policy_id_t *reason) { dds_qos_policy_id_t dummy; - return qos_match_internal_p (rd, wr, reason ? reason : &dummy); + return qos_match_mask_p (rd, wr, ~(uint64_t)0, reason ? reason : &dummy); } diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 60bdab7..8ec7197 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -1952,7 +1952,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st src.encoding = (msg->smhdr.flags & SMFLAG_ENDIANNESS) ? PL_CDR_LE : PL_CDR_BE; src.buf = NN_RMSG_PAYLOADOFF (fragchain->rmsg, qos_offset); src.bufsz = NN_RDATA_PAYLOAD_OFF (fragchain) - qos_offset; - if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH | PP_COHERENT_SET | PP_PRISMTECH_EOTINFO, 0, &src)) < 0) + if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH | PP_COHERENT_SET, 0, &src)) < 0) { if (plist_ret != DDS_RETCODE_UNSUPPORTED) DDS_WARNING ("data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n", @@ -1980,9 +1980,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st } /* Generate the DDS_SampleInfo (which is faked to some extent - because we don't actually have a data reader); also note that - the PRISMTECH_WRITER_INFO thing is completely meaningless to - us */ + because we don't actually have a data reader) */ struct ddsi_tkmap_instance * tk; if ((tk = ddsi_tkmap_lookup_instance_ref(payload)) != NULL) { diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 7e8d77d..8f942b0 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -1029,19 +1029,6 @@ void nn_xmsg_addpar_parvinfo (struct nn_xmsg *m, nn_parameterid_t pid, const str memcpy(ps->contents, pvi->internals, slen); } -void nn_xmsg_addpar_eotinfo (struct nn_xmsg *m, nn_parameterid_t pid, const struct nn_prismtech_eotinfo *txnid) -{ - uint32_t *pu, i; - pu = nn_xmsg_addpar (m, pid, 2 * sizeof (uint32_t) + txnid->n * sizeof (txnid->tids[0])); - pu[0] = txnid->transactionId; - pu[1] = txnid->n; - for (i = 0; i < txnid->n; i++) - { - pu[2*i + 2] = toBE4u (txnid->tids[i].writer_entityid.u); - pu[2*i + 3] = txnid->tids[i].transactionId; - } -} - /* XMSG_CHAIN ---------------------------------------------------------- Xpacks refer to xmsgs and need to release these after having been diff --git a/src/core/xtests/rhc_torture/rhc_torture.c b/src/core/xtests/rhc_torture/rhc_torture.c index f743c12..1254b5e 100644 --- a/src/core/xtests/rhc_torture/rhc_torture.c +++ b/src/core/xtests/rhc_torture/rhc_torture.c @@ -147,7 +147,7 @@ static struct proxy_writer *mkwr (bool auto_dispose) wr_iid = ddsi_iid_gen (); memset (pwr, 0, sizeof (*pwr)); nn_xqos_init_empty (xqos); - nn_xqos_mergein_missing (xqos, &gv.default_xqos_wr); + nn_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; @@ -170,7 +170,7 @@ static struct rhc *mkrhc (dds_reader *rd, dds_history_kind_t hk, int32_t hdepth, rqos.history.kind = hk; rqos.history.depth = hdepth; rqos.destination_order.kind = dok; - nn_xqos_mergein_missing (&rqos, &gv.default_xqos_rd); + nn_xqos_mergein_missing (&rqos, &gv.default_xqos_rd, ~(uint64_t)0); thread_state_awake (lookup_thread_state ()); rhc = dds_rhc_new (rd, mdtopic); dds_rhc_set_qos(rhc, &rqos); diff --git a/src/ddsrt/include/dds/ddsrt/attributes.h b/src/ddsrt/include/dds/ddsrt/attributes.h index c91584d..25ab3b1 100644 --- a/src/ddsrt/include/dds/ddsrt/attributes.h +++ b/src/ddsrt/include/dds/ddsrt/attributes.h @@ -105,4 +105,10 @@ # define ddsrt_attribute_assume_aligned(params) #endif +#if ddsrt_has_attribute(packed) +# define ddsrt_attribute_packed __attribute__ ((__packed__)) +#else +# define ddsrt_attribute_packed +#endif + #endif /* DDSRT_ATTRIBUTES_H */ diff --git a/src/mpt/tests/CMakeLists.txt b/src/mpt/tests/CMakeLists.txt index 91a9183..63e786b 100644 --- a/src/mpt/tests/CMakeLists.txt +++ b/src/mpt/tests/CMakeLists.txt @@ -16,4 +16,4 @@ if(MPT_ENABLE_SELFTEST) endif() add_subdirectory(basic) - +add_subdirectory(qosmatch) diff --git a/src/mpt/tests/qosmatch/CMakeLists.txt b/src/mpt/tests/qosmatch/CMakeLists.txt new file mode 100644 index 0000000..efa3324 --- /dev/null +++ b/src/mpt/tests/qosmatch/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# 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(${MPT_CMAKE}) + +set(sources + "procs/rw.c" + "qosmatch.c") + +add_compile_options("-I${PROJECT_SOURCE_DIR}/core/ddsi/include") +add_mpt_executable(mpt_qosmatch ${sources}) + +idlc_generate(mpt_qosmatch_rwdata_lib "procs/rwdata.idl") +target_link_libraries(mpt_qosmatch PRIVATE mpt_qosmatch_rwdata_lib) + diff --git a/src/mpt/tests/qosmatch/procs/rw.c b/src/mpt/tests/qosmatch/procs/rw.c new file mode 100644 index 0000000..b4720ff --- /dev/null +++ b/src/mpt/tests/qosmatch/procs/rw.c @@ -0,0 +1,376 @@ +#include +#include +#include + +#include "mpt/mpt.h" + +#include "dds/dds.h" +#include "rwdata.h" + +#include "dds/ddsrt/time.h" +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/sockets.h" +#include "dds/ddsrt/heap.h" + +#include "dds/ddsi/q_xqos.h" + +#define NPUB 10 +#define NWR_PUB 2 + +void rw_init (void) +{ +} + +void rw_fini (void) +{ +} + +static void setqos (dds_qos_t *q, size_t i, bool isrd, bool create) +{ + size_t psi = i - (i % NWR_PUB); + /* Participant, publisher & topic get created with i == 0, + so make sure those have some crazy data set. The writers + should inherit the topic and group data, but the user data + should be updated for each writer */ + if (create) + { + if (psi == 1) + { + dds_qset_userdata (q, NULL, 0); + dds_qset_topicdata (q, NULL, 0); + dds_qset_groupdata (q, NULL, 0); + } + else + { + char buf[20]; + snprintf (buf, sizeof (buf), "ud%zu%c", i, isrd ? 'r' : 'w'); + dds_qset_userdata (q, buf, strlen (buf)); + snprintf (buf, sizeof (buf), "td%zu", i); + dds_qset_topicdata (q, buf, strlen (buf)); + snprintf (buf, sizeof (buf), "gd%zu", psi); + dds_qset_groupdata (q, buf, strlen (buf)); + } + } + else + { + if (psi == 1) + { + dds_qset_userdata (q, NULL, 0); + dds_qset_topicdata (q, NULL, 0); + dds_qset_groupdata (q, NULL, 0); + } + else + { + char buf[20]; + snprintf (buf, sizeof (buf), "ud%zu%c", i, isrd ? 'r' : 'w'); + dds_qset_userdata (q, buf, strlen (buf)); + snprintf (buf, sizeof (buf), "td%zu", (size_t) 0); + dds_qset_topicdata (q, buf, strlen (buf)); + snprintf (buf, sizeof (buf), "gd%zu", psi); + dds_qset_groupdata (q, buf, strlen (buf)); + } + } + + /* Cyclone's accepting unimplemented QoS settings is a bug, but it does allow + us to feed it all kinds of nonsense and see whether discovery manages it */ + + /* this makes topic transient-local, keep-last 1 */ + dds_qset_durability (q, (dds_durability_kind_t) ((i + 1) % 4)); + dds_qset_history (q, (dds_history_kind_t) ((i + 1) % 2), (int32_t) (i + 1)); + dds_qset_resource_limits (q, (int32_t) i + 3, (int32_t) i + 2, (int32_t) i + 1); + dds_qset_presentation (q, (dds_presentation_access_scope_kind_t) ((psi + 1) % 3), 1, 1); + dds_qset_lifespan (q, INT64_C (23456789012345678) + (int32_t) i); + dds_qset_deadline (q, INT64_C (67890123456789012) + (int32_t) i); + 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); + dds_qset_liveliness (q, (dds_liveliness_kind_t) ((i + i) % 2), INT64_C (456789012345678901) + (int32_t) i); + dds_qset_time_based_filter (q, INT64_C (34567890123456789) + (int32_t) i); /* must be <= deadline */ + if (psi == 0) + dds_qset_partition1 (q, "p"); + else if (psi == 1) + dds_qset_partition (q, 0, NULL); + else + { + char **ps = ddsrt_malloc (psi * sizeof (*ps)); + for (size_t j = 0; j < psi; j++) + { + const size_t n = 40; + ps[j] = ddsrt_malloc (n); + snprintf (ps[j], n, "p%zu_%zu", psi, isrd ? (psi-j-1) : j); + } + dds_qset_partition (q, (uint32_t) psi, (const char **) ps); + for (size_t j = 0; j < psi; j++) + ddsrt_free (ps[j]); + ddsrt_free (ps); + } + dds_qset_reliability (q, (dds_reliability_kind_t) ((i + 1) % 2), INT64_C (890123456789012345) + (int32_t) i); + dds_qset_transport_priority (q, 0x23456701 + (int32_t) i); + dds_qset_destination_order (q, (dds_destination_order_kind_t) ((i + 1) % 2)); + dds_qset_writer_data_lifecycle (q, ((i + 1) % 2) != 0); + dds_qset_reader_data_lifecycle (q, INT64_C (41234567890123456) + (int32_t) i, INT64_C (912345678901234567) + (int32_t) i); + dds_qset_durability_service (q, INT64_C (123456789012345678) + (int32_t) i, (dds_history_kind_t) ((i + 1) % 2), (int32_t) (i + 1), (int32_t) i + 3, (int32_t) i + 2, (int32_t) i + 1); +} + +static bool pubsub_qos_eq_h (const dds_qos_t *a, dds_entity_t ent) +{ + dds_qos_t *b = dds_create_qos (); + 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); + if (delta) + { + DDS_LOG (DDS_LC_ERROR, "pub/sub: delta = %"PRIx64"\n", delta); + nn_log_xqos (DDS_LC_ERROR, a); DDS_LOG (DDS_LC_ERROR, "\n"); + nn_log_xqos (DDS_LC_ERROR, b); DDS_LOG (DDS_LC_ERROR, "\n"); + } + dds_delete_qos (b); + return delta == 0; +} + +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); +} + +static bool reader_qos_eq_h (const dds_qos_t *a, dds_entity_t ent) +{ + dds_qos_t *b = dds_create_qos (); + dds_get_qos (ent, b); + uint64_t delta = reader_qos_delta (a, b); + if (delta) + { + DDS_LOG (DDS_LC_ERROR, "reader: delta = %"PRIx64"\n", delta); + nn_log_xqos (DDS_LC_ERROR, a); DDS_LOG (DDS_LC_ERROR, "\n"); + nn_log_xqos (DDS_LC_ERROR, b); DDS_LOG (DDS_LC_ERROR, "\n"); + } + dds_delete_qos (b); + return delta == 0; +} + +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); +} + +static bool writer_qos_eq_h (const dds_qos_t *a, dds_entity_t ent) +{ + dds_qos_t *b = dds_create_qos (); + dds_get_qos (ent, b); + uint64_t delta = writer_qos_delta (a, b); + if (delta) + { + DDS_LOG (DDS_LC_ERROR, "writer: delta = %"PRIx64"\n", delta); + nn_log_xqos (DDS_LC_ERROR, a); DDS_LOG (DDS_LC_ERROR, "\n"); + nn_log_xqos (DDS_LC_ERROR, b); DDS_LOG (DDS_LC_ERROR, "\n"); + } + dds_delete_qos (b); + return delta == 0; +} + +MPT_ProcessEntry (rw_publisher, + MPT_Args (dds_domainid_t domainid, + const char *topic_name)) +{ + dds_entity_t dp; + dds_entity_t tp; + dds_entity_t pub[NPUB]; + dds_entity_t wr[NPUB][NWR_PUB]; + bool chk[NPUB][NWR_PUB] = { { false } }; + dds_return_t rc; + dds_qos_t *qos; + int id = (int) ddsrt_getpid (); + + printf ("=== [Publisher(%d)] Start(%d) ...\n", id, (int) domainid); + + qos = dds_create_qos (); + setqos (qos, 0, false, true); + dp = dds_create_participant (domainid, NULL, NULL); + MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp)); + + tp = dds_create_topic (dp, &RWData_Msg_desc, topic_name, qos, NULL); + MPT_ASSERT_FATAL_GT (tp, 0, "Could not create topic: %s\n", dds_strretcode (tp)); + + for (size_t i = 0; i < NPUB; i++) + { + setqos (qos, i * NWR_PUB, false, true); + pub[i] = dds_create_publisher (dp, qos, NULL); + MPT_ASSERT_FATAL_GT (pub[i], 0, "Could not create publisher %zu: %s\n", i, dds_strretcode (pub[i])); + for (size_t j = 0; j < NWR_PUB; j++) + { + setqos (qos, i * NWR_PUB + j, false, true); + wr[i][j] = dds_create_writer (pub[i], tp, qos, NULL); + MPT_ASSERT_FATAL_GT (wr[i][j], 0, "Could not create writer %zu %zu: %s\n", i, j, dds_strretcode (wr[i][j])); + } + } + + for (size_t i = 0; i < NPUB; i++) + { + setqos (qos, i * NWR_PUB, false, false); + MPT_ASSERT (pubsub_qos_eq_h (qos, pub[i]), "publisher %zu QoS mismatch\n", i); + for (size_t j = 0; j < NWR_PUB; j++) + { + setqos (qos, i * NWR_PUB + j, false, false); + MPT_ASSERT (writer_qos_eq_h (qos, wr[i][j]), "writer %zu %zu QoS mismatch\n", i, j); + } + } + + /* Each writer should match exactly one reader */ + uint32_t nchk = 0; + while (nchk != NPUB * NWR_PUB) + { + for (size_t i = 0; i < NPUB; i++) + { + for (size_t j = 0; j < NWR_PUB; j++) + { + if (chk[i][j]) + continue; + dds_instance_handle_t ih; + dds_builtintopic_endpoint_t *ep; + rc = dds_get_matched_subscriptions (wr[i][j], &ih, 1); + MPT_ASSERT (rc == 0 || rc == 1, "Unexpected return from get_matched_subscriptions for writer %zu %zu: %s\n", + i, j, dds_strretcode (rc)); + if (rc == 1) + { + ep = dds_get_matched_subscription_data (wr[i][j], ih); + MPT_ASSERT (ep != NULL, "Failed to retrieve matched subscription data for writer %zu %zu\n", i, j); + setqos (qos, i * NWR_PUB + j, true, false); + uint64_t delta = reader_qos_delta (qos, ep->qos); + if (delta) + { + DDS_LOG (DDS_LC_ERROR, "matched reader: delta = %"PRIx64"\n", delta); + nn_log_xqos (DDS_LC_ERROR, qos); DDS_LOG (DDS_LC_ERROR, "\n"); + nn_log_xqos (DDS_LC_ERROR, ep->qos); DDS_LOG (DDS_LC_ERROR, "\n"); + } + MPT_ASSERT (delta == 0, "writer %zu %zu matched reader QoS mismatch\n", i, j); + dds_delete_qos (ep->qos); + dds_free (ep->topic_name); + dds_free (ep->type_name); + dds_free (ep); + chk[i][j] = true; + nchk++; + } + } + } + dds_sleepfor (DDS_MSECS (100)); + } + + /* Wait until subscribers terminate */ + while (true) + { + for (size_t i = 0; i < NPUB; i++) + { + for (size_t j = 0; j < NWR_PUB; j++) + { + dds_publication_matched_status_t st; + rc = dds_get_publication_matched_status (wr[i][j], &st); + MPT_ASSERT_FATAL_EQ (rc, DDS_RETCODE_OK, "dds_get_matched_publication_status failed for writer %zu %zu: %s\n", + i, j, dds_strretcode (rc)); + if (st.current_count) + goto have_matches; + } + } + break; + have_matches: + ; + } + + dds_delete_qos (qos); + rc = dds_delete (dp); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n"); + printf ("=== [Publisher(%d)] Done\n", id); +} + +MPT_ProcessEntry (rw_subscriber, + MPT_Args (dds_domainid_t domainid, + const char *topic_name)) +{ + dds_entity_t dp; + dds_entity_t tp; + dds_entity_t sub[NPUB]; + dds_entity_t rd[NPUB][NWR_PUB]; + bool chk[NPUB][NWR_PUB] = { { false } }; + dds_return_t rc; + dds_qos_t *qos; + int id = (int) ddsrt_getpid (); + + printf ("=== [Subscriber(%d)] Start(%d) ...\n", id, (int) domainid); + + qos = dds_create_qos (); + setqos (qos, 0, true, true); + dp = dds_create_participant (domainid, NULL, NULL); + MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp)); + + tp = dds_create_topic (dp, &RWData_Msg_desc, topic_name, qos, NULL); + MPT_ASSERT_FATAL_GT (tp, 0, "Could not create topic: %s\n", dds_strretcode (tp)); + + for (size_t i = 0; i < NPUB; i++) + { + setqos (qos, i * NWR_PUB, true, true); + sub[i] = dds_create_subscriber (dp, qos, NULL); + MPT_ASSERT_FATAL_GT (sub[i], 0, "Could not create subscriber %zu: %s\n", i, dds_strretcode (sub[i])); + for (size_t j = 0; j < NWR_PUB; j++) + { + setqos (qos, i * NWR_PUB + j, true, true); + rd[i][j] = dds_create_reader (sub[i], tp, qos, NULL); + MPT_ASSERT_FATAL_GT (rd[i][j], 0, "Could not create reader %zu %zu: %s\n", i, j, dds_strretcode (rd[i][j])); + } + } + + for (size_t i = 0; i < NPUB; i++) + { + setqos (qos, i * NWR_PUB, true, false); + MPT_ASSERT (pubsub_qos_eq_h (qos, sub[i]), "subscriber %zu QoS mismatch\n", i); + for (size_t j = 0; j < NWR_PUB; j++) + { + setqos (qos, i * NWR_PUB + j, true, false); + MPT_ASSERT (reader_qos_eq_h (qos, rd[i][j]), "reader %zu %zu QoS mismatch\n", i, j); + } + } + + /* Each writer should match exactly one reader */ + uint32_t nchk = 0; + while (nchk != NPUB * NWR_PUB) + { + for (size_t i = 0; i < NPUB; i++) + { + for (size_t j = 0; j < NWR_PUB; j++) + { + if (chk[i][j]) + continue; + dds_instance_handle_t ih; + dds_builtintopic_endpoint_t *ep; + rc = dds_get_matched_publications (rd[i][j], &ih, 1); + MPT_ASSERT (rc == 0 || rc == 1, "Unexpected return from get_matched_publications for writer %zu %zu: %s\n", + i, j, dds_strretcode (rc)); + if (rc == 1) + { + ep = dds_get_matched_publication_data (rd[i][j], ih); + MPT_ASSERT (ep != NULL, "Failed to retrieve matched publication data for writer %zu %zu\n", i, j); + setqos (qos, i * NWR_PUB + j, false, false); + uint64_t delta = writer_qos_delta (qos, ep->qos); + if (delta) + { + DDS_LOG (DDS_LC_ERROR, "matched writer: delta = %"PRIx64"\n", delta); + nn_log_xqos (DDS_LC_ERROR, qos); DDS_LOG (DDS_LC_ERROR, "\n"); + nn_log_xqos (DDS_LC_ERROR, ep->qos); DDS_LOG (DDS_LC_ERROR, "\n"); + } + MPT_ASSERT (delta == 0, "reader %zu %zu matched writer QoS mismatch\n", i, j); + dds_delete_qos (ep->qos); + dds_free (ep->topic_name); + dds_free (ep->type_name); + dds_free (ep); + chk[i][j] = true; + nchk++; + } + } + } + dds_sleepfor (DDS_MSECS (100)); + } + + dds_delete_qos (qos); + rc = dds_delete (dp); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n"); + printf ("=== [Subscriber(%d)] Done\n", id); +} diff --git a/src/mpt/tests/qosmatch/procs/rw.h b/src/mpt/tests/qosmatch/procs/rw.h new file mode 100644 index 0000000..851ee20 --- /dev/null +++ b/src/mpt/tests/qosmatch/procs/rw.h @@ -0,0 +1,41 @@ +/* + * 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 MPT_QOSMATCH_PROCS_RW_H +#define MPT_QOSMATCH_PROCS_RW_H + +#include +#include + +#include "dds/dds.h" +#include "mpt/mpt.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +void rw_init (void); +void rw_fini (void); + +MPT_ProcessEntry (rw_publisher, + MPT_Args (dds_domainid_t domainid, + const char *topic_name)); + +MPT_ProcessEntry (rw_subscriber, + MPT_Args (dds_domainid_t domainid, + const char *topic_name)); + +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/src/mpt/tests/qosmatch/procs/rwdata.idl b/src/mpt/tests/qosmatch/procs/rwdata.idl new file mode 100644 index 0000000..7722451 --- /dev/null +++ b/src/mpt/tests/qosmatch/procs/rwdata.idl @@ -0,0 +1,8 @@ +module RWData +{ + struct Msg + { + long k; + }; + #pragma keylist Msg k +}; diff --git a/src/mpt/tests/qosmatch/qosmatch.c b/src/mpt/tests/qosmatch/qosmatch.c new file mode 100644 index 0000000..b249b35 --- /dev/null +++ b/src/mpt/tests/qosmatch/qosmatch.c @@ -0,0 +1,20 @@ +#include "mpt/mpt.h" +#include "procs/rw.h" + + +/* + * Tests to check communication between multiple publisher(s) and subscriber(s). + */ + + +/* + * The publisher expects 2 publication matched. + * The subscribers expect 1 sample each. + */ +#define TEST_PUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_qosmatch") +#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_qosmatch") +MPT_TestProcess(qosmatch, qosmatch, pub, rw_publisher, TEST_PUB_ARGS); +MPT_TestProcess(qosmatch, qosmatch, sub, rw_subscriber, TEST_SUB_ARGS); +MPT_Test(qosmatch, qosmatch, .init=rw_init, .fini=rw_fini); +#undef TEST_SUB_ARGS +#undef TEST_PUB_ARGS From b3b0e52e25260b7b58a1e3133b2efec1a27de02c Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Thu, 13 Jun 2019 09:48:51 +0200 Subject: [PATCH 089/178] Do not reset dds_sample_rejected_status_t::last_reason Signed-off-by: Martin Bremmer --- src/core/ddsc/src/dds_reader.c | 2 +- src/core/ddsc/tests/entity_status.c | 83 ++++++++++++++++++++++++++- src/core/ddsc/tests/listener.c | 87 +++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+), 2 deletions(-) diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index f40dfe1..b5896ad 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -561,7 +561,7 @@ DDSRT_STATIC_ASSERT ((int) DDS_NOT_REJECTED == 0); DDS_GET_STATUS (reader, subscription_matched, SUBSCRIPTION_MATCHED, total_count_change, current_count_change) DDS_GET_STATUS (reader, liveliness_changed, LIVELINESS_CHANGED, alive_count_change, not_alive_count_change) -DDS_GET_STATUS (reader, sample_rejected, SAMPLE_REJECTED, total_count_change, last_reason) +DDS_GET_STATUS (reader, sample_rejected, SAMPLE_REJECTED, total_count_change) DDS_GET_STATUS (reader, sample_lost, SAMPLE_LOST, total_count_change) DDS_GET_STATUS (reader, requested_deadline_missed, REQUESTED_DEADLINE_MISSED, total_count_change) DDS_GET_STATUS (reader, requested_incompatible_qos, REQUESTED_INCOMPATIBLE_QOS, total_count_change) diff --git a/src/core/ddsc/tests/entity_status.c b/src/core/ddsc/tests/entity_status.c index 662d3ae..4f1f94d 100644 --- a/src/core/ddsc/tests/entity_status.c +++ b/src/core/ddsc/tests/entity_status.c @@ -145,6 +145,15 @@ CU_Test(ddsc_entity_status, publication_matched, .init=init_entity_status, .fini CU_ASSERT_EQUAL_FATAL(publication_matched.total_count_change, 1); CU_ASSERT_EQUAL_FATAL(publication_matched.last_subscription_handle, reader_i_hdl); + /* Second call should reset the changed count. */ + ret = dds_get_publication_matched_status(wri, &publication_matched); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(publication_matched.current_count, 1); + CU_ASSERT_EQUAL_FATAL(publication_matched.current_count_change, 0); + CU_ASSERT_EQUAL_FATAL(publication_matched.total_count, 1); + CU_ASSERT_EQUAL_FATAL(publication_matched.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(publication_matched.last_subscription_handle, reader_i_hdl); + /* Getting the status should have reset the trigger, * meaning that the wait should timeout. */ ret = dds_waitset_wait(waitSetwr, wsresults, wsresultsize, shortTimeout); @@ -163,6 +172,15 @@ CU_Test(ddsc_entity_status, publication_matched, .init=init_entity_status, .fini CU_ASSERT_EQUAL_FATAL(publication_matched.total_count, 1); CU_ASSERT_EQUAL_FATAL(publication_matched.total_count_change, 0); CU_ASSERT_EQUAL_FATAL(publication_matched.last_subscription_handle, reader_i_hdl); + + /* Second call should reset the changed count. */ + ret = dds_get_publication_matched_status(wri, &publication_matched); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(publication_matched.current_count, 0); + CU_ASSERT_EQUAL_FATAL(publication_matched.current_count_change, 0); + CU_ASSERT_EQUAL_FATAL(publication_matched.total_count, 1); + CU_ASSERT_EQUAL_FATAL(publication_matched.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(publication_matched.last_subscription_handle, reader_i_hdl); } CU_Test(ddsc_entity_status, subscription_matched, .init=init_entity_status, .fini=fini_entity_status) @@ -182,6 +200,15 @@ CU_Test(ddsc_entity_status, subscription_matched, .init=init_entity_status, .fin CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count_change, 1); CU_ASSERT_EQUAL_FATAL(subscription_matched.last_publication_handle, writer_i_hdl); + /* Second call should reset the changed count. */ + ret = dds_get_subscription_matched_status(rea, &subscription_matched); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(subscription_matched.current_count, 1); + CU_ASSERT_EQUAL_FATAL(subscription_matched.current_count_change, 0); + CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count, 1); + CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(subscription_matched.last_publication_handle, writer_i_hdl); + /* Getting the status should have reset the trigger, * meaning that the wait should timeout. */ ret = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); @@ -200,6 +227,15 @@ CU_Test(ddsc_entity_status, subscription_matched, .init=init_entity_status, .fin CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count, 1); CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count_change, 0); CU_ASSERT_EQUAL_FATAL(subscription_matched.last_publication_handle, writer_i_hdl); + + /* Second call should reset the changed count. */ + ret = dds_get_subscription_matched_status(rea, &subscription_matched); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(subscription_matched.current_count, 0); + CU_ASSERT_EQUAL_FATAL(subscription_matched.current_count_change, 0); + CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count, 1); + CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(subscription_matched.last_publication_handle, writer_i_hdl); } CU_Test(ddsc_entity, incompatible_qos, .init=init_entity_status, .fini=fini_entity_status) @@ -238,6 +274,13 @@ CU_Test(ddsc_entity, incompatible_qos, .init=init_entity_status, .fini=fini_enti CU_ASSERT_EQUAL_FATAL(req_incompatible_qos.total_count_change, 1); CU_ASSERT_EQUAL_FATAL(req_incompatible_qos.last_policy_id, DDS_DURABILITY_QOS_POLICY_ID); + /* Second call should reset the changed count. */ + ret = dds_get_requested_incompatible_qos_status (reader2, &req_incompatible_qos); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(req_incompatible_qos.total_count, 1); + CU_ASSERT_EQUAL_FATAL(req_incompatible_qos.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(req_incompatible_qos.last_policy_id, DDS_DURABILITY_QOS_POLICY_ID); + /*Getting the status should have reset the trigger, waitset should timeout */ ret = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); CU_ASSERT_EQUAL_FATAL(ret, 0); @@ -251,6 +294,13 @@ CU_Test(ddsc_entity, incompatible_qos, .init=init_entity_status, .fini=fini_enti CU_ASSERT_EQUAL_FATAL(off_incompatible_qos.total_count_change, 1); CU_ASSERT_EQUAL_FATAL(off_incompatible_qos.last_policy_id, DDS_DURABILITY_QOS_POLICY_ID); + /* Second call should reset the changed count. */ + ret = dds_get_offered_incompatible_qos_status (wri, &off_incompatible_qos); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(off_incompatible_qos.total_count, 1); + CU_ASSERT_EQUAL_FATAL(off_incompatible_qos.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(off_incompatible_qos.last_policy_id, DDS_DURABILITY_QOS_POLICY_ID); + /*Getting the status should have reset the trigger, waitset should timeout */ ret = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); CU_ASSERT_EQUAL_FATAL(ret, 0); @@ -285,6 +335,15 @@ CU_Test(ddsc_entity, liveliness_changed, .init=init_entity_status, .fini=fini_en CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count_change,0); CU_ASSERT_EQUAL_FATAL(liveliness_changed.last_publication_handle, writer_i_hdl); + /* Second call should reset the changed count. */ + ret = dds_get_liveliness_changed_status (rea, &liveliness_changed); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count, 1); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count_change, 0); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count, 0); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count_change,0); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.last_publication_handle, writer_i_hdl); + /*Getting the status should have reset the trigger, waitset should timeout */ ret = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); CU_ASSERT_EQUAL_FATAL(ret, 0); @@ -305,6 +364,15 @@ CU_Test(ddsc_entity, liveliness_changed, .init=init_entity_status, .fini=fini_en CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count, 1); CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count_change,1); CU_ASSERT_EQUAL_FATAL(liveliness_changed.last_publication_handle, writer_i_hdl); + + /* Second call should reset the changed count. */ + ret = dds_get_liveliness_changed_status (rea, &liveliness_changed); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count, 0); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count_change, 0); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count, 1); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count_change,0); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.last_publication_handle, writer_i_hdl); } CU_Test(ddsc_entity, sample_rejected, .init=init_entity_status, .fini=fini_entity_status) @@ -346,6 +414,13 @@ CU_Test(ddsc_entity, sample_rejected, .init=init_entity_status, .fini=fini_entit CU_ASSERT_EQUAL_FATAL(sample_rejected.total_count_change, 4); CU_ASSERT_EQUAL_FATAL(sample_rejected.last_reason, DDS_REJECTED_BY_SAMPLES_LIMIT); + /* Second call should reset the changed count. */ + ret = dds_get_sample_rejected_status (rea, &sample_rejected); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(sample_rejected.total_count, 4); + CU_ASSERT_EQUAL_FATAL(sample_rejected.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(sample_rejected.last_reason, DDS_REJECTED_BY_SAMPLES_LIMIT); + /*Getting the status should have reset the trigger, waitset should timeout */ ret = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); CU_ASSERT_EQUAL_FATAL(ret, 0); @@ -433,9 +508,15 @@ CU_Test(ddsc_entity, sample_lost, .init=init_entity_status, .fini=fini_entity_st CU_ASSERT_EQUAL_FATAL(ret, (dds_return_t)wsresultsize); ret = dds_get_sample_lost_status (rea, &sample_lost); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(sample_lost.total_count, 1); + CU_ASSERT_EQUAL_FATAL(sample_lost.total_count, 1); CU_ASSERT_EQUAL_FATAL(sample_lost.total_count_change, 1); + /* Second call should reset the changed count. */ + ret = dds_get_sample_lost_status (rea, &sample_lost); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(sample_lost.total_count, 1); + CU_ASSERT_EQUAL_FATAL(sample_lost.total_count_change, 0); + /*Getting the status should have reset the trigger, waitset should timeout */ ret = dds_waitset_wait(waitSetrd, wsresults, wsresultsize, shortTimeout); CU_ASSERT_EQUAL_FATAL(ret, 0); diff --git a/src/core/ddsc/tests/listener.c b/src/core/ddsc/tests/listener.c index d049c85..b0b42a7 100644 --- a/src/core/ddsc/tests/listener.c +++ b/src/core/ddsc/tests/listener.c @@ -692,6 +692,7 @@ CU_Test(ddsc_listener, matched, .init=init_triggering_base, .fini=fini_triggerin CU_Test(ddsc_listener, publication_matched, .init=init_triggering_test, .fini=fini_triggering_test) { + dds_publication_matched_status_t publication_matched; dds_instance_handle_t reader_hdl; dds_return_t ret; uint32_t triggered; @@ -716,6 +717,15 @@ CU_Test(ddsc_listener, publication_matched, .init=init_triggering_test, .fini=fi CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(status, 0); + /* The listener should have reset the count_change. */ + ret = dds_get_publication_matched_status(g_writer, &publication_matched); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(publication_matched.current_count, 1); + CU_ASSERT_EQUAL_FATAL(publication_matched.current_count_change, 0); + CU_ASSERT_EQUAL_FATAL(publication_matched.total_count, 1); + CU_ASSERT_EQUAL_FATAL(publication_matched.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(publication_matched.last_subscription_handle, reader_hdl); + /* Reset the trigger flags. */ cb_called = 0; @@ -731,10 +741,20 @@ CU_Test(ddsc_listener, publication_matched, .init=init_triggering_test, .fini=fi CU_ASSERT_EQUAL_FATAL(cb_publication_matched_status.total_count, 1); CU_ASSERT_EQUAL_FATAL(cb_publication_matched_status.total_count_change, 0); CU_ASSERT_EQUAL_FATAL(cb_publication_matched_status.last_subscription_handle, reader_hdl); + + /* The listener should have reset the count_change. */ + ret = dds_get_publication_matched_status(g_writer, &publication_matched); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(publication_matched.current_count, 0); + CU_ASSERT_EQUAL_FATAL(publication_matched.current_count_change, 0); + CU_ASSERT_EQUAL_FATAL(publication_matched.total_count, 1); + CU_ASSERT_EQUAL_FATAL(publication_matched.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(publication_matched.last_subscription_handle, reader_hdl); } CU_Test(ddsc_listener, subscription_matched, .init=init_triggering_test, .fini=fini_triggering_test) { + dds_subscription_matched_status_t subscription_matched; dds_instance_handle_t writer_hdl; dds_return_t ret; uint32_t triggered; @@ -759,6 +779,15 @@ CU_Test(ddsc_listener, subscription_matched, .init=init_triggering_test, .fini=f CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(status, 0); + /* The listener should have reset the count_change. */ + ret = dds_get_subscription_matched_status(g_reader, &subscription_matched); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(subscription_matched.current_count, 1); + CU_ASSERT_EQUAL_FATAL(subscription_matched.current_count_change, 0); + CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count, 1); + CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(subscription_matched.last_publication_handle, writer_hdl); + /* Reset the trigger flags. */ cb_called = 0; @@ -774,10 +803,21 @@ CU_Test(ddsc_listener, subscription_matched, .init=init_triggering_test, .fini=f CU_ASSERT_EQUAL_FATAL(cb_subscription_matched_status.total_count, 1); CU_ASSERT_EQUAL_FATAL(cb_subscription_matched_status.total_count_change, 0); CU_ASSERT_EQUAL_FATAL(cb_subscription_matched_status.last_publication_handle, writer_hdl); + + /* The listener should have reset the count_change. */ + ret = dds_get_subscription_matched_status(g_reader, &subscription_matched); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(subscription_matched.current_count, 0); + CU_ASSERT_EQUAL_FATAL(subscription_matched.current_count_change, 0); + CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count, 1); + CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(subscription_matched.last_publication_handle, writer_hdl); } CU_Test(ddsc_listener, incompatible_qos, .init=init_triggering_base, .fini=fini_triggering_base) { + dds_offered_incompatible_qos_status_t offered_incompatible_qos; + dds_requested_incompatible_qos_status_t requested_incompatible_qos; dds_return_t ret; uint32_t triggered; uint32_t status; @@ -815,6 +855,18 @@ CU_Test(ddsc_listener, incompatible_qos, .init=init_triggering_base, .fini=fini_ CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(status, 0); + /* The listener should have reset the count_change. */ + ret = dds_get_offered_incompatible_qos_status(g_writer, &offered_incompatible_qos); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + ret = dds_get_requested_incompatible_qos_status(g_reader, &requested_incompatible_qos); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(offered_incompatible_qos.total_count, 1); + CU_ASSERT_EQUAL_FATAL(offered_incompatible_qos.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(offered_incompatible_qos.last_policy_id, DDS_DURABILITY_QOS_POLICY_ID); + CU_ASSERT_EQUAL_FATAL(requested_incompatible_qos.total_count, 1); + CU_ASSERT_EQUAL_FATAL(requested_incompatible_qos.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(requested_incompatible_qos.last_policy_id, DDS_DURABILITY_QOS_POLICY_ID); + dds_delete(g_writer); dds_delete(g_reader); } @@ -997,6 +1049,7 @@ CU_Test(ddsc_listener, data_on_readers, .init=init_triggering_test, .fini=fini_t CU_Test(ddsc_listener, sample_lost, .init=init_triggering_test, .fini=fini_triggering_test) { + dds_sample_lost_status_t sample_lost; dds_return_t ret; uint32_t triggered; dds_time_t the_past; @@ -1031,10 +1084,17 @@ CU_Test(ddsc_listener, sample_lost, .init=init_triggering_test, .fini=fini_trigg ret = dds_read_status(g_reader, &status, DDS_SAMPLE_LOST_STATUS); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(status, 0); + + /* The listener should have reset the count_change. */ + ret = dds_get_sample_lost_status(g_reader, &sample_lost); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(sample_lost.total_count, 1); + CU_ASSERT_EQUAL_FATAL(sample_lost.total_count_change, 0); } CU_Test(ddsc_listener, sample_rejected, .init=init_triggering_test, .fini=fini_triggering_test) { + dds_sample_rejected_status_t sample_rejected; dds_return_t ret; uint32_t triggered; uint32_t status; @@ -1060,15 +1120,24 @@ CU_Test(ddsc_listener, sample_rejected, .init=init_triggering_test, .fini=fini_t CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); CU_ASSERT_EQUAL_FATAL(cb_sample_rejected_status.total_count, 2); CU_ASSERT_EQUAL_FATAL(cb_sample_rejected_status.total_count_change, 1); + CU_ASSERT_EQUAL_FATAL(cb_sample_rejected_status.last_reason, DDS_REJECTED_BY_SAMPLES_LIMIT); /* The listener should have swallowed the status. */ ret = dds_read_status(g_reader, &status, DDS_SAMPLE_REJECTED_STATUS); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(status, 0); + + /* The listener should have reset the count_change. */ + ret = dds_get_sample_rejected_status(g_reader, &sample_rejected); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(sample_rejected.total_count, 2); + CU_ASSERT_EQUAL_FATAL(sample_rejected.total_count_change, 0); + CU_ASSERT_EQUAL_FATAL(cb_sample_rejected_status.last_reason, DDS_REJECTED_BY_SAMPLES_LIMIT); } CU_Test(ddsc_listener, liveliness_changed, .init=init_triggering_test, .fini=fini_triggering_base) { + dds_liveliness_changed_status_t liveliness_changed; dds_instance_handle_t writer_hdl; dds_return_t ret; uint32_t triggered; @@ -1095,6 +1164,15 @@ CU_Test(ddsc_listener, liveliness_changed, .init=init_triggering_test, .fini=fin CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(status, 0); + /* The listener should have reset the count_change. */ + ret = dds_get_liveliness_changed_status(g_reader, &liveliness_changed); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count, 1); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count_change, 0); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count, 0); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count_change, 0); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.last_publication_handle, writer_hdl); + /* Reset the trigger flags. */ cb_called = 0; @@ -1110,6 +1188,15 @@ CU_Test(ddsc_listener, liveliness_changed, .init=init_triggering_test, .fini=fin CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.not_alive_count, 1); CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.not_alive_count_change, 1); CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.last_publication_handle, writer_hdl); + + /* The listener should have reset the count_change. */ + ret = dds_get_liveliness_changed_status(g_reader, &liveliness_changed); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count, 0); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count_change, 0); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count, 1); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count_change, 0); + CU_ASSERT_EQUAL_FATAL(liveliness_changed.last_publication_handle, writer_hdl); } #if 0 From cdfeb0aaccb9b4d6abb523c73357d4c7e1065d87 Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Thu, 13 Jun 2019 10:57:07 +0200 Subject: [PATCH 090/178] Removed redundant closing parentheses of dds_err_nr(). Signed-off-by: Martin Bremmer --- src/core/ddsc/include/dds/ddsc/dds_public_error.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_error.h b/src/core/ddsc/include/dds/ddsc/dds_public_error.h index bc73a57..ef356b4 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_error.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_error.h @@ -39,7 +39,7 @@ extern "C" { /* Error code handling functions */ /** Macro to extract error number */ -#define dds_err_nr(e) (e)) +#define dds_err_nr(e) (e) /** Macro to extract line number */ #define dds_err_line(e) (0) From 7bffaedde836a26701b3096e8122f24d96815111 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 7 Jun 2019 14:56:06 +0200 Subject: [PATCH 091/178] Clear padding in outgoing messages Padding used to not be cleared in this code base, but that has the downside of valgrind reporting nuisance warnings (which could be fixed using valgrind's programmatic interface) but also of potentially leaking information. The cost of clearing the padding appears to be insignificant compared to the cost of doing the real work, and so it is probably best to just clear it. Signed-off-by: Erik Boasson --- src/core/ddsi/src/ddsi_serdata_default.c | 11 ++++------- src/core/ddsi/src/q_ddsi_discovery.c | 1 + src/core/ddsi/src/q_plist.c | 9 +++++++-- src/core/ddsi/src/q_xmsg.c | 13 +++++-------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 630c6c0..8c5b38c 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -102,17 +102,13 @@ static void *serdata_default_append (struct ddsi_serdata_default **d, size_t n) static void *serdata_default_append_aligned (struct ddsi_serdata_default **d, size_t n, size_t a) { -#if CLEAR_PADDING - size_t pos0 = st->pos; -#endif + size_t pos0 = (*d)->pos; char *p; assert (ispowerof2_size (a)); (*d)->pos = (uint32_t) alignup_size ((*d)->pos, a); p = serdata_default_append (d, n); -#if CLEAR_PADDING - if (p && (*d)->pos > pos0) - memset ((*d)->data + pos0, 0, (*d)->pos - pos0); -#endif + while (pos0 < (*d)->pos) + (*d)->data[pos0++] = 0; return p; } @@ -512,6 +508,7 @@ static struct ddsi_serdata *serdata_default_from_sample_rawcdr (const struct dds return NULL; assert (sample->keysize <= 16); serdata_default_append_blob (&d, 1, sample->size, sample->blob); + serdata_default_append_aligned (&d, 0, 4); d->keyhash.m_set = 1; d->keyhash.m_iskey = 1; if (sample->keysize == 0) diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 3973840..9218611 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -289,6 +289,7 @@ int spdp_write (struct participant *pp) /* Add PrismTech specific version information */ { ps.present |= PP_PRISMTECH_PARTICIPANT_VERSION_INFO; + memset (&ps.prismtech_participant_version_info, 0, sizeof (ps.prismtech_participant_version_info)); ps.prismtech_participant_version_info.version = 0; ps.prismtech_participant_version_info.flags = NN_PRISMTECH_FL_DDSI2_PARTICIPANT_FLAG | diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 7d396c3..0cf2da1 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -158,8 +158,13 @@ static const void *deser_generic_src (const void * __restrict src, size_t *srcof static void *ser_generic_align4 (char * __restrict p, size_t * __restrict off) { - *off = align4size (*off); - return p + *off; + const size_t off1 = align4size (*off); + size_t pad = off1 - *off; + char *dst = p + *off; + *off = off1; + while (pad--) + *dst++ = 0; + return dst; } static dds_return_t deser_uint32 (uint32_t *dst, const struct dd * __restrict dd, size_t * __restrict off) diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 8f942b0..f21214d 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -506,7 +506,7 @@ void *nn_xmsg_submsg_from_marker (struct nn_xmsg *msg, struct nn_xmsg_marker mar return msg->data->payload + marker.offset; } -void * nn_xmsg_append (struct nn_xmsg *m, struct nn_xmsg_marker *marker, size_t sz) +void *nn_xmsg_append (struct nn_xmsg *m, struct nn_xmsg_marker *marker, size_t sz) { static const size_t a = 4; @@ -809,13 +809,10 @@ void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len) phdr->parameterid = pid; phdr->length = (uint16_t) len4; p = (char *) (phdr + 1); - if (len4 > len) - { - /* zero out padding bytes added to satisfy parameter alignment -- - alternative: zero out, but this way valgrind/purify can tell us - where we forgot to initialize something */ - memset (p + len, 0, len4 - len); - } + /* zero out padding bytes added to satisfy parameter alignment: this way + valgrind can tell us where we forgot to initialize something */ + while (len < len4) + p[len++] = 0; return p; } From 8a1980faa606d840ee8771a40e35218dcc4582b5 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 6 Jun 2019 10:20:19 +0200 Subject: [PATCH 092/178] Remove ArrivalOfDataAssertsPpAndEpLiveliness option The Compatibility/ArrivalOfDataAssertsPpAndEpLiveliness option was a rather strange option: receipt of a message is proof of the existence of the sender, so having an option to not treat it as such only adds complexity without any benefit. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_config.h | 1 - src/core/ddsi/include/dds/ddsi/q_entity.h | 2 -- src/core/ddsi/src/q_config.c | 2 -- src/core/ddsi/src/q_entity.c | 8 -------- src/core/ddsi/src/q_lease.c | 5 +++-- src/core/ddsi/src/q_receive.c | 20 ++++++-------------- 6 files changed, 9 insertions(+), 29 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index a83fbf8..095717c 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -372,7 +372,6 @@ struct config enum nn_standards_conformance standards_conformance; int explicitly_publish_qos_set_to_default; enum many_sockets_mode many_sockets_mode; - int arrival_of_data_asserts_pp_and_ep_liveliness; int assume_rti_has_pmd_endpoints; int port_dg; diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index f809489..5011b2e 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -351,7 +351,6 @@ struct proxy_writer { unsigned last_fragnum_reset: 1; /* iff set, heartbeat advertising last_seq as highest seq resets last_fragnum */ unsigned deliver_synchronously: 1; /* iff 1, delivery happens straight from receive thread for non-historical data; else through delivery queue "dqueue" */ unsigned have_seen_heartbeat: 1; /* iff 1, we have received at least on heartbeat from this proxy writer */ - unsigned assert_pp_lease: 1; /* iff 1, renew the proxy-participant's lease when data comes in */ unsigned local_matching_inprogress: 1; /* iff 1, we are still busy matching local readers; this is so we don't deliver incoming data to some but not all readers initially */ #ifdef DDSI_INCLUDE_SSM unsigned supports_ssm: 1; /* iff 1, this proxy writer supports SSM */ @@ -370,7 +369,6 @@ struct proxy_reader { struct proxy_endpoint_common c; unsigned deleting: 1; /* set when being deleted */ unsigned is_fict_trans_reader: 1; /* only true when it is certain that is a fictitious transient data reader (affects built-in topic generation) */ - unsigned assert_pp_lease: 1; /* iff 1, renew the proxy-participant's lease when data comes in */ #ifdef DDSI_INCLUDE_SSM unsigned favours_ssm: 1; /* iff 1, this proxy reader favours SSM when available */ #endif diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 1fb1155..99b697c 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -432,8 +432,6 @@ static const struct cfgelem compatibility_cfgelems[] = { { LEAF ("ManySocketsMode"), 1, "single", ABSOFF (many_sockets_mode), 0, uf_many_sockets_mode, 0, pf_many_sockets_mode, BLURB("

    This option specifies whether a network socket will be created for each domain participant on a host. The specification seems to assume that each participant has a unique address, and setting this option will ensure this to be the case. This is not the defeault.

    \n\

    Disabling it slightly improves performance and reduces network traffic somewhat. It also causes the set of port numbers needed by DDSI2E to become predictable, which may be useful for firewall and NAT configuration.

    ") }, - { LEAF("ArrivalOfDataAssertsPpAndEpLiveliness"), 1, "true", ABSOFF(arrival_of_data_asserts_pp_and_ep_liveliness), 0, uf_boolean, 0, pf_boolean, - BLURB("

    When set to true, arrival of a message from a peer asserts liveliness of that peer. When set to false, only SPDP and explicit lease renewals have this effect.

    ") }, { LEAF("AssumeRtiHasPmdEndpoints"), 1, "false", ABSOFF(assume_rti_has_pmd_endpoints), 0, uf_boolean, 0, pf_boolean, BLURB("

    This option assumes ParticipantMessageData endpoints required by the liveliness protocol are present in RTI participants even when not properly advertised by the participant discovery protocol.

    ") }, END_MARKER diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index d8e66fc..14f03ef 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -4128,11 +4128,6 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, pwr->supports_ssm = (addrset_contains_ssm (as) && config.allowMulticast & AMC_SSM) ? 1 : 0; #endif - /* Only assert PP lease on receipt of data if enabled (duh) and the proxy participant is a - "real" participant, rather than the thing we use for endpoints discovered via the DS */ - pwr->assert_pp_lease = - (unsigned) !!config.arrival_of_data_asserts_pp_and_ep_liveliness; - assert (pwr->c.xqos->present & QP_LIVELINESS); if (pwr->c.xqos->liveliness.kind != DDS_LIVELINESS_AUTOMATIC) DDS_LOG(DDS_LC_DISCOVERY, " FIXME: only AUTOMATIC liveliness supported"); @@ -4336,9 +4331,6 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, prd->favours_ssm = (favours_ssm && config.allowMulticast & AMC_SSM) ? 1 : 0; #endif prd->is_fict_trans_reader = 0; - /* Only assert PP lease on receipt of data if enabled (duh) and the proxy participant is a - "real" participant, rather than the thing we use for endpoints discovered via the DS */ - prd->assert_pp_lease = (unsigned) !!config.arrival_of_data_asserts_pp_and_ep_liveliness; ddsrt_avl_init (&prd_writers_treedef, &prd->writers); diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index d0dc03b..f3d2e5b 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -363,8 +363,9 @@ void handle_PMD (UNUSED_ARG (const struct receiver_state *rst), nn_wctime_t time { /* Renew lease if arrival of this message didn't already do so, also renew the lease of the virtual participant used for DS-discovered endpoints */ - if (!config.arrival_of_data_asserts_pp_and_ep_liveliness) - lease_renew (ddsrt_atomic_ldvoidp (&pp->lease), now_et ()); +#if 0 // FIXME: superfluous ... receipt of the message already did it */ + lease_renew (ddsrt_atomic_ldvoidp (&pp->lease), now_et ()); +#endif } } break; diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 8ec7197..7c9d4a0 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -715,8 +715,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac } /* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */ - if (prd->assert_pp_lease) - lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow); + lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow); if (!wr->reliable) /* note: reliability can't be changed */ { @@ -1189,8 +1188,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct /* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */ - if (pwr->assert_pp_lease) - lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); + lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); DDS_TRACE(PGUIDFMT" -> "PGUIDFMT":", PGUID (src), PGUID (dst)); @@ -1326,8 +1324,7 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime } /* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */ - if (pwr->assert_pp_lease) - lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); + lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst)); ddsrt_mutex_lock (&pwr->e.lock); @@ -1453,8 +1450,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N } /* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */ - if (prd->assert_pp_lease) - lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow); + lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow); if (!wr->reliable) /* note: reliability can't be changed */ { @@ -1700,8 +1696,7 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm } /* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */ - if (pwr->assert_pp_lease) - lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); + lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); ddsrt_mutex_lock (&pwr->e.lock); if ((wn = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, &dst)) == NULL) @@ -2133,10 +2128,7 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct /* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */ - if (pwr->assert_pp_lease) - { - lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); - } + lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); /* Shouldn't lock the full writer, but will do so for now */ ddsrt_mutex_lock (&pwr->e.lock); From 4a4f092f7b5f747bf1e243a81d0f9447ba11f7fa Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 6 Jun 2019 10:22:37 +0200 Subject: [PATCH 093/178] Accept and generate ACKNACK/GAP with empty bitset The DDSI spec version 2.1 forbade the use of ACKNACK/GAP messages with an empty bitset, but most vendors used these forms anyway. The DDSI stack of Cyclone had code to avoid generating these (though with a bug where it could generate an invalid GAP), but for no real benefit. Because the other vendors used them anyway, the stack has always been perfectly capable of handling them. DDSI spec version 2.3 allows these forms, and so there's no value in maintaining the old complications. This also eliminates the invalid GAP messages that could be generated at times. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_receive.c | 45 ++++------------------------------- 1 file changed, 4 insertions(+), 41 deletions(-) diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 7c9d4a0..33cb5c9 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -104,20 +104,12 @@ static void maybe_set_reader_in_sync (struct proxy_writer *pwr, struct pwr_rd_ma static int valid_sequence_number_set (const nn_sequence_number_set_t *snset) { - if (fromSN (snset->bitmap_base) <= 0) - return 0; - if (snset->numbits <= 0 || snset->numbits > 256) - return 0; - return 1; + return (fromSN (snset->bitmap_base) > 0 && snset->numbits <= 256); } static int valid_fragment_number_set (const nn_fragment_number_set_t *fnset) { - if (fnset->bitmap_base <= 0) - return 0; - if (fnset->numbits <= 0 || fnset->numbits > 256) - return 0; - return 1; + return (fnset->bitmap_base > 0 && fnset->numbits <= 256); } static int valid_AckNack (AckNack_t *msg, size_t size, int byteswap) @@ -136,25 +128,7 @@ static int valid_AckNack (AckNack_t *msg, size_t size, int byteswap) msg->writerId = nn_ntoh_entityid (msg->writerId); /* Validation following 8.3.7.1.3 + 8.3.5.5 */ if (!valid_sequence_number_set (&msg->readerSNState)) - { - if (NN_STRICT_P) - return 0; - else - { - /* RTI generates AckNacks with bitmapBase = 0 and numBits = 0 - (and possibly others that I don't know about) - their - Wireshark RTPS dissector says that such a message has a - length-0 bitmap, which is to expected given the way the - length is computed from numbits */ - if (fromSN (msg->readerSNState.bitmap_base) == 0 && - msg->readerSNState.numbits == 0) - ; /* accept this one known case */ - else if (msg->readerSNState.numbits == 0) - ; /* maybe RTI, definitely Twinoaks */ - else - return 0; - } - } + return 0; /* Given the number of bits, we can compute the size of the AckNack submessage, and verify that the submessage is large enough */ if (size < ACKNACK_SIZE (msg->readerSNState.numbits)) @@ -182,10 +156,7 @@ static int valid_Gap (Gap_t *msg, size_t size, int byteswap) if (fromSN (msg->gapStart) <= 0) return 0; if (!valid_sequence_number_set (&msg->gapList)) - { - if (NN_STRICT_P || msg->gapList.numbits != 0) - return 0; - } + return 0; /* One would expect gapStart < gapList.base, but it is not required by the spec for the GAP to valid. */ if (size < GAP_SIZE (msg->gapList.numbits)) @@ -564,7 +535,6 @@ static int add_Gap (struct nn_xmsg *msg, struct writer *wr, struct proxy_reader struct nn_xmsg_marker sm_marker; Gap_t *gap; ASSERT_MUTEX_HELD (wr->e.lock); - assert (numbits > 0); gap = nn_xmsg_append (msg, &sm_marker, GAP_SIZE (numbits)); nn_xmsg_submsg_init (msg, sm_marker, SMID_GAP); gap->readerId = nn_hton_entityid (prd->e.guid.entityid); @@ -973,13 +943,6 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac to the remote reader. */ gapend = grow_gap_to_next_seq (wr, gapend); } - if (gapnumbits == 0) - { - /* Avoid sending an invalid bitset */ - gapnumbits = 1; - nn_bitset_set (gapnumbits, gapbits, 0); - gapend--; - } /* The non-bitmap part of a gap message says everything <= gapend-1 is no more (so the maximum sequence number it informs the peer of is gapend-1); each bit adds one sequence number to From 11a1b9d6f978818fc9fbc72c9cdeb5d4ff2c2f2d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 4 Jun 2019 10:51:17 +0200 Subject: [PATCH 094/178] Don't perform discovery for subscriptions to built-in topics These topics are generated internally and never sent over the wire. Performing full discovery for these is therefore a significant waste of effort. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds__builtin.h | 3 ++- src/core/ddsc/src/dds_builtin.c | 13 ++++++++++--- src/core/ddsc/src/dds_init.c | 1 + src/core/ddsc/src/dds_whc_builtintopic.c | 2 +- src/core/ddsi/include/dds/ddsi/q_config.h | 3 ++- src/core/ddsi/src/q_entity.c | 12 +++++++----- 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/core/ddsc/src/dds__builtin.h b/src/core/ddsc/src/dds__builtin.h index fd191f9..767396e 100644 --- a/src/core/ddsc/src/dds__builtin.h +++ b/src/core/ddsc/src/dds__builtin.h @@ -34,7 +34,8 @@ struct ddsi_tkmap_instance; void dds__builtin_init (void); void dds__builtin_fini (void); -bool dds__builtin_is_visible (nn_entityid_t entityid, bool onlylocal, nn_vendorid_t vendorid); +bool dds__builtin_is_builtintopic (const struct ddsi_sertopic *tp); +bool dds__builtin_is_visible (const nn_guid_t *guid, nn_vendorid_t vendorid); struct ddsi_tkmap_instance *dds__builtin_get_tkmap_entry (const struct nn_guid *guid); struct ddsi_serdata *dds__builtin_make_sample (const struct entity_common *e, nn_wctime_t timestamp, bool alive); void dds__builtin_write (const struct entity_common *e, nn_wctime_t timestamp, bool alive); diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index ba9c31d..f7cc781 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -172,9 +172,16 @@ dds_entity_t dds__get_builtin_subscriber (dds_entity_t e) return sub; } -bool dds__builtin_is_visible (nn_entityid_t entityid, bool onlylocal, nn_vendorid_t vendorid) +bool dds__builtin_is_builtintopic (const struct ddsi_sertopic *tp) { - return !(onlylocal || is_builtin_endpoint (entityid, vendorid)); + return tp->ops == &ddsi_sertopic_ops_builtintopic; +} + +bool dds__builtin_is_visible (const nn_guid_t *guid, nn_vendorid_t vendorid) +{ + if (is_builtin_endpoint (guid->entityid, vendorid)) + return false; + return true; } struct ddsi_tkmap_instance *dds__builtin_get_tkmap_entry (const struct nn_guid *guid) @@ -221,7 +228,7 @@ struct ddsi_serdata *dds__builtin_make_sample (const struct entity_common *e, nn void dds__builtin_write (const struct entity_common *e, nn_wctime_t timestamp, bool alive) { - if (ddsi_plugin.builtintopic_is_visible (e->guid.entityid, e->onlylocal, get_entity_vendorid (e))) + if (dds__builtin_is_visible (&e->guid, get_entity_vendorid (e))) { /* initialize to avoid gcc warning ultimately caused by C's horrible type system */ struct local_orphan_writer *bwr = NULL; diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index ce068eb..9f70a1d 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -268,6 +268,7 @@ void ddsi_plugin_init (void) ddsi_plugin.init_fn = dds__init_plugin; ddsi_plugin.fini_fn = dds__fini_plugin; + ddsi_plugin.builtintopic_is_builtintopic = dds__builtin_is_builtintopic; ddsi_plugin.builtintopic_is_visible = dds__builtin_is_visible; ddsi_plugin.builtintopic_get_tkmap_entry = dds__builtin_get_tkmap_entry; ddsi_plugin.builtintopic_write = dds__builtin_write; diff --git a/src/core/ddsc/src/dds_whc_builtintopic.c b/src/core/ddsc/src/dds_whc_builtintopic.c index 58ac495..76926ed 100644 --- a/src/core/ddsc/src/dds_whc_builtintopic.c +++ b/src/core/ddsc/src/dds_whc_builtintopic.c @@ -62,7 +62,7 @@ static void bwhc_sample_iter_init (const struct whc *whc_generic, struct whc_sam static bool is_visible (const struct entity_common *e) { const nn_vendorid_t vendorid = get_entity_vendorid (e); - return ddsi_plugin.builtintopic_is_visible (e->guid.entityid, e->onlylocal, vendorid); + return ddsi_plugin.builtintopic_is_visible (&e->guid, vendorid); } static bool bwhc_sample_iter_borrow_next (struct whc_sample_iter *opaque_it, struct whc_borrowed_sample *sample) diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index 095717c..0e3e2de 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -397,7 +397,8 @@ struct ddsi_plugin int (*init_fn) (void); void (*fini_fn) (void); - bool (*builtintopic_is_visible) (nn_entityid_t entityid, bool onlylocal, nn_vendorid_t vendorid); + bool (*builtintopic_is_builtintopic) (const struct ddsi_sertopic *topic); + bool (*builtintopic_is_visible) (const nn_guid_t *guid, nn_vendorid_t vendorid); struct ddsi_tkmap_instance * (*builtintopic_get_tkmap_entry) (const struct nn_guid *guid); void (*builtintopic_write) (const struct entity_common *e, nn_wctime_t timestamp, bool alive); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 14f03ef..5870a41 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -170,7 +170,7 @@ static void entity_common_init (struct entity_common *e, const struct nn_guid *g e->name = ddsrt_strdup (name ? name : ""); e->onlylocal = onlylocal; ddsrt_mutex_init (&e->lock); - if (ddsi_plugin.builtintopic_is_visible (guid->entityid, onlylocal, vendorid)) + if (ddsi_plugin.builtintopic_is_visible (guid, vendorid)) { e->tk = ddsi_plugin.builtintopic_get_tkmap_entry (guid); e->iid = e->tk->m_iid; @@ -2428,9 +2428,9 @@ static void new_reader_writer_common (const struct nn_guid *guid, const struct d topic ? topic->type_name : "(null)"); } -static void endpoint_common_init (struct entity_common *e, struct endpoint_common *c, enum entity_kind kind, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp) +static void endpoint_common_init (struct entity_common *e, struct endpoint_common *c, enum entity_kind kind, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, bool onlylocal) { - entity_common_init (e, guid, NULL, kind, now (), NN_VENDORID_ECLIPSE, pp->e.onlylocal); + entity_common_init (e, guid, NULL, kind, now (), NN_VENDORID_ECLIPSE, pp->e.onlylocal || onlylocal); c->pp = ref_participant (pp, &e->guid); if (group_guid) c->group_guid = *group_guid; @@ -2834,7 +2834,8 @@ static dds_return_t new_writer_guid (struct writer **wr_out, const struct nn_gui delete_participant won't interfere with our ability to address the participant */ - endpoint_common_init (&wr->e, &wr->c, EK_WRITER, guid, group_guid, pp); + const bool onlylocal = topic && ddsi_plugin.builtintopic_is_builtintopic (topic); + endpoint_common_init (&wr->e, &wr->c, EK_WRITER, guid, group_guid, pp, onlylocal); new_writer_guid_common_init(wr, topic, xqos, whc, status_cb, status_entity); /* guid_hash needed for protocol handling, so add it before we send @@ -3217,7 +3218,8 @@ static dds_return_t new_reader_guid if (rd_out) *rd_out = rd; - endpoint_common_init (&rd->e, &rd->c, EK_READER, guid, group_guid, pp); + const bool onlylocal = topic && ddsi_plugin.builtintopic_is_builtintopic (topic); + endpoint_common_init (&rd->e, &rd->c, EK_READER, guid, group_guid, pp, onlylocal); /* Copy QoS, merging in defaults */ rd->xqos = ddsrt_malloc (sizeof (*rd->xqos)); From a4d8aba4f921d6f0cee2b7674a2ff2de931796e1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 4 Jun 2019 20:47:08 +0200 Subject: [PATCH 095/178] Add limited support for QoS changes This commit adds support for changing all mutable QoS except those that affect reader/writer matching (i.e., deadline, latency budget and partition). This is simply because the recalculation of the matches hasn't been implemented yet, it is not a fundamental limitation. Implementing this basically forced fixing up a bunch of inconsistencies in handling QoS in entity creation. A silly multi-process ping-pong test built on changing the value of user data has been added. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds__qos.h | 33 +- src/core/ddsc/src/dds_builtin.c | 1 - src/core/ddsc/src/dds_entity.c | 180 +++++- src/core/ddsc/src/dds_matched.c | 1 - src/core/ddsc/src/dds_participant.c | 48 +- src/core/ddsc/src/dds_publisher.c | 31 +- src/core/ddsc/src/dds_qos.c | 25 +- src/core/ddsc/src/dds_reader.c | 35 +- src/core/ddsc/src/dds_serdata_builtintopic.c | 12 +- src/core/ddsc/src/dds_subscriber.c | 31 +- src/core/ddsc/src/dds_topic.c | 79 ++- src/core/ddsc/src/dds_writer.c | 49 +- src/core/ddsc/tests/entity_api.c | 2 +- src/core/ddsc/tests/unsupported.c | 16 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 15 +- src/core/ddsi/include/dds/ddsi/q_xqos.h | 1 + src/core/ddsi/src/q_ddsi_discovery.c | 46 +- src/core/ddsi/src/q_entity.c | 111 +++- src/core/ddsi/src/q_plist.c | 72 ++- src/ddsrt/src/expand_envvars.c | 11 +- src/mpt/CMakeLists.txt | 1 - src/mpt/tests/CMakeLists.txt | 2 +- .../tests/{qosmatch => qos}/CMakeLists.txt | 21 +- src/mpt/tests/qos/ppuserdata.c | 58 ++ src/mpt/tests/qos/procs/ppud.c | 569 ++++++++++++++++++ src/mpt/tests/qos/procs/ppud.h | 55 ++ src/mpt/tests/{qosmatch => qos}/procs/rw.c | 11 + src/mpt/tests/{qosmatch => qos}/procs/rw.h | 2 +- src/mpt/tests/qos/procs/rwdata.idl | 19 + src/mpt/tests/qos/qosmatch.c | 21 + src/mpt/tests/qosmatch/procs/rwdata.idl | 8 - src/mpt/tests/qosmatch/qosmatch.c | 20 - 32 files changed, 1225 insertions(+), 361 deletions(-) rename src/mpt/tests/{qosmatch => qos}/CMakeLists.txt (53%) create mode 100644 src/mpt/tests/qos/ppuserdata.c create mode 100644 src/mpt/tests/qos/procs/ppud.c create mode 100644 src/mpt/tests/qos/procs/ppud.h rename src/mpt/tests/{qosmatch => qos}/procs/rw.c (96%) rename src/mpt/tests/{qosmatch => qos}/procs/rw.h (93%) create mode 100644 src/mpt/tests/qos/procs/rwdata.idl create mode 100644 src/mpt/tests/qos/qosmatch.c delete mode 100644 src/mpt/tests/qosmatch/procs/rwdata.idl delete mode 100644 src/mpt/tests/qosmatch/qosmatch.c diff --git a/src/core/ddsc/src/dds__qos.h b/src/core/ddsc/src/dds__qos.h index 4d66c67..be21eb9 100644 --- a/src/core/ddsc/src/dds__qos.h +++ b/src/core/ddsc/src/dds__qos.h @@ -12,14 +12,43 @@ #ifndef _DDS_QOS_H_ #define _DDS_QOS_H_ -#include "dds__entity.h" #include "dds/ddsi/q_xqos.h" #if defined (__cplusplus) extern "C" { #endif -dds_return_t dds_qos_validate_mutable_common (const dds_qos_t *qos); +#define DDS_TOPIC_QOS_MASK \ + (QP_TOPIC_DATA | QP_DURABILITY | QP_DURABILITY_SERVICE | \ + QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_LIVELINESS | \ + QP_RELIABILITY | QP_TRANSPORT_PRIORITY | QP_LIFESPAN | \ + QP_DESTINATION_ORDER | QP_HISTORY | QP_RESOURCE_LIMITS) + +#define DDS_PARTICIPANT_QOS_MASK \ + (QP_USER_DATA | QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL) + +#define DDS_PUBLISHER_QOS_MASK \ + (QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | \ + QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL) + +#define DDS_READER_QOS_MASK \ + (QP_USER_DATA | QP_DURABILITY | QP_DEADLINE | QP_LATENCY_BUDGET | \ + QP_OWNERSHIP | QP_LIVELINESS | QP_TIME_BASED_FILTER | \ + QP_RELIABILITY | QP_DESTINATION_ORDER | QP_HISTORY | \ + QP_RESOURCE_LIMITS | QP_PRISMTECH_READER_DATA_LIFECYCLE | \ + QP_CYCLONE_IGNORELOCAL) + +#define DDS_SUBSCRIBER_QOS_MASK \ + (QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | \ + QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL) + +#define DDS_WRITER_QOS_MASK \ + (QP_USER_DATA | QP_DURABILITY | QP_DURABILITY_SERVICE | QP_DEADLINE | \ + QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_OWNERSHIP_STRENGTH | \ + QP_LIVELINESS | QP_RELIABILITY | QP_TRANSPORT_PRIORITY | \ + QP_LIFESPAN | QP_DESTINATION_ORDER | QP_HISTORY | \ + QP_RESOURCE_LIMITS | QP_PRISMTECH_WRITER_DATA_LIFECYCLE | \ + QP_CYCLONE_IGNORELOCAL) #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index f7cc781..c663bc4 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -17,7 +17,6 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_plist.h" /* for nn_keyhash */ #include "dds__init.h" -#include "dds__qos.h" #include "dds__domain.h" #include "dds__participant.h" #include "dds__types.h" diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index 368f40c..4b51023 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -19,6 +19,8 @@ #include "dds__writer.h" #include "dds__reader.h" #include "dds__listener.h" +#include "dds__qos.h" +#include "dds__topic.h" #include "dds/version.h" #include "dds/ddsi/q_xqos.h" @@ -339,6 +341,32 @@ dds_return_t dds_get_children (dds_entity_t entity, dds_entity_t *children, size } } +static uint64_t entity_kind_qos_mask (dds_entity_kind_t kind) +{ + switch (kind) + { + case DDS_KIND_TOPIC: + return DDS_TOPIC_QOS_MASK; + case DDS_KIND_PARTICIPANT: + return DDS_PARTICIPANT_QOS_MASK; + case DDS_KIND_READER: + return DDS_READER_QOS_MASK; + case DDS_KIND_WRITER: + return DDS_WRITER_QOS_MASK; + case DDS_KIND_SUBSCRIBER: + return DDS_SUBSCRIBER_QOS_MASK; + case DDS_KIND_PUBLISHER: + return DDS_PUBLISHER_QOS_MASK; + case DDS_KIND_DONTCARE: + case DDS_KIND_COND_READ: + case DDS_KIND_COND_QUERY: + case DDS_KIND_COND_GUARD: + case DDS_KIND_WAITSET: + break; + } + return 0; +} + dds_return_t dds_get_qos (dds_entity_t entity, dds_qos_t *qos) { dds_entity *e; @@ -362,29 +390,159 @@ dds_return_t dds_get_qos (dds_entity_t entity, dds_qos_t *qos) return ret; } +static dds_return_t dds_set_qos_locked_impl (dds_entity *e, const dds_qos_t *qos, uint64_t mask) +{ + dds_return_t ret; + 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 (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?) */ + 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 + { + /* yay! */ + } + } + + if (ret != DDS_RETCODE_OK) + dds_delete_qos (newqos); + else if ((ret = e->m_deriver.set_qos (e, newqos, e->m_flags & DDS_ENTITY_ENABLED)) != DDS_RETCODE_OK) + dds_delete_qos (newqos); + else + { + dds_delete_qos (e->m_qos); + e->m_qos = newqos; + } + return ret; +} + +static void pushdown_pubsub_qos (dds_entity_t entity) +{ + dds_entity_t *cs = NULL; + int ncs, size = 0; + while ((ncs = dds_get_children (entity, cs, (size_t) size)) > size) + { + size = ncs; + cs = ddsrt_realloc (cs, (size_t) size * sizeof (*cs)); + } + for (int i = 0; i < ncs; i++) + { + dds_entity *e; + if (dds_entity_lock (cs[i], DDS_KIND_DONTCARE, &e) == DDS_RETCODE_OK) + { + if (dds_entity_kind (e) == DDS_KIND_READER || dds_entity_kind (e) == DDS_KIND_WRITER) + { + dds_entity *pe; + if (dds_entity_lock (entity, DDS_KIND_DONTCARE, &pe) == DDS_RETCODE_OK) + { + dds_set_qos_locked_impl (e, pe->m_qos, QP_GROUP_DATA | QP_PARTITION); + dds_entity_unlock (pe); + } + } + dds_entity_unlock (e); + } + } + ddsrt_free (cs); +} + +static void pushdown_topic_qos (dds_entity_t parent, dds_entity_t topic) +{ + dds_entity_t *cs = NULL; + int ncs, size = 0; + while ((ncs = dds_get_children (parent, cs, (size_t) size)) > size) + { + size = ncs; + cs = ddsrt_realloc (cs, (size_t) size * sizeof (*cs)); + } + for (int i = 0; i < ncs; i++) + { + dds_entity *e; + if (dds_entity_lock (cs[i], DDS_KIND_DONTCARE, &e) == DDS_RETCODE_OK) + { + enum { NOP, PROP, CHANGE } todo; + switch (dds_entity_kind (e)) + { + case DDS_KIND_READER: { + dds_reader *rd = (dds_reader *) e; + todo = (rd->m_topic->m_entity.m_hdllink.hdl == topic) ? CHANGE : NOP; + break; + } + case DDS_KIND_WRITER: { + dds_writer *wr = (dds_writer *) e; + todo = (wr->m_topic->m_entity.m_hdllink.hdl == topic) ? CHANGE : NOP; + break; + case DDS_KIND_PUBLISHER: + case DDS_KIND_SUBSCRIBER: + todo = PROP; + break; + default: + todo = NOP; + break; + } + } + if (todo == CHANGE) + { + dds_topic *tp; + if (dds_topic_lock (topic, &tp) == DDS_RETCODE_OK) + { + dds_set_qos_locked_impl (e, tp->m_entity.m_qos, QP_TOPIC_DATA); + dds_topic_unlock (tp); + } + } + dds_entity_unlock (e); + if (todo == PROP) + { + pushdown_topic_qos (cs[i], topic); + } + } + } + ddsrt_free (cs); +} + dds_return_t dds_set_qos (dds_entity_t entity, const dds_qos_t *qos) { dds_entity *e; dds_return_t ret; - if (qos == NULL) return DDS_RETCODE_BAD_PARAMETER; - - if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + else if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) return ret; - - if (e->m_deriver.set_qos == 0) - ret = DDS_RETCODE_ILLEGAL_OPERATION; else { - if ((ret = e->m_deriver.set_qos (e, qos, e->m_flags & DDS_ENTITY_ENABLED)) == DDS_RETCODE_OK) + const dds_entity_kind_t kind = dds_entity_kind (e); + dds_entity_t pphandle = e->m_participant->m_hdllink.hdl; + if (e->m_deriver.set_qos == 0) + ret = DDS_RETCODE_ILLEGAL_OPERATION; + else + ret = dds_set_qos_locked_impl (e, qos, entity_kind_qos_mask (kind)); + dds_entity_unlock (e); + if (ret == DDS_RETCODE_OK) { - if (e->m_qos == NULL) - e->m_qos = dds_create_qos (); - ret = dds_copy_qos (e->m_qos, qos); + switch (dds_entity_kind (e)) + { + case DDS_KIND_TOPIC: + pushdown_topic_qos (pphandle, entity); + break; + case DDS_KIND_PUBLISHER: + case DDS_KIND_SUBSCRIBER: + pushdown_pubsub_qos (entity); + break; + default: + break; + } } } - dds_entity_unlock (e); return ret; } diff --git a/src/core/ddsc/src/dds_matched.c b/src/core/ddsc/src/dds_matched.c index 327ec56..10fb690 100644 --- a/src/core/ddsc/src/dds_matched.c +++ b/src/core/ddsc/src/dds_matched.c @@ -21,7 +21,6 @@ #include "dds/ddsi/q_bswap.h" #include "dds__writer.h" #include "dds__reader.h" -#include "dds__qos.h" #include "dds__topic.h" dds_return_t dds_get_matched_subscriptions (dds_entity_t writer, dds_instance_handle_t *rds, size_t nrds) diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 614ec59..fea399b 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -16,16 +16,18 @@ #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__init.h" -#include "dds__qos.h" #include "dds__domain.h" #include "dds__participant.h" #include "dds__builtin.h" +#include "dds__qos.h" DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_participant) #define DDS_PARTICIPANT_STATUS_MASK (0u) + /* List of created participants */ static dds_entity *dds_pp_head = NULL; @@ -70,28 +72,24 @@ static dds_return_t dds_participant_instance_hdl (dds_entity *e, dds_instance_ha return DDS_RETCODE_OK; } -static dds_return_t dds_participant_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; - -static dds_return_t dds_participant_qos_validate (const dds_qos_t *qos, bool enabled) -{ - dds_return_t ret; - (void)enabled; - if ((ret = nn_xqos_valid (qos)) < 0) - return ret; - return DDS_RETCODE_OK; -} - -static dds_return_t dds_participant_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; - static dds_return_t dds_participant_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) { - dds_return_t ret; - (void)e; - if ((ret = dds_participant_qos_validate (qos, enabled)) != DDS_RETCODE_OK) - return ret; - if (enabled) /* FIXME: changing QoS */ - return DDS_RETCODE_UNSUPPORTED; - return ret; + /* note: e->m_qos is still the old one to allow for failure here */ + if (enabled) + { + struct participant *pp; + thread_state_awake (lookup_thread_state ()); + if ((pp = ephash_lookup_participant_guid (&e->m_guid)) != NULL) + { + nn_plist_t plist; + nn_plist_init_empty (&plist); + plist.qos.present = plist.qos.aliased = qos->present; + plist.qos = *qos; + update_participant_plist (pp, &plist); + } + thread_state_asleep (lookup_thread_state ()); + } + return DDS_RETCODE_OK; } dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_t *qos, const dds_listener_t *listener) @@ -110,13 +108,11 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_ if ((ret = dds__check_domain (domain)) != DDS_RETCODE_OK) goto err_domain_check; - -#define DDS_QOSMASK_PARTICIPANT (QP_USER_DATA | QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL) new_qos = dds_create_qos (); if (qos != NULL) - nn_xqos_mergein_missing (new_qos, qos, DDS_QOSMASK_PARTICIPANT); - /* Validate qos or use default if NULL */ - if ((ret = dds_participant_qos_validate (new_qos, false)) != DDS_RETCODE_OK) + nn_xqos_mergein_missing (new_qos, qos, DDS_PARTICIPANT_QOS_MASK); + nn_xqos_mergein_missing (new_qos, &gv.default_plist_pp.qos, ~(uint64_t)0); + if ((ret = nn_xqos_valid (new_qos)) < 0) goto err_qos_validation; /* Translate qos */ diff --git a/src/core/ddsc/src/dds_publisher.c b/src/core/ddsc/src/dds_publisher.c index bbaa4c5..307a40b 100644 --- a/src/core/ddsc/src/dds_publisher.c +++ b/src/core/ddsc/src/dds_publisher.c @@ -29,34 +29,14 @@ static dds_return_t dds_publisher_instance_hdl (dds_entity *e, dds_instance_hand static dds_return_t dds_publisher_instance_hdl (dds_entity *e, dds_instance_handle_t *i) { /* FIXME: Get/generate proper handle. */ - (void) e; - (void) i; + (void) e; (void) i; return DDS_RETCODE_UNSUPPORTED; } -static dds_return_t dds_publisher_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; - -static dds_return_t dds_publisher_qos_validate (const dds_qos_t *qos, bool enabled) -{ - dds_return_t ret; - if ((ret = nn_xqos_valid (qos)) < 0) - return ret; - /* FIXME: Improve/check immutable check. */ - if (enabled && (qos->present & QP_PRESENTATION)) - return DDS_RETCODE_IMMUTABLE_POLICY; - return DDS_RETCODE_OK; -} - -static dds_return_t dds_publisher_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; - static dds_return_t dds_publisher_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) { - dds_return_t ret; - (void)e; - if ((ret = dds_publisher_qos_validate (qos, enabled)) != DDS_RETCODE_OK) - return ret; - if (enabled) /* FIXME: QoS changes. */ - return DDS_RETCODE_UNSUPPORTED; + /* note: e->m_qos is still the old one to allow for failure here */ + (void) e; (void) qos; (void) enabled; return DDS_RETCODE_OK; } @@ -73,12 +53,11 @@ dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qo dds_qos_t *new_qos; dds_return_t ret; -#define DDS_QOSMASK_PUBLISHER (QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL) new_qos = dds_create_qos (); if (qos) - nn_xqos_mergein_missing (new_qos, qos, DDS_QOSMASK_PUBLISHER); + nn_xqos_mergein_missing (new_qos, qos, DDS_PUBLISHER_QOS_MASK); nn_xqos_mergein_missing (new_qos, &gv.default_xqos_pub, ~(uint64_t)0); - if ((ret = dds_publisher_qos_validate (new_qos, false)) != DDS_RETCODE_OK) + if ((ret = nn_xqos_valid (new_qos)) != DDS_RETCODE_OK) { dds_delete_qos (new_qos); return ret; diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index a67329e..a9c0296 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -11,10 +11,11 @@ */ #include #include -#include "dds__qos.h" +#include +#include "dds/dds.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" -#include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_plist.h" static void dds_qos_data_copy_in (ddsi_octetseq_t *data, const void * __restrict value, size_t sz, bool overwrite) { @@ -47,26 +48,6 @@ static bool dds_qos_data_copy_out (const ddsi_octetseq_t *data, void **value, si return true; } -dds_return_t dds_qos_validate_mutable_common (const dds_qos_t *qos) -{ - /* FIXME: Check whether immutable QoS are changed should actually incorporate change to current QoS */ - if (qos->present & QP_DEADLINE) - return DDS_RETCODE_IMMUTABLE_POLICY; - if (qos->present & QP_OWNERSHIP) - return DDS_RETCODE_IMMUTABLE_POLICY; - if (qos->present & QP_LIVELINESS) - return DDS_RETCODE_IMMUTABLE_POLICY; - if (qos->present & QP_RELIABILITY) - return DDS_RETCODE_IMMUTABLE_POLICY; - if (qos->present & QP_DESTINATION_ORDER) - return DDS_RETCODE_IMMUTABLE_POLICY; - if (qos->present & QP_HISTORY) - return DDS_RETCODE_IMMUTABLE_POLICY; - if (qos->present & QP_RESOURCE_LIMITS) - return DDS_RETCODE_IMMUTABLE_POLICY; - return DDS_RETCODE_OK; -} - dds_qos_t *dds_create_qos (void) { dds_qos_t *qos = ddsrt_malloc (sizeof (dds_qos_t)); diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index b5896ad..9fcecd6 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -17,11 +17,11 @@ #include "dds__subscriber.h" #include "dds__reader.h" #include "dds__listener.h" -#include "dds__qos.h" #include "dds__init.h" #include "dds__rhc.h" #include "dds__topic.h" #include "dds__get_status.h" +#include "dds__qos.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_globals.h" @@ -77,26 +77,18 @@ static dds_return_t dds_reader_delete (dds_entity *e) return ret; } -static dds_return_t dds_reader_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; - -static dds_return_t dds_reader_qos_validate (const dds_qos_t *qos, bool enabled) -{ - dds_return_t ret; - if ((ret = nn_xqos_valid (qos)) < 0) - return ret; - return (enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK); -} - -static dds_return_t dds_reader_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; - static dds_return_t dds_reader_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) { - dds_return_t ret; - (void) e; - if ((ret = dds_reader_qos_validate (qos, enabled)) != DDS_RETCODE_OK) - return ret; - /* FIXME: QoS changes. */ - return (enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK); + /* note: e->m_qos is still the old one to allow for failure here */ + if (enabled) + { + struct reader *rd; + thread_state_awake (lookup_thread_state ()); + if ((rd = ephash_lookup_reader_guid (&e->m_guid)) != NULL) + update_reader_qos (rd, qos); + thread_state_asleep (lookup_thread_state ()); + } + return DDS_RETCODE_OK; } static dds_return_t dds_reader_status_validate (uint32_t mask) @@ -363,17 +355,16 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti /* 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 */ -#define DDS_QOSMASK_READER (QP_USER_DATA | QP_DURABILITY | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_LIVELINESS | QP_TIME_BASED_FILTER | QP_RELIABILITY | QP_DESTINATION_ORDER | QP_HISTORY | QP_RESOURCE_LIMITS | QP_PRISMTECH_READER_DATA_LIFECYCLE | QP_CYCLONE_IGNORELOCAL) rqos = dds_create_qos (); if (qos) - nn_xqos_mergein_missing (rqos, qos, DDS_QOSMASK_READER); + 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); nn_xqos_mergein_missing (rqos, &gv.default_xqos_rd, ~(uint64_t)0); - if ((ret = dds_reader_qos_validate (rqos, false)) != DDS_RETCODE_OK) + if ((ret = nn_xqos_valid (rqos)) != DDS_RETCODE_OK) { dds_delete_qos (rqos); reader = ret; diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index b95df6e..b1b7e01 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -190,21 +190,13 @@ static char *dds_string_dup_reuse (char *old, const char *src) static dds_qos_t *dds_qos_from_xqos_reuse (dds_qos_t *old, const dds_qos_t *src) { if (old == NULL) - { old = ddsrt_malloc (sizeof (*old)); - nn_xqos_init_empty (old); - old->present |= QP_TOPIC_NAME | QP_TYPE_NAME; - nn_xqos_mergein_missing (old, src, ~(uint64_t)0); - old->present &= ~(QP_TOPIC_NAME | QP_TYPE_NAME); - } else { nn_xqos_fini (old); - nn_xqos_init_empty (old); - old->present |= QP_TOPIC_NAME | QP_TYPE_NAME; - nn_xqos_mergein_missing (old, src, ~(uint64_t)0); - old->present &= ~(QP_TOPIC_NAME | QP_TYPE_NAME); } + nn_xqos_init_empty (old); + nn_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 1054ef6..181a6af 100644 --- a/src/core/ddsc/src/dds_subscriber.c +++ b/src/core/ddsc/src/dds_subscriber.c @@ -12,8 +12,8 @@ #include #include "dds__listener.h" #include "dds__participant.h" -#include "dds__qos.h" #include "dds__subscriber.h" +#include "dds__qos.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_globals.h" #include "dds/version.h" @@ -27,32 +27,16 @@ static dds_return_t dds_subscriber_instance_hdl (dds_entity *e, dds_instance_han static dds_return_t dds_subscriber_instance_hdl (dds_entity *e, dds_instance_handle_t *i) { - (void) e; - (void) i; + (void) e; (void) i; /* FIXME: Get/generate proper handle. */ return DDS_RETCODE_UNSUPPORTED; } -static dds_return_t dds__subscriber_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; - -static dds_return_t dds__subscriber_qos_validate (const dds_qos_t *qos, bool enabled) -{ - dds_return_t ret; - if ((ret = nn_xqos_valid (qos)) < 0) - return ret; - return (enabled && (qos->present & QP_PRESENTATION)) ? DDS_RETCODE_IMMUTABLE_POLICY : DDS_RETCODE_OK; -} - -static dds_return_t dds_subscriber_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; - static dds_return_t dds_subscriber_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) { - /* FIXME: QoS changes. */ - dds_return_t ret; - (void) e; - if ((ret = dds__subscriber_qos_validate (qos, enabled)) != DDS_RETCODE_OK) - return ret; - return (enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK); + /* note: e->m_qos is still the old one to allow for failure here */ + (void) e; (void) qos; (void) enabled; + return DDS_RETCODE_OK; } static dds_return_t dds_subscriber_status_validate (uint32_t mask) @@ -68,12 +52,11 @@ dds_entity_t dds__create_subscriber_l (dds_participant *participant, const dds_q dds_return_t ret; dds_qos_t *new_qos; -#define DDS_QOSMASK_SUBSCRIBER (QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL) new_qos = dds_create_qos (); if (qos) - nn_xqos_mergein_missing (new_qos, qos, DDS_QOSMASK_SUBSCRIBER); + nn_xqos_mergein_missing (new_qos, qos, DDS_SUBSCRIBER_QOS_MASK); nn_xqos_mergein_missing (new_qos, &gv.default_xqos_sub, ~(uint64_t)0); - if ((ret = dds__subscriber_qos_validate (new_qos, false)) != DDS_RETCODE_OK) + if ((ret = nn_xqos_valid (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 7804a67..90bf553 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -18,12 +18,12 @@ #include "dds/ddsrt/string.h" #include "dds__topic.h" #include "dds__listener.h" -#include "dds__qos.h" #include "dds__participant.h" #include "dds__stream.h" #include "dds__init.h" #include "dds__domain.h" #include "dds__get_status.h" +#include "dds__qos.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/ddsi_sertopic.h" @@ -182,25 +182,11 @@ static dds_return_t dds_topic_delete (dds_entity *e) return DDS_RETCODE_OK; } -static dds_return_t dds_topic_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; - -static dds_return_t dds_topic_qos_validate (const dds_qos_t *qos, bool enabled) -{ - dds_return_t ret; - if ((ret = nn_xqos_valid (qos)) < 0) - return ret; - return enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK; -} - - static dds_return_t dds_topic_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) { - /* FIXME: QoS changes */ - dds_return_t ret; - (void) e; - if ((ret = dds_topic_qos_validate (qos, enabled)) != DDS_RETCODE_OK) - return ret; - return enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK; + /* note: e->m_qos is still the old one to allow for failure here */ + (void) e; (void) qos; (void) enabled; + return DDS_RETCODE_OK; } static bool dupdef_qos_ok (const dds_qos_t *qos, const struct ddsi_sertopic *st) @@ -239,13 +225,25 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s if (sertopic == NULL) return DDS_RETCODE_BAD_PARAMETER; - if (qos && (rc = dds_topic_qos_validate (qos, false)) != DDS_RETCODE_OK) - return rc; + new_qos = dds_create_qos (); + if (qos) + nn_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); + * + * but the crazy defaults of the DDS specification has a default settings + * for reliability that are 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 (new_qos)) != DDS_RETCODE_OK) + goto err_invalid_qos; if ((rc = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK) - return rc; - - /* FIXME: I find it weird that qos may be NULL in the entity */ + goto err_lock_participant; /* Check if topic already exists with same name */ ddsrt_mutex_lock (&dds_global.m_mutex); @@ -254,27 +252,22 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */ rc = DDS_RETCODE_PRECONDITION_NOT_MET; goto err_mismatch; - } else if (!dupdef_qos_ok(qos, stgeneric)) { + } else if (!dupdef_qos_ok (new_qos, stgeneric)) { /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */ rc = DDS_RETCODE_INCONSISTENT_POLICY; goto err_mismatch; } else { /* FIXME: calling addref is wrong because the Cyclone library has no - knowledge of the reference and hence simply deleting the participant - won't make the ref count drop to 0. On the other hand, the DDS spec - says find_topic (and a second call to create_topic) return a new - proxy that must separately be deleted. */ + knowledge of the reference and hence simply deleting the participant + won't make the ref count drop to 0. On the other hand, the DDS spec + says find_topic (and a second call to create_topic) return a new + proxy that must separately be deleted. */ dds_entity_add_ref (&stgeneric->status_cb_entity->m_entity); hdl = stgeneric->status_cb_entity->m_entity.m_hdllink.hdl; + dds_delete_qos (new_qos); } ddsrt_mutex_unlock (&dds_global.m_mutex); } else { - if (qos) - { - new_qos = dds_create_qos (); - (void)dds_copy_qos (new_qos, qos); - } - /* Create topic */ top = dds_alloc (sizeof (*top)); hdl = dds_entity_init (&top->m_entity, &par->m_entity, DDS_KIND_TOPIC, new_qos, listener, DDS_TOPIC_STATUS_MASK); @@ -293,7 +286,14 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s ddsi_pp = ephash_lookup_participant_guid (&par->m_entity.m_guid); assert (ddsi_pp); if (sedp_plist) - sedp_write_topic (ddsi_pp, 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_participant_unlock (par); @@ -302,6 +302,9 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s err_mismatch: ddsrt_mutex_unlock (&dds_global.m_mutex); dds_participant_unlock (par); +err_lock_participant: +err_invalid_qos: + dds_delete_qos (new_qos); return rc; } @@ -310,7 +313,6 @@ dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descrip char *key = NULL; struct ddsi_sertopic_default *st; const char *typename; - dds_qos_t *new_qos = NULL; nn_plist_t plist; dds_entity_t hdl; size_t keysz; @@ -346,12 +348,7 @@ dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descrip st->opt_size = dds_stream_check_optimize (desc); } -#define DDS_QOSMASK_TOPIC (QP_TOPIC_DATA | QP_DURABILITY | QP_DURABILITY_SERVICE | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_LIVELINESS | QP_RELIABILITY | QP_TRANSPORT_PRIORITY | QP_LIFESPAN | QP_DESTINATION_ORDER | QP_HISTORY | QP_RESOURCE_LIMITS) nn_plist_init_empty (&plist); - if (new_qos) - nn_xqos_mergein_missing (&plist.qos, new_qos, DDS_QOSMASK_TOPIC); - nn_xqos_mergein_missing (&plist.qos, &gv.default_xqos_tp, DDS_QOSMASK_TOPIC); - /* 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); diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 847e85a..bf55b18 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -20,11 +20,11 @@ #include "dds/ddsi/q_xmsg.h" #include "dds__writer.h" #include "dds__listener.h" -#include "dds__qos.h" #include "dds__init.h" #include "dds__publisher.h" #include "dds__topic.h" #include "dds__get_status.h" +#include "dds__qos.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds__whc.h" @@ -206,48 +206,18 @@ static dds_return_t dds_writer_delete (dds_entity *e) return ret; } -static dds_return_t dds_writer_qos_validate (const dds_qos_t *qos, bool enabled) -{ - dds_return_t ret; - if ((ret = nn_xqos_valid (qos)) < 0) - return ret; - return enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK; -} - static dds_return_t dds_writer_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) { - /* FIXME: QoS changes */ - dds_return_t ret; - - if ((ret = dds_writer_qos_validate (qos, enabled)) != DDS_RETCODE_OK) - return ret; - - /* Sort-of support updating ownership strength */ - if ((qos->present & QP_OWNERSHIP_STRENGTH) && (qos->present & ~QP_OWNERSHIP_STRENGTH) == 0) + /* note: e->m_qos is still the old one to allow for failure here */ + if (enabled) { - dds_ownership_kind_t kind; - dds_qget_ownership (e->m_qos, &kind); - - if (kind != DDS_OWNERSHIP_EXCLUSIVE) - return DDS_RETCODE_ERROR; - - struct writer *ddsi_wr = ((dds_writer *) e)->m_wr; - dds_qset_ownership_strength (e->m_qos, qos->ownership_strength.value); - + struct writer *wr; thread_state_awake (lookup_thread_state ()); - - /* FIXME: with QoS changes being unsupported by the underlying stack I wonder what will happen; locking the underlying DDSI writer is of doubtful value as well */ - ddsrt_mutex_lock (&ddsi_wr->e.lock); - ddsi_wr->xqos->ownership_strength.value = qos->ownership_strength.value; - ddsrt_mutex_unlock (&ddsi_wr->e.lock); + if ((wr = ephash_lookup_writer_guid (&e->m_guid)) != NULL) + update_writer_qos (wr, qos); thread_state_asleep (lookup_thread_state ()); } - else - { - if (enabled) - ret = DDS_RETCODE_UNSUPPORTED; - } - return ret; + return DDS_RETCODE_OK; } static struct whc *make_whc (const dds_qos_t *qos) @@ -309,17 +279,16 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit assert (pub->m_entity.m_domain == tp->m_entity.m_domain); /* Merge Topic & Publisher qos */ -#define DDS_QOSMASK_WRITER (QP_USER_DATA | QP_DURABILITY | QP_DURABILITY_SERVICE | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_OWNERSHIP_STRENGTH | QP_LIVELINESS | QP_RELIABILITY | QP_TRANSPORT_PRIORITY | QP_LIFESPAN | QP_DESTINATION_ORDER | QP_HISTORY | QP_RESOURCE_LIMITS | QP_PRISMTECH_WRITER_DATA_LIFECYCLE | QP_CYCLONE_IGNORELOCAL) wqos = dds_create_qos (); if (qos) - nn_xqos_mergein_missing (wqos, qos, DDS_QOSMASK_WRITER); + 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); nn_xqos_mergein_missing (wqos, &gv.default_xqos_wr, ~(uint64_t)0); - if ((rc = dds_writer_qos_validate (wqos, false)) != DDS_RETCODE_OK) + if ((rc = nn_xqos_valid (wqos)) < 0) { dds_delete_qos(wqos); goto err_bad_qos; diff --git a/src/core/ddsc/tests/entity_api.c b/src/core/ddsc/tests/entity_api.c index fa098b5..f3241ac 100644 --- a/src/core/ddsc/tests/entity_api.c +++ b/src/core/ddsc/tests/entity_api.c @@ -78,7 +78,7 @@ void entity_qos_get_set(dds_entity_t e, const char* info) CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); status = dds_set_qos (e, qos); /* Doesn't change anything, so no need to forbid. But we return NOT_SUPPORTED anyway for now*/ - CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_UNSUPPORTED); + CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); dds_delete_qos(qos); } diff --git a/src/core/ddsc/tests/unsupported.c b/src/core/ddsc/tests/unsupported.c index 279e8cd..417302a 100644 --- a/src/core/ddsc/tests/unsupported.c +++ b/src/core/ddsc/tests/unsupported.c @@ -76,7 +76,7 @@ CU_Test(ddsc_unsupported, dds_begin_end_coherent, .init = setup, .fini = teardow {BAD, DDS_RETCODE_BAD_PARAMETER} }; - for (int i=0; i < 5; i++) { + for (size_t i=0; i < sizeof (pars) / sizeof (pars[0]);i++) { result = dds_begin_coherent(e[pars[i].index]); CU_ASSERT_EQUAL(result, pars[i].exp_res); result = dds_end_coherent(e[pars[i].index]); @@ -93,7 +93,7 @@ CU_Test(ddsc_unsupported, dds_wait_for_acks, .init = setup, .fini = teardown) {BAD, DDS_RETCODE_BAD_PARAMETER} }; - for (int i=0; i< 3; i++) { + 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); } @@ -108,7 +108,7 @@ CU_Test(ddsc_unsupported, dds_suspend_resume, .init = setup, .fini = teardown) {BAD, DDS_RETCODE_BAD_PARAMETER} }; - for (int i=0; i< 3; i++) { + for (size_t i=0; i < sizeof (pars) / sizeof (pars[0]);i++) { result = dds_suspend(e[pars[i].index]); CU_ASSERT_EQUAL(result, pars[i].exp_res); result = dds_resume(e[pars[i].index]); @@ -128,7 +128,7 @@ CU_Test(ddsc_unsupported, dds_get_instance_handle, .init = setup, .fini = teardo {BAD, DDS_RETCODE_BAD_PARAMETER} }; - for (int i=0; i < 5; i++) { + for (size_t i=0; i < sizeof (pars) / sizeof (pars[0]);i++) { result = dds_get_instance_handle(e[pars[i].index], &ih); CU_ASSERT_EQUAL(result, pars[i].exp_res); } @@ -139,18 +139,12 @@ CU_Test(ddsc_unsupported, dds_set_qos, .init = setup, .fini = teardown) dds_return_t result; dds_qos_t *qos; static struct index_result pars[] = { - {PAR, DDS_RETCODE_UNSUPPORTED}, - {TOP, DDS_RETCODE_UNSUPPORTED}, - {PUB, DDS_RETCODE_UNSUPPORTED}, - {WRI, DDS_RETCODE_UNSUPPORTED}, - {SUB, DDS_RETCODE_UNSUPPORTED}, - {REA, DDS_RETCODE_UNSUPPORTED}, {RCD, DDS_RETCODE_ILLEGAL_OPERATION}, {BAD, DDS_RETCODE_BAD_PARAMETER} }; qos = dds_create_qos(); - for (int i=0; i < 8;i++) { + for (size_t i=0; i < sizeof (pars) / sizeof (pars[0]);i++) { result = dds_set_qos(e[pars[i].index], qos); CU_ASSERT_EQUAL(result, pars[i].exp_res); } diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 5011b2e..bb55315 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -301,6 +301,7 @@ struct proxy_participant struct addrset *as_meta; /* default address set to use for discovery traffic */ struct proxy_endpoint_common *endpoints; /* all proxy endpoints can be reached from here */ ddsrt_avl_tree_t groups; /* table of all groups (publisher, subscriber), see struct proxy_group */ + seqno_t seq; /* sequence number of most recent SPDP message */ unsigned kernel_sequence_numbers : 1; /* whether this proxy participant generates OSPL kernel sequence numbers */ unsigned implicitly_created : 1; /* participants are implicitly created for Cloud/Fog discovered endpoints */ unsigned is_ddsi2_pp: 1; /* if this is the federation-leader on the remote node */ @@ -527,6 +528,7 @@ dds_return_t new_participant (struct nn_guid *ppguid, unsigned flags, const stru * ppguid lookup failed. */ dds_return_t delete_participant (const struct nn_guid *ppguid); +void update_participant_plist (struct participant *pp, const struct nn_plist *plist); /* To obtain the builtin writer to be used for publishing SPDP, SEDP, PMD stuff for PP and its endpoints, given the entityid. If PP has @@ -541,6 +543,9 @@ dds_return_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const s dds_return_t new_reader (struct reader **rd_out, struct nn_guid *rdguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct rhc * rhc, status_cb_t status_cb, void *status_cb_arg); +void update_reader_qos (struct reader *rd, const struct dds_qos *xqos); +void update_writer_qos (struct writer *wr, const struct dds_qos *xqos); + struct whc_node; struct whc_state; unsigned remove_acked_messages (struct writer *wr, struct whc_state *whcst, struct whc_node **deferred_free_list); @@ -586,7 +591,7 @@ 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 (const struct nn_guid *guid, unsigned bes, unsigned prismtech_bes, const struct nn_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct nn_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp); +void new_proxy_participant (const struct nn_guid *guid, unsigned bes, unsigned prismtech_bes, const struct nn_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct nn_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq); int delete_proxy_participant_by_guid (const struct nn_guid * guid, nn_wctime_t timestamp, int isimplicit); uint64_t participant_instance_id (const struct nn_guid *guid); @@ -595,8 +600,8 @@ enum update_proxy_participant_source { UPD_PROXYPP_CM }; -int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, const struct nn_plist *datap, enum update_proxy_participant_source source, nn_wctime_t timestamp); -int update_proxy_participant_plist (struct proxy_participant *proxypp, 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, 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); void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct lease *newlease); void purge_proxy_participants (const nn_locator_t *loc, bool delete_from_as_disc); @@ -618,8 +623,8 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, int delete_proxy_writer (const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit); int delete_proxy_reader (const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit); -void update_proxy_reader (struct proxy_reader * prd, struct addrset *as); -void update_proxy_writer (struct proxy_writer * pwr, struct addrset *as); +void update_proxy_reader (struct proxy_reader *prd, struct addrset *as, const struct dds_qos *xqos, nn_wctime_t timestamp); +void update_proxy_writer (struct proxy_writer *pwr, struct addrset *as, const struct dds_qos *xqos, nn_wctime_t timestamp); int new_proxy_group (const struct nn_guid *guid, const char *name, const struct dds_qos *xqos, nn_wctime_t timestamp); void delete_proxy_group (const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit); diff --git a/src/core/ddsi/include/dds/ddsi/q_xqos.h b/src/core/ddsi/include/dds/ddsi/q_xqos.h index 7b5e8ea..e34fb58 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xqos.h +++ b/src/core/ddsi/include/dds/ddsi/q_xqos.h @@ -277,6 +277,7 @@ 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 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); diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 9218611..5df36a1 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -506,7 +506,7 @@ static void make_participants_dependent_on_ddsi2 (const nn_guid_t *ddsi2guid, nn } } -static int handle_SPDP_alive (const struct receiver_state *rst, 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 nn_plist_t *datap) { const unsigned bes_sedp_announcer_mask = NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER | @@ -593,11 +593,14 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time DDS_LOG(DDS_LC_TRACE, "SPDP ST0 "PGUIDFMT" (known)", PGUID (datap->participant_guid)); lease_renew (ddsrt_atomic_ldvoidp (&proxypp->lease), now_et ()); ddsrt_mutex_lock (&proxypp->e.lock); - if (proxypp->implicitly_created) + if (proxypp->implicitly_created || seq > proxypp->seq) { - DDS_LOG(DDS_LC_DISCOVERY, " (NEW was-implicitly-created)"); + if (proxypp->implicitly_created) + DDS_LOG(DDS_LC_DISCOVERY, " (NEW was-implicitly-created)"); + else + DDS_LOG(DDS_LC_DISCOVERY, " (update)"); proxypp->implicitly_created = 0; - update_proxy_participant_plist_locked (proxypp, datap, UPD_PROXYPP_SPDP, timestamp); + update_proxy_participant_plist_locked (proxypp, seq, datap, UPD_PROXYPP_SPDP, timestamp); } ddsrt_mutex_unlock (&proxypp->e.lock); return 0; @@ -739,7 +742,8 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time lease_duration, rst->vendor, custom_flags, - timestamp + timestamp, + seq ); /* Force transmission of SPDP messages - we're not very careful @@ -779,7 +783,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time return 1; } -static void handle_SPDP (const struct receiver_state *rst, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len) +static void handle_SPDP (const struct receiver_state *rst, seqno_t seq, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len) { const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ DDS_TRACE("SPDP ST%x", statusinfo); @@ -809,7 +813,7 @@ static void handle_SPDP (const struct receiver_state *rst, nn_wctime_t timestamp switch (statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER)) { case 0: - interesting = handle_SPDP_alive (rst, timestamp, &decoded_data); + interesting = handle_SPDP_alive (rst, seq, timestamp, &decoded_data); break; case NN_STATUSINFO_DISPOSE: @@ -1019,7 +1023,7 @@ static const char *durability_to_string (dds_durability_kind_t k) return "undefined-durability"; } -static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppguid, nn_plist_t *datap /* note: potentially modifies datap */, const nn_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp) +static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppguid, nn_plist_t *datap /* note: potentially modifies datap */, const nn_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp, seqno_t seq) { nn_guid_t privguid; nn_plist_t pp_plist; @@ -1056,7 +1060,7 @@ static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppg 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(ppguid, 0, 0, &privguid, new_addrset(), new_addrset(), &pp_plist, T_NEVER, actual_vendorid, CF_IMPLICITLY_CREATED_PROXYPP, timestamp); + new_proxy_participant(ppguid, 0, 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)) { @@ -1090,7 +1094,7 @@ static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppg ddsrt_mutex_unlock (&privpp->e.lock); pp_plist.prismtech_participant_version_info.flags &= ~NN_PRISMTECH_FL_PARTICIPANT_IS_DDSI2; - new_proxy_participant (ppguid, 0, 0, &privguid, as_default, as_meta, &pp_plist, T_NEVER, vendorid, CF_IMPLICITLY_CREATED_PROXYPP | CF_PROXYPP_NO_SPDP, timestamp); + new_proxy_participant (ppguid, 0, 0, &privguid, as_default, as_meta, &pp_plist, T_NEVER, vendorid, CF_IMPLICITLY_CREATED_PROXYPP | CF_PROXYPP_NO_SPDP, timestamp, seq); } } @@ -1138,7 +1142,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat if ((pp = ephash_lookup_proxy_participant_guid (&ppguid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, " unknown-proxypp"); - if ((pp = implicitly_create_proxypp (&ppguid, datap, src_guid_prefix, vendorid, timestamp)) == NULL) + if ((pp = implicitly_create_proxypp (&ppguid, datap, src_guid_prefix, vendorid, timestamp, 0)) == NULL) E ("?\n", err); /* Repeat regular SEDP trace for convenience */ DDS_LOG(DDS_LC_DISCOVERY, "SEDP ST0 "PGUIDFMT" (cont)", PGUID (datap->endpoint_guid)); @@ -1185,18 +1189,10 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat } if (pwr || prd) { - /* Cloud load balances by updating participant endpoints */ - - if (! vendor_is_cloud (vendorid)) - { - DDS_LOG(DDS_LC_DISCOVERY, " known\n"); - goto err; - } - /* Re-bind the proxy participant to the discovery service - and do this if it is currently bound to another DS instance, because that other DS instance may have already failed and with a new one taking over, without our noticing it. */ - DDS_LOG(DDS_LC_DISCOVERY, " known-DS"); + DDS_LOG(DDS_LC_DISCOVERY, " known%s", vendor_is_cloud (vendorid) ? "-DS" : ""); if (vendor_is_cloud (vendorid) && pp->implicitly_created && memcmp(&pp->privileged_pp_guid.prefix, src_guid_prefix, sizeof(pp->privileged_pp_guid.prefix)) != 0) { nn_etime_t never = { T_NEVER }; @@ -1261,7 +1257,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat { if (pwr) { - update_proxy_writer (pwr, as); + update_proxy_writer (pwr, as, xqos, timestamp); } else { @@ -1281,7 +1277,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat { if (prd) { - update_proxy_reader (prd, as); + update_proxy_reader (prd, as, xqos, timestamp); } else { @@ -1484,9 +1480,9 @@ static void handle_SEDP_CM (const struct receiver_state *rst, nn_entityid_t wr_e else { if ((proxypp = ephash_lookup_proxy_participant_guid (&decoded_data.participant_guid)) == NULL) - proxypp = implicitly_create_proxypp (&decoded_data.participant_guid, &decoded_data, &rst->src_guid_prefix, rst->vendor, timestamp); + proxypp = implicitly_create_proxypp (&decoded_data.participant_guid, &decoded_data, &rst->src_guid_prefix, rst->vendor, timestamp, 0); if (proxypp != NULL) - update_proxy_participant_plist (proxypp, &decoded_data, UPD_PROXYPP_CM, timestamp); + update_proxy_participant_plist (proxypp, 0, &decoded_data, UPD_PROXYPP_CM, timestamp); } } @@ -1864,7 +1860,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str switch (srcguid.entityid.u) { case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER: - handle_SPDP (sampleinfo->rst, timestamp, statusinfo, datap, datasz); + handle_SPDP (sampleinfo->rst, sampleinfo->seq, timestamp, statusinfo, datap, datasz); break; case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER: case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER: diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 5870a41..3ae6d2a 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -375,6 +375,36 @@ static void remove_deleted_participant_guid (const struct nn_guid *guid, unsigne /* PARTICIPANT ------------------------------------------------------ */ +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; + + mask = nn_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; + char *astr = (ent_qos->present & QP_TOPIC_DATA) ? (char *) ent_qos->topic_data.value : "(null)"; + char *bstr = (xqos->present & QP_TOPIC_DATA) ? (char *) xqos->topic_data.value : "(null)"; + printf ("%d: "PGUIDFMT" ent_qos %d \"%*.*s\" xqos %d \"%*.*s\" => mask %d\n", + (int) getpid (), PGUID (e->guid), + !!(ent_qos->present & QP_TOPIC_DATA), a, a, astr, + !!(xqos->present & QP_TOPIC_DATA), b, b, bstr, + !!(mask & QP_TOPIC_DATA)); +#endif + DDS_LOG (DDS_LC_DISCOVERY, "update_qos_locked "PGUIDFMT" delta=%"PRIu64" QOS={", PGUID(e->guid), mask); + nn_log_xqos(DDS_LC_DISCOVERY, xqos); + DDS_LOG (DDS_LC_DISCOVERY, "}\n"); + + if (mask == 0) + /* no change, or an as-yet unsupported one */ + return false; + + nn_xqos_fini_mask (ent_qos, mask); + nn_xqos_mergein_missing (ent_qos, xqos, mask); + ddsi_plugin.builtintopic_write (e, timestamp, true); + return true; +} + static dds_return_t pp_allocate_entityid(nn_entityid_t *id, unsigned kind, struct participant *pp) { uint32_t id1; @@ -674,6 +704,14 @@ dds_return_t new_participant (nn_guid_t *p_ppguid, unsigned flags, const nn_plis return new_participant_guid (p_ppguid, flags, plist); } +void update_participant_plist (struct participant *pp, const nn_plist_t *plist) +{ + ddsrt_mutex_lock (&pp->e.lock); + if (update_qos_locked (&pp->e, &pp->plist->qos, &plist->qos, now ())) + spdp_write (pp); + ddsrt_mutex_unlock (&pp->e.lock); +} + static void delete_builtin_endpoint (const struct nn_guid *ppguid, unsigned entityid) { nn_guid_t guid; @@ -2909,6 +2947,14 @@ struct local_orphan_writer *new_local_orphan_writer (nn_entityid_t entityid, str return lowr; } +void update_writer_qos (struct writer *wr, const dds_qos_t *xqos) +{ + ddsrt_mutex_lock (&wr->e.lock); + if (update_qos_locked (&wr->e, wr->xqos, xqos, now ())) + sedp_write_writer (wr); + ddsrt_mutex_unlock (&wr->e.lock); +} + static void gc_delete_writer (struct gcreq *gcreq) { struct writer *wr = gcreq->arg; @@ -3432,6 +3478,13 @@ uint64_t reader_instance_id (const struct nn_guid *guid) return 0; } +void update_reader_qos (struct reader *rd, const dds_qos_t *xqos) +{ + ddsrt_mutex_lock (&rd->e.lock); + if (update_qos_locked (&rd->e, rd->xqos, xqos, now ())) + sedp_write_reader (rd); + ddsrt_mutex_unlock (&rd->e.lock); +} /* PROXY-PARTICIPANT ------------------------------------------------ */ static void gc_proxy_participant_lease (struct gcreq *gcreq) @@ -3481,7 +3534,8 @@ void new_proxy_participant dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, - nn_wctime_t timestamp + nn_wctime_t timestamp, + seqno_t seq ) { /* No locking => iff all participants use unique guids, and sedp @@ -3503,6 +3557,7 @@ void new_proxy_participant 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; } else { @@ -3543,6 +3598,7 @@ void new_proxy_participant 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); ddsrt_avl_init (&proxypp_groups_treedef, &proxypp->groups); if (custom_flags & CF_INC_KERNEL_SEQUENCE_NUMBERS) @@ -3656,51 +3712,39 @@ void new_proxy_participant ddsrt_mutex_unlock (&proxypp->e.lock); } -int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, 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, enum update_proxy_participant_source source, nn_wctime_t timestamp) { - /* Currently, built-in processing is single-threaded, and it is only through this function and the proxy participant deletion (which necessarily happens when no-one else potentially references the proxy participant anymore). So at the moment, the lock is superfluous. */ - nn_plist_t *new_plist; + 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, &gv.default_plist_pp, ~(uint64_t)0, ~(uint64_t)0); - new_plist = nn_plist_dup (datap); - nn_plist_mergein_missing (new_plist, proxypp->plist, ~(uint64_t)0, ~(uint64_t)0); - nn_plist_fini (proxypp->plist); - ddsrt_free (proxypp->plist); - proxypp->plist = new_plist; + if (seq && seq > proxypp->seq) + proxypp->seq = seq; switch (source) { case UPD_PROXYPP_SPDP: - ddsi_plugin.builtintopic_write (&proxypp->e, timestamp, true); + 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; } - return 0; } -int update_proxy_participant_plist (struct proxy_participant *proxypp, 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) { - nn_plist_t tmp; - - /* FIXME: find a better way of restricting which bits can get updated */ ddsrt_mutex_lock (&proxypp->e.lock); - switch (source) - { - case UPD_PROXYPP_SPDP: - update_proxy_participant_plist_locked (proxypp, datap, source, timestamp); - break; - case UPD_PROXYPP_CM: - tmp = *datap; - tmp.present &= - PP_PRISMTECH_NODE_NAME | PP_PRISMTECH_EXEC_NAME | PP_PRISMTECH_PROCESS_ID | - PP_ENTITY_NAME; - tmp.qos.present &= QP_PRISMTECH_ENTITY_FACTORY; - update_proxy_participant_plist_locked (proxypp, &tmp, source, timestamp); - break; - } + update_proxy_participant_plist_locked (proxypp, seq, datap, source, timestamp); ddsrt_mutex_unlock (&proxypp->e.lock); return 0; } @@ -4064,7 +4108,6 @@ static void proxy_endpoint_common_init (struct entity_common *e, struct proxy_en else memset (&c->group_guid, 0, sizeof (c->group_guid)); - ref_proxy_participant (proxypp, c); } @@ -4175,7 +4218,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, return 0; } -void update_proxy_writer (struct proxy_writer * pwr, struct addrset * as) +void update_proxy_writer (struct proxy_writer *pwr, struct addrset *as, const struct dds_qos *xqos, nn_wctime_t timestamp) { struct reader * rd; struct pwr_rd_match * m; @@ -4203,10 +4246,12 @@ void update_proxy_writer (struct proxy_writer * pwr, struct addrset * as) m = ddsrt_avl_iter_next (&iter); } } + + update_qos_locked (&pwr->e, pwr->c.xqos, xqos, timestamp); ddsrt_mutex_unlock (&pwr->e.lock); } -void update_proxy_reader (struct proxy_reader * prd, struct addrset * as) +void update_proxy_reader (struct proxy_reader *prd, struct addrset *as, const struct dds_qos *xqos, nn_wctime_t timestamp) { struct prd_wr_match * m; nn_guid_t wrguid; @@ -4255,6 +4300,8 @@ void update_proxy_reader (struct proxy_reader * prd, struct addrset * as) ddsrt_mutex_lock (&prd->e.lock); } } + + update_qos_locked (&prd->e, prd->c.xqos, xqos, timestamp); ddsrt_mutex_unlock (&prd->e.lock); } diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 0cf2da1..15f27f4 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -1248,7 +1248,7 @@ void nn_plist_init_tables (void) ddsrt_once (&table_init_control, nn_plist_init_tables_real); } -static void plist_or_xqos_fini (void * __restrict dst, size_t shift) +static void plist_or_xqos_fini (void * __restrict dst, size_t shift, uint64_t pmask, uint64_t qmask) { /* shift == 0: plist, shift > 0: just qos */ struct flagset pfs, qfs; @@ -1277,7 +1277,8 @@ static void plist_or_xqos_fini (void * __restrict dst, size_t shift) assert (shift == 0 || entry->plist_offset - shift < sizeof (dds_qos_t)); size_t dstoff = entry->plist_offset - shift; struct flagset * const fs = (entry->flags & PDF_QOS) ? &qfs : &pfs; - if ((*fs->present & entry->present_flag)) + uint64_t mask = (entry->flags & PDF_QOS) ? qmask : pmask; + if (*fs->present & entry->present_flag & mask) { if (!(entry->flags & PDF_FUNCTION)) fini_generic (dst, &dstoff, fs, entry->present_flag, entry->op.desc); @@ -1285,8 +1286,8 @@ static void plist_or_xqos_fini (void * __restrict dst, size_t shift) entry->op.f.fini (dst, &dstoff, fs, entry->present_flag); } } - if (pfs.present) { *pfs.present = *pfs.aliased = 0; } - *qfs.present = *qfs.aliased = 0; + if (pfs.present) { *pfs.present &= ~pmask; *pfs.aliased &= ~pmask; } + *qfs.present &= ~qmask; *qfs.aliased &= ~qmask; } static void plist_or_xqos_unalias (void * __restrict dst, size_t shift) @@ -1441,7 +1442,7 @@ static void plist_or_xqos_addtomsg (struct nn_xmsg *xmsg, const void * __restric void nn_plist_fini (nn_plist_t *plist) { - plist_or_xqos_fini (plist, 0); + plist_or_xqos_fini (plist, 0, ~(uint64_t)0, ~(uint64_t)0); } void nn_plist_unalias (nn_plist_t *plist) @@ -2322,18 +2323,19 @@ void nn_xqos_init_empty (dds_qos_t *dest) void nn_plist_init_default_participant (nn_plist_t *plist) { nn_plist_init_empty (plist); + plist->qos.present |= QP_PRISMTECH_ENTITY_FACTORY; plist->qos.entity_factory.autoenable_created_entities = 0; + + plist->qos.present |= QP_USER_DATA; + plist->qos.user_data.length = 0; + plist->qos.user_data.value = NULL; } static void xqos_init_default_common (dds_qos_t *xqos) { nn_xqos_init_empty (xqos); - xqos->present |= QP_PARTITION; - xqos->partition.n = 0; - xqos->partition.strs = NULL; - xqos->present |= QP_PRESENTATION; xqos->presentation.access_scope = DDS_PRESENTATION_INSTANCE; xqos->presentation.coherent_access = 0; @@ -2374,10 +2376,31 @@ static void xqos_init_default_common (dds_qos_t *xqos) xqos->ignorelocal.value = DDS_IGNORELOCAL_NONE; } -void nn_xqos_init_default_reader (dds_qos_t *xqos) +static void nn_xqos_init_default_endpoint (dds_qos_t *xqos) { xqos_init_default_common (xqos); + xqos->present |= QP_TOPIC_DATA; + xqos->topic_data.length = 0; + xqos->topic_data.value = NULL; + + xqos->present |= QP_GROUP_DATA; + xqos->group_data.length = 0; + xqos->group_data.value = NULL; + + xqos->present |= QP_USER_DATA; + xqos->user_data.length = 0; + xqos->user_data.value = NULL; + + xqos->present |= QP_PARTITION; + xqos->partition.n = 0; + xqos->partition.strs = NULL; +} + +void nn_xqos_init_default_reader (dds_qos_t *xqos) +{ + nn_xqos_init_default_endpoint (xqos); + xqos->present |= QP_RELIABILITY; xqos->reliability.kind = DDS_RELIABILITY_BEST_EFFORT; @@ -2400,7 +2423,7 @@ void nn_xqos_init_default_reader (dds_qos_t *xqos) void nn_xqos_init_default_writer (dds_qos_t *xqos) { - xqos_init_default_common (xqos); + nn_xqos_init_default_endpoint (xqos); xqos->present |= QP_DURABILITY_SERVICE; xqos->durability_service.service_cleanup_delay = 0; @@ -2461,10 +2484,14 @@ void nn_xqos_init_default_topic (dds_qos_t *xqos) xqos->subscription_keys.key_list.strs = NULL; } -void nn_xqos_init_default_subscriber (dds_qos_t *xqos) +static void nn_xqos_init_default_publisher_subscriber (dds_qos_t *xqos) { nn_xqos_init_empty (xqos); + xqos->present |= QP_GROUP_DATA; + xqos->group_data.length = 0; + xqos->group_data.value = NULL; + xqos->present |= QP_PRISMTECH_ENTITY_FACTORY; xqos->entity_factory.autoenable_created_entities = 1; @@ -2473,16 +2500,14 @@ void nn_xqos_init_default_subscriber (dds_qos_t *xqos) xqos->partition.strs = NULL; } +void nn_xqos_init_default_subscriber (dds_qos_t *xqos) +{ + nn_xqos_init_default_publisher_subscriber (xqos); +} + void nn_xqos_init_default_publisher (dds_qos_t *xqos) { - nn_xqos_init_empty (xqos); - - xqos->present |= QP_PRISMTECH_ENTITY_FACTORY; - xqos->entity_factory.autoenable_created_entities = 1; - - xqos->present |= QP_PARTITION; - xqos->partition.n = 0; - xqos->partition.strs = NULL; + nn_xqos_init_default_publisher_subscriber (xqos); } void nn_xqos_copy (dds_qos_t *dst, const dds_qos_t *src) @@ -2493,7 +2518,12 @@ void nn_xqos_copy (dds_qos_t *dst, const dds_qos_t *src) void nn_xqos_fini (dds_qos_t *xqos) { - plist_or_xqos_fini (xqos, offsetof (nn_plist_t, qos)); + plist_or_xqos_fini (xqos, offsetof (nn_plist_t, qos), ~(uint64_t)0, ~(uint64_t)0); +} + +void nn_xqos_fini_mask (dds_qos_t *xqos, uint64_t mask) +{ + plist_or_xqos_fini (xqos, offsetof (nn_plist_t, qos), ~(uint64_t)0, mask); } void nn_xqos_unalias (dds_qos_t *xqos) diff --git a/src/ddsrt/src/expand_envvars.c b/src/ddsrt/src/expand_envvars.c index dbaa33a..f34d424 100644 --- a/src/ddsrt/src/expand_envvars.c +++ b/src/ddsrt/src/expand_envvars.c @@ -19,6 +19,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" #include "dds/ddsrt/string.h" +#include "dds/ddsrt/process.h" typedef char * (*expand_fn)(const char *src0); @@ -34,8 +35,16 @@ static void expand_append (char **dst, size_t *sz, size_t *pos, char c) static char *expand_env (const char *name, char op, const char *alt, expand_fn expand) { + char pidstr[20]; char *env = NULL; - (void)ddsrt_getenv (name, &env); + + if (name[0] == '$' && name[1] == 0) { + snprintf (pidstr, sizeof (pidstr), "%"PRIdPID, ddsrt_getpid ()); + env = pidstr; + } else { + (void) ddsrt_getenv (name, &env); + } + switch (op) { case 0: diff --git a/src/mpt/CMakeLists.txt b/src/mpt/CMakeLists.txt index 5c9ec7f..1a9c4ef 100644 --- a/src/mpt/CMakeLists.txt +++ b/src/mpt/CMakeLists.txt @@ -20,4 +20,3 @@ set(MPT_DEFAULT_TIMEOUT "60") add_subdirectory(mpt) add_subdirectory(tests) - diff --git a/src/mpt/tests/CMakeLists.txt b/src/mpt/tests/CMakeLists.txt index 63e786b..02eadaa 100644 --- a/src/mpt/tests/CMakeLists.txt +++ b/src/mpt/tests/CMakeLists.txt @@ -16,4 +16,4 @@ if(MPT_ENABLE_SELFTEST) endif() add_subdirectory(basic) -add_subdirectory(qosmatch) +add_subdirectory(qos) diff --git a/src/mpt/tests/qosmatch/CMakeLists.txt b/src/mpt/tests/qos/CMakeLists.txt similarity index 53% rename from src/mpt/tests/qosmatch/CMakeLists.txt rename to src/mpt/tests/qos/CMakeLists.txt index efa3324..e2f8109 100644 --- a/src/mpt/tests/qosmatch/CMakeLists.txt +++ b/src/mpt/tests/qos/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others +# Copyright(c) 2019 ADLINK Technology Limited and others # # This program and the accompanying materials are made available under the # terms of the Eclipse Public License v. 2.0 which is available at @@ -11,13 +11,18 @@ # include(${MPT_CMAKE}) -set(sources +add_compile_options("-I${PROJECT_SOURCE_DIR}/core/ddsi/include") + +idlc_generate(mpt_rwdata_lib "procs/rwdata.idl") + +set(sources_qosmatch "procs/rw.c" "qosmatch.c") +add_mpt_executable(mpt_qosmatch ${sources_qosmatch}) +target_link_libraries(mpt_qosmatch PRIVATE mpt_rwdata_lib) -add_compile_options("-I${PROJECT_SOURCE_DIR}/core/ddsi/include") -add_mpt_executable(mpt_qosmatch ${sources}) - -idlc_generate(mpt_qosmatch_rwdata_lib "procs/rwdata.idl") -target_link_libraries(mpt_qosmatch PRIVATE mpt_qosmatch_rwdata_lib) - +set(sources_ppuserdata + "procs/ppud.c" + "ppuserdata.c") +add_mpt_executable(mpt_ppuserdata ${sources_ppuserdata}) +target_link_libraries(mpt_ppuserdata PRIVATE mpt_rwdata_lib) diff --git a/src/mpt/tests/qos/ppuserdata.c b/src/mpt/tests/qos/ppuserdata.c new file mode 100644 index 0000000..9e52042 --- /dev/null +++ b/src/mpt/tests/qos/ppuserdata.c @@ -0,0 +1,58 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include "mpt/mpt.h" +#include "procs/ppud.h" + + +/* + * Checks whether participant user_data QoS changes work. + */ +#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, true, 10) +#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, false, 0) +MPT_TestProcess(qos, ppuserdata, a, ppud, TEST_A_ARGS); +MPT_TestProcess(qos, ppuserdata, b, ppud, TEST_B_ARGS); +MPT_Test(qos, ppuserdata, .init=ppud_init, .fini=ppud_fini); +#undef TEST_A_ARGS +#undef TEST_B_ARGS + +/* + * Checks whether reader/writer user_data QoS changes work. + */ +#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwuserdata", true, 10) +#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwuserdata", false, 0) +MPT_TestProcess(qos, rwuserdata, a, rwud, TEST_A_ARGS); +MPT_TestProcess(qos, rwuserdata, b, rwud, TEST_B_ARGS); +MPT_Test(qos, rwuserdata, .init=ppud_init, .fini=ppud_fini); +#undef TEST_A_ARGS +#undef TEST_B_ARGS + +/* + * Checks whether topic_data QoS changes become visible in reader/writer. + */ +#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwtopicdata", true, 10) +#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwtopicdata", false, 0) +MPT_TestProcess(qos, rwtopicdata, a, rwtd, TEST_A_ARGS); +MPT_TestProcess(qos, rwtopicdata, b, rwtd, TEST_B_ARGS); +MPT_Test(qos, rwtopicdata, .init=ppud_init, .fini=ppud_fini); +#undef TEST_A_ARGS +#undef TEST_B_ARGS + +/* + * Checks whether group_data QoS changes become visible in reader/writer. + */ +#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwgroupdata", true, 10) +#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwgroupdata", false, 0) +MPT_TestProcess(qos, rwgroupdata, a, rwgd, TEST_A_ARGS); +MPT_TestProcess(qos, rwgroupdata, b, rwgd, TEST_B_ARGS); +MPT_Test(qos, rwgroupdata, .init=ppud_init, .fini=ppud_fini); +#undef TEST_A_ARGS +#undef TEST_B_ARGS diff --git a/src/mpt/tests/qos/procs/ppud.c b/src/mpt/tests/qos/procs/ppud.c new file mode 100644 index 0000000..0d564fb --- /dev/null +++ b/src/mpt/tests/qos/procs/ppud.c @@ -0,0 +1,569 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include + +#include "mpt/mpt.h" +#include "rwdata.h" + +#include "dds/dds.h" + +#include "dds/ddsrt/time.h" +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/sockets.h" +#include "dds/ddsrt/heap.h" + +void ppud_init (void) { } +void ppud_fini (void) { } + +static const char *exp_ud[] = { + "a", "bc", "def", "" +}; + +MPT_ProcessEntry (ppud, + MPT_Args (dds_domainid_t domainid, + bool active, + unsigned ncycles)) +{ + dds_entity_t dp, rd, ws; + dds_instance_handle_t dpih; + dds_return_t rc; + dds_qos_t *qos; + int id = (int) ddsrt_getpid (); + + printf ("=== [Check(%d)] active=%d ncycles=%u Start(%d) ...\n", id, active, ncycles, (int) domainid); + + qos = dds_create_qos (); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0); + dp = dds_create_participant (domainid, qos, NULL); + MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp)); + rc = dds_get_instance_handle (dp, &dpih); + MPT_ASSERT_FATAL_EQ (rc, 0, "Could not get participant instance handle: %s\n", dds_strretcode (rc)); + rd = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPARTICIPANT, qos, NULL); + MPT_ASSERT_FATAL_GT (rd, 0, "Could not create DCPSParticipant reader: %s\n", dds_strretcode (rd)); + rc = dds_set_status_mask (rd, DDS_DATA_AVAILABLE_STATUS); + MPT_ASSERT_FATAL_EQ (rc, 0, "Could not set status mask: %s\n", dds_strretcode (rc)); + ws = dds_create_waitset (dp); + MPT_ASSERT_FATAL_GT (ws, 0, "Could not create waitset: %s\n", dds_strretcode (ws)); + rc = dds_waitset_attach (ws, rd, 0); + MPT_ASSERT_FATAL_EQ (rc, 0, "Could not attach reader to waitset: %s\n", dds_strretcode (rc)); + + bool done = false; + bool first = true; + unsigned exp_index = 0; + unsigned exp_cycle = 0; + while (!done) + { + rc = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY); + MPT_ASSERT_FATAL_GEQ (rc, 0, "Wait failed: %s\n", dds_strretcode (ws)); + + void *raw = NULL; + dds_sample_info_t si; + int32_t n; + while ((n = dds_take (rd, &raw, &si, 1, 1)) == 1) + { + const dds_builtintopic_participant_t *sample = raw; + if (si.instance_state != DDS_IST_ALIVE) + done = true; + else if (si.instance_handle == dpih || !si.valid_data) + continue; + else + { + void *ud = NULL; + size_t usz = 0; + if (!dds_qget_userdata (sample->qos, &ud, &usz)) + printf ("%d: user data not set in QoS\n", id); + if (first && usz == 0) + { + dds_qset_userdata (qos, "X", 1); + rc = dds_set_qos (dp, qos); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); + } + else + { + const char *exp = exp_ud[exp_index]; + if (first && strcmp (ud, "X") == 0) + exp = "X"; + const size_t expsz = strlen (exp); + bool eq = (usz == expsz && (usz == 0 || memcmp (ud, exp, usz) == 0)); + printf ("%d: expected %u %zu/%s received %zu/%s\n", + id, exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)"); + MPT_ASSERT (eq, "User data mismatch: expected %u %zu/%s received %zu/%s\n", + exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)"); + if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0])) + { + exp_index = 0; + exp_cycle++; + } + + if (active && exp_cycle == ncycles) + done = true; + else + { + const void *newud; + size_t newusz; + if (!active) + { + /* Set user data to the same value in response */ + newud = ud; newusz = usz; + dds_qset_userdata (qos, ud, usz); + } + else /* Set next agreed value */ + { + newud = exp_ud[exp_index]; newusz = strlen (exp_ud[exp_index]); + dds_qset_userdata (qos, newud, newusz); + } + + rc = dds_set_qos (dp, qos); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); + + dds_qos_t *chk = dds_create_qos (); + rc = dds_get_qos (dp, chk); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Get QoS failed: %s\n", dds_strretcode (rc)); + + void *chkud = NULL; + size_t chkusz = 0; + if (!dds_qget_userdata (chk, &chkud, &chkusz)) + MPT_ASSERT (0, "Check QoS: no user data present\n"); + MPT_ASSERT (chkusz == newusz && (newusz == 0 || memcmp (chkud, newud, newusz) == 0), + "Retrieved user data differs from user data just set (%zu/%s vs %zu/%s)\n", + chkusz, chkud ? (char *) chkud : "(null)", newusz, newud ? (char *) newud : "(null)"); + dds_free (chkud); + dds_delete_qos (chk); + first = false; + } + } + dds_free (ud); + } + } + MPT_ASSERT_FATAL_EQ (n, 0, "Read failed: %s\n", dds_strretcode (n)); + dds_return_loan (rd, &raw, 1); + } + dds_delete_qos (qos); + rc = dds_delete (dp); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n"); + printf ("=== [Publisher(%d)] Done\n", id); +} + +MPT_ProcessEntry (rwud, + MPT_Args (dds_domainid_t domainid, + const char *topic_name, + bool active, + unsigned ncycles)) +{ + dds_entity_t dp, tp, ep, rdep, ws; + dds_return_t rc; + dds_qos_t *qos; + int id = (int) ddsrt_getpid (); + + printf ("=== [Check(%d)] active=%d ncycles=%u Start(%d) ...\n", id, active, ncycles, (int) domainid); + + qos = dds_create_qos (); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0); + dp = dds_create_participant (domainid, NULL, NULL); + MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp)); + tp = dds_create_topic (dp, &RWData_Msg_desc, topic_name, qos, NULL); + MPT_ASSERT_FATAL_GT (tp, 0, "Could not create topic: %s\n", dds_strretcode (tp)); + if (active) + { + rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, qos, NULL); + MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSSubscription reader: %s\n", dds_strretcode (rdep)); + ep = dds_create_writer (dp, tp, qos, NULL); + MPT_ASSERT_FATAL_GT (ep, 0, "Could not create writer: %s\n", dds_strretcode (ep)); + } + else + { + rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, qos, NULL); + MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSPublication reader: %s\n", dds_strretcode (rdep)); + ep = dds_create_reader (dp, tp, qos, NULL); + MPT_ASSERT_FATAL_GT (ep, 0, "Could not create reader: %s\n", dds_strretcode (ep)); + } + rc = dds_set_status_mask (rdep, DDS_DATA_AVAILABLE_STATUS); + MPT_ASSERT_FATAL_EQ (rc, 0, "Could not set status mask: %s\n", dds_strretcode (rc)); + ws = dds_create_waitset (dp); + MPT_ASSERT_FATAL_GT (ws, 0, "Could not create waitset: %s\n", dds_strretcode (ws)); + rc = dds_waitset_attach (ws, rdep, 0); + MPT_ASSERT_FATAL_EQ (rc, 0, "Could not attach built-in reader to waitset: %s\n", dds_strretcode (rc)); + + bool done = false; + bool first = true; + unsigned exp_index = 0; + unsigned exp_cycle = 0; + while (!done) + { + rc = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY); + MPT_ASSERT_FATAL_GEQ (rc, 0, "Wait failed: %s\n", dds_strretcode (ws)); + + void *raw = NULL; + dds_sample_info_t si; + int32_t n; + while ((n = dds_take (rdep, &raw, &si, 1, 1)) == 1) + { + const dds_builtintopic_endpoint_t *sample = raw; + if (si.instance_state != DDS_IST_ALIVE) + done = true; + else if (!si.valid_data || strcmp (sample->topic_name, topic_name) != 0) + continue; + else + { + void *ud = NULL; + size_t usz = 0; + if (!dds_qget_userdata (sample->qos, &ud, &usz)) + printf ("%d: user data not set in QoS\n", id); + if (first && usz == 0) + { + dds_qset_userdata (qos, "X", 1); + rc = dds_set_qos (ep, qos); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); + } + else + { + const char *exp = exp_ud[exp_index]; + if (first && strcmp (ud, "X") == 0) + exp = "X"; + const size_t expsz = first ? 1 : strlen (exp); + bool eq = (usz == expsz && (usz == 0 || memcmp (ud, exp, usz) == 0)); + printf ("%d: expected %u %zu/%s received %zu/%s\n", + id, exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)"); + MPT_ASSERT (eq, "User data mismatch: expected %u %zu/%s received %zu/%s\n", + exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)"); + if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0])) + { + exp_index = 0; + exp_cycle++; + } + + if (active && exp_cycle == ncycles) + done = true; + else + { + const void *newud; + size_t newusz; + if (!active) + { + /* Set user data to the same value in response */ + newud = ud; newusz = usz; + dds_qset_userdata (qos, ud, usz); + } + else /* Set next agreed value */ + { + newud = exp_ud[exp_index]; newusz = strlen (exp_ud[exp_index]); + dds_qset_userdata (qos, newud, newusz); + } + + rc = dds_set_qos (ep, qos); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); + + dds_qos_t *chk = dds_create_qos (); + rc = dds_get_qos (ep, chk); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Get QoS failed: %s\n", dds_strretcode (rc)); + + void *chkud = NULL; + size_t chkusz = 0; + if (!dds_qget_userdata (chk, &chkud, &chkusz)) + MPT_ASSERT (0, "Check QoS: no user data present\n"); + MPT_ASSERT (chkusz == newusz && (newusz == 0 || memcmp (chkud, newud, newusz) == 0), + "Retrieved user data differs from user data just set (%zu/%s vs %zu/%s)\n", + chkusz, chkud ? (char *) chkud : "(null)", newusz, newud ? (char *) newud : "(null)"); + dds_free (chkud); + dds_delete_qos (chk); + first = false; + } + } + dds_free (ud); + } + } + MPT_ASSERT_FATAL_EQ (n, 0, "Read failed: %s\n", dds_strretcode (n)); + dds_return_loan (rdep, &raw, 1); + } + dds_delete_qos (qos); + rc = dds_delete (dp); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n"); + printf ("=== [Publisher(%d)] Done\n", id); +} + +MPT_ProcessEntry (rwtd, + MPT_Args (dds_domainid_t domainid, + const char *topic_name, + bool active, + unsigned ncycles)) +{ + dds_entity_t dp, tp, ep, rdep, ws; + dds_return_t rc; + dds_qos_t *qos; + int id = (int) ddsrt_getpid (); + + printf ("=== [Check(%d)] active=%d ncycles=%u Start(%d) ...\n", id, active, ncycles, (int) domainid); + + qos = dds_create_qos (); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0); + dp = dds_create_participant (domainid, NULL, NULL); + MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp)); + tp = dds_create_topic (dp, &RWData_Msg_desc, topic_name, qos, NULL); + MPT_ASSERT_FATAL_GT (tp, 0, "Could not create topic: %s\n", dds_strretcode (tp)); + if (active) + { + rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, qos, NULL); + MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSSubscription reader: %s\n", dds_strretcode (rdep)); + ep = dds_create_writer (dp, tp, qos, NULL); + MPT_ASSERT_FATAL_GT (ep, 0, "Could not create writer: %s\n", dds_strretcode (ep)); + } + else + { + rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, qos, NULL); + MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSPublication reader: %s\n", dds_strretcode (rdep)); + ep = dds_create_reader (dp, tp, qos, NULL); + MPT_ASSERT_FATAL_GT (ep, 0, "Could not create reader: %s\n", dds_strretcode (ep)); + } + rc = dds_set_status_mask (rdep, DDS_DATA_AVAILABLE_STATUS); + MPT_ASSERT_FATAL_EQ (rc, 0, "Could not set status mask: %s\n", dds_strretcode (rc)); + ws = dds_create_waitset (dp); + MPT_ASSERT_FATAL_GT (ws, 0, "Could not create waitset: %s\n", dds_strretcode (ws)); + rc = dds_waitset_attach (ws, rdep, 0); + MPT_ASSERT_FATAL_EQ (rc, 0, "Could not attach built-in reader to waitset: %s\n", dds_strretcode (rc)); + + bool done = false; + bool first = true; + unsigned exp_index = 0; + unsigned exp_cycle = 0; + while (!done) + { + rc = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY); + MPT_ASSERT_FATAL_GEQ (rc, 0, "Wait failed: %s\n", dds_strretcode (ws)); + + void *raw = NULL; + dds_sample_info_t si; + int32_t n; + while ((n = dds_take (rdep, &raw, &si, 1, 1)) == 1) + { + const dds_builtintopic_endpoint_t *sample = raw; + if (si.instance_state != DDS_IST_ALIVE) + done = true; + else if (!si.valid_data || strcmp (sample->topic_name, topic_name) != 0) + continue; + else + { + void *td = NULL; + size_t tsz = 0; + if (!dds_qget_topicdata (sample->qos, &td, &tsz)) + printf ("%d: topic data not set in QoS\n", id); + if (first && tsz == 0) + { + dds_qset_topicdata (qos, "X", 1); + rc = dds_set_qos (tp, qos); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); + } + else + { + const char *exp = exp_ud[exp_index]; + if (first && strcmp (td, "X") == 0) + exp = "X"; + const size_t expsz = first ? 1 : strlen (exp); + bool eq = (tsz == expsz && (tsz == 0 || memcmp (td, exp, tsz) == 0)); + printf ("%d: expected %u %zu/%s received %zu/%s\n", + id, exp_index, expsz, exp, tsz, td ? (char *) td : "(null)"); + MPT_ASSERT (eq, "Topic data mismatch: expected %u %zu/%s received %zu/%s\n", + exp_index, expsz, exp, tsz, td ? (char *) td : "(null)"); + if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0])) + { + exp_index = 0; + exp_cycle++; + } + + if (active && exp_cycle == ncycles) + done = true; + else + { + const void *newtd; + size_t newtsz; + if (!active) + { + /* Set topic data to the same value in response */ + newtd = td; newtsz = tsz; + dds_qset_topicdata (qos, td, tsz); + } + else /* Set next agreed value */ + { + newtd = exp_ud[exp_index]; newtsz = strlen (exp_ud[exp_index]); + dds_qset_topicdata (qos, newtd, newtsz); + } + + rc = dds_set_qos (tp, qos); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); + + dds_qos_t *chk = dds_create_qos (); + rc = dds_get_qos (ep, chk); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Get QoS failed: %s\n", dds_strretcode (rc)); + + void *chktd = NULL; + size_t chktsz = 0; + if (!dds_qget_topicdata (chk, &chktd, &chktsz)) + MPT_ASSERT (0, "Check QoS: no topic data present\n"); + MPT_ASSERT (chktsz == newtsz && (newtsz == 0 || memcmp (chktd, newtd, newtsz) == 0), + "Retrieved topic data differs from topic data just set (%zu/%s vs %zu/%s)\n", + chktsz, chktd ? (char *) chktd : "(null)", newtsz, newtd ? (char *) newtd : "(null)"); + dds_free (chktd); + dds_delete_qos (chk); + first = false; + } + } + dds_free (td); + } + } + MPT_ASSERT_FATAL_EQ (n, 0, "Read failed: %s\n", dds_strretcode (n)); + dds_return_loan (rdep, &raw, 1); + } + dds_delete_qos (qos); + rc = dds_delete (dp); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n"); + printf ("=== [Publisher(%d)] Done\n", id); +} + +MPT_ProcessEntry (rwgd, + MPT_Args (dds_domainid_t domainid, + const char *topic_name, + bool active, + unsigned ncycles)) +{ + dds_entity_t dp, tp, ep, rdep, grp, ws; + dds_return_t rc; + dds_qos_t *qos; + int id = (int) ddsrt_getpid (); + + printf ("=== [Check(%d)] active=%d ncycles=%u Start(%d) ...\n", id, active, ncycles, (int) domainid); + + qos = dds_create_qos (); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0); + dp = dds_create_participant (domainid, NULL, NULL); + MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp)); + tp = dds_create_topic (dp, &RWData_Msg_desc, topic_name, qos, NULL); + MPT_ASSERT_FATAL_GT (tp, 0, "Could not create topic: %s\n", dds_strretcode (tp)); + if (active) + { + rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, qos, NULL); + MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSSubscription reader: %s\n", dds_strretcode (rdep)); + ep = dds_create_writer (dp, tp, qos, NULL); + MPT_ASSERT_FATAL_GT (ep, 0, "Could not create writer: %s\n", dds_strretcode (ep)); + } + else + { + rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, qos, NULL); + MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSPublication reader: %s\n", dds_strretcode (rdep)); + ep = dds_create_reader (dp, tp, qos, NULL); + MPT_ASSERT_FATAL_GT (ep, 0, "Could not create reader: %s\n", dds_strretcode (ep)); + } + grp = dds_get_parent (ep); + MPT_ASSERT_FATAL_GT (grp, 0, "Could not get pub/sub from wr/rd: %s\n", dds_strretcode (grp)); + rc = dds_set_status_mask (rdep, DDS_DATA_AVAILABLE_STATUS); + MPT_ASSERT_FATAL_EQ (rc, 0, "Could not set status mask: %s\n", dds_strretcode (rc)); + ws = dds_create_waitset (dp); + MPT_ASSERT_FATAL_GT (ws, 0, "Could not create waitset: %s\n", dds_strretcode (ws)); + rc = dds_waitset_attach (ws, rdep, 0); + MPT_ASSERT_FATAL_EQ (rc, 0, "Could not attach built-in reader to waitset: %s\n", dds_strretcode (rc)); + + bool done = false; + bool first = true; + unsigned exp_index = 0; + unsigned exp_cycle = 0; + while (!done) + { + rc = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY); + MPT_ASSERT_FATAL_GEQ (rc, 0, "Wait failed: %s\n", dds_strretcode (ws)); + + void *raw = NULL; + dds_sample_info_t si; + int32_t n; + while ((n = dds_take (rdep, &raw, &si, 1, 1)) == 1) + { + const dds_builtintopic_endpoint_t *sample = raw; + if (si.instance_state != DDS_IST_ALIVE) + done = true; + else if (!si.valid_data || strcmp (sample->topic_name, topic_name) != 0) + continue; + else + { + void *gd = NULL; + size_t gsz = 0; + if (!dds_qget_groupdata (sample->qos, &gd, &gsz)) + printf ("%d: group data not set in QoS\n", id); + if (first && gsz == 0) + { + dds_qset_groupdata (qos, "X", 1); + rc = dds_set_qos (grp, qos); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); + } + else + { + const char *exp = exp_ud[exp_index]; + if (first && strcmp (gd, "X") == 0) + exp = "X"; + const size_t expsz = first ? 1 : strlen (exp); + bool eq = (gsz == expsz && (gsz == 0 || memcmp (gd, exp, gsz) == 0)); + printf ("%d: expected %u %zu/%s received %zu/%s\n", + id, exp_index, expsz, exp, gsz, gd ? (char *) gd : "(null)"); + MPT_ASSERT (eq, "Group data mismatch: expected %u %zu/%s received %zu/%s\n", + exp_index, expsz, exp, gsz, gd ? (char *) gd : "(null)"); + if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0])) + { + exp_index = 0; + exp_cycle++; + } + + if (active && exp_cycle == ncycles) + done = true; + else + { + const void *newgd; + size_t newgsz; + if (!active) + { + /* Set group data to the same value in response */ + newgd = gd; newgsz = gsz; + dds_qset_groupdata (qos, gd, gsz); + } + else /* Set next agreed value */ + { + newgd = exp_ud[exp_index]; newgsz = strlen (exp_ud[exp_index]); + dds_qset_groupdata (qos, newgd, newgsz); + } + + rc = dds_set_qos (grp, qos); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); + + dds_qos_t *chk = dds_create_qos (); + rc = dds_get_qos (ep, chk); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Get QoS failed: %s\n", dds_strretcode (rc)); + + void *chkgd = NULL; + size_t chkgsz = 0; + if (!dds_qget_groupdata (chk, &chkgd, &chkgsz)) + MPT_ASSERT (0, "Check QoS: no group data present\n"); + MPT_ASSERT (chkgsz == newgsz && (newgsz == 0 || memcmp (chkgd, newgd, newgsz) == 0), + "Retrieved group data differs from group data just set (%zu/%s vs %zu/%s)\n", + chkgsz, chkgd ? (char *) chkgd : "(null)", newgsz, newgd ? (char *) newgd : "(null)"); + dds_free (chkgd); + dds_delete_qos (chk); + first = false; + } + } + dds_free (gd); + } + } + MPT_ASSERT_FATAL_EQ (n, 0, "Read failed: %s\n", dds_strretcode (n)); + dds_return_loan (rdep, &raw, 1); + } + dds_delete_qos (qos); + rc = dds_delete (dp); + MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n"); + printf ("=== [Publisher(%d)] Done\n", id); +} diff --git a/src/mpt/tests/qos/procs/ppud.h b/src/mpt/tests/qos/procs/ppud.h new file mode 100644 index 0000000..c017aaa --- /dev/null +++ b/src/mpt/tests/qos/procs/ppud.h @@ -0,0 +1,55 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#ifndef MPT_QOSMATCH_PROCS_PPUD_H +#define MPT_QOSMATCH_PROCS_PPUD_H + +#include +#include + +#include "dds/dds.h" +#include "mpt/mpt.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +void ppud_init (void); +void ppud_fini (void); + +MPT_ProcessEntry (ppud, + MPT_Args (dds_domainid_t domainid, + bool active, + unsigned ncycles)); + +MPT_ProcessEntry (rwud, + MPT_Args (dds_domainid_t domainid, + const char *topic_name, + bool active, + unsigned ncycles)); + +MPT_ProcessEntry (rwtd, + MPT_Args (dds_domainid_t domainid, + const char *topic_name, + bool active, + unsigned ncycles)); + +MPT_ProcessEntry (rwgd, + MPT_Args (dds_domainid_t domainid, + const char *topic_name, + bool active, + unsigned ncycles)); +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/src/mpt/tests/qosmatch/procs/rw.c b/src/mpt/tests/qos/procs/rw.c similarity index 96% rename from src/mpt/tests/qosmatch/procs/rw.c rename to src/mpt/tests/qos/procs/rw.c index b4720ff..ba0d3b9 100644 --- a/src/mpt/tests/qosmatch/procs/rw.c +++ b/src/mpt/tests/qos/procs/rw.c @@ -1,3 +1,14 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ #include #include #include diff --git a/src/mpt/tests/qosmatch/procs/rw.h b/src/mpt/tests/qos/procs/rw.h similarity index 93% rename from src/mpt/tests/qosmatch/procs/rw.h rename to src/mpt/tests/qos/procs/rw.h index 851ee20..bfd5b69 100644 --- a/src/mpt/tests/qosmatch/procs/rw.h +++ b/src/mpt/tests/qos/procs/rw.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * Copyright(c) 2019 ADLINK Technology Limited and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at diff --git a/src/mpt/tests/qos/procs/rwdata.idl b/src/mpt/tests/qos/procs/rwdata.idl new file mode 100644 index 0000000..3e821a1 --- /dev/null +++ b/src/mpt/tests/qos/procs/rwdata.idl @@ -0,0 +1,19 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +module RWData +{ + struct Msg + { + long k; + }; + #pragma keylist Msg k +}; diff --git a/src/mpt/tests/qos/qosmatch.c b/src/mpt/tests/qos/qosmatch.c new file mode 100644 index 0000000..c6b0c5a --- /dev/null +++ b/src/mpt/tests/qos/qosmatch.c @@ -0,0 +1,21 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include "mpt/mpt.h" +#include "procs/rw.h" + +#define TEST_PUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_qosmatch") +#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_qosmatch") +MPT_TestProcess(qos, qosmatch, pub, rw_publisher, TEST_PUB_ARGS); +MPT_TestProcess(qos, qosmatch, sub, rw_subscriber, TEST_SUB_ARGS); +MPT_Test(qos, qosmatch, .init=rw_init, .fini=rw_fini); +#undef TEST_SUB_ARGS +#undef TEST_PUB_ARGS diff --git a/src/mpt/tests/qosmatch/procs/rwdata.idl b/src/mpt/tests/qosmatch/procs/rwdata.idl deleted file mode 100644 index 7722451..0000000 --- a/src/mpt/tests/qosmatch/procs/rwdata.idl +++ /dev/null @@ -1,8 +0,0 @@ -module RWData -{ - struct Msg - { - long k; - }; - #pragma keylist Msg k -}; diff --git a/src/mpt/tests/qosmatch/qosmatch.c b/src/mpt/tests/qosmatch/qosmatch.c deleted file mode 100644 index b249b35..0000000 --- a/src/mpt/tests/qosmatch/qosmatch.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "mpt/mpt.h" -#include "procs/rw.h" - - -/* - * Tests to check communication between multiple publisher(s) and subscriber(s). - */ - - -/* - * The publisher expects 2 publication matched. - * The subscribers expect 1 sample each. - */ -#define TEST_PUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_qosmatch") -#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_qosmatch") -MPT_TestProcess(qosmatch, qosmatch, pub, rw_publisher, TEST_PUB_ARGS); -MPT_TestProcess(qosmatch, qosmatch, sub, rw_subscriber, TEST_SUB_ARGS); -MPT_Test(qosmatch, qosmatch, .init=rw_init, .fini=rw_fini); -#undef TEST_SUB_ARGS -#undef TEST_PUB_ARGS From 32b683bf371b68f002ef19cae85ec28e9ccdb61d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 5 Jun 2019 11:19:43 +0200 Subject: [PATCH 096/178] Enable "missing prototypes" warning for gcc, clang Missing prototypes for exported functions cause a really huge issue on Windows. Enabling the "missing prototypes" warning makes it much easier to catch this problem. Naturally, any warnings caused by this have been fixed. Signed-off-by: Erik Boasson --- src/CMakeLists.txt | 5 +- src/cmake/modules/CUnit/include/CUnit/Test.h | 15 +- .../modules/CUnit/include/CUnit/Theory.h | 1 + src/core/ddsc/src/dds_rhc.c | 2 + src/core/ddsc/src/dds_serdata_builtintopic.c | 2 +- src/core/ddsc/src/dds_waitset.c | 4 +- src/core/ddsc/tests/entity_api.c | 6 +- src/core/ddsc/tests/return_loan.c | 6 +- src/core/ddsi/include/dds/ddsi/q_plist.h | 1 + src/core/ddsi/include/dds/ddsi/q_xmsg.h | 17 +- src/core/ddsi/src/ddsi_serdata_default.c | 4 +- src/core/ddsi/src/ddsi_udp.c | 2 +- src/core/ddsi/src/q_addrset.c | 18 -- src/core/ddsi/src/q_entity.c | 10 +- src/core/ddsi/src/q_thread.c | 2 +- src/core/ddsi/src/q_xmsg.c | 208 +----------------- src/ddsrt/src/cdtors.c | 3 + src/ddsrt/src/strtol.c | 2 +- src/ddsrt/tests/thread.c | 6 +- src/mpt/mpt/include/mpt/mpt.h | 1 + src/mpt/tests/basic/procs/hello.c | 3 +- src/mpt/tests/qos/procs/ppud.c | 4 +- src/mpt/tests/qos/procs/rw.c | 4 +- src/tools/ddsls/ddsls.c | 66 +++--- src/tools/pubsub/common.c | 2 +- src/tools/pubsub/common.h | 2 + 26 files changed, 92 insertions(+), 304 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 491da54..d5f906d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,12 +87,12 @@ endif() # Set reasonably strict warning options for clang, gcc, msvc # Enable coloured ouput if Ninja is used for building if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_C_COMPILER_ID} STREQUAL "AppleClang") - add_definitions(-Wall -Wextra -Wconversion -Wunused) + add_definitions(-Wall -Wextra -Wconversion -Wunused -Wmissing-prototypes) if(${CMAKE_GENERATOR} STREQUAL "Ninja") add_definitions(-Xclang -fcolor-diagnostics) endif() elseif(${CMAKE_C_COMPILER_ID} STREQUAL "GNU") - add_definitions(-Wall -Wextra -Wconversion) + add_definitions(-Wall -Wextra -Wconversion -Wmissing-prototypes) if(${CMAKE_GENERATOR} STREQUAL "Ninja") add_definitions(-fdiagnostics-color=always) endif() @@ -131,6 +131,7 @@ if(${CMAKE_GENERATOR} STREQUAL "Xcode") set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VALUE YES) set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VARIABLE YES) set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_DOCUMENTATION_COMMENTS YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_MISSING_PROTOTYPES YES) endif() # Make it easy to enable one of Clang's/gcc's analyzers, and default to using diff --git a/src/cmake/modules/CUnit/include/CUnit/Test.h b/src/cmake/modules/CUnit/include/CUnit/Test.h index 4e9f2d4..9c36bcb 100644 --- a/src/cmake/modules/CUnit/include/CUnit/Test.h +++ b/src/cmake/modules/CUnit/include/CUnit/Test.h @@ -28,21 +28,24 @@ typedef struct { #define CU_TestProxyName(suite, test) \ CU_TestProxy_ ## suite ## _ ## test -#define CU_Init(suite) \ - int CU_InitName(suite)(void) #define CU_InitDecl(suite) \ - extern CU_Init(suite) + extern int CU_InitName(suite)(void) +#define CU_Init(suite) \ + CU_InitDecl(suite); \ + int CU_InitName(suite)(void) -#define CU_Clean(suite) \ - int CU_CleanName(suite)(void) #define CU_CleanDecl(suite) \ - extern CU_Clean(suite) + extern int CU_CleanName(suite)(void) +#define CU_Clean(suite) \ + CU_CleanDecl(suite); \ + int CU_CleanName(suite)(void) /* CU_Test generates a wrapper function that takes care of per-test initialization and deinitialization, if provided in the CU_Test signature. */ #define CU_Test(suite, test, ...) \ static void CU_TestName(suite, test)(void); \ + void CU_TestProxyName(suite, test)(void); \ \ void CU_TestProxyName(suite, test)(void) { \ cu_data_t data = CU_Fixture(__VA_ARGS__); \ diff --git a/src/cmake/modules/CUnit/include/CUnit/Theory.h b/src/cmake/modules/CUnit/include/CUnit/Theory.h index 81dd7f7..946dfb7 100644 --- a/src/cmake/modules/CUnit/include/CUnit/Theory.h +++ b/src/cmake/modules/CUnit/include/CUnit/Theory.h @@ -44,6 +44,7 @@ extern "C" { #define CU_Theory(signature, suite, test, ...) \ static void CU_TestName(suite, test) signature; \ + void CU_TestProxyName(suite, test)(void); \ \ void CU_TestProxyName(suite, test)(void) { \ cu_data_t data = CU_Fixture(__VA_ARGS__); \ diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 4c160c1..1d1814d 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -217,12 +217,14 @@ static int lwregs_delete (struct lwregs *rt, uint64_t iid, uint64_t wr_iid) return ddsrt_ehh_remove (rt->regs, &dummy); } +#if 0 void lwregs_dump (struct lwregs *rt) { struct ddsrt_ehh_iter it; for (struct lwreg *r = ddsrt_ehh_iter_first(rt->regs, &it); r; r = ddsrt_ehh_iter_next(&it)) printf("iid=%"PRIu64" wr_iid=%"PRIu64"\n", r->iid, r->wr_iid); } +#endif /************************* ****** RHC ****** diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index b1b7e01..573fd89 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -126,7 +126,7 @@ static void from_entity_pwr (struct ddsi_serdata_builtintopic *d, const struct p assert (d->xqos.present & QP_TYPE_NAME); } -struct ddsi_serdata *ddsi_serdata_builtin_from_keyhash (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash) +static struct ddsi_serdata *ddsi_serdata_builtin_from_keyhash (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash) { /* 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; diff --git a/src/core/ddsc/src/dds_waitset.c b/src/core/ddsc/src/dds_waitset.c index 08cd290..7bbeefe 100644 --- a/src/core/ddsc/src/dds_waitset.c +++ b/src/core/ddsc/src/dds_waitset.c @@ -133,7 +133,7 @@ static bool dds_waitset_remove_from_list (dds_attachment **list, dds_entity_t ob return true; } -dds_return_t dds_waitset_close (struct dds_entity *e) +static dds_return_t dds_waitset_close (struct dds_entity *e) { dds_waitset *ws = (dds_waitset *) e; dds_waitset_close_list (&ws->observed, e->m_hdllink.hdl); @@ -206,7 +206,7 @@ static void dds_waitset_remove (dds_waitset *ws, dds_entity_t observed) } /* This is called when the observed entity signals a status change. */ -void dds_waitset_observer (dds_entity_t observer, dds_entity_t observed, uint32_t status) +static void dds_waitset_observer (dds_entity_t observer, dds_entity_t observed, uint32_t status) { dds_waitset *ws; if (dds_waitset_lock (observer, &ws) == DDS_RETCODE_OK) { diff --git a/src/core/ddsc/tests/entity_api.c b/src/core/ddsc/tests/entity_api.c index f3241ac..66daa70 100644 --- a/src/core/ddsc/tests/entity_api.c +++ b/src/core/ddsc/tests/entity_api.c @@ -24,7 +24,7 @@ static dds_entity_t entity = -1; /* Fixture to create prerequisite entity */ -void create_entity(void) +static void create_entity(void) { CU_ASSERT_EQUAL_FATAL(entity, -1); entity = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); @@ -32,7 +32,7 @@ void create_entity(void) } /* Fixture to delete prerequisite entity */ -void delete_entity(void) +static void delete_entity(void) { CU_ASSERT_FATAL(entity > 0); dds_return_t ret = dds_delete(entity); @@ -66,7 +66,7 @@ CU_Test(ddsc_entity, enable, .init = create_entity, .fini = delete_entity) CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK); } -void entity_qos_get_set(dds_entity_t e, const char* info) +static void entity_qos_get_set(dds_entity_t e, const char* info) { dds_return_t status; dds_qos_t *qos = dds_create_qos(); diff --git a/src/core/ddsc/tests/return_loan.c b/src/core/ddsc/tests/return_loan.c index 4ff1fcc..812e024 100644 --- a/src/core/ddsc/tests/return_loan.c +++ b/src/core/ddsc/tests/return_loan.c @@ -15,9 +15,9 @@ #include #include "CUnit/Test.h" -dds_entity_t participant = 0, topic = 0, reader = 0, read_condition = 0; +static dds_entity_t participant = 0, topic = 0, reader = 0, read_condition = 0; -void create_entities(void) +static void create_entities(void) { participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); @@ -32,7 +32,7 @@ void create_entities(void) CU_ASSERT_FATAL(read_condition > 0); } -void delete_entities(void) +static void delete_entities(void) { dds_return_t result; result = dds_delete(participant); diff --git a/src/core/ddsi/include/dds/ddsi/q_plist.h b/src/core/ddsi/include/dds/ddsi/q_plist.h index 6028da8..58e76d2 100644 --- a/src/core/ddsi/include/dds/ddsi/q_plist.h +++ b/src/core/ddsi/include/dds/ddsi/q_plist.h @@ -230,6 +230,7 @@ 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_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); diff --git a/src/core/ddsi/include/dds/ddsi/q_xmsg.h b/src/core/ddsi/include/dds/ddsi/q_xmsg.h index b70a5c4..25e1415 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xmsg.h +++ b/src/core/ddsi/include/dds/ddsi/q_xmsg.h @@ -120,23 +120,8 @@ void nn_xmsg_submsg_init (struct nn_xmsg *msg, struct nn_xmsg_marker marker, Sub void nn_xmsg_add_timestamp (struct nn_xmsg *m, nn_wctime_t t); void nn_xmsg_add_entityid (struct nn_xmsg * m); void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len); -void nn_xmsg_addpar_string (struct nn_xmsg *m, nn_parameterid_t pid, const char *str); -void nn_xmsg_addpar_octetseq (struct nn_xmsg *m, nn_parameterid_t pid, const ddsi_octetseq_t *oseq); -void nn_xmsg_addpar_stringseq (struct nn_xmsg *m, nn_parameterid_t pid, const ddsi_stringseq_t *sseq); -void nn_xmsg_addpar_guid (struct nn_xmsg *m, nn_parameterid_t pid, const nn_guid_t *guid); -void nn_xmsg_addpar_BE4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x); -void nn_xmsg_addpar_4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x); void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata); -void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, uint32_t statusinfo); -void nn_xmsg_addpar_reliability (struct nn_xmsg *m, nn_parameterid_t pid, const struct dds_reliability_qospolicy *rq); -void nn_xmsg_addpar_duration (struct nn_xmsg *m, nn_parameterid_t pid, const dds_duration_t dur); -void nn_xmsg_addpar_subscription_keys (struct nn_xmsg *m, nn_parameterid_t pid, const struct dds_subscription_keys_qospolicy *rq); -void nn_xmsg_addpar_durability_service (struct nn_xmsg *m, nn_parameterid_t pid, const dds_durability_service_qospolicy_t *rq); -void nn_xmsg_addpar_reader_lifespan (struct nn_xmsg *m, nn_parameterid_t pid, const dds_reader_lifespan_qospolicy_t *rq); -void nn_xmsg_addpar_reader_data_lifecycle (struct nn_xmsg *m, nn_parameterid_t pid, const dds_reader_data_lifecycle_qospolicy_t *rq); -void nn_xmsg_addpar_liveliness (struct nn_xmsg *m, nn_parameterid_t pid, const dds_liveliness_qospolicy_t *rq); - -void nn_xmsg_addpar_parvinfo (struct nn_xmsg *m, nn_parameterid_t pid, const struct nn_prismtech_participant_version_info *pvi); +void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, unsigned statusinfo); void nn_xmsg_addpar_sentinel (struct nn_xmsg *m); int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg *m); diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 8c5b38c..86c7a5f 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -333,7 +333,7 @@ static struct ddsi_serdata *serdata_default_from_ser_nokey (const struct ddsi_se return fix_serdata_default_nokey (d, tpcmn->serdata_basehash); } -struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash) +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 */ const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn; @@ -360,7 +360,7 @@ struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr (const struct ddsi_sertopic * } } -struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr_nokey (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash) +static struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr_nokey (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash) { const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn; struct ddsi_serdata_default *d = serdata_default_new(tp, SDK_KEY); diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 85fde82..f35171c 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -408,7 +408,7 @@ static void ddsi_udp_release_conn (ddsi_tran_conn_t conn) ddsrt_free (conn); } -void ddsi_udp_fini (void) +static void ddsi_udp_fini (void) { if(ddsrt_atomic_dec32_nv (&ddsi_udp_init_g) == 0) { free_group_membership(ddsi_udp_config_g.mship); diff --git a/src/core/ddsi/src/q_addrset.c b/src/core/ddsi/src/q_addrset.c index ffd1d76..b20eb72 100644 --- a/src/core/ddsi/src/q_addrset.c +++ b/src/core/ddsi/src/q_addrset.c @@ -384,24 +384,6 @@ void copy_addrset_into_addrset_no_ssm (struct addrset *as, const struct addrset copy_addrset_into_addrset_uc (as, asadd); copy_addrset_into_addrset_no_ssm_mc (as, asadd); } - -void addrset_purge_ssm (struct addrset *as) -{ - struct addrset_node *n; - LOCK (as); - n = ddsrt_avl_cfind_min (&addrset_treedef, &as->mcaddrs); - while (n) - { - struct addrset_node *n1 = n; - n = ddsrt_avl_cfind_succ (&addrset_treedef, &as->mcaddrs, n); - if (ddsi_is_ssm_mcaddr (&n1->loc)) - { - ddsrt_avl_cdelete (&addrset_treedef, &as->mcaddrs, n1); - ddsrt_free (n1); - } - } - UNLOCK (as); -} #endif size_t addrset_count (const struct addrset *as) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 3ae6d2a..21eea71 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -190,7 +190,7 @@ static void entity_common_fini (struct entity_common *e) ddsrt_mutex_destroy (&e->lock); } -void local_reader_ary_init (struct local_reader_ary *x) +static void local_reader_ary_init (struct local_reader_ary *x) { ddsrt_mutex_init (&x->rdary_lock); x->valid = 1; @@ -200,13 +200,13 @@ void local_reader_ary_init (struct local_reader_ary *x) x->rdary[0] = NULL; } -void local_reader_ary_fini (struct local_reader_ary *x) +static void local_reader_ary_fini (struct local_reader_ary *x) { ddsrt_free (x->rdary); ddsrt_mutex_destroy (&x->rdary_lock); } -void local_reader_ary_insert (struct local_reader_ary *x, struct reader *rd) +static void local_reader_ary_insert (struct local_reader_ary *x, struct reader *rd) { ddsrt_mutex_lock (&x->rdary_lock); x->n_readers++; @@ -216,7 +216,7 @@ void local_reader_ary_insert (struct local_reader_ary *x, struct reader *rd) ddsrt_mutex_unlock (&x->rdary_lock); } -void local_reader_ary_remove (struct local_reader_ary *x, struct reader *rd) +static void local_reader_ary_remove (struct local_reader_ary *x, struct reader *rd) { uint32_t i; ddsrt_mutex_lock (&x->rdary_lock); @@ -242,7 +242,7 @@ void local_reader_ary_setfastpath_ok (struct local_reader_ary *x, bool fastpath_ ddsrt_mutex_unlock (&x->rdary_lock); } -void local_reader_ary_setinvalid (struct local_reader_ary *x) +static void local_reader_ary_setinvalid (struct local_reader_ary *x) { ddsrt_mutex_lock (&x->rdary_lock); x->valid = 0; diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index 08b5de1..c6d1848 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -46,7 +46,7 @@ extern inline void thread_state_awake_to_awake_no_nest (struct thread_state1 *ts static struct thread_state1 *init_thread_state (const char *tname, enum thread_state state); -void *ddsrt_malloc_aligned_cacheline (size_t size) +static void *ddsrt_malloc_aligned_cacheline (size_t size) { /* This wastes some space, but we use it only once and it isn't a huge amount of memory, just a little over a cache line. diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index f21214d..5cebfeb 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -147,7 +147,7 @@ typedef struct { ddsrt_cond_t cv; } ddsi_sem_t; -dds_return_t +static dds_return_t ddsi_sem_init (ddsi_sem_t *sem, uint32_t value) { sem->value = value; @@ -156,7 +156,7 @@ ddsi_sem_init (ddsi_sem_t *sem, uint32_t value) return DDS_RETCODE_OK; } -dds_return_t +static dds_return_t ddsi_sem_destroy (ddsi_sem_t *sem) { ddsrt_cond_destroy (&sem->cv); @@ -164,7 +164,7 @@ ddsi_sem_destroy (ddsi_sem_t *sem) return DDS_RETCODE_OK; } -dds_return_t +static dds_return_t ddsi_sem_post (ddsi_sem_t *sem) { ddsrt_mutex_lock (&sem->mtx); @@ -174,7 +174,7 @@ ddsi_sem_post (ddsi_sem_t *sem) return DDS_RETCODE_OK; } -dds_return_t +static dds_return_t ddsi_sem_wait (ddsi_sem_t *sem) { ddsrt_mutex_lock (&sem->mtx); @@ -763,41 +763,6 @@ void nn_xmsg_setwriterseq_fragid (struct nn_xmsg *msg, const nn_guid_t *wrguid, msg->kindspecific.data.wrfragid = wrfragid; } -size_t nn_xmsg_add_string_padded(unsigned char *buf, char *str) -{ - size_t len = strlen (str) + 1; - assert (len <= UINT32_MAX); - if (buf) { - /* Add cdr string */ - struct cdrstring *p = (struct cdrstring *) buf; - p->length = (uint32_t)len; - memcpy (p->contents, str, len); - /* clear padding */ - if (len < align4u (len)) { - memset (p->contents + len, 0, align4u (len) - len); - } - } - len = 4 + /* cdr string len arg + */ - align4u(len); /* strlen + possible padding */ - return len; -} - -size_t nn_xmsg_add_octseq_padded(unsigned char *buf, ddsi_octetseq_t *seq) -{ - uint32_t len = seq->length; - if (buf) { - /* Add cdr octet seq */ - *((uint32_t *) buf) = len; - buf += sizeof (uint32_t); - memcpy (buf, seq->value, len); - /* clear padding */ - if (len < align4u (len)) { - memset (buf + len, 0, align4u (len) - len); - } - } - return 4 + align4u (len); -} - void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len) { const size_t len4 = (len + 3) & ~(size_t)3; /* must alloc a multiple of 4 */ @@ -816,43 +781,6 @@ void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len) return p; } -void nn_xmsg_addpar_string (struct nn_xmsg *m, nn_parameterid_t pid, const char *str) -{ - struct cdrstring *p; - size_t len = strlen (str) + 1; - p = nn_xmsg_addpar (m, pid, 4 + len); - p->length = (uint32_t) len; - memcpy (p->contents, str, len); -} - -void nn_xmsg_addpar_octetseq (struct nn_xmsg *m, nn_parameterid_t pid, const ddsi_octetseq_t *oseq) -{ - char *p = nn_xmsg_addpar (m, pid, 4 + oseq->length); - *((unsigned *) p) = oseq->length; - memcpy (p + sizeof (int), oseq->value, oseq->length); -} - -void nn_xmsg_addpar_stringseq (struct nn_xmsg *m, nn_parameterid_t pid, const ddsi_stringseq_t *sseq) -{ - unsigned char *tmp; - uint32_t i; - size_t len = 0; - - for (i = 0; i < sseq->n; i++) - { - len += nn_xmsg_add_string_padded(NULL, sseq->strs[i]); - } - - tmp = nn_xmsg_addpar (m, pid, 4 + len); - - *((uint32_t *) tmp) = sseq->n; - tmp += sizeof (uint32_t); - for (i = 0; i < sseq->n; i++) - { - tmp += nn_xmsg_add_string_padded(tmp, sseq->strs[i]); - } -} - void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata) { if (serdata->kind != SDK_EMPTY) @@ -863,78 +791,7 @@ void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serda } } -void nn_xmsg_addpar_guid (struct nn_xmsg *m, nn_parameterid_t pid, const nn_guid_t *guid) -{ - unsigned *pu; - int i; - pu = nn_xmsg_addpar (m, pid, 16); - for (i = 0; i < 3; i++) - { - pu[i] = toBE4u (guid->prefix.u[i]); - } - pu[i] = toBE4u (guid->entityid.u); -} - -void nn_xmsg_addpar_reliability (struct nn_xmsg *m, nn_parameterid_t pid, const struct dds_reliability_qospolicy *rq) -{ - struct dds_external_reliability_qospolicy *p; - p = nn_xmsg_addpar (m, pid, sizeof (*p)); - switch (rq->kind) - { - case DDS_RELIABILITY_BEST_EFFORT: - p->kind = DDS_EXTERNAL_RELIABILITY_BEST_EFFORT; - break; - case DDS_RELIABILITY_RELIABLE: - p->kind = DDS_EXTERNAL_RELIABILITY_RELIABLE; - break; - default: - assert (0); - } - p->max_blocking_time = nn_to_ddsi_duration (rq->max_blocking_time); -} - -void nn_xmsg_addpar_duration (struct nn_xmsg *m, nn_parameterid_t pid, const dds_duration_t rq) -{ - ddsi_duration_t *p = nn_xmsg_addpar (m, pid, sizeof (*p)); - *p = nn_to_ddsi_duration (rq); -} - -void nn_xmsg_addpar_durability_service (struct nn_xmsg *m, nn_parameterid_t pid, const dds_durability_service_qospolicy_t *rq) -{ - dds_external_durability_service_qospolicy_t *p = nn_xmsg_addpar (m, pid, sizeof (*p)); - p->history = rq->history; - p->resource_limits = rq->resource_limits; - p->service_cleanup_delay = nn_to_ddsi_duration (rq->service_cleanup_delay); -} - -void nn_xmsg_addpar_reader_lifespan (struct nn_xmsg *m, nn_parameterid_t pid, const dds_reader_lifespan_qospolicy_t *rq) -{ - dds_external_reader_lifespan_qospolicy_t *p = nn_xmsg_addpar (m, pid, sizeof (*p)); - p->use_lifespan = rq->use_lifespan; - p->duration = nn_to_ddsi_duration (rq->duration); -} - -void nn_xmsg_addpar_reader_data_lifecycle (struct nn_xmsg *m, nn_parameterid_t pid, const dds_reader_data_lifecycle_qospolicy_t *rq) -{ - dds_external_reader_data_lifecycle_qospolicy_t *p = nn_xmsg_addpar (m, pid, sizeof (*p)); - p->autopurge_disposed_samples_delay = nn_to_ddsi_duration (rq->autopurge_disposed_samples_delay); - p->autopurge_nowriter_samples_delay = nn_to_ddsi_duration (rq->autopurge_nowriter_samples_delay); -} - -void nn_xmsg_addpar_liveliness (struct nn_xmsg *m, nn_parameterid_t pid, const dds_liveliness_qospolicy_t *rq) -{ - dds_external_liveliness_qospolicy_t *p = nn_xmsg_addpar (m, pid, sizeof (*p)); - p->kind = rq->kind; - p->lease_duration = nn_to_ddsi_duration (rq->lease_duration); -} - -void nn_xmsg_addpar_4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x) -{ - unsigned *p = nn_xmsg_addpar (m, pid, sizeof (x)); - *p = x; -} - -void nn_xmsg_addpar_BE4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x) +static void nn_xmsg_addpar_BE4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x) { unsigned *p = nn_xmsg_addpar (m, pid, sizeof (x)); *p = toBE4u (x); @@ -956,40 +813,6 @@ void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, unsigned statusinfo) } } -void nn_xmsg_addpar_subscription_keys (struct nn_xmsg *m, nn_parameterid_t pid, const struct dds_subscription_keys_qospolicy *q) -{ - unsigned char *tmp; - size_t len = 8; /* use_key_list, length of key_list */ - - for (uint32_t i = 0; i < q->key_list.n; i++) - { - size_t len1 = strlen (q->key_list.strs[i]) + 1; - len += 4 + align4u (len1); - } - - tmp = nn_xmsg_addpar (m, pid, len); - - tmp[0] = q->use_key_list; - for (uint32_t i = 1; i < sizeof (int); i++) - { - tmp[i] = 0; - } - tmp += sizeof (int); - *((uint32_t *) tmp) = q->key_list.n; - tmp += sizeof (uint32_t); - for (uint32_t i = 0; i < q->key_list.n; i++) - { - struct cdrstring *p = (struct cdrstring *) tmp; - size_t len1 = strlen (q->key_list.strs[i]) + 1; - assert (len1 <= UINT32_MAX); - p->length = (uint32_t)len1; - memcpy (p->contents, q->key_list.strs[i], len1); - if (len1 < align4u (len1)) - memset (p->contents + len1, 0, align4u (len1) - len1); - tmp += 4 + align4u (len1); - } -} - void nn_xmsg_addpar_sentinel (struct nn_xmsg * m) { nn_xmsg_addpar (m, PID_SENTINEL, 0); @@ -1005,27 +828,6 @@ int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg * m) return 0; } -void nn_xmsg_addpar_parvinfo (struct nn_xmsg *m, nn_parameterid_t pid, const struct nn_prismtech_participant_version_info *pvi) -{ - int i; - unsigned slen; - unsigned *pu; - struct cdrstring *ps; - - /* pvi->internals cannot be NULL here */ - slen = (unsigned) strlen(pvi->internals) + 1; /* +1 for '\0' terminator */ - pu = nn_xmsg_addpar (m, pid, NN_PRISMTECH_PARTICIPANT_VERSION_INFO_FIXED_CDRSIZE + slen); - pu[0] = pvi->version; - pu[1] = pvi->flags; - for (i = 0; i < 3; i++) - { - pu[i+2] = (pvi->unused[i]); - } - ps = (struct cdrstring *)&pu[5]; - ps->length = slen; - memcpy(ps->contents, pvi->internals, slen); -} - /* XMSG_CHAIN ---------------------------------------------------------- Xpacks refer to xmsgs and need to release these after having been diff --git a/src/ddsrt/src/cdtors.c b/src/ddsrt/src/cdtors.c index 3888c87..de63e32 100644 --- a/src/ddsrt/src/cdtors.c +++ b/src/ddsrt/src/cdtors.c @@ -139,6 +139,9 @@ ddsrt_cdtor( #pragma data_seg() #endif #else /* _WIN32 */ +void __attribute__((constructor)) ddsrt_ctor(void); +void __attribute__((destructor)) ddsrt_dtor(void); + void __attribute__((constructor)) ddsrt_ctor(void) { ddsrt_init(); diff --git a/src/ddsrt/src/strtol.c b/src/ddsrt/src/strtol.c index 009c012..5269d96 100644 --- a/src/ddsrt/src/strtol.c +++ b/src/ddsrt/src/strtol.c @@ -16,7 +16,7 @@ #include "dds/ddsrt/strtol.h" -int ddsrt_todigit(const int chr) +static int ddsrt_todigit(const int chr) { if (chr >= '0' && chr <= '9') { return chr - '0'; diff --git a/src/ddsrt/tests/thread.c b/src/ddsrt/tests/thread.c index 2e6b5d6..a217ac6 100644 --- a/src/ddsrt/tests/thread.c +++ b/src/ddsrt/tests/thread.c @@ -65,7 +65,7 @@ typedef struct { ddsrt_threadattr_t *attr; } thread_arg_t; -uint32_t thread_main(void *ptr) +static uint32_t thread_main(void *ptr) { thread_arg_t *arg = (thread_arg_t *)ptr; ddsrt_threadattr_t *attr; @@ -193,7 +193,7 @@ CU_Test(ddsrt_thread, thread_id) static ddsrt_mutex_t locks[2]; -uint32_t thread_main_waitforme(void *ptr) +static uint32_t thread_main_waitforme(void *ptr) { uint32_t ret = 0; (void)ptr; @@ -203,7 +203,7 @@ uint32_t thread_main_waitforme(void *ptr) return ret; } -uint32_t thread_main_waitforit(void *ptr) +static uint32_t thread_main_waitforit(void *ptr) { uint32_t res = 0; ddsrt_thread_t *thr = (ddsrt_thread_t *)ptr; diff --git a/src/mpt/mpt/include/mpt/mpt.h b/src/mpt/mpt/include/mpt/mpt.h index 719c9d6..f8b95fe 100644 --- a/src/mpt/mpt/include/mpt/mpt.h +++ b/src/mpt/mpt/include/mpt/mpt.h @@ -52,6 +52,7 @@ void MPT_ProcessEntryName(process)(args) #define MPT_TestProcess(suite, test, name, process, args, ...) \ MPT_TestInitDeclaration(suite, test); \ MPT_TestFiniDeclaration(suite, test); \ +MPT_TestProcessDeclaration(suite, test, name); \ MPT_TestProcessDeclaration(suite, test, name) \ { \ mpt_data_t data = MPT_Fixture(__VA_ARGS__); \ diff --git a/src/mpt/tests/basic/procs/hello.c b/src/mpt/tests/basic/procs/hello.c index 8623ac0..84e6c5e 100644 --- a/src/mpt/tests/basic/procs/hello.c +++ b/src/mpt/tests/basic/procs/hello.c @@ -5,7 +5,6 @@ #include "mpt/mpt.h" #include "dds/dds.h" -#include "helloworlddata.h" #include "dds/ddsrt/time.h" #include "dds/ddsrt/strtol.h" @@ -14,6 +13,8 @@ #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/sync.h" +#include "hello.h" +#include "helloworlddata.h" /* An array of one message (aka sample in dds terms) will be used. */ #define MAX_SAMPLES 1 diff --git a/src/mpt/tests/qos/procs/ppud.c b/src/mpt/tests/qos/procs/ppud.c index 0d564fb..65528fe 100644 --- a/src/mpt/tests/qos/procs/ppud.c +++ b/src/mpt/tests/qos/procs/ppud.c @@ -14,7 +14,6 @@ #include #include "mpt/mpt.h" -#include "rwdata.h" #include "dds/dds.h" @@ -23,6 +22,9 @@ #include "dds/ddsrt/sockets.h" #include "dds/ddsrt/heap.h" +#include "ppud.h" +#include "rwdata.h" + void ppud_init (void) { } void ppud_fini (void) { } diff --git a/src/mpt/tests/qos/procs/rw.c b/src/mpt/tests/qos/procs/rw.c index ba0d3b9..0a3ec32 100644 --- a/src/mpt/tests/qos/procs/rw.c +++ b/src/mpt/tests/qos/procs/rw.c @@ -16,7 +16,6 @@ #include "mpt/mpt.h" #include "dds/dds.h" -#include "rwdata.h" #include "dds/ddsrt/time.h" #include "dds/ddsrt/process.h" @@ -25,6 +24,9 @@ #include "dds/ddsi/q_xqos.h" +#include "rwdata.h" +#include "rw.h" + #define NPUB 10 #define NWR_PUB 2 diff --git a/src/tools/ddsls/ddsls.c b/src/tools/ddsls/ddsls.c index fed04c4..216cff6 100644 --- a/src/tools/ddsls/ddsls.c +++ b/src/tools/ddsls/ddsls.c @@ -24,7 +24,7 @@ #define MAX_SAMPLES 10 #define MAX_DURATION_BUFSZ 21 -char *qp_duration_str (char *buf, size_t bufsz, dds_duration_t d) +static char *qp_duration_str (char *buf, size_t bufsz, dds_duration_t d) { if (d == DDS_INFINITY) snprintf (buf, bufsz, "infinite"); @@ -33,7 +33,7 @@ char *qp_duration_str (char *buf, size_t bufsz, dds_duration_t d) return buf; } -size_t printable_seq_length (const unsigned char *as, size_t n) +static size_t printable_seq_length (const unsigned char *as, size_t n) { size_t i; for (i = 0; i < n; i++) { @@ -43,7 +43,7 @@ size_t printable_seq_length (const unsigned char *as, size_t n) return i; } -void print_octetseq (const unsigned char *v, size_t sz, FILE *fp) +static void print_octetseq (const unsigned char *v, size_t sz, FILE *fp) { size_t i, n; fprintf (fp, "%zu<", sz); @@ -69,7 +69,7 @@ void print_octetseq (const unsigned char *v, size_t sz, FILE *fp) fprintf (fp, ">"); } -void qp_user_data (const dds_qos_t *q, FILE *fp) +static void qp_user_data (const dds_qos_t *q, FILE *fp) { void *ud; size_t udsz; @@ -82,7 +82,7 @@ void qp_user_data (const dds_qos_t *q, FILE *fp) } } -void qp_topic_data (const dds_qos_t *q, FILE *fp) +static void qp_topic_data (const dds_qos_t *q, FILE *fp) { void *ud; size_t udsz; @@ -95,7 +95,7 @@ void qp_topic_data (const dds_qos_t *q, FILE *fp) } } -void qp_group_data (const dds_qos_t *q, FILE *fp) +static void qp_group_data (const dds_qos_t *q, FILE *fp) { void *ud; size_t udsz; @@ -108,7 +108,7 @@ void qp_group_data (const dds_qos_t *q, FILE *fp) } } -void qp_durability (const dds_qos_t *q, FILE *fp) +static void qp_durability (const dds_qos_t *q, FILE *fp) { dds_durability_kind_t kind; if (dds_qget_durability (q, &kind)) @@ -125,7 +125,7 @@ void qp_durability (const dds_qos_t *q, FILE *fp) } } -void qp_history (const dds_qos_t *q, FILE *fp) +static void qp_history (const dds_qos_t *q, FILE *fp) { dds_history_kind_t kind; int32_t depth; @@ -144,7 +144,7 @@ void qp_history (const dds_qos_t *q, FILE *fp) } } -void qp_resource_limits_1 (FILE *fp, int32_t max_samples, int32_t max_instances, int32_t max_samples_per_instance, int indent) +static void qp_resource_limits_1 (FILE *fp, int32_t max_samples, int32_t max_instances, int32_t max_samples_per_instance, int indent) { fprintf (fp, "%*.*sresource_limits: max_samples = ", indent, indent, ""); if (max_samples == DDS_LENGTH_UNLIMITED) @@ -163,14 +163,14 @@ void qp_resource_limits_1 (FILE *fp, int32_t max_samples, int32_t max_instances, fprintf (fp, "%"PRId32"\n", max_samples_per_instance); } -void qp_resource_limits (const dds_qos_t *q, FILE *fp) +static void qp_resource_limits (const dds_qos_t *q, FILE *fp) { int32_t max_samples, max_instances, max_samples_per_instance; if (dds_qget_resource_limits (q, &max_samples, &max_instances, &max_samples_per_instance)) qp_resource_limits_1 (fp, max_samples, max_instances, max_samples_per_instance, 2); } -void qp_presentation (const dds_qos_t *q, FILE *fp) +static void qp_presentation (const dds_qos_t *q, FILE *fp) { dds_presentation_access_scope_kind_t access_scope; bool coherent_access, ordered_access; @@ -187,7 +187,7 @@ void qp_presentation (const dds_qos_t *q, FILE *fp) } } -void qp_duration_qos (const dds_qos_t *q, FILE *fp, const char *what, bool (*qget) (const dds_qos_t * __restrict qos, dds_duration_t *d)) +static void qp_duration_qos (const dds_qos_t *q, FILE *fp, const char *what, bool (*qget) (const dds_qos_t * __restrict qos, dds_duration_t *d)) { dds_duration_t d; char buf[MAX_DURATION_BUFSZ]; @@ -195,27 +195,27 @@ void qp_duration_qos (const dds_qos_t *q, FILE *fp, const char *what, bool (*qge fprintf (fp, " %s = %s\n", what, qp_duration_str (buf, sizeof (buf), d)); } -void qp_lifespan (const dds_qos_t *q, FILE *fp) +static void qp_lifespan (const dds_qos_t *q, FILE *fp) { qp_duration_qos (q, fp, "lifespan: duration", dds_qget_lifespan); } -void qp_deadline (const dds_qos_t *q, FILE *fp) +static void qp_deadline (const dds_qos_t *q, FILE *fp) { qp_duration_qos (q, fp, "deadline: period", dds_qget_deadline); } -void qp_latency_budget (const dds_qos_t *q, FILE *fp) +static void qp_latency_budget (const dds_qos_t *q, FILE *fp) { qp_duration_qos (q, fp, "latency_budget: duration", dds_qget_latency_budget); } -void qp_time_based_filter (const dds_qos_t *q, FILE *fp) +static void qp_time_based_filter (const dds_qos_t *q, FILE *fp) { qp_duration_qos (q, fp, "time_based_filter: minimum_separation", dds_qget_time_based_filter); } -void qp_ownership (const dds_qos_t *q, FILE *fp) +static void qp_ownership (const dds_qos_t *q, FILE *fp) { dds_ownership_kind_t kind; char *s = "?"; @@ -230,14 +230,14 @@ void qp_ownership (const dds_qos_t *q, FILE *fp) } } -void qp_ownership_strength (const dds_qos_t *q, FILE *fp) +static void qp_ownership_strength (const dds_qos_t *q, FILE *fp) { int32_t value; if (dds_qget_ownership_strength (q, &value)) fprintf (fp, " ownership_strength: value = %"PRId32"\n", value); } -void qp_liveliness (const dds_qos_t *q, FILE *fp) +static void qp_liveliness (const dds_qos_t *q, FILE *fp) { dds_liveliness_kind_t kind; dds_duration_t lease_duration; @@ -255,7 +255,7 @@ void qp_liveliness (const dds_qos_t *q, FILE *fp) } } -void qp_reliability (const dds_qos_t *q, FILE *fp) +static void qp_reliability (const dds_qos_t *q, FILE *fp) { dds_reliability_kind_t kind; dds_duration_t max_blocking_time; @@ -272,14 +272,14 @@ void qp_reliability (const dds_qos_t *q, FILE *fp) } } -void qp_transport_priority (const dds_qos_t *q, FILE *fp) +static void qp_transport_priority (const dds_qos_t *q, FILE *fp) { int32_t value; if (dds_qget_transport_priority (q, &value)) fprintf (fp, " transport_priority: priority = %"PRId32"\n", value); } -void qp_destination_order (const dds_qos_t *q, FILE *fp) +static void qp_destination_order (const dds_qos_t *q, FILE *fp) { dds_destination_order_kind_t kind; if (dds_qget_destination_order (q, &kind)) @@ -294,14 +294,14 @@ void qp_destination_order (const dds_qos_t *q, FILE *fp) } } -void qp_writer_data_lifecycle (const dds_qos_t *q, FILE *fp) +static void qp_writer_data_lifecycle (const dds_qos_t *q, FILE *fp) { bool value; if (dds_qget_writer_data_lifecycle (q, &value)) fprintf (fp, " writer_data_lifecycle: autodispose_unregistered_instances = %s\n", value ? "true" : "false"); } -void qp_reader_data_lifecycle (const dds_qos_t *q, FILE *fp) +static void qp_reader_data_lifecycle (const dds_qos_t *q, FILE *fp) { dds_duration_t autopurge_nowriter_samples_delay, autopurge_disposed_samples_delay; if (dds_qget_reader_data_lifecycle (q, &autopurge_nowriter_samples_delay, &autopurge_disposed_samples_delay)) @@ -311,7 +311,7 @@ void qp_reader_data_lifecycle (const dds_qos_t *q, FILE *fp) } } -void qp_durability_service (const dds_qos_t *q, FILE *fp) +static void qp_durability_service (const dds_qos_t *q, FILE *fp) { dds_duration_t service_cleanup_delay; dds_history_kind_t history_kind; @@ -335,7 +335,7 @@ void qp_durability_service (const dds_qos_t *q, FILE *fp) } } -void qp_partition (const dds_qos_t *q, FILE *fp) +static void qp_partition (const dds_qos_t *q, FILE *fp) { uint32_t n; char **ps; @@ -360,7 +360,7 @@ void qp_partition (const dds_qos_t *q, FILE *fp) } } -void qp_qos (const dds_qos_t *q, FILE *fp) +static void qp_qos (const dds_qos_t *q, FILE *fp) { qp_reliability (q, fp); qp_durability (q, fp); @@ -385,7 +385,7 @@ void qp_qos (const dds_qos_t *q, FILE *fp) qp_group_data (q, fp); } -void print_key(FILE *fp, const char *label, const dds_builtintopic_guid_t *key) +static void print_key(FILE *fp, const char *label, const dds_builtintopic_guid_t *key) { fprintf(fp, "%s", label); for(size_t j = 0; j < sizeof (key->v); j++) { @@ -422,7 +422,7 @@ void print_dcps_topic (FILE *fp, dds_entity_t pp) } #endif -void print_dcps_participant (FILE *fp, dds_entity_t pp) +static void print_dcps_participant (FILE *fp, dds_entity_t pp) { dds_entity_t rd = dds_create_reader (pp, DDS_BUILTIN_TOPIC_DCPSPARTICIPANT, NULL, NULL); (void)dds_reader_wait_for_historical_data (rd, DDS_SECS (5)); @@ -448,7 +448,7 @@ void print_dcps_participant (FILE *fp, dds_entity_t pp) dds_delete (rd); } -void print_dcps_endpoint (FILE *fp, dds_entity_t pp, const char *type, dds_entity_t topic) +static void print_dcps_endpoint (FILE *fp, dds_entity_t pp, const char *type, dds_entity_t topic) { dds_entity_t rd = dds_create_reader (pp, topic, NULL, NULL); (void)dds_reader_wait_for_historical_data (rd, DDS_SECS (5)); @@ -477,12 +477,12 @@ void print_dcps_endpoint (FILE *fp, dds_entity_t pp, const char *type, dds_entit dds_delete (rd); } -void print_dcps_subscription (FILE *fp, dds_entity_t pp) +static void print_dcps_subscription (FILE *fp, dds_entity_t pp) { print_dcps_endpoint (fp, pp, "SUBSCRIPTION", DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION); } -void print_dcps_publication (FILE *fp, dds_entity_t pp) +static void print_dcps_publication (FILE *fp, dds_entity_t pp) { print_dcps_endpoint (fp, pp, "PUBLICATION", DDS_BUILTIN_TOPIC_DCPSPUBLICATION); } @@ -504,7 +504,7 @@ static struct topictab { }; #define TOPICTAB_SIZE (sizeof(topictab)/sizeof(struct topictab)) -void usage (void) +static void usage (void) { fprintf (stderr, "Usage: ddsls [OPTIONS] TOPIC... for specified topics\n\n"); fprintf (stderr, " or: ddsls [OPTIONS] -a for all topics\n"); diff --git a/src/tools/pubsub/common.c b/src/tools/pubsub/common.c index be217cb..b9bcd60 100644 --- a/src/tools/pubsub/common.c +++ b/src/tools/pubsub/common.c @@ -943,7 +943,7 @@ void setqos_from_args(dds_entity_kind_t qt, dds_qos_t *q, int n, const char *arg #define DDS_ERR_MSG_MAX 128 -void dds_fail (const char * msg, const char * where) +static void dds_fail (const char * msg, const char * where) { fprintf (stderr, "Aborting Failure: %s %s\n", where, msg); abort (); diff --git a/src/tools/pubsub/common.h b/src/tools/pubsub/common.h index 1beca88..036e7b7 100644 --- a/src/tools/pubsub/common.h +++ b/src/tools/pubsub/common.h @@ -106,9 +106,11 @@ void qos_ownership(dds_entity_kind_t qt, dds_qos_t *q, const char *arg); void qos_transport_priority(dds_entity_kind_t qt, dds_qos_t *q, const char *arg); void qos_reliability(dds_entity_kind_t qt, dds_qos_t *q, const char *arg); void qos_resource_limits(dds_entity_kind_t qt, dds_qos_t *q, const char *arg); +void qos_durability_service(dds_entity_kind_t qt, dds_qos_t *q, const char *arg); void qos_user_data(dds_entity_kind_t qt, dds_qos_t *q, const char *arg); void qos_latency_budget(dds_entity_kind_t qt, dds_qos_t *q, const char *arg); void qos_lifespan(dds_entity_kind_t qt, dds_qos_t *q, const char *arg); +void qos_presentation(dds_entity_kind_t qt, dds_qos_t *q, const char *arg); void qos_autodispose_unregistered_instances(dds_entity_kind_t qt, dds_qos_t *q, const char *arg); void set_qosprovider(const char *arg); void setqos_from_args(dds_entity_kind_t qt, dds_qos_t *q, int n, const char *args[]); From f6fc1751e9c2f650b2f0ce434851e8784e659fa9 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 5 Jun 2019 12:13:10 +0200 Subject: [PATCH 097/178] Treat warnings as errors in CI builds The CMake files now add "-Werror"/"/WX" if the "WERROR" CMake variable is true. By default it is not; the CI builds set this. Signed-off-by: Erik Boasson --- .travis.yml | 1 + appveyor.yml | 2 +- src/CMakeLists.txt | 37 +++++++++++++++++++++++++++---------- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 70b0781..6738669 100644 --- a/.travis.yml +++ b/.travis.yml @@ -164,6 +164,7 @@ script: -DCMAKE_INSTALL_PREFIX=$(pwd)/install -DUSE_SANITIZER=${ASAN} -DBUILD_TESTING=on + -DWERROR=on -G "${GENERATOR}" ../src - ${SCAN_BUILD} cmake --build . --config ${BUILD_TYPE} --target install - CYCLONEDDS_URI='all' ctest -T test -C ${BUILD_TYPE} diff --git a/appveyor.yml b/appveyor.yml index 0c96ec1..363272b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -36,7 +36,7 @@ build_script: - mkdir build - cd build - conan install -s arch=%ARCH% -s build_type=%CONFIGURATION% .. - - cmake -DBUILD_TESTING=on -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DCMAKE_INSTALL_PREFIX=%CD%/install -G "%GENERATOR%" ../src + - cmake -DBUILD_TESTING=on -DWERROR=ON -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DCMAKE_INSTALL_PREFIX=%CD%/install -G "%GENERATOR%" ../src - cmake --build . --config %CONFIGURATION% --target install -- /maxcpucount - cd install/share/CycloneDDS/examples/helloworld - mkdir build diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d5f906d..e5beb7a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,6 +22,11 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() +# By default don't treat warnings as errors, else anyone building it with a different compiler that +# just happens to generate a warning, as well as anyone adding or modifying something and making a +# small mistake would run into errors. CI builds can be configured differently. +option(WERROR "Treat compiler warnings as errors" OFF) + FUNCTION(PREPEND var prefix) SET(listVar "") FOREACH(f ${ARGN}) @@ -86,18 +91,30 @@ endif() # Set reasonably strict warning options for clang, gcc, msvc # Enable coloured ouput if Ninja is used for building -if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_C_COMPILER_ID} STREQUAL "AppleClang") - add_definitions(-Wall -Wextra -Wconversion -Wunused -Wmissing-prototypes) - if(${CMAKE_GENERATOR} STREQUAL "Ninja") - add_definitions(-Xclang -fcolor-diagnostics) +if("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") + #message(STATUS clang) + add_compile_options(-Wall -Wextra -Wconversion -Wunused -Wmissing-prototypes) + if(${WERROR}) + add_compile_options(-Werror) endif() -elseif(${CMAKE_C_COMPILER_ID} STREQUAL "GNU") - add_definitions(-Wall -Wextra -Wconversion -Wmissing-prototypes) - if(${CMAKE_GENERATOR} STREQUAL "Ninja") - add_definitions(-fdiagnostics-color=always) + if("${CMAKE_GENERATOR}" STREQUAL "Ninja") + add_compile_options(-Xclang -fcolor-diagnostics) + endif() +elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") + #message(STATUS gcc) + add_compile_options(-Wall -Wextra -Wconversion -Wmissing-prototypes) + if(${WERROR}) + add_compile_options(-Werror) + endif() + if("${CMAKE_GENERATOR}" STREQUAL "Ninja") + add_compile_options(-fdiagnostics-color=always) + endif() +elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") + #message(STATUS msvc) + add_compile_options(/W3) + if(${WERROR}) + add_compile_options(/WX) endif() -elseif(${CMAKE_C_COMPILER_ID} STREQUAL "MSVC") - add_definitions(/W3) endif() # I don't know how to enable warnings properly so that it ends up in Xcode projects as well From 95ea8fbf3296cb7211ab228c835dfde088064e51 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 20 Jun 2019 18:00:02 +0200 Subject: [PATCH 098/178] Update Travis to use xcode 10.2 Signed-off-by: Erik Boasson --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6738669..f0af13a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -67,9 +67,9 @@ linux_clang: &linux_clang install: - pip install conan --upgrade --user -osx_xcode10_1: &osx_xcode10_1 +osx_xcode10_2: &osx_xcode10_2 os: osx - osx_image: xcode10.1 + osx_image: xcode10.2 compiler: clang addons: homebrew: @@ -141,9 +141,9 @@ jobs: env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, GENERATOR="Unix Makefiles" ] - <<: *linux_clang env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, GENERATOR="Unix Makefiles" ] - - <<: *osx_xcode10_1 + - <<: *osx_xcode10_2 env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, GENERATOR="Unix Makefiles" ] - - <<: *osx_xcode10_1 + - <<: *osx_xcode10_2 env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, GENERATOR="Unix Makefiles" ] - <<: *windows_vs2017 env: [ ARCH=x86, ASAN=none, BUILD_TYPE=Debug, GENERATOR="Visual Studio 15 2017" ] From f1db768b3911182c9f0683797e73c0d760aeafff Mon Sep 17 00:00:00 2001 From: Juan Oxoby <49600381+joxoby@users.noreply.github.com> Date: Thu, 20 Jun 2019 10:41:33 -0700 Subject: [PATCH 099/178] Add PacketCapture for received messages in UDP (#202) * Add PacketCapture for receiving messages in UDP Signed-off-by: Juan Oxoby * Explicit cast ret to size_t in write_pcap_received() Signed-off-by: Juan Oxoby --- src/core/ddsi/src/ddsi_udp.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index f35171c..4fb17db 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -86,6 +86,15 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s if (srcloc) ddsi_ipaddr_to_loc(srcloc, (struct sockaddr *)&src, src.ss_family == AF_INET ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_UDPv6); + if(gv.pcap_fp) + { + struct sockaddr_storage dest; + socklen_t dest_len = sizeof (dest); + if (ddsrt_getsockname (((ddsi_udp_conn_t) conn)->m_sock, (struct sockaddr *) &dest, &dest_len) != DDS_RETCODE_OK) + memset(&dest, 0, sizeof(dest)); + write_pcap_received(gv.pcap_fp, now(), &src, &dest, buf, (size_t) ret); + } + /* Check for udp packet truncation */ if ((((size_t) ret) > len) #if DDSRT_MSGHDR_FLAGS From 23b45b961081878eb924726d43ca16ff10c609c9 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Tue, 11 Jun 2019 20:31:20 +0200 Subject: [PATCH 100/178] Add CMake module to interact with Sphinx Signed-off-by: Jeroen Koekkoek --- src/cmake/modules/FindSphinx.cmake | 324 +++++++++++++++++++++++++++++ 1 file changed, 324 insertions(+) create mode 100644 src/cmake/modules/FindSphinx.cmake diff --git a/src/cmake/modules/FindSphinx.cmake b/src/cmake/modules/FindSphinx.cmake new file mode 100644 index 0000000..2e39dfb --- /dev/null +++ b/src/cmake/modules/FindSphinx.cmake @@ -0,0 +1,324 @@ +# +# Copyright(c) 2019 Jeroen Koekkoek +# +# 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(FindPackageHandleStandardArgs) + +macro(_Sphinx_find_executable _exe) + string(TOUPPER "${_exe}" _uc) + # sphinx-(build|quickstart)-3 x.x.x + # FIXME: This works on Fedora (and probably most other UNIX like targets). + # Windows targets and PIP installs might need some work. + find_program( + SPHINX_${_uc}_EXECUTABLE + NAMES "sphinx-${_exe}-3" "sphinx-${_exe}" "sphinx-${_exe}.exe") + + if(SPHINX_${_uc}_EXECUTABLE) + execute_process( + COMMAND "${SPHINX_${_uc}_EXECUTABLE}" --version + RESULT_VARIABLE _result + OUTPUT_VARIABLE _output + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(_result EQUAL 0 AND _output MATCHES " ([0-9]+\\.[0-9]+\\.[0-9]+)$") + set(SPHINX_${_uc}_VERSION "${CMAKE_MATCH_1}") + endif() + + add_executable(Sphinx::${_exe} IMPORTED GLOBAL) + set_target_properties(Sphinx::${_exe} PROPERTIES + IMPORTED_LOCATION "${SPHINX_${_uc}_EXECUTABLE}") + set(Sphinx_${_exe}_FOUND TRUE) + else() + set(Sphinx_${_exe}_FOUND FALSE) + endif() + unset(_uc) +endmacro() + +macro(_Sphinx_find_extension _ext) + if(_SPHINX_PYTHON_EXECUTABLE) + execute_process( + COMMAND ${_SPHINX_PYTHON_EXECUTABLE} -c "import ${_ext}" + RESULT_VARIABLE _result) + if(_result EQUAL 0) + set(Sphinx_${_ext}_FOUND TRUE) + else() + set(Sphinx_${_ext}_FOUND FALSE) + endif() + elseif(CMAKE_HOST_WIN32 AND SPHINX_BUILD_EXECUTABLE) + # script-build on Windows located under (when PIP is used): + # C:/Program Files/PythonXX/Scripts + # C:/Users/username/AppData/Roaming/Python/PythonXX/Sripts + # + # Python modules are installed under: + # C:/Program Files/PythonXX/Lib + # C:/Users/username/AppData/Roaming/Python/PythonXX/site-packages + # + # To verify a given module is installed, use the Python base directory + # and test if either Lib/module.py or site-packages/module.py exists. + get_filename_component(_dirname "${SPHINX_BUILD_EXECUTABLE}" DIRECTORY) + get_filename_component(_dirname "${_dirname}" DIRECTORY) + if(IS_DIRECTORY "${_dirname}/Lib/${_ext}" OR + IS_DIRECTORY "${_dirname}/site-packages/${_ext}") + set(Sphinx_${_ext}_FOUND TRUE) + else() + set(Sphinx_${_ext}_FOUND FALSE) + endif() + endif() +endmacro() + +# +# Find sphinx-build and sphinx-quickstart. +# +_Sphinx_find_executable(build) +_Sphinx_find_executable(quickstart) + +# +# Verify both executables are part of the Sphinx distribution. +# +if(SPHINX_BUILD_EXECUTABLE AND SPHINX_QUICKSTART_EXECUTABLE) + if(NOT SPHINX_BUILD_VERSION STREQUAL SPHINX_QUICKSTART_VERSION) + message(FATAL_ERROR "Versions for sphinx-build (${SPHINX_BUILD_VERSION})" + "and sphinx-quickstart (${SPHINX_QUICKSTART_VERSION})" + "do not match") + endif() +endif() + +# +# To verify the required Sphinx extensions are available, the right Python +# installation must be queried (2 vs 3). Of course, this only makes sense on +# UNIX-like systems. +# +if(NOT CMAKE_HOST_WIN32 AND SPHINX_BUILD_EXECUTABLE) + file(READ "${SPHINX_BUILD_EXECUTABLE}" _contents) + if(_contents MATCHES "^#!([^\n]+)") + string(STRIP "${CMAKE_MATCH_1}" _shebang) + if(EXISTS "${_shebang}") + set(_SPHINX_PYTHON_EXECUTABLE "${_shebang}") + endif() + endif() +endif() + +foreach(_comp IN LISTS Sphinx_FIND_COMPONENTS) + if(_comp STREQUAL "build") + # Do nothing, sphinx-build is always required. + elseif(_comp STREQUAL "quickstart") + # Do nothing, sphinx-quickstart is optional, but looked up by default. + elseif(_comp STREQUAL "breathe") + _Sphinx_find_extension(${_comp}) + else() + message(WARNING "${_comp} is not a valid or supported Sphinx extension") + set(Sphinx_${_comp}_FOUND FALSE) + continue() + endif() +endforeach() + +find_package_handle_standard_args( + Sphinx + VERSION_VAR SPHINX_VERSION + REQUIRED_VARS SPHINX_BUILD_EXECUTABLE SPHINX_BUILD_VERSION + HANDLE_COMPONENTS) + + +# Generate a conf.py template file using sphinx-quickstart. +# +# sphinx-quickstart allows for quiet operation and a lot of settings can be +# specified as command line arguments, therefore its not required to parse the +# generated conf.py. +function(_Sphinx_generate_confpy _target _cachedir) + if(NOT TARGET Sphinx::quickstart) + message(FATAL_ERROR "sphinx-quickstart is not available, needed by" + "sphinx_add_docs for target ${_target}") + endif() + + if(NOT DEFINED SPHINX_PROJECT) + set(SPHINX_PROJECT ${PROJECT_NAME}) + endif() + + if(NOT DEFINED SPHINX_AUTHOR) + set(SPHINX_AUTHOR "${SPHINX_PROJECT} committers") + endif() + + if(NOT DEFINED SPHINX_COPYRIGHT) + string(TIMESTAMP "%Y, ${SPHINX_AUTHOR}" SPHINX_COPYRIGHT) + endif() + + if(NOT DEFINED SPHINX_VERSION) + set(SPHINX_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") + endif() + + if(NOT DEFINED SPHINX_RELEASE) + set(SPHINX_RELEASE "${PROJECT_VERSION}") + endif() + + if(NOT DEFINED SPHINX_LANGUAGE) + set(SPHINX_LANGUAGE "en") + endif() + + set(_known_exts autodoc doctest intersphinx todo coverage imgmath mathjax + ifconfig viewcode githubpages) + + if(DEFINED SPHINX_EXTENSIONS) + foreach(_ext ${SPHINX_EXTENSIONS}) + set(_is_known_ext FALSE) + foreach(_known_ext ${_known_exsts}) + if(_ext STREQUAL _known_ext) + set(_opts "${opts} --ext-${_ext}") + set(_is_known_ext TRUE) + break() + endif() + endforeach() + if(NOT _is_known_ext) + if(_exts) + set(_exts "${_exts},${_ext}") + else() + set(_exts "${_ext}") + endif() + endif() + endforeach() + endif() + + if(_exts) + set(_exts "--extensions=${_exts}") + endif() + + set(_templatedir "${CMAKE_CURRENT_BINARY_DIR}/${_target}.template") + file(MAKE_DIRECTORY "${_templatedir}") + execute_process( + COMMAND "${SPHINX_QUICKSTART_EXECUTABLE}" + -q --no-makefile --no-batchfile + -p "${SPHINX_PROJECT}" + -a "${SPHINX_AUTHOR}" + -v "${SPHINX_VERSION}" + -r "${SPHINX_RELEASE}" + -l "${SPHINX_LANGUAGE}" + ${_opts} ${_exts} "${_templatedir}" + RESULT_VARIABLE _result + OUTPUT_QUIET) + + if(_result EQUAL 0 AND EXISTS "${_templatedir}/conf.py") + file(COPY "${_templatedir}/conf.py" DESTINATION "${_cachedir}") + endif() + + file(REMOVE_RECURSE "${_templatedir}") + + if(NOT _result EQUAL 0 OR NOT EXISTS "${_cachedir}/conf.py") + message(FATAL_ERROR "Sphinx configuration file not generated for " + "target ${_target}") + endif() +endfunction() + +function(sphinx_add_docs _target) + set(_opts) + set(_single_opts BUILDER OUTPUT_DIRECTORY SOURCE_DIRECTORY) + set(_multi_opts BREATHE_PROJECTS) + cmake_parse_arguments(_args "${_opts}" "${_single_opts}" "${_multi_opts}" ${ARGN}) + + unset(SPHINX_BREATHE_PROJECTS) + + if(NOT _args_BUILDER) + message(FATAL_ERROR "Sphinx builder not specified for target ${_target}") + elseif(NOT _args_SOURCE_DIRECTORY) + message(FATAL_ERROR "Sphinx source directory not specified for target ${_target}") + else() + if(NOT IS_ABSOLUTE "${_args_SOURCE_DIRECTORY}") + get_filename_component(_sourcedir "${_args_SOURCE_DIRECTORY}" ABSOLUTE) + else() + set(_sourcedir "${_args_SOURCE_DIRECTORY}") + endif() + if(NOT IS_DIRECTORY "${_sourcedir}") + message(FATAL_ERROR "Sphinx source directory '${_sourcedir}' for" + "target ${_target} does not exist") + endif() + endif() + + set(_builder "${_args_BUILDER}") + if(_args_OUTPUT_DIRECTORY) + set(_outputdir "${_args_OUTPUT_DIRECTORY}") + else() + set(_outputdir "${CMAKE_CURRENT_BINARY_DIR}/${_target}") + endif() + + + if(_args_BREATHE_PROJECTS) + if(NOT Sphinx_breathe_FOUND) + message(FATAL_ERROR "Sphinx extension 'breathe' is not available. Needed" + "by sphinx_add_docs for target ${_target}") + endif() + list(APPEND SPHINX_EXTENSIONS breathe) + + foreach(_doxygen_target ${_args_BREATHE_PROJECTS}) + if(TARGET ${_doxygen_target}) + list(APPEND _depends ${_doxygen_target}) + + # Doxygen targets are supported. Verify that a Doxyfile exists. + get_target_property(_dir ${_doxygen_target} BINARY_DIR) + set(_doxyfile "${_dir}/Doxyfile.${_doxygen_target}") + if(NOT EXISTS "${_doxyfile}") + message(FATAL_ERROR "Target ${_doxygen_target} is not a Doxygen" + "target, needed by sphinx_add_docs for target" + "${_target}") + endif() + + # Read the Doxyfile, verify XML generation is enabled and retrieve the + # output directory. + file(READ "${_doxyfile}" _contents) + if(NOT _contents MATCHES "GENERATE_XML *= *YES") + message(FATAL_ERROR "Doxygen target ${_doxygen_target} does not" + "generate XML, needed by sphinx_add_docs for" + "target ${_target}") + elseif(_contents MATCHES "OUTPUT_DIRECTORY *= *([^ ][^\n]*)") + string(STRIP "${CMAKE_MATCH_1}" _dir) + set(_name "${_doxygen_target}") + set(_dir "${_dir}/xml") + else() + message(FATAL_ERROR "Cannot parse Doxyfile generated by Doxygen" + "target ${_doxygen_target}, needed by" + "sphinx_add_docs for target ${_target}") + endif() + elseif(_doxygen_target MATCHES "([^: ]+) *: *(.*)") + set(_name "${CMAKE_MATCH_1}") + string(STRIP "${CMAKE_MATCH_2}" _dir) + endif() + + if(_name AND _dir) + if(_breathe_projects) + set(_breathe_projects "${_breathe_projects}, \"${_name}\": \"${_dir}\"") + else() + set(_breathe_projects "\"${_name}\": \"${_dir}\"") + endif() + if(NOT _breathe_default_project) + set(_breathe_default_project "${_name}") + endif() + endif() + endforeach() + endif() + + set(_cachedir "${CMAKE_CURRENT_BINARY_DIR}/${_target}.cache") + file(MAKE_DIRECTORY "${_cachedir}") + file(MAKE_DIRECTORY "${_cachedir}/_static") + + _Sphinx_generate_confpy(${_target} "${_cachedir}") + + if(_breathe_projects) + file(APPEND "${_cachedir}/conf.py" + "\nbreathe_projects = { ${_breathe_projects} }" + "\nbreathe_default_project = '${_breathe_default_project}'") + endif() + + add_custom_target( + ${_target} + COMMAND ${SPHINX_BUILD_EXECUTABLE} + -b ${_builder} + -d "${CMAKE_CURRENT_BINARY_DIR}/${_target}.cache/_doctrees" + -c "${CMAKE_CURRENT_BINARY_DIR}/${_target}.cache" + "${_sourcedir}" + "${_outputdir}" + DEPENDS ${_depends}) +endfunction() + From 348e68e9dfb9cea27c8d5e5573f25f90ccb5042e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 27 Jun 2019 11:07:48 +0200 Subject: [PATCH 101/178] Update FindMaven for Travis/Windows It appears the Chocolately maven package now installs in different location (or some shims that used to be installed no longer are). Because the Travis build uses bash instead of cmd/powershell it doesn't properly pick up M2_HOME. This commits adds the new location. Signed-off-by: Erik Boasson --- src/cmake/modules/FindMaven.cmake | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cmake/modules/FindMaven.cmake b/src/cmake/modules/FindMaven.cmake index 5a2e3c3..02d2dbd 100644 --- a/src/cmake/modules/FindMaven.cmake +++ b/src/cmake/modules/FindMaven.cmake @@ -18,8 +18,13 @@ if(DEFINED ENV{M2_HOME}) endif() # Chocolatey installs packages under C:\ProgramData\chocolatey. -if(ENV{ProgramData} AND IS_DIRECTORY "$ENV{ProgramData}/chocolatey/bin") - list(APPEND _mvn_paths "$ENV{ProgramData}/chocolatey/bin") +if(NOT "$ENV{ProgramData}" STREQUAL "") + if(IS_DIRECTORY "$ENV{ProgramData}/chocolatey/bin") + list(APPEND _mvn_paths "$ENV{ProgramData}/chocolatey/bin") + endif() + if(IS_DIRECTORY "$ENV{ProgramData}/chocolatey/bin") + list(APPEND _dirs "$ENV{ProgramData}/chocolatey/lib/maven") + endif() endif() # Maven documentation mentions intalling maven under C:\Program Files on From e016ef20e24eb8d8b015b8e5055b99d1808720d1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 12 Jun 2019 09:55:00 +0200 Subject: [PATCH 102/178] Add changing user data QoS to pubsub Signed-off-by: Erik Boasson --- src/tools/pubsub/common.c | 3 ++- src/tools/pubsub/pubsub.c | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/tools/pubsub/common.c b/src/tools/pubsub/common.c index b9bcd60..a9b5418 100644 --- a/src/tools/pubsub/common.c +++ b/src/tools/pubsub/common.c @@ -400,6 +400,7 @@ static void inapplicable_qos(dds_entity_kind_t qt, const char *n) { #define get_qos_W(qt, q, n) ((qt == DDS_KIND_WRITER) ? q : (inapplicable_qos((qt), n), (dds_qos_t*)0)) #define get_qos_TW(qt, q, n) ((qt == DDS_KIND_TOPIC) || (qt == DDS_KIND_WRITER) ? q : (inapplicable_qos((qt), n), (dds_qos_t*)0)) #define get_qos_RW(qt, q, n) ((qt == DDS_KIND_READER) || (qt == DDS_KIND_WRITER) ? q : (inapplicable_qos((qt), n), (dds_qos_t*)0)) +#define get_qos_MRW(qt, q, n) ((qt == DDS_KIND_READER) || (qt == DDS_KIND_WRITER) || (qt == DDS_KIND_PARTICIPANT) ? q : (inapplicable_qos((qt), n), (dds_qos_t*)0)) #define get_qos_PS(qt, q, n) ((qt == DDS_KIND_PUBLISHER) || (qt == DDS_KIND_SUBSCRIBER) ? q : (inapplicable_qos((qt), n), (dds_qos_t*)0)) #define get_qos_TRW(qt, q, n) ((qt == DDS_KIND_TOPIC) || (qt == DDS_KIND_READER) || (qt == DDS_KIND_WRITER) ? q : (inapplicable_qos((qt), n), (dds_qos_t*)0)) @@ -563,7 +564,7 @@ static void *unescape(const char *str, size_t *len) { } void qos_user_data(dds_entity_kind_t qt, dds_qos_t *q, const char *arg) { - dds_qos_t *qp = get_qos_RW(qt, q, "user_data"); + dds_qos_t *qp = get_qos_MRW(qt, q, "user_data"); size_t len; if (qp == NULL) return; diff --git a/src/tools/pubsub/pubsub.c b/src/tools/pubsub/pubsub.c index 60f9fc6..e3c356f 100644 --- a/src/tools/pubsub/pubsub.c +++ b/src/tools/pubsub/pubsub.c @@ -567,7 +567,7 @@ static int read_value(char *command, int *key, struct tstamp_t *tstamp, char **a return 1; } break; - case 'p': case 'S': case ':': { + case 'p': case 'S': case ':': case 'Q': { int i = 0; *command = (char) c; while ((c = getc(stdin)) != EOF && !isspace((unsigned char) c)) { @@ -1424,6 +1424,13 @@ static char *pub_do_nonarb(const struct writerspec *spec, uint32_t *seq) { dds_sleepfor(DDS_SECS(k)); } break; + case 'Q': { + dds_qos_t *qos = dds_create_qos (); + setqos_from_args (DDS_KIND_PARTICIPANT, qos, 1, (const char **) &arg); + dds_set_qos (dp, qos); + dds_delete_qos (qos); + break; + } case 'Y': case 'B': case 'E': case 'W': non_data_operation(command, spec->wr); break; From b3d6eec4054fa94139ab8d4a919b28996ea6fb9c Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 10 Jun 2019 12:09:39 +0200 Subject: [PATCH 103/178] Remove prototypes for non-existent functions (#75) * dds_set_allocator * dds_set_aligned_allocator The intent behind them is good, but the approach too primitive ... there is far more work to be done for managing dynamic allocation in a meaningful way. Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/ddsc/dds_public_alloc.h | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_alloc.h b/src/core/ddsc/include/dds/ddsc/dds_public_alloc.h index 9e66a11..918a4bb 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_alloc.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_alloc.h @@ -54,20 +54,6 @@ typedef struct dds_allocator } dds_allocator_t; -DDS_EXPORT void dds_set_allocator (const dds_allocator_t * __restrict n, dds_allocator_t * __restrict o); - -typedef struct dds_aligned_allocator -{ - /* size is a multiple of align, align is a power of 2 no less than - the machine's page size, returned pointer MUST be aligned to at - least align. */ - void * (*alloc) (size_t size, size_t align); - void (*free) (size_t size, void *ptr); -} -dds_aligned_allocator_t; - -DDS_EXPORT void dds_set_aligned_allocator (const dds_aligned_allocator_t * __restrict n, dds_aligned_allocator_t * __restrict o); - DDS_EXPORT void * dds_alloc (size_t size); DDS_EXPORT void * dds_realloc (void * ptr, size_t size); DDS_EXPORT void * dds_realloc_zero (void * ptr, size_t size); From 0356af470d076f070aa2a3300c4639e76a74ccdc Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 7 Jun 2019 16:08:52 +0200 Subject: [PATCH 104/178] Fix undefined behaviour reported by ubsan * calling ddsrt_memdup, ddsrt_strdup with a null pointer (they handle it gracefully but forbid it in the interface ...) * replacement of all pre-C99 flexible arrays (i.e., declaring as array[1], then mallocing and using as if array[N]) by C99 flexible arrays. * also add a missing null-pointer test in dds_dispose_ts, and fix the test cases that pass a null pointer and a non-writer handle to it to instead pass an invalid adress Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_instance.c | 3 ++ src/core/ddsc/src/dds_qos.c | 2 +- src/core/ddsc/src/dds_whc.c | 4 --- src/core/ddsc/tests/dispose.c | 6 ++-- .../include/dds/ddsi/ddsi_serdata_default.h | 2 +- src/core/ddsi/include/dds/ddsi/q_protocol.h | 14 +++------ src/core/ddsi/include/dds/ddsi/q_radmin.h | 10 +++---- src/core/ddsi/src/q_plist.c | 6 ++-- src/core/ddsi/src/q_radmin.c | 30 +++++++++---------- src/core/ddsi/src/q_xmsg.c | 2 +- 10 files changed, 37 insertions(+), 42 deletions(-) diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index 5631a1c..11ee1d6 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -238,6 +238,9 @@ dds_return_t dds_dispose_ts (dds_entity_t writer, const void *data, dds_time_t t dds_return_t ret; dds_writer *wr; + if (data == NULL) + return DDS_RETCODE_BAD_PARAMETER; + if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) return ret; diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index a9c0296..68f12e6 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -22,7 +22,7 @@ static void dds_qos_data_copy_in (ddsi_octetseq_t *data, const void * __restrict if (overwrite && data->value) ddsrt_free (data->value); data->length = (uint32_t) sz; - data->value = ddsrt_memdup (value, sz); + data->value = value ? ddsrt_memdup (value, sz) : NULL; } static bool dds_qos_data_copy_out (const ddsi_octetseq_t *data, void **value, size_t *sz) diff --git a/src/core/ddsc/src/dds_whc.c b/src/core/ddsc/src/dds_whc.c index 1c29649..a501579 100644 --- a/src/core/ddsc/src/dds_whc.c +++ b/src/core/ddsc/src/dds_whc.c @@ -60,11 +60,7 @@ struct whc_idxnode { seqno_t prune_seq; struct ddsi_tkmap_instance *tk; uint32_t headidx; -#if __STDC_VERSION__ >= 199901L struct whc_node *hist[]; -#else - struct whc_node *hist[1]; -#endif }; #if USE_EHH diff --git a/src/core/ddsc/tests/dispose.c b/src/core/ddsc/tests/dispose.c index 2df1714..ef6435f 100644 --- a/src/core/ddsc/tests/dispose.c +++ b/src/core/ddsc/tests/dispose.c @@ -560,7 +560,8 @@ CU_Theory((dds_entity_t *writer), ddsc_dispose, non_writers, .init=disposing_ini { dds_return_t ret; DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ - ret = dds_dispose(*writer, NULL); + /* pass a non-null pointer that'll trigger a crash if it is read */ + ret = dds_dispose(*writer, (void *) 1); DDSRT_WARNING_MSVC_ON(6387); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } @@ -714,7 +715,8 @@ CU_Theory((dds_entity_t *writer), ddsc_dispose_ts, non_writers, .init=disposing_ { dds_return_t ret; DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ - ret = dds_dispose_ts(*writer, NULL, g_present); + /* pass a non-null pointer that'll trigger a crash if it is read */ + ret = dds_dispose_ts(*writer, (void *) 1, g_present); DDSRT_WARNING_MSVC_ON(6387); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } 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 e6e2f56..0604ff5 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -66,7 +66,7 @@ struct ddsi_serdata_default { serdata is 8-byte aligned */ char pad[8 - ((sizeof (struct ddsi_serdata) + 4) % 8)]; struct CDRHeader hdr; - char data[1]; + char data[]; }; struct dds_key_descriptor; diff --git a/src/core/ddsi/include/dds/ddsi/q_protocol.h b/src/core/ddsi/include/dds/ddsi/q_protocol.h index e120f59..0386402 100644 --- a/src/core/ddsi/include/dds/ddsi/q_protocol.h +++ b/src/core/ddsi/include/dds/ddsi/q_protocol.h @@ -35,8 +35,8 @@ typedef struct { typedef struct nn_sequence_number_set { nn_sequence_number_t bitmap_base; uint32_t numbits; - uint32_t bits[1]; -} nn_sequence_number_set_t; /* Why strict C90? zero-length/flexible array members are far nicer */ + uint32_t bits[]; +} nn_sequence_number_set_t; /* SequenceNumberSet size is base (2 words) + numbits (1 word) + bitmap ((numbits+31)/32 words), and this at 4 bytes/word */ #define NN_SEQUENCE_NUMBER_SET_BITS_SIZE(numbits) ((unsigned) (4 * (((numbits) + 31) / 32))) @@ -45,7 +45,7 @@ typedef unsigned nn_fragment_number_t; typedef struct nn_fragment_number_set { nn_fragment_number_t bitmap_base; uint32_t numbits; - uint32_t bits[1]; + uint32_t bits[]; } nn_fragment_number_set_t; /* FragmentNumberSet size is base (2 words) + numbits (1 word) + bitmap ((numbits+31)/32 words), and this at 4 bytes/word */ @@ -70,12 +70,6 @@ typedef struct nn_udpv4mcgen_address { uint8_t idx; /* must be last: then sorting will put them consecutively */ } nn_udpv4mcgen_address_t; - -struct cdrstring { - uint32_t length; - unsigned char contents[1]; /* C90 does not support flex. array members */ -}; - #define NN_STATUSINFO_DISPOSE 0x1u #define NN_STATUSINFO_UNREGISTER 0x2u #define NN_STATUSINFO_STANDARDIZED (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER) @@ -317,7 +311,7 @@ typedef struct ParticipantMessageData { nn_guid_prefix_t participantGuidPrefix; uint32_t kind; /* really 4 octets */ uint32_t length; - char value[1 /* length */]; + char value[]; } ParticipantMessageData_t; #define PARTICIPANT_MESSAGE_DATA_KIND_UNKNOWN 0x0u #define PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE 0x1u diff --git a/src/core/ddsi/include/dds/ddsi/q_radmin.h b/src/core/ddsi/include/dds/ddsi/q_radmin.h index bfba76c..9b302d5 100644 --- a/src/core/ddsi/include/dds/ddsi/q_radmin.h +++ b/src/core/ddsi/include/dds/ddsi/q_radmin.h @@ -47,15 +47,15 @@ struct nn_rmsg_chunk { nn_rmsg_setsize after receiving a packet from the kernel and before processing it. */ uint32_t size; - union { - /* payload array stretched to whatever it really is */ - unsigned char payload[1]; - /* to ensure reasonable alignment of payload[] */ + /* to ensure reasonable alignment of payload[] */ + union { int64_t l; double d; void *p; } u; + /* payload array stretched to whatever it really is */ + unsigned char payload[]; }; struct nn_rmsg { @@ -95,7 +95,7 @@ struct nn_rmsg { struct nn_rmsg_chunk chunk; }; -#define NN_RMSG_PAYLOAD(m) ((m)->chunk.u.payload) +#define NN_RMSG_PAYLOAD(m) ((m)->chunk.payload) #define NN_RMSG_PAYLOADOFF(m, o) (NN_RMSG_PAYLOAD (m) + (o)) struct receiver_state { diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 15f27f4..39ccc73 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -712,9 +712,9 @@ static dds_return_t unalias_generic (void * __restrict dst, size_t * __restrict { case XSTOP: return 0; - case XO: COMPLEX (XO, ddsi_octetseq_t, x->value = ddsrt_memdup (x->value, x->length)); break; - case XS: COMPLEX (XS, char *, *x = ddsrt_strdup (*x)); break; - case XZ: COMPLEX (XZ, ddsi_stringseq_t, { + case XO: COMPLEX (XO, ddsi_octetseq_t, if (x->value) { x->value = ddsrt_memdup (x->value, x->length); }); break; + case XS: COMPLEX (XS, char *, if (*x) { *x = ddsrt_strdup (*x); }); break; + case XZ: COMPLEX (XZ, ddsi_stringseq_t, if (x->n) { x->strs = ddsrt_memdup (x->strs, x->n * sizeof (*x->strs)); for (uint32_t i = 0; i < x->n; i++) x->strs[i] = ddsrt_strdup (x->strs[i]); diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index a45d4e0..70f7869 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -320,8 +320,8 @@ static uint32_t max_rmsg_size_w_hdr (uint32_t max_rmsg_size) allocate for the worst case, and may waste a few bytes here or there. */ return - max_uint32 ((uint32_t) offsetof (struct nn_rmsg, chunk.u.payload), - (uint32_t) offsetof (struct nn_rmsg_chunk, u.payload)) + max_uint32 ((uint32_t) offsetof (struct nn_rmsg, chunk.payload), + (uint32_t) offsetof (struct nn_rmsg_chunk, payload)) + max_rmsg_size; } @@ -405,15 +405,15 @@ struct nn_rbuf { approach. Changes would be confined rmsg_new and rmsg_free. */ unsigned char *freeptr; + /* to ensure reasonable alignment of raw[] */ union { - /* raw data array, nn_rbuf::size bytes long in reality */ - unsigned char raw[1]; - - /* to ensure reasonable alignment of raw[] */ int64_t l; double d; void *p; } u; + + /* raw data array, nn_rbuf::size bytes long in reality */ + unsigned char raw[]; }; static struct nn_rbuf *nn_rbuf_alloc_new (struct nn_rbufpool *rbufpool) @@ -421,17 +421,17 @@ static struct nn_rbuf *nn_rbuf_alloc_new (struct nn_rbufpool *rbufpool) struct nn_rbuf *rb; ASSERT_RBUFPOOL_OWNER (rbufpool); - if ((rb = ddsrt_malloc (offsetof (struct nn_rbuf, u.raw) + rbufpool->rbuf_size)) == NULL) + if ((rb = ddsrt_malloc (sizeof (struct nn_rbuf) + rbufpool->rbuf_size)) == NULL) return NULL; #if USE_VALGRIND - VALGRIND_MAKE_MEM_NOACCESS (rb->u.raw, rbufpool->rbuf_size); + VALGRIND_MAKE_MEM_NOACCESS (rb->raw, rbufpool->rbuf_size); #endif rb->rbufpool = rbufpool; ddsrt_atomic_st32 (&rb->n_live_rmsg_chunks, 1); rb->size = rbufpool->rbuf_size; rb->max_rmsg_size = rbufpool->max_rmsg_size; - rb->freeptr = rb->u.raw; + rb->freeptr = rb->raw; DDS_LOG(DDS_LC_RADMIN, "rbuf_alloc_new(%p) = %p\n", (void *) rbufpool, (void *) rb); return rb; } @@ -488,17 +488,17 @@ static void *nn_rbuf_alloc (struct nn_rbufpool *rbufpool) ASSERT_RBUFPOOL_OWNER (rbufpool); rb = rbufpool->current; assert (rb != NULL); - assert (rb->freeptr >= rb->u.raw); - assert (rb->freeptr <= rb->u.raw + rb->size); + assert (rb->freeptr >= rb->raw); + assert (rb->freeptr <= rb->raw + rb->size); - if ((uint32_t) (rb->u.raw + rb->size - rb->freeptr) < asize) + if ((uint32_t) (rb->raw + rb->size - rb->freeptr) < asize) { /* not enough space left for new rmsg */ if ((rb = nn_rbuf_new (rbufpool)) == NULL) return NULL; /* a new one should have plenty of space */ - assert ((uint32_t) (rb->u.raw + rb->size - rb->freeptr) >= asize); + assert ((uint32_t) (rb->raw + rb->size - rb->freeptr) >= asize); } DDS_LOG(DDS_LC_RADMIN, "rmsg_rbuf_alloc(%p, %"PRIu32") = %p\n", (void *) rbufpool, asize, (void *) rb->freeptr); @@ -587,7 +587,7 @@ static void commit_rmsg_chunk (struct nn_rmsg_chunk *chunk) { struct nn_rbuf *rbuf = chunk->rbuf; DDS_LOG(DDS_LC_RADMIN, "commit_rmsg_chunk(%p)\n", (void *) chunk); - rbuf->freeptr = chunk->u.payload + chunk->size; + rbuf->freeptr = chunk->payload + chunk->size; } void nn_rmsg_commit (struct nn_rmsg *rmsg) @@ -688,7 +688,7 @@ void *nn_rmsg_alloc (struct nn_rmsg *rmsg, uint32_t size) chunk = newchunk; } - ptr = chunk->u.payload + chunk->size; + ptr = chunk->payload + chunk->size; chunk->size += size8; DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %"PRIu32") = %p\n", (void *) rmsg, size, ptr); #if USE_VALGRIND diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 5cebfeb..fabe8c0 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -52,7 +52,7 @@ struct nn_xmsgpool { struct nn_xmsg_data { InfoSRC_t src; InfoDST_t dst; - char payload[1]; /* of size maxsz */ + char payload[]; /* of size maxsz */ }; struct nn_xmsg_chain_elem { From c6c5a872eb44af50f19e8a6851d9b2d063e77496 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 7 Jun 2019 17:49:39 +0200 Subject: [PATCH 105/178] Trivial changes for thread sanitizer Thread sanitizer warns about reads and writes of variables that are meant to be read without holding a lock: * Global "keep_going" is now a ddsrt_atomic_uint32_t * Thread "vtime" is now a ddsrt_atomic_uint32_t Previously the code relied on the assumption that a 32-bit int would be treated as atomic, now that is all wrapped in ddsrt_atomic_{ld,st}32. These being inline functions doing exactly the same thing, there is no functional change, but it does allow annotating the loads and stores for via function attributes on the ddsrt_atomic_{ld,st}X. The concurrent hashtable implementation is replaced by a locked version of the non-concurrent implementation if thread sanitizer is used. This changes eliminates the scores of problems signalled by thread sanitizer in the GUID-to-entity translation and the key-to-instance id lookups. Other than that, this replaces a flag used in a waitset test case to be a ddsrt_atomic_uint32_t. Signed-off-by: Erik Boasson --- src/core/ddsc/tests/waitset.c | 15 +- src/core/ddsi/include/dds/ddsi/q_globals.h | 2 +- src/core/ddsi/include/dds/ddsi/q_thread.h | 31 +- src/core/ddsi/src/ddsi_tcp.c | 3 +- src/core/ddsi/src/ddsi_threadmon.c | 2 +- src/core/ddsi/src/ddsi_tran.c | 3 +- src/core/ddsi/src/q_gc.c | 4 +- src/core/ddsi/src/q_init.c | 6 +- src/core/ddsi/src/q_receive.c | 6 +- src/core/ddsi/src/q_thread.c | 15 +- src/core/ddsi/src/q_transmit.c | 2 +- src/core/ddsi/src/q_xevent.c | 2 +- src/ddsrt/include/dds/ddsrt/atomics/gcc.h | 49 ++- src/ddsrt/include/dds/ddsrt/attributes.h | 12 + src/ddsrt/include/dds/ddsrt/hopscotch.h | 43 +- src/ddsrt/src/hopscotch.c | 460 ++++++++++++--------- src/mpt/tests/qos/procs/ppud.c | 16 +- 17 files changed, 404 insertions(+), 267 deletions(-) diff --git a/src/core/ddsc/tests/waitset.c b/src/core/ddsc/tests/waitset.c index cffa069..42e4a82 100644 --- a/src/core/ddsc/tests/waitset.c +++ b/src/core/ddsc/tests/waitset.c @@ -20,6 +20,7 @@ #include "dds/ddsrt/misc.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" +#include "dds/ddsrt/atomics.h" #include "dds/ddsrt/time.h" /************************************************************************************************** @@ -36,7 +37,7 @@ typedef enum thread_state_t { typedef struct thread_arg_t { ddsrt_thread_t tid; - thread_state_t state; + ddsrt_atomic_uint32_t state; dds_entity_t expected; } thread_arg_t; @@ -1056,26 +1057,26 @@ waiting_thread(void *a) dds_attach_t triggered; dds_return_t ret; - arg->state = WAITING; + ddsrt_atomic_st32 (&arg->state, WAITING); /* This should block until the main test released all claims. */ ret = dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(1000)); CU_ASSERT_EQUAL_FATAL(ret, 1); CU_ASSERT_EQUAL_FATAL(arg->expected, (dds_entity_t)(intptr_t)triggered); - arg->state = STOPPED; + ddsrt_atomic_st32 (&arg->state, STOPPED); return 0; } static dds_return_t -thread_reached_state(thread_state_t *actual, thread_state_t expected, int32_t msec) +thread_reached_state(ddsrt_atomic_uint32_t *actual, thread_state_t expected, int32_t msec) { /* Convenience function. */ dds_time_t msec10 = DDS_MSECS(10); - while ((msec > 0) && (*actual != expected)) { + while ((msec > 0) && ((thread_state_t) ddsrt_atomic_ld32 (actual) != expected)) { dds_sleepfor(msec10); msec -= 10; } - return (*actual == expected) ? DDS_RETCODE_OK : DDS_RETCODE_TIMEOUT; + return ((thread_state_t) ddsrt_atomic_ld32 (actual) == expected) ? DDS_RETCODE_OK : DDS_RETCODE_TIMEOUT; } static void @@ -1089,7 +1090,7 @@ waiting_thread_start(struct thread_arg_t *arg, dds_entity_t expected) /* Create an other thread that will blocking wait on the waitset. */ arg->expected = expected; - arg->state = STARTING; + ddsrt_atomic_st32 (&arg->state, STARTING); ddsrt_threadattr_init(&thread_attr); rc = ddsrt_thread_create(&thread_id, "waiting_thread", &thread_attr, waiting_thread, arg); CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/q_globals.h index 46cafab..aa048ba 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/q_globals.h @@ -221,7 +221,7 @@ struct q_globals { struct thread_state1 *listen_ts; /* Flag cleared when stopping (receive threads). FIXME. */ - int rtps_keepgoing; + ddsrt_atomic_uint32_t rtps_keepgoing; /* Start time of the DDSI2 service, for logging relative time stamps, should I ever so desire. */ diff --git a/src/core/ddsi/include/dds/ddsi/q_thread.h b/src/core/ddsi/include/dds/ddsi/q_thread.h index 79c4c48..fb8fd0a 100644 --- a/src/core/ddsi/include/dds/ddsi/q_thread.h +++ b/src/core/ddsi/include/dds/ddsi/q_thread.h @@ -57,13 +57,14 @@ enum thread_state { struct logbuf; /* - * watchdog indicates progress for the service lease liveliness mechsanism, while vtime - * indicates progress for the Garbage collection purposes. - * vtime even : thread awake - * vtime odd : thread asleep + * vtime indicates progress for the garbage collector and the liveliness monitoring. + * + * vtime is updated without using atomic operations: only the owning thread updates + * them, and the garbage collection mechanism and the liveliness monitoring only + * observe the value */ #define THREAD_BASE \ - volatile vtime_t vtime; \ + ddsrt_atomic_uint32_t vtime; \ ddsrt_thread_t tid; \ ddsrt_thread_t extTid; \ enum thread_state state; \ @@ -131,17 +132,21 @@ DDS_EXPORT inline bool vtime_gt (vtime_t vtime1, vtime_t vtime0) DDS_EXPORT inline bool thread_is_awake (void) { - return vtime_awake_p (lookup_thread_state ()->vtime); + struct thread_state1 *ts = lookup_thread_state (); + vtime_t vt = ddsrt_atomic_ld32 (&ts->vtime); + return vtime_awake_p (vt); } DDS_EXPORT inline bool thread_is_asleep (void) { - return vtime_asleep_p (lookup_thread_state ()->vtime); + struct thread_state1 *ts = lookup_thread_state (); + vtime_t vt = ddsrt_atomic_ld32 (&ts->vtime); + return vtime_asleep_p (vt); } DDS_EXPORT inline void thread_state_asleep (struct thread_state1 *ts1) { - vtime_t vt = ts1->vtime; + vtime_t vt = ddsrt_atomic_ld32 (&ts1->vtime); assert (vtime_awake_p (vt)); /* nested calls a rare and an extra fence doesn't break things */ ddsrt_atomic_fence_rel (); @@ -149,24 +154,24 @@ DDS_EXPORT inline void thread_state_asleep (struct thread_state1 *ts1) vt += (1u << VTIME_TIME_SHIFT) - 1u; else vt -= 1u; - ts1->vtime = vt; + ddsrt_atomic_st32 (&ts1->vtime, vt); } DDS_EXPORT inline void thread_state_awake (struct thread_state1 *ts1) { - vtime_t vt = ts1->vtime; + vtime_t vt = ddsrt_atomic_ld32 (&ts1->vtime); assert ((vt & VTIME_NEST_MASK) < VTIME_NEST_MASK); - ts1->vtime = vt + 1u; + ddsrt_atomic_st32 (&ts1->vtime, vt + 1u); /* nested calls a rare and an extra fence doesn't break things */ ddsrt_atomic_fence_acq (); } DDS_EXPORT inline void thread_state_awake_to_awake_no_nest (struct thread_state1 *ts1) { - vtime_t vt = ts1->vtime; + vtime_t vt = ddsrt_atomic_ld32 (&ts1->vtime); assert ((vt & VTIME_NEST_MASK) == 1); ddsrt_atomic_fence_rel (); - ts1->vtime = vt + (1u << VTIME_TIME_SHIFT); + ddsrt_atomic_st32 (&ts1->vtime, vt + (1u << VTIME_TIME_SHIFT)); ddsrt_atomic_fence_acq (); } diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index bc65a40..bf19025 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -706,6 +706,7 @@ static ddsrt_socket_t ddsi_tcp_conn_handle (ddsi_tran_base_t base) return ((ddsi_tcp_conn_t) base)->m_sock; } +ddsrt_attribute_no_sanitize (("thread")) static bool ddsi_tcp_supports (int32_t kind) { return kind == ddsi_tcp_factory_g.m_kind; @@ -770,7 +771,7 @@ static ddsi_tran_conn_t ddsi_tcp_accept (ddsi_tran_listener_t listener) { rc = ddsrt_accept(tl->m_sock, NULL, NULL, &sock); } - if (! gv.rtps_keepgoing) + if (!ddsrt_atomic_ld32(&gv.rtps_keepgoing)) { ddsi_tcp_sock_free (sock, NULL); return NULL; diff --git a/src/core/ddsi/src/ddsi_threadmon.c b/src/core/ddsi/src/ddsi_threadmon.c index 9af19c9..7617332 100644 --- a/src/core/ddsi/src/ddsi_threadmon.c +++ b/src/core/ddsi/src/ddsi_threadmon.c @@ -83,7 +83,7 @@ static uint32_t threadmon_thread (struct ddsi_threadmon *sl) n_unused++; else { - vtime_t vt = thread_states.ts[i].vtime; + vtime_t vt = ddsrt_atomic_ld32 (&thread_states.ts[i].vtime); bool alive = vtime_asleep_p (vt) || vtime_asleep_p (sl->av_ary[i].vt) || vtime_gt (vt, sl->av_ary[i].vt); n_alive += (unsigned) alive; DDS_TRACE(" %u(%s):%c:%"PRIx32"->%"PRIx32, i, thread_states.ts[i].name, alive ? 'a' : 'd', sl->av_ary[i].vt, vt); diff --git a/src/core/ddsi/src/ddsi_tran.c b/src/core/ddsi/src/ddsi_tran.c index ceb2256..3984610 100644 --- a/src/core/ddsi/src/ddsi_tran.c +++ b/src/core/ddsi/src/ddsi_tran.c @@ -91,6 +91,7 @@ static ddsi_tran_factory_t ddsi_factory_find_with_len (const char * type, size_t return factory; } +ddsrt_attribute_no_sanitize (("thread")) ddsi_tran_factory_t ddsi_factory_find_supported_kind (int32_t kind) { /* FIXME: MUST speed up */ @@ -124,7 +125,7 @@ void ddsi_conn_free (ddsi_tran_conn_t conn) for (uint32_t i = 0; i < gv.n_recv_threads; i++) { if (!gv.recv_threads[i].ts) - assert (!gv.rtps_keepgoing); + assert (!ddsrt_atomic_ld32 (&gv.rtps_keepgoing)); else { switch (gv.recv_threads[i].arg.mode) diff --git a/src/core/ddsi/src/q_gc.c b/src/core/ddsi/src/q_gc.c index 0aff75b..7bbbb56 100644 --- a/src/core/ddsi/src/q_gc.c +++ b/src/core/ddsi/src/q_gc.c @@ -44,7 +44,7 @@ static void threads_vtime_gather_for_wait (unsigned *nivs, struct idx_vtime *ivs uint32_t i, j; for (i = j = 0; i < thread_states.nthreads; i++) { - vtime_t vtime = thread_states.ts[i].vtime; + vtime_t vtime = ddsrt_atomic_ld32 (&thread_states.ts[i].vtime); if (vtime_awake_p (vtime)) { ivs[j].idx = i; @@ -63,7 +63,7 @@ static int threads_vtime_check (uint32_t *nivs, struct idx_vtime *ivs) while (i < *nivs) { uint32_t thridx = ivs[i].idx; - vtime_t vtime = thread_states.ts[thridx].vtime; + vtime_t vtime = ddsrt_atomic_ld32 (&thread_states.ts[thridx].vtime); assert (vtime_awake_p (ivs[i].vtime)); if (!vtime_gt (vtime, ivs[i].vtime)) ++i; diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index e04b7fb..df5f77a 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -679,9 +679,9 @@ static void rtps_term_prep (void) { /* Stop all I/O */ ddsrt_mutex_lock (&gv.lock); - if (gv.rtps_keepgoing) + if (ddsrt_atomic_ld32 (&gv.rtps_keepgoing)) { - gv.rtps_keepgoing = 0; /* so threads will stop once they get round to checking */ + ddsrt_atomic_st32 (&gv.rtps_keepgoing, 0); /* so threads will stop once they get round to checking */ ddsrt_atomic_fence (); /* can't wake up throttle_writer, currently, but it'll check every few seconds */ trigger_recv_threads (); @@ -1252,7 +1252,7 @@ int rtps_init (void) gv.gcreq_queue = gcreq_queue_new (); - gv.rtps_keepgoing = 1; + ddsrt_atomic_st32 (&gv.rtps_keepgoing, 1); ddsrt_rwlock_init (&gv.qoslock); if (config.xpack_send_async) diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 33cb5c9..6964ddf 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -3156,7 +3156,7 @@ uint32_t listen_thread (struct ddsi_tran_listener * listener) { ddsi_tran_conn_t conn; - while (gv.rtps_keepgoing) + while (ddsrt_atomic_ld32 (&gv.rtps_keepgoing)) { /* Accept connection from listener */ @@ -3310,7 +3310,7 @@ uint32_t recv_thread (void *vrecv_thread_arg) nn_rbufpool_setowner (rbpool, ddsrt_thread_self ()); if (waitset == NULL) { - while (gv.rtps_keepgoing) + while (ddsrt_atomic_ld32 (&gv.rtps_keepgoing)) { LOG_THREAD_CPUTIME (next_thread_cputime); (void) do_packet (ts1, recv_thread_arg->u.single.conn, NULL, rbpool); @@ -3343,7 +3343,7 @@ uint32_t recv_thread (void *vrecv_thread_arg) num_fixed += (unsigned)rc; } - while (gv.rtps_keepgoing) + while (ddsrt_atomic_ld32 (&gv.rtps_keepgoing)) { int rebuildws; LOG_THREAD_CPUTIME (next_thread_cputime); diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index c6d1848..9b22dc4 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -75,7 +75,7 @@ static void ddsrt_free_aligned (void *ptr) void thread_states_init_static (void) { static struct thread_state1 ts = { - .state = THREAD_STATE_ALIVE, .vtime = 0u, .name = "(anon)" + .state = THREAD_STATE_ALIVE, .vtime = DDSRT_ATOMIC_UINT32_INIT (0), .name = "(anon)" }; tsd_thread_state = &ts; } @@ -92,7 +92,7 @@ void thread_states_init (unsigned maxthreads) for (uint32_t i = 0; i < thread_states.nthreads; i++) { thread_states.ts[i].state = THREAD_STATE_ZERO; - thread_states.ts[i].vtime = 0u; + ddsrt_atomic_st32 (&thread_states.ts[i].vtime, 0); thread_states.ts[i].name = NULL; } DDSRT_WARNING_MSVC_ON(6386); @@ -113,6 +113,7 @@ void thread_states_fini (void) thread_states.ts = NULL; } +ddsrt_attribute_no_sanitize (("thread")) static struct thread_state1 *find_thread_state (ddsrt_thread_t tid) { if (thread_states.ts) { @@ -132,7 +133,7 @@ static void cleanup_thread_state (void *data) if (ts) { assert(ts->state == THREAD_STATE_LAZILY_CREATED); - assert(vtime_asleep_p(ts->vtime)); + assert(vtime_asleep_p(ddsrt_atomic_ld32 (&ts->vtime))); reset_thread_state(ts); } ddsrt_fini(); @@ -207,7 +208,7 @@ void upgrade_main_thread (void) abort (); ts1 = &thread_states.ts[cand]; if (ts1->state == THREAD_STATE_ZERO) - assert (vtime_asleep_p (ts1->vtime)); + assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts1->vtime))); ts1->state = THREAD_STATE_LAZILY_CREATED; ts1->tid = ddsrt_thread_self (); ts1->name = main_thread_name; @@ -233,7 +234,7 @@ static struct thread_state1 *init_thread_state (const char *tname, enum thread_s return NULL; ts = &thread_states.ts[cand]; - assert (vtime_asleep_p (ts->vtime)); + assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts->vtime))); ts->name = ddsrt_strdup (tname); ts->state = state; @@ -300,7 +301,7 @@ dds_return_t join_thread (struct thread_state1 *ts1) dds_return_t ret; assert (ts1->state == THREAD_STATE_ALIVE); ret = ddsrt_thread_join (ts1->extTid, NULL); - assert (vtime_asleep_p (ts1->vtime)); + assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts1->vtime))); reap_thread_state (ts1, 1); return ret; } @@ -317,7 +318,7 @@ void reset_thread_state (struct thread_state1 *ts1) void downgrade_main_thread (void) { struct thread_state1 *ts1 = lookup_thread_state (); - assert (vtime_asleep_p (ts1->vtime)); + assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts1->vtime))); /* no need to sync with service lease: already stopped */ reap_thread_state (ts1, 0); thread_states_init_static (); diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 8ecedf8..5686fb6 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -968,7 +968,7 @@ static dds_return_t throttle_writer (struct thread_state1 * const ts1, struct nn whc_get_state (wr->whc, &whcst); } - while (gv.rtps_keepgoing && !writer_may_continue (wr, &whcst)) + while (ddsrt_atomic_ld32 (&gv.rtps_keepgoing) && !writer_may_continue (wr, &whcst)) { int64_t reltimeout; tnow = now_mt (); diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index 7698d12..a7cb357 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -597,8 +597,8 @@ static void handle_xevk_heartbeat (struct nn_xpack *xp, struct xevent *ev, nn_mt return; } - assert (wr->reliable); ddsrt_mutex_lock (&wr->e.lock); + assert (wr->reliable); whc_get_state(wr->whc, &whcst); if (!writer_must_have_hb_scheduled (wr, &whcst)) { diff --git a/src/ddsrt/include/dds/ddsrt/atomics/gcc.h b/src/ddsrt/include/dds/ddsrt/atomics/gcc.h index 4da5f29..a567e81 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/gcc.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/gcc.h @@ -13,6 +13,7 @@ #define DDSRT_ATOMICS_GCC_H #include "dds/ddsrt/misc.h" +#include "dds/ddsrt/attributes.h" #if defined (__cplusplus) extern "C" { @@ -25,19 +26,51 @@ extern "C" { /* LD, ST */ -inline uint32_t ddsrt_atomic_ld32(const volatile ddsrt_atomic_uint32_t *x) { return x->v; } +ddsrt_attribute_no_sanitize (("thread")) +inline uint32_t ddsrt_atomic_ld32(const volatile ddsrt_atomic_uint32_t *x) +{ + return x->v; +} #if DDSRT_HAVE_ATOMIC64 -inline uint64_t ddsrt_atomic_ld64(const volatile ddsrt_atomic_uint64_t *x) { return x->v; } +ddsrt_attribute_no_sanitize (("thread")) +inline uint64_t ddsrt_atomic_ld64(const volatile ddsrt_atomic_uint64_t *x) +{ + return x->v; +} #endif -inline uintptr_t ddsrt_atomic_ldptr(const volatile ddsrt_atomic_uintptr_t *x) { return x->v; } -inline void *ddsrt_atomic_ldvoidp(const volatile ddsrt_atomic_voidp_t *x) { return (void *) ddsrt_atomic_ldptr(x); } +ddsrt_attribute_no_sanitize (("thread")) +inline uintptr_t ddsrt_atomic_ldptr(const volatile ddsrt_atomic_uintptr_t *x) +{ + return x->v; +} +ddsrt_attribute_no_sanitize (("thread")) +inline void *ddsrt_atomic_ldvoidp(const volatile ddsrt_atomic_voidp_t *x) +{ + return (void *) ddsrt_atomic_ldptr(x); +} -inline void ddsrt_atomic_st32(volatile ddsrt_atomic_uint32_t *x, uint32_t v) { x->v = v; } +ddsrt_attribute_no_sanitize (("thread")) +inline void ddsrt_atomic_st32(volatile ddsrt_atomic_uint32_t *x, uint32_t v) +{ + x->v = v; +} #if DDSRT_HAVE_ATOMIC64 -inline void ddsrt_atomic_st64(volatile ddsrt_atomic_uint64_t *x, uint64_t v) { x->v = v; } +ddsrt_attribute_no_sanitize (("thread")) +inline void ddsrt_atomic_st64(volatile ddsrt_atomic_uint64_t *x, uint64_t v) +{ + x->v = v; +} #endif -inline void ddsrt_atomic_stptr(volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) { x->v = v; } -inline void ddsrt_atomic_stvoidp(volatile ddsrt_atomic_voidp_t *x, void *v) { ddsrt_atomic_stptr(x, (uintptr_t)v); } +ddsrt_attribute_no_sanitize (("thread")) +inline void ddsrt_atomic_stptr(volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) +{ + x->v = v; +} +ddsrt_attribute_no_sanitize (("thread")) +inline void ddsrt_atomic_stvoidp(volatile ddsrt_atomic_voidp_t *x, void *v) +{ + ddsrt_atomic_stptr(x, (uintptr_t)v); +} /* INC */ diff --git a/src/ddsrt/include/dds/ddsrt/attributes.h b/src/ddsrt/include/dds/ddsrt/attributes.h index 25ab3b1..08e1e0a 100644 --- a/src/ddsrt/include/dds/ddsrt/attributes.h +++ b/src/ddsrt/include/dds/ddsrt/attributes.h @@ -111,4 +111,16 @@ # define ddsrt_attribute_packed #endif +#if ddsrt_has_attribute(no_sanitize) +# define ddsrt_attribute_no_sanitize(params) __attribute__ ((__no_sanitize__ params)) +#else +# define ddsrt_attribute_no_sanitize(params) +#endif + +#if defined(__has_feature) +# define ddsrt_has_feature_thread_sanitizer __has_feature(thread_sanitizer) +#else +# define ddsrt_has_feature_thread_sanitizer 0 +#endif + #endif /* DDSRT_ATTRIBUTES_H */ diff --git a/src/ddsrt/include/dds/ddsrt/hopscotch.h b/src/ddsrt/include/dds/ddsrt/hopscotch.h index 24d9213..8a5846f 100644 --- a/src/ddsrt/include/dds/ddsrt/hopscotch.h +++ b/src/ddsrt/include/dds/ddsrt/hopscotch.h @@ -20,15 +20,6 @@ extern "C" { #endif -/* Concurrent version */ -struct ddsrt_chh; -struct ddsrt_chh_bucket; -struct ddsrt_chh_iter { - struct ddsrt_chh_bucket *bs; - uint32_t size; - uint32_t cursor; -}; - /* * The hopscotch hash table is dependent on a proper functioning hash. * If the hash function generates a lot of hash collisions, then it will @@ -54,15 +45,6 @@ typedef int (*ddsrt_hh_equals_fn) (const void *, const void *); */ typedef void (*ddsrt_hh_buckets_gc_fn) (void *); -DDS_EXPORT struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets); -DDS_EXPORT void ddsrt_chh_free (struct ddsrt_chh * __restrict hh); -DDS_EXPORT void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict rt, const void * __restrict template); -DDS_EXPORT int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data); -DDS_EXPORT int ddsrt_chh_remove (struct ddsrt_chh * __restrict rt, const void * __restrict template); -DDS_EXPORT void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ -void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_iter *it); -void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it); - /* Sequential version */ struct ddsrt_hh; @@ -80,6 +62,31 @@ DDS_EXPORT void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void DDS_EXPORT void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter); /* may delete nodes */ DDS_EXPORT void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter); +/* Concurrent version */ +struct ddsrt_chh; +struct ddsrt_chh_bucket; + +#if ! ddsrt_has_feature_thread_sanitizer +struct ddsrt_chh_iter { + struct ddsrt_chh_bucket *bs; + uint32_t size; + uint32_t cursor; +}; +#else +struct ddsrt_chh_iter { + struct ddsrt_chh *chh; + struct ddsrt_hh_iter it; +}; +#endif + +DDS_EXPORT struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets); +DDS_EXPORT void ddsrt_chh_free (struct ddsrt_chh * __restrict hh); +DDS_EXPORT void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict rt, const void * __restrict template); +DDS_EXPORT int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data); +DDS_EXPORT int ddsrt_chh_remove (struct ddsrt_chh * __restrict rt, const void * __restrict template); +DDS_EXPORT void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ +DDS_EXPORT void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_iter *it); +DDS_EXPORT void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it); /* Sequential version, embedded data */ struct ddsrt_ehh; diff --git a/src/ddsrt/src/hopscotch.c b/src/ddsrt/src/hopscotch.c index eef7efb..24eefcb 100644 --- a/src/ddsrt/src/hopscotch.c +++ b/src/ddsrt/src/hopscotch.c @@ -12,6 +12,7 @@ #include #include +#include "dds/ddsrt/attributes.h" #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" @@ -22,8 +23,229 @@ #define NOT_A_BUCKET (~(uint32_t)0) +/************* SEQUENTIAL VERSION ***************/ + +struct ddsrt_hh_bucket { + uint32_t hopinfo; + void *data; +}; + +struct ddsrt_hh { + uint32_t size; /* power of 2 */ + struct ddsrt_hh_bucket *buckets; + ddsrt_hh_hash_fn hash; + ddsrt_hh_equals_fn equals; +}; + +static void ddsrt_hh_init (struct ddsrt_hh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals) +{ + uint32_t size = HH_HOP_RANGE; + uint32_t i; + while (size < init_size) { + size *= 2; + } + rt->hash = hash; + rt->equals = equals; + rt->size = size; + rt->buckets = ddsrt_malloc (size * sizeof (*rt->buckets)); + for (i = 0; i < size; i++) { + rt->buckets[i].hopinfo = 0; + rt->buckets[i].data = NULL; + } +} + +static void ddsrt_hh_fini (struct ddsrt_hh *rt) +{ + ddsrt_free (rt->buckets); +} + +struct ddsrt_hh *ddsrt_hh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals) +{ + struct ddsrt_hh *hh = ddsrt_malloc (sizeof (*hh)); + ddsrt_hh_init (hh, init_size, hash, equals); + return hh; +} + +void ddsrt_hh_free (struct ddsrt_hh * __restrict hh) +{ + ddsrt_hh_fini (hh); + ddsrt_free (hh); +} + +static void *ddsrt_hh_lookup_internal (const struct ddsrt_hh *rt, const uint32_t bucket, const void *template) +{ + const uint32_t idxmask = rt->size - 1; + uint32_t hopinfo = rt->buckets[bucket].hopinfo; + uint32_t idx; + for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) { + const uint32_t bidx = (bucket + idx) & idxmask; + void *data = rt->buckets[bidx].data; + if (data && rt->equals (data, template)) + return data; + } + return NULL; +} + +void *ddsrt_hh_lookup (const struct ddsrt_hh * __restrict rt, const void * __restrict template) +{ + const uint32_t hash = rt->hash (template); + const uint32_t idxmask = rt->size - 1; + const uint32_t bucket = hash & idxmask; + return ddsrt_hh_lookup_internal (rt, bucket, template); +} + +static uint32_t ddsrt_hh_find_closer_free_bucket (struct ddsrt_hh *rt, uint32_t free_bucket, uint32_t *free_distance) +{ + const uint32_t idxmask = rt->size - 1; + uint32_t move_bucket, free_dist; + move_bucket = (free_bucket - (HH_HOP_RANGE - 1)) & idxmask; + for (free_dist = HH_HOP_RANGE - 1; free_dist > 0; free_dist--) { + uint32_t move_free_distance = NOT_A_BUCKET; + uint32_t mask = 1; + uint32_t i; + for (i = 0; i < free_dist; i++, mask <<= 1) { + if (mask & rt->buckets[move_bucket].hopinfo) { + move_free_distance = i; + break; + } + } + if (move_free_distance != NOT_A_BUCKET) { + uint32_t new_free_bucket = (move_bucket + move_free_distance) & idxmask; + rt->buckets[move_bucket].hopinfo |= 1u << free_dist; + rt->buckets[free_bucket].data = rt->buckets[new_free_bucket].data; + rt->buckets[new_free_bucket].data = NULL; + rt->buckets[move_bucket].hopinfo &= ~(1u << move_free_distance); + *free_distance -= free_dist - move_free_distance; + return new_free_bucket; + } + move_bucket = (move_bucket + 1) & idxmask; + } + return NOT_A_BUCKET; +} + +static void ddsrt_hh_resize (struct ddsrt_hh *rt) +{ + struct ddsrt_hh_bucket *bs1; + uint32_t i, idxmask0, idxmask1; + + bs1 = ddsrt_malloc (2 * rt->size * sizeof (*rt->buckets)); + + for (i = 0; i < 2 * rt->size; i++) { + bs1[i].hopinfo = 0; + bs1[i].data = NULL; + } + idxmask0 = rt->size - 1; + idxmask1 = 2 * rt->size - 1; + for (i = 0; i < rt->size; i++) { + void *data = rt->buckets[i].data; + if (data) { + const uint32_t hash = rt->hash (data); + const uint32_t old_start_bucket = hash & idxmask0; + const uint32_t new_start_bucket = hash & idxmask1; + const uint32_t dist = (i >= old_start_bucket) ? (i - old_start_bucket) : (rt->size + i - old_start_bucket); + const uint32_t newb = (new_start_bucket + dist) & idxmask1; + assert (dist < HH_HOP_RANGE); + bs1[new_start_bucket].hopinfo |= 1u << dist; + bs1[newb].data = data; + } + } + + ddsrt_free (rt->buckets); + rt->size *= 2; + rt->buckets = bs1; +} + +int ddsrt_hh_add (struct ddsrt_hh * __restrict rt, const void * __restrict data) +{ + const uint32_t hash = rt->hash (data); + const uint32_t idxmask = rt->size - 1; + const uint32_t start_bucket = hash & idxmask; + uint32_t free_distance, free_bucket; + + if (ddsrt_hh_lookup_internal (rt, start_bucket, data)) { + return 0; + } + + free_bucket = start_bucket; + for (free_distance = 0; free_distance < HH_ADD_RANGE; free_distance++) { + if (rt->buckets[free_bucket].data == NULL) + break; + free_bucket = (free_bucket + 1) & idxmask; + } + if (free_distance < HH_ADD_RANGE) { + do { + if (free_distance < HH_HOP_RANGE) { + assert ((uint32_t) free_bucket == ((start_bucket + free_distance) & idxmask)); + rt->buckets[start_bucket].hopinfo |= 1u << free_distance; + rt->buckets[free_bucket].data = (void *) data; + return 1; + } + free_bucket = ddsrt_hh_find_closer_free_bucket (rt, free_bucket, &free_distance); + assert (free_bucket == NOT_A_BUCKET || free_bucket <= idxmask); + } while (free_bucket != NOT_A_BUCKET); + } + + ddsrt_hh_resize (rt); + return ddsrt_hh_add (rt, data); +} + +int ddsrt_hh_remove (struct ddsrt_hh * __restrict rt, const void * __restrict template) +{ + const uint32_t hash = rt->hash (template); + const uint32_t idxmask = rt->size - 1; + const uint32_t bucket = hash & idxmask; + uint32_t hopinfo; + uint32_t idx; + hopinfo = rt->buckets[bucket].hopinfo; + for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) { + if (hopinfo & 1) { + const uint32_t bidx = (bucket + idx) & idxmask; + void *data = rt->buckets[bidx].data; + if (data && rt->equals (data, template)) { + rt->buckets[bidx].data = NULL; + rt->buckets[bucket].hopinfo &= ~(1u << idx); + return 1; + } + } + } + return 0; +} + +void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg) +{ + uint32_t i; + for (i = 0; i < rt->size; i++) { + void *data = rt->buckets[i].data; + if (data) { + f (data, f_arg); + } + } +} + +void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter) +{ + iter->hh = rt; + iter->cursor = 0; + return ddsrt_hh_iter_next (iter); +} + +void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter) +{ + struct ddsrt_hh *rt = iter->hh; + while (iter->cursor < rt->size) { + void *data = rt->buckets[iter->cursor].data; + iter->cursor++; + if (data) { + return data; + } + } + return NULL; +} + /********** CONCURRENT VERSION ************/ +#if ! ddsrt_has_feature_thread_sanitizer + #define N_BACKING_LOCKS 32 #define N_RESIZE_LOCKS 8 @@ -228,7 +450,7 @@ static void *ddsrt_chh_lookup_internal (struct ddsrt_chh_bucket_array const * co #define ddsrt_atomic_rmw32_nonatomic(var_, tmp_, expr_) do { \ ddsrt_atomic_uint32_t *var__ = (var_); \ - uint32_t tmp_ = ddsrt_atomic_ld32 (var__); \ + uint32_t tmp_ = ddsrt_atomic_ld32 (var__); \ ddsrt_atomic_st32 (var__, (expr_)); \ } while (0) @@ -467,224 +689,78 @@ void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_i return ddsrt_chh_iter_next (it); } -/************* SEQUENTIAL VERSION ***************/ +#else -struct ddsrt_hh_bucket { - uint32_t hopinfo; - void *data; +struct ddsrt_chh { + ddsrt_mutex_t lock; + struct ddsrt_hh rt; }; -struct ddsrt_hh { - uint32_t size; /* power of 2 */ - struct ddsrt_hh_bucket *buckets; - ddsrt_hh_hash_fn hash; - ddsrt_hh_equals_fn equals; -}; - -static void ddsrt_hh_init (struct ddsrt_hh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals) +struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc) { - uint32_t size = HH_HOP_RANGE; - uint32_t i; - while (size < init_size) { - size *= 2; - } - rt->hash = hash; - rt->equals = equals; - rt->size = size; - rt->buckets = ddsrt_malloc (size * sizeof (*rt->buckets)); - for (i = 0; i < size; i++) { - rt->buckets[i].hopinfo = 0; - rt->buckets[i].data = NULL; - } + struct ddsrt_chh *hh = ddsrt_malloc (sizeof (*hh)); + (void) gc; + ddsrt_mutex_init (&hh->lock); + ddsrt_hh_init (&hh->rt, init_size, hash, equals); + return hh; } -static void ddsrt_hh_fini (struct ddsrt_hh *rt) +void ddsrt_chh_free (struct ddsrt_chh * __restrict hh) { - ddsrt_free (rt->buckets); + ddsrt_hh_fini (&hh->rt); + ddsrt_mutex_destroy (&hh->lock); + ddsrt_free (hh); } -struct ddsrt_hh *ddsrt_hh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals) +void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict hh, const void * __restrict template) { - struct ddsrt_hh *hh = ddsrt_malloc (sizeof (*hh)); - ddsrt_hh_init (hh, init_size, hash, equals); - return hh; + ddsrt_mutex_lock (&hh->lock); + void *x = ddsrt_hh_lookup (&hh->rt, template); + ddsrt_mutex_unlock (&hh->lock); + return x; } -void ddsrt_hh_free (struct ddsrt_hh * __restrict hh) +int ddsrt_chh_add (struct ddsrt_chh * __restrict hh, const void * __restrict data) { - ddsrt_hh_fini (hh); - ddsrt_free (hh); + ddsrt_mutex_lock (&hh->lock); + int x = ddsrt_hh_add (&hh->rt, data); + ddsrt_mutex_unlock (&hh->lock); + return x; } -static void *ddsrt_hh_lookup_internal (const struct ddsrt_hh *rt, const uint32_t bucket, const void *template) +int ddsrt_chh_remove (struct ddsrt_chh * __restrict hh, const void * __restrict template) { - const uint32_t idxmask = rt->size - 1; - uint32_t hopinfo = rt->buckets[bucket].hopinfo; - uint32_t idx; - for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) { - const uint32_t bidx = (bucket + idx) & idxmask; - void *data = rt->buckets[bidx].data; - if (data && rt->equals (data, template)) - return data; - } - return NULL; + ddsrt_mutex_lock (&hh->lock); + int x = ddsrt_hh_remove (&hh->rt, template); + ddsrt_mutex_unlock (&hh->lock); + return x; } -void *ddsrt_hh_lookup (const struct ddsrt_hh * __restrict rt, const void * __restrict template) +void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict hh, void (*f) (void *a, void *f_arg), void *f_arg) { - const uint32_t hash = rt->hash (template); - const uint32_t idxmask = rt->size - 1; - const uint32_t bucket = hash & idxmask; - return ddsrt_hh_lookup_internal (rt, bucket, template); + ddsrt_mutex_lock (&hh->lock); + ddsrt_hh_enum (&hh->rt, f, f_arg); + ddsrt_mutex_unlock (&hh->lock); } -static uint32_t ddsrt_hh_find_closer_free_bucket (struct ddsrt_hh *rt, uint32_t free_bucket, uint32_t *free_distance) +void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict hh, struct ddsrt_chh_iter *it) { - const uint32_t idxmask = rt->size - 1; - uint32_t move_bucket, free_dist; - move_bucket = (free_bucket - (HH_HOP_RANGE - 1)) & idxmask; - for (free_dist = HH_HOP_RANGE - 1; free_dist > 0; free_dist--) { - uint32_t move_free_distance = NOT_A_BUCKET; - uint32_t mask = 1; - uint32_t i; - for (i = 0; i < free_dist; i++, mask <<= 1) { - if (mask & rt->buckets[move_bucket].hopinfo) { - move_free_distance = i; - break; - } - } - if (move_free_distance != NOT_A_BUCKET) { - uint32_t new_free_bucket = (move_bucket + move_free_distance) & idxmask; - rt->buckets[move_bucket].hopinfo |= 1u << free_dist; - rt->buckets[free_bucket].data = rt->buckets[new_free_bucket].data; - rt->buckets[new_free_bucket].data = NULL; - rt->buckets[move_bucket].hopinfo &= ~(1u << move_free_distance); - *free_distance -= free_dist - move_free_distance; - return new_free_bucket; - } - move_bucket = (move_bucket + 1) & idxmask; - } - return NOT_A_BUCKET; + ddsrt_mutex_lock (&hh->lock); + it->chh = hh; + void *x = ddsrt_hh_iter_first (&hh->rt, &it->it); + ddsrt_mutex_unlock (&hh->lock); + return x; } -static void ddsrt_hh_resize (struct ddsrt_hh *rt) +void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it) { - struct ddsrt_hh_bucket *bs1; - uint32_t i, idxmask0, idxmask1; - - bs1 = ddsrt_malloc (2 * rt->size * sizeof (*rt->buckets)); - - for (i = 0; i < 2 * rt->size; i++) { - bs1[i].hopinfo = 0; - bs1[i].data = NULL; - } - idxmask0 = rt->size - 1; - idxmask1 = 2 * rt->size - 1; - for (i = 0; i < rt->size; i++) { - void *data = rt->buckets[i].data; - if (data) { - const uint32_t hash = rt->hash (data); - const uint32_t old_start_bucket = hash & idxmask0; - const uint32_t new_start_bucket = hash & idxmask1; - const uint32_t dist = (i >= old_start_bucket) ? (i - old_start_bucket) : (rt->size + i - old_start_bucket); - const uint32_t newb = (new_start_bucket + dist) & idxmask1; - assert (dist < HH_HOP_RANGE); - bs1[new_start_bucket].hopinfo |= 1u << dist; - bs1[newb].data = data; - } - } - - ddsrt_free (rt->buckets); - rt->size *= 2; - rt->buckets = bs1; + ddsrt_mutex_lock (&it->chh->lock); + void *x = ddsrt_hh_iter_next (&it->it); + ddsrt_mutex_unlock (&it->chh->lock); + return x; } -int ddsrt_hh_add (struct ddsrt_hh * __restrict rt, const void * __restrict data) -{ - const uint32_t hash = rt->hash (data); - const uint32_t idxmask = rt->size - 1; - const uint32_t start_bucket = hash & idxmask; - uint32_t free_distance, free_bucket; - - if (ddsrt_hh_lookup_internal (rt, start_bucket, data)) { - return 0; - } - - free_bucket = start_bucket; - for (free_distance = 0; free_distance < HH_ADD_RANGE; free_distance++) { - if (rt->buckets[free_bucket].data == NULL) - break; - free_bucket = (free_bucket + 1) & idxmask; - } - if (free_distance < HH_ADD_RANGE) { - do { - if (free_distance < HH_HOP_RANGE) { - assert ((uint32_t) free_bucket == ((start_bucket + free_distance) & idxmask)); - rt->buckets[start_bucket].hopinfo |= 1u << free_distance; - rt->buckets[free_bucket].data = (void *) data; - return 1; - } - free_bucket = ddsrt_hh_find_closer_free_bucket (rt, free_bucket, &free_distance); - assert (free_bucket == NOT_A_BUCKET || free_bucket <= idxmask); - } while (free_bucket != NOT_A_BUCKET); - } - - ddsrt_hh_resize (rt); - return ddsrt_hh_add (rt, data); -} - -int ddsrt_hh_remove (struct ddsrt_hh * __restrict rt, const void * __restrict template) -{ - const uint32_t hash = rt->hash (template); - const uint32_t idxmask = rt->size - 1; - const uint32_t bucket = hash & idxmask; - uint32_t hopinfo; - uint32_t idx; - hopinfo = rt->buckets[bucket].hopinfo; - for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) { - if (hopinfo & 1) { - const uint32_t bidx = (bucket + idx) & idxmask; - void *data = rt->buckets[bidx].data; - if (data && rt->equals (data, template)) { - rt->buckets[bidx].data = NULL; - rt->buckets[bucket].hopinfo &= ~(1u << idx); - return 1; - } - } - } - return 0; -} - -void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg) -{ - uint32_t i; - for (i = 0; i < rt->size; i++) { - void *data = rt->buckets[i].data; - if (data) { - f (data, f_arg); - } - } -} - -void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter) -{ - iter->hh = rt; - iter->cursor = 0; - return ddsrt_hh_iter_next (iter); -} - -void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter) -{ - struct ddsrt_hh *rt = iter->hh; - while (iter->cursor < rt->size) { - void *data = rt->buckets[iter->cursor].data; - iter->cursor++; - if (data) { - return data; - } - } - return NULL; -} +#endif /************* SEQUENTIAL VERSION WITH EMBEDDED DATA ***************/ diff --git a/src/mpt/tests/qos/procs/ppud.c b/src/mpt/tests/qos/procs/ppud.c index 65528fe..e87386f 100644 --- a/src/mpt/tests/qos/procs/ppud.c +++ b/src/mpt/tests/qos/procs/ppud.c @@ -98,8 +98,8 @@ MPT_ProcessEntry (ppud, exp = "X"; const size_t expsz = strlen (exp); bool eq = (usz == expsz && (usz == 0 || memcmp (ud, exp, usz) == 0)); - printf ("%d: expected %u %zu/%s received %zu/%s\n", - id, exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)"); + //printf ("%d: expected %u %zu/%s received %zu/%s\n", + // id, exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)"); MPT_ASSERT (eq, "User data mismatch: expected %u %zu/%s received %zu/%s\n", exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)"); if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0])) @@ -235,8 +235,8 @@ MPT_ProcessEntry (rwud, exp = "X"; const size_t expsz = first ? 1 : strlen (exp); bool eq = (usz == expsz && (usz == 0 || memcmp (ud, exp, usz) == 0)); - printf ("%d: expected %u %zu/%s received %zu/%s\n", - id, exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)"); + //printf ("%d: expected %u %zu/%s received %zu/%s\n", + // id, exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)"); MPT_ASSERT (eq, "User data mismatch: expected %u %zu/%s received %zu/%s\n", exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)"); if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0])) @@ -372,8 +372,8 @@ MPT_ProcessEntry (rwtd, exp = "X"; const size_t expsz = first ? 1 : strlen (exp); bool eq = (tsz == expsz && (tsz == 0 || memcmp (td, exp, tsz) == 0)); - printf ("%d: expected %u %zu/%s received %zu/%s\n", - id, exp_index, expsz, exp, tsz, td ? (char *) td : "(null)"); + //printf ("%d: expected %u %zu/%s received %zu/%s\n", + // id, exp_index, expsz, exp, tsz, td ? (char *) td : "(null)"); MPT_ASSERT (eq, "Topic data mismatch: expected %u %zu/%s received %zu/%s\n", exp_index, expsz, exp, tsz, td ? (char *) td : "(null)"); if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0])) @@ -511,8 +511,8 @@ MPT_ProcessEntry (rwgd, exp = "X"; const size_t expsz = first ? 1 : strlen (exp); bool eq = (gsz == expsz && (gsz == 0 || memcmp (gd, exp, gsz) == 0)); - printf ("%d: expected %u %zu/%s received %zu/%s\n", - id, exp_index, expsz, exp, gsz, gd ? (char *) gd : "(null)"); + //printf ("%d: expected %u %zu/%s received %zu/%s\n", + // id, exp_index, expsz, exp, gsz, gd ? (char *) gd : "(null)"); MPT_ASSERT (eq, "Group data mismatch: expected %u %zu/%s received %zu/%s\n", exp_index, expsz, exp, gsz, gd ? (char *) gd : "(null)"); if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0])) From 6ad99463ce87e6d9cbf92c5ae789e67379da6980 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 7 Jun 2019 17:52:14 +0200 Subject: [PATCH 106/178] Fix ddsperf race conditions Tracking pings and expected number of pongs was done without holding the correct locks. Terminate flag was also not a ddsrt_atomic... and hence flagged by thread sanitizer as a race condition. Signed-off-by: Erik Boasson --- src/tools/ddsperf/ddsperf.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index eaaefc9..8d51e5b 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -32,6 +32,7 @@ #include "dds/ddsrt/random.h" #include "dds/ddsrt/avl.h" #include "dds/ddsrt/fibheap.h" +#include "dds/ddsrt/atomics.h" #if !defined(_WIN32) && !defined(LWIP_SOCKET) #include @@ -57,7 +58,7 @@ enum submode { }; static const char *argv0; -static volatile sig_atomic_t termflag = 0; +static ddsrt_atomic_uint32_t termflag = DDSRT_ATOMIC_UINT32_INIT (0); /* Domain participant, guard condition for termination, domain id */ static dds_entity_t dp; @@ -555,7 +556,7 @@ static uint32_t pubthread (void *varg) tfirst0 = tfirst = dds_time(); unsigned bi = 0; - while (!termflag) + while (!ddsrt_atomic_ld32 (&termflag)) { /* lsb of timestamp is abused to signal whether the sample is a ping requiring a response or not */ bool reqresp = (ping_frac == 0) ? 0 : (ping_frac == UINT32_MAX) ? 1 : (ddsrt_random () <= ping_frac); @@ -591,7 +592,7 @@ static uint32_t pubthread (void *varg) if (++bi == burstsize) { /* FIXME: should average rate over a short-ish period, rather than over the entire run */ - while (((double) (ntot / burstsize) / ((double) (t - tfirst0) / 1e9 + 5e-3)) > pub_rate && !termflag) + while (((double) (ntot / burstsize) / ((double) (t - tfirst0) / 1e9 + 5e-3)) > pub_rate && !ddsrt_atomic_ld32 (&termflag)) { /* FIXME: flushing manually because batching is not yet implemented properly */ dds_write_flush (wr_data); @@ -695,9 +696,15 @@ static bool update_roundtrip (dds_instance_handle_t pubhandle, uint64_t tdelta, bool allseen; ddsrt_mutex_lock (&pongstat_lock); if (isping && seq == cur_ping_seq) + { + ddsrt_mutex_lock (&pongwr_lock); allseen = (++n_pong_seen == n_pong_expected); + ddsrt_mutex_unlock (&pongwr_lock); + } else + { allseen = false; + } for (uint32_t i = 0; i < npongstat; i++) if (pongstat[i].pubhandle == pubhandle) { @@ -936,7 +943,7 @@ static uint32_t subthread_waitset (void *varg) 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); - while (!termflag) + while (!ddsrt_atomic_ld32 (&termflag)) { if (!process_data (rd_data, arg)) { @@ -962,7 +969,7 @@ static uint32_t subpingthread_waitset (void *varg) 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); - while (!termflag) + while (!ddsrt_atomic_ld32 (&termflag)) { int32_t nxs; if ((nxs = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY)) < 0) @@ -984,7 +991,7 @@ static uint32_t subpongthread_waitset (void *varg) 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); - while (!termflag) + while (!ddsrt_atomic_ld32 (&termflag)) { int32_t nxs; if ((nxs = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY)) < 0) @@ -997,7 +1004,7 @@ static uint32_t subpongthread_waitset (void *varg) static uint32_t subthread_polling (void *varg) { struct subthread_arg * const arg = varg; - while (!termflag) + while (!ddsrt_atomic_ld32 (&termflag)) { if (!process_data (rd_data, arg)) dds_sleepfor (DDS_MSECS (1)); @@ -1174,14 +1181,14 @@ static void participant_data_listener (dds_entity_t rd, void *arg) if (n_pong_expected_delta) { - ddsrt_mutex_lock (&pongstat_lock); + ddsrt_mutex_lock (&pongwr_lock); n_pong_expected += n_pong_expected_delta; /* potential initial packet loss & lazy writer creation conspire against receiving the expected number of responses, so allow for a few attempts before starting to warn about timeouts */ twarn_ping_timeout = dds_time () + DDS_MSECS (3333); //printf ("[%"PRIdPID"] n_pong_expected = %u\n", ddsrt_getpid (), n_pong_expected); - ddsrt_mutex_unlock (&pongstat_lock); + ddsrt_mutex_unlock (&pongwr_lock); } } @@ -1410,7 +1417,7 @@ static void subthread_arg_fini (struct subthread_arg *arg) static void signal_handler (int sig) { (void) sig; - termflag = 1; + ddsrt_atomic_st32 (&termflag, 1); dds_set_guardcondition (termcond, true); } #endif @@ -1928,7 +1935,7 @@ int main (int argc, char *argv[]) dds_time_t tnext = tstart + DDS_SECS (1); dds_time_t tlast = tstart; dds_time_t tnextping = (ping_intv == DDS_INFINITY) ? DDS_NEVER : (ping_intv == 0) ? tstart + DDS_SECS (1) : tstart + ping_intv; - while (!termflag && tnow < tstop) + while (!ddsrt_atomic_ld32 (&termflag) && tnow < tstop) { dds_time_t twakeup = DDS_NEVER; int32_t nxs; From 559c3253070f8df014fd51adfa6c1c11ca35a417 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 12 Jun 2019 14:40:49 +0200 Subject: [PATCH 107/178] Emulate 64-bit atomic ops if hardware doesn't support them Signed-off-by: Erik Boasson --- src/ddsrt/include/dds/ddsrt/atomics.h | 28 +++ src/ddsrt/include/dds/ddsrt/atomics/gcc.h | 8 + src/ddsrt/src/atomics.c | 205 ++++++++++++++++++++++ src/ddsrt/src/cdtors.c | 2 + 4 files changed, 243 insertions(+) diff --git a/src/ddsrt/include/dds/ddsrt/atomics.h b/src/ddsrt/include/dds/ddsrt/atomics.h index 5acbed4..294085e 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics.h +++ b/src/ddsrt/include/dds/ddsrt/atomics.h @@ -59,6 +59,34 @@ typedef ddsrt_atomic_uintptr_t ddsrt_atomic_voidp_t; #error "Atomic operations are not supported" #endif +#if ! DDSRT_HAVE_ATOMIC64 +/* 64-bit atomics are not supported by all hardware, but it would be a shame not to use them when + they are available. That necessitates an alternative implementation when they are not, either in + the form of a different implementation where it is used, or as an emulation using a mutex in + ddsrt. It seems that the places where they'd be used end up adding a mutex, so an emulation in + ddsrt while being able to check whether it is supported by hardware is a sensible approach. */ +DDS_EXPORT uint64_t ddsrt_atomic_ld64 (const volatile ddsrt_atomic_uint64_t *x); +DDS_EXPORT void ddsrt_atomic_st64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v); +DDS_EXPORT void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x); +DDS_EXPORT uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x); +DDS_EXPORT void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x); +DDS_EXPORT uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x); +DDS_EXPORT void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v); +DDS_EXPORT uint64_t ddsrt_atomic_add64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v); +DDS_EXPORT void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v); +DDS_EXPORT uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v); +DDS_EXPORT void ddsrt_atomic_and64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v); +DDS_EXPORT uint64_t ddsrt_atomic_and64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v); +DDS_EXPORT uint64_t ddsrt_atomic_and64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v); +DDS_EXPORT void ddsrt_atomic_or64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v); +DDS_EXPORT uint64_t ddsrt_atomic_or64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v); +DDS_EXPORT uint64_t ddsrt_atomic_or64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v); +DDS_EXPORT int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_t exp, uint64_t des); +#endif + +void ddsrt_atomics_init (void); +void ddsrt_atomics_fini (void); + #if defined(__cplusplus) } #endif diff --git a/src/ddsrt/include/dds/ddsrt/atomics/gcc.h b/src/ddsrt/include/dds/ddsrt/atomics/gcc.h index a567e81..59e05a7 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/gcc.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/gcc.h @@ -318,10 +318,18 @@ inline void ddsrt_atomic_fence_ldld (void) { #endif } inline void ddsrt_atomic_fence_acq (void) { +#if !(defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64) ddsrt_atomic_fence (); +#else + asm volatile ("" ::: "memory"); +#endif } inline void ddsrt_atomic_fence_rel (void) { +#if !(defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64) ddsrt_atomic_fence (); +#else + asm volatile ("" ::: "memory"); +#endif } #if defined (__cplusplus) diff --git a/src/ddsrt/src/atomics.c b/src/ddsrt/src/atomics.c index bc87a7b..5919a40 100644 --- a/src/ddsrt/src/atomics.c +++ b/src/ddsrt/src/atomics.c @@ -161,3 +161,208 @@ void ddsrt_atomic_lifo_pushmany (ddsrt_atomic_lifo_t *head, void *first, void *l } while (!ddsrt_atomic_casvoidp2 (&head->aba_head, a0, b0, a0+1, (uintptr_t)first)); } #endif + +#if DDSRT_HAVE_ATOMIC64 +void ddsrt_atomics_init (void) +{ +} + +void ddsrt_atomics_fini (void) +{ +} + +#else + +/* Emulation by hashing the variable's address to a small set of mutexes. */ +#include "dds/ddsrt/sync.h" + +#define N_MUTEXES_LG2 4 +#define N_MUTEXES (1 << N_MUTEXES_LG2) +static ddsrt_mutex_t mutexes[N_MUTEXES]; + +void ddsrt_atomics_init (void) +{ + for (int i = 0; i < N_MUTEXES; i++) + ddsrt_mutex_init (&mutexes[i]); +} + +void ddsrt_atomics_fini (void) +{ + for (int i = 0; i < N_MUTEXES; i++) + ddsrt_mutex_destroy (&mutexes[i]); +} + +static uint32_t atomic64_lock_index (const volatile ddsrt_atomic_uint64_t *x) +{ + const uint32_t u = (uint16_t) ((uintptr_t) x >> 3); + const uint32_t v = u * 0xb4817365; + return v >> (32 - N_MUTEXES_LG2); +} + +int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_t exp, uint64_t des) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + if (x->v == exp) + { + x->v = des; + ddsrt_mutex_unlock (&mutexes[idx]); + return true; + } + else + { + ddsrt_mutex_unlock (&mutexes[idx]); + return false; + } +} + +uint64_t ddsrt_atomic_ld64(const volatile ddsrt_atomic_uint64_t *x) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + const uint64_t v = x->v; + ddsrt_mutex_unlock (&mutexes[idx]); + return v; +} + +void ddsrt_atomic_st64(volatile ddsrt_atomic_uint64_t *x, uint64_t v) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + x->v = v; + ddsrt_mutex_unlock (&mutexes[idx]); +} + +void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + ++x->v; + ddsrt_mutex_unlock (&mutexes[idx]); +} + +uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + const uint64_t nv = ++x->v; + ddsrt_mutex_unlock (&mutexes[idx]); + return nv; +} + +void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + --x->v; + ddsrt_mutex_unlock (&mutexes[idx]); +} + +uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + const uint64_t nv = --x->v; + ddsrt_mutex_unlock (&mutexes[idx]); + return nv; +} + +void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + x->v += v; + ddsrt_mutex_unlock (&mutexes[idx]); +} + +uint64_t ddsrt_atomic_add64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + const uint64_t ov = x->v; + const uint64_t nv = ov + v; + x->v = nv; + ddsrt_mutex_unlock (&mutexes[idx]); + return nv; +} + +void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + x->v -= v; + ddsrt_mutex_unlock (&mutexes[idx]); +} + +uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + const uint64_t ov = x->v; + const uint64_t nv = ov - v; + x->v = nv; + ddsrt_mutex_unlock (&mutexes[idx]); + return nv; +} + +void ddsrt_atomic_and64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + x->v &= v; + ddsrt_mutex_unlock (&mutexes[idx]); +} + +uint64_t ddsrt_atomic_and64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + const uint64_t ov = x->v; + const uint64_t nv = ov & v; + x->v = nv; + ddsrt_mutex_unlock (&mutexes[idx]); + return ov; +} + +uint64_t ddsrt_atomic_and64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + const uint64_t ov = x->v; + const uint64_t nv = ov & v; + x->v = nv; + ddsrt_mutex_unlock (&mutexes[idx]); + return nv; +} + +void ddsrt_atomic_or64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + x->v |= v; + ddsrt_mutex_unlock (&mutexes[idx]); +} + +uint64_t ddsrt_atomic_or64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + const uint64_t ov = x->v; + const uint64_t nv = ov | v; + x->v = nv; + ddsrt_mutex_unlock (&mutexes[idx]); + return ov; +} + +uint64_t ddsrt_atomic_or64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) +{ + const uint32_t idx = atomic64_lock_index (x); + ddsrt_mutex_lock (&mutexes[idx]); + const uint64_t ov = x->v; + const uint64_t nv = ov | v; + x->v = nv; + ddsrt_mutex_unlock (&mutexes[idx]); + return nv; +} + +#endif /* DDSRT_HAVE_ATOMIC64 */ diff --git a/src/ddsrt/src/cdtors.c b/src/ddsrt/src/cdtors.c index de63e32..e184098 100644 --- a/src/ddsrt/src/cdtors.c +++ b/src/ddsrt/src/cdtors.c @@ -43,6 +43,7 @@ retry: ddsrt_time_init(); #endif ddsrt_random_init(); + ddsrt_atomics_init(); ddsrt_atomic_or32(&init_status, INIT_STATUS_OK); } else { while (v > 1 && !(v & INIT_STATUS_OK)) { @@ -68,6 +69,7 @@ void ddsrt_fini (void) { ddsrt_mutex_destroy(&init_mutex); ddsrt_random_fini(); + ddsrt_atomics_fini(); #if _WIN32 ddsrt_winsock_fini(); ddsrt_time_fini(); From 9c2f3bdf2b4133af26a65b2bca04f431c1fe87b3 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 12 Jun 2019 13:46:06 +0200 Subject: [PATCH 108/178] Update leases with atomic ops instead of hashing leases to lease_locks Lease_renew is the key one, and that one only ever shifts the lease expiry to the future, providing the lease hasn't expired already. All other operations work within leaseheap_lock. Other updates to lease end time are in set_expiry (which is used in some special cases). So ... the number of ways this can go wrong is rather limited. --- src/core/ddsi/include/dds/ddsi/q_globals.h | 4 - src/core/ddsi/src/q_lease.c | 94 +++++++--------------- 2 files changed, 31 insertions(+), 67 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/q_globals.h index aa048ba..39acf96 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/q_globals.h @@ -64,9 +64,6 @@ enum recvips_mode { RECVIPS_MODE_SOME /* explicit list of interfaces; only one requiring recvips */ }; -#define N_LEASE_LOCKS_LG2 4 -#define N_LEASE_LOCKS ((int) (1 << N_LEASE_LOCKS_LG2)) - enum recv_thread_mode { RTM_SINGLE, RTM_MANY @@ -109,7 +106,6 @@ struct q_globals { /* Lease junk */ ddsrt_mutex_t leaseheap_lock; - ddsrt_mutex_t lease_locks[N_LEASE_LOCKS]; ddsrt_fibheap_t leaseheap; /* Transport factory */ diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index f3d2e5b..dd17cea 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -45,9 +45,9 @@ struct lease { ddsrt_fibheap_node_t heapnode; - nn_etime_t tsched; /* access guarded by leaseheap_lock */ - nn_etime_t tend; /* access guarded by lock_lease/unlock_lease */ - dds_duration_t tdur; /* constant (renew depends on it) */ + nn_etime_t tsched; /* access guarded by leaseheap_lock */ + ddsrt_atomic_uint64_t tend; /* really an nn_etime_t */ + dds_duration_t tdur; /* constant (renew depends on it) */ struct entity_common *entity; /* constant */ }; @@ -69,40 +69,16 @@ static int compare_lease_tsched (const void *va, const void *vb) void lease_management_init (void) { - int i; ddsrt_mutex_init (&gv.leaseheap_lock); - for (i = 0; i < N_LEASE_LOCKS; i++) - ddsrt_mutex_init (&gv.lease_locks[i]); ddsrt_fibheap_init (&lease_fhdef, &gv.leaseheap); } void lease_management_term (void) { - int i; assert (ddsrt_fibheap_min (&lease_fhdef, &gv.leaseheap) == NULL); - for (i = 0; i < N_LEASE_LOCKS; i++) - ddsrt_mutex_destroy (&gv.lease_locks[i]); ddsrt_mutex_destroy (&gv.leaseheap_lock); } -static ddsrt_mutex_t *lock_lease_addr (struct lease const * const l) -{ - uint32_t u = (uint16_t) ((uintptr_t) l >> 3); - uint32_t v = u * 0xb4817365; - uint32_t idx = v >> (32 - N_LEASE_LOCKS_LG2); - return &gv.lease_locks[idx]; -} - -static void lock_lease (const struct lease *l) -{ - ddsrt_mutex_lock (lock_lease_addr (l)); -} - -static void unlock_lease (const struct lease *l) -{ - ddsrt_mutex_unlock (lock_lease_addr (l)); -} - struct lease *lease_new (nn_etime_t texpire, dds_duration_t tdur, struct entity_common *e) { struct lease *l; @@ -110,7 +86,7 @@ struct lease *lease_new (nn_etime_t texpire, dds_duration_t tdur, struct entity_ return NULL; DDS_TRACE("lease_new(tdur %"PRId64" guid "PGUIDFMT") @ %p\n", tdur, PGUID (e->guid), (void *) l); l->tdur = tdur; - l->tend = texpire; + ddsrt_atomic_st64 (&l->tend, (uint64_t) texpire.v); l->tsched.v = TSCHED_NOT_ON_HEAP; l->entity = e; return l; @@ -120,14 +96,13 @@ void lease_register (struct lease *l) { DDS_TRACE("lease_register(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid)); ddsrt_mutex_lock (&gv.leaseheap_lock); - lock_lease (l); assert (l->tsched.v == TSCHED_NOT_ON_HEAP); - if (l->tend.v != T_NEVER) + int64_t tend = (int64_t) ddsrt_atomic_ld64 (&l->tend); + if (tend != T_NEVER) { - l->tsched = l->tend; + l->tsched.v = tend; ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l); } - unlock_lease (l); ddsrt_mutex_unlock (&gv.leaseheap_lock); /* check_and_handle_lease_expiration runs on GC thread and the only way to be sure that it wakes up in time is by forcing re-evaluation (strictly speaking only needed if this is the first lease to expire, but this operation is quite rare anyway) */ @@ -150,19 +125,16 @@ void lease_free (struct lease *l) void lease_renew (struct lease *l, nn_etime_t tnowE) { nn_etime_t tend_new = add_duration_to_etime (tnowE, l->tdur); - int did_update; - lock_lease (l); - /* do not touch tend if moving forward or if already expired */ - if (tend_new.v <= l->tend.v || tnowE.v >= l->tend.v) - did_update = 0; - else - { - l->tend = tend_new; - did_update = 1; - } - unlock_lease (l); - if (did_update && (dds_get_log_mask() & DDS_LC_TRACE)) + /* do not touch tend if moving forward or if already expired */ + int64_t tend; + do { + tend = (int64_t) ddsrt_atomic_ld64 (&l->tend); + if (tend_new.v <= tend || tnowE.v >= tend) + return; + } while (!ddsrt_atomic_cas64 (&l->tend, (uint64_t) tend, (uint64_t) tend_new.v)); + + if ((dds_get_log_mask() & DDS_LC_TRACE)) { int32_t tsec, tusec; DDS_TRACE(" L("); @@ -180,24 +152,24 @@ void lease_set_expiry (struct lease *l, nn_etime_t when) bool trigger = false; assert (when.v >= 0); ddsrt_mutex_lock (&gv.leaseheap_lock); - lock_lease (l); - l->tend = when; - if (l->tend.v < l->tsched.v) + /* only possible concurrent action is to move tend into the future (renew_lease), + all other operations occur with leaseheap_lock held */ + ddsrt_atomic_st64 (&l->tend, (uint64_t) when.v); + if (when.v < l->tsched.v) { /* moved forward and currently scheduled (by virtue of TSCHED_NOT_ON_HEAP == INT64_MIN) */ - l->tsched = l->tend; + l->tsched = when; ddsrt_fibheap_decrease_key (&lease_fhdef, &gv.leaseheap, l); trigger = true; } - else if (l->tsched.v == TSCHED_NOT_ON_HEAP && l->tend.v < T_NEVER) + else if (l->tsched.v == TSCHED_NOT_ON_HEAP && when.v < T_NEVER) { /* not currently scheduled, with a finite new expiry time */ - l->tsched = l->tend; + l->tsched = when; ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l); trigger = true; } - unlock_lease (l); ddsrt_mutex_unlock (&gv.leaseheap_lock); /* see lease_register() */ @@ -217,23 +189,22 @@ int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) assert (l->tsched.v != TSCHED_NOT_ON_HEAP); ddsrt_fibheap_extract_min (&lease_fhdef, &gv.leaseheap); - - lock_lease (l); - if (tnowE.v < l->tend.v) + /* only possible concurrent action is to move tend into the future (renew_lease), + all other operations occur with leaseheap_lock held */ + int64_t tend = (int64_t) ddsrt_atomic_ld64 (&l->tend); + if (tnowE.v < tend) { - if (l->tend.v == T_NEVER) { + if (tend == T_NEVER) { /* don't reinsert if it won't expire */ l->tsched.v = TSCHED_NOT_ON_HEAP; - unlock_lease (l); } else { - l->tsched = l->tend; - unlock_lease (l); + l->tsched.v = tend; ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l); } continue; } - DDS_LOG(DDS_LC_DISCOVERY, "lease expired: l %p guid "PGUIDFMT" tend %"PRId64" < now %"PRId64"\n", (void *) l, PGUID (g), l->tend.v, tnowE.v); + DDS_LOG(DDS_LC_DISCOVERY, "lease expired: l %p guid "PGUIDFMT" tend %"PRId64" < now %"PRId64"\n", (void *) l, PGUID (g), tend, tnowE.v); /* If the proxy participant is relying on another participant for writing its discovery data (on the privileged participant, @@ -268,15 +239,12 @@ int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) { DDS_LOG(DDS_LC_DISCOVERY, "but postponing because privileged pp "PGUIDFMT" is still live\n", PGUID (proxypp->privileged_pp_guid)); - l->tsched = l->tend = add_duration_to_etime (tnowE, 200 * T_MILLISECOND); - unlock_lease (l); + l->tsched = add_duration_to_etime (tnowE, 200 * T_MILLISECOND); ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l); continue; } } - unlock_lease (l); - l->tsched.v = TSCHED_NOT_ON_HEAP; ddsrt_mutex_unlock (&gv.leaseheap_lock); From 28317ba49e9a3adf284ab67ba91ff7cabea4a68e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 8 Jun 2019 19:23:53 +0200 Subject: [PATCH 109/178] Give all entities an instance handle (#43) Add the instance handle to the DDSC entity type, initialize it properly for all types, and remove the per-type handling of dds_get_instance_handle. Those entities that have a DDSI variant take the instance handle from DDSI (which plays tricks to get the instance handles of the entities matching the built-in topics). For those that do not have a DDSI variant, just generate a unique identifier using the same generate that DDSI uses. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds__types.h | 66 ++++++++++++----------- src/core/ddsc/src/dds_entity.c | 10 ++-- src/core/ddsc/src/dds_guardcond.c | 4 +- src/core/ddsc/src/dds_participant.c | 10 +--- src/core/ddsc/src/dds_publisher.c | 11 +--- src/core/ddsc/src/dds_readcond.c | 2 + src/core/ddsc/src/dds_reader.c | 10 +--- src/core/ddsc/src/dds_subscriber.c | 11 +--- src/core/ddsc/src/dds_topic.c | 1 + src/core/ddsc/src/dds_waitset.c | 2 + src/core/ddsc/src/dds_writer.c | 10 +--- src/core/ddsc/tests/unsupported.c | 11 ++-- src/core/ddsi/include/dds/ddsi/q_entity.h | 5 +- src/core/ddsi/src/q_entity.c | 48 ++++------------- src/core/ddsi/src/q_ephash.c | 1 + src/core/ddsi/src/q_xevent.c | 2 +- 16 files changed, 70 insertions(+), 134 deletions(-) diff --git a/src/core/ddsc/src/dds__types.h b/src/core/ddsc/src/dds__types.h index ba2319a..ea54811 100644 --- a/src/core/ddsc/src/dds__types.h +++ b/src/core/ddsc/src/dds__types.h @@ -103,41 +103,45 @@ dds_domain; struct dds_entity; typedef struct dds_entity_deriver { - /* Close can be used to terminate (blocking) actions on a entity before actually deleting it. */ - dds_return_t (*close)(struct dds_entity *e) ddsrt_nonnull_all; - /* Delete is used to actually free the entity. */ - dds_return_t (*delete)(struct dds_entity *e) ddsrt_nonnull_all; - dds_return_t (*set_qos)(struct dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; - dds_return_t (*validate_status)(uint32_t mask); - dds_return_t (*get_instance_hdl)(struct dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all; -} -dds_entity_deriver; + /* Close can be used to terminate (blocking) actions on a entity before actually deleting it. */ + dds_return_t (*close)(struct dds_entity *e) ddsrt_nonnull_all; + /* Delete is used to actually free the entity. */ + dds_return_t (*delete)(struct dds_entity *e) ddsrt_nonnull_all; + dds_return_t (*set_qos)(struct dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all; + dds_return_t (*validate_status)(uint32_t mask); +} dds_entity_deriver; typedef void (*dds_entity_callback)(dds_entity_t observer, dds_entity_t observed, uint32_t status); -typedef struct dds_entity_observer -{ - dds_entity_callback m_cb; - dds_entity_t m_observer; - struct dds_entity_observer *m_next; -} -dds_entity_observer; +typedef struct dds_entity_observer { + dds_entity_callback m_cb; + dds_entity_t m_observer; + struct dds_entity_observer *m_next; +} dds_entity_observer; -typedef struct dds_entity -{ - struct dds_handle_link m_hdllink; - dds_entity_kind_t m_kind; - dds_entity_deriver m_deriver; - uint32_t m_refc; - struct dds_entity * m_next; - struct dds_entity * m_parent; - struct dds_entity * m_children; - struct dds_entity * m_participant; - struct dds_domain * m_domain; - dds_qos_t * m_qos; - dds_domainid_t m_domainid; - nn_guid_t m_guid; - uint32_t m_flags; +typedef struct dds_entity { + struct dds_handle_link m_hdllink; /* handle is constant, cnt_flags private to dds_handle.c */ + dds_entity_kind_t m_kind; /* constant */ + dds_entity_deriver m_deriver; /* constant; FIXME: no point in having function pointers embedded */ + uint32_t m_refc; /* [m_mutex] */ + struct dds_entity *m_next; /* [m_mutex] */ + struct dds_entity *m_parent; /* constant */ + struct dds_entity *m_children; /* [m_mutex] */ + struct dds_entity *m_participant; /* constant */ + struct dds_domain *m_domain; /* constant */ + dds_qos_t *m_qos; /* [m_mutex] */ + dds_domainid_t m_domainid; /* constant; FIXME: why? hardly ever used, m_domain should give that info, too */ + nn_guid_t m_guid; /* ~ constant: FIXME: set during creation, but possibly after becoming visible */ + dds_instance_handle_t m_iid; /* ~ constant: FIXME: like GUID */ + uint32_t m_flags; /* [m_mutex] */ + + /* Allowed: + - locking parent->...->m_mutex while holding m_mutex + - locking topic::m_mutex while holding {publisher,subscriber}::m_mutex + (no hierarchical relationship there) + - locking topic::m_mutex while holding {reader,writer}::m_mutex + - locking observers_lock while holding m_mutex + */ ddsrt_mutex_t m_mutex; ddsrt_cond_t m_cond; diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index 4b51023..2fc5f25 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -889,14 +889,10 @@ dds_return_t dds_get_instance_handle (dds_entity_t entity, dds_instance_handle_t if (ihdl == NULL) return DDS_RETCODE_BAD_PARAMETER; - if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + if ((ret = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) return ret; - - if (e->m_deriver.get_instance_hdl) - ret = e->m_deriver.get_instance_hdl (e, ihdl); - else - ret = DDS_RETCODE_ILLEGAL_OPERATION; - dds_entity_unlock(e); + *ihdl = e->m_iid; + dds_entity_release(e); return ret; } diff --git a/src/core/ddsc/src/dds_guardcond.c b/src/core/ddsc/src/dds_guardcond.c index 8dcb956..5e7e83b 100644 --- a/src/core/ddsc/src/dds_guardcond.c +++ b/src/core/ddsc/src/dds_guardcond.c @@ -14,6 +14,7 @@ #include "dds__reader.h" #include "dds__guardcond.h" #include "dds__participant.h" +#include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" @@ -29,8 +30,9 @@ dds_entity_t dds_create_guardcondition (dds_entity_t participant) return rc; else { - dds_guardcond * gcond = dds_alloc (sizeof (*gcond)); + dds_guardcond *gcond = dds_alloc (sizeof (*gcond)); dds_entity_t hdl = dds_entity_init (&gcond->m_entity, &pp->m_entity, DDS_KIND_COND_GUARD, NULL, NULL, 0); + gcond->m_entity.m_iid = ddsi_iid_gen (); dds_participant_unlock (pp); return hdl; } diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index fea399b..57aca98 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -64,14 +64,6 @@ static dds_return_t dds_participant_delete (dds_entity *e) return DDS_RETCODE_OK; } -static dds_return_t dds_participant_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all; - -static dds_return_t dds_participant_instance_hdl (dds_entity *e, dds_instance_handle_t *i) -{ - *i = participant_instance_id (&e->m_guid); - return DDS_RETCODE_OK; -} - static dds_return_t dds_participant_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 */ @@ -134,11 +126,11 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_ goto err_entity_init; pp->m_entity.m_guid = guid; + pp->m_entity.m_iid = get_entity_instance_id (&guid); pp->m_entity.m_domain = dds_domain_create (dds_domain_default ()); pp->m_entity.m_domainid = dds_domain_default (); pp->m_entity.m_deriver.delete = dds_participant_delete; pp->m_entity.m_deriver.set_qos = dds_participant_qos_set; - pp->m_entity.m_deriver.get_instance_hdl = dds_participant_instance_hdl; pp->m_entity.m_deriver.validate_status = dds_participant_status_validate; pp->m_builtin_subscriber = 0; diff --git a/src/core/ddsc/src/dds_publisher.c b/src/core/ddsc/src/dds_publisher.c index 307a40b..850623d 100644 --- a/src/core/ddsc/src/dds_publisher.c +++ b/src/core/ddsc/src/dds_publisher.c @@ -24,15 +24,6 @@ DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_publisher) #define DDS_PUBLISHER_STATUS_MASK (0u) -static dds_return_t dds_publisher_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all; - -static dds_return_t dds_publisher_instance_hdl (dds_entity *e, dds_instance_handle_t *i) -{ - /* FIXME: Get/generate proper handle. */ - (void) e; (void) i; - return DDS_RETCODE_UNSUPPORTED; -} - static dds_return_t dds_publisher_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 */ @@ -70,8 +61,8 @@ dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qo } pub = dds_alloc (sizeof (*pub)); hdl = dds_entity_init (&pub->m_entity, &par->m_entity, DDS_KIND_PUBLISHER, new_qos, listener, DDS_PUBLISHER_STATUS_MASK); + pub->m_entity.m_iid = ddsi_iid_gen (); pub->m_entity.m_deriver.set_qos = dds_publisher_qos_set; - pub->m_entity.m_deriver.get_instance_hdl = dds_publisher_instance_hdl; pub->m_entity.m_deriver.validate_status = dds_publisher_status_validate; dds_participant_unlock (par); return hdl; diff --git a/src/core/ddsc/src/dds_readcond.c b/src/core/ddsc/src/dds_readcond.c index c5b0ace..0de3879 100644 --- a/src/core/ddsc/src/dds_readcond.c +++ b/src/core/ddsc/src/dds_readcond.c @@ -14,6 +14,7 @@ #include "dds__readcond.h" #include "dds__rhc.h" #include "dds__entity.h" +#include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" @@ -31,6 +32,7 @@ dds_readcond *dds_create_readcond (dds_reader *rd, dds_entity_kind_t kind, uint3 dds_readcond *cond = dds_alloc (sizeof (*cond)); assert ((kind == DDS_KIND_COND_READ && filter == 0) || (kind == DDS_KIND_COND_QUERY && filter != 0)); (void) dds_entity_init (&cond->m_entity, &rd->m_entity, kind, NULL, NULL, 0); + cond->m_entity.m_iid = ddsi_iid_gen (); cond->m_entity.m_deriver.delete = dds_readcond_delete; cond->m_rhc = rd->m_rd->rhc; cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE; diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 9fcecd6..dd40d40 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -39,14 +39,6 @@ DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_reader) DDS_SAMPLE_LOST_STATUS |\ DDS_SUBSCRIPTION_MATCHED_STATUS) -static dds_return_t dds_reader_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all; - -static dds_return_t dds_reader_instance_hdl (dds_entity *e, dds_instance_handle_t *i) -{ - *i = reader_instance_id (&e->m_guid); - return DDS_RETCODE_OK; -} - static dds_return_t dds_reader_close (dds_entity *e) ddsrt_nonnull_all; static dds_return_t dds_reader_close (dds_entity *e) @@ -392,7 +384,6 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti rd->m_entity.m_deriver.delete = dds_reader_delete; rd->m_entity.m_deriver.set_qos = dds_reader_qos_set; rd->m_entity.m_deriver.validate_status = dds_reader_status_validate; - rd->m_entity.m_deriver.get_instance_hdl = dds_reader_instance_hdl; /* Extra claim of this reader to make sure that the delete waits until DDSI has deleted its reader as well. This can be known through the callback. */ @@ -407,6 +398,7 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti ddsrt_mutex_lock (&tp->m_entity.m_mutex); assert (ret == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */ thread_state_asleep (lookup_thread_state ()); + rd->m_entity.m_iid = get_entity_instance_id (&rd->m_entity.m_guid); /* For persistent data register reader with durability */ if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > DDS_DURABILITY_TRANSIENT_LOCAL)) { diff --git a/src/core/ddsc/src/dds_subscriber.c b/src/core/ddsc/src/dds_subscriber.c index 181a6af..084558d 100644 --- a/src/core/ddsc/src/dds_subscriber.c +++ b/src/core/ddsc/src/dds_subscriber.c @@ -23,15 +23,6 @@ DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_subscriber) #define DDS_SUBSCRIBER_STATUS_MASK \ (DDS_DATA_ON_READERS_STATUS) -static dds_return_t dds_subscriber_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all; - -static dds_return_t dds_subscriber_instance_hdl (dds_entity *e, dds_instance_handle_t *i) -{ - (void) e; (void) i; - /* FIXME: Get/generate proper handle. */ - return DDS_RETCODE_UNSUPPORTED; -} - static dds_return_t dds_subscriber_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 */ @@ -64,9 +55,9 @@ dds_entity_t dds__create_subscriber_l (dds_participant *participant, const dds_q sub = dds_alloc (sizeof (*sub)); subscriber = dds_entity_init (&sub->m_entity, &participant->m_entity, DDS_KIND_SUBSCRIBER, new_qos, listener, DDS_SUBSCRIBER_STATUS_MASK); + sub->m_entity.m_iid = ddsi_iid_gen (); sub->m_entity.m_deriver.set_qos = dds_subscriber_qos_set; sub->m_entity.m_deriver.validate_status = dds_subscriber_status_validate; - sub->m_entity.m_deriver.get_instance_hdl = dds_subscriber_instance_hdl; return subscriber; } diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 90bf553..d7f04c7 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -271,6 +271,7 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s /* Create topic */ top = dds_alloc (sizeof (*top)); hdl = dds_entity_init (&top->m_entity, &par->m_entity, DDS_KIND_TOPIC, new_qos, listener, DDS_TOPIC_STATUS_MASK); + top->m_entity.m_iid = ddsi_iid_gen (); top->m_entity.m_deriver.delete = dds_topic_delete; top->m_entity.m_deriver.set_qos = dds_topic_qos_set; top->m_entity.m_deriver.validate_status = dds_topic_status_validate; diff --git a/src/core/ddsc/src/dds_waitset.c b/src/core/ddsc/src/dds_waitset.c index 7bbeefe..004f1e6 100644 --- a/src/core/ddsc/src/dds_waitset.c +++ b/src/core/ddsc/src/dds_waitset.c @@ -18,6 +18,7 @@ #include "dds__querycond.h" #include "dds__readcond.h" #include "dds__rhc.h" +#include "dds/ddsi/ddsi_iid.h" DEFINE_ENTITY_LOCK_UNLOCK (static, dds_waitset, DDS_KIND_WAITSET) @@ -153,6 +154,7 @@ dds_entity_t dds_create_waitset (dds_entity_t participant) dds_waitset *waitset = dds_alloc (sizeof (*waitset)); hdl = dds_entity_init (&waitset->m_entity, &par->m_entity, DDS_KIND_WAITSET, NULL, NULL, 0); + waitset->m_entity.m_iid = ddsi_iid_gen (); waitset->m_entity.m_deriver.close = dds_waitset_close; waitset->observed = NULL; waitset->triggered = NULL; diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index bf55b18..1a404e9 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -36,14 +36,6 @@ DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_writer) DDS_OFFERED_INCOMPATIBLE_QOS_STATUS |\ DDS_PUBLICATION_MATCHED_STATUS) -static dds_return_t dds_writer_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all; - -static dds_return_t dds_writer_instance_hdl (dds_entity *e, dds_instance_handle_t *i) -{ - *i = writer_instance_id(&e->m_guid); - return DDS_RETCODE_OK; -} - static dds_return_t dds_writer_status_validate (uint32_t mask) { return (mask & ~DDS_WRITER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK; @@ -305,7 +297,6 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit wr->m_entity.m_deriver.delete = dds_writer_delete; wr->m_entity.m_deriver.set_qos = dds_writer_qos_set; wr->m_entity.m_deriver.validate_status = dds_writer_status_validate; - wr->m_entity.m_deriver.get_instance_hdl = dds_writer_instance_hdl; wr->m_whc = make_whc (wqos); /* Extra claim of this writer to make sure that the delete waits until DDSI @@ -321,6 +312,7 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit ddsrt_mutex_lock (&tp->m_entity.m_mutex); assert(rc == DDS_RETCODE_OK); thread_state_asleep (lookup_thread_state ()); + wr->m_entity.m_iid = get_entity_instance_id (&wr->m_entity.m_guid); dds_topic_unlock (tp); dds_publisher_unlock (pub); return writer; diff --git a/src/core/ddsc/tests/unsupported.c b/src/core/ddsc/tests/unsupported.c index 417302a..b7e63cb 100644 --- a/src/core/ddsc/tests/unsupported.c +++ b/src/core/ddsc/tests/unsupported.c @@ -121,16 +121,19 @@ CU_Test(ddsc_unsupported, dds_get_instance_handle, .init = setup, .fini = teardo dds_return_t result; dds_instance_handle_t ih; static struct index_result pars[] = { - {TOP, DDS_RETCODE_ILLEGAL_OPERATION}, /* TODO: Shouldn't this be either supported or unsupported? */ - {PUB, DDS_RETCODE_UNSUPPORTED}, - {SUB, DDS_RETCODE_UNSUPPORTED}, - {RCD, DDS_RETCODE_ILLEGAL_OPERATION}, + {TOP, DDS_RETCODE_OK}, + {PUB, DDS_RETCODE_OK}, + {SUB, DDS_RETCODE_OK}, + {RCD, DDS_RETCODE_OK}, {BAD, DDS_RETCODE_BAD_PARAMETER} }; for (size_t i=0; i < sizeof (pars) / sizeof (pars[0]);i++) { result = dds_get_instance_handle(e[pars[i].index], &ih); CU_ASSERT_EQUAL(result, pars[i].exp_res); + if (pars[i].exp_res == DDS_RETCODE_OK) { + CU_ASSERT(ih > 0); + } } } diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index bb55315..5d6dccb 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -529,6 +529,7 @@ dds_return_t new_participant (struct nn_guid *ppguid, unsigned flags, const stru */ dds_return_t delete_participant (const struct nn_guid *ppguid); void update_participant_plist (struct participant *pp, const struct nn_plist *plist); +uint64_t get_entity_instance_id (const struct nn_guid *guid); /* To obtain the builtin writer to be used for publishing SPDP, SEDP, PMD stuff for PP and its endpoints, given the entityid. If PP has @@ -559,7 +560,6 @@ dds_return_t delete_writer_nolinger (const struct nn_guid *guid); dds_return_t delete_writer_nolinger_locked (struct writer *wr); dds_return_t delete_reader (const struct nn_guid *guid); -uint64_t reader_instance_id (const struct nn_guid *guid); struct local_orphan_writer { struct writer wr; @@ -593,7 +593,6 @@ void delete_local_orphan_writer (struct local_orphan_writer *wr); void new_proxy_participant (const struct nn_guid *guid, unsigned bes, unsigned prismtech_bes, const struct nn_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct nn_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq); int delete_proxy_participant_by_guid (const struct nn_guid * guid, nn_wctime_t timestamp, int isimplicit); -uint64_t participant_instance_id (const struct nn_guid *guid); enum update_proxy_participant_source { UPD_PROXYPP_SPDP, @@ -629,8 +628,6 @@ void update_proxy_writer (struct proxy_writer *pwr, struct addrset *as, const st int new_proxy_group (const struct nn_guid *guid, const char *name, const struct dds_qos *xqos, nn_wctime_t timestamp); void delete_proxy_group (const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit); -uint64_t writer_instance_id (const struct nn_guid *guid); - /* 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(int rebuild); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 21eea71..1aa7ca0 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -3124,20 +3124,6 @@ dds_return_t delete_writer (const struct nn_guid *guid) return 0; } -uint64_t writer_instance_id (const struct nn_guid *guid) -{ - struct entity_common *e; - e = (struct entity_common*)ephash_lookup_writer_guid(guid); - if (e) { - return e->iid; - } - e = (struct entity_common*)ephash_lookup_proxy_writer_guid(guid); - if (e) { - return e->iid; - } - return 0; -} - /* READER ----------------------------------------------------------- */ #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS @@ -3464,20 +3450,6 @@ dds_return_t delete_reader (const struct nn_guid *guid) return 0; } -uint64_t reader_instance_id (const struct nn_guid *guid) -{ - struct entity_common *e; - e = (struct entity_common*)ephash_lookup_reader_guid(guid); - if (e) { - return e->iid; - } - e = (struct entity_common*)ephash_lookup_proxy_reader_guid(guid); - if (e) { - return e->iid; - } - return 0; -} - void update_reader_qos (struct reader *rd, const dds_qos_t *xqos) { ddsrt_mutex_lock (&rd->e.lock); @@ -3967,18 +3939,16 @@ int delete_proxy_participant_by_guid (const struct nn_guid * guid, nn_wctime_t t return 0; } -uint64_t participant_instance_id (const struct nn_guid *guid) +uint64_t get_entity_instance_id (const struct nn_guid *guid) { - struct entity_common *e; - e = (struct entity_common*)ephash_lookup_participant_guid(guid); - if (e) { - return e->iid; - } - e = (struct entity_common*)ephash_lookup_proxy_participant_guid(guid); - if (e) { - return e->iid; - } - return 0; + struct thread_state1 *ts1 = lookup_thread_state (); + struct entity_common *e; + uint64_t iid = 0; + thread_state_awake (ts1); + if ((e = ephash_lookup_guid_untyped (guid)) != NULL) + iid = e->iid; + thread_state_asleep (ts1); + return iid; } /* PROXY-GROUP --------------------------------------------------- */ diff --git a/src/core/ddsi/src/q_ephash.c b/src/core/ddsi/src/q_ephash.c index d02fcba..4401010 100644 --- a/src/core/ddsi/src/q_ephash.c +++ b/src/core/ddsi/src/q_ephash.c @@ -121,6 +121,7 @@ void *ephash_lookup_guid_untyped (const struct nn_guid *guid) /* FIXME: could (now) require guid to be first in entity_common; entity_common already is first in entity */ struct entity_common e; e.guid = *guid; + assert (thread_is_awake ()); return ddsrt_chh_lookup (gv.guid_hash->hash, &e); } diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index a7cb357..c1bd837 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -542,9 +542,9 @@ void xeventq_free (struct xeventq *evq) handle_nontimed_xevent (getnext_from_non_timed_xmit_list (evq), xp); } ddsrt_mutex_unlock (&evq->lock); - thread_state_asleep (lookup_thread_state ()); nn_xpack_send (xp, false); nn_xpack_free (xp); + thread_state_asleep (lookup_thread_state ()); } assert (ddsrt_avl_is_empty (&evq->msg_xevents)); From 4cdcff8be7d34ac5648a1c8ac4f7efff3d8d4496 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 21 Jun 2019 07:41:13 +0200 Subject: [PATCH 110/178] Combine {user,group,topic}_data set_qos tests Signed-off-by: Erik Boasson --- src/mpt/tests/qos/ppuserdata.c | 20 +- src/mpt/tests/qos/procs/ppud.c | 338 +++++---------------------------- src/mpt/tests/qos/procs/ppud.h | 20 +- 3 files changed, 63 insertions(+), 315 deletions(-) diff --git a/src/mpt/tests/qos/ppuserdata.c b/src/mpt/tests/qos/ppuserdata.c index 9e52042..0b319c7 100644 --- a/src/mpt/tests/qos/ppuserdata.c +++ b/src/mpt/tests/qos/ppuserdata.c @@ -27,8 +27,8 @@ MPT_Test(qos, ppuserdata, .init=ppud_init, .fini=ppud_fini); /* * Checks whether reader/writer user_data QoS changes work. */ -#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwuserdata", true, 10) -#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwuserdata", false, 0) +#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwuserdata", true, 10, RWUD_USERDATA) +#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwuserdata", false, 0, RWUD_USERDATA) MPT_TestProcess(qos, rwuserdata, a, rwud, TEST_A_ARGS); MPT_TestProcess(qos, rwuserdata, b, rwud, TEST_B_ARGS); MPT_Test(qos, rwuserdata, .init=ppud_init, .fini=ppud_fini); @@ -38,10 +38,10 @@ MPT_Test(qos, rwuserdata, .init=ppud_init, .fini=ppud_fini); /* * Checks whether topic_data QoS changes become visible in reader/writer. */ -#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwtopicdata", true, 10) -#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwtopicdata", false, 0) -MPT_TestProcess(qos, rwtopicdata, a, rwtd, TEST_A_ARGS); -MPT_TestProcess(qos, rwtopicdata, b, rwtd, TEST_B_ARGS); +#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwtopicdata", true, 10, RWUD_TOPICDATA) +#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwtopicdata", false, 0, RWUD_TOPICDATA) +MPT_TestProcess(qos, rwtopicdata, a, rwud, TEST_A_ARGS); +MPT_TestProcess(qos, rwtopicdata, b, rwud, TEST_B_ARGS); MPT_Test(qos, rwtopicdata, .init=ppud_init, .fini=ppud_fini); #undef TEST_A_ARGS #undef TEST_B_ARGS @@ -49,10 +49,10 @@ MPT_Test(qos, rwtopicdata, .init=ppud_init, .fini=ppud_fini); /* * Checks whether group_data QoS changes become visible in reader/writer. */ -#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwgroupdata", true, 10) -#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwgroupdata", false, 0) -MPT_TestProcess(qos, rwgroupdata, a, rwgd, TEST_A_ARGS); -MPT_TestProcess(qos, rwgroupdata, b, rwgd, TEST_B_ARGS); +#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwgroupdata", true, 10, RWUD_GROUPDATA) +#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwgroupdata", false, 0, RWUD_GROUPDATA) +MPT_TestProcess(qos, rwgroupdata, a, rwud, TEST_A_ARGS); +MPT_TestProcess(qos, rwgroupdata, b, rwud, TEST_B_ARGS); MPT_Test(qos, rwgroupdata, .init=ppud_init, .fini=ppud_fini); #undef TEST_A_ARGS #undef TEST_B_ARGS diff --git a/src/mpt/tests/qos/procs/ppud.c b/src/mpt/tests/qos/procs/ppud.c index e87386f..9978778 100644 --- a/src/mpt/tests/qos/procs/ppud.c +++ b/src/mpt/tests/qos/procs/ppud.c @@ -154,16 +154,21 @@ MPT_ProcessEntry (ppud, dds_delete_qos (qos); rc = dds_delete (dp); MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n"); - printf ("=== [Publisher(%d)] Done\n", id); + printf ("=== [Check(%d)] Done\n", id); } MPT_ProcessEntry (rwud, MPT_Args (dds_domainid_t domainid, const char *topic_name, bool active, - unsigned ncycles)) + unsigned ncycles, + enum rwud which)) { - dds_entity_t dp, tp, ep, rdep, ws; + bool (*qget) (const dds_qos_t * __restrict qos, void **value, size_t *sz) = 0; + void (*qset) (dds_qos_t * __restrict qos, const void *value, size_t sz) = 0; + const char *qname = "UNDEFINED"; + + dds_entity_t dp, tp, ep, rdep, qent = 0, ws; dds_return_t rc; dds_qos_t *qos; int id = (int) ddsrt_getpid (); @@ -197,6 +202,29 @@ MPT_ProcessEntry (rwud, rc = dds_waitset_attach (ws, rdep, 0); MPT_ASSERT_FATAL_EQ (rc, 0, "Could not attach built-in reader to waitset: %s\n", dds_strretcode (rc)); + switch (which) + { + case RWUD_USERDATA: + qget = dds_qget_userdata; + qset = dds_qset_userdata; + qname = "user data"; + qent = ep; + break; + case RWUD_GROUPDATA: + qget = dds_qget_groupdata; + qset = dds_qset_groupdata; + qname = "group data"; + qent = dds_get_parent (ep); + MPT_ASSERT_FATAL_GT (qent, 0, "Could not get pub/sub from wr/rd: %s\n", dds_strretcode (qent)); + break; + case RWUD_TOPICDATA: + qget = dds_qget_topicdata; + qset = dds_qset_topicdata; + qname = "topic data"; + qent = tp; + break; + } + bool done = false; bool first = true; unsigned exp_index = 0; @@ -220,12 +248,12 @@ MPT_ProcessEntry (rwud, { void *ud = NULL; size_t usz = 0; - if (!dds_qget_userdata (sample->qos, &ud, &usz)) - printf ("%d: user data not set in QoS\n", id); + if (!qget (sample->qos, &ud, &usz)) + printf ("%d: group data not set in QoS\n", id); if (first && usz == 0) { - dds_qset_userdata (qos, "X", 1); - rc = dds_set_qos (ep, qos); + qset (qos, "X", 1); + rc = dds_set_qos (qent, qos); MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); } else @@ -237,8 +265,8 @@ MPT_ProcessEntry (rwud, bool eq = (usz == expsz && (usz == 0 || memcmp (ud, exp, usz) == 0)); //printf ("%d: expected %u %zu/%s received %zu/%s\n", // id, exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)"); - MPT_ASSERT (eq, "User data mismatch: expected %u %zu/%s received %zu/%s\n", - exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)"); + MPT_ASSERT (eq, "%s mismatch: expected %u %zu/%s received %zu/%s\n", + qname, exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)"); if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0])) { exp_index = 0; @@ -253,17 +281,17 @@ MPT_ProcessEntry (rwud, size_t newusz; if (!active) { - /* Set user data to the same value in response */ + /* Set group data to the same value in response */ newud = ud; newusz = usz; - dds_qset_userdata (qos, ud, usz); + qset (qos, ud, usz); } else /* Set next agreed value */ { newud = exp_ud[exp_index]; newusz = strlen (exp_ud[exp_index]); - dds_qset_userdata (qos, newud, newusz); + qset (qos, newud, newusz); } - rc = dds_set_qos (ep, qos); + rc = dds_set_qos (qent, qos); MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); dds_qos_t *chk = dds_create_qos (); @@ -272,10 +300,10 @@ MPT_ProcessEntry (rwud, void *chkud = NULL; size_t chkusz = 0; - if (!dds_qget_userdata (chk, &chkud, &chkusz)) - MPT_ASSERT (0, "Check QoS: no user data present\n"); + if (!qget (chk, &chkud, &chkusz)) + MPT_ASSERT (0, "Check QoS: no %s present\n", qname); MPT_ASSERT (chkusz == newusz && (newusz == 0 || memcmp (chkud, newud, newusz) == 0), - "Retrieved user data differs from user data just set (%zu/%s vs %zu/%s)\n", + "Retrieved %s differs from group data just set (%zu/%s vs %zu/%s)\n", qname, chkusz, chkud ? (char *) chkud : "(null)", newusz, newud ? (char *) newud : "(null)"); dds_free (chkud); dds_delete_qos (chk); @@ -291,281 +319,5 @@ MPT_ProcessEntry (rwud, dds_delete_qos (qos); rc = dds_delete (dp); MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n"); - printf ("=== [Publisher(%d)] Done\n", id); -} - -MPT_ProcessEntry (rwtd, - MPT_Args (dds_domainid_t domainid, - const char *topic_name, - bool active, - unsigned ncycles)) -{ - dds_entity_t dp, tp, ep, rdep, ws; - dds_return_t rc; - dds_qos_t *qos; - int id = (int) ddsrt_getpid (); - - printf ("=== [Check(%d)] active=%d ncycles=%u Start(%d) ...\n", id, active, ncycles, (int) domainid); - - qos = dds_create_qos (); - dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0); - dp = dds_create_participant (domainid, NULL, NULL); - MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp)); - tp = dds_create_topic (dp, &RWData_Msg_desc, topic_name, qos, NULL); - MPT_ASSERT_FATAL_GT (tp, 0, "Could not create topic: %s\n", dds_strretcode (tp)); - if (active) - { - rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, qos, NULL); - MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSSubscription reader: %s\n", dds_strretcode (rdep)); - ep = dds_create_writer (dp, tp, qos, NULL); - MPT_ASSERT_FATAL_GT (ep, 0, "Could not create writer: %s\n", dds_strretcode (ep)); - } - else - { - rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, qos, NULL); - MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSPublication reader: %s\n", dds_strretcode (rdep)); - ep = dds_create_reader (dp, tp, qos, NULL); - MPT_ASSERT_FATAL_GT (ep, 0, "Could not create reader: %s\n", dds_strretcode (ep)); - } - rc = dds_set_status_mask (rdep, DDS_DATA_AVAILABLE_STATUS); - MPT_ASSERT_FATAL_EQ (rc, 0, "Could not set status mask: %s\n", dds_strretcode (rc)); - ws = dds_create_waitset (dp); - MPT_ASSERT_FATAL_GT (ws, 0, "Could not create waitset: %s\n", dds_strretcode (ws)); - rc = dds_waitset_attach (ws, rdep, 0); - MPT_ASSERT_FATAL_EQ (rc, 0, "Could not attach built-in reader to waitset: %s\n", dds_strretcode (rc)); - - bool done = false; - bool first = true; - unsigned exp_index = 0; - unsigned exp_cycle = 0; - while (!done) - { - rc = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY); - MPT_ASSERT_FATAL_GEQ (rc, 0, "Wait failed: %s\n", dds_strretcode (ws)); - - void *raw = NULL; - dds_sample_info_t si; - int32_t n; - while ((n = dds_take (rdep, &raw, &si, 1, 1)) == 1) - { - const dds_builtintopic_endpoint_t *sample = raw; - if (si.instance_state != DDS_IST_ALIVE) - done = true; - else if (!si.valid_data || strcmp (sample->topic_name, topic_name) != 0) - continue; - else - { - void *td = NULL; - size_t tsz = 0; - if (!dds_qget_topicdata (sample->qos, &td, &tsz)) - printf ("%d: topic data not set in QoS\n", id); - if (first && tsz == 0) - { - dds_qset_topicdata (qos, "X", 1); - rc = dds_set_qos (tp, qos); - MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); - } - else - { - const char *exp = exp_ud[exp_index]; - if (first && strcmp (td, "X") == 0) - exp = "X"; - const size_t expsz = first ? 1 : strlen (exp); - bool eq = (tsz == expsz && (tsz == 0 || memcmp (td, exp, tsz) == 0)); - //printf ("%d: expected %u %zu/%s received %zu/%s\n", - // id, exp_index, expsz, exp, tsz, td ? (char *) td : "(null)"); - MPT_ASSERT (eq, "Topic data mismatch: expected %u %zu/%s received %zu/%s\n", - exp_index, expsz, exp, tsz, td ? (char *) td : "(null)"); - if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0])) - { - exp_index = 0; - exp_cycle++; - } - - if (active && exp_cycle == ncycles) - done = true; - else - { - const void *newtd; - size_t newtsz; - if (!active) - { - /* Set topic data to the same value in response */ - newtd = td; newtsz = tsz; - dds_qset_topicdata (qos, td, tsz); - } - else /* Set next agreed value */ - { - newtd = exp_ud[exp_index]; newtsz = strlen (exp_ud[exp_index]); - dds_qset_topicdata (qos, newtd, newtsz); - } - - rc = dds_set_qos (tp, qos); - MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); - - dds_qos_t *chk = dds_create_qos (); - rc = dds_get_qos (ep, chk); - MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Get QoS failed: %s\n", dds_strretcode (rc)); - - void *chktd = NULL; - size_t chktsz = 0; - if (!dds_qget_topicdata (chk, &chktd, &chktsz)) - MPT_ASSERT (0, "Check QoS: no topic data present\n"); - MPT_ASSERT (chktsz == newtsz && (newtsz == 0 || memcmp (chktd, newtd, newtsz) == 0), - "Retrieved topic data differs from topic data just set (%zu/%s vs %zu/%s)\n", - chktsz, chktd ? (char *) chktd : "(null)", newtsz, newtd ? (char *) newtd : "(null)"); - dds_free (chktd); - dds_delete_qos (chk); - first = false; - } - } - dds_free (td); - } - } - MPT_ASSERT_FATAL_EQ (n, 0, "Read failed: %s\n", dds_strretcode (n)); - dds_return_loan (rdep, &raw, 1); - } - dds_delete_qos (qos); - rc = dds_delete (dp); - MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n"); - printf ("=== [Publisher(%d)] Done\n", id); -} - -MPT_ProcessEntry (rwgd, - MPT_Args (dds_domainid_t domainid, - const char *topic_name, - bool active, - unsigned ncycles)) -{ - dds_entity_t dp, tp, ep, rdep, grp, ws; - dds_return_t rc; - dds_qos_t *qos; - int id = (int) ddsrt_getpid (); - - printf ("=== [Check(%d)] active=%d ncycles=%u Start(%d) ...\n", id, active, ncycles, (int) domainid); - - qos = dds_create_qos (); - dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0); - dp = dds_create_participant (domainid, NULL, NULL); - MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp)); - tp = dds_create_topic (dp, &RWData_Msg_desc, topic_name, qos, NULL); - MPT_ASSERT_FATAL_GT (tp, 0, "Could not create topic: %s\n", dds_strretcode (tp)); - if (active) - { - rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, qos, NULL); - MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSSubscription reader: %s\n", dds_strretcode (rdep)); - ep = dds_create_writer (dp, tp, qos, NULL); - MPT_ASSERT_FATAL_GT (ep, 0, "Could not create writer: %s\n", dds_strretcode (ep)); - } - else - { - rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, qos, NULL); - MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSPublication reader: %s\n", dds_strretcode (rdep)); - ep = dds_create_reader (dp, tp, qos, NULL); - MPT_ASSERT_FATAL_GT (ep, 0, "Could not create reader: %s\n", dds_strretcode (ep)); - } - grp = dds_get_parent (ep); - MPT_ASSERT_FATAL_GT (grp, 0, "Could not get pub/sub from wr/rd: %s\n", dds_strretcode (grp)); - rc = dds_set_status_mask (rdep, DDS_DATA_AVAILABLE_STATUS); - MPT_ASSERT_FATAL_EQ (rc, 0, "Could not set status mask: %s\n", dds_strretcode (rc)); - ws = dds_create_waitset (dp); - MPT_ASSERT_FATAL_GT (ws, 0, "Could not create waitset: %s\n", dds_strretcode (ws)); - rc = dds_waitset_attach (ws, rdep, 0); - MPT_ASSERT_FATAL_EQ (rc, 0, "Could not attach built-in reader to waitset: %s\n", dds_strretcode (rc)); - - bool done = false; - bool first = true; - unsigned exp_index = 0; - unsigned exp_cycle = 0; - while (!done) - { - rc = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY); - MPT_ASSERT_FATAL_GEQ (rc, 0, "Wait failed: %s\n", dds_strretcode (ws)); - - void *raw = NULL; - dds_sample_info_t si; - int32_t n; - while ((n = dds_take (rdep, &raw, &si, 1, 1)) == 1) - { - const dds_builtintopic_endpoint_t *sample = raw; - if (si.instance_state != DDS_IST_ALIVE) - done = true; - else if (!si.valid_data || strcmp (sample->topic_name, topic_name) != 0) - continue; - else - { - void *gd = NULL; - size_t gsz = 0; - if (!dds_qget_groupdata (sample->qos, &gd, &gsz)) - printf ("%d: group data not set in QoS\n", id); - if (first && gsz == 0) - { - dds_qset_groupdata (qos, "X", 1); - rc = dds_set_qos (grp, qos); - MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); - } - else - { - const char *exp = exp_ud[exp_index]; - if (first && strcmp (gd, "X") == 0) - exp = "X"; - const size_t expsz = first ? 1 : strlen (exp); - bool eq = (gsz == expsz && (gsz == 0 || memcmp (gd, exp, gsz) == 0)); - //printf ("%d: expected %u %zu/%s received %zu/%s\n", - // id, exp_index, expsz, exp, gsz, gd ? (char *) gd : "(null)"); - MPT_ASSERT (eq, "Group data mismatch: expected %u %zu/%s received %zu/%s\n", - exp_index, expsz, exp, gsz, gd ? (char *) gd : "(null)"); - if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0])) - { - exp_index = 0; - exp_cycle++; - } - - if (active && exp_cycle == ncycles) - done = true; - else - { - const void *newgd; - size_t newgsz; - if (!active) - { - /* Set group data to the same value in response */ - newgd = gd; newgsz = gsz; - dds_qset_groupdata (qos, gd, gsz); - } - else /* Set next agreed value */ - { - newgd = exp_ud[exp_index]; newgsz = strlen (exp_ud[exp_index]); - dds_qset_groupdata (qos, newgd, newgsz); - } - - rc = dds_set_qos (grp, qos); - MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc)); - - dds_qos_t *chk = dds_create_qos (); - rc = dds_get_qos (ep, chk); - MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Get QoS failed: %s\n", dds_strretcode (rc)); - - void *chkgd = NULL; - size_t chkgsz = 0; - if (!dds_qget_groupdata (chk, &chkgd, &chkgsz)) - MPT_ASSERT (0, "Check QoS: no group data present\n"); - MPT_ASSERT (chkgsz == newgsz && (newgsz == 0 || memcmp (chkgd, newgd, newgsz) == 0), - "Retrieved group data differs from group data just set (%zu/%s vs %zu/%s)\n", - chkgsz, chkgd ? (char *) chkgd : "(null)", newgsz, newgd ? (char *) newgd : "(null)"); - dds_free (chkgd); - dds_delete_qos (chk); - first = false; - } - } - dds_free (gd); - } - } - MPT_ASSERT_FATAL_EQ (n, 0, "Read failed: %s\n", dds_strretcode (n)); - dds_return_loan (rdep, &raw, 1); - } - dds_delete_qos (qos); - rc = dds_delete (dp); - MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n"); - printf ("=== [Publisher(%d)] Done\n", id); + printf ("=== [Check(%d)] Done\n", id); } diff --git a/src/mpt/tests/qos/procs/ppud.h b/src/mpt/tests/qos/procs/ppud.h index c017aaa..f94ca48 100644 --- a/src/mpt/tests/qos/procs/ppud.h +++ b/src/mpt/tests/qos/procs/ppud.h @@ -26,6 +26,12 @@ extern "C" { void ppud_init (void); void ppud_fini (void); +enum rwud { + RWUD_USERDATA, + RWUD_GROUPDATA, + RWUD_TOPICDATA +}; + MPT_ProcessEntry (ppud, MPT_Args (dds_domainid_t domainid, bool active, @@ -35,19 +41,9 @@ MPT_ProcessEntry (rwud, MPT_Args (dds_domainid_t domainid, const char *topic_name, bool active, - unsigned ncycles)); + unsigned ncycles, + enum rwud which)); -MPT_ProcessEntry (rwtd, - MPT_Args (dds_domainid_t domainid, - const char *topic_name, - bool active, - unsigned ncycles)); - -MPT_ProcessEntry (rwgd, - MPT_Args (dds_domainid_t domainid, - const char *topic_name, - bool active, - unsigned ncycles)); #if defined (__cplusplus) } #endif From f61b2d54dad9eea9c67fbc1333bf03d6cfc7b4d0 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 21 Jun 2019 07:44:43 +0200 Subject: [PATCH 111/178] Add some atomic operations returning old value * ddsrt_atomic_inc32_ov * ddsrt_atomic_add32_ov * ddsrt_atomic_sub32_ov Signed-off-by: Erik Boasson --- src/ddsrt/include/dds/ddsrt/atomics/arm.h | 9 +++++++++ src/ddsrt/include/dds/ddsrt/atomics/gcc.h | 9 +++++++++ src/ddsrt/include/dds/ddsrt/atomics/msvc.h | 12 ++++++++++++ src/ddsrt/include/dds/ddsrt/atomics/sun.h | 11 +++++++++++ src/ddsrt/src/atomics.c | 3 +++ 5 files changed, 44 insertions(+) diff --git a/src/ddsrt/include/dds/ddsrt/atomics/arm.h b/src/ddsrt/include/dds/ddsrt/atomics/arm.h index 863e483..fd43723 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/arm.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/arm.h @@ -85,6 +85,9 @@ inline void *ddsrt_atomic_addvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff inline void ddsrt_atomic_add32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { (void) ddsrt_atomic_add32_nv (x, v); } +inline uint32_t ddsrt_atomic_add32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { + return ddsrt_atomic_add32_nv (x, v) - v; +} inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) { (void) ddsrt_atomic_addptr_nv (x, v); } @@ -115,6 +118,9 @@ inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v /* INC */ +inline uint32_t ddsrt_atomic_inc32_ov (volatile ddsrt_atomic_uint32_t *x) { + return ddsrt_atomic_add32_nv (x, 1) - 1; +} inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) { return ddsrt_atomic_add32_nv (x, 1); } @@ -130,6 +136,9 @@ inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) { /* DEC */ +inline uint32_t ddsrt_atomic_dec32_ov (volatile ddsrt_atomic_uint32_t *x) { + return ddsrt_atomic_sub32_nv (x, 1) + 1; +} inline uint32_t ddsrt_atomic_dec32_nv (volatile ddsrt_atomic_uint32_t *x) { return ddsrt_atomic_sub32_nv (x, 1); } diff --git a/src/ddsrt/include/dds/ddsrt/atomics/gcc.h b/src/ddsrt/include/dds/ddsrt/atomics/gcc.h index 59e05a7..a005da2 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/gcc.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/gcc.h @@ -85,6 +85,9 @@ inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) { inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) { __sync_fetch_and_add (&x->v, 1); } +inline uint32_t ddsrt_atomic_inc32_ov (volatile ddsrt_atomic_uint32_t *x) { + return __sync_fetch_and_add (&x->v, 1); +} inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) { return __sync_add_and_fetch (&x->v, 1); } @@ -149,6 +152,9 @@ inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v inline void ddsrt_atomic_addvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) { ddsrt_atomic_addptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v); } +inline uint32_t ddsrt_atomic_add32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { + return __sync_fetch_and_add (&x->v, v); +} inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { return __sync_add_and_fetch (&x->v, v); } @@ -180,6 +186,9 @@ inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) { ddsrt_atomic_subptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v); } +inline uint32_t ddsrt_atomic_sub32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { + return __sync_fetch_and_sub (&x->v, v); +} inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { return __sync_sub_and_fetch (&x->v, v); } diff --git a/src/ddsrt/include/dds/ddsrt/atomics/msvc.h b/src/ddsrt/include/dds/ddsrt/atomics/msvc.h index f7f2218..c30f5f0 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/msvc.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/msvc.h @@ -74,6 +74,9 @@ inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) { inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) { DDSRT_ATOMIC_PTROP (InterlockedIncrement) (&x->v); } +inline uint32_t ddsrt_atomic_inc32_ov (volatile ddsrt_atomic_uint32_t *x) { + return InterlockedIncrement (&x->v) - 1; +} inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) { return InterlockedIncrement (&x->v); } @@ -138,6 +141,9 @@ inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v inline void ddsrt_atomic_addvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) { ddsrt_atomic_addptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v); } +inline uint32_t ddsrt_atomic_add32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { + return InterlockedExchangeAdd (&x->v, v); +} inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { return InterlockedExchangeAdd (&x->v, v) + v; } @@ -178,6 +184,12 @@ inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) { ddsrt_atomic_subptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v); } +inline uint32_t ddsrt_atomic_sub32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { + /* disable unary minus applied to unsigned type, result still unsigned */ + DDSRT_WARNING_MSVC_OFF(4146) + return InterlockedExchangeAdd (&x->v, -v); + DDSRT_WARNING_MSVC_ON(4146) +} inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { /* disable unary minus applied to unsigned type, result still unsigned */ DDSRT_WARNING_MSVC_OFF(4146) diff --git a/src/ddsrt/include/dds/ddsrt/atomics/sun.h b/src/ddsrt/include/dds/ddsrt/atomics/sun.h index 74a7469..f9f1434 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/sun.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/sun.h @@ -40,6 +40,11 @@ inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) { inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) { atomic_inc_ulong (&x->v); } +inline uint32_t ddsrt_atomic_inc32_ov (volatile ddsrt_atomic_uint32_t *x) { + uint32_t oldval, newval; + do { oldval = x->v; newval = oldval + 1; } while (atomic_cas_32 (&x->v, oldval, newval) != oldval); + return oldval; +} inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) { return atomic_inc_32_nv (&x->v); } @@ -100,6 +105,9 @@ inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v inline void ddsrt_atomic_addvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) { atomic_add_ptr (&x->v, v); } +inline uint32_t ddsrt_atomic_add32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { + return atomic_add_32_nv (&x->v, v) - v; +} inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { return atomic_add_32_nv (&x->v, v); } @@ -127,6 +135,9 @@ inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) { atomic_add_ptr (&x->v, -v); } +inline uint32_t ddsrt_atomic_sub32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { + return atomic_add_32_nv (&x->v, -v) + v; +} inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { return atomic_add_32_nv (&x->v, -v); } diff --git a/src/ddsrt/src/atomics.c b/src/ddsrt/src/atomics.c index 5919a40..a23113c 100644 --- a/src/ddsrt/src/atomics.c +++ b/src/ddsrt/src/atomics.c @@ -30,6 +30,7 @@ extern inline void ddsrt_atomic_inc32 (volatile ddsrt_atomic_uint32_t *x); extern inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x); #endif extern inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x); +extern inline uint32_t ddsrt_atomic_inc32_ov (volatile ddsrt_atomic_uint32_t *x); extern inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x); #if DDSRT_HAVE_ATOMIC64 extern inline uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x); @@ -58,6 +59,7 @@ extern inline void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64 #endif extern inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v); extern inline void ddsrt_atomic_addvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v); +extern inline uint32_t ddsrt_atomic_add32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v); extern inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v); #if DDSRT_HAVE_ATOMIC64 extern inline uint64_t ddsrt_atomic_add64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v); @@ -71,6 +73,7 @@ extern inline void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64 #endif extern inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v); extern inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v); +extern inline uint32_t ddsrt_atomic_sub32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v); extern inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v); #if DDSRT_HAVE_ATOMIC64 extern inline uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v); From 647f7466d658dd046f4d953f81fd13f043758362 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 21 Jun 2019 07:13:57 +0200 Subject: [PATCH 112/178] Address locking order for entity locks There were inconsistencies in the order in which entity locks were taken when multiple entities needed to be locked at the same time. In most cases, the order was first locking entity X, then locking the parent entity of X. However, in some cases the order was reversed, a likely cause of deadlocks. This commit sorts these problems, and in particular propagating operations into children. The entity refcount is now part of the handle administration so that it is no longer necessary to lock an entity to determine whether it is still allowed to be used (previously it had to check the CLOSED flag afterward). This allows recursing into the children while holding handles and the underlying objects alive, but without violating lock order. Attendant changes that would warrant there own commits but are too hard to split off: * Children are now no longer in a singly linked list, but in an AVL tree; this was necessary at some intermediate stage to allow unlocking an entity and restarting iteration over all children at the "next" child (all thanks to the eternally unique instance handle); * Waitsets shifted to using arrays of attached entities instead of linked lists; this was a consequence of dealing with some locking issues in reading triggers and considering which operations on the "triggered" and "observed" sets are actually needed. * Entity status flags and waitset/condition trigger counts are now handled using atomic operations. Entities are now classified as having a "status" with a corresponding mask, or as having a "trigger count" (conditions). As there are fewer than 16 status bits, the status and its mask can squeeze into the same 32-bits as the trigger count. These atomic updates avoid the need for a separate lock just for the trigger/status values and results in a significant speedup with waitsets. * Create topic now has a more rational behaviour when multiple participants attempt to create the same topic: each participant now gets its own topic definition, but the underlying type representation is shared. Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/dds.h | 6 +- .../ddsc/include/dds/ddsc/dds_public_impl.h | 25 +- src/core/ddsc/src/dds__entity.h | 47 +- src/core/ddsc/src/dds__get_status.h | 2 +- src/core/ddsc/src/dds__handles.h | 9 +- src/core/ddsc/src/dds__types.h | 193 ++--- src/core/ddsc/src/dds_entity.c | 716 ++++++++++-------- src/core/ddsc/src/dds_guardcond.c | 23 +- src/core/ddsc/src/dds_handles.c | 56 +- src/core/ddsc/src/dds_instance.c | 74 +- src/core/ddsc/src/dds_participant.c | 13 +- src/core/ddsc/src/dds_publisher.c | 10 +- src/core/ddsc/src/dds_querycond.c | 9 +- src/core/ddsc/src/dds_read.c | 18 +- src/core/ddsc/src/dds_readcond.c | 19 +- src/core/ddsc/src/dds_reader.c | 46 +- src/core/ddsc/src/dds_rhc.c | 163 ++-- src/core/ddsc/src/dds_sertopic_builtintopic.c | 2 - src/core/ddsc/src/dds_subscriber.c | 22 +- src/core/ddsc/src/dds_topic.c | 374 ++++++--- src/core/ddsc/src/dds_waitset.c | 326 ++++---- src/core/ddsc/src/dds_writer.c | 33 +- src/core/ddsc/tests/instance_get_key.c | 2 +- .../ddsi/include/dds/ddsi/ddsi_sertopic.h | 4 - src/core/ddsi/src/q_entity.c | 35 +- src/core/xtests/rhc_torture/rhc_torture.c | 1 + 26 files changed, 1224 insertions(+), 1004 deletions(-) diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index 4e3233f..a1649c6 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -79,7 +79,6 @@ DDS_EXPORT dds_domainid_t dds_domain_default (void); /** @name Communication Status definitions @{**/ -/** Another topic exists with the same name but with different characteristics. */ typedef enum dds_status_id { DDS_INCONSISTENT_TOPIC_STATUS_ID, DDS_OFFERED_DEADLINE_MISSED_STATUS_ID, @@ -94,8 +93,9 @@ typedef enum dds_status_id { DDS_LIVELINESS_CHANGED_STATUS_ID, DDS_PUBLICATION_MATCHED_STATUS_ID, DDS_SUBSCRIPTION_MATCHED_STATUS_ID -} -dds_status_id_t; +} dds_status_id_t; + +/** Another topic exists with the same name but with different characteristics. */ #define DDS_INCONSISTENT_TOPIC_STATUS (1u << DDS_INCONSISTENT_TOPIC_STATUS_ID) /** The deadline that the writer has committed through its deadline QoS policy was not respected for a specific instance. */ #define DDS_OFFERED_DEADLINE_MISSED_STATUS (1u << DDS_OFFERED_DEADLINE_MISSED_STATUS_ID) 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 58df3f2..96d1bb3 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_impl.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_impl.h @@ -98,19 +98,18 @@ dds_topic_descriptor_t; typedef enum dds_entity_kind { - DDS_KIND_DONTCARE = 0x00000000, - DDS_KIND_TOPIC = 0x01000000, - DDS_KIND_PARTICIPANT = 0x02000000, - DDS_KIND_READER = 0x03000000, - DDS_KIND_WRITER = 0x04000000, - DDS_KIND_SUBSCRIBER = 0x05000000, - DDS_KIND_PUBLISHER = 0x06000000, - DDS_KIND_COND_READ = 0x07000000, - DDS_KIND_COND_QUERY = 0x08000000, - DDS_KIND_COND_GUARD = 0x09000000, - DDS_KIND_WAITSET = 0x0A000000 -} -dds_entity_kind_t; + DDS_KIND_DONTCARE, + DDS_KIND_TOPIC, + DDS_KIND_PARTICIPANT, + DDS_KIND_READER, + DDS_KIND_WRITER, + DDS_KIND_SUBSCRIBER, + DDS_KIND_PUBLISHER, + DDS_KIND_COND_READ, + DDS_KIND_COND_QUERY, + DDS_KIND_COND_GUARD, + DDS_KIND_WAITSET +} dds_entity_kind_t; /* 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 f74b03e..8541729 100644 --- a/src/core/ddsc/src/dds__entity.h +++ b/src/core/ddsc/src/dds__entity.h @@ -26,20 +26,22 @@ dds_entity_init( dds_entity_kind_t kind, dds_qos_t * qos, const dds_listener_t *listener, - uint32_t mask); + status_mask_t mask); DDS_EXPORT void -dds_entity_add_ref(dds_entity *e); +dds_entity_register_child ( + dds_entity *parent, + dds_entity *child); DDS_EXPORT void -dds_entity_add_ref_nolock(dds_entity *e); +dds_entity_add_ref_locked(dds_entity *e); #define DEFINE_ENTITY_LOCK_UNLOCK(qualifier_, type_, kind_) \ qualifier_ dds_return_t type_##_lock (dds_entity_t hdl, type_ **x) \ { \ dds_return_t rc; \ dds_entity *e; \ - if ((rc = dds_entity_lock (hdl, kind_, &e)) != DDS_RETCODE_OK) \ + if ((rc = dds_entity_lock (hdl, kind_, &e)) < 0) \ return rc; \ *x = (type_ *) e; \ return DDS_RETCODE_OK; \ @@ -61,30 +63,27 @@ DDS_EXPORT inline bool dds_entity_is_enabled (const dds_entity *e) { return (e->m_flags & DDS_ENTITY_ENABLED) != 0; } -DDS_EXPORT void dds_entity_status_set (dds_entity *e, uint32_t t); +DDS_EXPORT void dds_entity_status_set (dds_entity *e, status_mask_t t); +DDS_EXPORT void dds_entity_trigger_set (dds_entity *e, uint32_t t); -DDS_EXPORT inline void dds_entity_status_reset (dds_entity *e, uint32_t t) { - e->m_trigger &= ~t; -} - -DDS_EXPORT inline bool dds_entity_status_match (const dds_entity *e, uint32_t t) { - return (e->m_trigger & t) != 0; +DDS_EXPORT inline void dds_entity_status_reset (dds_entity *e, status_mask_t t) { + ddsrt_atomic_and32 (&e->m_status.m_status_and_mask, SAM_ENABLED_MASK | (status_mask_t) ~t); } DDS_EXPORT inline dds_entity_kind_t dds_entity_kind (const dds_entity *e) { return e->m_kind; } -DDS_EXPORT void dds_entity_status_signal (dds_entity *e); +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_return_t -dds_entity_claim ( +dds_entity_pin ( dds_entity_t hdl, dds_entity **eptr); -DDS_EXPORT void dds_entity_release ( +DDS_EXPORT void dds_entity_unpin ( dds_entity *e); DDS_EXPORT dds_return_t @@ -96,27 +95,17 @@ dds_entity_lock( DDS_EXPORT void dds_entity_unlock(dds_entity *e); -DDS_EXPORT dds_return_t -dds_entity_observer_register_nl( - dds_entity *observed, - dds_entity_t observer, - dds_entity_callback cb); - DDS_EXPORT dds_return_t dds_entity_observer_register( - dds_entity_t observed, - dds_entity_t observer, - dds_entity_callback cb); - -DDS_EXPORT dds_return_t -dds_entity_observer_unregister_nl( dds_entity *observed, - dds_entity_t observer); + dds_entity *observer, + dds_entity_callback cb, + dds_entity_delete_callback delete_cb); DDS_EXPORT dds_return_t dds_entity_observer_unregister( - dds_entity_t observed, - dds_entity_t observer); + dds_entity *observed, + dds_entity *observer); DDS_EXPORT dds_return_t dds_delete_impl( diff --git a/src/core/ddsc/src/dds__get_status.h b/src/core/ddsc/src/dds__get_status.h index 881b7d1..3dec7dc 100644 --- a/src/core/ddsc/src/dds__get_status.h +++ b/src/core/ddsc/src/dds__get_status.h @@ -29,7 +29,7 @@ { \ if (status) \ *status = ent->m_##status_##_status; \ - if (ent->m_entity.m_status_enable & DDS_##STATUS_##_STATUS) { \ + if (ddsrt_atomic_ld32 (&ent->m_entity.m_status.m_status_and_mask) & (DDS_##STATUS_##_STATUS << SAM_ENABLED_SHIFT)) { \ do { DDS_GET_STATUS_LOCKED_RESET_N (DDSRT_COUNT_ARGS (__VA_ARGS__), status_, __VA_ARGS__) } while (0); \ dds_entity_status_reset (&ent->m_entity, DDS_##STATUS_##_STATUS); \ } \ diff --git a/src/core/ddsc/src/dds__handles.h b/src/core/ddsc/src/dds__handles.h index c13bc59..70321d3 100644 --- a/src/core/ddsc/src/dds__handles.h +++ b/src/core/ddsc/src/dds__handles.h @@ -145,13 +145,13 @@ dds_handle_delete( * Returns OK when succeeded. */ DDS_EXPORT int32_t -dds_handle_claim( +dds_handle_pin( dds_handle_t hdl, struct dds_handle_link **entity); DDS_EXPORT void -dds_handle_claim_inc( +dds_handle_repin( struct dds_handle_link *link); @@ -159,7 +159,7 @@ dds_handle_claim_inc( * The active claims count is decreased. */ DDS_EXPORT void -dds_handle_release( +dds_handle_unpin( struct dds_handle_link *link); @@ -177,6 +177,9 @@ dds_handle_is_closed( struct dds_handle_link *link); +DDS_EXPORT void dds_handle_add_ref (struct dds_handle_link *link); +DDS_EXPORT bool dds_handle_drop_ref (struct dds_handle_link *link); + #if defined (__cplusplus) } #endif diff --git a/src/core/ddsc/src/dds__types.h b/src/core/ddsc/src/dds__types.h index ea54811..3d30790 100644 --- a/src/core/ddsc/src/dds__types.h +++ b/src/core/ddsc/src/dds__types.h @@ -39,12 +39,11 @@ struct dds_statuscond; struct ddsi_sertopic; struct rhc; -/* Internal entity status flags */ - -#define DDS_INTERNAL_STATUS_MASK (0xFF000000u) - -#define DDS_WAITSET_TRIGGER_STATUS (0x01000000u) -#define DDS_DELETING_STATUS (0x02000000u) +typedef uint16_t status_mask_t; +typedef ddsrt_atomic_uint32_t status_and_enabled_t; +#define SAM_STATUS_MASK 0xffffu +#define SAM_ENABLED_MASK 0xffff0000u +#define SAM_ENABLED_SHIFT 16 /* This can be used when polling for various states. * Obviously, it is encouraged to use condition variables and such. But @@ -92,14 +91,12 @@ struct dds_listener { #define DDS_ENTITY_ENABLED 0x0001u #define DDS_ENTITY_IMPLICIT 0x0002u -typedef struct dds_domain -{ +typedef struct dds_domain { ddsrt_avl_node_t m_node; dds_domainid_t m_id; ddsrt_avl_tree_t m_topics; uint32_t m_refc; -} -dds_domain; +} dds_domain; struct dds_entity; typedef struct dds_entity_deriver { @@ -111,28 +108,28 @@ typedef struct dds_entity_deriver { dds_return_t (*validate_status)(uint32_t mask); } dds_entity_deriver; -typedef void (*dds_entity_callback)(dds_entity_t observer, dds_entity_t observed, uint32_t status); +typedef void (*dds_entity_callback)(struct dds_entity *observer, dds_entity_t observed, uint32_t status); +typedef void (*dds_entity_delete_callback)(struct dds_entity *observer, dds_entity_t observed); typedef struct dds_entity_observer { dds_entity_callback m_cb; - dds_entity_t m_observer; + dds_entity_delete_callback m_delete_cb; + struct dds_entity *m_observer; struct dds_entity_observer *m_next; } dds_entity_observer; typedef struct dds_entity { struct dds_handle_link m_hdllink; /* handle is constant, cnt_flags private to dds_handle.c */ dds_entity_kind_t m_kind; /* constant */ - dds_entity_deriver m_deriver; /* constant; FIXME: no point in having function pointers embedded */ - uint32_t m_refc; /* [m_mutex] */ struct dds_entity *m_next; /* [m_mutex] */ struct dds_entity *m_parent; /* constant */ - struct dds_entity *m_children; /* [m_mutex] */ + ddsrt_avl_node_t m_avlnode_child; /* [m_mutex of m_parent] */ + ddsrt_avl_tree_t m_children; /* [m_mutex] tree on m_iid using m_avlnode_child */ struct dds_entity *m_participant; /* constant */ struct dds_domain *m_domain; /* constant */ dds_qos_t *m_qos; /* [m_mutex] */ - dds_domainid_t m_domainid; /* constant; FIXME: why? hardly ever used, m_domain should give that info, too */ - nn_guid_t m_guid; /* ~ constant: FIXME: set during creation, but possibly after becoming visible */ - dds_instance_handle_t m_iid; /* ~ constant: FIXME: like GUID */ + nn_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] */ /* Allowed: @@ -145,47 +142,78 @@ typedef struct dds_entity { ddsrt_mutex_t m_mutex; ddsrt_cond_t m_cond; - ddsrt_mutex_t m_observers_lock; + union { + status_and_enabled_t m_status_and_mask; /* for most entities */ + ddsrt_atomic_uint32_t m_trigger; /* for conditions & waitsets */ + } m_status; + + ddsrt_mutex_t m_observers_lock; /* locking parent->...->m_observers_lock while holding it is allowed */ ddsrt_cond_t m_observers_cond; - dds_listener_t m_listener; - uint32_t m_trigger; - uint32_t m_status_enable; - uint32_t m_cb_count; - dds_entity_observer *m_observers; -} -dds_entity; + dds_listener_t m_listener; /* [m_observers_lock] */ + uint32_t m_cb_count; /* [m_observers_lock] */ + dds_entity_observer *m_observers; /* [m_observers_lock] */ +} dds_entity; extern const ddsrt_avl_treedef_t dds_topictree_def; +extern const ddsrt_avl_treedef_t dds_entity_children_td; -typedef struct dds_subscriber -{ - struct dds_entity m_entity; +extern const struct dds_entity_deriver dds_entity_deriver_topic; +extern const struct dds_entity_deriver dds_entity_deriver_participant; +extern const struct dds_entity_deriver dds_entity_deriver_reader; +extern const struct dds_entity_deriver dds_entity_deriver_writer; +extern const struct dds_entity_deriver dds_entity_deriver_subscriber; +extern const struct dds_entity_deriver dds_entity_deriver_publisher; +extern const struct dds_entity_deriver dds_entity_deriver_readcondition; +extern const struct dds_entity_deriver dds_entity_deriver_guardcondition; +extern const struct dds_entity_deriver dds_entity_deriver_waitset; +extern const struct dds_entity_deriver *dds_entity_deriver_table[]; + +dds_return_t dds_entity_deriver_dummy_close (struct dds_entity *e); +dds_return_t dds_entity_deriver_dummy_delete (struct dds_entity *e); +dds_return_t dds_entity_deriver_dummy_set_qos (struct dds_entity *e, const dds_qos_t *qos, bool enabled); +dds_return_t dds_entity_deriver_dummy_validate_status (uint32_t mask); + +inline dds_return_t dds_entity_deriver_close (struct dds_entity *e) { + return dds_entity_deriver_table[e->m_kind]->close (e); } -dds_subscriber; - -typedef struct dds_publisher -{ - struct dds_entity m_entity; +inline dds_return_t dds_entity_deriver_delete (struct dds_entity *e) { + return dds_entity_deriver_table[e->m_kind]->delete (e); +} +inline dds_return_t dds_entity_deriver_set_qos (struct dds_entity *e, const dds_qos_t *qos, bool enabled) { + return dds_entity_deriver_table[e->m_kind]->set_qos (e, qos, enabled); +} +inline dds_return_t dds_entity_deriver_validate_status (struct dds_entity *e, uint32_t mask) { + return dds_entity_deriver_table[e->m_kind]->validate_status (mask); +} +inline bool dds_entity_supports_set_qos (struct dds_entity *e) { + return dds_entity_deriver_table[e->m_kind]->set_qos != dds_entity_deriver_dummy_set_qos; +} +inline bool dds_entity_supports_validate_status (struct dds_entity *e) { + return dds_entity_deriver_table[e->m_kind]->validate_status != dds_entity_deriver_dummy_validate_status; } -dds_publisher; -typedef struct dds_participant -{ +typedef struct dds_subscriber { + struct dds_entity m_entity; +} dds_subscriber; + +typedef struct dds_publisher { + struct dds_entity m_entity; +} dds_publisher; + +typedef struct dds_participant { struct dds_entity m_entity; struct dds_entity * m_dur_reader; struct dds_entity * m_dur_writer; dds_entity_t m_builtin_subscriber; -} -dds_participant; +} dds_participant; -typedef struct dds_reader -{ +typedef struct dds_reader { struct dds_entity m_entity; - const struct dds_topic * m_topic; - struct reader * m_rd; + const struct dds_topic *m_topic; + struct reader *m_rd; bool m_data_on_readers; bool m_loan_out; - void * m_loan; + void *m_loan; uint32_t m_loan_size; /* Status metrics */ @@ -196,15 +224,13 @@ typedef struct dds_reader dds_requested_incompatible_qos_status_t m_requested_incompatible_qos_status; dds_sample_lost_status_t m_sample_lost_status; dds_subscription_matched_status_t m_subscription_matched_status; -} -dds_reader; +} dds_reader; -typedef struct dds_writer -{ +typedef struct dds_writer { struct dds_entity m_entity; - const struct dds_topic * m_topic; - struct nn_xpack * m_xp; - struct writer * m_wr; + const struct dds_topic *m_topic; + struct nn_xpack *m_xp; + struct writer *m_wr; struct whc *m_whc; /* FIXME: ownership still with underlying DDSI writer (cos of DDSI built-in writers )*/ /* Status metrics */ @@ -213,74 +239,62 @@ typedef struct dds_writer dds_offered_deadline_missed_status_t m_offered_deadline_missed_status; dds_offered_incompatible_qos_status_t m_offered_incompatible_qos_status; dds_publication_matched_status_t m_publication_matched_status; -} -dds_writer; +} dds_writer; #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 -typedef struct dds_topic -{ +typedef struct dds_topic { struct dds_entity m_entity; - struct ddsi_sertopic * m_stopic; + struct ddsi_sertopic *m_stopic; dds_topic_intern_filter_fn filter_fn; - void * filter_ctx; + void *filter_ctx; /* Status metrics */ dds_inconsistent_topic_status_t m_inconsistent_topic_status; -} -dds_topic; +} dds_topic; typedef uint32_t dds_querycond_mask_t; -typedef struct dds_readcond -{ +typedef struct dds_readcond { dds_entity m_entity; - struct rhc * m_rhc; + struct rhc *m_rhc; uint32_t m_qminv; uint32_t m_sample_states; uint32_t m_view_states; uint32_t m_instance_states; nn_guid_t m_rd_guid; - struct dds_readcond * m_next; - struct - { - dds_querycondition_filter_fn m_filter; - dds_querycond_mask_t m_qcmask; /* condition mask in RHC*/ + struct dds_readcond *m_next; + struct { + dds_querycondition_filter_fn m_filter; + dds_querycond_mask_t m_qcmask; /* condition mask in RHC*/ } m_query; -} -dds_readcond; +} dds_readcond; -typedef struct dds_guardcond -{ +typedef struct dds_guardcond { dds_entity m_entity; -} -dds_guardcond; +} dds_guardcond; -typedef struct dds_attachment -{ - dds_entity *entity; - dds_attach_t arg; - struct dds_attachment* next; -} -dds_attachment; +typedef struct dds_attachment { + dds_entity *entity; + dds_entity_t handle; + dds_attach_t arg; +} dds_attachment; -typedef struct dds_waitset -{ +typedef struct dds_waitset { dds_entity m_entity; - dds_attachment *observed; - dds_attachment *triggered; -} -dds_waitset; + size_t nentities; /* [m_entity.m_mutex] */ + size_t ntriggered; /* [m_entity.m_mutex] */ + dds_attachment *entities; /* [m_entity.m_mutex] 0 .. ntriggered are triggred, ntriggred .. nentities are not */ +} dds_waitset; /* Globals */ -typedef struct dds_globals -{ +typedef struct dds_globals { dds_domainid_t m_default_domain; int32_t m_init_count; void (*m_dur_reader) (struct dds_reader * reader, struct rhc * rhc); @@ -289,8 +303,7 @@ typedef struct dds_globals void (*m_dur_fini) (void); ddsrt_avl_tree_t m_domains; ddsrt_mutex_t m_mutex; -} -dds_globals; +} dds_globals; DDS_EXPORT extern dds_globals dds_global; diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index 2fc5f25..9b6ca2c 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -26,23 +26,58 @@ extern inline dds_entity *dds_entity_from_handle_link (struct dds_handle_link *hdllink); extern inline bool dds_entity_is_enabled (const dds_entity *e); -extern inline void dds_entity_status_reset (dds_entity *e, uint32_t t); -extern inline bool dds_entity_status_match (const dds_entity *e, uint32_t t); +extern inline void dds_entity_status_reset (dds_entity *e, status_mask_t t); extern inline dds_entity_kind_t dds_entity_kind (const dds_entity *e); -static void dds_entity_observers_signal (dds_entity *observed, uint32_t status); -static void dds_entity_observers_delete (dds_entity *observed); +const struct dds_entity_deriver *dds_entity_deriver_table[] = { + [DDS_KIND_TOPIC] = &dds_entity_deriver_topic, + [DDS_KIND_PARTICIPANT] = &dds_entity_deriver_participant, + [DDS_KIND_READER] = &dds_entity_deriver_reader, + [DDS_KIND_WRITER] = &dds_entity_deriver_writer, + [DDS_KIND_SUBSCRIBER] = &dds_entity_deriver_subscriber, + [DDS_KIND_PUBLISHER] = &dds_entity_deriver_publisher, + [DDS_KIND_COND_READ] = &dds_entity_deriver_readcondition, + [DDS_KIND_COND_QUERY] = &dds_entity_deriver_readcondition, + [DDS_KIND_COND_GUARD] = &dds_entity_deriver_guardcondition, + [DDS_KIND_WAITSET] = &dds_entity_deriver_waitset, +}; -void dds_entity_add_ref_nolock (dds_entity *e) -{ - e->m_refc++; +dds_return_t dds_entity_deriver_dummy_close (struct dds_entity *e) { + (void) e; return DDS_RETCODE_OK; +} +dds_return_t dds_entity_deriver_dummy_delete (struct dds_entity *e) { + (void) e; return DDS_RETCODE_OK; +} +dds_return_t dds_entity_deriver_dummy_set_qos (struct dds_entity *e, const dds_qos_t *qos, bool enabled) { + (void) e; (void) qos; (void) enabled; return DDS_RETCODE_ILLEGAL_OPERATION; +} +dds_return_t dds_entity_deriver_dummy_validate_status (uint32_t mask) { + (void) mask; return DDS_RETCODE_ILLEGAL_OPERATION; } -void dds_entity_add_ref (dds_entity *e) +extern inline dds_return_t dds_entity_deriver_close (struct dds_entity *e); +extern inline dds_return_t dds_entity_deriver_delete (struct dds_entity *e); +extern inline dds_return_t dds_entity_deriver_set_qos (struct dds_entity *e, const dds_qos_t *qos, bool enabled); +extern inline dds_return_t dds_entity_deriver_validate_status (struct dds_entity *e, uint32_t mask); +extern inline bool dds_entity_supports_set_qos (struct dds_entity *e); +extern inline bool dds_entity_supports_validate_status (struct dds_entity *e); + +static int compare_instance_handle (const void *va, const void *vb) { - ddsrt_mutex_lock (&e->m_mutex); - dds_entity_add_ref_nolock (e); - ddsrt_mutex_unlock (&e->m_mutex); + const dds_instance_handle_t *a = va; + const dds_instance_handle_t *b = vb; + return (*a == *b) ? 0 : (*a < *b) ? -1 : 1; +} + +const ddsrt_avl_treedef_t dds_entity_children_td = DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct dds_entity, m_avlnode_child), offsetof (struct dds_entity, m_iid), compare_instance_handle, 0); + +static void dds_entity_observers_signal (dds_entity *observed, uint32_t status); +static void dds_entity_observers_signal_delete (dds_entity *observed); +static void dds_entity_observers_delete (dds_entity *observed); + +void dds_entity_add_ref_locked (dds_entity *e) +{ + dds_handle_add_ref (&e->m_hdllink); } dds_domain *dds__entity_domain (dds_entity *e) @@ -50,41 +85,54 @@ dds_domain *dds__entity_domain (dds_entity *e) return e->m_domain; } -static void dds_set_explicit (dds_entity_t entity) -{ - dds_entity *e; - dds_return_t rc; - if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) == DDS_RETCODE_OK) - { - e->m_flags &= ~DDS_ENTITY_IMPLICIT; - dds_entity_unlock (e); - } -} - static dds_entity *dds__nonself_parent (dds_entity *e) { return e->m_parent == e ? NULL : e->m_parent; } -dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind_t kind, dds_qos_t *qos, const dds_listener_t *listener, uint32_t mask) +static bool entity_has_status (const dds_entity *e) +{ + switch (e->m_kind) + { + case DDS_KIND_TOPIC: + 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_COND_READ: + case DDS_KIND_COND_QUERY: + case DDS_KIND_COND_GUARD: + case DDS_KIND_WAITSET: + break; + case DDS_KIND_DONTCARE: + abort (); + break; + } + return false; +} + +dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind_t kind, dds_qos_t *qos, const dds_listener_t *listener, status_mask_t mask) { dds_handle_t handle; assert ((kind == DDS_KIND_PARTICIPANT) == (parent == NULL)); assert (e); - e->m_refc = 1; e->m_kind = kind; e->m_qos = qos; e->m_cb_count = 0; e->m_observers = NULL; - e->m_trigger = 0; /* TODO: CHAM-96: Implement dynamic enabling of entity. */ e->m_flags |= DDS_ENTITY_ENABLED; /* set the status enable based on kind */ - e->m_status_enable = mask | DDS_INTERNAL_STATUS_MASK; + if (entity_has_status (e)) + ddsrt_atomic_st32 (&e->m_status.m_status_and_mask, (uint32_t) mask << SAM_ENABLED_SHIFT); + else + ddsrt_atomic_st32 (&e->m_status.m_trigger, 0); ddsrt_mutex_init (&e->m_mutex); ddsrt_mutex_init (&e->m_observers_lock); @@ -95,10 +143,8 @@ dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind { e->m_parent = parent; e->m_domain = parent->m_domain; - e->m_domainid = parent->m_domainid; e->m_participant = parent->m_participant; - e->m_next = parent->m_children; - parent->m_children = e; + ddsrt_avl_init (&dds_entity_children_td, &e->m_children); } else { @@ -111,9 +157,9 @@ dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind dds_merge_listener (&e->m_listener, listener); if (parent) { - ddsrt_mutex_lock (&e->m_observers_lock); + ddsrt_mutex_lock (&parent->m_observers_lock); dds_inherit_listener (&e->m_listener, &parent->m_listener); - ddsrt_mutex_unlock (&e->m_observers_lock); + ddsrt_mutex_unlock (&parent->m_observers_lock); } if ((handle = dds_handle_create (&e->m_hdllink)) <= 0) @@ -123,16 +169,27 @@ dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind return (dds_entity_t) handle; } +void dds_entity_register_child (dds_entity *parent, dds_entity *child) +{ + assert (child->m_iid != 0); + assert (ddsrt_avl_lookup (&dds_entity_children_td, &parent->m_children, &child->m_iid) == NULL); + ddsrt_avl_insert (&dds_entity_children_td, &parent->m_children, child); +} + dds_return_t dds_delete (dds_entity_t entity) { return dds_delete_impl (entity, false); } -static dds_entity *next_non_topic_child (dds_entity *remaining_children) +static dds_entity *next_non_topic_child (ddsrt_avl_tree_t *remaining_children) { - while (remaining_children != NULL && dds_entity_kind (remaining_children) == DDS_KIND_TOPIC) - remaining_children = remaining_children->m_next; - return remaining_children; + ddsrt_avl_iter_t it; + for (dds_entity *e = ddsrt_avl_iter_first (&dds_entity_children_td, remaining_children, &it); e != NULL; e = ddsrt_avl_iter_next (&it)) + { + if (dds_entity_kind (e) != DDS_KIND_TOPIC) + return e; + } + return NULL; } dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) @@ -140,45 +197,39 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) dds_time_t timeout = DDS_SECS(10); dds_entity *e; dds_entity *child; - dds_entity *parent; - dds_entity *prev = NULL; - dds_entity *next = NULL; dds_return_t ret; dds_return_t rc; - rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e); - if (rc != DDS_RETCODE_OK) + if ((rc = dds_entity_pin (entity, &e)) < 0) { DDS_TRACE ("dds_delete_impl: error on locking entity %"PRIu32" keep_if_explicit %d\n", entity, (int) keep_if_explicit); return rc; } + ddsrt_mutex_lock (&e->m_mutex); if (keep_if_explicit == true && (e->m_flags & DDS_ENTITY_IMPLICIT) == 0) { - dds_entity_unlock(e); + ddsrt_mutex_unlock (&e->m_mutex); + dds_entity_unpin (e); return DDS_RETCODE_OK; } - if (--e->m_refc != 0) + if (! dds_handle_drop_ref (&e->m_hdllink)) { - dds_entity_unlock (e); + ddsrt_mutex_unlock (&e->m_mutex); + dds_entity_unpin (e); return DDS_RETCODE_OK; } - /* FIXME: "closing" the handle here means a listener invoked on X - can still discover that X has become inaccessible */ - /* FIXME: RHC reads m_status_enable outside lock and might still - just invoke the listener */ - dds_handle_close (&e->m_hdllink); - e->m_status_enable = 0; + ddsrt_mutex_lock (&e->m_observers_lock); + if (entity_has_status (e)) + ddsrt_atomic_and32 (&e->m_status.m_status_and_mask, SAM_STATUS_MASK); dds_reset_listener (&e->m_listener); - e->m_trigger |= DDS_DELETING_STATUS; - dds_entity_unlock(e); /* Signal observers that this entity will be deleted and wait for all listeners to complete. */ - ddsrt_mutex_lock (&e->m_observers_lock); - dds_entity_observers_signal (e, e->m_trigger); + ddsrt_mutex_unlock (&e->m_mutex); + dds_entity_observers_signal_delete (e); while (e->m_cb_count > 0) ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock); ddsrt_mutex_unlock (&e->m_observers_lock); @@ -201,29 +252,27 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) * To circumvent the problem. We ignore topics in the first loop. */ ret = DDS_RETCODE_OK; - child = next_non_topic_child (e->m_children); - while (child != NULL && ret == DDS_RETCODE_OK) + ddsrt_mutex_lock (&e->m_mutex); + while ((child = next_non_topic_child (&e->m_children)) && ret == DDS_RETCODE_OK) { - next = next_non_topic_child (child->m_next); - /* This will probably delete the child entry from the current children's list */ - ret = dds_delete (child->m_hdllink.hdl); - child = next; + dds_entity_t child_handle = child->m_hdllink.hdl; + ddsrt_mutex_unlock (&e->m_mutex); + ret = dds_delete (child_handle); + ddsrt_mutex_lock (&e->m_mutex); } - child = e->m_children; - while (child != NULL && ret == DDS_RETCODE_OK) + while ((child = ddsrt_avl_find_min (&dds_entity_children_td, &e->m_children)) != NULL && ret == DDS_RETCODE_OK) { - next = child->m_next; assert (dds_entity_kind (child) == DDS_KIND_TOPIC); - ret = dds_delete (child->m_hdllink.hdl); - child = next; - } - if (ret == DDS_RETCODE_OK && e->m_deriver.close) - { - /* Close the entity. This can terminate threads or kick of - * other destroy stuff that takes a while. */ - ret = e->m_deriver.close (e); + dds_entity_t child_handle = child->m_hdllink.hdl; + ddsrt_mutex_unlock (&e->m_mutex); + ret = dds_delete (child_handle); + ddsrt_mutex_lock (&e->m_mutex); } + ddsrt_mutex_unlock (&e->m_mutex); + if (ret == DDS_RETCODE_OK) + ret = dds_entity_deriver_close (e); + dds_entity_unpin (e); if (ret == DDS_RETCODE_OK) { /* The dds_handle_delete will wait until the last active claim on that handle @@ -239,26 +288,17 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) dds_entity_observers_delete (e); /* Remove from parent */ + dds_entity *parent; if ((parent = dds__nonself_parent(e)) != NULL) { ddsrt_mutex_lock (&parent->m_mutex); - child = parent->m_children; - while (child && child != e) - { - prev = child; - child = child->m_next; - } - assert (child != NULL); - if (prev) - prev->m_next = e->m_next; - else - parent->m_children = e->m_next; + assert (ddsrt_avl_lookup (&dds_entity_children_td, &parent->m_children, &e->m_iid) != NULL); + ddsrt_avl_delete (&dds_entity_children_td, &parent->m_children, e); ddsrt_mutex_unlock (&parent->m_mutex); } /* Do some specific deletion when needed. */ - if (e->m_deriver.delete) - ret = e->m_deriver.delete(e); + ret = dds_entity_deriver_delete (e); } if (ret == DDS_RETCODE_OK) @@ -288,8 +328,13 @@ dds_entity_t dds_get_parent (dds_entity_t entity) hdl = DDS_ENTITY_NIL; else { + dds_entity *x; hdl = parent->m_hdllink.hdl; - dds_set_explicit (hdl); + if (dds_entity_lock (hdl, DDS_KIND_DONTCARE, &x) == DDS_RETCODE_OK) + { + parent->m_flags &= ~DDS_ENTITY_IMPLICIT; + dds_entity_unlock (parent); + } } dds_entity_unlock (e); return hdl; @@ -320,24 +365,43 @@ dds_return_t dds_get_children (dds_entity_t entity, dds_entity_t *children, size if (children == NULL && size != 0) return DDS_RETCODE_BAD_PARAMETER; - if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + if ((rc = dds_entity_pin (entity, &e)) != DDS_RETCODE_OK) return rc; else { - dds_return_t n = 0; - dds_entity *iter = e->m_children; - while (iter) + /* FIXME: fix the implicit/explicit stuff so the set_explicit isn't needed; and then this can also be done with a regular iterator & without unlocking */ + size_t n = 0; + dds_instance_handle_t last_iid = 0; + struct dds_entity *c; + ddsrt_mutex_lock (&e->m_mutex); + while ((c = ddsrt_avl_lookup_succ (&dds_entity_children_td, &e->m_children, &last_iid)) != NULL) { - if ((size_t) n < size) + last_iid = c->m_iid; + if (n < size) { - children[n] = iter->m_hdllink.hdl; - dds_set_explicit (iter->m_hdllink.hdl); + dds_entity *x; + /* Claim child handle to guarantee the child entity remains valid; as we unlock "e" only when we manage to claim the child, and the child has to remain in existence until we release it, "c" remains a valid pointer despite the unlocking. */ + if (dds_entity_pin (c->m_hdllink.hdl, &x) == DDS_RETCODE_OK) + { + assert (x == c); + children[n] = c->m_hdllink.hdl; + ddsrt_mutex_unlock (&e->m_mutex); + + ddsrt_mutex_lock (&c->m_mutex); + c->m_flags &= ~DDS_ENTITY_IMPLICIT; + ddsrt_mutex_unlock (&c->m_mutex); + + ddsrt_mutex_lock (&e->m_mutex); + dds_entity_unpin (c); + } } n++; - iter = iter->m_next; } - dds_entity_unlock(e); - return n; + ddsrt_mutex_unlock (&e->m_mutex); + dds_entity_unpin (e); + /* there are fewer than INT32_MAX handles, so there can never be more entities */ + assert (n <= INT32_MAX); + return (dds_return_t) n; } } @@ -378,7 +442,7 @@ dds_return_t dds_get_qos (dds_entity_t entity, dds_qos_t *qos) if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) return ret; - if (e->m_deriver.set_qos == 0) + if (!dds_entity_supports_set_qos (e)) ret = DDS_RETCODE_ILLEGAL_OPERATION; else { @@ -417,7 +481,7 @@ static dds_return_t dds_set_qos_locked_impl (dds_entity *e, const dds_qos_t *qos if (ret != DDS_RETCODE_OK) dds_delete_qos (newqos); - else if ((ret = e->m_deriver.set_qos (e, newqos, e->m_flags & DDS_ENTITY_ENABLED)) != DDS_RETCODE_OK) + else if ((ret = dds_entity_deriver_set_qos (e, newqos, e->m_flags & DDS_ENTITY_ENABLED)) != DDS_RETCODE_OK) dds_delete_qos (newqos); else { @@ -427,87 +491,90 @@ static dds_return_t dds_set_qos_locked_impl (dds_entity *e, const dds_qos_t *qos return ret; } -static void pushdown_pubsub_qos (dds_entity_t entity) +static void pushdown_pubsub_qos (dds_entity *e) { - dds_entity_t *cs = NULL; - int ncs, size = 0; - while ((ncs = dds_get_children (entity, cs, (size_t) size)) > size) + /* e claimed but no mutex held */ + struct dds_entity *c; + dds_instance_handle_t last_iid = 0; + ddsrt_mutex_lock (&e->m_mutex); + while ((c = ddsrt_avl_lookup_succ (&dds_entity_children_td, &e->m_children, &last_iid)) != NULL) { - size = ncs; - cs = ddsrt_realloc (cs, (size_t) size * sizeof (*cs)); - } - for (int i = 0; i < ncs; i++) - { - dds_entity *e; - if (dds_entity_lock (cs[i], DDS_KIND_DONTCARE, &e) == DDS_RETCODE_OK) + struct dds_entity *x; + last_iid = c->m_iid; + if (dds_entity_pin (c->m_hdllink.hdl, &x) == DDS_RETCODE_OK) { - if (dds_entity_kind (e) == DDS_KIND_READER || dds_entity_kind (e) == DDS_KIND_WRITER) - { - dds_entity *pe; - if (dds_entity_lock (entity, DDS_KIND_DONTCARE, &pe) == DDS_RETCODE_OK) - { - dds_set_qos_locked_impl (e, pe->m_qos, QP_GROUP_DATA | QP_PARTITION); - dds_entity_unlock (pe); - } - } - dds_entity_unlock (e); + assert (x == c); + assert (dds_entity_kind (c) == DDS_KIND_READER || dds_entity_kind (c) == DDS_KIND_WRITER); + /* see dds_get_children for why "c" remains valid despite unlocking m_mutex; + unlock e, lock c, relock e sequence is to avoid locking a child while holding the parent */ + ddsrt_mutex_unlock (&e->m_mutex); + + ddsrt_mutex_lock (&c->m_mutex); + ddsrt_mutex_lock (&e->m_mutex); + dds_set_qos_locked_impl (c, e->m_qos, QP_GROUP_DATA | QP_PARTITION); + ddsrt_mutex_unlock (&c->m_mutex); + dds_entity_unpin (c); } } - ddsrt_free (cs); + ddsrt_mutex_unlock (&e->m_mutex); } -static void pushdown_topic_qos (dds_entity_t parent, dds_entity_t topic) +static void pushdown_topic_qos (dds_entity *e, struct dds_entity *tp) { - dds_entity_t *cs = NULL; - int ncs, size = 0; - while ((ncs = dds_get_children (parent, cs, (size_t) size)) > size) + /* on input: both entities claimed but no mutexes held */ + enum { NOP, PROP, CHANGE } todo; + switch (dds_entity_kind (e)) { - size = ncs; - cs = ddsrt_realloc (cs, (size_t) size * sizeof (*cs)); - } - for (int i = 0; i < ncs; i++) - { - dds_entity *e; - if (dds_entity_lock (cs[i], DDS_KIND_DONTCARE, &e) == DDS_RETCODE_OK) - { - enum { NOP, PROP, CHANGE } todo; - switch (dds_entity_kind (e)) - { - case DDS_KIND_READER: { - dds_reader *rd = (dds_reader *) e; - todo = (rd->m_topic->m_entity.m_hdllink.hdl == topic) ? CHANGE : NOP; - break; - } - case DDS_KIND_WRITER: { - dds_writer *wr = (dds_writer *) e; - todo = (wr->m_topic->m_entity.m_hdllink.hdl == topic) ? CHANGE : NOP; - break; - case DDS_KIND_PUBLISHER: - case DDS_KIND_SUBSCRIBER: - todo = PROP; - break; - default: - todo = NOP; - break; - } - } - if (todo == CHANGE) - { - dds_topic *tp; - if (dds_topic_lock (topic, &tp) == DDS_RETCODE_OK) - { - dds_set_qos_locked_impl (e, tp->m_entity.m_qos, QP_TOPIC_DATA); - dds_topic_unlock (tp); - } - } - dds_entity_unlock (e); - if (todo == PROP) - { - pushdown_topic_qos (cs[i], topic); - } + case DDS_KIND_READER: { + dds_reader *rd = (dds_reader *) e; + todo = (&rd->m_topic->m_entity == tp) ? CHANGE : NOP; + break; + } + case DDS_KIND_WRITER: { + dds_writer *wr = (dds_writer *) e; + todo = (&wr->m_topic->m_entity == tp) ? CHANGE : NOP; + break; + } + default: { + todo = PROP; + break; + } + } + switch (todo) + { + case NOP: + break; + case CHANGE: { + /* may lock topic while holding reader/writer lock */ + 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_unlock (&e->m_mutex); + break; + } + case PROP: { + struct dds_entity *c; + dds_instance_handle_t last_iid = 0; + ddsrt_mutex_lock (&e->m_mutex); + while ((c = ddsrt_avl_lookup_succ (&dds_entity_children_td, &e->m_children, &last_iid)) != NULL) + { + struct dds_entity *x; + last_iid = c->m_iid; + if (dds_entity_pin (c->m_hdllink.hdl, &x) == DDS_RETCODE_OK) + { + 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); + ddsrt_mutex_lock (&e->m_mutex); + dds_entity_unpin (c); + } + } + ddsrt_mutex_unlock (&e->m_mutex); + break; } } - ddsrt_free (cs); } dds_return_t dds_set_qos (dds_entity_t entity, const dds_qos_t *qos) @@ -516,34 +583,48 @@ dds_return_t dds_set_qos (dds_entity_t entity, const dds_qos_t *qos) dds_return_t ret; if (qos == NULL) return DDS_RETCODE_BAD_PARAMETER; - else if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + if ((ret = dds_entity_pin (entity, &e)) < 0) return ret; - else + + const dds_entity_kind_t kind = dds_entity_kind (e); + if (!dds_entity_supports_set_qos (e)) { - const dds_entity_kind_t kind = dds_entity_kind (e); - dds_entity_t pphandle = e->m_participant->m_hdllink.hdl; - if (e->m_deriver.set_qos == 0) - ret = DDS_RETCODE_ILLEGAL_OPERATION; - else - ret = dds_set_qos_locked_impl (e, qos, entity_kind_qos_mask (kind)); - dds_entity_unlock (e); - if (ret == DDS_RETCODE_OK) - { - switch (dds_entity_kind (e)) + dds_entity_unpin (e); + return DDS_RETCODE_ILLEGAL_OPERATION; + } + + ddsrt_mutex_lock (&e->m_mutex); + ret = dds_set_qos_locked_impl (e, qos, entity_kind_qos_mask (kind)); + ddsrt_mutex_unlock (&e->m_mutex); + if (ret < 0) + { + dds_entity_unpin (e); + return ret; + } + + switch (dds_entity_kind (e)) + { + case DDS_KIND_TOPIC: { + dds_entity *pp; + if (dds_entity_pin (e->m_participant->m_hdllink.hdl, &pp) == DDS_RETCODE_OK) { - case DDS_KIND_TOPIC: - pushdown_topic_qos (pphandle, entity); - break; - case DDS_KIND_PUBLISHER: - case DDS_KIND_SUBSCRIBER: - pushdown_pubsub_qos (entity); - break; - default: - break; + pushdown_topic_qos (pp, e); + dds_entity_unpin (pp); } + break; + } + case DDS_KIND_PUBLISHER: + case DDS_KIND_SUBSCRIBER: { + pushdown_pubsub_qos (e); + break; + } + default: { + break; } } - return ret; + + dds_entity_unpin (e); + return 0; } dds_return_t dds_get_listener (dds_entity_t entity, dds_listener_t *listener) @@ -552,14 +633,14 @@ dds_return_t dds_get_listener (dds_entity_t entity, dds_listener_t *listener) dds_return_t ret; if (listener == NULL) return DDS_RETCODE_BAD_PARAMETER; - else if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + else if ((ret = dds_entity_pin (entity, &e)) != DDS_RETCODE_OK) return ret; else { ddsrt_mutex_lock (&e->m_observers_lock); dds_copy_listener (listener, &e->m_listener); ddsrt_mutex_unlock (&e->m_observers_lock); - dds_entity_unlock(e); + dds_entity_unpin (e); return DDS_RETCODE_OK; } } @@ -638,62 +719,70 @@ void dds_entity_invoke_listener (const dds_entity *entity, enum dds_status_id wh static void clear_status_with_listener (struct dds_entity *e) { const struct dds_listener *lst = &e->m_listener; + status_mask_t mask = 0; if (lst->on_inconsistent_topic) - e->m_trigger &= ~DDS_INCONSISTENT_TOPIC_STATUS; + mask |= DDS_INCONSISTENT_TOPIC_STATUS; if (lst->on_liveliness_lost) - e->m_trigger &= ~DDS_LIVELINESS_LOST_STATUS; + mask |= DDS_LIVELINESS_LOST_STATUS; if (lst->on_offered_deadline_missed) - e->m_trigger &= ~DDS_OFFERED_DEADLINE_MISSED_STATUS; + mask |= DDS_OFFERED_DEADLINE_MISSED_STATUS; if (lst->on_offered_deadline_missed_arg) - e->m_trigger &= ~DDS_OFFERED_DEADLINE_MISSED_STATUS; + mask |= DDS_OFFERED_DEADLINE_MISSED_STATUS; if (lst->on_offered_incompatible_qos) - e->m_trigger &= ~DDS_OFFERED_INCOMPATIBLE_QOS_STATUS; + mask |= DDS_OFFERED_INCOMPATIBLE_QOS_STATUS; if (lst->on_data_on_readers) - e->m_trigger &= ~DDS_DATA_ON_READERS_STATUS; + mask |= DDS_DATA_ON_READERS_STATUS; if (lst->on_sample_lost) - e->m_trigger &= ~DDS_SAMPLE_LOST_STATUS; + mask |= DDS_SAMPLE_LOST_STATUS; if (lst->on_data_available) - e->m_trigger &= ~DDS_DATA_AVAILABLE_STATUS; + mask |= DDS_DATA_AVAILABLE_STATUS; if (lst->on_sample_rejected) - e->m_trigger &= ~DDS_SAMPLE_REJECTED_STATUS; + mask |= DDS_SAMPLE_REJECTED_STATUS; if (lst->on_liveliness_changed) - e->m_trigger &= ~DDS_LIVELINESS_CHANGED_STATUS; + mask |= DDS_LIVELINESS_CHANGED_STATUS; if (lst->on_requested_deadline_missed) - e->m_trigger &= ~DDS_REQUESTED_DEADLINE_MISSED_STATUS; + mask |= DDS_REQUESTED_DEADLINE_MISSED_STATUS; if (lst->on_requested_incompatible_qos) - e->m_trigger &= ~DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS; + mask |= DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS; if (lst->on_publication_matched) - e->m_trigger &= ~DDS_PUBLICATION_MATCHED_STATUS; + mask |= DDS_PUBLICATION_MATCHED_STATUS; if (lst->on_subscription_matched) - e->m_trigger &= ~DDS_SUBSCRIPTION_MATCHED_STATUS; + mask |= DDS_SUBSCRIPTION_MATCHED_STATUS; + ddsrt_atomic_and32 (&e->m_status.m_status_and_mask, ~(uint32_t)mask); } -static void pushdown_listener (dds_entity_t entity) +static void pushdown_listener (dds_entity *e) { - dds_entity_t *cs = NULL; - int ncs, size = 0; - while ((ncs = dds_get_children (entity, cs, (size_t) size)) > size) + /* Note: e is claimed, no mutexes held */ + struct dds_entity *c; + dds_instance_handle_t last_iid = 0; + ddsrt_mutex_lock (&e->m_mutex); + while ((c = ddsrt_avl_lookup_succ (&dds_entity_children_td, &e->m_children, &last_iid)) != NULL) { - size = ncs; - cs = ddsrt_realloc (cs, (size_t) size * sizeof (*cs)); - } - for (int i = 0; i < ncs; i++) - { - dds_entity *e; - if (dds_entity_lock (cs[i], DDS_KIND_DONTCARE, &e) == DDS_RETCODE_OK) + struct dds_entity *x; + last_iid = c->m_iid; + if (dds_entity_pin (c->m_hdllink.hdl, &x) == DDS_RETCODE_OK) { - dds_listener_t tmp; + ddsrt_mutex_unlock (&e->m_mutex); + + ddsrt_mutex_lock (&c->m_observers_lock); + while (c->m_cb_count > 0) + ddsrt_cond_wait (&c->m_observers_cond, &c->m_observers_lock); + ddsrt_mutex_lock (&e->m_observers_lock); - while (e->m_cb_count > 0) - ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock); - dds_get_listener (entity, &tmp); - dds_override_inherited_listener (&e->m_listener, &tmp); - clear_status_with_listener (e); + dds_override_inherited_listener (&c->m_listener, &e->m_listener); ddsrt_mutex_unlock (&e->m_observers_lock); - dds_entity_unlock (e); + + clear_status_with_listener (c); + ddsrt_mutex_unlock (&c->m_observers_lock); + + pushdown_listener (c); + + ddsrt_mutex_lock (&e->m_mutex); + dds_entity_unpin (c); } } - ddsrt_free (cs); + ddsrt_mutex_unlock (&e->m_mutex); } dds_return_t dds_set_listener (dds_entity_t entity, const dds_listener_t *listener) @@ -701,7 +790,7 @@ dds_return_t dds_set_listener (dds_entity_t entity, const dds_listener_t *listen dds_entity *e, *x; dds_return_t rc; - if ((rc = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) + if ((rc = dds_entity_pin (entity, &e)) != DDS_RETCODE_OK) return rc; ddsrt_mutex_lock (&e->m_observers_lock); @@ -718,12 +807,14 @@ dds_return_t dds_set_listener (dds_entity_t entity, const dds_listener_t *listen while (dds_entity_kind (x) != DDS_KIND_PARTICIPANT) { x = x->m_parent; + ddsrt_mutex_lock (&x->m_observers_lock); dds_inherit_listener (&e->m_listener, &x->m_listener); + ddsrt_mutex_unlock (&x->m_observers_lock); } clear_status_with_listener (e); ddsrt_mutex_unlock (&e->m_observers_lock); - dds_entity_release (e); - pushdown_listener (entity); + pushdown_listener (e); + dds_entity_unpin (e); return DDS_RETCODE_OK; } @@ -756,13 +847,12 @@ dds_return_t dds_get_status_changes (dds_entity_t entity, uint32_t *status) if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) return ret; - if (e->m_deriver.validate_status == 0) + if (!dds_entity_supports_validate_status (e)) ret = DDS_RETCODE_ILLEGAL_OPERATION; else { - ddsrt_mutex_lock (&e->m_observers_lock); - *status = e->m_trigger; - ddsrt_mutex_unlock (&e->m_observers_lock); + assert (entity_has_status (e)); + *status = ddsrt_atomic_ld32 (&e->m_status.m_status_and_mask) & SAM_STATUS_MASK; ret = DDS_RETCODE_OK; } dds_entity_unlock(e); @@ -777,19 +867,18 @@ dds_return_t dds_get_status_mask (dds_entity_t entity, uint32_t *mask) if (mask == NULL) return DDS_RETCODE_BAD_PARAMETER; - if ((ret = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) + if ((ret = dds_entity_pin (entity, &e)) != DDS_RETCODE_OK) return ret; - if (e->m_deriver.validate_status == 0) + if (!dds_entity_supports_validate_status (e)) ret = DDS_RETCODE_ILLEGAL_OPERATION; else { - ddsrt_mutex_lock (&e->m_observers_lock); - *mask = (e->m_status_enable & ~DDS_INTERNAL_STATUS_MASK); - ddsrt_mutex_unlock (&e->m_observers_lock); + assert (entity_has_status (e)); + *mask = ddsrt_atomic_ld32 (&e->m_status.m_status_and_mask) >> SAM_ENABLED_SHIFT; ret = DDS_RETCODE_OK; } - dds_entity_release(e); + dds_entity_unpin(e); return ret; } @@ -803,30 +892,34 @@ dds_return_t dds_set_status_mask (dds_entity_t entity, uint32_t mask) dds_entity *e; dds_return_t ret; - if ((ret = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) + if ((mask & ~SAM_STATUS_MASK) != 0) + return DDS_RETCODE_BAD_PARAMETER; + + if ((ret = dds_entity_pin (entity, &e)) != DDS_RETCODE_OK) return ret; - if (e->m_deriver.validate_status == 0) - ret = DDS_RETCODE_ILLEGAL_OPERATION; - else if ((ret = e->m_deriver.validate_status (mask)) == DDS_RETCODE_OK) + if ((ret = dds_entity_deriver_validate_status (e, mask)) == DDS_RETCODE_OK) { + assert (entity_has_status (e)); ddsrt_mutex_lock (&e->m_observers_lock); while (e->m_cb_count > 0) ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock); /* Don't block internal status triggers. */ - mask |= DDS_INTERNAL_STATUS_MASK; - e->m_status_enable = mask; - e->m_trigger &= mask; + uint32_t old, new; + do { + old = ddsrt_atomic_ld32 (&e->m_status.m_status_and_mask); + new = (mask << SAM_ENABLED_SHIFT) | (old & mask); + } while (!ddsrt_atomic_cas32 (&e->m_status.m_status_and_mask, old, new)); ddsrt_mutex_unlock (&e->m_observers_lock); } - dds_entity_release (e); + dds_entity_unpin (e); return ret; } dds_return_t dds_set_enabled_status(dds_entity_t entity, uint32_t mask) { - return dds_set_status_mask( entity, mask); + return dds_set_status_mask (entity, mask); } static dds_return_t dds_readtake_status (dds_entity_t entity, uint32_t *status, uint32_t mask, bool reset) @@ -836,19 +929,21 @@ static dds_return_t dds_readtake_status (dds_entity_t entity, uint32_t *status, if (status == NULL) return DDS_RETCODE_BAD_PARAMETER; + if ((mask & ~SAM_STATUS_MASK) != 0) + return DDS_RETCODE_BAD_PARAMETER; if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) return ret; - if (e->m_deriver.validate_status == 0) - ret = DDS_RETCODE_ILLEGAL_OPERATION; - else if ((ret = e->m_deriver.validate_status (mask)) == DDS_RETCODE_OK) + if ((ret = dds_entity_deriver_validate_status (e, mask)) == DDS_RETCODE_OK) { - ddsrt_mutex_lock (&e->m_observers_lock); - *status = e->m_trigger & mask; + uint32_t s; + assert (entity_has_status (e)); if (reset) - e->m_trigger &= ~mask; - ddsrt_mutex_unlock (&e->m_observers_lock); + s = ddsrt_atomic_and32_ov (&e->m_status.m_status_and_mask, ~mask) & mask; + else + s = ddsrt_atomic_ld32 (&e->m_status.m_status_and_mask) & mask; + *status = s; } dds_entity_unlock (e); return ret; @@ -876,7 +971,7 @@ dds_return_t dds_get_domainid (dds_entity_t entity, dds_domainid_t *id) if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) return rc; - *id = e->m_domainid; + *id = e->m_domain->m_id; dds_entity_unlock(e); return DDS_RETCODE_OK; } @@ -889,18 +984,18 @@ dds_return_t dds_get_instance_handle (dds_entity_t entity, dds_instance_handle_t if (ihdl == NULL) return DDS_RETCODE_BAD_PARAMETER; - if ((ret = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) + if ((ret = dds_entity_pin (entity, &e)) != DDS_RETCODE_OK) return ret; *ihdl = e->m_iid; - dds_entity_release(e); + dds_entity_unpin(e); return ret; } -dds_return_t dds_entity_claim (dds_entity_t hdl, dds_entity **eptr) +dds_return_t dds_entity_pin (dds_entity_t hdl, dds_entity **eptr) { dds_return_t hres; struct dds_handle_link *hdllink; - if ((hres = dds_handle_claim (hdl, &hdllink)) != DDS_RETCODE_OK) + if ((hres = dds_handle_pin (hdl, &hdllink)) < 0) return hres; else { @@ -909,41 +1004,26 @@ dds_return_t dds_entity_claim (dds_entity_t hdl, dds_entity **eptr) } } -void dds_entity_release (dds_entity *e) +void dds_entity_unpin (dds_entity *e) { - dds_handle_release (&e->m_hdllink); + dds_handle_unpin (&e->m_hdllink); } dds_return_t dds_entity_lock (dds_entity_t hdl, dds_entity_kind_t kind, dds_entity **eptr) { dds_return_t hres; dds_entity *e; - - /* When the given handle already contains an error, then return that - * same error to retain the original information. */ - if ((hres = dds_entity_claim (hdl, &e)) != DDS_RETCODE_OK) + if ((hres = dds_entity_pin (hdl, &e)) < 0) return hres; else { if (dds_entity_kind (e) != kind && kind != DDS_KIND_DONTCARE) { - dds_handle_release (&e->m_hdllink); + dds_entity_unpin (e); return DDS_RETCODE_ILLEGAL_OPERATION; } ddsrt_mutex_lock (&e->m_mutex); - /* FIXME: The handle could have been closed while we were waiting for the mutex -- that should be handled differently! - - For now, however, it is really important at two points in the logic: - (1) preventing creating new entities as children of a one that is currently being deleted, and - (2) preventing dds_delete_impl from doing anything once the entity is being deleted. - - Without (1), it would be possible to add children while trying to delete them, without (2) you're looking at crashes. */ - if (dds_handle_is_closed (&e->m_hdllink)) - { - dds_entity_unlock (e); - return DDS_RETCODE_BAD_PARAMETER; - } *eptr = e; return DDS_RETCODE_OK; } @@ -952,7 +1032,7 @@ dds_return_t dds_entity_lock (dds_entity_t hdl, dds_entity_kind_t kind, dds_enti void dds_entity_unlock (dds_entity *e) { ddsrt_mutex_unlock (&e->m_mutex); - dds_handle_release (&e->m_hdllink); + dds_handle_unpin (&e->m_hdllink); } dds_return_t dds_triggered (dds_entity_t entity) @@ -960,16 +1040,17 @@ dds_return_t dds_triggered (dds_entity_t entity) dds_entity *e; dds_return_t ret; - if ((ret = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) return ret; - ddsrt_mutex_lock (&e->m_observers_lock); - ret = (e->m_trigger != 0); - ddsrt_mutex_unlock (&e->m_observers_lock); + if (entity_has_status (e)) + ret = ((ddsrt_atomic_ld32 (&e->m_status.m_status_and_mask) & SAM_STATUS_MASK) != 0); + else + ret = (ddsrt_atomic_ld32 (&e->m_status.m_trigger) != 0); dds_entity_unlock (e); return ret; } -static bool in_observer_list_p (const struct dds_entity *observed, const dds_entity_t observer) +static bool in_observer_list_p (const struct dds_entity *observed, const dds_entity *observer) { dds_entity_observer *cur; for (cur = observed->m_observers; cur != NULL; cur = cur->m_next) @@ -978,7 +1059,7 @@ static bool in_observer_list_p (const struct dds_entity *observed, const dds_ent return false; } -dds_return_t dds_entity_observer_register_nl (dds_entity *observed, dds_entity_t observer, dds_entity_callback cb) +dds_return_t dds_entity_observer_register (dds_entity *observed, dds_entity *observer, dds_entity_callback cb, dds_entity_delete_callback delete_cb) { dds_return_t rc; assert (observed); @@ -989,6 +1070,7 @@ dds_return_t dds_entity_observer_register_nl (dds_entity *observed, dds_entity_t { dds_entity_observer *o = ddsrt_malloc (sizeof (dds_entity_observer)); o->m_cb = cb; + o->m_delete_cb = delete_cb; o->m_observer = observer; o->m_next = observed->m_observers; observed->m_observers = o; @@ -998,19 +1080,7 @@ dds_return_t dds_entity_observer_register_nl (dds_entity *observed, dds_entity_t return rc; } -dds_return_t dds_entity_observer_register (dds_entity_t observed, dds_entity_t observer, dds_entity_callback cb) -{ - dds_return_t rc; - dds_entity *e; - assert (cb); - if ((rc = dds_entity_lock (observed, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return rc; - rc = dds_entity_observer_register_nl (e, observer, cb); - dds_entity_unlock (e); - return rc; -} - -dds_return_t dds_entity_observer_unregister_nl (dds_entity *observed, dds_entity_t observer) +dds_return_t dds_entity_observer_unregister (dds_entity *observed, dds_entity *observer) { dds_return_t rc; dds_entity_observer *prev, *idx; @@ -1038,17 +1108,6 @@ dds_return_t dds_entity_observer_unregister_nl (dds_entity *observed, dds_entity return rc; } -dds_return_t dds_entity_observer_unregister (dds_entity_t observed, dds_entity_t observer) -{ - dds_return_t rc; - dds_entity *e; - if ((rc = dds_entity_lock (observed, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - return rc; - rc = dds_entity_observer_unregister_nl (e, observer); - dds_entity_unlock (e); - return rc; -} - static void dds_entity_observers_delete (dds_entity *observed) { dds_entity_observer *idx; @@ -1070,20 +1129,43 @@ static void dds_entity_observers_signal (dds_entity *observed, uint32_t status) idx->m_cb (idx->m_observer, observed->m_hdllink.hdl, status); } -void dds_entity_status_signal (dds_entity *e) +static void dds_entity_observers_signal_delete (dds_entity *observed) +{ + for (dds_entity_observer *idx = observed->m_observers; idx; idx = idx->m_next) + idx->m_delete_cb (idx->m_observer, observed->m_hdllink.hdl); +} + +void dds_entity_status_signal (dds_entity *e, uint32_t status) { ddsrt_mutex_lock (&e->m_observers_lock); - dds_entity_observers_signal (e, e->m_trigger); + dds_entity_observers_signal (e, status); ddsrt_mutex_unlock (&e->m_observers_lock); } -void dds_entity_status_set (dds_entity *e, uint32_t t) +void dds_entity_status_set (dds_entity *e, status_mask_t status) { - if (!(e->m_trigger & t)) - { - e->m_trigger |= e->m_status_enable & t; - dds_entity_observers_signal (e, e->m_trigger); - } + assert (entity_has_status (e)); + uint32_t old, delta, new; + do { + old = ddsrt_atomic_ld32 (&e->m_status.m_status_and_mask); + delta = ((uint32_t) status & (old >> SAM_ENABLED_SHIFT)); + if (delta == 0) + return; + new = old | delta; + } while (!ddsrt_atomic_cas32 (&e->m_status.m_status_and_mask, old, new)); + if (delta) + dds_entity_observers_signal (e, status); +} + +void dds_entity_trigger_set (dds_entity *e, uint32_t t) +{ + assert (! entity_has_status (e)); + uint32_t oldst; + do { + oldst = ddsrt_atomic_ld32 (&e->m_status.m_trigger); + } while (!ddsrt_atomic_cas32 (&e->m_status.m_trigger, oldst, t)); + if (oldst == 0 && t != 0) + dds_entity_observers_signal (e, t); } dds_entity_t dds_get_topic (dds_entity_t entity) @@ -1126,7 +1208,7 @@ dds_return_t dds_generic_unimplemented_operation_manykinds (dds_entity_t handle, { dds_entity *e; dds_return_t ret; - if ((ret = dds_entity_claim (handle, &e)) != DDS_RETCODE_OK) + if ((ret = dds_entity_pin (handle, &e)) != DDS_RETCODE_OK) return ret; else { @@ -1141,7 +1223,7 @@ dds_return_t dds_generic_unimplemented_operation_manykinds (dds_entity_t handle, break; } } - dds_entity_release (e); + dds_entity_unpin (e); return ret; } } diff --git a/src/core/ddsc/src/dds_guardcond.c b/src/core/ddsc/src/dds_guardcond.c index 5e7e83b..d6f7de6 100644 --- a/src/core/ddsc/src/dds_guardcond.c +++ b/src/core/ddsc/src/dds_guardcond.c @@ -21,6 +21,13 @@ DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_guardcond) +const struct dds_entity_deriver dds_entity_deriver_guardcondition = { + .close = dds_entity_deriver_dummy_close, + .delete = dds_entity_deriver_dummy_delete, + .set_qos = dds_entity_deriver_dummy_set_qos, + .validate_status = dds_entity_deriver_dummy_validate_status +}; + dds_entity_t dds_create_guardcondition (dds_entity_t participant) { dds_participant *pp; @@ -33,6 +40,7 @@ dds_entity_t dds_create_guardcondition (dds_entity_t participant) dds_guardcond *gcond = dds_alloc (sizeof (*gcond)); dds_entity_t hdl = dds_entity_init (&gcond->m_entity, &pp->m_entity, DDS_KIND_COND_GUARD, NULL, NULL, 0); gcond->m_entity.m_iid = ddsi_iid_gen (); + dds_entity_register_child (&pp->m_entity, &gcond->m_entity); dds_participant_unlock (pp); return hdl; } @@ -47,12 +55,10 @@ dds_return_t dds_set_guardcondition (dds_entity_t condition, bool triggered) return rc; else { - ddsrt_mutex_lock (&gcond->m_entity.m_observers_lock); if (triggered) - dds_entity_status_set (&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); + dds_entity_trigger_set (&gcond->m_entity, 1); else - dds_entity_status_reset (&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); - ddsrt_mutex_unlock (&gcond->m_entity.m_observers_lock); + ddsrt_atomic_st32 (&gcond->m_entity.m_status.m_trigger, 0); dds_guardcond_unlock (gcond); return DDS_RETCODE_OK; } @@ -71,9 +77,7 @@ dds_return_t dds_read_guardcondition (dds_entity_t condition, bool *triggered) return rc; else { - ddsrt_mutex_lock (&gcond->m_entity.m_observers_lock); - *triggered = dds_entity_status_match (&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); - ddsrt_mutex_unlock (&gcond->m_entity.m_observers_lock); + *triggered = (ddsrt_atomic_ld32 (&gcond->m_entity.m_status.m_trigger) != 0); dds_guardcond_unlock (gcond); return DDS_RETCODE_OK; } @@ -92,10 +96,7 @@ dds_return_t dds_take_guardcondition (dds_entity_t condition, bool *triggered) return rc; else { - ddsrt_mutex_lock (&gcond->m_entity.m_observers_lock); - *triggered = dds_entity_status_match (&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); - dds_entity_status_reset (&gcond->m_entity, DDS_WAITSET_TRIGGER_STATUS); - ddsrt_mutex_unlock (&gcond->m_entity.m_observers_lock); + *triggered = (ddsrt_atomic_and32_ov (&gcond->m_entity.m_status.m_trigger, 0) != 0); dds_guardcond_unlock (gcond); return DDS_RETCODE_OK; } diff --git a/src/core/ddsc/src/dds_handles.c b/src/core/ddsc/src/dds_handles.c index eff8005..def0975 100644 --- a/src/core/ddsc/src/dds_handles.c +++ b/src/core/ddsc/src/dds_handles.c @@ -28,7 +28,19 @@ #define USE_CHH 0 #define HDL_FLAG_CLOSED (0x80000000u) -#define HDL_COUNT_MASK (0x00ffffffu) + +/* ref count: # outstanding references to this handle/object (not so sure it is + ideal to have a one-to-one mapping between the two, but that is what the rest + of the code assumes at the moment); so this limits one to having, e.g., no + more than 64k endpoints referencing the same topic */ +#define HDL_REFCOUNT_MASK (0x0ffff000u) +#define HDL_REFCOUNT_UNIT (0x00001000u) +#define HDL_REFCOUNT_SHIFT 12 + +/* pin count: # concurrent operations, so allowing up to 4096 threads had better + be enough ... */ +#define HDL_PINCOUNT_MASK (0x00000fffu) +#define HDL_PINCOUNT_UNIT (0x00000001u) /* Maximum number of handles is INT32_MAX - 1, but as the allocator relies on a random generator for finding a free one, the time spent in the dds_handle_create @@ -105,7 +117,7 @@ static bool hhadd (struct ddsrt_hh *ht, void *elem) { return ddsrt_hh_add (ht, e #endif static dds_handle_t dds_handle_create_int (struct dds_handle_link *link) { - ddsrt_atomic_st32 (&link->cnt_flags, 0); + ddsrt_atomic_st32 (&link->cnt_flags, HDL_REFCOUNT_UNIT); do { do { link->hdl = (int32_t) (ddsrt_random () & INT32_MAX); @@ -159,11 +171,12 @@ int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout) #endif assert (ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_FLAG_CLOSED); ddsrt_mutex_lock (&handles.lock); - if ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_COUNT_MASK) != 0) + if ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_PINCOUNT_MASK) != 0) { - /* FIXME: */ + /* FIXME: there is no sensible solution when this times out, so it must + never do that ... */ const dds_time_t abstimeout = dds_time () + timeout; - while ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_COUNT_MASK) != 0) + while ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_PINCOUNT_MASK) != 0) { if (!ddsrt_cond_waituntil (&handles.cond, &handles.lock, abstimeout)) { @@ -188,7 +201,7 @@ int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout) return DDS_RETCODE_OK; } -int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) +int32_t dds_handle_pin (dds_handle_t hdl, struct dds_handle_link **link) { #if USE_CHH struct thread_state1 * const ts1 = lookup_thread_state (); @@ -196,7 +209,7 @@ int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) struct dds_handle_link dummy = { .hdl = hdl }; int32_t rc; /* it makes sense to check here for initialization: the first thing any operation - (other than create_participant) does is to call dds_handle_claim on the supplied + (other than create_participant) does is to call dds_handle_pin on the supplied entity, so checking here whether the library has been initialised helps avoid crashes if someone forgets to create a participant (or allows a program to continue after failing to create one). @@ -228,7 +241,7 @@ int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) rc = DDS_RETCODE_BAD_PARAMETER; break; } - } while (!ddsrt_atomic_cas32 (&(*link)->cnt_flags, cnt_flags, cnt_flags + 1)); + } while (!ddsrt_atomic_cas32 (&(*link)->cnt_flags, cnt_flags, cnt_flags + HDL_PINCOUNT_UNIT)); } #if USE_CHH thread_state_asleep (ts1); @@ -238,16 +251,18 @@ int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) return rc; } -void dds_handle_claim_inc (struct dds_handle_link *link) +void dds_handle_repin (struct dds_handle_link *link) { + DDSRT_STATIC_ASSERT (HDL_PINCOUNT_UNIT == 1); uint32_t x = ddsrt_atomic_inc32_nv (&link->cnt_flags); assert (!(x & HDL_FLAG_CLOSED)); (void) x; } -void dds_handle_release (struct dds_handle_link *link) +void dds_handle_unpin (struct dds_handle_link *link) { - if (ddsrt_atomic_dec32_ov (&link->cnt_flags) == (HDL_FLAG_CLOSED | 1)) + DDSRT_STATIC_ASSERT (HDL_PINCOUNT_UNIT == 1); + if ((ddsrt_atomic_dec32_ov (&link->cnt_flags) & (HDL_FLAG_CLOSED | HDL_PINCOUNT_MASK)) == (HDL_FLAG_CLOSED | HDL_PINCOUNT_UNIT)) { ddsrt_mutex_lock (&handles.lock); ddsrt_cond_broadcast (&handles.cond); @@ -255,6 +270,25 @@ void dds_handle_release (struct dds_handle_link *link) } } +void dds_handle_add_ref (struct dds_handle_link *link) +{ + ddsrt_atomic_add32 (&link->cnt_flags, HDL_REFCOUNT_UNIT); +} + +bool dds_handle_drop_ref (struct dds_handle_link *link) +{ + assert ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_REFCOUNT_MASK) != 0); + uint32_t old, new; + do { + old = ddsrt_atomic_ld32 (&link->cnt_flags); + if ((old & HDL_REFCOUNT_MASK) != HDL_REFCOUNT_UNIT) + new = old - HDL_REFCOUNT_UNIT; + else + new = (old - HDL_REFCOUNT_UNIT) | HDL_FLAG_CLOSED; + } while (!ddsrt_atomic_cas32 (&link->cnt_flags, old, new)); + return (new & HDL_REFCOUNT_MASK) == 0; +} + bool dds_handle_is_closed (struct dds_handle_link *link) { return (ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_FLAG_CLOSED) != 0; diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index 11ee1d6..ddb65f4 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -62,46 +62,6 @@ static void dds_instance_remove (const dds_topic *topic, const void *data, dds_i } } -static const dds_topic *dds_instance_info (dds_entity *e) -{ - const dds_topic *topic; - switch (dds_entity_kind (e)) - { - case DDS_KIND_READER: - topic = ((dds_reader*) e)->m_topic; - break; - case DDS_KIND_WRITER: - topic = ((dds_writer*) e)->m_topic; - break; - default: - assert (0); - topic = NULL; - } - return topic; -} - -static const dds_topic *dds_instance_info_by_hdl (dds_entity_t e) -{ - const dds_topic *topic; - dds_entity *w_or_r; - - if (dds_entity_lock (e, DDS_KIND_DONTCARE, &w_or_r) != DDS_RETCODE_OK) - return NULL; - - switch (dds_entity_kind (w_or_r)) - { - case DDS_KIND_WRITER: - case DDS_KIND_READER: - topic = dds_instance_info (w_or_r); - break; - default: - topic = NULL; - break; - } - dds_entity_unlock (w_or_r); - return topic; -} - dds_return_t dds_register_instance (dds_entity_t writer, dds_instance_handle_t *handle, const void *data) { struct thread_state1 * const ts1 = lookup_thread_state (); @@ -284,18 +244,32 @@ dds_instance_handle_t dds_lookup_instance (dds_entity_t entity, const void *data dds_instance_handle_t ih = DDS_HANDLE_NIL; const dds_topic *topic; struct ddsi_serdata *sd; + dds_entity *w_or_r; if (data == NULL) return DDS_HANDLE_NIL; - if ((topic = dds_instance_info_by_hdl (entity)) == NULL) + if (dds_entity_lock (entity, DDS_KIND_DONTCARE, &w_or_r) < 0) return DDS_HANDLE_NIL; + switch (dds_entity_kind (w_or_r)) + { + case DDS_KIND_WRITER: + topic = ((dds_writer *) w_or_r)->m_topic; + break; + case DDS_KIND_READER: + topic = ((dds_reader *) w_or_r)->m_topic; + break; + default: + dds_entity_unlock (w_or_r); + return DDS_HANDLE_NIL; + } thread_state_awake (ts1); sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data); ih = ddsi_tkmap_lookup (gv.m_tkmap, sd); ddsi_serdata_unref (sd); thread_state_asleep (ts1); + dds_entity_unlock (w_or_r); return ih; } @@ -310,12 +284,25 @@ dds_return_t dds_instance_get_key (dds_entity_t entity, dds_instance_handle_t ih dds_return_t ret; const dds_topic *topic; struct ddsi_tkmap_instance *tk; + dds_entity *w_or_r; if (data == NULL) return DDS_RETCODE_BAD_PARAMETER; - if ((topic = dds_instance_info_by_hdl (entity)) == NULL) - return DDS_RETCODE_BAD_PARAMETER; + if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &w_or_r)) < 0) + return ret; + switch (dds_entity_kind (w_or_r)) + { + case DDS_KIND_WRITER: + topic = ((dds_writer *) w_or_r)->m_topic; + break; + case DDS_KIND_READER: + topic = ((dds_reader *) w_or_r)->m_topic; + break; + default: + dds_entity_unlock (w_or_r); + return DDS_RETCODE_ILLEGAL_OPERATION; + } thread_state_awake (ts1); if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, ih)) == NULL) @@ -328,5 +315,6 @@ dds_return_t dds_instance_get_key (dds_entity_t entity, dds_instance_handle_t ih ret = DDS_RETCODE_OK; } thread_state_asleep (ts1); + dds_entity_unlock (w_or_r); return ret; } diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 57aca98..31108d7 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -84,6 +84,13 @@ static dds_return_t dds_participant_qos_set (dds_entity *e, const dds_qos_t *qos return DDS_RETCODE_OK; } +const struct dds_entity_deriver dds_entity_deriver_participant = { + .close = dds_entity_deriver_dummy_close, + .delete = dds_participant_delete, + .set_qos = dds_participant_qos_set, + .validate_status = dds_participant_status_validate +}; + dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_t *qos, const dds_listener_t *listener) { dds_entity_t ret; @@ -128,10 +135,6 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_ pp->m_entity.m_guid = guid; pp->m_entity.m_iid = get_entity_instance_id (&guid); pp->m_entity.m_domain = dds_domain_create (dds_domain_default ()); - pp->m_entity.m_domainid = dds_domain_default (); - pp->m_entity.m_deriver.delete = dds_participant_delete; - pp->m_entity.m_deriver.set_qos = dds_participant_qos_set; - pp->m_entity.m_deriver.validate_status = dds_participant_status_validate; pp->m_builtin_subscriber = 0; /* Add participant to extent */ @@ -175,7 +178,7 @@ dds_entity_t dds_lookup_participant (dds_domainid_t domain_id, dds_entity_t *par ddsrt_mutex_lock (&dds_global.m_mutex); for (dds_entity *iter = dds_pp_head; iter; iter = iter->m_next) { - if (iter->m_domainid == domain_id) + if (iter->m_domain->m_id == domain_id) { if ((size_t) ret < size) participants[ret] = iter->m_hdllink.hdl; diff --git a/src/core/ddsc/src/dds_publisher.c b/src/core/ddsc/src/dds_publisher.c index 850623d..067ca1c 100644 --- a/src/core/ddsc/src/dds_publisher.c +++ b/src/core/ddsc/src/dds_publisher.c @@ -36,6 +36,13 @@ static dds_return_t dds_publisher_status_validate (uint32_t mask) return (mask & ~DDS_PUBLISHER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK; } +const struct dds_entity_deriver dds_entity_deriver_publisher = { + .close = dds_entity_deriver_dummy_close, + .delete = dds_entity_deriver_dummy_delete, + .set_qos = dds_publisher_qos_set, + .validate_status = dds_publisher_status_validate +}; + dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qos, const dds_listener_t *listener) { dds_participant *par; @@ -62,8 +69,7 @@ dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qo pub = dds_alloc (sizeof (*pub)); hdl = dds_entity_init (&pub->m_entity, &par->m_entity, DDS_KIND_PUBLISHER, new_qos, listener, DDS_PUBLISHER_STATUS_MASK); pub->m_entity.m_iid = ddsi_iid_gen (); - pub->m_entity.m_deriver.set_qos = dds_publisher_qos_set; - pub->m_entity.m_deriver.validate_status = dds_publisher_status_validate; + dds_entity_register_child (&par->m_entity, &pub->m_entity); dds_participant_unlock (par); return hdl; } diff --git a/src/core/ddsc/src/dds_querycond.c b/src/core/ddsc/src/dds_querycond.c index fc5b0ea..a589ce0 100644 --- a/src/core/ddsc/src/dds_querycond.c +++ b/src/core/ddsc/src/dds_querycond.c @@ -33,15 +33,8 @@ dds_entity_t dds_create_querycondition (dds_entity_t reader, uint32_t mask, dds_ dds_entity_t hdl; dds_readcond *cond = dds_create_readcond (r, DDS_KIND_COND_QUERY, mask, filter); assert (cond); - const bool success = (cond->m_entity.m_deriver.delete != 0); dds_reader_unlock (r); - if (success) - hdl = cond->m_entity.m_hdllink.hdl; - else - { - dds_delete (cond->m_entity.m_hdllink.hdl); - hdl = DDS_RETCODE_OUT_OF_RESOURCES; - } + hdl = cond->m_entity.m_hdllink.hdl; return hdl; } } diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index ca5e839..b4ede31 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -134,12 +134,11 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, /* read/take resets data available status -- must reset before reading because the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ - ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); + /* reset DATA_ON_READERS status on subscriber after successful read/take */ - if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) - dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); - ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); + assert (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER); + dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); if (take) ret = dds_rhc_take (rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); @@ -158,7 +157,7 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, if (nodata_cleanups & NC_RESET_BUF) buf[0] = NULL; } - dds_read_unlock(rd, cond); + dds_read_unlock (rd, cond); thread_state_asleep (ts1); return ret; @@ -191,13 +190,12 @@ static dds_return_t dds_readcdr_impl (bool take, dds_entity_t reader_or_conditio if ((ret = dds_read_lock (reader_or_condition, &rd, &cond, false)) == DDS_RETCODE_OK) { /* read/take resets data available status -- must reset before reading because - the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ - ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); + the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); + /* reset DATA_ON_READERS status on subscriber after successful read/take */ - if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) - dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); - ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); + assert (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER); + dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); ret = dds_rhc_takecdr (rd->m_rd->rhc, lock, buf, si, maxs, mask & DDS_ANY_SAMPLE_STATE, mask & DDS_ANY_VIEW_STATE, mask & DDS_ANY_INSTANCE_STATE, hand); dds_read_unlock (rd, cond); diff --git a/src/core/ddsc/src/dds_readcond.c b/src/core/ddsc/src/dds_readcond.c index 0de3879..b6d56d3 100644 --- a/src/core/ddsc/src/dds_readcond.c +++ b/src/core/ddsc/src/dds_readcond.c @@ -27,13 +27,20 @@ static dds_return_t dds_readcond_delete (dds_entity *e) return DDS_RETCODE_OK; } +const struct dds_entity_deriver dds_entity_deriver_readcondition = { + .close = dds_entity_deriver_dummy_close, + .delete = dds_readcond_delete, + .set_qos = dds_entity_deriver_dummy_set_qos, + .validate_status = dds_entity_deriver_dummy_validate_status +}; + dds_readcond *dds_create_readcond (dds_reader *rd, dds_entity_kind_t kind, uint32_t mask, dds_querycondition_filter_fn filter) { dds_readcond *cond = dds_alloc (sizeof (*cond)); assert ((kind == DDS_KIND_COND_READ && filter == 0) || (kind == DDS_KIND_COND_QUERY && filter != 0)); (void) dds_entity_init (&cond->m_entity, &rd->m_entity, kind, NULL, NULL, 0); cond->m_entity.m_iid = ddsi_iid_gen (); - cond->m_entity.m_deriver.delete = dds_readcond_delete; + dds_entity_register_child (&rd->m_entity, &cond->m_entity); cond->m_rhc = rd->m_rd->rhc; cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE; cond->m_view_states = mask & DDS_ANY_VIEW_STATE; @@ -47,9 +54,8 @@ dds_readcond *dds_create_readcond (dds_reader *rd, dds_entity_kind_t kind, uint3 if (!dds_rhc_add_readcondition (cond)) { /* FIXME: current entity management code can't deal with an error late in the creation of the - entity because it doesn't allow deleting it again ... instead use a hack to signal a problem - to the caller and let that one handle it. */ - cond->m_entity.m_deriver.delete = 0; + entity because it doesn't allow deleting it again ... */ + abort(); } return cond; } @@ -65,7 +71,6 @@ dds_entity_t dds_create_readcondition (dds_entity_t reader, uint32_t mask) dds_entity_t hdl; dds_readcond *cond = dds_create_readcond(rd, DDS_KIND_COND_READ, mask, 0); assert (cond); - assert (cond->m_entity.m_deriver.delete); hdl = cond->m_entity.m_hdllink.hdl; dds_reader_unlock (rd); return hdl; @@ -76,7 +81,7 @@ dds_entity_t dds_get_datareader (dds_entity_t condition) { struct dds_entity *e; dds_return_t rc; - if ((rc = dds_entity_claim (condition, &e)) != DDS_RETCODE_OK) + if ((rc = dds_entity_pin (condition, &e)) != DDS_RETCODE_OK) return rc; else { @@ -92,7 +97,7 @@ dds_entity_t dds_get_datareader (dds_entity_t condition) rdh = DDS_RETCODE_ILLEGAL_OPERATION; break; } - dds_entity_release (e); + dds_entity_unpin (e); return rdh; } } diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index dd40d40..0006d3a 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -96,13 +96,11 @@ void dds_reader_data_available_cb (struct dds_reader *rd) overhead really matters. Otherwise, it is pretty much like dds_reader_status_cb. */ - ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); - if (!(rd->m_entity.m_status_enable & DDS_DATA_AVAILABLE_STATUS)) - { - ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); + const bool data_av_enabled = (ddsrt_atomic_ld32 (&rd->m_entity.m_status.m_status_and_mask) & (DDS_DATA_AVAILABLE_STATUS << SAM_ENABLED_SHIFT)); + if (!data_av_enabled) return; - } + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); while (rd->m_entity.m_cb_count > 0) ddsrt_cond_wait (&rd->m_entity.m_observers_cond, &rd->m_entity.m_observers_lock); rd->m_entity.m_cb_count++; @@ -136,7 +134,6 @@ void dds_reader_data_available_cb (struct dds_reader *rd) else { dds_entity_status_set (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); - ddsrt_mutex_lock (&sub->m_observers_lock); dds_entity_status_set (sub, DDS_DATA_ON_READERS_STATUS); ddsrt_mutex_unlock (&sub->m_observers_lock); @@ -156,7 +153,7 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) { /* Release the initial claim that was done during the create. This * will indicate that further API deletion is now possible. */ - dds_handle_release (&entity->m_hdllink); + dds_handle_unpin (&entity->m_hdllink); return; } @@ -270,7 +267,7 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) if (invoke) { ddsrt_mutex_unlock (&entity->m_observers_lock); - dds_entity_invoke_listener(entity, status_id, vst); + dds_entity_invoke_listener (entity, status_id, vst); ddsrt_mutex_lock (&entity->m_observers_lock); *reset[0] = 0; if (reset[1]) @@ -278,7 +275,7 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) } else { - dds_entity_status_set (entity, 1u << status_id); + dds_entity_status_set (entity, (status_mask_t) (1u << status_id)); } entity->m_cb_count--; @@ -286,6 +283,13 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) ddsrt_mutex_unlock (&entity->m_observers_lock); } +const struct dds_entity_deriver dds_entity_deriver_reader = { + .close = dds_reader_close, + .delete = dds_reader_delete, + .set_qos = dds_reader_qos_set, + .validate_status = dds_reader_status_validate +}; + dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_entity_t topic, const dds_qos_t *qos, const dds_listener_t *listener) { dds_qos_t *rqos; @@ -312,13 +316,13 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti default: { dds_entity *p_or_s; - if ((ret = dds_entity_claim (participant_or_subscriber, &p_or_s)) != DDS_RETCODE_OK) + if ((ret = dds_entity_pin (participant_or_subscriber, &p_or_s)) != DDS_RETCODE_OK) return ret; if (dds_entity_kind (p_or_s) == DDS_KIND_PARTICIPANT) subscriber = dds_create_subscriber (participant_or_subscriber, qos, NULL); else subscriber = participant_or_subscriber; - dds_entity_release (p_or_s); + dds_entity_unpin (p_or_s); internal_topic = false; t = topic; break; @@ -379,15 +383,11 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED; rd->m_topic = tp; rhc = dds_rhc_new (rd, tp->m_stopic); - dds_entity_add_ref_nolock (&tp->m_entity); - rd->m_entity.m_deriver.close = dds_reader_close; - rd->m_entity.m_deriver.delete = dds_reader_delete; - rd->m_entity.m_deriver.set_qos = dds_reader_qos_set; - rd->m_entity.m_deriver.validate_status = dds_reader_status_validate; + dds_entity_add_ref_locked (&tp->m_entity); /* Extra claim of this reader to make sure that the delete waits until DDSI has deleted its reader as well. This can be known through the callback. */ - dds_handle_claim_inc (&rd->m_entity.m_hdllink); + dds_handle_repin (&rd->m_entity.m_hdllink); ddsrt_mutex_unlock (&tp->m_entity.m_mutex); ddsrt_mutex_unlock (&sub->m_entity.m_mutex); @@ -398,7 +398,9 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti ddsrt_mutex_lock (&tp->m_entity.m_mutex); assert (ret == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */ thread_state_asleep (lookup_thread_state ()); + rd->m_entity.m_iid = get_entity_instance_id (&rd->m_entity.m_guid); + dds_entity_register_child (&sub->m_entity, &rd->m_entity); /* For persistent data register reader with durability */ if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > DDS_DURABILITY_TRANSIENT_LOCAL)) { @@ -429,11 +431,11 @@ err_sub_lock: void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb, void *cbarg) { dds_entity *dds_entity; - if (dds_entity_claim (entity, &dds_entity) != DDS_RETCODE_OK) + if (dds_entity_pin (entity, &dds_entity) != DDS_RETCODE_OK) return; if (dds_entity_kind (dds_entity) != DDS_KIND_READER) { - dds_entity_release (dds_entity); + dds_entity_unpin (dds_entity); return; } @@ -473,7 +475,7 @@ void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb ddsrt_mutex_lock (&rd->e.lock); } ddsrt_mutex_unlock (&rd->e.lock); - dds_entity_release (dds_entity); + dds_entity_unpin (dds_entity); } uint32_t dds_reader_lock_samples (dds_entity_t reader) @@ -513,7 +515,7 @@ dds_entity_t dds_get_subscriber (dds_entity_t entity) { dds_entity *e; dds_return_t ret; - if ((ret = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) + if ((ret = dds_entity_pin (entity, &e)) != DDS_RETCODE_OK) return ret; else { @@ -534,7 +536,7 @@ dds_entity_t dds_get_subscriber (dds_entity_t entity) subh = DDS_RETCODE_ILLEGAL_OPERATION; break; } - dds_entity_release (e); + dds_entity_unpin (e); return subh; } } diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 1d1814d..8849cfb 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -153,6 +153,7 @@ the tkmap data. */ #define MAX_ATTACHED_QUERYCONDS (CHAR_BIT * sizeof (dds_querycond_mask_t)) +#define MAX_FAST_TRIGGERS 32 #define INCLUDE_TRACE 1 #if INCLUDE_TRACE @@ -381,7 +382,7 @@ static void topicless_to_clean_invsample (const struct ddsi_sertopic *topic, con } static unsigned qmask_of_inst (const struct rhc_instance *inst); -static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, const struct trigger_info_pre *pre, const struct trigger_info_post *post, const struct trigger_info_qcond *trig_qc, const struct rhc_instance *inst); +static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, const struct trigger_info_pre *pre, const struct trigger_info_post *post, const struct trigger_info_qcond *trig_qc, const struct rhc_instance *inst, struct dds_entity *triggers[], size_t *ntriggers); #ifndef NDEBUG static int rhc_check_counts_locked (struct rhc *rhc, bool check_conds, bool check_qcmask); #endif @@ -769,16 +770,19 @@ static bool add_sample (struct rhc *rhc, struct rhc_instance *inst, const struct return true; } -static bool content_filter_accepts (const struct ddsi_sertopic *sertopic, const struct ddsi_serdata *sample) +static bool content_filter_accepts (const dds_reader *reader, const struct ddsi_serdata *sample) { bool ret = true; - const struct dds_topic *tp = sertopic->status_cb_entity; - if (tp->filter_fn) + if (reader) { - char *tmp = ddsi_sertopic_alloc_sample (sertopic); - ddsi_serdata_to_sample (sample, tmp, NULL, NULL); - ret = (tp->filter_fn) (tmp, tp->filter_ctx); - ddsi_sertopic_free_sample (sertopic, tmp, DDS_FREE_ALL); + const struct dds_topic *tp = reader->m_topic; + if (tp->filter_fn) + { + char *tmp = ddsi_sertopic_alloc_sample (tp->m_stopic); + ddsi_serdata_to_sample (sample, tmp, NULL, NULL); + ret = (tp->filter_fn) (tmp, tp->filter_ctx); + ddsi_sertopic_free_sample (tp->m_stopic, tmp, DDS_FREE_ALL); + } } return ret; } @@ -822,7 +826,7 @@ static int inst_accepts_sample (const struct rhc *rhc, const struct rhc_instance return 0; } } - if (has_data && !content_filter_accepts (rhc->topic, sample)) + if (has_data && !content_filter_accepts (rhc->reader, sample)) { return 0; } @@ -1166,7 +1170,7 @@ static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst attribute (rather than a key), an empty instance should be instantiated. */ - if (has_data && !content_filter_accepts (rhc->topic, sample)) + if (has_data && !content_filter_accepts (rhc->reader, sample)) { return RHC_FILTERED; } @@ -1225,7 +1229,6 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info struct trigger_info_pre pre; struct trigger_info_post post; struct trigger_info_qcond trig_qc; - bool trigger_waitsets; rhc_store_result_t stored; status_cb_data_t cb_data; /* Callback data for reader status callback */ bool delivered = true; @@ -1440,7 +1443,10 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info TRACE (")\n"); - trigger_waitsets = trigger_info_differs (rhc, &pre, &post, &trig_qc) && update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst); + dds_entity *triggers[MAX_FAST_TRIGGERS]; + size_t ntriggers = 0; + if (trigger_info_differs (rhc, &pre, &post, &trig_qc)) + update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst, triggers, &ntriggers); assert (rhc_check_counts_locked (rhc, true, true)); @@ -1450,8 +1456,8 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info { if (notify_data_available) dds_reader_data_available_cb (rhc->reader); - if (trigger_waitsets) - dds_entity_status_signal (&rhc->reader->m_entity); + for (size_t i = 0; i < ntriggers; i++) + dds_entity_status_signal (triggers[i], 0); } return delivered; @@ -1490,13 +1496,14 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ need to get two IIDs: the one visible to the application in the built-in topics and in get_instance_handle, and one used internally for tracking registrations and unregistrations. */ - bool trigger_waitsets = false; bool notify_data_available = false; struct rhc_instance *inst; struct ddsrt_hh_iter iter; const uint64_t wr_iid = pwr_info->iid; const int auto_dispose = pwr_info->auto_dispose; + size_t ntriggers = SIZE_MAX; + ddsrt_mutex_lock (&rhc->lock); TRACE ("rhc_unregister_wr_iid(%"PRIx64",%d:\n", wr_iid, auto_dispose); for (inst = ddsrt_hh_iter_first (rhc->instances, &iter); inst; inst = ddsrt_hh_iter_next (&iter)) @@ -1538,8 +1545,8 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ TRACE ("\n"); notify_data_available = true; - if (trigger_info_differs (rhc, &pre, &post, &trig_qc) && update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst)) - trigger_waitsets = true; + if (trigger_info_differs (rhc, &pre, &post, &trig_qc)) + update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst, NULL, &ntriggers); assert (rhc_check_counts_locked (rhc, true, false)); } } @@ -1551,8 +1558,6 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ { if (notify_data_available) dds_reader_data_available_cb (rhc->reader); - if (trigger_waitsets) - dds_entity_status_signal (&rhc->reader->m_entity); } } @@ -1726,10 +1731,11 @@ static bool read_sample_update_conditions (struct rhc *rhc, struct trigger_info_ trig_qc->dec_sample_read = sample_wasread; trig_qc->inc_sample_read = true; get_trigger_info_cmn (&post->c, inst); - const bool trigger_waitsets = update_conditions_locked (rhc, false, pre, post, trig_qc, inst); + size_t ntriggers = SIZE_MAX; + update_conditions_locked (rhc, false, pre, post, trig_qc, inst, NULL, &ntriggers); trig_qc->dec_conds_sample = trig_qc->inc_conds_sample = 0; pre->c = post->c; - return trigger_waitsets; + return false; } static bool take_sample_update_conditions (struct rhc *rhc, struct trigger_info_pre *pre, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc, struct rhc_instance *inst, dds_querycond_mask_t conds, bool sample_wasread) @@ -1742,15 +1748,15 @@ static bool take_sample_update_conditions (struct rhc *rhc, struct trigger_info_ trig_qc->dec_conds_sample = conds; trig_qc->dec_sample_read = sample_wasread; get_trigger_info_cmn (&post->c, inst); - const bool trigger_waitsets = update_conditions_locked (rhc, false, pre, post, trig_qc, inst); + size_t ntriggers = SIZE_MAX; + update_conditions_locked (rhc, false, pre, post, trig_qc, inst, NULL, &ntriggers); trig_qc->dec_conds_sample = 0; pre->c = post->c; - return trigger_waitsets; + return false; } static int dds_rhc_read_w_qminv (struct rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, unsigned qminv, dds_instance_handle_t handle, dds_readcond *cond) { - bool trigger_waitsets = false; uint32_t n = 0; if (lock) @@ -1797,8 +1803,7 @@ static int dds_rhc_read_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ if (!sample->isread) { TRACE ("s"); - if (read_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, sample->conds, false)) - trigger_waitsets = true; + read_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, sample->conds, false); sample->isread = true; inst->nvread++; rhc->n_vread++; @@ -1820,8 +1825,7 @@ static int dds_rhc_read_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ if (!inst->inv_isread) { TRACE ("i"); - if (read_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, inst->conds, false)) - trigger_waitsets = true; + read_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, inst->conds, false); inst->inv_isread = 1; rhc->n_invread++; } @@ -1837,13 +1841,13 @@ static int dds_rhc_read_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ } if (nread != inst_nread (inst) || inst_became_old) { + size_t ntriggers = SIZE_MAX; get_trigger_info_cmn (&post.c, inst); assert (trig_qc.dec_conds_invsample == 0); assert (trig_qc.dec_conds_sample == 0); assert (trig_qc.inc_conds_invsample == 0); assert (trig_qc.inc_conds_sample == 0); - if (update_conditions_locked (rhc, false, &pre, &post, &trig_qc, inst)) - trigger_waitsets = true; + update_conditions_locked (rhc, false, &pre, &post, &trig_qc, inst, NULL, &ntriggers); } if (n > n_first) { @@ -1862,19 +1866,15 @@ static int dds_rhc_read_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ TRACE ("read: returning %"PRIu32"\n", n); assert (rhc_check_counts_locked (rhc, true, false)); ddsrt_mutex_unlock (&rhc->lock); - - if (trigger_waitsets) - dds_entity_status_signal (&rhc->reader->m_entity); - assert (n <= INT_MAX); return (int)n; } static int dds_rhc_take_w_qminv (struct rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, unsigned qminv, dds_instance_handle_t handle, dds_readcond *cond) { - bool trigger_waitsets = false; uint64_t iid; uint32_t n = 0; + size_t ntriggers = SIZE_MAX; if (lock) { @@ -1923,8 +1923,7 @@ static int dds_rhc_take_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ } else { - if (take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, sample->conds, sample->isread)) - trigger_waitsets = true; + take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, sample->conds, sample->isread); set_sample_info (info_seq + n, inst, sample); ddsi_serdata_to_sample (sample->sample, values[n], 0, 0); @@ -1963,8 +1962,7 @@ static int dds_rhc_take_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ #ifndef NDEBUG init_trigger_info_qcond (&dummy_trig_qc); #endif - if (take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, inst->conds, inst->inv_isread)) - trigger_waitsets = true; + take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, inst->conds, inst->inv_isread); set_sample_info_invsample (info_seq + n, inst); topicless_to_clean_invsample (rhc->topic, inst->tk->m_sample, values[n], 0, 0); inst_clear_invsample (rhc, inst, &dummy_trig_qc); @@ -1986,8 +1984,7 @@ static int dds_rhc_take_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ assert (trig_qc.dec_conds_sample == 0); assert (trig_qc.inc_conds_invsample == 0); assert (trig_qc.inc_conds_sample == 0); - if (update_conditions_locked (rhc, false, &pre, &post, &trig_qc, inst)) - trigger_waitsets = true; + update_conditions_locked (rhc, false, &pre, &post, &trig_qc, inst, NULL, &ntriggers); } if (inst_is_empty (inst)) @@ -2024,17 +2021,12 @@ static int dds_rhc_take_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ TRACE ("take: returning %"PRIu32"\n", n); assert (rhc_check_counts_locked (rhc, true, false)); ddsrt_mutex_unlock (&rhc->lock); - - if (trigger_waitsets) - dds_entity_status_signal(&rhc->reader->m_entity); - assert (n <= INT_MAX); return (int)n; } static int dds_rhc_takecdr_w_qminv (struct rhc *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, unsigned qminv, dds_instance_handle_t handle, dds_readcond *cond) { - bool trigger_waitsets = false; uint64_t iid; uint32_t n = 0; (void)cond; @@ -2085,9 +2077,7 @@ static int dds_rhc_takecdr_w_qminv (struct rhc *rhc, bool lock, struct ddsi_serd } else { - if (take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, sample->conds, sample->isread)) - trigger_waitsets = true; - + take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, sample->conds, sample->isread); set_sample_info (info_seq + n, inst, sample); values[n] = ddsi_serdata_ref(sample->sample); rhc->n_vsamples--; @@ -2119,8 +2109,7 @@ static int dds_rhc_takecdr_w_qminv (struct rhc *rhc, bool lock, struct ddsi_serd #ifndef NDEBUG init_trigger_info_qcond (&dummy_trig_qc); #endif - if (take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, inst->conds, inst->inv_isread)) - trigger_waitsets = true; + take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, inst->conds, inst->inv_isread); set_sample_info_invsample (info_seq + n, inst); values[n] = ddsi_serdata_ref(inst->tk->m_sample); inst_clear_invsample (rhc, inst, &dummy_trig_qc); @@ -2137,9 +2126,9 @@ static int dds_rhc_takecdr_w_qminv (struct rhc *rhc, bool lock, struct ddsi_serd { /* if nsamples = 0, it won't match anything, so no need to do anything here for drop_instance_noupdate_no_writers */ + size_t ntriggers = SIZE_MAX; get_trigger_info_cmn (&post.c, inst); - if (update_conditions_locked (rhc, false, &pre, &post, &trig_qc, inst)) - trigger_waitsets = true; + update_conditions_locked (rhc, false, &pre, &post, &trig_qc, inst, NULL, &ntriggers); } if (inst_is_empty (inst)) @@ -2176,10 +2165,6 @@ static int dds_rhc_takecdr_w_qminv (struct rhc *rhc, bool lock, struct ddsi_serd TRACE ("take: returning %"PRIu32"\n", n); assert (rhc_check_counts_locked (rhc, true, false)); ddsrt_mutex_unlock (&rhc->lock); - - if (trigger_waitsets) - dds_entity_status_signal (&rhc->reader->m_entity); - assert (n <= INT_MAX); return (int)n; } @@ -2239,7 +2224,7 @@ bool dds_rhc_add_readcondition (dds_readcond *cond) assert ((dds_entity_kind (&cond->m_entity) == DDS_KIND_COND_READ && cond->m_query.m_filter == 0) || (dds_entity_kind (&cond->m_entity) == DDS_KIND_COND_QUERY && cond->m_query.m_filter != 0)); - assert (cond->m_entity.m_trigger == 0); + assert (ddsrt_atomic_ld32 (&cond->m_entity.m_status.m_trigger) == 0); assert (cond->m_query.m_qcmask == 0); cond->m_qminv = qmask_from_dcpsquery (cond->m_sample_states, cond->m_view_states, cond->m_instance_states); @@ -2270,6 +2255,7 @@ bool dds_rhc_add_readcondition (dds_readcond *cond) cond->m_next = rhc->conds; rhc->conds = cond; + uint32_t trigger = 0; if (cond->m_query.m_filter == 0) { /* Read condition is not cached inside the instances and samples, so it only needs @@ -2278,7 +2264,7 @@ bool dds_rhc_add_readcondition (dds_readcond *cond) { struct rhc_instance *inst = rhc->nonempty_instances; do { - cond->m_entity.m_trigger += rhc_get_cond_trigger (inst, cond); + trigger += rhc_get_cond_trigger (inst, cond); inst = inst->next; } while (inst != rhc->nonempty_instances); } @@ -2296,7 +2282,6 @@ bool dds_rhc_add_readcondition (dds_readcond *cond) /* Attaching a query condition means clearing the allocated bit in all instances and samples, except for those that match the predicate. */ const dds_querycond_mask_t qcmask = cond->m_query.m_qcmask; - uint32_t trigger = 0; for (struct rhc_instance *inst = ddsrt_hh_iter_first (rhc->instances, &it); inst != NULL; inst = ddsrt_hh_iter_next (&it)) { const bool instmatch = eval_predicate_invsample (rhc, inst, cond->m_query.m_filter);; @@ -2317,12 +2302,14 @@ bool dds_rhc_add_readcondition (dds_readcond *cond) if (!inst_is_empty (inst) && rhc_get_cond_trigger (inst, cond)) trigger += (inst->inv_exists ? instmatch : 0) + matches; } - cond->m_entity.m_trigger = trigger; } - if (cond->m_entity.m_trigger) - dds_entity_status_signal (&cond->m_entity); - + if (trigger) + { + ddsrt_atomic_st32 (&cond->m_entity.m_status.m_trigger, trigger); + dds_entity_status_signal (&cond->m_entity, DDS_DATA_AVAILABLE_STATUS); + } + TRACE ("add_readcondition(%p, %"PRIx32", %"PRIx32", %"PRIx32") => %p qminv %"PRIx32" ; rhc %"PRIu32" conds\n", (void *) rhc, cond->m_sample_states, cond->m_view_states, cond->m_instance_states, (void *) cond, cond->m_qminv, rhc->nconds); @@ -2356,7 +2343,7 @@ void dds_rhc_remove_readcondition (dds_readcond *cond) ddsrt_mutex_unlock (&rhc->lock); } -static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, const struct trigger_info_pre *pre, const struct trigger_info_post *post, const struct trigger_info_qcond *trig_qc, const struct rhc_instance *inst) +static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, const struct trigger_info_pre *pre, const struct trigger_info_post *post, const struct trigger_info_qcond *trig_qc, const struct rhc_instance *inst, struct dds_entity *triggers[], size_t *ntriggers) { /* Pre: rhc->lock held; returns 1 if triggering required, else 0. */ bool trigger = false; @@ -2417,14 +2404,14 @@ static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, else if (m_pre < m_post) { TRACE ("now matches"); - trigger = (iter->m_entity.m_trigger++ == 0); + trigger = (ddsrt_atomic_inc32_ov (&iter->m_entity.m_status.m_trigger) == 0); if (trigger) TRACE (" (cond now triggers)"); } else { TRACE ("no longer matches"); - if (--iter->m_entity.m_trigger == 0) + if (ddsrt_atomic_dec32_nv (&iter->m_entity.m_status.m_trigger) == 0) TRACE (" (cond no longer triggers)"); } } @@ -2477,19 +2464,19 @@ static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, there is always space for a valid and an invalid sample, both add and remove inserting an update always has unread data added, but a read pretends it is a removal of whatever and an insertion of read data */ - assert (mdelta >= 0 || iter->m_entity.m_trigger >= (uint32_t) -mdelta); + assert (mdelta >= 0 || ddsrt_atomic_ld32 (&iter->m_entity.m_status.m_trigger) >= (uint32_t) -mdelta); if (mdelta == 0) - TRACE ("no change @ %"PRIu32" (0)", iter->m_entity.m_trigger); + TRACE ("no change @ %"PRIu32" (0)", ddsrt_atomic_ld32 (&iter->m_entity.m_status.m_trigger)); else - TRACE ("m=%"PRId32" @ %"PRIu32" (0)", mdelta, iter->m_entity.m_trigger + (uint32_t) mdelta); + TRACE ("m=%"PRId32" @ %"PRIu32" (0)", mdelta, ddsrt_atomic_ld32 (&iter->m_entity.m_status.m_trigger) + (uint32_t) mdelta); /* even though it matches now and matched before, it is not a given that any of the samples matched before, so m_trigger may still be 0 */ - if (mdelta > 0 && iter->m_entity.m_trigger == 0) + const uint32_t ov = ddsrt_atomic_add32_ov (&iter->m_entity.m_status.m_trigger, (uint32_t) mdelta); + if (mdelta > 0 && ov == 0) trigger = true; - iter->m_entity.m_trigger += (uint32_t) mdelta; if (trigger) TRACE (" (cond now triggers)"); - else if (mdelta < 0 && iter->m_entity.m_trigger == 0) + else if (mdelta < 0 && ov == (uint32_t) -mdelta) TRACE (" (cond no longer triggers)"); } else @@ -2509,7 +2496,7 @@ static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, } while (sample != end); } if (mdelta == 0 && mcurrent == 0) - TRACE ("no change @ %"PRIu32" (2)", iter->m_entity.m_trigger); + TRACE ("no change @ %"PRIu32" (2)", ddsrt_atomic_ld32 (&iter->m_entity.m_status.m_trigger)); else if (m_pre < m_post) { /* No match previously, so the instance wasn't accounted for at all in the trigger value. @@ -2519,10 +2506,9 @@ static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, sample, so mrem reflects the state before the change, and the incremental change needs to be taken into account. */ const int32_t m = called_from_insert ? mcurrent : mcurrent + mdelta; - TRACE ("mdelta=%"PRId32" mcurrent=%"PRId32" => %"PRId32" => %"PRIu32" (2a)", mdelta, mcurrent, m, iter->m_entity.m_trigger + (uint32_t) m); - assert (m >= 0 || iter->m_entity.m_trigger >= (uint32_t) -m); - trigger = (iter->m_entity.m_trigger == 0) && m > 0; - iter->m_entity.m_trigger += (uint32_t) m; + TRACE ("mdelta=%"PRId32" mcurrent=%"PRId32" => %"PRId32" => %"PRIu32" (2a)", mdelta, mcurrent, m, ddsrt_atomic_ld32 (&iter->m_entity.m_status.m_trigger) + (uint32_t) m); + assert (m >= 0 || ddsrt_atomic_ld32 (&iter->m_entity.m_status.m_trigger) >= (uint32_t) -m); + trigger = (ddsrt_atomic_add32_ov (&iter->m_entity.m_status.m_trigger, (uint32_t) m) == 0 && m > 0); if (trigger) TRACE (" (cond now triggers)"); } @@ -2532,18 +2518,21 @@ static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, of matches as well as those that were removed just before, hence need the incremental change as well */ const int32_t m = mcurrent - mdelta; - TRACE ("mdelta=%"PRId32" mcurrent=%"PRId32" => %"PRId32" => %"PRIu32" (2b)", mdelta, mcurrent, m, iter->m_entity.m_trigger - (uint32_t) m); - assert (m < 0 || iter->m_entity.m_trigger >= (uint32_t) m); - iter->m_entity.m_trigger -= (uint32_t) m; - if (iter->m_entity.m_trigger == 0) + TRACE ("mdelta=%"PRId32" mcurrent=%"PRId32" => %"PRId32" => %"PRIu32" (2b)", mdelta, mcurrent, m, ddsrt_atomic_ld32 (&iter->m_entity.m_status.m_trigger) - (uint32_t) m); + assert (m < 0 || ddsrt_atomic_ld32 (&iter->m_entity.m_status.m_trigger) >= (uint32_t) m); + if (ddsrt_atomic_sub32_nv (&iter->m_entity.m_status.m_trigger, (uint32_t) m) == 0) TRACE (" (cond no longer triggers)"); } } } - if (iter->m_entity.m_trigger) - dds_entity_status_signal (&iter->m_entity); - + if (trigger) + { + if (*ntriggers < MAX_FAST_TRIGGERS) + triggers[(*ntriggers)++] = &iter->m_entity; + else + dds_entity_status_signal (&iter->m_entity, DDS_DATA_AVAILABLE_STATUS); + } TRACE ("\n"); iter = iter->m_next; } @@ -2717,7 +2706,9 @@ static int rhc_check_counts_locked (struct rhc *rhc, bool check_conds, bool chec if (check_conds) { for (i = 0, rciter = rhc->conds; i < ncheck; i++, rciter = rciter->m_next) - assert (cond_match_count[i] == rciter->m_entity.m_trigger); + { + assert (cond_match_count[i] == ddsrt_atomic_ld32 (&rciter->m_entity.m_status.m_trigger)); + } } if (rhc->n_nonempty_instances == 0) diff --git a/src/core/ddsc/src/dds_sertopic_builtintopic.c b/src/core/ddsc/src/dds_sertopic_builtintopic.c index b38deba..325d536 100644 --- a/src/core/ddsc/src/dds_sertopic_builtintopic.c +++ b/src/core/ddsc/src/dds_sertopic_builtintopic.c @@ -38,8 +38,6 @@ struct ddsi_sertopic *new_sertopic_builtintopic (enum ddsi_sertopic_builtintopic tp->c.ops = &ddsi_sertopic_ops_builtintopic; tp->c.serdata_ops = &ddsi_serdata_ops_builtintopic; tp->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (tp->c.serdata_ops); - tp->c.status_cb = 0; - tp->c.status_cb_entity = NULL; ddsrt_atomic_st32 (&tp->c.refc, 1); tp->type = type; return &tp->c; diff --git a/src/core/ddsc/src/dds_subscriber.c b/src/core/ddsc/src/dds_subscriber.c index 084558d..59bc7d1 100644 --- a/src/core/ddsc/src/dds_subscriber.c +++ b/src/core/ddsc/src/dds_subscriber.c @@ -16,6 +16,7 @@ #include "dds__qos.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_globals.h" +#include "dds/ddsrt/heap.h" #include "dds/version.h" DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_subscriber) @@ -35,6 +36,13 @@ static dds_return_t dds_subscriber_status_validate (uint32_t mask) return (mask & ~DDS_SUBSCRIBER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK; } +const struct dds_entity_deriver dds_entity_deriver_subscriber = { + .close = dds_entity_deriver_dummy_close, + .delete = dds_entity_deriver_dummy_delete, + .set_qos = dds_subscriber_qos_set, + .validate_status = dds_subscriber_status_validate +}; + dds_entity_t dds__create_subscriber_l (dds_participant *participant, const dds_qos_t *qos, const dds_listener_t *listener) { /* participant entity lock must be held */ @@ -56,8 +64,7 @@ dds_entity_t dds__create_subscriber_l (dds_participant *participant, const dds_q sub = dds_alloc (sizeof (*sub)); subscriber = dds_entity_init (&sub->m_entity, &participant->m_entity, DDS_KIND_SUBSCRIBER, new_qos, listener, DDS_SUBSCRIBER_STATUS_MASK); sub->m_entity.m_iid = ddsi_iid_gen (); - sub->m_entity.m_deriver.set_qos = dds_subscriber_qos_set; - sub->m_entity.m_deriver.validate_status = dds_subscriber_status_validate; + dds_entity_register_child (&participant->m_entity, &sub->m_entity); return subscriber; } @@ -77,19 +84,10 @@ dds_return_t dds_notify_readers (dds_entity_t subscriber) { dds_subscriber *sub; dds_return_t ret; - if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK) return ret; - - ret = DDS_RETCODE_UNSUPPORTED; - for (dds_entity *iter = sub->m_entity.m_children; iter; iter = iter->m_next) - { - ddsrt_mutex_lock (&iter->m_mutex); - // FIXME: check if reader has data available, call listener - ddsrt_mutex_unlock(&iter->m_mutex); - } dds_subscriber_unlock (sub); - return ret; + return DDS_RETCODE_UNSUPPORTED; } dds_return_t dds_subscriber_begin_coherent (dds_entity_t e) diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index d7f04c7..aa2a5c5 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -37,12 +37,20 @@ DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_topic) #define DDS_TOPIC_STATUS_MASK \ (DDS_INCONSISTENT_TOPIC_STATUS) -static int strcmp_wrapper (const void *va, const void *vb) +struct topic_sertopic_node { + ddsrt_avl_node_t avlnode; + uint32_t refc; + const struct ddsi_sertopic *st; +}; + +static int topic_sertopic_node_cmp (const void *va, const void *vb) { - return strcmp (va, 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 ddsi_sertopic, avlnode), offsetof (struct ddsi_sertopic, name_type_name), strcmp_wrapper, 0); +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; @@ -72,9 +80,10 @@ static dds_return_t dds_topic_status_validate (uint32_t mask) /* Topic status change callback handler. Supports INCONSISTENT_TOPIC - status (only defined status on a topic). + status (only defined status on a topic). Irrelevant until inconsistent topic + definitions can be detected, so until topic discovery is added. */ - +#if 0 static void dds_topic_status_cb (struct dds_topic *tp) { struct dds_listener const * const lst = &tp->m_entity.m_listener; @@ -99,66 +108,31 @@ static void dds_topic_status_cb (struct dds_topic *tp) ddsrt_cond_broadcast (&tp->m_entity.m_observers_cond); ddsrt_mutex_unlock (&tp->m_entity.m_observers_lock); } - -struct ddsi_sertopic *dds_topic_lookup_locked (dds_domain *domain, const char *name) ddsrt_nonnull_all; - -struct ddsi_sertopic *dds_topic_lookup_locked (dds_domain *domain, const char *name) -{ - ddsrt_avl_iter_t iter; - for (struct ddsi_sertopic *st = ddsrt_avl_iter_first (&dds_topictree_def, &domain->m_topics, &iter); st; st = ddsrt_avl_iter_next (&iter)) - if (strcmp (st->name, name) == 0) - return st; - return NULL; -} +#endif struct ddsi_sertopic *dds_topic_lookup (dds_domain *domain, const char *name) { + const struct ddsi_sertopic key = { .name = (char *) name }; struct ddsi_sertopic *st; + struct topic_sertopic_node *nst; ddsrt_mutex_lock (&dds_global.m_mutex); - st = dds_topic_lookup_locked (domain, name); + 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; } -void dds_topic_free (dds_domainid_t domainid, struct ddsi_sertopic *st) +static bool dds_find_topic_check_and_add_ref (dds_entity_t participant, dds_entity_t topic, const char *name) { - dds_domain *domain; - ddsrt_mutex_lock (&dds_global.m_mutex); - domain = ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &domainid); - if (domain != NULL) - { - assert (ddsrt_avl_lookup (&dds_topictree_def, &domain->m_topics, st->name_type_name) != NULL); - ddsrt_avl_delete (&dds_topictree_def, &domain->m_topics, st); - } - ddsrt_mutex_unlock (&dds_global.m_mutex); - st->status_cb_entity = NULL; - ddsi_sertopic_unref (st); -} + dds_topic *tp; + if (dds_topic_lock (topic, &tp) != DDS_RETCODE_OK) + return false; -static void dds_topic_add_locked (dds_domainid_t id, struct ddsi_sertopic *st) -{ - dds_domain *dom = dds_domain_find_locked (id); - assert (dom); - assert (ddsrt_avl_lookup (&dds_topictree_def, &dom->m_topics, st->name_type_name) == NULL); - ddsrt_avl_insert (&dds_topictree_def, &dom->m_topics, st); -} - -dds_entity_t dds_find_topic (dds_entity_t participant, const char *name) -{ - dds_entity_t tp; - dds_participant *p; - struct ddsi_sertopic *st; - dds_return_t rc; - - if (name == NULL) - return DDS_RETCODE_BAD_PARAMETER; - - if ((rc = dds_participant_lock (participant, &p)) != DDS_RETCODE_OK) - return rc; - - ddsrt_mutex_lock (&dds_global.m_mutex); - if ((st = dds_topic_lookup_locked (p->m_entity.m_domain, name)) == NULL) - tp = DDS_RETCODE_PRECONDITION_NOT_MET; + bool ret; + if (tp->m_entity.m_participant->m_hdllink.hdl != participant || strcmp (tp->m_stopic->name, name) != 0) + ret = false; else { /* FIXME: calling addref is wrong because the Cyclone library has no @@ -166,19 +140,76 @@ dds_entity_t dds_find_topic (dds_entity_t participant, const char *name) won't make the ref count drop to 0. On the other hand, the DDS spec says find_topic (and a second call to create_topic) return a new proxy that must separately be deleted. */ - dds_entity_add_ref (&st->status_cb_entity->m_entity); - tp = st->status_cb_entity->m_entity.m_hdllink.hdl; + dds_entity_add_ref_locked (&tp->m_entity); + ret = true; } - ddsrt_mutex_unlock (&dds_global.m_mutex); - dds_participant_unlock (p); - return tp; + dds_topic_unlock (tp); + return ret; +} + +dds_entity_t dds_find_topic (dds_entity_t participant, const char *name) +{ + dds_entity *pe; + 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) + return ret; + if (dds_entity_kind (pe) != DDS_KIND_PARTICIPANT) + { + dds_entity_unpin (pe); + return DDS_RETCODE_ILLEGAL_OPERATION; + } + + 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)); + + dds_entity_unpin (pe); + return topic; } 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_free (e->m_domainid, ((dds_topic *) e)->m_stopic); + 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); + } + + ddsi_sertopic_unref (tp->m_stopic); + ddsrt_mutex_unlock (&dds_global.m_mutex); return DDS_RETCODE_OK; } @@ -189,14 +220,14 @@ static dds_return_t dds_topic_qos_set (dds_entity *e, const dds_qos_t *qos, bool return DDS_RETCODE_OK; } -static bool dupdef_qos_ok (const dds_qos_t *qos, const struct ddsi_sertopic *st) +static bool dupdef_qos_ok (const dds_qos_t *qos, const dds_topic *tp) { - if ((qos == NULL) != (st->status_cb_entity->m_entity.m_qos == NULL)) + if ((qos == NULL) != (tp->m_entity.m_qos == NULL)) return false; else if (qos == NULL) return true; else - return dds_qos_equal (st->status_cb_entity->m_entity.m_qos, qos); + return dds_qos_equal (tp->m_entity.m_qos, qos); } static bool sertopic_equivalent (const struct ddsi_sertopic *a, const struct ddsi_sertopic *b) @@ -212,11 +243,46 @@ static bool sertopic_equivalent (const struct ddsi_sertopic *a, const struct dds return true; } +static dds_return_t create_topic_topic_arbirary_check_sertopic (dds_entity_t participant, dds_entity_t topic, struct ddsi_sertopic *sertopic, const dds_qos_t *qos) +{ + dds_topic *tp; + dds_return_t ret; + + if (dds_topic_lock (topic, &tp) < 0) + return DDS_RETCODE_NOT_FOUND; + + if (tp->m_entity.m_participant->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 + { + /* FIXME: calling addref is wrong because the Cyclone library has no + knowledge of the reference and hence simply deleting the participant + won't make the ref count drop to 0. On the other hand, the DDS spec + says find_topic (and a second call to create_topic) return a new + proxy that must separately be deleted. */ + dds_entity_add_ref_locked (&tp->m_entity); + ret = DDS_RETCODE_OK; + } + dds_topic_unlock (tp); + return ret; +} + +const struct dds_entity_deriver dds_entity_deriver_topic = { + .close = dds_entity_deriver_dummy_close, + .delete = dds_topic_delete, + .set_qos = dds_topic_qos_set, + .validate_status = dds_topic_status_validate +}; + 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) { - struct ddsi_sertopic *stgeneric; dds_return_t rc; dds_participant *par; + dds_entity *par_ent; dds_topic *top; dds_qos_t *new_qos = NULL; dds_entity_t hdl; @@ -242,68 +308,146 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s if ((rc = nn_xqos_valid (new_qos)) != DDS_RETCODE_OK) goto err_invalid_qos; + /* 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) + goto err_claim_participant; + + /* 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; - /* Check if topic already exists with same name */ - ddsrt_mutex_lock (&dds_global.m_mutex); - if ((stgeneric = dds_topic_lookup_locked (par->m_entity.m_domain, sertopic->name)) != NULL) { - if (!sertopic_equivalent (stgeneric, sertopic)) { - /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */ - rc = DDS_RETCODE_PRECONDITION_NOT_MET; - goto err_mismatch; - } else if (!dupdef_qos_ok (new_qos, stgeneric)) { - /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */ - rc = DDS_RETCODE_INCONSISTENT_POLICY; - goto err_mismatch; - } else { - /* FIXME: calling addref is wrong because the Cyclone library has no - knowledge of the reference and hence simply deleting the participant - won't make the ref count drop to 0. On the other hand, the DDS spec - says find_topic (and a second call to create_topic) return a new - proxy that must separately be deleted. */ - dds_entity_add_ref (&stgeneric->status_cb_entity->m_entity); - hdl = stgeneric->status_cb_entity->m_entity.m_hdllink.hdl; - dds_delete_qos (new_qos); - } - ddsrt_mutex_unlock (&dds_global.m_mutex); - } else { - /* Create topic */ - top = dds_alloc (sizeof (*top)); - hdl = dds_entity_init (&top->m_entity, &par->m_entity, DDS_KIND_TOPIC, new_qos, listener, DDS_TOPIC_STATUS_MASK); - top->m_entity.m_iid = ddsi_iid_gen (); - top->m_entity.m_deriver.delete = dds_topic_delete; - top->m_entity.m_deriver.set_qos = dds_topic_qos_set; - top->m_entity.m_deriver.validate_status = dds_topic_status_validate; - top->m_stopic = ddsi_sertopic_ref (sertopic); - sertopic->status_cb_entity = top; + bool retry_lookup; + do { + dds_entity_t topic; - /* Add topic to extent */ - dds_topic_add_locked (par->m_entity.m_domainid, sertopic); - ddsrt_mutex_unlock (&dds_global.m_mutex); - - /* Publish Topic */ - thread_state_awake (lookup_thread_state ()); - ddsi_pp = ephash_lookup_participant_guid (&par->m_entity.m_guid); - assert (ddsi_pp); - if (sedp_plist) + /* 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)) { - 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); + 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_arbirary_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 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; } - thread_state_asleep (lookup_thread_state ()); } + + /* Create topic */ + top = dds_alloc (sizeof (*top)); + hdl = dds_entity_init (&top->m_entity, &par->m_entity, DDS_KIND_TOPIC, new_qos, listener, DDS_TOPIC_STATUS_MASK); + 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 ()); + ddsi_pp = ephash_lookup_participant_guid (&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_participant_unlock (par); + dds_entity_unpin (par_ent); return hdl; -err_mismatch: - ddsrt_mutex_unlock (&dds_global.m_mutex); +err_sertopic_reuse: dds_participant_unlock (par); err_lock_participant: + dds_entity_unpin (par_ent); +err_claim_participant: err_invalid_qos: dds_delete_qos (new_qos); return rc; @@ -330,8 +474,6 @@ dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descrip ddsrt_atomic_st32 (&st->c.refc, 1); st->c.iid = ddsi_iid_gen (); - st->c.status_cb = dds_topic_status_cb; - st->c.status_cb_entity = NULL; /* set by dds_create_topic_arbitrary */ st->c.name_type_name = key; st->c.name = ddsrt_strdup (name); st->c.type_name = ddsrt_strdup (typename); diff --git a/src/core/ddsc/src/dds_waitset.c b/src/core/ddsc/src/dds_waitset.c index 004f1e6..1305979 100644 --- a/src/core/ddsc/src/dds_waitset.c +++ b/src/core/ddsc/src/dds_waitset.c @@ -22,127 +22,96 @@ DEFINE_ENTITY_LOCK_UNLOCK (static, dds_waitset, DDS_KIND_WAITSET) -static void dds_waitset_swap (dds_attachment **dst, dds_attachment **src, dds_attachment *prev, dds_attachment *idx) +static bool is_triggered (struct dds_entity *e) { - /* Remove from source. */ - if (prev == NULL) - *src = idx->next; - else - prev->next = idx->next; - - /* Add to destination. */ - idx->next = *dst; - *dst = idx; + bool t; + switch (e->m_kind) + { + case DDS_KIND_COND_READ: + case DDS_KIND_COND_QUERY: + case DDS_KIND_COND_GUARD: + case DDS_KIND_WAITSET: + t = ddsrt_atomic_ld32 (&e->m_status.m_trigger) != 0; + break; + default: + t = (ddsrt_atomic_ld32 (&e->m_status.m_status_and_mask) & SAM_STATUS_MASK) != 0; + break; + } + return t; } static dds_return_t dds_waitset_wait_impl (dds_entity_t waitset, dds_attach_t *xs, size_t nxs, dds_time_t abstimeout) { dds_waitset *ws; dds_return_t ret; - dds_attachment *idx; - dds_attachment *prev; - if (xs == NULL && nxs != 0) - return DDS_RETCODE_BAD_PARAMETER; - if (xs != NULL && nxs == 0) + if ((xs == NULL) != (nxs == 0)) return DDS_RETCODE_BAD_PARAMETER; /* Locking the waitset here will delay a possible deletion until it is * unlocked. Even when the related mutex is unlocked by a conditioned wait. */ - if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK) - return ret; + { + dds_entity *ent; + if ((ret = dds_entity_pin (waitset, &ent)) != DDS_RETCODE_OK) + return ret; + if (dds_entity_kind (ent) != DDS_KIND_WAITSET) + { + dds_entity_unpin (ent); + return DDS_RETCODE_ILLEGAL_OPERATION; + } + ws = (dds_waitset *) ent; + } /* Move any previously but no longer triggering entities back to the observed list */ - idx = ws->triggered; - prev = NULL; - while (idx != NULL) + ddsrt_mutex_lock (&ws->m_entity.m_mutex); + ws->ntriggered = 0; + for (size_t i = 0; i < ws->nentities; i++) { - dds_attachment *next = idx->next; - if (idx->entity->m_trigger == 0) - dds_waitset_swap (&ws->observed, &ws->triggered, prev, idx); - else - prev = idx; - idx = next; - } - /* Check if any of the observed entities are currently triggered, moving them - to the triggered list */ - idx = ws->observed; - prev = NULL; - while (idx != NULL) - { - dds_attachment *next = idx->next; - if (idx->entity->m_trigger > 0) - dds_waitset_swap (&ws->triggered, &ws->observed, prev, idx); - else - prev = idx; - idx = next; + if (is_triggered (ws->entities[i].entity)) + { + dds_attachment tmp = ws->entities[i]; + ws->entities[i] = ws->entities[ws->ntriggered]; + ws->entities[ws->ntriggered++] = tmp; + } } /* Only wait/keep waiting when we have something to observe and there aren't any triggers yet. */ - while (ws->observed != NULL && ws->triggered == NULL) + while (ws->nentities > 0 && ws->ntriggered == 0) if (!ddsrt_cond_waituntil (&ws->m_entity.m_cond, &ws->m_entity.m_mutex, abstimeout)) break; - /* Get number of triggered entities - * - set attach array when needed - * - swap them back to observed */ - ret = 0; - idx = ws->triggered; - while (idx != NULL) - { - if ((uint32_t) ret < (uint32_t) nxs) - xs[ret] = idx->arg; - ret++; - - /* The idx is always the first in triggered, so no prev. */ - dds_attachment *next = idx->next; - dds_waitset_swap (&ws->observed, &ws->triggered, NULL, idx); - idx = next; - } - dds_waitset_unlock (ws); + ret = (int32_t) ws->ntriggered; + for (size_t i = 0; i < ws->ntriggered && i < nxs; i++) + xs[i] = ws->entities[i].arg; + ddsrt_mutex_unlock (&ws->m_entity.m_mutex); + dds_entity_unpin (&ws->m_entity); return ret; } -static void dds_waitset_close_list (dds_attachment **list, dds_entity_t waitset) -{ - dds_attachment *idx = *list; - dds_attachment *next; - while (idx != NULL) - { - next = idx->next; - (void) dds_entity_observer_unregister (idx->entity->m_hdllink.hdl, waitset); - ddsrt_free (idx); - idx = next; - } - *list = NULL; -} - -static bool dds_waitset_remove_from_list (dds_attachment **list, dds_entity_t observed) -{ - dds_attachment *idx, *prev; - for (idx = *list, prev = NULL; idx != NULL; prev = idx, idx = idx->next) - if (idx->entity->m_hdllink.hdl == observed) - break; - if (idx == NULL) - return false; - - if (prev == NULL) - *list = idx->next; - else - prev->next = idx->next; - ddsrt_free (idx); - return true; -} - static dds_return_t dds_waitset_close (struct dds_entity *e) { + /* deep in the process of deleting the entity, so this is the only thread */ dds_waitset *ws = (dds_waitset *) e; - dds_waitset_close_list (&ws->observed, e->m_hdllink.hdl); - dds_waitset_close_list (&ws->triggered, e->m_hdllink.hdl); - ddsrt_cond_broadcast (&e->m_cond); + for (size_t i = 0; i < ws->nentities; i++) + (void) dds_entity_observer_unregister (ws->entities[i].entity, &ws->m_entity); return DDS_RETCODE_OK; } +static dds_return_t dds_waitset_delete (struct dds_entity *e) +{ + /* deep in the process of deleting the entity, so this is the only thread */ + dds_waitset *ws = (dds_waitset *) e; + ddsrt_free (ws->entities); + return DDS_RETCODE_OK; +} + +const struct dds_entity_deriver dds_entity_deriver_waitset = { + .close = dds_waitset_close, + .delete = dds_waitset_delete, + .set_qos = dds_entity_deriver_dummy_set_qos, + .validate_status = dds_entity_deriver_dummy_validate_status +}; + dds_entity_t dds_create_waitset (dds_entity_t participant) { dds_entity_t hdl; @@ -155,14 +124,14 @@ dds_entity_t dds_create_waitset (dds_entity_t participant) dds_waitset *waitset = dds_alloc (sizeof (*waitset)); hdl = dds_entity_init (&waitset->m_entity, &par->m_entity, DDS_KIND_WAITSET, NULL, NULL, 0); waitset->m_entity.m_iid = ddsi_iid_gen (); - waitset->m_entity.m_deriver.close = dds_waitset_close; - waitset->observed = NULL; - waitset->triggered = NULL; + dds_entity_register_child (&par->m_entity, &waitset->m_entity); + waitset->nentities = 0; + waitset->ntriggered = 0; + waitset->entities = NULL; dds_participant_unlock (par); return hdl; } - dds_return_t dds_waitset_get_entities (dds_entity_t waitset, dds_entity_t *entities, size_t size) { dds_return_t ret; @@ -171,62 +140,72 @@ dds_return_t dds_waitset_get_entities (dds_entity_t waitset, dds_entity_t *entit if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK) return ret; - ret = 0; - for (dds_attachment *iter = ws->observed; iter != NULL; iter = iter->next) + if (entities != NULL) { - if ((size_t) ret < size && entities != NULL) - entities[ret] = iter->entity->m_hdllink.hdl; - ret++; + for (size_t i = 0; i < ws->nentities && i < size; i++) + entities[i] = ws->entities[i].handle; } - for (dds_attachment *iter = ws->triggered; iter != NULL; iter = iter->next) - { - if ((size_t) ret < size && entities != NULL) - entities[ret] = iter->entity->m_hdllink.hdl; - ret++; - } - dds_waitset_unlock(ws); + ret = (int32_t) ws->nentities; + dds_waitset_unlock (ws); return ret; } -static void dds_waitset_move (dds_attachment **src, dds_attachment **dst, dds_entity_t entity) -{ - dds_attachment *idx, *prev; - for (idx = *src, prev = NULL; idx != NULL; prev = idx, idx = idx->next) - if (idx->entity->m_hdllink.hdl == entity) - break; - if (idx != NULL) - { - /* Swap idx from src to dst. */ - dds_waitset_swap (dst, src, prev, idx); - } -} - static void dds_waitset_remove (dds_waitset *ws, dds_entity_t observed) { - if (!dds_waitset_remove_from_list (&ws->observed, observed)) - (void) dds_waitset_remove_from_list (&ws->triggered, observed); + size_t i; + for (i = 0; i < ws->nentities; i++) + if (ws->entities[i].handle == observed) + break; + if (i < ws->nentities) + { + if (i < ws->ntriggered) + { + ws->entities[i] = ws->entities[--ws->ntriggered]; + ws->entities[ws->ntriggered] = ws->entities[--ws->nentities]; + } + else + { + ws->entities[i] = ws->entities[--ws->nentities]; + } + return; + } } /* This is called when the observed entity signals a status change. */ -static void dds_waitset_observer (dds_entity_t observer, dds_entity_t observed, uint32_t status) +static void dds_waitset_observer (dds_entity *ent, dds_entity_t observed, uint32_t status) { - dds_waitset *ws; - if (dds_waitset_lock (observer, &ws) == DDS_RETCODE_OK) { - if (status & DDS_DELETING_STATUS) { - /* Remove this observed entity, which is being deleted, from the waitset. */ - dds_waitset_remove (ws, observed); - /* Our registration to this observed entity will be removed automatically. */ - } else if (status != 0) { - /* Move observed entity to triggered list. */ - dds_waitset_move (&ws->observed, &ws->triggered, observed); - } else { - /* Remove observed entity from triggered list (which it possibly resides in). */ - dds_waitset_move (&ws->triggered, &ws->observed, observed); - } - /* Trigger waitset to wake up. */ - ddsrt_cond_broadcast (&ws->m_entity.m_cond); - dds_waitset_unlock (ws); + assert (dds_entity_kind (ent) == DDS_KIND_WAITSET); + dds_waitset *ws = (dds_waitset *) ent; + (void) status; + + ddsrt_mutex_lock (&ws->m_entity.m_mutex); + /* Move observed entity to triggered list. */ + size_t i; + for (i = 0; i < ws->nentities; i++) + if (ws->entities[i].handle == observed) + break; + if (i < ws->nentities && i >= ws->ntriggered) + { + dds_attachment tmp = ws->entities[i]; + ws->entities[i] = ws->entities[ws->ntriggered]; + ws->entities[ws->ntriggered++] = tmp; } + /* Trigger waitset to wake up. */ + ddsrt_cond_broadcast (&ws->m_entity.m_cond); + ddsrt_mutex_unlock (&ws->m_entity.m_mutex); +} + +static void dds_waitset_delete_observer (dds_entity *ent, dds_entity_t observed) +{ + assert (dds_entity_kind (ent) == DDS_KIND_WAITSET); + dds_waitset *ws = (dds_waitset *) ent; + ddsrt_mutex_lock (&ws->m_entity.m_mutex); + /* Remove this observed entity, which is being deleted, from the waitset. */ + dds_waitset_remove (ws, observed); + /* Our registration to this observed entity will be removed automatically. */ + /* Trigger waitset to wake up. */ + ddsrt_cond_broadcast (&ws->m_entity.m_cond); + ddsrt_mutex_unlock (&ws->m_entity.m_mutex); } dds_return_t dds_waitset_attach (dds_entity_t waitset, dds_entity_t entity, dds_attach_t x) @@ -235,35 +214,35 @@ dds_return_t dds_waitset_attach (dds_entity_t waitset, dds_entity_t entity, dds_ dds_waitset *ws; dds_return_t ret; - if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK) + if ((ret = dds_waitset_lock (waitset, &ws)) < 0) return ret; if (waitset == entity) e = &ws->m_entity; - else if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) - { - ret = DDS_RETCODE_BAD_PARAMETER; + else if ((ret = dds_entity_pin (entity, &e)) < 0) goto err_waitset; - } /* This will fail if given entity is already attached (or deleted). */ - if ((ret = dds_entity_observer_register_nl (e, waitset, dds_waitset_observer)) != DDS_RETCODE_OK) + if ((ret = dds_entity_observer_register (e, &ws->m_entity, dds_waitset_observer, dds_waitset_delete_observer)) != DDS_RETCODE_OK) goto err_entity; - dds_attachment *a = ddsrt_malloc (sizeof (*a)); - a->arg = x; - a->entity = e; - if (e->m_trigger > 0) { - a->next = ws->triggered; - ws->triggered = a; - } else { - a->next = ws->observed; - ws->observed = a; + ws->entities = ddsrt_realloc (ws->entities, (ws->nentities + 1) * sizeof (*ws->entities)); + ws->entities[ws->nentities].arg = x; + ws->entities[ws->nentities].entity = e; + ws->entities[ws->nentities].handle = e->m_hdllink.hdl; + ws->nentities++; + if (is_triggered (e)) + { + const size_t i = ws->nentities - 1; + dds_attachment tmp = ws->entities[i]; + ws->entities[i] = ws->entities[ws->ntriggered]; + ws->entities[ws->ntriggered++] = tmp; } + ddsrt_cond_broadcast (&ws->m_entity.m_cond); err_entity: if (e != &ws->m_entity) - dds_entity_unlock (e); + dds_entity_unpin (e); err_waitset: dds_waitset_unlock (ws); return ret; @@ -272,6 +251,7 @@ err_waitset: dds_return_t dds_waitset_detach (dds_entity_t waitset, dds_entity_t entity) { dds_waitset *ws; + dds_entity *e; dds_return_t ret; if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK) @@ -279,12 +259,19 @@ dds_return_t dds_waitset_detach (dds_entity_t waitset, dds_entity_t entity) /* Possibly fails when entity was not attached. */ if (waitset == entity) - ret = dds_entity_observer_unregister_nl (&ws->m_entity, waitset); + ret = dds_entity_observer_unregister (&ws->m_entity, &ws->m_entity); + else if ((ret = dds_entity_pin (entity, &e)) < 0) + ; /* entity invalid */ else - ret = dds_entity_observer_unregister (entity, waitset); + { + ret = dds_entity_observer_unregister (e, &ws->m_entity); + dds_entity_unpin (e); + } if (ret == DDS_RETCODE_OK) + { dds_waitset_remove (ws, entity); + } else { if (ret != DDS_RETCODE_PRECONDITION_NOT_MET) @@ -296,7 +283,7 @@ dds_return_t dds_waitset_detach (dds_entity_t waitset, dds_entity_t entity) dds_return_t dds_waitset_wait_until (dds_entity_t waitset, dds_attach_t *xs, size_t nxs, dds_time_t abstimeout) { - return dds_waitset_wait_impl(waitset, xs, nxs, abstimeout); + return dds_waitset_wait_impl (waitset, xs, nxs, abstimeout); } dds_return_t dds_waitset_wait (dds_entity_t waitset, dds_attach_t *xs, size_t nxs, dds_duration_t reltimeout) @@ -310,22 +297,21 @@ dds_return_t dds_waitset_wait (dds_entity_t waitset, dds_attach_t *xs, size_t nx dds_return_t dds_waitset_set_trigger (dds_entity_t waitset, bool trigger) { - dds_waitset *ws; + dds_entity *ent; dds_return_t rc; - if ((rc = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK) + if ((rc = dds_entity_pin (waitset, &ent)) != DDS_RETCODE_OK) return rc; + else if (dds_entity_kind (ent) != DDS_KIND_WAITSET) + { + dds_entity_unpin (ent); + return DDS_RETCODE_ILLEGAL_OPERATION; + } - ddsrt_mutex_unlock (&ws->m_entity.m_mutex); + ddsrt_mutex_lock (&ent->m_observers_lock); + dds_entity_trigger_set (ent, trigger); + ddsrt_mutex_unlock (&ent->m_observers_lock); - ddsrt_mutex_lock (&ws->m_entity.m_observers_lock); - if (trigger) - dds_entity_status_set (&ws->m_entity, DDS_WAITSET_TRIGGER_STATUS); - else - dds_entity_status_reset (&ws->m_entity, DDS_WAITSET_TRIGGER_STATUS); - ddsrt_mutex_unlock (&ws->m_entity.m_observers_lock); - - ddsrt_mutex_lock (&ws->m_entity.m_mutex); - dds_waitset_unlock (ws); + dds_entity_unpin (ent); return DDS_RETCODE_OK; } diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 1a404e9..856d828 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -13,6 +13,7 @@ #include "dds/dds.h" #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/q_entity.h" @@ -57,7 +58,7 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) { /* Release the initial claim that was done during the create. This * will indicate that further API deletion is now possible. */ - dds_handle_release (&entity->m_hdllink); + dds_handle_unpin (&entity->m_hdllink); return; } @@ -74,7 +75,7 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) /* Reset the status for possible Listener call. * When a listener is not called, the status will be set (again). */ - dds_entity_status_reset (entity, 1u << status_id); + dds_entity_status_reset (entity, (status_mask_t) (1u << status_id)); /* Update status metrics. */ dds_writer * const wr = (dds_writer *) entity; @@ -146,7 +147,7 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) } else { - dds_entity_status_set (entity, 1u << status_id); + dds_entity_status_set (entity, (status_mask_t) (1u << status_id)); } entity->m_cb_count--; @@ -236,6 +237,13 @@ static struct whc *make_whc (const dds_qos_t *qos) return whc_new (handle_as_transient_local, hdepth, tldepth); } +const struct dds_entity_deriver dds_entity_deriver_writer = { + .close = dds_writer_close, + .delete = dds_writer_delete, + .set_qos = dds_writer_qos_set, + .validate_status = dds_writer_status_validate +}; + dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entity_t topic, const dds_qos_t *qos, const dds_listener_t *listener) { dds_return_t rc; @@ -249,13 +257,13 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit { dds_entity *p_or_p; - if ((rc = dds_entity_claim (participant_or_publisher, &p_or_p)) != DDS_RETCODE_OK) + if ((rc = dds_entity_pin (participant_or_publisher, &p_or_p)) != DDS_RETCODE_OK) return rc; if (dds_entity_kind (p_or_p) == DDS_KIND_PARTICIPANT) publisher = dds_create_publisher(participant_or_publisher, qos, NULL); else publisher = participant_or_publisher; - dds_entity_release (p_or_p); + dds_entity_unpin (p_or_p); } if ((rc = dds_publisher_lock (publisher, &pub)) != DDS_RETCODE_OK) @@ -291,17 +299,13 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit writer = dds_entity_init (&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK); wr->m_topic = tp; - dds_entity_add_ref_nolock (&tp->m_entity); + dds_entity_add_ref_locked (&tp->m_entity); wr->m_xp = nn_xpack_new (conn, get_bandwidth_limit (wqos->transport_priority), config.xpack_send_async); - wr->m_entity.m_deriver.close = dds_writer_close; - wr->m_entity.m_deriver.delete = dds_writer_delete; - wr->m_entity.m_deriver.set_qos = dds_writer_qos_set; - wr->m_entity.m_deriver.validate_status = dds_writer_status_validate; wr->m_whc = make_whc (wqos); /* Extra claim of this writer to make sure that the delete waits until DDSI * has deleted its writer as well. This can be known through the callback. */ - dds_handle_claim_inc (&wr->m_entity.m_hdllink); + dds_handle_repin (&wr->m_entity.m_hdllink); ddsrt_mutex_unlock (&tp->m_entity.m_mutex); ddsrt_mutex_unlock (&pub->m_entity.m_mutex); @@ -312,7 +316,10 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit ddsrt_mutex_lock (&tp->m_entity.m_mutex); assert(rc == DDS_RETCODE_OK); thread_state_asleep (lookup_thread_state ()); + wr->m_entity.m_iid = get_entity_instance_id (&wr->m_entity.m_guid); + dds_entity_register_child (&pub->m_entity, &wr->m_entity); + dds_topic_unlock (tp); dds_publisher_unlock (pub); return writer; @@ -331,7 +338,7 @@ dds_entity_t dds_get_publisher (dds_entity_t writer) { dds_entity *e; dds_return_t rc; - if ((rc = dds_entity_claim (writer, &e)) != DDS_RETCODE_OK) + if ((rc = dds_entity_pin (writer, &e)) != DDS_RETCODE_OK) return rc; else { @@ -343,7 +350,7 @@ dds_entity_t dds_get_publisher (dds_entity_t writer) assert (dds_entity_kind (e->m_parent) == DDS_KIND_PUBLISHER); pubh = e->m_parent->m_hdllink.hdl; } - dds_entity_release (e); + dds_entity_unpin (e); return pubh; } } diff --git a/src/core/ddsc/tests/instance_get_key.c b/src/core/ddsc/tests/instance_get_key.c index 9c25d1a..54b1aa5 100644 --- a/src/core/ddsc/tests/instance_get_key.c +++ b/src/core/ddsc/tests/instance_get_key.c @@ -63,7 +63,7 @@ CU_Test(ddsc_instance_get_key, bad_entity, .init=setup, .fini=teardown) dds_return_t ret; ret = dds_instance_get_key(participant, handle, &data); - CU_ASSERT_EQUAL(ret, DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_ILLEGAL_OPERATION); } CU_Test(ddsc_instance_get_key, null_data, .init=setup, .fini=teardown) diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h index 3f7ae75..b423101 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h @@ -29,7 +29,6 @@ typedef void (*topic_cb_t) (struct dds_topic * topic); struct ddsi_sertopic_ops; struct ddsi_sertopic { - ddsrt_avl_node_t avlnode; /* index on name_typename */ const struct ddsi_sertopic_ops *ops; const struct ddsi_serdata_ops *serdata_ops; uint32_t serdata_basehash; @@ -38,9 +37,6 @@ struct ddsi_sertopic { char *type_name; uint64_t iid; ddsrt_atomic_uint32_t refc; /* counts refs from entities, not from data */ - - topic_cb_t status_cb; - struct dds_topic * status_cb_entity; }; /* Called when the refcount dropped to zero */ diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 1aa7ca0..a6090a2 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -2063,19 +2063,12 @@ static void writer_qos_mismatch (struct writer * wr, dds_qos_policy_id_t reason) { /* When the reason is DDS_INVALID_QOS_POLICY_ID, it means that we compared * readers/writers from different topics: ignore that. */ - if (reason != DDS_INVALID_QOS_POLICY_ID) + if (reason != DDS_INVALID_QOS_POLICY_ID && wr->status_cb) { - if (wr->topic->status_cb) { - /* Handle INCONSISTENT_TOPIC on topic */ - (wr->topic->status_cb) (wr->topic->status_cb_entity); - } - if (wr->status_cb) - { - status_cb_data_t data; - data.raw_status_id = (int) DDS_OFFERED_INCOMPATIBLE_QOS_STATUS_ID; - data.extra = reason; - (wr->status_cb) (wr->status_cb_entity, &data); - } + status_cb_data_t data; + data.raw_status_id = (int) DDS_OFFERED_INCOMPATIBLE_QOS_STATUS_ID; + data.extra = reason; + (wr->status_cb) (wr->status_cb_entity, &data); } } @@ -2083,20 +2076,12 @@ static void reader_qos_mismatch (struct reader * rd, dds_qos_policy_id_t reason) { /* When the reason is DDS_INVALID_QOS_POLICY_ID, it means that we compared * readers/writers from different topics: ignore that. */ - if (reason != DDS_INVALID_QOS_POLICY_ID) + if (reason != DDS_INVALID_QOS_POLICY_ID && rd->status_cb) { - if (rd->topic->status_cb) - { - /* Handle INCONSISTENT_TOPIC on topic */ - (rd->topic->status_cb) (rd->topic->status_cb_entity); - } - if (rd->status_cb) - { - status_cb_data_t data; - data.raw_status_id = (int) DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS_ID; - data.extra = reason; - (rd->status_cb) (rd->status_cb_entity, &data); - } + status_cb_data_t data; + data.raw_status_id = (int) DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS_ID; + data.extra = reason; + (rd->status_cb) (rd->status_cb_entity, &data); } } diff --git a/src/core/xtests/rhc_torture/rhc_torture.c b/src/core/xtests/rhc_torture/rhc_torture.c index 1254b5e..8509195 100644 --- a/src/core/xtests/rhc_torture/rhc_torture.c +++ b/src/core/xtests/rhc_torture/rhc_torture.c @@ -982,6 +982,7 @@ int main (int argc, char **argv) for (size_t i = 0; i < sizeof (rres_iseq) / sizeof (rres_iseq[0]); i++) RhcTypes_T_free (&rres_mseq[i], DDS_FREE_CONTENTS); + ddsi_sertopic_unref (mdtopic); dds_delete(pp); return 0; } From 12d2a82823ec827464ac51d771baef29c15a5b6b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 12 Jun 2019 16:27:25 +0200 Subject: [PATCH 113/178] Remove superfluous lock/unlock pairs in read Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_read.c | 126 +++++++++++++++++------------------ src/tools/ddsperf/ddsperf.c | 2 +- 2 files changed, 62 insertions(+), 66 deletions(-) diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index b4ede31..09139f5 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -21,50 +21,6 @@ #include "dds/ddsi/q_globals.h" #include "dds/ddsi/ddsi_sertopic.h" -static dds_return_t dds_read_lock (dds_entity_t hdl, dds_reader **reader, dds_readcond **condition, bool only_reader) -{ - dds_return_t rc; - dds_entity *entity, *parent_entity; - if ((rc = dds_entity_lock (hdl, DDS_KIND_DONTCARE, &entity)) != DDS_RETCODE_OK) - { - return rc; - } - else if (dds_entity_kind (entity) == DDS_KIND_READER) - { - *reader = (dds_reader *) entity; - *condition = NULL; - return DDS_RETCODE_OK; - } - else if (only_reader) - { - dds_entity_unlock (entity); - return DDS_RETCODE_ILLEGAL_OPERATION; - } - else if (dds_entity_kind (entity) != DDS_KIND_COND_READ && dds_entity_kind (entity) != DDS_KIND_COND_QUERY) - { - dds_entity_unlock (entity); - return DDS_RETCODE_ILLEGAL_OPERATION; - } - else if ((rc = dds_entity_lock (entity->m_parent->m_hdllink.hdl, DDS_KIND_READER, &parent_entity)) != DDS_RETCODE_OK) - { - dds_entity_unlock (entity); - return rc; - } - else - { - *reader = (dds_reader *) parent_entity; - *condition = (dds_readcond *) entity; - return DDS_RETCODE_OK; - } -} - -static void dds_read_unlock (dds_reader *reader, dds_readcond *condition) -{ - dds_entity_unlock (&reader->m_entity); - if (condition) - dds_entity_unlock (&condition->m_entity); -} - /* dds_read_impl: Core read/take function. Usually maxs is size of buf and si into which samples/status are written, when set to zero is special case @@ -76,6 +32,7 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, { struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; + struct dds_entity *entity; struct dds_reader *rd; struct dds_readcond *cond; unsigned nodata_cleanups = 0; @@ -87,14 +44,28 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, return DDS_RETCODE_BAD_PARAMETER; thread_state_awake (ts1); - if ((ret = dds_read_lock (reader_or_condition, &rd, &cond, only_reader)) != DDS_RETCODE_OK) + + if ((ret = dds_entity_pin (reader_or_condition, &entity)) < 0) { goto fail_awake; + } else if (dds_entity_kind (entity) == DDS_KIND_READER) { + rd = (dds_reader *) entity; + cond = NULL; + } else if (only_reader) { + ret = DDS_RETCODE_ILLEGAL_OPERATION; + goto fail_awake_pinned; + } else if (dds_entity_kind (entity) != DDS_KIND_COND_READ && dds_entity_kind (entity) != DDS_KIND_COND_QUERY) { + ret = DDS_RETCODE_ILLEGAL_OPERATION; + goto fail_awake_pinned; + } else { + rd = (dds_reader *) entity->m_parent; + cond = (dds_readcond *) entity; + } if (hand != DDS_HANDLE_NIL) { if (ddsi_tkmap_find_by_id (gv.m_tkmap, hand) == NULL) { ret = DDS_RETCODE_PRECONDITION_NOT_MET; - goto fail_awake_lock; + goto fail_awake_pinned; } } @@ -102,6 +73,7 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, if (buf[0] == NULL) { /* Allocate, use or reallocate loan cached on reader */ + ddsrt_mutex_lock (&rd->m_entity.m_mutex); if (rd->m_loan_out) { ddsi_sertopic_realloc_samples (buf, rd->m_topic->m_stopic, NULL, 0, maxs); @@ -130,6 +102,7 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, rd->m_loan_out = true; nodata_cleanups |= NC_CLEAR_LOAN_OUT; } + ddsrt_mutex_unlock (&rd->m_entity.m_mutex); } /* read/take resets data available status -- must reset before reading because @@ -150,14 +123,16 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, rd->m_loan */ if (ret <= 0 && nodata_cleanups) { + ddsrt_mutex_lock (&rd->m_entity.m_mutex); if (nodata_cleanups & NC_CLEAR_LOAN_OUT) rd->m_loan_out = false; if (nodata_cleanups & NC_FREE_BUF) ddsi_sertopic_free_samples (rd->m_topic->m_stopic, buf[0], maxs, DDS_FREE_ALL); if (nodata_cleanups & NC_RESET_BUF) buf[0] = NULL; + ddsrt_mutex_unlock (&rd->m_entity.m_mutex); } - dds_read_unlock (rd, cond); + dds_entity_unpin (entity); thread_state_asleep (ts1); return ret; @@ -165,8 +140,8 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, #undef NC_FREE_BUF #undef NC_RESET_BUF -fail_awake_lock: - dds_read_unlock (rd, cond); +fail_awake_pinned: + dds_entity_unpin (entity); fail_awake: thread_state_asleep (ts1); return ret; @@ -177,7 +152,7 @@ static dds_return_t dds_readcdr_impl (bool take, dds_entity_t reader_or_conditio struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; struct dds_reader *rd; - struct dds_readcond *cond; + struct dds_entity *entity; assert (take); assert (buf); @@ -187,19 +162,31 @@ static dds_return_t dds_readcdr_impl (bool take, dds_entity_t reader_or_conditio (void)take; thread_state_awake (ts1); - if ((ret = dds_read_lock (reader_or_condition, &rd, &cond, false)) == DDS_RETCODE_OK) - { - /* read/take resets data available status -- must reset before reading because - the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ - dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); - /* reset DATA_ON_READERS status on subscriber after successful read/take */ - assert (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER); - dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); - - ret = dds_rhc_takecdr (rd->m_rd->rhc, lock, buf, si, maxs, mask & DDS_ANY_SAMPLE_STATE, mask & DDS_ANY_VIEW_STATE, mask & DDS_ANY_INSTANCE_STATE, hand); - dds_read_unlock (rd, cond); + if ((ret = dds_entity_pin (reader_or_condition, &entity)) < 0) { + goto fail_awake; + } else if (dds_entity_kind (entity) == DDS_KIND_READER) { + rd = (dds_reader *) entity; + } else if (dds_entity_kind (entity) != DDS_KIND_COND_READ && dds_entity_kind (entity) != DDS_KIND_COND_QUERY) { + dds_entity_unpin (entity); + ret = DDS_RETCODE_ILLEGAL_OPERATION; + goto fail_awake; + } else { + rd = (dds_reader *) entity->m_parent; } + + /* read/take resets data available status -- must reset before reading because + the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ + dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); + + /* reset DATA_ON_READERS status on subscriber after successful read/take */ + assert (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER); + dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); + + ret = dds_rhc_takecdr (rd->m_rd->rhc, lock, buf, si, maxs, mask & DDS_ANY_SAMPLE_STATE, mask & DDS_ANY_VIEW_STATE, mask & DDS_ANY_INSTANCE_STATE, hand); + dds_entity_unpin (entity); + +fail_awake: thread_state_asleep (ts1); return ret; } @@ -471,27 +458,36 @@ dds_return_t dds_return_loan (dds_entity_t reader_or_condition, void **buf, int3 { const struct ddsi_sertopic *st; dds_reader *rd; - dds_readcond *cond; + dds_entity *entity; dds_return_t ret = DDS_RETCODE_OK; if (buf == NULL || (*buf == NULL && bufsz > 0)) return DDS_RETCODE_BAD_PARAMETER; - if ((ret = dds_read_lock(reader_or_condition, &rd, &cond, false)) != DDS_RETCODE_OK) + if ((ret = dds_entity_pin (reader_or_condition, &entity)) < 0) { return ret; + } else if (dds_entity_kind (entity) == DDS_KIND_READER) { + rd = (dds_reader *) entity; + } else if (dds_entity_kind (entity) != DDS_KIND_COND_READ && dds_entity_kind (entity) != DDS_KIND_COND_QUERY) { + dds_entity_unpin (entity); + return DDS_RETCODE_ILLEGAL_OPERATION; + } else { + rd = (dds_reader *) entity->m_parent; + } st = rd->m_topic->m_stopic; for (int32_t i = 0; i < bufsz; i++) ddsi_sertopic_free_sample (st, buf[i], DDS_FREE_CONTENTS); /* If possible return loan buffer to reader */ + ddsrt_mutex_lock (&rd->m_entity.m_mutex); if (rd->m_loan != 0 && (buf[0] == rd->m_loan)) { rd->m_loan_out = false; ddsi_sertopic_zero_samples (st, rd->m_loan, rd->m_loan_size); buf[0] = NULL; } - - dds_read_unlock(rd, cond); + ddsrt_mutex_unlock (&rd->m_entity.m_mutex); + dds_entity_unpin (entity); return DDS_RETCODE_OK; } diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index 8d51e5b..4524751 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -1886,7 +1886,7 @@ int main (int argc, char *argv[]) have a reader or will never really be receiving data) */ struct subthread_arg subarg_data, subarg_ping, subarg_pong; init_eseq_admin (&eseq_admin, nkeyvals); - subthread_arg_init (&subarg_data, rd_data, 100); + subthread_arg_init (&subarg_data, rd_data, 1000); subthread_arg_init (&subarg_ping, rd_ping, 100); subthread_arg_init (&subarg_pong, rd_pong, 100); uint32_t (*subthread_func) (void *arg) = 0; From 0b8fd9fcc01f550287d47cf8e0759e1c7532a970 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 24 Jun 2019 09:58:58 +0200 Subject: [PATCH 114/178] Use ddsrt_malloc in macOS socket waitset code Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_sockwaitset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsi/src/q_sockwaitset.c b/src/core/ddsi/src/q_sockwaitset.c index 4284b0b..e0cecef 100644 --- a/src/core/ddsi/src/q_sockwaitset.c +++ b/src/core/ddsi/src/q_sockwaitset.c @@ -118,7 +118,7 @@ os_sockWaitset os_sockWaitsetNew (void) ws->ctx.nevs = 0; ws->ctx.index = 0; ws->ctx.evs_sz = sz; - if ((ws->ctx.evs = malloc (ws->ctx.evs_sz * sizeof (*ws->ctx.evs))) == NULL) + if ((ws->ctx.evs = ddsrt_malloc (ws->ctx.evs_sz * sizeof (*ws->ctx.evs))) == NULL) goto fail_ctx_evs; if ((ws->kqueue = kqueue ()) == -1) goto fail_kqueue; From 0e888eb2ec63ab2ea207d859aea0497f35d73b4e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 24 Jun 2019 10:05:00 +0200 Subject: [PATCH 115/178] Special-case size-1 sequential hopscotch hash table Rather than allocate a HH_HOP_RANGE large array of buckets, allocate just 1 if the initial size is 1, then jump to HH_HOP_RANGE as soon as a second element is added to the table. There are quite a few cases where hash tables are created where there never be more than 1 (or even 0) elements in the table (e.g., a writer without readers, a reader for a keyless topic). Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_whc.c | 4 +- src/ddsrt/src/hopscotch.c | 80 ++++++++++++++++++++++++------------- 2 files changed, 55 insertions(+), 29 deletions(-) diff --git a/src/core/ddsc/src/dds_whc.c b/src/core/ddsc/src/dds_whc.c index a501579..dc1d00c 100644 --- a/src/core/ddsc/src/dds_whc.c +++ b/src/core/ddsc/src/dds_whc.c @@ -366,11 +366,11 @@ struct whc *whc_new (int is_transient_local, uint32_t hdepth, uint32_t tldepth) #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 (32, whc_node_hash, whc_node_eq); + whc->seq_hash = ddsrt_hh_new (1, whc_node_hash, whc_node_eq); #endif if (whc->idxdepth > 0) - whc->idx_hash = ddsrt_hh_new (32, whc_idxnode_hash_key, whc_idxnode_eq_key); + whc->idx_hash = ddsrt_hh_new (1, whc_idxnode_hash_key, whc_idxnode_eq_key); else whc->idx_hash = NULL; diff --git a/src/ddsrt/src/hopscotch.c b/src/ddsrt/src/hopscotch.c index 24eefcb..daac7d7 100644 --- a/src/ddsrt/src/hopscotch.c +++ b/src/ddsrt/src/hopscotch.c @@ -39,10 +39,16 @@ struct ddsrt_hh { static void ddsrt_hh_init (struct ddsrt_hh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals) { - uint32_t size = HH_HOP_RANGE; + uint32_t size; uint32_t i; - while (size < init_size) { - size *= 2; + /* degenerate case to minimize memory use */ + if (init_size == 1) { + size = 1; + } else { + size = HH_HOP_RANGE; + while (size < init_size) { + size *= 2; + } } rt->hash = hash; rt->equals = equals; @@ -125,34 +131,54 @@ static uint32_t ddsrt_hh_find_closer_free_bucket (struct ddsrt_hh *rt, uint32_t static void ddsrt_hh_resize (struct ddsrt_hh *rt) { - struct ddsrt_hh_bucket *bs1; - uint32_t i, idxmask0, idxmask1; + if (rt->size == 1) { + assert (rt->size == 1); + assert (rt->buckets[0].hopinfo == 1); + assert (rt->buckets[0].data != NULL); - bs1 = ddsrt_malloc (2 * rt->size * sizeof (*rt->buckets)); + rt->size = HH_HOP_RANGE; + const uint32_t hash = rt->hash (rt->buckets[0].data); + const uint32_t idxmask = rt->size - 1; + const uint32_t start_bucket = hash & idxmask; - for (i = 0; i < 2 * rt->size; i++) { - bs1[i].hopinfo = 0; - bs1[i].data = NULL; - } - idxmask0 = rt->size - 1; - idxmask1 = 2 * rt->size - 1; - for (i = 0; i < rt->size; i++) { - void *data = rt->buckets[i].data; - if (data) { - const uint32_t hash = rt->hash (data); - const uint32_t old_start_bucket = hash & idxmask0; - const uint32_t new_start_bucket = hash & idxmask1; - const uint32_t dist = (i >= old_start_bucket) ? (i - old_start_bucket) : (rt->size + i - old_start_bucket); - const uint32_t newb = (new_start_bucket + dist) & idxmask1; - assert (dist < HH_HOP_RANGE); - bs1[new_start_bucket].hopinfo |= 1u << dist; - bs1[newb].data = data; + struct ddsrt_hh_bucket *newbs = ddsrt_malloc (rt->size * sizeof (*newbs)); + for (uint32_t i = 0; i < rt->size; i++) { + newbs[i].hopinfo = 0; + newbs[i].data = NULL; } - } + newbs[start_bucket] = rt->buckets[0]; + ddsrt_free (rt->buckets); + rt->buckets = newbs; + } else { + struct ddsrt_hh_bucket *bs1; + uint32_t i, idxmask0, idxmask1; - ddsrt_free (rt->buckets); - rt->size *= 2; - rt->buckets = bs1; + bs1 = ddsrt_malloc (2 * rt->size * sizeof (*rt->buckets)); + + for (i = 0; i < 2 * rt->size; i++) { + bs1[i].hopinfo = 0; + bs1[i].data = NULL; + } + idxmask0 = rt->size - 1; + idxmask1 = 2 * rt->size - 1; + for (i = 0; i < rt->size; i++) { + void *data = rt->buckets[i].data; + if (data) { + const uint32_t hash = rt->hash (data); + const uint32_t old_start_bucket = hash & idxmask0; + const uint32_t new_start_bucket = hash & idxmask1; + const uint32_t dist = (i >= old_start_bucket) ? (i - old_start_bucket) : (rt->size + i - old_start_bucket); + const uint32_t newb = (new_start_bucket + dist) & idxmask1; + assert (dist < HH_HOP_RANGE); + bs1[new_start_bucket].hopinfo |= 1u << dist; + bs1[newb].data = data; + } + } + + ddsrt_free (rt->buckets); + rt->size *= 2; + rt->buckets = bs1; + } } int ddsrt_hh_add (struct ddsrt_hh * __restrict rt, const void * __restrict data) From 260f8cd86b65d5ba87193db146fc8a5ec09c3830 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 24 Jun 2019 10:07:33 +0200 Subject: [PATCH 116/178] Lazily allocate state for multi-writer instances Multiple writers for a single instance is pretty rare, so it makes sense to lazily allocate the tables for keeping track of them. The more elegant solution would be to have a single lock-free table. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_rhc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 8849cfb..de4f20f 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -192,30 +192,33 @@ static int lwreg_equals (const void *va, const void *vb) static void lwregs_init (struct lwregs *rt) { - rt->regs = ddsrt_ehh_new (sizeof (struct lwreg), 1, lwreg_hash, lwreg_equals); + rt->regs = NULL; } static void lwregs_fini (struct lwregs *rt) { - ddsrt_ehh_free (rt->regs); + if (rt->regs) + ddsrt_ehh_free (rt->regs); } static int lwregs_contains (struct lwregs *rt, uint64_t iid, uint64_t wr_iid) { struct lwreg dummy = { .iid = iid, .wr_iid = wr_iid }; - return ddsrt_ehh_lookup (rt->regs, &dummy) != NULL; + return rt->regs != NULL && ddsrt_ehh_lookup (rt->regs, &dummy) != NULL; } static int lwregs_add (struct lwregs *rt, uint64_t iid, uint64_t wr_iid) { struct lwreg dummy = { .iid = iid, .wr_iid = wr_iid }; + if (rt->regs == NULL) + rt->regs = ddsrt_ehh_new (sizeof (struct lwreg), 1, lwreg_hash, lwreg_equals); return ddsrt_ehh_add (rt->regs, &dummy); } static int lwregs_delete (struct lwregs *rt, uint64_t iid, uint64_t wr_iid) { struct lwreg dummy = { .iid = iid, .wr_iid = wr_iid }; - return ddsrt_ehh_remove (rt->regs, &dummy); + return rt->regs != NULL && ddsrt_ehh_remove (rt->regs, &dummy); } #if 0 From ee9a12b469ec4a463a4bb1ff39db7827417a314c Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 24 Jun 2019 12:38:50 +0200 Subject: [PATCH 117/178] Allocate xpack::iov once writer has to send data Currently each DDSC (not DDSI) writer has its own "xpack" for packing submessages into larger messages, but that is a bit wasteful, especially when a lot of samples are being generated that never need to go onto the wire. Lazily allocating them and only pushing message into them when they have a destination address saves memory and improves speed for local communications. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_transmit.c | 16 ++++++++++++++++ src/core/ddsi/src/q_xmsg.c | 7 ++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 5686fb6..4cfa4ea 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -1103,6 +1103,22 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * ddsrt_free (plist); } } + else if (addrset_empty (wr->as) && (wr->as_group == NULL || addrset_empty (wr->as_group))) + { + /* No network destination, so no point in doing all the work involved + in going all the way. We do have to record that we "transmitted" + this sample, or it might not be retransmitted on request. + + (Note that no network destination is very nearly the same as no + matching proxy readers. The exception is the SPDP writer.) */ + UPDATE_SEQ_XMIT_LOCKED (wr, seq); + ddsrt_mutex_unlock (&wr->e.lock); + if (plist != NULL) + { + nn_plist_fini (plist); + ddsrt_free (plist); + } + } else { /* Note the subtlety of enqueueing with the lock held but diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index fabe8c0..c38fca7 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -200,7 +200,7 @@ struct nn_xpack ddsi_tran_conn_t conn; ddsi_sem_t sem; size_t niov; - ddsrt_iovec_t iov[NN_XMSG_MAX_MESSAGE_IOVECS]; + ddsrt_iovec_t *iov; enum nn_xmsg_dstmode dstmode; union @@ -978,6 +978,7 @@ struct nn_xpack * nn_xpack_new (ddsi_tran_conn_t conn, uint32_t bw_limit, bool a xp = ddsrt_malloc (sizeof (*xp)); memset (xp, 0, sizeof (*xp)); xp->async_mode = async_mode; + xp->iov = NULL; /* Fixed header fields, initialized just once */ xp->hdr.protocol.id[0] = 'R'; @@ -1030,6 +1031,7 @@ void nn_xpack_free (struct nn_xpack *xp) #endif if (gv.thread_pool) ddsi_sem_destroy (&xp->sem); + ddsrt_free (xp->iov); ddsrt_free (xp); } @@ -1411,6 +1413,9 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag assert ((m->sz % 4) == 0); assert (m->refd_payload == NULL || (m->refd_payload_iov.iov_len % 4) == 0); + if (xp->iov == NULL) + xp->iov = malloc (NN_XMSG_MAX_MESSAGE_IOVECS * sizeof (*xp->iov)); + if (!nn_xpack_mayaddmsg (xp, m, flags)) { assert (xp->niov > 0); From 2fe4a4ca358ac409905d2d69fe6f7f292bb89436 Mon Sep 17 00:00:00 2001 From: Thijs Sassen Date: Fri, 5 Jul 2019 14:16:28 +0200 Subject: [PATCH 118/178] Fixed failing FreeRTOS target due to recent code refactors Signed-off-by: Thijs Sassen Adjusted the close methode not to expand by the lwip close macro and added a check for DDSI_INCLUDE_SSM to match the correct pid table size. Signed-off-by: Thijs Sassen --- src/core/ddsc/src/dds__types.h | 3 ++- src/core/ddsc/src/dds__whc.h | 2 +- src/core/ddsi/include/dds/ddsi/q_whc.h | 4 ++-- src/core/ddsi/src/q_lease.c | 2 +- src/core/ddsi/src/q_plist.c | 4 ++++ src/ddsrt/src/ifaddrs/lwip/ifaddrs.c | 8 ++++---- src/ddsrt/src/rusage/freertos/rusage.c | 10 +++++----- src/ddsrt/src/sync/freertos/sync.c | 8 ++++---- src/ddsrt/src/threads/freertos/threads.c | 22 +++++++++++----------- 9 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/core/ddsc/src/dds__types.h b/src/core/ddsc/src/dds__types.h index 3d30790..667d0b0 100644 --- a/src/core/ddsc/src/dds__types.h +++ b/src/core/ddsc/src/dds__types.h @@ -173,8 +173,9 @@ dds_return_t dds_entity_deriver_dummy_delete (struct dds_entity *e); dds_return_t dds_entity_deriver_dummy_set_qos (struct dds_entity *e, const dds_qos_t *qos, bool enabled); dds_return_t dds_entity_deriver_dummy_validate_status (uint32_t mask); + inline dds_return_t dds_entity_deriver_close (struct dds_entity *e) { - return dds_entity_deriver_table[e->m_kind]->close (e); + return (dds_entity_deriver_table[e->m_kind]->close) (e); } inline dds_return_t dds_entity_deriver_delete (struct dds_entity *e) { return dds_entity_deriver_table[e->m_kind]->delete (e); diff --git a/src/core/ddsc/src/dds__whc.h b/src/core/ddsc/src/dds__whc.h index 13b542d..d069612 100644 --- a/src/core/ddsc/src/dds__whc.h +++ b/src/core/ddsc/src/dds__whc.h @@ -18,7 +18,7 @@ extern "C" { #endif -struct whc *whc_new (int is_transient_local, unsigned hdepth, unsigned tldepth); +struct whc *whc_new (int is_transient_local, uint32_t hdepth, uint32_t tldepth); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/q_whc.h b/src/core/ddsi/include/dds/ddsi/q_whc.h index 038772b..9eb73a5 100644 --- a/src/core/ddsi/include/dds/ddsi/q_whc.h +++ b/src/core/ddsi/include/dds/ddsi/q_whc.h @@ -73,8 +73,8 @@ typedef void (*whc_free_t)(struct whc *whc); /* 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, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); -typedef unsigned (*whc_downgrade_to_volatile_t)(struct whc *whc, struct whc_state *st); -typedef unsigned (*whc_remove_acked_messages_t)(struct whc *whc, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list); +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); struct whc_ops { diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index dd17cea..da00caa 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -295,7 +295,7 @@ static void debug_print_rawdata (const char *msg, const void *data, size_t len) DDS_TRACE(">"); } -void handle_PMD (UNUSED_ARG (const struct receiver_state *rst), nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len) +void handle_PMD (UNUSED_ARG (const struct receiver_state *rst), nn_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len) { const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ const int bswap = (data->identifier == CDR_LE) ^ (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN); diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 39ccc73..a109d74 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -1106,7 +1106,11 @@ 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. */ +#ifdef DDSI_INCLUDE_SSM static const struct piddesc *piddesc_omg_index[115]; +#else +static const struct piddesc *piddesc_omg_index[114]; +#endif static const struct piddesc *piddesc_eclipse_index[19]; static const struct piddesc *piddesc_prismtech_index[19]; diff --git a/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c b/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c index 9d1e64e..65985f5 100644 --- a/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c +++ b/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c @@ -67,13 +67,13 @@ sockaddr_from_ip_addr( } } -static dds_retcode_t +static dds_return_t copyaddr( ddsrt_ifaddrs_t **ifap, const struct netif *netif, const ip_addr_t *addr) { - dds_retcode_t rc = DDS_RETCODE_OK; + dds_return_t rc = DDS_RETCODE_OK; ddsrt_ifaddrs_t *ifa; struct sockaddr_storage sa; @@ -122,12 +122,12 @@ copyaddr( return rc; } -dds_retcode_t +dds_return_t ddsrt_getifaddrs( ddsrt_ifaddrs_t **ifap, const int *afs) { - dds_retcode_t rc = DDS_RETCODE_OK; + dds_return_t rc = DDS_RETCODE_OK; int use_ip4, use_ip6; struct netif *netif; ddsrt_ifaddrs_t *ifa, *next_ifa, *root_ifa; diff --git a/src/ddsrt/src/rusage/freertos/rusage.c b/src/ddsrt/src/rusage/freertos/rusage.c index 1f9d2f3..49e533e 100644 --- a/src/ddsrt/src/rusage/freertos/rusage.c +++ b/src/ddsrt/src/rusage/freertos/rusage.c @@ -29,10 +29,10 @@ #error "Time base for run time stats is not defined" #endif -static dds_retcode_t +static dds_return_t rusage_self(ddsrt_rusage_t *usage) { - dds_retcode_t rc = DDS_RETCODE_OK; + dds_return_t rc = DDS_RETCODE_OK; dds_duration_t nsecs; UBaseType_t cnt, len; TaskStatus_t *states = NULL, *ptr; @@ -65,7 +65,7 @@ rusage_self(ddsrt_rusage_t *usage) return rc; } -static dds_retcode_t +static dds_return_t rusage_thread(ddsrt_rusage_t *usage) { TaskStatus_t states; @@ -78,10 +78,10 @@ rusage_thread(ddsrt_rusage_t *usage) return DDS_RETCODE_OK; } -dds_retcode_t +dds_return_t ddsrt_getrusage(int who, ddsrt_rusage_t *usage) { - dds_retcode_t rc; + dds_return_t rc; assert(who == DDSRT_RUSAGE_SELF || who == DDSRT_RUSAGE_THREAD); assert(usage != NULL); diff --git a/src/ddsrt/src/sync/freertos/sync.c b/src/ddsrt/src/sync/freertos/sync.c index 6b75f7f..c721fb9 100644 --- a/src/ddsrt/src/sync/freertos/sync.c +++ b/src/ddsrt/src/sync/freertos/sync.c @@ -82,13 +82,13 @@ void ddsrt_mutex_unlock(ddsrt_mutex_t *mutex) } } -static dds_retcode_t +static dds_return_t cond_timedwait( ddsrt_cond_t *cond, ddsrt_mutex_t *mutex, dds_duration_t reltime) { - dds_retcode_t rc = DDS_RETCODE_OK; + dds_return_t rc = DDS_RETCODE_OK; dds_time_t abstime; TaskHandle_t task; TickType_t ticks = 0; @@ -174,7 +174,7 @@ ddsrt_cond_waitfor( ddsrt_mutex_t *mutex, dds_duration_t reltime) { - dds_retcode_t rc; + dds_return_t rc; assert(cond != NULL); assert(mutex != NULL); @@ -198,7 +198,7 @@ ddsrt_cond_waituntil( ddsrt_mutex_t *mutex, dds_time_t abstime) { - dds_retcode_t rc; + dds_return_t rc; dds_time_t time; dds_duration_t reltime; diff --git a/src/ddsrt/src/threads/freertos/threads.c b/src/ddsrt/src/threads/freertos/threads.c index 20a536e..be4e177 100644 --- a/src/ddsrt/src/threads/freertos/threads.c +++ b/src/ddsrt/src/threads/freertos/threads.c @@ -135,10 +135,10 @@ thread_context_find(TaskHandle_t task) return ctx; } -static dds_retcode_t +static dds_return_t thread_context_create(thread_context_t **ctxptr) { - dds_retcode_t rc = DDS_RETCODE_OK; + dds_return_t rc = DDS_RETCODE_OK; size_t len; thread_context_t *ctx = NULL, **ctxs = NULL; @@ -172,10 +172,10 @@ thread_context_create(thread_context_t **ctxptr) #define thread_context_require() thread_context_acquire(NULL) -static dds_retcode_t +static dds_return_t thread_context_acquire(thread_context_t **ctxptr) { - dds_retcode_t rc = DDS_RETCODE_OK; + dds_return_t rc = DDS_RETCODE_OK; thread_context_t *ctx = thread_context; if (ctx == NULL) { @@ -340,7 +340,7 @@ thread_start_routine(void *arg) the user to change it on a per-thread basis at runtime. */ #define MIN_STACK_SIZE ((uint16_t)(configMINIMAL_STACK_SIZE * WORD_SIZE)) -dds_retcode_t +dds_return_t ddsrt_thread_create( ddsrt_thread_t *thread, const char *name, @@ -348,7 +348,7 @@ ddsrt_thread_create( ddsrt_thread_routine_t start_routine, void *arg) { - dds_retcode_t rc; + dds_return_t rc; TaskHandle_t task; UBaseType_t prio; uint16_t size = MIN_STACK_SIZE; @@ -437,10 +437,10 @@ ddsrt_thread_fini(void) } } -dds_retcode_t +dds_return_t ddsrt_thread_join(ddsrt_thread_t thread, uint32_t *thread_result) { - dds_retcode_t rc; + dds_return_t rc; thread_context_t *ctx; eTaskState status; @@ -502,10 +502,10 @@ ddsrt_thread_join(ddsrt_thread_t thread, uint32_t *thread_result) return rc; } -dds_retcode_t +dds_return_t ddsrt_thread_cleanup_push(void (*routine)(void *), void *arg) { - dds_retcode_t rc = DDS_RETCODE_OK; + dds_return_t rc = DDS_RETCODE_OK; thread_cleanup_t *tail = NULL; thread_context_t *ctx; @@ -525,7 +525,7 @@ ddsrt_thread_cleanup_push(void (*routine)(void *), void *arg) return rc; } -dds_retcode_t +dds_return_t ddsrt_thread_cleanup_pop(int execute) { thread_cleanup_t *tail; From 0dd2155f9973e35b01f5ab01af9710c3134e1133 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Jul 2019 16:45:45 +0200 Subject: [PATCH 119/178] 64-bit alignment in serialised data The payload in a struct serdata_default is assumed to be at a 64-bit offset for conversion to/from a dds_{i,o}stream_t and getting padding calculations in the serialised representation correct. The definition did not guarantee this and got it wrong on a 32-bit release build. This commit computes the required padding at compile time and at verifies the assumption holds where it matters. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_stream.c | 2 + .../include/dds/ddsi/ddsi_serdata_default.h | 53 ++++++++++++++----- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/core/ddsc/src/dds_stream.c b/src/core/ddsc/src/dds_stream.c index 9593e4c..8a301c6 100644 --- a/src/core/ddsc/src/dds_stream.c +++ b/src/core/ddsc/src/dds_stream.c @@ -1614,6 +1614,8 @@ void dds_stream_extract_keyhash (dds_istream_t * __restrict is, dds_keyhash_t * ** *******************************************************************************************/ +DDSRT_STATIC_ASSERT ((offsetof (struct ddsi_serdata_default, data) % 8) == 0); + void dds_istream_from_serdata_default (dds_istream_t * __restrict s, const struct ddsi_serdata_default * __restrict d) { s->m_buffer = (const unsigned char *) 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 0604ff5..43e3158 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -49,26 +49,52 @@ typedef struct dds_keyhash { unsigned m_iskey : 1; /* m_hash is key value */ } dds_keyhash_t; -struct ddsi_serdata_default { - struct ddsi_serdata c; - uint32_t pos; - uint32_t size; +/* Debug builds may want to keep some additional state */ #ifndef NDEBUG +#define DDSI_SERDATA_DEFAULT_DEBUG_FIELDS \ bool fixed; +#else +#define DDSI_SERDATA_DEFAULT_DEBUG_FIELDS #endif - dds_keyhash_t keyhash; - struct serdatapool *pool; - struct ddsi_serdata_default *next; /* in pool->freelist */ +/* There is an alignment requirement on the raw data (it must be at + offset mod 8 for the conversion to/from a dds_stream to work). + So we define two types: one without any additional padding, and + one where the appropriate amount of padding is inserted */ +#define DDSI_SERDATA_DEFAULT_PREPAD \ + struct ddsi_serdata c; \ + uint32_t pos; \ + uint32_t size; \ + DDSI_SERDATA_DEFAULT_DEBUG_FIELDS \ + dds_keyhash_t keyhash; \ + struct serdatapool *pool; \ + struct ddsi_serdata_default *next /* in pool->freelist */ +#define DDSI_SERDATA_DEFAULT_POSTPAD \ + struct CDRHeader hdr; \ + char data[] - /* padding to ensure CDRHeader is at an offset 4 mod 8 from the - start of the memory, so that data is 8-byte aligned provided - serdata is 8-byte aligned */ - char pad[8 - ((sizeof (struct ddsi_serdata) + 4) % 8)]; - struct CDRHeader hdr; - char data[]; +struct ddsi_serdata_default_unpadded { + DDSI_SERDATA_DEFAULT_PREPAD; + DDSI_SERDATA_DEFAULT_POSTPAD; }; +#ifdef __GNUC__ +#define DDSI_SERDATA_DEFAULT_PAD(n) ((n) % 8) +#else +#define DDSI_SERDATA_DEFAULT_PAD(n) (n) +#endif + +struct ddsi_serdata_default { + DDSI_SERDATA_DEFAULT_PREPAD; + char pad[DDSI_SERDATA_DEFAULT_PAD (8 - (offsetof (struct ddsi_serdata_default_unpadded, data) % 8))]; + DDSI_SERDATA_DEFAULT_POSTPAD; +}; + +#undef DDSI_SERDATA_DEFAULT_PAD +#undef DDSI_SERDATA_DEFAULT_POSTPAD +#undef DDSI_SERDATA_DEFAULT_PREPAD +#undef DDSI_SERDATA_DEFAULT_FIXED_FIELD + struct dds_key_descriptor; struct dds_topic_descriptor; @@ -80,6 +106,7 @@ typedef bool (*dds_topic_intern_filter_fn) (const void * sample, void *ctx); 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; From 1f5083aa44c73adf380adcda21f1bef80ed22ea1 Mon Sep 17 00:00:00 2001 From: TheFixer Date: Tue, 16 Jul 2019 13:09:06 +0200 Subject: [PATCH 120/178] =?UTF-8?q?#213=20-=20Allow=20readconditions=20and?= =?UTF-8?q?=20queryconditions=20as=20valid=20entities=20for=E2=80=A6=20(#2?= =?UTF-8?q?14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow readconditions and queryconditions as valid entities for dds_instance_get_key Signed-off-by: TheFixer --- src/core/ddsc/include/dds/dds.h | 2 +- src/core/ddsc/src/dds_instance.c | 18 +++-- src/core/ddsc/tests/instance_get_key.c | 102 ++++++++++++++++++++++++- 3 files changed, 110 insertions(+), 12 deletions(-) diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index a1649c6..491d447 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -2939,7 +2939,7 @@ dds_instance_lookup(dds_entity_t entity, const void *data); /** * @brief This operation takes an instance handle and return a key-value corresponding to it. * - * @param[in] entity Reader or writer entity. + * @param[in] entity Reader, writer, readcondition or querycondition entity. * @param[in] inst Instance handle. * @param[out] data pointer to an instance, to which the key ID corresponding to the instance handle will be * returned, the sample in the instance should be ignored. diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index ddb65f4..2864c6c 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -284,23 +284,27 @@ dds_return_t dds_instance_get_key (dds_entity_t entity, dds_instance_handle_t ih dds_return_t ret; const dds_topic *topic; struct ddsi_tkmap_instance *tk; - dds_entity *w_or_r; + dds_entity *e; if (data == NULL) return DDS_RETCODE_BAD_PARAMETER; - if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &w_or_r)) < 0) + if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) < 0) return ret; - switch (dds_entity_kind (w_or_r)) + switch (dds_entity_kind (e)) { case DDS_KIND_WRITER: - topic = ((dds_writer *) w_or_r)->m_topic; + topic = ((dds_writer *) e)->m_topic; break; case DDS_KIND_READER: - topic = ((dds_reader *) w_or_r)->m_topic; + topic = ((dds_reader *) e)->m_topic; + break; + case DDS_KIND_COND_READ: + case DDS_KIND_COND_QUERY: + topic = ((dds_reader *) e->m_parent)->m_topic; break; default: - dds_entity_unlock (w_or_r); + dds_entity_unlock (e); return DDS_RETCODE_ILLEGAL_OPERATION; } @@ -315,6 +319,6 @@ dds_return_t dds_instance_get_key (dds_entity_t entity, dds_instance_handle_t ih ret = DDS_RETCODE_OK; } thread_state_asleep (ts1); - dds_entity_unlock (w_or_r); + dds_entity_unlock (e); return ret; } diff --git a/src/core/ddsc/tests/instance_get_key.c b/src/core/ddsc/tests/instance_get_key.c index 54b1aa5..a0861b3 100644 --- a/src/core/ddsc/tests/instance_get_key.c +++ b/src/core/ddsc/tests/instance_get_key.c @@ -18,20 +18,40 @@ #include "dds/ddsrt/string.h" #include "RoundTrip.h" +#define MAX_SAMPLES 10 + static dds_entity_t participant = DDS_ENTITY_NIL; +static dds_entity_t waitset = DDS_ENTITY_NIL; static dds_entity_t topic = DDS_ENTITY_NIL; static dds_entity_t publisher = DDS_ENTITY_NIL; +static dds_entity_t subscriber = DDS_ENTITY_NIL; static dds_entity_t writer = DDS_ENTITY_NIL; - +static dds_entity_t reader = DDS_ENTITY_NIL; +static dds_entity_t readcondition = DDS_ENTITY_NIL; +static dds_entity_t querycondition = DDS_ENTITY_NIL; static dds_instance_handle_t handle = DDS_HANDLE_NIL; +static bool +filter(const void * sample) +{ + const RoundTripModule_Address *s = sample; + return (s->port == 1); +} + static RoundTripModule_Address data; /* Fixture to create prerequisite entity */ static void setup(void) { + uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; + dds_return_t ret; + participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); + + waitset = dds_create_waitset(participant); + CU_ASSERT_FATAL(waitset > 0); + topic = dds_create_topic(participant, &RoundTripModule_Address_desc, "ddsc_instance_get_key", NULL, NULL); CU_ASSERT_FATAL(topic > 0); @@ -41,6 +61,24 @@ static void setup(void) writer = dds_create_writer(publisher, topic, NULL, NULL); CU_ASSERT_FATAL(writer > 0); + subscriber = dds_create_subscriber(participant, NULL, NULL); + CU_ASSERT_FATAL(subscriber > 0); + + reader = dds_create_reader(subscriber, topic, NULL, NULL); + CU_ASSERT_FATAL(reader > 0); + + readcondition = dds_create_readcondition(reader, mask); + CU_ASSERT_FATAL(readcondition > 0); + + ret = dds_waitset_attach(waitset, readcondition, readcondition); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + querycondition = dds_create_querycondition(reader, mask, filter); + CU_ASSERT_FATAL(querycondition > 0); + + ret = dds_waitset_attach(waitset, querycondition, querycondition); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + memset(&data, 0, sizeof(data)); data.ip = ddsrt_strdup("some data"); CU_ASSERT_PTR_NOT_NULL_FATAL(data.ip); @@ -52,9 +90,6 @@ static void teardown(void) { RoundTripModule_Address_free(&data, DDS_FREE_CONTENTS); - dds_delete(writer); - dds_delete(publisher); - dds_delete(topic); dds_delete(participant); } @@ -104,3 +139,62 @@ CU_Test(ddsc_instance_get_key, registered_instance, .init=setup, .fini=teardown) RoundTripModule_Address_free(&key_data, DDS_FREE_CONTENTS); } +CU_Test(ddsc_instance_get_key, readcondition, .init=setup, .fini=teardown) +{ + dds_return_t ret; + RoundTripModule_Address key_data; + + /* The instance handle of a successful write is by + * design the same as the instance handle for the + * readers,readconditions and queryconditions. + * For that reason there is no need to actually read + * the data. It is sufficient to do a successful write + * and use the instance handle to obtain the key_data + * for the readcondition. */ + ret = dds_write(writer, &data); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + handle = dds_lookup_instance (writer, &data); + CU_ASSERT_PTR_NOT_NULL_FATAL(handle); + + memset(&key_data, 0, sizeof(key_data)); + + ret = dds_instance_get_key(readcondition, handle, &key_data); + + CU_ASSERT_PTR_NOT_NULL_FATAL(key_data.ip); + CU_ASSERT_STRING_EQUAL_FATAL(key_data.ip, data.ip); + CU_ASSERT_EQUAL_FATAL(key_data.port, data.port); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + RoundTripModule_Address_free(&key_data, DDS_FREE_CONTENTS); +} + +CU_Test(ddsc_instance_get_key, querycondition, .init=setup, .fini=teardown) +{ + dds_return_t ret; + RoundTripModule_Address key_data; + + /* The instance handle of a successful write is by + * design the same as the instance handle for the + * readers,readconditions and queryconditions. + * For that reason there is no need to actually read + * the data. It is sufficient to do a successful write + * and use the instance handle to obtain the key_data + * for the querycondition. */ + ret = dds_write(writer, &data); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + handle = dds_lookup_instance (writer, &data); + CU_ASSERT_PTR_NOT_NULL_FATAL(handle); + + memset(&key_data, 0, sizeof(key_data)); + + ret = dds_instance_get_key(querycondition, handle, &key_data); + + CU_ASSERT_PTR_NOT_NULL_FATAL(key_data.ip); + CU_ASSERT_STRING_EQUAL_FATAL(key_data.ip, data.ip); + CU_ASSERT_EQUAL_FATAL(key_data.port, data.port); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + RoundTripModule_Address_free(&key_data, DDS_FREE_CONTENTS); +} From 20b91796b12bd7d9d9e22442b2991996c263b2b3 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 5 Jul 2019 22:24:18 +0200 Subject: [PATCH 121/178] Fix big-endian build failure Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsc/src/dds_stream.c b/src/core/ddsc/src/dds_stream.c index 8a301c6..3e5e48a 100644 --- a/src/core/ddsc/src/dds_stream.c +++ b/src/core/ddsc/src/dds_stream.c @@ -1342,7 +1342,7 @@ static void dds_stream_extract_keyBE_from_key_prim_op (dds_istream_t * __restric #if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN dds_stream_swap_copy (dst, src, num, align); #else - dds_stream_read_fixed_buffer (is, dst, num, align); + memcpy (dst, src, num * align); #endif os->x.m_index += num * align; is->m_index += num * align; From 5a83d422eafa2595f0156d6045a2ac0e4c47faa1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 5 Jul 2019 22:25:18 +0200 Subject: [PATCH 122/178] Do not use msg_flags if DDSRT_MSGHDR_FLAGS not set Signed-off-by: Erik Boasson --- src/core/ddsi/src/ddsi_udp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 4fb17db..4b46999 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -147,7 +147,6 @@ static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *d #if DDSRT_MSGHDR_FLAGS msg.msg_flags = (int) flags; #else - msg.msg_flags = 0; DDSRT_UNUSED_ARG(flags); #endif #if MSG_NOSIGNAL && !LWIP_SOCKET From bf5920385f6afce8645a5c81f355d1426cfb2356 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 5 Jul 2019 22:35:19 +0200 Subject: [PATCH 123/178] Account for DDSI_INCLUDE_SSM in parameterlist size The parameter list table indices ought to be a small as possible to avoid wasting space, and that means the index size is dependent on whether or not DDSI_INCLUDE_SSM is set. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_plist.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index a109d74..607c8ec 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -1105,10 +1105,12 @@ 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. */ + nn_plist_init_tables. + + FIXME: should compute them at build-time */ #ifdef DDSI_INCLUDE_SSM static const struct piddesc *piddesc_omg_index[115]; -#else +#else /* status info is the highest */ static const struct piddesc *piddesc_omg_index[114]; #endif static const struct piddesc *piddesc_eclipse_index[19]; From 0d33462664c10e70035df95cb26728fea287fec5 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 5 Jul 2019 23:25:51 +0200 Subject: [PATCH 124/178] Use uintptr_t rather than uintmax_t for thread ids On 32-bit machines uintmax_t is likely to be slower than uintptr_t, and for that reason, using an uintmax_t for a thread id seems highly unlikely. For the current platforms, uintptr_t works. Signed-off-by: Erik Boasson --- src/ddsrt/include/dds/ddsrt/threads/posix.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ddsrt/include/dds/ddsrt/threads/posix.h b/src/ddsrt/include/dds/ddsrt/threads/posix.h index 0d15c27..19b4ed0 100644 --- a/src/ddsrt/include/dds/ddsrt/threads/posix.h +++ b/src/ddsrt/include/dds/ddsrt/threads/posix.h @@ -49,7 +49,7 @@ typedef TASK_ID ddsrt_tid_t; # endif /* __VXWORKS__ */ #else -typedef uintmax_t ddsrt_tid_t; +typedef uintptr_t ddsrt_tid_t; #define PRIdTID PRIuPTR #endif From 96e09d2d4ef94ba45d6017b9056b410d31bf59d1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 5 Jul 2019 23:57:26 +0200 Subject: [PATCH 125/178] Use ddsrt_strsep instead of ddsrt_strtok_r The two do essentially the same think, and ddsrt_strtok_r was only used in one place. (Triggered by Solaris 2.6 not providing strtok_r.) Signed-off-by: Erik Boasson --- src/ddsrt/include/dds/ddsrt/string.h | 15 ------------- src/ddsrt/src/string.c | 16 -------------- src/ddsrt/tests/string.c | 32 ---------------------------- src/tools/pubsub/pubsub.c | 6 +++--- 4 files changed, 3 insertions(+), 66 deletions(-) diff --git a/src/ddsrt/include/dds/ddsrt/string.h b/src/ddsrt/include/dds/ddsrt/string.h index 1d449b7..7fca58c 100644 --- a/src/ddsrt/include/dds/ddsrt/string.h +++ b/src/ddsrt/include/dds/ddsrt/string.h @@ -52,21 +52,6 @@ ddsrt_strncasecmp( size_t n) ddsrt_nonnull((1,2)); -/** - * @brief Split string into tokens. - * - * @param[in] str String to split into tokens. - * @param[in] delim Characters that delimit a token. - * @param[in,out] saveptr Pointer to a char * used internally. - * - * @returns The next token or NULL if there are no more tokens. - */ -DDS_EXPORT char * -ddsrt_strtok_r( - char *str, - const char *delim, - char **saveptr); - /** * @brief Extract token from string. * diff --git a/src/ddsrt/src/string.c b/src/ddsrt/src/string.c index 24d2631..d048e5f 100644 --- a/src/ddsrt/src/string.c +++ b/src/ddsrt/src/string.c @@ -12,9 +12,6 @@ #include #include #include -#if defined(__IAR_SYSTEMS_ICC__) -#define _DLIB_ADD_EXTRA_SYMBOLS /* Export strtok_r. */ -#endif #include #include "dds/ddsrt/heap.h" @@ -65,19 +62,6 @@ ddsrt_strncasecmp( return cr; } -char * -ddsrt_strtok_r( - char *str, - const char *delim, - char **saveptr) -{ -#if _WIN32 - return strtok_s(str, delim, saveptr); -#else - return strtok_r(str, delim, saveptr); -#endif -} - char * ddsrt_strsep(char **str, const char *sep) { diff --git a/src/ddsrt/tests/string.c b/src/ddsrt/tests/string.c index cd3ffbf..eae2cc7 100644 --- a/src/ddsrt/tests/string.c +++ b/src/ddsrt/tests/string.c @@ -67,35 +67,3 @@ CU_Theory((const char *s1, const char *s2, size_t n, eq_t e), ddsrt_strncasecmp, CU_ASSERT((e == eq && r == 0) || (e == lt && r < 0) || (e == gt && r > 0)); } -CU_Test(ddsrt_string, strtok_r) -{ - char *res; - char *saveptr; - char ts1[] = "123,234"; - char ts2[] = ",;,123abc,,456,:,"; - char ts3[] = ",,,123,,456,789,,,"; - - res = ddsrt_strtok_r(ts1, ",", &saveptr); - CU_ASSERT(strcmp(res, "123") == 0); - res = ddsrt_strtok_r( NULL, ",", &saveptr); - CU_ASSERT(strcmp(res, "234") == 0); - res = ddsrt_strtok_r( NULL, ",", &saveptr); - CU_ASSERT(res == NULL); - - res = ddsrt_strtok_r(ts2, ",;", &saveptr); - CU_ASSERT(strcmp(res, "123abc") == 0); - res = ddsrt_strtok_r( NULL, ",", &saveptr); - CU_ASSERT(strcmp(res, "456") == 0); - res = ddsrt_strtok_r( NULL, ",:", &saveptr); - CU_ASSERT(res == NULL); - - res = ddsrt_strtok_r(ts3, ",", &saveptr); - CU_ASSERT(strcmp(res, "123") == 0); - res = ddsrt_strtok_r( NULL, ",", &saveptr); - CU_ASSERT(strcmp(res, "456") == 0); - res = ddsrt_strtok_r( NULL, ",", &saveptr); - CU_ASSERT(strcmp(res, "789") == 0); - res = ddsrt_strtok_r( NULL, ",:", &saveptr); - CU_ASSERT(res == NULL); -} - diff --git a/src/tools/pubsub/pubsub.c b/src/tools/pubsub/pubsub.c index e3c356f..b810d24 100644 --- a/src/tools/pubsub/pubsub.c +++ b/src/tools/pubsub/pubsub.c @@ -2516,10 +2516,10 @@ int main(int argc, char *argv[]) { } break; case 'S': { - char *copy = dds_string_dup(optarg), *tok, *lasts; + char *copy = dds_string_dup(optarg), *tok, *cursor = copy; if (copy == NULL) abort(); - tok = ddsrt_strtok_r(copy, ",", &lasts); + tok = ddsrt_strsep(&cursor, ","); while (tok) { if (strcmp(tok, "pr") == 0 || strcmp(tok, "pre-read") == 0) spec[specidx].rd.print_match_pre_read = 1; @@ -2551,7 +2551,7 @@ int main(int argc, char *argv[]) { fprintf (stderr, "-S %s: invalid event\n", tok); exit(2); } - tok = ddsrt_strtok_r(NULL, ",", &lasts); + tok = ddsrt_strsep(&cursor, ","); } dds_free(copy); } From 47920df65ce8ce24301088b865d48507eefa1705 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 5 Jul 2019 22:28:41 +0200 Subject: [PATCH 126/178] Remove qoslock Creating a reader/writer in a listener for a built-in topic (as ddsperf does) recursively ends up in reader/writer matching, recursively read-locking qoslock. As nobody ever takes a write-lock, it is a non-issue provided the rwlock really is an rwlock. On Solaris 2.6 those don't exist, and mapping it onto a mutex deadlocks. This commit removes the thing in its entirety, the fact that it is currently only ever locked for reading is hint that perhaps it is not that valuable a thing. The way it was used in the code would in any case not have helped with re-matching on QoS changes (save for duplicating all the matching code), and it is doubtful that serializing the matching in that case would be necessary in the first place. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_globals.h | 4 ---- src/core/ddsi/src/q_entity.c | 6 ------ src/core/ddsi/src/q_init.c | 2 -- 3 files changed, 12 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/q_globals.h index 39acf96..93bdd5e 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/q_globals.h @@ -195,10 +195,6 @@ struct q_globals { struct addrset *as_disc; struct addrset *as_disc_group; - /* qoslock serializes QoS changes, probably not strictly necessary, - but a lot more straightforward that way */ - ddsrt_rwlock_t qoslock; - ddsrt_mutex_t lock; /* Receive thread. (We can only has one for now, cos of the signal diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index a6090a2..e9f09bc 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -1294,7 +1294,6 @@ void rebuild_or_clear_writer_addrsets(int rebuild) struct addrset *empty = rebuild ? NULL : new_addrset(); DDS_LOG(DDS_LC_DISCOVERY, "rebuild_or_delete_writer_addrsets(%d)\n", rebuild); ephash_enum_writer_init (&est); - ddsrt_rwlock_read (&gv.qoslock); while ((wr = ephash_enum_writer_next (&est)) != NULL) { ddsrt_mutex_lock (&wr->e.lock); @@ -1318,7 +1317,6 @@ void rebuild_or_clear_writer_addrsets(int rebuild) } ddsrt_mutex_unlock (&wr->e.lock); } - ddsrt_rwlock_unlock (&gv.qoslock); ephash_enum_writer_fini (&est); unref_addrset(empty); DDS_LOG(DDS_LC_DISCOVERY, "rebuild_or_delete_writer_addrsets(%d) done\n", rebuild); @@ -2334,10 +2332,8 @@ static void generic_do_match (struct entity_common *e, nn_mtime_t tnow) enumerating), but we may visit a single proxy reader multiple times. */ ephash_enum_init (&est, mkind); - ddsrt_rwlock_read (&gv.qoslock); while ((em = ephash_enum_next (&est)) != NULL) generic_do_match_connect(e, em, tnow); - ddsrt_rwlock_unlock (&gv.qoslock); ephash_enum_fini (&est); } else @@ -2386,10 +2382,8 @@ static void generic_do_local_match (struct entity_common *e, nn_mtime_t tnow) enumerating), but we may visit a single proxy reader multiple times. */ ephash_enum_init (&est, mkind); - ddsrt_rwlock_read (&gv.qoslock); while ((em = ephash_enum_next (&est)) != NULL) generic_do_local_match_connect(e, em, tnow); - ddsrt_rwlock_unlock (&gv.qoslock); ephash_enum_fini (&est); } diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index df5f77a..9832ab2 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -1253,7 +1253,6 @@ int rtps_init (void) gv.gcreq_queue = gcreq_queue_new (); ddsrt_atomic_st32 (&gv.rtps_keepgoing, 1); - ddsrt_rwlock_init (&gv.qoslock); if (config.xpack_send_async) { @@ -1645,7 +1644,6 @@ void rtps_fini (void) nn_plist_fini (&gv.default_plist_pp); ddsrt_mutex_destroy (&gv.lock); - ddsrt_rwlock_destroy (&gv.qoslock); while (gv.recvips) { From fda285e2f500ca912bb65f4c9d3041ab8a7b1ddd Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 5 Jul 2019 23:15:41 +0200 Subject: [PATCH 127/178] Add support for Solaris 2.6 on sun4m builds It is an excellent platform for catching bugs: big-endian, slow enough that a context switch in the middle of an operation becomes a regular occurrence, and all that on a SMP box. Or: I just wanted to see if it would work. Signed-off-by: Erik Boasson --- performance/quick-microbenchmark | 30 + ports/solaris2.6/README.md | 40 + ports/solaris2.6/config.mk | 264 ++ ports/solaris2.6/guess-config | 52 + ports/solaris2.6/include/inttypes.h | 8 + ports/solaris2.6/include/math.h | 22 + ports/solaris2.6/include/netinet/in.h | 10 + ports/solaris2.6/include/stdint.h | 11 + ports/solaris2.6/include/sys/socket.h | 14 + ports/solaris2.6/makefile | 59 + src/core/ddsi/include/dds/ddsi/ddsi_udp.h | 9 + src/core/ddsi/include/dds/ddsi/q_protocol.h | 8 - src/core/ddsi/src/q_addrset.c | 1 + src/core/ddsi/src/q_entity.c | 1 + src/core/ddsi/src/q_plist.c | 1 + src/core/ddsi/src/q_transmit.c | 12 +- src/core/ddsi/src/q_xevent.c | 10 +- src/ddsrt/CMakeLists.txt | 14 +- src/ddsrt/include/dds/ddsrt/sockets/posix.h | 33 +- src/ddsrt/include/dds/ddsrt/sockets/windows.h | 7 +- src/ddsrt/include/dds/ddsrt/sync.h | 2 + src/ddsrt/include/dds/ddsrt/sync/solaris2.6.h | 44 + src/ddsrt/src/atomics.c | 244 +- src/ddsrt/src/environ/solaris2.6/environ.c | 100 + src/ddsrt/src/ifaddrs/solaris2.6/ifaddrs.c | 84 + src/ddsrt/src/sockets.c | 42 +- .../sockets/include/dds/ddsrt/sockets_priv.h | 3 +- src/ddsrt/src/sockets/posix/gethostname.c | 4 + src/ddsrt/src/string/solaris2.6/strerror.c | 34 + src/ddsrt/src/sync/solaris2.6/sync.c | 236 ++ src/ddsrt/src/threads/posix/threads.c | 6 + src/ddsrt/src/time.c | 9 +- src/ddsrt/src/time/solaris2.6/time.c | 38 + src/tools/ddsperf/ddsperf.c | 3 + .../vdds-xcode.xcodeproj/project.pbxproj | 2310 ----------------- .../contents.xcworkspacedata | 7 - .../xcschemes/ddpingpong.xcscheme | 91 - .../xcshareddata/xcschemes/ping.xcscheme | 91 - .../xcshareddata/xcschemes/pong.xcscheme | 91 - .../xcshareddata/xcschemes/publisher.xcscheme | 97 - .../xcshareddata/xcschemes/rpc-ping.xcscheme | 91 - .../xcschemes/rpc-pingpong.xcscheme | 91 - .../xcshareddata/xcschemes/rpc-pong.xcscheme | 91 - .../xcschemes/rpc-publisher.xcscheme | 91 - .../xcschemes/rpc-subscriber.xcscheme | 91 - .../xcschemes/subscriber.xcscheme | 91 - .../xcschemes/vdds-server.xcscheme | 91 - .../xcschemes/vdds-server2.xcscheme | 91 - .../xcschemes/vdds-stubs.xcscheme | 80 - .../xcschemes/vdds-xcode.xcscheme | 271 -- .../xcshareddata/xcschemes/vdds.xcscheme | 80 - .../xcschemes/xcschememanagement.plist | 162 -- 52 files changed, 1266 insertions(+), 4197 deletions(-) create mode 100644 performance/quick-microbenchmark create mode 100644 ports/solaris2.6/README.md create mode 100644 ports/solaris2.6/config.mk create mode 100755 ports/solaris2.6/guess-config create mode 100644 ports/solaris2.6/include/inttypes.h create mode 100644 ports/solaris2.6/include/math.h create mode 100644 ports/solaris2.6/include/netinet/in.h create mode 100644 ports/solaris2.6/include/stdint.h create mode 100644 ports/solaris2.6/include/sys/socket.h create mode 100644 ports/solaris2.6/makefile create mode 100644 src/ddsrt/include/dds/ddsrt/sync/solaris2.6.h create mode 100644 src/ddsrt/src/environ/solaris2.6/environ.c create mode 100644 src/ddsrt/src/ifaddrs/solaris2.6/ifaddrs.c create mode 100644 src/ddsrt/src/string/solaris2.6/strerror.c create mode 100644 src/ddsrt/src/sync/solaris2.6/sync.c create mode 100644 src/ddsrt/src/time/solaris2.6/time.c delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/project.pbxproj delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/ddpingpong.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/ping.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/pong.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/publisher.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-ping.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-pingpong.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-pong.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-publisher.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-subscriber.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/subscriber.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-server.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-server2.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-stubs.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-xcode.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds.xcscheme delete mode 100644 vdds-xcode/vdds-xcode.xcodeproj/xcuserdata/erik.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/performance/quick-microbenchmark b/performance/quick-microbenchmark new file mode 100644 index 0000000..3150bcf --- /dev/null +++ b/performance/quick-microbenchmark @@ -0,0 +1,30 @@ +export CYCLONEDDS_URI='250kB65500B65000B' +set -x +gen/ddsperf -D20 -L ping pon +for x in 16 32 64 128 1024 4096 16384 ; do + gen/ddsperf -D20 -TKS -z$x -L ping pong +done +gen/ddsperf -D20 -L pub sub +for x in 16 32 64 128 1024 4096 16384 ; do + gen/ddsperf -D20 -TKS -z$x -L pub sub +done +gen/ddsperf pong & pid=$! +gen/ddsperf -D20 ping +kill $pid +wait +gen/ddsperf -TKS pong & pid=$! +for x in 16 32 64 128 1024 4096 16384 ; do + gen/ddsperf -D20 -TKS -z$x ping +done +kill $pid +wait +gen/ddsperf sub & pid=$! +gen/ddsperf -D20 pub +kill $pid +wait +gen/ddsperf -TKS sub & pid=$! +for x in 16 32 64 128 1024 4096 16384 ; do + gen/ddsperf -D20 -TKS -z$x pub +done +kill $pid +wait diff --git a/ports/solaris2.6/README.md b/ports/solaris2.6/README.md new file mode 100644 index 0000000..058d245 --- /dev/null +++ b/ports/solaris2.6/README.md @@ -0,0 +1,40 @@ +# Solaris 2.6 / sun4m port + +Building for Solaris 2.6 / sun4m, e.g., a Sun Microsystems SPARCStation 20 running Solaris 2.6, +firstly involves getting a sufficiently modern gcc onto the machine (gcc-4.3.x with GNU binutils +certainly works, but it is very well possible that older versions and/or using the Sun assembler and +linker work fine, too) and a sufficiently new gmake (3.81 should do). + +Secondly, because the port relies on a custom makefile rather than "cmake", and that makefile +doesn't build the Java-based IDL preprocessor to avoid pulling in tons of dependencies, you will +need to do a build on a "normal" platform first. The makefile assumes that the required parts of +that build process are available in a "build" directory underneath the project root. Note that only +the CMake generate export.h and the ddsperf-related IDL preprocessor output is required (if other +applications are to be be built, they may require additional files). + +The results are stored in a directory named "gen". After a successful build, there will be +libddsc.so and ddsperf in that directory. No attempts are made at tracking header file +dependencies. It seems unlikely that anyone would want to use such a machine as a development +machine. + +The makefile expects to be run from the project root directory. + +E.g., on a regular supported platform: +``` +# mkdir build && cd build +# cmake ../src +# make +# cd .. +# git archive -o cdds.zip HEAD +# find build -name '*.[ch]' | xargs zip -9r cdds.zip +``` + +copy cdds.zip to the Solaris box, log in and: +``` +# mkdir cdds && cd cdds +# unzip .../cdds.zip +# make -f ports/solaris2.6/makefile -j4 +# gen/ddsperf -D20 sub & gen/ddsperf -D20 pub & +``` + +It takes about 10 minutes to do the build on a quad 100MHz HyperSPARC. diff --git a/ports/solaris2.6/config.mk b/ports/solaris2.6/config.mk new file mode 100644 index 0000000..ded9531 --- /dev/null +++ b/ports/solaris2.6/config.mk @@ -0,0 +1,264 @@ +ifeq "$(CONFIG)" "" + override CONFIG := $(shell $(dir $(lastword $(MAKEFILE_LIST)))/guess-config) + ifeq "$(CONFIG)" "" + $(error "Failed to guess config") + endif +endif + +OS := $(shell echo $(CONFIG) | sed -e 's/^[^.]*\.//' -e 's/^\([^-_]*\)[-_].*/\1/') +PROC := $(shell echo $(CONFIG) | sed -e 's/^\([^.]*\)\..*/\1/') + +ifeq "$(OS)" "darwin" + DDSRT = $(OS) posix + RULES = darwin + CC = clang + LD = $(CC) + OPT = -fsanitize=address #-O3 -DNDEBUG + PROF = + CPPFLAGS += -Wall -g $(OPT) $(PROF) + CFLAGS += $(CPPFLAGS) #-fno-inline + LDFLAGS += -g $(OPT) $(PROF) + X = + O = .o + A = .a + SO = .dylib + LIBPRE = lib +endif +ifeq "$(OS)" "solaris2.6" + DDSRT = $(OS) posix + RULES = unix + CC = gcc -std=gnu99 -mcpu=v8 + LD = $(CC) + OPT = -O2 -DNDEBUG + PROF = + CPPFLAGS += -Wall -g $(OPT) $(PROF) -D_REENTRANT -D__EXTENSIONS__ -D__SunOS_5_6 -I$(PWD)/ports/solaris2.6/include + CFLAGS += $(CPPFLAGS) + LDFLAGS += -g $(OPT) $(PROF) + LDLIBS += -lposix4 -lsocket -lnsl -lc + X = + O = .o + A = .a + SO = .so + LIBPRE = lib +endif +ifeq "$(OS)" "linux" + DDSRT = posix + RULES = unix + CC = gcc-6.2 -std=gnu99 -fpic -mcx16 + OPT = #-fsanitize=address + # CC = gcc-6.2 -std=gnu99 -fpic -mcx16 + # OPT = -O3 -DNDEBUG -flto + LD = $(CC) + PROF = + CPPFLAGS += -Wall -g $(OPT) $(PROF) + CFLAGS += $(CPPFLAGS) #-fno-inline + LDFLAGS += -g $(OPT) $(PROF) + X = + O = .o + A = .a + SO = .so + LIBPRE = lib +endif +ifeq "$(OS)" "win32" + DDSRT = windows + RULES = windows + CC = cl + LD = link + # OPT = -O2 -DNDEBUG + OPT = -MDd + PROF = + CPPFLAGS = -Zi -W3 $(OPT) $(PROF) -TC # -bigobj + CFLAGS += $(CPPFLAGS) + LDFLAGS += -nologo -incremental:no -subsystem:console -debug + X = .exe + O = .obj + A = .lib + SO = .dll + LIBPRE = +# VS_VERSION=12.0 +# ifeq "$(VS_VERSION)" "12.0" # This works for VS2013 + Windows 10 +# VS_HOME=/cygdrive/c/Program Files (x86)/Microsoft Visual Studio 12.0 +# WINDOWSSDKDIR=/cygdrive/c/Program Files (x86)/Windows Kits/8.1 +# else # This works for VS2010 + Windows 7 +# VS_HOME=/cygdrive/C/Program Files (x86)/Microsoft Visual Studio 10.0 +# WINDOWSSDKDIR=/cygdrive/C/Program Files (x86)/Microsoft SDKs/Windows/v7.0A +# endif +endif +ifeq "$(OS)" "wine" + export WINEDEBUG=-all + DDSRT = windows + RULES = wine + GEN = gen.wine + CC = wine cl + LD = wine link + CPPFLAGS = -nologo -W3 -TC -analyze -D_WINNT=0x0604 -Drestrict= + CFLAGS += $(CPPFLAGS) + LDFLAGS += -nologo -incremental:no -subsystem:console -debug + X = .exe + O = .obj + A = .lib + SO = .dll + LIBPRE = +endif + +# use $(DDSRT) as a proxy for $(CONFIG) not matching anything +ifeq "$(DDSRT)" "" + $(error "$(CONFIG): unsupported config") +endif + +# We're assuming use of cygwin, which means Windows path names can be +# obtained using "cygpath". With "-m" we get slashes (rather than +# backslashes), which all of MS' tools accept and which are far less +# troublesome in make. +ifeq "$(CC)" "cl" + N_PWD := $(shell cygpath -m '$(PWD)') + #N_VS_HOME := $(shell cygpath -m '$(VS_HOME)') + #N_WINDOWSSDKDIR := $(shell cygpath -m '$(WINDOWSSDKDIR)') +else # not Windows + N_PWD := $(PWD) +endif + +# More machine- and platform-specific matters. +ifeq "$(CC)" "cl" # Windows + ifeq "$(PROC)" "x86_64" + MACHINE = -machine:X64 + endif + LDFLAGS += $(MACHINE) + OBJ_OFLAG = -Fo + EXE_OFLAG = -out: + SHLIB_OFLAG = -out: + CPPFLAGS += -D_CRT_SECURE_NO_WARNINGS +# ifeq "$(VS_VERSION)" "12.0" # This works for VS2013 + Windows 10 +# CPPFLAGS += '-I$(N_VS_HOME)/VC/include' '-I$(N_WINDOWSSDKDIR)/Include/um' '-I$(N_WINDOWSSDKDIR)/Include/shared' +# ifeq "$(PROC)" "x86_64" +# LDFLAGS += '-libpath:$(N_VS_HOME)/VC/lib/amd64' '-libpath:$(N_WINDOWSSDKDIR)/lib/winv6.3/um/x64' +# else +# LDFLAGS += '-libpath:$(N_VS_HOME)/VC/lib' '-libpath:$(N_WINDOWSSDKDIR)/lib/winv6.3/um/x86' +# endif +# else # This works for VS2010 + Windows 7 +# CPPFLAGS += '-I$(N_VS_HOME)/VC/include' '-I$(N_WINDOWSSDKDIR)/Include' +# ifeq "$(PROC)" "x86_64" +# LDFLAGS += '-libpath:$(N_VS_HOME)/VC/lib/amd64' '-libpath:$(N_WINDOWSSDKDIR)/lib/x64' +# else +# LDFLAGS += '-libpath:$(N_VS_HOME)/VC/lib' '-libpath:$(N_WINDOWSSDKDIR)/lib' +# endif +# endif +else + ifeq "$(CC)" "wine cl" + OBJ_OFLAG =-Fo + EXE_OFLAG = -out: + SHLIB_OFLAG = -out: + CPPFLAGS += -D_CRT_SECURE_NO_WARNINGS + else # not Windows (-like) + OBJ_OFLAG = -o + EXE_OFLAG = -o + SHLIB_OFLAG = -o + ifeq "$(PROC)" "x86" + CFLAGS += -m32 + LDFLAGS += -m32 + endif + ifeq "$(PROC)" "x86_64" + CFLAGS += -m64 + LDFLAGS += -m64 + endif + endif +endif + +ifeq "$(CC)" "cl" + LDFLAGS += -libpath:$(N_PWD)/gen + LIBDEP_SYS = kernel32 ws2_32 +else + ifeq "$(CC)" "wine cl" + else + LDFLAGS += -L$(N_PWD)/gen + LIBDEP_SYS = kernel32 ws2_32 + endif +endif + +getabspath=$(abspath $1) +ifeq "$(RULES)" "darwin" + ifneq "$(findstring clang, $(CC))" "" + define make_exe + $(LD) $(LDFLAGS) $(patsubst -L%, -rpath %, $(filter -L%, $(LDFLAGS))) $(EXE_OFLAG)$@ $^ $(LDLIBS) + endef + define make_shlib + $(LD) $(LDFLAGS) $(patsubst -L%, -rpath %, $(filter -L%, $(LDFLAGS))) -dynamiclib -install_name @rpath/$(notdir $@) $(SHLIB_OFLAG)$@ $^ $(LDLIBS) + endef + else # assume gcc + comma=, + define make_exe + $(LD) $(LDFLAGS) $(patsubst -L%, -Wl$(comma)-rpath$(comma)%, $(filter -L%, $(LDFLAGS))) $(EXE_OFLAG)$@ $^ $(LDLIBS) + endef + define make_shlib + $(LD) $(LDFLAGS) $(patsubst -L%, -Wl$(comma)-rpath$(comma)%, $(filter -L%, $(LDFLAGS))) -dynamiclib -Wl,-install_name,@rpath/$(notdir $@) $(SHLIB_OFLAG)$@ $^ $(LDLIBS) + endef + endif + define make_archive + ar -ru $@ $? + endef + define make_dep + $(CC) -M $(CPPFLAGS) $< | sed 's|[a-zA-Z0-9_-]*\.o|gen/&|' > $@ || { rm $@ ; exit 1 ; } + endef +else + ifeq "$(RULES)" "unix" + LDLIBS += -lpthread + comma=, + define make_exe + $(LD) $(LDFLAGS) $(patsubst -L%,-Wl$(comma)-rpath$(comma)%, $(filter -L%, $(LDFLAGS))) $(EXE_OFLAG)$@ $^ $(LDLIBS) + endef + define make_shlib + $(LD) $(LDFLAGS) -Wl$(comma)--no-allow-shlib-undefined $(patsubst -L%,-Wl$(comma)-rpath$(comma)%, $(filter -L%, $(LDFLAGS))) -shared $(SHLIB_OFLAG)$@ $^ $(LDLIBS) + endef + define make_archive + ar -ru $@ $? + endef + define make_dep + $(CC) -M $(CPPFLAGS) $< | sed 's|[a-zA-Z0-9_-]*\.o|gen/&|' > $@ || { rm $@ ; exit 1 ; } + endef + else + ifeq "$(RULES)" "windows" + define make_exe + $(LD) $(LDFLAGS) $(EXE_OFLAG)$@ $^ $(LDLIBS) + endef + define make_shlib + $(LD) $(LDFLAGS) $(SHLIB_OFLAG)$@ $^ $(LDLIBS) + endef + define make_archive + lib $(MACHINE) /out:$@ $^ + endef + define make_dep + $(CC) -E $(CPPFLAGS) $(CPPFLAGS) $< | grep "^#line.*\\\\vdds\\\\" | cut -d '"' -f 2 | sort -u | sed -e 's@\([A-Za-z]\)\:@ /cygdrive/\1@' -e 's@\\\\@/@g' -e '$$!s@$$@ \\@' -e '1s@^@$*$O: @' >$@ + endef + else + ifeq "$(RULES)" "wine" + COMPILE_MANY_ATONCE=true + getabspath=$1 + lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1)))))))))))))))))))))))))) + FAKEPWD = $(call lc,z:$(subst /,\\\\,$(PWD))) + define make_exe + $(LD) $(LDFLAGS) $(EXE_OFLAG)$@ $^ $(LDLIBS) + endef + define make_shlib + $(LD) $(LDFLAGS) $(SHLIB_OFLAG)$@ $^ $(LDLIBS) + endef + define make_archive + lib $(MACHINE) /out:$@ $^ + endef + define make_dep + $(CC) -E $(CPPFLAGS) $(CPPFLAGS) $< | grep "^#line.*\\\\vdds\\\\" | cut -d '"' -f 2 | sort -u | sed -e 's@$(FAKEPWD)\(\\\\\)*@ @' -e 's@\\\\@/@g' -e '$$!s@$$@ \\@' -e '1s@^@$*$O: @' >$@ + endef + else + $(error "$(OS) not covered by build macros for") + endif + endif + endif +endif + +ifeq "$(GEN)" "" + GEN = gen +endif + +%$O: +%$X: +%$(SO): +%.d: diff --git a/ports/solaris2.6/guess-config b/ports/solaris2.6/guess-config new file mode 100755 index 0000000..845b587 --- /dev/null +++ b/ports/solaris2.6/guess-config @@ -0,0 +1,52 @@ +#!/bin/sh + +s=`uname -s` +case "$s" in + [Dd]arwin) + # default to G4 for now + m=`uname -m` + case "$m" in + x86_64) + cfg="x86_64.darwin" + ;; + *) + echo "guess-config: darwin: didn't recognize machine type $m - please fix" 2>&1 + ;; + esac + ;; + [Ll]inux) + m=`uname -m` + case "$m" in + arm*) + cfg=arm.linux.6 + ;; + x86_64) + cfg=x86_64.linux.6 + ;; + *) + cfg=x86.linux.6 + ;; + esac + ;; + [Ss]un[Oo][Ss]|[Ss]olaris) + m=`uname -m`:`uname -r` + #should check OS rev + case "$m" in + sun4m:5.6) + cfg="sparc.solaris2.6" + ;; + sun4u:*) + cfg="sparcv9.solaris" + ;; + *) + cfg="x86_64.solaris" + ;; + esac + ;; + *) + echo "guess-config: didn't recognize system type $s - please fix" 2>&1 + ;; +esac + +[ -z "$cfg" ] && cfg="asjemenou" +echo $cfg diff --git a/ports/solaris2.6/include/inttypes.h b/ports/solaris2.6/include/inttypes.h new file mode 100644 index 0000000..9db935f --- /dev/null +++ b/ports/solaris2.6/include/inttypes.h @@ -0,0 +1,8 @@ +#ifndef DDSRT_FIXUP_INTTYPES_H +#define DDSRT_FIXUP_INTTYPES_H + +#include_next "inttypes.h" +#define PRIuPTR "lu" +#define PRIxPTR "lx" + +#endif /* DDSRT_FIXUP_INTTYPES_H */ diff --git a/ports/solaris2.6/include/math.h b/ports/solaris2.6/include/math.h new file mode 100644 index 0000000..21339b1 --- /dev/null +++ b/ports/solaris2.6/include/math.h @@ -0,0 +1,22 @@ +#ifndef DDSRT_FIXUP_MATH_H +#define DDSRT_FIXUP_MATH_H + +#include_next "math.h" + +/* INFINITY, HUGE_VALF, HUGE_VALL are all standard C99, but Solaris 2.6 + antedates that by a good margin and GCC's fixed-up headers don't + define it, so we do it here */ +#undef HUGE_VAL +#ifdef __GNUC__ +# define INFINITY (__builtin_inff ()) +# define HUGE_VAL (__builtin_huge_val ()) +# define HUGE_VALF (__builtin_huge_valf ()) +# define HUGE_VALL (__builtin_huge_vall ()) +#else +# define INFINITY 1e10000 +# define HUGE_VAL 1e10000 +# define HUGE_VALF 1e10000f +# define HUGE_VALL 1e10000L +#endif + +#endif /* DDSRT_FIXUP_MATH_H */ diff --git a/ports/solaris2.6/include/netinet/in.h b/ports/solaris2.6/include/netinet/in.h new file mode 100644 index 0000000..fa608eb --- /dev/null +++ b/ports/solaris2.6/include/netinet/in.h @@ -0,0 +1,10 @@ +#ifndef DDSRT_FIXUP_NETINET_IN_H +#define DDSRT_FIXUP_NETINET_IN_H + +#include_next "netinet/in.h" + +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif + +#endif /* DDSRT_FIXUP_NETINET_IN_H */ diff --git a/ports/solaris2.6/include/stdint.h b/ports/solaris2.6/include/stdint.h new file mode 100644 index 0000000..490a41e --- /dev/null +++ b/ports/solaris2.6/include/stdint.h @@ -0,0 +1,11 @@ +#ifndef DDSRT_FIXUP_STDINT_H +#define DDSRT_FIXUP_STDINT_H + +#include +#include + +#ifndef UINT32_C +#define UINT32_C(v) (v ## U) +#endif + +#endif /* DDSRT_FIXUP_STDINT_H */ diff --git a/ports/solaris2.6/include/sys/socket.h b/ports/solaris2.6/include/sys/socket.h new file mode 100644 index 0000000..1160e15 --- /dev/null +++ b/ports/solaris2.6/include/sys/socket.h @@ -0,0 +1,14 @@ +#ifndef DDSRT_FIXUP_SYS_SOCKET_H +#define DDSRT_FIXUP_SYS_SOCKET_H + +#include "netinet/in.h" +#include_next "sys/socket.h" + +typedef size_t socklen_t; + +struct sockaddr_storage { + sa_family_t ss_family; + struct sockaddr_in stuff; +}; + +#endif /* DDSRT_FIXUP_SYS_SOCKET_H */ diff --git a/ports/solaris2.6/makefile b/ports/solaris2.6/makefile new file mode 100644 index 0000000..31d0233 --- /dev/null +++ b/ports/solaris2.6/makefile @@ -0,0 +1,59 @@ +.PHONY: all clean + +include $(dir $(lastword $(MAKEFILE_LIST)))/config.mk + +CPPFLAGS += -Isrc/core/ddsc/src -Isrc/core/ddsc/include -Isrc/core/ddsi/include -Isrc/ddsrt/include +CPPFLAGS += $(addprefix -I, $(wildcard src/ddsrt/src/*/include)) +CPPFLAGS += -Ibuild/core/include -Ibuild/ddsrt/include +CPPFLAGS += -DDDSI_INCLUDE_NETWORK_PARTITIONS # -DDDSI_INCLUDE_BANDWIDTH_LIMITING -DDDSI_INCLUDE_NETWORK_CHANNELS + +SHLIBS = ddsc +EXES = ddsperf + +all: $(SHLIBS:%=$(GEN)/$(LIBPRE)%$(SO)) $(EXES:%=$(GEN)/%$X) +lib: $(SHLIBS:%=$(GEN)/$(LIBPRE)%$(SO)) + +clean: + rm -rf $(GEN)/* + +LIBCDDS_SRCDIRS := src/core/ddsi/src src/core/ddsc/src src/ddsrt/src $(DDSRT:%=src/ddsrt/src/*/%) +LIBCDDS_SRC := $(filter-out %/getopt.c, $(wildcard $(LIBCDDS_SRCDIRS:%=%/*.c))) +ifeq "$(words $(DDSRT))" "2" # max = 2 ... + pct=% + XX=$(filter src/ddsrt/src/%/$(word 1, $(DDSRT))/, $(dir $(LIBCDDS_SRC))) + YY=$(patsubst %/$(word 1, $(DDSRT))/, %/$(word 2, $(DDSRT))/, $(XX)) + LIBCDDS_SRC := $(filter-out $(YY:%=%$(pct)), $(LIBCDDS_SRC)) +endif + +$(GEN)/$(LIBPRE)ddsc$(SO): CPPFLAGS += -Dddsc_EXPORTS +$(GEN)/$(LIBPRE)ddsc$(SO): CPPFLAGS += -fPIC + +ifneq "$(COMPILE_MANY_ATONCE)" "true" +$(GEN)/$(LIBPRE)ddsc$(SO): $(LIBCDDS_SRC:%.c=$(GEN)/%$O) + $(make_shlib) +else # /Fo bit is MSVC specific +$(GEN)/$(LIBPRE)ddsc$(SO): $(LIBCDDS_SRC) + xs="" ;\ + for x in $(foreach x, $^, $(call getabspath, $x)) ; do \ + [ $$x -nt $(GEN)/`basename $$x .c`$O ] && xs="$$xs $$x" ; \ + done ; \ + echo "compile: $$xs" ; \ + [ -z "$$xs" ] || $(CC) $(CPPFLAGS) -MP8 -Fo.\\$(GEN)\\ -c $$xs + $(LD) $(LDFLAGS) $(SHLIB_OFLAG)$@ $(LIBCDDS_SC:%=$(GEN)/%$O) $(LDLIBS) +endif + +DDSPERF_SRCDIRS := src/tools/ddsperf build/tools/ddsperf +DDSPERF_SRC := $(wildcard $(DDSPERF_SRCDIRS:%=%/*.c)) + +$(GEN)/ddsperf$X: LDLIBS += -L. -lddsc +$(GEN)/ddsperf$X: CPPFLAGS += -Ibuild/tools/ddsperf +$(GEN)/ddsperf$X: $(DDSPERF_SRC:%.c=%.o) | $(GEN)/$(LIBPRE)ddsc$(SO) + $(make_exe) + +$(GEN)/%.STAMP: ; @[ -d $(dir $@) ] || { mkdir -p $(dir $@) ; touch $@ ; } + +$(GEN)/%$O: %.c $(GEN)/%.STAMP + $(CC) $(CPPFLAGS) $(OBJ_OFLAG)$@ -c $< + +$(GEN)/%.d: %.c + $(make_dep) diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_udp.h b/src/core/ddsi/include/dds/ddsi/ddsi_udp.h index 1305dab..5e9a22e 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_udp.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_udp.h @@ -16,6 +16,15 @@ extern "C" { #endif + typedef struct nn_udpv4mcgen_address { + /* base IPv4 MC address is ipv4, host bits are bits base .. base+count-1, this machine is bit idx */ + struct in_addr ipv4; + uint8_t base; + uint8_t count; + uint8_t idx; /* must be last: then sorting will put them consecutively */ + } nn_udpv4mcgen_address_t; + + int ddsi_udp_init (void); #if defined (__cplusplus) diff --git a/src/core/ddsi/include/dds/ddsi/q_protocol.h b/src/core/ddsi/include/dds/ddsi/q_protocol.h index 0386402..6980285 100644 --- a/src/core/ddsi/include/dds/ddsi/q_protocol.h +++ b/src/core/ddsi/include/dds/ddsi/q_protocol.h @@ -62,14 +62,6 @@ typedef struct { unsigned char address[16]; } nn_locator_t; -typedef struct nn_udpv4mcgen_address { - /* base IPv4 MC address is ipv4, host bits are bits base .. base+count-1, this machine is bit idx */ - struct in_addr ipv4; - uint8_t base; - uint8_t count; - uint8_t idx; /* must be last: then sorting will put them consecutively */ -} nn_udpv4mcgen_address_t; - #define NN_STATUSINFO_DISPOSE 0x1u #define NN_STATUSINFO_UNREGISTER 0x2u #define NN_STATUSINFO_STANDARDIZED (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER) diff --git a/src/core/ddsi/src/q_addrset.c b/src/core/ddsi/src/q_addrset.c index b20eb72..e29c12a 100644 --- a/src/core/ddsi/src/q_addrset.c +++ b/src/core/ddsi/src/q_addrset.c @@ -23,6 +23,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_addrset.h" #include "dds/ddsi/q_globals.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 pure function just in case some other thread is trying to change diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index e9f09bc..6347bde 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -41,6 +41,7 @@ #include "dds/ddsi/ddsi_serdata_default.h" #include "dds/ddsi/ddsi_mcgroup.h" #include "dds/ddsi/q_receive.h" +#include "dds/ddsi/ddsi_udp.h" /* nn_mc4gen_address_t */ #include "dds/ddsi/sysdeps.h" #include "dds__whc.h" diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 607c8ec..ee8bc80 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -28,6 +28,7 @@ #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/ddsi_vendor.h" +#include "dds/ddsi/ddsi_udp.h" /* nn_mc4gen_address_t */ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_globals.h" diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 4cfa4ea..03bb09a 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -38,16 +38,6 @@ #include "dds/ddsi/sysdeps.h" #include "dds__whc.h" -#if __STDC_VERSION__ >= 199901L -#define POS_INFINITY_DOUBLE INFINITY -#elif defined HUGE_VAL -/* Hope for the best -- the only consequence of getting this wrong is - that T_NEVER may be printed as a fugly value instead of as +inf. */ -#define POS_INFINITY_DOUBLE (HUGE_VAL + HUGE_VAL) -#else -#define POS_INFINITY_DOUBLE 1e1000 -#endif - static const struct wr_prd_match *root_rdmatch (const struct writer *wr) { return ddsrt_avl_root (&wr_readers_treedef, &wr->readers); @@ -310,7 +300,7 @@ struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_ DDS_TRACE("heartbeat(wr "PGUIDFMT"%s) piggybacked, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n", PGUID (wr->e.guid), *hbansreq ? "" : " final", - (hbc->tsched.v == T_NEVER) ? POS_INFINITY_DOUBLE : (double) (hbc->tsched.v - tnow.v) / 1e9, + (hbc->tsched.v == T_NEVER) ? INFINITY : (double) (hbc->tsched.v - tnow.v) / 1e9, ddsrt_avl_is_empty (&wr->readers) ? -1 : root_rdmatch (wr)->min_seq, ddsrt_avl_is_empty (&wr->readers) || root_rdmatch (wr)->all_have_replied_to_hb ? "" : "!", whcst->max_seq, READ_SEQ_XMIT(wr)); diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index c1bd837..9f1ad3a 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -48,14 +48,6 @@ != 0 -- and note that it had better be 2's complement machine! */ #define TSCHED_DELETE ((int64_t) ((uint64_t) 1 << 63)) -#if __STDC_VERSION__ >= 199901L -#define POS_INFINITY_DOUBLE INFINITY -#else -/* Hope for the best -- the only consequence of getting this wrong is - that T_NEVER may be printed as a fugly value instead of as +inf. */ -#define POS_INFINITY_DOUBLE (HUGE_VAL + HUGE_VAL) -#endif - enum xeventkind { XEVK_HEARTBEAT, @@ -623,7 +615,7 @@ static void handle_xevk_heartbeat (struct nn_xpack *xp, struct xevent *ev, nn_mt PGUID (wr->e.guid), hbansreq ? "" : " final", msg ? "sent" : "suppressed", - (t_next.v == T_NEVER) ? POS_INFINITY_DOUBLE : (double)(t_next.v - tnow.v) / 1e9, + (t_next.v == T_NEVER) ? INFINITY : (double)(t_next.v - tnow.v) / 1e9, ddsrt_avl_is_empty (&wr->readers) ? (seqno_t) -1 : ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->min_seq, ddsrt_avl_is_empty (&wr->readers) || ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->all_have_replied_to_hb ? "" : "!", whcst.max_seq, READ_SEQ_XMIT(wr)); diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index ca286ed..c78faf1 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -150,10 +150,10 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage sockets string sync threads time md5 process) if(EXISTS "${include_path}/dds/ddsrt/${feature}.h") list(APPEND headers "${include_path}/dds/ddsrt/${feature}.h") - file(GLOB + file(GLOB_RECURSE files CONFIGURE_DEPENDS - "${include_path}/dds/ddsrt/${feature}/**.h") + "${include_path}/dds/ddsrt/${feature}/*.h") list(APPEND headers ${files}) # Do not add any sources if a feature is not offered by the target. The @@ -193,20 +193,20 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage # Headers that must remain private but are required by other runtime # source files must be located in src//dds/ddsrt. if(IS_DIRECTORY "${source_path}/${feature}/include") - file(GLOB + file(GLOB_RECURSE files CONFIGURE_DEPENDS - "${source_path}/${feature}/include/**.h") - list(APPEND sources ${files}) + "${source_path}/${feature}/include/*.h") + list(APPEND headers ${files}) target_include_directories( ddsrt INTERFACE "$") endif() if(IS_DIRECTORY "${source_path}/${feature}/${system}") - file(GLOB + file(GLOB_RECURSE files CONFIGURE_DEPENDS - "${source_path}/${feature}/${system}/**.c") + "${source_path}/${feature}/${system}/*.c") list(APPEND sources ${files}) set(system_exists TRUE) endif() diff --git a/src/ddsrt/include/dds/ddsrt/sockets/posix.h b/src/ddsrt/include/dds/ddsrt/sockets/posix.h index a6f9574..21cc327 100644 --- a/src/ddsrt/include/dds/ddsrt/sockets/posix.h +++ b/src/ddsrt/include/dds/ddsrt/sockets/posix.h @@ -16,12 +16,12 @@ #include #include #else +#include #include #include #include #include #include -#include #endif #if defined(__cplusplus) @@ -37,19 +37,32 @@ typedef int ddsrt_socket_t; # define DDSRT_HAVE_IPV6 1 # endif # if LWIP_DNS && LWIP_SOCKET -# define DDSRT_HAVE_DNS DDSRT_WITH_DNS +# define DDSRT_HAVE_DNS DDSRT_WITH_DNS +# define DDSRT_HAVE_GETADDRINFO DDSRT_WITH_DNS # endif -# define DDSRT_HAVE_SSM 0 +# define DDSRT_HAVE_SSM 0 +# define DDSRT_HAVE_INET_NTOP 1 +# define DDSRT_HAVE_INET_PTON 1 -# define IFF_UP 0x1 -# define IFF_BROADCAST 0x2 -# define IFF_LOOPBACK 0x8 -# define IFF_POINTOPOINT 0x10 +# define IFF_UP 0x1 +# define IFF_BROADCAST 0x2 +# define IFF_LOOPBACK 0x8 +# define IFF_POINTOPOINT 0x10 # define IFF_MULTICAST 0x1000 +#elif __SunOS_5_6 +# define DDSRT_HAVE_IPV6 0 +# define DDSRT_HAVE_DNS DDSRT_WITH_DNS +# define DDSRT_HAVE_GETADDRINFO 0 +# define DDSRT_HAVE_SSM 0 +# define DDSRT_HAVE_INET_NTOP 0 +# define DDSRT_HAVE_INET_PTON 0 #else /* LWIP_SOCKET */ -# define DDSRT_HAVE_IPV6 1 -# define DDSRT_HAVE_DNS DDSRT_WITH_DNS -# define DDSRT_HAVE_SSM 1 +# define DDSRT_HAVE_IPV6 1 +# define DDSRT_HAVE_DNS DDSRT_WITH_DNS +# define DDSRT_HAVE_GETADDRINFO DDSRT_WITH_DNS +# define DDSRT_HAVE_SSM 1 +# define DDSRT_HAVE_INET_NTOP 1 +# define DDSRT_HAVE_INET_PTON 1 #endif /* LWIP_SOCKET */ typedef struct iovec ddsrt_iovec_t; diff --git a/src/ddsrt/include/dds/ddsrt/sockets/windows.h b/src/ddsrt/include/dds/ddsrt/sockets/windows.h index 1735d39..b557a21 100644 --- a/src/ddsrt/include/dds/ddsrt/sockets/windows.h +++ b/src/ddsrt/include/dds/ddsrt/sockets/windows.h @@ -12,8 +12,11 @@ typedef SOCKET ddsrt_socket_t; #define DDSRT_INVALID_SOCKET (INVALID_SOCKET) #define PRIdSOCK PRIuPTR -#define DDSRT_HAVE_IPV6 1 -#define DDSRT_HAVE_DNS DDSRT_WITH_DNS +#define DDSRT_HAVE_IPV6 1 +#define DDSRT_HAVE_DNS DDSRT_WITH_DNS +#define DDSRT_HAVE_GETADDRINFO DDSRT_WITH_DNS +#define DDSRT_HAVE_INET_NTOP 1 +#define DDSRT_HAVE_INET_PTON 1 #if defined(NTDDI_VERSION) && \ defined(_WIN32_WINNT_WS03) && \ diff --git a/src/ddsrt/include/dds/ddsrt/sync.h b/src/ddsrt/include/dds/ddsrt/sync.h index f071237..a9e62e3 100644 --- a/src/ddsrt/include/dds/ddsrt/sync.h +++ b/src/ddsrt/include/dds/ddsrt/sync.h @@ -22,6 +22,8 @@ #include "dds/ddsrt/sync/freertos.h" #elif _WIN32 #include "dds/ddsrt/sync/windows.h" +#elif __SunOS_5_6 +#include "dds/ddsrt/sync/solaris2.6.h" #else #include "dds/ddsrt/sync/posix.h" #endif diff --git a/src/ddsrt/include/dds/ddsrt/sync/solaris2.6.h b/src/ddsrt/include/dds/ddsrt/sync/solaris2.6.h new file mode 100644 index 0000000..34b1956 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/sync/solaris2.6.h @@ -0,0 +1,44 @@ +/* + * 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_POSIX_SYNC_H +#define DDSRT_POSIX_SYNC_H + +#include +#include +#if HAVE_LKST +#include "lkst.h" +#endif + +#if defined (__cplusplus) +extern "C" { +#endif + +typedef struct { + pthread_cond_t cond; +} ddsrt_cond_t; + +typedef struct { + pthread_mutex_t mutex; +} ddsrt_mutex_t; + +typedef struct { + pthread_mutex_t rwlock; +} ddsrt_rwlock_t; + +typedef pthread_once_t ddsrt_once_t; +#define DDSRT_ONCE_INIT PTHREAD_ONCE_INIT + +#if defined (__cplusplus) +} +#endif + +#endif /* DDSRT_POSIX_SYNC_H */ diff --git a/src/ddsrt/src/atomics.c b/src/ddsrt/src/atomics.c index a23113c..8be481e 100644 --- a/src/ddsrt/src/atomics.c +++ b/src/ddsrt/src/atomics.c @@ -165,22 +165,30 @@ void ddsrt_atomic_lifo_pushmany (ddsrt_atomic_lifo_t *head, void *first, void *l } #endif -#if DDSRT_HAVE_ATOMIC64 -void ddsrt_atomics_init (void) -{ -} +/* On platforms that don't provide 64-bit atomic operations, emulate them by hashing + the variable's address to a small set of mutexes. -void ddsrt_atomics_fini (void) -{ -} + This also defines the GCC builtins on SPARCv8 for 32-bit operations. It would be + more appropriate to simply define the ddsrt_atomic_... functions properly in that + case and avoid squatting in the __sync_... namespace, but SPARCv8 support really + is just for fun and it doesn't seem worth the bother right now */ + +#if DDSRT_HAVE_ATOMIC64 + +void ddsrt_atomics_init (void) { } +void ddsrt_atomics_fini (void) { } #else -/* Emulation by hashing the variable's address to a small set of mutexes. */ #include "dds/ddsrt/sync.h" +/* SPARCv8 depends on these mutexes already for one-shot initialisation of the ddsrt + code. Using PTHREAD_MUTEX_INITIALIZER guarantees they are properly initialized. + Once a platform shows up that defines that macro where we don't used pthread mutexes + something else will have to be done. */ #define N_MUTEXES_LG2 4 #define N_MUTEXES (1 << N_MUTEXES_LG2) +#ifndef PTHREAD_MUTEX_INITIALIZER static ddsrt_mutex_t mutexes[N_MUTEXES]; void ddsrt_atomics_init (void) @@ -194,6 +202,20 @@ void ddsrt_atomics_fini (void) for (int i = 0; i < N_MUTEXES; i++) ddsrt_mutex_destroy (&mutexes[i]); } +#else +static ddsrt_mutex_t mutexes[N_MUTEXES] = { + { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, + { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, + { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, + { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, + { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, + { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, + { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }, + { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER } +}; +void ddsrt_atomics_init (void) { } +void ddsrt_atomics_fini (void) { } +#endif static uint32_t atomic64_lock_index (const volatile ddsrt_atomic_uint64_t *x) { @@ -219,7 +241,25 @@ int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_t exp, uint64_ } } -uint64_t ddsrt_atomic_ld64(const volatile ddsrt_atomic_uint64_t *x) +#define DDSRT_FAKE_ATOMIC64(name, oper, ret) \ + uint64_t ddsrt_atomic_##name##64_##ret (volatile ddsrt_atomic_uint64_t *x, uint64_t v) \ + { \ + const uint64_t idx = atomic64_lock_index (x); \ + ddsrt_mutex_lock (&mutexes[idx]); \ + const uint64_t ov = x->v; \ + const uint64_t nv = ov oper v; \ + x->v = nv; \ + ddsrt_mutex_unlock (&mutexes[idx]); \ + return ret; \ + } +#define DDSRT_FAKE_ATOMIC64_TRIPLET(name, oper) \ + DDSRT_FAKE_ATOMIC64(name, oper, nv) \ + DDSRT_FAKE_ATOMIC64(name, oper, ov) \ + void ddsrt_atomic_##name##64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) { \ + (void) ddsrt_atomic_##name##64_ov (x, v); \ + } + +uint64_t ddsrt_atomic_ld64 (const volatile ddsrt_atomic_uint64_t *x) { const uint32_t idx = atomic64_lock_index (x); ddsrt_mutex_lock (&mutexes[idx]); @@ -228,7 +268,7 @@ uint64_t ddsrt_atomic_ld64(const volatile ddsrt_atomic_uint64_t *x) return v; } -void ddsrt_atomic_st64(volatile ddsrt_atomic_uint64_t *x, uint64_t v) +void ddsrt_atomic_st64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) { const uint32_t idx = atomic64_lock_index (x); ddsrt_mutex_lock (&mutexes[idx]); @@ -236,136 +276,70 @@ void ddsrt_atomic_st64(volatile ddsrt_atomic_uint64_t *x, uint64_t v) ddsrt_mutex_unlock (&mutexes[idx]); } -void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) -{ - const uint32_t idx = atomic64_lock_index (x); - ddsrt_mutex_lock (&mutexes[idx]); - ++x->v; - ddsrt_mutex_unlock (&mutexes[idx]); +DDSRT_FAKE_ATOMIC64_TRIPLET(add, +) +DDSRT_FAKE_ATOMIC64_TRIPLET(sub, -) +DDSRT_FAKE_ATOMIC64_TRIPLET(or, |) +DDSRT_FAKE_ATOMIC64_TRIPLET(and, &) + +void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) { + ddsrt_atomic_add64 (x, 1); +} +uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x) { + return ddsrt_atomic_add64_nv (x, 1); +} +void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x) { + ddsrt_atomic_sub64 (x, 1); +} +uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x) { + return ddsrt_atomic_sub64_nv (x, 1); } -uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x) +#undef DDSRT_FAKE_ATOMIC64_TRIPLET +#undef DDSRT_FAKE_ATOMIC64 + +/* SPARCv8 doesn't support any atomic operations beyond a simple atomic exchange. GCC happily + compiles the __sync_* functions into library calls, and implementing them as such will do + the trick. The rarity of SPARCv8 machines (EOL'd 2 decades ago) */ +#ifdef __sparc_v8__ +#define DDSRT_FAKE_SYNC(name, size, oper, ret) \ + unsigned __sync_##name##_##size (volatile unsigned *x, unsigned v) \ + { \ + const uint32_t idx = atomic64_lock_index ((const volatile ddsrt_atomic_uint64_t *) x); \ + ddsrt_mutex_lock (&mutexes[idx]); \ + const uint32_t ov = *x; \ + const uint32_t nv = ov oper v; \ + *x = nv; \ + ddsrt_mutex_unlock (&mutexes[idx]); \ + return ret; \ + } +#define DDSRT_FAKE_SYNC_PAIR(name, size, oper) \ + DDSRT_FAKE_SYNC(name##_and_fetch, size, oper, nv) \ + DDSRT_FAKE_SYNC(fetch_and_##name, size, oper, ov) + +DDSRT_FAKE_SYNC_PAIR (add, 4, +) +DDSRT_FAKE_SYNC_PAIR (sub, 4, -) +DDSRT_FAKE_SYNC_PAIR (or, 4, |) +DDSRT_FAKE_SYNC_PAIR (and, 4, &) + +bool __sync_bool_compare_and_swap_4 (volatile unsigned *x, unsigned exp, unsigned des) { - const uint32_t idx = atomic64_lock_index (x); + const uint32_t idx = atomic64_lock_index ((const volatile ddsrt_atomic_uint64_t *) x); ddsrt_mutex_lock (&mutexes[idx]); - const uint64_t nv = ++x->v; - ddsrt_mutex_unlock (&mutexes[idx]); - return nv; + if (*x == exp) + { + *x = des; + ddsrt_mutex_unlock (&mutexes[idx]); + return true; + } + else + { + ddsrt_mutex_unlock (&mutexes[idx]); + return false; + } } -void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x) -{ - const uint32_t idx = atomic64_lock_index (x); - ddsrt_mutex_lock (&mutexes[idx]); - --x->v; - ddsrt_mutex_unlock (&mutexes[idx]); -} - -uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x) -{ - const uint32_t idx = atomic64_lock_index (x); - ddsrt_mutex_lock (&mutexes[idx]); - const uint64_t nv = --x->v; - ddsrt_mutex_unlock (&mutexes[idx]); - return nv; -} - -void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) -{ - const uint32_t idx = atomic64_lock_index (x); - ddsrt_mutex_lock (&mutexes[idx]); - x->v += v; - ddsrt_mutex_unlock (&mutexes[idx]); -} - -uint64_t ddsrt_atomic_add64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) -{ - const uint32_t idx = atomic64_lock_index (x); - ddsrt_mutex_lock (&mutexes[idx]); - const uint64_t ov = x->v; - const uint64_t nv = ov + v; - x->v = nv; - ddsrt_mutex_unlock (&mutexes[idx]); - return nv; -} - -void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) -{ - const uint32_t idx = atomic64_lock_index (x); - ddsrt_mutex_lock (&mutexes[idx]); - x->v -= v; - ddsrt_mutex_unlock (&mutexes[idx]); -} - -uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) -{ - const uint32_t idx = atomic64_lock_index (x); - ddsrt_mutex_lock (&mutexes[idx]); - const uint64_t ov = x->v; - const uint64_t nv = ov - v; - x->v = nv; - ddsrt_mutex_unlock (&mutexes[idx]); - return nv; -} - -void ddsrt_atomic_and64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) -{ - const uint32_t idx = atomic64_lock_index (x); - ddsrt_mutex_lock (&mutexes[idx]); - x->v &= v; - ddsrt_mutex_unlock (&mutexes[idx]); -} - -uint64_t ddsrt_atomic_and64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v) -{ - const uint32_t idx = atomic64_lock_index (x); - ddsrt_mutex_lock (&mutexes[idx]); - const uint64_t ov = x->v; - const uint64_t nv = ov & v; - x->v = nv; - ddsrt_mutex_unlock (&mutexes[idx]); - return ov; -} - -uint64_t ddsrt_atomic_and64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) -{ - const uint32_t idx = atomic64_lock_index (x); - ddsrt_mutex_lock (&mutexes[idx]); - const uint64_t ov = x->v; - const uint64_t nv = ov & v; - x->v = nv; - ddsrt_mutex_unlock (&mutexes[idx]); - return nv; -} - -void ddsrt_atomic_or64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) -{ - const uint32_t idx = atomic64_lock_index (x); - ddsrt_mutex_lock (&mutexes[idx]); - x->v |= v; - ddsrt_mutex_unlock (&mutexes[idx]); -} - -uint64_t ddsrt_atomic_or64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v) -{ - const uint32_t idx = atomic64_lock_index (x); - ddsrt_mutex_lock (&mutexes[idx]); - const uint64_t ov = x->v; - const uint64_t nv = ov | v; - x->v = nv; - ddsrt_mutex_unlock (&mutexes[idx]); - return ov; -} - -uint64_t ddsrt_atomic_or64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) -{ - const uint32_t idx = atomic64_lock_index (x); - ddsrt_mutex_lock (&mutexes[idx]); - const uint64_t ov = x->v; - const uint64_t nv = ov | v; - x->v = nv; - ddsrt_mutex_unlock (&mutexes[idx]); - return nv; -} +#undef DDSRT_FAKE_SYNC_PAIR +#undef DDSRT_FAKE_SYNC +#endif /* SPARCv8 hack */ #endif /* DDSRT_HAVE_ATOMIC64 */ diff --git a/src/ddsrt/src/environ/solaris2.6/environ.c b/src/ddsrt/src/environ/solaris2.6/environ.c new file mode 100644 index 0000000..83f0d8f --- /dev/null +++ b/src/ddsrt/src/environ/solaris2.6/environ.c @@ -0,0 +1,100 @@ +/* + * 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 +#include +#include + +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/retcode.h" + +extern char **environ; + +static int +isenvvar(const char *name) +{ + return (*name == '\0' || strchr(name, '=') != NULL) == 0; +} + +dds_return_t +ddsrt_getenv(const char *name, char **value) +{ + char *env; + + assert(name != NULL); + assert(value != NULL); + + if (!isenvvar(name)) + return DDS_RETCODE_BAD_PARAMETER; + if ((env = getenv(name)) != NULL) { + *value = env; + return DDS_RETCODE_OK; + } + return DDS_RETCODE_NOT_FOUND; +} + +dds_return_t +ddsrt_setenv(const char *name, const char *value) +{ + /* Not MT-Safe -- but it is only used in a tests to set + CYCLONEDDS_URI, so for Solaris 2.6 support it is not worth the + bother to do a better job. Same for a bit of leakage. */ + assert(name != NULL); + assert(value != NULL); + + if (strlen(value) == 0) + return ddsrt_unsetenv(name); + if (!isenvvar(name)) + return DDS_RETCODE_BAD_PARAMETER; + + const size_t namelen = strlen (name); + const size_t entrysize = namelen + 1 + strlen (value) + 1; + char *entry = malloc (entrysize); + snprintf (entry, entrysize, "%s=%s", name, value); + size_t n = 0; + while (environ[n] != NULL) + { + if (strncmp (environ[n], name, namelen) == 0 && environ[n][namelen] == '=') + { + environ[n] = entry; + return DDS_RETCODE_OK; + } + n++; + } + environ = realloc (environ, (n + 2) * sizeof (*environ)); + environ[n] = entry; + environ[n+1] = NULL; + return DDS_RETCODE_OK; +} + +dds_return_t +ddsrt_unsetenv(const char *name) +{ + /* Same considerations as setenv. */ + assert(name != NULL); + + if (!isenvvar(name)) + return DDS_RETCODE_BAD_PARAMETER; + + const size_t namelen = strlen (name); + size_t n = 0, idx = SIZE_MAX; + while (environ[n] != NULL) + { + if (idx > n && strncmp (environ[n], name, namelen) == 0 && environ[n][namelen] == '=') + idx = n; + n++; + } + if (idx < n) + memmove (&environ[idx], &environ[idx + 1], (n - idx) * sizeof (*environ)); + return DDS_RETCODE_OK; +} diff --git a/src/ddsrt/src/ifaddrs/solaris2.6/ifaddrs.c b/src/ddsrt/src/ifaddrs/solaris2.6/ifaddrs.c new file mode 100644 index 0000000..11e2231 --- /dev/null +++ b/src/ddsrt/src/ifaddrs/solaris2.6/ifaddrs.c @@ -0,0 +1,84 @@ +/* + * 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/ifaddrs.h" +#include +#include + +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/retcode.h" +#include "dds/ddsrt/string.h" + +extern const int *const os_supp_afs; + +#include +#include +#include +#include + +dds_return_t +ddsrt_getifaddrs( + ddsrt_ifaddrs_t **ret_ifap, + const int *afs) +{ + int sock; + char *buf; + int32_t n; + struct ifconf ifc; + struct ifreq *ifr; + + /* get interfaces */ + buf = ddsrt_malloc (8192); + memset (&ifc, 0, sizeof (ifc)); + ifc.ifc_len = 8192; + ifc.ifc_buf = buf; + sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (ioctl (sock, SIOCGIFCONF, (char *) &ifc) < 0) + { + perror ("ioctl (SIOCGIFCONF)"); + exit (77); + } + + ddsrt_ifaddrs_t **ifap, *ifa_root; + ifap = &ifa_root; ifa_root = NULL; + ifr = ifc.ifc_req; + for (n = ifc.ifc_len / sizeof (struct ifreq); --n >= 0; ifr++) + { + ddsrt_ifaddrs_t *ifa; + if (ifr->ifr_name[0] == '\0') + continue; /* Forget about anonymous network devices */ + + if (ifr->ifr_addr.sa_family != AF_INET) { + printf ("%s: not INET\n", ifr->ifr_name); + continue; + } + + ifa = ddsrt_malloc (sizeof (*ifa)); + memset (ifa, 0, sizeof (*ifa)); + ifa->index = (int) (ifr - ifc.ifc_req); + ifa->flags = IFF_UP | ((strcmp(ifr->ifr_name, "lo0")==0) ? IFF_LOOPBACK : IFF_MULTICAST); + ifa->name = strdup (ifr->ifr_name); + ifa->addr = ddsrt_memdup (&ifr->ifr_addr, sizeof (struct sockaddr_in)); + ifa->netmask = ddsrt_memdup (&ifr->ifr_addr, sizeof (struct sockaddr_in)); + ((struct sockaddr_in *) ifa->netmask)->sin_addr.s_addr = htonl (0xffffff00); + ifa->broadaddr = NULL; + ifa->next = NULL; + *ifap = ifa; + ifap = &ifa->next; + } + + ddsrt_free (buf); + close (sock); + *ret_ifap = ifa_root; + return DDS_RETCODE_OK; +} diff --git a/src/ddsrt/src/sockets.c b/src/ddsrt/src/sockets.c index 2aaffb8..533b902 100644 --- a/src/ddsrt/src/sockets.c +++ b/src/ddsrt/src/sockets.c @@ -186,13 +186,19 @@ ddsrt_sockaddrfromstr(int af, const char *str, void *sa) switch (af) { case AF_INET: { struct in_addr buf; +#if DDSRT_HAVE_INET_PTON if (inet_pton(af, str, &buf) != 1) { return DDS_RETCODE_BAD_PARAMETER; - } else { - memset(sa, 0, sizeof(struct sockaddr_in)); - ((struct sockaddr_in *)sa)->sin_family = AF_INET; - memcpy(&((struct sockaddr_in *)sa)->sin_addr, &buf, sizeof(buf)); } +#else + buf.s_addr = inet_addr (str); + if (buf.s_addr == (in_addr_t)-1) { + return DDS_RETCODE_BAD_PARAMETER; + } +#endif + memset(sa, 0, sizeof(struct sockaddr_in)); + ((struct sockaddr_in *)sa)->sin_family = AF_INET; + memcpy(&((struct sockaddr_in *)sa)->sin_addr, &buf, sizeof(buf)); } break; #if DDSRT_HAVE_IPV6 case AF_INET6: { @@ -225,8 +231,16 @@ DDSRT_WARNING_GNUC_OFF(sign-conversion) #endif switch (((struct sockaddr *)sa)->sa_family) { case AF_INET: +#if DDSRT_HAVE_INET_NTOP ptr = inet_ntop( AF_INET, &((struct sockaddr_in *)sa)->sin_addr, buf, (socklen_t)size); +#else + { + in_addr_t x = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr); + snprintf(buf,size,"%u.%u.%u.%u",(x>>24),(x>>16)&0xff,(x>>8)&0xff,x&0xff); + ptr = buf; + } +#endif break; #if DDSRT_HAVE_IPV6 case AF_INET6: @@ -249,6 +263,7 @@ DDSRT_WARNING_GNUC_ON(sign-conversion) } #if DDSRT_HAVE_DNS +#if DDSRT_HAVE_GETADDRINFO dds_return_t ddsrt_gethostbyname(const char *name, int af, ddsrt_hostent_t **hentp) { @@ -363,4 +378,23 @@ ddsrt_gethostbyname(const char *name, int af, ddsrt_hostent_t **hentp) *hentp = hent; return DDS_RETCODE_OK; } +#else +dds_return_t +ddsrt_gethostbyname(const char *name, int af, ddsrt_hostent_t **hentp) +{ + struct hostent hest, *he; + char buf[256]; + int err; + he = gethostbyname_r (name, &hest, buf, sizeof (buf), &err); + if (he == NULL) { + return DDS_RETCODE_HOST_NOT_FOUND; + } else { + size_t size = sizeof(**hentp) + (1 * sizeof((*hentp)->addrs[0])); + *hentp = ddsrt_calloc_s(1, size); + (*hentp)->naddrs = 1; + memcpy(&(*hentp)->addrs[0], he->h_addr, he->h_length); + return DDS_RETCODE_OK; + } +} +#endif /* DDSRT_HAVE_GETADDRINFO */ #endif /* DDSRT_HAVE_DNS */ diff --git a/src/ddsrt/src/sockets/include/dds/ddsrt/sockets_priv.h b/src/ddsrt/src/sockets/include/dds/ddsrt/sockets_priv.h index 6c793d3..f76e150 100644 --- a/src/ddsrt/src/sockets/include/dds/ddsrt/sockets_priv.h +++ b/src/ddsrt/src/sockets/include/dds/ddsrt/sockets_priv.h @@ -27,7 +27,6 @@ typedef long ddsrt_tv_sec_t; typedef long ddsrt_tv_usec_t; #else typedef time_t ddsrt_tv_sec_t; -typedef suseconds_t ddsrt_tv_usec_t; #endif #define DDSRT_TIME_T_MAX \ @@ -62,7 +61,7 @@ ddsrt_duration_to_timeval_ceil(dds_duration_t reltime, struct timeval *tv) if (reltime < (max_nsecs - DDS_NSECS_IN_USEC - 1)) { reltime += (DDS_NSECS_IN_USEC - 1); tv->tv_sec = (ddsrt_tv_sec_t)(reltime / DDS_NSECS_IN_SEC); - tv->tv_usec = (ddsrt_tv_usec_t)((reltime % DDS_NSECS_IN_SEC) / DDS_NSECS_IN_USEC); + tv->tv_usec = (int)((reltime % DDS_NSECS_IN_SEC) / DDS_NSECS_IN_USEC); } else { tv->tv_sec = DDSRT_TIME_T_MAX; tv->tv_usec = 999999; diff --git a/src/ddsrt/src/sockets/posix/gethostname.c b/src/ddsrt/src/sockets/posix/gethostname.c index fcf7618..109af1e 100644 --- a/src/ddsrt/src/sockets/posix/gethostname.c +++ b/src/ddsrt/src/sockets/posix/gethostname.c @@ -45,6 +45,10 @@ ddsrt_gethostname( return DDS_RETCODE_OK; } #else +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 256 +#endif + dds_return_t ddsrt_gethostname( char *name, diff --git a/src/ddsrt/src/string/solaris2.6/strerror.c b/src/ddsrt/src/string/solaris2.6/strerror.c new file mode 100644 index 0000000..d3177f9 --- /dev/null +++ b/src/ddsrt/src/string/solaris2.6/strerror.c @@ -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 + */ +/* Make sure we get the XSI compliant version of strerror_r */ +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE +#undef _GNU_SOURCE +#define _POSIX_C_SOURCE 200112L + +#include +#include +#include +#include + +#include "dds/ddsrt/string.h" + +dds_return_t +ddsrt_strerror_r(int errnum, char *buf, size_t buflen) +{ + assert(buf != NULL); + assert(buflen > 0); + if (snprintf (buf, buflen, "errno=%d", errnum) >= buflen) + return DDS_RETCODE_NOT_ENOUGH_SPACE; + else + return DDS_RETCODE_OK; +} diff --git a/src/ddsrt/src/sync/solaris2.6/sync.c b/src/ddsrt/src/sync/solaris2.6/sync.c new file mode 100644 index 0000000..884f597 --- /dev/null +++ b/src/ddsrt/src/sync/solaris2.6/sync.c @@ -0,0 +1,236 @@ +/* + * 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 +#include +#include +#include +#include + +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/timeconv.h" + +void ddsrt_mutex_init (ddsrt_mutex_t *mutex) +{ + int shared; + assert (mutex != NULL); + + pthread_mutex_init (&mutex->mutex, NULL); + (void)shared; +} + +void ddsrt_mutex_destroy (ddsrt_mutex_t *mutex) +{ + assert (mutex != NULL); + + if (pthread_mutex_destroy (&mutex->mutex) != 0) + abort(); +} + +void ddsrt_mutex_lock (ddsrt_mutex_t *mutex) +{ + assert (mutex != NULL); + + if (pthread_mutex_lock (&mutex->mutex) != 0) + abort(); +} + +bool +ddsrt_mutex_trylock (ddsrt_mutex_t *mutex) +{ + int err; + assert (mutex != NULL); + + err = pthread_mutex_trylock (&mutex->mutex); + if (err != 0 && err != EBUSY) + abort(); + return (err == 0); +} + +void +ddsrt_mutex_unlock (ddsrt_mutex_t *mutex) +{ + assert (mutex != NULL); + + if (pthread_mutex_unlock (&mutex->mutex) != 0) + abort(); +} + +void +ddsrt_cond_init (ddsrt_cond_t *cond) +{ + assert (cond != NULL); + + pthread_cond_init (&cond->cond, NULL); +} + +void +ddsrt_cond_destroy (ddsrt_cond_t *cond) +{ + assert (cond != NULL); + + if (pthread_cond_destroy (&cond->cond) != 0) + abort(); +} + +void +ddsrt_cond_wait (ddsrt_cond_t *cond, ddsrt_mutex_t *mutex) +{ + assert (cond != NULL); + assert (mutex != NULL); + + if (pthread_cond_wait (&cond->cond, &mutex->mutex) != 0) + abort(); +} + +bool +ddsrt_cond_waituntil( + ddsrt_cond_t *cond, + ddsrt_mutex_t *mutex, + dds_time_t abstime) +{ + struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; + + assert(cond != NULL); + assert(mutex != NULL); + + if (abstime == DDS_NEVER) { + ddsrt_cond_wait(cond, mutex); + return true; + } + if (abstime > 0) { + ts.tv_sec = abstime / DDS_NSECS_IN_SEC; + ts.tv_nsec = abstime % DDS_NSECS_IN_SEC; + } + + switch (pthread_cond_timedwait(&cond->cond, &mutex->mutex, &ts)) { + case 0: + return true; + case ETIMEDOUT: + return false; + default: + break; + } + + abort(); +} + +bool +ddsrt_cond_waitfor( + ddsrt_cond_t *cond, + ddsrt_mutex_t *mutex, + dds_duration_t reltime) +{ + assert(cond != NULL); + assert(mutex != NULL); + + return ddsrt_cond_waituntil( + cond, mutex, ddsrt_time_add_duration(dds_time(), reltime)); +} + +void +ddsrt_cond_signal (ddsrt_cond_t *cond) +{ + assert (cond != NULL); + + if (pthread_cond_signal (&cond->cond) != 0) + abort(); +} + +void +ddsrt_cond_broadcast (ddsrt_cond_t *cond) +{ + assert (cond != NULL); + + if (pthread_cond_broadcast (&cond->cond) != 0) + abort(); +} + +void +ddsrt_rwlock_init (ddsrt_rwlock_t *rwlock) +{ + int err = 0; + + assert(rwlock != NULL); + + /* process-shared attribute is set to PTHREAD_PROCESS_PRIVATE by default */ + if ((err = pthread_mutex_init(&rwlock->rwlock, NULL)) != 0) + abort(); +} + +void +ddsrt_rwlock_destroy (ddsrt_rwlock_t *rwlock) +{ + int err; + + assert(rwlock != NULL); + if ((err = pthread_mutex_destroy (&rwlock->rwlock)) != 0) + abort(); +} + +void ddsrt_rwlock_read (ddsrt_rwlock_t *rwlock) +{ + int err; + + assert(rwlock != NULL); + err = pthread_mutex_lock(&rwlock->rwlock); + assert(err == 0); + (void)err; +} + +void ddsrt_rwlock_write (ddsrt_rwlock_t *rwlock) +{ + int err; + + assert(rwlock != NULL); + err = pthread_mutex_lock (&rwlock->rwlock); + assert(err == 0); + (void)err; +} + +bool ddsrt_rwlock_tryread (ddsrt_rwlock_t *rwlock) +{ + int err; + + assert(rwlock != NULL); + err = pthread_mutex_trylock(&rwlock->rwlock); + assert(err == 0 || err == EBUSY); + return err == 0; +} + +bool ddsrt_rwlock_trywrite (ddsrt_rwlock_t *rwlock) +{ + int err; + + assert(rwlock != NULL); + err = pthread_mutex_trylock(&rwlock->rwlock); + assert(err == 0 || err == EBUSY); + + return err == 0; +} + +void ddsrt_rwlock_unlock (ddsrt_rwlock_t *rwlock) +{ + int err; + + assert(rwlock != NULL); + err = pthread_mutex_unlock(&rwlock->rwlock); + assert(err == 0); + (void)err; +} + +void ddsrt_once (ddsrt_once_t *control, ddsrt_once_fn init_fn) +{ + /* There are no defined errors that can be returned by pthread_once */ + (void)pthread_once(control, init_fn); +} diff --git a/src/ddsrt/src/threads/posix/threads.c b/src/ddsrt/src/threads/posix/threads.c index bca8e36..619093d 100644 --- a/src/ddsrt/src/threads/posix/threads.c +++ b/src/ddsrt/src/threads/posix/threads.c @@ -80,7 +80,11 @@ ddsrt_thread_getname(char *str, size_t size) (void)pthread_get_name_np(pthread_self(), buf, sizeof(buf)); cnt = ddsrt_strlcpy(str, buf, size); #elif defined(__sun) +#if !(__SunOS_5_6 || __SunOS_5_7 || __SunOS_5_8 || __SunOS_5_9 || __SunOS_5_10) (void)pthread_getname_np(pthread_self(), buf, sizeof(buf)); +#else + buf[0] = 0; +#endif cnt = ddsrt_strlcpy(str, buf, size); #elif defined(__VXWORKS__) { @@ -125,7 +129,9 @@ ddsrt_thread_setname(const char *__restrict name) #elif defined(__sun) /* Thread names are limited to 31 bytes on Solaris. Excess bytes are silently truncated. */ +#if !(__SunOS_5_6 || __SunOS_5_7 || __SunOS_5_8 || __SunOS_5_9 || __SunOS_5_10) (void)pthread_setname_np(pthread_self(), name); +#endif #else /* VxWorks does not support the task name to be set after a task is created. Setting the name of a task can be done through pthread_attr_setname. */ diff --git a/src/ddsrt/src/time.c b/src/ddsrt/src/time.c index 3f344f3..e8c845f 100644 --- a/src/ddsrt/src/time.c +++ b/src/ddsrt/src/time.c @@ -47,7 +47,12 @@ size_t ddsrt_ctime(dds_time_t n, char *str, size_t size) { struct tm tm; +#if __SunOS_5_6 + /* Solaris 2.6 doesn't recognize %z so we just leave it out */ + static const char fmt[] = "%Y-%m-%d %H:%M:%S"; +#else static const char fmt[] = "%Y-%m-%d %H:%M:%S%z"; +#endif char buf[] = "YYYY-mm-dd HH:MM:SS.hh:mm"; /* RFC 3339 */ size_t cnt; time_t sec = (time_t)(n / DDS_NSECS_IN_SEC); @@ -61,12 +66,14 @@ ddsrt_ctime(dds_time_t n, char *str, size_t size) #endif /* _WIN32 */ cnt = strftime(buf, sizeof(buf), fmt, &tm); +#if ! __SunOS_5_6 + /* %z is without a separator between hours and minutes, fixup */ assert(cnt == (sizeof(buf) - 2 /* ':' + '\0' */)); buf[sizeof(buf) - 1] = '\0'; buf[sizeof(buf) - 2] = buf[sizeof(buf) - 3]; buf[sizeof(buf) - 3] = buf[sizeof(buf) - 4]; buf[sizeof(buf) - 4] = ':'; - +#endif (void)cnt; return ddsrt_strlcpy(str, buf, size); diff --git a/src/ddsrt/src/time/solaris2.6/time.c b/src/ddsrt/src/time/solaris2.6/time.c new file mode 100644 index 0000000..0c5fb7c --- /dev/null +++ b/src/ddsrt/src/time/solaris2.6/time.c @@ -0,0 +1,38 @@ +/* + * 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 +#include +#include +#include + +#include "dds/ddsrt/time.h" + +dds_time_t dds_time(void) +{ + struct timespec ts; + + (void)clock_gettime(CLOCK_REALTIME, &ts); + return (ts.tv_sec * DDS_NSECS_IN_SEC) + ts.tv_nsec; +} + +dds_time_t ddsrt_time_monotonic(void) +{ + return gethrtime (); +} + +dds_time_t ddsrt_time_elapsed(void) +{ + /* Elapsed time clock not worth the bother for now. */ + return ddsrt_time_monotonic(); +} diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index 4524751..b9f3487 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -10,6 +10,7 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #define _ISOC99_SOURCE +#define _POSIX_PTHREAD_SEMANTICS #include #include #include @@ -19,7 +20,9 @@ #include #include #include +#if _WIN32 #include +#endif #include "dds/dds.h" #include "ddsperf_types.h" diff --git a/vdds-xcode/vdds-xcode.xcodeproj/project.pbxproj b/vdds-xcode/vdds-xcode.xcodeproj/project.pbxproj deleted file mode 100644 index 78c5dc7..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/project.pbxproj +++ /dev/null @@ -1,2310 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 0335203F1CEDD22A003E7429 /* rpc-ping.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF421CCE0DAB00D73982 /* rpc-ping.c */; }; - 033520401CEDD22A003E7429 /* RoundTrip.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEB71CCE0DAB00D73982 /* RoundTrip.c */; }; - 033520481CEDD242003E7429 /* rpc-pong.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF431CCE0DAB00D73982 /* rpc-pong.c */; }; - 033520491CEDD244003E7429 /* rpc-pingpong.c in Sources */ = {isa = PBXBuildFile; fileRef = 0335203C1CEDD031003E7429 /* rpc-pingpong.c */; }; - 0335204A1CEDDC48003E7429 /* libvdds.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E6CEA91CCE0CA400D73982 /* libvdds.dylib */; }; - 034CF9311DE2FDF300DD6073 /* q_freelist.c in Sources */ = {isa = PBXBuildFile; fileRef = 034CF92F1DE2FDF300DD6073 /* q_freelist.c */; }; - 034CF9321DE2FDF300DD6073 /* q_freelist.h in Headers */ = {isa = PBXBuildFile; fileRef = 034CF9301DE2FDF300DD6073 /* q_freelist.h */; }; - 034CF9331DE3043A00DD6073 /* q_freelist.c in Sources */ = {isa = PBXBuildFile; fileRef = 034CF92F1DE2FDF300DD6073 /* q_freelist.c */; }; - 035877BB1DDB0F5B000F61E2 /* sysdeps.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF701CCE0DAB00D73982 /* sysdeps.c */; }; - 035877C61DDCA45B000F61E2 /* os_platform_errno.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877BD1DDCA45B000F61E2 /* os_platform_errno.c */; }; - 035877C71DDCA45B000F61E2 /* os_platform_heap.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877BE1DDCA45B000F61E2 /* os_platform_heap.c */; }; - 035877C81DDCA45B000F61E2 /* os_platform_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877BF1DDCA45B000F61E2 /* os_platform_init.c */; }; - 035877C91DDCA45B000F61E2 /* os_platform_process.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877C01DDCA45B000F61E2 /* os_platform_process.c */; }; - 035877CA1DDCA45B000F61E2 /* os_platform_socket.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877C11DDCA45B000F61E2 /* os_platform_socket.c */; }; - 035877CB1DDCA45B000F61E2 /* os_platform_stdlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877C21DDCA45B000F61E2 /* os_platform_stdlib.c */; }; - 035877CC1DDCA45B000F61E2 /* os_platform_sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877C31DDCA45B000F61E2 /* os_platform_sync.c */; }; - 035877CD1DDCA45B000F61E2 /* os_platform_thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877C41DDCA45B000F61E2 /* os_platform_thread.c */; }; - 035877CE1DDCA45B000F61E2 /* os_platform_time.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877C51DDCA45B000F61E2 /* os_platform_time.c */; }; - 035877CF1DDCA477000F61E2 /* os_platform_errno.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877BD1DDCA45B000F61E2 /* os_platform_errno.c */; }; - 035877D01DDCA477000F61E2 /* os_platform_heap.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877BE1DDCA45B000F61E2 /* os_platform_heap.c */; }; - 035877D11DDCA477000F61E2 /* os_platform_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877BF1DDCA45B000F61E2 /* os_platform_init.c */; }; - 035877D21DDCA477000F61E2 /* os_platform_process.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877C01DDCA45B000F61E2 /* os_platform_process.c */; }; - 035877D31DDCA477000F61E2 /* os_platform_socket.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877C11DDCA45B000F61E2 /* os_platform_socket.c */; }; - 035877D41DDCA477000F61E2 /* os_platform_stdlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877C21DDCA45B000F61E2 /* os_platform_stdlib.c */; }; - 035877D51DDCA477000F61E2 /* os_platform_sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877C31DDCA45B000F61E2 /* os_platform_sync.c */; }; - 035877D61DDCA477000F61E2 /* os_platform_thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877C41DDCA45B000F61E2 /* os_platform_thread.c */; }; - 035877D71DDCA477000F61E2 /* os_platform_time.c in Sources */ = {isa = PBXBuildFile; fileRef = 035877C51DDCA45B000F61E2 /* os_platform_time.c */; }; - 035877E01DDCA54F000F61E2 /* os_platform_public.h in Headers */ = {isa = PBXBuildFile; fileRef = 035877D91DDCA54F000F61E2 /* os_platform_public.h */; }; - 035877E11DDCA54F000F61E2 /* os_platform_socket.h in Headers */ = {isa = PBXBuildFile; fileRef = 035877DA1DDCA54F000F61E2 /* os_platform_socket.h */; }; - 035877E21DDCA54F000F61E2 /* os_platform_stdlib.h in Headers */ = {isa = PBXBuildFile; fileRef = 035877DB1DDCA54F000F61E2 /* os_platform_stdlib.h */; }; - 035877E31DDCA54F000F61E2 /* os_platform_sync.h in Headers */ = {isa = PBXBuildFile; fileRef = 035877DC1DDCA54F000F61E2 /* os_platform_sync.h */; }; - 035877E41DDCA54F000F61E2 /* os_platform_thread.h in Headers */ = {isa = PBXBuildFile; fileRef = 035877DD1DDCA54F000F61E2 /* os_platform_thread.h */; }; - 035877E51DDCA54F000F61E2 /* os_platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 035877DF1DDCA54F000F61E2 /* os_platform.h */; }; - 036D25861DF15EB9009A18C5 /* RoundTrip.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEB71CCE0DAB00D73982 /* RoundTrip.c */; }; - 036D25881DF15EB9009A18C5 /* libvdds.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E6CEA91CCE0CA400D73982 /* libvdds.dylib */; }; - 036D258E1DF15ECA009A18C5 /* ddpingpong.c in Sources */ = {isa = PBXBuildFile; fileRef = 036D25821DF15EAF009A18C5 /* ddpingpong.c */; }; - 03C96E9F1CCE5B8D0012F15D /* libvdds.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E6CEA91CCE0CA400D73982 /* libvdds.dylib */; }; - 03C96EA51CCE5B9F0012F15D /* server2.c in Sources */ = {isa = PBXBuildFile; fileRef = 03C96E9A1CCE5B800012F15D /* server2.c */; }; - 03C96EA71CCE5CD20012F15D /* libevent_pthreads-2.0.5.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03C96EA61CCE5CD20012F15D /* libevent_pthreads-2.0.5.dylib */; }; - 03C96EA91CCF6D030012F15D /* libevent-2.0.5.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03C96EA81CCF6D030012F15D /* libevent-2.0.5.dylib */; }; - 03E6CFD01CCE0DD400D73982 /* ddsi_ser.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF481CCE0DAB00D73982 /* ddsi_ser.c */; }; - 03E6CFD11CCE0DD400D73982 /* ddsi_ssl.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF491CCE0DAB00D73982 /* ddsi_ssl.c */; }; - 03E6CFD21CCE0DD400D73982 /* ddsi_tcp.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF4A1CCE0DAB00D73982 /* ddsi_tcp.c */; }; - 03E6CFD31CCE0DD400D73982 /* ddsi_tran.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF4B1CCE0DAB00D73982 /* ddsi_tran.c */; }; - 03E6CFD41CCE0DD400D73982 /* ddsi_udp.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF4C1CCE0DAB00D73982 /* ddsi_udp.c */; }; - 03E6CFD51CCE0DD400D73982 /* q_addrset.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF4D1CCE0DAB00D73982 /* q_addrset.c */; }; - 03E6CFD61CCE0DD400D73982 /* q_bitset_inlines.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF4E1CCE0DAB00D73982 /* q_bitset_inlines.c */; }; - 03E6CFD81CCE0DD400D73982 /* q_bswap.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF501CCE0DAB00D73982 /* q_bswap.c */; }; - 03E6CFD91CCE0DD400D73982 /* q_bswap_inlines.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF511CCE0DAB00D73982 /* q_bswap_inlines.c */; }; - 03E6CFDB1CCE0DD400D73982 /* q_config.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF531CCE0DAB00D73982 /* q_config.c */; }; - 03E6CFDC1CCE0DD400D73982 /* q_ddsi_discovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF541CCE0DAB00D73982 /* q_ddsi_discovery.c */; }; - 03E6CFDD1CCE0DD400D73982 /* q_debmon.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF551CCE0DAB00D73982 /* q_debmon.c */; }; - 03E6CFDE1CCE0DD400D73982 /* q_entity.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF561CCE0DAB00D73982 /* q_entity.c */; }; - 03E6CFDF1CCE0DD400D73982 /* q_ephash.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF571CCE0DAB00D73982 /* q_ephash.c */; }; - 03E6CFE01CCE0DD400D73982 /* q_gc.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF581CCE0DAB00D73982 /* q_gc.c */; }; - 03E6CFE11CCE0DD400D73982 /* q_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF591CCE0DAB00D73982 /* q_init.c */; }; - 03E6CFE21CCE0DD400D73982 /* q_lat_estim.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF5A1CCE0DAB00D73982 /* q_lat_estim.c */; }; - 03E6CFE31CCE0DD400D73982 /* q_lease.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF5B1CCE0DAB00D73982 /* q_lease.c */; }; - 03E6CFE41CCE0DD400D73982 /* q_log.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF5C1CCE0DAB00D73982 /* q_log.c */; }; - 03E6CFE51CCE0DD400D73982 /* q_md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF5D1CCE0DAB00D73982 /* q_md5.c */; }; - 03E6CFE61CCE0DD400D73982 /* q_misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF5E1CCE0DAB00D73982 /* q_misc.c */; }; - 03E6CFE71CCE0DD400D73982 /* q_nwif.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF5F1CCE0DAB00D73982 /* q_nwif.c */; }; - 03E6CFE81CCE0DD400D73982 /* q_pcap.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF601CCE0DAB00D73982 /* q_pcap.c */; }; - 03E6CFE91CCE0DD400D73982 /* q_plist.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF611CCE0DAB00D73982 /* q_plist.c */; }; - 03E6CFEA1CCE0DD400D73982 /* q_qosmatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF621CCE0DAB00D73982 /* q_qosmatch.c */; }; - 03E6CFEB1CCE0DD400D73982 /* q_radmin.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF631CCE0DAB00D73982 /* q_radmin.c */; }; - 03E6CFEC1CCE0DD400D73982 /* q_receive.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF641CCE0DAB00D73982 /* q_receive.c */; }; - 03E6CFED1CCE0DD400D73982 /* q_security.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF651CCE0DAB00D73982 /* q_security.c */; }; - 03E6CFEE1CCE0DD400D73982 /* q_servicelease.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF661CCE0DAB00D73982 /* q_servicelease.c */; }; - 03E6CFEF1CCE0DD400D73982 /* q_sockwaitset.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF671CCE0DAB00D73982 /* q_sockwaitset.c */; }; - 03E6CFF01CCE0DD400D73982 /* q_thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF681CCE0DAB00D73982 /* q_thread.c */; }; - 03E6CFF11CCE0DD400D73982 /* q_thread_inlines.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF691CCE0DAB00D73982 /* q_thread_inlines.c */; }; - 03E6CFF31CCE0DD400D73982 /* q_time.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF6B1CCE0DAB00D73982 /* q_time.c */; }; - 03E6CFF41CCE0DD400D73982 /* q_transmit.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF6C1CCE0DAB00D73982 /* q_transmit.c */; }; - 03E6CFF51CCE0DD400D73982 /* q_whc.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF6D1CCE0DAB00D73982 /* q_whc.c */; }; - 03E6CFF61CCE0DD400D73982 /* q_xevent.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF6E1CCE0DAB00D73982 /* q_xevent.c */; }; - 03E6CFF71CCE0DD400D73982 /* q_xmsg.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF6F1CCE0DAB00D73982 /* q_xmsg.c */; }; - 03E6CFF81CCE0DD400D73982 /* sysdeps.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF701CCE0DAB00D73982 /* sysdeps.c */; }; - 03E6CFF91CCE0DE300D73982 /* dds_alloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF721CCE0DAB00D73982 /* dds_alloc.c */; }; - 03E6CFFA1CCE0DE300D73982 /* dds_condition.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF731CCE0DAB00D73982 /* dds_condition.c */; }; - 03E6CFFB1CCE0DE300D73982 /* dds_domain.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF741CCE0DAB00D73982 /* dds_domain.c */; }; - 03E6CFFC1CCE0DE300D73982 /* dds_entity.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF751CCE0DAB00D73982 /* dds_entity.c */; }; - 03E6CFFD1CCE0DE300D73982 /* dds_err.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF761CCE0DAB00D73982 /* dds_err.c */; }; - 03E6CFFE1CCE0DE300D73982 /* dds_guardcond.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF771CCE0DAB00D73982 /* dds_guardcond.c */; }; - 03E6CFFF1CCE0DE300D73982 /* dds_iid.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF781CCE0DAB00D73982 /* dds_iid.c */; }; - 03E6D0001CCE0DE300D73982 /* dds_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF791CCE0DAB00D73982 /* dds_init.c */; }; - 03E6D0011CCE0DE300D73982 /* dds_instance.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF7A1CCE0DAB00D73982 /* dds_instance.c */; }; - 03E6D0021CCE0DE300D73982 /* dds_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF7B1CCE0DAB00D73982 /* dds_key.c */; }; - 03E6D0031CCE0DE300D73982 /* dds_listener.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF7C1CCE0DAB00D73982 /* dds_listener.c */; }; - 03E6D0041CCE0DE300D73982 /* dds_log.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF7D1CCE0DAB00D73982 /* dds_log.c */; }; - 03E6D0051CCE0DE300D73982 /* dds_participant.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF7E1CCE0DAB00D73982 /* dds_participant.c */; }; - 03E6D0061CCE0DE300D73982 /* dds_publisher.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF7F1CCE0DAB00D73982 /* dds_publisher.c */; }; - 03E6D0071CCE0DE300D73982 /* dds_qos.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF801CCE0DAB00D73982 /* dds_qos.c */; }; - 03E6D0081CCE0DE300D73982 /* dds_querycond.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF811CCE0DAB00D73982 /* dds_querycond.c */; }; - 03E6D0091CCE0DE300D73982 /* dds_read.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF821CCE0DAB00D73982 /* dds_read.c */; }; - 03E6D00A1CCE0DE300D73982 /* dds_readcond.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF831CCE0DAB00D73982 /* dds_readcond.c */; }; - 03E6D00B1CCE0DE300D73982 /* dds_reader.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF841CCE0DAB00D73982 /* dds_reader.c */; }; - 03E6D00C1CCE0DE300D73982 /* dds_rhc.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF851CCE0DAB00D73982 /* dds_rhc.c */; }; - 03E6D00D1CCE0DE300D73982 /* dds_status.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF861CCE0DAB00D73982 /* dds_status.c */; }; - 03E6D00E1CCE0DE300D73982 /* dds_statuscond.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF871CCE0DAB00D73982 /* dds_statuscond.c */; }; - 03E6D00F1CCE0DE300D73982 /* dds_stream.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF881CCE0DAB00D73982 /* dds_stream.c */; }; - 03E6D0101CCE0DE300D73982 /* dds_subscriber.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF891CCE0DAB00D73982 /* dds_subscriber.c */; }; - 03E6D0111CCE0DE300D73982 /* dds_thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF8A1CCE0DAB00D73982 /* dds_thread.c */; }; - 03E6D0121CCE0DE300D73982 /* dds_time.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF8B1CCE0DAB00D73982 /* dds_time.c */; }; - 03E6D0131CCE0DE300D73982 /* dds_tkmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF8C1CCE0DAB00D73982 /* dds_tkmap.c */; }; - 03E6D0141CCE0DE300D73982 /* dds_topic.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF8D1CCE0DAB00D73982 /* dds_topic.c */; }; - 03E6D0151CCE0DE300D73982 /* dds_waitset.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF8E1CCE0DAB00D73982 /* dds_waitset.c */; }; - 03E6D0161CCE0DE300D73982 /* dds_write.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF8F1CCE0DAB00D73982 /* dds_write.c */; }; - 03E6D0171CCE0DE300D73982 /* dds_writer.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF901CCE0DAB00D73982 /* dds_writer.c */; }; - 03E6D0181CCE0DE300D73982 /* q_osplser.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF911CCE0DAB00D73982 /* q_osplser.c */; }; - 03E6D0191CCE0DED00D73982 /* os_atomics.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF9E1CCE0DAB00D73982 /* os_atomics.c */; }; - 03E6D01A1CCE0DED00D73982 /* os_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF9F1CCE0DAB00D73982 /* os_init.c */; }; - 03E6D01B1CCE0DED00D73982 /* os_report.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFA01CCE0DAB00D73982 /* os_report.c */; }; - 03E6D01C1CCE0DED00D73982 /* os_socket.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFA11CCE0DAB00D73982 /* os_socket.c */; }; - 03E6D01D1CCE0DED00D73982 /* os_sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFA21CCE0DAB00D73982 /* os_sync.c */; }; - 03E6D01E1CCE0DED00D73982 /* os_thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFA31CCE0DAB00D73982 /* os_thread.c */; }; - 03E6D01F1CCE0DED00D73982 /* os_time.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFA41CCE0DAB00D73982 /* os_time.c */; }; - 03E6D0291CCE0E0500D73982 /* ut_avl.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFC51CCE0DAB00D73982 /* ut_avl.c */; }; - 03E6D02A1CCE0E0500D73982 /* ut_crc.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFC61CCE0DAB00D73982 /* ut_crc.c */; }; - 03E6D02B1CCE0E0500D73982 /* ut_expand_envvars.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFC71CCE0DAB00D73982 /* ut_expand_envvars.c */; }; - 03E6D02C1CCE0E0500D73982 /* ut_fibheap.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFC81CCE0DAB00D73982 /* ut_fibheap.c */; }; - 03E6D02D1CCE0E0500D73982 /* ut_hopscotch.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFC91CCE0DAB00D73982 /* ut_hopscotch.c */; }; - 03E6D02E1CCE0E0500D73982 /* ut_thread_pool.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFCA1CCE0DAB00D73982 /* ut_thread_pool.c */; }; - 03E6D02F1CCE0E0500D73982 /* ut_xmlparser.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFCB1CCE0DAB00D73982 /* ut_xmlparser.c */; }; - 03E6D0391CCE0E6200D73982 /* os_atomics.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF9E1CCE0DAB00D73982 /* os_atomics.c */; }; - 03E6D03A1CCE0E6200D73982 /* os_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF9F1CCE0DAB00D73982 /* os_init.c */; }; - 03E6D03B1CCE0E6200D73982 /* os_report.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFA01CCE0DAB00D73982 /* os_report.c */; }; - 03E6D03C1CCE0E6200D73982 /* os_socket.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFA11CCE0DAB00D73982 /* os_socket.c */; }; - 03E6D03D1CCE0E6200D73982 /* os_sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFA21CCE0DAB00D73982 /* os_sync.c */; }; - 03E6D03E1CCE0E6200D73982 /* os_thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFA31CCE0DAB00D73982 /* os_thread.c */; }; - 03E6D03F1CCE0E6200D73982 /* os_time.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFA41CCE0DAB00D73982 /* os_time.c */; }; - 03E6D0401CCE0E7000D73982 /* vdds-stubs.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFCF1CCE0DAB00D73982 /* vdds-stubs.c */; }; - 03E6D0411CCE0EB700D73982 /* dds_alloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF721CCE0DAB00D73982 /* dds_alloc.c */; }; - 03E6D0421CCE0EBD00D73982 /* dds_time.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF8B1CCE0DAB00D73982 /* dds_time.c */; }; - 03E6D0431CCE0EC000D73982 /* dds_stream.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF881CCE0DAB00D73982 /* dds_stream.c */; }; - 03E6D0441CCE0EC600D73982 /* dds_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF7B1CCE0DAB00D73982 /* dds_key.c */; }; - 03E6D0451CCE0ECB00D73982 /* dds_err.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF761CCE0DAB00D73982 /* dds_err.c */; }; - 03E6D0461CCE0ED000D73982 /* dds_qos.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF801CCE0DAB00D73982 /* dds_qos.c */; }; - 03E6D0471CCE0EDE00D73982 /* q_bswap.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF501CCE0DAB00D73982 /* q_bswap.c */; }; - 03E6D0481CCE0EE200D73982 /* q_bswap_inlines.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF511CCE0DAB00D73982 /* q_bswap_inlines.c */; }; - 03E6D0491CCE0EE800D73982 /* q_md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF5D1CCE0DAB00D73982 /* q_md5.c */; }; - 03E6D04A1CCE0EEC00D73982 /* q_plist.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF611CCE0DAB00D73982 /* q_plist.c */; }; - 03E6D04B1CCE0EF100D73982 /* q_time.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF6B1CCE0DAB00D73982 /* q_time.c */; }; - 03E6D04C1CCE104600D73982 /* q_misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF5E1CCE0DAB00D73982 /* q_misc.c */; }; - 03E6D04D1CCE104E00D73982 /* q_osplser.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF911CCE0DAB00D73982 /* q_osplser.c */; }; - 03E6D04E1CCE105600D73982 /* ddsi_ser.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF481CCE0DAB00D73982 /* ddsi_ser.c */; }; - 03E6D05A1CCE11D300D73982 /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CFCD1CCE0DAB00D73982 /* server.c */; }; - 03E6D05B1CCE11DA00D73982 /* libvdds.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E6CEA91CCE0CA400D73982 /* libvdds.dylib */; }; - 03E6D0B41CCE124D00D73982 /* libvdds-stubs.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E6CEB11CCE0CCC00D73982 /* libvdds-stubs.dylib */; }; - 03E6D0B51CCE125100D73982 /* libvdds-stubs.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E6CEB11CCE0CCC00D73982 /* libvdds-stubs.dylib */; }; - 03E6D0B61CCE125500D73982 /* libvdds-stubs.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E6CEB11CCE0CCC00D73982 /* libvdds-stubs.dylib */; }; - 03E6D0B71CCE125800D73982 /* libvdds-stubs.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E6CEB11CCE0CCC00D73982 /* libvdds-stubs.dylib */; }; - 03E6D0B81CCE125C00D73982 /* libvdds.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E6CEA91CCE0CA400D73982 /* libvdds.dylib */; }; - 03E6D0B91CCE125F00D73982 /* libvdds.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E6CEA91CCE0CA400D73982 /* libvdds.dylib */; }; - 03E6D0BA1CCE126300D73982 /* libvdds.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E6CEA91CCE0CA400D73982 /* libvdds.dylib */; }; - 03E6D0BB1CCE126700D73982 /* libvdds.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E6CEA91CCE0CA400D73982 /* libvdds.dylib */; }; - 03E6D0BC1CCE127500D73982 /* publisher.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEBF1CCE0DAB00D73982 /* publisher.c */; }; - 03E6D0BD1CCE127800D73982 /* Throughput.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEBA1CCE0DAB00D73982 /* Throughput.c */; }; - 03E6D0BE1CCE127C00D73982 /* subscriber.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEC01CCE0DAB00D73982 /* subscriber.c */; }; - 03E6D0BF1CCE127F00D73982 /* Throughput.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEBA1CCE0DAB00D73982 /* Throughput.c */; }; - 03E6D0C01CCE128500D73982 /* ping.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEBD1CCE0DAB00D73982 /* ping.c */; }; - 03E6D0C11CCE128700D73982 /* RoundTrip.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEB71CCE0DAB00D73982 /* RoundTrip.c */; }; - 03E6D0C21CCE128D00D73982 /* pong.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEBE1CCE0DAB00D73982 /* pong.c */; }; - 03E6D0C31CCE128F00D73982 /* RoundTrip.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEB71CCE0DAB00D73982 /* RoundTrip.c */; }; - 03E6D0C41CCE129C00D73982 /* rpc-publisher.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF441CCE0DAB00D73982 /* rpc-publisher.c */; }; - 03E6D0C51CCE129F00D73982 /* Throughput.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEBA1CCE0DAB00D73982 /* Throughput.c */; }; - 03E6D0C61CCE12A400D73982 /* rpc-subscriber.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF451CCE0DAB00D73982 /* rpc-subscriber.c */; }; - 03E6D0C71CCE12A600D73982 /* Throughput.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEBA1CCE0DAB00D73982 /* Throughput.c */; }; - 03E6D0C81CCE12AC00D73982 /* rpc-ping.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF421CCE0DAB00D73982 /* rpc-ping.c */; }; - 03E6D0C91CCE12AE00D73982 /* RoundTrip.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEB71CCE0DAB00D73982 /* RoundTrip.c */; }; - 03E6D0CA1CCE12B400D73982 /* rpc-pong.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CF431CCE0DAB00D73982 /* rpc-pong.c */; }; - 03E6D0CB1CCE12B600D73982 /* RoundTrip.c in Sources */ = {isa = PBXBuildFile; fileRef = 03E6CEB71CCE0DAB00D73982 /* RoundTrip.c */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 033520431CEDD22A003E7429 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 036D25891DF15EB9009A18C5 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 03C96EA01CCE5B8D0012F15D /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 03E6D0511CCE116900D73982 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 03E6D05E1CCE121300D73982 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 03E6D0691CCE121A00D73982 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 03E6D0741CCE121F00D73982 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 03E6D07F1CCE122400D73982 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 03E6D08A1CCE122A00D73982 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 03E6D0951CCE123000D73982 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 03E6D0A01CCE123500D73982 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 03E6D0AB1CCE123A00D73982 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 0335203C1CEDD031003E7429 /* rpc-pingpong.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "rpc-pingpong.c"; sourceTree = ""; }; - 033520471CEDD22A003E7429 /* rpc-pingpong */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "rpc-pingpong"; sourceTree = BUILT_PRODUCTS_DIR; }; - 0335204B1CEF4B21003E7429 /* q_bitset_template.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_bitset_template.h; sourceTree = ""; }; - 0335204C1CEF4B21003E7429 /* q_bswap_template.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_bswap_template.h; sourceTree = ""; }; - 0335204D1CEF4B21003E7429 /* q_thread_template.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_thread_template.h; sourceTree = ""; }; - 034CF92F1DE2FDF300DD6073 /* q_freelist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = q_freelist.c; sourceTree = ""; }; - 034CF9301DE2FDF300DD6073 /* q_freelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = q_freelist.h; sourceTree = ""; }; - 035877B71DDB0A20000F61E2 /* lite.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = lite.xml; path = ../lite.xml; sourceTree = ""; }; - 035877B81DDB0A20000F61E2 /* config.mk */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; name = config.mk; path = ../config.mk; sourceTree = ""; }; - 035877B91DDB0A20000F61E2 /* guess-config */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = "guess-config"; path = "../guess-config"; sourceTree = ""; }; - 035877BA1DDB0A20000F61E2 /* makefile */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; name = makefile; path = ../makefile; sourceTree = ""; }; - 035877BD1DDCA45B000F61E2 /* os_platform_errno.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = os_platform_errno.c; sourceTree = ""; }; - 035877BE1DDCA45B000F61E2 /* os_platform_heap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = os_platform_heap.c; sourceTree = ""; }; - 035877BF1DDCA45B000F61E2 /* os_platform_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = os_platform_init.c; sourceTree = ""; }; - 035877C01DDCA45B000F61E2 /* os_platform_process.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = os_platform_process.c; sourceTree = ""; }; - 035877C11DDCA45B000F61E2 /* os_platform_socket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = os_platform_socket.c; sourceTree = ""; }; - 035877C21DDCA45B000F61E2 /* os_platform_stdlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = os_platform_stdlib.c; sourceTree = ""; }; - 035877C31DDCA45B000F61E2 /* os_platform_sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = os_platform_sync.c; sourceTree = ""; }; - 035877C41DDCA45B000F61E2 /* os_platform_thread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = os_platform_thread.c; sourceTree = ""; }; - 035877C51DDCA45B000F61E2 /* os_platform_time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = os_platform_time.c; sourceTree = ""; }; - 035877D91DDCA54F000F61E2 /* os_platform_public.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = os_platform_public.h; sourceTree = ""; }; - 035877DA1DDCA54F000F61E2 /* os_platform_socket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = os_platform_socket.h; sourceTree = ""; }; - 035877DB1DDCA54F000F61E2 /* os_platform_stdlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = os_platform_stdlib.h; sourceTree = ""; }; - 035877DC1DDCA54F000F61E2 /* os_platform_sync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = os_platform_sync.h; sourceTree = ""; }; - 035877DD1DDCA54F000F61E2 /* os_platform_thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = os_platform_thread.h; sourceTree = ""; }; - 035877DF1DDCA54F000F61E2 /* os_platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = os_platform.h; sourceTree = ""; }; - 036D25821DF15EAF009A18C5 /* ddpingpong.c */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = ddpingpong.c; sourceTree = ""; }; - 036D258D1DF15EBA009A18C5 /* ddpingpong */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ddpingpong; sourceTree = BUILT_PRODUCTS_DIR; }; - 037D2E711CD2455A004434B2 /* os_platform_heap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_platform_heap.c; sourceTree = ""; }; - 037D2E721CD2455A004434B2 /* os_platform_init.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_platform_init.c; sourceTree = ""; }; - 037D2E731CD2455A004434B2 /* os_platform_socket.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_platform_socket.c; sourceTree = ""; }; - 037D2E741CD2455A004434B2 /* os_platform_sync.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_platform_sync.c; sourceTree = ""; }; - 037D2E751CD2455A004434B2 /* os_platform_thread.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_platform_thread.c; sourceTree = ""; }; - 037D2E761CD2455A004434B2 /* os_platform_time.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_platform_time.c; sourceTree = ""; }; - 037D2E771CD24576004434B2 /* os_atomics_win32.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_atomics_win32.h; sourceTree = ""; }; - 037D2E801CD245BB004434B2 /* os_platform_public.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_platform_public.h; sourceTree = ""; }; - 037D2E811CD245BB004434B2 /* os_platform_socket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_platform_socket.h; sourceTree = ""; }; - 037D2E821CD245BB004434B2 /* os_platform_stdlib.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_platform_stdlib.h; sourceTree = ""; }; - 037D2E831CD245BB004434B2 /* os_platform_sync.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_platform_sync.h; sourceTree = ""; }; - 037D2E841CD245BB004434B2 /* os_platform_thread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_platform_thread.h; sourceTree = ""; }; - 037D2E851CD245BB004434B2 /* os_platform_time.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_platform_time.h; sourceTree = ""; }; - 037D2E861CD245BB004434B2 /* os_platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_platform.h; sourceTree = ""; }; - 03C96E9A1CCE5B800012F15D /* server2.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = server2.c; sourceTree = ""; }; - 03C96EA41CCE5B8D0012F15D /* vdds-server2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "vdds-server2"; sourceTree = BUILT_PRODUCTS_DIR; }; - 03C96EA61CCE5CD20012F15D /* libevent_pthreads-2.0.5.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libevent_pthreads-2.0.5.dylib"; path = "../../../../../usr/local/Cellar/libevent/2.0.22/lib/libevent_pthreads-2.0.5.dylib"; sourceTree = ""; }; - 03C96EA81CCF6D030012F15D /* libevent-2.0.5.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libevent-2.0.5.dylib"; path = "../../../../../usr/local/Cellar/libevent/2.0.22/lib/libevent-2.0.5.dylib"; sourceTree = ""; }; - 03E6CEA91CCE0CA400D73982 /* libvdds.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libvdds.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; - 03E6CEB11CCE0CCC00D73982 /* libvdds-stubs.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "libvdds-stubs.dylib"; sourceTree = BUILT_PRODUCTS_DIR; }; - 03E6CEB71CCE0DAB00D73982 /* RoundTrip.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = RoundTrip.c; sourceTree = ""; }; - 03E6CEB81CCE0DAB00D73982 /* RoundTrip.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RoundTrip.h; sourceTree = ""; }; - 03E6CEB91CCE0DAB00D73982 /* RoundTrip.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = RoundTrip.idl; sourceTree = ""; }; - 03E6CEBA1CCE0DAB00D73982 /* Throughput.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Throughput.c; sourceTree = ""; }; - 03E6CEBB1CCE0DAB00D73982 /* Throughput.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Throughput.h; sourceTree = ""; }; - 03E6CEBC1CCE0DAB00D73982 /* Throughput.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = Throughput.idl; sourceTree = ""; }; - 03E6CEBD1CCE0DAB00D73982 /* ping.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ping.c; sourceTree = ""; }; - 03E6CEBE1CCE0DAB00D73982 /* pong.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pong.c; sourceTree = ""; }; - 03E6CEBF1CCE0DAB00D73982 /* publisher.c */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = publisher.c; sourceTree = ""; }; - 03E6CEC01CCE0DAB00D73982 /* subscriber.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = subscriber.c; sourceTree = ""; }; - 03E6CEC31CCE0DAB00D73982 /* dds_public_alloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_public_alloc.h; sourceTree = ""; }; - 03E6CEC41CCE0DAB00D73982 /* dds_public_error.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_public_error.h; sourceTree = ""; }; - 03E6CEC51CCE0DAB00D73982 /* dds_public_impl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_public_impl.h; sourceTree = ""; }; - 03E6CEC61CCE0DAB00D73982 /* dds_public_log.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_public_log.h; sourceTree = ""; }; - 03E6CEC71CCE0DAB00D73982 /* dds_public_qos.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_public_qos.h; sourceTree = ""; }; - 03E6CEC81CCE0DAB00D73982 /* dds_public_status.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_public_status.h; sourceTree = ""; }; - 03E6CEC91CCE0DAB00D73982 /* dds_public_stream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_public_stream.h; sourceTree = ""; }; - 03E6CECA1CCE0DAB00D73982 /* dds_public_time.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_public_time.h; sourceTree = ""; }; - 03E6CED21CCE0DAB00D73982 /* dds.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds.h; sourceTree = ""; }; - 03E6CED41CCE0DAB00D73982 /* ddsi_ser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ddsi_ser.h; sourceTree = ""; }; - 03E6CED51CCE0DAB00D73982 /* ddsi_ssl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ddsi_ssl.h; sourceTree = ""; }; - 03E6CED61CCE0DAB00D73982 /* ddsi_tcp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ddsi_tcp.h; sourceTree = ""; }; - 03E6CED71CCE0DAB00D73982 /* ddsi_tran.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ddsi_tran.h; sourceTree = ""; }; - 03E6CED81CCE0DAB00D73982 /* ddsi_udp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ddsi_udp.h; sourceTree = ""; }; - 03E6CED91CCE0DAB00D73982 /* probes-constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "probes-constants.h"; sourceTree = ""; }; - 03E6CEDA1CCE0DAB00D73982 /* q_addrset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_addrset.h; sourceTree = ""; }; - 03E6CEDB1CCE0DAB00D73982 /* q_align.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_align.h; sourceTree = ""; }; - 03E6CEDC1CCE0DAB00D73982 /* q_bitset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_bitset.h; sourceTree = ""; }; - 03E6CEDD1CCE0DAB00D73982 /* q_bswap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_bswap.h; sourceTree = ""; }; - 03E6CEDE1CCE0DAB00D73982 /* q_builtin_topic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_builtin_topic.h; sourceTree = ""; }; - 03E6CEDF1CCE0DAB00D73982 /* q_config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_config.h; sourceTree = ""; }; - 03E6CEE01CCE0DAB00D73982 /* q_ddsi_discovery.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_ddsi_discovery.h; sourceTree = ""; }; - 03E6CEE11CCE0DAB00D73982 /* q_debmon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_debmon.h; sourceTree = ""; }; - 03E6CEE21CCE0DAB00D73982 /* q_entity.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_entity.h; sourceTree = ""; }; - 03E6CEE31CCE0DAB00D73982 /* q_ephash.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_ephash.h; sourceTree = ""; }; - 03E6CEE41CCE0DAB00D73982 /* q_error.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_error.h; sourceTree = ""; }; - 03E6CEE51CCE0DAB00D73982 /* q_feature_check.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_feature_check.h; sourceTree = ""; }; - 03E6CEE61CCE0DAB00D73982 /* q_gc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_gc.h; sourceTree = ""; }; - 03E6CEE71CCE0DAB00D73982 /* q_globals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_globals.h; sourceTree = ""; }; - 03E6CEE81CCE0DAB00D73982 /* q_hbcontrol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_hbcontrol.h; sourceTree = ""; }; - 03E6CEE91CCE0DAB00D73982 /* q_inline.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_inline.h; sourceTree = ""; }; - 03E6CEEA1CCE0DAB00D73982 /* q_lat_estim.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_lat_estim.h; sourceTree = ""; }; - 03E6CEEB1CCE0DAB00D73982 /* q_lease.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_lease.h; sourceTree = ""; }; - 03E6CEEC1CCE0DAB00D73982 /* q_log.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_log.h; sourceTree = ""; }; - 03E6CEED1CCE0DAB00D73982 /* q_md5.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_md5.h; sourceTree = ""; }; - 03E6CEEE1CCE0DAB00D73982 /* q_misc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_misc.h; sourceTree = ""; }; - 03E6CEEF1CCE0DAB00D73982 /* q_nwif.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_nwif.h; sourceTree = ""; }; - 03E6CEF01CCE0DAB00D73982 /* q_pcap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_pcap.h; sourceTree = ""; }; - 03E6CEF11CCE0DAB00D73982 /* q_plist.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_plist.h; sourceTree = ""; }; - 03E6CEF21CCE0DAB00D73982 /* q_protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_protocol.h; sourceTree = ""; }; - 03E6CEF31CCE0DAB00D73982 /* q_qosmatch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_qosmatch.h; sourceTree = ""; }; - 03E6CEF41CCE0DAB00D73982 /* q_radmin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_radmin.h; sourceTree = ""; }; - 03E6CEF51CCE0DAB00D73982 /* q_receive.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_receive.h; sourceTree = ""; }; - 03E6CEF61CCE0DAB00D73982 /* q_rtps.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_rtps.h; sourceTree = ""; }; - 03E6CEF71CCE0DAB00D73982 /* q_security.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_security.h; sourceTree = ""; }; - 03E6CEF81CCE0DAB00D73982 /* q_servicelease.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_servicelease.h; sourceTree = ""; }; - 03E6CEF91CCE0DAB00D73982 /* q_sockwaitset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_sockwaitset.h; sourceTree = ""; }; - 03E6CEFA1CCE0DAB00D73982 /* q_static_assert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_static_assert.h; sourceTree = ""; }; - 03E6CEFB1CCE0DAB00D73982 /* q_thread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_thread.h; sourceTree = ""; }; - 03E6CEFC1CCE0DAB00D73982 /* q_time.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_time.h; sourceTree = ""; }; - 03E6CEFD1CCE0DAB00D73982 /* q_transmit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_transmit.h; sourceTree = ""; }; - 03E6CEFE1CCE0DAB00D73982 /* q_unused.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_unused.h; sourceTree = ""; }; - 03E6CEFF1CCE0DAB00D73982 /* q_whc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_whc.h; sourceTree = ""; }; - 03E6CF001CCE0DAB00D73982 /* q_xevent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_xevent.h; sourceTree = ""; }; - 03E6CF011CCE0DAB00D73982 /* q_xmsg.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_xmsg.h; sourceTree = ""; }; - 03E6CF021CCE0DAB00D73982 /* q_xqos.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_xqos.h; sourceTree = ""; }; - 03E6CF031CCE0DAB00D73982 /* sysdeps.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sysdeps.h; sourceTree = ""; }; - 03E6CF051CCE0DAB00D73982 /* dds_alloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_alloc.h; sourceTree = ""; }; - 03E6CF061CCE0DAB00D73982 /* dds_condition.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_condition.h; sourceTree = ""; }; - 03E6CF071CCE0DAB00D73982 /* dds_domain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_domain.h; sourceTree = ""; }; - 03E6CF081CCE0DAB00D73982 /* dds_entity.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_entity.h; sourceTree = ""; }; - 03E6CF091CCE0DAB00D73982 /* dds_export.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_export.h; sourceTree = ""; }; - 03E6CF0A1CCE0DAB00D73982 /* dds_guardcond.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_guardcond.h; sourceTree = ""; }; - 03E6CF0B1CCE0DAB00D73982 /* dds_iid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_iid.h; sourceTree = ""; }; - 03E6CF0C1CCE0DAB00D73982 /* dds_init.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_init.h; sourceTree = ""; }; - 03E6CF0D1CCE0DAB00D73982 /* dds_key.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_key.h; sourceTree = ""; }; - 03E6CF0E1CCE0DAB00D73982 /* dds_listener.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_listener.h; sourceTree = ""; }; - 03E6CF0F1CCE0DAB00D73982 /* dds_participant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_participant.h; sourceTree = ""; }; - 03E6CF101CCE0DAB00D73982 /* dds_qos.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_qos.h; sourceTree = ""; }; - 03E6CF111CCE0DAB00D73982 /* dds_querycond.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_querycond.h; sourceTree = ""; }; - 03E6CF121CCE0DAB00D73982 /* dds_readcond.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_readcond.h; sourceTree = ""; }; - 03E6CF131CCE0DAB00D73982 /* dds_reader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_reader.h; sourceTree = ""; }; - 03E6CF141CCE0DAB00D73982 /* dds_rhc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_rhc.h; sourceTree = ""; }; - 03E6CF151CCE0DAB00D73982 /* dds_status.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_status.h; sourceTree = ""; }; - 03E6CF161CCE0DAB00D73982 /* dds_statuscond.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_statuscond.h; sourceTree = ""; }; - 03E6CF171CCE0DAB00D73982 /* dds_stream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_stream.h; sourceTree = ""; }; - 03E6CF181CCE0DAB00D73982 /* dds_tkmap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_tkmap.h; sourceTree = ""; }; - 03E6CF191CCE0DAB00D73982 /* dds_topic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_topic.h; sourceTree = ""; }; - 03E6CF1A1CCE0DAB00D73982 /* dds_types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_types.h; sourceTree = ""; }; - 03E6CF1B1CCE0DAB00D73982 /* dds_waitset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_waitset.h; sourceTree = ""; }; - 03E6CF1C1CCE0DAB00D73982 /* dds_write.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_write.h; sourceTree = ""; }; - 03E6CF1D1CCE0DAB00D73982 /* dds_writer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dds_writer.h; sourceTree = ""; }; - 03E6CF1E1CCE0DAB00D73982 /* q_osplser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = q_osplser.h; sourceTree = ""; }; - 03E6CF211CCE0DAB00D73982 /* os_platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_platform.h; sourceTree = ""; }; - 03E6CF271CCE0DAB00D73982 /* os.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os.h; sourceTree = ""; }; - 03E6CF281CCE0DAB00D73982 /* os_atomics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_atomics.h; sourceTree = ""; }; - 03E6CF291CCE0DAB00D73982 /* os_atomics_gcc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_atomics_gcc.h; sourceTree = ""; }; - 03E6CF2A1CCE0DAB00D73982 /* os_decl_attributes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_decl_attributes.h; sourceTree = ""; }; - 03E6CF2B1CCE0DAB00D73982 /* os_decl_attributes_sal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_decl_attributes_sal.h; sourceTree = ""; }; - 03E6CF2C1CCE0DAB00D73982 /* os_defs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_defs.h; sourceTree = ""; }; - 03E6CF2D1CCE0DAB00D73982 /* os_errno.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_errno.h; sourceTree = ""; }; - 03E6CF2E1CCE0DAB00D73982 /* os_heap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_heap.h; sourceTree = ""; }; - 03E6CF2F1CCE0DAB00D73982 /* os_init.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_init.h; sourceTree = ""; }; - 03E6CF301CCE0DAB00D73982 /* os_process.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_process.h; sourceTree = ""; }; - 03E6CF311CCE0DAB00D73982 /* os_public.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_public.h; sourceTree = ""; }; - 03E6CF321CCE0DAB00D73982 /* os_report.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_report.h; sourceTree = ""; }; - 03E6CF331CCE0DAB00D73982 /* os_socket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_socket.h; sourceTree = ""; }; - 03E6CF341CCE0DAB00D73982 /* os_stdlib.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_stdlib.h; sourceTree = ""; }; - 03E6CF351CCE0DAB00D73982 /* os_sync.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_sync.h; sourceTree = ""; }; - 03E6CF361CCE0DAB00D73982 /* os_thread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_thread.h; sourceTree = ""; }; - 03E6CF371CCE0DAB00D73982 /* os_time.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_time.h; sourceTree = ""; }; - 03E6CF391CCE0DAB00D73982 /* ut_avl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ut_avl.h; sourceTree = ""; }; - 03E6CF3A1CCE0DAB00D73982 /* ut_crc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ut_crc.h; sourceTree = ""; }; - 03E6CF3B1CCE0DAB00D73982 /* ut_expand_envvars.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ut_expand_envvars.h; sourceTree = ""; }; - 03E6CF3C1CCE0DAB00D73982 /* ut_fibheap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ut_fibheap.h; sourceTree = ""; }; - 03E6CF3D1CCE0DAB00D73982 /* ut_hopscotch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ut_hopscotch.h; sourceTree = ""; }; - 03E6CF3E1CCE0DAB00D73982 /* ut_thread_pool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ut_thread_pool.h; sourceTree = ""; }; - 03E6CF3F1CCE0DAB00D73982 /* ut_xmlparser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ut_xmlparser.h; sourceTree = ""; }; - 03E6CF421CCE0DAB00D73982 /* rpc-ping.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "rpc-ping.c"; sourceTree = ""; }; - 03E6CF431CCE0DAB00D73982 /* rpc-pong.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "rpc-pong.c"; sourceTree = ""; }; - 03E6CF441CCE0DAB00D73982 /* rpc-publisher.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "rpc-publisher.c"; sourceTree = ""; }; - 03E6CF451CCE0DAB00D73982 /* rpc-subscriber.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "rpc-subscriber.c"; sourceTree = ""; }; - 03E6CF481CCE0DAB00D73982 /* ddsi_ser.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ddsi_ser.c; sourceTree = ""; }; - 03E6CF491CCE0DAB00D73982 /* ddsi_ssl.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ddsi_ssl.c; sourceTree = ""; }; - 03E6CF4A1CCE0DAB00D73982 /* ddsi_tcp.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ddsi_tcp.c; sourceTree = ""; }; - 03E6CF4B1CCE0DAB00D73982 /* ddsi_tran.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ddsi_tran.c; sourceTree = ""; }; - 03E6CF4C1CCE0DAB00D73982 /* ddsi_udp.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ddsi_udp.c; sourceTree = ""; }; - 03E6CF4D1CCE0DAB00D73982 /* q_addrset.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_addrset.c; sourceTree = ""; }; - 03E6CF4E1CCE0DAB00D73982 /* q_bitset_inlines.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_bitset_inlines.c; sourceTree = ""; }; - 03E6CF501CCE0DAB00D73982 /* q_bswap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_bswap.c; sourceTree = ""; }; - 03E6CF511CCE0DAB00D73982 /* q_bswap_inlines.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_bswap_inlines.c; sourceTree = ""; }; - 03E6CF531CCE0DAB00D73982 /* q_config.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_config.c; sourceTree = ""; }; - 03E6CF541CCE0DAB00D73982 /* q_ddsi_discovery.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_ddsi_discovery.c; sourceTree = ""; }; - 03E6CF551CCE0DAB00D73982 /* q_debmon.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_debmon.c; sourceTree = ""; }; - 03E6CF561CCE0DAB00D73982 /* q_entity.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_entity.c; sourceTree = ""; }; - 03E6CF571CCE0DAB00D73982 /* q_ephash.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_ephash.c; sourceTree = ""; }; - 03E6CF581CCE0DAB00D73982 /* q_gc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_gc.c; sourceTree = ""; }; - 03E6CF591CCE0DAB00D73982 /* q_init.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_init.c; sourceTree = ""; }; - 03E6CF5A1CCE0DAB00D73982 /* q_lat_estim.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_lat_estim.c; sourceTree = ""; }; - 03E6CF5B1CCE0DAB00D73982 /* q_lease.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_lease.c; sourceTree = ""; }; - 03E6CF5C1CCE0DAB00D73982 /* q_log.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_log.c; sourceTree = ""; }; - 03E6CF5D1CCE0DAB00D73982 /* q_md5.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_md5.c; sourceTree = ""; }; - 03E6CF5E1CCE0DAB00D73982 /* q_misc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_misc.c; sourceTree = ""; }; - 03E6CF5F1CCE0DAB00D73982 /* q_nwif.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_nwif.c; sourceTree = ""; }; - 03E6CF601CCE0DAB00D73982 /* q_pcap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_pcap.c; sourceTree = ""; }; - 03E6CF611CCE0DAB00D73982 /* q_plist.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_plist.c; sourceTree = ""; }; - 03E6CF621CCE0DAB00D73982 /* q_qosmatch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_qosmatch.c; sourceTree = ""; }; - 03E6CF631CCE0DAB00D73982 /* q_radmin.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_radmin.c; sourceTree = ""; }; - 03E6CF641CCE0DAB00D73982 /* q_receive.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_receive.c; sourceTree = ""; }; - 03E6CF651CCE0DAB00D73982 /* q_security.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_security.c; sourceTree = ""; }; - 03E6CF661CCE0DAB00D73982 /* q_servicelease.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_servicelease.c; sourceTree = ""; }; - 03E6CF671CCE0DAB00D73982 /* q_sockwaitset.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_sockwaitset.c; sourceTree = ""; }; - 03E6CF681CCE0DAB00D73982 /* q_thread.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_thread.c; sourceTree = ""; }; - 03E6CF691CCE0DAB00D73982 /* q_thread_inlines.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_thread_inlines.c; sourceTree = ""; }; - 03E6CF6B1CCE0DAB00D73982 /* q_time.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_time.c; sourceTree = ""; }; - 03E6CF6C1CCE0DAB00D73982 /* q_transmit.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_transmit.c; sourceTree = ""; }; - 03E6CF6D1CCE0DAB00D73982 /* q_whc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_whc.c; sourceTree = ""; }; - 03E6CF6E1CCE0DAB00D73982 /* q_xevent.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_xevent.c; sourceTree = ""; }; - 03E6CF6F1CCE0DAB00D73982 /* q_xmsg.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_xmsg.c; sourceTree = ""; }; - 03E6CF701CCE0DAB00D73982 /* sysdeps.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sysdeps.c; sourceTree = ""; }; - 03E6CF721CCE0DAB00D73982 /* dds_alloc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_alloc.c; sourceTree = ""; }; - 03E6CF731CCE0DAB00D73982 /* dds_condition.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_condition.c; sourceTree = ""; }; - 03E6CF741CCE0DAB00D73982 /* dds_domain.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_domain.c; sourceTree = ""; }; - 03E6CF751CCE0DAB00D73982 /* dds_entity.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_entity.c; sourceTree = ""; }; - 03E6CF761CCE0DAB00D73982 /* dds_err.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_err.c; sourceTree = ""; }; - 03E6CF771CCE0DAB00D73982 /* dds_guardcond.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_guardcond.c; sourceTree = ""; }; - 03E6CF781CCE0DAB00D73982 /* dds_iid.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_iid.c; sourceTree = ""; }; - 03E6CF791CCE0DAB00D73982 /* dds_init.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_init.c; sourceTree = ""; }; - 03E6CF7A1CCE0DAB00D73982 /* dds_instance.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_instance.c; sourceTree = ""; }; - 03E6CF7B1CCE0DAB00D73982 /* dds_key.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_key.c; sourceTree = ""; }; - 03E6CF7C1CCE0DAB00D73982 /* dds_listener.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_listener.c; sourceTree = ""; }; - 03E6CF7D1CCE0DAB00D73982 /* dds_log.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_log.c; sourceTree = ""; }; - 03E6CF7E1CCE0DAB00D73982 /* dds_participant.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_participant.c; sourceTree = ""; }; - 03E6CF7F1CCE0DAB00D73982 /* dds_publisher.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_publisher.c; sourceTree = ""; }; - 03E6CF801CCE0DAB00D73982 /* dds_qos.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_qos.c; sourceTree = ""; }; - 03E6CF811CCE0DAB00D73982 /* dds_querycond.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_querycond.c; sourceTree = ""; }; - 03E6CF821CCE0DAB00D73982 /* dds_read.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_read.c; sourceTree = ""; }; - 03E6CF831CCE0DAB00D73982 /* dds_readcond.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_readcond.c; sourceTree = ""; }; - 03E6CF841CCE0DAB00D73982 /* dds_reader.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_reader.c; sourceTree = ""; }; - 03E6CF851CCE0DAB00D73982 /* dds_rhc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_rhc.c; sourceTree = ""; }; - 03E6CF861CCE0DAB00D73982 /* dds_status.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_status.c; sourceTree = ""; }; - 03E6CF871CCE0DAB00D73982 /* dds_statuscond.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_statuscond.c; sourceTree = ""; }; - 03E6CF881CCE0DAB00D73982 /* dds_stream.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_stream.c; sourceTree = ""; }; - 03E6CF891CCE0DAB00D73982 /* dds_subscriber.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_subscriber.c; sourceTree = ""; }; - 03E6CF8A1CCE0DAB00D73982 /* dds_thread.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_thread.c; sourceTree = ""; }; - 03E6CF8B1CCE0DAB00D73982 /* dds_time.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_time.c; sourceTree = ""; }; - 03E6CF8C1CCE0DAB00D73982 /* dds_tkmap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_tkmap.c; sourceTree = ""; }; - 03E6CF8D1CCE0DAB00D73982 /* dds_topic.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_topic.c; sourceTree = ""; }; - 03E6CF8E1CCE0DAB00D73982 /* dds_waitset.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_waitset.c; sourceTree = ""; }; - 03E6CF8F1CCE0DAB00D73982 /* dds_write.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_write.c; sourceTree = ""; }; - 03E6CF901CCE0DAB00D73982 /* dds_writer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dds_writer.c; sourceTree = ""; }; - 03E6CF911CCE0DAB00D73982 /* q_osplser.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = q_osplser.c; sourceTree = ""; }; - 03E6CF9E1CCE0DAB00D73982 /* os_atomics.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_atomics.c; sourceTree = ""; }; - 03E6CF9F1CCE0DAB00D73982 /* os_init.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_init.c; sourceTree = ""; }; - 03E6CFA01CCE0DAB00D73982 /* os_report.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_report.c; sourceTree = ""; }; - 03E6CFA11CCE0DAB00D73982 /* os_socket.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_socket.c; sourceTree = ""; }; - 03E6CFA21CCE0DAB00D73982 /* os_sync.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_sync.c; sourceTree = ""; }; - 03E6CFA31CCE0DAB00D73982 /* os_thread.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_thread.c; sourceTree = ""; }; - 03E6CFA41CCE0DAB00D73982 /* os_time.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_time.c; sourceTree = ""; }; - 03E6CFA71CCE0DAB00D73982 /* os_gethostname.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_gethostname.c; sourceTree = ""; }; - 03E6CFA81CCE0DAB00D73982 /* os_heap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_heap.c; sourceTree = ""; }; - 03E6CFA91CCE0DAB00D73982 /* os_posix_errno.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_posix_errno.c; sourceTree = ""; }; - 03E6CFAA1CCE0DAB00D73982 /* os_posix_process.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_posix_process.c; sourceTree = ""; }; - 03E6CFAB1CCE0DAB00D73982 /* os_posix_thread.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_posix_thread.c; sourceTree = ""; }; - 03E6CFAC1CCE0DAB00D73982 /* os_stdlib.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_stdlib.c; sourceTree = ""; }; - 03E6CFAD1CCE0DAB00D73982 /* os_stdlib_bsearch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_stdlib_bsearch.c; sourceTree = ""; }; - 03E6CFAE1CCE0DAB00D73982 /* os_stdlib_strsep.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_stdlib_strsep.c; sourceTree = ""; }; - 03E6CFAF1CCE0DAB00D73982 /* os_stdlib_strtod.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_stdlib_strtod.c; sourceTree = ""; }; - 03E6CFB01CCE0DAB00D73982 /* os_stdlib_strtok_r.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_stdlib_strtok_r.c; sourceTree = ""; }; - 03E6CFB11CCE0DAB00D73982 /* os_stdlib_strtol.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = os_stdlib_strtol.c; sourceTree = ""; }; - 03E6CFB31CCE0DAB00D73982 /* os_posix_stdlib.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = os_posix_stdlib.h; sourceTree = ""; }; - 03E6CFC51CCE0DAB00D73982 /* ut_avl.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ut_avl.c; sourceTree = ""; }; - 03E6CFC61CCE0DAB00D73982 /* ut_crc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ut_crc.c; sourceTree = ""; }; - 03E6CFC71CCE0DAB00D73982 /* ut_expand_envvars.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ut_expand_envvars.c; sourceTree = ""; }; - 03E6CFC81CCE0DAB00D73982 /* ut_fibheap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ut_fibheap.c; sourceTree = ""; }; - 03E6CFC91CCE0DAB00D73982 /* ut_hopscotch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ut_hopscotch.c; sourceTree = ""; }; - 03E6CFCA1CCE0DAB00D73982 /* ut_thread_pool.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ut_thread_pool.c; sourceTree = ""; }; - 03E6CFCB1CCE0DAB00D73982 /* ut_xmlparser.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ut_xmlparser.c; sourceTree = ""; }; - 03E6CFCD1CCE0DAB00D73982 /* server.c */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = ""; }; - 03E6CFCE1CCE0DAB00D73982 /* server.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = server.h; sourceTree = ""; }; - 03E6CFCF1CCE0DAB00D73982 /* vdds-stubs.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "vdds-stubs.c"; sourceTree = ""; }; - 03E6D0531CCE116900D73982 /* vdds-server */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "vdds-server"; sourceTree = BUILT_PRODUCTS_DIR; }; - 03E6D0601CCE121300D73982 /* publisher */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = publisher; sourceTree = BUILT_PRODUCTS_DIR; }; - 03E6D06B1CCE121A00D73982 /* subscriber */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = subscriber; sourceTree = BUILT_PRODUCTS_DIR; }; - 03E6D0761CCE121F00D73982 /* ping */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ping; sourceTree = BUILT_PRODUCTS_DIR; }; - 03E6D0811CCE122400D73982 /* pong */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = pong; sourceTree = BUILT_PRODUCTS_DIR; }; - 03E6D08C1CCE122A00D73982 /* rpc-publisher */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "rpc-publisher"; sourceTree = BUILT_PRODUCTS_DIR; }; - 03E6D0971CCE123000D73982 /* rpc-subscriber */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "rpc-subscriber"; sourceTree = BUILT_PRODUCTS_DIR; }; - 03E6D0A21CCE123500D73982 /* rpc-ping */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "rpc-ping"; sourceTree = BUILT_PRODUCTS_DIR; }; - 03E6D0AD1CCE123A00D73982 /* rpc-pong */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "rpc-pong"; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 033520411CEDD22A003E7429 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 0335204A1CEDDC48003E7429 /* libvdds.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 036D25871DF15EB9009A18C5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 036D25881DF15EB9009A18C5 /* libvdds.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03C96E9E1CCE5B8D0012F15D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 03C96EA91CCF6D030012F15D /* libevent-2.0.5.dylib in Frameworks */, - 03C96EA71CCE5CD20012F15D /* libevent_pthreads-2.0.5.dylib in Frameworks */, - 03C96E9F1CCE5B8D0012F15D /* libvdds.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6CEA61CCE0CA400D73982 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6CEAE1CCE0CCC00D73982 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D0501CCE116900D73982 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D05B1CCE11DA00D73982 /* libvdds.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D05D1CCE121300D73982 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0BB1CCE126700D73982 /* libvdds.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D0681CCE121A00D73982 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0BA1CCE126300D73982 /* libvdds.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D0731CCE121F00D73982 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0B91CCE125F00D73982 /* libvdds.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D07E1CCE122400D73982 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0B81CCE125C00D73982 /* libvdds.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D0891CCE122A00D73982 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0B71CCE125800D73982 /* libvdds-stubs.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D0941CCE123000D73982 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0B61CCE125500D73982 /* libvdds-stubs.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D09F1CCE123500D73982 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0B51CCE125100D73982 /* libvdds-stubs.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D0AA1CCE123A00D73982 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0B41CCE124D00D73982 /* libvdds-stubs.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 035877BC1DDCA45B000F61E2 /* posix */ = { - isa = PBXGroup; - children = ( - 035877BD1DDCA45B000F61E2 /* os_platform_errno.c */, - 035877BE1DDCA45B000F61E2 /* os_platform_heap.c */, - 035877BF1DDCA45B000F61E2 /* os_platform_init.c */, - 035877C01DDCA45B000F61E2 /* os_platform_process.c */, - 035877C11DDCA45B000F61E2 /* os_platform_socket.c */, - 035877C21DDCA45B000F61E2 /* os_platform_stdlib.c */, - 035877C31DDCA45B000F61E2 /* os_platform_sync.c */, - 035877C41DDCA45B000F61E2 /* os_platform_thread.c */, - 035877C51DDCA45B000F61E2 /* os_platform_time.c */, - ); - path = posix; - sourceTree = ""; - }; - 035877D81DDCA54F000F61E2 /* posix */ = { - isa = PBXGroup; - children = ( - 035877D91DDCA54F000F61E2 /* os_platform_public.h */, - 035877DA1DDCA54F000F61E2 /* os_platform_socket.h */, - 035877DB1DDCA54F000F61E2 /* os_platform_stdlib.h */, - 035877DC1DDCA54F000F61E2 /* os_platform_sync.h */, - 035877DD1DDCA54F000F61E2 /* os_platform_thread.h */, - ); - path = posix; - sourceTree = ""; - }; - 035877DE1DDCA54F000F61E2 /* linux */ = { - isa = PBXGroup; - children = ( - 035877DF1DDCA54F000F61E2 /* os_platform.h */, - ); - path = linux; - sourceTree = ""; - }; - 037D2E7F1CD24583004434B2 /* win32 */ = { - isa = PBXGroup; - children = ( - 037D2E801CD245BB004434B2 /* os_platform_public.h */, - 037D2E811CD245BB004434B2 /* os_platform_socket.h */, - 037D2E821CD245BB004434B2 /* os_platform_stdlib.h */, - 037D2E831CD245BB004434B2 /* os_platform_sync.h */, - 037D2E841CD245BB004434B2 /* os_platform_thread.h */, - 037D2E851CD245BB004434B2 /* os_platform_time.h */, - 037D2E861CD245BB004434B2 /* os_platform.h */, - ); - path = win32; - sourceTree = ""; - }; - 03E6CE951CCE0C6B00D73982 = { - isa = PBXGroup; - children = ( - 035877B71DDB0A20000F61E2 /* lite.xml */, - 035877B81DDB0A20000F61E2 /* config.mk */, - 035877B91DDB0A20000F61E2 /* guess-config */, - 035877BA1DDB0A20000F61E2 /* makefile */, - 03C96EA81CCF6D030012F15D /* libevent-2.0.5.dylib */, - 03C96EA61CCE5CD20012F15D /* libevent_pthreads-2.0.5.dylib */, - 03E6CEC11CCE0DAB00D73982 /* include */, - 03E6CF461CCE0DAB00D73982 /* src */, - 03E6CFCC1CCE0DAB00D73982 /* vdds-server */, - 03E6CEB51CCE0DAB00D73982 /* examples */, - 03E6CF401CCE0DAB00D73982 /* rpc-examples */, - 03E6CE9F1CCE0C6B00D73982 /* Products */, - ); - sourceTree = ""; - }; - 03E6CE9F1CCE0C6B00D73982 /* Products */ = { - isa = PBXGroup; - children = ( - 03E6CEA91CCE0CA400D73982 /* libvdds.dylib */, - 03E6CEB11CCE0CCC00D73982 /* libvdds-stubs.dylib */, - 03E6D0531CCE116900D73982 /* vdds-server */, - 03E6D0601CCE121300D73982 /* publisher */, - 03E6D06B1CCE121A00D73982 /* subscriber */, - 03E6D0761CCE121F00D73982 /* ping */, - 03E6D0811CCE122400D73982 /* pong */, - 03E6D08C1CCE122A00D73982 /* rpc-publisher */, - 03E6D0971CCE123000D73982 /* rpc-subscriber */, - 03E6D0A21CCE123500D73982 /* rpc-ping */, - 03E6D0AD1CCE123A00D73982 /* rpc-pong */, - 03C96EA41CCE5B8D0012F15D /* vdds-server2 */, - 033520471CEDD22A003E7429 /* rpc-pingpong */, - 036D258D1DF15EBA009A18C5 /* ddpingpong */, - ); - name = Products; - sourceTree = ""; - }; - 03E6CEB51CCE0DAB00D73982 /* examples */ = { - isa = PBXGroup; - children = ( - 036D25821DF15EAF009A18C5 /* ddpingpong.c */, - 03E6CEB61CCE0DAB00D73982 /* generated */, - 03E6CEBD1CCE0DAB00D73982 /* ping.c */, - 03E6CEBE1CCE0DAB00D73982 /* pong.c */, - 03E6CEBF1CCE0DAB00D73982 /* publisher.c */, - 03E6CEC01CCE0DAB00D73982 /* subscriber.c */, - ); - indentWidth = 4; - name = examples; - path = ../examples; - sourceTree = ""; - }; - 03E6CEB61CCE0DAB00D73982 /* generated */ = { - isa = PBXGroup; - children = ( - 03E6CEB71CCE0DAB00D73982 /* RoundTrip.c */, - 03E6CEB81CCE0DAB00D73982 /* RoundTrip.h */, - 03E6CEB91CCE0DAB00D73982 /* RoundTrip.idl */, - 03E6CEBA1CCE0DAB00D73982 /* Throughput.c */, - 03E6CEBB1CCE0DAB00D73982 /* Throughput.h */, - 03E6CEBC1CCE0DAB00D73982 /* Throughput.idl */, - ); - path = generated; - sourceTree = ""; - }; - 03E6CEC11CCE0DAB00D73982 /* include */ = { - isa = PBXGroup; - children = ( - 03E6CEC21CCE0DAB00D73982 /* dds */, - 03E6CED21CCE0DAB00D73982 /* dds.h */, - 03E6CED31CCE0DAB00D73982 /* ddsi */, - 03E6CF041CCE0DAB00D73982 /* kernel */, - 03E6CF1F1CCE0DAB00D73982 /* os */, - 03E6CF381CCE0DAB00D73982 /* util */, - ); - name = include; - path = ../include; - sourceTree = ""; - }; - 03E6CEC21CCE0DAB00D73982 /* dds */ = { - isa = PBXGroup; - children = ( - 03E6CEC31CCE0DAB00D73982 /* dds_public_alloc.h */, - 03E6CEC41CCE0DAB00D73982 /* dds_public_error.h */, - 03E6CEC51CCE0DAB00D73982 /* dds_public_impl.h */, - 03E6CEC61CCE0DAB00D73982 /* dds_public_log.h */, - 03E6CEC71CCE0DAB00D73982 /* dds_public_qos.h */, - 03E6CEC81CCE0DAB00D73982 /* dds_public_status.h */, - 03E6CEC91CCE0DAB00D73982 /* dds_public_stream.h */, - 03E6CECA1CCE0DAB00D73982 /* dds_public_time.h */, - 03E6CECB1CCE0DAB00D73982 /* os */, - ); - path = dds; - sourceTree = ""; - }; - 03E6CECB1CCE0DAB00D73982 /* os */ = { - isa = PBXGroup; - children = ( - 03E6CECC1CCE0DAB00D73982 /* linux */, - 03E6CECD1CCE0DAB00D73982 /* osx */, - 03E6CECE1CCE0DAB00D73982 /* qnx */, - 03E6CECF1CCE0DAB00D73982 /* solaris */, - 03E6CED01CCE0DAB00D73982 /* vxworks */, - 03E6CED11CCE0DAB00D73982 /* win32 */, - ); - path = os; - sourceTree = ""; - }; - 03E6CECC1CCE0DAB00D73982 /* linux */ = { - isa = PBXGroup; - children = ( - ); - path = linux; - sourceTree = ""; - }; - 03E6CECD1CCE0DAB00D73982 /* osx */ = { - isa = PBXGroup; - children = ( - ); - path = osx; - sourceTree = ""; - }; - 03E6CECE1CCE0DAB00D73982 /* qnx */ = { - isa = PBXGroup; - children = ( - ); - path = qnx; - sourceTree = ""; - }; - 03E6CECF1CCE0DAB00D73982 /* solaris */ = { - isa = PBXGroup; - children = ( - ); - path = solaris; - sourceTree = ""; - }; - 03E6CED01CCE0DAB00D73982 /* vxworks */ = { - isa = PBXGroup; - children = ( - ); - path = vxworks; - sourceTree = ""; - }; - 03E6CED11CCE0DAB00D73982 /* win32 */ = { - isa = PBXGroup; - children = ( - ); - path = win32; - sourceTree = ""; - }; - 03E6CED31CCE0DAB00D73982 /* ddsi */ = { - isa = PBXGroup; - children = ( - 03E6CED41CCE0DAB00D73982 /* ddsi_ser.h */, - 03E6CED51CCE0DAB00D73982 /* ddsi_ssl.h */, - 03E6CED61CCE0DAB00D73982 /* ddsi_tcp.h */, - 03E6CED71CCE0DAB00D73982 /* ddsi_tran.h */, - 03E6CED81CCE0DAB00D73982 /* ddsi_udp.h */, - 03E6CED91CCE0DAB00D73982 /* probes-constants.h */, - 03E6CEDA1CCE0DAB00D73982 /* q_addrset.h */, - 03E6CEDB1CCE0DAB00D73982 /* q_align.h */, - 0335204B1CEF4B21003E7429 /* q_bitset_template.h */, - 03E6CEDC1CCE0DAB00D73982 /* q_bitset.h */, - 0335204C1CEF4B21003E7429 /* q_bswap_template.h */, - 03E6CEDD1CCE0DAB00D73982 /* q_bswap.h */, - 03E6CEDE1CCE0DAB00D73982 /* q_builtin_topic.h */, - 03E6CEDF1CCE0DAB00D73982 /* q_config.h */, - 03E6CEE01CCE0DAB00D73982 /* q_ddsi_discovery.h */, - 03E6CEE11CCE0DAB00D73982 /* q_debmon.h */, - 03E6CEE21CCE0DAB00D73982 /* q_entity.h */, - 03E6CEE31CCE0DAB00D73982 /* q_ephash.h */, - 03E6CEE41CCE0DAB00D73982 /* q_error.h */, - 03E6CEE51CCE0DAB00D73982 /* q_feature_check.h */, - 03E6CEE61CCE0DAB00D73982 /* q_gc.h */, - 03E6CEE71CCE0DAB00D73982 /* q_globals.h */, - 03E6CEE81CCE0DAB00D73982 /* q_hbcontrol.h */, - 03E6CEE91CCE0DAB00D73982 /* q_inline.h */, - 03E6CEEA1CCE0DAB00D73982 /* q_lat_estim.h */, - 03E6CEEB1CCE0DAB00D73982 /* q_lease.h */, - 03E6CEEC1CCE0DAB00D73982 /* q_log.h */, - 03E6CEED1CCE0DAB00D73982 /* q_md5.h */, - 03E6CEEE1CCE0DAB00D73982 /* q_misc.h */, - 03E6CEEF1CCE0DAB00D73982 /* q_nwif.h */, - 03E6CEF01CCE0DAB00D73982 /* q_pcap.h */, - 03E6CEF11CCE0DAB00D73982 /* q_plist.h */, - 03E6CEF21CCE0DAB00D73982 /* q_protocol.h */, - 03E6CEF31CCE0DAB00D73982 /* q_qosmatch.h */, - 03E6CEF41CCE0DAB00D73982 /* q_radmin.h */, - 03E6CEF51CCE0DAB00D73982 /* q_receive.h */, - 03E6CEF61CCE0DAB00D73982 /* q_rtps.h */, - 03E6CEF71CCE0DAB00D73982 /* q_security.h */, - 03E6CEF81CCE0DAB00D73982 /* q_servicelease.h */, - 03E6CEF91CCE0DAB00D73982 /* q_sockwaitset.h */, - 03E6CEFA1CCE0DAB00D73982 /* q_static_assert.h */, - 0335204D1CEF4B21003E7429 /* q_thread_template.h */, - 03E6CEFB1CCE0DAB00D73982 /* q_thread.h */, - 034CF9301DE2FDF300DD6073 /* q_freelist.h */, - 03E6CEFC1CCE0DAB00D73982 /* q_time.h */, - 03E6CEFD1CCE0DAB00D73982 /* q_transmit.h */, - 03E6CEFE1CCE0DAB00D73982 /* q_unused.h */, - 03E6CEFF1CCE0DAB00D73982 /* q_whc.h */, - 03E6CF001CCE0DAB00D73982 /* q_xevent.h */, - 03E6CF011CCE0DAB00D73982 /* q_xmsg.h */, - 03E6CF021CCE0DAB00D73982 /* q_xqos.h */, - 03E6CF031CCE0DAB00D73982 /* sysdeps.h */, - ); - path = ddsi; - sourceTree = ""; - }; - 03E6CF041CCE0DAB00D73982 /* kernel */ = { - isa = PBXGroup; - children = ( - 03E6CF051CCE0DAB00D73982 /* dds_alloc.h */, - 03E6CF061CCE0DAB00D73982 /* dds_condition.h */, - 03E6CF071CCE0DAB00D73982 /* dds_domain.h */, - 03E6CF081CCE0DAB00D73982 /* dds_entity.h */, - 03E6CF091CCE0DAB00D73982 /* dds_export.h */, - 03E6CF0A1CCE0DAB00D73982 /* dds_guardcond.h */, - 03E6CF0B1CCE0DAB00D73982 /* dds_iid.h */, - 03E6CF0C1CCE0DAB00D73982 /* dds_init.h */, - 03E6CF0D1CCE0DAB00D73982 /* dds_key.h */, - 03E6CF0E1CCE0DAB00D73982 /* dds_listener.h */, - 03E6CF0F1CCE0DAB00D73982 /* dds_participant.h */, - 03E6CF101CCE0DAB00D73982 /* dds_qos.h */, - 03E6CF111CCE0DAB00D73982 /* dds_querycond.h */, - 03E6CF121CCE0DAB00D73982 /* dds_readcond.h */, - 03E6CF131CCE0DAB00D73982 /* dds_reader.h */, - 03E6CF141CCE0DAB00D73982 /* dds_rhc.h */, - 03E6CF151CCE0DAB00D73982 /* dds_status.h */, - 03E6CF161CCE0DAB00D73982 /* dds_statuscond.h */, - 03E6CF171CCE0DAB00D73982 /* dds_stream.h */, - 03E6CF181CCE0DAB00D73982 /* dds_tkmap.h */, - 03E6CF191CCE0DAB00D73982 /* dds_topic.h */, - 03E6CF1A1CCE0DAB00D73982 /* dds_types.h */, - 03E6CF1B1CCE0DAB00D73982 /* dds_waitset.h */, - 03E6CF1C1CCE0DAB00D73982 /* dds_write.h */, - 03E6CF1D1CCE0DAB00D73982 /* dds_writer.h */, - 03E6CF1E1CCE0DAB00D73982 /* q_osplser.h */, - ); - path = kernel; - sourceTree = ""; - }; - 03E6CF1F1CCE0DAB00D73982 /* os */ = { - isa = PBXGroup; - children = ( - 035877D81DDCA54F000F61E2 /* posix */, - 035877DE1DDCA54F000F61E2 /* linux */, - 037D2E7F1CD24583004434B2 /* win32 */, - 03E6CF201CCE0DAB00D73982 /* darwin */, - 03E6CF271CCE0DAB00D73982 /* os.h */, - 03E6CF281CCE0DAB00D73982 /* os_atomics.h */, - 03E6CF291CCE0DAB00D73982 /* os_atomics_gcc.h */, - 037D2E771CD24576004434B2 /* os_atomics_win32.h */, - 03E6CF2A1CCE0DAB00D73982 /* os_decl_attributes.h */, - 03E6CF2B1CCE0DAB00D73982 /* os_decl_attributes_sal.h */, - 03E6CF2C1CCE0DAB00D73982 /* os_defs.h */, - 03E6CF2D1CCE0DAB00D73982 /* os_errno.h */, - 03E6CF2E1CCE0DAB00D73982 /* os_heap.h */, - 03E6CF2F1CCE0DAB00D73982 /* os_init.h */, - 03E6CF301CCE0DAB00D73982 /* os_process.h */, - 03E6CF311CCE0DAB00D73982 /* os_public.h */, - 03E6CF321CCE0DAB00D73982 /* os_report.h */, - 03E6CF331CCE0DAB00D73982 /* os_socket.h */, - 03E6CF341CCE0DAB00D73982 /* os_stdlib.h */, - 03E6CF351CCE0DAB00D73982 /* os_sync.h */, - 03E6CF361CCE0DAB00D73982 /* os_thread.h */, - 03E6CF371CCE0DAB00D73982 /* os_time.h */, - ); - path = os; - sourceTree = ""; - }; - 03E6CF201CCE0DAB00D73982 /* darwin */ = { - isa = PBXGroup; - children = ( - 03E6CF211CCE0DAB00D73982 /* os_platform.h */, - ); - path = darwin; - sourceTree = ""; - }; - 03E6CF381CCE0DAB00D73982 /* util */ = { - isa = PBXGroup; - children = ( - 03E6CF391CCE0DAB00D73982 /* ut_avl.h */, - 03E6CF3A1CCE0DAB00D73982 /* ut_crc.h */, - 03E6CF3B1CCE0DAB00D73982 /* ut_expand_envvars.h */, - 03E6CF3C1CCE0DAB00D73982 /* ut_fibheap.h */, - 03E6CF3D1CCE0DAB00D73982 /* ut_hopscotch.h */, - 03E6CF3E1CCE0DAB00D73982 /* ut_thread_pool.h */, - 03E6CF3F1CCE0DAB00D73982 /* ut_xmlparser.h */, - ); - path = util; - sourceTree = ""; - }; - 03E6CF401CCE0DAB00D73982 /* rpc-examples */ = { - isa = PBXGroup; - children = ( - 03E6CF421CCE0DAB00D73982 /* rpc-ping.c */, - 03E6CF431CCE0DAB00D73982 /* rpc-pong.c */, - 03E6CF441CCE0DAB00D73982 /* rpc-publisher.c */, - 03E6CF451CCE0DAB00D73982 /* rpc-subscriber.c */, - 0335203C1CEDD031003E7429 /* rpc-pingpong.c */, - ); - indentWidth = 2; - name = "rpc-examples"; - path = "../rpc-examples"; - sourceTree = ""; - }; - 03E6CF461CCE0DAB00D73982 /* src */ = { - isa = PBXGroup; - children = ( - 03E6CF471CCE0DAB00D73982 /* ddsi */, - 03E6CF711CCE0DAB00D73982 /* kernel */, - 03E6CF921CCE0DAB00D73982 /* os */, - 03E6CFC41CCE0DAB00D73982 /* util */, - ); - name = src; - path = ../src; - sourceTree = ""; - }; - 03E6CF471CCE0DAB00D73982 /* ddsi */ = { - isa = PBXGroup; - children = ( - 03E6CF481CCE0DAB00D73982 /* ddsi_ser.c */, - 03E6CF491CCE0DAB00D73982 /* ddsi_ssl.c */, - 03E6CF4A1CCE0DAB00D73982 /* ddsi_tcp.c */, - 03E6CF4B1CCE0DAB00D73982 /* ddsi_tran.c */, - 03E6CF4C1CCE0DAB00D73982 /* ddsi_udp.c */, - 03E6CF4D1CCE0DAB00D73982 /* q_addrset.c */, - 03E6CF4E1CCE0DAB00D73982 /* q_bitset_inlines.c */, - 03E6CF501CCE0DAB00D73982 /* q_bswap.c */, - 03E6CF511CCE0DAB00D73982 /* q_bswap_inlines.c */, - 03E6CF531CCE0DAB00D73982 /* q_config.c */, - 03E6CF541CCE0DAB00D73982 /* q_ddsi_discovery.c */, - 03E6CF551CCE0DAB00D73982 /* q_debmon.c */, - 03E6CF561CCE0DAB00D73982 /* q_entity.c */, - 03E6CF571CCE0DAB00D73982 /* q_ephash.c */, - 03E6CF581CCE0DAB00D73982 /* q_gc.c */, - 03E6CF591CCE0DAB00D73982 /* q_init.c */, - 03E6CF5A1CCE0DAB00D73982 /* q_lat_estim.c */, - 03E6CF5B1CCE0DAB00D73982 /* q_lease.c */, - 03E6CF5C1CCE0DAB00D73982 /* q_log.c */, - 03E6CF5D1CCE0DAB00D73982 /* q_md5.c */, - 03E6CF5E1CCE0DAB00D73982 /* q_misc.c */, - 03E6CF5F1CCE0DAB00D73982 /* q_nwif.c */, - 03E6CF601CCE0DAB00D73982 /* q_pcap.c */, - 03E6CF611CCE0DAB00D73982 /* q_plist.c */, - 03E6CF621CCE0DAB00D73982 /* q_qosmatch.c */, - 03E6CF631CCE0DAB00D73982 /* q_radmin.c */, - 03E6CF641CCE0DAB00D73982 /* q_receive.c */, - 03E6CF651CCE0DAB00D73982 /* q_security.c */, - 03E6CF661CCE0DAB00D73982 /* q_servicelease.c */, - 03E6CF671CCE0DAB00D73982 /* q_sockwaitset.c */, - 03E6CF681CCE0DAB00D73982 /* q_thread.c */, - 03E6CF691CCE0DAB00D73982 /* q_thread_inlines.c */, - 03E6CF6B1CCE0DAB00D73982 /* q_time.c */, - 03E6CF6C1CCE0DAB00D73982 /* q_transmit.c */, - 03E6CF6D1CCE0DAB00D73982 /* q_whc.c */, - 03E6CF6E1CCE0DAB00D73982 /* q_xevent.c */, - 03E6CF6F1CCE0DAB00D73982 /* q_xmsg.c */, - 03E6CF701CCE0DAB00D73982 /* sysdeps.c */, - 034CF92F1DE2FDF300DD6073 /* q_freelist.c */, - ); - path = ddsi; - sourceTree = ""; - }; - 03E6CF711CCE0DAB00D73982 /* kernel */ = { - isa = PBXGroup; - children = ( - 03E6CF721CCE0DAB00D73982 /* dds_alloc.c */, - 03E6CF731CCE0DAB00D73982 /* dds_condition.c */, - 03E6CF741CCE0DAB00D73982 /* dds_domain.c */, - 03E6CF751CCE0DAB00D73982 /* dds_entity.c */, - 03E6CF761CCE0DAB00D73982 /* dds_err.c */, - 03E6CF771CCE0DAB00D73982 /* dds_guardcond.c */, - 03E6CF781CCE0DAB00D73982 /* dds_iid.c */, - 03E6CF791CCE0DAB00D73982 /* dds_init.c */, - 03E6CF7A1CCE0DAB00D73982 /* dds_instance.c */, - 03E6CF7B1CCE0DAB00D73982 /* dds_key.c */, - 03E6CF7C1CCE0DAB00D73982 /* dds_listener.c */, - 03E6CF7D1CCE0DAB00D73982 /* dds_log.c */, - 03E6CF7E1CCE0DAB00D73982 /* dds_participant.c */, - 03E6CF7F1CCE0DAB00D73982 /* dds_publisher.c */, - 03E6CF801CCE0DAB00D73982 /* dds_qos.c */, - 03E6CF811CCE0DAB00D73982 /* dds_querycond.c */, - 03E6CF821CCE0DAB00D73982 /* dds_read.c */, - 03E6CF831CCE0DAB00D73982 /* dds_readcond.c */, - 03E6CF841CCE0DAB00D73982 /* dds_reader.c */, - 03E6CF851CCE0DAB00D73982 /* dds_rhc.c */, - 03E6CF861CCE0DAB00D73982 /* dds_status.c */, - 03E6CF871CCE0DAB00D73982 /* dds_statuscond.c */, - 03E6CF881CCE0DAB00D73982 /* dds_stream.c */, - 03E6CF891CCE0DAB00D73982 /* dds_subscriber.c */, - 03E6CF8A1CCE0DAB00D73982 /* dds_thread.c */, - 03E6CF8B1CCE0DAB00D73982 /* dds_time.c */, - 03E6CF8C1CCE0DAB00D73982 /* dds_tkmap.c */, - 03E6CF8D1CCE0DAB00D73982 /* dds_topic.c */, - 03E6CF8E1CCE0DAB00D73982 /* dds_waitset.c */, - 03E6CF8F1CCE0DAB00D73982 /* dds_write.c */, - 03E6CF901CCE0DAB00D73982 /* dds_writer.c */, - 03E6CF911CCE0DAB00D73982 /* q_osplser.c */, - ); - path = kernel; - sourceTree = ""; - }; - 03E6CF921CCE0DAB00D73982 /* os */ = { - isa = PBXGroup; - children = ( - 035877BC1DDCA45B000F61E2 /* posix */, - 03E6CF9E1CCE0DAB00D73982 /* os_atomics.c */, - 03E6CF9F1CCE0DAB00D73982 /* os_init.c */, - 03E6CFA01CCE0DAB00D73982 /* os_report.c */, - 03E6CFA11CCE0DAB00D73982 /* os_socket.c */, - 03E6CFA21CCE0DAB00D73982 /* os_sync.c */, - 03E6CFA31CCE0DAB00D73982 /* os_thread.c */, - 03E6CFA41CCE0DAB00D73982 /* os_time.c */, - 03E6CFA51CCE0DAB00D73982 /* snippets */, - 03E6CFB41CCE0DAB00D73982 /* win32 */, - ); - path = os; - sourceTree = ""; - }; - 03E6CFA51CCE0DAB00D73982 /* snippets */ = { - isa = PBXGroup; - children = ( - 03E6CFA61CCE0DAB00D73982 /* code */, - 03E6CFB21CCE0DAB00D73982 /* include */, - ); - path = snippets; - sourceTree = ""; - }; - 03E6CFA61CCE0DAB00D73982 /* code */ = { - isa = PBXGroup; - children = ( - 03E6CFA71CCE0DAB00D73982 /* os_gethostname.c */, - 03E6CFA81CCE0DAB00D73982 /* os_heap.c */, - 03E6CFA91CCE0DAB00D73982 /* os_posix_errno.c */, - 03E6CFAA1CCE0DAB00D73982 /* os_posix_process.c */, - 03E6CFAB1CCE0DAB00D73982 /* os_posix_thread.c */, - 03E6CFAC1CCE0DAB00D73982 /* os_stdlib.c */, - 03E6CFAD1CCE0DAB00D73982 /* os_stdlib_bsearch.c */, - 03E6CFAE1CCE0DAB00D73982 /* os_stdlib_strsep.c */, - 03E6CFAF1CCE0DAB00D73982 /* os_stdlib_strtod.c */, - 03E6CFB01CCE0DAB00D73982 /* os_stdlib_strtok_r.c */, - 03E6CFB11CCE0DAB00D73982 /* os_stdlib_strtol.c */, - ); - path = code; - sourceTree = ""; - }; - 03E6CFB21CCE0DAB00D73982 /* include */ = { - isa = PBXGroup; - children = ( - 03E6CFB31CCE0DAB00D73982 /* os_posix_stdlib.h */, - ); - path = include; - sourceTree = ""; - }; - 03E6CFB41CCE0DAB00D73982 /* win32 */ = { - isa = PBXGroup; - children = ( - 037D2E711CD2455A004434B2 /* os_platform_heap.c */, - 037D2E721CD2455A004434B2 /* os_platform_init.c */, - 037D2E731CD2455A004434B2 /* os_platform_socket.c */, - 037D2E741CD2455A004434B2 /* os_platform_sync.c */, - 037D2E751CD2455A004434B2 /* os_platform_thread.c */, - 037D2E761CD2455A004434B2 /* os_platform_time.c */, - ); - path = win32; - sourceTree = ""; - }; - 03E6CFC41CCE0DAB00D73982 /* util */ = { - isa = PBXGroup; - children = ( - 03E6CFC51CCE0DAB00D73982 /* ut_avl.c */, - 03E6CFC61CCE0DAB00D73982 /* ut_crc.c */, - 03E6CFC71CCE0DAB00D73982 /* ut_expand_envvars.c */, - 03E6CFC81CCE0DAB00D73982 /* ut_fibheap.c */, - 03E6CFC91CCE0DAB00D73982 /* ut_hopscotch.c */, - 03E6CFCA1CCE0DAB00D73982 /* ut_thread_pool.c */, - 03E6CFCB1CCE0DAB00D73982 /* ut_xmlparser.c */, - ); - path = util; - sourceTree = ""; - }; - 03E6CFCC1CCE0DAB00D73982 /* vdds-server */ = { - isa = PBXGroup; - children = ( - 03C96E9A1CCE5B800012F15D /* server2.c */, - 03E6CFCD1CCE0DAB00D73982 /* server.c */, - 03E6CFCE1CCE0DAB00D73982 /* server.h */, - 03E6CFCF1CCE0DAB00D73982 /* vdds-stubs.c */, - ); - indentWidth = 4; - name = "vdds-server"; - path = "../vdds-server"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 03E6CEA71CCE0CA400D73982 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 035877E21DDCA54F000F61E2 /* os_platform_stdlib.h in Headers */, - 034CF9321DE2FDF300DD6073 /* q_freelist.h in Headers */, - 035877E41DDCA54F000F61E2 /* os_platform_thread.h in Headers */, - 035877E11DDCA54F000F61E2 /* os_platform_socket.h in Headers */, - 035877E51DDCA54F000F61E2 /* os_platform.h in Headers */, - 035877E31DDCA54F000F61E2 /* os_platform_sync.h in Headers */, - 035877E01DDCA54F000F61E2 /* os_platform_public.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6CEAF1CCE0CCC00D73982 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 0335203D1CEDD22A003E7429 /* rpc-pingpong */ = { - isa = PBXNativeTarget; - buildConfigurationList = 033520441CEDD22A003E7429 /* Build configuration list for PBXNativeTarget "rpc-pingpong" */; - buildPhases = ( - 0335203E1CEDD22A003E7429 /* Sources */, - 033520411CEDD22A003E7429 /* Frameworks */, - 033520431CEDD22A003E7429 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "rpc-pingpong"; - productName = "rpc-ping"; - productReference = 033520471CEDD22A003E7429 /* rpc-pingpong */; - productType = "com.apple.product-type.tool"; - }; - 036D25831DF15EB9009A18C5 /* ddpingpong */ = { - isa = PBXNativeTarget; - buildConfigurationList = 036D258A1DF15EB9009A18C5 /* Build configuration list for PBXNativeTarget "ddpingpong" */; - buildPhases = ( - 036D25841DF15EB9009A18C5 /* Sources */, - 036D25871DF15EB9009A18C5 /* Frameworks */, - 036D25891DF15EB9009A18C5 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = ddpingpong; - productName = ping; - productReference = 036D258D1DF15EBA009A18C5 /* ddpingpong */; - productType = "com.apple.product-type.tool"; - }; - 03C96E9B1CCE5B8D0012F15D /* vdds-server2 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03C96EA11CCE5B8D0012F15D /* Build configuration list for PBXNativeTarget "vdds-server2" */; - buildPhases = ( - 03C96E9C1CCE5B8D0012F15D /* Sources */, - 03C96E9E1CCE5B8D0012F15D /* Frameworks */, - 03C96EA01CCE5B8D0012F15D /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "vdds-server2"; - productName = "vdds-server"; - productReference = 03C96EA41CCE5B8D0012F15D /* vdds-server2 */; - productType = "com.apple.product-type.tool"; - }; - 03E6CEA81CCE0CA400D73982 /* vdds */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03E6CEAA1CCE0CA400D73982 /* Build configuration list for PBXNativeTarget "vdds" */; - buildPhases = ( - 03E6CEA51CCE0CA400D73982 /* Sources */, - 03E6CEA61CCE0CA400D73982 /* Frameworks */, - 03E6CEA71CCE0CA400D73982 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = vdds; - productName = vdds; - productReference = 03E6CEA91CCE0CA400D73982 /* libvdds.dylib */; - productType = "com.apple.product-type.library.dynamic"; - }; - 03E6CEB01CCE0CCC00D73982 /* vdds-stubs */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03E6CEB21CCE0CCC00D73982 /* Build configuration list for PBXNativeTarget "vdds-stubs" */; - buildPhases = ( - 03E6CEAD1CCE0CCC00D73982 /* Sources */, - 03E6CEAE1CCE0CCC00D73982 /* Frameworks */, - 03E6CEAF1CCE0CCC00D73982 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "vdds-stubs"; - productName = "vdds-stubs"; - productReference = 03E6CEB11CCE0CCC00D73982 /* libvdds-stubs.dylib */; - productType = "com.apple.product-type.library.dynamic"; - }; - 03E6D0521CCE116900D73982 /* vdds-server */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03E6D0571CCE116900D73982 /* Build configuration list for PBXNativeTarget "vdds-server" */; - buildPhases = ( - 03E6D04F1CCE116900D73982 /* Sources */, - 03E6D0501CCE116900D73982 /* Frameworks */, - 03E6D0511CCE116900D73982 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "vdds-server"; - productName = "vdds-server"; - productReference = 03E6D0531CCE116900D73982 /* vdds-server */; - productType = "com.apple.product-type.tool"; - }; - 03E6D05F1CCE121300D73982 /* publisher */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03E6D0641CCE121300D73982 /* Build configuration list for PBXNativeTarget "publisher" */; - buildPhases = ( - 03E6D05C1CCE121300D73982 /* Sources */, - 03E6D05D1CCE121300D73982 /* Frameworks */, - 03E6D05E1CCE121300D73982 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = publisher; - productName = publisher; - productReference = 03E6D0601CCE121300D73982 /* publisher */; - productType = "com.apple.product-type.tool"; - }; - 03E6D06A1CCE121A00D73982 /* subscriber */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03E6D06F1CCE121A00D73982 /* Build configuration list for PBXNativeTarget "subscriber" */; - buildPhases = ( - 03E6D0671CCE121A00D73982 /* Sources */, - 03E6D0681CCE121A00D73982 /* Frameworks */, - 03E6D0691CCE121A00D73982 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = subscriber; - productName = subscriber; - productReference = 03E6D06B1CCE121A00D73982 /* subscriber */; - productType = "com.apple.product-type.tool"; - }; - 03E6D0751CCE121F00D73982 /* ping */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03E6D07A1CCE121F00D73982 /* Build configuration list for PBXNativeTarget "ping" */; - buildPhases = ( - 03E6D0721CCE121F00D73982 /* Sources */, - 03E6D0731CCE121F00D73982 /* Frameworks */, - 03E6D0741CCE121F00D73982 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = ping; - productName = ping; - productReference = 03E6D0761CCE121F00D73982 /* ping */; - productType = "com.apple.product-type.tool"; - }; - 03E6D0801CCE122400D73982 /* pong */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03E6D0851CCE122400D73982 /* Build configuration list for PBXNativeTarget "pong" */; - buildPhases = ( - 03E6D07D1CCE122400D73982 /* Sources */, - 03E6D07E1CCE122400D73982 /* Frameworks */, - 03E6D07F1CCE122400D73982 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = pong; - productName = pong; - productReference = 03E6D0811CCE122400D73982 /* pong */; - productType = "com.apple.product-type.tool"; - }; - 03E6D08B1CCE122A00D73982 /* rpc-publisher */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03E6D0901CCE122A00D73982 /* Build configuration list for PBXNativeTarget "rpc-publisher" */; - buildPhases = ( - 03E6D0881CCE122A00D73982 /* Sources */, - 03E6D0891CCE122A00D73982 /* Frameworks */, - 03E6D08A1CCE122A00D73982 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "rpc-publisher"; - productName = "rpc-publisher"; - productReference = 03E6D08C1CCE122A00D73982 /* rpc-publisher */; - productType = "com.apple.product-type.tool"; - }; - 03E6D0961CCE123000D73982 /* rpc-subscriber */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03E6D09B1CCE123000D73982 /* Build configuration list for PBXNativeTarget "rpc-subscriber" */; - buildPhases = ( - 03E6D0931CCE123000D73982 /* Sources */, - 03E6D0941CCE123000D73982 /* Frameworks */, - 03E6D0951CCE123000D73982 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "rpc-subscriber"; - productName = "rpc-subscriber"; - productReference = 03E6D0971CCE123000D73982 /* rpc-subscriber */; - productType = "com.apple.product-type.tool"; - }; - 03E6D0A11CCE123500D73982 /* rpc-ping */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03E6D0A61CCE123500D73982 /* Build configuration list for PBXNativeTarget "rpc-ping" */; - buildPhases = ( - 03E6D09E1CCE123500D73982 /* Sources */, - 03E6D09F1CCE123500D73982 /* Frameworks */, - 03E6D0A01CCE123500D73982 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "rpc-ping"; - productName = "rpc-ping"; - productReference = 03E6D0A21CCE123500D73982 /* rpc-ping */; - productType = "com.apple.product-type.tool"; - }; - 03E6D0AC1CCE123A00D73982 /* rpc-pong */ = { - isa = PBXNativeTarget; - buildConfigurationList = 03E6D0B11CCE123A00D73982 /* Build configuration list for PBXNativeTarget "rpc-pong" */; - buildPhases = ( - 03E6D0A91CCE123A00D73982 /* Sources */, - 03E6D0AA1CCE123A00D73982 /* Frameworks */, - 03E6D0AB1CCE123A00D73982 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "rpc-pong"; - productName = "rpc-pong"; - productReference = 03E6D0AD1CCE123A00D73982 /* rpc-pong */; - productType = "com.apple.product-type.tool"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 03E6CE961CCE0C6B00D73982 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0810; - ORGANIZATIONNAME = PrismTech; - TargetAttributes = { - 03E6CEA81CCE0CA400D73982 = { - CreatedOnToolsVersion = 7.3; - }; - 03E6CEB01CCE0CCC00D73982 = { - CreatedOnToolsVersion = 7.3; - }; - 03E6D0521CCE116900D73982 = { - CreatedOnToolsVersion = 7.3; - }; - 03E6D05F1CCE121300D73982 = { - CreatedOnToolsVersion = 7.3; - }; - 03E6D06A1CCE121A00D73982 = { - CreatedOnToolsVersion = 7.3; - }; - 03E6D0751CCE121F00D73982 = { - CreatedOnToolsVersion = 7.3; - }; - 03E6D0801CCE122400D73982 = { - CreatedOnToolsVersion = 7.3; - }; - 03E6D08B1CCE122A00D73982 = { - CreatedOnToolsVersion = 7.3; - }; - 03E6D0961CCE123000D73982 = { - CreatedOnToolsVersion = 7.3; - }; - 03E6D0A11CCE123500D73982 = { - CreatedOnToolsVersion = 7.3; - }; - 03E6D0AC1CCE123A00D73982 = { - CreatedOnToolsVersion = 7.3; - }; - }; - }; - buildConfigurationList = 03E6CE991CCE0C6B00D73982 /* Build configuration list for PBXProject "vdds-xcode" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 03E6CE951CCE0C6B00D73982; - productRefGroup = 03E6CE9F1CCE0C6B00D73982 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 03E6CEA81CCE0CA400D73982 /* vdds */, - 03E6CEB01CCE0CCC00D73982 /* vdds-stubs */, - 03E6D0521CCE116900D73982 /* vdds-server */, - 03E6D05F1CCE121300D73982 /* publisher */, - 03E6D06A1CCE121A00D73982 /* subscriber */, - 03E6D0751CCE121F00D73982 /* ping */, - 03E6D0801CCE122400D73982 /* pong */, - 03E6D08B1CCE122A00D73982 /* rpc-publisher */, - 03E6D0961CCE123000D73982 /* rpc-subscriber */, - 03E6D0A11CCE123500D73982 /* rpc-ping */, - 03E6D0AC1CCE123A00D73982 /* rpc-pong */, - 03C96E9B1CCE5B8D0012F15D /* vdds-server2 */, - 0335203D1CEDD22A003E7429 /* rpc-pingpong */, - 036D25831DF15EB9009A18C5 /* ddpingpong */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 0335203E1CEDD22A003E7429 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0335203F1CEDD22A003E7429 /* rpc-ping.c in Sources */, - 033520481CEDD242003E7429 /* rpc-pong.c in Sources */, - 033520491CEDD244003E7429 /* rpc-pingpong.c in Sources */, - 033520401CEDD22A003E7429 /* RoundTrip.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 036D25841DF15EB9009A18C5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 036D258E1DF15ECA009A18C5 /* ddpingpong.c in Sources */, - 036D25861DF15EB9009A18C5 /* RoundTrip.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03C96E9C1CCE5B8D0012F15D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03C96EA51CCE5B9F0012F15D /* server2.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6CEA51CCE0CA400D73982 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0191CCE0DED00D73982 /* os_atomics.c in Sources */, - 03E6D01A1CCE0DED00D73982 /* os_init.c in Sources */, - 03E6D01B1CCE0DED00D73982 /* os_report.c in Sources */, - 03E6D01C1CCE0DED00D73982 /* os_socket.c in Sources */, - 03E6D01D1CCE0DED00D73982 /* os_sync.c in Sources */, - 035877CE1DDCA45B000F61E2 /* os_platform_time.c in Sources */, - 03E6D01E1CCE0DED00D73982 /* os_thread.c in Sources */, - 03E6D01F1CCE0DED00D73982 /* os_time.c in Sources */, - 03E6D0291CCE0E0500D73982 /* ut_avl.c in Sources */, - 03E6D02A1CCE0E0500D73982 /* ut_crc.c in Sources */, - 03E6D02B1CCE0E0500D73982 /* ut_expand_envvars.c in Sources */, - 035877CD1DDCA45B000F61E2 /* os_platform_thread.c in Sources */, - 035877C91DDCA45B000F61E2 /* os_platform_process.c in Sources */, - 03E6D02C1CCE0E0500D73982 /* ut_fibheap.c in Sources */, - 03E6D02D1CCE0E0500D73982 /* ut_hopscotch.c in Sources */, - 03E6D02E1CCE0E0500D73982 /* ut_thread_pool.c in Sources */, - 03E6D02F1CCE0E0500D73982 /* ut_xmlparser.c in Sources */, - 03E6CFF91CCE0DE300D73982 /* dds_alloc.c in Sources */, - 03E6CFFA1CCE0DE300D73982 /* dds_condition.c in Sources */, - 03E6CFFB1CCE0DE300D73982 /* dds_domain.c in Sources */, - 03E6CFFC1CCE0DE300D73982 /* dds_entity.c in Sources */, - 03E6CFFD1CCE0DE300D73982 /* dds_err.c in Sources */, - 035877CB1DDCA45B000F61E2 /* os_platform_stdlib.c in Sources */, - 03E6CFFE1CCE0DE300D73982 /* dds_guardcond.c in Sources */, - 03E6CFFF1CCE0DE300D73982 /* dds_iid.c in Sources */, - 035877CC1DDCA45B000F61E2 /* os_platform_sync.c in Sources */, - 035877C61DDCA45B000F61E2 /* os_platform_errno.c in Sources */, - 03E6D0001CCE0DE300D73982 /* dds_init.c in Sources */, - 03E6D0011CCE0DE300D73982 /* dds_instance.c in Sources */, - 03E6D0021CCE0DE300D73982 /* dds_key.c in Sources */, - 03E6D0031CCE0DE300D73982 /* dds_listener.c in Sources */, - 03E6D0041CCE0DE300D73982 /* dds_log.c in Sources */, - 035877C81DDCA45B000F61E2 /* os_platform_init.c in Sources */, - 03E6D0051CCE0DE300D73982 /* dds_participant.c in Sources */, - 03E6D0061CCE0DE300D73982 /* dds_publisher.c in Sources */, - 03E6D0071CCE0DE300D73982 /* dds_qos.c in Sources */, - 035877CA1DDCA45B000F61E2 /* os_platform_socket.c in Sources */, - 03E6D0081CCE0DE300D73982 /* dds_querycond.c in Sources */, - 03E6D0091CCE0DE300D73982 /* dds_read.c in Sources */, - 03E6D00A1CCE0DE300D73982 /* dds_readcond.c in Sources */, - 03E6D00B1CCE0DE300D73982 /* dds_reader.c in Sources */, - 03E6D00C1CCE0DE300D73982 /* dds_rhc.c in Sources */, - 03E6D00D1CCE0DE300D73982 /* dds_status.c in Sources */, - 03E6D00E1CCE0DE300D73982 /* dds_statuscond.c in Sources */, - 03E6D00F1CCE0DE300D73982 /* dds_stream.c in Sources */, - 03E6D0101CCE0DE300D73982 /* dds_subscriber.c in Sources */, - 03E6D0111CCE0DE300D73982 /* dds_thread.c in Sources */, - 03E6D0121CCE0DE300D73982 /* dds_time.c in Sources */, - 03E6D0131CCE0DE300D73982 /* dds_tkmap.c in Sources */, - 03E6D0141CCE0DE300D73982 /* dds_topic.c in Sources */, - 03E6D0151CCE0DE300D73982 /* dds_waitset.c in Sources */, - 035877C71DDCA45B000F61E2 /* os_platform_heap.c in Sources */, - 03E6D0161CCE0DE300D73982 /* dds_write.c in Sources */, - 03E6D0171CCE0DE300D73982 /* dds_writer.c in Sources */, - 03E6D0181CCE0DE300D73982 /* q_osplser.c in Sources */, - 03E6CFD01CCE0DD400D73982 /* ddsi_ser.c in Sources */, - 03E6CFD11CCE0DD400D73982 /* ddsi_ssl.c in Sources */, - 03E6CFD21CCE0DD400D73982 /* ddsi_tcp.c in Sources */, - 03E6CFD31CCE0DD400D73982 /* ddsi_tran.c in Sources */, - 03E6CFD41CCE0DD400D73982 /* ddsi_udp.c in Sources */, - 03E6CFD51CCE0DD400D73982 /* q_addrset.c in Sources */, - 03E6CFD61CCE0DD400D73982 /* q_bitset_inlines.c in Sources */, - 03E6CFD81CCE0DD400D73982 /* q_bswap.c in Sources */, - 03E6CFD91CCE0DD400D73982 /* q_bswap_inlines.c in Sources */, - 03E6CFDB1CCE0DD400D73982 /* q_config.c in Sources */, - 034CF9311DE2FDF300DD6073 /* q_freelist.c in Sources */, - 03E6CFDC1CCE0DD400D73982 /* q_ddsi_discovery.c in Sources */, - 03E6CFDD1CCE0DD400D73982 /* q_debmon.c in Sources */, - 03E6CFDE1CCE0DD400D73982 /* q_entity.c in Sources */, - 03E6CFDF1CCE0DD400D73982 /* q_ephash.c in Sources */, - 03E6CFE01CCE0DD400D73982 /* q_gc.c in Sources */, - 03E6CFE11CCE0DD400D73982 /* q_init.c in Sources */, - 03E6CFE21CCE0DD400D73982 /* q_lat_estim.c in Sources */, - 03E6CFE31CCE0DD400D73982 /* q_lease.c in Sources */, - 03E6CFE41CCE0DD400D73982 /* q_log.c in Sources */, - 03E6CFE51CCE0DD400D73982 /* q_md5.c in Sources */, - 03E6CFE61CCE0DD400D73982 /* q_misc.c in Sources */, - 03E6CFE71CCE0DD400D73982 /* q_nwif.c in Sources */, - 03E6CFE81CCE0DD400D73982 /* q_pcap.c in Sources */, - 03E6CFE91CCE0DD400D73982 /* q_plist.c in Sources */, - 03E6CFEA1CCE0DD400D73982 /* q_qosmatch.c in Sources */, - 03E6CFEB1CCE0DD400D73982 /* q_radmin.c in Sources */, - 03E6CFEC1CCE0DD400D73982 /* q_receive.c in Sources */, - 03E6CFED1CCE0DD400D73982 /* q_security.c in Sources */, - 03E6CFEE1CCE0DD400D73982 /* q_servicelease.c in Sources */, - 03E6CFEF1CCE0DD400D73982 /* q_sockwaitset.c in Sources */, - 03E6CFF01CCE0DD400D73982 /* q_thread.c in Sources */, - 03E6CFF11CCE0DD400D73982 /* q_thread_inlines.c in Sources */, - 03E6CFF31CCE0DD400D73982 /* q_time.c in Sources */, - 03E6CFF41CCE0DD400D73982 /* q_transmit.c in Sources */, - 03E6CFF51CCE0DD400D73982 /* q_whc.c in Sources */, - 03E6CFF61CCE0DD400D73982 /* q_xevent.c in Sources */, - 03E6CFF71CCE0DD400D73982 /* q_xmsg.c in Sources */, - 03E6CFF81CCE0DD400D73982 /* sysdeps.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6CEAD1CCE0CCC00D73982 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 035877CF1DDCA477000F61E2 /* os_platform_errno.c in Sources */, - 035877D01DDCA477000F61E2 /* os_platform_heap.c in Sources */, - 035877D11DDCA477000F61E2 /* os_platform_init.c in Sources */, - 035877D21DDCA477000F61E2 /* os_platform_process.c in Sources */, - 035877D31DDCA477000F61E2 /* os_platform_socket.c in Sources */, - 035877D41DDCA477000F61E2 /* os_platform_stdlib.c in Sources */, - 035877D51DDCA477000F61E2 /* os_platform_sync.c in Sources */, - 035877D61DDCA477000F61E2 /* os_platform_thread.c in Sources */, - 035877D71DDCA477000F61E2 /* os_platform_time.c in Sources */, - 03E6D0391CCE0E6200D73982 /* os_atomics.c in Sources */, - 03E6D03A1CCE0E6200D73982 /* os_init.c in Sources */, - 03E6D03B1CCE0E6200D73982 /* os_report.c in Sources */, - 03E6D03C1CCE0E6200D73982 /* os_socket.c in Sources */, - 03E6D03D1CCE0E6200D73982 /* os_sync.c in Sources */, - 03E6D03E1CCE0E6200D73982 /* os_thread.c in Sources */, - 03E6D03F1CCE0E6200D73982 /* os_time.c in Sources */, - 03E6D0401CCE0E7000D73982 /* vdds-stubs.c in Sources */, - 03E6D0411CCE0EB700D73982 /* dds_alloc.c in Sources */, - 03E6D0421CCE0EBD00D73982 /* dds_time.c in Sources */, - 03E6D0431CCE0EC000D73982 /* dds_stream.c in Sources */, - 03E6D0441CCE0EC600D73982 /* dds_key.c in Sources */, - 03E6D0451CCE0ECB00D73982 /* dds_err.c in Sources */, - 03E6D0461CCE0ED000D73982 /* dds_qos.c in Sources */, - 03E6D0471CCE0EDE00D73982 /* q_bswap.c in Sources */, - 03E6D0481CCE0EE200D73982 /* q_bswap_inlines.c in Sources */, - 03E6D0491CCE0EE800D73982 /* q_md5.c in Sources */, - 03E6D04A1CCE0EEC00D73982 /* q_plist.c in Sources */, - 03E6D04B1CCE0EF100D73982 /* q_time.c in Sources */, - 03E6D04C1CCE104600D73982 /* q_misc.c in Sources */, - 03E6D04D1CCE104E00D73982 /* q_osplser.c in Sources */, - 034CF9331DE3043A00DD6073 /* q_freelist.c in Sources */, - 03E6D04E1CCE105600D73982 /* ddsi_ser.c in Sources */, - 035877BB1DDB0F5B000F61E2 /* sysdeps.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D04F1CCE116900D73982 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D05A1CCE11D300D73982 /* server.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D05C1CCE121300D73982 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0BC1CCE127500D73982 /* publisher.c in Sources */, - 03E6D0BD1CCE127800D73982 /* Throughput.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D0671CCE121A00D73982 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0BE1CCE127C00D73982 /* subscriber.c in Sources */, - 03E6D0BF1CCE127F00D73982 /* Throughput.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D0721CCE121F00D73982 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0C01CCE128500D73982 /* ping.c in Sources */, - 03E6D0C11CCE128700D73982 /* RoundTrip.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D07D1CCE122400D73982 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0C21CCE128D00D73982 /* pong.c in Sources */, - 03E6D0C31CCE128F00D73982 /* RoundTrip.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D0881CCE122A00D73982 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0C41CCE129C00D73982 /* rpc-publisher.c in Sources */, - 03E6D0C51CCE129F00D73982 /* Throughput.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D0931CCE123000D73982 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0C61CCE12A400D73982 /* rpc-subscriber.c in Sources */, - 03E6D0C71CCE12A600D73982 /* Throughput.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D09E1CCE123500D73982 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0C81CCE12AC00D73982 /* rpc-ping.c in Sources */, - 03E6D0C91CCE12AE00D73982 /* RoundTrip.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 03E6D0A91CCE123A00D73982 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03E6D0CA1CCE12B400D73982 /* rpc-pong.c in Sources */, - 03E6D0CB1CCE12B600D73982 /* RoundTrip.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 033520451CEDD22A003E7429 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 033520461CEDD22A003E7429 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 036D258B1DF15EB9009A18C5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 036D258C1DF15EB9009A18C5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 03C96EA21CCE5B8D0012F15D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - HEADER_SEARCH_PATHS = /usr/local/include; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - /usr/local/Cellar/libevent/2.0.22/lib, - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - USER_HEADER_SEARCH_PATHS = "../include ../examples/generated"; - }; - name = Debug; - }; - 03C96EA31CCE5B8D0012F15D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - HEADER_SEARCH_PATHS = /usr/local/include; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - /usr/local/Cellar/libevent/2.0.22/lib, - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - USER_HEADER_SEARCH_PATHS = "../include ../examples/generated"; - }; - name = Release; - }; - 03E6CEA01CCE0C6B00D73982 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DDSI_INCLUDE_NETWORK_PARTITIONS=1", - "DDSI_INCLUDE_BANDWIDTH_LIMITING=1", - "DDSI_INCLUDE_NETWORK_CHANNELS=1", - "DDSI_INCLUDE_SSM=1", - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - USER_HEADER_SEARCH_PATHS = "../include ../examples/generated"; - USE_HEADERMAP = NO; - }; - name = Debug; - }; - 03E6CEA11CCE0C6B00D73982 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - USER_HEADER_SEARCH_PATHS = "../include ../examples/generated"; - USE_HEADERMAP = NO; - }; - name = Release; - }; - 03E6CEAB1CCE0CA400D73982 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - EXECUTABLE_PREFIX = lib; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 03E6CEAC1CCE0CA400D73982 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - EXECUTABLE_PREFIX = lib; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 03E6CEB31CCE0CCC00D73982 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - EXECUTABLE_PREFIX = lib; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 03E6CEB41CCE0CCC00D73982 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - EXECUTABLE_PREFIX = lib; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 03E6D0581CCE116900D73982 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 03E6D0591CCE116900D73982 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 03E6D0651CCE121300D73982 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 03E6D0661CCE121300D73982 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 03E6D0701CCE121A00D73982 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 03E6D0711CCE121A00D73982 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 03E6D07B1CCE121F00D73982 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 03E6D07C1CCE121F00D73982 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 03E6D0861CCE122400D73982 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 03E6D0871CCE122400D73982 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 03E6D0911CCE122A00D73982 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 03E6D0921CCE122A00D73982 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 03E6D09C1CCE123000D73982 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 03E6D09D1CCE123000D73982 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 03E6D0A71CCE123500D73982 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 03E6D0A81CCE123500D73982 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 03E6D0B21CCE123A00D73982 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 03E6D0B31CCE123A00D73982 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 033520441CEDD22A003E7429 /* Build configuration list for PBXNativeTarget "rpc-pingpong" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 033520451CEDD22A003E7429 /* Debug */, - 033520461CEDD22A003E7429 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 036D258A1DF15EB9009A18C5 /* Build configuration list for PBXNativeTarget "ddpingpong" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 036D258B1DF15EB9009A18C5 /* Debug */, - 036D258C1DF15EB9009A18C5 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03C96EA11CCE5B8D0012F15D /* Build configuration list for PBXNativeTarget "vdds-server2" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03C96EA21CCE5B8D0012F15D /* Debug */, - 03C96EA31CCE5B8D0012F15D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03E6CE991CCE0C6B00D73982 /* Build configuration list for PBXProject "vdds-xcode" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03E6CEA01CCE0C6B00D73982 /* Debug */, - 03E6CEA11CCE0C6B00D73982 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03E6CEAA1CCE0CA400D73982 /* Build configuration list for PBXNativeTarget "vdds" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03E6CEAB1CCE0CA400D73982 /* Debug */, - 03E6CEAC1CCE0CA400D73982 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03E6CEB21CCE0CCC00D73982 /* Build configuration list for PBXNativeTarget "vdds-stubs" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03E6CEB31CCE0CCC00D73982 /* Debug */, - 03E6CEB41CCE0CCC00D73982 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03E6D0571CCE116900D73982 /* Build configuration list for PBXNativeTarget "vdds-server" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03E6D0581CCE116900D73982 /* Debug */, - 03E6D0591CCE116900D73982 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03E6D0641CCE121300D73982 /* Build configuration list for PBXNativeTarget "publisher" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03E6D0651CCE121300D73982 /* Debug */, - 03E6D0661CCE121300D73982 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03E6D06F1CCE121A00D73982 /* Build configuration list for PBXNativeTarget "subscriber" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03E6D0701CCE121A00D73982 /* Debug */, - 03E6D0711CCE121A00D73982 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03E6D07A1CCE121F00D73982 /* Build configuration list for PBXNativeTarget "ping" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03E6D07B1CCE121F00D73982 /* Debug */, - 03E6D07C1CCE121F00D73982 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03E6D0851CCE122400D73982 /* Build configuration list for PBXNativeTarget "pong" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03E6D0861CCE122400D73982 /* Debug */, - 03E6D0871CCE122400D73982 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03E6D0901CCE122A00D73982 /* Build configuration list for PBXNativeTarget "rpc-publisher" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03E6D0911CCE122A00D73982 /* Debug */, - 03E6D0921CCE122A00D73982 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03E6D09B1CCE123000D73982 /* Build configuration list for PBXNativeTarget "rpc-subscriber" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03E6D09C1CCE123000D73982 /* Debug */, - 03E6D09D1CCE123000D73982 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03E6D0A61CCE123500D73982 /* Build configuration list for PBXNativeTarget "rpc-ping" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03E6D0A71CCE123500D73982 /* Debug */, - 03E6D0A81CCE123500D73982 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 03E6D0B11CCE123A00D73982 /* Build configuration list for PBXNativeTarget "rpc-pong" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 03E6D0B21CCE123A00D73982 /* Debug */, - 03E6D0B31CCE123A00D73982 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 03E6CE961CCE0C6B00D73982 /* Project object */; -} diff --git a/vdds-xcode/vdds-xcode.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/vdds-xcode/vdds-xcode.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 3331f11..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/ddpingpong.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/ddpingpong.xcscheme deleted file mode 100644 index f3eaf63..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/ddpingpong.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/ping.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/ping.xcscheme deleted file mode 100644 index 16d61a9..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/ping.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/pong.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/pong.xcscheme deleted file mode 100644 index 3069d2a..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/pong.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/publisher.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/publisher.xcscheme deleted file mode 100644 index 750882b..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/publisher.xcscheme +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-ping.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-ping.xcscheme deleted file mode 100644 index 644e38e..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-ping.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-pingpong.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-pingpong.xcscheme deleted file mode 100644 index f0357df..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-pingpong.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-pong.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-pong.xcscheme deleted file mode 100644 index 2a6d66f..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-pong.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-publisher.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-publisher.xcscheme deleted file mode 100644 index d89ca2a..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-publisher.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-subscriber.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-subscriber.xcscheme deleted file mode 100644 index 8c230d3..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/rpc-subscriber.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/subscriber.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/subscriber.xcscheme deleted file mode 100644 index d032a34..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/subscriber.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-server.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-server.xcscheme deleted file mode 100644 index 6e356bb..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-server.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-server2.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-server2.xcscheme deleted file mode 100644 index 94057cb..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-server2.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-stubs.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-stubs.xcscheme deleted file mode 100644 index 627b501..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-stubs.xcscheme +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-xcode.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-xcode.xcscheme deleted file mode 100644 index c773778..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds-xcode.xcscheme +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds.xcscheme b/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds.xcscheme deleted file mode 100644 index cc1b1a5..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcshareddata/xcschemes/vdds.xcscheme +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vdds-xcode/vdds-xcode.xcodeproj/xcuserdata/erik.xcuserdatad/xcschemes/xcschememanagement.plist b/vdds-xcode/vdds-xcode.xcodeproj/xcuserdata/erik.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 286b5c2..0000000 --- a/vdds-xcode/vdds-xcode.xcodeproj/xcuserdata/erik.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,162 +0,0 @@ - - - - - SchemeUserState - - ddpingpong.xcscheme_^#shared#^_ - - orderHint - 14 - - ping.xcscheme_^#shared#^_ - - orderHint - 6 - - pong.xcscheme_^#shared#^_ - - orderHint - 7 - - publisher.xcscheme_^#shared#^_ - - orderHint - 4 - - rpc-ping.xcscheme_^#shared#^_ - - orderHint - 10 - - rpc-pingpong.xcscheme_^#shared#^_ - - orderHint - 13 - - rpc-pong.xcscheme_^#shared#^_ - - orderHint - 11 - - rpc-publisher.xcscheme_^#shared#^_ - - orderHint - 8 - - rpc-subscriber.xcscheme_^#shared#^_ - - orderHint - 9 - - subscriber.xcscheme_^#shared#^_ - - orderHint - 5 - - vdds-server.xcscheme_^#shared#^_ - - orderHint - 3 - - vdds-server2.xcscheme_^#shared#^_ - - orderHint - 12 - - vdds-stubs.xcscheme_^#shared#^_ - - orderHint - 2 - - vdds-xcode.xcscheme_^#shared#^_ - - orderHint - 0 - - vdds.xcscheme_^#shared#^_ - - orderHint - 1 - - - SuppressBuildableAutocreation - - 0335203D1CEDD22A003E7429 - - primary - - - 036D25831DF15EB9009A18C5 - - primary - - - 03C96E9B1CCE5B8D0012F15D - - primary - - - 03E6CE9D1CCE0C6B00D73982 - - primary - - - 03E6CEA81CCE0CA400D73982 - - primary - - - 03E6CEB01CCE0CCC00D73982 - - primary - - - 03E6D0521CCE116900D73982 - - primary - - - 03E6D05F1CCE121300D73982 - - primary - - - 03E6D06A1CCE121A00D73982 - - primary - - - 03E6D0751CCE121F00D73982 - - primary - - - 03E6D0801CCE122400D73982 - - primary - - - 03E6D08B1CCE122A00D73982 - - primary - - - 03E6D0961CCE123000D73982 - - primary - - - 03E6D0A11CCE123500D73982 - - primary - - - 03E6D0AC1CCE123A00D73982 - - primary - - - - - From 4e805597631ed0dcbdc0eecfe9d532cb75180ae7 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 16 Jul 2019 16:50:02 +0200 Subject: [PATCH 128/178] Improve multicast related defaults * use multicast only for participant discovery if using a WiFi network * default to using unicast for retransmits Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_config.h | 3 +- src/core/ddsi/include/dds/ddsi/q_nwif.h | 1 + src/core/ddsi/src/q_config.c | 31 ++++-- src/core/ddsi/src/q_init.c | 17 ++++ src/core/ddsi/src/q_nwif.c | 13 +++ src/ddsrt/include/dds/ddsrt/ifaddrs.h | 7 ++ src/ddsrt/src/ifaddrs/lwip/ifaddrs.c | 1 + src/ddsrt/src/ifaddrs/posix/ifaddrs.c | 111 +++++++++++++++++++++- src/ddsrt/src/ifaddrs/windows/ifaddrs.c | 16 ++++ 9 files changed, 190 insertions(+), 10 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index 0e3e2de..ae718e1 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -184,7 +184,7 @@ struct prune_deleted_ppant { int enforce_delay; }; -/* allow multicast bits: */ +/* allow multicast bits (default depends on network type): */ #define AMC_FALSE 0u #define AMC_SPDP 1u #define AMC_ASM 2u @@ -194,6 +194,7 @@ struct prune_deleted_ppant { #else #define AMC_TRUE (AMC_SPDP | AMC_ASM) #endif +#define AMC_DEFAULT 0x80000000u /* FIXME: this should be fully dynamic ... but this is easier for a quick hack */ enum transport_selector { diff --git a/src/core/ddsi/include/dds/ddsi/q_nwif.h b/src/core/ddsi/include/dds/ddsi/q_nwif.h index 5fa789b..5ca0c38 100644 --- a/src/core/ddsi/include/dds/ddsi/q_nwif.h +++ b/src/core/ddsi/include/dds/ddsi/q_nwif.h @@ -28,6 +28,7 @@ struct nn_interface { nn_locator_t netmask; uint32_t if_index; unsigned mc_capable: 1; + unsigned mc_flaky: 1; unsigned point_to_point: 1; char *name; }; diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 99b697c..88dc26b 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -234,15 +234,16 @@ static const struct cfgelem general_cfgelems[] = { BLURB("

    This element allows explicitly overruling the network address DDSI2E advertises in the discovery protocol, which by default is the address of the preferred network interface (General/NetworkInterfaceAddress), to allow DDSI2E to communicate across a Network Address Translation (NAT) device.

    ") }, { LEAF("ExternalNetworkMask"), 1, "0.0.0.0", ABSOFF(externalMaskString), 0, uf_string, ff_free, pf_string, BLURB("

    This element specifies the network mask of the external network address. This element is relevant only when an external network address (General/ExternalNetworkAddress) is explicitly configured. In this case locators received via the discovery protocol that are within the same external subnet (as defined by this mask) will be translated to an internal address by replacing the network portion of the external address with the corresponding portion of the preferred network interface address. This option is IPv4-only.

    ") }, - { LEAF("AllowMulticast"), 1, "true", ABSOFF(allowMulticast), 0, uf_allow_multicast, 0, pf_allow_multicast, + { LEAF("AllowMulticast"), 1, "default", ABSOFF(allowMulticast), 0, uf_allow_multicast, 0, pf_allow_multicast, BLURB("

    This element controls whether DDSI2E uses multicasts for data traffic.

    \n\ -

    It is a comma-separated list of some of the following keywords: \"spdp\", \"asm\", \"ssm\", or either of \"false\" or \"true\".

    \n\ +

    It is a comma-separated list of some of the following keywords: \"spdp\", \"asm\", \"ssm\", or either of \"false\" or \"true\", or \"default\".

    \n\
      \n\
    • spdp: enables the use of ASM (any-source multicast) for participant discovery, joining the multicast group on the discovery socket, transmitting SPDP messages to this group, but never advertising nor using any multicast address in any discovery message, thus forcing unicast communications for all endpoint discovery and user data.
    • \n\
    • asm: enables the use of ASM for all traffic, including receiving SPDP but not transmitting SPDP messages via multicast
    • \n\
    • ssm: enables the use of SSM (source-specific multicast) for all non-SPDP traffic (if supported)
    • \n\
    \n\ -

    When set to \"false\" all multicasting is disabled. The default, \"true\" enables full use of multicasts. Listening for multicasts can be controlled by General/MulticastRecvNetworkInterfaceAddresses.

    ") }, +

    When set to \"false\" all multicasting is disabled. The default, \"true\" enables full use of multicasts. Listening for multicasts can be controlled by General/MulticastRecvNetworkInterfaceAddresses.

    \n\ +

    \"default\" maps on spdp if the network is a WiFi network, on true if it is a wired network

    ") }, { LEAF("PreferMulticast"), 1, "false", ABSOFF(prefer_multicast), 0, uf_boolean, 0, pf_boolean, BLURB("

    When false (default) Cyclone DDS uses unicast for data whenever there a single unicast suffices. Setting this to true makes it prefer multicasting data, falling back to unicast only when no multicast address is available.

    ") }, { LEAF("MulticastTimeToLive"), 1, "32", ABSOFF(multicast_ttl), 0, uf_natint_255, 0, pf_int, @@ -532,12 +533,12 @@ static const struct cfgelem unsupp_cfgelems[] = { BLURB("

    This elements configures the maximum number of DCPS domain participants this DDSI2E instance is willing to service. 0 is unlimited.

    ") }, { LEAF("AccelerateRexmitBlockSize"), 1, "0", ABSOFF(accelerate_rexmit_block_size), 0, uf_uint, 0, pf_uint, BLURB("

    Proxy readers that are assumed to sill be retrieving historical data get this many samples retransmitted when they NACK something, even if some of these samples have sequence numbers outside the set covered by the NACK.

    ") }, - { LEAF("RetransmitMerging"), 1, "adaptive", ABSOFF(retransmit_merging), 0, uf_retransmit_merging, 0, pf_retransmit_merging, + { LEAF("RetransmitMerging"), 1, "never", ABSOFF(retransmit_merging), 0, uf_retransmit_merging, 0, pf_retransmit_merging, BLURB("

    This elements controls the addressing and timing of retransmits. Possible values are:

    \n\
    • never: retransmit only to the NACK-ing reader;
    • \n \
    • adaptive: attempt to combine retransmits needed for reliability, but send historical (transient-local) data to the requesting reader only;
    • \n\
    • always: do not distinguish between different causes, always try to merge.
    \n\ -

    The default is adaptive. See also Internal/RetransmitMergingPeriod.

    ") }, +

    The default is never. See also Internal/RetransmitMergingPeriod.

    ") }, { LEAF("RetransmitMergingPeriod"), 1, "5 ms", ABSOFF(retransmit_merging_period), 0, uf_duration_us_1s, 0, pf_duration, BLURB("

    This setting determines the size of the time window in which a NACK of some sample is ignored because a retransmit of that sample has been multicasted too recently. This setting has no effect on unicasted retransmits.

    \n\

    See also Internal/RetransmitMerging.

    ") }, @@ -1760,13 +1761,29 @@ static const uint32_t allow_multicast_codes[] = { AMC_FALSE, AMC_SPDP, AMC_ASM, static int uf_allow_multicast (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { uint32_t * const elem = cfg_address (cfgst, parent, cfgelem); - return do_uint32_bitset (cfgst, elem, allow_multicast_names, allow_multicast_codes, value); + if (ddsrt_strcasecmp (value, "default") == 0) + { + *elem = AMC_DEFAULT; + return 1; + } + else + { + *elem = 0; + return do_uint32_bitset (cfgst, elem, allow_multicast_names, allow_multicast_codes, value); + } } static void pf_allow_multicast(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) { uint32_t *p = cfg_address (cfgst, parent, cfgelem); - do_print_uint32_bitset (cfgst, *p, sizeof (allow_multicast_codes) / sizeof (*allow_multicast_codes), allow_multicast_names, allow_multicast_codes, sources, ""); + if (*p == AMC_DEFAULT) + { + cfg_logelem (cfgst, sources, "default"); + } + else + { + do_print_uint32_bitset (cfgst, *p, sizeof (allow_multicast_codes) / sizeof (*allow_multicast_codes), allow_multicast_names, allow_multicast_codes, sources, ""); + } } static int uf_maybe_int32 (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 9832ab2..38b6e9c 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -936,7 +936,24 @@ int rtps_init (void) config.participantIndex = PARTICIPANT_INDEX_AUTO; mc_available = false; } + else if (config.allowMulticast & AMC_DEFAULT) + { + /* default is dependent on network interface type: if multicast is believed to be flaky, + use multicast only for SPDP packets */ + assert ((config.allowMulticast & ~AMC_DEFAULT) == 0); + if (gv.interfaces[gv.selected_interface].mc_flaky) + { + config.allowMulticast = AMC_SPDP; + DDS_LOG(DDS_LC_CONFIG, "presumed flaky multicast, use for SPDP only\n"); + } + else + { + DDS_LOG(DDS_LC_CONFIG, "presumed robust multicast support, use for everything\n"); + config.allowMulticast = AMC_TRUE; + } + } } + assert ((config.allowMulticast & AMC_DEFAULT) == 0); if (set_recvips () < 0) goto err_set_recvips; if (set_spdp_address () < 0) diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index 87b2acd..a6a758e 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -485,6 +485,18 @@ int find_own_ip (const char *requested_address) continue; } + switch (ifa->type) + { + case DDSRT_IFTYPE_WIFI: + DDS_LOG(DDS_LC_CONFIG, " wireless"); + break; + case DDSRT_IFTYPE_WIRED: + DDS_LOG(DDS_LC_CONFIG, " wired"); + break; + case DDSRT_IFTYPE_UNKNOWN: + break; + } + #if defined(__linux) && !LWIP_SOCKET if (ifa->addr->sa_family == AF_PACKET) { @@ -571,6 +583,7 @@ int find_own_ip (const char *requested_address) memset(&gv.interfaces[gv.n_interfaces].netmask.address, 0, sizeof(gv.interfaces[gv.n_interfaces].netmask.address)); } gv.interfaces[gv.n_interfaces].mc_capable = ((ifa->flags & IFF_MULTICAST) != 0); + gv.interfaces[gv.n_interfaces].mc_flaky = ((ifa->type == DDSRT_IFTYPE_WIFI) != 0); gv.interfaces[gv.n_interfaces].point_to_point = ((ifa->flags & IFF_POINTOPOINT) != 0); gv.interfaces[gv.n_interfaces].if_index = ifa->index; gv.interfaces[gv.n_interfaces].name = ddsrt_strdup (if_name); diff --git a/src/ddsrt/include/dds/ddsrt/ifaddrs.h b/src/ddsrt/include/dds/ddsrt/ifaddrs.h index 389356e..3eea634 100644 --- a/src/ddsrt/include/dds/ddsrt/ifaddrs.h +++ b/src/ddsrt/include/dds/ddsrt/ifaddrs.h @@ -18,11 +18,18 @@ extern "C" { #endif +enum ddsrt_iftype { + DDSRT_IFTYPE_UNKNOWN, + DDSRT_IFTYPE_WIRED, + DDSRT_IFTYPE_WIFI +}; + struct ddsrt_ifaddrs { struct ddsrt_ifaddrs *next; char *name; uint32_t index; uint32_t flags; + enum ddsrt_iftype type; struct sockaddr *addr; struct sockaddr *netmask; struct sockaddr *broadaddr; diff --git a/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c b/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c index 65985f5..68b4401 100644 --- a/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c +++ b/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c @@ -95,6 +95,7 @@ copyaddr( } else { ifa->flags = getflags(netif, addr); ifa->index = netif->num; + ifa->type = DDSRT_IFTYPE_UNKNOWN; if (IP_IS_V4(addr)) { static const size_t sz = sizeof(struct sockaddr_in); diff --git a/src/ddsrt/src/ifaddrs/posix/ifaddrs.c b/src/ddsrt/src/ifaddrs/posix/ifaddrs.c index 208c4e0..8bf8f52 100644 --- a/src/ddsrt/src/ifaddrs/posix/ifaddrs.c +++ b/src/ddsrt/src/ifaddrs/posix/ifaddrs.c @@ -21,8 +21,113 @@ extern const int *const os_supp_afs; +#if defined __linux +#include + +static enum ddsrt_iftype guess_iftype (const struct ifaddrs *sys_ifa) +{ + FILE *fp; + char ifnam[IFNAMSIZ + 1]; /* not sure whether IFNAMSIZ includes a terminating 0, can't be bothered */ + int c; + size_t np; + enum ddsrt_iftype type = DDSRT_IFTYPE_UNKNOWN; + if ((fp = fopen ("/proc/net/wireless", "r")) == NULL) + return type; + /* expected format: + :Inter-| sta-| Quality | Discarded packets | Missed | WE + : face | tus | link level noise | nwid crypt frag retry misc | beacon | 22 + : wlan0: 0000 67. -43. -256 0 0 0 0 0 0 + (where : denotes the start of the line) + + SKIP_HEADER_1 skips up to and including the first newline; then SKIP_TO_EOL skips + up to and including the second newline, so the first line that gets interpreted is + the third. + */ + enum { SKIP_HEADER_1, SKIP_WHITE, READ_NAME, SKIP_TO_EOL } state = SKIP_HEADER_1; + np = 0; + while (type != DDSRT_IFTYPE_WIFI && (c = fgetc (fp)) != EOF) { + switch (state) { + case SKIP_HEADER_1: + if (c == '\n') { + state = SKIP_TO_EOL; + } + break; + case SKIP_WHITE: + if (c != ' ' && c != '\t') { + ifnam[np++] = (char) c; + state = READ_NAME; + } + break; + case READ_NAME: + if (c == ':') { + ifnam[np] = 0; + if (strcmp (ifnam, sys_ifa->ifa_name) == 0) + type = DDSRT_IFTYPE_WIFI; + state = SKIP_TO_EOL; + np = 0; + } else if (np < sizeof (ifnam) - 1) { + ifnam[np++] = (char) c; + } + break; + case SKIP_TO_EOL: + if (c == '\n') { + state = SKIP_WHITE; + } + break; + } + } + fclose (fp); + return type; +} +#elif defined __APPLE__ /* probably works for all BSDs */ +#include +#include +#include +#include + +static enum ddsrt_iftype guess_iftype (const struct ifaddrs *sys_ifa) +{ + int sock; + if ((sock = socket (sys_ifa->ifa_addr->sa_family, SOCK_DGRAM, 0)) == -1) + return DDSRT_IFTYPE_UNKNOWN; + + struct ifmediareq ifmr; + enum ddsrt_iftype type; + memset (&ifmr, 0, sizeof (ifmr)); + ddsrt_strlcpy (ifmr.ifm_name, sys_ifa->ifa_name, sizeof (ifmr.ifm_name)); + if (ioctl (sock, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) + { + type = DDSRT_IFTYPE_UNKNOWN; + } + else + { + switch (IFM_TYPE (ifmr.ifm_active)) + { + case IFM_ETHER: + case IFM_TOKEN: + case IFM_FDDI: + type = DDSRT_IFTYPE_WIRED; + break; + case IFM_IEEE80211: + type = DDSRT_IFTYPE_WIFI; + break; + default: + type = DDSRT_IFTYPE_UNKNOWN; + break; + } + } + close (sock); + return type; +} +#else +static enum ddsrt_iftype guess_iftype (const struct ifaddrs *sys_ifa) +{ + return DDSRT_IFTYPE_UNKNOWN; +} +#endif + static dds_return_t -copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) +copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa, enum ddsrt_iftype type) { dds_return_t err = DDS_RETCODE_OK; ddsrt_ifaddrs_t *ifa; @@ -37,6 +142,7 @@ copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) err = DDS_RETCODE_OUT_OF_RESOURCES; } else { ifa->index = if_nametoindex(sys_ifa->ifa_name); + ifa->type = type; ifa->flags = sys_ifa->ifa_flags; if ((ifa->name = ddsrt_strdup(sys_ifa->ifa_name)) == NULL || (ifa->addr = ddsrt_memdup(sys_ifa->ifa_addr, sz)) == NULL || @@ -109,7 +215,8 @@ ddsrt_getifaddrs( } if (use) { - err = copyaddr(&ifa_next, sys_ifa); + enum ddsrt_iftype type = guess_iftype (sys_ifa); + err = copyaddr(&ifa_next, sys_ifa, type); if (err == DDS_RETCODE_OK) { if (ifa == NULL) { ifa = ifa_root = ifa_next; diff --git a/src/ddsrt/src/ifaddrs/windows/ifaddrs.c b/src/ddsrt/src/ifaddrs/windows/ifaddrs.c index 7dcb8aa..7c5045c 100644 --- a/src/ddsrt/src/ifaddrs/windows/ifaddrs.c +++ b/src/ddsrt/src/ifaddrs/windows/ifaddrs.c @@ -152,6 +152,21 @@ getflags(const PIP_ADAPTER_ADDRESSES iface) return flags; } +static enum ddsrt_iftype +guess_iftype (const PIP_ADAPTER_ADDRESSES iface) +{ + switch (iface->IfType) { + case IF_TYPE_IEEE80211: + return DDSRT_IFTYPE_WIFI; + case IF_TYPE_ETHERNET_CSMACD: + case IF_TYPE_IEEE1394: + case IF_TYPE_ISO88025_TOKENRING: + return DDSRT_IFTYPE_WIRED; + default: + return DDSRT_IFTYPE_UNKNOWN; + } +} + static int copyaddr( ddsrt_ifaddrs_t **ifap, @@ -175,6 +190,7 @@ copyaddr( err = DDS_RETCODE_OUT_OF_RESOURCES; } else { ifa->flags = getflags(iface); + ifa->type = guess_iftype(iface); ifa->addr = ddsrt_memdup(sa, sz); (void)ddsrt_asprintf(&ifa->name, "%wS", iface->FriendlyName); if (ifa->addr == NULL || ifa->name == NULL) { From 9cf4b97f1ad23a8525db678a68b7f7f89605c9dc Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 26 Jul 2019 09:43:53 +0200 Subject: [PATCH 129/178] Reorganize repository * Move the project top-level CMakeLists.txt to the root of the project; this allows building Cyclone as part of ROS2 without any special tricks; * Clean up the build options: ENABLE_SSL: whether to check for and include OpenSSL support if a library can be found (default = ON); this used to be called DDSC_ENABLE_OPENSSL, the old name is deprecated but still works BUILD_DOCS: whether to build docs (default = OFF) BUILD_TESTING: whether to build test (default = OFF) * Collect all documentation into top-level "docs" directory; * Move the examples to the top-level directory; * Remove the unused and somewhat misleading pseudo-default cyclonedds.xml; * Remove unused cmake files Signed-off-by: Erik Boasson --- .travis.yml | 2 +- CMakeLists.txt | 214 ++++++++++++++++ README.md | 97 ++++++-- appveyor.yml | 2 +- .../Modules}/AnalyzeBuild.cmake | 0 .../modules => cmake/Modules}/CUnit.cmake | 0 .../Modules}/CUnit/include/CUnit/Test.h | 0 .../Modules}/CUnit/include/CUnit/Theory.h | 0 .../Modules}/CUnit/src/main.c.in | 0 .../modules => cmake/Modules}/FindCUnit.cmake | 0 .../modules => cmake/Modules}/FindMaven.cmake | 0 .../Modules}/FindOpenSSL.cmake | 0 .../Modules}/FindSphinx.cmake | 0 .../Modules}/GenerateDummyExportHeader.cmake | 0 .../modules => cmake/Modules}/Glob.cmake | 0 .../modules => cmake/Modules}/Packaging.cmake | 35 +-- .../Modules}/Packaging/PackageConfig.cmake.in | 0 docs/CMakeLists.txt | 49 ++++ {notes => docs/dev}/data path - rbuf.svg | 0 {notes => docs/dev}/data path - receive.svg | 0 {notes => docs/dev}/data path - transmit.svg | 0 {notes => docs/dev}/data path.graffle | 0 docs/manual/CMakeLists.txt | 122 ++++++++++ {src/docs => docs/manual}/Doxyfile.in | 4 +- .../GettingStartedGuide/helloworld.rst | 2 +- .../helloworld_indepth.rst | 6 +- .../manual}/GettingStartedGuide/index.rst | 0 .../GettingStartedGuide/installation.rst | 0 .../GettingStartedGuide/next_steps.rst | 0 .../manual}/GettingStartedGuide/uninstall.rst | 0 .../manual}/_static/BuildSchema.odg | Bin .../manual}/_static/pictures/BuildSchema.png | Bin .../pictures/HelloworldPublisherWindows.png | Bin .../pictures/HelloworldSubscriberWindows.png | Bin .../manual}/_static/pictures/VORTEX_LOGO.png | Bin .../_static/pictures/settings-icon.png | Bin {src/docs => docs/manual}/conf.py.in | 0 {src/docs => docs/manual}/config.rst | 0 {src/docs => docs/manual}/ddsc.rst | 0 {src/docs => docs/manual}/index.rst | 0 examples/CMakeLists.txt | 105 ++++++++ {src/examples => examples}/examples.rst | 0 .../helloworld/CMakeLists.export | 0 .../helloworld/CMakeLists.txt | 0 .../helloworld/HelloWorld.sln | 0 .../helloworld/HelloWorldData.idl | 0 .../examples => examples}/helloworld/Makefile | 0 .../helloworld/publisher.c | 0 .../helloworld/readme.rst | 0 .../helloworld/subscriber.c | 0 .../helloworld/vs/HelloWorldPublisher.vcxproj | 0 .../vs/HelloWorldSubscriber.vcxproj | 0 .../helloworld/vs/HelloWorldType.vcxproj | 0 .../helloworld/vs/directories.props | 0 {performance => examples/perfscript}/ethload | 0 .../perfscript}/quick-microbenchmark | 0 .../perfscript}/throughput-fanout-test | 0 .../perfscript}/throughput-test | 0 .../perfscript}/throughput-test-extract | 0 .../perfscript}/throughput-test-plot | 0 .../roundtrip/CMakeLists.txt | 0 .../roundtrip/RoundTrip.idl | 0 {src/examples => examples}/roundtrip/ping.c | 0 {src/examples => examples}/roundtrip/pong.c | 0 .../roundtrip/readme.rst | 0 {src/examples => examples}/sphinx-conf.py.in | 2 +- .../throughput/CMakeLists.txt | 0 .../throughput/Throughput.idl | 0 .../throughput/publisher.c | 0 .../throughput/readme.rst | 0 .../throughput/subscriber.c | 0 src/CMakeLists.txt | 210 +--------------- src/cmake/CoverageSettings.cmake.in | 31 --- src/cmake/launch-c.bat.in | 26 -- src/cmake/launch-c.in | 40 --- src/cmake/launch-cxx.bat.in | 26 -- src/cmake/launch-cxx.in | 40 --- src/cmake/modules/Coverage.cmake | 50 ---- src/cmake/modules/Packaging/banner.bmp | Bin 85894 -> 0 bytes src/cmake/modules/Packaging/dialog.png | Bin 20635 -> 0 bytes src/cmake/modules/Packaging/examples.xml | 228 ------------------ src/cmake/modules/Packaging/vortex.ico | Bin 30321 -> 0 bytes src/cmake/modules/Platform/VxWorks6.cmake | 213 ---------------- src/cmake/scripts/CoverageConvenience.cmake | 134 ---------- src/cmake/scripts/CoveragePostCobertura.cmake | 52 ---- src/cmake/scripts/CoveragePostHtml.cmake | 71 ------ src/cmake/scripts/CoveragePreCobertura.cmake | 30 --- src/cmake/scripts/CoveragePreHtml.cmake | 52 ---- src/cmake/vxworks.example.cmake | 33 --- src/core/CMakeLists.txt | 22 +- src/core/xtests/cdrtest/CMakeLists.txt | 14 +- src/docs/CMakeLists.txt | 218 ----------------- src/etc/CMakeLists.txt | 20 -- src/etc/cmake/default.xml.in | 29 --- src/examples/CMakeLists.txt | 128 ---------- .../eclipse/cyclonedds/templates/c/banner.st | 1 - .../eclipse/cyclonedds/templates/h/banner.st | 1 - src/mpt/tests/qos/CMakeLists.txt | 2 +- src/scripts/CMakeLists.txt | 21 -- src/scripts/cmake/vdds_install_examples.in | 199 --------------- src/tools/CMakeLists.txt | 19 +- src/tools/ddsperf/CMakeLists.txt | 2 + 102 files changed, 627 insertions(+), 1925 deletions(-) create mode 100644 CMakeLists.txt rename {src/cmake/modules => cmake/Modules}/AnalyzeBuild.cmake (100%) rename {src/cmake/modules => cmake/Modules}/CUnit.cmake (100%) rename {src/cmake/modules => cmake/Modules}/CUnit/include/CUnit/Test.h (100%) rename {src/cmake/modules => cmake/Modules}/CUnit/include/CUnit/Theory.h (100%) rename {src/cmake/modules => cmake/Modules}/CUnit/src/main.c.in (100%) rename {src/cmake/modules => cmake/Modules}/FindCUnit.cmake (100%) rename {src/cmake/modules => cmake/Modules}/FindMaven.cmake (100%) rename {src/cmake/modules => cmake/Modules}/FindOpenSSL.cmake (100%) rename {src/cmake/modules => cmake/Modules}/FindSphinx.cmake (100%) rename {src/cmake/modules => cmake/Modules}/GenerateDummyExportHeader.cmake (100%) rename {src/cmake/modules => cmake/Modules}/Glob.cmake (100%) rename {src/cmake/modules => cmake/Modules}/Packaging.cmake (77%) rename {src/cmake/modules => cmake/Modules}/Packaging/PackageConfig.cmake.in (100%) create mode 100644 docs/CMakeLists.txt rename {notes => docs/dev}/data path - rbuf.svg (100%) rename {notes => docs/dev}/data path - receive.svg (100%) rename {notes => docs/dev}/data path - transmit.svg (100%) rename {notes => docs/dev}/data path.graffle (100%) create mode 100644 docs/manual/CMakeLists.txt rename {src/docs => docs/manual}/Doxyfile.in (99%) rename {src/docs => docs/manual}/GettingStartedGuide/helloworld.rst (99%) rename {src/docs => docs/manual}/GettingStartedGuide/helloworld_indepth.rst (98%) rename {src/docs => docs/manual}/GettingStartedGuide/index.rst (100%) rename {src/docs => docs/manual}/GettingStartedGuide/installation.rst (100%) rename {src/docs => docs/manual}/GettingStartedGuide/next_steps.rst (100%) rename {src/docs => docs/manual}/GettingStartedGuide/uninstall.rst (100%) rename {src/docs => docs/manual}/_static/BuildSchema.odg (100%) rename {src/docs => docs/manual}/_static/pictures/BuildSchema.png (100%) rename {src/docs => docs/manual}/_static/pictures/HelloworldPublisherWindows.png (100%) rename {src/docs => docs/manual}/_static/pictures/HelloworldSubscriberWindows.png (100%) rename {src/docs => docs/manual}/_static/pictures/VORTEX_LOGO.png (100%) rename {src/docs => docs/manual}/_static/pictures/settings-icon.png (100%) rename {src/docs => docs/manual}/conf.py.in (100%) rename {src/docs => docs/manual}/config.rst (100%) rename {src/docs => docs/manual}/ddsc.rst (100%) rename {src/docs => docs/manual}/index.rst (100%) create mode 100644 examples/CMakeLists.txt rename {src/examples => examples}/examples.rst (100%) rename {src/examples => examples}/helloworld/CMakeLists.export (100%) rename {src/examples => examples}/helloworld/CMakeLists.txt (100%) rename {src/examples => examples}/helloworld/HelloWorld.sln (100%) rename {src/examples => examples}/helloworld/HelloWorldData.idl (100%) rename {src/examples => examples}/helloworld/Makefile (100%) rename {src/examples => examples}/helloworld/publisher.c (100%) rename {src/examples => examples}/helloworld/readme.rst (100%) rename {src/examples => examples}/helloworld/subscriber.c (100%) rename {src/examples => examples}/helloworld/vs/HelloWorldPublisher.vcxproj (100%) rename {src/examples => examples}/helloworld/vs/HelloWorldSubscriber.vcxproj (100%) rename {src/examples => examples}/helloworld/vs/HelloWorldType.vcxproj (100%) rename {src/examples => examples}/helloworld/vs/directories.props (100%) rename {performance => examples/perfscript}/ethload (100%) rename {performance => examples/perfscript}/quick-microbenchmark (100%) rename {performance => examples/perfscript}/throughput-fanout-test (100%) rename {performance => examples/perfscript}/throughput-test (100%) rename {performance => examples/perfscript}/throughput-test-extract (100%) rename {performance => examples/perfscript}/throughput-test-plot (100%) rename {src/examples => examples}/roundtrip/CMakeLists.txt (100%) rename {src/examples => examples}/roundtrip/RoundTrip.idl (100%) rename {src/examples => examples}/roundtrip/ping.c (100%) rename {src/examples => examples}/roundtrip/pong.c (100%) rename {src/examples => examples}/roundtrip/readme.rst (100%) rename {src/examples => examples}/sphinx-conf.py.in (97%) rename {src/examples => examples}/throughput/CMakeLists.txt (100%) rename {src/examples => examples}/throughput/Throughput.idl (100%) rename {src/examples => examples}/throughput/publisher.c (100%) rename {src/examples => examples}/throughput/readme.rst (100%) rename {src/examples => examples}/throughput/subscriber.c (100%) delete mode 100644 src/cmake/CoverageSettings.cmake.in delete mode 100644 src/cmake/launch-c.bat.in delete mode 100644 src/cmake/launch-c.in delete mode 100644 src/cmake/launch-cxx.bat.in delete mode 100644 src/cmake/launch-cxx.in delete mode 100644 src/cmake/modules/Coverage.cmake delete mode 100644 src/cmake/modules/Packaging/banner.bmp delete mode 100644 src/cmake/modules/Packaging/dialog.png delete mode 100644 src/cmake/modules/Packaging/examples.xml delete mode 100644 src/cmake/modules/Packaging/vortex.ico delete mode 100644 src/cmake/modules/Platform/VxWorks6.cmake delete mode 100644 src/cmake/scripts/CoverageConvenience.cmake delete mode 100644 src/cmake/scripts/CoveragePostCobertura.cmake delete mode 100644 src/cmake/scripts/CoveragePostHtml.cmake delete mode 100644 src/cmake/scripts/CoveragePreCobertura.cmake delete mode 100644 src/cmake/scripts/CoveragePreHtml.cmake delete mode 100644 src/cmake/vxworks.example.cmake delete mode 100644 src/docs/CMakeLists.txt delete mode 100644 src/etc/CMakeLists.txt delete mode 100644 src/etc/cmake/default.xml.in delete mode 100644 src/examples/CMakeLists.txt delete mode 100644 src/scripts/CMakeLists.txt delete mode 100755 src/scripts/cmake/vdds_install_examples.in diff --git a/.travis.yml b/.travis.yml index f0af13a..4d8d28c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -165,7 +165,7 @@ script: -DUSE_SANITIZER=${ASAN} -DBUILD_TESTING=on -DWERROR=on - -G "${GENERATOR}" ../src + -G "${GENERATOR}" .. - ${SCAN_BUILD} cmake --build . --config ${BUILD_TYPE} --target install - CYCLONEDDS_URI='all' ctest -T test -C ${BUILD_TYPE} - if [ "${ASAN}" != "none" ]; then diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2b14033 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,214 @@ +# +# 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 +# +cmake_minimum_required(VERSION 3.7) + +# Set a default build type if none was specified +set(default_build_type "RelWithDebInfo") +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to '${default_build_type}' as none was specified.") + set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE + STRING "Choose the type of build." FORCE) + # Set the possible values of build type for cmake-gui + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Release" "MinSizeRel" "RelWithDebInfo") +endif() + +# By default the Java-based components get built, but make it possible to disable that: if only the +# core library is required, there's no need to build them, and that in turn eliminates the Maven and +# JDK dependency. +option(BUILD_IDLC "Build IDL preprocessor" ON) +option(BUILD_CONFTOOL "Build configuration file edit tool" ON) + +# By default don't treat warnings as errors, else anyone building it with a different compiler that +# just happens to generate a warning, as well as anyone adding or modifying something and making a +# small mistake would run into errors. CI builds can be configured differently. +option(WERROR "Treat compiler warnings as errors" OFF) + +FUNCTION(PREPEND var prefix) + SET(listVar "") + FOREACH(f ${ARGN}) + LIST(APPEND listVar "${prefix}/${f}") + ENDFOREACH(f) + SET(${var} "${listVar}" PARENT_SCOPE) +ENDFUNCTION(PREPEND) + +# Update the git submodules +execute_process(COMMAND git submodule init + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +execute_process(COMMAND git submodule update + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + +# Set module path before defining project so platform files will work. +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules") +set(CMAKE_PROJECT_NAME_FULL "Eclipse Cyclone DDS") +set(PROJECT_NAME "CycloneDDS") +project(${PROJECT_NAME} VERSION 0.1.0) + +# Set some convenience variants of the project-name +string(REPLACE " " "-" CMAKE_PROJECT_NAME_DASHED "${CMAKE_PROJECT_NAME_FULL}") +string(TOUPPER ${CMAKE_PROJECT_NAME} CMAKE_PROJECT_NAME_CAPS) +string(TOLOWER ${CMAKE_PROJECT_NAME} CMAKE_PROJECT_NAME_SMALL) + +set(CMAKE_C_STANDARD 99) +if(CMAKE_SYSTEM_NAME STREQUAL "VxWorks") + add_definitions(-std=c99) +endif() + +if(${CMAKE_C_COMPILER_ID} STREQUAL "SunPro") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64 -xc99 -D__restrict=restrict -D__deprecated__=") + set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} -m64") +elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64") + set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} -m64") +endif() + +# Conan +if(EXISTS "${CMAKE_BINARY_DIR}/conanbuildinfo.cmake") + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + if(APPLE) + # By default Conan strips all RPATHs (see conanbuildinfo.cmake), which + # causes tests to fail as the executables cannot find the library target. + # By setting KEEP_RPATHS, Conan does not set CMAKE_SKIP_RPATH and the + # resulting binaries still have the RPATH information. This is fine because + # CMake will strip the build RPATH information in the install step. + # + # NOTE: + # Conan's default approach is to use the "imports" feature, which copies + # all the dependencies into the bin directory. Of course, this doesn't work + # quite that well for libraries generated in this Project (see Conan + # documentation). + # + # See the links below for more information. + # https://github.com/conan-io/conan/issues/337 + # https://docs.conan.io/en/latest/howtos/manage_shared_libraries/rpaths.html + # https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling + conan_basic_setup(KEEP_RPATHS) + else() + conan_basic_setup() + endif() + conan_define_targets() +endif() + +# Set reasonably strict warning options for clang, gcc, msvc +# Enable coloured ouput if Ninja is used for building +if("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") + #message(STATUS clang) + add_compile_options(-Wall -Wextra -Wconversion -Wunused -Wmissing-prototypes) + if(${WERROR}) + add_compile_options(-Werror) + endif() + if("${CMAKE_GENERATOR}" STREQUAL "Ninja") + add_compile_options(-Xclang -fcolor-diagnostics) + endif() +elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") + #message(STATUS gcc) + add_compile_options(-Wall -Wextra -Wconversion -Wmissing-prototypes) + if(${WERROR}) + add_compile_options(-Werror) + endif() + if("${CMAKE_GENERATOR}" STREQUAL "Ninja") + add_compile_options(-fdiagnostics-color=always) + endif() +elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") + #message(STATUS msvc) + add_compile_options(/W3) + if(${WERROR}) + add_compile_options(/WX) + endif() +endif() + +# I don't know how to enable warnings properly so that they are enabled in Xcode projects as well +if(${CMAKE_GENERATOR} STREQUAL "Xcode") + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_EMPTY_BODY YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_SHADOW YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_BOOL_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_CONSTANT_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_64_TO_32_BIT_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_ENUM_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_FLOAT_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_INT_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_NON_LITERAL_NULL_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_IMPLICIT_SIGN_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_INFINITE_RECURSION YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_ABOUT_RETURN_TYPE YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_MISSING_PARENTHESES YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_ABOUT_MISSING_NEWLINE YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_ASSIGN_ENUM YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_SIGN_COMPARE YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_STRICT_PROTOTYPES YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_COMMA YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNINITIALIZED_AUTOS YES_AGGRESSIVE) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_FUNCTION YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_LABEL YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_PARAMETER YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VALUE YES) + set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VARIABLE YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_DOCUMENTATION_COMMENTS YES) + set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_MISSING_PROTOTYPES YES) +endif() + +# Make it easy to enable one of Clang's/gcc's analyzers, and default to using +# the address sanitizer for ordinary debug builds; gcc is giving some grief on +# Travis, so don't enable it for gcc by default +if(NOT USE_SANITIZER) + if(${CMAKE_BUILD_TYPE} STREQUAL "Debug" AND + NOT (${CMAKE_GENERATOR} STREQUAL "Xcode") AND + (${CMAKE_C_COMPILER_ID} STREQUAL "Clang" + OR ${CMAKE_C_COMPILER_ID} STREQUAL "AppleClang")) + message(STATUS "Enabling address sanitizer; set USE_SANITIZER=none to prevent this") + set(USE_SANITIZER address) + else() + set(USE_SANITIZER none) + endif() +endif() +if(NOT (${USE_SANITIZER} STREQUAL "none")) + message(STATUS "Sanitizer set to ${USE_SANITIZER}") + add_compile_options(-fno-omit-frame-pointer -fsanitize=${USE_SANITIZER}) + link_libraries(-fno-omit-frame-pointer -fsanitize=${USE_SANITIZER}) +endif() + +include(GNUInstallDirs) +include(AnalyzeBuild) +if(APPLE) + set(CMAKE_INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR}") +else() + set(CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") +endif() +set(MEMORYCHECK_COMMAND_OPTIONS "--track-origins=yes --leak-check=full --trace-children=yes --child-silent-after-fork=yes --xml=yes --xml-file=TestResultValgrind_%p.xml --tool=memcheck --show-reachable=yes --leak-resolution=high") + +# By default building the testing tree is enabled by including CTest, but +# since not everybody has CUnit, and because it is not strictly required to +# build the product itself, switch to off by default. +option(BUILD_TESTING "Build the testing tree." OFF) +include(CTest) + +# Build all executables and libraries into the top-level /bin and /lib folders. +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") + +add_subdirectory(src) +if(BUILD_IDLC) + add_subdirectory(examples) +endif() + +option(BUILD_DOCS "Build documentation." OFF) +if(BUILD_DOCS) + add_subdirectory(docs) +endif() + +# Pull-in CPack and support for generating Config.cmake and packages. +include(Packaging) diff --git a/README.md b/README.md index 3817027..d8ac3e3 100644 --- a/README.md +++ b/README.md @@ -8,21 +8,28 @@ market. Moreover, Cyclone DDS is developed completely in the open as an Eclipse ## Building Eclipse Cyclone DDS -In order to build Cyclone DDS you need a Linux, Mac or Windows 10 machine with the following -installed on your host: +In order to build Cyclone DDS you need a Linux, Mac or Windows 10 machine (or, with some caveats, an +OpenIndiana one or a Solaris 2.6 one) with the following installed on your host: - * [CMake](https://cmake.org/download/), version 3.7 or later. (Version 3.6 should work but you - will have to edit the ``cmake_minimum_required`` version and may have to disable building the - tests.) - * [OpenSSL](https://www.openssl.org/), preferably version 1.1 or later. If you wish, you can - build without support for OpenSSL by setting DDSC\_ENABLE\_OPENSSL to FALSE on the ``cmake `` - command line (i.e., ``cmake -DDDSC_ENABLE_OPENSSL=FALSE`` ../src). In that, there is no need to - have openssl available. - * Java JDK, version 8 or later, e.g., [OpenJDK 11](http://jdk.java.net/11/). - * [Apache Maven](http://maven.apache.org/download.cgi), version 3.5 or later. + * C compiler (most commonly GCC on Linux, Visual Studio on Windows, Xcode on macOS); + * GIT version control system; + * [CMake](https://cmake.org/download/), version 3.7 or later; + * [OpenSSL](https://www.openssl.org/), preferably version 1.1 or later if you want to use TLS over + TCP. You can explicitly disable it by setting ``ENABLE_SSL=NO``, which is very useful for + reducing the footprint or when the FindOpenSSL CMake script gives you trouble; + * Java JDK, version 8 or later, e.g., [OpenJDK](https://jdk.java.net/); + * [Apache Maven](https://maven.apache.org/download.cgi), version 3.5 or later. + +On Ubuntu ``apt install maven default-jdk`` should do the trick for getting Java and Maven +installed, and the rest should already be there. On Windows, installing chocolatey and ``choco +install git cmake openjdk maven`` should get you a long way. On macOS, ``brew install maven cmake`` +and downloading and installing the JDK is easiest. The Java-based components are the preprocessor and a configurator tool. The run-time libraries are -pure C code, so there is no need to have Java available on "target" machines. +pure C code, so there is no need to have Java available on "target" machines. If desired, it is +possible to do a build without Java or Maven installed by defining ``BUILD_IDLC=NO`` and +``BUILD_CONFTOOL=NO``, but that effectively only gets you the core library. For the +current [ROS2 RMW layer](https://github.com/atolab/rmw_cyclonedds), that is sufficient. To obtain Eclipse Cyclone DDS, do @@ -40,13 +47,13 @@ DDS requires a few simple steps. There are some small differences between Linux hand, and Windows on the other. For Linux or macOS: $ cd build - $ cmake -DCMAKE_INSTALL_PREFIX= ../src + $ cmake -DCMAKE_INSTALL_PREFIX= .. $ cmake --build . and for Windows: $ cd build - $ cmake -G "" -DCMAKE_INSTALL_PREFIX= ../src + $ cmake -G "" -DCMAKE_INSTALL_PREFIX= .. $ cmake --build . where you should replace ```` by the directory under which you would like to @@ -65,7 +72,6 @@ which will copy everything to: * ``/bin`` * ``/include/ddsc`` * ``/share/CycloneDDS`` - * ``/etc/CycloneDDS`` Depending on the installation location you may need administrator privileges. @@ -85,7 +91,7 @@ present in the repository and that there is a test suite using CTest and CUnit t locally if desired. To build it, set the cmake variable ``BUILD_TESTING`` to on when configuring, e.g.: $ cd build - $ cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON ../src + $ cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON .. $ cmake --build . $ ctest @@ -100,10 +106,65 @@ also need to add switches to select the architecture and build type, e.g., ``con arch=x86_64 -s build_type=Debug ..`` This will automatically download and/or build CUnit (and, at the moment, OpenSSL). +## Configuration + +The out-of-the-box configuration should usually be fine, but there are a great many options that can +be tweaked by creating an XML file with the desired settings and defining the ``CYCLONEDDS_URI`` to +point to it. E.g. (on Linux): + + $ cat cyclonedds.xml + + + auto + auto + 65500B + 65000B + + + + 500kB + + + + config + stdout + + + $ export CYCLONEDDS_URI=file://$PWD/cyclonedds.xml + +(on Windows, one would have to use ``set CYCLONEDDS_URI=file://...`` instead.) + +This example shows a few things: + +* ``NetworkInterfaceAddress`` can be used to override the interface selected by default (you can use + the address or the interface name). Proper use of multiple network interfaces simultaneously will + come, but is not there yet. +* ``AllowMulticast`` configures the circumstances under which multicast will be used. If the + selected interface doesn't support it, it obviously wonn't be used (``false``); but if it does + support it, the type of the network adapter determines the default value. For a wired network, it + will use multicast for initial discovery as well as for data when there are multiple peers that + the data needs to go to (``true``); but on a WiFi network it will use it only for initial + discovery (``spdp``), because multicast on WiFi is very unreliable. +* ``Verbosity`` allows control over the tracing, "config" dumps the configuration to the trace + output (which defaults to "cyclonedds.log"). Which interface is used, what multicast settings are + used, etc., is all in the trace. Setting the verbosity to "finest" gives way more output on the + inner workings, and there are various other levels as well. +* ``MaxMessageSize`` and ``FragmentSize`` control the maximum size of the RTPS messages (basically + the size of the UDP payload), and the size of the fragments into which very large samples get + split (which needs to be "a bit" less). Large values such as these typically improve performance + over the (current) default values. +* ``WhcHigh`` determines when the sender will wait for acknolwedgements from the readers because it + has buffered too much unacknowledged data. There is some auto-tuning, the (current) default value + is a bit small to get really high throughput. + +The configurator tool ``cycloneddsconf`` can help in discovering the settings, as can the config +dump. Background information on configuring Cyclone DDS can be +found [here](https://docs/manual/config.rst). + ## Documentation The documentation is still rather limited, and at the moment only available in the sources (in the -form of restructured text files in ``src/docs`` and Doxygen comments in the header files), or as +form of restructured text files in ``docs`` and Doxygen comments in the header files), or as a [PDF](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/pdf/CycloneDDS-0.1.0.pdf). The intent is to automate the process of building the documentation and have them available in more @@ -133,7 +194,7 @@ We will show you how to build and run an example program that measures latency. built automatically when you build Cyclone DDS, so you don't need to follow these steps to be able to run the program, it is merely to illustrate the process. - $ cd cyclonedds/src/examples/roundtrip + $ cd cyclonedds/examples/roundtrip $ mkdir build $ cd build $ cmake .. diff --git a/appveyor.yml b/appveyor.yml index 363272b..9e07208 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -36,7 +36,7 @@ build_script: - mkdir build - cd build - conan install -s arch=%ARCH% -s build_type=%CONFIGURATION% .. - - cmake -DBUILD_TESTING=on -DWERROR=ON -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DCMAKE_INSTALL_PREFIX=%CD%/install -G "%GENERATOR%" ../src + - cmake -DBUILD_TESTING=on -DWERROR=ON -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DCMAKE_INSTALL_PREFIX=%CD%/install -G "%GENERATOR%" .. - cmake --build . --config %CONFIGURATION% --target install -- /maxcpucount - cd install/share/CycloneDDS/examples/helloworld - mkdir build diff --git a/src/cmake/modules/AnalyzeBuild.cmake b/cmake/Modules/AnalyzeBuild.cmake similarity index 100% rename from src/cmake/modules/AnalyzeBuild.cmake rename to cmake/Modules/AnalyzeBuild.cmake diff --git a/src/cmake/modules/CUnit.cmake b/cmake/Modules/CUnit.cmake similarity index 100% rename from src/cmake/modules/CUnit.cmake rename to cmake/Modules/CUnit.cmake diff --git a/src/cmake/modules/CUnit/include/CUnit/Test.h b/cmake/Modules/CUnit/include/CUnit/Test.h similarity index 100% rename from src/cmake/modules/CUnit/include/CUnit/Test.h rename to cmake/Modules/CUnit/include/CUnit/Test.h diff --git a/src/cmake/modules/CUnit/include/CUnit/Theory.h b/cmake/Modules/CUnit/include/CUnit/Theory.h similarity index 100% rename from src/cmake/modules/CUnit/include/CUnit/Theory.h rename to cmake/Modules/CUnit/include/CUnit/Theory.h diff --git a/src/cmake/modules/CUnit/src/main.c.in b/cmake/Modules/CUnit/src/main.c.in similarity index 100% rename from src/cmake/modules/CUnit/src/main.c.in rename to cmake/Modules/CUnit/src/main.c.in diff --git a/src/cmake/modules/FindCUnit.cmake b/cmake/Modules/FindCUnit.cmake similarity index 100% rename from src/cmake/modules/FindCUnit.cmake rename to cmake/Modules/FindCUnit.cmake diff --git a/src/cmake/modules/FindMaven.cmake b/cmake/Modules/FindMaven.cmake similarity index 100% rename from src/cmake/modules/FindMaven.cmake rename to cmake/Modules/FindMaven.cmake diff --git a/src/cmake/modules/FindOpenSSL.cmake b/cmake/Modules/FindOpenSSL.cmake similarity index 100% rename from src/cmake/modules/FindOpenSSL.cmake rename to cmake/Modules/FindOpenSSL.cmake diff --git a/src/cmake/modules/FindSphinx.cmake b/cmake/Modules/FindSphinx.cmake similarity index 100% rename from src/cmake/modules/FindSphinx.cmake rename to cmake/Modules/FindSphinx.cmake diff --git a/src/cmake/modules/GenerateDummyExportHeader.cmake b/cmake/Modules/GenerateDummyExportHeader.cmake similarity index 100% rename from src/cmake/modules/GenerateDummyExportHeader.cmake rename to cmake/Modules/GenerateDummyExportHeader.cmake diff --git a/src/cmake/modules/Glob.cmake b/cmake/Modules/Glob.cmake similarity index 100% rename from src/cmake/modules/Glob.cmake rename to cmake/Modules/Glob.cmake diff --git a/src/cmake/modules/Packaging.cmake b/cmake/Modules/Packaging.cmake similarity index 77% rename from src/cmake/modules/Packaging.cmake rename to cmake/Modules/Packaging.cmake index 9b76487..4d06fd2 100644 --- a/src/cmake/modules/Packaging.cmake +++ b/cmake/Modules/Packaging.cmake @@ -17,7 +17,7 @@ set(PACKAGING_INCLUDED true) include(CMakePackageConfigHelpers) include(GNUInstallDirs) -set(PACKAGING_MODULE_DIR "${PROJECT_SOURCE_DIR}/cmake/modules/Packaging") +set(PACKAGING_MODULE_DIR "${PROJECT_SOURCE_DIR}/cmake/Modules/Packaging") set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}") # Generates Config.cmake. @@ -54,15 +54,13 @@ set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) set(CPACK_PACKAGE_VERSION_TWEAK ${PROJECT_VERSION_TWEAK}) set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) -set(VENDOR_INSTALL_ROOT "ADLINK") set(CPACK_PACKAGE_NAME ${CMAKE_PROJECT_NAME}) -set(CPACK_PACKAGE_VENDOR "ADLINK Technology Inc.") -set(CPACK_PACKAGE_CONTACT "${CMAKE_PROJECT_NAME} core developers ") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Leading OMG DDS implementation from ADLINK Technology") -set(CPACK_PACKAGE_ICON "${PACKAGING_MODULE_DIR}/vortex.ico") +set(CPACK_PACKAGE_VENDOR "Eclipse Cyclone DDS project") +set(CPACK_PACKAGE_CONTACT "https://github.com/eclipse-cyclonedds/cyclonedds") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Implementation of the OMG DDS standard") # WiX requires a .txt file extension for CPACK_RESOURCE_FILE_LICENSE -file(COPY "${PROJECT_SOURCE_DIR}/../LICENSE" DESTINATION "${CMAKE_BINARY_DIR}") +file(COPY "${PROJECT_SOURCE_DIR}/LICENSE" DESTINATION "${CMAKE_BINARY_DIR}") file(RENAME "${CMAKE_BINARY_DIR}/LICENSE" "${CMAKE_BINARY_DIR}/license.txt") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_BINARY_DIR}/license.txt") @@ -95,24 +93,7 @@ if(WIN32 AND NOT UNIX) set(CPACK_GENERATOR "WIX;ZIP;${CPACK_GENERATOR}" CACHE STRING "List of package generators") set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION}-${__arch}") - set(CPACK_PACKAGE_INSTALL_DIRECTORY "${VENDOR_INSTALL_ROOT}/${CMAKE_PROJECT_NAME_FULL}") - - set(CPACK_WIX_LIGHT_EXTENSIONS "WixUtilExtension") - set(CPACK_WIX_COMPONENT_INSTALL ON) - set(CPACK_WIX_ROOT_FEATURE_TITLE "${CMAKE_PROJECT_NAME_FULL}") - set(CPACK_WIX_PRODUCT_ICON "${PACKAGING_MODULE_DIR}/vortex.ico") - # Bitmap (.bmp) of size 493x58px - set(CPACK_WIX_UI_BANNER "${PACKAGING_MODULE_DIR}/banner.bmp") - # Bitmap (.bmp) of size 493x312px - set(CPACK_WIX_UI_DIALOG "${PACKAGING_MODULE_DIR}/dialog.png") - set(CPACK_WIX_PROGRAM_MENU_FOLDER "${CPACK_PACKAGE_NAME_FULL}") - set(CPACK_WIX_PATCH_FILE "${PACKAGING_MODULE_DIR}/examples.xml") - set(CPACK_WIX_PROPERTY_ARPHELPLINK "http://www.adlinktech.com/support") - set(CPACK_WIX_PROPERTY_ARPURLINFOABOUT "http://www.adlinktech.com/") - set(CPACK_WIX_PROPERTY_ARPURLUPDATEINFO "http://www.adlinktech.com/") - - # A constant GUID allows installers to replace existing installations that use the same GUID. - set(CPACK_WIX_UPGRADE_GUID "1351F59A-972B-4624-A7F1-439381BFA41D") + set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CMAKE_PROJECT_NAME_FULL}") include(InstallRequiredSystemLibraries) elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") @@ -159,10 +140,6 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") # Generic tgz package set(CPACK_GENERATOR "TGZ;${CPACK_GENERATOR}" CACHE STRING "List of package generators") endif() -elseif(CMAKE_SYSTEM_NAME MATCHES "VxWorks") - # FIXME: Support for VxWorks packages must still be implemented (probably - # just a compressed tarball) - message(STATUS "Packaging for VxWorks is unsupported") endif() # This must always be last! diff --git a/src/cmake/modules/Packaging/PackageConfig.cmake.in b/cmake/Modules/Packaging/PackageConfig.cmake.in similarity index 100% rename from src/cmake/modules/Packaging/PackageConfig.cmake.in rename to cmake/Modules/Packaging/PackageConfig.cmake.in diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt new file mode 100644 index 0000000..891bc0d --- /dev/null +++ b/docs/CMakeLists.txt @@ -0,0 +1,49 @@ +# +# 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 + +# TODO depending on requirements we can add/remove options as needed, +# these are examples of generators we'll need as a minimum. +# Perhaps we should also consider options for building subset of all docs. +# When a certain doc is related to a target, no option is needed; you can simply check if the target exists +# (i.e. if a target 'ddsc' exists, build ddsc api docs). And possibly make the target definition dependent on an option. + +find_program(SPHINX_EXECUTABLE NAMES sphinx-build DOC "Sphinx documentation builder") +if (NOT SPHINX_EXECUTABLE) + message(FATAL_ERROR "${CMAKE_PROJECT_NAME} documentation: unable to find sphinx-build executable") +endif() + +find_package(Doxygen) +if (NOT Doxygen_FOUND) + message(FATAL_ERROR "${CMAKE_PROJECT_NAME} documentation: unable to find Doxygen") +endif() + +# Creating pdf from latex requires latexmk (which depends on perl, latexpdf et. al) +find_program(LATEXMK_EXECUTABLE NAMES latexmk DOC "LateX PDF Generator") +if (NOT LATEXMK_EXECUTABLE) + message(FATAL_ERROR "${CMAKE_PROJECT_NAME} documentation: unable to find latexmk") +endif() + +if (SPHINX_EXECUTABLE AND Doxygen_FOUND AND LATEXMK_EXECUTABLE) + set(BUILD_DOCS ON PARENT_SCOPE) # for examples' docs + set(BUILD_DOCS ON) + message(STATUS "${CMAKE_PROJECT_NAME} documentation: Success (build)") +endif() + +if(BUILD_DOCS) + add_subdirectory(manual) +endif() + +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html + DESTINATION ${CMAKE_INSTALL_DOCDIR} + COMPONENT dev) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.pdf + DESTINATION ${CMAKE_INSTALL_DOCDIR} + COMPONENT dev) diff --git a/notes/data path - rbuf.svg b/docs/dev/data path - rbuf.svg similarity index 100% rename from notes/data path - rbuf.svg rename to docs/dev/data path - rbuf.svg diff --git a/notes/data path - receive.svg b/docs/dev/data path - receive.svg similarity index 100% rename from notes/data path - receive.svg rename to docs/dev/data path - receive.svg diff --git a/notes/data path - transmit.svg b/docs/dev/data path - transmit.svg similarity index 100% rename from notes/data path - transmit.svg rename to docs/dev/data path - transmit.svg diff --git a/notes/data path.graffle b/docs/dev/data path.graffle similarity index 100% rename from notes/data path.graffle rename to docs/dev/data path.graffle diff --git a/docs/manual/CMakeLists.txt b/docs/manual/CMakeLists.txt new file mode 100644 index 0000000..c49b5cf --- /dev/null +++ b/docs/manual/CMakeLists.txt @@ -0,0 +1,122 @@ +# +# 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 + +# TODO depending on requirements we can add/remove options as needed, +# these are examples of generators we'll need as a minimum. +# Perhaps we should also consider options for building subset of all docs. +# When a certain doc is related to a target, no option is needed; you can simply check if the target exists +# (i.e. if a target 'ddsc' exists, build ddsc api docs). And possibly make the target definition dependent on an option. + +# Generate ddsc API docs in XML format using Doxygen, if the ddsc target is defined. +# The XML will serve as input for sphinx' breathe plugin +if (TARGET ${CMAKE_PROJECT_NAME}::ddsc) + # Process doxygen configuration file, for ddsc + set(doxy_conf_project "${CMAKE_PROJECT_NAME_FULL} C API Documentation") + set(doxy_conf_outputdir "ddsc_api") + set(doxy_conf_input "${PROJECT_SOURCE_DIR}/src/core/ddsc/include/dds/dds.h ${PROJECT_SOURCE_DIR}/src/core/ddsc/include/dds") + configure_file(Doxyfile.in Doxyfile @ONLY) + + add_custom_target(ddsc_docs + ${DOXYGEN_EXECUTABLE} Doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Running Doxygen for API docs generation" + VERBATIM) + + # Remove generated files when cleaning the build tree + set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${doxy_conf_outputdir}) + + # Add ddsc api docs to sphinx' breathe projects + set(sph_conf_breathe_projs "\"ddsc_api\": \"${doxy_conf_outputdir}/xml\"") + + add_custom_command(TARGET ddsc_docs + POST_BUILD + WORKING_DIRECTORY "${doxy_conf_outputdir}" + COMMAND ${CMAKE_COMMAND} -E tar "zcf" "${CMAKE_PROJECT_NAME}_C_HTML.tar.gz" "ddsc") +endif() + +# Process sphinx configuration file +set(sph_conf_author "Eclipse Cyclone DDS project") +set(sph_conf_version "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") +set(sph_conf_release "${PROJECT_VERSION}") +configure_file(conf.py.in conf.py @ONLY) + +# Define a list of output formats (-b option for sphinx-build) +set(docs_builders "") +list(APPEND docs_builders html) +list(APPEND docs_builders latex) + +# Define custom commands for running sphinx-build for different docs builders +set(docs_outputs "") +foreach(builder ${docs_builders}) + set(docs_builder_output "docs_${builder}_output") + # Log stdout (not stderr) to a file instead of messing up build output + set(docs_builder_log "sphinx-build-${builder}.log") + + add_custom_command(OUTPUT ${docs_builder_output} + COMMAND ${SPHINX_EXECUTABLE} + -b ${builder} + -d ${CMAKE_CURRENT_BINARY_DIR}/cache + -c ${CMAKE_CURRENT_BINARY_DIR} + ${PROJECT_SOURCE_DIR}/docs/manual + ${CMAKE_CURRENT_BINARY_DIR}/${builder} > ${docs_builder_log} + COMMENT "Running Sphinx for ${builder} output" + VERBATIM) + + # FIXME: This is definitely in the wrong location + if(builder STREQUAL html) + add_custom_command(OUTPUT ${docs_builder_output} + COMMAND ${CMAKE_COMMAND} + -E tar "zcf" + "${CMAKE_PROJECT_NAME}HTML.tar.gz" + "html" + APPEND + VERBATIM) + endif() + + # Create a pdf from the latex builder output, by appending a latexmk command + # TODO look into rinohtype as an alternative (don't bother with rst2pdf, it's no good) + if(builder STREQUAL latex) + add_custom_command(OUTPUT ${docs_builder_output} + COMMAND ${LATEXMK_EXECUTABLE} + -interaction=nonstopmode + -silent + -output-directory=${builder} + -pdf -dvi- -ps- -cd- ${builder}/${CMAKE_PROJECT_NAME}.tex + APPEND + VERBATIM) + + # Move the pdf, so that install rules don't need to differentiate between built and downloaded docs + add_custom_command(OUTPUT ${docs_builder_output} + COMMAND ${CMAKE_COMMAND} + -E rename + "latex/${CMAKE_PROJECT_NAME}.pdf" + "${CMAKE_PROJECT_NAME}.pdf" + APPEND + VERBATIM) + endif() + + # OUTPUT is a fake target / symbolic name, not an actual file + set_property(SOURCE ${docs_builder_output} PROPERTY SYMBOLIC 1) + # Remove generated files when cleaning the build tree + set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES + ${builder} + ${docs_builder_log}) + + # Include this builder as a dependency of the general 'docs' target + list(APPEND docs_outputs ${docs_builder_output}) +endforeach() + +# Remove generated files when cleaning the build tree +set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES + ${CMAKE_PROJECT_NAME}HTML.tar.gz + ${CMAKE_PROJECT_NAME}.pdf) + +add_custom_target(docs ALL DEPENDS ddsc_docs ${docs_outputs}) diff --git a/src/docs/Doxyfile.in b/docs/manual/Doxyfile.in similarity index 99% rename from src/docs/Doxyfile.in rename to docs/manual/Doxyfile.in index 32aebfe..3d139a2 100644 --- a/src/docs/Doxyfile.in +++ b/docs/manual/Doxyfile.in @@ -2019,7 +2019,7 @@ SEARCH_INCLUDES = YES # preprocessor. # This tag requires that the tag SEARCH_INCLUDES is set to YES. -INCLUDE_PATH = @PROJECT_SOURCE_DIR@/core/ddsc/include +INCLUDE_PATH = @PROJECT_SOURCE_DIR@/src/core/ddsc/include # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the @@ -2037,7 +2037,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = __restrict= __attribute__(x)= __declspec(x)= +PREDEFINED = __restrict= __attribute__(x)= __declspec(x)= DDS_EXPORT= DDS_DEPRECATED_EXPORT= # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The diff --git a/src/docs/GettingStartedGuide/helloworld.rst b/docs/manual/GettingStartedGuide/helloworld.rst similarity index 99% rename from src/docs/GettingStartedGuide/helloworld.rst rename to docs/manual/GettingStartedGuide/helloworld.rst index 3b0169f..c2c7862 100644 --- a/src/docs/GettingStartedGuide/helloworld.rst +++ b/docs/manual/GettingStartedGuide/helloworld.rst @@ -195,7 +195,7 @@ example. Apart from the native build files, CMake build files are provided as well. See :code:`examples/helloworld/CMakeLists.txt` -.. literalinclude:: ../../examples/helloworld/CMakeLists.export +.. literalinclude:: ../../../examples/helloworld/CMakeLists.export :linenos: :language: cmake diff --git a/src/docs/GettingStartedGuide/helloworld_indepth.rst b/docs/manual/GettingStartedGuide/helloworld_indepth.rst similarity index 98% rename from src/docs/GettingStartedGuide/helloworld_indepth.rst rename to docs/manual/GettingStartedGuide/helloworld_indepth.rst index 94a4575..8313290 100644 --- a/src/docs/GettingStartedGuide/helloworld_indepth.rst +++ b/docs/manual/GettingStartedGuide/helloworld_indepth.rst @@ -77,7 +77,7 @@ There are a few ways to describe the structures that make up the data layer. The HelloWorld uses the IDL language to describe the data type in HelloWorldData.idl: -.. literalinclude:: ../../examples/helloworld/HelloWorldData.idl +.. literalinclude:: ../../../examples/helloworld/HelloWorldData.idl :linenos: :language: idl @@ -202,7 +202,7 @@ business logic. Subscriber.c contains the source that will wait for a *Hello World!* message and reads it when it receives one. -.. literalinclude:: ../../examples/helloworld/subscriber.c +.. literalinclude:: ../../../examples/helloworld/subscriber.c :linenos: :language: c @@ -331,7 +331,7 @@ automatically delete the topic and reader as well. Publisher.c contains the source that will write an *Hello World!* message on which the subscriber is waiting. -.. literalinclude:: ../../examples/helloworld/publisher.c +.. literalinclude:: ../../../examples/helloworld/publisher.c :linenos: :language: c diff --git a/src/docs/GettingStartedGuide/index.rst b/docs/manual/GettingStartedGuide/index.rst similarity index 100% rename from src/docs/GettingStartedGuide/index.rst rename to docs/manual/GettingStartedGuide/index.rst diff --git a/src/docs/GettingStartedGuide/installation.rst b/docs/manual/GettingStartedGuide/installation.rst similarity index 100% rename from src/docs/GettingStartedGuide/installation.rst rename to docs/manual/GettingStartedGuide/installation.rst diff --git a/src/docs/GettingStartedGuide/next_steps.rst b/docs/manual/GettingStartedGuide/next_steps.rst similarity index 100% rename from src/docs/GettingStartedGuide/next_steps.rst rename to docs/manual/GettingStartedGuide/next_steps.rst diff --git a/src/docs/GettingStartedGuide/uninstall.rst b/docs/manual/GettingStartedGuide/uninstall.rst similarity index 100% rename from src/docs/GettingStartedGuide/uninstall.rst rename to docs/manual/GettingStartedGuide/uninstall.rst diff --git a/src/docs/_static/BuildSchema.odg b/docs/manual/_static/BuildSchema.odg similarity index 100% rename from src/docs/_static/BuildSchema.odg rename to docs/manual/_static/BuildSchema.odg diff --git a/src/docs/_static/pictures/BuildSchema.png b/docs/manual/_static/pictures/BuildSchema.png similarity index 100% rename from src/docs/_static/pictures/BuildSchema.png rename to docs/manual/_static/pictures/BuildSchema.png diff --git a/src/docs/_static/pictures/HelloworldPublisherWindows.png b/docs/manual/_static/pictures/HelloworldPublisherWindows.png similarity index 100% rename from src/docs/_static/pictures/HelloworldPublisherWindows.png rename to docs/manual/_static/pictures/HelloworldPublisherWindows.png diff --git a/src/docs/_static/pictures/HelloworldSubscriberWindows.png b/docs/manual/_static/pictures/HelloworldSubscriberWindows.png similarity index 100% rename from src/docs/_static/pictures/HelloworldSubscriberWindows.png rename to docs/manual/_static/pictures/HelloworldSubscriberWindows.png diff --git a/src/docs/_static/pictures/VORTEX_LOGO.png b/docs/manual/_static/pictures/VORTEX_LOGO.png similarity index 100% rename from src/docs/_static/pictures/VORTEX_LOGO.png rename to docs/manual/_static/pictures/VORTEX_LOGO.png diff --git a/src/docs/_static/pictures/settings-icon.png b/docs/manual/_static/pictures/settings-icon.png similarity index 100% rename from src/docs/_static/pictures/settings-icon.png rename to docs/manual/_static/pictures/settings-icon.png diff --git a/src/docs/conf.py.in b/docs/manual/conf.py.in similarity index 100% rename from src/docs/conf.py.in rename to docs/manual/conf.py.in diff --git a/src/docs/config.rst b/docs/manual/config.rst similarity index 100% rename from src/docs/config.rst rename to docs/manual/config.rst diff --git a/src/docs/ddsc.rst b/docs/manual/ddsc.rst similarity index 100% rename from src/docs/ddsc.rst rename to docs/manual/ddsc.rst diff --git a/src/docs/index.rst b/docs/manual/index.rst similarity index 100% rename from src/docs/index.rst rename to docs/manual/index.rst diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..28e9944 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,105 @@ +# +# 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 +# +set(CMAKE_INSTALL_EXAMPLESDIR "${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}/examples") + +add_subdirectory(helloworld) +add_subdirectory(roundtrip) +add_subdirectory(throughput) + +if (BUILD_DOCS) + message(STATUS "${CMAKE_PROJECT_NAME} Examples documentation: Success (build)") + set(EXAMPLES_HTML_ARCHIVE "${CMAKE_PROJECT_NAME}ExamplesHTML.tar.gz") + # Process sphinx configuration file + set(sph_conf_author "Eclipse Cyclone DDS project") + string(TIMESTAMP sph_conf_copyright "%Y") + set(sph_conf_version "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") + set(sph_conf_release "${PROJECT_VERSION}") + configure_file(sphinx-conf.py.in conf.py @ONLY) + + set(builder_output "examples_html_output") + set(builder_log "sphinx-examples-html.log") + add_custom_command(OUTPUT ${builder_output} + COMMAND ${SPHINX_EXECUTABLE} + -b html + -d ${CMAKE_CURRENT_BINARY_DIR}/cache + -c ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} > ${builder_log} + COMMENT "Running Sphinx for examples html output" + VERBATIM) + + # OUTPUT is a fake target / symbolic name, not an actual file + set_property(SOURCE ${builder_output} PROPERTY SYMBOLIC 1) + add_custom_target(examples_docs ALL DEPENDS ${builder_output}) + + # Archive the output html files, will become a jenkins artifact for use in other jobs + # TODO this hardcoded list and archiving should be replaced by ExternalData refs + set(html_outputs + "_static" + "search.html" + "searchindex.js" + "genindex.html" + "examples.html" + "helloworld/readme.html" + "roundtrip/readme.html" + "throughput/readme.html") + + add_custom_command(OUTPUT ${builder_output} + COMMAND ${CMAKE_COMMAND} + -E tar "zcf" + "${EXAMPLES_HTML_ARCHIVE}" + ${html_outputs} + APPEND + VERBATIM) + + # Remove generated files when cleaning the build tree + set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES + "cache" + "${builder_log}" + "objects.inv" + ${html_outputs} + "_sources" + "${EXAMPLES_HTML_ARCHIVE}") +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "Windows") + set(platform_exclude "examples/helloworld/Makefile") +elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") + set(platform_exclude "examples/helloworld/vs|examples/helloworld/HelloWorld\.sln") +else() + set(platform_exclude "this_is_a_placeholder") +endif() + +# Install example source-files +install( + DIRECTORY "${PROJECT_SOURCE_DIR}/examples/" + DESTINATION "${CMAKE_INSTALL_EXAMPLESDIR}" + COMPONENT dev + PATTERN "CMakeLists.export" EXCLUDE + PATTERN "examples/CMakeLists.txt" EXCLUDE + REGEX ${platform_exclude} EXCLUDE + REGEX "\.rst|\.py" EXCLUDE) + +# Install example html docs files +# TODO this should be replaced by install commands that use ExternalData refs (preferably in examples' CMakeLists.txt) +install( + DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" + DESTINATION "${CMAKE_INSTALL_EXAMPLESDIR}" + COMPONENT dev + FILES_MATCHING + PATTERN "CMakeFiles" EXCLUDE + PATTERN "cache" EXCLUDE + PATTERN "_sources" EXCLUDE + PATTERN "*.html" + PATTERN "*.js" + PATTERN "_static/*") + diff --git a/src/examples/examples.rst b/examples/examples.rst similarity index 100% rename from src/examples/examples.rst rename to examples/examples.rst diff --git a/src/examples/helloworld/CMakeLists.export b/examples/helloworld/CMakeLists.export similarity index 100% rename from src/examples/helloworld/CMakeLists.export rename to examples/helloworld/CMakeLists.export diff --git a/src/examples/helloworld/CMakeLists.txt b/examples/helloworld/CMakeLists.txt similarity index 100% rename from src/examples/helloworld/CMakeLists.txt rename to examples/helloworld/CMakeLists.txt diff --git a/src/examples/helloworld/HelloWorld.sln b/examples/helloworld/HelloWorld.sln similarity index 100% rename from src/examples/helloworld/HelloWorld.sln rename to examples/helloworld/HelloWorld.sln diff --git a/src/examples/helloworld/HelloWorldData.idl b/examples/helloworld/HelloWorldData.idl similarity index 100% rename from src/examples/helloworld/HelloWorldData.idl rename to examples/helloworld/HelloWorldData.idl diff --git a/src/examples/helloworld/Makefile b/examples/helloworld/Makefile similarity index 100% rename from src/examples/helloworld/Makefile rename to examples/helloworld/Makefile diff --git a/src/examples/helloworld/publisher.c b/examples/helloworld/publisher.c similarity index 100% rename from src/examples/helloworld/publisher.c rename to examples/helloworld/publisher.c diff --git a/src/examples/helloworld/readme.rst b/examples/helloworld/readme.rst similarity index 100% rename from src/examples/helloworld/readme.rst rename to examples/helloworld/readme.rst diff --git a/src/examples/helloworld/subscriber.c b/examples/helloworld/subscriber.c similarity index 100% rename from src/examples/helloworld/subscriber.c rename to examples/helloworld/subscriber.c diff --git a/src/examples/helloworld/vs/HelloWorldPublisher.vcxproj b/examples/helloworld/vs/HelloWorldPublisher.vcxproj similarity index 100% rename from src/examples/helloworld/vs/HelloWorldPublisher.vcxproj rename to examples/helloworld/vs/HelloWorldPublisher.vcxproj diff --git a/src/examples/helloworld/vs/HelloWorldSubscriber.vcxproj b/examples/helloworld/vs/HelloWorldSubscriber.vcxproj similarity index 100% rename from src/examples/helloworld/vs/HelloWorldSubscriber.vcxproj rename to examples/helloworld/vs/HelloWorldSubscriber.vcxproj diff --git a/src/examples/helloworld/vs/HelloWorldType.vcxproj b/examples/helloworld/vs/HelloWorldType.vcxproj similarity index 100% rename from src/examples/helloworld/vs/HelloWorldType.vcxproj rename to examples/helloworld/vs/HelloWorldType.vcxproj diff --git a/src/examples/helloworld/vs/directories.props b/examples/helloworld/vs/directories.props similarity index 100% rename from src/examples/helloworld/vs/directories.props rename to examples/helloworld/vs/directories.props diff --git a/performance/ethload b/examples/perfscript/ethload similarity index 100% rename from performance/ethload rename to examples/perfscript/ethload diff --git a/performance/quick-microbenchmark b/examples/perfscript/quick-microbenchmark similarity index 100% rename from performance/quick-microbenchmark rename to examples/perfscript/quick-microbenchmark diff --git a/performance/throughput-fanout-test b/examples/perfscript/throughput-fanout-test similarity index 100% rename from performance/throughput-fanout-test rename to examples/perfscript/throughput-fanout-test diff --git a/performance/throughput-test b/examples/perfscript/throughput-test similarity index 100% rename from performance/throughput-test rename to examples/perfscript/throughput-test diff --git a/performance/throughput-test-extract b/examples/perfscript/throughput-test-extract similarity index 100% rename from performance/throughput-test-extract rename to examples/perfscript/throughput-test-extract diff --git a/performance/throughput-test-plot b/examples/perfscript/throughput-test-plot similarity index 100% rename from performance/throughput-test-plot rename to examples/perfscript/throughput-test-plot diff --git a/src/examples/roundtrip/CMakeLists.txt b/examples/roundtrip/CMakeLists.txt similarity index 100% rename from src/examples/roundtrip/CMakeLists.txt rename to examples/roundtrip/CMakeLists.txt diff --git a/src/examples/roundtrip/RoundTrip.idl b/examples/roundtrip/RoundTrip.idl similarity index 100% rename from src/examples/roundtrip/RoundTrip.idl rename to examples/roundtrip/RoundTrip.idl diff --git a/src/examples/roundtrip/ping.c b/examples/roundtrip/ping.c similarity index 100% rename from src/examples/roundtrip/ping.c rename to examples/roundtrip/ping.c diff --git a/src/examples/roundtrip/pong.c b/examples/roundtrip/pong.c similarity index 100% rename from src/examples/roundtrip/pong.c rename to examples/roundtrip/pong.c diff --git a/src/examples/roundtrip/readme.rst b/examples/roundtrip/readme.rst similarity index 100% rename from src/examples/roundtrip/readme.rst rename to examples/roundtrip/readme.rst diff --git a/src/examples/sphinx-conf.py.in b/examples/sphinx-conf.py.in similarity index 97% rename from src/examples/sphinx-conf.py.in rename to examples/sphinx-conf.py.in index a364e80..acd4026 100644 --- a/src/examples/sphinx-conf.py.in +++ b/examples/sphinx-conf.py.in @@ -68,7 +68,7 @@ html_theme_options = { 'show_powered_by': False } # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['@PROJECT_SOURCE_DIR@/docs/_static'] +html_static_path = ['@PROJECT_SOURCE_DIR@/docs/manual/_static'] # Custom sidebar templates, must be a dictionary that maps document names # to template names. diff --git a/src/examples/throughput/CMakeLists.txt b/examples/throughput/CMakeLists.txt similarity index 100% rename from src/examples/throughput/CMakeLists.txt rename to examples/throughput/CMakeLists.txt diff --git a/src/examples/throughput/Throughput.idl b/examples/throughput/Throughput.idl similarity index 100% rename from src/examples/throughput/Throughput.idl rename to examples/throughput/Throughput.idl diff --git a/src/examples/throughput/publisher.c b/examples/throughput/publisher.c similarity index 100% rename from src/examples/throughput/publisher.c rename to examples/throughput/publisher.c diff --git a/src/examples/throughput/readme.rst b/examples/throughput/readme.rst similarity index 100% rename from src/examples/throughput/readme.rst rename to examples/throughput/readme.rst diff --git a/src/examples/throughput/subscriber.c b/examples/throughput/subscriber.c similarity index 100% rename from src/examples/throughput/subscriber.c rename to examples/throughput/subscriber.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e5beb7a..ca59544 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others +# Copyright(c) 2019 ADLINK Technology Limited and others # # This program and the accompanying materials are made available under the # terms of the Eclipse Public License v. 2.0 which is available at @@ -11,208 +11,20 @@ # cmake_minimum_required(VERSION 3.7) -# Set a default build type if none was specified -set(default_build_type "RelWithDebInfo") -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - message(STATUS "Setting build type to '${default_build_type}' as none was specified.") - set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE - STRING "Choose the type of build." FORCE) - # Set the possible values of build type for cmake-gui - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Release" "MinSizeRel" "RelWithDebInfo") +if(NOT ${PROJECT_NAME} STREQUAL "CycloneDDS") + get_filename_component(dir ${CMAKE_CURRENT_LIST_DIR} DIRECTORY) + message(FATAL_ERROR "Top-level CMakeLists.txt was moved to the top-level directory. Please run cmake on ${dir} instead of ${CMAKE_CURRENT_LIST_DIR}") endif() -# By default don't treat warnings as errors, else anyone building it with a different compiler that -# just happens to generate a warning, as well as anyone adding or modifying something and making a -# small mistake would run into errors. CI builds can be configured differently. -option(WERROR "Treat compiler warnings as errors" OFF) - -FUNCTION(PREPEND var prefix) - SET(listVar "") - FOREACH(f ${ARGN}) - LIST(APPEND listVar "${prefix}/${f}") - ENDFOREACH(f) - SET(${var} "${listVar}" PARENT_SCOPE) -ENDFUNCTION(PREPEND) - -# Update the git submodules -execute_process(COMMAND git submodule init - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) -execute_process(COMMAND git submodule update - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - -# Set module path before defining project so platform files will work. -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules") -set(CMAKE_PROJECT_NAME_FULL "Eclipse Cyclone DDS") -set(PROJECT_NAME "CycloneDDS") -project(${PROJECT_NAME} VERSION 0.1.0) - -# Set some convenience variants of the project-name -string(REPLACE " " "-" CMAKE_PROJECT_NAME_DASHED "${CMAKE_PROJECT_NAME_FULL}") -string(TOUPPER ${CMAKE_PROJECT_NAME} CMAKE_PROJECT_NAME_CAPS) -string(TOLOWER ${CMAKE_PROJECT_NAME} CMAKE_PROJECT_NAME_SMALL) - -set(CMAKE_C_STANDARD 99) -if(CMAKE_SYSTEM_NAME STREQUAL "VxWorks") - add_definitions(-std=c99) -endif() - -if(${CMAKE_C_COMPILER_ID} STREQUAL "SunPro") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64 -xc99 -D__restrict=restrict -D__deprecated__=") - set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} -m64") -endif() - -# Conan -if(EXISTS "${CMAKE_BINARY_DIR}/conanbuildinfo.cmake") - include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) - if(APPLE) - # By default Conan strips all RPATHs (see conanbuildinfo.cmake), which - # causes tests to fail as the executables cannot find the library target. - # By setting KEEP_RPATHS, Conan does not set CMAKE_SKIP_RPATH and the - # resulting binaries still have the RPATH information. This is fine because - # CMake will strip the build RPATH information in the install step. - # - # NOTE: - # Conan's default approach is to use the "imports" feature, which copies - # all the dependencies into the bin directory. Of course, this doesn't work - # quite that well for libraries generated in this Project (see Conan - # documentation). - # - # See the links below for more information. - # https://github.com/conan-io/conan/issues/337 - # https://docs.conan.io/en/latest/howtos/manage_shared_libraries/rpaths.html - # https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling - conan_basic_setup(KEEP_RPATHS) - else() - conan_basic_setup() - endif() - conan_define_targets() -endif() - -# Set reasonably strict warning options for clang, gcc, msvc -# Enable coloured ouput if Ninja is used for building -if("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") - #message(STATUS clang) - add_compile_options(-Wall -Wextra -Wconversion -Wunused -Wmissing-prototypes) - if(${WERROR}) - add_compile_options(-Werror) - endif() - if("${CMAKE_GENERATOR}" STREQUAL "Ninja") - add_compile_options(-Xclang -fcolor-diagnostics) - endif() -elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") - #message(STATUS gcc) - add_compile_options(-Wall -Wextra -Wconversion -Wmissing-prototypes) - if(${WERROR}) - add_compile_options(-Werror) - endif() - if("${CMAKE_GENERATOR}" STREQUAL "Ninja") - add_compile_options(-fdiagnostics-color=always) - endif() -elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") - #message(STATUS msvc) - add_compile_options(/W3) - if(${WERROR}) - add_compile_options(/WX) - endif() -endif() - -# I don't know how to enable warnings properly so that it ends up in Xcode projects as well -if(${CMAKE_GENERATOR} STREQUAL "Xcode") - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_EMPTY_BODY YES) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_SHADOW YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_BOOL_CONVERSION YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_CONSTANT_CONVERSION YES) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_64_TO_32_BIT_CONVERSION YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_ENUM_CONVERSION YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_FLOAT_CONVERSION YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_INT_CONVERSION YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_NON_LITERAL_NULL_CONVERSION YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_IMPLICIT_SIGN_CONVERSION YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_INFINITE_RECURSION YES) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED YES) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_ABOUT_RETURN_TYPE YES) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_MISSING_PARENTHESES YES) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS YES) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_ABOUT_MISSING_NEWLINE YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_ASSIGN_ENUM YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY YES) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_SIGN_COMPARE YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_STRICT_PROTOTYPES YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_COMMA YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION YES) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNINITIALIZED_AUTOS YES_AGGRESSIVE) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_FUNCTION YES) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_LABEL YES) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_PARAMETER YES) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VALUE YES) - set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VARIABLE YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_DOCUMENTATION_COMMENTS YES) - set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_MISSING_PROTOTYPES YES) -endif() - -# Make it easy to enable one of Clang's/gcc's analyzers, and default to using -# the address sanitizer for ordinary debug builds; gcc is giving some grief on -# Travis, so don't enable it for gcc by default -if(NOT USE_SANITIZER) - if(${CMAKE_BUILD_TYPE} STREQUAL "Debug" AND - NOT (${CMAKE_GENERATOR} STREQUAL "Xcode") AND - (${CMAKE_C_COMPILER_ID} STREQUAL "Clang" - OR ${CMAKE_C_COMPILER_ID} STREQUAL "AppleClang")) - message(STATUS "Enabling address sanitizer; set USE_SANITIZER=none to prevent this") - set(USE_SANITIZER address) - else() - set(USE_SANITIZER none) - endif() -endif() -if(NOT (${USE_SANITIZER} STREQUAL "none")) - message(STATUS "Sanitizer set to ${USE_SANITIZER}") - add_compile_options(-fno-omit-frame-pointer -fsanitize=${USE_SANITIZER}) - link_libraries(-fno-omit-frame-pointer -fsanitize=${USE_SANITIZER}) -endif() - -include(GNUInstallDirs) -include(AnalyzeBuild) -if(APPLE) - set(CMAKE_INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR}") -else() - set(CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") -endif() -# Include Coverage before CTest so that COVERAGE_COMMAND can be modified -# in the Coverage module should that ever be necessary. -include(Coverage) -set(MEMORYCHECK_COMMAND_OPTIONS "--track-origins=yes --leak-check=full --trace-children=yes --child-silent-after-fork=yes --xml=yes --xml-file=TestResultValgrind_%p.xml --tool=memcheck --show-reachable=yes --leak-resolution=high") - -# By default building the testing tree is enabled by including CTest, but -# since not everybody has CUnit, and because it is not strictly required to -# build the product itself, switch to off by default. -option(BUILD_TESTING "Build the testing tree." OFF) -include(CTest) - -# Build all executables and libraries into the top-level /bin and /lib folders. -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") - -add_subdirectory(idlc) add_subdirectory(ddsrt) -add_subdirectory(etc) + +# some of the tests in the core rely on preprocessing IDL, so idlc has to +# come first +if(BUILD_IDLC) + add_subdirectory(idlc) +endif() add_subdirectory(core) add_subdirectory(tools) -add_subdirectory(scripts) - -option(USE_DOCS "Enable documentation." OFF) -if(USE_DOCS) - add_subdirectory(docs) -else() - message(STATUS "${CMAKE_PROJECT_NAME} documentation: disabled (-DUSE_DOCS=1 to enable)") -endif() - -add_subdirectory(examples) - -if(BUILD_TESTING AND HAVE_MULTI_PROCESS) +if(BUILD_TESTING AND HAVE_MULTI_PROCESS AND BUILD_IDLC) add_subdirectory(mpt) endif() - -# Pull-in CPack and support for generating Config.cmake and packages. -include(Packaging) diff --git a/src/cmake/CoverageSettings.cmake.in b/src/cmake/CoverageSettings.cmake.in deleted file mode 100644 index 818584e..0000000 --- a/src/cmake/CoverageSettings.cmake.in +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# -cmake_minimum_required(VERSION 3.5) - -set(COVERAGE_SOURCE_DIR "@PROJECT_SOURCE_DIR@") -set(COVERAGE_RUN_DIR "@CMAKE_BINARY_DIR@") -set(COVERAGE_OUTPUT_DIR "@CMAKE_BINARY_DIR@/coverage") - -# TODO: Make this a list instead of separate variables when more directories -# need to be excluded. Currently there's actually only one directory to -# be excluded, but when the test(s) are moved, more directories will be -# added. I just added two directories to indicate how the coverage -# generators handle multiple exclusion directories. -# -# Do not include the various test directories. -set(COVERAGE_EXCLUDE_TESTS "tests") -set(COVERAGE_EXCLUDE_EXAMPLES "examples") -set(COVERAGE_EXCLUDE_BUILD_SUPPORT "cmake") - -# Add this flag when you want to suppress LCOV and ctest outputs during coverage collecting. -#set(COVERAGE_QUIET_FLAG "--quiet") - diff --git a/src/cmake/launch-c.bat.in b/src/cmake/launch-c.bat.in deleted file mode 100644 index 8f771d9..0000000 --- a/src/cmake/launch-c.bat.in +++ /dev/null @@ -1,26 +0,0 @@ -@echo off -REM Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -REM -REM This program and the accompanying materials are made available under the -REM terms of the Eclipse Public License v. 2.0 which is available at -REM http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -REM v. 1.0 which is available at -REM http://www.eclipse.org/org/documents/edl-v10.php. -REM -REM SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - -REM VxWorks toolchain requires WIND_BASE to be exported, should the user be -REM compiling for VxWorks and not have WIND_BASE exported, do that here before -REM invoking the compiler. -if "%WIND_BASE%" == "" ( - set WIND_BASE="@WIND_BASE@" -) - -REM Strip C compiler from command line arguments for compatibility because -REM this launcher may also be used from an integrated development environment -REM at some point. -if "%1" == "@CMAKE_C_COMPILER@" ( - shift -) - -"@CMAKE_C_COMPILER@" %* diff --git a/src/cmake/launch-c.in b/src/cmake/launch-c.in deleted file mode 100644 index 27a64da..0000000 --- a/src/cmake/launch-c.in +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh -# -# 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 -# - -# VxWorks toolchain requires WIND_BASE to be exported, should the user be -# compiling for VxWorks and not have WIND_BASE exported, to that here before -# invoking the compiler. -if [ -z "${WIND_BASE}" ] && [ -n "@WIND_BASE@" ]; then - WIND_BASE="@WIND_BASE@" - export WIND_BASE -fi - -if [ -n "@WIND_LMAPI@" ]; then - if [ -z "${LD_LIBRARY_PATH}" ]; then - LD_LIBRARY_PATH="@WIND_LMAPI@" - export LD_LIBRARY_PATH - elif [[ "${LD_LIBRARY_PATH}" == ?(*:)"@WIND_LMAPI@"?(:*) ]]; then - LD_LIBRARY_PATH="@WIND_LMAPI@:${LD_LIBRARY_PATH}" - export LD_LIBRARY_PATH - fi -fi - -# Strip C compiler from command line arguments for compatibility because this -# launcher may also be used from an integrated development environment at some -# point. -if [ "$1" = "@CMAKE_C_COMPILER@" ]; then - shift -fi - -exec "@CMAKE_C_COMPILER@" "$@" - diff --git a/src/cmake/launch-cxx.bat.in b/src/cmake/launch-cxx.bat.in deleted file mode 100644 index 5d38b3d..0000000 --- a/src/cmake/launch-cxx.bat.in +++ /dev/null @@ -1,26 +0,0 @@ -@echo off -REM Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -REM -REM This program and the accompanying materials are made available under the -REM terms of the Eclipse Public License v. 2.0 which is available at -REM http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -REM v. 1.0 which is available at -REM http://www.eclipse.org/org/documents/edl-v10.php. -REM -REM SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - -REM VxWorks toolchain requires WIND_BASE to be exported, should the user be -REM compiling for VxWorks and not have WIND_BASE exported, do that here before -REM invoking the compiler. -if "%WIND_BASE%" == "" ( - set WIND_BASE="@WIND_BASE@" -) - -REM Strip C compiler from command line arguments for compatibility because -REM this launcher may also be used from an integrated development environment -REM at some point. -if "%1" == "@CMAKE_CXX_COMPILER@" ( - shift -) - -"@CMAKE_CXX_COMPILER@" %* diff --git a/src/cmake/launch-cxx.in b/src/cmake/launch-cxx.in deleted file mode 100644 index 0d3bd19..0000000 --- a/src/cmake/launch-cxx.in +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh -# -# 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 -# - -# VxWorks toolchain requires WIND_BASE to be exported, should the user be -# compiling for VxWorks and not have WIND_BASE exported, to that here before -# invoking the compiler. -if [ -z "${WIND_BASE}" ] && [ -n "@WIND_BASE@" ]; then - WIND_BASE="@WIND_BASE@" - export WIND_BASE -fi - -if [ -n "@WIND_LMAPI@" ]; then - if [ -z "${LD_LIBRARY_PATH}" ]; then - LD_LIBRARY_PATH="@WIND_LMAPI@" - export LD_LIBRARY_PATH - elif [[ "${LD_LIBRARY_PATH}" == ?(*:)"@WIND_LMAPI@"?(:*) ]]; then - LD_LIBRARY_PATH="@WIND_LMAPI@:${LD_LIBRARY_PATH}" - export LD_LIBRARY_PATH - fi -fi - -# Strip C compiler from command line arguments for compatibility because this -# launcher may also be used from an integrated development environment at some -# point. -if [ "$1" = "@CMAKE_CXX_COMPILER@" ]; then - shift -fi - -exec "@CMAKE_CXX_COMPILER@" "$@" - diff --git a/src/cmake/modules/Coverage.cmake b/src/cmake/modules/Coverage.cmake deleted file mode 100644 index 5e6fc6d..0000000 --- a/src/cmake/modules/Coverage.cmake +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# -if("${CMAKE_BUILD_TYPE}" STREQUAL "Coverage") - set(BUILD_TYPE_SUPPORTED False) - mark_as_advanced(BUILD_TYPE_SUPPORTED) - if(CMAKE_COMPILER_IS_GNUCXX) - set(BUILD_TYPE_SUPPORTED True) - elseif(("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") AND - ("${CMAKE_C_COMPILER_VERSION}" VERSION_GREATER "3.0.0")) - set(BUILD_TYPE_SUPPORTED True) - endif() - - if(NOT BUILD_TYPE_SUPPORTED) - message(FATAL_ERROR "Coverage build type not supported. (GCC or Clang " - ">3.0.0 required)") - endif() - - # NOTE: Since either GCC or Clang is required for now, and the coverage - # flags are the same for both, there is no need for seperate branches - # to set compiler flags. That might change in the future. - - # CMake has per build type compiler and linker flags. If 'Coverage' is - # chosen, the flags below are automatically inserted into CMAKE_C_FLAGS. - # - # Any optimizations are disabled to ensure coverage results are correct. - # See https://gcc.gnu.org/onlinedocs/gcc/Gcov-and-Optimization.html. - set(CMAKE_C_FLAGS_COVERAGE - "-DNDEBUG -g -O0 --coverage -fprofile-arcs -ftest-coverage") - set(CMAKE_CXX_FLAGS_COVERAGE - "-DNDEBUG -g -O0 --coverage -fprofile-arcs -ftest-coverage") - mark_as_advanced( - CMAKE_C_FLAGS_COVERAGE - CMAKE_CXX_FLAGS_COVERAGE - CMAKE_EXE_LINKER_FLAGS_COVERAGE - CMAKE_SHARED_LINKER_FLAGS_COVERAGE) - - configure_file(${CMAKE_MODULE_PATH}/../CoverageSettings.cmake.in CoverageSettings.cmake @ONLY) - - message(STATUS "Coverage build type available") -endif() - diff --git a/src/cmake/modules/Packaging/banner.bmp b/src/cmake/modules/Packaging/banner.bmp deleted file mode 100644 index e795038430d7b54ccdb7b28d098b787414f36d3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85894 zcmeI52Ut|sw#UtliHb%6O}Tld8Hx&0Ofi>|XDSrf5u1gEclBKzflP9p+4X>u_)wMo`e?eeYh^e4FELXPw1w&G%=y&ptEr zmPeSqGJ<-|hM%eM(+JHu@b4=l-htzY5#}&{Vf=`mpPmjl$nk{)kN^@u0{_kgP{;qB zqldmD0VIF~0@AB!C3|d;(IbOu3LEkwhXJS)2J!GBa;n~k}JczH!v?J{DL* z0!RP}yf^`c5JN>KmkV$H=)LMSe;YOLRU^}Pn1g-g34_(?X+v}db$p1Ra2gUo0!ZN5 z1eA3dR9qzLPVkxKv-)*^o3T*5tzNzQivX-BPa9(WDc43Fe+nENLIOwt2@HdPiXy|A zXAebycGDsbN53^{(HyiMFL0w2@FO+MTlWqb@{FEP4D}! zp)zqO0lmj@C%FDFsxtrinzS>hnN4x|PM3l}~xTI_)3o_%PyxQ;`4?Kmr32P*!1h*ys8MZWL?$ zHs=YxYt&%JA$5n-S`9Ms7`7&;Ig|*OF-OxJUpytJok1NRFeuoG1dsp{7zP1l9T#08*9GZ@HXsA30OPMfA!cv`#0jZ zzZ>PO9?jB>f*gF4dTiLcJGt74`#(-h*NRVh|J;#KxRSDwVby6bQOAcGEu4o0kN^@; zA)u_ekXAzxBs=)5dY#%|xMr-6`KZVplXnSpV>~8-jzfkH1v2!+)G0f8Iy(v7*r2x) z+~2DyfBrp)v_GihDsjOk5BkUZCQfPXTGb)_*$#^t{M|;_eR2=DLd1(6Ax%5rfJ3cy%q1Oncy~&D(p!~G4E3w zSDe+OT-4*;-no^35G<(J97>b+3Uyp1I@m-4NB{{ugTMd^E0bOLF&4I?M7XF&Fw`S9 zP1x!?X=f&-;GpA4ncCa7|J}u9ER#773RFD3H4>9QOi21LA^F3&#L34`yL5K93}CkZ zmkK>Ofp!#i{22kmVI+VAkbp9QC&d(c>Kh9)zndHD|7HwJGnPFuf~{feJSHsRz2uCZ zd_47Ic>KrNWvmTj%sR%HwT#g=&ZD>Q`XC8zcxFP;+L@^|ns2|SH} zLOqo#QaIu8`RKs(FGAA449Wa5gtyQ?@b7N^6WIP5EME(1_H8SVX-o4WP5E0)`N2zxAph^v;3_idP_uH{H`H-OjIe?P zkN^@Gl)!)@-q!wTbD*xh)2mh~_ABzj&G`Wi%n3G*Bez8VS4x&v^8ODkxL(Whwyg~{ zac~@A&lqn(_%6y0_03qYC;h#IG_CcpR_^#W>v)S5d7);6uQ}mo$qzVw_X0TaODJ(qwp6N3JN;NbVs&N5<<8oBn3&HDyI!nDw@=LDOv+YD}*Q z`_kXtoV9EzKfr?TWwqDA!SQdaW6eP8SMUQ@XM649>iPstShr!MgY#>4thdZFH!tV= zFX#C{VIGUAY^jIqD1=)!`0hj6J=AeUn6QEbkN^@Gm;f!}kJ==6E4mA-y6;zY7u86A zy;0~EvS2NH>RR@+wVY2@MXt1Sn`p-vW5-mpcOK~zHPu`Yx}4}KywKGVD=hajEiyRf z8ElJ8jz{tw2hJp0&f8GdyT0wXYd!m)$*kjXtmCol6H%uNFG!V^R!I0HT!~a6>&g|{ zUDWY`!-l;`00|(0{sd&Dbt2ou$|a#?OT)^RhE}Xf=bG>?eVQqR@(J&TmEST*%k=ZcKY ztfP^)>q@Iy>MNV;iyA7qw`!}}V3nL&g>UKV$hmR0s-ATo4hcx0# zXA)v#LcH-TwH))^kzfbrI6IfuZQN%W5FK-~k6G~9X8Zs%!f$Dom*B=3u>_P`_D8+k zL?FqzD-}y99WSW7w~Xs^x-fshl$`byb-aJXu!RJW021g=pijqTvTl*oETUYGRkk#3 zhh>hNCE@ldQ87c%VeR$RhK(a26SrlmZP++!ZX$QaLAf!HG$zQ|*<{{*ka2l?N3++K z>5dyl%}eC!=gN(UPBS9VobUo2hh=f=oRG@qx-PNY?-!{~2D$i%q_I=hA?gbHK4o#H zhtuI5O&zTYPZSl}Q`GVP5yKV|KmtfWi2x`jqQwv0DzUEj2G(%2BVV*XL_+(WW?hsdwcA@l!72n(LQ1~iAa7Mu? zg?uY2w5O=!N)f{<59 zoVOfq$7n zK>0N9=6MO3R(VV_UVu5Vc^MJ5_~1EH-nJz~;u0dkl%JGdaPoF-$(5?YE0u-6SKJke z#R>&i7zCTBml2Zll?j{lC&bv_wX-CW&cqi2)iV-W{y@TzMf7ll+zV+v=mg!-&veNM>= zUXX>rVoqVC7;^zB4cs5w1^I<7#36(oQJkU&2I z3b`c3vXtu*tqjuU6xrG>BPFurs}k)D`D~)df^fGGcz+e0tK-yS?03~7XR`%AAgy4~ zFHn|9WZ&htOlKF*;7~=6Rq=WF|ExN=aS4%ZK!}V8=|70`Rs@S)Yynf5S5ARX3Qtrj zw7aO|{lbO~B!C2v08KzyF=2JPv{`C?LVUJd2HQwLi_6>Ot4@=PcySg4+nn!d#`QJy zxU(oV(K3f)mhI(oZ2NQ4)59`{=S980VoT2`x7o+?jn0ra`-C(3+`QH--0{1 zjygU-{IClNAc2>hfI@TW3bkdWOXhY)G~KgwI!id6U8KhWD3BWvazjGC;IRCM zGWq(b`suD!)0kCX`qrMiDT38-6+3hjZhO{s%5A=v8s|Wf%*>U{2yZY->oVrUW^+o) z4YoHKWJnG9lyQBYe8G3J!bWPx3zXV+8T&`^jfd1ubFfB-33dD>f4kzZj|7mw00f@Y z-<-P=gB*$B?iPK6Sqkd+t)R;%v*W;4$1(3wcpa||t zwKK@Lo+j$}0FlEkB!C2v01yCuRDMDFEPN#WTtFJab3J*|8KE`$Ordd(n37<~p!wpt zhsE_B@ImBMb{v{h4-b3_t3|Y(0Y#kdg!zFNBr^z7-{XP4n^2EYXt=Az_>ffJqePEg zq|Xu>rgcz%DtazqNQet+WwmXxFAjy=ZONZ2Sd$|rnXyQ{+S}SU9mzai?L3568NpX#cJ`pa5I!*-$Uq}E6AOQsd zT49f0ZvB`c^h~eq?C$;SZN1KFxS#{7H zx`-=gf@SWH%|@F`^f#Bx+E}l9~U%IPM0-}=!@tsgiGcb{s4 zAvm4(8FgF{JFFl9B!C1c0<^r=J`#HzsQq2oNjD)Ohv#=JqbjK9Fx`vwIK^KDmEJ7v zqDQNnNDpq^wFkXTx^sv}unhM_mv1YlEOUyda*CN8Vcmn?>((@hx8&B}uOsQ$JZhJ0 z5!Bx(>&AVD_+~`{NB{{8N`Tg1*yPvIErsO{x(Tz-TyLA>|DadL*~L+Z8$^$v$La2r zT)WiL*gy_ZyOpPbWyt+!`}Cyw?!~$+YTIIG7kmRyZ^r${&GtS1MLWHPP?Fv6|9GN7 zB<@{*r+){`#|Moi4j=&}@NyDRh^+GMN~ps+xF5HUUQ~hmnGb6FHW%K%(dNG3+7E{w zD$X5x1uVC9Njdv!>3m$DUHnC0>4kf}`8X_}w>FX?c6U}zy99+}dZXla-x53>Ak^`f z^NotXH4;DqgAy1_g5d;Mv1&ijl%HT7>`&OtSM@|cWK*W{tV#^MMKd7&vJ~3QbqlZ!l?T0Po zNhcd457oyUX^1}29F|>MRY7feq$Rtyvb#*!>jvGU@ECPmfdVT?00|(0UIK?RZY}&c z-E?}^Vx3Hn)hEgRkM<}sVp^b8sHuz&MZ^_zluhL%UEN}L8hYqa>Tk&7G+%id)KSM( zfM62|Ac2>i0O+PfEdAEy>|))_m9w%R6b|V*dxaLicm)DbTG(V`A}}}R|8}+QPRJz2}yTXr+6FZr)7Fv_z!{Snp5>P zeH&EZx=)4&b^J*t*nm{huKd~!X6}m1dzbXLqH*#uq^(6oQ%_#CP_(0JK0;>NKtq12E@Vi uSyjjX+)ycSykOm>a z?#%R=>bq;IyQ{9gZawo`RapiVi3kY-0s>V|R!SWL0`lT><3oV^lz7NgSbl!NnJCCe zL4f~z=XI7Qeo7FXWOZC2AXusY+aLkOq8^_@csDsEY4{yP5_l%Av3CUJG|~Yof;vPD3Yx|ki&?u3{fBi?Z<q!9(OP0= zUw(Ve8AW-rvn#x!74vJ#^H*BRjzhiMcu3q8R1`!W}@r9Y{5OAD5N(~7We^U z?xB4Hu`N=ur`VaH9i&%tePUtlFDjX%T`IHNj5u}{bh7?Tx`gsCZGqi@*j4W~rd>BX zlR}v}qaEu|L>5mC@BeUBNoqteG1J=~i|QcSw~SVFOpQB!hza?}3pYuYT(CVR_;%)Q z|52CrtPggF?GbV3;9_dfbFH0kvtxgoiie>V;5DKbXad#-I9MKpUJ9Zw!aY6;93FA{ zP8eZ^Y5ll;mpi&WAa>YTnTN^$ZH-J_ur=4l?q0C?#93CVh%|D2j#?f!Bt4_d)o~2%d>B)c37y-dB!+^@$yA>U#s`UT z^G9qAuIc$A3Ejbza-|pExzQXD&X3y5S5qELi;SOOZD~%a@}W#0pfAy~1K%Bk?`f6mPV(sftF5s8EQu`7I*sq2BBfGOfv zT-+=&&6%u8=bLES@6pa#990nH$Hrc#?@KWzSL65hogNFj@?WNYBADY&0f9d^`R^jT zbVhfFe@wQUfO-!a09x$I=?!UC9k0?-Qkx86a2HO#q+BcqCfgLq9aWSjv(~8z7hnF6 z%eIbd{6ImgVv19rs;StSV5l9);^#Y3s<7PAh9{Ebvxfw3hUU=hHc9YKy9*mELeHZi zIgQ>EDMwPVavnKxv5EkAN}=(0Non_|cUh|OFGZ34B{ zU(!RCCw8}~T-uF}=75JXD_BRqaj+RvI%J8$!&s zDcbNS=p2KjNh{Kq{)H+29QabQqXx%SC`24lehQ!ijvP=rweoAa9^I^Pv2h&UmO6rM zPfu-H1aznPDJ7e_qZC0xl^$pq;>O57L~|R<$%fg(9~(#FesoTdes#wnyqkww-gpv- z!y#Mkwk=eVB3=pWU7ol>8aJ42OKr=Ml6p+0^)b$QEQ>pgri`JSk+{7@xy;p^9@V$y zW08w!vg_$*ws|G~J1QodmDsMnxvVqz*PPKDjsC%s-yCgS=x5UgTnchl8cHqAuX;WH zg$e4v=|Q@Y%L|fE#yA3}a&2&eolIG!_0nVxZ=SD2V0uq2<^I=pfZ4d#upuFfh?`t2 zKi3!FwYEx!%d(b@Ewn8^==95%dSkh>au$Ul?UH|}l?OAlI)`L>3eqJRdetQ8a#6V6 zR##`cz2MUr`k9#S3&6txq4(<$niQ;p_S4TUFHKwH%3l`pTc8N}g6svZjB+H?JSOty zrh5lJrm!Ahw_!tK=eP25_N6WX3^v16_>irON+zbdQ90elk$qeq*;-h*N+R2K9HBROjbBIT%bvW&XG^afeI7R`dSdab3nu;%ahB| zp6zb7P!)5Irv+hYmJ4bQKVlv?q62)`-hKS@8Q?|^?v?DQ39LVh&YzcJ&Q6Z6TC%5gj+^U^VbD6&3Rxr9aeA`#?mPziD*KN}8o#ZY4B!YNvm? zy^dnJStWimjcD0jjrv`Gq|W@2K@7gg0YG)j5NnT{2l!&O9(NXf&}9AqQFT3q<>Z_1 zA}&x>rL z>#uYf7_Wjma*_bRr?2DxEq?*GoUb<9`5nuTaypF%rpB%3e!13gVud32iZ)7?$}#=s z@8g$lN4i4W!bb4JVc4%uJ{li2$|wiZ(!i7Iv=xuoX+LSkV@HwA0qtm$z5*JjyH3gcX}Db;;us)I!n_OuyKV1I6 zh>XTD_F6w7YJ&$n2TB2-Fr)(}aUH8-$j9}`Yq|oA_Qfs5Y!G`>=eNLKO>WiXI&iXu z%!`^_jN>^HIGs^?mo-0G!3$f>>-URqdvg~tH2yX(*%O&Q;0V9*FRtI0eKU-P8;YM? z@7*0q)Jkkk{cW3hAO;H(C+#R1KLRH+{l6BxYlkh&!)&_jZN#|_!h*%=UXjPfK57s8 z&_R;(_TZaW?e^hP!=Fl;i(id~RYwAT6LT&8-pz9|SP zZA)YMY6{Ye8ceFmg~!Ld+sE)gen|0jmS$sNG0 z-?Y*MpEZMnDbjhTs%rlWYbmpj@%U~to8!+Pr?;e9)!vkN%Dqv%bvFm8VGcI@SI`ZN zOknmQU!j*T)0J%^{vLo-7A7qS94lKtMvEIJJr4_F^K=zVAi3+@-_D!UH^)esizTIA z$w*Jn!B4Jq-G8*_8M;Q%`nb6Zo!ClTUV^QsJyS9&yee){|Ap8tQ~5 z_qtW-x4m=-y^cy2;s^P-nx%jlug~ECetj+0dwM^6A4W!Ze(Gr;d3-)I>u&lr*?eDj z(DHNaYJAq`t`5A{n28UH<8rWVF&m9D*iWF+OZ@#ThT!YwO?yP{g34d*zr35v&HOSG zhkffF9`C>x+NDc$JP|^S!OztG`mzcCMf)R&vwYLA_ih-kRoER3HHc}F59&CR!<3gb zg{{&L@0pZRAXUdTE=@Mo4kZj|-Qt;W4;CQ9I^L7U*HqOAKn=QMpflWg4FH`)1a^j` znala!bqmYqU*#g$QDIjf?Aqch?Khk&qMYm!Uj`sNWpW7qD!(leu5wlMVbmL9a%8M+ z1>qNcU`Md-&H(WT1t-iRbV!_EN>hwxhn*eG`!lWv$5S3uT2jr(SBX_lF)@LpdvNv+ zqFKwU5e)T3t2%%~3mXgEQ9V87Md0H1k437}ldYED42k(JtI;(b+Jj6WGiFsXqi=NM ztxUHhicP!1-=~G2qL^&nQlI{G7s^gEsWKxID0`w^PFC&TL?#tu3S~38td%Tl=P+KY zIxUqlqLT#hp3$#<75RSGz_$VA7( z%n@HcKX1q+H`=jVh0lFAG!@I7ciShq0YMLj0l%wDwKRNBzeb+51Jh{kH+%?`u59RA zi{psf1zNVcR5p3;tepH$YU21??Ddqk_kD6<9Q)6qSoz&c$8(z`@{Ct?(k5vi1T(e% zIb?oW>f06bx@69aTyXq(JHynDqgZXEBhhu|X*B+u^GHq9aTD;SC`)ACOIg1mAcM_$ zX*fRcHHcUAz8?(1pOmTc{(IEwHRa-OR(?BT_O zY)YRRn{5KZ+)p@s+l98RML(+G(>iy`Xmjbmh$c&T@;<~hCOYV;aQoqDE+&gs_*`{_ zFTLN7!fGzKJtl~(`^wPYCMTRN{S@6v=urSGP-S zIAF?tw|nWggG+nT7iiWS11&a3i_-g8rmR2izAjZLYs+u5F^uP6_s8vV+)ggdi>S)* z=tY;-%r&&yYxe-o3cM$jhjpa2rVC9c*Eav^=5CH?#ylB6(uc0k_B8BW)N^qlb4hg} zOfcXXrfUbTMPUMXli`s3L5S7w`<{sAxg`a=AeJM)=k|q#cgPjOqQQWpFhPG}@@xN~ z*}=AM7OFR3Xz=4$GD>63dRHGXY%ogjZ-zU)g(XJkocmZW^yA3*_zzW&54SHB@M#>S zHkwEL^Om%pPr@B^@_+drk{&?m2QuH-JcYM3Hl{mDyd_lPQ7^tem*Z!m6|5@wwGW~Q zS!W9=*`7#jz)Z26-xe?k{*j;&3E}qDUf?7>SDV_x&>@84YY+e{k9>ouG|L- zU%wf-c3(JSvfLFR24p4MXRe@fj3=}J4&_~d{+uGBa8aIneOqu#^+w`hgu38XIKPg_{R+;>;dW|#?1?E3^STf4K7WlRLY-1F?P!_K}2@$Uk34J|?R zciDt{Zv!9DP#Uh!g7(^SSJ~`7RXw>9gVnS_L^HaVs>fZuIW)^%iJ?k1%NKN}Qwa*6 ziSx%UOM#`D0t*9ZxP>eMaIfaHsM6s~;qUVDYw6+5_O?9{wC-o8f?JY@{J6`1ow%cg zY)R&$C^P^#gYkoxjfA6Pg1i3n-=#Tz$nIDPZ%=GfVUyiZi04p!i*>@WxDUj`}K`*rO56_Qh%jhB^WDA9Q$ zS)^`v42gl8Gq2ue9lp}g4Rj)%6QK#;7htY==vfUi1a7U&HD7BfF?o;y_7{0a5hUOKen*XxK=rR|aYsJUHkEDVaT){{Qa(Jx^D^ z8V77#flee-vgN!^0rrHX`nYax--E>$lNWJpD`by{50etpJ@AMnQetW#ddqS*H+kQL zUC9PeRNhW}E`qoWTc7?`={#=Y)!0l950in23&xNUXK7iYGOuijun1Or_$+pALTf{d z0LZ+XH}?_Dbz;_84M2mITx*QH9Qhvl*7y6o!(2SCziApr|nXF zPoXaFzbs%@p^zt}GU4F;C8iD!gc^DfWY)=qmrv|J?5w*^>hT3=bDFNdUV{w79Jheg zAl<(oRSGd}2M8WS%3+PqxJaO<>-X%6Os#5WWj>?+%Z)j-lv34}c*CumyPHTT=8``2 z+#X9Co!fZ+Bui1aOPbLwOzA7SOb}mcfQjjv(iQ>G2@BIJakU{2^kjIo3x1!BkxC!5 zLmG}p|5nC^^*}g(>ccR7_*WroswlchIOG5_#0W9wK{!bomLa$ysPUP}-(|jHkJLrw ztK@0|+B+UofMEK>Uk)Km$L#vAoyKIL&El^Zox;-!-Ac%X&~h{>Cu=0h@k{-joH72d}vedxqsgW5)CT-RN|I4so4I z*#xtnC2Z9*j;b=lAn{YL@%1!jh>(;O$WDsYHI8YyM`{%(EuwG#L)2v+#~YtJimUaX z-zc=m^3lQOv*i_zx?zaV?)M^3Lk!Vxr1T^L2qm^8x;5w>dRVEA`W7=_P};4{Z7Ob-H{i^Y~In z+|V#=vx_-fO{zwkK=r;ytTmo2Y53@%&I|N?`q*5O!BX>k|G1hc+sx|wfusHAgPk)k zi!D$hV?CBDJfkhqv^HgMaxwInSx8^`C@g&Fm3fj`fsmjDU%`i+)xPx@G%v%%n_}3& zN44fOwB5(zdE-5taq~!6jwocXG&kAP<0(5AUVBZ+3f{Zh)9;kbCR@=RtYSvgbG|@? zd4t|26A%D1m3-ZTA*<;q7V~_naq3Psy4ud`pZ@*Sw^bf7^1a!UH8ifNs%JiTw+mAx zdy}R=!xvW?-Ay}IB&rq#L%a&tsuuE;!3c+;gtyLOPxy_+h-*c%*6XgY$5z{oQejiA zU%Vj}S`cQgxbeg6PMHbt0Hk+zpbO<<$n`hwaM}rVQFuP}F>Z!xX3g%EwA(5n&1Lz|x7_R;NYXsLPDCRJzUNIYAyfOKVt980MbF0sv8d`L=#8NQfKI80IzgiZ&JUlF;w8Jb@A2r}m*#!6IGgifG zFl+Ct;Cy`aTcx`#qx=-zqzOi)yFc=v%CzdsGR)@f89ez>WCJ+U?iu^bScYy!M)xN7 z7#+~=fDW|0SQ6`JZJ zep|3*>zvpb{=jQcfvEYTLLRNdli%y4w9Ufn|G>x!dIraMwtEUdtxfb~bMrcA$E0qokn?`@vXxosh5mY)by_JW zaEKW8iTItqgJwSH99Nf}j1BZj=Qv}L+$3J#@{>xOLU@ioxY<1<9~l4Hrc250_u2~6 zj--$}SNCyrQ@(^5herCvLIYBiO51?<4*T+6O2Gn65t&tAAF6JV zgw+zulG%j;z9lA>sc{DXrgWNpBOdWQ%G9m7+T1v2fisOGM za^OMMQCvefcXP@nd{EvRj5@QvG{KP}i0Eootvan+gc zNi}TsYsOpLbrEn721LOTh`PBg_ERO|*z|rCPd01wD;OsI;$Txm;2QayeR1LP{2}Os4cE5Rq_Xb z9`b0=UfQYoiRrPmoZ^#P^1U7Hb&KSsagRWM_3m_~OtMX)T2pQc=~PeRc?|vh}SA2<2{teDasQDs~*N8Oq$H{v?%exL3w=ZPUR#sz3MIM<$KX z6Q8GB9zL{&);>=!^{rVY!~;cn?N){nuWO`4lQ-tW*9P-5aTn3ad7$vwfo{NL(BM<> zzkBgxG(sgroY(oaJ+?$74Ir&j)#Ec*MV-@E_png;$cpQliM|vBH$|LN!rI4!WPzV8 z#Q$kw>PkI^1~-lP<1jfyjgYC%-~qunEz)MqWc{_NN4QUdbv@R%xu)oe(po?_W+xqnnrMn6m>s$ zFfcWM|3(%{{@eNe6mb2$2QPg$$vTQe`|W+Rsopl87tMT?3SPA%F2ou|98z~bMpFE< z>zWMo9CwVuKC0}-9u@q`X4Xe>wNpGV&%Xg_x}eS^dnTi(j$X!jymXjHnzbJuEVqaG zin?Yt8a;Sk*lHy#oL-82|A+YVD$Eih=m|nimG-c_=GABL(xp6jC?>yt4z8qv4-qeC zR*53;IRe$^q$vsrnyrmhOPdj+N@1s)bs-!^XS+v@WTyVSrb_(t3CieipGcE3i&V8W zFvE&^GVK=#bL-%waxuDSMh=enOn(x7CY>?k872PDZZmkFD@uja__^XG2>&l1qOEkm z_`hla{vQthzr)o3fBgS*GY~&I_4(M>^A2JRG2K~UO9~heVq(s~e*Z-K*e5mo-@rIM zI4AG&y)?}u#TM>U=g3=hKv8kF3PHKU<;pQ`S~y(+4(Rz!AI~L^uMDLUU}VFT1Go|p z#u}#QH@i$Gh=#C-g92Vsv1Jn^J<0;0sMr;*%R)x9=4WTS0%2d0E19820X~k)+LHP^ z-}8dFCmpxGLOr2Sc6`%X?mwSA3BbjLkB{1vuz{r@^-vuDu2$=FY#ZRdmig}={hl$| zezG7XeqFxHAer{*Y!(!I*DAylIdYT4=z&BX}waV!4nOH>k-e~R(G02K9+2g z-x32S#mw}#*Y+#Ou;m7>220-AWlv@c*o1eqH|cFk1svG9K5REnQC@G_#JEoe#lhxi z_&ZXfL0wKvR(Lv_fY*V9#i%!wbbe$6t z<>^4-#Tr!wg`6W~N}YnZGYRk(J1Br2fUk_%L^e;-5Heb%1zo`i+egBvg$>kHHRzeA z6rbWODq2_yNUn}`gn||%v-$pSFyxrcm#B}hg?{ZdGz+IN^0H5T+Y|x?g+%!@mwIes zxGG@n<;Dnxsj%`H0<=CZ75s=&PMG#6?)@ejsu8lI?eON&5a>f_K}_MBczJm=Ty1x& z_Q|ahWW_EHM%#Da+;!ro=Aj<0U`i}za=1zpOm6gXK)+tMd$Ri=>w0fNzMqZA z)8+lcJw0QR?L=cZf7S2Bx$bo`#t7bF>=_N+m+Zm*zU&vZ-8{dzC}M+q86@@&eBi;Z`g*p#Tq10Gcg~})et1^uH@9GbpE6gC9tktnLp}%;jx(0T_*T?E(_IP3F;`Kpixbe^o1?LFV)-G8QZ3Ely z^yy7j9U!{m%}pRqfk0qahVsH%oZA|Qk&lDO9k=94ySj1~M50`U0PtOjw(&Zm*4`*nUq7eIe!``_a6vP}#0{&G z)QWxv&CO&9o!~H;z@6Z$7+#b6XZc5uaDKhX*T06b_%%nl;D>CRcf>L+j?X`Y1t&uJP=6)y99xl}zR(9r=OaQoC?Mnt0-KZRX{LMZh zy}+;em=P2ONG`h`*{$~Ap({4Cz15r3G#Gj4C<#8)Cs)P?;ZhWIm!X-cYV6ut!shYg zbAN(o0iTfg;AN9XBnz~m9<*@o{ux$FdZ?zr zWh38TVd)!$6R3=HeQ*lH$vqbmMF)0>V^shBVy6=X4e&JhGgi|&@ zP)xYrGnx-_2-^}v70XfII(gi-r)kj&=?;J8=bf*6Jc!r43gezMZu-T2C-@nBUAG3( znrVyNaVG>xhdSZ@&HmoDCCFXT;J@BbG&s%W=S`f+)5&Aur;(WKP2r2z+to8CNVScB zJ_+fDy*R@jNAp5K>5F4U^AM{(jTl>uiC14#IoJ|Z9vNV~(e|*X$&Xv+qi2Q$NC@z% z=#~DH!bKyS1l5ciI4v@EPH4K!E=MBIulDF7q!%_X*rB`5C5CSy+UrXy8Lpi=_OMN& zFbC#H+ZJBDNxDq6kb4^&Vv=W)UR~aju{`2sSOr6o^+#O0g&ROA$by`ZM%#zVZRA}g zPMYr|ukXR7{;!(nS8I?lG4zSIu(i|M2JlHxJbZ`d+9TWR=)SR{YwxYR@;z{$rtII{ zr=D22vn}V4%0(68qDaa@(3>Bcc-b61P-3wtM9>Vg-X+VwR) z4jP9Oe~XL{rEwAhpf;lt;n!B5xuWHR?R!Dt`!6&bq|4akfd+wo|5@D$KEbP86vFes zIwlW6YOX&C;1Ou<31a)VB6iy!xG#P1>}bO$ram5r#S}+um@m`7mby&tHnj7_-g9d~ zdP*gx-jA%?+ZXECI#C?}nJH>v+}Rfsf1H1)M=?##NF32Prlc17A*ob32d1czB&10T@16IW@svr)QR;IBiCJTdKAC;6{d@7W!|h&jX^ zj(R3=7L1Jai51@P@ao_cO+Nb;Tp4RUoS<(|!?9g=IK~F2VNU+PfGRz{+S?wUSx`f> z+qsP9>me?!oj5%k99VYSDC%I6XT2={^+bE>ok^5+_JAM^hrp@Hz3&3%|Iv@hH!w#m zTYh8KqViEW5vA#KahKmog`Aml3P$x{NA%pt6JO31 zrbaigpmj<9jv`u8WaK1Y4Yn-&FdW)Z%3!DOei-AxWDv=-K>chtG*}q$5&jXwe+k_} z9&v$ z#Yb*svJ&~j6cNs&Ph&x!%U~2#efg`qAB3^uyvQ|ev?PbH++ZI5FeoT!NEO;$>Nf2^ zTsg_1E6d@B4sU}Ot>h`;l;GAll(hHP(eTAi-j%uBtUpW%Fo;k2!e7i`C^_xJxECgk z19B|0=1Wv%2*&peFnG?J`v{tv!bg16xdsn)#FDn3-oTW?&50I?f^{sWvcB5*Y5dR9 zYDzy~#&&Mia%PUy$G1qX9$$;D(#=DZy$;dxU0LjVva|Pl1@88+$pE>EP3JFqsc zF6PF}QZ)oGHVV(%uTb57>{?GoRNr7hDa2xa~7UY4<4P+YiPV<081VE@278k&25A)W5Tb@q&on@t77+t?6&*5ZB|2%%Yg zVtiAw`0O@YXJzZP!Tqz+r(3)RJD`I6{FKILQFyj%!D@9}_BP5F+RjefPPZU5!4B_{ z6c9wiBsCWklZhhzwE+^&n~?{1a;7mC!GD_kZ)6@2`EyuN79?I{|b{RPm%6qXbq2F&5;_3iv5+F!cqOV4~VWL~X0 z`FIUDR17%k6fy{~1?w9^Z|@H+0ay(lVHSp$UbWbAt)X6b1||=u*(ghEf zrDB|M(oK_!`nBr_{uG^*0!5Z& z#?u?RBbz41LZmUhdH zVfZQA8vDNYpUm&P#idCX*TRo#J)7l)rnuI(ynjB3?ug{4y$Ew2Bt;=hEmp)F&Frj zPf$4%{RL0z8h4x<8^l1|%cibb?CH)S=i!Z@7q^MiK!4`8#6)Eq z%Y*HNZMCf`8uL`69f|dDA%echZQQhg2)mb%nNB8KV?hf{Idw?aFMrvXP`A&l&}VS1 z>?US6^p(B5psfYM|L8=}AMN>L#m1qmkQw)KbjK>`qsRD|5-WkF z$boDchK6!7!&cDbr7)lBS?-uM#mvTPvbWJLmRrh=Xd!{#ka&a@N|65#*;Ob|`iG44 zsY{qvpr+){JsNi-YpG*DC^A7v55ViJ$oF{w4$f9MS1P7P2OQTv_qsf|M6-X>)=p2{ z=SV}!A5G4iT+>_y#V7c?&sN2PrZ2LJ3dCvng1r%_$RLcCyr9~FFgu%#gN)v230ASc zuUnOuJ@6?tSjo=}AiN)iX`W2D?yB7s#+|KP%UoQ{l}!rGgXh$3E_d`hU|IgmN``cF z)U+#N;R89+xS4JIM_C>Q2)7oT%eu7qFCj8gC4mX-bInBfaFg~nlk&(zg#L;nx244{ zYM<0Y+PfX1to|lwLxg7fqkmbu)dkSXXv7N^kTNp_B)v+idzTymj*ZHMA>T2=U#b3S zD*wbASrkumcy7e0aen3CB)~L61ng?hj<|&!k!-^M>kg^jiuOG3G#O1mi4*anv>1-_ zuUV=TWV^-9FW;&f zV>xU5!wE#)LVQpy8Wd22HX_{N_M;B=3tr=ihlMUT7nh&DsNH*pPDJj^W_e8}`qlGr)=HG1gIz0KE{iatQ zKDUuicM|Pq&B*Du1Own_w)n329P}%6)<``EHfRr#Bx>a@tR7>k7-I*d?FoE ziC_?RN7mMM2}!oz#o~^jt1_Yb!{&U3!$OaXDf_YNAmo5SUl3Zg$ByMP&O}c}<%sm2 z{nb*1QJ8#ugRpKh0v8ChOpDNC?e#bZuB=`Y+;*ape~l>pi`}=x#eFa2b@Hy%lft5+ zws!4x&1RB?l)^Syx;57P(O;MEZqY+B#|^6xj(YC;)SC<(YIe9wH4TwR8(K9($8T5!!bne^Oym z(N$~V@stbZJ7*iFoFdzC6}d#wK?xS^`U}3$q>nC*(PR+qdlId6c!0A}6YPUga#0r3CQ`G6tJUWao z*@~SUs@Sp>*pZrl`1vr(d-3^q66m*+{k$Co<%j}dke5xDRMeRV%fKh3E3k#tl=bT_7 zk#sR+2b;o5o$B-3{Y?JI)qGgFB7dUoxVdUvWt#arEQEpX+ z?$&-d8tVHGrT+5+^{1}hU|2+A9w9L#ZCN>a&_`%*4y;O!$wmnxbFrY+-61_=%_~;= zx!~{01h*01SSXyxAO_~GM}x2!nv)nQ;~yt@1KV%CD0e87-YF?5zu^}iA9+fqUv*!7 zL?w9eWy9f2i3NcCQ97^|!x?q4h*d%WqYF99=n>Yar`=VEn*p{?jX8bhQ4)Du3+%6p z=4OXPBnb&*XZO=ejEB+nF4W~*68}s??ppu;YFw4$GNQyt*Qg9~qQ4%+KKA$M*t?{I z9!uk?s%)h59KJ@j^Xr`5$gXwJXFE@}8%k?v2@aZ?h%n_KO?U{J)bv{MHhi0LA!?5H zy?l@|Ye2LeSI7HNQmM@W2=GbmmNZ(bL_+#?4F2bNRp+kfX)@g1?P_rul8VEqmQ)qa zGFD)&OT#8T+r&()d>qrMLx0xMHU?#nk*8l|l?nSgT)={KPL9tI$@)hWsZp%?g!rN< zQ@?6&K$)t&ZrP4RC&lh37VTUL%V;CZnNp#vbffrhfzQvYu7d^1h3Uq z7llVyzJRW8Z5hjphCan6&pYVI12=Q9b{QF=g)*i_B3C_gbLsD9ObC%l1j*8MlAZw}W5FJWZRKX-KEFM!SSHwYl$|`0Ka_hbwS37G5k%mB zLN%aReK(_R@xD%IszqX722T1KnhT5%6dO7s_RvPYB&N-wUmjo!y>q5dpi>A_Q7v%(!g2+wq;jS#An(Gu2kXfOxZ@r+O=~LAfFwI4V0Lk^dZpyo%bu%A zxSFAcQw^l)5?cw)#03*y*3%mz-zeFs%RHm%Em+N8i8^dDhR$I3=Kql|5_YIyFJ@^$ zJv?WLXP~Hm_wC%x=t+TrlBrh%-c&p7@j_d0rWe=eWsmw!v9fzuk)ntbW6CVnr|U#| zXZd%BL?R_eZ9pKoKp`DjPr_%7(}zln-@zr`4FnD2z%pE~sUqmAuURj05%)k;adsL(Or4;M+r4V^lY-H!5eK6YpiNn;m^WLf zM4<%bo+n-WL$!n8_Re~3tayMC(hz;8S&$IK)cR;vu1I&sKW?*{K5=Bm`%rOO2UeWv zpjr|$nC;-yRh)r?o{Z!PF+?j#QnrbKPH0u+3a~!5UyWwP$(k5GD*j%F_U`$%v)nUW zBbGdB=D?t%Bo}V*sM19F1|qct2>rl&kKOWk+R&BZ<0(@UW)606Ef5`(#m;-YmCRO_oXfzq zKe==tU6h9Mx~(;a7vIH_oF>$K6cJYCEK%OL`Q{EEU;b4#rB<^eeZU9>57M3&KvU2>56p4$67e; z-VXn&Z7Ip`+%*p~RxM$h0P87nYodvx>wN#AKu;!Ir;hL*b4Ex@wrIY!#2mH)qsR~| zI4tsTjt$Ax&}&Aojb+2}(y{$on_Ril=;I~1c?+kytu|rwUFpx)xX+u3@As3bMMsoE z-us)tidSYuMnj>G>@!EP7nzPhptax8L-Q<)apa7^lVxjR2scM%6;cqBrxcmg6J=sT z5ghgJyw&wfo*_}*%`E5MG+XP6N!3ltF&m9Vh1g(Wr|ys1>u=4K!eC@?gX zR6=KLGd4e`UR>kYRUx&~)!B33Xl!J(^Tk!d);4G9$Fc2i>oxKj^{-C4uOCqRE@N+3 zk{AsA{hB>@%xi7J#DSN|r6H|03sM1kQ_FD!tkuFm4#yUx= zRW$~Bd*G?G_xJD>~wGrXEtP6)i{a|^y9biSTJ z)Ce!TKu{Xg$a$b}$>q^Fx|KQ`b2+H4hF!pU+axGookQr(OmNDfKTX6S0CZe%=jK@h`2^dMW$gWG z9!nOp(&kQmN(K+T3!N2*_<&$6DeChWefzxUHI?NX&1W#0pD$|q0kX2y{Z{vk(VA8G z!zU!G6F+{j>^CNP5G*-7gI8sG3AhJb)Zogr;(kNQ&C6C(=dMIa?*W8awmiXT@!nF>ZecYmsTQvr!@wB>&52gqR z-jRTHc-TIQQ|;2fnX5*09fX>KnR(8O<1^13e4hcP9!x1jt7M8EzsS?a+3pNN`@s3I{ttmJ>|4dYu>iK8X)yXBH^{tcMKYkpW zpmtPOi;2OvL==DmwH;+vB2=hCA=G-YO}XQi?_E**A6lLv`*s!1*ZJjThKVY@qO&S3 z-VW)3TuC1i19P&+K7owe5P5d1ZoI4?L?%D>Krlm!5KO97{j0n?TrHj=&^j|yX4N6$ zM7#}vN;U`x42=K&7vRe+Y)}VPLogAo0bS@3j)5wmx3Jxo8%-48jCvde`I6z@%dJNM zv7$0>i|1b{TN5M`Bs2H5d9no}@({)YLJMs*IkL6<@KOrrOw>kH!P5txs5;mzLmQre zBnv99v=q~@9b1ulCG_V7f~2HnS`Dq{m#|zAfJ?I*%d|YA(!$?4c@K5oO+T%unpOA{ zV!YTmycCN9!NFo~v7ivisA@CaHO}3($p{>0tQ}B03QE@QtsD={4+^*w`dEXW{kxU{ zD$c>#!mmvZxZhch**JP3xVZj|e>K|Ba(*@cZW(9^?CKnunDCfktpv(UUD7paXk)Wu z<1^rvLWrw&Xl&z_tC73AQp(PNml1*c0 zd6O)n)wY*Sk>wdsU&Au^Vdn}B3>?4pC~yz+Pd)FhN4j1N+(58H^njimDdgLn>vliO zWc4vb&9DGuDxyo=Q0P>bkbfli@8Hw3-OCKuciFiLlOoa1e#s80evsHke$URQ*n&W1 zzdW+ylO!n7xcP}J;zFQy3`>~azFd?^$fc|@J$-zYD_(-bScHwG`Q>`ul_@RfgEVUs z?Up*JnLTLujig0r@Z=>wlDFeOJ)2v%OmTnQAI!*vg;)*Q^Jfe3eL!t%Sjye zVzyeJ*VI%DJkGu#wx=R=+aCNwD*&aiIH&aY2BpRaDx*jopI4$kj_DeGM`+ezCp#wAznDsY) zwElDo3oROntZjKFPgQY-Pecz4jX>}$DolOs)D(C;Uy>Y)KrO+{P7V89f(ovNOXy}G zy|r(W@$w3)7*d9Qt@*0Zdy2~4v+$Ki{8GmN$a`xn)5k9@B{sz8vcDgG?)n*YvPVES zH4CNyL%lt*7$B5 z*I%LQWo{mxf=k$Y_$&aetp#!o5muD2bcTHk-Y4hu;%j>QV64M{oCPzD(1rJ>fnSj? zD2Z1B1C@%WqoX|6ZSx{+ZF?^7tG}6KK|7QAj9HeoD*Rp0TR=la-Z9Ak@yLH1W%TqT zT(~Y{n;(Q(7(X@$f0|JLLO}RW9RBw~n*_}%@^^qsLA%(z7VJYru^`nJVl$1H+h|$y zAiWP=`-5+|v<~8X$mO17@80v2%guQGDskKa{67vKK1W;I%N#wL(Al|+h~H+#icJg; z4{-YQHjLQ>=4Z^#o<<}`K6nWA%>b0V;Cz7hLSJ7FTpgY_DHivT1EOd>&V3DdmDbh* zh42Av5EA>JFfdT1T)qcO2dcRx*By(ZUNGFl)~-AdU~NJmL+t5)GffRpMI@lF&oEzX znTm(03kE?SB$}uv*X*gy)+6?9_U&8Pj3TUCSD>@t*>yB+?icG(-$8e|4lGy#s&bIS zufMVA+N@oP;Wk8u2*;PsC10sPSJ$mT4&_av*-K5`0DF&~rn@|X_jfQjXjxq!aKYtq z?l|hlvB8~G^9?-sU_fp90X+K%%r=nQNRo8)k#mX_LF4qjD{oteiS9#u9`9#aw@#Rt z5LB-&hbq4|#Ecu%7(}idqxygjgn%jX=0$33!~4hR=^18v##3A{KqCm&0!5rXy!gKD z4cJ}_$>-w*iE}r!Y{*w8^BFS)8$maFrb59yrP%L!#{W$hqbDBu93~@ahp5cd;4;Sl zNHPBqrK_RKOrQ`_3L&9pSE!I%a@**}-f><9u!5L`JCPeicNfMWyRw-P6} z6UB{J+#g`oDvu9ps9KyeB#A-A;A2l^K@xC#dx=%ef56GoR{~e<_5#*E2PjGM74rEK&RsgPF*!sHfnQwE+&a=lZT25{{)0cr~ z*uK5U(9n4l<4{zn2D7}O0Atx0)YM}99y3ZFeaj|&Ql~uV(aiO#)T&cIf7^pP(uA{3=W>4+%bcggfPf6pKpLs zypG}AJLJp|8k|PtB>VfvDc@2eSe@>7qVLk@)zAQVFd{4*2=+-NQ-=L-yh~TtZbZL? z(1Z;_k~lq|kEg&S#M5<)Ul_KazMa4yq_Xs|H=>)OWRc0-j9!EwVfrD1U2mxS;{s!U zaw7!ng#>&D=Z;3$KejadD@WZ+AVZ;cCxVcX^bMWpdjkO<|6w0Cm0x*=E#xBCFcW} zI{zL<-a_OK8qF<>wpA*I_I8Ep+ZdS!zlk7NTw5>y_&%Jh#k*nJ+Z{fiBk^hJWoRfu zqgN2AfvH3F6yOPhD&9GQ+5Fs51bhq};LxF6JNh^Miq~I%*CGtlSQf`Gf*wU#M;u$MNo)BoK91LMg52-W);53L;G9R*Q>%Gy zlBk{4v@@B{NRd*r!)^%BKkDF1PYc)B2Yemf%Z2f`;a|_ta7>Vmh47v5(2$xbvTj|G_3HzG%455yD^CaSqT0*dcQ@0}kUr4Y zt}QY=Tq6wgh*%_;W!*Z**|P={I*4V)x{(9od3`;3mBL)}*H+k6gROz_bv#D)|W1l~)>6;v#0n%J_X6%z-T zqD3{Kq2U9@$J6s@vYhcVYw76;IDfv3kuLz}2<-rUeN}pU6Gle%W6jqIPq|5>+{vLSv$yIe1A|u((Z+wA9kOIa-7(=QYw6%?OiVt1(u|?9cynTu+Q=9 z{fi5MiXaHnmsi1^q)C5X=mW|ss28epx53a*#C`YeBCf5**cOrmKzf_sJlHp~xf6m1 zX(;`Dy6@Qqg&B-C;(Xd_Lxr0maA!d~llct%CD?kTIYxip$=Ct-w3n{_^xX-yK?+ZL z;(Lc!cIW1i)335(RS3ERv>ET#|q&4jg!!?(Q{6@(^Rw_1HoUAFU=Qr`fT?uyg10Z0Y<8 z68$|!YcEnP#<=8moJ)hhF-nrm;9MFogc=Jck{KCs1i=imv&!DR3FTW}KyG=0IQT;X zod8o$An(y=m)5o;Vl0!0-hprz8YoGe1082__^&(D?x^&=Nf;w9<0MJ?eGtT`n*_abeuk6hP;J9&CpFuNixe>i=k`&Jk1X1^ z1(*nCQHe2TaW|L*HGDLI4-igW+y_+ccB0@w3`YI%pgPou` z#N3I`e;@Jbq=Krasrf2YuC6crbCw0|Oy)E2ZE!HPcwF#Jpq+D5quv%Zu9xKE@t~4IP?o1cwmUxsSdn1h<$@NehYwAt0tMA-p%y%2*bk>+q(`B z1q-L}oWhu2a^_4L7{B$8XQ@`7edKNHnv(w`@U zz#F_K9Iu|>?kHlc;b|HQjnursdxyvw1_n;Bl;_~V=h(dYRl=|hQz)V{31KisZYEtO zRqEa%h$lfIuBF!>271EuUOsL;;1D)CLrv1*Xe(B{!|3Q=5QZQ2 z^QO|tWqv?cS2u>$B;pCe4|w8TdKq(FW|kQrRB2boSD}l{{imgd3wL@`HN=` z!OS~&S=^UD-S#W;M^6G{ROar1H0kg^v3+|R6BDzgSCCy9ImiQbEFhOw!aK61|ROy+Zz)wDC2%-=p?SdS(fiNh8&E+Bps znLUsN?97cW3)-1X=5HI1$Qu+mOlzGMP*! olgVT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed - - - - - - - - - - - - - - - - - - - diff --git a/src/cmake/modules/Packaging/vortex.ico b/src/cmake/modules/Packaging/vortex.ico deleted file mode 100644 index 65d2a450387e00879f5351b371a1d9d6698cbe87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30321 zcmeHQXIK=;*6tzapd>+}5(G(#ND_u92nw=F&Kb!PL>*wrL6D#l6a@tZR}>^FDnUe0 zK!PGkB?$;fj)Opd)vV*i?C!mLzx!i(os13j!e*luZXg zYS15l$o)=H2pR`*>z{L@AxKQ@V|rc)dZGhC0w4<)An<6d91uVd$j2@62d&+Me=rPx zqS*7C<$$n&K+6Bl-#7Tffd2#__x}ch@9;-3Ak+;A{deN{34c6}a)3kZ@4)ek{P8%_ z01mGIBo20)wlqL%WrDI1Iq|%{7b3RtAG1-w8wNB12pg6tQuPb`@wmD{T8n>I7a#c} z7+?X%>IIuH8+`e{8a4tP=)a0%J%9Z54%b5XX!QPH<&RHS4sdY&SsZwt-wI`pUWWtE zNaD-?)i4&|_+|ga5jO_2J9n+=|63T4IBiTA9FZjStNf94Yc~2Ty5P)QfDz&d8G_jz zI=+izt9>1;7jW{=U_jD#1G4xL4m|(0Fntc@zz%#D1ELEdrwaHl*l0Pxf&Lbb&-j1T z1!w9E%;DSnLmY^0`~@3L130+W;oA*xTC8txUtWJp#xLW<&(*^xQ&j&9 z-#_htzvPMB^Ck7eZiz;JhA)yf4bU(5Ki}fZeQ^RdI2-h5`IZB|Twm(Y7(0MHAlCjby9AW|6SLV-mAuqpsS3V>(<5duO1f&u_>0wM*30)+oVu8}z88AyYq zMe-ndkuv@$6DfO*2jGS9M0iK)9N0@u!Ab%0QERBH=>AbG3L+x`F(yZ|?LdI?)ZMED z-Fmip7~F7KtLyHEpc7!70~-uMI8Ztk#Crql9I=2PnPdoJc1tj?Mixy-tTgwkKwyCb zg3}*lodGfA?&^k~5G1k%A(Zb`1s`xBrJFKZh-oG^B zU%v3Bd%(t!#POB+%CsaTgmRAAv+Nt;wTDXWy2Tb#GzlBZt8~1*u)({APhr@KC0ZBD zhtj!A8b#;KXG#`)@O=|l?&%?&j2Jz=f8y?V`wOK~7Lp8u%ZH&udZ_l%QtRhiZpljS zIwKNRDIn><44rF$-dN+H;LD zP^GrdZs)Kwz5{~HU;*nodB+asU=j5MMC#I0VIG!kJ`vLA&7(d z_9;S#&R^DI8@H{C+C&wqy8$}KBv71wZh$aaH;aK7ZA)n&Um@VJ&k%wtCT`twz4)Q$ zShrJWYbTPu%6Xq2v{|0>_aqV3L9bd{@4Ran5V&!pZphjnij^2UVvB<^9JU=nxi4a}O$x~d_BZtSnvL4(1p?SS zR|SZ%$E0-Lyoi3P$yC`pH|*UJv!?xwWC1~xj-UTrOKgRysmmkbJZbvth3d7BW$Gms_p5#wt>+Ky%wcvSm(?0pUqya)Ip{ijIiT3#1dM8vKGnTBU zPBWlor3)jk(9tl&A-ur!ier(LZFcjB(`D+4`CDBjVd_kk7H?0zVXC0**&XiYB_<&ZB2K%8w>dUm#sR;yUpt+TZ>22`+`Jj*%Mc4GIDNtYOHjO!63vUz^IO>n8wN#6-+_kVFt3@sHU@NOicKQDnODVJBPsBGgvwsq2#J$H(!GGK~ek|z9acbtz=dVA2`_CoGp zz4}y=9OB6=P~DV7m%85J5aiLXGa1H=jifM#%^bBQ?d++ z%T`2jkyJFX4J$;KQtu^B>RWHu+vCr|;}aT2ERm z{5T(nwzArsQ4?#KBjiw@_O^&WR+dZ+|DTGk-bogdMdT{i`*hDc`n`!WD9dV zGIFVNLv}1En-)|x6Oo3(#*908XQAw9a@XZi-n1%Iw@HC(3iI!cw6rvDXW0};Q96#K zz)i?lX`pn-j}t5owlrD?9Xszgx+#)|cFU_a%5CwrxShwzp!8XjcJf48F)!>A0ND`F zEjRZp)_vl-PyN8-h?fabYR{IIF=qbMi{c%L(V)>N-JT_@;DZiRN|Q}m%&r`{fBRwh z#FDWX--X>galGXHdtMhTEjz!JCP>~#SK$K+F0|;N$CjrkR~fP0FWQ`$jJ>@3NS<#A zVPiSWP?m6_?kwv=KR+oyivUH@a+*S@{p7+pb?mDLCzW?TQDS*nb(EloTtKv}JSBL) z6g-j168rq*V6UeFXZ1v^Lg0;NM|EnCgO8d5SCZe2HrN|AI!G$tChk&aewas-NDqZG zXPeq8H(cFJq(7e)Gj~tC`Ax*VfCA3gIoPNKgPz0nT|cAtVXeV<0=5^AO}xpA2Q6WV zo}xVDb~};n9rHJF0UsuBZ}Go#8j3ZYB6wq>cUhVf2)fblK?D^|!m7;CtD7ncKt{Td z9WL#PrCcNzb@mVlxaov_Ffv=!3Nyc1-S?VCu4JNZ(dx>U+(tDLQjetyf1wARcn=%Z+VO4E^G>N?Xd7O+@`q_6;p2FI&D$)7FZ%epj*T*fwq) z*PxTg=(YtkHIeM|Bn&2Ki%4pb0RJ?~aE#R4JKp1d*N(P|EhTC$8oj0->LAz_Utyq6 z7CAK)RGwtA&7D=uTuH}S@m|Vq+a_|xO=xa;bD<3ORsmU_%YJj7i!)abFDB({8#N3$ zUEMS^9cbK<-`5g$hj{YkNdHU`SG6xyxzVY^Y$?W2 z4xeWkv@V6nMA8R!X^L)0N!`!ngfS1fMXzX^M)NDMJnm;^R}GEhF-_o3O<_ zeaLKtP5T4^(jt>S4gsaSl-UBY=t?@2&fpAVTG~Xa{LK($Gj;7<{h__`ax&qo7_R3- z{5B`KlcouMGlADWxt&u$-is0PmM`~@$=_eXvgt$y31!;#Dz@uq+Bdx8Gkr!J{dB-r z{5DN4zdrZ&le70{1wqeU0D8&`8VdZ%oL(Ctx0};_+9mr-+T*O`4#2lj=I#Bed#h1` z(}6_qefQj@C_iO>@dohOYI&G+hbB!(#jK|?kbgz)S^^zA%Sk)=)v+QX|Bcut$FBy?3Nxzj)FQrrSf5%2Z;Sn8T z_3mU>n0mlL&I#(1V`6eQXe*mvP#)0nq2xO;Xt8nwwR~(r<5j|HUWIIZ^vI0)0ZeLG z5+~@GUl!h&qfewYpj5U)^=;fnwOQRNuj=$$6^{;rHwrY3Pcz(w$3q&tdo@%6s6GQi zSNIg+$r>7~nC&Az6F?dKMfFsmDjRg1QFWx-gDgiODMclf=!}Ii3ANKwT-7~sKq^4t8ro2DghV_c?m{YqM0RA<8yXlKhTOF)l6q;l4@43-0s7q81;23wE3AC?Vl z^ehPXx9kXJ-Z(mGWp$C!92jhRGzo`gF;-ryn>sn7x^a-Ou#@1zZURIjqO#&QftyL~ zi(%C< z@!U2EE`D`)k#}Jad<1eEc}qv=Xe1^8&gxpt;Bh-H2pec~5MVvH~&~vIN>wx8gQ2E24TE`aN zlqXEkMUb^5)QkHn2_ut5r&G{g)ti*7yahvqI0NWFT#v&@Xoe-a#E9}Xw9_(|U9HAe z1QXCpqBS{q(Z^Y`*Ppz%Y(~wD8!A!bEEQ5OE!M>vp>%FnMpkT~xzw356KFzQ(JW?B ztJ6(}f*5XZ7`*s+r_+$-!mFZE^E8rc^w2pj25z$WTep)hKPAxG%j!YJ5qWumF=^1Y z`uE0TBJcS6W{P;Se79=1_T^qmsn`jxNa;m4w*^$7!GMe)k(PyQjvzfjUA1XOja8ZS zXd|ifEuvR-2XuhLPB<;ip4R-@BJ1{`!#vmUR&Qi^-E1UJIcWgpS z+Dyb`7 z%B5sC*jwLk3>50TH`&j8NxA=yIv68P5&Aw_Y5g!?T7JTua@Z9fiVRfbKYKsg(a+IGTtL)2L$|a53 zIWMoXNFbxCr-hcJ!$VhNu5h5Vss~7q=zAo}=M>TmftTD|4&C<;U9aOfR?rg(K4wo~xS9oPwRn(Gi zisv31Fs=qRXsEm)_9iUw=64q^-Fq6K{*f_*Y&>aJNWx~64bL6yc}?jTxAH4{c}-(* zAt&E2E*E^5tTzhgmf~xo7w5yI^jSDR3O6SGtw*81R^Jd zqB&Rkq?a24S2F9GISomePY1El2euP;Rh2;RW?y*?F}2v9C*O#5)M=xY$PsR~tzJ2h z<3FXmJh{8Ee~Vu*$QACZbbP9c-eT}o9c_B6=ktpfFI^Z16NdavXE9{Sl;ZR(G6|PF z3~!%PuIR{J{tprPVkO;)Ku`=xD_N zDeKElouWL68Ps@O^u(Uqr10b*TV~x8c0)bPYVD?*q6%Uii8;wLC_d=8&Kod^nht9z zAZ`{%&6qJyWthvyQuAvki0})UNKv>tc*y|gE-cW3!5Ts_pjw*fZ4Eudjj<{25*iK< z=A(j=7)Otw`pDfkTB7%{;oh-B#cG$z6dc~}uMZ+e2Vxej7}dI+LsEH;HEknDRssTX z2jt3}chN{L?J`wnM#Z)CJm#m^1m>UYQFI~o_piTs#|OQJ<+Lxo_W8o8t*4rzTnXs>?rR*-5~w>e_r@iO(vBRhmL3xhQ8ROkgi7l>UvxjvQ+|cyL=s zZ(<{SE9;H9!P&>pggm=^QcIw%XL=sJiV=Oys~)O=>=MYeIhzv)aNE6%(X5sB`X;VbisHi;q|7~5N7Yuh*xW165{y&` z$l0WAT8il`Pdg0RY%(1uzkt5GO%;XTzoeE~7eGYn$4M96t z9k!U(dL{EA<&Cx~Lx<87X4UpT8=@t+OOAc&T;(YIZX0CetSP^cr0}qJwMgHx@D;TM z2}+%>GG;IKEcu&exgeboF7?tlEiGoKBH8spC`Cm(y~5JGME$#&g7{b{yPhH2QIQrU zu=P&;!fMdYm|Fwq7Au#uQ$-LHlnpm41!ST0n;N75EXTs=0o=`Qs#gmC=WsVCeZd=GAX$QA>c1r zq~q1BlulCPD6kCu%_Ujf_GxJ`N<@%U678XVojzTTeyG}mXy$wxZA))Q?^2pPZ zWFnr~@u{WzwMQ%!-#?Rhe8lZ=pho1AJX)Z^28{5`k`EUba*=sUY;S~-J`6YBpT}1D*tN8 zEYm6GMTG~phPtDlK#Jy7kNaSEaphYKwsfo_<+ZOI%I{hou!AfP(~w){W;q|~+=vby zP>Q9i;z~oaE@=fG&Lo!LH7zY)KCzLFIZuG0`b<{$m-cXe`YM?R zN7cyg&EclUhsT)hA>p*VzX-0Kz+{}hU}}Y?!QJe*FXoI8}`qzFT;jD6L6@^X;44lMj>i`C=~W;*ge)E@!O#ED6qX? zDEmD&KTiEcftDs%C$-znac=3b$gEtONfQ`k)`L++R3Y~FCv$`&l-V`s351g$uy?Sl z_mP&Jnkv2V^u7&JtxIC%8Zt|m5J_Q=dmiLwFHFiTnD%3ECM`Qz7s9oK@9k4*aWV(Sq*)O6)W z9Xm=4wd10m&l!;#ua-FO&IFbr-Snf!?pIE(NIFkQN1+pXS}acon~aB=9FAY8Gly|5R)F+RB5#!vnV?-8BdDIJTQFQYx3}^`jYg6!#nVnd((}5mnbPU{5tq|qw^SRR z7&0+i_IOW-@$4f~3q81l`0Q~mQo({S3`qg~)52cKn=W<2PN;lu_I>lDaqoWLD`WSp zsmYmAtaWsO!b9b*r|d|*tEOEs@w?CnQf+o6{r9QuC*{jXmV=7o68N;3W!}g6y-D@+ zmy|HV4%1z}ESxex#MM?73?^37RnqFS_2T!fa}5c^o>Np_CxDW>66?34BBni-rM$@8 zVzmQIQX2Zh?8ju>=aLkoSlv76+D``7T?>azi5pwf0&UVrrLQW>JoI>q zDXY2qpFX&ttkCDW|3=0~Wzpz>++7eN$reK2);n<=9KvIILOC z@nPU%WrzoW=Q>fs`}{ZP3TAVx4`)qXUwEmBcJ-h~#`~w#6{nL6$h>ssC9$tD%HG}Km+6q5uzZZXD3|_Ymu(>~3Bwm6PH^{Snbvp+$XPAztkF(YS$=dtO3#eg|A`S~3npxY zkBBN9(sGISRzdHJl-0djm02lRiqEy@Yz&^}rrxxrcfh=zh(Glyt+d)Mq>Zf9qqYyP?C}Qr`gWfUgbS5apVY@!wy9)a@78nBm?#5+6A}o z_D$x<8M(`+EA_qTQPSy5&?t2gm*=DI4bP%U8JWono;m#RcCTIgh^XEwdb2D{nkjLo zS^W7m)PA0jP2fL0w5QYmOrNuS)8Sl4Ll61A&dm|$X&qenWR6hwhhGejSX|bU%3^zX z-ibTMAgzmZgNA!mMwlqkj=-_ne7ag4RMSikZHv_T6JVJDyZGd|`h25*A`}Cx%dwWF zZzG+{lhm%rtmEYON{1(L52NPjUYbxoyKWgJx`B{6##o%wAv~X->nvF5?0aTpeDXOB zn5Kip59@I#f%D~-=85ti`{*MN_7iS9pq5K_p{V(tP_wJtbftKoe79bJ_+~a&lA#;h z-zy!Fr#t0zWXW;|d#&}(xN&%2jLh;GKIb=Nsi(BDx$|56k8-q-S2NiZ4-48|NevO< zJ~4m%FsSmAH46uOXU6njK|t4jqN)3~;n0^{%C(e2!p15}$_6Z>E>I;X zyP@gr%or#9;;!SKf_PgnH$iW;vy-O_IuIWAZgq6up3XYsI>rVnG+%)*^Xa1-uAG?} zlGr}e%C@Iun2BKMMu=ZSQBP71_sTf|(CF)~*R!ykp^a#|D}2YY|8OPo3zMhZd`A;a z3F9=%s8x5gwHZ62nzZU)p03+|C`~lSz-`=JLEp-Qm$Oz1I>hf&feluq+MOe!pi}-> z&8x(mn<3v;%F}N}Rg&Wp5%J3CjLIPIvOdSyooE%)GULg@OUw7fKN2^U*_*&6{0$C|7B#pnn5u4!k%iqKiT=|BU_ z<0{1hx}Y65+gxoTuc^J1L}eS*UcMig;mU8pr&dT!IBRb1#_(bhlf^dg-S!+=WKa*% z-0C?d%k^<=W_MQ2=Gi`XRMCyI7_65lR% zYi!zP1-0tw*E7Y#OtQMHuTrMyv?g&K=}Hj9%SpEV;52GyBEtngOuMs+G`VSX5X1_mw7%ysTsw$fHxfbE*$~p(XJW#@ zc0%^(XiVq99h5d=_5B3gQU21zDaTKJ_UsxbIYg>IH zm4Zm1YQ`ixrL>IV~F@s`N6V`)6&Gp47QuS^fdxJx`!J*q@v@uu<$5xLbqSrOKB zJ?PMK!;o{}OAOj+H)qS+QrKToMm*$Y|JyDP^47!I%gbuMdcyoh;ZH)ul#vW(5Y`ii zEsYas!*K1AxNDxa0qn?m!+wnR%Bl}jJmtmsLT=A&#rc>>#g^Mh8IpZjn5SA;K}0dv@Y;ry4EnH|H_>`WJIv#YO;pxQHL5;!bGq) zT<=nog2SEzW3QGt@mhZO$BE~Qhq#2hybzK4mPUJw?#DT>^F0rg>-1>G@)ARL+`DeK zAG991E}t2x&9PT6aWFniYrm|>D=(}O-H5*CgqFmgKMMBIWnL%(Nn+njKY zXwYcRC-|6LI$U=Uhl{BnGN#j{sL-NTKMqUDt!BKqIsKf?2ve5fAtLDZ#^8v&0?|bT z=~Xb^@gyEAQl=xwc+`d)ZNQFE8EJ3cTDHFp^xdGYuD+Y`c0rUtkHs9LIvPZ@_czfH z>8fiJv(GPN?m11W9q(2{3=OoI#YBzf3hhcOCnPECzk(Ve=Hk1OehDS1|Ed&M@mA85 zwbSD+lc>tvplIUxM%srJKo0axDATH`$Vtae-a@5>^Fc?_NX@eh(#Q`OprqCd<+T|9 zc%_TbTQEmTNTGe#JfZCtHfBFraZm>1e_f<|*9~@NY8_t4&YR?EJ!zrOaw`Ie|HA>D z0!#^ld~l}A;wWM(N{|&#L@K+5XLYZc56{FUxRgiT7mO-LiiZ=aHZv1lM!+0`bj5W% zPS8zo?(G;+zBWX-w<(sB^IAH){#|Cq-Tq9B`Z>Ia`9aPxa=0;{me9D62q^Qn^yy{v zE>5Y5R|-xino))RUG!IFBetLGwdUBTp+I=Gnc}h5$h5hX1d&Ti0 zAtYMN*hqg{oXAanB9FCBzkRLKH*9lMW-S@McF`xALzVb8w3rjr}>E1nhy<(@LrtB?D(!|q* z5U{nZLPDzZ<`q?Vn-XRAGy0(Ez7hajk7^^-IyBncbcO_Mhvc=<45ZSkY^GoSFctjB zPhO{8(iCjZy}NAL&vt^-FhT4kqmqp~UD;!j795srpxSMVVaVa;{SZ;o(Wb2U(M88C zsfkmx6TVNttQlx76;>&gPK|i+KJMSTs|5Xen}SRpiD3s ze5|ntejuw>${<)g{8*LVE2l&|%HFBPc6RFni^4i$n4@|1c z)HEi)bV+GC5NOOles(A0mTSVqdNYCfSZuRS)DniP0j156QgLimZeJ;brrYxvu*=RD zC2%9r&nKZD?R~ndKp}Kr(fKO@$HQWdtulq)BNzZDc*nO&%&d zkcuu@>dWNZ`0zYqPm(BV=+L#=s66_bLn@H0HLXG!@>UD6ATgxl99WKfwG^l{gCehZ z;1;dhJL59vX#v0GufW}BUN()F=u18=DNsJA3f@wBrg#%d6>hrvmhg8vhbN@|euB{- z%;|wUd^QxiawZLX(|>d%Oi|*dfT6TC}2ABNc|#8DmvwMG?eY@bZ(BYqciH1E-SqFkd9qGpnAjP z4gJ(PoYCbwh!9%E{Z>_eOSe-YXlRHqh4hp<wDJCSYP|;gpi4`hEam~uMD{!ki_5#}Dn-rEOG0-cb~X>KtAzDK%6)g~q_}Rk73e{12>}>@iN)O=--k07Jt9`taP#sGzQ$U3-HdS6lh= z#mfgEf7pkiWSo^}VrC~8&rwEBc~Ei6Q-K$ViD#pb2UDu4AvvH8Z`*zge zj3$#6Sd>sq*svJ+Iym5{+sFnDe{x0?^Q{kEw(quG2tW4Wsd}OnpCV*jMZ2044D9$Q z9X-~DNVH?m;=TL^Q|<)XiD@!}fPRdL&&7P#0Pbf!)^i)%J+EwdZ6D>iNc-~isdyBB zU1)5n^l9bUscVL!XQO)vA#))Br)1}Hgd>wh^*Qf5^O{K&11V;NCm*N!_TJ&N_NaSb zo<>cd!_I6?ag7Xn7HzQ4%DB4wm|sAm<|YwnzowAKSdvI(>hZg{<+gi%z9qR-Q)e6A zwM1u9BY9Yc`KVX>X^ZTK6gV^)V6cVMiy3=p zb8vo0c^w!)f^I42PCkwP8!1jkRMMrS>PUL#po@$WgM>T=vLb36?<6VX665w&Pu|>& zDeILGzWHb=roqAJcXQcWT1n`LBa zOD(*mV9dUG^K8$YYg#i7a;m9rBCeyTNIh<5^5Lo`So#R1)9#pbHBX_(p=ANwu+s(y zplc%CS5t0F#ah@CABbjPv;!pBJ#Sk!NoOvPxoWFLF;^-(1?A+ZmVudOb> z+Sco-sWw@;DQmIsNz~YitpDv`ul><2!BHjePno2dza?rfdq6OJ9Mv+A{N(g;#wjET zcY;XB!Slf1Lp^&b;4B^2P+s$gCN`Jf{HwIqN6N4y-(F206L`fbzt6Zd$WzOx2Np{=>?Z?3jcP_|lOY!7I zU~^O?b4uEkF3HnAZ|^O&r1yNL2~3^o%P*NVm>*hbg&slaqy$U3_MY%yuw4w^oVQP& z4w>e~iG)-plWX4B5Il8PjLFlob0&~3xzXN$2(0@)J^YGH&)s_QjEU-R@?2K=?96QA zJ9C1-^g`zvwL%TG74PoTNdx;@aA-E{n6pu=<*w~Qkl_A^J|>ZtilF}?ei zunSdhFRGByzAcg-&6k3!kmx!cY|-VliC5(bSlBEbTLiV@R>ydmzTM4MKJDOGh{KR< zv5!)PK6Z^HTaHC3LY?XLL*WQ_18N~kG#w%`$ZmN!M*!jm+1E-)R z4ujXwAzm+411}p(FIySwqqZP`c8G~f2#f6&7MDD4Nrw!I0?Lm%~pnqP1{%G^BhW{Mx z|0O-IjS;>cZG0W`BfbA~wEvfM-3V+N{k3L)Ee5aue~$LUzw&8;v@iX~uW9-Fss6|3 zAKgISe~$Klzxw{|C;#6^`;m1Da4H|N0EB$HaP4pFk3T{9N1{Le1OJf=2n&dAefwiU# zU%}6p*#k>wq#)SwGy$%${|hqw2tRk`1iUNbIv(@4!fqhP-`WrSOh@0t&+XvaA{FcT zEzDoVsa*6Z|Lvp*;_m+If8WDTLPL3%nv;1_{J8N~c-PqxtQD;d8@e&UCJtl>r2+b{ z`rGyR1-$!nx0|>B_ECwKK?pwZ0PH$Sn4aV1B;z!aTZNvRPSr^~M|BcUhayYcZOz5DmocK>&u3I<%xR>y0-I&wO^a7TaFM>&_ z*}jrPNOB|W8_4>Z{j6^j>+mBoAcO_-({Qo(-VZ20#3N$a7oXw33he(Iet*5+S>Fy2{Oa3oz}kG3 zpVbW>KVCK^i5z${pYd06u&@xrMp_h~)xnqe{fsH#a3JT$_;L`U*URx4{^ZH|pM827 zFN?6w^RIB@+r^jo5jpk=wldc2|2uh)%Ub~rb`6Rm-rEUhz~lzU;fEv zeuQ6D>~~m40|UG0ZTW=zOFQ{f?H7+9=zRS+2>En5(k^y6_rnK-|J4uR@qg)q@bPOl z_0gw(rT@K&u%`~gcX6+mIVpgB2w?9f_Y`#m}SRR0C=&f_t!57*kG+dLT5!enI@$J9zx88sL4F6icu+E?U48O+y3vkq#ZC_zWWWeKI7yjGh=WpT% zctvc$&oF%Brx?D6Usd`Z7^5kD6Zd!Y{~wvZe2E`v%gB6ERkd}^){!v-Nb`xl#IGe< z4_mqf{}A^V`2VBxM?8MScX9$Bif^k3e!L$?F!LLykFW;EWrNVdC1T7{JrO&=^yd` zpuKWL41ZP!>+x%f)x&BAQJ-+**LT+AN3Qo?@q!&M?S~^T@RtMJT;JpW@5X=_>pmgwq_O_n!FuG)O@!^;F!F@L%^uLSmXZgR2|Dznpd`4cs2FApw zd}a^GIw7)N_znF3)xD)3;penz`svRNVZxbUD_2VV-as1A`G4HTe^duw;9vOY-&Z7T z<3=LSvVW#?yzl-pJe9~^Zjxpq_9H%j*RwD1j{*G6fHnfVC`Z;S5&eFNcinwAxYqf* zu>DH8U*IlEz zZ>3p}fBp0I`0;W$`_dwHkp_rsecJ!e>py`XsSou3C)RKA{ssKq0Jp`r^8PQx{Q!S1 zz>Nj;U-gH7Rwv5=KmxD|v#jtjr2QBYehk6Sk*qz30zQVEA4BkaA|T&e@KYm5*z?Cy z7!oRcyay$%#e;-v;o1+Ifajp3wR?#3V~G4v2@;R|XbBP`yPa#H!pD&FV@UcjM12fF z(zSH>5Fd|EhtG#E2mT{Ho)4Zc9>+&qc$|3LcscNLeUuk3_aA!b0n)&0VZ}ED= Q>k+S41@IW8!|VP30L&!(eE/gnu/4.3.3-vxworks-6.9/x86-linux2/bin -# /gnu/4.1.2-vxworks-6.8/x86-win32/bin -foreach(COMPILER CMAKE_C_COMPILER CMAKE_CXX_COMPILER) - if("${${COMPILER}}" MATCHES "${WIND_PROCESSOR_TYPE_PATTERN}") - string( - REGEX REPLACE - "${WIND_PROCESSOR_TYPE_PATTERN}" "\\2" - PROCESSOR_TYPE - ${${COMPILER}}) - if(NOT WIND_PROCESSOR_TYPE) - set(WIND_PROCESSOR_TYPE ${PROCESSOR_TYPE}) - endif() - - get_filename_component(COMPILER_NAME "${${COMPILER}}" NAME) - if((NOT "${COMPILER_NAME}" STREQUAL "${${COMPILER}}") AND - (NOT "${COMPILER_DIRECTORY}")) - get_filename_component( - COMPILER_PATH "${${COMPILER}}" REALPATH) - get_filename_component( - COMPILER_DIRECTORY "${COMPILER_PATH}" DIRECTORY) - endif() - else() - message(FATAL_ERROR "${COMPILER} did not conform to the expected " - "executable format. i.e. it did not end with " - "arm, mips, pentium, or ppc.") - endif() -endforeach() - - -get_filename_component(C_COMPILER_NAME "${CMAKE_C_COMPILER}" NAME) -get_filename_component(CXX_COMPILER_NAME "${CMAKE_CXX_COMPILER}" NAME) - -# Ideally the location of the compiler should be resolved at this, but invoke -# find_program as a last resort. -if(NOT COMPILER_DIRECTORY) - find_program( - COMPILER_PATH NAMES "${C_COMPILER_NAME}" "${CXX_COMPILER_NAME}") - if(COMPILER_PATH) - get_filename_component( - COMPILER_DIRECTORY "${COMPILER_PATH}" COMPILER_PATH) - else() - # The compiler must be successfully be detected by now. - message(FATAL_ERROR "Could not determine location of compiler path.") - endif() -endif() - - -get_filename_component(basename "${COMPILER_DIRECTORY}" NAME) -get_filename_component(basedir "${COMPILER_DIRECTORY}" DIRECTORY) -while(basename) - if("${basename}" MATCHES "${WIND_PLATFORM_PATTERN}") - string( - REGEX REPLACE "${WIND_PLATFORM_PATTERN}" "\\1" version ${basename}) - if(NOT CMAKE_SYSTEM_VERSION) - set(CMAKE_SYSTEM_VERSION ${version}) - endif() - - # The current base directory may be the WindRiver directory depending - # on wether a "gnu" directory exists or not, but that is evaluated in - # the next iteration. - set(WIND_HOME "${basedir}") - set(WIND_PLATFORM "${basename}") - elseif(CMAKE_SYSTEM_VERSION AND WIND_HOME AND WIND_HOST_TYPE) - # The "gnu" directory may not be part of the path. If it is, strip it. - if("${basename}" STREQUAL "gnu") - set(WIND_HOME "${basedir}") - endif() - break() - elseif("${basename}" MATCHES "${WIND_HOST_TYPE_PATTERN}") - set(WIND_HOST_TYPE "${basename}") - endif() - - get_filename_component(basename ${basedir} NAME) - get_filename_component(basedir ${basedir} DIRECTORY) -endwhile() - - -# VxWorks commands require the WIND_BASE environment variable, so this script -# will support it too. If the environment variable is not set, the necessary -# path information is deduced from the compiler path. -if(NOT WIND_BASE) - set(WIND_BASE $ENV{WIND_BASE}) -endif() - -if(NOT WIND_BASE) - set(WIND_BASE "${WIND_HOME}/vxworks-${CMAKE_SYSTEM_VERSION}") -endif() - -# Verify the location WIND_BASE references actually exists. -if(NOT EXISTS ${WIND_BASE}) - message(FATAL_ERROR "VxWorks base directory ${WIND_BASE} does not exist, " - "please ensure the toolchain information is correct.") -elseif(NOT ENV{WIND_BASE}) - # WIND_BASE environment variable must be exported during generation - # otherwise compiler tests will fail. - set(ENV{WIND_BASE} "${WIND_BASE}") -endif() - - -if(NOT CMAKE_C_COMPILER_VERSION) - execute_process( - COMMAND "${CMAKE_C_COMPILER}" -dumpversion - OUTPUT_VARIABLE CMAKE_C_COMPILER_VERSION) - string(STRIP "${CMAKE_C_COMPILER_VERSION}" CMAKE_C_COMPILER_VERSION) - message(STATUS "VxWorks C compiler version ${CMAKE_C_COMPILER_VERSION}") -endif() - -if(NOT CMAKE_CXX_COMPILER_VERSION) - execute_process( - COMMAND "${CMAKE_CXX_COMPILER}" -dumpversion - OUTPUT_VARIABLE CMAKE_CXX_COMPILER_VERSION) - string(STRIP "${CMAKE_CXX_COMPILER_VERSION}" CMAKE_CXX_COMPILER_VERSION) - message(STATUS "VxWorks CXX compiler version ${CMAKE_C_COMPILER_VERSION}") -endif() - -set(CMAKE_C_COMPILER_ID GNU) -set(CMAKE_CXX_COMPILER_ID GNU) - - -# CMAKE_SOURCE_DIR does not resolve to the actual source directory because -# platform files are processed to early on in the process. -set(ROOT "${CMAKE_MODULE_PATH}/../") - -if(WIN32) - set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_BINARY_DIR}/launch-c.bat") - set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_BINARY_DIR}/launch-cxx.bat") - configure_file( - "${ROOT}/launch-c.bat.in" "${CMAKE_C_COMPILER_LAUNCHER}" @ONLY) - configure_file( - "${ROOT}/launch-cxx.bat.in" "${CMAKE_CXX_COMPILER_LAUNCHER}" @ONLY) -else() - # Check if a directory like lmapi-* exists (VxWorks 6.9) and append it to - # LD_LIBRARY_PATH. - file(GLOB WIND_LMAPI LIST_DIRECTORIES true "${WIND_HOME}/lmapi-*") - if(WIND_LMAPI) - set(WIND_LMAPI "${WIND_LMAPI}/${WIND_HOST_TYPE}/lib") - endif() - - set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_BINARY_DIR}/launch-c") - set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_BINARY_DIR}/launch-cxx") - configure_file( - "${ROOT}/launch-c.in" "${CMAKE_C_COMPILER_LAUNCHER}" @ONLY) - configure_file( - "${ROOT}/launch-cxx.in" "${CMAKE_CXX_COMPILER_LAUNCHER}" @ONLY) - execute_process(COMMAND chmod a+rx "${CMAKE_C_COMPILER_LAUNCHER}") - execute_process(COMMAND chmod a+rx "${CMAKE_CXX_COMPILER_LAUNCHER}") -endif() - - -set(WIND_INCLUDE_DIRECTORY "${WIND_BASE}/target/h") - -# Versions before 6.8 have a different path for common libs. -if("${CMAKE_SYSTEM_VERSION}" VERSION_GREATER "6.8") - set(WIND_LIBRARY_DIRECTORY "${WIND_BASE}/target/lib/usr/lib/${WIND_PROCESSOR_TYPE}/${CMAKE_SYSTEM_PROCESSOR}/common") -else() - set(WIND_LIBRARY_DIRECTORY "${WIND_BASE}/target/usr/lib/${WIND_PROCESSOR_TYPE}/${CMAKE_SYSTEM_PROCESSOR}/common") -endif() - -if(NOT EXISTS "${WIND_LIBRARY_DIRECTORY}") - message(FATAL_ERROR "${CMAKE_SYSTEM_PROCESSOR} is not part of the " - "${WIND_PROCESSOR_TYPE} processor family.") -endif() - -include_directories(BEFORE SYSTEM "${WIND_INCLUDE_DIRECTORY}") -link_directories("${WIND_LIBRARY_DIRECTORY}") - diff --git a/src/cmake/scripts/CoverageConvenience.cmake b/src/cmake/scripts/CoverageConvenience.cmake deleted file mode 100644 index 6a952b8..0000000 --- a/src/cmake/scripts/CoverageConvenience.cmake +++ /dev/null @@ -1,134 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# - -# -# This script will run all tests and generates various coverage reports. -# -# Example usage: -# $ cmake -DCOVERAGE_SETTINGS=/CoverageSettings.cmake -P /cmake/scripts/CoverageConvenience.cmake -# If you start the scripts while in then you don't have to provide the COVERAGE_SETTINGS file. -# -cmake_minimum_required(VERSION 3.5) - -# Get Coverage configuration file -if(NOT COVERAGE_SETTINGS) - set(COVERAGE_SETTINGS ${CMAKE_CURRENT_BINARY_DIR}/CoverageSettings.cmake) -endif() -include(${COVERAGE_SETTINGS}) - -message(STATUS "Config file: ${COVERAGE_SETTINGS}") -message(STATUS "Source directory: ${COVERAGE_SOURCE_DIR}") -message(STATUS "Test directory: ${COVERAGE_RUN_DIR}") -message(STATUS "Output directory: ${COVERAGE_OUTPUT_DIR}") - -set(COVERAGE_SCRIPTS_DIR "${COVERAGE_SOURCE_DIR}/cmake/scripts") - -############################################################################### -# -# Detect generators -# -############################################################################### -set(GENERATE_COVERAGE TRUE) -if(GENERATE_COVERAGE) - find_program(GCOV_PATH gcov PARENT_SCOPE) - if(NOT GCOV_PATH) - set(GENERATE_COVERAGE FALSE) - message(STATUS "[SKIP] Coverage generators - gcov (could not find gcov)") - endif() -endif() -if(GENERATE_COVERAGE) - message(STATUS "[ OK ] Coverage generators - gcov") -endif() - -set(GENERATE_COVERAGE_HTML TRUE) -if(GENERATE_COVERAGE_HTML) - find_program(LCOV_PATH lcov PARENT_SCOPE) - if(NOT LCOV_PATH) - set(GENERATE_COVERAGE_HTML FALSE) - message(STATUS "[SKIP] Coverage generators - HTML (could not find lcov)") - endif() -endif() -if(GENERATE_COVERAGE_HTML) - find_program(GENHTML_PATH genhtml PARENT_SCOPE) - if(NOT GENHTML_PATH) - set(GENERATE_COVERAGE_HTML FALSE) - message(STATUS "[SKIP] Coverage generators - HTML (could not find genhtml)") - endif() -endif() -if(GENERATE_COVERAGE_HTML) - message(STATUS "[ OK ] Coverage generators - HTML (lcov and genhtml)") -endif() - -set(GENERATE_COVERAGE_COBERTURA TRUE) -if(GENERATE_COVERAGE_COBERTURA) - find_program(GCOVR_PATH gcovr PARENT_SCOPE) - if(NOT GCOVR_PATH) - set(GENERATE_COVERAGE_COBERTURA FALSE) - message(STATUS "[SKIP] Coverage generators - Cobertura (could not find gcovr)") - endif() -endif() -if(GENERATE_COVERAGE_COBERTURA) - message(STATUS "[ OK ] Coverage generators - Cobertura (gcovr)") -endif() - -if(NOT GENERATE_COVERAGE) - message(FATAL_ERROR "Could not find the main coverage generator 'gcov'") -elseif(NOT GENERATE_COVERAGE_HTML AND NOT GENERATE_COVERAGE_COBERTURA) - message(FATAL_ERROR "Could not find either of the two coverage report generators") -endif() - - - -############################################################################### -# -# Setup environment -# -############################################################################### -message(STATUS "Setup environment") -if(GENERATE_COVERAGE_HTML) - execute_process(COMMAND ${CMAKE_COMMAND} -DCOVERAGE_SETTINGS=${COVERAGE_SETTINGS} -P ${COVERAGE_SCRIPTS_DIR}/CoveragePreHtml.cmake - WORKING_DIRECTORY ${COVERAGE_RUN_DIR}) -endif() -if(GENERATE_COVERAGE_COBERTURA) - execute_process(COMMAND ${CMAKE_COMMAND} -DCOVERAGE_SETTINGS=${COVERAGE_SETTINGS} -P ${COVERAGE_SCRIPTS_DIR}/CoveragePreCobertura.cmake - WORKING_DIRECTORY ${COVERAGE_RUN_DIR}) -endif() - - - -############################################################################### -# -# Generate coverage results by running all the tests -# -############################################################################### -message(STATUS "Run all test to get coverage") -execute_process(COMMAND ctest ${COVERAGE_QUIET_FLAG} -T test - WORKING_DIRECTORY ${COVERAGE_RUN_DIR}) -execute_process(COMMAND ctest ${COVERAGE_QUIET_FLAG} -T coverage - WORKING_DIRECTORY ${COVERAGE_RUN_DIR}) - - - -############################################################################### -# -# Generate coverage reports -# -############################################################################### -if(GENERATE_COVERAGE_HTML) - execute_process(COMMAND ${CMAKE_COMMAND} -DCOVERAGE_SETTINGS=${COVERAGE_SETTINGS} -P ${COVERAGE_SCRIPTS_DIR}/CoveragePostHtml.cmake - WORKING_DIRECTORY ${COVERAGE_RUN_DIR}) -endif() -if(GENERATE_COVERAGE_COBERTURA) - execute_process(COMMAND ${CMAKE_COMMAND} -DCOVERAGE_SETTINGS=${COVERAGE_SETTINGS} -P ${COVERAGE_SCRIPTS_DIR}/CoveragePostCobertura.cmake - WORKING_DIRECTORY ${COVERAGE_RUN_DIR}) -endif() - diff --git a/src/cmake/scripts/CoveragePostCobertura.cmake b/src/cmake/scripts/CoveragePostCobertura.cmake deleted file mode 100644 index c28a1c8..0000000 --- a/src/cmake/scripts/CoveragePostCobertura.cmake +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# - -# -# This script assumes that all test have been run and gcov results are available. -# It will generate the Cobertura output from the gcov results. -# -# Example usage: -# $ cmake -DCOVERAGE_SETTINGS=/CoverageSettings.cmake -P /cmake/scripts/CoveragePreCobertura.cmake -# $ ctest -T test -# $ ctest -T coverage -# $ ctest -DCOVERAGE_SETTINGS=/CoverageSettings.cmake -P /cmake/scripts/CoveragePostCobertura.cmake -# If you start the scripts while in then you don't have to provide the COVERAGE_SETTINGS file. -# -cmake_minimum_required(VERSION 3.5) - -# Get Coverage configuration file -if(NOT COVERAGE_SETTINGS) - set(COVERAGE_SETTINGS ${CMAKE_CURRENT_BINARY_DIR}/CoverageSettings.cmake) -endif() -include(${COVERAGE_SETTINGS}) - -# Some debug -#message(STATUS "Config file: ${COVERAGE_SETTINGS}") -#message(STATUS "Source directory: ${COVERAGE_SOURCE_DIR}") -#message(STATUS "Test directory: ${COVERAGE_RUN_DIR}") -#message(STATUS "Output directory: ${COVERAGE_OUTPUT_DIR}") - -# Find gcovr to generate Cobertura results -find_program(GCOVR_PATH gcovr PARENT_SCOPE) -if(NOT GCOVR_PATH) - message(FATAL_ERROR "Could not find gcovr to generate Cobertura coverage.") -endif() - -# Create location to put the result file. -file(MAKE_DIRECTORY ${COVERAGE_OUTPUT_DIR}) - -execute_process(COMMAND ${GCOVR_PATH} -x -r ${COVERAGE_SOURCE_DIR} -e ".*/${COVERAGE_EXCLUDE_TESTS}/.*" -e ".*/${COVERAGE_EXCLUDE_EXAMPLES}/.*" -e ".*/${COVERAGE_EXCLUDE_BUILD_SUPPORT}/.*" -o ${COVERAGE_OUTPUT_DIR}/cobertura.xml - WORKING_DIRECTORY ${COVERAGE_RUN_DIR}) - - -message(STATUS "The Cobertura report can be found here: ${COVERAGE_OUTPUT_DIR}/cobertura.xml") - diff --git a/src/cmake/scripts/CoveragePostHtml.cmake b/src/cmake/scripts/CoveragePostHtml.cmake deleted file mode 100644 index f8a5739..0000000 --- a/src/cmake/scripts/CoveragePostHtml.cmake +++ /dev/null @@ -1,71 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# - -# -# This script assumes that all test have been run and gcov results are available. -# It will generate the HTML output from the gcov results. -# -# Example usage: -# $ cmake -DCOVERAGE_SETTINGS=/CoverageSettings.cmake -P /cmake/scripts/CoveragePreHtml.cmake -# $ ctest -T test -# $ ctest -T coverage -# $ ctest -DCOVERAGE_SETTINGS=/CoverageSettings.cmake -P /cmake/scripts/CoveragePostHtml.cmake -# If you start the scripts while in then you don't have to provide the COVERAGE_SETTINGS file. -# -cmake_minimum_required(VERSION 3.5) - -# Get Coverage configuration file -if(NOT COVERAGE_SETTINGS) - set(COVERAGE_SETTINGS ${CMAKE_CURRENT_BINARY_DIR}/CoverageSettings.cmake) -endif() -include(${COVERAGE_SETTINGS}) - -# Some debug -#message(STATUS "Config file: ${COVERAGE_SETTINGS}") -#message(STATUS "Source directory: ${COVERAGE_SOURCE_DIR}") -#message(STATUS "Test directory: ${COVERAGE_RUN_DIR}") -#message(STATUS "Output directory: ${COVERAGE_OUTPUT_DIR}") - -# Find tools to generate HTML coverage results -find_program(LCOV_PATH lcov PARENT_SCOPE) -if(NOT LCOV_PATH) - message(FATAL_ERROR "Could not find lcov to generate HTML coverage.") -endif() -find_program(GENHTML_PATH genhtml PARENT_SCOPE) -if(NOT GENHTML_PATH) - message(FATAL_ERROR "Could not find genhtml to generate HTML coverage.") -endif() - -# Create location to put the result file. -file(MAKE_DIRECTORY ${COVERAGE_OUTPUT_DIR}) -set(COVERAGE_HTML_OUTPUT "${COVERAGE_OUTPUT_DIR}/html") -file(MAKE_DIRECTORY ${COVERAGE_HTML_OUTPUT}) - -# Setup tmp analysis files -set(COVERAGE_INFO "${COVERAGE_HTML_OUTPUT}/coverage_html.info") -set(COVERAGE_CLEANED "${COVERAGE_INFO}.cleaned") - -# Execute lcov and genhtml commands to get HTML results -execute_process(COMMAND ${LCOV_PATH} ${COVERAGE_QUIET_FLAG} --directory . --capture --output-file ${COVERAGE_INFO} - WORKING_DIRECTORY ${COVERAGE_RUN_DIR}) -execute_process(COMMAND ${LCOV_PATH} ${COVERAGE_QUIET_FLAG} --remove ${COVERAGE_INFO} "${COVERAGE_EXCLUDE_TESTS}/*" "${COVERAGE_EXCLUDE_EXAMPLES}/*" "${COVERAGE_EXCLUDE_BUILD_SUPPORT}/*" "/usr/*" --output-file ${COVERAGE_CLEANED} - WORKING_DIRECTORY ${COVERAGE_RUN_DIR}) -execute_process(COMMAND ${GENHTML_PATH} ${COVERAGE_QUIET_FLAG} -o ${COVERAGE_HTML_OUTPUT} ${COVERAGE_CLEANED} - WORKING_DIRECTORY ${COVERAGE_RUN_DIR}) - -# Remove tmp analysis files -execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${COVERAGE_INFO} ${COVERAGE_CLEANED} - WORKING_DIRECTORY ${COVERAGE_RUN_DIR}) - - -message(STATUS "The HTML coverage report can be found here: ${COVERAGE_HTML_OUTPUT}/index.html") - diff --git a/src/cmake/scripts/CoveragePreCobertura.cmake b/src/cmake/scripts/CoveragePreCobertura.cmake deleted file mode 100644 index f774d3d..0000000 --- a/src/cmake/scripts/CoveragePreCobertura.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# - -# -# This script assumes that it is called before all tests are run and gcov results are available. -# It can be used to setup the environment needed to get proper Cobertura coverage results. -# -# Example usage: -# $ cmake -DCOVERAGE_SETTINGS=/CoverageSettings.cmake -P /cmake/scripts/CoveragePreCobertura.cmake -# $ ctest -T test -# $ ctest -T coverage -# $ ctest -DCOVERAGE_SETTINGS=/CoverageSettings.cmake -P /cmake/scripts/CoveragePostCobertura.cmake -# If you start the scripts while in then you don't have to provide the COVERAGE_SETTINGS file. -# -cmake_minimum_required(VERSION 3.5) - -# -# Nothing to do really. -# This is just added to provide consistency between Coverage scripts. -# - diff --git a/src/cmake/scripts/CoveragePreHtml.cmake b/src/cmake/scripts/CoveragePreHtml.cmake deleted file mode 100644 index a6deaa7..0000000 --- a/src/cmake/scripts/CoveragePreHtml.cmake +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# - -# -# This script assumes that it is called before all tests are run and gcov results are available. -# It can be used to setup the environment needed to get proper HTML coverage results. -# -# Example usage: -# $ cmake -DCOVERAGE_SETTINGS=/CoverageSettings.cmake -P /cmake/scripts/CoveragePreHtml.cmake -# $ ctest -T test -# $ ctest -T coverage -# $ ctest -DCOVERAGE_SETTINGS=/CoverageSettings.cmake -P /cmake/scripts/CoveragePostHtml.cmake -# If you start the scripts while in then you don't have to provide the COVERAGE_SETTINGS file. -# -cmake_minimum_required(VERSION 3.5) - -# Get Coverage configuration file -if(NOT COVERAGE_SETTINGS) - set(COVERAGE_SETTINGS ${CMAKE_CURRENT_BINARY_DIR}/CoverageSettings.cmake) -endif() -include(${COVERAGE_SETTINGS}) - -# Some debug -#message(STATUS "Config file: ${COVERAGE_SETTINGS}") -#message(STATUS "Source directory: ${COVERAGE_SOURCE_DIR}") -#message(STATUS "Test directory: ${COVERAGE_RUN_DIR}") -#message(STATUS "Output directory: ${COVERAGE_OUTPUT_DIR}") - -# Find tools to generate HTML coverage results -find_program(LCOV_PATH lcov PARENT_SCOPE) -if(NOT LCOV_PATH) - message(FATAL_ERROR "Could not find lcov to generate HTML coverage.") -endif() -find_program(GENHTML_PATH genhtml PARENT_SCOPE) -if(NOT GENHTML_PATH) - message(FATAL_ERROR "Could not find genhtml to generate HTML coverage.") -endif() - -# Reset LCOV environment -execute_process(COMMAND ${LCOV_PATH} ${COVERAGE_QUIET_FLAG} --directory . --zerocounters - WORKING_DIRECTORY ${COVERAGE_RUN_DIR}) - - diff --git a/src/cmake/vxworks.example.cmake b/src/cmake/vxworks.example.cmake deleted file mode 100644 index 9af56e8..0000000 --- a/src/cmake/vxworks.example.cmake +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# -set(CMAKE_SYSTEM_NAME VxWorks) -set(CMAKE_SYSTEM_PROCESSOR PENTIUM4) - -set(WIND_HOME "/path/to/WindRiver") -set(WIND_PROCESSOR_TYPE "pentium") - -# Binaries are named e.g. ccpentium or ccarm -set(CMAKE_C_COMPILER ${WIND_HOME}/gnu/4.3.3-vxworks-6.9/x86-linux2/bin/cc${WIND_PROCESSOR_TYPE}) -set(CMAKE_CXX_COMPILER ${WIND_HOME}/gnu/4.3.3-vxworks-6.9/x86-linux2/bin/c++${WIND_PROCESSOR_TYPE}) -set(CMAKE_AR ${WIND_HOME}/gnu/4.3.3-vxworks-6.9/x86-linux2/bin/ar${WIND_PROCESSOR_TYPE}) - -set(WIND_PROGRAM_PATH ${WIND_HOME}/vxworks-6.9/host/x86-linux2/bin;${WIND_BASE}/gnu/4.3.3-vxworks-6.9/x86-linux2/bin) -set(WIND_LIBRARY_PATH ${WIND_HOME}/target/lib/${WIND_PROCESSOR_TYPE}/${CMAKE_SYSTEM_PROCESSOR}/common) -set(WIND_INCLUDE_PATH ${WIND_HOME}/vxworks-6.9/target/h) - -set(CMAKE_FIND_ROOT_PATH ${WIND_PROGRAM_PATH};${WIND_LIBRARY_PATH};${WIND_INCLUDE_PATH}) - -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index f08808e..507aa9c 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -27,8 +27,19 @@ endif() add_definitions(-DDDSI_INCLUDE_NETWORK_PARTITIONS -DDDSI_INCLUDE_SSM) -option(DDSC_ENABLE_OPENSSL "Enable openssl support" ON) -if(DDSC_ENABLE_OPENSSL) +# 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. +# +# Historically the option was DDSC_ENABLE_OPENSSL so make some allowance for those who are +# currently relying on it. +option(ENABLE_SSL "Enable openssl support" ON) +option(DDSC_ENABLE_OPENSSL "Deprecated: please use ENABLE_SSL instead" ON) +if(NOT DDSC_ENABLE_OPENSSL) + message(ERROR "DDSC_ENABLE_OPENSSL is deprecated, please use ENABLE_SSL instead") + set(ENABLE_SSL OFF) +endif() +if(ENABLE_SSL) find_package(OpenSSL) if(OPENSSL_FOUND) add_definitions(-DDDSI_INCLUDE_SSL) @@ -36,8 +47,9 @@ if(DDSC_ENABLE_OPENSSL) if(CMAKE_GENERATOR MATCHES "Visual Studio") set_target_properties(ddsc PROPERTIES LINK_FLAGS "/ignore:4099") endif() + message(STATUS "Building with OpenSSL support") else() - message(FATAL_ERROR "To build without openssl support, set DDSC_ENABLE_OPENSSL to OFF") + message(STATUS "Building without OpenSSL support") endif() endif() @@ -68,4 +80,6 @@ install( ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib ) -add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/xtests") +if(BUILD_IDLC) + add_subdirectory(xtests) +endif() diff --git a/src/core/xtests/cdrtest/CMakeLists.txt b/src/core/xtests/cdrtest/CMakeLists.txt index 9566927..1535a9c 100644 --- a/src/core/xtests/cdrtest/CMakeLists.txt +++ b/src/core/xtests/cdrtest/CMakeLists.txt @@ -11,16 +11,10 @@ # cmake_minimum_required(VERSION 3.5) -if (NOT TARGET CycloneDDS::ddsc) - # Find the CycloneDDS package. If it is not in a default location, try - # finding it relative to the example where it most likely resides. - find_package(CycloneDDS REQUIRED PATHS ../../) -endif() - -add_compile_options("-I${PROJECT_SOURCE_DIR}/ddsrt/include") -add_compile_options("-I${PROJECT_SOURCE_DIR}/core/ddsc/include") -add_compile_options("-I${PROJECT_SOURCE_DIR}/core/ddsc/src") -add_compile_options("-I${PROJECT_SOURCE_DIR}/core/ddsi/include") +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") +add_compile_options("-I${PROJECT_SOURCE_DIR}/src/core/ddsi/include") add_compile_options("-I$ENV{OSPL_HOME}/src/abstraction/os/include") add_compile_options("-I$ENV{OSPL_HOME}/src/database/database/include") diff --git a/src/docs/CMakeLists.txt b/src/docs/CMakeLists.txt deleted file mode 100644 index 6b95a4d..0000000 --- a/src/docs/CMakeLists.txt +++ /dev/null @@ -1,218 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - -# TODO depending on requirements we can add/remove options as needed, -# these are examples of generators we'll need as a minimum. -# Perhaps we should also consider options for building subset of all docs. -# When a certain doc is related to a target, no option is needed; you can simply check if the target exists -# (i.e. if a target 'ddsc' exists, build ddsc api docs). And possibly make the target definition dependent on an option. - -option(BUILD_DOCS "Build documentation." OFF) -option(DOWNLOAD_DOCS "Download documentation." OFF) - -# When BUILD_DOCS is set, missing deps are treated as fatal errors -if (BUILD_DOCS) - set(mode FATAL_ERROR) -else() - set(mode STATUS) -endif() - -find_program(SPHINX_EXECUTABLE NAMES sphinx-build DOC "Sphinx documentation builder") -if (NOT SPHINX_EXECUTABLE) - message(${mode} "${CMAKE_PROJECT_NAME} documentation: unable to find sphinx-build executable") -endif() - -find_package(Doxygen) -if (NOT Doxygen_FOUND) - message(${mode} "${CMAKE_PROJECT_NAME} documentation: unable to find Doxygen") -endif() - -# Creating pdf from latex requires latexmk (which depends on perl, latexpdf et. al) -find_program(LATEXMK_EXECUTABLE NAMES latexmk DOC "LateX PDF Generator") -if (NOT LATEXMK_EXECUTABLE) - message(${mode} "${CMAKE_PROJECT_NAME} documentation: unable to find latexmk") -endif() - -if ((NOT DOWNLOAD_DOCS) AND SPHINX_EXECUTABLE AND Doxygen_FOUND AND LATEXMK_EXECUTABLE) - # User requested docs (USE_DOCS=1) and did not explicitely request to download docs (DOWNLOAD_DOCS=0) - # All prerequisites are available to build docs, so force BUILD_DOCS even when the user did not enable it explicitely - set(BUILD_DOCS ON PARENT_SCOPE) # for examples' docs - set(BUILD_DOCS ON) - message(STATUS "${CMAKE_PROJECT_NAME} documentation: Success (build)") -else() - # User requested docs (USE_DOCS=1) and prefers to download instead of build (or prerequisites are not available). - # So force DOWNLOAD_DOCS even when user did not enable it explicitely - set(DOWNLOAD_DOCS ON PARENT_SCOPE) # for examples' docs - set(DOWNLOAD_DOCS ON) - message(STATUS "${CMAKE_PROJECT_NAME} documentation: Success (download)") -endif() - -#set(DOCS_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/..") - -if (DOWNLOAD_DOCS) - set(JENKINS_BASE_URI "http://jenkins.prismtech.com:8080/") - set(JENKINS_DOCS_JOB_NAME "BuildChameleonLinux64bit") - set(PROJECT_PDF_URI "${JENKINS_BASE_URI}/job/${JENKINS_DOCS_JOB_NAME}/lastSuccessfulBuild/artifact/cham/builds/docs/${CMAKE_PROJECT_NAME}.pdf") - set(PROJECT_HTML_URI "${JENKINS_BASE_URI}/job/${JENKINS_DOCS_JOB_NAME}/lastSuccessfulBuild/artifact/cham/builds/docs/${CMAKE_PROJECT_NAME}HTML.tar.gz") - - add_custom_target(docs ALL) - find_program(WGET_EXECUTABLE NAMES wget DOC "wget") - if (WGET_EXECUTABLE) - # prevent wget to create numbered downloads. - add_custom_command(TARGET docs - COMMAND ${CMAKE_COMMAND} - -E remove -f "${CMAKE_PROJECT_NAME}HTML.tar.gz" - VERBATIM) - - add_custom_command(TARGET docs - COMMAND ${WGET_EXECUTABLE} - -q ${PROJECT_HTML_URI} ${PROJECT_PDF_URI} - COMMENT "Downloading documentation from target." - VERBATIM) - - # To make downloading and packaging easier. -# add_custom_command(TARGET docs -# COMMAND ${CMAKE_COMMAND} -# -E rename ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.pdf ${DOCS_OUTPUT_DIR}/${CMAKE_PROJECT_NAME}.pdf -# VERBATIM) - else() - message(STATUS "Unable to find wget. Download docs now.") - # Just try to download the docs straight away. - file(DOWNLOAD ${PROJECT_HTML_URI} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}HTML.tar.gz) - file(DOWNLOAD ${PROJECT_PDF_URI} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.pdf) - endif() - - add_custom_command(TARGET docs - COMMAND ${CMAKE_COMMAND} - -E tar "zxf" "${CMAKE_PROJECT_NAME}HTML.tar.gz" . - VERBATIM) - - # Remove downloaded files when cleaning the build tree - set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES - html - ${CMAKE_PROJECT_NAME}HTML.tar.gz - ${CMAKE_PROJECT_NAME}.pdf) - -elseif(BUILD_DOCS) - # Generate ddsc API docs in XML format using Doxygen, if the ddsc target is defined. - # The XML will serve as input for sphinx' breathe plugin - if (TARGET ${CMAKE_PROJECT_NAME}::ddsc) - # Process doxygen configuration file, for ddsc - set(doxy_conf_project "${CMAKE_PROJECT_NAME_FULL} C API Documentation") - set(doxy_conf_outputdir "ddsc_api") - set(doxy_conf_input "${PROJECT_SOURCE_DIR}/core/ddsc/include/dds/dds.h ${PROJECT_SOURCE_DIR}/core/ddsc/include/dds") - configure_file(Doxyfile.in Doxyfile @ONLY) - - add_custom_target(ddsc_docs - ${DOXYGEN_EXECUTABLE} Doxyfile - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Running Doxygen for API docs generation" - VERBATIM - ) - - # Remove generated files when cleaning the build tree - set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${doxy_conf_outputdir}) - - # Add ddsc api docs to sphinx' breathe projects - set(sph_conf_breathe_projs "\"ddsc_api\": \"${doxy_conf_outputdir}/xml\"") - - add_custom_command(TARGET ddsc_docs - POST_BUILD - WORKING_DIRECTORY "${doxy_conf_outputdir}" - COMMAND ${CMAKE_COMMAND} -E tar "zcf" "${CMAKE_PROJECT_NAME}_C_HTML.tar.gz" "ddsc") - endif() - - # Process sphinx configuration file - set(sph_conf_author "Eclipse Cyclone DDS project") - set(sph_conf_version "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") - set(sph_conf_release "${PROJECT_VERSION}") - configure_file(conf.py.in conf.py @ONLY) - - # Define a list of output formats (-b option for sphinx-build) - set(docs_builders "") - list(APPEND docs_builders html) - list(APPEND docs_builders latex) - - # Define custom commands for running sphinx-build for different docs builders - set(docs_outputs "") - foreach(builder ${docs_builders}) - set(docs_builder_output "docs_${builder}_output") - # Log stdout (not stderr) to a file instead of messing up build output - set(docs_builder_log "sphinx-build-${builder}.log") - - add_custom_command(OUTPUT ${docs_builder_output} - COMMAND ${SPHINX_EXECUTABLE} - -b ${builder} - -d ${CMAKE_CURRENT_BINARY_DIR}/cache - -c ${CMAKE_CURRENT_BINARY_DIR} - ${PROJECT_SOURCE_DIR}/docs - ${CMAKE_CURRENT_BINARY_DIR}/${builder} > ${docs_builder_log} - COMMENT "Running Sphinx for ${builder} output" - VERBATIM) - - # FIXME: This is definitely in the wrong location - if(builder STREQUAL html) - add_custom_command(OUTPUT ${docs_builder_output} - COMMAND ${CMAKE_COMMAND} - -E tar "zcf" - "${CMAKE_PROJECT_NAME}HTML.tar.gz" - "html" - APPEND - VERBATIM) - endif() - - # Create a pdf from the latex builder output, by appending a latexmk command - # TODO look into rinohtype as an alternative (don't bother with rst2pdf, it's no good) - if(builder STREQUAL latex) - add_custom_command(OUTPUT ${docs_builder_output} - COMMAND ${LATEXMK_EXECUTABLE} - -interaction=nonstopmode - -silent - -output-directory=${builder} - -pdf -dvi- -ps- -cd- ${builder}/${CMAKE_PROJECT_NAME}.tex - APPEND - VERBATIM) - - # Move the pdf, so that install rules don't need to differentiate between built and downloaded docs - add_custom_command(OUTPUT ${docs_builder_output} - COMMAND ${CMAKE_COMMAND} - -E rename - "latex/${CMAKE_PROJECT_NAME}.pdf" - "${CMAKE_PROJECT_NAME}.pdf" - APPEND - VERBATIM) - endif() - - # OUTPUT is a fake target / symbolic name, not an actual file - set_property(SOURCE ${docs_builder_output} PROPERTY SYMBOLIC 1) - # Remove generated files when cleaning the build tree - set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES - ${builder} - ${docs_builder_log}) - - # Include this builder as a dependency of the general 'docs' target - list(APPEND docs_outputs ${docs_builder_output}) - endforeach() - - # Remove generated files when cleaning the build tree - set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES - ${CMAKE_PROJECT_NAME}HTML.tar.gz - ${CMAKE_PROJECT_NAME}.pdf) - - add_custom_target(docs ALL DEPENDS ddsc_docs ${docs_outputs}) -endif() - -install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html - DESTINATION ${CMAKE_INSTALL_DOCDIR} - COMPONENT dev) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.pdf - DESTINATION ${CMAKE_INSTALL_DOCDIR} - COMPONENT dev) diff --git a/src/etc/CMakeLists.txt b/src/etc/CMakeLists.txt deleted file mode 100644 index 8bba5af..0000000 --- a/src/etc/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# -configure_file("cmake/default.xml.in" "${CMAKE_PROJECT_NAME_SMALL}.xml" @ONLY) - -set(CONFIG_FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME_SMALL}.xml") - -install( - FILES ${CONFIG_FILES} - DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}/${CMAKE_PROJECT_NAME}" - COMPONENT lib -) diff --git a/src/etc/cmake/default.xml.in b/src/etc/cmake/default.xml.in deleted file mode 100644 index 2a4853e..0000000 --- a/src/etc/cmake/default.xml.in +++ /dev/null @@ -1,29 +0,0 @@ - -<@CMAKE_PROJECT_NAME@> - - any - - - - auto - true - true - - - lax - - - warning - - - diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt deleted file mode 100644 index cdefbcc..0000000 --- a/src/examples/CMakeLists.txt +++ /dev/null @@ -1,128 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# -set(CMAKE_INSTALL_EXAMPLESDIR "${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}/examples") - -add_subdirectory(helloworld) -add_subdirectory(roundtrip) -add_subdirectory(throughput) - -if (USE_DOCS) - # TODO Move to docs CMakeLists - set(EXAMPLES_HTML_ARCHIVE "${CMAKE_PROJECT_NAME}ExamplesHTML.tar.gz") - if (DOWNLOAD_DOCS) - message(STATUS "${CMAKE_PROJECT_NAME} Examples documentation: Success (download)") - set(EXAMPLES_HTML_URI "http://jenkins.prismtech.com:8080/job/BuildChameleonLinux64bit/lastSuccessfulBuild/artifact/cham/builds/examples/${EXAMPLES_HTML_ARCHIVE}") - file(DOWNLOAD "${EXAMPLES_HTML_URI}" "${CMAKE_CURRENT_BINARY_DIR}/Downloaded${EXAMPLES_HTML_ARCHIVE}" - TIMEOUT 10 - STATUS status) - list(GET status 0 status_code) - list(GET status 1 status_string) - if (NOT status_code EQUAL 0) - message(FATAL_ERROR - "Failed to download ${EXAMPLES_HTML_URI} (Code: ${status_code}, ${status_string})") - endif() - - add_custom_target(examples_docs ALL) - add_custom_command(TARGET examples_docs - COMMAND ${CMAKE_COMMAND} -E tar "zxf" "Downloaded${EXAMPLES_HTML_ARCHIVE}" - VERBATIM) - - elseif (BUILD_DOCS) - message(STATUS "${CMAKE_PROJECT_NAME} Examples documentation: Success (build)") - # Process sphinx configuration file - set(sph_conf_author "ADLINK") - string(TIMESTAMP sph_conf_copyright "%Y, ADLINK") - set(sph_conf_version "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") - set(sph_conf_release "${PROJECT_VERSION}") - configure_file(sphinx-conf.py.in conf.py @ONLY) - - set(builder_output "examples_html_output") - set(builder_log "sphinx-examples-html.log") - add_custom_command(OUTPUT ${builder_output} - COMMAND ${SPHINX_EXECUTABLE} - -b html - -d ${CMAKE_CURRENT_BINARY_DIR}/cache - -c ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} > ${builder_log} - COMMENT "Running Sphinx for examples html output" - VERBATIM) - - # OUTPUT is a fake target / symbolic name, not an actual file - set_property(SOURCE ${builder_output} PROPERTY SYMBOLIC 1) - add_custom_target(examples_docs ALL DEPENDS ${builder_output}) - - # Archive the output html files, will become a jenkins artifact for use in other jobs - # TODO this hardcoded list and archiving should be replaced by ExternalData refs - set(html_outputs - "_static" - "search.html" - "searchindex.js" - "genindex.html" - "examples.html" - "helloworld/readme.html" - "roundtrip/readme.html" - "throughput/readme.html") - - add_custom_command(OUTPUT ${builder_output} - COMMAND ${CMAKE_COMMAND} - -E tar "zcf" - "${EXAMPLES_HTML_ARCHIVE}" - ${html_outputs} - APPEND - VERBATIM) - - # Remove generated files when cleaning the build tree - set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES - "cache" - "${builder_log}" - "objects.inv" - ${html_outputs} - "_sources" - "${EXAMPLES_HTML_ARCHIVE}") - endif() -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "Windows") - set(platform_exclude "examples/helloworld/Makefile") -elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") - set(platform_exclude "examples/helloworld/vs|examples/helloworld/HelloWorld\.sln") -else() - set(platform_exclude "this_is_a_placeholder") -endif() - -# Install example source-files -install( - DIRECTORY "${PROJECT_SOURCE_DIR}/examples/" - DESTINATION "${CMAKE_INSTALL_EXAMPLESDIR}" - COMPONENT dev - PATTERN "CMakeLists.export" EXCLUDE - PATTERN "examples/CMakeLists.txt" EXCLUDE - REGEX ${platform_exclude} EXCLUDE - REGEX "\.rst|\.py" EXCLUDE -) - -# Install example html docs files -# TODO this should be replaced by install commands that use ExternalData refs (preferably in examples' CMakeLists.txt) -install( - DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/" - DESTINATION "${CMAKE_INSTALL_EXAMPLESDIR}" - COMPONENT dev - FILES_MATCHING - PATTERN "CMakeFiles" EXCLUDE - PATTERN "cache" EXCLUDE - PATTERN "_sources" EXCLUDE - PATTERN "*.html" - PATTERN "*.js" - PATTERN "_static/*" -) - diff --git a/src/idlc/src/org/eclipse/cyclonedds/templates/c/banner.st b/src/idlc/src/org/eclipse/cyclonedds/templates/c/banner.st index d27deb4..44334ae 100644 --- a/src/idlc/src/org/eclipse/cyclonedds/templates/c/banner.st +++ b/src/idlc/src/org/eclipse/cyclonedds/templates/c/banner.st @@ -14,7 +14,6 @@ banner (file, date, version) ::= << Generated by Eclipse Cyclone DDS IDL to C Translator File name: .c Source: .idl - Generated: Cyclone DDS: V *****************************************************************/ diff --git a/src/idlc/src/org/eclipse/cyclonedds/templates/h/banner.st b/src/idlc/src/org/eclipse/cyclonedds/templates/h/banner.st index 84c3044..17c56c7 100644 --- a/src/idlc/src/org/eclipse/cyclonedds/templates/h/banner.st +++ b/src/idlc/src/org/eclipse/cyclonedds/templates/h/banner.st @@ -14,7 +14,6 @@ banner (file, date, version) ::= << Generated by Eclipse Cyclone DDS IDL to C Translator File name: .h Source: .idl - Generated: Cyclone DDS: V *****************************************************************/ diff --git a/src/mpt/tests/qos/CMakeLists.txt b/src/mpt/tests/qos/CMakeLists.txt index e2f8109..0632570 100644 --- a/src/mpt/tests/qos/CMakeLists.txt +++ b/src/mpt/tests/qos/CMakeLists.txt @@ -11,7 +11,7 @@ # include(${MPT_CMAKE}) -add_compile_options("-I${PROJECT_SOURCE_DIR}/core/ddsi/include") +add_compile_options("-I${PROJECT_SOURCE_DIR}/src/core/ddsi/include") idlc_generate(mpt_rwdata_lib "procs/rwdata.idl") diff --git a/src/scripts/CMakeLists.txt b/src/scripts/CMakeLists.txt deleted file mode 100644 index 6c82db7..0000000 --- a/src/scripts/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# - -if(CMAKE_SYSTEM_NAME MATCHES "Linux") - configure_file( - "cmake/vdds_install_examples.in" "vdds_install_examples" @ONLY) - - install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/vdds_install_examples - DESTINATION "${CMAKE_INSTALL_BINDIR}" - COMPONENT dev) -endif() - diff --git a/src/scripts/cmake/vdds_install_examples.in b/src/scripts/cmake/vdds_install_examples.in deleted file mode 100755 index 88d3210..0000000 --- a/src/scripts/cmake/vdds_install_examples.in +++ /dev/null @@ -1,199 +0,0 @@ -#!/bin/sh -# -# 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 -# - -OUTPUT_DIR= -SCRIPT_DIR= -EXAMPLES_DIR= -EXPLICIT_YES=false -HELP_SHOWN=false - - -show_help() { -# Show help only once. -if [ $HELP_SHOWN = false ]; then -cat << EOF -Usage: ${0##*/} [-h] [-y] [-d OUTDIR] - -The @CMAKE_PROJECT_NAME@ examples are probably installed in a read-only location. -By executing this script, the examples can be (re)installed to a writable -location. That could be helpful when trying to experiment with the examples. - - -d|--dir OUTDIR Install the examples in OUTDIR. - This directory should not be a sub-directory of the - examples location. - If not set, an output dir will be asked for. When asking - for an output dir, the current directory is used as - suggestion. - -h|--help This text. - -y|--yes Use 'yes' for every question. -EOF -HELP_SHOWN=true -fi -} - - -# -# Parse command line arguments. -# -if [ -z "$1" ]; then - show_help - printf '\n' -else - while :; do - case $1 in - -h|-\?|--help) - show_help - exit - ;; - -d|--dir) - if [ "$2" ]; then - OUTPUT_DIR=$2 - shift - else - show_help - printf '\nERROR: "-d|--dir" requires a non-empty option argument.\n' "$1" >&2 - exit 1 - fi - ;; - -y|--yes) - EXPLICIT_YES=true - ;; - -?*) - printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2 - ;; - *) - break - esac - shift - done -fi - - -# -# Get the location of the script. -# -SCRIPT=`readlink -f "$0"` -SCRIPT_DIR=`dirname "$SCRIPT"` - - -# -# Try a few locations where the examples probably are. -# -EXAMPLES_DIR_DEFAULT="/usr/share/@CMAKE_PROJECT_NAME@/examples" -EXAMPLES_DIR_RELATIVE="$SCRIPT_DIR/../share/@CMAKE_PROJECT_NAME@/examples" -EXAMPLES_DIR_CURRENT=`pwd` - -if [ -d "$EXAMPLES_DIR_DEFAULT" ]; then - EXAMPLES_DIR="$EXAMPLES_DIR_DEFAULT" -elif [ -d "$EXAMPLES_DIR_RELATIVE" ]; then - EXAMPLES_DIR="$EXAMPLES_DIR_RELATIVE" -elif [ -d "$EXAMPLES_DIR_CURRENT" ]; then - case "$EXAMPLES_DIR_CURRENT" in - *@CMAKE_PROJECT_NAME@/examples) EXAMPLES_DIR="$EXAMPLES_DIR_CURRENT" - esac -fi - -if [ -z "$EXAMPLES_DIR" ]; then - show_help - printf '\nERROR: Could not find the @CMAKE_PROJECT_NAME@ examples at any of these locations:\n' >&2 - printf ' - [Default ] - %s\n' "$EXAMPLES_DIR_DEFAULT" >&2 - printf ' - [Relative] - %s\n' "$EXAMPLES_DIR_RELATIVE" >&2 - printf ' - [Current ] - %s\n' "$EXAMPLES_DIR_CURRENT" >&2 - exit 1 -fi - - -# -# Only get the output dir ourselves when it wasn't already set by the -# command line arguments. -# -if [ -z "$OUTPUT_DIR" ]; then - # Assume the examples should be installed in the current directory. - OUTPUT_DIR=`pwd` - - # When explicit 'yes' is provided as a command line argument, then - # don't ask if the assumption is correct. - if [ $EXPLICIT_YES = false ]; then - - # Keep pestering the user until we have a proper answer. - while true; do - YNC= - if [ "$OUTPUT_DIR" = "$EXAMPLES_DIR" ]; then - YNC="N" - elif [ ! -w "$OUTPUT_DIR" ]; then - YNC="N" - else - read -p "Do you wish to install the @CMAKE_PROJECT_NAME@ examples in \"$OUTPUT_DIR\"? [Yes|No|Cancel] " YNC - fi - case $YNC in - [Yy]* ) break;; - [Nn]* ) read -p "New examples install directory> " OUTPUT_DIR; break;; - [Cc]* ) exit;; - * ) echo "Please answer yes, no or cancel.";; - esac - done - elif [ "$OUTPUT_DIR" = "$EXAMPLES_DIR" ]; then - show_help - printf '\nERROR: Destination is same as source.\n' - exit 1 - fi -fi - - -# -# Check if the output dir is valid. -# -if [ ! -d "$OUTPUT_DIR" ]; then - # Only ask for permission if an explicit yes wasn't part of - # the command line arguments. - if [ $EXPLICIT_YES = false ]; then - while true; do - read -p "Do you wish to create directory \"$OUTPUT_DIR\"? [Yes|No] " YN - case $YN in - [Yy]* ) break;; - [Nn]* ) exit;; - * ) echo "Please answer yes or no.";; - esac - done - fi - mkdir -p "$OUTPUT_DIR" - if [ $? -ne 0 ]; then - printf 'ERROR: Could not create directory "%s"\n' "$OUTPUT_DIR" - exit 1 - fi -fi -# If the directory still doesn't exist, exit. -if [ ! -d "$OUTPUT_DIR" ]; then - show_help - printf '\nERROR: Directory "%s" does not exist.\n' "$OUTPUT_DIR" >&2 - exit 1 -fi -# If the directory isn't writable, exit. -if [ ! -w "$OUTPUT_DIR" ]; then - show_help - printf '\nERROR: Directory "%s" does not have write permission.\n' "$OUTPUT_DIR" >&2 - exit 1 -fi - - -# -# Copy the examples. -# -cp -Rf "$EXAMPLES_DIR" "$OUTPUT_DIR" -if [ $? -ne 0 ]; then - printf 'ERROR: Could not install examples\n' - exit 1 -else - printf 'Installed @CMAKE_PROJECT_NAME@ examples into "%s"\n' "$OUTPUT_DIR" -fi - diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index 9c2d51c..27801bf 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others +# Copyright(c) 2006 to 2019 ADLINK Technology Limited and others # # This program and the accompanying materials are made available under the # terms of the Eclipse Public License v. 2.0 which is available at @@ -11,15 +11,10 @@ # set(CMAKE_INSTALL_TOOLSDIR "${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}/tools") add_subdirectory(pubsub) -add_subdirectory(config) +if(BUILD_CONFTOOL) + add_subdirectory(config) +endif() add_subdirectory(ddsls) -add_subdirectory(ddsperf) - -# VxWorks build machines use OpenJDK 8, which lack jfxrt.jar. Do not build launcher on that platform. -# -# TODO Instead of making inclusion dependent on platform name, the condition should instead be on the -# jdk vendor (Oracle JDK, not OpenJDK). Find a way to make CMake aware of jdk vendor. -#option(BUILD_LAUNCHER "Enable building of launcher." ON) -#if(NOT CMAKE_SYSTEM_NAME STREQUAL "VxWorks" AND BUILD_LAUNCHER) -# add_subdirectory(launcher) -#endif() +if(BUILD_IDLC) + add_subdirectory(ddsperf) +endif() diff --git a/src/tools/ddsperf/CMakeLists.txt b/src/tools/ddsperf/CMakeLists.txt index c1c12e0..c09c8e9 100644 --- a/src/tools/ddsperf/CMakeLists.txt +++ b/src/tools/ddsperf/CMakeLists.txt @@ -9,9 +9,11 @@ # # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # + idlc_generate(ddsperf_types ddsperf_types.idl) add_executable(ddsperf ddsperf.c) target_link_libraries(ddsperf ddsperf_types ddsc) + if(WIN32) target_compile_definitions(ddsperf PRIVATE _CRT_SECURE_NO_WARNINGS) endif() From b916f0bfb78b74c7fc1fe13558bcbf304eccfa2f Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Wed, 31 Jul 2019 08:37:41 +0200 Subject: [PATCH 130/178] Generate documentation using the FindSphinx.cmake module Signed-off-by: Jeroen Koekkoek --- CMakeLists.txt | 4 +- cmake/Modules/FindSphinx.cmake | 15 +- docs/CMakeLists.txt | 39 +- docs/manual/CMakeLists.txt | 123 +- docs/manual/Doxyfile.in | 2427 ----------------- docs/manual/_static/pictures/VORTEX_LOGO.png | Bin 27746 -> 0 bytes docs/manual/conf.py.in | 178 -- docs/manual/ddsc.rst | 2 +- examples/CMakeLists.txt | 96 +- examples/helloworld/CMakeLists.txt | 37 +- examples/helloworld/HelloWorld.sln | 54 - examples/helloworld/Makefile | 54 - .../helloworld/vs/HelloWorldPublisher.vcxproj | 142 - .../vs/HelloWorldSubscriber.vcxproj | 142 - examples/helloworld/vs/HelloWorldType.vcxproj | 86 - examples/helloworld/vs/directories.props | 30 - examples/{examples.rst => index.rst} | 0 examples/roundtrip/CMakeLists.export | 33 + examples/roundtrip/CMakeLists.txt | 29 +- examples/sphinx-conf.py.in | 86 - examples/throughput/CMakeLists.export | 33 + examples/throughput/CMakeLists.txt | 29 +- src/core/CMakeLists.txt | 15 + 23 files changed, 151 insertions(+), 3503 deletions(-) delete mode 100644 docs/manual/Doxyfile.in delete mode 100644 docs/manual/_static/pictures/VORTEX_LOGO.png delete mode 100644 docs/manual/conf.py.in delete mode 100644 examples/helloworld/HelloWorld.sln delete mode 100644 examples/helloworld/Makefile delete mode 100644 examples/helloworld/vs/HelloWorldPublisher.vcxproj delete mode 100644 examples/helloworld/vs/HelloWorldSubscriber.vcxproj delete mode 100644 examples/helloworld/vs/HelloWorldType.vcxproj delete mode 100644 examples/helloworld/vs/directories.props rename examples/{examples.rst => index.rst} (100%) create mode 100644 examples/roundtrip/CMakeLists.export delete mode 100644 examples/sphinx-conf.py.in create mode 100644 examples/throughput/CMakeLists.export diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b14033..e174ce0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -206,9 +206,7 @@ if(BUILD_IDLC) endif() option(BUILD_DOCS "Build documentation." OFF) -if(BUILD_DOCS) - add_subdirectory(docs) -endif() +add_subdirectory(docs) # Pull-in CPack and support for generating Config.cmake and packages. include(Packaging) diff --git a/cmake/Modules/FindSphinx.cmake b/cmake/Modules/FindSphinx.cmake index 2e39dfb..b4296b5 100644 --- a/cmake/Modules/FindSphinx.cmake +++ b/cmake/Modules/FindSphinx.cmake @@ -30,9 +30,11 @@ macro(_Sphinx_find_executable _exe) set(SPHINX_${_uc}_VERSION "${CMAKE_MATCH_1}") endif() - add_executable(Sphinx::${_exe} IMPORTED GLOBAL) - set_target_properties(Sphinx::${_exe} PROPERTIES - IMPORTED_LOCATION "${SPHINX_${_uc}_EXECUTABLE}") + if(NOT TARGET Sphinx::${_exe}) + add_executable(Sphinx::${_exe} IMPORTED GLOBAL) + set_target_properties(Sphinx::${_exe} PROPERTIES + IMPORTED_LOCATION "${SPHINX_${_uc}_EXECUTABLE}") + endif() set(Sphinx_${_exe}_FOUND TRUE) else() set(Sphinx_${_exe}_FOUND FALSE) @@ -120,7 +122,7 @@ endforeach() find_package_handle_standard_args( Sphinx - VERSION_VAR SPHINX_VERSION + VERSION_VAR SPHINX_BUILD_VERSION REQUIRED_VARS SPHINX_BUILD_EXECUTABLE SPHINX_BUILD_VERSION HANDLE_COMPONENTS) @@ -160,6 +162,10 @@ function(_Sphinx_generate_confpy _target _cachedir) set(SPHINX_LANGUAGE "en") endif() + if(NOT DEFINED SPHINX_MASTER) + set(SPHINX_MASTER "index") + endif() + set(_known_exts autodoc doctest intersphinx todo coverage imgmath mathjax ifconfig viewcode githubpages) @@ -197,6 +203,7 @@ function(_Sphinx_generate_confpy _target _cachedir) -v "${SPHINX_VERSION}" -r "${SPHINX_RELEASE}" -l "${SPHINX_LANGUAGE}" + --master "${SPHINX_MASTER}" ${_opts} ${_exts} "${_templatedir}" RESULT_VARIABLE _result OUTPUT_QUIET) diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 891bc0d..fa1b946 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -8,42 +8,5 @@ # http://www.eclipse.org/org/documents/edl-v10.php. # # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +add_subdirectory(manual) -# TODO depending on requirements we can add/remove options as needed, -# these are examples of generators we'll need as a minimum. -# Perhaps we should also consider options for building subset of all docs. -# When a certain doc is related to a target, no option is needed; you can simply check if the target exists -# (i.e. if a target 'ddsc' exists, build ddsc api docs). And possibly make the target definition dependent on an option. - -find_program(SPHINX_EXECUTABLE NAMES sphinx-build DOC "Sphinx documentation builder") -if (NOT SPHINX_EXECUTABLE) - message(FATAL_ERROR "${CMAKE_PROJECT_NAME} documentation: unable to find sphinx-build executable") -endif() - -find_package(Doxygen) -if (NOT Doxygen_FOUND) - message(FATAL_ERROR "${CMAKE_PROJECT_NAME} documentation: unable to find Doxygen") -endif() - -# Creating pdf from latex requires latexmk (which depends on perl, latexpdf et. al) -find_program(LATEXMK_EXECUTABLE NAMES latexmk DOC "LateX PDF Generator") -if (NOT LATEXMK_EXECUTABLE) - message(FATAL_ERROR "${CMAKE_PROJECT_NAME} documentation: unable to find latexmk") -endif() - -if (SPHINX_EXECUTABLE AND Doxygen_FOUND AND LATEXMK_EXECUTABLE) - set(BUILD_DOCS ON PARENT_SCOPE) # for examples' docs - set(BUILD_DOCS ON) - message(STATUS "${CMAKE_PROJECT_NAME} documentation: Success (build)") -endif() - -if(BUILD_DOCS) - add_subdirectory(manual) -endif() - -install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html - DESTINATION ${CMAKE_INSTALL_DOCDIR} - COMPONENT dev) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.pdf - DESTINATION ${CMAKE_INSTALL_DOCDIR} - COMPONENT dev) diff --git a/docs/manual/CMakeLists.txt b/docs/manual/CMakeLists.txt index c49b5cf..de5d686 100644 --- a/docs/manual/CMakeLists.txt +++ b/docs/manual/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others +# Copyright(c) 2006 to 2019 ADLINK Technology Limited and others # # This program and the accompanying materials are made available under the # terms of the Eclipse Public License v. 2.0 which is available at @@ -8,115 +8,16 @@ # http://www.eclipse.org/org/documents/edl-v10.php. # # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - -# TODO depending on requirements we can add/remove options as needed, -# these are examples of generators we'll need as a minimum. -# Perhaps we should also consider options for building subset of all docs. -# When a certain doc is related to a target, no option is needed; you can simply check if the target exists -# (i.e. if a target 'ddsc' exists, build ddsc api docs). And possibly make the target definition dependent on an option. - -# Generate ddsc API docs in XML format using Doxygen, if the ddsc target is defined. -# The XML will serve as input for sphinx' breathe plugin -if (TARGET ${CMAKE_PROJECT_NAME}::ddsc) - # Process doxygen configuration file, for ddsc - set(doxy_conf_project "${CMAKE_PROJECT_NAME_FULL} C API Documentation") - set(doxy_conf_outputdir "ddsc_api") - set(doxy_conf_input "${PROJECT_SOURCE_DIR}/src/core/ddsc/include/dds/dds.h ${PROJECT_SOURCE_DIR}/src/core/ddsc/include/dds") - configure_file(Doxyfile.in Doxyfile @ONLY) - - add_custom_target(ddsc_docs - ${DOXYGEN_EXECUTABLE} Doxyfile - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Running Doxygen for API docs generation" - VERBATIM) - - # Remove generated files when cleaning the build tree - set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${doxy_conf_outputdir}) - - # Add ddsc api docs to sphinx' breathe projects - set(sph_conf_breathe_projs "\"ddsc_api\": \"${doxy_conf_outputdir}/xml\"") - - add_custom_command(TARGET ddsc_docs - POST_BUILD - WORKING_DIRECTORY "${doxy_conf_outputdir}" - COMMAND ${CMAKE_COMMAND} -E tar "zcf" "${CMAKE_PROJECT_NAME}_C_HTML.tar.gz" "ddsc") +if(BUILD_DOCS) + find_package(Sphinx REQUIRED breathe) + sphinx_add_docs( + docs + BREATHE_PROJECTS ddsc_api_docs + BUILDER html + SOURCE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") + install( + DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs/" + DESTINATION "${CMAKE_INSTALL_DOCDIR}/manual" + COMPONENT dev) endif() -# Process sphinx configuration file -set(sph_conf_author "Eclipse Cyclone DDS project") -set(sph_conf_version "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") -set(sph_conf_release "${PROJECT_VERSION}") -configure_file(conf.py.in conf.py @ONLY) - -# Define a list of output formats (-b option for sphinx-build) -set(docs_builders "") -list(APPEND docs_builders html) -list(APPEND docs_builders latex) - -# Define custom commands for running sphinx-build for different docs builders -set(docs_outputs "") -foreach(builder ${docs_builders}) - set(docs_builder_output "docs_${builder}_output") - # Log stdout (not stderr) to a file instead of messing up build output - set(docs_builder_log "sphinx-build-${builder}.log") - - add_custom_command(OUTPUT ${docs_builder_output} - COMMAND ${SPHINX_EXECUTABLE} - -b ${builder} - -d ${CMAKE_CURRENT_BINARY_DIR}/cache - -c ${CMAKE_CURRENT_BINARY_DIR} - ${PROJECT_SOURCE_DIR}/docs/manual - ${CMAKE_CURRENT_BINARY_DIR}/${builder} > ${docs_builder_log} - COMMENT "Running Sphinx for ${builder} output" - VERBATIM) - - # FIXME: This is definitely in the wrong location - if(builder STREQUAL html) - add_custom_command(OUTPUT ${docs_builder_output} - COMMAND ${CMAKE_COMMAND} - -E tar "zcf" - "${CMAKE_PROJECT_NAME}HTML.tar.gz" - "html" - APPEND - VERBATIM) - endif() - - # Create a pdf from the latex builder output, by appending a latexmk command - # TODO look into rinohtype as an alternative (don't bother with rst2pdf, it's no good) - if(builder STREQUAL latex) - add_custom_command(OUTPUT ${docs_builder_output} - COMMAND ${LATEXMK_EXECUTABLE} - -interaction=nonstopmode - -silent - -output-directory=${builder} - -pdf -dvi- -ps- -cd- ${builder}/${CMAKE_PROJECT_NAME}.tex - APPEND - VERBATIM) - - # Move the pdf, so that install rules don't need to differentiate between built and downloaded docs - add_custom_command(OUTPUT ${docs_builder_output} - COMMAND ${CMAKE_COMMAND} - -E rename - "latex/${CMAKE_PROJECT_NAME}.pdf" - "${CMAKE_PROJECT_NAME}.pdf" - APPEND - VERBATIM) - endif() - - # OUTPUT is a fake target / symbolic name, not an actual file - set_property(SOURCE ${docs_builder_output} PROPERTY SYMBOLIC 1) - # Remove generated files when cleaning the build tree - set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES - ${builder} - ${docs_builder_log}) - - # Include this builder as a dependency of the general 'docs' target - list(APPEND docs_outputs ${docs_builder_output}) -endforeach() - -# Remove generated files when cleaning the build tree -set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES - ${CMAKE_PROJECT_NAME}HTML.tar.gz - ${CMAKE_PROJECT_NAME}.pdf) - -add_custom_target(docs ALL DEPENDS ddsc_docs ${docs_outputs}) diff --git a/docs/manual/Doxyfile.in b/docs/manual/Doxyfile.in deleted file mode 100644 index 3d139a2..0000000 --- a/docs/manual/Doxyfile.in +++ /dev/null @@ -1,2427 +0,0 @@ -# Doxyfile 1.8.11 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a double hash (##) is considered a comment and is placed in -# front of the TAG it is preceding. -# -# All text after a single hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists, items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (\" \"). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all text -# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv -# for the list of possible encodings. -# The default value is: UTF-8. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by -# double-quotes, unless you are using Doxywizard) that should identify the -# project for which the documentation is generated. This name is used in the -# title of most generated pages and in a few other places. -# The default value is: My Project. - -PROJECT_NAME = "@doxy_conf_project@" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. This -# could be handy for archiving the generated documentation or if some version -# control system is used. - -PROJECT_NUMBER = - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a -# quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = - -# With the PROJECT_LOGO tag one can specify a logo or an icon that is included -# in the documentation. The maximum height of the logo should not exceed 55 -# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy -# the logo to the output directory. - -PROJECT_LOGO = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path -# into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If -# left blank the current directory will be used. - -OUTPUT_DIRECTORY = @doxy_conf_outputdir@ - -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this -# option can be useful when feeding doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise causes -# performance problems for the file system. -# The default value is: NO. - -CREATE_SUBDIRS = NO - -# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII -# characters to appear in the names of generated files. If set to NO, non-ASCII -# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode -# U+3044. -# The default value is: NO. - -ALLOW_UNICODE_NAMES = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. -# The default value is: English. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member -# descriptions after the members that are listed in the file and class -# documentation (similar to Javadoc). Set to NO to disable this. -# The default value is: YES. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief -# description of a member or function before the detailed description -# -# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. -# The default value is: YES. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator that is -# used to form the text in various listings. Each string in this list, if found -# as the leading text of the brief description, will be stripped from the text -# and the result, after processing the whole list, is used as the annotated -# text. Otherwise, the brief description is used as-is. If left blank, the -# following values are used ($name is automatically replaced with the name of -# the entity):The $name class, The $name widget, The $name file, is, provides, -# specifies, contains, represents, a, an and the. - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# doxygen will generate a detailed section even if there is only a brief -# description. -# The default value is: NO. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. -# The default value is: NO. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path -# before files name in the file list and in the header files. If set to NO the -# shortest path that makes the file name unique will be used -# The default value is: YES. - -FULL_PATH_NAMES = YES - -# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. -# Stripping is only done if one of the specified strings matches the left-hand -# part of the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the path to -# strip. -# -# Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where doxygen is started. -# This tag requires that the tag FULL_PATH_NAMES is set to YES. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the -# path mentioned in the documentation of a class, which tells the reader which -# header file to include in order to use a class. If left blank only the name of -# the header file containing the class definition is used. Otherwise one should -# specify the list of include paths that are normally passed to the compiler -# using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but -# less readable) file names. This can be useful is your file systems doesn't -# support long names like on DOS, Mac, or CD-ROM. -# The default value is: NO. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the -# first line (until the first dot) of a Javadoc-style comment as the brief -# description. If set to NO, the Javadoc-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) -# The default value is: NO. - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first -# line (until the first dot) of a Qt-style comment as the brief description. If -# set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) -# The default value is: NO. - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a -# multi-line C++ special comment block (i.e. a block of //! or /// comments) as -# a brief description. This used to be the default behavior. The new default is -# to treat a multi-line C++ comment block as a detailed description. Set this -# tag to YES if you prefer the old behavior instead. -# -# Note that setting this tag to YES also means that rational rose comments are -# not recognized any more. -# The default value is: NO. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the -# documentation from any documented member that it re-implements. -# The default value is: YES. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new -# page for each member. If set to NO, the documentation of a member will be part -# of the file/class/namespace that contains it. -# The default value is: NO. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen -# uses this value to replace tabs by spaces in code fragments. -# Minimum value: 1, maximum value: 16, default value: 4. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that act as commands in -# the documentation. An alias has the form: -# name=value -# For example adding -# "sideeffect=@par Side Effects:\n" -# will allow you to put the command \sideeffect (or @sideeffect) in the -# documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines. - -ALIASES = - -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. For -# instance, some of the names that are used will be different. The list of all -# members will be omitted, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or -# Python sources only. Doxygen will then generate output that is more tailored -# for that language. For instance, namespaces will be presented as packages, -# qualified scopes will look different, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources. Doxygen will then generate output that is tailored for Fortran. -# The default value is: NO. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for VHDL. -# The default value is: NO. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given -# extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: -# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: -# Fortran. In the later case the parser tries to guess whether the code is fixed -# or free formatted code, this is the default for Fortran type files), VHDL. For -# instance to make doxygen treat .inc files as Fortran files (default is PHP), -# and .f files as C (default is Fortran), use: inc=Fortran f=C. -# -# Note: For files without extension you can use no_extension as a placeholder. -# -# Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments -# according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in -# case of backward compatibilities issues. -# The default value is: YES. - -MARKDOWN_SUPPORT = YES - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. -# The default value is: YES. - -AUTOLINK_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. -# The default value is: NO. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. -# The default value is: NO. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. -# The default value is: NO. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES will make -# doxygen to replace the get and set methods by a property in the documentation. -# This will only work if the methods are indeed getting or setting a simple -# type. If this is not the case, or you want to show the methods anyway, you -# should set this option to NO. -# The default value is: YES. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. -# The default value is: NO. - -DISTRIBUTE_GROUP_DOC = NO - -# If one adds a struct or class to a group and this option is enabled, then also -# any nested class or struct is added to the same group. By default this option -# is disabled and one has to add nested compounds explicitly via \ingroup. -# The default value is: NO. - -GROUP_NESTED_COMPOUNDS = NO - -# Set the SUBGROUPING tag to YES to allow class member groups of the same type -# (for instance a group of public functions) to be put as a subgroup of that -# type (e.g. under the Public Functions section). Set it to NO to prevent -# subgrouping. Alternatively, this can be done per class using the -# \nosubgrouping command. -# The default value is: YES. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions -# are shown inside the group in which they are included (e.g. using \ingroup) -# instead of on a separate page (for HTML and Man pages) or section (for LaTeX -# and RTF). -# -# Note that this feature does not work in combination with -# SEPARATE_MEMBER_PAGES. -# The default value is: NO. - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions -# with only public data fields or simple typedef fields will be shown inline in -# the documentation of the scope in which they are defined (i.e. file, -# namespace, or group documentation), provided this scope is documented. If set -# to NO, structs, classes, and unions are shown on a separate page (for HTML and -# Man pages) or section (for LaTeX and RTF). -# The default value is: NO. - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or -# enum is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically be -# useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. -# The default value is: NO. - -TYPEDEF_HIDES_STRUCT = NO - -# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This -# cache is used to resolve symbols given their name and scope. Since this can be -# an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The -# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range -# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest -# the optimal cache size from a speed point of view. -# Minimum value: 0, maximum value: 9, default value: 0. - -LOOKUP_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in -# documentation are documented, even if no documentation was available. Private -# class members and static file members will be hidden unless the -# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. -# Note: This will also disable the warnings about undocumented members that are -# normally produced when WARNINGS is set to YES. -# The default value is: NO. - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will -# be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal -# scope will be included in the documentation. -# The default value is: NO. - -EXTRACT_PACKAGE = NO - -# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be -# included in the documentation. -# The default value is: NO. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO, -# only classes defined in header files are included. Does not have any effect -# for Java sources. -# The default value is: YES. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. If set to YES, local methods, -# which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO, only methods in the interface are -# included. -# The default value is: NO. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base name of -# the file that contains the anonymous namespace. By default anonymous namespace -# are hidden. -# The default value is: NO. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all -# undocumented members inside documented classes or files. If set to NO these -# members will be included in the various overviews, but no documentation -# section is generated. This option has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. If set -# to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO, these declarations will be -# included in the documentation. -# The default value is: NO. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO, these -# blocks will be appended to the function's detailed documentation block. -# The default value is: NO. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation that is typed after a -# \internal command is included. If the tag is set to NO then the documentation -# will be excluded. Set it to YES to include the internal documentation. -# The default value is: NO. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. -# The default value is: system dependent. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES, the -# scope will be hidden. -# The default value is: NO. - -HIDE_SCOPE_NAMES = NO - -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will -# append additional text to a page's title, such as Class Reference. If set to -# YES the compound reference will be hidden. -# The default value is: NO. - -HIDE_COMPOUND_REFERENCE = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of -# the files that are included by a file in the documentation of that file. -# The default value is: YES. - -SHOW_INCLUDE_FILES = YES - -# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each -# grouped member an include statement to the documentation, telling the reader -# which file to include in order to use the member. -# The default value is: NO. - -SHOW_GROUPED_MEMB_INC = NO - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include -# files with double quotes in the documentation rather than with sharp brackets. -# The default value is: NO. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the -# documentation for inline members. -# The default value is: YES. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the -# (detailed) documentation of file and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. -# The default value is: YES. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief -# descriptions of file, namespace and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. Note that -# this will also influence the order of the classes in the class list. -# The default value is: NO. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the -# (brief and detailed) documentation of class members so that constructors and -# destructors are listed first. If set to NO the constructors will appear in the -# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. -# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief -# member documentation. -# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting -# detailed member documentation. -# The default value is: NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy -# of group names into alphabetical order. If set to NO the group names will -# appear in their defined order. -# The default value is: NO. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by -# fully-qualified names, including namespaces. If set to NO, the class list will -# be sorted only by class name, not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the alphabetical -# list. -# The default value is: NO. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper -# type resolution of all parameters of a function it will reject a match between -# the prototype and the implementation of a member function even if there is -# only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still -# accept a match between prototype and implementation in such cases. -# The default value is: NO. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo -# list. This list is created by putting \todo commands in the documentation. -# The default value is: YES. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test -# list. This list is created by putting \test commands in the documentation. -# The default value is: YES. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug -# list. This list is created by putting \bug commands in the documentation. -# The default value is: YES. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) -# the deprecated list. This list is created by putting \deprecated commands in -# the documentation. -# The default value is: YES. - -GENERATE_DEPRECATEDLIST = YES - -# The ENABLED_SECTIONS tag can be used to enable conditional documentation -# sections, marked by \if ... \endif and \cond -# ... \endcond blocks. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the -# initial value of a variable or macro / define can have for it to appear in the -# documentation. If the initializer consists of more lines than specified here -# it will be hidden. Use a value of 0 to hide initializers completely. The -# appearance of the value of individual variables and macros / defines can be -# controlled using \showinitializer or \hideinitializer command in the -# documentation regardless of this setting. -# Minimum value: 0, maximum value: 10000, default value: 30. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES, the -# list will mention the files that were used to generate the documentation. -# The default value is: YES. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This -# will remove the Files entry from the Quick Index and from the Folder Tree View -# (if specified). -# The default value is: YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces -# page. This will remove the Namespaces entry from the Quick Index and from the -# Folder Tree View (if specified). -# The default value is: YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command command input-file, where command is the value of the -# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by doxygen. Whatever the program writes to standard output is used as the file -# version. For an example see the documentation. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can -# optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. -# -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE -# tag is left empty. - -LAYOUT_FILE = - -# The CITE_BIB_FILES tag can be used to specify one or more bib files containing -# the reference definitions. This must be a list of .bib files. The .bib -# extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. -# For LaTeX the style of the bibliography can be controlled using -# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. See also \cite for info how to create references. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the -# messages are off. -# The default value is: NO. - -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES -# this implies that the warnings are on. -# -# Tip: Turn warnings on while writing the documentation. -# The default value is: YES. - -WARNINGS = NO - -# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate -# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag -# will automatically be disabled. -# The default value is: YES. - -WARN_IF_UNDOCUMENTED = NO - -# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. -# The default value is: YES. - -WARN_IF_DOC_ERROR = NO - -# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that -# are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. -# The default value is: NO. - -WARN_NO_PARAMDOC = NO - -# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. -# The default value is: NO. - -WARN_AS_ERROR = NO - -# The WARN_FORMAT tag determines the format of the warning messages that doxygen -# can produce. The string should contain the $file, $line, and $text tags, which -# will be replaced by the file and line number from which the warning originated -# and the warning text. Optionally the format may contain $version, which will -# be replaced by the version of the file (if it could be obtained via -# FILE_VERSION_FILTER) -# The default value is: $file:$line: $text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning and error -# messages should be written. If left blank the output is written to standard -# error (stderr). - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like myfile.cpp or -# directories like /usr/src/myproject. Separate the files or directories with -# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING -# Note: If this tag is empty the current directory is searched. - -INPUT = @doxy_conf_input@ - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses -# libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: http://www.gnu.org/software/libiconv) for the list of -# possible encodings. -# The default value is: UTF-8. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. -# -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl, -# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to specify whether or not subdirectories should -# be searched for input files as well. -# The default value is: NO. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. -# The default value is: NO. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories for example use the pattern */test/* - -EXCLUDE_PATTERNS = */tests/* - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or directories -# that contain example code fragments that are included (see the \include -# command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank all -# files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude commands -# irrespective of the value of the RECURSIVE tag. -# The default value is: NO. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or directories -# that contain images that are to be included in the documentation (see the -# \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command: -# -# -# -# where is the value of the INPUT_FILTER tag, and is the -# name of an input file. Doxygen will then use the output that the filter -# program writes to standard output. If FILTER_PATTERNS is specified, this tag -# will be ignored. -# -# Note that the filter must not add or remove lines; it is applied before the -# code is scanned, but not when the output code is generated. If lines are added -# or removed, the anchors will not be placed correctly. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: pattern=filter -# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how -# filters are used. If the FILTER_PATTERNS tag is empty or if none of the -# patterns match the file name, INPUT_FILTER is applied. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will also be used to filter the input files that are used for -# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). -# The default value is: NO. - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and -# it is also possible to disable source filtering for a specific pattern using -# *.ext= (so without naming a filter). -# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. - -FILTER_SOURCE_PATTERNS = - -# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that -# is part of the input, its contents will be placed on the main page -# (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. - -USE_MDFILE_AS_MAINPAGE = - -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will be -# generated. Documented entities will be cross-referenced with these sources. -# -# Note: To get rid of all source code in the generated output, make sure that -# also VERBATIM_HEADERS is set to NO. -# The default value is: NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. -# The default value is: NO. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any -# special comment blocks from generated source code fragments. Normal C, C++ and -# Fortran comments will always remain visible. -# The default value is: YES. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# function all documented functions referencing it will be listed. -# The default value is: NO. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES then for each documented function -# all documented entities called/used by that function will be listed. -# The default value is: NO. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES then the hyperlinks from functions in REFERENCES_RELATION and -# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will -# link to the documentation. -# The default value is: YES. - -REFERENCES_LINK_SOURCE = YES - -# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the -# source code will show a tooltip with additional information such as prototype, -# brief description and links to the definition and documentation. Since this -# will make the HTML file larger and loading of large files a bit slower, you -# can opt to disable this feature. -# The default value is: YES. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -SOURCE_TOOLTIPS = YES - -# If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of doxygen built-in -# source browser. The htags tool is part of GNU's global source tagging system -# (see http://www.gnu.org/software/global/global.html). You will need version -# 4.8.6 or higher. -# -# To use it do the following: -# - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the config file -# - Make sure the INPUT points to the root of the source tree -# - Run doxygen as normal -# -# Doxygen will invoke htags (and that will in turn invoke gtags), so these -# tools must be available from the command line (i.e. in the search path). -# -# The result: instead of the source browser generated by doxygen, the links to -# source code will now point to the output of htags. -# The default value is: NO. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a -# verbatim copy of the header file for each class for which an include is -# specified. Set to NO to disable this. -# See also: Section \class. -# The default value is: YES. - -VERBATIM_HEADERS = YES - -# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the -# cost of reduced performance. This can be particularly helpful with template -# rich C++ code for which doxygen's built-in parser lacks the necessary type -# information. -# Note: The availability of this option depends on whether or not doxygen was -# generated with the -Duse-libclang=ON option for CMake. -# The default value is: NO. - -# CLANG_ASSISTED_PARSING = NO - -# If clang assisted parsing is enabled you can provide the compiler with command -# line options that you would normally use when invoking the compiler. Note that -# the include paths will already be set by doxygen for the files and directories -# specified with INPUT and INCLUDE_PATH. -# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. - -# CLANG_OPTIONS = - -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all -# compounds will be generated. Enable this if the project contains a lot of -# classes, structs, unions or interfaces. -# The default value is: YES. - -ALPHABETICAL_INDEX = YES - -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output -# The default value is: YES. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_OUTPUT = ddsc - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each -# generated HTML page (for example: .htm, .php, .asp). -# The default value is: .html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a -# standard header. -# -# To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. -# the setting GENERATE_TREEVIEW). It is highly recommended to start with a -# default header using -# doxygen -w html new_header.html new_footer.html new_stylesheet.css -# YourConfigFile -# and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally -# uses. -# Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description -# of the possible markers and block names see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard -# footer. See HTML_HEADER for more information on how to generate a default -# footer and what special commands can be used inside the footer. See also -# section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style -# sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank doxygen will generate a default style sheet. -# See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. -# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as -# it is more robust and this tag (HTML_STYLESHEET) will in the future become -# obsolete. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_STYLESHEET = - -# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined -# cascading style sheets that are included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. -# This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefore more robust against future updates. -# Doxygen will copy the style sheet files to the output directory. -# Note: The order of the extra style sheet files is of importance (e.g. the last -# style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that the -# files will be copied as-is; there are no commands or markers available. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value -# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 -# purple, and 360 is red again. -# Minimum value: 0, maximum value: 359, default value: 220. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A -# value of 255 will produce the most vivid colors. -# Minimum value: 0, maximum value: 255, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the -# luminance component of the colors in the HTML output. Values below 100 -# gradually make the output lighter, whereas values above 100 make the output -# darker. The value divided by 100 is the actual gamma applied, so 80 represents -# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not -# change the gamma. -# Minimum value: 40, maximum value: 240, default value: 80. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = NO - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_SECTIONS = NO - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries -# shown in the various tree structured indices initially; the user can expand -# and collapse entries dynamically later on. Doxygen will expand the tree to -# such a level that at most the specified number of entries are visible (unless -# a fully collapsed tree already exceeds this amount). So setting the number of -# entries 1 will produce a full collapsed tree by default. 0 is a special value -# representing an infinite number of entries and will result in a full expanded -# tree by default. -# Minimum value: 0, maximum value: 9999, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files will be -# generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_DOCSET = NO - -# This tag determines the name of the docset feed. A documentation feed provides -# an umbrella under which multiple documentation sets from a single provider -# (such as a company or product suite) can be grouped. -# The default value is: Doxygen generated docs. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# This tag specifies a string that should uniquely identify the documentation -# set bundle. This should be a reverse domain-name style string, e.g. -# com.mycompany.MyDocSet. Doxygen will append .docset to the name. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. -# The default value is: org.doxygen.Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. -# The default value is: Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three -# additional HTML index files: index.hhp, index.hhc, and index.hhk. The -# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. -# -# The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML -# files are now used as the Windows 98 help format, and will replace the old -# Windows help format (.hlp) on all Windows platforms in the future. Compressed -# HTML files also contain an index, a table of contents, and you can search for -# words in the documentation. The HTML workshop also contains a viewer for -# compressed HTML files. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_HTMLHELP = NO - -# The CHM_FILE tag can be used to specify the file name of the resulting .chm -# file. You can add a path in front of the file if the result should not be -# written to the html output directory. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_FILE = - -# The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler (hhc.exe). If non-empty, -# doxygen will try to run the HTML help compiler on the generated index.hhp. -# The file has to be specified with full path. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -HHC_LOCATION = - -# The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -GENERATE_CHI = NO - -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) -# and project file content. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_INDEX_ENCODING = - -# The BINARY_TOC flag controls whether a binary table of contents is generated -# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it -# enables the Previous and Next buttons. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members to -# the table of contents of the HTML help documentation and to the tree view. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that -# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help -# (.qch) of the generated HTML documentation. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify -# the file name of the resulting .qch file. The path specified is relative to -# the HTML output folder. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help -# Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt -# Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- -# folders). -# The default value is: doc. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_VIRTUAL_FOLDER = doc - -# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom -# filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_SECT_FILTER_ATTRS = - -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be -# generated, together with the HTML files, they form an Eclipse help plugin. To -# install this plugin and make it available under the help contents menu in -# Eclipse, the contents of the directory containing the HTML and XML files needs -# to be copied into the plugins directory of eclipse. The name of the directory -# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. -# After copying Eclipse needs to be restarted before the help appears. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the Eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have this -# name. Each documentation set should have its own identifier. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# If you want full control over the layout of the generated HTML pages it might -# be necessary to disable the index and replace it with your own. The -# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top -# of each HTML page. A value of NO enables the index and the value YES disables -# it. Since the tabs in the index contain the same information as the navigation -# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. If the tag -# value is set to YES, a side panel will be generated containing a tree-like -# index structure (just like the one that is generated for HTML Help). For this -# to work a browser that supports JavaScript, DHTML, CSS and frames is required -# (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_TREEVIEW = YES - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. -# -# Note that a value of 0 will completely suppress the enum values from appearing -# in the overview section. -# Minimum value: 0, maximum value: 20, default value: 4. -# This tag requires that the tag GENERATE_HTML is set to YES. - -ENUM_VALUES_PER_LINE = 4 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used -# to set the initial width (in pixels) of the frame in which the tree is shown. -# Minimum value: 0, maximum value: 1500, default value: 250. -# This tag requires that the tag GENERATE_HTML is set to YES. - -TREEVIEW_WIDTH = 250 - -# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to -# external symbols imported via tag files in a separate window. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of LaTeX formulas included as images in -# the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML -# output directory to force them to be regenerated. -# Minimum value: 8, maximum value: 50, default value: 10. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering -# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX -# installed or if you want to formulas look prettier in the HTML output. When -# enabled you may also need to install MathJax separately and configure the path -# to it using the MATHJAX_RELPATH option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -USE_MATHJAX = NO - -# When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. -# Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. -# The default value is: HTML-CSS. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_FORMAT = HTML-CSS - -# When MathJax is enabled you need to specify the location relative to the HTML -# output directory using the MATHJAX_RELPATH option. The destination directory -# should contain the MathJax.js script. For instance, if the mathjax directory -# is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax -# Content Delivery Network so you can quickly see the result without installing -# MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest - -# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax -# extension names that should be enabled during MathJax rendering. For example -# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_EXTENSIONS = - -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces -# of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an -# example see the documentation. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_CODEFILE = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and -# should work on any modern browser. Note that when using HTML help -# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) -# there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then -# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to -# search using the keyboard; to jump to the search box use + S -# (what the is depends on the OS and browser, but it is typically -# , /