From 29f542b9169c21cb485b430635afddfd5ff7aa97 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 9 Nov 2018 15:28:21 +0100 Subject: [PATCH 1/7] iid and tkmap are integral to this DDSI stack and should be part of it They were made available from the DCPS layer to DDSI using some function pointers, but it makes more sense to have them as part of the DDSI core. Signed-off-by: Erik Boasson --- src/core/ddsc/CMakeLists.txt | 4 -- src/core/ddsc/src/dds__rhc.h | 4 +- src/core/ddsc/src/dds__tkmap.h | 52 ----------------- src/core/ddsc/src/dds__types.h | 7 --- src/core/ddsc/src/dds_domain.c | 2 +- src/core/ddsc/src/dds_init.c | 12 +--- src/core/ddsc/src/dds_instance.c | 30 +++++----- src/core/ddsc/src/dds_read.c | 4 +- src/core/ddsc/src/dds_rhc.c | 14 ++--- src/core/ddsc/src/dds_topic.c | 4 +- src/core/ddsc/src/dds_whc.c | 14 ++--- src/core/ddsc/src/dds_write.c | 16 ++--- src/core/ddsc/src/dds_writer.c | 2 +- src/core/ddsi/CMakeLists.txt | 4 ++ .../include/ddsi/ddsi_iid.h} | 18 ++++-- src/core/ddsi/include/ddsi/ddsi_rhc_plugin.h | 6 +- src/core/ddsi/include/ddsi/ddsi_tkmap.h | 52 +++++++++++++++++ src/core/ddsi/include/ddsi/q_config.h | 4 -- src/core/ddsi/include/ddsi/q_globals.h | 7 ++- src/core/ddsi/include/ddsi/q_transmit.h | 6 +- src/core/ddsi/include/ddsi/q_whc.h | 6 +- .../src/dds_iid.c => ddsi/src/ddsi_iid.c} | 48 +++++++++------ src/core/ddsi/src/ddsi_serdata_default.c | 2 +- .../src/dds_tkmap.c => ddsi/src/ddsi_tkmap.c} | 58 +++++++++---------- src/core/ddsi/src/q_entity.c | 6 +- src/core/ddsi/src/q_init.c | 14 +++-- src/core/ddsi/src/q_receive.c | 7 ++- src/core/ddsi/src/q_transmit.c | 22 +++---- src/core/ddsi/src/q_whc.c | 2 +- src/core/ddsi/src/q_xevent.c | 7 ++- 30 files changed, 221 insertions(+), 213 deletions(-) delete mode 100644 src/core/ddsc/src/dds__tkmap.h rename src/core/{ddsc/src/dds__iid.h => ddsi/include/ddsi/ddsi_iid.h} (69%) create mode 100644 src/core/ddsi/include/ddsi/ddsi_tkmap.h rename src/core/{ddsc/src/dds_iid.c => ddsi/src/ddsi_iid.c} (69%) rename src/core/{ddsc/src/dds_tkmap.c => ddsi/src/ddsi_tkmap.c} (78%) diff --git a/src/core/ddsc/CMakeLists.txt b/src/core/ddsc/CMakeLists.txt index b29de10..571e2fb 100644 --- a/src/core/ddsc/CMakeLists.txt +++ b/src/core/ddsc/CMakeLists.txt @@ -13,7 +13,6 @@ PREPEND(srcs_ddsc "${CMAKE_CURRENT_LIST_DIR}/src" dds_alloc.c dds_builtin.c dds_coherent.c - dds_iid.c dds_participant.c dds_reader.c dds_writer.c @@ -24,7 +23,6 @@ PREPEND(srcs_ddsc "${CMAKE_CURRENT_LIST_DIR}/src" dds_domain.c dds_instance.c dds_qos.c - dds_tkmap.c dds_entity.c dds_key.c dds_querycond.c @@ -57,7 +55,6 @@ PREPEND(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src" dds__builtin.h dds__domain.h dds__entity.h - dds__iid.h dds__init.h dds__key.h dds__listener.h @@ -71,7 +68,6 @@ PREPEND(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src" dds__rhc.h dds__stream.h dds__subscriber.h - dds__tkmap.h dds__topic.h dds__types.h dds__write.h diff --git a/src/core/ddsc/src/dds__rhc.h b/src/core/ddsc/src/dds__rhc.h index 13ff911..3007692 100644 --- a/src/core/ddsc/src/dds__rhc.h +++ b/src/core/ddsc/src/dds__rhc.h @@ -24,7 +24,7 @@ extern "C" { struct rhc; struct nn_xqos; struct ddsi_serdata; -struct tkmap_instance; +struct ddsi_tkmap_instance; struct proxy_writer_info; struct rhc * dds_rhc_new (dds_reader * reader, const struct ddsi_sertopic * topic); @@ -36,7 +36,7 @@ uint32_t dds_rhc_lock_samples (struct rhc * rhc); DDS_EXPORT bool dds_rhc_store ( struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, - struct ddsi_serdata * __restrict sample, struct tkmap_instance * __restrict tk + struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk ); void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info); void dds_rhc_relinquish_ownership (struct rhc * __restrict rhc, const uint64_t wr_iid); diff --git a/src/core/ddsc/src/dds__tkmap.h b/src/core/ddsc/src/dds__tkmap.h deleted file mode 100644 index c25be3e..0000000 --- a/src/core/ddsc/src/dds__tkmap.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 _DDS_TKMAP_H_ -#define _DDS_TKMAP_H_ - -#include "dds__types.h" -#include "os/os_atomics.h" - -#if defined (__cplusplus) -extern "C" { -#endif - -struct tkmap; -struct ddsi_serdata; -struct dds_topic; - -struct tkmap_instance -{ - struct ddsi_serdata * m_sample; - struct tkmap * m_map; - uint64_t m_iid; - os_atomic_uint32_t m_refc; -}; - - -struct tkmap * dds_tkmap_new (void); -void dds_tkmap_free (_Inout_ _Post_invalid_ struct tkmap *tkmap); -void dds_tkmap_instance_ref (_In_ struct tkmap_instance *tk); -uint64_t dds_tkmap_lookup (_In_ struct tkmap *tkmap, _In_ const struct ddsi_serdata *serdata); -_Check_return_ bool dds_tkmap_get_key (_In_ struct tkmap * map, const struct ddsi_sertopic *topic, _In_ uint64_t iid, _Out_ void * sample); -_Check_return_ struct tkmap_instance * dds_tkmap_find( - _In_ struct ddsi_serdata * sd, - _In_ const bool rd, - _In_ const bool create); -_Check_return_ struct tkmap_instance * dds_tkmap_find_by_id (_In_ struct tkmap * map, _In_ uint64_t iid); - -DDS_EXPORT _Check_return_ struct tkmap_instance * dds_tkmap_lookup_instance_ref (_In_ struct ddsi_serdata * sd); -DDS_EXPORT void dds_tkmap_instance_unref (_In_ struct tkmap_instance * tk); - -#if defined (__cplusplus) -} -#endif -#endif diff --git a/src/core/ddsc/src/dds__types.h b/src/core/ddsc/src/dds__types.h index 4821c76..158d14e 100644 --- a/src/core/ddsc/src/dds__types.h +++ b/src/core/ddsc/src/dds__types.h @@ -259,13 +259,6 @@ typedef struct dds_waitset } dds_waitset; -typedef struct dds_iid -{ - uint64_t counter; - uint32_t key[4]; -} -dds_iid; - /* Globals */ typedef struct dds_globals diff --git a/src/core/ddsc/src/dds_domain.c b/src/core/ddsc/src/dds_domain.c index 4b3e23e..4c10db5 100644 --- a/src/core/ddsc/src/dds_domain.c +++ b/src/core/ddsc/src/dds_domain.c @@ -10,7 +10,7 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include "dds__domain.h" -#include "dds__tkmap.h" +#include "ddsi/ddsi_tkmap.h" static int dds_domain_compare (const int32_t * a, const int32_t * b) { diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 5759f75..19d11fc 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -15,11 +15,11 @@ #include "os/os.h" #include "dds__init.h" #include "dds__rhc.h" -#include "dds__tkmap.h" -#include "dds__iid.h" #include "dds__domain.h" #include "dds__err.h" #include "dds__builtin.h" +#include "ddsi/ddsi_iid.h" +#include "ddsi/ddsi_tkmap.h" #include "ddsi/ddsi_serdata.h" #include "ddsi/q_servicelease.h" #include "ddsi/q_entity.h" @@ -239,7 +239,6 @@ extern void dds_fini (void) static int dds__init_plugin (void) { - dds_iid_init (); if (dds_global.m_dur_init) (dds_global.m_dur_init) (); return 0; } @@ -247,7 +246,6 @@ static int dds__init_plugin (void) static void dds__fini_plugin (void) { if (dds_global.m_dur_fini) (dds_global.m_dur_fini) (); - dds_iid_fini (); } void ddsi_plugin_init (void) @@ -265,12 +263,6 @@ void ddsi_plugin_init (void) ddsi_plugin.rhc_plugin.rhc_unregister_wr_fn = dds_rhc_unregister_wr; ddsi_plugin.rhc_plugin.rhc_relinquish_ownership_fn = dds_rhc_relinquish_ownership; ddsi_plugin.rhc_plugin.rhc_set_qos_fn = dds_rhc_set_qos; - ddsi_plugin.rhc_plugin.rhc_lookup_fn = dds_tkmap_lookup_instance_ref; - ddsi_plugin.rhc_plugin.rhc_unref_fn = dds_tkmap_instance_unref; - - /* Register iid generator */ - - ddsi_plugin.iidgen_fn = dds_iid_gen; } diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index f1f6ec4..bfb3252 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -16,8 +16,8 @@ #include "dds__write.h" #include "dds__writer.h" #include "dds__rhc.h" -#include "dds__tkmap.h" #include "dds__err.h" +#include "ddsi/ddsi_tkmap.h" #include "ddsi/ddsi_serdata.h" #include "ddsi/q_entity.h" #include "ddsi/q_thread.h" @@ -50,14 +50,14 @@ dds_dispose_ih( return dds_dispose_ih_ts(writer, handle, dds_time()); } -static struct tkmap_instance* +static struct ddsi_tkmap_instance* dds_instance_find( _In_ const dds_topic *topic, _In_ const void *data, _In_ const bool create) { struct ddsi_serdata *sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data); - struct tkmap_instance * inst = dds_tkmap_find (sd, false, create); + struct ddsi_tkmap_instance * inst = ddsi_tkmap_find (sd, false, create); ddsi_serdata_unref (sd); return inst; } @@ -68,10 +68,10 @@ dds_instance_remove( _In_opt_ const void *data, _In_ dds_instance_handle_t handle) { - struct tkmap_instance * inst; + struct ddsi_tkmap_instance * inst; if (handle != DDS_HANDLE_NIL) { - inst = dds_tkmap_find_by_id (gv.m_tkmap, handle); + inst = ddsi_tkmap_find_by_id (gv.m_tkmap, handle); } else { assert (data); inst = dds_instance_find (topic, data, false); @@ -83,7 +83,7 @@ dds_instance_remove( if (asleep) { thread_state_awake(thr); } - dds_tkmap_instance_unref (inst); + ddsi_tkmap_instance_unref (inst); if (asleep) { thread_state_asleep(thr); } @@ -133,7 +133,7 @@ dds_register_instance( _Out_ dds_instance_handle_t *handle, _In_ const void *data) { - struct tkmap_instance * inst; + struct ddsi_tkmap_instance * inst; dds_entity *wr; dds_return_t ret; dds__retcode_t rc; @@ -241,7 +241,7 @@ dds_unregister_instance_ih_ts( bool autodispose = true; dds_write_action action = DDS_WR_ACTION_UNREGISTER; dds_entity *wr; - struct tkmap *map; + struct ddsi_tkmap *map; const dds_topic *topic; void *sample; @@ -263,7 +263,7 @@ dds_unregister_instance_ih_ts( map = gv.m_tkmap; topic = dds_instance_info((dds_entity*)wr); sample = dds_alloc (topic->m_descriptor->m_size); - if (dds_tkmap_get_key (map, topic->m_stopic, handle, sample)) { + if (ddsi_tkmap_get_key (map, topic->m_stopic, handle, sample)) { ret = dds_write_impl ((dds_writer*)wr, sample, timestamp, action); } else{ DDS_ERROR("No instance related with the provided handle is found\n"); @@ -354,10 +354,10 @@ dds_dispose_ih_ts( rc = dds_writer_lock(writer, &wr); if (rc == DDS_RETCODE_OK) { - struct tkmap *map = gv.m_tkmap; + struct ddsi_tkmap *map = gv.m_tkmap; const dds_topic *topic = dds_instance_info((dds_entity*)wr); void *sample = dds_alloc (topic->m_descriptor->m_size); - if (dds_tkmap_get_key (map, topic->m_stopic, handle, sample)) { + if (ddsi_tkmap_get_key (map, topic->m_stopic, handle, sample)) { ret = dds_dispose_impl(wr, sample, handle, timestamp); } else { DDS_ERROR("No instance related with the provided handle is found\n"); @@ -381,7 +381,7 @@ dds_instance_lookup( { dds_instance_handle_t ih = DDS_HANDLE_NIL; const dds_topic * topic; - struct tkmap * map = gv.m_tkmap; + struct ddsi_tkmap * map = gv.m_tkmap; struct ddsi_serdata *sd; if(data == NULL){ @@ -392,7 +392,7 @@ dds_instance_lookup( topic = dds_instance_info_by_hdl (entity); if (topic) { sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data); - ih = dds_tkmap_lookup (map, sd); + ih = ddsi_tkmap_lookup (map, sd); ddsi_serdata_unref (sd); } else { DDS_ERROR("Acquired topic is NULL\n"); @@ -410,7 +410,7 @@ dds_instance_get_key( { dds_return_t ret; const dds_topic * topic; - struct tkmap * map = gv.m_tkmap; + struct ddsi_tkmap * map = gv.m_tkmap; if(data == NULL){ DDS_ERROR("Argument data is NULL\n"); @@ -426,7 +426,7 @@ dds_instance_get_key( } memset (data, 0, topic->m_descriptor->m_size); - if (dds_tkmap_get_key (map, topic->m_stopic, inst, data)) { + if (ddsi_tkmap_get_key (map, topic->m_stopic, inst, data)) { ret = DDS_RETCODE_OK; } else{ DDS_ERROR("No instance related with the provided entity is found\n"); diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 6133dd7..3e459e1 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -13,7 +13,7 @@ #include #include "dds__entity.h" #include "dds__reader.h" -#include "dds__tkmap.h" +#include "ddsi/ddsi_tkmap.h" #include "dds__rhc.h" #include "dds__err.h" #include "ddsi/q_thread.h" @@ -137,7 +137,7 @@ dds_read_impl( goto fail; } if (hand != DDS_HANDLE_NIL) { - if (dds_tkmap_find_by_id(gv.m_tkmap, hand) == NULL) { + 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); diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 72e4260..e54a7b2 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -24,7 +24,7 @@ #include "dds__entity.h" #include "dds__reader.h" #include "dds__rhc.h" -#include "dds__tkmap.h" +#include "ddsi/ddsi_tkmap.h" #include "util/ut_hopscotch.h" #include "util/ut_avl.h" @@ -253,7 +253,7 @@ struct rhc_instance nn_wctime_t tstamp; /* source time stamp of last update */ struct rhc_instance *next; /* next non-empty instance in arbitrary ordering */ struct rhc_instance *prev; - struct tkmap_instance *tk; /* backref into TK for unref'ing */ + struct ddsi_tkmap_instance *tk; /* backref into TK for unref'ing */ struct rhc_sample a_sample; /* pre-allocated storage for 1 sample */ }; @@ -504,7 +504,7 @@ static void free_instance (void *vnode, void *varg) { remove_inst_from_nonempty_list (rhc, inst); } - dds_tkmap_instance_unref (inst->tk); + ddsi_tkmap_instance_unref (inst->tk); dds_free (inst); } @@ -1023,12 +1023,12 @@ static struct rhc_instance * alloc_new_instance ( const struct proxy_writer_info *pwr_info, struct ddsi_serdata *serdata, - struct tkmap_instance *tk + struct ddsi_tkmap_instance *tk ) { struct rhc_instance *inst; - dds_tkmap_instance_ref (tk); + ddsi_tkmap_instance_ref (tk); inst = dds_alloc (sizeof (*inst)); inst->iid = tk->m_iid; inst->tk = tk; @@ -1052,7 +1052,7 @@ static rhc_store_result_t rhc_store_new_instance struct rhc *rhc, const struct proxy_writer_info *pwr_info, struct ddsi_serdata *sample, - struct tkmap_instance *tk, + struct ddsi_tkmap_instance *tk, const bool has_data, status_cb_data_t * cb_data ) @@ -1124,7 +1124,7 @@ static rhc_store_result_t rhc_store_new_instance bool dds_rhc_store ( struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, - struct ddsi_serdata * __restrict sample, struct tkmap_instance * __restrict tk + struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk ) { const uint64_t wr_iid = pwr_info->iid; diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 5e88b9d..dc63198 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -24,7 +24,7 @@ #include "ddsi/ddsi_sertopic.h" #include "ddsi/q_ddsi_discovery.h" #include "os/os_atomics.h" -#include "dds__iid.h" +#include "ddsi/ddsi_iid.h" #define DDS_TOPIC_STATUS_MASK \ DDS_INCONSISTENT_TOPIC_STATUS @@ -423,7 +423,7 @@ dds_create_topic( st = dds_alloc (sizeof (*st)); os_atomic_st32 (&st->c.refc, 1); - st->c.iid = dds_iid_gen (); + st->c.iid = ddsi_iid_gen (); st->c.status_cb = dds_topic_status_cb; st->c.status_cb_entity = top; st->c.name_typename = key; diff --git a/src/core/ddsc/src/dds_whc.c b/src/core/ddsc/src/dds_whc.c index c1dca65..1f02d62 100644 --- a/src/core/ddsc/src/dds_whc.c +++ b/src/core/ddsc/src/dds_whc.c @@ -18,7 +18,7 @@ #include "ddsi/q_unused.h" #include "ddsi/q_config.h" #include "dds__whc.h" -#include "dds__tkmap.h" +#include "ddsi/ddsi_tkmap.h" #include "util/ut_avl.h" #include "util/ut_hopscotch.h" @@ -55,7 +55,7 @@ struct whc_intvnode { struct whc_idxnode { uint64_t iid; seqno_t prune_seq; - struct tkmap_instance *tk; + struct ddsi_tkmap_instance *tk; unsigned headidx; #if __STDC_VERSION__ >= 199901L struct whc_node *hist[]; @@ -128,7 +128,7 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se 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 void whc_default_free_deferred_free_list (struct whc *whc, struct whc_node *deferred_free_list); static void whc_default_get_state(const struct whc *whc, struct whc_state *st); -static int whc_default_insert (struct whc *whc, seqno_t max_drop_seq, seqno_t seq, struct nn_plist *plist, struct ddsi_serdata *serdata, struct tkmap_instance *tk); +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); @@ -324,7 +324,7 @@ static struct whc_node *whc_findkey (const struct whc_impl *whc, const struct dd } template; struct whc_idxnode *n; check_whc (whc); - template.idxn.iid = dds_tkmap_lookup(gv.m_tkmap, serdata_key); + template.idxn.iid = ddsi_tkmap_lookup(gv.m_tkmap, serdata_key); n = ut_hhLookup (whc->idx_hash, &template.idxn); if (n == NULL) return NULL; @@ -537,7 +537,7 @@ static void delete_one_sample_from_idx (struct whc_impl *whc, struct whc_node *w #endif if (!ut_hhRemove (whc->idx_hash, idxn)) assert (0); - dds_tkmap_instance_unref(idxn->tk); + ddsi_tkmap_instance_unref(idxn->tk); os_free (idxn); } whcn->idxnode = NULL; @@ -1081,7 +1081,7 @@ static struct whc_node *whc_default_insert_seq (struct whc_impl *whc, seqno_t ma return newn; } -static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, seqno_t seq, struct nn_plist *plist, struct ddsi_serdata *serdata, struct tkmap_instance *tk) +static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, seqno_t seq, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) { struct whc_impl * const whc = (struct whc_impl *)whc_generic; struct whc_node *newn = NULL; @@ -1190,7 +1190,7 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se unsigned i; idxn = os_malloc (sizeof (*idxn) + whc->idxdepth * sizeof (idxn->hist[0])); DDS_LOG(DDS_LC_WHC, " idxn %p", (void *)idxn); - dds_tkmap_instance_ref(tk); + ddsi_tkmap_instance_ref(tk); idxn->iid = tk->m_iid; idxn->tk = tk; idxn->prune_seq = 0; diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index f0fe316..73e5f4d 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -13,7 +13,7 @@ #include #include "dds__writer.h" #include "dds__write.h" -#include "dds__tkmap.h" +#include "ddsi/ddsi_tkmap.h" #include "ddsi/q_error.h" #include "ddsi/q_thread.h" #include "ddsi/q_xmsg.h" @@ -115,7 +115,7 @@ static int deliver_locally( _In_ struct writer *wr, _In_ struct ddsi_serdata *payload, - _In_ struct tkmap_instance *tk) + _In_ struct ddsi_tkmap_instance *tk) { dds_return_t ret = DDS_RETCODE_OK; os_mutexLock (&wr->rdary.rdary_lock); @@ -193,7 +193,7 @@ dds_write_impl( const bool writekey = action & DDS_WR_KEY_BIT; dds_writer * writer = (dds_writer*) wr; struct writer * ddsi_wr = writer->m_wr; - struct tkmap_instance * tk; + struct ddsi_tkmap_instance * tk; struct ddsi_serdata *d; if (data == NULL) { @@ -220,7 +220,7 @@ dds_write_impl( ((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0) ; d->timestamp.v = tstamp; ddsi_serdata_ref(d); - tk = (ddsi_plugin.rhc_plugin.rhc_lookup_fn) (d); + tk = ddsi_tkmap_lookup_instance_ref(d); w_rc = write_sample_gc (writer->m_xp, ddsi_wr, d, tk); if (w_rc >= 0) { @@ -243,7 +243,7 @@ dds_write_impl( ret = deliver_locally (ddsi_wr, d, tk); } ddsi_serdata_unref(d); - (ddsi_plugin.rhc_plugin.rhc_unref_fn) (tk); + ddsi_tkmap_instance_unref(tk); if (asleep) { thread_state_asleep (thr); @@ -267,7 +267,7 @@ dds_writecdr_impl( struct thread_state1 * const thr = lookup_thread_state (); const bool asleep = !vtime_awake_p (thr->vtime); struct writer * ddsi_wr = wr->m_wr; - struct tkmap_instance * tk; + struct ddsi_tkmap_instance * tk; if (wr->m_topic->filter_fn) { abort(); @@ -283,7 +283,7 @@ dds_writecdr_impl( ((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0) ; d->timestamp.v = tstamp; ddsi_serdata_ref(d); - tk = (ddsi_plugin.rhc_plugin.rhc_lookup_fn) (d); + tk = ddsi_tkmap_lookup_instance_ref(d); w_rc = write_sample_gc (wr->m_xp, ddsi_wr, d, tk); if (w_rc >= 0) { /* Flush out write unless configured to batch */ @@ -306,7 +306,7 @@ dds_writecdr_impl( ret = deliver_locally (ddsi_wr, d, tk); } ddsi_serdata_unref(d); - (ddsi_plugin.rhc_plugin.rhc_unref_fn) (tk); + ddsi_tkmap_instance_unref(tk); if (asleep) { thread_state_asleep (thr); diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 3e9f1fe..4a958e6 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -20,7 +20,7 @@ #include "dds__qos.h" #include "dds__err.h" #include "dds__init.h" -#include "dds__tkmap.h" +#include "ddsi/ddsi_tkmap.h" #include "dds__whc.h" #include "ddsc/ddsc_project.h" diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 039c4a6..f88393b 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -23,6 +23,8 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" ddsi_sertopic.c ddsi_sertopic_default.c ddsi_rhc_plugin.c + ddsi_iid.c + ddsi_tkmap.c q_addrset.c q_bitset_inlines.c q_bswap.c @@ -74,6 +76,8 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/ddsi" ddsi_sertopic.h ddsi_serdata_default.h ddsi_rhc_plugin.h + ddsi_iid.h + ddsi_tkmap.h probes-constants.h q_addrset.h q_align.h diff --git a/src/core/ddsc/src/dds__iid.h b/src/core/ddsi/include/ddsi/ddsi_iid.h similarity index 69% rename from src/core/ddsc/src/dds__iid.h rename to src/core/ddsi/include/ddsi/ddsi_iid.h index b7134d4..a5b9528 100644 --- a/src/core/ddsc/src/dds__iid.h +++ b/src/core/ddsi/include/ddsi/ddsi_iid.h @@ -12,15 +12,25 @@ #ifndef _DDS_IID_H_ #define _DDS_IID_H_ -#include "dds__types.h" +#include "os/os.h" #if defined (__cplusplus) extern "C" { #endif -void dds_iid_init (void); -void dds_iid_fini (void); -uint64_t dds_iid_gen (void); +struct ddsi_iid { +#if OS_ATOMIC64_SUPPORT + os_atomic_uint64_t counter; +#else + os_mutex lock; + uint64_t counter; +#endif + uint32_t key[4]; +}; + +void ddsi_iid_init (void); +void ddsi_iid_fini (void); +uint64_t ddsi_iid_gen (void); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/ddsi/ddsi_rhc_plugin.h b/src/core/ddsi/include/ddsi/ddsi_rhc_plugin.h index ba378a3..0516e89 100644 --- a/src/core/ddsi/include/ddsi/ddsi_rhc_plugin.h +++ b/src/core/ddsi/include/ddsi/ddsi_rhc_plugin.h @@ -14,7 +14,7 @@ struct rhc; struct nn_xqos; -struct tkmap_instance; +struct ddsi_tkmap_instance; struct ddsi_serdata; struct ddsi_sertopic; struct entity_common; @@ -33,14 +33,12 @@ struct ddsi_rhc_plugin 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 tkmap_instance * __restrict tk); + struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk); void (*rhc_unregister_wr_fn) (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); - struct tkmap_instance * (*rhc_lookup_fn) (struct ddsi_serdata *serdata); - void (*rhc_unref_fn) (struct tkmap_instance *tk); }; void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct nn_xqos *xqos); diff --git a/src/core/ddsi/include/ddsi/ddsi_tkmap.h b/src/core/ddsi/include/ddsi/ddsi_tkmap.h new file mode 100644 index 0000000..82cc825 --- /dev/null +++ b/src/core/ddsi/include/ddsi/ddsi_tkmap.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 _DDS_TKMAP_H_ +#define _DDS_TKMAP_H_ + +#include "dds__types.h" +#include "os/os_atomics.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +struct ddsi_tkmap; +struct ddsi_serdata; +struct dds_topic; + +struct ddsi_tkmap_instance +{ + struct ddsi_serdata * m_sample; + struct ddsi_tkmap * m_map; + uint64_t m_iid; + os_atomic_uint32_t m_refc; +}; + + +struct ddsi_tkmap * ddsi_tkmap_new (void); +void ddsi_tkmap_free (_Inout_ _Post_invalid_ struct ddsi_tkmap *tkmap); +void ddsi_tkmap_instance_ref (_In_ struct ddsi_tkmap_instance *tk); +uint64_t ddsi_tkmap_lookup (_In_ struct ddsi_tkmap *tkmap, _In_ const struct ddsi_serdata *serdata); +_Check_return_ bool ddsi_tkmap_get_key (_In_ struct ddsi_tkmap * map, const struct ddsi_sertopic *topic, _In_ uint64_t iid, _Out_ void * sample); +_Check_return_ struct ddsi_tkmap_instance * ddsi_tkmap_find( + _In_ struct ddsi_serdata * sd, + _In_ const bool rd, + _In_ const bool create); +_Check_return_ struct ddsi_tkmap_instance * ddsi_tkmap_find_by_id (_In_ struct ddsi_tkmap * map, _In_ uint64_t iid); + +DDS_EXPORT _Check_return_ struct ddsi_tkmap_instance * ddsi_tkmap_lookup_instance_ref (_In_ struct ddsi_serdata * sd); +DDS_EXPORT void ddsi_tkmap_instance_unref (_In_ struct ddsi_tkmap_instance * tk); + +#if defined (__cplusplus) +} +#endif +#endif diff --git a/src/core/ddsi/include/ddsi/q_config.h b/src/core/ddsi/include/ddsi/q_config.h index 087b685..30989b1 100644 --- a/src/core/ddsi/include/ddsi/q_config.h +++ b/src/core/ddsi/include/ddsi/q_config.h @@ -414,10 +414,6 @@ struct ddsi_plugin /* Read cache */ struct ddsi_rhc_plugin rhc_plugin; - - /* IID generator */ - - uint64_t (*iidgen_fn) (void); }; extern struct config OSAPI_EXPORT config; diff --git a/src/core/ddsi/include/ddsi/q_globals.h b/src/core/ddsi/include/ddsi/q_globals.h index 91a2123..7c19652 100644 --- a/src/core/ddsi/include/ddsi/q_globals.h +++ b/src/core/ddsi/include/ddsi/q_globals.h @@ -18,11 +18,11 @@ #include "util/ut_fibheap.h" - #include "ddsi/q_plist.h" #include "ddsi/q_protocol.h" #include "ddsi/q_nwif.h" #include "ddsi/q_sockwaitset.h" +#include "ddsi/ddsi_iid.h" #ifdef DDSI_INCLUDE_ENCRYPTION #include "ddsi/q_security.h" /* for q_securityDecoderSet */ @@ -47,7 +47,7 @@ struct ddsi_tran_listener; struct ddsi_tran_factory; struct ut_thread_pool_s; struct debug_monitor; -struct tkmap; +struct ddsi_tkmap; typedef struct ospl_in_addr_node { nn_locator_t loc; @@ -90,7 +90,8 @@ struct q_globals { volatile int deaf; volatile int mute; - struct tkmap * m_tkmap; + struct ddsi_tkmap * m_tkmap; + struct ddsi_iid dds_iid; /* Hash tables for participants, readers, writers, proxy participants, proxy readers and proxy writers by GUID diff --git a/src/core/ddsi/include/ddsi/q_transmit.h b/src/core/ddsi/include/ddsi/q_transmit.h index 7573592..1f87abd 100644 --- a/src/core/ddsi/include/ddsi/q_transmit.h +++ b/src/core/ddsi/include/ddsi/q_transmit.h @@ -25,7 +25,7 @@ struct writer; struct whc_state; struct proxy_reader; struct ddsi_serdata; -struct tkmap_instance; +struct ddsi_tkmap_instance; /* Writing new data; serdata_twrite (serdata) is assumed to be really recentish; serdata is unref'd. If xp == NULL, data is queued, else @@ -34,8 +34,8 @@ struct 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 tkmap_instance *tk); -int write_sample_nogc (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct tkmap_instance *tk); +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); diff --git a/src/core/ddsi/include/ddsi/q_whc.h b/src/core/ddsi/include/ddsi/q_whc.h index 1a99e65..f5bc549 100644 --- a/src/core/ddsi/include/ddsi/q_whc.h +++ b/src/core/ddsi/include/ddsi/q_whc.h @@ -18,7 +18,7 @@ extern "C" { struct ddsi_serdata; struct nn_plist; -struct tkmap_instance; +struct ddsi_tkmap_instance; struct whc_node; /* opaque, but currently used for deferred free lists */ struct whc; @@ -70,7 +70,7 @@ typedef void (*whc_free_t)(struct whc *whc); reliable readers that have not acknowledged all data */ /* max_drop_seq must go soon, it's way too ugly. */ /* plist may be NULL or os_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 tkmap_instance *tk); +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 void (*whc_free_deferred_free_list_t)(struct whc *whc, struct whc_node *deferred_free_list); @@ -118,7 +118,7 @@ inline bool whc_sample_iter_borrow_next (struct whc_sample_iter *it, struct whc_ inline void whc_free (struct whc *whc) { whc->ops->free (whc); } -inline int whc_insert (struct whc *whc, seqno_t max_drop_seq, seqno_t seq, struct nn_plist *plist, struct ddsi_serdata *serdata, struct tkmap_instance *tk) { +inline int whc_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) { return whc->ops->insert (whc, max_drop_seq, seq, plist, serdata, tk); } inline unsigned whc_downgrade_to_volatile (struct whc *whc, struct whc_state *st) { diff --git a/src/core/ddsc/src/dds_iid.c b/src/core/ddsi/src/ddsi_iid.c similarity index 69% rename from src/core/ddsc/src/dds_iid.c rename to src/core/ddsi/src/ddsi_iid.c index 1809dd8..d8c092d 100644 --- a/src/core/ddsc/src/dds_iid.c +++ b/src/core/ddsi/src/ddsi_iid.c @@ -9,13 +9,10 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include "dds__iid.h" +#include "ddsi/ddsi_iid.h" #include "ddsi/q_time.h" #include "ddsi/q_globals.h" -static os_mutex dds_iid_lock_g; -static dds_iid dds_iid_g; - static void dds_tea_encrypt (uint32_t v[2], const uint32_t k[4]) { /* TEA encryption straight from Wikipedia */ @@ -43,37 +40,50 @@ static void dds_tea_decrypt (uint32_t v[2], const uint32_t k[4]) v[0]=v0; v[1]=v1; } -uint64_t dds_iid_gen (void) +uint64_t ddsi_iid_gen (void) { uint64_t iid; union { uint64_t u64; uint32_t u32[2]; } tmp; - os_mutexLock (&dds_iid_lock_g); - tmp.u64 = ++dds_iid_g.counter; - dds_tea_encrypt (tmp.u32, dds_iid_g.key); +#if OS_ATOMIC64_SUPPORT + tmp.u64 = os_atomic_inc64_nv (&gv.dds_iid.counter); +#else + os_mutexLock (&gv.dds_iid.lock); + tmp.u64 = ++gv.dds_iid.counter; + os_mutexUnlock (&gv.dds_iid.lock); +#endif + + dds_tea_encrypt (tmp.u32, gv.dds_iid.key); iid = tmp.u64; - os_mutexUnlock (&dds_iid_lock_g); return iid; } -void dds_iid_init (void) +void ddsi_iid_init (void) { union { uint64_t u64; uint32_t u32[2]; } tmp; nn_wctime_t tnow = now (); - os_mutexInit (&dds_iid_lock_g); +#if ! OS_ATOMIC64_SUPPORT + os_mutexInit (&gv.dds_iid.lock); +#endif - dds_iid_g.key[0] = (uint32_t) ((uintptr_t) &dds_iid_g); - dds_iid_g.key[1] = (uint32_t) tnow.v; - dds_iid_g.key[2] = (uint32_t) (tnow.v >> 32); - dds_iid_g.key[3] = 0xdeadbeef; + gv.dds_iid.key[0] = (uint32_t) os_procIdSelf(); + gv.dds_iid.key[1] = (uint32_t) tnow.v; + gv.dds_iid.key[2] = (uint32_t) (tnow.v >> 32); + gv.dds_iid.key[3] = 0xdeadbeef; tmp.u64 = 0; - dds_tea_decrypt (tmp.u32, dds_iid_g.key); - dds_iid_g.counter = tmp.u64; + dds_tea_decrypt (tmp.u32, gv.dds_iid.key); +#if OS_ATOMIC64_SUPPORT + os_atomic_st64 (&gv.dds_iid.counter, tmp.u64); +#else + gv.dds_iid.counter = tmp.u64; +#endif } -void dds_iid_fini (void) +void ddsi_iid_fini (void) { - os_mutexDestroy (&dds_iid_lock_g); +#if ! OS_ATOMIC64_SUPPORT + os_mutexDestroy (&gv.dds_iid.lock); +#endif } diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 548a92e..52552e7 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -24,7 +24,7 @@ #include #include "os/os.h" #include "dds__key.h" -#include "dds__tkmap.h" +#include "ddsi/ddsi_tkmap.h" #include "dds__stream.h" #include "ddsi/q_radmin.h" #include "ddsi/ddsi_serdata_default.h" diff --git a/src/core/ddsc/src/dds_tkmap.c b/src/core/ddsi/src/ddsi_tkmap.c similarity index 78% rename from src/core/ddsc/src/dds_tkmap.c rename to src/core/ddsi/src/ddsi_tkmap.c index 951ede2..089aaf5 100644 --- a/src/core/ddsc/src/dds_tkmap.c +++ b/src/core/ddsi/src/ddsi_tkmap.c @@ -17,8 +17,8 @@ #include "ddsi/q_globals.h" #include "ddsi/q_config.h" #include "ddsi/sysdeps.h" -#include "dds__tkmap.h" -#include "dds__iid.h" +#include "ddsi/ddsi_iid.h" +#include "ddsi/ddsi_tkmap.h" #include "util/ut_hopscotch.h" #include "dds__stream.h" #include "os/os.h" @@ -27,7 +27,7 @@ #define REFC_DELETE 0x80000000 #define REFC_MASK 0x0fffffff -struct tkmap +struct ddsi_tkmap { struct ut_chh * m_hh; os_mutex m_lock; @@ -49,20 +49,20 @@ static void gc_buckets (void *a) static void gc_tkmap_instance_impl (struct gcreq *gcreq) { - struct tkmap_instance *tk = gcreq->arg; + struct ddsi_tkmap_instance *tk = gcreq->arg; ddsi_serdata_unref (tk->m_sample); dds_free (tk); gcreq_free (gcreq); } -static void gc_tkmap_instance (struct tkmap_instance *tk) +static void gc_tkmap_instance (struct ddsi_tkmap_instance *tk) { struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, gc_tkmap_instance_impl); gcreq->arg = tk; gcreq_enqueue (gcreq); } -static uint32_t dds_tk_hash (const struct tkmap_instance * inst) +static uint32_t dds_tk_hash (const struct ddsi_tkmap_instance * inst) { return inst->m_sample->hash; } @@ -72,7 +72,7 @@ static uint32_t dds_tk_hash_void (const void * inst) return dds_tk_hash (inst); } -static int dds_tk_equals (const struct tkmap_instance *a, const struct tkmap_instance *b) +static int dds_tk_equals (const struct ddsi_tkmap_instance *a, const struct ddsi_tkmap_instance *b) { return (a->m_sample->ops == b->m_sample->ops) ? ddsi_serdata_eqkey (a->m_sample, b->m_sample) : 0; } @@ -82,9 +82,9 @@ static int dds_tk_equals_void (const void *a, const void *b) return dds_tk_equals (a, b); } -struct tkmap * dds_tkmap_new (void) +struct ddsi_tkmap * ddsi_tkmap_new (void) { - struct tkmap *tkmap = dds_alloc (sizeof (*tkmap)); + struct ddsi_tkmap *tkmap = dds_alloc (sizeof (*tkmap)); tkmap->m_hh = ut_chhNew (1, dds_tk_hash_void, dds_tk_equals_void, gc_buckets); os_mutexInit (&tkmap->m_lock); os_condInit (&tkmap->m_cond, &tkmap->m_lock); @@ -93,12 +93,12 @@ struct tkmap * dds_tkmap_new (void) static void free_tkmap_instance (void *vtk, UNUSED_ARG(void *f_arg)) { - struct tkmap_instance *tk = vtk; + struct ddsi_tkmap_instance *tk = vtk; ddsi_serdata_unref (tk->m_sample); os_free (tk); } -void dds_tkmap_free (_Inout_ _Post_invalid_ struct tkmap * map) +void ddsi_tkmap_free (_Inout_ _Post_invalid_ struct ddsi_tkmap * map) { ut_chhEnumUnsafe (map->m_hh, free_tkmap_instance, NULL); ut_chhFree (map->m_hh); @@ -107,10 +107,10 @@ void dds_tkmap_free (_Inout_ _Post_invalid_ struct tkmap * map) dds_free (map); } -uint64_t dds_tkmap_lookup (_In_ struct tkmap * map, _In_ const struct ddsi_serdata * sd) +uint64_t ddsi_tkmap_lookup (_In_ struct ddsi_tkmap * map, _In_ const struct ddsi_serdata * sd) { - struct tkmap_instance dummy; - struct tkmap_instance * tk; + struct ddsi_tkmap_instance dummy; + struct ddsi_tkmap_instance * tk; dummy.m_sample = (struct ddsi_serdata *) sd; tk = ut_chhLookup (map->m_hh, &dummy); return (tk) ? tk->m_iid : DDS_HANDLE_NIL; @@ -127,7 +127,7 @@ tkmap_get_key_arg; static void dds_tkmap_get_key_fn (void * vtk, void * varg) { - struct tkmap_instance * tk = vtk; + struct ddsi_tkmap_instance * tk = vtk; tkmap_get_key_arg * arg = (tkmap_get_key_arg*) varg; if (tk->m_iid == arg->m_iid) { @@ -137,7 +137,7 @@ static void dds_tkmap_get_key_fn (void * vtk, void * varg) } _Check_return_ -bool dds_tkmap_get_key (_In_ struct tkmap * map, const struct ddsi_sertopic *topic, _In_ uint64_t iid, _Out_ void * sample) +bool ddsi_tkmap_get_key (_In_ struct ddsi_tkmap * map, const struct ddsi_sertopic *topic, _In_ uint64_t iid, _Out_ void * sample) { tkmap_get_key_arg arg = { topic, iid, sample, false }; os_mutexLock (&map->m_lock); @@ -149,13 +149,13 @@ bool dds_tkmap_get_key (_In_ struct tkmap * map, const struct ddsi_sertopic *top typedef struct { uint64_t m_iid; - struct tkmap_instance * m_inst; + struct ddsi_tkmap_instance * m_inst; } tkmap_get_inst_arg; static void dds_tkmap_get_inst_fn (void * vtk, void * varg) { - struct tkmap_instance * tk = vtk; + struct ddsi_tkmap_instance * tk = vtk; tkmap_get_inst_arg * arg = (tkmap_get_inst_arg*) varg; if (tk->m_iid == arg->m_iid) { @@ -164,7 +164,7 @@ static void dds_tkmap_get_inst_fn (void * vtk, void * varg) } _Check_return_ -struct tkmap_instance * dds_tkmap_find_by_id (_In_ struct tkmap * map, _In_ uint64_t iid) +struct ddsi_tkmap_instance * ddsi_tkmap_find_by_id (_In_ struct ddsi_tkmap * map, _In_ uint64_t iid) { tkmap_get_inst_arg arg = { iid, NULL }; ut_chhEnumUnsafe (map->m_hh, dds_tkmap_get_inst_fn, &arg); @@ -184,14 +184,14 @@ struct tkmap_instance * dds_tkmap_find_by_id (_In_ struct tkmap * map, _In_ uint #endif _Check_return_ -struct tkmap_instance * dds_tkmap_find( +struct ddsi_tkmap_instance * ddsi_tkmap_find( _In_ struct ddsi_serdata * sd, _In_ const bool rd, _In_ const bool create) { - struct tkmap_instance dummy; - struct tkmap_instance * tk; - struct tkmap * map = gv.m_tkmap; + struct ddsi_tkmap_instance dummy; + struct ddsi_tkmap_instance * tk; + struct ddsi_tkmap * map = gv.m_tkmap; dummy.m_sample = sd; retry: @@ -222,7 +222,7 @@ retry: tk->m_sample = ddsi_serdata_to_topicless (sd); tk->m_map = map; os_atomic_st32 (&tk->m_refc, 1); - tk->m_iid = dds_iid_gen (); + tk->m_iid = ddsi_iid_gen (); if (!ut_chhAdd (map->m_hh, tk)) { /* Lost a race from another thread, retry */ @@ -240,18 +240,18 @@ retry: } _Check_return_ -struct tkmap_instance * dds_tkmap_lookup_instance_ref (_In_ struct ddsi_serdata * sd) +struct ddsi_tkmap_instance * ddsi_tkmap_lookup_instance_ref (_In_ struct ddsi_serdata * sd) { assert (vtime_awake_p (lookup_thread_state ()->vtime)); - return dds_tkmap_find (sd, true, true); + return ddsi_tkmap_find (sd, true, true); } -void dds_tkmap_instance_ref (_In_ struct tkmap_instance *tk) +void ddsi_tkmap_instance_ref (_In_ struct ddsi_tkmap_instance *tk) { os_atomic_inc32 (&tk->m_refc); } -void dds_tkmap_instance_unref (_In_ struct tkmap_instance * tk) +void ddsi_tkmap_instance_unref (_In_ struct ddsi_tkmap_instance * tk) { uint32_t old, new; assert (vtime_awake_p(lookup_thread_state()->vtime)); @@ -267,7 +267,7 @@ void dds_tkmap_instance_unref (_In_ struct tkmap_instance * tk) } while (!os_atomic_cas32(&tk->m_refc, old, new)); if (new == REFC_DELETE) { - struct tkmap *map = tk->m_map; + struct ddsi_tkmap *map = tk->m_map; /* Remove from hash table */ int removed = ut_chhRemove(map->m_hh, tk); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index ae487e1..dfea79d 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -42,6 +42,8 @@ #include "ddsi/sysdeps.h" #include "dds__whc.h" +#include "ddsi/ddsi_iid.h" +#include "ddsi/ddsi_tkmap.h" struct deleted_participant { ut_avlNode_t avlnode; @@ -158,7 +160,7 @@ static void entity_common_init (struct entity_common *e, const struct nn_guid *g e->guid = *guid; e->kind = kind; e->name = os_strdup (name ? name : ""); - e->iid = (ddsi_plugin.iidgen_fn) (); + e->iid = ddsi_iid_gen (); os_mutexInit (&e->lock); e->onlylocal = onlylocal; } @@ -1613,7 +1615,7 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd) struct proxy_writer_info pwr_info; struct ddsi_serdata *payload = sample.serdata; /* FIXME: whc has tk reference in its index nodes, which is what we really should be iterating over anyway, and so we don't really have to look them up anymore */ - struct tkmap_instance *tk = (ddsi_plugin.rhc_plugin.rhc_lookup_fn) (payload); + struct ddsi_tkmap_instance *tk = ddsi_tkmap_lookup_instance_ref(payload); make_proxy_writer_info(&pwr_info, &wr->e, wr->xqos); (void)(ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk); } diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 037d794..58464ef 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -57,8 +57,9 @@ #include "ddsi/ddsi_mcgroup.h" #include "ddsi/ddsi_serdata_default.h" -#include "dds__tkmap.h" +#include "ddsi/ddsi_tkmap.h" #include "dds__whc.h" +#include "ddsi/ddsi_iid.h" static void add_peer_addresses (struct addrset *as, const struct config_peer_listelem *list) { @@ -772,7 +773,7 @@ static struct ddsi_sertopic *make_special_topic (uint16_t enc_id, const struct d st->c.ops = &ddsi_sertopic_ops_default; st->c.serdata_ops = ops; st->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (st->c.serdata_ops); - st->c.iid = ddsi_plugin.iidgen_fn(); + st->c.iid = ddsi_iid_gen (); st->native_encoding_identifier = enc_id; st->nkeys = 1; return (struct ddsi_sertopic *)st; @@ -880,6 +881,7 @@ int rtps_init (void) /* Initialize implementation (Lite or OSPL) */ ddsi_plugin_init (); + ddsi_iid_init (); gv.tstart = now (); /* wall clock time, used in logs */ @@ -1060,7 +1062,7 @@ int rtps_init (void) gv.spdp_defrag = nn_defrag_new (NN_DEFRAG_DROP_OLDEST, config.defrag_unreliable_maxsamples); gv.spdp_reorder = nn_reorder_new (NN_REORDER_MODE_ALWAYS_DELIVER, config.primary_reorder_maxsamples); - gv.m_tkmap = dds_tkmap_new (); + gv.m_tkmap = ddsi_tkmap_new (); if (gv.m_factory->m_connless) { @@ -1339,7 +1341,7 @@ err_mc_conn: ddsi_conn_free (gv.data_conn_uc); free_group_membership(gv.mship); err_unicast_sockets: - dds_tkmap_free (gv.m_tkmap); + ddsi_tkmap_free (gv.m_tkmap); nn_reorder_free (gv.spdp_reorder); nn_defrag_free (gv.spdp_defrag); os_mutexDestroy (&gv.spdp_lock); @@ -1368,6 +1370,7 @@ err_unicast_sockets: nn_plist_fini (&gv.default_plist_pp); ddsi_serdatapool_free (gv.serpool); nn_xmsgpool_free (gv.xmsgpool); + ddsi_iid_fini (); (ddsi_plugin.fini_fn) (); #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS err_network_partition_addrset: @@ -1621,7 +1624,7 @@ void rtps_term (void) } } - dds_tkmap_free (gv.m_tkmap); + ddsi_tkmap_free (gv.m_tkmap); ephash_free (gv.guid_hash); gv.guid_hash = NULL; @@ -1663,6 +1666,7 @@ OS_WARNING_MSVC_ON(6001); ddsi_serdatapool_free (gv.serpool); nn_xmsgpool_free (gv.xmsgpool); + ddsi_iid_fini (); (ddsi_plugin.fini_fn) (); DDS_LOG(DDS_LC_CONFIG, "Finis.\n"); } diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 3a8e0a7..10f8310 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -46,6 +46,7 @@ #include "ddsi/q_globals.h" #include "ddsi/q_static_assert.h" #include "ddsi/q_init.h" +#include "ddsi/ddsi_tkmap.h" #include "ddsi/ddsi_mcgroup.h" #include "ddsi/ddsi_serdata.h" #include "ddsi/ddsi_serdata_default.h" /* FIXME: get rid of this */ @@ -1995,8 +1996,8 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st the PRISMTECH_WRITER_INFO thing is completely meaningless to us */ { - struct tkmap_instance * tk; - tk = (ddsi_plugin.rhc_plugin.rhc_lookup_fn) (payload); + struct ddsi_tkmap_instance * tk; + tk = ddsi_tkmap_lookup_instance_ref(payload); if (tk) { struct proxy_writer_info pwr_info; @@ -2075,7 +2076,7 @@ retry: if (pwr_locked) os_mutexLock (&pwr->e.lock); } } - (ddsi_plugin.rhc_plugin.rhc_unref_fn) (tk); + ddsi_tkmap_instance_unref (tk); } } ddsi_serdata_unref (payload); diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 4c0a412..6c314da 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -31,7 +31,7 @@ #include "ddsi/q_unused.h" #include "ddsi/q_hbcontrol.h" #include "ddsi/q_static_assert.h" - +#include "ddsi/ddsi_tkmap.h" #include "ddsi/ddsi_serdata.h" #include "ddsi/ddsi_sertopic.h" @@ -851,7 +851,7 @@ int enqueue_sample_wrlock_held (struct writer *wr, seqno_t seq, const struct nn_ return enqueued ? 0 : -1; } -static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist *plist, struct ddsi_serdata *serdata, struct tkmap_instance *tk) +static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) { /* returns: < 0 on error, 0 if no need to insert in whc, > 0 if inserted */ int do_insert, insres, res; @@ -1027,7 +1027,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 tkmap_instance *tk, int end_of_txn, int gc_allowed) +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) { int r; seqno_t seq; @@ -1163,33 +1163,33 @@ drop: return r; } -int write_sample_gc (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct tkmap_instance *tk) +int write_sample_gc (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); } -int write_sample_nogc (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct tkmap_instance *tk) +int write_sample_nogc (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); } int write_sample_gc_notk (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata) { - struct tkmap_instance *tk; + struct ddsi_tkmap_instance *tk; int res; - tk = (ddsi_plugin.rhc_plugin.rhc_lookup_fn) (serdata); + tk = ddsi_tkmap_lookup_instance_ref (serdata); res = write_sample_eot (xp, wr, NULL, serdata, tk, 0, 1); - (ddsi_plugin.rhc_plugin.rhc_unref_fn) (tk); + ddsi_tkmap_instance_unref (tk); return res; } int write_sample_nogc_notk (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata) { - struct tkmap_instance *tk; + struct ddsi_tkmap_instance *tk; int res; - tk = (ddsi_plugin.rhc_plugin.rhc_lookup_fn) (serdata); + tk = ddsi_tkmap_lookup_instance_ref (serdata); res = write_sample_eot (xp, wr, NULL, serdata, tk, 0, 0); - (ddsi_plugin.rhc_plugin.rhc_unref_fn) (tk); + ddsi_tkmap_instance_unref (tk); return res; } diff --git a/src/core/ddsi/src/q_whc.c b/src/core/ddsi/src/q_whc.c index dd7e95c..3be0df2 100644 --- a/src/core/ddsi/src/q_whc.c +++ b/src/core/ddsi/src/q_whc.c @@ -22,7 +22,7 @@ extern inline void whc_return_sample (struct whc *whc, struct whc_borrowed_sampl extern inline void whc_sample_iter_init (const struct whc *whc, struct whc_sample_iter *it); extern inline bool whc_sample_iter_borrow_next (struct whc_sample_iter *it, struct whc_borrowed_sample *sample); extern inline void whc_free (struct whc *whc); -extern int whc_insert (struct whc *whc, seqno_t max_drop_seq, seqno_t seq, struct nn_plist *plist, struct ddsi_serdata *serdata, struct tkmap_instance *tk); +extern int whc_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); extern unsigned whc_downgrade_to_volatile (struct whc *whc, struct whc_state *st); extern unsigned whc_remove_acked_messages (struct whc *whc, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list); extern void whc_free_deferred_free_list (struct whc *whc, struct whc_node *deferred_free_list); diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index fb545ac..7f9ee9a 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -38,6 +38,7 @@ #include "ddsi/q_xmsg.h" #include "ddsi/ddsi_serdata.h" #include "ddsi/ddsi_serdata_default.h" +#include "ddsi/ddsi_tkmap.h" #include "dds__whc.h" #include "ddsi/sysdeps.h" @@ -1128,7 +1129,7 @@ static void write_pmd_message (struct nn_xpack *xp, struct participant *pp, unsi char pad[offsetof (ParticipantMessageData_t, value) + PMD_DATA_LENGTH]; } u; struct ddsi_serdata *serdata; - struct tkmap_instance *tk; + struct ddsi_tkmap_instance *tk; if ((wr = get_builtin_writer (pp, NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER)) == NULL) { @@ -1150,9 +1151,9 @@ static void write_pmd_message (struct nn_xpack *xp, struct participant *pp, unsi serdata = ddsi_serdata_from_sample (gv.rawcdr_topic, SDK_DATA, &raw); serdata->timestamp = now (); - tk = (ddsi_plugin.rhc_plugin.rhc_lookup_fn) (serdata); + tk = ddsi_tkmap_lookup_instance_ref(serdata); write_sample_nogc (xp, wr, serdata, tk); - (ddsi_plugin.rhc_plugin.rhc_unref_fn) (tk); + ddsi_tkmap_instance_unref(tk); #undef PMD_DATA_LENGTH } From ef65101ad7924679d3a30e2b441686be7ded0a8b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 9 Nov 2018 15:29:40 +0100 Subject: [PATCH 2/7] pushing released serdata:s onto a freelist was dropped by accident in the rewriting of them Signed-off-by: Erik Boasson --- src/core/ddsi/src/ddsi_serdata_default.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 52552e7..1373474 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -53,9 +53,9 @@ static void serdata_free_wrap (void *elem) { #ifndef NDEBUG struct ddsi_serdata_default *d = elem; - assert(os_atomic_ld32(&d->c.refc) == 1); + assert(os_atomic_ld32(&d->c.refc) == 0); #endif - ddsi_serdata_unref(elem); + dds_free(elem); } void ddsi_serdatapool_free (struct serdatapool * pool) @@ -200,7 +200,9 @@ static bool serdata_default_eqkey_nokey (const struct ddsi_serdata *acmn, const static void serdata_default_free(struct ddsi_serdata *dcmn) { struct ddsi_serdata_default *d = (struct ddsi_serdata_default *)dcmn; - dds_free (d); + assert(os_atomic_ld32(&d->c.refc) == 0); + if (!nn_freelist_push (&gv.serpool->freelist, d)) + dds_free (d); } static void serdata_default_init(struct ddsi_serdata_default *d, const struct ddsi_sertopic_default *tp, enum ddsi_serdata_kind kind) @@ -231,6 +233,8 @@ static struct ddsi_serdata_default *serdata_default_new(const struct ddsi_sertop struct ddsi_serdata_default *d; if ((d = nn_freelist_pop (&gv.serpool->freelist)) == NULL) d = serdata_default_allocnew(gv.serpool); + else + os_atomic_st32(&d->c.refc, 1); serdata_default_init(d, tp, kind); return d; } From c169df62274d4913c5f9d775e72514abfbd418bc Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 9 Nov 2018 15:30:27 +0100 Subject: [PATCH 3/7] fix refcount leak of tkmap instances when copying transient-local history from a local writer Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_entity.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index dfea79d..83d2277 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -1618,6 +1618,7 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd) struct ddsi_tkmap_instance *tk = ddsi_tkmap_lookup_instance_ref(payload); make_proxy_writer_info(&pwr_info, &wr->e, wr->xqos); (void)(ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk); + ddsi_tkmap_instance_unref(tk); } } From e631567c354f1860f60afb4da4beaef3c6879402 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 3 Dec 2018 17:29:32 +0100 Subject: [PATCH 4/7] extend sertopic interface and move the concept of a type descriptor to just the sertopic definition Signed-off-by: Erik Boasson --- src/core/ddsc/include/ddsc/dds.h | 35 ++- src/core/ddsc/src/dds__types.h | 3 +- src/core/ddsc/src/dds_instance.c | 12 +- src/core/ddsc/src/dds_read.c | 42 ++-- src/core/ddsc/src/dds_rhc.c | 10 +- src/core/ddsc/src/dds_topic.c | 199 +++++++++++------- .../ddsi/include/ddsi/ddsi_serdata_default.h | 4 +- src/core/ddsi/include/ddsi/ddsi_sertopic.h | 32 ++- src/core/ddsi/src/ddsi_sertopic.c | 5 + src/core/ddsi/src/ddsi_sertopic_default.c | 49 ++++- src/core/ddsi/src/q_init.c | 2 +- 11 files changed, 269 insertions(+), 124 deletions(-) diff --git a/src/core/ddsc/include/ddsc/dds.h b/src/core/ddsc/include/ddsc/dds.h index 1044c4a..77f69ec 100644 --- a/src/core/ddsc/include/ddsc/dds.h +++ b/src/core/ddsc/include/ddsc/dds.h @@ -947,7 +947,7 @@ dds_lookup_participant( _In_ size_t size); /** - * @brief Creates a new topic. + * @brief Creates a new topic with default type handling. * * The type name for the topic is taken from the generated descriptor. Topic * matching is done on a combination of topic name and type name. @@ -975,6 +975,39 @@ dds_create_topic( _In_opt_ const dds_qos_t *qos, _In_opt_ const dds_listener_t *listener); +/** + * @brief Creates a new topic with arbitrary type handling. + * + * The type name for the topic is taken from the provided "sertopic" object. Topic + * matching is done on a combination of topic name and type name. + * + * @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] 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). + * + * @returns A valid topic handle or an error code. + * + * @retval >=0 + * A valid topic handle. + * @retval DDS_RETCODE_BAD_PARAMETER + * Either participant, descriptor, name or qos is invalid. + */ +/* TODO: Check list of retcodes is complete. */ +struct ddsi_sertopic; +struct nn_plist; +_Pre_satisfies_((participant & DDS_ENTITY_KIND_MASK) == DDS_KIND_PARTICIPANT) +DDS_EXPORT dds_entity_t +dds_create_topic_arbitrary ( + _In_ dds_entity_t participant, + _In_ struct ddsi_sertopic *sertopic, + _In_z_ const char *name, + _In_opt_ const dds_qos_t *qos, + _In_opt_ const dds_listener_t *listener, + _In_opt_ const struct nn_plist *sedp_plist); + /** * @brief Finds a named topic. * diff --git a/src/core/ddsc/src/dds__types.h b/src/core/ddsc/src/dds__types.h index 158d14e..ab6edb0 100644 --- a/src/core/ddsc/src/dds__types.h +++ b/src/core/ddsc/src/dds__types.h @@ -169,7 +169,7 @@ typedef struct dds_reader struct reader * m_rd; bool m_data_on_readers; bool m_loan_out; - char * m_loan; + void * m_loan; uint32_t m_loan_size; /* Status metrics */ @@ -209,7 +209,6 @@ typedef struct dds_topic { struct dds_entity m_entity; struct ddsi_sertopic * m_stopic; - const dds_topic_descriptor_t * m_descriptor; dds_topic_intern_filter_fn filter_fn; void * filter_ctx; diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index bfb3252..1fbaa0c 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -262,15 +262,14 @@ dds_unregister_instance_ih_ts( map = gv.m_tkmap; topic = dds_instance_info((dds_entity*)wr); - sample = dds_alloc (topic->m_descriptor->m_size); + sample = ddsi_sertopic_alloc_sample (topic->m_stopic); if (ddsi_tkmap_get_key (map, topic->m_stopic, handle, sample)) { ret = dds_write_impl ((dds_writer*)wr, sample, timestamp, action); } else{ DDS_ERROR("No instance related with the provided handle is found\n"); ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); } - dds_sample_free (sample, topic->m_descriptor, DDS_FREE_ALL); - + ddsi_sertopic_free_sample (topic->m_stopic, sample, DDS_FREE_ALL); dds_entity_unlock(wr); err: return ret; @@ -356,14 +355,14 @@ dds_dispose_ih_ts( if (rc == DDS_RETCODE_OK) { struct ddsi_tkmap *map = gv.m_tkmap; const dds_topic *topic = dds_instance_info((dds_entity*)wr); - void *sample = dds_alloc (topic->m_descriptor->m_size); + void *sample = ddsi_sertopic_alloc_sample (topic->m_stopic); if (ddsi_tkmap_get_key (map, topic->m_stopic, handle, sample)) { ret = dds_dispose_impl(wr, sample, handle, timestamp); } else { DDS_ERROR("No instance related with the provided handle is found\n"); ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); } - dds_free(sample); + ddsi_sertopic_free_sample (topic->m_stopic, sample, DDS_FREE_ALL); dds_writer_unlock(wr); } else { DDS_ERROR("Error occurred on locking writer\n"); @@ -424,8 +423,7 @@ dds_instance_get_key( ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } - memset (data, 0, topic->m_descriptor->m_size); - + ddsi_sertopic_zero_sample (topic->m_stopic, data); if (ddsi_tkmap_get_key (map, topic->m_stopic, inst, data)) { ret = DDS_RETCODE_OK; } else{ diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 3e459e1..ef7f16f 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -19,6 +19,7 @@ #include "ddsi/q_thread.h" #include "ddsi/q_ephash.h" #include "ddsi/q_entity.h" +#include "ddsi/ddsi_sertopic.h" static _Check_return_ dds__retcode_t @@ -93,7 +94,6 @@ dds_read_impl( _In_ bool lock, _In_ bool only_reader) { - uint32_t i; dds_return_t ret = DDS_RETCODE_OK; dds__retcode_t rc; struct dds_reader * rd; @@ -146,28 +146,24 @@ dds_read_impl( } /* Allocate samples if not provided (assuming all or none provided) */ if (buf[0] == NULL) { - char * loan; - const size_t sz = rd->m_topic->m_descriptor->m_size; - const uint32_t loan_size = (uint32_t) (sz * maxs); /* Allocate, use or reallocate loan cached on reader */ if (rd->m_loan_out) { - loan = dds_alloc (loan_size); + ddsi_sertopic_realloc_samples (buf, rd->m_topic->m_stopic, NULL, 0, maxs); } else { if (rd->m_loan) { - if (rd->m_loan_size < loan_size) { - rd->m_loan = dds_realloc_zero (rd->m_loan, loan_size); - rd->m_loan_size = loan_size; + 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; + } else { + buf[0] = rd->m_loan; } } else { - rd->m_loan = dds_alloc (loan_size); - rd->m_loan_size = loan_size; + ddsi_sertopic_realloc_samples (buf, rd->m_topic->m_stopic, NULL, 0, maxs); + rd->m_loan = buf[0]; + rd->m_loan_size = maxs; } - loan = rd->m_loan; - rd->m_loan_out = true; - } - for (i = 0; i < maxs; i++) { - buf[i] = loan; - loan += sz; + rd->m_loan_out = true; } } if (take) { @@ -759,7 +755,7 @@ dds_return_loan( _In_ int32_t bufsz) { dds__retcode_t rc; - const dds_topic_descriptor_t * desc; + const struct ddsi_sertopic *st; dds_reader *rd; dds_readcond *cond; dds_return_t ret = DDS_RETCODE_OK; @@ -781,20 +777,16 @@ dds_return_loan( ret = DDS_ERRNO(rc); goto fail; } - desc = rd->m_topic->m_descriptor; + st = rd->m_topic->m_stopic; - /* Only free sample contents if they have been allocated */ - if (desc->m_flagset & DDS_TOPIC_NO_OPTIMIZE) { - int32_t i = 0; - for (i = 0; i < bufsz; i++) { - dds_sample_free(buf[i], desc, DDS_FREE_CONTENTS); - } + 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; - memset (rd->m_loan, 0, rd->m_loan_size); + ddsi_sertopic_zero_samples (st, rd->m_loan, rd->m_loan_size); buf[0] = NULL; } diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index e54a7b2..f30b5e4 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -668,8 +668,7 @@ static bool content_filter_accepts (const struct ddsi_sertopic *sertopic, const const struct dds_topic *tp = sertopic->status_cb_entity; if (tp->filter_fn) { - const dds_topic_descriptor_t * desc = tp->m_descriptor; - char *tmp = dds_alloc (desc->m_size); + 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); @@ -2168,7 +2167,6 @@ static bool update_conditions_locked dds_readcond * iter; int m_pre; int m_post; - const struct dds_topic_descriptor *desc = rhc->topic->status_cb_entity->m_descriptor; char *tmp = NULL; DDS_TRACE("update_conditions_locked(%p) - inst %u nonempty %u disp %u nowr %u new %u samples %u read %u\n", @@ -2214,8 +2212,7 @@ static bool update_conditions_locked { if (sample && tmp == NULL && (dds_entity_kind(iter->m_entity.m_hdl) == DDS_KIND_COND_QUERY)) { - tmp = os_malloc (desc->m_size); - memset (tmp, 0, desc->m_size); + tmp = ddsi_sertopic_alloc_sample (rhc->topic); ddsi_serdata_to_sample (sample, tmp, NULL, NULL); } if @@ -2251,8 +2248,7 @@ static bool update_conditions_locked if (tmp) { - ddsi_sertopic_free_sample (rhc->topic, tmp, DDS_FREE_CONTENTS); - os_free (tmp); + ddsi_sertopic_free_sample (rhc->topic, tmp, DDS_FREE_ALL); } return trigger; } diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index dc63198..0d85690 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -322,31 +322,42 @@ 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) +{ + printf ("sertopic_equivalent %p %p (%s %s; %u %u; %p %p; %p %p)\n", a, b, a->name_typename, b->name_typename, a->serdata_basehash, b->serdata_basehash, a->ops, b->ops, a->serdata_ops, b->serdata_ops); + + if (strcmp (a->name_typename, b->name_typename) != 0) + return false; + if (a->serdata_basehash != b->serdata_basehash) + return false; + if (a->ops != b->ops) + return false; + if (a->serdata_ops != b->serdata_ops) + return false; + return true; +} + _Pre_satisfies_((participant & DDS_ENTITY_KIND_MASK) == DDS_KIND_PARTICIPANT) DDS_EXPORT dds_entity_t -dds_create_topic( +dds_create_topic_arbitrary ( _In_ dds_entity_t participant, - _In_ const dds_topic_descriptor_t *desc, + _In_ struct ddsi_sertopic *sertopic, _In_z_ const char *name, _In_opt_ const dds_qos_t *qos, - _In_opt_ const dds_listener_t *listener) + _In_opt_ const dds_listener_t *listener, + _In_opt_ const nn_plist_t *sedp_plist) { - char *key = NULL; struct ddsi_sertopic *stgeneric; - struct ddsi_sertopic_default *st; - const char *typename; dds__retcode_t rc; dds_entity *par; dds_topic *top; dds_qos_t *new_qos = NULL; - nn_plist_t plist; dds_entity_t hdl; struct participant *ddsi_pp; struct thread_state1 *const thr = lookup_thread_state (); const bool asleep = !vtime_awake_p (thr->vtime); - uint32_t index; - if (desc == NULL){ + if (sertopic == NULL){ DDS_ERROR("Topic description is NULL\n"); hdl = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto bad_param_err; @@ -384,8 +395,7 @@ dds_create_topic( /* Check if topic already exists with same name */ os_mutexLock (&dds_global.m_mutex); if ((stgeneric = dds_topic_lookup_locked (par->m_domain, name)) != NULL) { - st = (struct ddsi_sertopic_default *)stgeneric; - if (st->type != desc) { + 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); @@ -394,17 +404,11 @@ dds_create_topic( DDS_ERROR("Create topic with mismatching qos\n"); hdl = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); } else { - dds_entity_add_ref (&st->c.status_cb_entity->m_entity); - hdl = st->c.status_cb_entity->m_entity.m_hdl; + dds_entity_add_ref (&stgeneric->status_cb_entity->m_entity); + hdl = stgeneric->status_cb_entity->m_entity.m_hdl; } os_mutexUnlock (&dds_global.m_mutex); } else { - typename = desc->m_typename; - key = (char*) dds_alloc (strlen (name) + strlen (typename) + 2); - strcpy (key, name); - strcat (key, "/"); - strcat (key, typename); - if (qos) { new_qos = dds_create_qos(); /* Only returns failure when one of the qos args is NULL, which @@ -414,77 +418,29 @@ dds_create_topic( /* Create topic */ top = dds_alloc (sizeof (*top)); - top->m_descriptor = desc; 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; - - st = dds_alloc (sizeof (*st)); - - os_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 = top; - st->c.name_typename = key; - st->c.name = dds_alloc (strlen (name) + 1); - strcpy (st->c.name, name); - st->c.typename = dds_alloc (strlen (typename) + 1); - strcpy (st->c.typename, 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 = (PLATFORM_IS_LITTLE_ENDIAN ? CDR_LE : CDR_BE); - - st->type = (void*) desc; - st->nkeys = desc->m_nkeys; - st->keys = desc->m_keys; - - /* 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); - } - top->m_stopic = &st->c; + top->m_stopic = ddsi_sertopic_ref (sertopic); + sertopic->status_cb_entity = top; /* Add topic to extent */ - dds_topic_add_locked (par->m_domainid, &st->c); + dds_topic_add_locked (par->m_domainid, sertopic); os_mutexUnlock (&dds_global.m_mutex); - 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.typename); - 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); - } - } - /* Publish Topic */ if (asleep) { thread_state_awake (thr); } ddsi_pp = ephash_lookup_participant_guid (&par->m_guid); assert (ddsi_pp); - sedp_write_topic (ddsi_pp, &plist); + if (sedp_plist) { + sedp_write_topic (ddsi_pp, sedp_plist); + } if (asleep) { thread_state_asleep (thr); } - nn_plist_fini (&plist); } qos_err: @@ -494,6 +450,103 @@ bad_param_err: return hdl; } +_Pre_satisfies_((participant & DDS_ENTITY_KIND_MASK) == DDS_KIND_PARTICIPANT) +DDS_EXPORT dds_entity_t +dds_create_topic( + _In_ dds_entity_t participant, + _In_ const dds_topic_descriptor_t *desc, + _In_z_ const char *name, + _In_opt_ const dds_qos_t *qos, + _In_opt_ 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; + + if (desc == NULL){ + DDS_ERROR("Topic description is NULL"); + hdl = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + goto bad_param_err; + } + + if (name == NULL) { + DDS_ERROR("Topic name is NULL"); + 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."); + hdl = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); + goto bad_param_err; + } + + typename = desc->m_typename; + key = (char*) dds_alloc (strlen (name) + strlen (typename) + 2); + strcpy (key, name); + strcat (key, "/"); + strcat (key, typename); + + st = dds_alloc (sizeof (*st)); + + os_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_typename = key; + st->c.name = dds_alloc (strlen (name) + 1); + strcpy (st->c.name, name); + st->c.typename = dds_alloc (strlen (typename) + 1); + strcpy (st->c.typename, 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 = (PLATFORM_IS_LITTLE_ENDIAN ? CDR_LE : CDR_BE); + + st->type = (void*) desc; + st->nkeys = desc->m_nkeys; + st->keys = desc->m_keys; + + /* 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); + } + + 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.typename); + 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, name, qos, listener, &plist); + ddsi_sertopic_unref (&st->c); + nn_plist_fini (&plist); + +bad_param_err: + return hdl; +} + static bool dds_topic_chaining_filter( const void *sample, diff --git a/src/core/ddsi/include/ddsi/ddsi_serdata_default.h b/src/core/ddsi/include/ddsi/ddsi_serdata_default.h index 5614ff1..b9328fb 100644 --- a/src/core/ddsi/include/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/ddsi/ddsi_serdata_default.h @@ -9,8 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef DDSI_SER_H -#define DDSI_SER_H +#ifndef DDSI_SERDATA_DEFAULT_H +#define DDSI_SERDATA_DEFAULT_H #include "os/os.h" #include "ddsi/q_plist.h" /* for nn_prismtech_writer_info */ diff --git a/src/core/ddsi/include/ddsi/ddsi_sertopic.h b/src/core/ddsi/include/ddsi/ddsi_sertopic.h index fe1d68f..d400245 100644 --- a/src/core/ddsi/include/ddsi/ddsi_sertopic.h +++ b/src/core/ddsi/include/ddsi/ddsi_sertopic.h @@ -41,11 +41,19 @@ struct ddsi_sertopic { typedef void (*ddsi_sertopic_deinit_t) (struct ddsi_sertopic *tp); /* Release any memory allocated by ddsi_sertopic_to_sample */ -typedef void (*ddsi_sertopic_free_sample_t) (const struct ddsi_sertopic *d, void *sample, dds_free_op_t op); +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 */ +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) */ +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_sample_t free_sample; + ddsi_sertopic_zero_samples_t zero_samples; + ddsi_sertopic_realloc_samples_t realloc_samples; + ddsi_sertopic_free_samples_t free_samples; }; struct ddsi_sertopic *ddsi_sertopic_ref (const struct ddsi_sertopic *tp); @@ -55,8 +63,26 @@ uint32_t ddsi_sertopic_compute_serdata_basehash (const struct ddsi_serdata_ops * inline void ddsi_sertopic_deinit (struct ddsi_sertopic *tp) { tp->ops->deinit (tp); } +inline void ddsi_sertopic_zero_samples (const struct ddsi_sertopic *tp, void *samples, size_t count) { + tp->ops->zero_samples (tp, samples, count); +} +inline void ddsi_sertopic_realloc_samples (void **ptrs, const struct ddsi_sertopic *tp, void *old, size_t oldcount, size_t count) +{ + tp->ops->realloc_samples (ptrs, tp, old, oldcount, count); +} +inline void ddsi_sertopic_free_samples (const struct ddsi_sertopic *tp, void **ptrs, size_t count, dds_free_op_t op) { + tp->ops->free_samples (tp, ptrs, count, op); +} +inline void ddsi_sertopic_zero_sample (const struct ddsi_sertopic *tp, void *sample) { + ddsi_sertopic_zero_samples (tp, sample, 1); +} +inline void *ddsi_sertopic_alloc_sample (const struct ddsi_sertopic *tp) { + void *ptr; + ddsi_sertopic_realloc_samples (&ptr, tp, NULL, 0, 1); + return ptr; +} inline void ddsi_sertopic_free_sample (const struct ddsi_sertopic *tp, void *sample, dds_free_op_t op) { - tp->ops->free_sample (tp, sample, op); + ddsi_sertopic_free_samples (tp, &sample, 1, op); } #endif diff --git a/src/core/ddsi/src/ddsi_sertopic.c b/src/core/ddsi/src/ddsi_sertopic.c index 3a5687b..c4d71db 100644 --- a/src/core/ddsi/src/ddsi_sertopic.c +++ b/src/core/ddsi/src/ddsi_sertopic.c @@ -61,4 +61,9 @@ uint32_t ddsi_sertopic_compute_serdata_basehash (const struct ddsi_serdata_ops * } extern inline void ddsi_sertopic_deinit (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); +extern inline void ddsi_sertopic_zero_sample (const struct ddsi_sertopic *tp, void *sample); extern inline void ddsi_sertopic_free_sample (const struct ddsi_sertopic *tp, void *sample, dds_free_op_t op); +extern inline void *ddsi_sertopic_alloc_sample (const struct ddsi_sertopic *tp); diff --git a/src/core/ddsi/src/ddsi_sertopic_default.c b/src/core/ddsi/src/ddsi_sertopic_default.c index e906d26..8afddb0 100644 --- a/src/core/ddsi/src/ddsi_sertopic_default.c +++ b/src/core/ddsi/src/ddsi_sertopic_default.c @@ -30,13 +30,56 @@ static void sertopic_default_deinit (struct ddsi_sertopic *tp) (void)tp; } -static void sertopic_default_free_sample (const struct ddsi_sertopic *sertopic_common, void *sample, dds_free_op_t op) +static void sertopic_default_zero_samples (const struct ddsi_sertopic *sertopic_common, void *sample, size_t count) { const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)sertopic_common; - dds_sample_free (sample, tp->type, op); + memset (sample, 0, tp->type->m_size * count); +} + +static void sertopic_default_realloc_samples (void **ptrs, const struct ddsi_sertopic *sertopic_common, void *old, size_t oldcount, size_t count) +{ + const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)sertopic_common; + const size_t size = tp->type->m_size; + char *new = dds_realloc (old, size * count); + if (new && count > oldcount) + memset (new + size * oldcount, 0, size * (count - oldcount)); + for (size_t i = 0; i < count; i++) + { + void *ptr = (char *) new + i * size; + ptrs[i] = ptr; + } +} + +static void sertopic_default_free_samples (const struct ddsi_sertopic *sertopic_common, void **ptrs, size_t count, dds_free_op_t op) +{ + if (count > 0) + { + const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)sertopic_common; + const struct dds_topic_descriptor *type = tp->type; + const size_t size = type->m_size; +#ifndef NDEBUG + for (size_t i = 0, off = 0; i < count; i++, off += size) + assert ((char *)ptrs[i] == (char *)ptrs[0] + off); +#endif + if (type->m_flagset & DDS_TOPIC_NO_OPTIMIZE) + { + char *ptr = ptrs[0]; + for (size_t i = 0; i < count; i++) + { + dds_sample_free (ptr, type, DDS_FREE_CONTENTS); + ptr += size; + } + } + if (op & DDS_FREE_ALL_BIT) + { + dds_free (ptrs[0]); + } + } } const struct ddsi_sertopic_ops ddsi_sertopic_ops_default = { .deinit = sertopic_default_deinit, - .free_sample = sertopic_default_free_sample + .zero_samples = sertopic_default_zero_samples, + .realloc_samples = sertopic_default_realloc_samples, + .free_samples = sertopic_default_free_samples }; diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 58464ef..8239391 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -1040,7 +1040,7 @@ int rtps_init (void) 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); - make_special_topics (); /* FIXME: leaking these for now */ + make_special_topics (); os_mutexInit (&gv.participant_set_lock); os_condInit (&gv.participant_set_cond, &gv.participant_set_lock); From 945fc94de7f0993435550e7dbf1984b4d0f51cd5 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 3 Dec 2018 17:33:59 +0100 Subject: [PATCH 5/7] setting "must inspect result" on return_loan is pedantry Signed-off-by: Erik Boasson --- src/core/ddsc/include/ddsc/dds.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsc/include/ddsc/dds.h b/src/core/ddsc/include/ddsc/dds.h index 77f69ec..32e7e59 100644 --- a/src/core/ddsc/include/ddsc/dds.h +++ b/src/core/ddsc/include/ddsc/dds.h @@ -3070,7 +3070,7 @@ dds_read_next_wl( _Pre_satisfies_(((reader_or_condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\ ((reader_or_condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \ ((reader_or_condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY )) -DDS_EXPORT _Must_inspect_result_ dds_return_t +DDS_EXPORT dds_return_t dds_return_loan( _In_ dds_entity_t reader_or_condition, _Inout_updates_(bufsz) void **buf, From 78d49b52a0d7b390540888b0aa67e55a7552e161 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 3 Dec 2018 17:37:16 +0100 Subject: [PATCH 6/7] add new "builtin topic" types and conversion routines Signed-off-by: Erik Boasson --- src/core/ddsc/include/ddsc/dds.h | 23 ++ src/core/ddsi/CMakeLists.txt | 3 + .../ddsi/include/ddsi/ddsi_serdata_builtin.h | 44 +++ src/core/ddsi/include/ddsi/q_ephash.h | 1 + src/core/ddsi/src/ddsi_serdata_builtin.c | 287 ++++++++++++++++++ src/core/ddsi/src/ddsi_sertopic_builtin.c | 147 +++++++++ src/core/ddsi/src/q_ephash.c | 14 +- 7 files changed, 514 insertions(+), 5 deletions(-) create mode 100644 src/core/ddsi/include/ddsi/ddsi_serdata_builtin.h create mode 100644 src/core/ddsi/src/ddsi_serdata_builtin.c create mode 100644 src/core/ddsi/src/ddsi_sertopic_builtin.c diff --git a/src/core/ddsc/include/ddsc/dds.h b/src/core/ddsc/include/ddsc/dds.h index 32e7e59..d407d95 100644 --- a/src/core/ddsc/include/ddsc/dds.h +++ b/src/core/ddsc/include/ddsc/dds.h @@ -177,6 +177,29 @@ typedef struct dds_sample_info } dds_sample_info_t; +typedef struct dds_builtintopic_guid +{ + uint8_t v[16]; +} +dds_builtintopic_guid_t; + +typedef struct dds_builtintopic_participant +{ + dds_builtintopic_guid_t key; + dds_qos_t *qos; +} +dds_builtintopic_participant_t; + +typedef struct dds_builtintopic_endpoint +{ + dds_builtintopic_guid_t key; + dds_builtintopic_guid_t participant_key; + char *topic_name; + char *type_name; + dds_qos_t *qos; +} +dds_builtintopic_endpoint_t; + /* All entities are represented by a process-private handle, with one call to enable an entity when it was created disabled. diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index f88393b..cf0f7b1 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -20,8 +20,10 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" ddsi_mcgroup.c ddsi_serdata.c ddsi_serdata_default.c + ddsi_serdata_builtin.c ddsi_sertopic.c ddsi_sertopic_default.c + ddsi_sertopic_builtin.c ddsi_rhc_plugin.c ddsi_iid.c ddsi_tkmap.c @@ -75,6 +77,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/ddsi" ddsi_serdata.h ddsi_sertopic.h ddsi_serdata_default.h + ddsi_serdata_builtin.h ddsi_rhc_plugin.h ddsi_iid.h ddsi_tkmap.h diff --git a/src/core/ddsi/include/ddsi/ddsi_serdata_builtin.h b/src/core/ddsi/include/ddsi/ddsi_serdata_builtin.h new file mode 100644 index 0000000..3770378 --- /dev/null +++ b/src/core/ddsi/include/ddsi/ddsi_serdata_builtin.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 DDSI_SERDATA_BUILTIN_H +#define DDSI_SERDATA_BUILTIN_H + +#include "os/os.h" +#include "util/ut_avl.h" +#include "sysdeps.h" +#include "ddsi/ddsi_serdata.h" +#include "ddsi/ddsi_sertopic.h" +#include "ddsi/q_xqos.h" + +struct ddsi_serdata_builtin { + struct ddsi_serdata c; + nn_guid_t key; + nn_xqos_t xqos; +}; + +enum ddsi_sertopic_builtin_type { + DSBT_PARTICIPANT, + DSBT_READER, + DSBT_WRITER +}; + +struct ddsi_sertopic_builtin { + struct ddsi_sertopic c; + enum ddsi_sertopic_builtin_type type; +}; + +extern const struct ddsi_sertopic_ops ddsi_sertopic_ops_builtin; +extern const struct ddsi_serdata_ops ddsi_serdata_ops_builtin; + +struct ddsi_sertopic *new_sertopic_builtin (enum ddsi_sertopic_builtin_type type, const char *name, const char *typename); + +#endif diff --git a/src/core/ddsi/include/ddsi/q_ephash.h b/src/core/ddsi/include/ddsi/q_ephash.h index 43863ce..3779d00 100644 --- a/src/core/ddsi/include/ddsi/q_ephash.h +++ b/src/core/ddsi/include/ddsi/q_ephash.h @@ -80,6 +80,7 @@ void ephash_remove_reader_guid (struct reader *rd); void ephash_remove_proxy_writer_guid (struct proxy_writer *pwr); void ephash_remove_proxy_reader_guid (struct proxy_reader *prd); +void *ephash_lookup_guid_untyped (const struct nn_guid *guid); void *ephash_lookup_guid (const struct nn_guid *guid, enum entity_kind kind); struct participant *ephash_lookup_participant_guid (const struct nn_guid *guid); diff --git a/src/core/ddsi/src/ddsi_serdata_builtin.c b/src/core/ddsi/src/ddsi_serdata_builtin.c new file mode 100644 index 0000000..a61bffe --- /dev/null +++ b/src/core/ddsi/src/ddsi_serdata_builtin.c @@ -0,0 +1,287 @@ +/* + * 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 "os/os.h" +#include "ddsi/sysdeps.h" +#include "ddsi/q_md5.h" +#include "ddsi/q_bswap.h" +#include "ddsi/q_config.h" +#include "ddsi/q_freelist.h" +#include +#include +#include "os/os.h" +#include "dds__key.h" +#include "ddsi/ddsi_tkmap.h" +#include "dds__stream.h" +#include "ddsi/q_entity.h" +#include "ddsi/ddsi_serdata_builtin.h" +//#include "dds.h" /* FIXME: need the sample types of the built-in topics */ + +static const uint64_t unihashconsts[] = { + UINT64_C (16292676669999574021), + UINT64_C (10242350189706880077), + UINT64_C (12844332200329132887), + UINT64_C (16728792139623414127) +}; + +static uint32_t hash_guid (const nn_guid_t *g) +{ + return + (uint32_t) (((((uint32_t) g->prefix.u[0] + unihashconsts[0]) * + ((uint32_t) g->prefix.u[1] + unihashconsts[1])) + + (((uint32_t) g->prefix.u[2] + unihashconsts[2]) * + ((uint32_t) g->entityid.u + unihashconsts[3]))) + >> 32); +} + +static struct ddsi_serdata *fix_serdata_builtin(struct ddsi_serdata_builtin *d, uint32_t basehash) +{ + d->c.hash = hash_guid (&d->key) ^ basehash; + return &d->c; +} + +static bool serdata_builtin_eqkey(const struct ddsi_serdata *acmn, const struct ddsi_serdata *bcmn) +{ + const struct ddsi_serdata_builtin *a = (const struct ddsi_serdata_builtin *)acmn; + const struct ddsi_serdata_builtin *b = (const struct ddsi_serdata_builtin *)bcmn; + return memcmp (&a->key, &b->key, sizeof (a->key)) == 0; +} + +static void serdata_builtin_free(struct ddsi_serdata *dcmn) +{ + struct ddsi_serdata_builtin *d = (struct ddsi_serdata_builtin *)dcmn; + if (d->c.kind == SDK_DATA) + nn_xqos_fini (&d->xqos); + os_free (d); +} + +static struct ddsi_serdata_builtin *serdata_builtin_new(const struct ddsi_sertopic_builtin *tp, enum ddsi_serdata_kind kind) +{ + struct ddsi_serdata_builtin *d = os_malloc(sizeof (*d)); + ddsi_serdata_init (&d->c, &tp->c, kind); + return d; +} + +static void from_entity_pp (struct ddsi_serdata_builtin *d, const struct participant *pp) +{ + nn_xqos_copy(&d->xqos, &pp->plist->qos); +} + +static void from_entity_proxypp (struct ddsi_serdata_builtin *d, const struct proxy_participant *proxypp) +{ + nn_xqos_copy(&d->xqos, &proxypp->plist->qos); +} + +static void set_topic_type_from_sertopic (struct ddsi_serdata_builtin *d, const struct ddsi_sertopic *tp) +{ + if (!(d->xqos.present & QP_TOPIC_NAME)) + { + d->xqos.topic_name = dds_string_dup (tp->name); + d->xqos.present |= QP_TOPIC_NAME; + } + if (!(d->xqos.present & QP_TYPE_NAME)) + { + d->xqos.type_name = dds_string_dup (tp->typename); + d->xqos.present |= QP_TYPE_NAME; + } +} + +static void from_entity_rd (struct ddsi_serdata_builtin *d, const struct reader *rd) +{ + nn_xqos_copy(&d->xqos, rd->xqos); + set_topic_type_from_sertopic(d, rd->topic); +} + +static void from_entity_prd (struct ddsi_serdata_builtin *d, const struct proxy_reader *prd) +{ + nn_xqos_copy(&d->xqos, prd->c.xqos); + assert (d->xqos.present & QP_TOPIC_NAME); + assert (d->xqos.present & QP_TYPE_NAME); +} + +static void from_entity_wr (struct ddsi_serdata_builtin *d, const struct writer *wr) +{ + nn_xqos_copy(&d->xqos, wr->xqos); + set_topic_type_from_sertopic(d, wr->topic); +} + +static void from_entity_pwr (struct ddsi_serdata_builtin *d, const struct proxy_writer *pwr) +{ + nn_xqos_copy(&d->xqos, pwr->c.xqos); + assert (d->xqos.present & QP_TOPIC_NAME); + 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) +{ + /* 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_builtin *tp = (const struct ddsi_sertopic_builtin *)tpcmn; + /* keyhash must in host format (which the GUIDs always are internally) */ + const struct entity_common *entity = ephash_lookup_guid_untyped ((const nn_guid_t *) keyhash->value); + struct ddsi_serdata_builtin *d = serdata_builtin_new(tp, entity ? SDK_DATA : SDK_KEY); + memcpy (&d->key, keyhash->value, sizeof (d->key)); + if (d->c.kind == SDK_DATA) + { + switch (entity->kind) + { + case EK_PARTICIPANT: + assert (tp->type == DSBT_PARTICIPANT); + from_entity_pp (d, (const struct participant *) entity); + break; + case EK_READER: + assert (tp->type == DSBT_READER); + from_entity_rd (d, (const struct reader *) entity); + break; + case EK_WRITER: + assert (tp->type == DSBT_WRITER); + from_entity_wr (d, (const struct writer *) entity); + break; + case EK_PROXY_PARTICIPANT: + assert (tp->type == DSBT_PARTICIPANT); + from_entity_proxypp (d, (const struct proxy_participant *) entity); + break; + case EK_PROXY_READER: + assert (tp->type == DSBT_READER); + from_entity_prd (d, (const struct proxy_reader *) entity); + break; + case EK_PROXY_WRITER: + assert (tp->type == DSBT_WRITER); + from_entity_pwr (d, (const struct proxy_writer *) entity); + break; + } + } + return fix_serdata_builtin(d, tp->c.serdata_basehash); +} + +static struct ddsi_serdata *serdata_builtin_to_topicless (const struct ddsi_serdata *serdata_common) +{ + /* All built-in ones are currently topicless */ + return ddsi_serdata_ref (serdata_common); +} + +static void convkey (dds_builtintopic_guid_t *key, const nn_guid_t *guid) +{ + nn_guid_t tmp; + tmp = nn_hton_guid (*guid); + memcpy (key, &tmp, sizeof (*key)); +} + +static char *dds_string_dup_reuse (char *old, const char *src) +{ + size_t size = strlen (src) + 1; + char *new = dds_realloc(old, size); + return memcpy (new, src, size); +} + +static dds_qos_t *dds_qos_from_xqos_reuse (dds_qos_t *old, const nn_xqos_t *src) +{ + if (old == NULL) + return nn_xqos_dup (src); + else + { + nn_xqos_fini (old); + nn_xqos_mergein_missing (old, src); + return old; + } +} + +static bool to_sample_pp (const struct ddsi_serdata_builtin *d, struct dds_builtintopic_participant *sample) +{ + convkey (&sample->key, &d->key); + if (d->c.kind == SDK_DATA) + { + sample->qos = dds_qos_from_xqos_reuse (sample->qos, &d->xqos); + } + return true; +} + +static bool to_sample_endpoint (const struct ddsi_serdata_builtin *d, struct dds_builtintopic_endpoint *sample) +{ + nn_guid_t ppguid; + convkey (&sample->key, &d->key); + ppguid = d->key; + ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; + convkey (&sample->participant_key, &ppguid); + if (d->c.kind == SDK_DATA) + { + assert (d->xqos.present & QP_TOPIC_NAME); + assert (d->xqos.present & QP_TYPE_NAME); + sample->topic_name = dds_string_dup_reuse (sample->topic_name, d->xqos.topic_name); + sample->type_name = dds_string_dup_reuse (sample->type_name, d->xqos.type_name); + sample->qos = dds_qos_from_xqos_reuse (sample->qos, &d->xqos); + } + return true; +} + +static bool serdata_builtin_topicless_to_sample (const struct ddsi_sertopic *topic, const struct ddsi_serdata *serdata_common, void *sample, void **bufptr, void *buflim) +{ + const struct ddsi_serdata_builtin *d = (const struct ddsi_serdata_builtin *)serdata_common; + const struct ddsi_sertopic_builtin *tp = (const struct ddsi_sertopic_builtin *)topic; + if (bufptr) abort(); else { (void)buflim; } /* FIXME: haven't implemented that bit yet! */ + /* FIXME: completing builtin topic support along these lines requires subscribers, publishers and topics to also become DDSI entities - which is probably a good thing anyway */ + switch (tp->type) + { + case DSBT_PARTICIPANT: + return to_sample_pp (d, sample); + case DSBT_READER: + case DSBT_WRITER: + return to_sample_endpoint (d, sample); + } + assert (0); + return false; +} + +static bool serdata_builtin_to_sample (const struct ddsi_serdata *serdata_common, void *sample, void **bufptr, void *buflim) +{ + return serdata_builtin_topicless_to_sample (serdata_common->topic, serdata_common, sample, bufptr, buflim); +} + +static uint32_t serdata_builtin_get_size (const struct ddsi_serdata *serdata_common) +{ + (void)serdata_common; + return 0; +} + +static void serdata_builtin_to_ser (const struct ddsi_serdata *serdata_common, size_t off, size_t sz, void *buf) +{ + (void)serdata_common; (void)off; (void)sz; (void)buf; +} + +static struct ddsi_serdata *serdata_builtin_to_ser_ref (const struct ddsi_serdata *serdata_common, size_t off, size_t sz, ddsi_iovec_t *ref) +{ + (void)serdata_common; (void)off; (void)sz; (void)ref; + return NULL; +} + +static void serdata_builtin_to_ser_unref (struct ddsi_serdata *serdata_common, const ddsi_iovec_t *ref) +{ + (void)serdata_common; (void)ref; +} + +const struct ddsi_serdata_ops ddsi_serdata_ops_builtin = { + .get_size = serdata_builtin_get_size, + .eqkey = serdata_builtin_eqkey, + .free = serdata_builtin_free, + .from_ser = 0, + .from_keyhash = ddsi_serdata_builtin_from_keyhash, + .from_sample = 0, + .to_ser = serdata_builtin_to_ser, + .to_sample = serdata_builtin_to_sample, + .to_ser_ref = serdata_builtin_to_ser_ref, + .to_ser_unref = serdata_builtin_to_ser_unref, + .to_topicless = serdata_builtin_to_topicless, + .topicless_to_sample = serdata_builtin_topicless_to_sample +}; diff --git a/src/core/ddsi/src/ddsi_sertopic_builtin.c b/src/core/ddsi/src/ddsi_sertopic_builtin.c new file mode 100644 index 0000000..31d2263 --- /dev/null +++ b/src/core/ddsi/src/ddsi_sertopic_builtin.c @@ -0,0 +1,147 @@ +/* + * 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 "os/os.h" +#include "ddsi/sysdeps.h" +#include "ddsi/q_md5.h" +#include "ddsi/q_bswap.h" +#include "ddsi/q_config.h" +#include "ddsi/q_freelist.h" +#include "ddsi/ddsi_sertopic.h" +#include "ddsi/ddsi_serdata_builtin.h" +#include "ddsc/dds.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 */ + +struct ddsi_sertopic *new_sertopic_builtin (enum ddsi_sertopic_builtin_type type, const char *name, const char *typename) +{ + struct ddsi_sertopic_builtin *tp = os_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.ops = &ddsi_sertopic_ops_builtin; + tp->c.serdata_ops = &ddsi_serdata_ops_builtin; + tp->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (tp->c.serdata_ops); + tp->c.status_cb = 0; + tp->c.status_cb_entity = NULL; + os_atomic_st32 (&tp->c.refc, 1); + tp->type = type; + return &tp->c; +} + +static void sertopic_builtin_deinit (struct ddsi_sertopic *tp) +{ + (void)tp; +} + +static void free_pp (void *vsample) +{ + dds_builtintopic_participant_t *sample = vsample; + dds_delete_qos (sample->qos); + sample->qos = NULL; +} + +static void free_endpoint (void *vsample) +{ + dds_builtintopic_endpoint_t *sample = vsample; + dds_free (sample->topic_name); + dds_free (sample->type_name); + dds_delete_qos (sample->qos); + sample->topic_name = sample->type_name = NULL; + sample->qos = NULL; +} + +static size_t get_size (enum ddsi_sertopic_builtin_type type) +{ + switch (type) + { + case DSBT_PARTICIPANT: + return sizeof (dds_builtintopic_participant_t); + case DSBT_READER: + case DSBT_WRITER: + return sizeof (dds_builtintopic_endpoint_t); + } + assert (0); + return 0; +} + +static void sertopic_builtin_zero_samples (const struct ddsi_sertopic *sertopic_common, void *samples, size_t count) +{ + const struct ddsi_sertopic_builtin *tp = (const struct ddsi_sertopic_builtin *)sertopic_common; + size_t size = get_size (tp->type); + memset (samples, 0, size * count); +} + +static void sertopic_builtin_realloc_samples (void **ptrs, const struct ddsi_sertopic *sertopic_common, void *old, size_t oldcount, size_t count) +{ + const struct ddsi_sertopic_builtin *tp = (const struct ddsi_sertopic_builtin *)sertopic_common; + const size_t size = get_size (tp->type); + char *new = dds_realloc (old, size * count); + if (new && count > oldcount) + memset (new + size * oldcount, 0, size * (count - oldcount)); + for (size_t i = 0; i < count; i++) + { + void *ptr = (char *) new + i * size; + ptrs[i] = ptr; + } +} + +static void sertopic_builtin_free_samples (const struct ddsi_sertopic *sertopic_common, void **ptrs, size_t count, dds_free_op_t op) +{ + if (count > 0) + { + const struct ddsi_sertopic_builtin *tp = (const struct ddsi_sertopic_builtin *)sertopic_common; + const size_t size = get_size (tp->type); +#ifndef NDEBUG + for (size_t i = 0, off = 0; i < count; i++, off += size) + assert ((char *)ptrs[i] == (char *)ptrs[0] + off); +#endif + if (op & DDS_FREE_CONTENTS_BIT) + { + void (*f) (void *); + char *ptr = ptrs[0]; + switch (tp->type) + { + case DSBT_PARTICIPANT: + f = free_pp; + break; + case DSBT_READER: + case DSBT_WRITER: + f = free_endpoint; + break; + } + for (size_t i = 0; i < count; i++) + { + f (ptr); + ptr += size; + } + } + if (op & DDS_FREE_ALL_BIT) + { + dds_free (ptrs[0]); + } + } +} + +const struct ddsi_sertopic_ops ddsi_sertopic_ops_builtin = { + .deinit = sertopic_builtin_deinit, + .zero_samples = sertopic_builtin_zero_samples, + .realloc_samples = sertopic_builtin_realloc_samples, + .free_samples = sertopic_builtin_free_samples +}; diff --git a/src/core/ddsi/src/q_ephash.c b/src/core/ddsi/src/q_ephash.c index 571d933..88cb373 100644 --- a/src/core/ddsi/src/q_ephash.c +++ b/src/core/ddsi/src/q_ephash.c @@ -116,15 +116,19 @@ static void ephash_guid_remove (struct entity_common *e) assert (x); } -static void *ephash_lookup_guid_int (const struct ephash *ephash, const struct nn_guid *guid, enum entity_kind kind) +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); +} + +static void *ephash_lookup_guid_int (const struct ephash *ephash, const struct nn_guid *guid, enum entity_kind kind) +{ struct entity_common *res; (void)ephash; - e.guid = *guid; - res = ut_chhLookup (gv.guid_hash->hash, &e); - if (res && res->kind == kind) + if ((res = ephash_lookup_guid_untyped (guid)) != NULL && res->kind == kind) return res; else return NULL; @@ -132,7 +136,7 @@ static void *ephash_lookup_guid_int (const struct ephash *ephash, const struct n void *ephash_lookup_guid (const struct nn_guid *guid, enum entity_kind kind) { - return ephash_lookup_guid_int (gv.guid_hash, guid, kind); + return ephash_lookup_guid_int (NULL, guid, kind); } void ephash_insert_participant_guid (struct participant *pp) From 1a0fcea0c2ea03c28ba06736146c9e1e90839cbf Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 3 Dec 2018 17:40:39 +0100 Subject: [PATCH 7/7] replace old builtin topics by new ones and add implementation of DCPSSubscription and DCPSPublication Signed-off-by: Erik Boasson --- src/core/ddsc/CMakeLists.txt | 13 - src/core/ddsc/include/ddsc/dds.h | 7 - src/core/ddsc/include/ddsc/dds_public_qos.h | 207 +-- src/core/ddsc/src/dds__builtin.h | 23 +- src/core/ddsc/src/dds_alloc.c | 5 +- src/core/ddsc/src/dds_builtin.c | 216 +-- src/core/ddsc/src/dds_builtinTopics.idl | 371 ----- src/core/ddsc/src/dds_dcps_builtintopics.idl | 130 -- src/core/ddsc/src/dds_init.c | 4 +- src/core/ddsc/src/dds_qos.c | 490 +++---- src/core/ddsc/src/dds_reader.c | 16 +- src/core/ddsc/src/dds_rhc.c | 10 +- src/core/ddsc/src/dds_topic.c | 12 +- src/core/ddsc/tests/builtin_topics.c | 711 ++------- src/core/ddsi/CMakeLists.txt | 2 - src/core/ddsi/include/ddsi/q_builtin_topic.h | 75 - src/core/ddsi/include/ddsi/q_config.h | 2 + src/core/ddsi/include/ddsi/q_globals.h | 5 + src/core/ddsi/src/q_builtin_topic.c | 183 --- src/core/ddsi/src/q_ddsi_discovery.c | 5 - src/core/ddsi/src/q_entity.c | 116 +- src/core/ddsi/src/q_init.c | 7 + src/tools/ddsls/ddsls.c | 1344 +++++++----------- 23 files changed, 1126 insertions(+), 2828 deletions(-) delete mode 100644 src/core/ddsc/src/dds_builtinTopics.idl delete mode 100644 src/core/ddsc/src/dds_dcps_builtintopics.idl delete mode 100644 src/core/ddsi/include/ddsi/q_builtin_topic.h delete mode 100644 src/core/ddsi/src/q_builtin_topic.c diff --git a/src/core/ddsc/CMakeLists.txt b/src/core/ddsc/CMakeLists.txt index 571e2fb..f9c5ff4 100644 --- a/src/core/ddsc/CMakeLists.txt +++ b/src/core/ddsc/CMakeLists.txt @@ -89,12 +89,6 @@ target_include_directories(ddsc PUBLIC "$") -# Generate builtin-topic sources -set(IDLC_ARGS "-dll" "FOO,ddsc/dds_export.h") -idlc_generate(BuiltinTypes ddsc/src/dds_dcps_builtintopics.idl ddsc/src/dds_builtinTopics.idl) -set(IDLC_ARGS) -target_link_libraries(ddsc PRIVATE BuiltinTypes) - target_include_directories(ddsc PUBLIC "$") @@ -127,13 +121,6 @@ install( DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ddsc" COMPONENT dev) -install( - FILES - "${CMAKE_CURRENT_BINARY_DIR}/dds_dcps_builtintopics.h" - "${CMAKE_CURRENT_BINARY_DIR}/dds_builtinTopics.h" - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ddsc" - COMPONENT dev) - # TODO: improve test inclusion. if((BUILD_TESTING) AND ((NOT DEFINED MSVC_VERSION) OR (MSVC_VERSION GREATER "1800"))) add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/tests") diff --git a/src/core/ddsc/include/ddsc/dds.h b/src/core/ddsc/include/ddsc/dds.h index d407d95..87f264e 100644 --- a/src/core/ddsc/include/ddsc/dds.h +++ b/src/core/ddsc/include/ddsc/dds.h @@ -48,7 +48,6 @@ typedef _Return_type_success_(return > 0) int32_t dds_entity_t; #include "ddsc/dds_public_error.h" #include "ddsc/dds_public_status.h" #include "ddsc/dds_public_listener.h" -#include "dds_dcps_builtintopics.h" #if defined (__cplusplus) extern "C" { @@ -74,15 +73,9 @@ 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_CMPARTICIPANT; -extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_DCPSTYPE; 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_CMPUBLISHER; extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION; -extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_CMSUBSCRIBER; -extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_CMDATAWRITER; -extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_CMDATAREADER; /** @}*/ /** @name Communication Status definitions diff --git a/src/core/ddsc/include/ddsc/dds_public_qos.h b/src/core/ddsc/include/ddsc/dds_public_qos.h index 64a7e4e..b7f2243 100644 --- a/src/core/ddsc/include/ddsc/dds_public_qos.h +++ b/src/core/ddsc/include/ddsc/dds_public_qos.h @@ -545,14 +545,10 @@ void dds_qset_durability_service * @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] 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 */ -DDS_EXPORT -void dds_qget_userdata -( - _In_ const dds_qos_t * __restrict qos, - _Outptr_result_bytebuffer_maybenull_(*sz) void ** value, - _Out_ size_t * sz -); +DDS_EXPORT bool dds_qget_userdata (const dds_qos_t * __restrict qos, void **value, size_t *sz); /** * @brief Get the topicdata from a qos structure @@ -560,14 +556,10 @@ void dds_qget_userdata * @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] sz - Pointer that will store the size of topicdata - */ -DDS_EXPORT -void dds_qget_topicdata -( - _In_ const dds_qos_t * __restrict qos, - _Outptr_result_bytebuffer_maybenull_(*sz) void ** value, - _Out_ size_t * sz -); + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object +*/ +DDS_EXPORT bool dds_qget_topicdata (const dds_qos_t * __restrict qos, void **value, size_t *sz); /** * @brief Get the groupdata from a qos structure @@ -575,27 +567,20 @@ void dds_qget_topicdata * @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] 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 */ -DDS_EXPORT -void dds_qget_groupdata -( - _In_ const dds_qos_t * __restrict qos, - _Outptr_result_bytebuffer_maybenull_(*sz) void ** value, - _Out_ size_t * sz -); +DDS_EXPORT bool dds_qget_groupdata (const dds_qos_t * __restrict qos, void **value, size_t *sz); /** * @brief Get the durability policy from a qos structure * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] kind - Pointer that will store the durability kind + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_durability -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_durability_kind_t *kind -); +DDS_EXPORT bool dds_qget_durability (const dds_qos_t * __restrict qos, dds_durability_kind_t *kind); /** * @brief Get the history policy from a qos structure @@ -603,14 +588,10 @@ void dds_qget_durability * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] kind - Pointer that will store the history kind (optional) * @param[in,out] depth - Pointer that will store the history depth (optional) + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_history -( - _In_ const dds_qos_t * __restrict qos, - _Out_opt_ dds_history_kind_t * kind, - _Out_opt_ int32_t *depth -); +DDS_EXPORT bool dds_qget_history (const dds_qos_t * __restrict qos, dds_history_kind_t *kind, int32_t *depth); /** * @brief Get the resource-limits policy from a qos structure @@ -619,15 +600,10 @@ void dds_qget_history * @param[in,out] max_samples - Pointer that will store the number of samples resource-limit (optional) * @param[in,out] max_instances - Pointer that will store the number of instances resource-limit (optional) * @param[in,out] max_samples_per_instance - Pointer that will store the number of samples per instance resource-limit (optional) + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_resource_limits -( - _In_ const dds_qos_t * __restrict qos, - _Out_opt_ int32_t *max_samples, - _Out_opt_ int32_t *max_instances, - _Out_opt_ int32_t *max_samples_per_instance -); +DDS_EXPORT 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); /** * @brief Get the presentation policy from a qos structure @@ -636,80 +612,60 @@ void dds_qget_resource_limits * @param[in,out] access_scope - Pointer that will store access scope kind (optional) * @param[in,out] coherent_access - Pointer that will store coherent access enable value (optional) * @param[in,out] ordered_access - Pointer that will store orderede access enable value (optional) + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_presentation -( - _In_ const dds_qos_t * __restrict qos, - _Out_opt_ dds_presentation_access_scope_kind_t *access_scope, - _Out_opt_ bool *coherent_access, - _Out_opt_ bool *ordered_access -); +DDS_EXPORT bool dds_qget_presentation (const dds_qos_t * __restrict qos, dds_presentation_access_scope_kind_t *access_scope, bool *coherent_access, bool *ordered_access); /** * @brief Get the lifespan policy from a qos structure * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] lifespan - Pointer that will store lifespan duration + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_lifespan -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_duration_t * lifespan -); +DDS_EXPORT bool dds_qget_lifespan (const dds_qos_t * __restrict qos, dds_duration_t *lifespan); /** * @brief Get the deadline policy from a qos structure * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] deadline - Pointer that will store deadline duration + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_deadline -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_duration_t * deadline -); +DDS_EXPORT bool dds_qget_deadline (const dds_qos_t * __restrict qos, dds_duration_t *deadline); /** * @brief Get the latency-budget policy from a qos structure * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] duration - Pointer that will store latency-budget duration + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_latency_budget -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_duration_t *duration -); +DDS_EXPORT bool dds_qget_latency_budget (const dds_qos_t * __restrict qos, dds_duration_t *duration); /** * @brief Get the ownership policy from a qos structure * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] kind - Pointer that will store the ownership kind + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_ownership -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_ownership_kind_t *kind -); +DDS_EXPORT bool dds_qget_ownership (const dds_qos_t * __restrict qos, dds_ownership_kind_t *kind); /** * @brief Get the ownership strength qos policy * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] value - Pointer that will store the ownership strength value + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_ownership_strength -( - _In_ const dds_qos_t * __restrict qos, - _Out_ int32_t *value -); +DDS_EXPORT bool dds_qget_ownership_strength (const dds_qos_t * __restrict qos, int32_t *value); /** * @brief Get the liveliness qos policy @@ -717,27 +673,20 @@ void dds_qget_ownership_strength * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] kind - Pointer that will store the liveliness kind (optional) * @param[in,out] lease_duration - Pointer that will store the liveliness lease duration (optional) + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_liveliness -( - _In_ const dds_qos_t * __restrict qos, - _Out_opt_ dds_liveliness_kind_t *kind, - _Out_opt_ dds_duration_t *lease_duration -); +DDS_EXPORT bool dds_qget_liveliness (const dds_qos_t * __restrict qos, dds_liveliness_kind_t *kind, dds_duration_t *lease_duration); /** * @brief Get the time-based filter qos policy * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] minimum_separation - Pointer that will store the minimum separation duration (optional) + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_time_based_filter -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_duration_t *minimum_separation -); +DDS_EXPORT bool dds_qget_time_based_filter (const dds_qos_t * __restrict qos, dds_duration_t *minimum_separation); /** * @brief Get the partition qos policy @@ -745,14 +694,10 @@ void dds_qget_time_based_filter * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] n - Pointer that will store the number of partitions (optional) * @param[in,out] ps - Pointer that will store the string(s) containing partition name(s) (optional) + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_partition -( - _In_ const dds_qos_t * __restrict qos, - _Out_ uint32_t *n, - _Outptr_opt_result_buffer_all_maybenull_(*n) char *** ps -); +DDS_EXPORT bool dds_qget_partition (const dds_qos_t * __restrict qos, uint32_t *n, char ***ps); /** * @brief Get the reliability qos policy @@ -760,53 +705,40 @@ void dds_qget_partition * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] kind - Pointer that will store the reliability kind (optional) * @param[in,out] max_blocking_time - Pointer that will store the max blocking time for reliable reliability (optional) + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_reliability -( - _In_ const dds_qos_t * __restrict qos, - _Out_opt_ dds_reliability_kind_t *kind, - _Out_opt_ dds_duration_t *max_blocking_time -); +DDS_EXPORT bool dds_qget_reliability (const dds_qos_t * __restrict qos, dds_reliability_kind_t *kind, dds_duration_t *max_blocking_time); /** * @brief Get the transport priority qos policy * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] value - Pointer that will store the transport priority value + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_transport_priority -( - _In_ const dds_qos_t * __restrict qos, - _Out_ int32_t *value -); +DDS_EXPORT bool dds_qget_transport_priority (const dds_qos_t * __restrict qos, int32_t *value); /** * @brief Get the destination-order qos policy * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] kind - Pointer that will store the destination-order kind + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_destination_order -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_destination_order_kind_t *kind -); +DDS_EXPORT bool dds_qget_destination_order (const dds_qos_t * __restrict qos, dds_destination_order_kind_t *kind); /** * @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 + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_writer_data_lifecycle -( - _In_ const dds_qos_t * __restrict qos, - _Out_ bool * autodispose -); +DDS_EXPORT bool dds_qget_writer_data_lifecycle (const dds_qos_t * __restrict qos, bool *autodispose); /** * @brief Get the reader data-lifecycle qos policy @@ -814,14 +746,10 @@ void dds_qget_writer_data_lifecycle * @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in,out] autopurge_nowriter_samples_delay - Pointer that will store the delay for auto-purging samples from instances in a no-writer state (optional) * @param[in,out] autopurge_disposed_samples_delay - Pointer that will store the delay for auto-purging of disposed instances (optional) + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT -void dds_qget_reader_data_lifecycle -( - _In_ const dds_qos_t * __restrict qos, - _Out_opt_ dds_duration_t *autopurge_nowriter_samples_delay, - _Out_opt_ dds_duration_t *autopurge_disposed_samples_delay -); +DDS_EXPORT 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); /** * @brief Get the durability-service qos policy values. @@ -833,17 +761,10 @@ void dds_qget_reader_data_lifecycle * @param[in,out] max_samples - Pointer that will store number of samples resource-limit policy applied by the durability service (optional) * @param[in,out] max_instances - Pointer that will store number of instances resource-limit policy applied by the durability service (optional) * @param[in,out] max_samples_per_instance - Pointer that will store number of samples per instance resource-limit policy applied by the durability service (optional) + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object */ -DDS_EXPORT void dds_qget_durability_service -( - _In_ const dds_qos_t * qos, - _Out_opt_ dds_duration_t * service_cleanup_delay, - _Out_opt_ dds_history_kind_t * history_kind, - _Out_opt_ int32_t * history_depth, - _Out_opt_ int32_t * max_samples, - _Out_opt_ int32_t * max_instances, - _Out_opt_ int32_t * max_samples_per_instance -); +DDS_EXPORT 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 defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds__builtin.h b/src/core/ddsc/src/dds__builtin.h index 284f968..3601d67 100644 --- a/src/core/ddsc/src/dds__builtin.h +++ b/src/core/ddsc/src/dds__builtin.h @@ -13,7 +13,7 @@ #define _DDS_BUILTIN_H_ #include "ddsi/q_time.h" -#include "dds_builtinTopics.h" +#include "ddsi/ddsi_serdata_builtin.h" #if defined (__cplusplus) @@ -22,7 +22,6 @@ extern "C" #endif - /* Get actual topic in related participant related to topic 'id'. */ _Must_inspect_result_ dds_entity_t dds__get_builtin_topic( @@ -39,7 +38,8 @@ _Must_inspect_result_ dds_entity_t dds__get_builtin_subscriber( _In_ dds_entity_t e); - +/* Checks whether the reader QoS is valid for use with built-in topic TOPIC */ +bool dds__validate_builtin_reader_qos(dds_entity_t topic, const dds_qos_t *qos); /* Initialization and finalize functions. */ void @@ -50,19 +50,12 @@ void dds__builtin_fini( void); - - -/* Callback functions that contain received builtin data. */ void -dds__builtin_participant_cb( - DDS_ParticipantBuiltinTopicData *data, - nn_wctime_t timestamp); - -void -dds__builtin_cmparticipant_cb( - DDS_CMParticipantBuiltinTopicData *data, - nn_wctime_t timestamp); - +dds__builtin_write( + _In_ enum ddsi_sertopic_builtin_type type, + _In_ const nn_guid_t *guid, + _In_ nn_wctime_t timestamp, + _In_ bool alive); #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds_alloc.c b/src/core/ddsc/src/dds_alloc.c index 049d9aa..3c5546d 100644 --- a/src/core/ddsc/src/dds_alloc.c +++ b/src/core/ddsc/src/dds_alloc.c @@ -76,8 +76,9 @@ char * dds_string_dup (const char * str) char * ret = NULL; if (str) { - ret = dds_alloc (strlen (str) + 1); - strcpy (ret, str); + size_t sz = strlen (str) + 1; + ret = dds_alloc (sz); + memcpy (ret, str, sz); } return ret; } diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index a93dabc..920e3f1 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -14,7 +14,6 @@ #include "ddsi/q_entity.h" #include "ddsi/q_thread.h" #include "ddsi/q_config.h" -#include "ddsi/q_builtin_topic.h" #include "dds__init.h" #include "dds__qos.h" #include "dds__domain.h" @@ -23,7 +22,10 @@ #include "dds__types.h" #include "dds__builtin.h" #include "dds__subscriber.h" - +#include "dds__write.h" +#include "dds__writer.h" +#include "ddsi/q_qosmatch.h" +#include "ddsi/ddsi_serdata_builtin.h" static dds_return_t dds__delete_builtin_participant( @@ -37,7 +39,7 @@ static _Must_inspect_result_ dds_entity_t dds__create_builtin_publisher( _In_ dds_entity_t participant); -static _Must_inspect_result_ dds_entity_t +static dds_entity_t dds__create_builtin_writer( _In_ dds_entity_t topic); @@ -56,17 +58,23 @@ static dds_entity_t g_builtin_local_participant = 0; static dds_entity_t g_builtin_local_publisher = 0; static dds_entity_t g_builtin_local_writers[] = { 0, /* index DDS_BUILTIN_TOPIC_DCPSPARTICIPANT - DDS_KIND_INTERNAL - 1 */ - 0, /* index DDS_BUILTIN_TOPIC_CMPARTICIPANT - DDS_KIND_INTERNAL - 1 */ - 0, /* index DDS_BUILTIN_TOPIC_DCPSTYPE - DDS_KIND_INTERNAL - 1 */ 0, /* index DDS_BUILTIN_TOPIC_DCPSTOPIC - DDS_KIND_INTERNAL - 1 */ 0, /* index DDS_BUILTIN_TOPIC_DCPSPUBLICATION - DDS_KIND_INTERNAL - 1 */ - 0, /* index DDS_BUILTIN_TOPIC_CMPUBLISHER - DDS_KIND_INTERNAL - 1 */ 0, /* index DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION - DDS_KIND_INTERNAL - 1 */ - 0, /* index DDS_BUILTIN_TOPIC_CMSUBSCRIBER - DDS_KIND_INTERNAL - 1 */ - 0, /* index DDS_BUILTIN_TOPIC_CMDATAWRITER - DDS_KIND_INTERNAL - 1 */ - 0, /* index DDS_BUILTIN_TOPIC_CMDATAREADER - DDS_KIND_INTERNAL - 1 */ }; +static _Must_inspect_result_ dds_qos_t * +dds__create_builtin_qos( + void) +{ + const char *partition = "__BUILT-IN PARTITION__"; + dds_qos_t *qos = dds_create_qos(); + dds_qset_durability(qos, DDS_DURABILITY_TRANSIENT_LOCAL); + dds_qset_presentation(qos, DDS_PRESENTATION_TOPIC, false, false); + dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_MSECS(100)); + dds_qset_partition(qos, 1, &partition); + return qos; +} static dds_return_t dds__delete_builtin_participant( @@ -148,17 +156,9 @@ static _Must_inspect_result_ dds_entity_t dds__create_builtin_publisher( _In_ dds_entity_t participant) { - dds_entity_t pub; - dds_qos_t *qos; - const char *partition = "__BUILT-IN PARTITION__"; - - qos = dds_create_qos(); - dds_qset_partition(qos, 1, &partition); - - pub = dds_create_publisher(participant, qos, NULL); - + dds_qos_t *qos = dds__create_builtin_qos(); + dds_entity_t pub = dds_create_publisher(participant, qos, NULL); dds_delete_qos(qos); - return pub; } @@ -166,21 +166,13 @@ static _Must_inspect_result_ dds_entity_t dds__create_builtin_subscriber( _In_ dds_entity *participant) { - dds_entity_t sub; - dds_qos_t *qos; - const char *partition = "__BUILT-IN PARTITION__"; - - qos = dds_create_qos(); - dds_qset_partition(qos, 1, &partition); - - /* Create builtin-subscriber */ - sub = dds__create_subscriber_l(participant, qos, NULL); + dds_qos_t *qos = dds__create_builtin_qos(); + dds_entity_t sub = dds__create_subscriber_l(participant, qos, NULL); dds_delete_qos(qos); - return sub; } -static _Must_inspect_result_ dds_entity_t +static dds_entity_t dds__create_builtin_writer( _In_ dds_entity_t topic) { @@ -189,13 +181,7 @@ dds__create_builtin_writer( if (pub > 0) { dds_entity_t top = dds__get_builtin_topic(pub, topic); if (top > 0) { - dds_qos_t *qos; - // TODO: set builtin qos - qos = dds_create_qos(); - dds_qset_durability(qos, DDS_DURABILITY_TRANSIENT_LOCAL); - dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_MSECS(100)); - wr = dds_create_writer(pub, top, qos, NULL); - dds_delete_qos(qos); + wr = dds_create_writer(pub, top, NULL, NULL); (void)dds_delete(top); } else { wr = top; @@ -213,6 +199,9 @@ dds__get_builtin_participant( { if (g_builtin_local_participant == 0) { g_builtin_local_participant = dds__create_builtin_participant(); + (void)dds__create_builtin_writer(DDS_BUILTIN_TOPIC_DCPSPARTICIPANT); + (void)dds__create_builtin_writer(DDS_BUILTIN_TOPIC_DCPSPUBLICATION); + (void)dds__create_builtin_writer(DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION); } return g_builtin_local_participant; } @@ -277,57 +266,26 @@ dds__get_builtin_topic( participant = dds_get_participant(e); if (participant > 0) { - const dds_topic_descriptor_t *desc; - const char *name; + struct ddsi_sertopic *sertopic; if (topic == DDS_BUILTIN_TOPIC_DCPSPARTICIPANT) { - desc = &DDS_ParticipantBuiltinTopicData_desc; - name = "DCPSParticipant"; - } else if (topic == DDS_BUILTIN_TOPIC_CMPARTICIPANT) { - desc = &DDS_CMParticipantBuiltinTopicData_desc; - name = "CMParticipant"; - } else if (topic == DDS_BUILTIN_TOPIC_DCPSTYPE) { - desc = &DDS_TypeBuiltinTopicData_desc; - name = "DCPSType"; - } else if (topic == DDS_BUILTIN_TOPIC_DCPSTOPIC) { - desc = &DDS_TopicBuiltinTopicData_desc; - name = "DCPSTopic"; + sertopic = gv.builtin_participant_topic; } else if (topic == DDS_BUILTIN_TOPIC_DCPSPUBLICATION) { - desc = &DDS_PublicationBuiltinTopicData_desc; - name = "DCPSPublication"; - } else if (topic == DDS_BUILTIN_TOPIC_CMPUBLISHER) { - desc = &DDS_CMPublisherBuiltinTopicData_desc; - name = "CMPublisher"; + sertopic = gv.builtin_writer_topic; } else if (topic == DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION) { - desc = &DDS_SubscriptionBuiltinTopicData_desc; - name = "DCPSSubscription"; - } else if (topic == DDS_BUILTIN_TOPIC_CMSUBSCRIBER) { - desc = &DDS_CMSubscriberBuiltinTopicData_desc; - name = "CMSubscriber"; - } else if (topic == DDS_BUILTIN_TOPIC_CMDATAWRITER) { - desc = &DDS_CMDataWriterBuiltinTopicData_desc; - name = "CMDataWriter"; - } else if (topic == DDS_BUILTIN_TOPIC_CMDATAREADER) { - desc = &DDS_CMDataReaderBuiltinTopicData_desc; - name = "CMDataReader"; + sertopic = gv.builtin_reader_topic; } else { DDS_ERROR("Invalid builtin-topic handle(%d)\n", topic); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err_invalid_topic; } - ret = dds_find_topic(participant, name); + ret = dds_find_topic (participant, sertopic->name); if (ret < 0 && dds_err_nr(ret) == DDS_RETCODE_PRECONDITION_NOT_MET) { - dds_qos_t *tqos; - - tqos = dds_create_qos(); - dds_qset_durability(tqos, DDS_DURABILITY_TRANSIENT_LOCAL); - dds_qset_presentation(tqos, DDS_PRESENTATION_TOPIC, false, false); - dds_qset_reliability(tqos, DDS_RELIABILITY_RELIABLE, DDS_MSECS(100)); - ret = dds_create_topic(participant, desc, name, tqos, NULL); - dds_delete_qos(tqos); + dds_qos_t *qos = dds__create_builtin_qos(); + ret = dds_create_topic_arbitrary(participant, sertopic, sertopic->name, qos, NULL, NULL); + dds_delete_qos(qos); } - } else { /* Failed to get participant of provided entity */ ret = participant; @@ -343,7 +301,7 @@ dds__get_builtin_writer( _In_ dds_entity_t topic) { dds_entity_t wr; - if ((topic >= DDS_BUILTIN_TOPIC_DCPSPARTICIPANT) && (topic <= DDS_BUILTIN_TOPIC_CMDATAREADER)) { + if ((topic >= DDS_BUILTIN_TOPIC_DCPSPARTICIPANT) && (topic <= DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION)) { int index = (int)(topic - DDS_KIND_INTERNAL - 1); os_mutexLock(&g_builtin_mutex); wr = g_builtin_local_writers[index]; @@ -362,21 +320,40 @@ dds__get_builtin_writer( } static dds_return_t -dds__builtin_write( - _In_ dds_entity_t topic, - _In_ const void *data, - _In_ dds_time_t timestamp, - _In_ int alive) +dds__builtin_write_int( + _In_ dds_entity_t topic, + _In_ const nn_guid_t *guid, + _In_ dds_time_t timestamp, + _In_ bool alive) { dds_return_t ret = DDS_RETCODE_OK; if (os_atomic_inc32_nv(&m_call_count) > 1) { dds_entity_t wr; wr = dds__get_builtin_writer(topic); if (wr > 0) { - if (alive) { - ret = dds_write_ts(wr, data, timestamp); + struct ddsi_sertopic *sertopic; + struct ddsi_serdata *serdata; + struct nn_keyhash keyhash; + struct dds_writer *wraddr; + + if (topic == DDS_BUILTIN_TOPIC_DCPSPARTICIPANT) { + sertopic = gv.builtin_participant_topic; + } else if (topic == DDS_BUILTIN_TOPIC_DCPSPUBLICATION) { + sertopic = gv.builtin_writer_topic; + } else if (topic == DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION) { + sertopic = gv.builtin_reader_topic; } else { - ret = dds_dispose_ts(wr, data, timestamp); + sertopic = NULL; + assert (0); + } + + memcpy (&keyhash, guid, sizeof (keyhash)); + serdata = ddsi_serdata_from_keyhash(sertopic, &keyhash); + + ret = dds_writer_lock(wr, &wraddr); + if (ret == DDS_RETCODE_OK) { + ret = dds_writecdr_impl (wraddr, serdata, timestamp, alive ? 0 : (DDS_WR_DISPOSE_BIT | DDS_WR_UNREGISTER_BIT)); + dds_writer_unlock(wraddr); } } else { ret = wr; @@ -386,6 +363,56 @@ dds__builtin_write( return ret; } +void +dds__builtin_write( + _In_ enum ddsi_sertopic_builtin_type type, + _In_ const nn_guid_t *guid, + _In_ nn_wctime_t timestamp, + _In_ bool alive) +{ + dds_entity_t topic; + switch (type) + { + case DSBT_PARTICIPANT: + topic = DDS_BUILTIN_TOPIC_DCPSPARTICIPANT; + break; + case DSBT_WRITER: + topic = DDS_BUILTIN_TOPIC_DCPSPUBLICATION; + break; + case DSBT_READER: + topic = DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION; + break; + } + (void)dds__builtin_write_int(topic, guid, timestamp.v, alive); +} + +bool dds__validate_builtin_reader_qos(dds_entity_t topic, const dds_qos_t *qos) +{ + if (qos == NULL) { + /* default QoS inherited from topic is ok by definition */ + return true; + } else { + dds_entity_t wr = dds__get_builtin_writer(topic); + dds_qos_t *wrqos = dds_create_qos(); + dds_return_t ret = dds_get_qos(wr, wrqos); + bool match; + assert (ret == DDS_RETCODE_OK); + (void)ret; + if (!qos_match_p (qos, wrqos)) { + match = false; + } else if (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) { + /* this means a write on the built-in topic writer can't fail */ + match = false; + } else { + match = true; + } + dds_delete_qos(wrqos); + return match; + } +} + void dds__builtin_init( void) @@ -410,22 +437,3 @@ dds__builtin_fini( memset(g_builtin_local_writers, 0, sizeof(g_builtin_local_writers)); os_mutexDestroy(&g_builtin_mutex); } - - -void -forward_builtin_participant( - _In_ DDS_ParticipantBuiltinTopicData *data, - _In_ nn_wctime_t timestamp, - _In_ int alive) -{ - dds__builtin_write(DDS_BUILTIN_TOPIC_DCPSPARTICIPANT, data, timestamp.v, alive); -} - -void -forward_builtin_cmparticipant( - _In_ DDS_CMParticipantBuiltinTopicData *data, - _In_ nn_wctime_t timestamp, - _In_ int alive) -{ - dds__builtin_write(DDS_BUILTIN_TOPIC_CMPARTICIPANT, data, timestamp.v, alive); -} diff --git a/src/core/ddsc/src/dds_builtinTopics.idl b/src/core/ddsc/src/dds_builtinTopics.idl deleted file mode 100644 index 1819849..0000000 --- a/src/core/ddsc/src/dds_builtinTopics.idl +++ /dev/null @@ -1,371 +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 OSPL_DDS_BUILTINTOPICS_IDL -#define OSPL_DDS_BUILTINTOPICS_IDL - -/* -This file was the one orginally in ./src/api/dcps/saj/code/. -(and therefore by implication ./src/api/dcps/cj/java/code). -*/ - -#define BUILTIN_TOPIC_KEY_TYPE_NATIVE unsigned long - -module DDS { - - - // Added octet sequence definition. - // Prevents IDL compiler warnings from deprecated anonymous types - // on composite type members. - typedef sequence octSeq; - - typedef BUILTIN_TOPIC_KEY_TYPE_NATIVE BuiltinTopicKey_t[3]; - typedef sequence StringSeq; - typedef short DataRepresentationId_t; - - const DataRepresentationId_t XCDR_REPRESENTATION = 0; - const DataRepresentationId_t XML_REPRESENTATION = 0x001; - const DataRepresentationId_t OSPL_REPRESENTATION = 0x400; - const DataRepresentationId_t GPB_REPRESENTATION = 0x401; - const DataRepresentationId_t INVALID_REPRESENTATION = 0x7FFF; - - struct Duration_t { - long sec; - unsigned long nanosec; - }; - - struct UserDataQosPolicy { - octSeq value; - // replaced deprecated anonymous sequence value; - }; - - struct TopicDataQosPolicy { - octSeq value; - // replaced deprecated anonymous sequence value; - }; - - struct GroupDataQosPolicy { - octSeq value; - // replaced deprected anonymous sequence value; - }; - - struct TransportPriorityQosPolicy { - long value; - }; - - struct LifespanQosPolicy { - Duration_t duration; - }; - - enum DurabilityQosPolicyKind { - VOLATILE_DURABILITY_QOS, - TRANSIENT_LOCAL_DURABILITY_QOS, - TRANSIENT_DURABILITY_QOS, - PERSISTENT_DURABILITY_QOS - }; - - struct DurabilityQosPolicy { - DurabilityQosPolicyKind kind; - }; - - enum PresentationQosPolicyAccessScopeKind { - INSTANCE_PRESENTATION_QOS, - TOPIC_PRESENTATION_QOS, - GROUP_PRESENTATION_QOS - }; - - struct PresentationQosPolicy { - PresentationQosPolicyAccessScopeKind access_scope; - boolean coherent_access; - boolean ordered_access; - }; - - struct DeadlineQosPolicy { - Duration_t period; - }; - - struct LatencyBudgetQosPolicy { - Duration_t duration; - }; - - enum OwnershipQosPolicyKind { - SHARED_OWNERSHIP_QOS, - EXCLUSIVE_OWNERSHIP_QOS - }; - - struct OwnershipQosPolicy { - OwnershipQosPolicyKind kind; - }; - - struct OwnershipStrengthQosPolicy { - long value; - }; - - enum LivelinessQosPolicyKind { - AUTOMATIC_LIVELINESS_QOS, - MANUAL_BY_PARTICIPANT_LIVELINESS_QOS, - MANUAL_BY_TOPIC_LIVELINESS_QOS - }; - - struct LivelinessQosPolicy { - LivelinessQosPolicyKind kind; - Duration_t lease_duration; - }; - - struct TimeBasedFilterQosPolicy { - Duration_t minimum_separation; - }; - - struct PartitionQosPolicy { - StringSeq name; - }; - - enum ReliabilityQosPolicyKind { - BEST_EFFORT_RELIABILITY_QOS, - RELIABLE_RELIABILITY_QOS - }; - - struct ReliabilityQosPolicy { - ReliabilityQosPolicyKind kind; - Duration_t max_blocking_time; - boolean synchronous; - }; - - enum DestinationOrderQosPolicyKind { - BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS, - BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS - }; - - struct DestinationOrderQosPolicy { - DestinationOrderQosPolicyKind kind; - }; - - enum HistoryQosPolicyKind { - KEEP_LAST_HISTORY_QOS, - KEEP_ALL_HISTORY_QOS - }; - - struct HistoryQosPolicy { - HistoryQosPolicyKind kind; - long depth; - }; - - struct ResourceLimitsQosPolicy { - long max_samples; - long max_instances; - long max_samples_per_instance; - }; - - struct DurabilityServiceQosPolicy { - Duration_t service_cleanup_delay; - HistoryQosPolicyKind history_kind; - long history_depth; - long max_samples; - long max_instances; - long max_samples_per_instance; - }; - - struct ProductDataQosPolicy { - string value; - }; - - struct EntityFactoryQosPolicy { - boolean autoenable_created_entities; - }; - - struct ShareQosPolicy { - string name; - boolean enable; - }; - - struct WriterDataLifecycleQosPolicy { - boolean autodispose_unregistered_instances; - Duration_t autopurge_suspended_samples_delay; - Duration_t autounregister_instance_delay; - }; - - enum InvalidSampleVisibilityQosPolicyKind { - NO_INVALID_SAMPLES, - MINIMUM_INVALID_SAMPLES, - ALL_INVALID_SAMPLES - }; - - struct InvalidSampleVisibilityQosPolicy { - InvalidSampleVisibilityQosPolicyKind kind; - }; - -// @discrepancy The below QoS did not exist in ./etc/idlpp/dds_dcps.idl Retain ? - - struct SubscriptionKeyQosPolicy { - boolean use_key_list; - StringSeq key_list; - }; - -// @discrepancy End of above discrepancy - - struct ReaderDataLifecycleQosPolicy { - Duration_t autopurge_nowriter_samples_delay; - Duration_t autopurge_disposed_samples_delay; - boolean autopurge_dispose_all; - // @discrepancy The below member existed in this file but did not - // in ./etc/idlpp/dds_dcps.idl. Retain ? - boolean enable_invalid_samples; // @deprecated Will be replaced by invalid_sample_visibility in due time - InvalidSampleVisibilityQosPolicy invalid_sample_visibility; - }; - - struct UserKeyQosPolicy { - boolean enable; - string expression; - }; - - struct ReaderLifespanQosPolicy { - boolean use_lifespan; - Duration_t duration; - }; - - struct TypeHash { - unsigned long long msb; - unsigned long long lsb; - }; - - struct ParticipantBuiltinTopicData { - BuiltinTopicKey_t key; - UserDataQosPolicy user_data; - }; -#pragma keylist ParticipantBuiltinTopicData key - - struct TopicBuiltinTopicData { - BuiltinTopicKey_t key; - string name; - string type_name; - DurabilityQosPolicy durability; - DurabilityServiceQosPolicy durability_service; - DeadlineQosPolicy deadline; - LatencyBudgetQosPolicy latency_budget; - LivelinessQosPolicy liveliness; - ReliabilityQosPolicy reliability; - TransportPriorityQosPolicy transport_priority; - LifespanQosPolicy lifespan; - DestinationOrderQosPolicy destination_order; - HistoryQosPolicy history; - ResourceLimitsQosPolicy resource_limits; - OwnershipQosPolicy ownership; - TopicDataQosPolicy topic_data; - }; -#pragma keylist TopicBuiltinTopicData key - - struct TypeBuiltinTopicData { - string name; - DataRepresentationId_t data_representation_id; - TypeHash type_hash; - octSeq meta_data; - octSeq extentions; - }; -#pragma keylist TypeBuiltinTopicData name data_representation_id type_hash.msb type_hash.lsb - - struct PublicationBuiltinTopicData { - BuiltinTopicKey_t key; - BuiltinTopicKey_t participant_key; - string topic_name; - string type_name; - DurabilityQosPolicy durability; - DeadlineQosPolicy deadline; - LatencyBudgetQosPolicy latency_budget; - LivelinessQosPolicy liveliness; - ReliabilityQosPolicy reliability; - LifespanQosPolicy lifespan; - DestinationOrderQosPolicy destination_order; - UserDataQosPolicy user_data; - OwnershipQosPolicy ownership; - OwnershipStrengthQosPolicy ownership_strength; - PresentationQosPolicy presentation; - PartitionQosPolicy partition; - TopicDataQosPolicy topic_data; - GroupDataQosPolicy group_data; - }; -#pragma keylist PublicationBuiltinTopicData key - - struct SubscriptionBuiltinTopicData { - BuiltinTopicKey_t key; - BuiltinTopicKey_t participant_key; - string topic_name; - string type_name; - DurabilityQosPolicy durability; - DeadlineQosPolicy deadline; - LatencyBudgetQosPolicy latency_budget; - LivelinessQosPolicy liveliness; - ReliabilityQosPolicy reliability; - OwnershipQosPolicy ownership; - DestinationOrderQosPolicy destination_order; - UserDataQosPolicy user_data; - TimeBasedFilterQosPolicy time_based_filter; - PresentationQosPolicy presentation; - PartitionQosPolicy partition; - TopicDataQosPolicy topic_data; - GroupDataQosPolicy group_data; - }; -#pragma keylist SubscriptionBuiltinTopicData key - - struct CMParticipantBuiltinTopicData { - BuiltinTopicKey_t key; - ProductDataQosPolicy product; - }; -#pragma keylist CMParticipantBuiltinTopicData key - - struct CMPublisherBuiltinTopicData { - BuiltinTopicKey_t key; - ProductDataQosPolicy product; - BuiltinTopicKey_t participant_key; - string name; - EntityFactoryQosPolicy entity_factory; - PartitionQosPolicy partition; - }; -#pragma keylist CMPublisherBuiltinTopicData key - - struct CMSubscriberBuiltinTopicData { - BuiltinTopicKey_t key; - ProductDataQosPolicy product; - BuiltinTopicKey_t participant_key; - string name; - EntityFactoryQosPolicy entity_factory; - ShareQosPolicy share; - PartitionQosPolicy partition; - }; -#pragma keylist CMSubscriberBuiltinTopicData key - - struct CMDataWriterBuiltinTopicData { - BuiltinTopicKey_t key; - ProductDataQosPolicy product; - BuiltinTopicKey_t publisher_key; - string name; - HistoryQosPolicy history; - ResourceLimitsQosPolicy resource_limits; - WriterDataLifecycleQosPolicy writer_data_lifecycle; - }; -#pragma keylist CMDataWriterBuiltinTopicData key - - struct CMDataReaderBuiltinTopicData { - BuiltinTopicKey_t key; - ProductDataQosPolicy product; - BuiltinTopicKey_t subscriber_key; - string name; - HistoryQosPolicy history; - ResourceLimitsQosPolicy resource_limits; - ReaderDataLifecycleQosPolicy reader_data_lifecycle; - UserKeyQosPolicy subscription_keys; - ReaderLifespanQosPolicy reader_lifespan; - ShareQosPolicy share; - }; -#pragma keylist CMDataReaderBuiltinTopicData key - -}; - -#endif /* OSPL_DDS_BUILTINTOPICS_IDL */ diff --git a/src/core/ddsc/src/dds_dcps_builtintopics.idl b/src/core/ddsc/src/dds_dcps_builtintopics.idl deleted file mode 100644 index cfa394a..0000000 --- a/src/core/ddsc/src/dds_dcps_builtintopics.idl +++ /dev/null @@ -1,130 +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 OSPL_DDS_DCPS_BUILTINTOPICS_IDL -#define OSPL_DDS_DCPS_BUILTINTOPICS_IDL - -/** -*This file (name) was orginally in ./src/api/dcps/ccpp/idl/. -*It's been modified to include from another file the base definitions -*required for this 'built in topics' superset... : -*/ - -#include "dds_builtinTopics.idl" - -module DDS { - - struct Time_t { - long sec; - unsigned long nanosec; - }; - - enum SchedulingClassQosPolicyKind { - SCHEDULE_DEFAULT, - SCHEDULE_TIMESHARING, - SCHEDULE_REALTIME - }; - - struct SchedulingClassQosPolicy { - SchedulingClassQosPolicyKind kind; - }; - - enum SchedulingPriorityQosPolicyKind { - PRIORITY_RELATIVE, - PRIORITY_ABSOLUTE - }; - - struct SchedulingPriorityQosPolicy { - SchedulingPriorityQosPolicyKind kind; - }; - - struct SchedulingQosPolicy { - SchedulingClassQosPolicy scheduling_class; - SchedulingPriorityQosPolicy scheduling_priority_kind; - long scheduling_priority; - }; - - struct DomainParticipantQos { - UserDataQosPolicy user_data; - EntityFactoryQosPolicy entity_factory; - SchedulingQosPolicy watchdog_scheduling; - SchedulingQosPolicy listener_scheduling; - }; - - struct TopicQos { - TopicDataQosPolicy topic_data; - DurabilityQosPolicy durability; - DurabilityServiceQosPolicy durability_service; - DeadlineQosPolicy deadline; - LatencyBudgetQosPolicy latency_budget; - LivelinessQosPolicy liveliness; - ReliabilityQosPolicy reliability; - DestinationOrderQosPolicy destination_order; - HistoryQosPolicy history; - ResourceLimitsQosPolicy resource_limits; - TransportPriorityQosPolicy transport_priority; - LifespanQosPolicy lifespan; - OwnershipQosPolicy ownership; - }; - - struct DataWriterQos { - DurabilityQosPolicy durability; - DeadlineQosPolicy deadline; - LatencyBudgetQosPolicy latency_budget; - LivelinessQosPolicy liveliness; - ReliabilityQosPolicy reliability; - DestinationOrderQosPolicy destination_order; - HistoryQosPolicy history; - ResourceLimitsQosPolicy resource_limits; - TransportPriorityQosPolicy transport_priority; - LifespanQosPolicy lifespan; - UserDataQosPolicy user_data; - OwnershipQosPolicy ownership; - OwnershipStrengthQosPolicy ownership_strength; - WriterDataLifecycleQosPolicy writer_data_lifecycle; - }; - - struct PublisherQos { - PresentationQosPolicy presentation; - PartitionQosPolicy partition; - GroupDataQosPolicy group_data; - EntityFactoryQosPolicy entity_factory; - }; - - struct DataReaderQos { - DurabilityQosPolicy durability; - DeadlineQosPolicy deadline; - LatencyBudgetQosPolicy latency_budget; - LivelinessQosPolicy liveliness; - ReliabilityQosPolicy reliability; - DestinationOrderQosPolicy destination_order; - HistoryQosPolicy history; - ResourceLimitsQosPolicy resource_limits; - UserDataQosPolicy user_data; - OwnershipQosPolicy ownership; - TimeBasedFilterQosPolicy time_based_filter; - ReaderDataLifecycleQosPolicy reader_data_lifecycle; - SubscriptionKeyQosPolicy subscription_keys; - ReaderLifespanQosPolicy reader_lifespan; - ShareQosPolicy share; - }; - - struct SubscriberQos { - PresentationQosPolicy presentation; - PartitionQosPolicy partition; - GroupDataQosPolicy group_data; - EntityFactoryQosPolicy entity_factory; - ShareQosPolicy share; - }; - -}; - -#endif /* DDS_DCPS_BUILTINTOPICS_IDL */ diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 19d11fc..cc224c4 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -250,12 +250,10 @@ static void dds__fini_plugin (void) void ddsi_plugin_init (void) { - /* Register initialization/clean functions */ - ddsi_plugin.init_fn = dds__init_plugin; ddsi_plugin.fini_fn = dds__fini_plugin; - /* Register read cache functions */ + ddsi_plugin.builtin_write = dds__builtin_write; ddsi_plugin.rhc_plugin.rhc_free_fn = dds_rhc_free; ddsi_plugin.rhc_plugin.rhc_fini_fn = dds_rhc_fini; diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index 30965f1..0e169fa 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -37,7 +37,7 @@ dds_qos_data_copy_in( } } -static void +static bool dds_qos_data_copy_out( _In_ const nn_octetseq_t * data, _When_(*sz == 0, _At_(*value, _Post_null_)) @@ -45,13 +45,22 @@ dds_qos_data_copy_out( _Outptr_result_bytebuffer_all_maybenull_(*sz) void ** value, _Out_ size_t * sz) { - if ((*sz = data->length) != 0) { - assert(data->value); - *value = dds_alloc(data->length); - memcpy(*value, data->value, data->length); - } else { - *value = NULL; + if (sz == NULL && value != NULL) { + return false; } + if (sz) { + *sz = data->length; + } + if (value) { + if (data->length != 0) { + assert(data->value); + *value = dds_alloc(data->length); + memcpy(*value, data->value, data->length); + } else { + *value = NULL; + } + } + return true; } bool @@ -657,397 +666,276 @@ void dds_qset_durability_service } } -void dds_qget_userdata -( - _In_ const dds_qos_t * __restrict qos, - _Outptr_result_bytebuffer_maybenull_(*sz) void ** value, - _Out_ size_t * sz -) +bool dds_qget_userdata (const dds_qos_t * __restrict qos, void **value, size_t *sz) { - if(!qos) { - DDS_ERROR("Argument QoS is NULL\n"); - return ; + if (!qos || !(qos->present & QP_USER_DATA)) { + return false; } - if(!value) { - DDS_ERROR("Argument value is NULL\n"); - return ; - } - if(!sz) { - DDS_ERROR("Argument sz is NULL\n"); - return ; - } - dds_qos_data_copy_out (&qos->user_data, value, sz); + return dds_qos_data_copy_out (&qos->user_data, value, sz); } -void dds_qget_topicdata -( - _In_ const dds_qos_t * __restrict qos, - _Outptr_result_bytebuffer_maybenull_(*sz) void ** value, - _Out_ size_t * sz -) +bool dds_qget_topicdata (const dds_qos_t * __restrict qos, void **value, size_t *sz) { - if(!qos) { - DDS_ERROR("Argument QoS is NULL\n"); - return ; + if (!qos || !(qos->present & QP_TOPIC_DATA)) { + return false; } - if(!value) { - DDS_ERROR("Argument value is NULL\n"); - return ; - } - if(!sz) { - DDS_ERROR("Argument sz is NULL\n"); - return ; - } - dds_qos_data_copy_out (&qos->topic_data, value, sz); + return dds_qos_data_copy_out (&qos->topic_data, value, sz); } -void dds_qget_groupdata -( - _In_ const dds_qos_t * __restrict qos, - _Outptr_result_bytebuffer_maybenull_(*sz) void ** value, - _Out_ size_t * sz -) +bool dds_qget_groupdata (const dds_qos_t * __restrict qos, void **value, size_t *sz) { - if(!qos) { - DDS_ERROR("Argument QoS is NULL\n"); - return ; + if (!qos || !(qos->present & QP_GROUP_DATA)) { + return false; } - if(!value) { - DDS_ERROR("Argument value is NULL\n"); - return ; - } - if(!sz) { - DDS_ERROR("Argument sz is NULL\n"); - return ; - } - dds_qos_data_copy_out (&qos->group_data, value, sz); + return dds_qos_data_copy_out (&qos->group_data, value, sz); } -void dds_qget_durability -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_durability_kind_t *kind -) +bool dds_qget_durability (const dds_qos_t * __restrict qos, dds_durability_kind_t *kind) { - if(!qos) { - DDS_ERROR("Argument QoS is NULL\n"); - return ; + if (!qos || !(qos->present & QP_DURABILITY)) { + return false; } - if(!kind) { - DDS_ERROR("Argument kind is NULL\n"); - return ; + if (kind) { + *kind = (dds_durability_kind_t) qos->durability.kind; } - *kind = (dds_durability_kind_t) qos->durability.kind; + return true; } -void dds_qget_history -( - _In_ const dds_qos_t * __restrict qos, - _Out_opt_ dds_history_kind_t * kind, - _Out_opt_ int32_t *depth -) +bool dds_qget_history (const dds_qos_t * __restrict qos, dds_history_kind_t *kind, int32_t *depth) { - if (qos) { - if (kind) *kind = (dds_history_kind_t) qos->history.kind; - if (depth) *depth = qos->history.depth; - } else { - DDS_ERROR("Argument qos is NULL\n"); + 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; } -void dds_qget_resource_limits -( - _In_ const dds_qos_t * __restrict qos, - _Out_opt_ int32_t *max_samples, - _Out_opt_ int32_t *max_instances, - _Out_opt_ int32_t *max_samples_per_instance -) +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) { - 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; - } - } else { - DDS_ERROR("Argument qos is NULL\n"); + 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; } -void dds_qget_presentation -( - _In_ const dds_qos_t * __restrict qos, - _Out_opt_ dds_presentation_access_scope_kind_t *access_scope, - _Out_opt_ bool *coherent_access, - _Out_opt_ bool *ordered_access -) +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) { - 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; - } else { - DDS_ERROR("Argument qos is NULL\n"); + 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; } -void dds_qget_lifespan -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_duration_t * lifespan -) +bool dds_qget_lifespan (const dds_qos_t * __restrict qos, dds_duration_t *lifespan) { - if(!qos){ - DDS_ERROR("Argument qos is NULL\n"); - return ; + if (!qos || !(qos->present & QP_LIFESPAN)) { + return false; } - if(!lifespan){ - DDS_ERROR("Argument lifespan is NULL\n"); - return ; + if (lifespan) { + *lifespan = nn_from_ddsi_duration (qos->lifespan.duration); } - *lifespan = nn_from_ddsi_duration (qos->lifespan.duration); + return true; } -void dds_qget_deadline -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_duration_t * deadline -) +bool dds_qget_deadline (const dds_qos_t * __restrict qos, dds_duration_t *deadline) { - if(!qos){ - DDS_ERROR("Argument qos is NULL\n"); - return ; + if (!qos || !(qos->present & QP_DEADLINE)) { + return false; } - if(!deadline){ - DDS_ERROR("Argument deadline is NULL\n"); - return ; + if (deadline) { + *deadline = nn_from_ddsi_duration (qos->deadline.deadline); } - *deadline = nn_from_ddsi_duration (qos->deadline.deadline); + return true; } -void dds_qget_latency_budget -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_duration_t *duration -) +bool dds_qget_latency_budget (const dds_qos_t * __restrict qos, dds_duration_t *duration) { - if(!qos){ - DDS_ERROR("Argument qos is NULL\n"); - return ; + if (!qos || !(qos->present & QP_LATENCY_BUDGET)) { + return false; } - if(!duration){ - DDS_ERROR("Argument duration is NULL\n"); - return ; + if (duration) { + *duration = nn_from_ddsi_duration (qos->latency_budget.duration); } - *duration = nn_from_ddsi_duration (qos->latency_budget.duration); + return true; } -void dds_qget_ownership -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_ownership_kind_t *kind -) +bool dds_qget_ownership (const dds_qos_t * __restrict qos, dds_ownership_kind_t *kind) { - if(!qos){ - DDS_ERROR("Argument qos is NULL\n"); - return ; + if (!qos || !(qos->present & QP_OWNERSHIP)) { + return false; } - if(!kind){ - DDS_ERROR("Argument kind is NULL\n"); - return ; + if (kind) { + *kind = (dds_ownership_kind_t) qos->ownership.kind; } - *kind = (dds_ownership_kind_t) qos->ownership.kind; + return true; } -void dds_qget_ownership_strength -( - _In_ const dds_qos_t * __restrict qos, - _Out_ int32_t *value -) +bool dds_qget_ownership_strength (const dds_qos_t * __restrict qos, int32_t *value) { - if(!qos){ - DDS_ERROR("Argument qos is NULL\n"); - return ; + if (!qos || !(qos->present & QP_OWNERSHIP_STRENGTH)) { + return false; } - if(!value){ - DDS_ERROR("Argument value is NULL\n"); - return ; + if (value) { + *value = qos->ownership_strength.value; } - *value = qos->ownership_strength.value; + return true; } -void dds_qget_liveliness -( - _In_ const dds_qos_t * __restrict qos, - _Out_opt_ dds_liveliness_kind_t *kind, - _Out_opt_ dds_duration_t *lease_duration -) +bool dds_qget_liveliness (const dds_qos_t * __restrict qos, dds_liveliness_kind_t *kind, dds_duration_t *lease_duration) { - if (qos) { - if (kind) *kind = (dds_liveliness_kind_t) qos->liveliness.kind; - if (lease_duration) *lease_duration = nn_from_ddsi_duration (qos->liveliness.lease_duration); - } else { - DDS_ERROR("Argument qos is NULL\n"); + 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; } -void dds_qget_time_based_filter -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_duration_t *minimum_separation -) +bool dds_qget_time_based_filter (const dds_qos_t * __restrict qos, dds_duration_t *minimum_separation) { - if(!qos){ - DDS_ERROR("Argument qos is NULL\n"); - return ; + if (!qos || !(qos->present & QP_TIME_BASED_FILTER)) { + return false; } - if(!minimum_separation){ - DDS_ERROR("Argument minimum_separation is NULL\n"); - return ; + if (minimum_separation) { + *minimum_separation = nn_from_ddsi_duration (qos->time_based_filter.minimum_separation); } - *minimum_separation = nn_from_ddsi_duration (qos->time_based_filter.minimum_separation); + return true; } -void dds_qget_partition -( - _In_ const dds_qos_t * __restrict qos, - _Out_ uint32_t *n, - _Outptr_opt_result_buffer_all_maybenull_(*n) char *** ps -) +bool dds_qget_partition (const dds_qos_t * __restrict qos, uint32_t *n, char ***ps) { - size_t len; - uint32_t i; - - if(!qos){ - DDS_ERROR("Argument qos is NULL\n"); - return ; + if (!qos || !(qos->present & QP_PARTITION)) { + return false; } - if(!n){ - DDS_ERROR("Argument n is NULL\n"); - return ; + if (n == NULL && ps != NULL) { + return false; } - - *n = qos->partition.n; - if ( ps ) { - if ( qos->partition.n != 0 ) { + if (n) { + *n = qos->partition.n; + } + if (ps) { + if (qos->partition.n != 0) { *ps = dds_alloc(sizeof(char*) * qos->partition.n); - for ( i = 0; i < qos->partition.n; i++ ) { - len = strlen(qos->partition.strs[i]) + 1; - (*ps)[i] = dds_alloc(len); - strncpy((*ps)[i], qos->partition.strs[i], len); + for (uint32_t i = 0; i < qos->partition.n; i++) { + (*ps)[i] = dds_string_dup(qos->partition.strs[i]); } } else { *ps = NULL; } } + return true; } -void dds_qget_reliability -( - _In_ const dds_qos_t * __restrict qos, - _Out_opt_ dds_reliability_kind_t *kind, - _Out_opt_ dds_duration_t *max_blocking_time -) +bool dds_qget_reliability (const dds_qos_t * __restrict qos, dds_reliability_kind_t *kind, dds_duration_t *max_blocking_time) { - if (qos) { - 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); - } else { - DDS_ERROR("Argument qos is NULL\n"); + 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; } -void dds_qget_transport_priority -( - _In_ const dds_qos_t * __restrict qos, - _Out_ int32_t *value -) +bool dds_qget_transport_priority (const dds_qos_t * __restrict qos, int32_t *value) { - if(!qos){ - DDS_ERROR("Argument qos is NULL\n"); - return ; + if (!qos || !(qos->present & QP_TRANSPORT_PRIORITY)) { + return false; } - if(!value){ - DDS_ERROR("Argument value is NULL\n"); - return ; + if (value) { + *value = qos->transport_priority.value; } - *value = qos->transport_priority.value; + return true; } -void dds_qget_destination_order -( - _In_ const dds_qos_t * __restrict qos, - _Out_ dds_destination_order_kind_t *kind -) +bool dds_qget_destination_order (const dds_qos_t * __restrict qos, dds_destination_order_kind_t *kind) { - if(!qos){ - DDS_ERROR("Argument qos is NULL\n"); - return ; + if (!qos || !(qos->present & QP_DESTINATION_ORDER)) { + return false; } - if(!kind){ - DDS_ERROR("Argument kind is NULL\n"); - return ; + if (kind) { + *kind = (dds_destination_order_kind_t) qos->destination_order.kind; } - *kind = (dds_destination_order_kind_t) qos->destination_order.kind; + return true; } -void dds_qget_writer_data_lifecycle -( - _In_ const dds_qos_t * __restrict qos, - _Out_ bool * autodispose -) +bool dds_qget_writer_data_lifecycle (const dds_qos_t * __restrict qos, bool *autodispose) { - if(!qos){ - DDS_ERROR("Argument qos is NULL\n"); - return ; + if (!qos || !(qos->present & QP_PRISMTECH_WRITER_DATA_LIFECYCLE)) { + return false; } - if(!autodispose){ - DDS_ERROR("Argument autodispose is NULL\n"); - return ; + if (autodispose) { + *autodispose = qos->writer_data_lifecycle.autodispose_unregistered_instances; } - *autodispose = qos->writer_data_lifecycle.autodispose_unregistered_instances; + return true; } -void dds_qget_reader_data_lifecycle -( - _In_ const dds_qos_t * __restrict qos, - _Out_opt_ dds_duration_t *autopurge_nowriter_samples_delay, - _Out_opt_ dds_duration_t *autopurge_disposed_samples_delay -) +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) { - 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); - } - } else { - DDS_ERROR("Argument qos is NULL\n"); + 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; } -void dds_qget_durability_service -( - _In_ const dds_qos_t * qos, - _Out_opt_ dds_duration_t * service_cleanup_delay, - _Out_opt_ dds_history_kind_t * history_kind, - _Out_opt_ int32_t * history_depth, - _Out_opt_ int32_t * max_samples, - _Out_opt_ int32_t * max_instances, - _Out_opt_ int32_t * max_samples_per_instance -) +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) { - 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; - } else { - DDS_ERROR("Argument qos is NULL\n"); + 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; } diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 0c8e3e3..a54763f 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -22,6 +22,7 @@ #include "ddsi/q_entity.h" #include "ddsi/q_thread.h" #include "dds__builtin.h" +#include "ddsi/ddsi_sertopic.h" #include "ddsc/ddsc_project.h" #include "os/os.h" @@ -337,7 +338,6 @@ dds_reader_status_cb( } } - _Pre_satisfies_(((participant_or_subscriber & DDS_ENTITY_KIND_MASK) == DDS_KIND_SUBSCRIBER ) ||\ ((participant_or_subscriber & DDS_ENTITY_KIND_MASK) == DDS_KIND_PARTICIPANT) ) _Pre_satisfies_(((topic & DDS_ENTITY_KIND_MASK) == DDS_KIND_TOPIC ) ||\ @@ -371,7 +371,6 @@ dds_create_reader( } t = topic; } else { - /* TODO If qos is provided, we need to compare with writer qos to determine compatibility */ subscriber = dds__get_builtin_subscriber(participant_or_subscriber); t = dds__get_builtin_topic(subscriber, topic); } @@ -425,6 +424,14 @@ dds_create_reader( goto err_bad_qos; } + /* Additional checks required for built-in topics */ + if (dds_entity_kind(topic) == DDS_KIND_INTERNAL && !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); + goto err_bad_qos; + } + /* 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); @@ -482,6 +489,11 @@ err_tp_lock: (void)dds_delete(subscriber); } err_sub_lock: + if (dds_entity_kind(topic) == DDS_KIND_INTERNAL) { + /* If topic is builtin, then the topic entity is local and should + * be deleted because the application won't. */ + dds_delete(t); + } return reader; } diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index f30b5e4..012435f 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -1401,7 +1401,15 @@ void dds_rhc_unregister_wr time a new WR_IID will be used for the same writer, then we have all the time in the world to scan the cache & clean up and that we don't have to keep it locked all the time (even if we do it - that way now). */ + that way now). + + WR_IID was never reused while the built-in topics weren't getting + generated, but those really require the same instance id for the + same GUID if an instance still exists in some reader for that GUID. + So, if unregistration without locking the RHC is desired, entities + 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; struct rhc_instance *inst; struct ut_hhIter iter; diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 0d85690..bd4774a 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -39,15 +39,9 @@ const ut_avlTreedef_t dds_topictree_def = UT_AVL_TREEDEF_INITIALIZER_INDKEY /* builtin-topic handles */ const dds_entity_t DDS_BUILTIN_TOPIC_DCPSPARTICIPANT = (DDS_KIND_INTERNAL + 1); -const dds_entity_t DDS_BUILTIN_TOPIC_CMPARTICIPANT = (DDS_KIND_INTERNAL + 2); -const dds_entity_t DDS_BUILTIN_TOPIC_DCPSTYPE = (DDS_KIND_INTERNAL + 3); -const dds_entity_t DDS_BUILTIN_TOPIC_DCPSTOPIC = (DDS_KIND_INTERNAL + 4); -const dds_entity_t DDS_BUILTIN_TOPIC_DCPSPUBLICATION = (DDS_KIND_INTERNAL + 5); -const dds_entity_t DDS_BUILTIN_TOPIC_CMPUBLISHER = (DDS_KIND_INTERNAL + 6); -const dds_entity_t DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION = (DDS_KIND_INTERNAL + 7); -const dds_entity_t DDS_BUILTIN_TOPIC_CMSUBSCRIBER = (DDS_KIND_INTERNAL + 8); -const dds_entity_t DDS_BUILTIN_TOPIC_CMDATAWRITER = (DDS_KIND_INTERNAL + 9); -const dds_entity_t DDS_BUILTIN_TOPIC_CMDATAREADER = (DDS_KIND_INTERNAL + 10); +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( diff --git a/src/core/ddsc/tests/builtin_topics.c b/src/core/ddsc/tests/builtin_topics.c index e6b59bc..ff24221 100644 --- a/src/core/ddsc/tests/builtin_topics.c +++ b/src/core/ddsc/tests/builtin_topics.c @@ -14,133 +14,28 @@ #include "ddsc/dds.h" #include "os/os.h" #include "test-common.h" - #include "CUnit/Test.h" +#include "CUnit/Theory.h" static dds_entity_t g_participant = 0; static dds_entity_t g_subscriber = 0; static dds_entity_t g_publisher = 0; +static dds_entity_t g_writer = 0; +static dds_entity_t g_reader = 0; static dds_entity_t g_topic = 0; -#define MAX_SAMPLES 1 +#define MAX_SAMPLES 2 static dds_sample_info_t g_info[MAX_SAMPLES]; -static struct DDS_UserDataQosPolicy g_pol_userdata; -static struct DDS_TopicDataQosPolicy g_pol_topicdata; -static struct DDS_GroupDataQosPolicy g_pol_groupdata; -static struct DDS_DurabilityQosPolicy g_pol_durability; -static struct DDS_HistoryQosPolicy g_pol_history; -static struct DDS_ResourceLimitsQosPolicy g_pol_resource_limits; -static struct DDS_PresentationQosPolicy g_pol_presentation; -static struct DDS_LifespanQosPolicy g_pol_lifespan; -static struct DDS_DeadlineQosPolicy g_pol_deadline; -static struct DDS_LatencyBudgetQosPolicy g_pol_latency_budget; -static struct DDS_OwnershipQosPolicy g_pol_ownership; -static struct DDS_OwnershipStrengthQosPolicy g_pol_ownership_strength; -static struct DDS_LivelinessQosPolicy g_pol_liveliness; -static struct DDS_TimeBasedFilterQosPolicy g_pol_time_based_filter; -static struct DDS_PartitionQosPolicy g_pol_partition; -static struct DDS_ReliabilityQosPolicy g_pol_reliability; -static struct DDS_TransportPriorityQosPolicy g_pol_transport_priority; -static struct DDS_DestinationOrderQosPolicy g_pol_destination_order; -static struct DDS_WriterDataLifecycleQosPolicy g_pol_writer_data_lifecycle; -static struct DDS_ReaderDataLifecycleQosPolicy g_pol_reader_data_lifecycle; -static struct DDS_DurabilityServiceQosPolicy g_pol_durability_service; - -static const char* c_userdata = "user_key"; -static const char* c_topicdata = "topic_key"; -static const char* c_groupdata = "group_key"; -static const char* c_partitions[] = {"Partition1", "Partition2"}; - -static dds_qos_t *g_qos = NULL; - static void qos_init(void) { - g_qos = dds_create_qos(); - CU_ASSERT_PTR_NOT_NULL_FATAL(g_qos); - - g_pol_userdata.value._buffer = dds_alloc(strlen(c_userdata) + 1); - g_pol_userdata.value._length = (uint32_t)strlen(c_userdata) + 1; - g_pol_userdata.value._release = true; - g_pol_userdata.value._maximum = 0; - - g_pol_topicdata.value._buffer = dds_alloc(strlen(c_topicdata) + 1); - g_pol_topicdata.value._length = (uint32_t)strlen(c_topicdata) + 1; - g_pol_topicdata.value._release = true; - g_pol_topicdata.value._maximum = 0; - - g_pol_groupdata.value._buffer = dds_alloc(strlen(c_groupdata) + 1); - g_pol_groupdata.value._length = (uint32_t)strlen(c_groupdata) + 1; - g_pol_groupdata.value._release = true; - g_pol_groupdata.value._maximum = 0; - - g_pol_history.kind = DDS_KEEP_LAST_HISTORY_QOS; - g_pol_history.depth = 1; - - g_pol_resource_limits.max_samples = 1; - g_pol_resource_limits.max_instances = 1; - g_pol_resource_limits.max_samples_per_instance = 1; - - g_pol_presentation.access_scope = DDS_INSTANCE_PRESENTATION_QOS; - g_pol_presentation.coherent_access = true; - g_pol_presentation.ordered_access = true; - - g_pol_lifespan.duration.sec = 10000; - g_pol_lifespan.duration.nanosec = 11000; - - g_pol_deadline.period.sec = 20000; - g_pol_deadline.period.nanosec = 220000; - - g_pol_latency_budget.duration.sec = 30000; - g_pol_latency_budget.duration.nanosec = 33000; - - g_pol_ownership.kind = DDS_EXCLUSIVE_OWNERSHIP_QOS; - - g_pol_ownership_strength.value = 10; - - g_pol_liveliness.kind = DDS_AUTOMATIC_LIVELINESS_QOS; - g_pol_liveliness.lease_duration.sec = 40000; - g_pol_liveliness.lease_duration.nanosec = 44000; - - g_pol_time_based_filter.minimum_separation.sec = 12000; - g_pol_time_based_filter.minimum_separation.nanosec = 55000; - - g_pol_partition.name._buffer = (char**)c_partitions; - g_pol_partition.name._length = 2; - - g_pol_reliability.kind = DDS_RELIABLE_RELIABILITY_QOS; - g_pol_reliability.max_blocking_time.sec = 60000; - g_pol_reliability.max_blocking_time.nanosec = 66000; - - g_pol_transport_priority.value = 42; - - g_pol_destination_order.kind = DDS_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS; - - g_pol_writer_data_lifecycle.autodispose_unregistered_instances = true; - - g_pol_reader_data_lifecycle.autopurge_disposed_samples_delay.sec = 70000; - g_pol_reader_data_lifecycle.autopurge_disposed_samples_delay.nanosec= 77000; - g_pol_reader_data_lifecycle.autopurge_nowriter_samples_delay.sec = 80000; - g_pol_reader_data_lifecycle.autopurge_nowriter_samples_delay.nanosec = 88000; - - g_pol_durability_service.history_depth = 1; - g_pol_durability_service.history_kind = DDS_KEEP_LAST_HISTORY_QOS; - g_pol_durability_service.max_samples = 12; - g_pol_durability_service.max_instances = 3; - g_pol_durability_service.max_samples_per_instance = 4; - g_pol_durability_service.service_cleanup_delay.sec = 90000; - g_pol_durability_service.service_cleanup_delay.nanosec = 99000; } static void qos_fini(void) { - dds_delete_qos(g_qos); - dds_free(g_pol_userdata.value._buffer); - dds_free(g_pol_groupdata.value._buffer); - dds_free(g_pol_topicdata.value._buffer); } static void @@ -151,11 +46,15 @@ setup(void) g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(g_participant > 0); g_topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, "RoundTrip", NULL, NULL); - CU_ASSERT_FATAL(g_topic> 0); + CU_ASSERT_FATAL(g_topic > 0); g_subscriber = dds_create_subscriber(g_participant, NULL, NULL); - CU_ASSERT_FATAL(g_subscriber> 0); + CU_ASSERT_FATAL(g_subscriber > 0); g_publisher = dds_create_publisher(g_participant, NULL, NULL); - CU_ASSERT_FATAL(g_publisher> 0); + CU_ASSERT_FATAL(g_publisher > 0); + g_writer = dds_create_writer(g_publisher, g_topic, NULL, NULL); + CU_ASSERT_FATAL(g_writer > 0); + g_reader = dds_create_reader(g_subscriber, g_topic, NULL, NULL); + CU_ASSERT_FATAL(g_reader > 0); } static void @@ -164,15 +63,6 @@ teardown(void) qos_fini(); dds_delete(g_participant); } -#define T_MILLISECOND 1000000ll -#define T_SECOND (1000 * T_MILLISECOND) - -int64_t from_ddsi_duration (DDS_Duration_t x) -{ - int64_t t; - t = (int64_t)x.sec * T_SECOND + x.nanosec; - return t; -} static void check_default_qos_of_builtin_entity(dds_entity_t entity) @@ -187,61 +77,64 @@ check_default_qos_of_builtin_entity(dds_entity_t entity) dds_durability_kind_t durability_kind; dds_presentation_access_scope_kind_t presentation_access_scope_kind; + bool presentation_coherent_access; + bool presentation_ordered_access; dds_ownership_kind_t ownership_kind; dds_liveliness_kind_t liveliness_kind; dds_reliability_kind_t reliability_kind; dds_destination_order_kind_t destination_order_kind; dds_history_kind_t history_kind; + int32_t history_depth; + int32_t resource_limits_max_samples; + int32_t resource_limits_max_instances; + int32_t resource_limits_max_samples_per_instance; char **partitions; uint32_t plen; dds_qos_t *qos = dds_create_qos(); - CU_ASSERT_PTR_NOT_NULL_FATAL(qos); + CU_ASSERT_FATAL(qos != NULL); ret = dds_get_qos(entity, qos); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_FATAL(ret == DDS_RETCODE_OK); dds_qget_durability(qos, &durability_kind); - dds_qget_presentation(qos, &presentation_access_scope_kind, &g_pol_presentation.coherent_access, &g_pol_presentation.ordered_access); + dds_qget_presentation(qos, &presentation_access_scope_kind, &presentation_coherent_access, &presentation_ordered_access); dds_qget_deadline(qos, &deadline); dds_qget_ownership(qos, &ownership_kind); dds_qget_liveliness(qos, &liveliness_kind, &liveliness_lease_duration); dds_qget_time_based_filter(qos, &minimum_separation); dds_qget_reliability(qos, &reliability_kind, &max_blocking_time); dds_qget_destination_order(qos, &destination_order_kind); - dds_qget_history(qos, &history_kind, &g_pol_history.depth); - dds_qget_resource_limits(qos, &g_pol_resource_limits.max_samples, &g_pol_resource_limits.max_instances, &g_pol_resource_limits.max_samples_per_instance); + dds_qget_history(qos, &history_kind, &history_depth); + dds_qget_resource_limits(qos, &resource_limits_max_samples, &resource_limits_max_instances, &resource_limits_max_samples_per_instance); dds_qget_reader_data_lifecycle(qos, &autopurge_nowriter_samples_delay, &autopurge_disposed_samples_delay); 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) { - CU_ASSERT_EQUAL(plen, 1); - if (plen > 0) { - CU_ASSERT_STRING_EQUAL(partitions[0], "__BUILT-IN PARTITION__"); - } - } else if ((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER) { - CU_ASSERT_EQUAL(durability_kind, DDS_DURABILITY_TRANSIENT_LOCAL); - CU_ASSERT_EQUAL(presentation_access_scope_kind, DDS_PRESENTATION_TOPIC); - CU_ASSERT_EQUAL(g_pol_presentation.coherent_access, false); - CU_ASSERT_EQUAL(g_pol_presentation.ordered_access, false); - CU_ASSERT_EQUAL(deadline, DDS_INFINITY); - CU_ASSERT_EQUAL(ownership_kind, DDS_OWNERSHIP_SHARED); - CU_ASSERT_EQUAL(liveliness_kind, DDS_LIVELINESS_AUTOMATIC); - CU_ASSERT_EQUAL(minimum_separation, 0); - CU_ASSERT_EQUAL(reliability_kind, DDS_RELIABILITY_RELIABLE); - CU_ASSERT_EQUAL(max_blocking_time, DDS_MSECS(100)); - CU_ASSERT_EQUAL(destination_order_kind, DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP); - CU_ASSERT_EQUAL(history_kind, DDS_HISTORY_KEEP_LAST); - CU_ASSERT_EQUAL(g_pol_history.depth, 1); - CU_ASSERT_EQUAL(g_pol_resource_limits.max_instances, DDS_LENGTH_UNLIMITED); - CU_ASSERT_EQUAL(g_pol_resource_limits.max_samples, DDS_LENGTH_UNLIMITED); - CU_ASSERT_EQUAL(g_pol_resource_limits.max_samples_per_instance, DDS_LENGTH_UNLIMITED); - CU_ASSERT_EQUAL(autopurge_nowriter_samples_delay, DDS_INFINITY); - CU_ASSERT_EQUAL(autopurge_disposed_samples_delay, DDS_INFINITY); + CU_ASSERT_FATAL(plen == 1); + CU_ASSERT_STRING_EQUAL_FATAL(partitions[0], "__BUILT-IN PARTITION__"); } else { - CU_FAIL_FATAL("Unsupported entity kind"); + CU_ASSERT_FATAL(durability_kind == DDS_DURABILITY_TRANSIENT_LOCAL); + CU_ASSERT_FATAL(presentation_access_scope_kind == DDS_PRESENTATION_TOPIC); + CU_ASSERT_FATAL(presentation_coherent_access == false); + CU_ASSERT_FATAL(presentation_ordered_access == false); + CU_ASSERT_FATAL(deadline == DDS_INFINITY); + CU_ASSERT_FATAL(ownership_kind == DDS_OWNERSHIP_SHARED); + CU_ASSERT_FATAL(liveliness_kind == DDS_LIVELINESS_AUTOMATIC); + CU_ASSERT_FATAL(minimum_separation == 0); + CU_ASSERT_FATAL(reliability_kind == DDS_RELIABILITY_RELIABLE); + CU_ASSERT_FATAL(max_blocking_time == DDS_MSECS(100)); + CU_ASSERT_FATAL(destination_order_kind == DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP); + CU_ASSERT_FATAL(history_kind == DDS_HISTORY_KEEP_LAST); + CU_ASSERT_FATAL(history_depth == 1); + CU_ASSERT_FATAL(resource_limits_max_instances == DDS_LENGTH_UNLIMITED); + CU_ASSERT_FATAL(resource_limits_max_samples == DDS_LENGTH_UNLIMITED); + CU_ASSERT_FATAL(resource_limits_max_samples_per_instance == DDS_LENGTH_UNLIMITED); + CU_ASSERT_FATAL(autopurge_nowriter_samples_delay == DDS_INFINITY); + CU_ASSERT_FATAL(autopurge_disposed_samples_delay == DDS_INFINITY); } if (plen > 0) { for (uint32_t i = 0; i < plen; i++) { @@ -252,29 +145,6 @@ check_default_qos_of_builtin_entity(dds_entity_t entity) dds_delete_qos(qos); } -static dds_entity_t builtin_topic_handles[10]; - -CU_Test(ddsc_builtin_topics, types_allocation) -{ -#define TEST_ALLOC(type) do { \ - DDS_##type##BuiltinTopicData *data = DDS_##type##BuiltinTopicData__alloc(); \ - CU_ASSERT_PTR_NOT_NULL(data); \ - DDS_##type##BuiltinTopicData_free(data, DDS_FREE_ALL); \ - } while(0) - - TEST_ALLOC(Participant); - TEST_ALLOC(CMParticipant); - TEST_ALLOC(Type); - TEST_ALLOC(Topic); - TEST_ALLOC(Publication); - TEST_ALLOC(CMPublisher); - TEST_ALLOC(Subscription); - TEST_ALLOC(CMSubscriber); - TEST_ALLOC(CMDataWriter); - TEST_ALLOC(CMDataReader); -#undef TEST_ALLOC -} - CU_Test(ddsc_builtin_topics, availability_builtin_topics, .init = setup, .fini = teardown) { dds_entity_t topic; @@ -285,259 +155,101 @@ CU_Test(ddsc_builtin_topics, availability_builtin_topics, .init = setup, .fini = topic = dds_find_topic(g_participant, "DCPSTopic"); CU_ASSERT_FATAL(topic < 0); //TODO CHAM-347: dds_delete(topic); - topic = dds_find_topic(g_participant, "DCPSType"); - CU_ASSERT_FATAL(topic < 0); - //TODO CHAM-347: dds_delete(topic); topic = dds_find_topic(g_participant, "DCPSSubscription"); - CU_ASSERT_FATAL(topic < 0); - //TODO CHAM-347: dds_delete(topic); - topic = dds_find_topic(g_participant, "DCSPPublication"); - CU_ASSERT_FATAL(topic < 0); - //TODO CHAM-347: dds_delete(topic); + CU_ASSERT_FATAL(topic > 0); + dds_delete(topic); + topic = dds_find_topic(g_participant, "DCPSPublication"); + CU_ASSERT_FATAL(topic > 0); + dds_delete(topic); } CU_Test(ddsc_builtin_topics, read_publication_data, .init = setup, .fini = teardown) { dds_entity_t reader; -#if 0 /* disabled pending CHAM-347 */ dds_return_t ret; - DDS_PublicationBuiltinTopicData *data; -#endif + dds_builtintopic_endpoint_t *data; void *samples[MAX_SAMPLES]; - reader = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, NULL, NULL); CU_ASSERT_FATAL(reader > 0); - samples[0] = DDS_PublicationBuiltinTopicData__alloc(); -#if 0 /* disabled pending CHAM-347 */ + samples[0] = NULL; ret = dds_read(reader, samples, g_info, MAX_SAMPLES, MAX_SAMPLES); + data = samples[0]; CU_ASSERT_FATAL(ret > 0); - - data = (DDS_PublicationBuiltinTopicData *)samples; - CU_ASSERT_STRING_EQUAL_FATAL(data->topic_name, "DCPSPublication"); -#endif - - DDS_PublicationBuiltinTopicData_free(samples[0], DDS_FREE_ALL); -} - -CU_Test(ddsc_builtin_topics, create_reader) -{ - dds_entity_t participant; - dds_entity_t t1; - - /* Create a participant */ - participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); - CU_ASSERT_FATAL(participant > 0); - - /* - * The topics are created by the middleware as soon as a participant - * is created. - */ -#define TEST_FIND(p, t) do { \ - t1 = dds_find_topic(p, t); \ - CU_ASSERT(t1 > 0); \ - dds_delete(t1); \ - } while(0); - - /* A builtin-topic proxy is created 'on demand' and should not exist before a reader is created for it */ - TEST_FIND(participant, "DCPSParticipant"); - TEST_FIND(participant, "CMParticipant"); -#undef TEST_FIND - - /* - * TODO CHAM-347: Not all builtin topics are created at the start. - */ -#define TEST_NOTFOUND(p, t) do { \ - t1 = dds_find_topic(p, t); \ - CU_ASSERT(t1 < 0); \ - } while(0); - - /* A builtin-topic proxy is created 'on demand' and should not exist before a reader is created for it */ - TEST_NOTFOUND(participant, "DCPSType"); - TEST_NOTFOUND(participant, "DCPSTopic"); - TEST_NOTFOUND(participant, "DCPSPublication"); - TEST_NOTFOUND(participant, "CMPublisher"); - TEST_NOTFOUND(participant, "DCPSSubscription"); - TEST_NOTFOUND(participant, "CMSubscriber"); - TEST_NOTFOUND(participant, "CMDataWriter"); - TEST_NOTFOUND(participant, "CMDataReader"); -#undef TEST_NOTFOUND - - /* A reader is created by providing a special builtin-topic handle */ - { - dds_entity_t readers[10]; - dds_entity_t builtin_subscriber, s; - - builtin_topic_handles[0] = DDS_BUILTIN_TOPIC_DCPSPARTICIPANT; - builtin_topic_handles[1] = DDS_BUILTIN_TOPIC_CMPARTICIPANT; - builtin_topic_handles[2] = DDS_BUILTIN_TOPIC_DCPSTYPE; - builtin_topic_handles[3] = DDS_BUILTIN_TOPIC_DCPSTOPIC; - builtin_topic_handles[4] = DDS_BUILTIN_TOPIC_DCPSPUBLICATION; - builtin_topic_handles[5] = DDS_BUILTIN_TOPIC_CMPUBLISHER; - builtin_topic_handles[6] = DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION; - builtin_topic_handles[7] = DDS_BUILTIN_TOPIC_CMSUBSCRIBER; - builtin_topic_handles[8] = DDS_BUILTIN_TOPIC_CMDATAWRITER; - builtin_topic_handles[9] = DDS_BUILTIN_TOPIC_CMDATAREADER; - - - for (int i = 0; i < 10; i++) { - readers[i] = dds_create_reader(participant, builtin_topic_handles[i], NULL, NULL); - CU_ASSERT(readers[i]> 0); - - if (i == 0) { - /* Check the parent of reader is a subscriber */ - builtin_subscriber = dds_get_parent(readers[i]); - CU_ASSERT_FATAL(builtin_subscriber > 0); - CU_ASSERT_EQUAL_FATAL(builtin_subscriber & DDS_ENTITY_KIND_MASK, DDS_KIND_SUBSCRIBER); - } else { - /* Check the parent of reader equals parent of first reader */ - s = dds_get_parent(readers[i]); - CU_ASSERT_FATAL(s > 0); - CU_ASSERT_EQUAL_FATAL(s, builtin_subscriber); - //dds_delete(s); - } - } - } - -#define TEST_FOUND(p, t) do { \ - t1 = dds_find_topic(p, t); \ - CU_ASSERT(t1 > 0); \ - if (t1 > 0) { \ - dds_delete(t1); \ - } \ - } while(0); - - /* Builtin-topics proxies should now be created */ - TEST_FOUND(participant, "DCPSParticipant"); - TEST_FOUND(participant, "CMParticipant"); - TEST_FOUND(participant, "DCPSType"); - TEST_FOUND(participant, "DCPSTopic"); - TEST_FOUND(participant, "DCPSPublication"); - TEST_FOUND(participant, "CMPublisher"); - TEST_FOUND(participant, "DCPSSubscription"); - TEST_FOUND(participant, "CMSubscriber"); - TEST_FOUND(participant, "CMDataWriter"); - TEST_FOUND(participant, "CMDataReader"); -#undef TEST_FOUND - - dds_delete(participant); + CU_ASSERT_STRING_EQUAL_FATAL(data->topic_name, "RoundTrip"); + dds_return_loan(reader, samples, ret); } CU_Test(ddsc_builtin_topics, read_subscription_data, .init = setup, .fini = teardown) { dds_entity_t reader; -#if 0 /* not supported yet */ dds_return_t ret; - DDS_SubscriptionBuiltinTopicData *data; -#endif void * samples[MAX_SAMPLES]; + const char *exp[] = { "DCPSSubscription", "RoundTrip" }; + unsigned seen = 0; + dds_qos_t *qos; reader = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL); - CU_ASSERT_FATAL(reader> 0); + CU_ASSERT_FATAL(reader > 0); - samples[0] = DDS_SubscriptionBuiltinTopicData__alloc(); - -#if 0 /* not supported yet */ + samples[0] = NULL; ret = dds_read(reader, samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_FATAL(ret> 0); + CU_ASSERT_FATAL(ret == 2); + qos = dds_create_qos(); + for (int i = 0; i < ret; i++) { + dds_builtintopic_endpoint_t *data = samples[i]; + for (size_t j = 0; j < sizeof (exp) / sizeof (exp[0]); j++) { + if (strcmp (data->topic_name, exp[j]) == 0) { + seen |= 1u << j; + dds_return_t get_qos_ret = dds_get_qos(j == 0 ? reader : g_reader, qos); + CU_ASSERT_FATAL(get_qos_ret == DDS_RETCODE_OK); + const bool eq = dds_qos_equal(qos, data->qos); + CU_ASSERT_FATAL(eq); + } + } + } + CU_ASSERT_FATAL(seen == 3); + dds_delete_qos(qos); - data = (DDS_SubscriptionBuiltinTopicData *)samples; - CU_ASSERT_STRING_EQUAL_FATAL(data->topic_name, "DCPSSubscription"); -#endif - - DDS_SubscriptionBuiltinTopicData_free(samples[0], DDS_FREE_ALL); + dds_return_loan(reader, samples, ret); } CU_Test(ddsc_builtin_topics, read_participant_data, .init = setup, .fini = teardown) { dds_entity_t reader; dds_return_t ret; + //dds_builtintopic_participant_t *data; void * samples[MAX_SAMPLES]; reader = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSPARTICIPANT, NULL, NULL); CU_ASSERT_FATAL(reader > 0); - samples[0] = DDS_ParticipantBuiltinTopicData__alloc(); - + samples[0] = NULL; ret = dds_read(reader, samples, g_info, MAX_SAMPLES, MAX_SAMPLES); CU_ASSERT_FATAL(ret > 0); -#if 0 - { - DDS_ParticipantBuiltinTopicData *data = (DDS_ParticipantBuiltinTopicData*)samples[0]; - } -#endif - - DDS_ParticipantBuiltinTopicData_free(samples[0], DDS_FREE_ALL); -} - -CU_Test(ddsc_builtin_topics, read_cmparticipant_data, .init = setup, .fini = teardown) -{ - dds_entity_t reader; - dds_return_t ret; - void * samples[MAX_SAMPLES]; - - reader = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_CMPARTICIPANT, NULL, NULL); - CU_ASSERT_FATAL(reader > 0); - - samples[0] = DDS_CMParticipantBuiltinTopicData__alloc(); - - ret = dds_read(reader, samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_FATAL(ret > 0); -#if 0 - { - DDS_CMParticipantBuiltinTopicData *data = (DDS_CMParticipantBuiltinTopicData*)samples[0]; - } -#endif - - DDS_CMParticipantBuiltinTopicData_free(samples[0], DDS_FREE_ALL); + dds_return_loan(reader, samples, ret); } CU_Test(ddsc_builtin_topics, read_topic_data, .init = setup, .fini = teardown) { - dds_entity_t reader; #if 0 /* disabled pending CHAM-347 */ + dds_entity_t reader; dds_return_t ret; DDS_TopicBuiltinTopicData *data; -#endif void * samples[MAX_SAMPLES]; - reader = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSTOPIC, NULL, NULL); CU_ASSERT_FATAL(reader > 0); - samples[0] = DDS_TopicBuiltinTopicData__alloc(); -#if 0 /* disabled pending CHAM-347 */ - ret = dds_read(reader, samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_FATAL(ret> 0); - - data = (DDS_TopicBuiltinTopicData *)samples; - CU_ASSERT_STRING_EQUAL_FATAL(data->name, "DCPSSubscription"); -#endif - DDS_ParticipantBuiltinTopicData_free(samples[0], DDS_FREE_ALL); -} - -CU_Test(ddsc_builtin_topics, read_type_data, .init = setup, .fini = teardown) -{ - dds_entity_t reader; -#if 0 /* disabled pending CHAM-347 */ - dds_return_t ret; - DDS_TypeBuiltinTopicData *data; -#endif - void * samples[MAX_SAMPLES]; - - reader = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSTYPE, NULL, NULL); - CU_ASSERT_FATAL(reader > 0); - - samples[0] = DDS_TypeBuiltinTopicData__alloc(); -#if 0 /* disabled pending CHAM-347 */ + samples[0] = NULL; ret = dds_read(reader, samples, g_info, MAX_SAMPLES, MAX_SAMPLES); CU_ASSERT_FATAL(ret > 0); - data = (DDS_TypeBuiltinTopicData *)samples; - CU_ASSERT_STRING_EQUAL_FATAL(data->name, "DCPSType"); + data = (DDS_TopicBuiltinTopicData *)samples; + CU_ASSERT_STRING_EQUAL_FATAL(data->name, "DCPSSubscription"); + dds_return_loan(reader, samples, ret); #endif - DDS_TypeBuiltinTopicData_free(samples[0], DDS_FREE_ALL); } CU_Test(ddsc_builtin_topics, same_subscriber, .init = setup, .fini = teardown) @@ -551,11 +263,10 @@ CU_Test(ddsc_builtin_topics, same_subscriber, .init = setup, .fini = teardown) dds_entity_t participant_rdr; dds_entity_t participant_subscriber; +#if 0 dds_entity_t topic_rdr; dds_entity_t topic_subscriber; - - dds_entity_t type_rdr; - dds_entity_t type_subscriber; +#endif subscription_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL); CU_ASSERT_FATAL(subscription_rdr > 0); @@ -567,28 +278,23 @@ CU_Test(ddsc_builtin_topics, same_subscriber, .init = setup, .fini = teardown) publication_subscriber = dds_get_parent(publication_rdr); CU_ASSERT_FATAL(publication_subscriber > 0); - CU_ASSERT_EQUAL_FATAL(subscription_subscriber, publication_subscriber); + CU_ASSERT_FATAL(subscription_subscriber == publication_subscriber); participant_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSPARTICIPANT, NULL, NULL); CU_ASSERT_FATAL(participant_rdr > 0); participant_subscriber = dds_get_parent(participant_rdr); CU_ASSERT_FATAL(participant_subscriber > 0); - CU_ASSERT_EQUAL_FATAL(publication_subscriber, participant_subscriber); + CU_ASSERT_FATAL(publication_subscriber == participant_subscriber); +#if 0 topic_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSTOPIC, NULL, NULL); CU_ASSERT_FATAL(topic_rdr > 0); topic_subscriber = dds_get_parent(topic_rdr); CU_ASSERT_FATAL(topic_subscriber > 0); - CU_ASSERT_EQUAL_FATAL(participant_subscriber, topic_subscriber); - - type_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSTYPE, NULL, NULL); - CU_ASSERT_FATAL(type_rdr > 0); - type_subscriber = dds_get_parent(type_rdr); - CU_ASSERT_FATAL(type_subscriber > 0); - - CU_ASSERT_EQUAL_FATAL(topic_subscriber, type_subscriber); + CU_ASSERT_FATAL(participant_subscriber == topic_subscriber); +#endif } CU_Test(ddsc_builtin_topics, builtin_qos, .init = setup, .fini = teardown) @@ -604,240 +310,3 @@ CU_Test(ddsc_builtin_topics, builtin_qos, .init = setup, .fini = teardown) CU_ASSERT_FATAL(dds_sub_subscriber > 0); check_default_qos_of_builtin_entity(dds_sub_subscriber); } - -CU_Test(ddsc_builtin_topics, datareader_qos, .init = setup, .fini = teardown) -{ - dds_entity_t rdr; - dds_entity_t subscription_rdr; - void * subscription_samples[MAX_SAMPLES]; -#if 0 /* disabled pending CHAM-347 */ - dds_return_t ret; - DDS_SubscriptionBuiltinTopicData *subscription_data; -#endif - - // Set some qos' which differ from the default - dds_qset_durability(g_qos, (dds_durability_kind_t)g_pol_durability.kind); - dds_qset_deadline(g_qos, from_ddsi_duration(g_pol_deadline.period)); - dds_qset_latency_budget(g_qos, from_ddsi_duration(g_pol_latency_budget.duration)); - dds_qset_liveliness(g_qos, (dds_liveliness_kind_t)g_pol_liveliness.kind, from_ddsi_duration(g_pol_liveliness.lease_duration)); - dds_qset_reliability(g_qos, (dds_reliability_kind_t)g_pol_reliability.kind, from_ddsi_duration(g_pol_reliability.max_blocking_time)); - dds_qset_ownership(g_qos, (dds_ownership_kind_t)g_pol_ownership.kind); - dds_qset_destination_order(g_qos, (dds_destination_order_kind_t)g_pol_destination_order.kind); - dds_qset_userdata(g_qos, g_pol_userdata.value._buffer, g_pol_userdata.value._length); - dds_qset_time_based_filter(g_qos, from_ddsi_duration(g_pol_time_based_filter.minimum_separation)); - dds_qset_presentation(g_qos, (dds_presentation_access_scope_kind_t)g_pol_presentation.access_scope, g_pol_presentation.coherent_access, g_pol_presentation.ordered_access); - dds_qset_partition(g_qos, g_pol_partition.name._length, c_partitions); - dds_qset_topicdata(g_qos, g_pol_topicdata.value._buffer, g_pol_topicdata.value._length); - dds_qset_groupdata(g_qos, g_pol_groupdata.value._buffer, g_pol_groupdata.value._length); - - rdr = dds_create_reader(g_subscriber, g_topic, g_qos, NULL); - CU_ASSERT_FATAL(rdr > 0); - - subscription_samples[0] = DDS_SubscriptionBuiltinTopicData__alloc(); - - subscription_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL); - CU_ASSERT_FATAL(subscription_rdr > 0); -#if 0 /* disabled pending CHAM-347 */ - ret = dds_read(subscription_rdr, subscription_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_FATAL(ret > 0); - - // Check the QOS settings of the 'remote' qos' - subscription_data = (DDS_SubscriptionBuiltinTopicData *)subscription_samples[0]; - - CU_ASSERT_STRING_EQUAL_FATAL(subscription_data->topic_name, "RoundTrip"); - CU_ASSERT_STRING_EQUAL_FATAL(subscription_data->type_name, "RoundTripModule::DataType"); - CU_ASSERT_EQUAL_FATAL(subscription_data->durability.kind, g_pol_durability.kind); - CU_ASSERT_EQUAL_FATAL(subscription_data->deadline.period.sec, g_pol_deadline.period.sec); - CU_ASSERT_EQUAL_FATAL(subscription_data->deadline.period.nanosec, g_pol_deadline.period.nanosec); - CU_ASSERT_EQUAL_FATAL(subscription_data->latency_budget.duration.sec, g_pol_latency_budget.duration.sec); - CU_ASSERT_EQUAL_FATAL(subscription_data->latency_budget.duration.nanosec, g_pol_latency_budget.duration.nanosec); - CU_ASSERT_EQUAL_FATAL(subscription_data->liveliness.kind, g_pol_liveliness.kind); - CU_ASSERT_EQUAL_FATAL(subscription_data->liveliness.lease_duration.sec, g_pol_liveliness.lease_duration.sec); - CU_ASSERT_EQUAL_FATAL(subscription_data->liveliness.lease_duration.nanosec, g_pol_liveliness.lease_duration.nanosec); - CU_ASSERT_EQUAL_FATAL(subscription_data->reliability.kind, g_pol_reliability.kind); - CU_ASSERT_EQUAL_FATAL(subscription_data->reliability.max_blocking_time.sec, g_pol_reliability.max_blocking_time.sec); - CU_ASSERT_EQUAL_FATAL(subscription_data->reliability.max_blocking_time.nanosec, g_pol_reliability.max_blocking_time.nanosec); - CU_ASSERT_EQUAL_FATAL(subscription_data->ownership.kind, g_pol_ownership.kind); - CU_ASSERT_EQUAL_FATAL(subscription_data->destination_order.kind, g_pol_destination_order.kind); - CU_ASSERT_EQUAL_FATAL(subscription_data->user_data.value._buffer, g_pol_userdata.value._buffer); - CU_ASSERT_EQUAL_FATAL(subscription_data->user_data.value._length, g_pol_userdata.value._length); - CU_ASSERT_EQUAL_FATAL(subscription_data->time_based_filter.minimum_separation.sec, g_pol_time_based_filter.minimum_separation.sec); - CU_ASSERT_EQUAL_FATAL(subscription_data->time_based_filter.minimum_separation.nanosec, g_pol_time_based_filter.minimum_separation.nanosec); - CU_ASSERT_EQUAL_FATAL(subscription_data->presentation.access_scope, g_pol_presentation.access_scope); - CU_ASSERT_EQUAL_FATAL(subscription_data->presentation.coherent_access, g_pol_presentation.coherent_access); - CU_ASSERT_EQUAL_FATAL(subscription_data->presentation.ordered_access, g_pol_presentation.ordered_access); - - CU_ASSERT_EQUAL_FATAL(subscription_data->partition.name._length, g_pol_partition.name._length); - for (uint32_t i = 0; i < subscription_data->partition.name._length; ++i) - { - CU_ASSERT_STRING_EQUAL_FATAL(subscription_data->partition.name._buffer[i], c_partitions[i]); - } - - CU_ASSERT_STRING_EQUAL_FATAL(subscription_data->topic_data.value._buffer, g_pol_topicdata.value._buffer); - CU_ASSERT_EQUAL_FATAL(subscription_data->topic_data.value._length, g_pol_topicdata.value._length); - CU_ASSERT_STRING_EQUAL_FATAL(subscription_data->group_data.value._buffer, g_pol_groupdata.value._buffer); - CU_ASSERT_EQUAL_FATAL(subscription_data->group_data.value._length, g_pol_groupdata.value._length); -#endif - DDS_SubscriptionBuiltinTopicData_free(subscription_samples[0], DDS_FREE_ALL); -} - -CU_Test(ddsc_builtin_topics, datawriter_qos, .init = setup, .fini = teardown) -{ - dds_entity_t wrtr; - dds_entity_t publication_rdr; -#if 0 /* disabled pending CHAM-347 */ - dds_return_t ret; - DDS_PublicationBuiltinTopicData *publication_data; -#endif - void * publication_samples[MAX_SAMPLES]; - - - dds_qset_durability(g_qos, (dds_durability_kind_t)g_pol_durability.kind); - dds_qset_deadline(g_qos, from_ddsi_duration(g_pol_deadline.period)); - dds_qset_latency_budget(g_qos, from_ddsi_duration(g_pol_latency_budget.duration)); - dds_qset_liveliness(g_qos, (dds_liveliness_kind_t)g_pol_liveliness.kind, from_ddsi_duration(g_pol_liveliness.lease_duration)); - dds_qset_reliability(g_qos, (dds_reliability_kind_t)g_pol_reliability.kind, from_ddsi_duration(g_pol_reliability.max_blocking_time)); - dds_qset_lifespan(g_qos, from_ddsi_duration(g_pol_lifespan.duration)); - dds_qset_destination_order(g_qos, (dds_destination_order_kind_t)g_pol_destination_order.kind); - dds_qset_userdata(g_qos, g_pol_userdata.value._buffer, g_pol_userdata.value._length); - dds_qset_ownership(g_qos, (dds_ownership_kind_t)g_pol_ownership.kind); - dds_qset_ownership_strength(g_qos, g_pol_ownership_strength.value); - dds_qset_presentation(g_qos, (dds_presentation_access_scope_kind_t)g_pol_presentation.access_scope, g_pol_presentation.coherent_access, g_pol_presentation.ordered_access); - dds_qset_partition(g_qos, g_pol_partition.name._length, c_partitions); - dds_qset_topicdata(g_qos, g_pol_topicdata.value._buffer, g_pol_topicdata.value._length); - - wrtr = dds_create_writer(g_publisher, g_topic, g_qos, NULL); - CU_ASSERT_FATAL(wrtr > 0); - - publication_samples[0] = DDS_PublicationBuiltinTopicData__alloc(); - - publication_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, NULL, NULL); - CU_ASSERT_FATAL(publication_rdr > 0); - -#if 0 /* disabled pending CHAM-347 */ - ret = dds_read(publication_rdr, publication_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_FATAL(ret> 0); - - // Check the QOS settings of the 'remote' qos' - publication_data = (DDS_PublicationBuiltinTopicData *)publication_samples[0]; - - CU_ASSERT_STRING_EQUAL_FATAL(publication_data->topic_name, "RoundTrip"); - CU_ASSERT_STRING_EQUAL_FATAL(publication_data->type_name, "RoundTripModule::DataType"); - CU_ASSERT_EQUAL_FATAL(publication_data->durability.kind, g_pol_durability.kind); - CU_ASSERT_EQUAL_FATAL(publication_data->deadline.period.sec, g_pol_deadline.period.sec); - CU_ASSERT_EQUAL_FATAL(publication_data->deadline.period.nanosec, g_pol_deadline.period.nanosec); - CU_ASSERT_EQUAL_FATAL(publication_data->latency_budget.duration.sec, g_pol_latency_budget.duration.sec); - CU_ASSERT_EQUAL_FATAL(publication_data->latency_budget.duration.nanosec, g_pol_latency_budget.duration.nanosec); - CU_ASSERT_EQUAL_FATAL(publication_data->liveliness.kind, g_pol_liveliness.kind); - CU_ASSERT_EQUAL_FATAL(publication_data->liveliness.lease_duration.sec, g_pol_liveliness.lease_duration.sec); - CU_ASSERT_EQUAL_FATAL(publication_data->liveliness.lease_duration.nanosec, g_pol_liveliness.lease_duration.nanosec); - CU_ASSERT_EQUAL_FATAL(publication_data->reliability.kind, g_pol_reliability.kind); - CU_ASSERT_EQUAL_FATAL(publication_data->reliability.max_blocking_time.sec, g_pol_reliability.max_blocking_time.sec); - CU_ASSERT_EQUAL_FATAL(publication_data->reliability.max_blocking_time.nanosec, g_pol_reliability.max_blocking_time.nanosec); - CU_ASSERT_EQUAL_FATAL(publication_data->lifespan.duration.sec, g_pol_lifespan.duration.sec); - CU_ASSERT_EQUAL_FATAL(publication_data->lifespan.duration.nanosec, g_pol_lifespan.duration.nanosec); - CU_ASSERT_EQUAL_FATAL(publication_data->destination_order.kind, g_pol_destination_order.kind); - CU_ASSERT_EQUAL_FATAL(publication_data->user_data.value._buffer, g_pol_userdata.value._buffer); - CU_ASSERT_EQUAL_FATAL(publication_data->user_data.value._length, g_pol_userdata.value._length); - CU_ASSERT_EQUAL_FATAL(publication_data->ownership.kind, g_pol_ownership.kind); - CU_ASSERT_EQUAL_FATAL(publication_data->ownership_strength.value, g_pol_ownership_strength.value); - CU_ASSERT_EQUAL_FATAL(publication_data->presentation.access_scope, g_pol_presentation.access_scope); - CU_ASSERT_EQUAL_FATAL(publication_data->presentation.coherent_access, g_pol_presentation.coherent_access); - CU_ASSERT_EQUAL_FATAL(publication_data->presentation.ordered_access, g_pol_presentation.ordered_access); - - CU_ASSERT_EQUAL_FATAL(publication_data->partition.name._length, g_pol_partition.name._length); - for (uint32_t i = 0; i < publication_data->partition.name._length; ++i) - { - CU_ASSERT_STRING_EQUAL_FATAL(publication_data->partition.name._buffer[i], c_partitions[i]); - } - - CU_ASSERT_STRING_EQUAL_FATAL(publication_data->topic_data.value._buffer, g_pol_topicdata.value._buffer); - CU_ASSERT_EQUAL_FATAL(publication_data->topic_data.value._length, g_pol_topicdata.value._length); - CU_ASSERT_STRING_EQUAL_FATAL(publication_data->group_data.value._buffer, g_pol_groupdata.value._buffer); - CU_ASSERT_EQUAL_FATAL(publication_data->group_data.value._length, g_pol_groupdata.value._length); -#endif - DDS_PublicationBuiltinTopicData_free(publication_samples[0], DDS_FREE_ALL); -} - -CU_Test(ddsc_builtin_topics, topic_qos, .init = setup, .fini = teardown) -{ - dds_entity_t tpc; - dds_entity_t topic_rdr; - -#if 0 /* disabled pending CHAM-347 */ - dds_return_t ret; - DDS_TopicBuiltinTopicData *topic_data; -#endif - - void * topic_samples[MAX_SAMPLES]; - - dds_qset_durability(g_qos, (dds_durability_kind_t)g_pol_durability.kind); - dds_qset_durability_service(g_qos, - from_ddsi_duration(g_pol_durability_service.service_cleanup_delay), - (dds_history_kind_t)g_pol_durability_service.history_kind, - g_pol_durability_service.history_depth, - g_pol_durability_service.max_samples, - g_pol_durability_service.max_instances, - g_pol_durability_service.max_samples_per_instance); - dds_qset_deadline(g_qos, from_ddsi_duration(g_pol_deadline.period)); - dds_qset_latency_budget(g_qos, from_ddsi_duration(g_pol_latency_budget.duration)); - dds_qset_liveliness(g_qos, (dds_liveliness_kind_t)g_pol_liveliness.kind, from_ddsi_duration(g_pol_liveliness.lease_duration)); - dds_qset_reliability(g_qos, (dds_reliability_kind_t)g_pol_reliability.kind, from_ddsi_duration(g_pol_reliability.max_blocking_time)); - dds_qset_transport_priority(g_qos, g_pol_transport_priority.value); - dds_qset_lifespan(g_qos, from_ddsi_duration(g_pol_lifespan.duration)); - dds_qset_destination_order(g_qos, (dds_destination_order_kind_t)g_pol_destination_order.kind); - dds_qset_history(g_qos, (dds_history_kind_t)g_pol_history.kind, g_pol_history.depth); - dds_qset_resource_limits(g_qos, g_pol_resource_limits.max_samples, g_pol_resource_limits.max_instances, - g_pol_resource_limits.max_samples_per_instance); - dds_qset_ownership(g_qos, (dds_ownership_kind_t)g_pol_ownership.kind); - dds_qset_topicdata(g_qos, g_pol_topicdata.value._buffer, g_pol_topicdata.value._length); - - - tpc = dds_create_topic(g_participant, &Space_Type1_desc, "SpaceType1", g_qos, NULL); - CU_ASSERT_FATAL(tpc > 0); - - topic_samples[0] = DDS_PublicationBuiltinTopicData__alloc(); - - topic_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSTOPIC, NULL, NULL); - CU_ASSERT_FATAL(topic_rdr > 0 ); -#if 0 /* disabled pending CHAM-347 */ - ret = dds_read(topic_rdr, topic_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_FATAL(ret > 0); - - topic_data = (DDS_TopicBuiltinTopicData *)topic_samples[0]; - - CU_ASSERT_STRING_EQUAL_FATAL(topic_data->name, "SpaceType1"); - CU_ASSERT_STRING_EQUAL_FATAL(topic_data->type_name, "RoundTripModule::DataType"); - CU_ASSERT_EQUAL_FATAL(topic_data->durability.kind, g_pol_durability.kind); - CU_ASSERT_EQUAL_FATAL(topic_data->durability_service.service_cleanup_delay.sec, g_pol_durability_service.service_cleanup_delay.sec); - CU_ASSERT_EQUAL(topic_data->durability_service.service_cleanup_delay.nanosec, g_pol_durability_service.service_cleanup_delay.nanosec); - CU_ASSERT_EQUAL_FATAL(topic_data->durability_service.history_kind, g_pol_durability_service.history_kind); - CU_ASSERT_EQUAL_FATAL(topic_data->durability_service.history_depth, g_pol_durability_service.history_depth); - CU_ASSERT_EQUAL_FATAL(topic_data->durability_service.max_samples, g_pol_durability_service.max_samples); - CU_ASSERT_EQUAL_FATAL(topic_data->durability_service.max_instances, g_pol_durability_service.max_instances); - CU_ASSERT_EQUAL_FATAL(topic_data->durability_service.max_samples_per_instance, g_pol_durability_service.max_samples_per_instance); - CU_ASSERT_EQUAL_FATAL(topic_data->deadline.period.sec, g_pol_deadline.period.sec); - CU_ASSERT_EQUAL_FATAL(topic_data->deadline.period.nanosec, g_pol_deadline.period.nanosec); - CU_ASSERT_EQUAL_FATAL(topic_data->latency_budget.duration.sec, g_pol_latency_budget.duration.sec); - CU_ASSERT_EQUAL_FATAL(topic_data->latency_budget.duration.nanosec, g_pol_latency_budget.duration.nanosec); - CU_ASSERT_EQUAL_FATAL(topic_data->liveliness.kind, g_pol_liveliness.kind); - CU_ASSERT_EQUAL_FATAL(topic_data->liveliness.lease_duration.sec, g_pol_liveliness.lease_duration.sec); - CU_ASSERT_EQUAL_FATAL(topic_data->liveliness.lease_duration.nanosec, g_pol_liveliness.lease_duration.nanosec); - CU_ASSERT_EQUAL_FATAL(topic_data->reliability.kind, g_pol_reliability.kind); - CU_ASSERT_EQUAL_FATAL(topic_data->reliability.max_blocking_time.sec, g_pol_reliability.max_blocking_time.sec); - CU_ASSERT_EQUAL_FATAL(topic_data->reliability.max_blocking_time.nanosec, g_pol_reliability.max_blocking_time.nanosec); - CU_ASSERT_EQUAL_FATAL(topic_data->transport_priority.value, g_pol_transport_priority.value); - CU_ASSERT_EQUAL_FATAL(topic_data->lifespan.duration.sec, g_pol_lifespan.duration.sec); - CU_ASSERT_EQUAL_FATAL(topic_data->lifespan.duration.nanosec, g_pol_lifespan.duration.nanosec); - CU_ASSERT_EQUAL_FATAL(topic_data->destination_order.kind, g_pol_destination_order.kind); - CU_ASSERT_EQUAL_FATAL(topic_data->history.kind, g_pol_history.kind); - CU_ASSERT_EQUAL_FATAL(topic_data->history.depth, g_pol_history.depth); - CU_ASSERT_EQUAL_FATAL(topic_data->resource_limits.max_samples, g_pol_resource_limits.max_samples); - CU_ASSERT_EQUAL_FATAL(topic_data->resource_limits.max_instances, g_pol_resource_limits.max_instances); - CU_ASSERT_EQUAL_FATAL(topic_data->resource_limits.max_samples_per_instance, g_pol_resource_limits.max_samples_per_instance); - CU_ASSERT_EQUAL_FATAL(topic_data->ownership.kind, g_pol_ownership.kind); - CU_ASSERT_STRING_EQUAL_FATAL(topic_data->topic_data.value._buffer, g_pol_topicdata.value._buffer); - CU_ASSERT_EQUAL_FATAL(topic_data->topic_data.value._length, g_pol_topicdata.value._length); -#endif - DDS_TopicBuiltinTopicData_free(topic_samples[0], DDS_FREE_ALL); -} diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index cf0f7b1..75d3af7 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -31,7 +31,6 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" q_bitset_inlines.c q_bswap.c q_bswap_inlines.c - q_builtin_topic.c q_config.c q_ddsi_discovery.c q_debmon.c @@ -88,7 +87,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/ddsi" q_bitset_template.h q_bswap.h q_bswap_template.h - q_builtin_topic.h q_config.h q_ddsi_discovery.h q_debmon.h diff --git a/src/core/ddsi/include/ddsi/q_builtin_topic.h b/src/core/ddsi/include/ddsi/q_builtin_topic.h deleted file mode 100644 index 47175d2..0000000 --- a/src/core/ddsi/include/ddsi/q_builtin_topic.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef Q_BUILTIN_TOPIC_H -#define Q_BUILTIN_TOPIC_H - -#include "ddsi/q_time.h" - -#include "dds_builtinTopics.h" - -struct entity_common; -struct nn_plist; - -/* Functions called at proxy entity creation/deletion time, so they - can do whatever is necessary to get the builtin topics function - correctly. - - These probably should return an error code, but I don't quite know - how to handle it yet and this way we have Coverity on our side. - Implementation is outside the common core. - - These may assume the proxy entities are stable, without parallel QoS - changes. */ - -void -propagate_builtin_topic_participant( - _In_ const struct entity_common *proxypp, - _In_ const nn_plist_t *plist, - _In_ nn_wctime_t timestamp, - _In_ int alive); - -void -propagate_builtin_topic_cmparticipant( - _In_ const struct entity_common *proxypp, - _In_ const nn_plist_t *plist, - _In_ nn_wctime_t timestamp, - _In_ int alive); -#if 0 -void dispose_builtin_topic_proxy_participant (const struct proxy_participant *proxypp, nn_wctime_t timestamp, int isimplicit); -void write_builtin_topic_proxy_writer (const struct proxy_writer *pwr, nn_wctime_t timestamp); -void dispose_builtin_topic_proxy_writer (const struct proxy_writer *pwr, nn_wctime_t timestamp, int isimplicit); -void write_builtin_topic_proxy_reader (const struct proxy_reader *prd, nn_wctime_t timestamp); -void dispose_builtin_topic_proxy_reader (const struct proxy_reader *prd, nn_wctime_t timestamp, int isimplicit); -void write_builtin_topic_proxy_group (const struct proxy_group *pgroup, nn_wctime_t timestamp); -void dispose_builtin_topic_proxy_group (const struct proxy_group *pgroup, nn_wctime_t timestamp, int isimplicit); - -void write_builtin_topic_proxy_topic (const struct nn_plist *datap, nn_wctime_t timestamp); -#endif - - -/* - * Let the layer on top of DDSI handle the received builtin data when it wants to. - */ -extern void -forward_builtin_participant( - _In_ DDS_ParticipantBuiltinTopicData *data, - _In_ nn_wctime_t timestamp, - _In_ int alive); - -extern void -forward_builtin_cmparticipant( - _In_ DDS_CMParticipantBuiltinTopicData *data, - _In_ nn_wctime_t timestamp, - _In_ int alive); - - -#endif diff --git a/src/core/ddsi/include/ddsi/q_config.h b/src/core/ddsi/include/ddsi/q_config.h index 30989b1..5c4f8d5 100644 --- a/src/core/ddsi/include/ddsi/q_config.h +++ b/src/core/ddsi/include/ddsi/q_config.h @@ -22,6 +22,7 @@ #include "ddsi/q_xqos.h" #include "ddsi/ddsi_tran.h" #include "ddsi/q_feature_check.h" +#include "ddsi/ddsi_serdata_builtin.h" #include "ddsi/ddsi_rhc_plugin.h" #if defined (__cplusplus) @@ -411,6 +412,7 @@ struct ddsi_plugin { int (*init_fn) (void); void (*fini_fn) (void); + void (*builtin_write) (enum ddsi_sertopic_builtin_type type, const nn_guid_t *guid, nn_wctime_t timestamp, bool alive); /* Read cache */ struct ddsi_rhc_plugin rhc_plugin; diff --git a/src/core/ddsi/include/ddsi/q_globals.h b/src/core/ddsi/include/ddsi/q_globals.h index 7c19652..c91a029 100644 --- a/src/core/ddsi/include/ddsi/q_globals.h +++ b/src/core/ddsi/include/ddsi/q_globals.h @@ -281,6 +281,11 @@ struct q_globals { struct ddsi_sertopic *plist_topic; /* used for all discovery data */ struct ddsi_sertopic *rawcdr_topic; /* used for participant message data */ + /* Sertopics for built-in topics -- FIXME: these really have little to do with topics, but everything with topic types, in other words, they are the type supports in DDS ... so a bit of refactoring is required */ + struct ddsi_sertopic *builtin_participant_topic; + struct ddsi_sertopic *builtin_reader_topic; + struct ddsi_sertopic *builtin_writer_topic; + /* Network ID needed by v_groupWrite -- FIXME: might as well pass it to the receive thread instead of making it global (and that would remove the need to include kernelModule.h) */ diff --git a/src/core/ddsi/src/q_builtin_topic.c b/src/core/ddsi/src/q_builtin_topic.c deleted file mode 100644 index 03119d8..0000000 --- a/src/core/ddsi/src/q_builtin_topic.c +++ /dev/null @@ -1,183 +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 "ddsi/q_misc.h" -#include "ddsi/q_config.h" -#include "ddsi/q_entity.h" -#include "ddsi/q_builtin_topic.h" - -#include "dds_builtinTopics.h" - -static void generate_user_data (_Out_ DDS_UserDataQosPolicy *a, _In_ const nn_xqos_t *xqos) -{ - if (!(xqos->present & QP_USER_DATA) || (xqos->user_data.length == 0)) - { - a->value._maximum = 0; - a->value._length = 0; - a->value._buffer = NULL; - a->value._release = false; - } else { - a->value._maximum = xqos->user_data.length; - a->value._length = xqos->user_data.length; - a->value._buffer = xqos->user_data.value; - a->value._release = false; - } -} - -static void -generate_product_data( - _Out_ DDS_ProductDataQosPolicy *a, - _In_ const struct entity_common *participant, - _In_ const nn_plist_t *plist) -{ - /* replicate format generated in v_builtinCreateCMParticipantInfo() */ - static const char product_tag[] = "Product"; - static const char exec_name_tag[] = "ExecName"; - static const char participant_name_tag[] = "ParticipantName"; - static const char process_id_tag[] = "PID"; - static const char node_name_tag[] = "NodeName"; - static const char federation_id_tag[] = "FederationId"; - static const char vendor_id_tag[] = "VendorId"; - static const char service_type_tag[] = "ServiceType"; - const size_t cdata_overhead = 12; /* */ - const size_t tag_overhead = 5; /* <> and */ - char pidstr[11]; /* unsigned 32-bits, so max < 5e9, or 10 chars + terminator */ - char federationidstr[20]; /* max 2 * unsigned 32-bits hex + separator, terminator */ - char vendoridstr[22]; /* max 2 * unsigned 32-bits + seperator, terminator */ - char servicetypestr[11]; /* unsigned 32-bits */ - unsigned servicetype; - size_t len = 1 + 2*(sizeof(product_tag)-1) + tag_overhead; - - if (plist->present & PP_PRISMTECH_EXEC_NAME) - len += 2*(sizeof(exec_name_tag)-1) + cdata_overhead + tag_overhead + strlen(plist->exec_name); - if (plist->present & PP_ENTITY_NAME) - len += 2*(sizeof(participant_name_tag)-1) + cdata_overhead + tag_overhead + strlen(plist->entity_name); - if (plist->present & PP_PRISMTECH_PROCESS_ID) - { - int n = snprintf (pidstr, sizeof (pidstr), "%u", plist->process_id); - assert (n > 0 && (size_t) n < sizeof (pidstr)); - len += 2*(sizeof(process_id_tag)-1) + tag_overhead + (size_t) n; - } - if (plist->present & PP_PRISMTECH_NODE_NAME) - len += 2*(sizeof(node_name_tag)-1) + cdata_overhead + tag_overhead + strlen(plist->node_name); - - { - int n = snprintf (vendoridstr, sizeof (vendoridstr), "%u.%u", plist->vendorid.id[0], plist->vendorid.id[1]); - assert (n > 0 && (size_t) n < sizeof (vendoridstr)); - len += 2*(sizeof(vendor_id_tag)-1) + tag_overhead + (size_t) n; - } - - { - int n; - if (vendor_is_opensplice (plist->vendorid)) - n = snprintf (federationidstr, sizeof (federationidstr), "%x", participant->guid.prefix.u[0]); - else - n = snprintf (federationidstr, sizeof (federationidstr), "%x:%x", participant->guid.prefix.u[0], participant->guid.prefix.u[1]); - assert (n > 0 && (size_t) n < sizeof (federationidstr)); - len += 2*(sizeof(federation_id_tag)-1) + tag_overhead + (size_t) n; - } - - if (plist->present & PP_PRISMTECH_SERVICE_TYPE) - servicetype = plist->service_type; - else - servicetype = 0; - - { - int n = snprintf (servicetypestr, sizeof (servicetypestr), "%u", (unsigned) servicetype); - assert (n > 0 && (size_t) n < sizeof (servicetypestr)); - len += 2*(sizeof(service_type_tag)-1) + tag_overhead + (size_t) n; - } - - a->value = os_malloc(len); - - { - char *p = a->value; - int n; - n = snprintf (p, len, "<%s>", product_tag); assert (n >= 0 && (size_t) n < len); p += n; len -= (size_t) n; - if (plist->present & PP_PRISMTECH_EXEC_NAME) - { - n = snprintf (p, len, "<%s>", exec_name_tag, plist->exec_name, exec_name_tag); - assert (n >= 0 && (size_t) n < len); - p += n; len -= (size_t) n; - } - if (plist->present & PP_ENTITY_NAME) - { - n = snprintf (p, len, "<%s>", participant_name_tag, plist->entity_name, participant_name_tag); - assert (n >= 0 && (size_t) n < len); - p += n; len -= (size_t) n; - } - if (plist->present & PP_PRISMTECH_PROCESS_ID) - { - n = snprintf (p, len, "<%s>%s", process_id_tag, pidstr, process_id_tag); - assert (n >= 0 && (size_t) n < len); - p += n; len -= (size_t) n; - } - if (plist->present & PP_PRISMTECH_NODE_NAME) - { - n = snprintf (p, len, "<%s>", node_name_tag, plist->node_name, node_name_tag); - assert (n >= 0 && (size_t) n < len); - p += n; len -= (size_t) n; - } - n = snprintf (p, len, "<%s>%s", federation_id_tag, federationidstr, federation_id_tag); - assert (n >= 0 && (size_t) n < len); - p += n; len -= (size_t) n; - n = snprintf (p, len, "<%s>%s", vendor_id_tag, vendoridstr, vendor_id_tag); - assert (n >= 0 && (size_t) n < len); - p += n; len -= (size_t) n; - - { - n = snprintf (p, len, "<%s>%s", service_type_tag, servicetypestr, service_type_tag); - assert (n >= 0 && (size_t) n < len); - p += n; len -= (size_t) n; - } - - n = snprintf (p, len, "", product_tag); - assert (n >= 0 && (size_t) n == len-1); - (void) n; - } -} - -static void generate_key (_Out_ DDS_BuiltinTopicKey_t *a, _In_ const nn_guid_prefix_t *gid) -{ - (*a)[0] = gid->u[0]; - (*a)[1] = gid->u[1]; - (*a)[2] = gid->u[2]; -} - -void -propagate_builtin_topic_participant( - _In_ const struct entity_common *participant, - _In_ const nn_plist_t *plist, - _In_ nn_wctime_t timestamp, - _In_ int alive) -{ - DDS_ParticipantBuiltinTopicData data; - generate_key(&(data.key), &(participant->guid.prefix)); - generate_user_data(&(data.user_data), &(plist->qos)); - forward_builtin_participant(&data, timestamp, alive); -} - -void -propagate_builtin_topic_cmparticipant( - _In_ const struct entity_common *participant, - _In_ const nn_plist_t *plist, - _In_ nn_wctime_t timestamp, - _In_ int alive) -{ - DDS_CMParticipantBuiltinTopicData data; - generate_key(&(data.key), &(participant->guid.prefix)); - generate_product_data(&(data.product), participant, plist); - forward_builtin_cmparticipant(&data, timestamp, alive); - os_free(data.product.value); -} diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index c6fe9f7..0b811d5 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -37,7 +37,6 @@ #include "ddsi/q_transmit.h" #include "ddsi/q_lease.h" #include "ddsi/q_error.h" -#include "ddsi/q_builtin_topic.h" #include "ddsi/ddsi_serdata_default.h" #include "ddsi/q_md5.h" #include "ddsi/q_feature_check.h" @@ -200,8 +199,6 @@ int spdp_write (struct participant *pp) return 0; } - propagate_builtin_topic_participant(&(pp->e), pp->plist, now(), true); - DDS_TRACE("spdp_write(%x:%x:%x:%x)\n", PGUID (pp->e.guid)); if ((wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL) @@ -1425,8 +1422,6 @@ int sedp_write_cm_participant (struct participant *pp, int alive) return 0; } - propagate_builtin_topic_cmparticipant(&(pp->e), pp->plist, now(), alive); - sedp_wr = get_sedp_writer (pp, NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER); /* The message is only a temporary thing, used only for encoding diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 83d2277..1ca70c5 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -35,7 +35,6 @@ #include "ddsi/q_protocol.h" /* NN_ENTITYID_... */ #include "ddsi/q_unused.h" #include "ddsi/q_error.h" -#include "ddsi/q_builtin_topic.h" #include "ddsi/ddsi_serdata_default.h" #include "ddsi/ddsi_mcgroup.h" #include "ddsi/q_receive.h" @@ -155,14 +154,30 @@ static int is_builtin_endpoint (nn_entityid_t id, nn_vendorid_t vendorid) return is_builtin_entityid (id, vendorid) && id.u != NN_ENTITYID_PARTICIPANT; } -static void entity_common_init (struct entity_common *e, const struct nn_guid *guid, const char *name, enum entity_kind kind, bool onlylocal) +static void entity_common_init (struct entity_common *e, const struct nn_guid *guid, const char *name, enum entity_kind kind, nn_vendorid_t vendorid, bool onlylocal, struct ddsi_tkmap_instance **tk) { e->guid = *guid; e->kind = kind; e->name = os_strdup (name ? name : ""); - e->iid = ddsi_iid_gen (); - os_mutexInit (&e->lock); e->onlylocal = onlylocal; + os_mutexInit (&e->lock); + if (onlylocal || is_builtin_entityid (guid->entityid, vendorid)) + { + e->iid = ddsi_iid_gen (); + *tk = NULL; + } + else + { + struct ddsi_serdata *sd; + struct nn_keyhash kh; + memcpy (&kh, guid, sizeof (kh)); + /* any random builtin topic will do (provided it has a GUID for a key), because what matters is the "class" of the topic, not the actual topic; also, this is called early in the initialisation of the entity with this GUID, which simply causes serdata_from_keyhash to create a key-only serdata because the key lookup fails. */ + sd = ddsi_serdata_from_keyhash (gv.builtin_participant_topic, &kh); + /* FIXME: this makes the iid for a reincarnation of a proxy entity dependent on whether an application reader kept the corresponding built-in topic instance around, it may be attractive to reconsider and guarantee a new iid in these cases, at least for the publication handle */ + *tk = ddsi_tkmap_find(sd, false, true); + ddsi_serdata_unref (sd); + e->iid = (*tk)->m_iid; + } } static void entity_common_fini (struct entity_common *e) @@ -223,6 +238,36 @@ void local_reader_ary_setinvalid (struct local_reader_ary *x) os_mutexUnlock (&x->rdary_lock); } +static void write_builtin_topic_any (const struct entity_common *e, nn_wctime_t timestamp, bool alive, nn_vendorid_t vendorid, struct ddsi_tkmap_instance *tk) +{ + enum ddsi_sertopic_builtin_type type; + switch (e->kind) + { + case EK_PARTICIPANT: + case EK_PROXY_PARTICIPANT: + type = DSBT_PARTICIPANT; + break; + case EK_READER: + case EK_PROXY_READER: + type = DSBT_READER; + break; + case EK_WRITER: + case EK_PROXY_WRITER: + type = DSBT_WRITER; + break; + } + if (!(e->onlylocal || is_builtin_endpoint(e->guid.entityid, vendorid))) + ddsi_plugin.builtin_write (type, &e->guid, timestamp, alive); + /* tkmap instance only needs to be kept around until the first write of a built-in topic (if none ever happens, it needn't be kept at all): afterward, the WHC of the local built-in topic writer will keep the entry alive. FIXME: the SPDP/SEPD ones currently use default sertopics instead of builtin sertopics, and so use different mappings and different instnace ids. No-one ever sees those ids, so it doesn't matter, but it would nicer if it could actually be the same one. FIXME: it would also be nicer if the local built-in topics and the SPDP/SEDP writers were the same, but I want the locally created endpoints visible in the built-in topics as well, and those don't exist in the discovery writers ... */ + if (tk) + ddsi_tkmap_instance_unref (tk); +} + +static void write_builtin_topic_local (const struct entity_common *e, nn_wctime_t timestamp, bool alive, struct ddsi_tkmap_instance *tk) +{ + write_builtin_topic_any(e, timestamp, alive, ownvendorid, tk); +} + /* DELETED PARTICIPANTS --------------------------------------------- */ int deleted_participants_admin_init (void) @@ -359,6 +404,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis { struct participant *pp; nn_guid_t subguid, group_guid; + struct ddsi_tkmap_instance *tk; /* no reserved bits may be set */ assert ((flags & ~(RTPS_PF_NO_BUILTIN_READERS | RTPS_PF_NO_BUILTIN_WRITERS | RTPS_PF_PRIVILEGED_PP | RTPS_PF_IS_DDSI2_PP | RTPS_PF_ONLY_LOCAL)) == 0); @@ -401,7 +447,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis pp = os_malloc (sizeof (*pp)); - entity_common_init (&pp->e, ppguid, "", EK_PARTICIPANT, ((flags & RTPS_PF_ONLY_LOCAL) != 0)); + entity_common_init (&pp->e, ppguid, "", EK_PARTICIPANT, ownvendorid, ((flags & RTPS_PF_ONLY_LOCAL) != 0), &tk); pp->user_refc = 1; pp->builtin_refc = 0; pp->builtins_deleted = 0; @@ -580,6 +626,8 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis trigger_recv_threads (); } + write_builtin_topic_local(&pp->e, now(), true, tk); + /* SPDP periodic broadcast uses the retransmit path, so the initial publication must be done differently. Must be later than making the participant globally visible, or the SPDP processing won't @@ -606,7 +654,6 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis tsched.v = (pp->lease_duration == T_NEVER) ? T_NEVER : 0; pp->pmd_update_xevent = qxev_pmd_update (tsched, &pp->e.guid); } - return 0; } @@ -815,11 +862,7 @@ int delete_participant (const struct nn_guid *ppguid) struct participant *pp; if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) return ERR_UNKNOWN_ENTITY; - if (!(pp->e.onlylocal)) - { - propagate_builtin_topic_cmparticipant(&(pp->e), pp->plist, now(), false); - propagate_builtin_topic_participant(&(pp->e), pp->plist, now(), false); - } + write_builtin_topic_local(&pp->e, now(), false, NULL); remember_deleted_participant_guid (&pp->e.guid); ephash_remove_participant_guid (pp); gcreq_participant (pp); @@ -2333,10 +2376,11 @@ static void endpoint_common_init enum entity_kind kind, const struct nn_guid *guid, const struct nn_guid *group_guid, - struct participant *pp + struct participant *pp, + struct ddsi_tkmap_instance **tk ) { - entity_common_init (e, guid, NULL, kind, pp->e.onlylocal); + entity_common_init (e, guid, NULL, kind, ownvendorid, pp->e.onlylocal, tk); c->pp = ref_participant (pp, &e->guid); if (group_guid) { @@ -2563,6 +2607,7 @@ static struct writer * new_writer_guid (const struct nn_guid *guid, const struct { struct writer *wr; nn_mtime_t tnow = now_mt (); + struct ddsi_tkmap_instance *tk; assert (is_writer_entityid (guid->entityid)); assert (ephash_lookup_writer_guid (guid) == NULL); @@ -2575,7 +2620,7 @@ static struct writer * new_writer_guid (const struct nn_guid *guid, const struct 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); + endpoint_common_init (&wr->e, &wr->c, EK_WRITER, guid, group_guid, pp, &tk); os_condInit (&wr->throttle_cond, &wr->e.lock); wr->seq = 0; @@ -2784,6 +2829,7 @@ static struct writer * new_writer_guid (const struct nn_guid *guid, const struct deleted while we do so */ match_writer_with_proxy_readers (wr, tnow); match_writer_with_local_readers (wr, tnow); + write_builtin_topic_local(&wr->e, now(), true, tk); sedp_write_writer (wr); if (wr->lease_duration != T_NEVER) @@ -2909,6 +2955,7 @@ 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)); ASSERT_MUTEX_HELD (&wr->e.lock); + write_builtin_topic_local(&wr->e, now(), false, NULL); local_reader_ary_setinvalid (&wr->rdary); ephash_remove_writer_guid (wr); writer_set_state (wr, WRST_DELETING); @@ -3125,6 +3172,7 @@ static struct reader * new_reader_guid struct reader * rd; nn_mtime_t tnow = now_mt (); + struct ddsi_tkmap_instance *tk; assert (!is_writer_entityid (guid->entityid)); assert (ephash_lookup_reader_guid (guid) == NULL); @@ -3133,7 +3181,7 @@ static struct reader * new_reader_guid new_reader_writer_common (guid, topic, xqos); rd = os_malloc (sizeof (*rd)); - endpoint_common_init (&rd->e, &rd->c, EK_READER, guid, group_guid, pp); + endpoint_common_init (&rd->e, &rd->c, EK_READER, guid, group_guid, pp, &tk); /* Copy QoS, merging in defaults */ rd->xqos = os_malloc (sizeof (*rd->xqos)); @@ -3237,6 +3285,7 @@ static struct reader * new_reader_guid ephash_insert_reader_guid (rd); match_reader_with_proxy_writers (rd, tnow); match_reader_with_local_writers (rd, tnow); + write_builtin_topic_local(&rd->e, now(), true, tk); sedp_write_reader (rd); return rd; } @@ -3329,6 +3378,7 @@ int delete_reader (const struct nn_guid *guid) (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)); + write_builtin_topic_local(&rd->e, now(), false, NULL); ephash_remove_reader_guid (rd); gcreq_reader (rd); return 0; @@ -3404,6 +3454,7 @@ void new_proxy_participant runs on a single thread, it can't go wrong. FIXME, maybe? The same holds for the other functions for creating entities. */ struct proxy_participant *proxypp; + struct ddsi_tkmap_instance *tk; assert (ppguid->entityid.u == NN_ENTITYID_PARTICIPANT); assert (ephash_lookup_proxy_participant_guid (ppguid) == NULL); @@ -3413,7 +3464,7 @@ void new_proxy_participant proxypp = os_malloc (sizeof (*proxypp)); - entity_common_init (&proxypp->e, ppguid, "", EK_PROXY_PARTICIPANT, false); + entity_common_init (&proxypp->e, ppguid, "", EK_PROXY_PARTICIPANT, vendor, false, &tk); proxypp->refc = 1; proxypp->lease_expired = 0; proxypp->vendor = vendor; @@ -3569,15 +3620,7 @@ void new_proxy_participant if (proxypp->owns_lease) lease_register (os_atomic_ldvoidp (&proxypp->lease)); - if (proxypp->proxypp_have_spdp) - { - propagate_builtin_topic_participant(&(proxypp->e), proxypp->plist, timestamp, true); - if (proxypp->proxypp_have_cm) - { - propagate_builtin_topic_cmparticipant(&(proxypp->e), proxypp->plist, timestamp, true); - } - } - + write_builtin_topic_any(&proxypp->e, timestamp, true, proxypp->vendor, tk); os_mutexUnlock (&proxypp->e.lock); } @@ -3595,14 +3638,10 @@ int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, co switch (source) { case UPD_PROXYPP_SPDP: - propagate_builtin_topic_participant(&(proxypp->e), proxypp->plist, timestamp, true); - if (!proxypp->proxypp_have_spdp && proxypp->proxypp_have_cm) - propagate_builtin_topic_cmparticipant(&(proxypp->e), proxypp->plist, timestamp, true); + write_builtin_topic_any(&proxypp->e, timestamp, true, proxypp->vendor, NULL); proxypp->proxypp_have_spdp = 1; break; case UPD_PROXYPP_CM: - if (proxypp->proxypp_have_spdp) - propagate_builtin_topic_cmparticipant(&(proxypp->e), proxypp->plist, timestamp, true); proxypp->proxypp_have_cm = 1; break; } @@ -3848,8 +3887,7 @@ int delete_proxy_participant_by_guid (const struct nn_guid * guid, nn_wctime_t t return ERR_UNKNOWN_ENTITY; } DDS_LOG(DDS_LC_DISCOVERY, "- deleting\n"); - propagate_builtin_topic_cmparticipant(&(ppt->e), ppt->plist, timestamp, false); - propagate_builtin_topic_participant(&(ppt->e), ppt->plist, timestamp, false); + write_builtin_topic_any(&ppt->e, timestamp, false, ppt->vendor, NULL); remember_deleted_participant_guid (&ppt->e.guid); ephash_remove_proxy_participant_guid (ppt); os_mutexUnlock (&gv.lock); @@ -3982,7 +4020,7 @@ static void proxy_endpoint_common_init ( struct entity_common *e, struct proxy_endpoint_common *c, enum entity_kind kind, const struct nn_guid *guid, struct proxy_participant *proxypp, - struct addrset *as, const nn_plist_t *plist + struct addrset *as, const nn_plist_t *plist, struct ddsi_tkmap_instance **tk ) { const char *name; @@ -3993,7 +4031,7 @@ static void proxy_endpoint_common_init assert ((plist->qos.present & (QP_TOPIC_NAME | QP_TYPE_NAME)) == (QP_TOPIC_NAME | QP_TYPE_NAME)); name = (plist->present & PP_ENTITY_NAME) ? plist->entity_name : ""; - entity_common_init (e, guid, name, kind, false); + entity_common_init (e, guid, name, kind, proxypp->vendor, false, tk); c->xqos = nn_xqos_dup (&plist->qos); c->as = ref_addrset (as); c->topic = NULL; /* set from first matching reader/writer */ @@ -4027,6 +4065,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, struct proxy_writer *pwr; int isreliable; nn_mtime_t tnow = now_mt (); + struct ddsi_tkmap_instance *tk; (void)timestamp; assert (is_writer_entityid (guid->entityid)); assert (ephash_lookup_proxy_writer_guid (guid) == NULL); @@ -4038,7 +4077,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, } pwr = os_malloc (sizeof (*pwr)); - proxy_endpoint_common_init (&pwr->e, &pwr->c, EK_PROXY_WRITER, guid, proxypp, as, plist); + proxy_endpoint_common_init (&pwr->e, &pwr->c, EK_PROXY_WRITER, guid, proxypp, as, plist, &tk); ut_avlInit (&pwr_readers_treedef, &pwr->readers); pwr->n_reliable_readers = 0; @@ -4104,6 +4143,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, local_reader_ary_init (&pwr->rdary); ephash_insert_proxy_writer_guid (pwr); match_proxy_writer_with_readers (pwr, tnow); + write_builtin_topic_any(&pwr->e, timestamp, true, pwr->c.vendor, tk); os_mutexLock (&pwr->e.lock); pwr->local_matching_inprogress = 0; @@ -4235,6 +4275,7 @@ int delete_proxy_writer (const struct nn_guid *guid, nn_wctime_t timestamp, int from removing themselves from the proxy writer's rdary[]. */ local_reader_ary_setinvalid (&pwr->rdary); DDS_LOG(DDS_LC_DISCOVERY, "- deleting\n"); + write_builtin_topic_any(&pwr->e, timestamp, false, pwr->c.vendor, NULL); ephash_remove_proxy_writer_guid (pwr); os_mutexUnlock (&gv.lock); gcreq_proxy_writer (pwr); @@ -4252,6 +4293,7 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, struct proxy_participant *proxypp; struct proxy_reader *prd; nn_mtime_t tnow = now_mt (); + struct ddsi_tkmap_instance *tk; (void)timestamp; assert (!is_writer_entityid (guid->entityid)); @@ -4264,7 +4306,7 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, } prd = os_malloc (sizeof (*prd)); - proxy_endpoint_common_init (&prd->e, &prd->c, EK_PROXY_READER, guid, proxypp, as, plist); + proxy_endpoint_common_init (&prd->e, &prd->c, EK_PROXY_READER, guid, proxypp, as, plist, &tk); prd->deleting = 0; #ifdef DDSI_INCLUDE_SSM @@ -4278,6 +4320,7 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, ut_avlInit (&prd_writers_treedef, &prd->writers); ephash_insert_proxy_reader_guid (prd); match_proxy_reader_with_writers (prd, tnow); + write_builtin_topic_any(&prd->e, timestamp, true, prd->c.vendor, tk); return 0; } @@ -4360,6 +4403,7 @@ int delete_proxy_reader (const struct nn_guid *guid, nn_wctime_t timestamp, int DDS_LOG(DDS_LC_DISCOVERY, "- unknown\n"); return ERR_UNKNOWN_ENTITY; } + write_builtin_topic_any(&prd->e, timestamp, false, prd->c.vendor, NULL); ephash_remove_proxy_reader_guid (prd); os_mutexUnlock (&gv.lock); DDS_LOG(DDS_LC_DISCOVERY, "- deleting\n"); diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 8239391..374ad8e 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -56,6 +56,7 @@ #include "ddsi/ddsi_raweth.h" #include "ddsi/ddsi_mcgroup.h" #include "ddsi/ddsi_serdata_default.h" +#include "ddsi/ddsi_serdata_builtin.h" #include "ddsi/ddsi_tkmap.h" #include "dds__whc.h" @@ -783,12 +784,18 @@ static void make_special_topics (void) { gv.plist_topic = make_special_topic (PLATFORM_IS_LITTLE_ENDIAN ? PL_CDR_LE : PL_CDR_BE, &ddsi_serdata_ops_plist); gv.rawcdr_topic = make_special_topic (PLATFORM_IS_LITTLE_ENDIAN ? CDR_LE : CDR_BE, &ddsi_serdata_ops_rawcdr); + gv.builtin_participant_topic = new_sertopic_builtin (DSBT_PARTICIPANT, "DCPSParticipant", "org::eclipse::cyclonedds::builtin::DCPSParticipant"); + gv.builtin_reader_topic = new_sertopic_builtin (DSBT_READER, "DCPSSubscription", "org::eclipse::cyclonedds::builtin::DCPSSubscription"); + gv.builtin_writer_topic = new_sertopic_builtin (DSBT_WRITER, "DCPSPublication", "org::eclipse::cyclonedds::builtin::DCPSPublication"); } static void free_special_topics (void) { ddsi_sertopic_unref (gv.plist_topic); ddsi_sertopic_unref (gv.rawcdr_topic); + ddsi_sertopic_unref (gv.builtin_participant_topic); + ddsi_sertopic_unref (gv.builtin_reader_topic); + ddsi_sertopic_unref (gv.builtin_writer_topic); } static int setup_and_start_recv_threads (void) diff --git a/src/tools/ddsls/ddsls.c b/src/tools/ddsls/ddsls.c index a117ecf..40cb1a3 100644 --- a/src/tools/ddsls/ddsls.c +++ b/src/tools/ddsls/ddsls.c @@ -11,836 +11,570 @@ */ #include "os/os.h" #include "ddsc/dds.h" -#include "dds_builtinTopics.h" - - -#define DURATION_INFINITE_SEC 0x7fffffff -#define DURATION_INFINITE_NSEC 0x7fffffff -#define zero(pp,sz) _zero((void**)pp,sz) // FIXME Temporary workaround for lack of wait_for_historical implementation. Remove this on completion of CHAM-268. #define dds_reader_wait_for_historical_data(a,b) DDS_SUCCESS; dds_sleepfor(DDS_MSECS(200)); -/* Enable DEBUG for printing debug statements*/ -//#define DEBUG +// FIXME should fix read/take interface to allow simple unlimited take +#define MAX_SAMPLES 10 -#ifdef DEBUG -#define PRINTD printf -#else -#define PRINTD(...) +#define MAX_DURATION_BUFSZ 21 +char *qp_duration_str (char *buf, size_t bufsz, dds_duration_t d) +{ + if (d == DDS_INFINITY) + snprintf (buf, bufsz, "infinite"); + else + snprintf (buf, bufsz, "%u.%09u", (unsigned)(d / DDS_NSECS_IN_SEC), (unsigned)(d % DDS_NSECS_IN_SEC)); + return buf; +} + +size_t printable_seq_length (const unsigned char *as, size_t n) +{ + size_t i; + for (i = 0; i < n; i++) { + if (as[i] < 32 || as[i] >= 127) + break; + } + return i; +} + +void print_octetseq (const unsigned char *v, size_t sz, FILE *fp) +{ + size_t i, n; + fprintf (fp, "%zu<", sz); + i = 0; + while (i < sz) + { + if ((n = printable_seq_length (v + i, sz - i)) < 4) + { + if (n == 0) + n = 1; + while (n--) + { + fprintf (fp, "%s%u", i == 0 ? "" : ",", v[i]); + i++; + } + } + else + { + fprintf (fp, "\"%*.*s\"", (int)n, (int)n, v + i); + i += n; + } + } + fprintf (fp, ">"); +} + +void qp_user_data (const dds_qos_t *q, FILE *fp) +{ + void *ud; + size_t udsz; + if (dds_qget_userdata(q, &ud, &udsz)) + { + fprintf (fp, " user_data: value = "); + print_octetseq (ud, udsz,fp); + fprintf (fp, "\n"); + dds_free (ud); + } +} + +void qp_topic_data (const dds_qos_t *q, FILE *fp) +{ + void *ud; + size_t udsz; + if (dds_qget_topicdata(q, &ud, &udsz)) + { + fprintf (fp, " topic_data: value = "); + print_octetseq (ud, udsz,fp); + fprintf (fp, "\n"); + dds_free (ud); + } +} + +void qp_group_data (const dds_qos_t *q, FILE *fp) +{ + void *ud; + size_t udsz; + if (dds_qget_groupdata(q, &ud, &udsz)) + { + fprintf (fp, " group_data: value = "); + print_octetseq (ud, udsz,fp); + fprintf (fp, "\n"); + dds_free (ud); + } +} + +void qp_durability (const dds_qos_t *q, FILE *fp) +{ + dds_durability_kind_t kind; + if (dds_qget_durability (q, &kind)) + { + static const char *s = "?"; + switch (kind) + { + case DDS_DURABILITY_VOLATILE: s = "volatile"; break; + case DDS_DURABILITY_TRANSIENT_LOCAL: s = "transient-local"; break; + case DDS_DURABILITY_TRANSIENT: s = "transient"; break; + case DDS_DURABILITY_PERSISTENT: s = "persistent"; break; + } + fprintf (fp, " durability: kind = %s\n", s); + } +} + +void qp_history (const dds_qos_t *q, FILE *fp) +{ + dds_history_kind_t kind; + int32_t depth; + if (dds_qget_history (q, &kind, &depth)) + { + fprintf (fp, " history: kind = "); + switch (kind) + { + case DDS_HISTORY_KEEP_LAST: + fprintf (fp, "keep-last, depth = %"PRId32"\n", depth); + break; + case DDS_HISTORY_KEEP_ALL: + fprintf (fp, "keep-all (depth = %"PRId32")\n", depth); + break; + } + } +} + +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) + fprintf (fp, "unlimited"); + else + fprintf (fp, "%d", max_samples); + fprintf (fp, ", max_instances = "); + if (max_instances == DDS_LENGTH_UNLIMITED) + fprintf (fp, "unlimited"); + else + fprintf (fp, "%d", 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); +} + +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) +{ + dds_presentation_access_scope_kind_t access_scope; + bool coherent_access, ordered_access; + if (dds_qget_presentation (q, &access_scope, &coherent_access, &ordered_access)) + { + static const char *s = "?"; + switch (access_scope) + { + case DDS_PRESENTATION_INSTANCE: s = "instance"; break; + case DDS_PRESENTATION_TOPIC: s = "topic"; break; + case DDS_PRESENTATION_GROUP: s = "group"; break; + } + fprintf (fp, " presentation: scope = %s, coherent_access = %s, ordered_access = %s\n", s, coherent_access ? "true" : "false", ordered_access ? "true" : "false"); + } +} + +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]; + if (qget (q, &d)) + fprintf (fp, " %s = %s\n", what, qp_duration_str (buf, sizeof (buf), d)); +} + +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) +{ + qp_duration_qos (q, fp, "deadline: period = ", dds_qget_deadline); +} + +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) +{ + 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) +{ + dds_ownership_kind_t kind; + char *s = "?"; + if (dds_qget_ownership (q, &kind)) + { + switch (kind) + { + case DDS_OWNERSHIP_SHARED: s = "shared"; break; + case DDS_OWNERSHIP_EXCLUSIVE: s = "exclusive"; break; + } + fprintf (fp, " ownership: kind = %s\n", s); + } +} + +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) +{ + dds_liveliness_kind_t kind; + dds_duration_t lease_duration; + if (dds_qget_liveliness (q, &kind, &lease_duration)) + { + char *s = "?"; + char buf[MAX_DURATION_BUFSZ]; + switch (kind) + { + case DDS_LIVELINESS_AUTOMATIC: s = "automatic"; break; + case DDS_LIVELINESS_MANUAL_BY_PARTICIPANT: s = "manual-by-participant"; break; + case DDS_LIVELINESS_MANUAL_BY_TOPIC: s = "manual-by-topic"; break; + } + fprintf (fp, " liveliness: kind = %s, lease_duration = %s\n", s, qp_duration_str (buf, sizeof (buf), lease_duration)); + } +} + +void qp_reliability (const dds_qos_t *q, FILE *fp) +{ + dds_reliability_kind_t kind; + dds_duration_t max_blocking_time; + if (dds_qget_reliability (q, &kind, &max_blocking_time)) + { + char *s = "?"; + char buf[MAX_DURATION_BUFSZ]; + switch (kind) + { + case DDS_RELIABILITY_BEST_EFFORT: s = "best-effort"; break; + case DDS_RELIABILITY_RELIABLE: s = "reliable"; break; + } + fprintf (fp, " reliability: kind = %s, max_blocking_time = %s\n", s, qp_duration_str (buf, sizeof (buf), max_blocking_time)); + } +} + +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) +{ + dds_destination_order_kind_t kind; + if (dds_qget_destination_order (q, &kind)) + { + static const char *s = "?"; + switch (kind) + { + case DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP: s = "by-reception-timestamp"; break; + case DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP: s = "by-source-timestamp"; break; + } + fprintf (fp, " destination_order: kind = %s\n", s); + } +} + +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) +{ + 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)) + { + char buf1[MAX_DURATION_BUFSZ], buf2[MAX_DURATION_BUFSZ]; + fprintf (fp, " reader_data_lifecycle: autopurge_nowriter_samples_delay = %s, autopurge_disposed_samples_delay = %s\n", qp_duration_str (buf1, sizeof (buf1), autopurge_nowriter_samples_delay), qp_duration_str (buf2, sizeof (buf2), autopurge_disposed_samples_delay)); + } +} + +void qp_durability_service (const dds_qos_t *q, FILE *fp) +{ + dds_duration_t service_cleanup_delay; + dds_history_kind_t history_kind; + int32_t history_depth; + int32_t max_samples, max_instances, max_samples_per_instance; + if (dds_qget_durability_service (q, &service_cleanup_delay, &history_kind, &history_depth, &max_samples, &max_instances, &max_samples_per_instance)) + { + char buf[MAX_DURATION_BUFSZ]; + fprintf (fp, " durability_service:\n"); + fprintf (fp, " service_cleanup_delay: %s\n", qp_duration_str (buf, sizeof (buf), service_cleanup_delay)); + switch (history_kind) + { + case DDS_HISTORY_KEEP_LAST: + fprintf (fp, " history: kind = keep-last, depth = %"PRId32"\n", history_depth); + break; + case DDS_HISTORY_KEEP_ALL: + fprintf (fp, " history: kind = keep-all (depth = %"PRId32")\n", history_depth); + break; + } + qp_resource_limits_1(fp, max_samples, max_instances, max_samples_per_instance, 4); + } +} + +void qp_partition (const dds_qos_t *q, FILE *fp) +{ + uint32_t n; + char **ps; + if (dds_qget_partition (q, &n, &ps)) + { + fprintf (fp, " partition: name = "); + if (n == 0) + fprintf (fp, "(default)"); + else if (n == 1) + fprintf (fp, "%s", ps[0]); + else + { + fprintf (fp, "{"); + for (uint32_t i = 0; i < n; i++) + fprintf (fp, "%s%s", (i > 0) ? "," : "", ps[i]); + fprintf (fp, "}"); + } + fprintf (fp, "\n"); + for (uint32_t i = 0; i < n; i++) + dds_free (ps[i]); + dds_free (ps); + } +} + +void qp_qos (const dds_qos_t *q, FILE *fp) +{ + qp_reliability (q, fp); + qp_durability (q, fp); + qp_destination_order (q, fp); + qp_partition (q, fp); + qp_history (q, fp); + qp_presentation (q, fp); + qp_resource_limits (q, fp); + qp_deadline (q, fp); + qp_latency_budget (q, fp); + qp_lifespan (q, fp); + qp_liveliness (q, fp); + qp_time_based_filter (q, fp); + qp_transport_priority (q, fp); + qp_writer_data_lifecycle (q, fp); + qp_reader_data_lifecycle (q, fp); + qp_durability_service (q, fp); + qp_ownership (q, fp); + qp_ownership_strength (q, fp); + qp_user_data (q, fp); + qp_topic_data (q, fp); + qp_group_data (q, fp); +} + +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++) { + fprintf(fp, "%s%02x", (j == 0) ? " " : ":", key->v[j]); + } + fprintf(fp, "\n"); +} + +#if 0 +void print_dcps_topic (FILE *fp, dds_entity_t pp) +{ + dds_entity_t rd = dds_create_reader (pp, DDS_BUILTIN_TOPIC_DCPSTOPIC, NULL, NULL); + (void)dds_reader_wait_for_historical_data (rd, DDS_SECS (5)); + while(true) + { + void *ptrs[MAX_SAMPLES] = { 0 }; + dds_sample_info_t info[sizeof (ptrs) / sizeof (ptrs[0])]; + int n = dds_take (rd, ptrs, info, sizeof (ptrs) / sizeof (ptrs[0]), sizeof (ptrs) / sizeof (ptrs[0])); + if (n <= 0) + break; + for (int i = 0; i < n; i++) + { + dds_builtintopic_topic_t *data = ptrs[i]; + fprintf (fp,"TOPIC:\n"); + print_key (fp, " key =", &data->key); + if (info[i].valid_data) + { + qp_qos (data->qos, fp); + } + } + dds_return_loan (rd, ptrs, n); + } + dds_delete (rd); +} #endif +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)); + while(true) + { + void *ptrs[MAX_SAMPLES] = { 0 }; + dds_sample_info_t info[sizeof (ptrs) / sizeof (ptrs[0])]; + int n = dds_take (rd, ptrs, info, sizeof (ptrs) / sizeof (ptrs[0]), sizeof (ptrs) / sizeof (ptrs[0])); + if (n <= 0) + break; + for (int i = 0; i < n; i++) + { + dds_builtintopic_participant_t *data = ptrs[i]; + fprintf (fp,"PARTICIPANT:\n"); + print_key (fp, " key =", &data->key); + if (info[i].valid_data) + { + qp_qos (data->qos, fp); + } + } + dds_return_loan (rd, ptrs, n); + } + dds_delete (rd); +} + +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)); + while(true) + { + void *ptrs[MAX_SAMPLES] = { 0 }; + dds_sample_info_t info[sizeof (ptrs) / sizeof (ptrs[0])]; + int n = dds_take (rd, ptrs, info, sizeof (ptrs) / sizeof (ptrs[0]), sizeof (ptrs) / sizeof (ptrs[0])); + if (n <= 0) + break; + for (int i = 0; i < n; i++) + { + dds_builtintopic_endpoint_t *data = ptrs[i]; + fprintf (fp,"%s:\n", type); + print_key (fp, " key =", &data->key); + if (info[i].valid_data) + { + print_key (fp, " participant_key =", &data->participant_key); + fprintf (fp," topic_name = %s\n", data->topic_name); + fprintf (fp," type_name = %s\n", data->type_name); + qp_qos (data->qos,fp); + } + } + dds_return_loan (rd, ptrs, n); + } + dds_delete (rd); +} + +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) +{ + print_dcps_endpoint (fp, pp, "PUBLICATION", DDS_BUILTIN_TOPIC_DCPSPUBLICATION); +} + #define DCPSTOPIC_FLAG 1 #define DCPSPARTICIPANT_FLAG (1<<1) #define DCPSSUBSCRIPTION_FLAG (1<<2) #define DCPSPUBLICATION_FLAG (1<<3) -#define CMPARTICIPANT_FLAG (1<<4) -#define CMPUBLISHER_FLAG (1<<5) -#define CMSUBSCRIBER_FLAG (1<<6) -#define CMDATAREADER_FLAG (1<<7) -#define CMDATAWRITER_FLAG (1<<8) -static struct topictab{ - const char *name; - const int flag; +static struct topictab { + const char *name; + const int flag; + void (*fun) (FILE *fp, dds_entity_t pp); } topictab[] = { - {"dcpstopic", DCPSTOPIC_FLAG}, - {"dcpsparticipant", DCPSPARTICIPANT_FLAG}, - {"dcpssubscription", DCPSSUBSCRIPTION_FLAG}, - {"dcpspublication", DCPSPUBLICATION_FLAG}, - {"cmparticipant", CMPARTICIPANT_FLAG}, - {"cmpublisher", CMPUBLISHER_FLAG}, - {"cmsubscriber", CMSUBSCRIBER_FLAG}, - {"cmdatareader", CMDATAREADER_FLAG}, - {"cmdatawriter", CMDATAWRITER_FLAG}, - + //{ "dcpstopic", DCPSTOPIC_FLAG, print_dcps_topic }, + { "dcpsparticipant", DCPSPARTICIPANT_FLAG, print_dcps_participant }, + { "dcpssubscription", DCPSSUBSCRIPTION_FLAG, print_dcps_subscription }, + { "dcpspublication", DCPSPUBLICATION_FLAG, print_dcps_publication } }; #define TOPICTAB_SIZE (sizeof(topictab)/sizeof(struct topictab)) -const unsigned int MAX_SAMPLES = 10; -unsigned int states = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE; -int reader_wait = 0; -dds_entity_t participant; -dds_entity_t subscriber; -dds_domainid_t did = DDS_DOMAIN_DEFAULT; -dds_sample_info_t info[10]; -dds_qos_t* tqos; -dds_qos_t* sqos; - -void _zero(void ** samples, size_t size) { - size_t i; - for(i = 0; i < size;i++) { - samples[i] = NULL; - } -} - -int duration_is_infinite(const DDS_Duration_t *d){ - return d->sec == DURATION_INFINITE_SEC && d->nanosec == DURATION_INFINITE_NSEC; -} - -void qp_durability (const DDS_DurabilityQosPolicy *q, FILE *fp) +void usage (void) { - char buf[40]; - char *k; - switch (q->kind) + fprintf (stderr, "Usage: ddsls [OPTIONS] TOPIC... for specified topics\n\n"); + fprintf (stderr, " or: ddsls [OPTIONS] -a for all topics\n"); + fprintf (stderr, "\nOPTIONS:\n"); + fprintf (stderr, "-f -- write to file\n"); + fprintf (stderr, "\nTOPICS\n"); + for (size_t i = 0; i < TOPICTAB_SIZE; i++) + fprintf (stderr, "%s\n", topictab[i].name); + exit (1); +} + +int main (int argc, char **argv) +{ + FILE *fp = stdout; + int flags = 0; + dds_entity_t pp; + int opt; + while ((opt = os_getopt (argc, argv, "f:a")) != EOF) + { + switch (opt) { - case DDS_VOLATILE_DURABILITY_QOS: k = "volatile"; break; - case DDS_TRANSIENT_LOCAL_DURABILITY_QOS: k = "transient-local"; break; - case DDS_TRANSIENT_DURABILITY_QOS: k = "transient"; break; - case DDS_PERSISTENT_DURABILITY_QOS: k = "persistent"; break; - default: (void) snprintf (buf, sizeof (buf), "invalid (%d)", (int) q->kind); k = buf; break; - } - fprintf (fp, " durability: kind = %s\n", k); -} - -void qp_deadline (const DDS_DeadlineQosPolicy *q, FILE *fp) -{ - fprintf (fp," deadline: period = "); - if (duration_is_infinite(&q->period)) - fprintf (fp, "infinite\n"); - else - fprintf (fp,"%d.%09u\n", q->period.sec, q->period.nanosec); -} - -void qp_latency_budget (const DDS_LatencyBudgetQosPolicy *q, FILE *fp) -{ - fprintf (fp," latency_budget: duration = "); - if (duration_is_infinite (&q->duration)) - fprintf (fp,"infinite\n"); - else - fprintf (fp,"%d.%09u\n", q->duration.sec, q->duration.nanosec); -} - -void qp_liveliness (const DDS_LivelinessQosPolicy *q, FILE *fp) -{ - char buf[40]; - char *k; - switch (q->kind) - { - case DDS_AUTOMATIC_LIVELINESS_QOS: k = "automatic"; break; - case DDS_MANUAL_BY_PARTICIPANT_LIVELINESS_QOS: k = "manual-by-participant"; break; - case DDS_MANUAL_BY_TOPIC_LIVELINESS_QOS: k = "manual-by-topic"; break; - default: (void) snprintf (buf, sizeof (buf), "invalid (%d)", (int) q->kind); k = buf; break; - } - fprintf (fp," liveliness: kind = %s, lease_duration = ", k); - if (duration_is_infinite(&q->lease_duration)) - fprintf (fp,"infinite\n"); - else - fprintf (fp,"%d.%09u\n", q->lease_duration.sec, q->lease_duration.nanosec); -} - -void qp_reliability (const DDS_ReliabilityQosPolicy *q, FILE *fp) -{ - char buf[40]; - char *k; - switch (q->kind) - { - case DDS_BEST_EFFORT_RELIABILITY_QOS: k = "best-effort"; break; - case DDS_RELIABLE_RELIABILITY_QOS: k = "reliable"; break; - default: (void) snprintf (buf, sizeof (buf), "invalid (%d)", (int) q->kind); k = buf; break; - } - fprintf (fp," reliability: kind = %s, max_blocking_time = ", k); - if (duration_is_infinite(&q->max_blocking_time)) - fprintf (fp,"infinite"); - else - fprintf (fp,"%d.%09u", q->max_blocking_time.sec, q->max_blocking_time.nanosec); - fprintf (fp,", synchronous = %s\n", q->synchronous ? "true" : "false"); -} - -void qp_transport_priority (const DDS_TransportPriorityQosPolicy *q, FILE *fp) -{ - fprintf (fp," transport_priority: priority = %d\n", q->value); -} - -void qp_lifespan (const DDS_LifespanQosPolicy *q, FILE *fp) -{ - fprintf (fp," lifespan: duration = "); - if (duration_is_infinite(&q->duration)) - fprintf (fp, "infinite\n"); - else - fprintf (fp, "%d.%09u\n", q->duration.sec, q->duration.nanosec); -} - -void qp_destination_order (const DDS_DestinationOrderQosPolicy *q, FILE *fp) -{ - char buf[40]; - char *k; - switch (q->kind) - { - case DDS_BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS: k = "by-reception-timestamp"; break; - case DDS_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS: k = "by-source-timestamp"; break; - default: (void) snprintf (buf, sizeof (buf), "invalid (%d)", (int) q->kind); k = buf; break; - } - fprintf (fp," destination_order: kind = %s\n", k); -} - -void qp_history_kind_1 (DDS_HistoryQosPolicyKind kind, int indent, FILE *fp) -{ - char buf[40]; - char *k; - switch (kind) - { - case DDS_KEEP_LAST_HISTORY_QOS: k = "keep-last"; break; - case DDS_KEEP_ALL_HISTORY_QOS: k = "keep-all"; break; - default: (void) snprintf (buf, sizeof (buf), "invalid (%d)", (int) kind); k = buf; break; - } - fprintf (fp,"%*.*shistory: kind = %s", indent, indent, "", k); -} - -void qp_history (const DDS_HistoryQosPolicy *q, FILE *fp) -{ - qp_history_kind_1 (q->kind, 2,fp); - if (q->kind == DDS_KEEP_LAST_HISTORY_QOS) - fprintf (fp,", depth = %d\n", q->depth); - else - fprintf (fp,", (depth = %d)\n", q->depth); -} - -void qp_resource_limits_1(int max_samples, int max_instances, int max_samples_per_instance, int indent, FILE *fp) -{ - fprintf (fp,"%*.*sresource_limits: max_samples = ", indent, indent, ""); - if (max_samples == DDS_LENGTH_UNLIMITED) - fprintf (fp,"unlimited"); - else - fprintf (fp, "%d", max_samples); - fprintf (fp, ", max_instances = "); - if (max_instances == DDS_LENGTH_UNLIMITED) - fprintf (fp, "unlimited"); - else - fprintf (fp, "%d", 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); -} - -void qp_resource_limits (const DDS_ResourceLimitsQosPolicy *q, FILE *fp) -{ - qp_resource_limits_1 (q->max_samples, q->max_instances, q->max_samples_per_instance, 2,fp); -} - -void qp_ownership (const DDS_OwnershipQosPolicy *q, FILE *fp) -{ - char buf[40]; - char *k; - switch (q->kind) - { - case DDS_SHARED_OWNERSHIP_QOS: k = "shared"; break; - case DDS_EXCLUSIVE_OWNERSHIP_QOS: k = "exclusive"; break; - default: (void) snprintf (buf, sizeof (buf), "invalid (%d)", (int) q->kind); k = buf; break; - } - fprintf (fp," ownership: kind = %s\n", k); -} - -unsigned printable_seq_length(const unsigned char *as, unsigned n) -{ - unsigned i; - for (i = 0; i < n; i++) { - if (as[i] < 32 || as[i] >= 127) - break; - } - return i; -} - -void print_octetseq (const DDS_octSeq *v, FILE *fp) -{ - - unsigned i, n; - const char *sep = ""; - fprintf (fp, "%u<", v->_length); - i = 0; - while (i < v->_length) - { - if ((n = printable_seq_length (v->_buffer + i, v->_length - i)) < 4) + case 'f': { + char *fname = os_get_optarg (); + fp = fopen (fname, "w"); + if (fp == NULL) { - while (n--) - fprintf (fp,"%s%u", sep, v->_buffer[i++]); + fprintf (stderr, "%s: can't open for writing\n", fname); + exit (1); } - else - { - fprintf (fp, "\"%*.*s\"", n, n, v->_buffer + i); - i += n; - } - sep = ","; + break; + } + case 'a': + for (size_t i = 0; i < TOPICTAB_SIZE; i++) + flags |= topictab[i].flag; + break; + default: + usage (); + break; } - fprintf (fp,">"); -} + } -void qp_topic_data (const DDS_TopicDataQosPolicy *q, FILE *fp) -{ - fprintf (fp, " topic_data: value = "); - print_octetseq (&q->value,fp); - fprintf (fp, "\n"); -} + if (argc == 1) { + usage(); + } -void qp_user_data (const DDS_UserDataQosPolicy *q, FILE *fp) -{ - fprintf (fp, " user_data: value = "); - print_octetseq (&q->value,fp); - fprintf (fp, "\n"); -} - -void qp_time_based_filter (const DDS_TimeBasedFilterQosPolicy *q, FILE *fp) -{ - fprintf (fp," time_based_filter: minimum_separation = "); - if (duration_is_infinite (&q->minimum_separation)) - fprintf (fp,"infinite\n"); - else - fprintf (fp,"%d.%09u\n", q->minimum_separation.sec, q->minimum_separation.nanosec); -} - -void qp_presentation (const DDS_PresentationQosPolicy *q, FILE *fp) -{ - char buf[40]; - char *k; - switch (q->access_scope) + for (int i = os_get_optind (); i < argc; i++) + { + size_t k; + for (k = 0; k < TOPICTAB_SIZE; k++) { - case DDS_INSTANCE_PRESENTATION_QOS: k = "instance"; break; - case DDS_TOPIC_PRESENTATION_QOS: k = "topic"; break; - case DDS_GROUP_PRESENTATION_QOS: k = "group"; break; - default: (void) snprintf (buf, sizeof (buf), "invalid (%d)", (int) q->access_scope); k = buf; break; + if (os_strcasecmp (argv[i], topictab[k].name) == 0) + { + flags |= topictab[k].flag; + break; + } } - fprintf (fp, " presentation: scope = %s, coherent_access = %s, ordered_access = %s\n", k, - q->coherent_access ? "true" : "false", - q->ordered_access ? "true" : "false"); -} - -void qp_partition (const DDS_PartitionQosPolicy *q, FILE *fp) -{ - const DDS_StringSeq *s = &q->name; - fprintf (fp, " partition: name = "); - if (s->_length == 0) - fprintf (fp, "(default)"); - else if (s->_length == 1) - fprintf (fp, "%s", s->_buffer[0]); - else + if (k == TOPICTAB_SIZE) { - unsigned i; - fprintf (fp,"{"); - for (i = 0; i < s->_length; i++) - fprintf (fp, "%s%s", (i > 0) ? "," : "", s->_buffer[i]); - fprintf (fp,"}"); + fprintf(stderr, "%s: topic unknown\n", argv[i]); + exit (1); } - fprintf (fp,"\n"); -} - -void qp_group_data (const DDS_GroupDataQosPolicy *q, FILE *fp) -{ - fprintf (fp," group_data: value = "); - print_octetseq (&q->value,fp); - fprintf (fp,"\n"); -} - -void qp_ownership_strength (const DDS_OwnershipStrengthQosPolicy *q, FILE *fp) -{ - fprintf (fp," ownership_strength: value = %d\n", q->value); -} - -void qp_product_data (const DDS_ProductDataQosPolicy *q, FILE *fp) -{ - fprintf (fp," product_data: value = %s\n", q->value); -} - -void qp_entity_factory (const DDS_EntityFactoryQosPolicy *q, FILE *fp) -{ - fprintf (fp," entity_factory: autoenable_created_entities = %s\n", - q->autoenable_created_entities ? "true" : "false"); -} - -void qp_share (const DDS_ShareQosPolicy *q, FILE *fp) -{ - fprintf (fp," share: enable = %s", q->enable ? "true" : "false"); - if (q->enable) - fprintf (fp,", name = %s", q->name); - fprintf (fp,"\n"); -} - -void qp_writer_data_lifecycle (const DDS_WriterDataLifecycleQosPolicy *q, FILE *fp) -{ - fprintf (fp," writer_data_lifecycle: autodispose_unregistered_instances = %s, autopurge_suspended_samples_delay = ", - q->autodispose_unregistered_instances ? "true" : "false"); - if (duration_is_infinite (&q->autopurge_suspended_samples_delay)) - fprintf (fp,"infinite"); - else - fprintf (fp,"%d.%09u", q->autopurge_suspended_samples_delay.sec, q->autopurge_suspended_samples_delay.nanosec); - fprintf (fp,", autounregister_instance_delay = "); - if (duration_is_infinite (&q->autounregister_instance_delay)) - fprintf (fp,"infinite\n"); - else - fprintf (fp,"%d.%09u\n", q->autounregister_instance_delay.sec, q->autounregister_instance_delay.nanosec); -} - -void qp_reader_data_lifecycle (const DDS_ReaderDataLifecycleQosPolicy *q, FILE *fp) -{ - fprintf (fp," reader_data_lifecycle: autopurge_nowriter_samples_delay = "); - if (duration_is_infinite (&q->autopurge_nowriter_samples_delay)) - fprintf (fp,"infinite"); - else - fprintf (fp,"%d.%09u", q->autopurge_nowriter_samples_delay.sec, q->autopurge_nowriter_samples_delay.nanosec); - fprintf (fp,", autopurge_disposed_samples_delay = "); - if (duration_is_infinite (&q->autopurge_disposed_samples_delay)) - fprintf (fp,"infinite"); - else - fprintf (fp,"%d.%09u", q->autopurge_disposed_samples_delay.sec, q->autopurge_disposed_samples_delay.nanosec); - fprintf (fp,", enable_invalid_samples = %s\n", q->enable_invalid_samples ? "true" : "false"); -} - -void qp_subscription_keys (const DDS_UserKeyQosPolicy *q, FILE *fp) -{ - fprintf (fp," subscription_keys: enable = %s expression = %s\n", q->enable ? "true" : "false", q->expression); -} - -void qp_reader_lifespan (const DDS_ReaderLifespanQosPolicy *q, FILE *fp) -{ - fprintf (fp," reader_lifespan: use_lifespan = %s, ", q->use_lifespan ? "true" : "false"); - if (!q->use_lifespan) - fprintf (fp,"("); - fprintf (fp,"duration = "); - if (duration_is_infinite (&q->duration)) - fprintf (fp,"infinite"); - else - fprintf (fp,"%d.%09u", q->duration.sec, q->duration.nanosec); - if (!q->use_lifespan) - fprintf (fp,")"); - fprintf (fp,"\n"); -} - -void print_dcps_topic(FILE *fp){ - DDS_TopicBuiltinTopicData * dcps_topic_samples[10]; - dds_entity_t dcps_topic_reader; - int i = 0; - dcps_topic_reader = dds_create_reader(participant, DDS_BUILTIN_TOPIC_DCPSTOPIC, NULL, NULL); - PRINTD("DCPSTopic Reader Create: %s\n", dds_err_str(dcps_topic_reader)); - reader_wait = dds_reader_wait_for_historical_data(dcps_topic_reader, DDS_SECS(5)); - PRINTD("reader wait status: %d, %s \n", reader_wait, dds_err_str(reader_wait)); - while(true){ - int status = 0; - zero(dcps_topic_samples, MAX_SAMPLES); - status = dds_take_mask(dcps_topic_reader, (void**)dcps_topic_samples, info, MAX_SAMPLES, MAX_SAMPLES, states); - PRINTD("DDS reading samples returns %d \n", status); - for(i = 0; i < status; i++) { - DDS_TopicBuiltinTopicData * data = dcps_topic_samples[i]; - fprintf(fp,"TOPIC:\n"); - fprintf(fp," key = %u:%u:%u \n", (unsigned) data->key[0], (unsigned) data->key[1], (unsigned) data->key[2]); - fprintf(fp," name = %s\n", data->name); - fprintf(fp," type_name = %s\n", data->type_name); - qp_durability (&data->durability,fp); - qp_deadline (&data->deadline,fp); - qp_latency_budget (&data->latency_budget,fp); - qp_liveliness (&data->liveliness,fp); - qp_reliability (&data->reliability,fp); - qp_transport_priority (&data->transport_priority,fp); - qp_lifespan (&data->lifespan,fp); - qp_destination_order (&data->destination_order,fp); - qp_history (&data->history,fp); - qp_resource_limits (&data->resource_limits,fp); - qp_ownership (&data->ownership,fp); - qp_topic_data (&data->topic_data,fp); - } - if(status > 0) { - status = dds_return_loan(dcps_topic_reader, (void**)dcps_topic_samples, status); - } - if(status <= 0){ - break; - } - } -} - -void print_dcps_participant(FILE *fp){ - - DDS_ParticipantBuiltinTopicData * dcps_participant_samples[10]; - dds_entity_t dcps_participant_reader; - int i = 0; - dcps_participant_reader = dds_create_reader(participant, DDS_BUILTIN_TOPIC_DCPSPARTICIPANT, NULL, NULL); - PRINTD("DCPSSubscription Reader Create: %s\n", dds_err_str(dcps_participant_reader)); - reader_wait = dds_reader_wait_for_historical_data(dcps_participant_reader, DDS_SECS(5)); - PRINTD("reader wait status: %d, %s \n", reader_wait, dds_err_str(reader_wait)); - while(true){ - int status = 0; - zero(dcps_participant_samples, MAX_SAMPLES); - status = dds_take_mask(dcps_participant_reader, (void**)dcps_participant_samples, info, MAX_SAMPLES, MAX_SAMPLES, states); - PRINTD("DDS reading samples returns %d \n", status); - for(i = 0; i < status; i++) { - DDS_ParticipantBuiltinTopicData *data = dcps_participant_samples[i]; - fprintf(fp,"PARTICIPANT:\n"); - fprintf(fp," key = %u:%u:%u \n", (unsigned) data->key[0], (unsigned) data->key[1], (unsigned) data->key[2]); - qp_user_data(&data->user_data,fp); - } - if(status > 0) { - status = dds_return_loan(dcps_participant_reader, (void**)dcps_participant_samples, status); - } - if(status <= 0){ - break; - } - } -} - -void print_dcps_subscription(FILE *fp){ - DDS_SubscriptionBuiltinTopicData * dcps_subscription_samples[10]; - dds_entity_t dcps_subscription_reader; - int i = 0; - dcps_subscription_reader = dds_create_reader(participant, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL); - PRINTD("DCPSParticipant Reader Create: %s\n", dds_err_str(dcps_subscription_reader)); - reader_wait = dds_reader_wait_for_historical_data(dcps_subscription_reader, DDS_SECS(5)); - PRINTD("reader wait status: %d, %s \n", reader_wait, dds_err_str(reader_wait)); - while(true){ - int status = 0; - zero(dcps_subscription_samples, MAX_SAMPLES); - status = dds_take_mask(dcps_subscription_reader, (void**)dcps_subscription_samples, info, MAX_SAMPLES, MAX_SAMPLES, states); - PRINTD("DDS reading samples returns %d \n", status); - for(i = 0; i < status; i++) { - DDS_SubscriptionBuiltinTopicData *data = dcps_subscription_samples[i]; - fprintf(fp,"SUBSCRIPTION:\n"); - fprintf(fp," key = %u:%u:%u\n", (uint32_t) data->key[0], (uint32_t) data->key[1], (uint32_t) data->key[2]); - fprintf(fp," participant_key = %u:%u:%u\n", (uint32_t) data->participant_key[0], (uint32_t) data->participant_key[1], (uint32_t) data->participant_key[2]); - fprintf(fp," topic_name = %s\n", data->topic_name); - fprintf(fp," type_name = %s\n", data->type_name); - qp_durability(&data->durability,fp); - qp_deadline(&data->deadline,fp); - qp_latency_budget(&data->latency_budget,fp); - qp_liveliness(&data->liveliness,fp); - qp_reliability(&data->reliability,fp); - qp_ownership(&data->ownership,fp); - qp_destination_order(&data->destination_order,fp); - qp_user_data(&data->user_data,fp); - qp_time_based_filter(&data->time_based_filter,fp); - qp_presentation(&data->presentation,fp); - qp_partition(&data->partition,fp); - qp_topic_data(&data->topic_data,fp); - qp_group_data(&data->group_data,fp); - } - if(status > 0) { - status = dds_return_loan(dcps_subscription_reader, (void**)dcps_subscription_samples, status); - } - if(status <= 0){ - break; - } - } -} - -void print_dcps_publication(FILE *fp){ - DDS_PublicationBuiltinTopicData * dcps_publication_samples[10]; - dds_entity_t dcps_publication_reader; - int i = 0; - dcps_publication_reader = dds_create_reader(participant, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, NULL, NULL); - PRINTD("DCPSPublication Reader Create: %s\n", dds_err_str(dcps_publication_reader)); - reader_wait = dds_reader_wait_for_historical_data(dcps_publication_reader, DDS_SECS(5)); - PRINTD("reader wait status: %d, %s \n", reader_wait, dds_err_str(reader_wait)); - while(true){ - int status = 0; - zero(dcps_publication_samples, MAX_SAMPLES); - status = dds_take_mask(dcps_publication_reader, (void**)dcps_publication_samples, info, MAX_SAMPLES, MAX_SAMPLES, states); - PRINTD("DDS reading samples returns %d \n", status); - for(i = 0; i < status; i++) { - DDS_PublicationBuiltinTopicData *data = dcps_publication_samples[i]; - fprintf(fp,"PUBLICATION:\n"); - fprintf(fp," key = %u:%u:%u\n", (uint32_t) data->key[0], (uint32_t) data->key[1], (uint32_t) data->key[2]); - fprintf(fp," participant_key = %u:%u:%u\n", (uint32_t) data->participant_key[0], (uint32_t) data->participant_key[1], (uint32_t) data->participant_key[2]); - fprintf(fp," topic_name = %s\n", data->topic_name); - fprintf(fp," type_name = %s\n", data->type_name); - qp_durability(&data->durability,fp); - qp_deadline(&data->deadline,fp); - qp_latency_budget(&data->latency_budget,fp); - qp_liveliness(&data->liveliness,fp); - qp_reliability(&data->reliability,fp); - qp_lifespan (&data->lifespan,fp); - qp_destination_order (&data->destination_order,fp); - qp_user_data (&data->user_data,fp); - qp_ownership (&data->ownership,fp); - qp_ownership_strength (&data->ownership_strength,fp); - qp_presentation (&data->presentation,fp); - qp_partition (&data->partition,fp); - qp_topic_data (&data->topic_data,fp); - qp_group_data (&data->group_data,fp); - } - if(status > 0) { - status = dds_return_loan(dcps_publication_reader, (void**)dcps_publication_samples, status); - } - if(status <= 0){ - break; - } - } -} - -void print_cm_participant(FILE *fp){ - DDS_CMParticipantBuiltinTopicData * cm_participant_samples[10]; - dds_entity_t cm_participant_reader; - int i = 0; - cm_participant_reader = dds_create_reader(participant, DDS_BUILTIN_TOPIC_CMPARTICIPANT, NULL, NULL); - PRINTD("CMParticipant Reader Create: %s\n", dds_err_str(cm_participant_reader)); - reader_wait = dds_reader_wait_for_historical_data(cm_participant_reader, DDS_SECS(5)); - PRINTD("reader wait status: %d, %s \n", reader_wait, dds_err_str(reader_wait)); - while(true){ - int status = 0; - zero(cm_participant_samples, MAX_SAMPLES); - status = dds_take_mask(cm_participant_reader, (void**)cm_participant_samples, info, MAX_SAMPLES, MAX_SAMPLES, states); - PRINTD("DDS reading samples returns %d \n", status); - for(i = 0; i < status; i++) { - DDS_CMParticipantBuiltinTopicData *data = cm_participant_samples[i]; - fprintf(fp,"CMPARTICIPANT:\n"); - fprintf(fp," key = %u:%u:%u \n", (unsigned) data->key[0], (unsigned) data->key[1], (unsigned) data->key[2]); - qp_product_data(&data->product,fp); - } - if(status > 0) { - status = dds_return_loan(cm_participant_reader, (void**)cm_participant_samples, status); - } - if(status <= 0){ - break; - } - } -} - -void print_cm_publisher(FILE *fp){ - DDS_CMPublisherBuiltinTopicData * cm_publisher_samples[10]; - dds_entity_t cm_publisher_reader; - int i = 0; - cm_publisher_reader = dds_create_reader(participant, DDS_BUILTIN_TOPIC_CMPUBLISHER, NULL, NULL); - PRINTD("CMPublisher Reader Create: %s\n", dds_err_str(cm_publisher_reader)); - reader_wait = dds_reader_wait_for_historical_data(cm_publisher_reader, DDS_SECS(5)); - PRINTD("reader wait status: %d, %s \n", reader_wait, dds_err_str(reader_wait)); - while(true){ - int status = 0; - zero(cm_publisher_samples, MAX_SAMPLES); - status = dds_take_mask(cm_publisher_reader, (void**)cm_publisher_samples, info, MAX_SAMPLES, MAX_SAMPLES, states); - PRINTD("DDS reading samples returns %d \n", status); - for(i = 0; i < status; i++) { - DDS_CMPublisherBuiltinTopicData *data = cm_publisher_samples[i]; - fprintf(fp,"CMPUBLISHER:\n"); - fprintf(fp," key = %u:%u:%u \n", (unsigned) data->key[0], (unsigned) data->key[1], (unsigned) data->key[2]); - fprintf(fp," participant_key = %u:%u:%u\n", (unsigned) data->key[0], (unsigned) data->key[1], (unsigned) data->key[2]); - fprintf(fp," name = %s\n", data->name); - qp_entity_factory(&data->entity_factory,fp); - qp_partition(&data->partition,fp); - qp_product_data(&data->product,fp); - } - if(status > 0) { - status = dds_return_loan(cm_publisher_reader, (void**)cm_publisher_samples, status); - } - if(status <= 0){ - break; - } - } -} - -void print_cm_subscriber(FILE *fp){ - DDS_CMSubscriberBuiltinTopicData * cm_subscriber_samples[10]; - dds_entity_t cm_subscriber_reader; - int i = 0; - cm_subscriber_reader = dds_create_reader(participant, DDS_BUILTIN_TOPIC_CMSUBSCRIBER, NULL, NULL); - PRINTD("CMSubscriber Reader Create: %s\n", dds_err_str(cm_subscriber_reader)); - reader_wait = dds_reader_wait_for_historical_data(cm_subscriber_reader, DDS_SECS(5)); - PRINTD("reader wait status: %d, %s \n", reader_wait, dds_err_str(reader_wait)); - while(true){ - int status = 0; - zero(cm_subscriber_samples, MAX_SAMPLES); - status = dds_take_mask(cm_subscriber_reader, (void**)cm_subscriber_samples, info, MAX_SAMPLES, MAX_SAMPLES, states); - PRINTD("DDS reading samples returns %d \n", status); - for(i = 0; i < status; i++) { - DDS_CMSubscriberBuiltinTopicData *data = cm_subscriber_samples[i]; - fprintf(fp,"CMSUBSCRIBER:\n"); - fprintf(fp," key = %u:%u:%u \n", (unsigned) data->key[0], (unsigned) data->key[1], (unsigned) data->key[2]); - fprintf(fp," participant_key = %u:%u:%u\n", (unsigned) data->participant_key[0], (unsigned) data->participant_key[1], (unsigned) data->participant_key[2]); - fprintf(fp," name = %s\n", data->name); - qp_entity_factory(&data->entity_factory,fp); - qp_partition(&data->partition,fp); - qp_share(&data->share,fp); - qp_product_data(&data->product,fp); - } - if(status > 0) { - status = dds_return_loan(cm_subscriber_reader, (void**)cm_subscriber_samples, status); - } - if(status <= 0){ - break; - } - } -} - -void print_cm_datawriter(FILE *fp){ - DDS_CMDataWriterBuiltinTopicData * cm_datawriter_samples[10]; - dds_entity_t cm_datawriter_reader; - int i = 0; - cm_datawriter_reader = dds_create_reader(participant, DDS_BUILTIN_TOPIC_CMDATAWRITER, NULL, NULL); - PRINTD("CMDataWriter Reader Create: %s\n", dds_err_str(cm_datawriter_reader)); - reader_wait = dds_reader_wait_for_historical_data(cm_datawriter_reader, DDS_SECS(5)); - PRINTD("reader wait status: %d, %s \n", reader_wait, dds_err_str(reader_wait)); - while(true){ - int status = 0; - zero(cm_datawriter_samples, MAX_SAMPLES); - status = dds_take_mask(cm_datawriter_reader, (void**)cm_datawriter_samples, info, MAX_SAMPLES, MAX_SAMPLES, states); - PRINTD("DDS reading samples returns %d \n", status); - for(i = 0; i < status; i++) { - DDS_CMDataWriterBuiltinTopicData *data = cm_datawriter_samples[i]; - fprintf(fp,"CMDATAWRITER:\n"); - fprintf(fp," key = %u:%u:%u \n", (unsigned) data->key[0], (unsigned) data->key[1], (unsigned) data->key[2]); - fprintf(fp," publisher_key = %u:%u:%u\n", (unsigned) data->publisher_key[0], (unsigned) data->publisher_key[1], (unsigned) data->publisher_key[2]); - fprintf(fp," name = %s\n", data->name); - qp_history (&data->history,fp); - qp_resource_limits (&data->resource_limits,fp); - qp_writer_data_lifecycle (&data->writer_data_lifecycle,fp); - qp_product_data (&data->product,fp); - } - if(status > 0) { - status = dds_return_loan(cm_datawriter_reader, (void**)cm_datawriter_samples, status); - } - if(status <= 0){ - break; - } - } -} - -void print_cm_datareader(FILE *fp){ - DDS_CMDataReaderBuiltinTopicData * cm_datareader_samples[10]; - dds_entity_t cm_datareader_reader; - int i = 0; - cm_datareader_reader = dds_create_reader(participant, DDS_BUILTIN_TOPIC_CMDATAREADER, NULL, NULL); - PRINTD("CMDataReader Reader Create: %s\n", dds_err_str(cm_datareader_reader)); - reader_wait = dds_reader_wait_for_historical_data(cm_datareader_reader, DDS_SECS(5)); - PRINTD("reader wait status: %d, %s \n", reader_wait, dds_err_str(reader_wait)); - while(true){ - int status = 0; - zero(cm_datareader_samples, MAX_SAMPLES); - status = dds_take_mask(cm_datareader_reader, (void**)cm_datareader_samples, info, MAX_SAMPLES, MAX_SAMPLES, states); - PRINTD("DDS reading samples returns %d \n", status); - for(i = 0; i < status; i++) { - DDS_CMDataReaderBuiltinTopicData *data = cm_datareader_samples[i]; - fprintf(fp,"CMDATAREADER:\n"); - fprintf(fp," key = %u:%u:%u \n", (unsigned) data->key[0], (unsigned) data->key[1], (unsigned) data->key[2]); - fprintf(fp," subscriber_key = %u:%u:%u\n", (unsigned) data->subscriber_key[0], (unsigned) data->subscriber_key[1], (unsigned) data->subscriber_key[2]); - fprintf(fp," name = %s\n", data->name); - qp_history (&data->history,fp); - qp_resource_limits (&data->resource_limits,fp); - qp_reader_data_lifecycle (&data->reader_data_lifecycle,fp); - qp_subscription_keys (&data->subscription_keys,fp); - qp_reader_lifespan (&data->reader_lifespan,fp); - qp_share (&data->share,fp); - qp_product_data (&data->product,fp); - } - if(status > 0) { - status = dds_return_loan(cm_datareader_reader, (void**)cm_datareader_samples, status); - } - if(status <= 0){ - break; - } - } -} - -void usage(){ - /*describe the default options*/ - size_t tpindex; - printf("\n OPTIONS:\n"); - printf("-f -- write to file\n"); - printf("-a -- all topics\n"); - printf("\nTOPICS\n"); - for(tpindex = 0; tpindex < TOPICTAB_SIZE; tpindex++){ - printf("%s\n", topictab[tpindex].name); - } -} - -int main(int argc, char **argv){ - FILE *fp = NULL; - int flags = 0; - int j; - size_t index; - char *fname = NULL; - if(argc == 1){ - usage(); - } - int choice=0; - while((choice = os_getopt(argc,argv,"f:a")) != -1) - { - switch(choice) - { - case 'f': - fname = os_get_optarg(); - if(fname != NULL){ - - PRINTD("opening file %s \n", fname); - fp = fopen(fname, "w"); - if(fp == NULL) - { - printf("file does not exist\n"); - exit(1); - } - } - break; - case 'a': - for(index=0; index