Consistent code formatting for the core code

Code formatting was quite a mess (different indentation, completely
different ideas on where opening braces should go, spacing in various
places, early out versus single return or goto-based error handling,
&c.).  This commit cleans it up.

A few doxygen comment fixes allowed turning on Clang's warnings for
doxygen comments, so those are no enabled by default as least on
Xcode-based builds.

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2019-05-23 20:40:51 +02:00 committed by eboasson
parent 19aec98b8a
commit 13480616e0
56 changed files with 2856 additions and 4542 deletions

View file

@ -130,6 +130,7 @@ if(${CMAKE_GENERATOR} STREQUAL "Xcode")
set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_PARAMETER YES) set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_PARAMETER YES)
set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VALUE YES) set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VALUE YES)
set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VARIABLE YES) set (CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VARIABLE YES)
set (CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_DOCUMENTATION_COMMENTS YES)
endif() endif()
# Make it easy to enable one of Clang's/gcc's analyzers, and default to using # Make it easy to enable one of Clang's/gcc's analyzers, and default to using

View file

@ -74,6 +74,7 @@ PREPEND(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src"
dds__whc.h dds__whc.h
dds__whc_builtintopic.h dds__whc_builtintopic.h
dds__serdata_builtintopic.h dds__serdata_builtintopic.h
dds__get_status.h
) )
generate_export_header( generate_export_header(

View file

@ -313,7 +313,7 @@ dds_delete(dds_entity_t entity);
* For instance, it will return the Publisher that was used when * For instance, it will return the Publisher that was used when
* creating a DataWriter (when that DataWriter was provided here). * creating a DataWriter (when that DataWriter was provided here).
* *
* @param[in] entity Entity from which to get its publisher. * @param[in] writer Entity from which to get its publisher.
* *
* @returns A valid entity or an error code. * @returns A valid entity or an error code.
* *
@ -361,7 +361,7 @@ dds_get_subscriber(dds_entity_t entity);
* For instance, it will return the DataReader that was used when * For instance, it will return the DataReader that was used when
* creating a ReadCondition (when that ReadCondition was provided here). * creating a ReadCondition (when that ReadCondition was provided here).
* *
* @param[in] entity Entity from which to get its datareader. * @param[in] condition Entity from which to get its datareader.
* *
* @returns A valid reader handle or an error code. * @returns A valid reader handle or an error code.
* *
@ -502,7 +502,7 @@ dds_get_status_changes(dds_entity_t entity, uint32_t *status);
* This operation returns the status enabled on the entity * This operation returns the status enabled on the entity
* *
* @param[in] entity Entity to get the status. * @param[in] entity Entity to get the status.
* @param[out] status Status set on the entity. * @param[out] mask Mask of enabled statuses set on the entity.
* *
* @returns A dds_return_t indicating success or failure. * @returns A dds_return_t indicating success or failure.
* *
@ -952,6 +952,8 @@ dds_create_topic(
const dds_qos_t *qos, const dds_qos_t *qos,
const dds_listener_t *listener); const dds_listener_t *listener);
struct ddsi_sertopic;
struct nn_plist;
/** /**
* @brief Creates a new topic with arbitrary type handling. * @brief Creates a new topic with arbitrary type handling.
* *
@ -972,8 +974,6 @@ dds_create_topic(
* Either participant, descriptor, name or qos is invalid. * Either participant, descriptor, name or qos is invalid.
*/ */
/* TODO: Check list of retcodes is complete. */ /* TODO: Check list of retcodes is complete. */
struct ddsi_sertopic;
struct nn_plist;
DDS_EXPORT dds_entity_t DDS_EXPORT dds_entity_t
dds_create_topic_arbitrary ( dds_create_topic_arbitrary (
dds_entity_t participant, dds_entity_t participant,
@ -1650,8 +1650,7 @@ dds_write_flush(dds_entity_t writer);
* @brief Write a CDR serialized value of a data instance * @brief Write a CDR serialized value of a data instance
* *
* @param[in] writer The writer entity. * @param[in] writer The writer entity.
* @param[in] cdr CDR serialized value to be written. * @param[in] serdata CDR serialized value to be written.
* @param[in] size Size (in bytes) of CDR encoded data to be written.
* *
* @returns A dds_return_t indicating success or failure. * @returns A dds_return_t indicating success or failure.
*/ */
@ -2604,7 +2603,7 @@ dds_take_mask_wl(
uint32_t maxs, uint32_t maxs,
uint32_t mask); uint32_t mask);
DDS_EXPORT int DDS_EXPORT dds_return_t
dds_takecdr( dds_takecdr(
dds_entity_t reader_or_condition, dds_entity_t reader_or_condition,
struct ddsi_serdata **buf, struct ddsi_serdata **buf,
@ -2898,7 +2897,7 @@ dds_read_next_wl(
* the memory is released so that the buffer can be reused during a successive read/take operation. * the memory is released so that the buffer can be reused during a successive read/take operation.
* When a condition is provided, the reader to which the condition belongs is looked up. * When a condition is provided, the reader to which the condition belongs is looked up.
* *
* @param[in] rd_or_cnd Reader or condition that belongs to a reader. * @param[in] reader_or_condition Reader or condition that belongs to a reader.
* @param[in] buf An array of (pointers to) samples. * @param[in] buf An array of (pointers to) samples.
* @param[in] bufsz The number of (pointers to) samples stored in buf. * @param[in] bufsz The number of (pointers to) samples stored in buf.
* *

View file

@ -212,8 +212,8 @@ dds_qos_merge (dds_qos_t * __restrict dst, const dds_qos_t * __restrict src);
* *
* Policies are copied from src to dst, unless src already has the policy set to a non-default value. * Policies are copied from src to dst, unless src already has the policy set to a non-default value.
* *
* @param[in,out] dst - Pointer to the destination qos structure * @param[in,out] a - Pointer to the destination qos structure
* @param[in] src - Pointer to the source qos structure * @param[in] b - Pointer to the source qos structure
*/ */
DDS_EXPORT bool DDS_EXPORT bool
dds_qos_equal (const dds_qos_t * __restrict a, const dds_qos_t * __restrict b); dds_qos_equal (const dds_qos_t * __restrict a, const dds_qos_t * __restrict b);
@ -448,7 +448,7 @@ dds_qset_destination_order (
* @brief Set the writer data-lifecycle policy of a qos structure * @brief Set the writer data-lifecycle policy of a qos structure
* *
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy * @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] autodispose_unregistered_instances - Automatic disposal of unregistered instances * @param[in] autodispose - Automatic disposal of unregistered instances
*/ */
DDS_EXPORT void DDS_EXPORT void
dds_qset_writer_data_lifecycle (dds_qos_t * __restrict qos, bool autodispose); dds_qset_writer_data_lifecycle (dds_qos_t * __restrict qos, bool autodispose);
@ -738,7 +738,7 @@ dds_qget_destination_order (
* @brief Get the writer data-lifecycle qos policy * @brief Get the writer data-lifecycle qos policy
* *
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy * @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] autodispose_unregistered_instances - Pointer that will store the autodispose unregistered instances enable value * @param[in,out] autodispose - Pointer that will store the autodispose unregistered instances enable value
* *
* @returns - false iff any of the arguments is invalid or the qos is not present in the qos object * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object
*/ */

View file

@ -0,0 +1,56 @@
/*
* Copyright(c) 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_GET_STATUS_H_
#define _DDS_GET_STATUS_H_
#include "dds/ddsrt/countargs.h"
#define DDS_GET_STATUS_LOCKED_RESET_1(status_, reset0_) \
(ent->m_##status_##_status.reset0_ = 0);
#define DDS_GET_STATUS_LOCKED_RESET_2(status_, reset0_, reset1_) \
(ent->m_##status_##_status.reset0_ = 0); \
(ent->m_##status_##_status.reset1_ = 0);
#define DDS_GET_STATUS_LOCKED_RESET_MSVC_WORKAROUND(x) x
#define DDS_GET_STATUS_LOCKED_RESET_N1(n_, status_, ...) \
DDS_GET_STATUS_LOCKED_RESET_MSVC_WORKAROUND (DDS_GET_STATUS_LOCKED_RESET_##n_ (status_, __VA_ARGS__))
#define DDS_GET_STATUS_LOCKED_RESET_N(n_, status_, ...) DDS_GET_STATUS_LOCKED_RESET_N1 (n_, status_, __VA_ARGS__)
#define DDS_GET_STATUS_LOCKED(ent_type_, status_, STATUS_, ...) \
static void dds_get_##status_##_status_locked (dds_##ent_type_ *ent, dds_##status_##_status_t *status) \
{ \
if (status) \
*status = ent->m_##status_##_status; \
if (ent->m_entity.m_status_enable & DDS_##STATUS_##_STATUS) { \
do { DDS_GET_STATUS_LOCKED_RESET_N (DDSRT_COUNT_ARGS (__VA_ARGS__), status_, __VA_ARGS__) } while (0); \
dds_entity_status_reset (&ent->m_entity, DDS_##STATUS_##_STATUS); \
} \
}
#define DDS_GET_STATUS_COMMON(ent_type_, status_) \
dds_return_t dds_get_##status_##_status (dds_entity_t entity, dds_##status_##_status_t *status) \
{ \
dds_##ent_type_ *ent; \
dds_return_t ret; \
if ((ret = dds_##ent_type_##_lock (entity, &ent)) != DDS_RETCODE_OK) \
return ret; \
ddsrt_mutex_lock (&ent->m_entity.m_observers_lock); \
dds_get_##status_##_status_locked (ent, status); \
ddsrt_mutex_unlock (&ent->m_entity.m_observers_lock); \
dds_##ent_type_##_unlock (ent); \
return DDS_RETCODE_OK; \
}
#define DDS_GET_STATUS(ent_type_, status_, STATUS_, ...) \
DDS_GET_STATUS_LOCKED (ent_type_, status_, STATUS_, __VA_ARGS__) \
DDS_GET_STATUS_COMMON (ent_type_, status_)
#endif

View file

@ -23,7 +23,7 @@ DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_subscriber, DDS_KIND_SUBSCRIBER)
dds_entity_t dds_entity_t
dds__create_subscriber_l( dds__create_subscriber_l(
struct dds_entity *participant, /* entity-lock must be held */ struct dds_participant *participant, /* entity-lock must be held */
const dds_qos_t *qos, const dds_qos_t *qos,
const dds_listener_t *listener); const dds_listener_t *listener);

View file

@ -21,8 +21,8 @@ extern "C" {
DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_topic, DDS_KIND_TOPIC) DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_topic, DDS_KIND_TOPIC)
DDS_EXPORT struct ddsi_sertopic * dds_topic_lookup (dds_domain * domain, const char * name); DDS_EXPORT struct ddsi_sertopic * dds_topic_lookup (dds_domain * domain, const char * name) ddsrt_nonnull_all;
DDS_EXPORT void dds_topic_free (dds_domainid_t domainid, struct ddsi_sertopic * st); DDS_EXPORT void dds_topic_free (dds_domainid_t domainid, struct ddsi_sertopic * st) ddsrt_nonnull_all;
#ifndef DDS_TOPIC_INTERN_FILTER_FN_DEFINED #ifndef DDS_TOPIC_INTERN_FILTER_FN_DEFINED
#define DDS_TOPIC_INTERN_FILTER_FN_DEFINED #define DDS_TOPIC_INTERN_FILTER_FN_DEFINED

View file

@ -104,12 +104,12 @@ dds_domain;
struct dds_entity; struct dds_entity;
typedef struct dds_entity_deriver { typedef struct dds_entity_deriver {
/* Close can be used to terminate (blocking) actions on a entity before actually deleting it. */ /* Close can be used to terminate (blocking) actions on a entity before actually deleting it. */
dds_return_t (*close)(struct dds_entity *e); dds_return_t (*close)(struct dds_entity *e) ddsrt_nonnull_all;
/* Delete is used to actually free the entity. */ /* Delete is used to actually free the entity. */
dds_return_t (*delete)(struct dds_entity *e); dds_return_t (*delete)(struct dds_entity *e) ddsrt_nonnull_all;
dds_return_t (*set_qos)(struct dds_entity *e, const dds_qos_t *qos, bool enabled); dds_return_t (*set_qos)(struct dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
dds_return_t (*validate_status)(uint32_t mask); dds_return_t (*validate_status)(uint32_t mask);
dds_return_t (*get_instance_hdl)(struct dds_entity *e, dds_instance_handle_t *i); dds_return_t (*get_instance_hdl)(struct dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all;
} }
dds_entity_deriver; dds_entity_deriver;

View file

@ -132,7 +132,7 @@ bool dds__validate_builtin_reader_qos (dds_entity_t topic, const dds_qos_t *qos)
} }
} }
static dds_entity_t dds__create_builtin_subscriber (dds_entity *participant) static dds_entity_t dds__create_builtin_subscriber (dds_participant *participant)
{ {
dds_qos_t *qos = dds__create_builtin_qos (); dds_qos_t *qos = dds__create_builtin_qos ();
dds_entity_t sub = dds__create_subscriber_l (participant, qos, NULL); dds_entity_t sub = dds__create_subscriber_l (participant, qos, NULL);
@ -153,7 +153,7 @@ dds_entity_t dds__get_builtin_subscriber (dds_entity_t e)
return ret; return ret;
if (p->m_builtin_subscriber <= 0) { if (p->m_builtin_subscriber <= 0) {
p->m_builtin_subscriber = dds__create_builtin_subscriber (&p->m_entity); p->m_builtin_subscriber = dds__create_builtin_subscriber (p);
} }
sub = p->m_builtin_subscriber; sub = p->m_builtin_subscriber;
dds_participant_unlock(p); dds_participant_unlock(p);

View file

@ -16,17 +16,13 @@
#include "dds__subscriber.h" #include "dds__subscriber.h"
#include "dds__publisher.h" #include "dds__publisher.h"
dds_return_t dds_return_t dds_begin_coherent (dds_entity_t entity)
dds_begin_coherent(
dds_entity_t entity)
{ {
static const dds_entity_kind_t kinds[] = { DDS_KIND_READER, DDS_KIND_WRITER, DDS_KIND_PUBLISHER, DDS_KIND_SUBSCRIBER }; static const dds_entity_kind_t kinds[] = { DDS_KIND_READER, DDS_KIND_WRITER, DDS_KIND_PUBLISHER, DDS_KIND_SUBSCRIBER };
return dds_generic_unimplemented_operation_manykinds (entity, sizeof (kinds) / sizeof (kinds[0]), kinds); return dds_generic_unimplemented_operation_manykinds (entity, sizeof (kinds) / sizeof (kinds[0]), kinds);
} }
dds_return_t dds_return_t dds_end_coherent (dds_entity_t entity)
dds_end_coherent(
dds_entity_t entity)
{ {
static const dds_entity_kind_t kinds[] = { DDS_KIND_READER, DDS_KIND_WRITER, DDS_KIND_PUBLISHER, DDS_KIND_SUBSCRIBER }; static const dds_entity_kind_t kinds[] = { DDS_KIND_READER, DDS_KIND_WRITER, DDS_KIND_PUBLISHER, DDS_KIND_SUBSCRIBER };
return dds_generic_unimplemented_operation_manykinds (entity, sizeof (kinds) / sizeof (kinds[0]), kinds); return dds_generic_unimplemented_operation_manykinds (entity, sizeof (kinds) / sizeof (kinds[0]), kinds);

View file

@ -12,27 +12,24 @@
#include "dds__domain.h" #include "dds__domain.h"
#include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_tkmap.h"
static int dds_domain_compare (const int32_t * a, const int32_t * b) static int dds_domain_compare (const void *va, const void *vb)
{ {
const int32_t *a = va;
const int32_t *b = vb;
return (*a == *b) ? 0 : (*a < *b) ? -1 : 1; return (*a == *b) ? 0 : (*a < *b) ? -1 : 1;
} }
const ddsrt_avl_treedef_t dds_domaintree_def = DDSRT_AVL_TREEDEF_INITIALIZER const ddsrt_avl_treedef_t dds_domaintree_def = DDSRT_AVL_TREEDEF_INITIALIZER (
( offsetof (dds_domain, m_node), offsetof (dds_domain, m_id), dds_domain_compare, 0);
offsetof (dds_domain, m_node),
offsetof (dds_domain, m_id),
(int (*) (const void *, const void *)) dds_domain_compare,
0
);
dds_domain * dds_domain_find_locked (dds_domainid_t id) dds_domain *dds_domain_find_locked (dds_domainid_t id)
{ {
return ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &id); return ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &id);
} }
dds_domain * dds_domain_create (dds_domainid_t id) dds_domain *dds_domain_create (dds_domainid_t id)
{ {
dds_domain * domain; dds_domain *domain;
ddsrt_mutex_lock (&dds_global.m_mutex); ddsrt_mutex_lock (&dds_global.m_mutex);
domain = dds_domain_find_locked (id); domain = dds_domain_find_locked (id);
if (domain == NULL) if (domain == NULL)
@ -47,7 +44,7 @@ dds_domain * dds_domain_create (dds_domainid_t id)
return domain; return domain;
} }
void dds_domain_free (dds_domain * domain) void dds_domain_free (dds_domain *domain)
{ {
ddsrt_mutex_lock (&dds_global.m_mutex); ddsrt_mutex_lock (&dds_global.m_mutex);
if (--domain->m_refc == 0) if (--domain->m_refc == 0)

View file

@ -18,7 +18,7 @@
#include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_thread.h"
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_guardcond) DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_guardcond)
dds_entity_t dds_create_guardcondition (dds_entity_t participant) dds_entity_t dds_create_guardcondition (dds_entity_t participant)
{ {

View file

@ -23,396 +23,307 @@
#include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_thread.h"
#include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_globals.h"
dds_return_t dds_return_t dds_writedispose (dds_entity_t writer, const void *data)
dds_writedispose(
dds_entity_t writer,
const void *data)
{ {
return dds_writedispose_ts(writer, data, dds_time()); return dds_writedispose_ts (writer, data, dds_time ());
} }
dds_return_t dds_return_t dds_dispose (dds_entity_t writer, const void *data)
dds_dispose(
dds_entity_t writer,
const void *data)
{ {
return dds_dispose_ts(writer, data, dds_time()); return dds_dispose_ts (writer, data, dds_time ());
} }
dds_return_t dds_return_t dds_dispose_ih (dds_entity_t writer, dds_instance_handle_t handle)
dds_dispose_ih(
dds_entity_t writer,
dds_instance_handle_t handle)
{ {
return dds_dispose_ih_ts(writer, handle, dds_time()); return dds_dispose_ih_ts (writer, handle, dds_time ());
} }
static struct ddsi_tkmap_instance* static struct ddsi_tkmap_instance *dds_instance_find (const dds_topic *topic, const void *data, const bool create)
dds_instance_find(
const dds_topic *topic,
const void *data,
const bool create)
{ {
struct ddsi_serdata *sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data); struct ddsi_serdata *sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data);
struct ddsi_tkmap_instance * inst = ddsi_tkmap_find (sd, false, create); struct ddsi_tkmap_instance *inst = ddsi_tkmap_find (sd, false, create);
ddsi_serdata_unref (sd); ddsi_serdata_unref (sd);
return inst; return inst;
} }
static void static void dds_instance_remove (const dds_topic *topic, const void *data, dds_instance_handle_t handle)
dds_instance_remove(
const dds_topic *topic,
const void *data,
dds_instance_handle_t handle)
{ {
struct ddsi_tkmap_instance * inst; struct ddsi_tkmap_instance *inst;
if (handle != DDS_HANDLE_NIL)
if (handle != DDS_HANDLE_NIL) inst = ddsi_tkmap_find_by_id (gv.m_tkmap, handle);
{ else
inst = ddsi_tkmap_find_by_id (gv.m_tkmap, handle); {
} assert (data);
else inst = dds_instance_find (topic, data, false);
{ }
assert (data); if (inst)
inst = dds_instance_find (topic, data, false); {
} ddsi_tkmap_instance_unref (inst);
if (inst) }
{
ddsi_tkmap_instance_unref (inst);
}
} }
static const dds_topic *dds_instance_info (dds_entity *e) static const dds_topic *dds_instance_info (dds_entity *e)
{ {
const dds_topic *topic; const dds_topic *topic;
switch (dds_entity_kind (e)) switch (dds_entity_kind (e))
{ {
case DDS_KIND_READER: case DDS_KIND_READER:
topic = ((dds_reader*) e)->m_topic; topic = ((dds_reader*) e)->m_topic;
break; break;
case DDS_KIND_WRITER: case DDS_KIND_WRITER:
topic = ((dds_writer*) e)->m_topic; topic = ((dds_writer*) e)->m_topic;
break; break;
default: default:
assert (0); assert (0);
topic = NULL; topic = NULL;
} }
return topic; return topic;
} }
static const dds_topic * dds_instance_info_by_hdl (dds_entity_t e) static const dds_topic *dds_instance_info_by_hdl (dds_entity_t e)
{ {
const dds_topic * topic = NULL; const dds_topic *topic;
dds_return_t rc; dds_entity *w_or_r;
dds_entity *w_or_r;
rc = dds_entity_lock(e, DDS_KIND_WRITER, &w_or_r); if (dds_entity_lock (e, DDS_KIND_DONTCARE, &w_or_r) != DDS_RETCODE_OK)
if (rc == DDS_RETCODE_ILLEGAL_OPERATION) return NULL;
{
rc = dds_entity_lock(e, DDS_KIND_READER, &w_or_r); switch (dds_entity_kind (w_or_r))
} {
if (rc != DDS_RETCODE_OK) case DDS_KIND_WRITER:
{ case DDS_KIND_READER:
return NULL; topic = dds_instance_info (w_or_r);
} break;
topic = dds_instance_info(w_or_r); default:
dds_entity_unlock(w_or_r); topic = NULL;
return topic; break;
}
dds_entity_unlock (w_or_r);
return topic;
} }
dds_return_t dds_return_t dds_register_instance (dds_entity_t writer, dds_instance_handle_t *handle, const void *data)
dds_register_instance(
dds_entity_t writer,
dds_instance_handle_t *handle,
const void *data)
{ {
struct thread_state1 * const ts1 = lookup_thread_state (); struct thread_state1 * const ts1 = lookup_thread_state ();
struct ddsi_tkmap_instance * inst; dds_writer *wr;
dds_writer *wr; dds_return_t ret;
dds_return_t ret;
if(data == NULL){ if (data == NULL || handle == NULL)
return DDS_RETCODE_BAD_PARAMETER; return DDS_RETCODE_BAD_PARAMETER;
}
if(handle == NULL){ if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
return DDS_RETCODE_BAD_PARAMETER;
}
ret = dds_writer_lock(writer, &wr);
if (ret != DDS_RETCODE_OK) {
goto err;
}
thread_state_awake (ts1);
inst = dds_instance_find (wr->m_topic, data, true);
if(inst != NULL){
*handle = inst->m_iid;
ret = DDS_RETCODE_OK;
} else {
ret = DDS_RETCODE_ERROR;
}
thread_state_asleep (ts1);
dds_writer_unlock(wr);
err:
return ret; return ret;
thread_state_awake (ts1);
struct ddsi_tkmap_instance * const inst = dds_instance_find (wr->m_topic, data, true);
if (inst == NULL)
ret = DDS_RETCODE_ERROR;
else
{
*handle = inst->m_iid;
ret = DDS_RETCODE_OK;
}
thread_state_asleep (ts1);
dds_writer_unlock (wr);
return ret;
} }
dds_return_t dds_return_t dds_unregister_instance (dds_entity_t writer, const void *data)
dds_unregister_instance(
dds_entity_t writer,
const void *data)
{ {
return dds_unregister_instance_ts (writer, data, dds_time()); return dds_unregister_instance_ts (writer, data, dds_time ());
} }
dds_return_t dds_return_t dds_unregister_instance_ih (dds_entity_t writer, dds_instance_handle_t handle)
dds_unregister_instance_ih(
dds_entity_t writer,
dds_instance_handle_t handle)
{ {
return dds_unregister_instance_ih_ts(writer, handle, dds_time()); return dds_unregister_instance_ih_ts (writer, handle, dds_time ());
} }
dds_return_t dds_return_t dds_unregister_instance_ts (dds_entity_t writer, const void *data, dds_time_t timestamp)
dds_unregister_instance_ts(
dds_entity_t writer,
const void *data,
dds_time_t timestamp)
{ {
struct thread_state1 * const ts1 = lookup_thread_state (); struct thread_state1 * const ts1 = lookup_thread_state ();
dds_return_t ret = DDS_RETCODE_OK; dds_return_t ret;
bool autodispose = true; bool autodispose = true;
dds_write_action action = DDS_WR_ACTION_UNREGISTER; dds_write_action action = DDS_WR_ACTION_UNREGISTER;
dds_writer *wr; dds_writer *wr;
if (data == NULL){ if (data == NULL || timestamp < 0)
ret = DDS_RETCODE_BAD_PARAMETER; return DDS_RETCODE_BAD_PARAMETER;
goto err;
}
if(timestamp < 0){
ret = DDS_RETCODE_BAD_PARAMETER;
goto err;
}
ret = dds_writer_lock(writer, &wr);
if (ret != DDS_RETCODE_OK) {
goto err;
}
if (wr->m_entity.m_qos) { if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose);
}
thread_state_awake (ts1);
if (autodispose) {
dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL);
action |= DDS_WR_DISPOSE_BIT;
}
ret = dds_write_impl (wr, data, timestamp, action);
thread_state_asleep (ts1);
dds_writer_unlock(wr);
err:
return ret; return ret;
if (wr->m_entity.m_qos)
dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose);
thread_state_awake (ts1);
if (autodispose)
{
dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL);
action |= DDS_WR_DISPOSE_BIT;
}
ret = dds_write_impl (wr, data, timestamp, action);
thread_state_asleep (ts1);
dds_writer_unlock (wr);
return ret;
} }
dds_return_t dds_return_t dds_unregister_instance_ih_ts (dds_entity_t writer, dds_instance_handle_t handle, dds_time_t timestamp)
dds_unregister_instance_ih_ts(
dds_entity_t writer,
dds_instance_handle_t handle,
dds_time_t timestamp)
{ {
struct thread_state1 * const ts1 = lookup_thread_state (); struct thread_state1 * const ts1 = lookup_thread_state ();
dds_return_t ret = DDS_RETCODE_OK; dds_return_t ret = DDS_RETCODE_OK;
bool autodispose = true; bool autodispose = true;
dds_write_action action = DDS_WR_ACTION_UNREGISTER; dds_write_action action = DDS_WR_ACTION_UNREGISTER;
dds_writer *wr; dds_writer *wr;
struct ddsi_tkmap_instance *tk; struct ddsi_tkmap_instance *tk;
ret = dds_writer_lock(writer, &wr); if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
if (ret != DDS_RETCODE_OK) {
goto err;
}
if (wr->m_entity.m_qos) {
dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose);
}
thread_state_awake (ts1);
if (autodispose) {
dds_instance_remove (wr->m_topic, NULL, handle);
action |= DDS_WR_DISPOSE_BIT;
}
tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle);
if (tk) {
struct ddsi_sertopic *tp = wr->m_topic->m_stopic;
void *sample = ddsi_sertopic_alloc_sample (tp);
ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL);
ddsi_tkmap_instance_unref (tk);
ret = dds_write_impl (wr, sample, timestamp, action);
ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL);
} else {
ret = DDS_RETCODE_PRECONDITION_NOT_MET;
}
thread_state_asleep (ts1);
dds_writer_unlock(wr);
err:
return ret; return ret;
if (wr->m_entity.m_qos)
dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose);
thread_state_awake (ts1);
if (autodispose)
{
dds_instance_remove (wr->m_topic, NULL, handle);
action |= DDS_WR_DISPOSE_BIT;
}
if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle)) == NULL)
ret = DDS_RETCODE_PRECONDITION_NOT_MET;
else
{
struct ddsi_sertopic *tp = wr->m_topic->m_stopic;
void *sample = ddsi_sertopic_alloc_sample (tp);
ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL);
ddsi_tkmap_instance_unref (tk);
ret = dds_write_impl (wr, sample, timestamp, action);
ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL);
}
thread_state_asleep (ts1);
dds_writer_unlock (wr);
return ret;
} }
dds_return_t dds_return_t dds_writedispose_ts (dds_entity_t writer, const void *data, dds_time_t timestamp)
dds_writedispose_ts(
dds_entity_t writer,
const void *data,
dds_time_t timestamp)
{ {
struct thread_state1 * const ts1 = lookup_thread_state (); struct thread_state1 * const ts1 = lookup_thread_state ();
dds_return_t ret; dds_return_t ret;
dds_writer *wr; dds_writer *wr;
ret = dds_writer_lock(writer, &wr);
if (ret == DDS_RETCODE_OK) {
thread_state_awake (ts1);
ret = dds_write_impl (wr, data, timestamp, DDS_WR_ACTION_WRITE_DISPOSE);
if (ret == DDS_RETCODE_OK) {
dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL);
}
thread_state_asleep (ts1);
dds_writer_unlock(wr);
}
if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
return ret; return ret;
thread_state_awake (ts1);
if ((ret = dds_write_impl (wr, data, timestamp, DDS_WR_ACTION_WRITE_DISPOSE)) == DDS_RETCODE_OK)
dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL);
thread_state_asleep (ts1);
dds_writer_unlock (wr);
return ret;
} }
static dds_return_t static dds_return_t dds_dispose_impl (dds_writer *wr, const void *data, dds_instance_handle_t handle, dds_time_t timestamp) ddsrt_nonnull_all;
dds_dispose_impl(
dds_writer *wr, static dds_return_t dds_dispose_impl (dds_writer *wr, const void *data, dds_instance_handle_t handle, dds_time_t timestamp)
const void *data,
dds_instance_handle_t handle,
dds_time_t timestamp)
{ {
dds_return_t ret; dds_return_t ret;
assert(thread_is_awake ()); assert (thread_is_awake ());
assert(wr); if ((ret = dds_write_impl (wr, data, timestamp, DDS_WR_ACTION_DISPOSE)) == DDS_RETCODE_OK)
ret = dds_write_impl(wr, data, timestamp, DDS_WR_ACTION_DISPOSE); dds_instance_remove (wr->m_topic, data, handle);
if (ret == DDS_RETCODE_OK) { return ret;
dds_instance_remove (wr->m_topic, data, handle); }
}
dds_return_t dds_dispose_ts (dds_entity_t writer, const void *data, dds_time_t timestamp)
{
struct thread_state1 * const ts1 = lookup_thread_state ();
dds_return_t ret;
dds_writer *wr;
if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
return ret; return ret;
thread_state_awake (ts1);
ret = dds_dispose_impl (wr, data, DDS_HANDLE_NIL, timestamp);
thread_state_asleep (ts1);
dds_writer_unlock(wr);
return ret;
} }
dds_return_t dds_return_t dds_dispose_ih_ts (dds_entity_t writer, dds_instance_handle_t handle, dds_time_t timestamp)
dds_dispose_ts(
dds_entity_t writer,
const void *data,
dds_time_t timestamp)
{ {
struct thread_state1 * const ts1 = lookup_thread_state (); struct thread_state1 * const ts1 = lookup_thread_state ();
dds_return_t ret; dds_return_t ret;
dds_writer *wr; dds_writer *wr;
ret = dds_writer_lock(writer, &wr);
if (ret == DDS_RETCODE_OK) {
thread_state_awake (ts1);
ret = dds_dispose_impl(wr, data, DDS_HANDLE_NIL, timestamp);
thread_state_asleep (ts1);
dds_writer_unlock(wr);
}
if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
return ret; return ret;
struct ddsi_tkmap_instance *tk;
thread_state_awake (ts1);
if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle)) == NULL)
ret = DDS_RETCODE_PRECONDITION_NOT_MET;
else
{
struct ddsi_sertopic *tp = wr->m_topic->m_stopic;
void *sample = ddsi_sertopic_alloc_sample (tp);
ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL);
ddsi_tkmap_instance_unref (tk);
ret = dds_dispose_impl (wr, sample, handle, timestamp);
ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL);
}
thread_state_asleep (ts1);
dds_writer_unlock (wr);
return ret;
} }
dds_return_t dds_instance_handle_t dds_lookup_instance (dds_entity_t entity, const void *data)
dds_dispose_ih_ts(
dds_entity_t writer,
dds_instance_handle_t handle,
dds_time_t timestamp)
{ {
struct thread_state1 * const ts1 = lookup_thread_state (); struct thread_state1 * const ts1 = lookup_thread_state ();
dds_return_t ret; dds_instance_handle_t ih = DDS_HANDLE_NIL;
dds_writer *wr; const dds_topic *topic;
struct ddsi_serdata *sd;
ret = dds_writer_lock(writer, &wr); if (data == NULL)
if (ret == DDS_RETCODE_OK) { return DDS_HANDLE_NIL;
struct ddsi_tkmap_instance *tk;
thread_state_awake (ts1);
if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle)) != NULL) {
struct ddsi_sertopic *tp = wr->m_topic->m_stopic;
void *sample = ddsi_sertopic_alloc_sample (tp);
ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL);
ddsi_tkmap_instance_unref (tk);
ret = dds_dispose_impl (wr, sample, handle, timestamp);
ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL);
} else {
ret = DDS_RETCODE_PRECONDITION_NOT_MET;
}
thread_state_asleep (ts1);
dds_writer_unlock(wr);
}
return ret; if ((topic = dds_instance_info_by_hdl (entity)) == NULL)
return DDS_HANDLE_NIL;
thread_state_awake (ts1);
sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data);
ih = ddsi_tkmap_lookup (gv.m_tkmap, sd);
ddsi_serdata_unref (sd);
thread_state_asleep (ts1);
return ih;
} }
dds_instance_handle_t dds_instance_handle_t dds_instance_lookup (dds_entity_t entity, const void *data)
dds_lookup_instance(
dds_entity_t entity,
const void *data)
{ {
struct thread_state1 * const ts1 = lookup_thread_state (); return dds_lookup_instance (entity, data);
dds_instance_handle_t ih = DDS_HANDLE_NIL;
const dds_topic * topic;
struct ddsi_tkmap * map = gv.m_tkmap;
struct ddsi_serdata *sd;
if(data == NULL){
goto err;
}
topic = dds_instance_info_by_hdl (entity);
if (topic) {
thread_state_awake (ts1);
sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data);
ih = ddsi_tkmap_lookup (map, sd);
ddsi_serdata_unref (sd);
thread_state_asleep (ts1);
}
err:
return ih;
} }
dds_instance_handle_t dds_return_t dds_instance_get_key (dds_entity_t entity, dds_instance_handle_t ih, void *data)
dds_instance_lookup (
dds_entity_t entity,
const void *data)
{ {
return dds_lookup_instance(entity, data); struct thread_state1 * const ts1 = lookup_thread_state ();
} dds_return_t ret;
const dds_topic *topic;
dds_return_t struct ddsi_tkmap_instance *tk;
dds_instance_get_key(
dds_entity_t entity, if (data == NULL)
dds_instance_handle_t ih, return DDS_RETCODE_BAD_PARAMETER;
void *data)
{ if ((topic = dds_instance_info_by_hdl (entity)) == NULL)
struct thread_state1 * const ts1 = lookup_thread_state (); return DDS_RETCODE_BAD_PARAMETER;
dds_return_t ret;
const dds_topic * topic; thread_state_awake (ts1);
struct ddsi_tkmap_instance * tk; if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, ih)) == NULL)
ret = DDS_RETCODE_BAD_PARAMETER;
if(data == NULL){ else
ret = DDS_RETCODE_BAD_PARAMETER; {
goto err; ddsi_sertopic_zero_sample (topic->m_stopic, data);
} ddsi_serdata_topicless_to_sample (topic->m_stopic, tk->m_sample, data, NULL, NULL);
ddsi_tkmap_instance_unref (tk);
topic = dds_instance_info_by_hdl (entity); ret = DDS_RETCODE_OK;
if(topic == NULL){ }
ret = DDS_RETCODE_BAD_PARAMETER; thread_state_asleep (ts1);
goto err; return ret;
}
thread_state_awake (ts1);
if ((tk = ddsi_tkmap_find_by_id(gv.m_tkmap, ih)) != NULL) {
ddsi_sertopic_zero_sample (topic->m_stopic, data);
ddsi_serdata_topicless_to_sample (topic->m_stopic, tk->m_sample, data, NULL, NULL);
ddsi_tkmap_instance_unref (tk);
ret = DDS_RETCODE_OK;
} else {
ret = DDS_RETCODE_BAD_PARAMETER;
}
thread_state_asleep (ts1);
err:
return ret;
} }

View file

@ -207,324 +207,169 @@ void dds_merge_listener (dds_listener_t * __restrict dst, const dds_listener_t *
void dds_listener_merge (dds_listener_t * __restrict dst, const dds_listener_t * __restrict src) void dds_listener_merge (dds_listener_t * __restrict dst, const dds_listener_t * __restrict src)
{ {
dds_merge_listener(dst, src); dds_merge_listener (dst, src);
} }
/************************************************************************************************ /************************************************************************************************
* Setters * Setters
************************************************************************************************/ ************************************************************************************************/
void void dds_lset_data_available (dds_listener_t * __restrict listener, dds_on_data_available_fn callback)
dds_lset_data_available (dds_listener_t * __restrict listener, dds_on_data_available_fn callback)
{ {
if (listener) { if (listener)
listener->on_data_available = callback; listener->on_data_available = callback;
} else {
DDS_ERROR("Argument listener is NULL\n");
}
} }
void void dds_lset_data_on_readers (dds_listener_t * __restrict listener, dds_on_data_on_readers_fn callback)
dds_lset_data_on_readers (dds_listener_t * __restrict listener, dds_on_data_on_readers_fn callback)
{ {
if (listener) { if (listener)
listener->on_data_on_readers = callback; listener->on_data_on_readers = callback;
} else {
DDS_ERROR("Argument listener is NULL\n");
}
} }
void void dds_lset_inconsistent_topic (dds_listener_t * __restrict listener, dds_on_inconsistent_topic_fn callback)
dds_lset_inconsistent_topic (dds_listener_t * __restrict listener, dds_on_inconsistent_topic_fn callback)
{ {
if (listener) { if (listener)
listener->on_inconsistent_topic = callback; listener->on_inconsistent_topic = callback;
} else {
DDS_ERROR("Argument listener is NULL\n");
}
} }
void void dds_lset_liveliness_changed (dds_listener_t * __restrict listener, dds_on_liveliness_changed_fn callback)
dds_lset_liveliness_changed (dds_listener_t * __restrict listener, dds_on_liveliness_changed_fn callback)
{ {
if (listener) { if (listener)
listener->on_liveliness_changed = callback; listener->on_liveliness_changed = callback;
} else {
DDS_ERROR("Argument listener is NULL\n");
}
} }
void void dds_lset_liveliness_lost (dds_listener_t * __restrict listener, dds_on_liveliness_lost_fn callback)
dds_lset_liveliness_lost (dds_listener_t * __restrict listener, dds_on_liveliness_lost_fn callback)
{ {
if (listener) { if (listener)
listener->on_liveliness_lost = callback; listener->on_liveliness_lost = callback;
} else {
DDS_ERROR("Argument listener is NULL\n");
}
} }
void void dds_lset_offered_deadline_missed (dds_listener_t * __restrict listener, dds_on_offered_deadline_missed_fn callback)
dds_lset_offered_deadline_missed (dds_listener_t * __restrict listener, dds_on_offered_deadline_missed_fn callback)
{ {
if (listener) { if (listener)
listener->on_offered_deadline_missed = callback; listener->on_offered_deadline_missed = callback;
} else {
DDS_ERROR("Argument listener is NULL\n");
}
} }
void void dds_lset_offered_incompatible_qos (dds_listener_t * __restrict listener, dds_on_offered_incompatible_qos_fn callback)
dds_lset_offered_incompatible_qos (dds_listener_t * __restrict listener, dds_on_offered_incompatible_qos_fn callback)
{ {
if (listener) { if (listener)
listener->on_offered_incompatible_qos = callback; listener->on_offered_incompatible_qos = callback;
} else {
DDS_ERROR("Argument listener is NULL\n");
}
} }
void void dds_lset_publication_matched (dds_listener_t * __restrict listener, dds_on_publication_matched_fn callback)
dds_lset_publication_matched (dds_listener_t * __restrict listener, dds_on_publication_matched_fn callback)
{ {
if (listener) { if (listener)
listener->on_publication_matched = callback; listener->on_publication_matched = callback;
} else {
DDS_ERROR("Argument listener is NULL");
}
} }
void void dds_lset_requested_deadline_missed (dds_listener_t * __restrict listener, dds_on_requested_deadline_missed_fn callback)
dds_lset_requested_deadline_missed (dds_listener_t * __restrict listener, dds_on_requested_deadline_missed_fn callback)
{ {
if (listener) { if (listener)
listener->on_requested_deadline_missed = callback; listener->on_requested_deadline_missed = callback;
} else {
DDS_ERROR("Argument listener is NULL\n");
}
} }
void void dds_lset_requested_incompatible_qos (dds_listener_t * __restrict listener, dds_on_requested_incompatible_qos_fn callback)
dds_lset_requested_incompatible_qos (dds_listener_t * __restrict listener, dds_on_requested_incompatible_qos_fn callback)
{ {
if (listener) { if (listener)
listener->on_requested_incompatible_qos = callback; listener->on_requested_incompatible_qos = callback;
} else {
DDS_ERROR("Argument listener is NULL\n");
}
} }
void void dds_lset_sample_lost (dds_listener_t * __restrict listener, dds_on_sample_lost_fn callback)
dds_lset_sample_lost (dds_listener_t * __restrict listener, dds_on_sample_lost_fn callback)
{ {
if (listener) { if (listener)
listener->on_sample_lost = callback; listener->on_sample_lost = callback;
} else {
DDS_ERROR("Argument listener is NULL\n");
}
} }
void void dds_lset_sample_rejected (dds_listener_t * __restrict listener, dds_on_sample_rejected_fn callback)
dds_lset_sample_rejected (dds_listener_t * __restrict listener, dds_on_sample_rejected_fn callback)
{ {
if (listener) { if (listener)
listener->on_sample_rejected = callback; listener->on_sample_rejected = callback;
} else {
DDS_ERROR("Argument listener is NULL\n");
}
} }
void void dds_lset_subscription_matched (dds_listener_t * __restrict listener, dds_on_subscription_matched_fn callback)
dds_lset_subscription_matched (dds_listener_t * __restrict listener, dds_on_subscription_matched_fn callback)
{ {
if (listener) { if (listener)
listener->on_subscription_matched = callback; listener->on_subscription_matched = callback;
} else {
DDS_ERROR("Argument listener is NULL\n");
}
} }
/************************************************************************************************ /************************************************************************************************
* Getters * Getters
************************************************************************************************/ ************************************************************************************************/
void void dds_lget_data_available (const dds_listener_t * __restrict listener, dds_on_data_available_fn *callback)
dds_lget_data_available (const dds_listener_t * __restrict listener, dds_on_data_available_fn *callback)
{ {
if(!callback){ if (callback && listener)
DDS_ERROR("Argument callback is NULL\n");
return ;
}
if (!listener) {
DDS_ERROR("Argument listener is NULL\n");
return ;
}
*callback = listener->on_data_available; *callback = listener->on_data_available;
} }
void void dds_lget_data_on_readers (const dds_listener_t * __restrict listener, dds_on_data_on_readers_fn *callback)
dds_lget_data_on_readers (const dds_listener_t * __restrict listener, dds_on_data_on_readers_fn *callback)
{ {
if(!callback){ if (callback && listener)
DDS_ERROR("Argument callback is NULL\n");
return ;
}
if (!listener) {
DDS_ERROR("Argument listener is NULL\n");
return ;
}
*callback = listener->on_data_on_readers; *callback = listener->on_data_on_readers;
} }
void dds_lget_inconsistent_topic (const dds_listener_t * __restrict listener, dds_on_inconsistent_topic_fn *callback) void dds_lget_inconsistent_topic (const dds_listener_t * __restrict listener, dds_on_inconsistent_topic_fn *callback)
{ {
if(!callback){ if (callback && listener)
DDS_ERROR("Argument callback is NULL\n");
return ;
}
if (!listener) {
DDS_ERROR("Argument listener is NULL\n");
return ;
}
*callback = listener->on_inconsistent_topic; *callback = listener->on_inconsistent_topic;
} }
void void dds_lget_liveliness_changed (const dds_listener_t * __restrict listener, dds_on_liveliness_changed_fn *callback)
dds_lget_liveliness_changed (const dds_listener_t * __restrict listener, dds_on_liveliness_changed_fn *callback)
{ {
if(!callback){ if (callback && listener)
DDS_ERROR("Argument callback is NULL\n");
return ;
}
if (!listener) {
DDS_ERROR("Argument listener is NULL\n");
return ;
}
*callback = listener->on_liveliness_changed; *callback = listener->on_liveliness_changed;
} }
void void dds_lget_liveliness_lost (const dds_listener_t * __restrict listener, dds_on_liveliness_lost_fn *callback)
dds_lget_liveliness_lost (const dds_listener_t * __restrict listener, dds_on_liveliness_lost_fn *callback)
{ {
if(!callback){ if (callback && listener)
DDS_ERROR("Argument callback is NULL\n");
return ;
}
if (!listener) {
DDS_ERROR("Argument listener is NULL\n");
return ;
}
*callback = listener->on_liveliness_lost; *callback = listener->on_liveliness_lost;
} }
void void dds_lget_offered_deadline_missed (const dds_listener_t * __restrict listener, dds_on_offered_deadline_missed_fn *callback)
dds_lget_offered_deadline_missed (const dds_listener_t * __restrict listener, dds_on_offered_deadline_missed_fn *callback)
{ {
if(!callback){ if (callback && listener)
DDS_ERROR("Argument callback is NULL\n");
return ;
}
if (!listener) {
DDS_ERROR("Argument listener is NULL\n");
return ;
}
*callback = listener->on_offered_deadline_missed; *callback = listener->on_offered_deadline_missed;
} }
void void dds_lget_offered_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_offered_incompatible_qos_fn *callback)
dds_lget_offered_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_offered_incompatible_qos_fn *callback)
{ {
if(!callback){ if (callback && listener)
DDS_ERROR("Argument callback is NULL\n");
return ;
}
if (!listener) {
DDS_ERROR("Argument listener is NULL\n");
return ;
}
*callback = listener->on_offered_incompatible_qos; *callback = listener->on_offered_incompatible_qos;
} }
void void dds_lget_publication_matched (const dds_listener_t * __restrict listener, dds_on_publication_matched_fn *callback)
dds_lget_publication_matched (const dds_listener_t * __restrict listener, dds_on_publication_matched_fn *callback)
{ {
if(!callback){ if (callback && listener)
DDS_ERROR("Argument callback is NULL\n");
return ;
}
if (!listener) {
DDS_ERROR("Argument listener is NULL\n");
return ;
}
*callback = listener->on_publication_matched; *callback = listener->on_publication_matched;
} }
void void dds_lget_requested_deadline_missed (const dds_listener_t * __restrict listener, dds_on_requested_deadline_missed_fn *callback)
dds_lget_requested_deadline_missed (const dds_listener_t * __restrict listener, dds_on_requested_deadline_missed_fn *callback)
{ {
if(!callback) { if (callback && listener)
DDS_ERROR("Argument callback is NULL\n");
return ;
}
if (!listener) {
DDS_ERROR("Argument listener is NULL\n");
return ;
}
*callback = listener->on_requested_deadline_missed; *callback = listener->on_requested_deadline_missed;
} }
void void dds_lget_requested_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_requested_incompatible_qos_fn *callback)
dds_lget_requested_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_requested_incompatible_qos_fn *callback)
{ {
if(!callback) { if (callback && listener)
DDS_ERROR("Argument callback is NULL\n");
return ;
}
if (!listener) {
DDS_ERROR("Argument listener is NULL\n");
return ;
}
*callback = listener->on_requested_incompatible_qos; *callback = listener->on_requested_incompatible_qos;
} }
void void dds_lget_sample_lost (const dds_listener_t *__restrict listener, dds_on_sample_lost_fn *callback)
dds_lget_sample_lost (const dds_listener_t *__restrict listener, dds_on_sample_lost_fn *callback)
{ {
if(!callback) { if (callback && listener)
DDS_ERROR("Argument callback is NULL\n");
return ;
}
if (!listener) {
DDS_ERROR("Argument listener is NULL\n");
return ;
}
*callback = listener->on_sample_lost; *callback = listener->on_sample_lost;
} }
void void dds_lget_sample_rejected (const dds_listener_t *__restrict listener, dds_on_sample_rejected_fn *callback)
dds_lget_sample_rejected (const dds_listener_t *__restrict listener, dds_on_sample_rejected_fn *callback)
{ {
if(!callback) { if (callback && listener)
DDS_ERROR("Argument callback is NULL\n");
return ;
}
if (!listener) {
DDS_ERROR("Argument listener is NULL\n");
return ;
}
*callback = listener->on_sample_rejected; *callback = listener->on_sample_rejected;
} }
void void dds_lget_subscription_matched (const dds_listener_t * __restrict listener, dds_on_subscription_matched_fn *callback)
dds_lget_subscription_matched (const dds_listener_t * __restrict listener, dds_on_subscription_matched_fn *callback)
{ {
if(!callback) { if (callback && listener)
DDS_ERROR("Argument callback is NULL\n");
return ;
}
if (!listener) {
DDS_ERROR("Argument listener is NULL\n");
return ;
}
*callback = listener->on_subscription_matched; *callback = listener->on_subscription_matched;
} }

View file

@ -21,260 +21,183 @@
#include "dds__participant.h" #include "dds__participant.h"
#include "dds__builtin.h" #include "dds__builtin.h"
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_participant) DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_participant)
#define DDS_PARTICIPANT_STATUS_MASK 0u #define DDS_PARTICIPANT_STATUS_MASK (0u)
/* List of created participants */ /* List of created participants */
static dds_entity *dds_pp_head = NULL;
static dds_entity * dds_pp_head = NULL; static dds_return_t dds_participant_status_validate (uint32_t mask)
static dds_return_t
dds_participant_status_validate(
uint32_t mask)
{ {
dds_return_t ret = DDS_RETCODE_OK; return (mask & ~DDS_PARTICIPANT_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK;
if (mask & ~(DDS_PARTICIPANT_STATUS_MASK)) {
ret = DDS_RETCODE_BAD_PARAMETER;
}
return ret;
} }
static dds_return_t static dds_return_t dds_participant_delete (dds_entity *e) ddsrt_nonnull_all;
dds_participant_delete(
dds_entity *e) static dds_return_t dds_participant_delete (dds_entity *e)
{ {
dds_entity *prev = NULL; assert (dds_entity_kind (e) == DDS_KIND_PARTICIPANT);
dds_entity *iter;
assert(e); thread_state_awake (lookup_thread_state ());
assert(dds_entity_kind(e) == DDS_KIND_PARTICIPANT); dds_domain_free (e->m_domain);
ddsrt_mutex_lock (&dds_global.m_mutex);
dds_entity *prev, *iter;
for (iter = dds_pp_head, prev = NULL; iter; prev = iter, iter = iter->m_next)
{
if (iter == e)
break;
}
assert (iter);
if (prev)
prev->m_next = iter->m_next;
else
dds_pp_head = iter->m_next;
ddsrt_mutex_unlock (&dds_global.m_mutex);
thread_state_asleep (lookup_thread_state ());
thread_state_awake (lookup_thread_state ()); /* Every dds_init needs a dds_fini. */
dds_fini ();
return DDS_RETCODE_OK;
}
dds_domain_free (e->m_domain); static dds_return_t dds_participant_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all;
static dds_return_t dds_participant_instance_hdl (dds_entity *e, dds_instance_handle_t *i)
{
*i = participant_instance_id (&e->m_guid);
return DDS_RETCODE_OK;
}
static dds_return_t dds_participant_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_participant_qos_validate (const dds_qos_t *qos, bool enabled)
{
(void)enabled;
if ((qos->present & QP_USER_DATA) && !validate_octetseq (&qos->user_data))
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy (&qos->entity_factory))
return DDS_RETCODE_INCONSISTENT_POLICY;
return DDS_RETCODE_OK;
}
static dds_return_t dds_participant_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_participant_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
{
dds_return_t ret;
(void)e;
if ((ret = dds_participant_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
return ret;
if (enabled) /* FIXME: changing QoS */
return DDS_RETCODE_UNSUPPORTED;
return ret;
}
dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_t *qos, const dds_listener_t *listener)
{
dds_entity_t ret;
nn_guid_t guid;
dds_participant * pp;
nn_plist_t plist;
dds_qos_t *new_qos = NULL;
/* Make sure DDS instance is initialized. */
if ((ret = dds_init (domain)) != DDS_RETCODE_OK)
goto err_dds_init;
/* Check domain id */
if ((ret = dds__check_domain (domain)) != DDS_RETCODE_OK)
goto err_domain_check;
/* Validate qos or use default if NULL */
if (qos && (ret = dds_participant_qos_validate (qos, false)) != DDS_RETCODE_OK)
goto err_qos_validation;
new_qos = dds_create_qos ();
if (qos != NULL)
(void) dds_copy_qos (new_qos, qos);
/* Translate qos */
nn_plist_init_empty (&plist);
dds_merge_qos (&plist.qos, new_qos);
thread_state_awake (lookup_thread_state ());
ret = new_participant (&guid, 0, &plist);
thread_state_asleep (lookup_thread_state ());
nn_plist_fini (&plist);
if (ret < 0)
{
ret = DDS_RETCODE_ERROR;
goto err_new_participant;
}
pp = dds_alloc (sizeof (*pp));
if ((ret = dds_entity_init (&pp->m_entity, NULL, DDS_KIND_PARTICIPANT, new_qos, listener, DDS_PARTICIPANT_STATUS_MASK)) < 0)
goto err_entity_init;
pp->m_entity.m_guid = guid;
pp->m_entity.m_domain = dds_domain_create (dds_domain_default ());
pp->m_entity.m_domainid = dds_domain_default ();
pp->m_entity.m_deriver.delete = dds_participant_delete;
pp->m_entity.m_deriver.set_qos = dds_participant_qos_set;
pp->m_entity.m_deriver.get_instance_hdl = dds_participant_instance_hdl;
pp->m_entity.m_deriver.validate_status = dds_participant_status_validate;
pp->m_builtin_subscriber = 0;
/* Add participant to extent */
ddsrt_mutex_lock (&dds_global.m_mutex);
pp->m_entity.m_next = dds_pp_head;
dds_pp_head = &pp->m_entity;
ddsrt_mutex_unlock (&dds_global.m_mutex);
return ret;
err_entity_init:
dds_free (pp);
err_new_participant:
dds_delete_qos (new_qos);
err_qos_validation:
err_domain_check:
dds_fini ();
err_dds_init:
return ret;
}
dds_entity_t dds_lookup_participant (dds_domainid_t domain_id, dds_entity_t *participants, size_t size)
{
ddsrt_mutex_t *init_mutex;
ddsrt_init ();
init_mutex = ddsrt_get_singleton_mutex ();
if ((participants != NULL && (size <= 0 || size >= INT32_MAX)) || (participants == NULL && size != 0))
{
ddsrt_fini ();
return DDS_RETCODE_BAD_PARAMETER;
}
if (participants)
participants[0] = 0;
dds_return_t ret = 0;
ddsrt_mutex_lock (init_mutex);
if (dds_global.m_init_count > 0)
{
ddsrt_mutex_lock (&dds_global.m_mutex); ddsrt_mutex_lock (&dds_global.m_mutex);
iter = dds_pp_head; for (dds_entity *iter = dds_pp_head; iter; iter = iter->m_next)
while (iter) { {
if (iter == e) { if (iter->m_domainid == domain_id)
if (prev) { {
prev->m_next = iter->m_next; if ((size_t) ret < size)
} else { participants[ret] = iter->m_hdllink.hdl;
dds_pp_head = iter->m_next; ret++;
} }
break;
}
prev = iter;
iter = iter->m_next;
} }
ddsrt_mutex_unlock (&dds_global.m_mutex); ddsrt_mutex_unlock (&dds_global.m_mutex);
}
assert (iter); ddsrt_mutex_unlock (init_mutex);
ddsrt_fini ();
thread_state_asleep (lookup_thread_state ()); return ret;
/* Every dds_init needs a dds_fini. */
dds_fini();
return DDS_RETCODE_OK;
}
static dds_return_t
dds_participant_instance_hdl(
dds_entity *e,
dds_instance_handle_t *i)
{
assert(e);
assert(i);
*i = (dds_instance_handle_t)participant_instance_id(&e->m_guid);
return DDS_RETCODE_OK;
}
static dds_return_t
dds_participant_qos_validate(
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = DDS_RETCODE_OK;
assert(qos);
(void)enabled;
/* Check consistency. */
if ((qos->present & QP_USER_DATA) && !validate_octetseq(&qos->user_data)) {
DDS_ERROR("User data QoS policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)) {
DDS_ERROR("Prismtech entity factory QoS policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
return ret;
}
static dds_return_t
dds_participant_qos_set(
dds_entity *e,
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = dds_participant_qos_validate(qos, enabled);
(void)e;
if (ret == DDS_RETCODE_OK) {
if (enabled) {
/* TODO: CHAM-95: DDSI does not support changing QoS policies. */
DDS_ERROR("Changing the participant QoS is not supported\n");
ret = DDS_RETCODE_UNSUPPORTED;
}
}
return ret;
}
dds_entity_t
dds_create_participant(
const dds_domainid_t domain,
const dds_qos_t *qos,
const dds_listener_t *listener)
{
int q_rc;
dds_return_t ret;
dds_entity_t e;
nn_guid_t guid;
dds_participant * pp;
nn_plist_t plist;
dds_qos_t * new_qos = NULL;
/* Make sure DDS instance is initialized. */
ret = dds_init(domain);
if (ret != DDS_RETCODE_OK) {
e = (dds_entity_t)ret;
goto fail_dds_init;
}
/* Check domain id */
ret = dds__check_domain (domain);
if (ret != DDS_RETCODE_OK) {
e = (dds_entity_t)ret;
goto fail_domain_check;
}
/* Validate qos */
if (qos) {
ret = dds_participant_qos_validate (qos, false);
if (ret != DDS_RETCODE_OK) {
e = (dds_entity_t)ret;
goto fail_qos_validation;
}
new_qos = dds_create_qos ();
/* Only returns failure when one of the qos args is NULL, which
* is not the case here. */
(void)dds_copy_qos(new_qos, qos);
} else {
/* Use default qos. */
new_qos = dds_create_qos ();
}
/* Translate qos */
nn_plist_init_empty(&plist);
dds_merge_qos (&plist.qos, new_qos);
thread_state_awake (lookup_thread_state ());
q_rc = new_participant (&guid, 0, &plist);
thread_state_asleep (lookup_thread_state ());
nn_plist_fini (&plist);
if (q_rc != 0) {
DDS_ERROR("Internal error");
e = DDS_RETCODE_ERROR;
goto fail_new_participant;
}
pp = dds_alloc (sizeof (*pp));
e = dds_entity_init (&pp->m_entity, NULL, DDS_KIND_PARTICIPANT, new_qos, listener, DDS_PARTICIPANT_STATUS_MASK);
if (e < 0) {
goto fail_entity_init;
}
pp->m_entity.m_guid = guid;
pp->m_entity.m_domain = dds_domain_create (dds_domain_default());
pp->m_entity.m_domainid = dds_domain_default();
pp->m_entity.m_deriver.delete = dds_participant_delete;
pp->m_entity.m_deriver.set_qos = dds_participant_qos_set;
pp->m_entity.m_deriver.get_instance_hdl = dds_participant_instance_hdl;
pp->m_entity.m_deriver.validate_status = dds_participant_status_validate;
pp->m_builtin_subscriber = 0;
/* Add participant to extent */
ddsrt_mutex_lock (&dds_global.m_mutex);
pp->m_entity.m_next = dds_pp_head;
dds_pp_head = &pp->m_entity;
ddsrt_mutex_unlock (&dds_global.m_mutex);
return e;
fail_entity_init:
dds_free(pp);
fail_new_participant:
dds_delete_qos(new_qos);
fail_qos_validation:
fail_domain_check:
dds_fini();
fail_dds_init:
return e;
}
dds_entity_t
dds_lookup_participant(
dds_domainid_t domain_id,
dds_entity_t *participants,
size_t size)
{
dds_return_t ret = 0;
ddsrt_mutex_t *init_mutex;
/* Be sure the DDS lifecycle resources are initialized. */
ddsrt_init();
init_mutex = ddsrt_get_singleton_mutex();
if ((participants != NULL) && ((size <= 0) || (size >= INT32_MAX))) {
DDS_ERROR("Array is given, but with invalid size\n");
ret = DDS_RETCODE_BAD_PARAMETER;
goto err;
}
if ((participants == NULL) && (size != 0)) {
DDS_ERROR("Size is given, but no array\n");
ret = DDS_RETCODE_BAD_PARAMETER;
goto err;
}
if(participants){
participants[0] = 0;
}
ddsrt_mutex_lock (init_mutex);
/* Check if dds is intialized. */
if (dds_global.m_init_count > 0) {
dds_entity* iter;
ddsrt_mutex_lock (&dds_global.m_mutex);
iter = dds_pp_head;
while (iter) {
if (iter->m_domainid == domain_id) {
if ((size_t)ret < size) {
participants[ret] = iter->m_hdllink.hdl;
}
ret++;
}
iter = iter->m_next;
}
ddsrt_mutex_unlock (&dds_global.m_mutex);
}
ddsrt_mutex_unlock (init_mutex);
err:
ddsrt_fini();
return ret;
} }

View file

@ -13,153 +13,102 @@
#include <string.h> #include <string.h>
#include "dds/ddsrt/misc.h" #include "dds/ddsrt/misc.h"
#include "dds__listener.h" #include "dds__listener.h"
#include "dds__participant.h"
#include "dds__publisher.h" #include "dds__publisher.h"
#include "dds__qos.h" #include "dds__qos.h"
#include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_entity.h"
#include "dds/version.h" #include "dds/version.h"
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_publisher) DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_publisher)
#define DDS_PUBLISHER_STATUS_MASK 0u #define DDS_PUBLISHER_STATUS_MASK (0u)
static dds_return_t static dds_return_t dds_publisher_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all;
dds_publisher_instance_hdl(
dds_entity *e, static dds_return_t dds_publisher_instance_hdl (dds_entity *e, dds_instance_handle_t *i)
dds_instance_handle_t *i)
{ {
(void)e; /* FIXME: Get/generate proper handle. */
(void)i; (void) e;
/* TODO: Get/generate proper handle. */ (void) i;
DDS_ERROR("Getting publisher instance handle is not supported\n"); return DDS_RETCODE_UNSUPPORTED;
}
static dds_return_t dds_publisher_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_publisher_qos_validate (const dds_qos_t *qos, bool enabled)
{
if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data))
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_PRESENTATION) && validate_presentation_qospolicy (&qos->presentation) < 0)
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_PARTITION) && !validate_stringseq (&qos->partition))
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy (&qos->entity_factory))
return DDS_RETCODE_INCONSISTENT_POLICY;
/* FIXME: Improve/check immutable check. */
if (enabled && (qos->present & QP_PRESENTATION))
return DDS_RETCODE_IMMUTABLE_POLICY;
return DDS_RETCODE_OK;
}
static dds_return_t dds_publisher_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_publisher_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
{
dds_return_t ret;
(void)e;
if ((ret = dds_publisher_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
return ret;
if (enabled) /* FIXME: QoS changes. */
return DDS_RETCODE_UNSUPPORTED; return DDS_RETCODE_UNSUPPORTED;
} return DDS_RETCODE_OK;
static dds_return_t
dds_publisher_qos_validate(
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = DDS_RETCODE_OK;
assert(qos);
/* Check consistency. */
if((qos->present & QP_GROUP_DATA) && !validate_octetseq(&qos->group_data)){
DDS_ERROR("Group data policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if((qos->present & QP_PRESENTATION) && (validate_presentation_qospolicy(&qos->presentation) != 0)){
DDS_ERROR("Presentation policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if((qos->present & QP_PARTITION) && !validate_stringseq(&qos->partition)){
DDS_ERROR("Partition policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)){
DDS_ERROR("Prismtech entity factory policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if(ret == DDS_RETCODE_OK && enabled && (qos->present & QP_PRESENTATION)){
/* TODO: Improve/check immutable check. */
DDS_ERROR("Presentation policy is immutable\n");
ret = DDS_RETCODE_IMMUTABLE_POLICY;
}
return ret;
}
static dds_return_t
dds_publisher_qos_set(
dds_entity *e,
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = dds_publisher_qos_validate(qos, enabled);
(void)e;
if (ret == DDS_RETCODE_OK) {
if (enabled) {
/* TODO: CHAM-95: DDSI does not support changing QoS policies. */
DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies yet\n");
ret = DDS_RETCODE_UNSUPPORTED;
}
}
return ret;
} }
static dds_return_t dds_publisher_status_validate (uint32_t mask) static dds_return_t dds_publisher_status_validate (uint32_t mask)
{ {
dds_return_t ret = DDS_RETCODE_OK; return (mask & ~DDS_PUBLISHER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK;
}
if (mask & ~(DDS_PUBLISHER_STATUS_MASK)) { dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qos, const dds_listener_t *listener)
DDS_ERROR("Invalid status mask\n"); {
ret = DDS_RETCODE_BAD_PARAMETER; dds_participant *par;
} dds_publisher *pub;
dds_entity_t hdl;
dds_qos_t *new_qos = NULL;
dds_return_t ret;
if (qos && (ret = dds_publisher_qos_validate (qos, false)) != DDS_RETCODE_OK)
return ret; return ret;
if ((ret = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK)
return ret;
if (qos)
{
new_qos = dds_create_qos ();
(void) dds_copy_qos (new_qos, qos);
}
pub = dds_alloc (sizeof (*pub));
hdl = dds_entity_init (&pub->m_entity, &par->m_entity, DDS_KIND_PUBLISHER, new_qos, listener, DDS_PUBLISHER_STATUS_MASK);
pub->m_entity.m_deriver.set_qos = dds_publisher_qos_set;
pub->m_entity.m_deriver.get_instance_hdl = dds_publisher_instance_hdl;
pub->m_entity.m_deriver.validate_status = dds_publisher_status_validate;
dds_participant_unlock (par);
return hdl;
} }
dds_entity_t dds_return_t dds_suspend (dds_entity_t publisher)
dds_create_publisher(
dds_entity_t participant,
const dds_qos_t *qos,
const dds_listener_t *listener)
{
dds_entity * par;
dds_publisher * pub;
dds_entity_t hdl;
dds_qos_t * new_qos = NULL;
dds_return_t ret;
ret = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par);
if (ret != DDS_RETCODE_OK) {
DDS_ERROR("Error occurred on locking participant\n");
hdl = ret;
goto lock_err;
}
/* Validate qos */
if (qos) {
ret = dds_publisher_qos_validate(qos, false);
if (ret != DDS_RETCODE_OK) {
hdl = ret;
goto qos_err;
}
new_qos = dds_create_qos ();
/* Only returns failure when one of the qos args is NULL, which
* is not the case here. */
(void)dds_copy_qos(new_qos, qos);
}
/* Create publisher */
pub = dds_alloc (sizeof (*pub));
hdl = dds_entity_init (&pub->m_entity, par, DDS_KIND_PUBLISHER, new_qos, listener, DDS_PUBLISHER_STATUS_MASK);
pub->m_entity.m_deriver.set_qos = dds_publisher_qos_set;
pub->m_entity.m_deriver.get_instance_hdl = dds_publisher_instance_hdl;
pub->m_entity.m_deriver.validate_status = dds_publisher_status_validate;
qos_err:
dds_entity_unlock(par);
lock_err:
return hdl;
}
DDS_EXPORT dds_return_t
dds_suspend(
dds_entity_t publisher)
{ {
return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER); return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER);
} }
dds_return_t dds_return_t dds_resume (dds_entity_t publisher)
dds_resume(
dds_entity_t publisher)
{ {
return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER); return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER);
} }
dds_return_t dds_return_t dds_wait_for_acks (dds_entity_t publisher_or_writer, dds_duration_t timeout)
dds_wait_for_acks(
dds_entity_t publisher_or_writer,
dds_duration_t timeout)
{ {
if (timeout < 0) if (timeout < 0)
return DDS_RETCODE_BAD_PARAMETER; return DDS_RETCODE_BAD_PARAMETER;
@ -167,23 +116,12 @@ dds_wait_for_acks(
return dds_generic_unimplemented_operation_manykinds (publisher_or_writer, sizeof (kinds) / sizeof (kinds[0]), kinds); return dds_generic_unimplemented_operation_manykinds (publisher_or_writer, sizeof (kinds) / sizeof (kinds[0]), kinds);
} }
dds_return_t dds_return_t dds_publisher_begin_coherent (dds_entity_t publisher)
dds_publisher_begin_coherent(
dds_entity_t e)
{ {
/* TODO: CHAM-124 Currently unsupported. */ return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER);
(void)e;
DDS_ERROR("Using coherency to get a coherent data set is not being supported yet\n");
return DDS_RETCODE_UNSUPPORTED;
} }
dds_return_t dds_return_t dds_publisher_end_coherent (dds_entity_t publisher)
dds_publisher_end_coherent(
dds_entity_t e)
{ {
/* TODO: CHAM-124 Currently unsupported. */ return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER);
(void)e;
DDS_ERROR("Using coherency to get a coherent data set is not being supported yet\n");
return DDS_RETCODE_UNSUPPORTED;
} }

File diff suppressed because it is too large Load diff

View file

@ -21,32 +21,27 @@
#include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_serdata.h"
#include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/ddsi_sertopic.h"
DDS_EXPORT dds_entity_t dds_entity_t dds_create_querycondition (dds_entity_t reader, uint32_t mask, dds_querycondition_filter_fn filter)
dds_create_querycondition(
dds_entity_t reader,
uint32_t mask,
dds_querycondition_filter_fn filter)
{ {
dds_return_t rc;
dds_reader *r;
if ((rc = dds_reader_lock (reader, &r)) != DDS_RETCODE_OK)
return rc;
else
{
dds_entity_t hdl; dds_entity_t hdl;
dds_return_t rc; dds_readcond *cond = dds_create_readcond (r, DDS_KIND_COND_QUERY, mask, filter);
dds_reader *r; assert (cond);
const bool success = (cond->m_entity.m_deriver.delete != 0);
rc = dds_reader_lock(reader, &r); dds_reader_unlock (r);
if (rc == DDS_RETCODE_OK) { if (success)
dds_readcond *cond = dds_create_readcond(r, DDS_KIND_COND_QUERY, mask, filter); hdl = cond->m_entity.m_hdllink.hdl;
assert(cond); else
const bool success = (cond->m_entity.m_deriver.delete != 0); {
dds_reader_unlock(r); dds_delete (cond->m_entity.m_hdllink.hdl);
if (success) { hdl = DDS_RETCODE_OUT_OF_RESOURCES;
hdl = cond->m_entity.m_hdllink.hdl;
} else {
dds_delete (cond->m_entity.m_hdllink.hdl);
hdl = DDS_RETCODE_OUT_OF_RESOURCES;
}
} else {
DDS_ERROR("Error occurred on locking reader\n");
hdl = rc;
} }
return hdl; return hdl;
}
} }

File diff suppressed because it is too large Load diff

View file

@ -18,65 +18,56 @@
#include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_thread.h"
static dds_return_t static dds_return_t dds_readcond_delete (dds_entity *e) ddsrt_nonnull_all;
dds_readcond_delete(
dds_entity *e) static dds_return_t dds_readcond_delete (dds_entity *e)
{ {
dds_rhc_remove_readcondition((dds_readcond*)e); dds_rhc_remove_readcondition ((dds_readcond *) e);
return DDS_RETCODE_OK; return DDS_RETCODE_OK;
} }
dds_readcond* dds_readcond *dds_create_readcond (dds_reader *rd, dds_entity_kind_t kind, uint32_t mask, dds_querycondition_filter_fn filter)
dds_create_readcond(
dds_reader *rd,
dds_entity_kind_t kind,
uint32_t mask,
dds_querycondition_filter_fn filter)
{ {
dds_readcond * cond = dds_alloc(sizeof(*cond)); dds_readcond *cond = dds_alloc (sizeof (*cond));
assert((kind == DDS_KIND_COND_READ && filter == 0) || (kind == DDS_KIND_COND_QUERY && filter != 0)); assert ((kind == DDS_KIND_COND_READ && filter == 0) || (kind == DDS_KIND_COND_QUERY && filter != 0));
(void) dds_entity_init(&cond->m_entity, (dds_entity*)rd, kind, NULL, NULL, 0); (void) dds_entity_init (&cond->m_entity, &rd->m_entity, kind, NULL, NULL, 0);
cond->m_entity.m_deriver.delete = dds_readcond_delete; cond->m_entity.m_deriver.delete = dds_readcond_delete;
cond->m_rhc = rd->m_rd->rhc; cond->m_rhc = rd->m_rd->rhc;
cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE; cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE;
cond->m_view_states = mask & DDS_ANY_VIEW_STATE; cond->m_view_states = mask & DDS_ANY_VIEW_STATE;
cond->m_instance_states = mask & DDS_ANY_INSTANCE_STATE; cond->m_instance_states = mask & DDS_ANY_INSTANCE_STATE;
cond->m_rd_guid = rd->m_entity.m_guid; cond->m_rd_guid = rd->m_entity.m_guid;
if (kind == DDS_KIND_COND_QUERY) { if (kind == DDS_KIND_COND_QUERY)
cond->m_query.m_filter = filter; {
cond->m_query.m_qcmask = 0; cond->m_query.m_filter = filter;
} cond->m_query.m_qcmask = 0;
if (!dds_rhc_add_readcondition (cond)) { }
/* FIXME: current entity management code can't deal with an error late in the creation of the if (!dds_rhc_add_readcondition (cond))
entity because it doesn't allow deleting it again ... instead use a hack to signal a problem {
to the caller and let that one handle it. */ /* FIXME: current entity management code can't deal with an error late in the creation of the
cond->m_entity.m_deriver.delete = 0; entity because it doesn't allow deleting it again ... instead use a hack to signal a problem
} to the caller and let that one handle it. */
return cond; cond->m_entity.m_deriver.delete = 0;
}
return cond;
} }
dds_entity_t dds_entity_t dds_create_readcondition (dds_entity_t reader, uint32_t mask)
dds_create_readcondition(
dds_entity_t reader,
uint32_t mask)
{ {
dds_reader *rd;
dds_return_t rc;
if ((rc = dds_reader_lock (reader, &rd)) != DDS_RETCODE_OK)
return rc;
else
{
dds_entity_t hdl; dds_entity_t hdl;
dds_reader * rd; dds_readcond *cond = dds_create_readcond(rd, DDS_KIND_COND_READ, mask, 0);
dds_return_t rc; assert (cond);
assert (cond->m_entity.m_deriver.delete);
rc = dds_reader_lock(reader, &rd); hdl = cond->m_entity.m_hdllink.hdl;
if (rc == DDS_RETCODE_OK) { dds_reader_unlock (rd);
dds_readcond *cond = dds_create_readcond(rd, DDS_KIND_COND_READ, mask, 0);
assert(cond);
assert(cond->m_entity.m_deriver.delete);
hdl = cond->m_entity.m_hdllink.hdl;
dds_reader_unlock(rd);
} else {
DDS_ERROR("Error occurred on locking reader\n");
hdl = rc;
}
return hdl; return hdl;
}
} }
dds_entity_t dds_get_datareader (dds_entity_t condition) dds_entity_t dds_get_datareader (dds_entity_t condition)

View file

@ -13,6 +13,7 @@
#include <string.h> #include <string.h>
#include "dds/dds.h" #include "dds/dds.h"
#include "dds/version.h" #include "dds/version.h"
#include "dds/ddsrt/static_assert.h"
#include "dds__subscriber.h" #include "dds__subscriber.h"
#include "dds__reader.h" #include "dds__reader.h"
#include "dds__listener.h" #include "dds__listener.h"
@ -20,135 +21,96 @@
#include "dds__init.h" #include "dds__init.h"
#include "dds__rhc.h" #include "dds__rhc.h"
#include "dds__topic.h" #include "dds__topic.h"
#include "dds__get_status.h"
#include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_thread.h"
#include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_globals.h"
#include "dds__builtin.h" #include "dds__builtin.h"
#include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/ddsi_sertopic.h"
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_reader) DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_reader)
#define DDS_READER_STATUS_MASK \ #define DDS_READER_STATUS_MASK \
DDS_SAMPLE_REJECTED_STATUS |\ (DDS_SAMPLE_REJECTED_STATUS |\
DDS_LIVELINESS_CHANGED_STATUS |\ DDS_LIVELINESS_CHANGED_STATUS |\
DDS_REQUESTED_DEADLINE_MISSED_STATUS |\ DDS_REQUESTED_DEADLINE_MISSED_STATUS |\
DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS |\ DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS |\
DDS_DATA_AVAILABLE_STATUS |\ DDS_DATA_AVAILABLE_STATUS |\
DDS_SAMPLE_LOST_STATUS |\ DDS_SAMPLE_LOST_STATUS |\
DDS_SUBSCRIPTION_MATCHED_STATUS DDS_SUBSCRIPTION_MATCHED_STATUS)
static dds_return_t static dds_return_t dds_reader_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all;
dds_reader_instance_hdl(
dds_entity *e, static dds_return_t dds_reader_instance_hdl (dds_entity *e, dds_instance_handle_t *i)
dds_instance_handle_t *i)
{ {
assert(e); *i = reader_instance_id (&e->m_guid);
assert(i); return DDS_RETCODE_OK;
*i = (dds_instance_handle_t)reader_instance_id(&e->m_guid);
return DDS_RETCODE_OK;
} }
static dds_return_t static dds_return_t dds_reader_close (dds_entity *e) ddsrt_nonnull_all;
dds_reader_close(
dds_entity *e) static dds_return_t dds_reader_close (dds_entity *e)
{ {
dds_return_t ret = DDS_RETCODE_OK; dds_return_t ret = DDS_RETCODE_OK;
thread_state_awake (lookup_thread_state ());
if (delete_reader (&e->m_guid) != 0)
ret = DDS_RETCODE_ERROR;
thread_state_asleep (lookup_thread_state ());
return ret;
}
assert(e); static dds_return_t dds_reader_delete (dds_entity *e) ddsrt_nonnull_all;
thread_state_awake (lookup_thread_state ()); static dds_return_t dds_reader_delete (dds_entity *e)
if (delete_reader(&e->m_guid) != 0) { {
DDS_ERROR("Internal error"); dds_reader * const rd = (dds_reader *) e;
ret = DDS_RETCODE_ERROR; dds_return_t ret;
} if ((ret = dds_delete (rd->m_topic->m_entity.m_hdllink.hdl)) == DDS_RETCODE_OK)
thread_state_asleep (lookup_thread_state ()); {
/* Delete an implicitly created parent; for normal ones, this is expected
to fail with BAD_PARAMETER - FIXME: there must be a cleaner way */
ret = dds_delete_impl (e->m_parent->m_hdllink.hdl, true);
if (ret == DDS_RETCODE_BAD_PARAMETER)
ret = DDS_RETCODE_OK;
}
dds_free (rd->m_loan);
return ret;
}
static dds_return_t dds_reader_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_reader_qos_validate (const dds_qos_t *qos, bool enabled)
{
if (!dds_qos_validate_common (qos))
return DDS_RETCODE_ERROR;
if ((qos->present & QP_USER_DATA) && !validate_octetseq (&qos->user_data))
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_PRISMTECH_READER_DATA_LIFECYCLE) && validate_reader_data_lifecycle (&qos->reader_data_lifecycle) < 0)
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_TIME_BASED_FILTER) && validate_duration (&qos->time_based_filter.minimum_separation) < 0)
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits (&qos->history, &qos->resource_limits) < 0)
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_TIME_BASED_FILTER) && (qos->present & QP_DEADLINE) && !validate_deadline_and_timebased_filter (qos->deadline.deadline, qos->time_based_filter.minimum_separation))
return DDS_RETCODE_INCONSISTENT_POLICY;
return (enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK);
}
static dds_return_t dds_reader_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_reader_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
{
dds_return_t ret;
(void) e;
if ((ret = dds_reader_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
return ret; return ret;
/* FIXME: QoS changes. */
return (enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK);
} }
static dds_return_t static dds_return_t dds_reader_status_validate (uint32_t mask)
dds_reader_delete(
dds_entity *e)
{ {
dds_reader *rd = (dds_reader*)e; return (mask & ~DDS_READER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK;
dds_return_t ret;
assert(e);
ret = dds_delete(rd->m_topic->m_entity.m_hdllink.hdl);
if(ret == DDS_RETCODE_OK){
ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true);
if(ret == DDS_RETCODE_BAD_PARAMETER){
ret = DDS_RETCODE_OK;
}
}
dds_free(rd->m_loan);
return ret;
}
static dds_return_t
dds_reader_qos_validate(
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = DDS_RETCODE_OK;
assert(qos);
/* Check consistency. */
if(!dds_qos_validate_common(qos)) {
DDS_ERROR("Argument Qos is not valid\n");
ret = DDS_RETCODE_ERROR;
}
if((qos->present & QP_USER_DATA) && !(validate_octetseq (&qos->user_data))) {
DDS_ERROR("User data policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if((qos->present & QP_PRISMTECH_READER_DATA_LIFECYCLE) && (validate_reader_data_lifecycle (&qos->reader_data_lifecycle) != 0)) {
DDS_ERROR("Prismtech reader data lifecycle policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if((qos->present & QP_TIME_BASED_FILTER) && (validate_duration (&qos->time_based_filter.minimum_separation) != 0)) {
DDS_ERROR("Time based filter policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits (&qos->history, &qos->resource_limits) != 0)) {
DDS_ERROR("History and resource limits policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if((qos->present & QP_TIME_BASED_FILTER) && (qos->present & QP_DEADLINE) && !(validate_deadline_and_timebased_filter (qos->deadline.deadline, qos->time_based_filter.minimum_separation))) {
DDS_ERROR("Time based filter and deadline policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if(ret == DDS_RETCODE_OK && enabled) {
ret = dds_qos_validate_mutable_common(qos);
}
return ret;
}
static dds_return_t
dds_reader_qos_set(
dds_entity *e,
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = dds_reader_qos_validate(qos, enabled);
(void)e;
if (ret == DDS_RETCODE_OK) {
if (enabled) {
/* TODO: CHAM-95: DDSI does not support changing QoS policies. */
DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies\n");
ret = DDS_RETCODE_UNSUPPORTED;
}
}
return ret;
}
static dds_return_t
dds_reader_status_validate(
uint32_t mask)
{
return (mask & ~(DDS_READER_STATUS_MASK)) ?
DDS_RETCODE_BAD_PARAMETER :
DDS_RETCODE_OK;
} }
void dds_reader_data_available_cb (struct dds_reader *rd) void dds_reader_data_available_cb (struct dds_reader *rd)
@ -349,170 +311,157 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data)
ddsrt_mutex_unlock (&entity->m_observers_lock); ddsrt_mutex_unlock (&entity->m_observers_lock);
} }
dds_entity_t dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_entity_t topic, const dds_qos_t *qos, const dds_listener_t *listener)
dds_create_reader(
dds_entity_t participant_or_subscriber,
dds_entity_t topic,
const dds_qos_t *qos,
const dds_listener_t *listener)
{ {
dds_qos_t * rqos; dds_qos_t *rqos;
dds_subscriber * sub = NULL; dds_subscriber *sub = NULL;
dds_entity_t subscriber; dds_entity_t subscriber;
dds_reader * rd; dds_reader *rd;
struct rhc * rhc; struct rhc *rhc;
dds_topic * tp; dds_topic *tp;
dds_entity_t reader; dds_entity_t reader;
dds_entity_t t; dds_entity_t t;
dds_return_t ret = DDS_RETCODE_OK; dds_return_t ret = DDS_RETCODE_OK;
bool internal_topic; bool internal_topic;
switch (topic) { switch (topic)
case DDS_BUILTIN_TOPIC_DCPSPARTICIPANT: {
case DDS_BUILTIN_TOPIC_DCPSTOPIC: case DDS_BUILTIN_TOPIC_DCPSPARTICIPANT:
case DDS_BUILTIN_TOPIC_DCPSPUBLICATION: case DDS_BUILTIN_TOPIC_DCPSTOPIC:
case DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION: case DDS_BUILTIN_TOPIC_DCPSPUBLICATION:
internal_topic = true; case DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION:
subscriber = dds__get_builtin_subscriber(participant_or_subscriber); internal_topic = true;
t = dds__get_builtin_topic (subscriber, topic); subscriber = dds__get_builtin_subscriber (participant_or_subscriber);
break; t = dds__get_builtin_topic (subscriber, topic);
break;
default: { default: {
dds_entity *p_or_s; dds_entity *p_or_s;
if ((ret = dds_entity_claim (participant_or_subscriber, &p_or_s)) != DDS_RETCODE_OK) { if ((ret = dds_entity_claim (participant_or_subscriber, &p_or_s)) != DDS_RETCODE_OK)
return ret; return ret;
} if (dds_entity_kind (p_or_s) == DDS_KIND_PARTICIPANT)
if (dds_entity_kind (p_or_s) == DDS_KIND_PARTICIPANT) { subscriber = dds_create_subscriber (participant_or_subscriber, qos, NULL);
subscriber = dds_create_subscriber(participant_or_subscriber, qos, NULL); else
} else { subscriber = participant_or_subscriber;
subscriber = participant_or_subscriber; dds_entity_release (p_or_s);
} internal_topic = false;
dds_entity_release (p_or_s); t = topic;
internal_topic = false; break;
t = topic;
break;
}
} }
}
if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK) { if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK)
reader = ret; {
goto err_sub_lock; reader = ret;
} goto err_sub_lock;
}
if ((subscriber != participant_or_subscriber) && !internal_topic) { if (subscriber != participant_or_subscriber && !internal_topic)
/* Delete implicit subscriber if reader creation fails */ {
sub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT; /* Delete implicit subscriber if reader creation fails */
} sub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT;
}
ret = dds_topic_lock(t, &tp); if ((ret = dds_topic_lock (t, &tp)) != DDS_RETCODE_OK)
if (ret != DDS_RETCODE_OK) { {
DDS_ERROR("Error occurred on locking topic\n"); reader = ret;
reader = ret; goto err_tp_lock;
goto err_tp_lock; }
} assert (tp->m_stopic);
assert (tp->m_stopic); assert (sub->m_entity.m_domain == tp->m_entity.m_domain);
assert (sub->m_entity.m_domain == tp->m_entity.m_domain);
/* Merge qos from topic and subscriber */ /* Merge qos from topic and subscriber, dds_copy_qos only fails when it is passed a null
rqos = dds_create_qos (); argument, but that isn't the case here */
if (qos) { rqos = dds_create_qos ();
/* Only returns failure when one of the qos args is NULL, which if (qos)
* is not the case here. */ (void) dds_copy_qos (rqos, qos);
(void)dds_copy_qos(rqos, qos);
}
if(sub->m_entity.m_qos){ if (sub->m_entity.m_qos)
dds_merge_qos (rqos, sub->m_entity.m_qos); dds_merge_qos (rqos, sub->m_entity.m_qos);
}
if (tp->m_entity.m_qos) { if (tp->m_entity.m_qos)
dds_merge_qos (rqos, tp->m_entity.m_qos); {
dds_merge_qos (rqos, tp->m_entity.m_qos);
/* reset the following qos policies if set during topic qos merge as they aren't applicable for reader */
rqos->present &= ~(QP_DURABILITY_SERVICE | QP_TRANSPORT_PRIORITY | QP_LIFESPAN);
}
nn_xqos_mergein_missing (rqos, &gv.default_xqos_rd);
/* reset the following qos policies if set during topic qos merge as they aren't applicable for reader */ if ((ret = dds_reader_qos_validate (rqos, false)) != DDS_RETCODE_OK)
rqos->present &= ~(QP_DURABILITY_SERVICE | QP_TRANSPORT_PRIORITY | QP_LIFESPAN); {
} dds_delete_qos (rqos);
nn_xqos_mergein_missing (rqos, &gv.default_xqos_rd); reader = ret;
goto err_bad_qos;
}
ret = dds_reader_qos_validate (rqos, false); /* Additional checks required for built-in topics: we don't want to
if (ret != 0) { run into a resource limit on a built-in topic, it is a needless
dds_delete_qos(rqos); complication */
reader = ret; if (internal_topic && !dds__validate_builtin_reader_qos (topic, qos))
goto err_bad_qos; {
} dds_delete_qos (rqos);
reader = DDS_RETCODE_INCONSISTENT_POLICY;
goto err_bad_qos;
}
/* Additional checks required for built-in topics */ /* Create reader and associated read cache */
if (internal_topic && !dds__validate_builtin_reader_qos(topic, qos)) { rd = dds_alloc (sizeof (*rd));
dds_delete_qos(rqos); reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, rqos, listener, DDS_READER_STATUS_MASK);
DDS_ERROR("Invalid QoS specified for built-in topic reader"); rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED;
reader = DDS_RETCODE_INCONSISTENT_POLICY; rd->m_topic = tp;
goto err_bad_qos; rhc = dds_rhc_new (rd, tp->m_stopic);
} dds_entity_add_ref_nolock (&tp->m_entity);
rd->m_entity.m_deriver.close = dds_reader_close;
rd->m_entity.m_deriver.delete = dds_reader_delete;
rd->m_entity.m_deriver.set_qos = dds_reader_qos_set;
rd->m_entity.m_deriver.validate_status = dds_reader_status_validate;
rd->m_entity.m_deriver.get_instance_hdl = dds_reader_instance_hdl;
/* Create reader and associated read cache */ /* Extra claim of this reader to make sure that the delete waits until DDSI
rd = dds_alloc (sizeof (*rd)); has deleted its reader as well. This can be known through the callback. */
reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, rqos, listener, DDS_READER_STATUS_MASK); dds_handle_claim_inc (&rd->m_entity.m_hdllink);
rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED;
rd->m_topic = tp;
rhc = dds_rhc_new (rd, tp->m_stopic);
dds_entity_add_ref_nolock (&tp->m_entity);
rd->m_entity.m_deriver.close = dds_reader_close;
rd->m_entity.m_deriver.delete = dds_reader_delete;
rd->m_entity.m_deriver.set_qos = dds_reader_qos_set;
rd->m_entity.m_deriver.validate_status = dds_reader_status_validate;
rd->m_entity.m_deriver.get_instance_hdl = dds_reader_instance_hdl;
/* Extra claim of this reader to make sure that the delete waits until DDSI ddsrt_mutex_unlock (&tp->m_entity.m_mutex);
* has deleted its reader as well. This can be known through the callback. */ ddsrt_mutex_unlock (&sub->m_entity.m_mutex);
dds_handle_claim_inc (&rd->m_entity.m_hdllink);
ddsrt_mutex_unlock(&tp->m_entity.m_mutex); thread_state_awake (lookup_thread_state ());
ddsrt_mutex_unlock(&sub->m_entity.m_mutex); ret = new_reader (&rd->m_rd, &rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, rqos, rhc, dds_reader_status_cb, rd);
ddsrt_mutex_lock (&sub->m_entity.m_mutex);
ddsrt_mutex_lock (&tp->m_entity.m_mutex);
assert (ret == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */
thread_state_asleep (lookup_thread_state ());
thread_state_awake (lookup_thread_state ()); /* For persistent data register reader with durability */
ret = new_reader(&rd->m_rd, &rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > NN_TRANSIENT_LOCAL_DURABILITY_QOS)) {
rqos, rhc, dds_reader_status_cb, rd); (dds_global.m_dur_reader) (rd, rhc);
ddsrt_mutex_lock(&sub->m_entity.m_mutex); }
ddsrt_mutex_lock(&tp->m_entity.m_mutex); dds_topic_unlock (tp);
assert (ret == DDS_RETCODE_OK); dds_subscriber_unlock (sub);
thread_state_asleep (lookup_thread_state ());
/* For persistent data register reader with durability */ if (internal_topic)
if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > NN_TRANSIENT_LOCAL_DURABILITY_QOS)) { {
(dds_global.m_dur_reader) (rd, rhc); /* If topic is builtin, then the topic entity is local and should be deleted because the application won't. */
} dds_delete (t);
dds_topic_unlock(tp); }
dds_subscriber_unlock(sub); return reader;
if (internal_topic) {
/* If topic is builtin, then the topic entity is local and should
* be deleted because the application won't. */
dds_delete(t);
}
return reader;
err_bad_qos: err_bad_qos:
dds_topic_unlock(tp); dds_topic_unlock (tp);
err_tp_lock: err_tp_lock:
dds_subscriber_unlock(sub); dds_subscriber_unlock (sub);
if((sub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){ if ((sub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0)
(void)dds_delete(subscriber); (void) dds_delete (subscriber);
}
err_sub_lock: err_sub_lock:
if (internal_topic) { if (internal_topic)
/* If topic is builtin, then the topic entity is local and should dds_delete (t);
* be deleted because the application won't. */ return reader;
dds_delete(t);
}
return reader;
} }
void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb, void *cbarg) void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb, void *cbarg)
{ {
dds_entity *dds_entity; dds_entity *dds_entity;
if (dds_entity_claim(entity, &dds_entity) != DDS_RETCODE_OK) if (dds_entity_claim (entity, &dds_entity) != DDS_RETCODE_OK)
return; return;
if (dds_entity_kind (dds_entity) != DDS_KIND_READER) if (dds_entity_kind (dds_entity) != DDS_KIND_READER)
{ {
dds_entity_release (dds_entity); dds_entity_release (dds_entity);
@ -532,7 +481,7 @@ void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb
while ((m = ddsrt_avl_lookup_succ_eq (&rd_writers_treedef, &rd->writers, &pwrguid)) != NULL) while ((m = ddsrt_avl_lookup_succ_eq (&rd_writers_treedef, &rd->writers, &pwrguid)) != NULL)
{ {
/* have to be careful walking the tree -- pretty is different, but /* have to be careful walking the tree -- pretty is different, but
I want to check this before I write a lookup_succ function. */ I want to check this before I write a lookup_succ function. */
struct rd_pwr_match *m_next; struct rd_pwr_match *m_next;
nn_guid_t pwrguid_next; nn_guid_t pwrguid_next;
pwrguid = m->pwr_guid; pwrguid = m->pwr_guid;
@ -621,169 +570,12 @@ dds_entity_t dds_get_subscriber (dds_entity_t entity)
} }
} }
dds_return_t /* Reset sets everything (type) 0, including the reason field, verify that 0 is correct */
dds_get_subscription_matched_status ( DDSRT_STATIC_ASSERT ((int) DDS_NOT_REJECTED == 0);
dds_entity_t reader,
dds_subscription_matched_status_t * status)
{
dds_reader *rd;
dds_return_t ret;
ret = dds_reader_lock(reader, &rd); DDS_GET_STATUS (reader, subscription_matched, SUBSCRIPTION_MATCHED, total_count_change, current_count_change)
if (ret != DDS_RETCODE_OK) { DDS_GET_STATUS (reader, liveliness_changed, LIVELINESS_CHANGED, alive_count_change, not_alive_count_change)
DDS_ERROR("Error occurred on locking reader\n"); DDS_GET_STATUS (reader, sample_rejected, SAMPLE_REJECTED, total_count_change, last_reason)
goto fail; DDS_GET_STATUS (reader, sample_lost, SAMPLE_LOST, total_count_change)
} DDS_GET_STATUS (reader, requested_deadline_missed, REQUESTED_DEADLINE_MISSED, total_count_change)
/* status = NULL, application do not need the status, but reset the counter & triggered bit */ DDS_GET_STATUS (reader, requested_incompatible_qos, REQUESTED_INCOMPATIBLE_QOS, total_count_change)
if (status) {
*status = rd->m_subscription_matched_status;
}
ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
if (rd->m_entity.m_status_enable & DDS_SUBSCRIPTION_MATCHED_STATUS) {
rd->m_subscription_matched_status.total_count_change = 0;
rd->m_subscription_matched_status.current_count_change = 0;
dds_entity_status_reset(&rd->m_entity, DDS_SUBSCRIPTION_MATCHED_STATUS);
}
ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
dds_reader_unlock(rd);
fail:
return ret;
}
dds_return_t
dds_get_liveliness_changed_status (
dds_entity_t reader,
dds_liveliness_changed_status_t * status)
{
dds_reader *rd;
dds_return_t ret;
ret = dds_reader_lock(reader, &rd);
if (ret != DDS_RETCODE_OK) {
DDS_ERROR("Error occurred on locking reader\n");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = rd->m_liveliness_changed_status;
}
ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
if (rd->m_entity.m_status_enable & DDS_LIVELINESS_CHANGED_STATUS) {
rd->m_liveliness_changed_status.alive_count_change = 0;
rd->m_liveliness_changed_status.not_alive_count_change = 0;
dds_entity_status_reset(&rd->m_entity, DDS_LIVELINESS_CHANGED_STATUS);
}
ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
dds_reader_unlock(rd);
fail:
return ret;
}
dds_return_t dds_get_sample_rejected_status (
dds_entity_t reader,
dds_sample_rejected_status_t * status)
{
dds_reader *rd;
dds_return_t ret;
ret = dds_reader_lock(reader, &rd);
if (ret != DDS_RETCODE_OK) {
DDS_ERROR("Error occurred on locking reader\n");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = rd->m_sample_rejected_status;
}
ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
if (rd->m_entity.m_status_enable & DDS_SAMPLE_REJECTED_STATUS) {
rd->m_sample_rejected_status.total_count_change = 0;
rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED;
dds_entity_status_reset(&rd->m_entity, DDS_SAMPLE_REJECTED_STATUS);
}
ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
dds_reader_unlock(rd);
fail:
return ret;
}
dds_return_t dds_get_sample_lost_status (
dds_entity_t reader,
dds_sample_lost_status_t * status)
{
dds_reader *rd;
dds_return_t ret;
ret = dds_reader_lock(reader, &rd);
if (ret != DDS_RETCODE_OK) {
DDS_ERROR("Error occurred on locking reader\n");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = rd->m_sample_lost_status;
}
ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
if (rd->m_entity.m_status_enable & DDS_SAMPLE_LOST_STATUS) {
rd->m_sample_lost_status.total_count_change = 0;
dds_entity_status_reset(&rd->m_entity, DDS_SAMPLE_LOST_STATUS);
}
ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
dds_reader_unlock(rd);
fail:
return ret;
}
dds_return_t dds_get_requested_deadline_missed_status (
dds_entity_t reader,
dds_requested_deadline_missed_status_t * status)
{
dds_reader *rd;
dds_return_t ret;
ret = dds_reader_lock(reader, &rd);
if (ret != DDS_RETCODE_OK) {
DDS_ERROR("Error occurred on locking reader\n");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = rd->m_requested_deadline_missed_status;
}
ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
if (rd->m_entity.m_status_enable & DDS_REQUESTED_DEADLINE_MISSED_STATUS) {
rd->m_requested_deadline_missed_status.total_count_change = 0;
dds_entity_status_reset(&rd->m_entity, DDS_REQUESTED_DEADLINE_MISSED_STATUS);
}
ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
dds_reader_unlock(rd);
fail:
return ret;
}
dds_return_t dds_get_requested_incompatible_qos_status (
dds_entity_t reader,
dds_requested_incompatible_qos_status_t * status)
{
dds_reader *rd;
dds_return_t ret;
ret = dds_reader_lock(reader, &rd);
if (ret != DDS_RETCODE_OK) {
DDS_ERROR("Error occurred on locking reader\n");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = rd->m_requested_incompatible_qos_status;
}
ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
if (rd->m_entity.m_status_enable & DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS) {
rd->m_requested_incompatible_qos_status.total_count_change = 0;
dds_entity_status_reset(&rd->m_entity, DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS);
}
ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
dds_reader_unlock(rd);
fail:
return ret;
}

View file

@ -204,9 +204,7 @@ static void dds_os_put_bytes_aligned (dds_ostream_t * __restrict s, const void *
static uint32_t get_type_size (enum dds_stream_typecode type) static uint32_t get_type_size (enum dds_stream_typecode type)
{ {
struct check { DDSRT_STATIC_ASSERT (DDS_OP_VAL_1BY == 1 && DDS_OP_VAL_2BY == 2 && DDS_OP_VAL_4BY == 3 && DDS_OP_VAL_8BY == 4);
char x[(DDS_OP_VAL_1BY == 1 && DDS_OP_VAL_2BY == 2 && DDS_OP_VAL_4BY == 3 && DDS_OP_VAL_8BY == 4) ? 1 : -1];
};
assert (type == DDS_OP_VAL_1BY || type == DDS_OP_VAL_2BY || type == DDS_OP_VAL_4BY || type == DDS_OP_VAL_8BY); assert (type == DDS_OP_VAL_1BY || type == DDS_OP_VAL_2BY || type == DDS_OP_VAL_4BY || type == DDS_OP_VAL_8BY);
return (uint32_t)1 << ((uint32_t) type - 1); return (uint32_t)1 << ((uint32_t) type - 1);
} }

View file

@ -11,199 +11,126 @@
*/ */
#include <string.h> #include <string.h>
#include "dds__listener.h" #include "dds__listener.h"
#include "dds__participant.h"
#include "dds__qos.h" #include "dds__qos.h"
#include "dds__subscriber.h" #include "dds__subscriber.h"
#include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_entity.h"
#include "dds/version.h" #include "dds/version.h"
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_subscriber) DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_subscriber)
#define DDS_SUBSCRIBER_STATUS_MASK \ #define DDS_SUBSCRIBER_STATUS_MASK \
DDS_DATA_ON_READERS_STATUS (DDS_DATA_ON_READERS_STATUS)
static dds_return_t static dds_return_t dds_subscriber_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all;
dds_subscriber_instance_hdl(
dds_entity *e, static dds_return_t dds_subscriber_instance_hdl (dds_entity *e, dds_instance_handle_t *i)
dds_instance_handle_t *i)
{ {
(void)e; (void) e;
(void)i; (void) i;
/* TODO: Get/generate proper handle. */ /* FIXME: Get/generate proper handle. */
DDS_ERROR("Generating subscriber instance handle is not supported"); return DDS_RETCODE_UNSUPPORTED;
return DDS_RETCODE_UNSUPPORTED;
} }
static dds_return_t static dds_return_t dds__subscriber_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
dds__subscriber_qos_validate(
const dds_qos_t *qos, static dds_return_t dds__subscriber_qos_validate (const dds_qos_t *qos, bool enabled)
bool enabled)
{ {
dds_return_t ret = DDS_RETCODE_OK; if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data))
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_PARTITION) && !validate_stringseq (&qos->partition))
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_PRESENTATION) && validate_presentation_qospolicy (&qos->presentation) < 0)
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy (&qos->entity_factory))
return DDS_RETCODE_INCONSISTENT_POLICY;
/* FIXME: Improve/check immutable check. */
return (enabled && (qos->present & QP_PRESENTATION)) ? DDS_RETCODE_IMMUTABLE_POLICY : DDS_RETCODE_OK;
}
assert(qos); static dds_return_t dds_subscriber_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
if((qos->present & QP_GROUP_DATA) && !validate_octetseq(&qos->group_data)) {
DDS_ERROR("Group data policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if((qos->present & QP_PARTITION) && !validate_stringseq(&qos->partition)) {
DDS_ERROR("Partition policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if((qos->present & QP_PRESENTATION) && validate_presentation_qospolicy(&qos->presentation)) {
DDS_ERROR("Presentation policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)) {
DDS_ERROR("Prismtech entity factory policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if(ret == DDS_RETCODE_OK && enabled && (qos->present & QP_PRESENTATION)) {
/* TODO: Improve/check immutable check. */
DDS_ERROR("Presentation QoS policy is immutable\n");
ret = DDS_RETCODE_IMMUTABLE_POLICY;
}
static dds_return_t dds_subscriber_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
{
/* FIXME: QoS changes. */
dds_return_t ret;
(void) e;
if ((ret = dds__subscriber_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
return ret; return ret;
return (enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK);
} }
static dds_return_t static dds_return_t dds_subscriber_status_validate (uint32_t mask)
dds_subscriber_qos_set(
dds_entity *e,
const dds_qos_t *qos,
bool enabled)
{ {
dds_return_t ret = dds__subscriber_qos_validate(qos, enabled); return (mask & ~DDS_SUBSCRIBER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK;
(void)e; }
if (ret == DDS_RETCODE_OK) {
if (enabled) { dds_entity_t dds__create_subscriber_l (dds_participant *participant, const dds_qos_t *qos, const dds_listener_t *listener)
/* TODO: CHAM-95: DDSI does not support changing QoS policies. */ {
DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies yet\n"); /* participant entity lock must be held */
ret = DDS_RETCODE_UNSUPPORTED; dds_subscriber *sub;
} dds_entity_t subscriber;
} dds_return_t ret;
dds_qos_t *new_qos;
/* Validate qos */
if (qos && (ret = dds__subscriber_qos_validate (qos, false)) != DDS_RETCODE_OK)
return ret; return ret;
if (qos == NULL)
new_qos = NULL;
else
{
new_qos = dds_create_qos ();
(void) dds_copy_qos (new_qos, qos);
}
sub = dds_alloc (sizeof (*sub));
subscriber = dds_entity_init (&sub->m_entity, &participant->m_entity, DDS_KIND_SUBSCRIBER, new_qos, listener, DDS_SUBSCRIBER_STATUS_MASK);
sub->m_entity.m_deriver.set_qos = dds_subscriber_qos_set;
sub->m_entity.m_deriver.validate_status = dds_subscriber_status_validate;
sub->m_entity.m_deriver.get_instance_hdl = dds_subscriber_instance_hdl;
return subscriber;
} }
static dds_return_t dds_entity_t dds_create_subscriber (dds_entity_t participant, const dds_qos_t *qos, const dds_listener_t *listener)
dds_subscriber_status_validate(
uint32_t mask)
{ {
dds_return_t ret = DDS_RETCODE_OK; dds_participant *par;
dds_entity_t hdl;
if (mask & ~(DDS_SUBSCRIBER_STATUS_MASK)) { dds_return_t ret;
DDS_ERROR("Invalid status mask\n"); if ((ret = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK)
ret = DDS_RETCODE_BAD_PARAMETER;
}
return ret; return ret;
hdl = dds__create_subscriber_l (par, qos, listener);
dds_participant_unlock (par);
return hdl;
} }
dds_entity_t dds_return_t dds_notify_readers (dds_entity_t subscriber)
dds__create_subscriber_l(
dds_entity *participant, /* entity-lock must be held */
const dds_qos_t *qos,
const dds_listener_t *listener)
{ {
dds_subscriber * sub; dds_subscriber *sub;
dds_entity_t subscriber; dds_return_t ret;
dds_return_t ret;
dds_qos_t * new_qos;
/* Validate qos */ if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK)
if (qos) {
if ((ret = dds__subscriber_qos_validate(qos, false)) != DDS_RETCODE_OK) {
goto err_param;
}
new_qos = dds_create_qos();
/* Only returns failure when one of the qos args is NULL, which
* is not the case here. */
(void)dds_copy_qos(new_qos, qos);
} else {
new_qos = NULL;
}
/* Create subscriber */
sub = dds_alloc(sizeof(*sub));
subscriber = dds_entity_init(&sub->m_entity, participant, DDS_KIND_SUBSCRIBER, new_qos, listener, DDS_SUBSCRIBER_STATUS_MASK);
sub->m_entity.m_deriver.set_qos = dds_subscriber_qos_set;
sub->m_entity.m_deriver.validate_status = dds_subscriber_status_validate;
sub->m_entity.m_deriver.get_instance_hdl = dds_subscriber_instance_hdl;
return subscriber;
/* Error handling */
err_param:
return ret; return ret;
ret = DDS_RETCODE_UNSUPPORTED;
for (dds_entity *iter = sub->m_entity.m_children; iter; iter = iter->m_next)
{
ddsrt_mutex_lock (&iter->m_mutex);
// FIXME: check if reader has data available, call listener
ddsrt_mutex_unlock(&iter->m_mutex);
}
dds_subscriber_unlock (sub);
return ret;
} }
dds_entity_t dds_return_t dds_subscriber_begin_coherent (dds_entity_t e)
dds_create_subscriber(
dds_entity_t participant,
const dds_qos_t *qos,
const dds_listener_t *listener)
{ {
dds_entity * par; return dds_generic_unimplemented_operation (e, DDS_KIND_SUBSCRIBER);
dds_entity_t hdl;
dds_return_t errnr;
errnr = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par);
if (errnr != DDS_RETCODE_OK) {
DDS_ERROR("Error occurred on locking participant\n");
hdl = errnr;
return hdl;
}
hdl = dds__create_subscriber_l(par, qos, listener);
dds_entity_unlock(par);
return hdl;
} }
dds_return_t dds_return_t dds_subscriber_end_coherent (dds_entity_t e)
dds_notify_readers(
dds_entity_t subscriber)
{ {
dds_entity *iter; return dds_generic_unimplemented_operation (e, DDS_KIND_SUBSCRIBER);
dds_entity *sub;
dds_return_t ret;
ret = dds_entity_lock(subscriber, DDS_KIND_SUBSCRIBER, &sub);
if (ret == DDS_RETCODE_OK) {
ret = DDS_RETCODE_UNSUPPORTED;
DDS_ERROR("Unsupported operation\n");
iter = sub->m_children;
while (iter) {
ddsrt_mutex_lock(&iter->m_mutex);
// TODO: check if reader has data available, call listener
ddsrt_mutex_unlock(&iter->m_mutex);
iter = iter->m_next;
}
dds_entity_unlock(sub);
} else {
DDS_ERROR("Error occurred on locking subscriber\n");
}
return ret;
}
dds_return_t
dds_subscriber_begin_coherent(
dds_entity_t e)
{
/* TODO: CHAM-124 Currently unsupported. */
(void)e;
DDS_ERROR("Using coherency to get a coherent data set is not currently being supported\n");
return DDS_RETCODE_UNSUPPORTED;
}
dds_return_t
dds_subscriber_end_coherent(
dds_entity_t e)
{
/* TODO: CHAM-124 Currently unsupported. */
(void)e;
DDS_ERROR("Using coherency to get a coherent data set is not currently being supported\n");
return DDS_RETCODE_UNSUPPORTED;
} }

View file

@ -17,68 +17,53 @@
#include "dds__topic.h" #include "dds__topic.h"
#include "dds__listener.h" #include "dds__listener.h"
#include "dds__qos.h" #include "dds__qos.h"
#include "dds__participant.h"
#include "dds__stream.h" #include "dds__stream.h"
#include "dds__init.h" #include "dds__init.h"
#include "dds__domain.h" #include "dds__domain.h"
#include "dds__get_status.h"
#include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_thread.h"
#include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/ddsi_sertopic.h"
#include "dds/ddsi/q_ddsi_discovery.h" #include "dds/ddsi/q_ddsi_discovery.h"
#include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/ddsi_iid.h"
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_topic) DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_topic)
#define DDS_TOPIC_STATUS_MASK \ #define DDS_TOPIC_STATUS_MASK \
DDS_INCONSISTENT_TOPIC_STATUS (DDS_INCONSISTENT_TOPIC_STATUS)
const ddsrt_avl_treedef_t dds_topictree_def = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY static int strcmp_wrapper (const void *va, const void *vb)
(
offsetof (struct ddsi_sertopic, avlnode),
offsetof (struct ddsi_sertopic, name_type_name),
(int (*) (const void *, const void *)) strcmp,
0
);
static bool
is_valid_name(
const char *name)
{ {
bool valid = false; return strcmp (va, vb);
/* DDS Spec:
* | TOPICNAME - A topic name is an identifier for a topic, and is defined as any series of characters
* | 'a', ..., 'z',
* | 'A', ..., 'Z',
* | '0', ..., '9',
* | '-' but may not start with a digit.
* It is considered that '-' is an error in the spec and should say '_'. So, that's what we'll check for.
* | '/' got added for ROS2
*/
assert(name);
if ((name[0] != '\0') && (!isdigit((unsigned char)name[0]))) {
while (isalnum((unsigned char)*name) || (*name == '_') || (*name == '/')) {
name++;
}
if (*name == '\0') {
valid = true;
}
}
return valid;
} }
const ddsrt_avl_treedef_t dds_topictree_def = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct ddsi_sertopic, avlnode), offsetof (struct ddsi_sertopic, name_type_name), strcmp_wrapper, 0);
static dds_return_t static bool is_valid_name (const char *name) ddsrt_nonnull_all;
dds_topic_status_validate(
uint32_t mask) static bool is_valid_name (const char *name)
{ {
dds_return_t ret = DDS_RETCODE_OK; /* DDS Spec:
* | TOPICNAME - A topic name is an identifier for a topic, and is defined as any series of characters
* | 'a', ..., 'z',
* | 'A', ..., 'Z',
* | '0', ..., '9',
* | '-' but may not start with a digit.
* It is considered that '-' is an error in the spec and should say '_'. So, that's what we'll check for.
* | '/' got added for ROS2
*/
if (name[0] == '\0' || isdigit ((unsigned char) name[0]))
return false;
for (size_t i = 0; name[i]; i++)
if (!(isalnum ((unsigned char) name[i]) || name[i] == '_' || name[i] == '/'))
return false;
return true;
}
if (mask & ~(DDS_TOPIC_STATUS_MASK)) { static dds_return_t dds_topic_status_validate (uint32_t mask)
DDS_ERROR("Argument mask is invalid\n"); {
ret = DDS_RETCODE_BAD_PARAMETER; return (mask & ~DDS_TOPIC_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK;
}
return ret;
} }
/* /*
@ -100,191 +85,135 @@ static void dds_topic_status_cb (struct dds_topic *tp)
if (lst->on_inconsistent_topic) if (lst->on_inconsistent_topic)
{ {
ddsrt_mutex_unlock (&tp->m_entity.m_observers_lock); ddsrt_mutex_unlock (&tp->m_entity.m_observers_lock);
dds_entity_invoke_listener(&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS_ID, &tp->m_inconsistent_topic_status); dds_entity_invoke_listener (&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS_ID, &tp->m_inconsistent_topic_status);
ddsrt_mutex_lock (&tp->m_entity.m_observers_lock); ddsrt_mutex_lock (&tp->m_entity.m_observers_lock);
tp->m_inconsistent_topic_status.total_count_change = 0; tp->m_inconsistent_topic_status.total_count_change = 0;
} }
dds_entity_status_set(&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS); dds_entity_status_set (&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS);
tp->m_entity.m_cb_count--; tp->m_entity.m_cb_count--;
ddsrt_cond_broadcast (&tp->m_entity.m_observers_cond); ddsrt_cond_broadcast (&tp->m_entity.m_observers_cond);
ddsrt_mutex_unlock (&tp->m_entity.m_observers_lock); ddsrt_mutex_unlock (&tp->m_entity.m_observers_lock);
} }
struct ddsi_sertopic * struct ddsi_sertopic *dds_topic_lookup_locked (dds_domain *domain, const char *name) ddsrt_nonnull_all;
dds_topic_lookup_locked(
dds_domain *domain, struct ddsi_sertopic *dds_topic_lookup_locked (dds_domain *domain, const char *name)
const char *name)
{ {
struct ddsi_sertopic *st = NULL; ddsrt_avl_iter_t iter;
ddsrt_avl_iter_t iter; for (struct ddsi_sertopic *st = ddsrt_avl_iter_first (&dds_topictree_def, &domain->m_topics, &iter); st; st = ddsrt_avl_iter_next (&iter))
if (strcmp (st->name, name) == 0)
assert (domain); return st;
assert (name); return NULL;
st = ddsrt_avl_iter_first (&dds_topictree_def, &domain->m_topics, &iter);
while (st) {
if (strcmp (st->name, name) == 0) {
break;
}
st = ddsrt_avl_iter_next (&iter);
}
return st;
} }
struct ddsi_sertopic * struct ddsi_sertopic *dds_topic_lookup (dds_domain *domain, const char *name)
dds_topic_lookup(
dds_domain *domain,
const char *name)
{ {
struct ddsi_sertopic *st; struct ddsi_sertopic *st;
ddsrt_mutex_lock (&dds_global.m_mutex); ddsrt_mutex_lock (&dds_global.m_mutex);
st = dds_topic_lookup_locked(domain, name); st = dds_topic_lookup_locked (domain, name);
ddsrt_mutex_unlock (&dds_global.m_mutex); ddsrt_mutex_unlock (&dds_global.m_mutex);
return st; return st;
} }
void void dds_topic_free (dds_domainid_t domainid, struct ddsi_sertopic *st)
dds_topic_free(
dds_domainid_t domainid,
struct ddsi_sertopic *st)
{ {
dds_domain *domain; dds_domain *domain;
ddsrt_mutex_lock (&dds_global.m_mutex);
assert (st); domain = ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &domainid);
if (domain != NULL)
ddsrt_mutex_lock (&dds_global.m_mutex); {
domain = ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &domainid); assert (ddsrt_avl_lookup (&dds_topictree_def, &domain->m_topics, st->name_type_name) != NULL);
if (domain != NULL) { ddsrt_avl_delete (&dds_topictree_def, &domain->m_topics, st);
ddsrt_avl_delete (&dds_topictree_def, &domain->m_topics, st); }
} ddsrt_mutex_unlock (&dds_global.m_mutex);
ddsrt_mutex_unlock (&dds_global.m_mutex); st->status_cb_entity = NULL;
st->status_cb_entity = NULL; ddsi_sertopic_unref (st);
ddsi_sertopic_unref (st);
} }
static void static void dds_topic_add_locked (dds_domainid_t id, struct ddsi_sertopic *st)
dds_topic_add_locked(
dds_domainid_t id,
struct ddsi_sertopic *st)
{ {
dds_domain * dom; dds_domain *dom = dds_domain_find_locked (id);
dom = dds_domain_find_locked (id); assert (dom);
assert (dom); assert (ddsrt_avl_lookup (&dds_topictree_def, &dom->m_topics, st->name_type_name) == NULL);
ddsrt_avl_insert (&dds_topictree_def, &dom->m_topics, st); ddsrt_avl_insert (&dds_topictree_def, &dom->m_topics, st);
} }
DDS_EXPORT dds_entity_t dds_entity_t dds_find_topic (dds_entity_t participant, const char *name)
dds_find_topic(
dds_entity_t participant,
const char *name)
{ {
dds_entity_t tp; dds_entity_t tp;
dds_entity *p = NULL; dds_participant *p;
struct ddsi_sertopic *st; struct ddsi_sertopic *st;
dds_return_t rc; dds_return_t rc;
if (name) { if (name == NULL)
rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &p); return DDS_RETCODE_BAD_PARAMETER;
if (rc == DDS_RETCODE_OK) {
ddsrt_mutex_lock (&dds_global.m_mutex);
st = dds_topic_lookup_locked (p->m_domain, name);
if (st) {
/* FIXME: calling addref is wrong because the Cyclone library has no
knowledge of the reference and hence simply deleting the participant
won't make the ref count drop to 0. On the other hand, the DDS spec
says find_topic (and a second call to create_topic) return a new
proxy that must separately be deleted. */
dds_entity_add_ref (&st->status_cb_entity->m_entity);
tp = st->status_cb_entity->m_entity.m_hdllink.hdl;
} else {
DDS_ERROR("Topic is not being created yet\n");
tp = DDS_RETCODE_PRECONDITION_NOT_MET;
}
ddsrt_mutex_unlock (&dds_global.m_mutex);
dds_entity_unlock(p);
} else {
tp = rc;
}
} else {
DDS_ERROR("Argument name is not valid\n");
tp = DDS_RETCODE_BAD_PARAMETER;
}
return tp; if ((rc = dds_participant_lock (participant, &p)) != DDS_RETCODE_OK)
return rc;
ddsrt_mutex_lock (&dds_global.m_mutex);
if ((st = dds_topic_lookup_locked (p->m_entity.m_domain, name)) == NULL)
tp = DDS_RETCODE_PRECONDITION_NOT_MET;
else
{
/* FIXME: calling addref is wrong because the Cyclone library has no
knowledge of the reference and hence simply deleting the participant
won't make the ref count drop to 0. On the other hand, the DDS spec
says find_topic (and a second call to create_topic) return a new
proxy that must separately be deleted. */
dds_entity_add_ref (&st->status_cb_entity->m_entity);
tp = st->status_cb_entity->m_entity.m_hdllink.hdl;
}
ddsrt_mutex_unlock (&dds_global.m_mutex);
dds_participant_unlock (p);
return tp;
} }
static dds_return_t static dds_return_t dds_topic_delete (dds_entity *e) ddsrt_nonnull_all;
dds_topic_delete(
dds_entity *e) static dds_return_t dds_topic_delete (dds_entity *e)
{ {
dds_topic_free(e->m_domainid, ((dds_topic*) e)->m_stopic); dds_topic_free (e->m_domainid, ((dds_topic *) e)->m_stopic);
return DDS_RETCODE_OK; return DDS_RETCODE_OK;
} }
static dds_return_t static dds_return_t dds_topic_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
dds_topic_qos_validate(
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = DDS_RETCODE_OK;
assert(qos);
/* Check consistency. */ static dds_return_t dds_topic_qos_validate (const dds_qos_t *qos, bool enabled)
if (!dds_qos_validate_common(qos)) { {
DDS_ERROR("Argument QoS is not valid\n"); if (!dds_qos_validate_common (qos))
ret = DDS_RETCODE_BAD_PARAMETER; return DDS_RETCODE_BAD_PARAMETER;
} if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data))
if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data)) { return DDS_RETCODE_INCONSISTENT_POLICY;
DDS_ERROR("Group data QoS policy is inconsistent and caused an error\n"); if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy(&qos->durability_service) < 0)
ret = DDS_RETCODE_INCONSISTENT_POLICY; return DDS_RETCODE_INCONSISTENT_POLICY;
} if ((qos->present & QP_LIFESPAN) && validate_duration(&qos->lifespan.duration) < 0)
if ((qos->present & QP_DURABILITY_SERVICE) && (validate_durability_service_qospolicy(&qos->durability_service) != 0)) { return DDS_RETCODE_INCONSISTENT_POLICY;
DDS_ERROR("Durability service QoS policy is inconsistent and caused an error\n"); if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits(&qos->history, &qos->resource_limits) < 0)
ret = DDS_RETCODE_INCONSISTENT_POLICY; return DDS_RETCODE_INCONSISTENT_POLICY;
} return enabled ? dds_qos_validate_mutable_common(qos) : DDS_RETCODE_OK;
if ((qos->present & QP_LIFESPAN) && (validate_duration(&qos->lifespan.duration) != 0)) { }
DDS_ERROR("Lifespan QoS policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
} static dds_return_t dds_topic_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
if (qos->present & QP_HISTORY && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits(&qos->history, &qos->resource_limits) != 0)) { {
DDS_ERROR("Lifespan QoS policy is inconsistent and caused an error\n"); /* FIXME: QoS changes */
ret = DDS_RETCODE_INCONSISTENT_POLICY; dds_return_t ret;
} (void) e;
if(ret == DDS_RETCODE_OK && enabled){ if ((ret = dds_topic_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
ret = dds_qos_validate_mutable_common(qos);
}
return ret; return ret;
return enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK;
} }
static bool dupdef_qos_ok (const dds_qos_t *qos, const struct ddsi_sertopic *st)
static dds_return_t
dds_topic_qos_set(
dds_entity *e,
const dds_qos_t *qos,
bool enabled)
{ {
dds_return_t ret = dds_topic_qos_validate(qos, enabled); if ((qos == NULL) != (st->status_cb_entity->m_entity.m_qos == NULL))
(void)e; return false;
if (ret == DDS_RETCODE_OK) { else if (qos == NULL)
if (enabled) { return true;
/* TODO: CHAM-95: DDSI does not support changing QoS policies. */ else
DDS_ERROR("Changing the topic QoS is not supported\n"); return dds_qos_equal (st->status_cb_entity->m_entity.m_qos, qos);
ret = DDS_RETCODE_UNSUPPORTED;
}
}
return ret;
}
static bool dupdef_qos_ok(const dds_qos_t *qos, const struct ddsi_sertopic *st)
{
if ((qos == NULL) != (st->status_cb_entity->m_entity.m_qos == NULL)) {
return false;
} else if (qos == NULL) {
return true;
} else {
return dds_qos_equal(st->status_cb_entity->m_entity.m_qos, qos);
}
} }
static bool sertopic_equivalent (const struct ddsi_sertopic *a, const struct ddsi_sertopic *b) static bool sertopic_equivalent (const struct ddsi_sertopic *a, const struct ddsi_sertopic *b)
@ -300,276 +229,213 @@ static bool sertopic_equivalent (const struct ddsi_sertopic *a, const struct dds
return true; return true;
} }
DDS_EXPORT dds_entity_t dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_sertopic *sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const nn_plist_t *sedp_plist)
dds_create_topic_arbitrary (
dds_entity_t participant,
struct ddsi_sertopic *sertopic,
const dds_qos_t *qos,
const dds_listener_t *listener,
const nn_plist_t *sedp_plist)
{ {
struct ddsi_sertopic *stgeneric; struct ddsi_sertopic *stgeneric;
dds_return_t rc; dds_return_t rc;
dds_entity *par; dds_participant *par;
dds_topic *top; dds_topic *top;
dds_qos_t *new_qos = NULL; dds_qos_t *new_qos = NULL;
dds_entity_t hdl; dds_entity_t hdl;
struct participant *ddsi_pp; struct participant *ddsi_pp;
if (sertopic == NULL){ if (sertopic == NULL)
DDS_ERROR("Topic description is NULL\n"); return DDS_RETCODE_BAD_PARAMETER;
hdl = DDS_RETCODE_BAD_PARAMETER;
goto bad_param_err;
}
rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); if (qos && (rc = dds_topic_qos_validate (qos, false)) != DDS_RETCODE_OK)
if (rc != DDS_RETCODE_OK) { return rc;
hdl = rc;
goto lock_err;
}
/* Validate qos */ if ((rc = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK)
if (qos) { return rc;
hdl = dds_topic_qos_validate (qos, false);
if (hdl != DDS_RETCODE_OK) {
goto qos_err;
}
}
/* FIXME: I find it weird that qos may be NULL in the entity */ /* FIXME: I find it weird that qos may be NULL in the entity */
/* Check if topic already exists with same name */ /* Check if topic already exists with same name */
ddsrt_mutex_lock (&dds_global.m_mutex); ddsrt_mutex_lock (&dds_global.m_mutex);
if ((stgeneric = dds_topic_lookup_locked (par->m_domain, sertopic->name)) != NULL) { if ((stgeneric = dds_topic_lookup_locked (par->m_entity.m_domain, sertopic->name)) != NULL) {
if (!sertopic_equivalent (stgeneric, sertopic)) { if (!sertopic_equivalent (stgeneric, sertopic)) {
/* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */ /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */
DDS_ERROR("Create topic with mismatching type\n"); rc = DDS_RETCODE_PRECONDITION_NOT_MET;
hdl = DDS_RETCODE_PRECONDITION_NOT_MET; goto err_mismatch;
} else if (!dupdef_qos_ok(qos, stgeneric)) { } else if (!dupdef_qos_ok(qos, stgeneric)) {
/* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */ /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */
DDS_ERROR("Create topic with mismatching qos\n"); rc = DDS_RETCODE_INCONSISTENT_POLICY;
hdl = DDS_RETCODE_INCONSISTENT_POLICY; goto err_mismatch;
} else {
/* FIXME: calling addref is wrong because the Cyclone library has no
knowledge of the reference and hence simply deleting the participant
won't make the ref count drop to 0. On the other hand, the DDS spec
says find_topic (and a second call to create_topic) return a new
proxy that must separately be deleted. */
dds_entity_add_ref (&stgeneric->status_cb_entity->m_entity);
hdl = stgeneric->status_cb_entity->m_entity.m_hdllink.hdl;
}
ddsrt_mutex_unlock (&dds_global.m_mutex);
} else { } else {
if (qos) { /* FIXME: calling addref is wrong because the Cyclone library has no
new_qos = dds_create_qos(); knowledge of the reference and hence simply deleting the participant
/* Only returns failure when one of the qos args is NULL, which won't make the ref count drop to 0. On the other hand, the DDS spec
* is not the case here. */ says find_topic (and a second call to create_topic) return a new
(void)dds_copy_qos(new_qos, qos); proxy that must separately be deleted. */
} dds_entity_add_ref (&stgeneric->status_cb_entity->m_entity);
hdl = stgeneric->status_cb_entity->m_entity.m_hdllink.hdl;
/* Create topic */ }
top = dds_alloc (sizeof (*top)); ddsrt_mutex_unlock (&dds_global.m_mutex);
hdl = dds_entity_init (&top->m_entity, par, DDS_KIND_TOPIC, new_qos, listener, DDS_TOPIC_STATUS_MASK); } else {
top->m_entity.m_deriver.delete = dds_topic_delete; if (qos)
top->m_entity.m_deriver.set_qos = dds_topic_qos_set; {
top->m_entity.m_deriver.validate_status = dds_topic_status_validate; new_qos = dds_create_qos ();
top->m_stopic = ddsi_sertopic_ref (sertopic); (void)dds_copy_qos (new_qos, qos);
sertopic->status_cb_entity = top;
/* Add topic to extent */
dds_topic_add_locked (par->m_domainid, sertopic);
ddsrt_mutex_unlock (&dds_global.m_mutex);
/* Publish Topic */
thread_state_awake (lookup_thread_state ());
ddsi_pp = ephash_lookup_participant_guid (&par->m_guid);
assert (ddsi_pp);
if (sedp_plist) {
sedp_write_topic (ddsi_pp, sedp_plist);
}
thread_state_asleep (lookup_thread_state ());
} }
qos_err: /* Create topic */
dds_entity_unlock(par); top = dds_alloc (sizeof (*top));
lock_err: hdl = dds_entity_init (&top->m_entity, &par->m_entity, DDS_KIND_TOPIC, new_qos, listener, DDS_TOPIC_STATUS_MASK);
bad_param_err: top->m_entity.m_deriver.delete = dds_topic_delete;
return hdl; top->m_entity.m_deriver.set_qos = dds_topic_qos_set;
top->m_entity.m_deriver.validate_status = dds_topic_status_validate;
top->m_stopic = ddsi_sertopic_ref (sertopic);
sertopic->status_cb_entity = top;
/* Add topic to extent */
dds_topic_add_locked (par->m_entity.m_domainid, sertopic);
ddsrt_mutex_unlock (&dds_global.m_mutex);
/* Publish Topic */
thread_state_awake (lookup_thread_state ());
ddsi_pp = ephash_lookup_participant_guid (&par->m_entity.m_guid);
assert (ddsi_pp);
if (sedp_plist)
sedp_write_topic (ddsi_pp, sedp_plist);
thread_state_asleep (lookup_thread_state ());
}
dds_participant_unlock (par);
return hdl;
err_mismatch:
ddsrt_mutex_unlock (&dds_global.m_mutex);
dds_participant_unlock (par);
return rc;
} }
DDS_EXPORT dds_entity_t dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descriptor_t *desc, const char *name, const dds_qos_t *qos, const dds_listener_t *listener)
dds_create_topic(
dds_entity_t participant,
const dds_topic_descriptor_t *desc,
const char *name,
const dds_qos_t *qos,
const dds_listener_t *listener)
{ {
char *key = NULL; char *key = NULL;
struct ddsi_sertopic_default *st; struct ddsi_sertopic_default *st;
const char *typename; const char *typename;
dds_qos_t *new_qos = NULL; dds_qos_t *new_qos = NULL;
nn_plist_t plist; nn_plist_t plist;
dds_entity_t hdl; dds_entity_t hdl;
uint32_t index; size_t keysz;
size_t keysz;
if (desc == NULL){ if (desc == NULL || name == NULL || !is_valid_name (name))
DDS_ERROR("Topic description is NULL"); return DDS_RETCODE_BAD_PARAMETER;
hdl = DDS_RETCODE_BAD_PARAMETER;
goto bad_param_err;
}
if (name == NULL) { typename = desc->m_typename;
DDS_ERROR("Topic name is NULL"); keysz = strlen (name) + strlen (typename) + 2;
hdl = DDS_RETCODE_BAD_PARAMETER; key = dds_alloc (keysz);
goto bad_param_err; (void) snprintf (key, keysz, "%s/%s", name, typename);
}
if (!is_valid_name(name)) { st = dds_alloc (sizeof (*st));
DDS_ERROR("Topic name contains characters that are not allowed.");
hdl = DDS_RETCODE_BAD_PARAMETER;
goto bad_param_err;
}
typename = desc->m_typename; ddsrt_atomic_st32 (&st->c.refc, 1);
keysz = strlen (name) + strlen (typename) + 2; st->c.iid = ddsi_iid_gen ();
key = (char*) dds_alloc (keysz); st->c.status_cb = dds_topic_status_cb;
(void) snprintf(key, keysz, "%s/%s", name, typename); st->c.status_cb_entity = NULL; /* set by dds_create_topic_arbitrary */
st->c.name_type_name = key;
st->c.name = dds_string_dup (name);
st->c.type_name = dds_string_dup (typename);
st->c.ops = &ddsi_sertopic_ops_default;
st->c.serdata_ops = desc->m_nkeys ? &ddsi_serdata_ops_cdr : &ddsi_serdata_ops_cdr_nokey;
st->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (st->c.serdata_ops);
st->native_encoding_identifier = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE);
st = dds_alloc (sizeof (*st)); st->type = (void*) desc;
st->nkeys = desc->m_nkeys;
st->keys = desc->m_keys;
ddsrt_atomic_st32 (&st->c.refc, 1); /* Check if topic cannot be optimised (memcpy marshal) */
st->c.iid = ddsi_iid_gen (); if (!(desc->m_flagset & DDS_TOPIC_NO_OPTIMIZE)) {
st->c.status_cb = dds_topic_status_cb; st->opt_size = dds_stream_check_optimize (desc);
st->c.status_cb_entity = NULL; /* set by dds_create_topic_arbitrary */ }
st->c.name_type_name = key;
st->c.name = dds_string_dup (name);
st->c.type_name = dds_string_dup (typename);
st->c.ops = &ddsi_sertopic_ops_default;
st->c.serdata_ops = desc->m_nkeys ? &ddsi_serdata_ops_cdr : &ddsi_serdata_ops_cdr_nokey;
st->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (st->c.serdata_ops);
st->native_encoding_identifier = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE);
st->type = (void*) desc; nn_plist_init_empty (&plist);
st->nkeys = desc->m_nkeys; if (new_qos)
st->keys = desc->m_keys; dds_merge_qos (&plist.qos, new_qos);
/* Check if topic cannot be optimised (memcpy marshal) */ /* Set Topic meta data (for SEDP publication) */
if ((desc->m_flagset & DDS_TOPIC_NO_OPTIMIZE) == 0) { plist.qos.topic_name = dds_string_dup (st->c.name);
st->opt_size = dds_stream_check_optimize (desc); plist.qos.type_name = dds_string_dup (st->c.type_name);
} plist.qos.present |= (QP_TOPIC_NAME | QP_TYPE_NAME);
if (desc->m_meta)
{
plist.type_description = dds_string_dup (desc->m_meta);
plist.present |= PP_PRISMTECH_TYPE_DESCRIPTION;
}
if (desc->m_nkeys)
{
plist.qos.present |= QP_PRISMTECH_SUBSCRIPTION_KEYS;
plist.qos.subscription_keys.use_key_list = 1;
plist.qos.subscription_keys.key_list.n = desc->m_nkeys;
plist.qos.subscription_keys.key_list.strs = dds_alloc (desc->m_nkeys * sizeof (char*));
for (uint32_t index = 0; index < desc->m_nkeys; index++)
plist.qos.subscription_keys.key_list.strs[index] = dds_string_dup (desc->m_keys[index].m_name);
}
nn_plist_init_empty (&plist); hdl = dds_create_topic_arbitrary (participant, &st->c, qos, listener, &plist);
if (new_qos) { ddsi_sertopic_unref (&st->c);
dds_merge_qos (&plist.qos, new_qos); nn_plist_fini (&plist);
} return hdl;
/* Set Topic meta data (for SEDP publication) */
plist.qos.topic_name = dds_string_dup (st->c.name);
plist.qos.type_name = dds_string_dup (st->c.type_name);
plist.qos.present |= (QP_TOPIC_NAME | QP_TYPE_NAME);
if (desc->m_meta) {
plist.type_description = dds_string_dup (desc->m_meta);
plist.present |= PP_PRISMTECH_TYPE_DESCRIPTION;
}
if (desc->m_nkeys) {
plist.qos.present |= QP_PRISMTECH_SUBSCRIPTION_KEYS;
plist.qos.subscription_keys.use_key_list = 1;
plist.qos.subscription_keys.key_list.n = desc->m_nkeys;
plist.qos.subscription_keys.key_list.strs = dds_alloc (desc->m_nkeys * sizeof (char*));
for (index = 0; index < desc->m_nkeys; index++) {
plist.qos.subscription_keys.key_list.strs[index] = dds_string_dup (desc->m_keys[index].m_name);
}
}
hdl = dds_create_topic_arbitrary(participant, &st->c, qos, listener, &plist);
ddsi_sertopic_unref (&st->c);
nn_plist_fini (&plist);
bad_param_err:
return hdl;
} }
static bool static bool dds_topic_chaining_filter (const void *sample, void *ctx)
dds_topic_chaining_filter(
const void *sample,
void *ctx)
{ {
dds_topic_filter_fn realf = (dds_topic_filter_fn)ctx; dds_topic_filter_fn realf = (dds_topic_filter_fn) ctx;
return realf (sample); return realf (sample);
} }
static void static void dds_topic_mod_filter (dds_entity_t topic, dds_topic_intern_filter_fn *filter, void **ctx, bool set)
dds_topic_mod_filter(
dds_entity_t topic,
dds_topic_intern_filter_fn *filter,
void **ctx,
bool set)
{ {
dds_topic *t; dds_topic *t;
if (dds_topic_lock(topic, &t) == DDS_RETCODE_OK) { if (dds_topic_lock (topic, &t) == DDS_RETCODE_OK)
if (set) { {
t->filter_fn = *filter; if (set) {
t->filter_ctx = *ctx; t->filter_fn = *filter;
} else { t->filter_ctx = *ctx;
*filter = t->filter_fn;
*ctx = t->filter_ctx;
}
dds_topic_unlock(t);
} else { } else {
*filter = 0; *filter = t->filter_fn;
*ctx = NULL; *ctx = t->filter_ctx;
} }
dds_topic_unlock (t);
}
else
{
*filter = 0;
*ctx = NULL;
}
} }
void void dds_set_topic_filter (dds_entity_t topic, dds_topic_filter_fn filter)
dds_set_topic_filter(
dds_entity_t topic,
dds_topic_filter_fn filter)
{ {
dds_topic_intern_filter_fn chaining = dds_topic_chaining_filter; dds_topic_intern_filter_fn chaining = dds_topic_chaining_filter;
void *realf = (void *)filter; void *realf = (void *) filter;
dds_topic_mod_filter (topic, &chaining, &realf, true); dds_topic_mod_filter (topic, &chaining, &realf, true);
} }
void void dds_topic_set_filter (dds_entity_t topic, dds_topic_filter_fn filter)
dds_topic_set_filter(
dds_entity_t topic,
dds_topic_filter_fn filter)
{ {
dds_set_topic_filter(topic, filter); dds_set_topic_filter (topic, filter);
} }
dds_topic_filter_fn dds_topic_filter_fn dds_get_topic_filter (dds_entity_t topic)
dds_get_topic_filter(
dds_entity_t topic)
{ {
dds_topic_intern_filter_fn filter; dds_topic_intern_filter_fn filter;
void *ctx; void *ctx;
dds_topic_mod_filter (topic, &filter, &ctx, false); dds_topic_mod_filter (topic, &filter, &ctx, false);
return (filter == dds_topic_chaining_filter) ? (dds_topic_filter_fn)ctx : 0; return (filter == dds_topic_chaining_filter) ? (dds_topic_filter_fn) ctx : 0;
} }
dds_topic_filter_fn dds_topic_filter_fn dds_topic_get_filter (dds_entity_t topic)
dds_topic_get_filter(
dds_entity_t topic)
{ {
return dds_get_topic_filter(topic); return dds_get_topic_filter (topic);
} }
void void dds_topic_set_filter_with_ctx (dds_entity_t topic, dds_topic_intern_filter_fn filter, void *ctx)
dds_topic_set_filter_with_ctx(
dds_entity_t topic,
dds_topic_intern_filter_fn filter,
void *ctx)
{ {
dds_topic_mod_filter (topic, &filter, &ctx, true); dds_topic_mod_filter (topic, &filter, &ctx, true);
} }
dds_topic_intern_filter_fn dds_topic_intern_filter_fn dds_topic_get_filter_with_ctx (dds_entity_t topic)
dds_topic_get_filter_with_ctx(
dds_entity_t topic)
{ {
dds_topic_intern_filter_fn filter; dds_topic_intern_filter_fn filter;
void *ctx; void *ctx;
@ -577,93 +443,32 @@ dds_topic_get_filter_with_ctx(
return (filter == dds_topic_chaining_filter) ? 0 : filter; return (filter == dds_topic_chaining_filter) ? 0 : filter;
} }
DDS_EXPORT dds_return_t dds_return_t dds_get_name (dds_entity_t topic, char *name, size_t size)
dds_get_name(
dds_entity_t topic,
char *name,
size_t size)
{ {
dds_topic *t; dds_topic *t;
dds_return_t ret; dds_return_t ret;
if (size <= 0 || name == NULL)
if(size <= 0){ return DDS_RETCODE_BAD_PARAMETER;
DDS_ERROR("Argument size is smaller than 0\n"); name[0] = '\0';
ret = DDS_RETCODE_BAD_PARAMETER; if ((ret = dds_topic_lock (topic, &t)) != DDS_RETCODE_OK)
goto fail;
}
if(name == NULL){
DDS_ERROR("Argument name is NULL\n");
ret = DDS_RETCODE_BAD_PARAMETER;
goto fail;
}
name[0] = '\0';
ret = dds_topic_lock(topic, &t);
if (ret == DDS_RETCODE_OK) {
(void)snprintf(name, size, "%s", t->m_stopic->name);
dds_topic_unlock(t);
} else {
DDS_ERROR("Error occurred on locking topic\n");
goto fail;
}
fail:
return ret; return ret;
(void) snprintf (name, size, "%s", t->m_stopic->name);
dds_topic_unlock (t);
return DDS_RETCODE_OK;
} }
DDS_EXPORT dds_return_t dds_return_t dds_get_type_name (dds_entity_t topic, char *name, size_t size)
dds_get_type_name(
dds_entity_t topic,
char *name,
size_t size)
{ {
dds_topic *t; dds_topic *t;
dds_return_t ret; dds_return_t ret;
if (size <= 0 || name == NULL)
if(size <= 0){ return DDS_RETCODE_BAD_PARAMETER;
DDS_ERROR("Argument size is smaller than 0\n"); name[0] = '\0';
ret = DDS_RETCODE_BAD_PARAMETER; if ((ret = dds_topic_lock (topic, &t)) != DDS_RETCODE_OK)
goto fail;
}
if(name == NULL){
DDS_ERROR("Argument name is NULL\n");
ret = DDS_RETCODE_BAD_PARAMETER;
goto fail;
}
name[0] = '\0';
ret = dds_topic_lock(topic, &t);
if (ret != DDS_RETCODE_OK) {
DDS_ERROR("Error occurred on locking topic\n");
goto fail;
}
(void)snprintf(name, size, "%s", t->m_stopic->type_name);
dds_topic_unlock(t);
fail:
return ret; return ret;
(void) snprintf (name, size, "%s", t->m_stopic->type_name);
dds_topic_unlock (t);
return DDS_RETCODE_OK;
} }
dds_return_t DDS_GET_STATUS(topic, inconsistent_topic, INCONSISTENT_TOPIC, total_count_change)
dds_get_inconsistent_topic_status(
dds_entity_t topic,
dds_inconsistent_topic_status_t *status)
{
dds_topic *t;
dds_return_t ret;
ret = dds_topic_lock(topic, &t);
if (ret != DDS_RETCODE_OK) {
DDS_ERROR("Error occurred on locking topic\n");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = t->m_inconsistent_topic_status;
}
ddsrt_mutex_lock (&t->m_entity.m_observers_lock);
if (t->m_entity.m_status_enable & DDS_INCONSISTENT_TOPIC_STATUS) {
t->m_inconsistent_topic_status.total_count_change = 0;
dds_entity_status_reset(&t->m_entity, DDS_INCONSISTENT_TOPIC_STATUS);
}
ddsrt_mutex_unlock (&t->m_entity.m_observers_lock);
dds_topic_unlock(t);
fail:
return ret;
}

View file

@ -14,424 +14,296 @@
#include "dds/ddsrt/heap.h" #include "dds/ddsrt/heap.h"
#include "dds/ddsrt/log.h" #include "dds/ddsrt/log.h"
#include "dds__entity.h" #include "dds__entity.h"
#include "dds__participant.h"
#include "dds__querycond.h" #include "dds__querycond.h"
#include "dds__readcond.h" #include "dds__readcond.h"
#include "dds__rhc.h" #include "dds__rhc.h"
DEFINE_ENTITY_LOCK_UNLOCK(static, dds_waitset, DDS_KIND_WAITSET) DEFINE_ENTITY_LOCK_UNLOCK (static, dds_waitset, DDS_KIND_WAITSET)
static void static void dds_waitset_swap (dds_attachment **dst, dds_attachment **src, dds_attachment *prev, dds_attachment *idx)
dds_waitset_swap(
dds_attachment **dst,
dds_attachment **src,
dds_attachment *prev,
dds_attachment *idx)
{ {
/* Remove from source. */ /* Remove from source. */
if (prev == NULL) { if (prev == NULL)
*src = idx->next; *src = idx->next;
} else { else
prev->next = idx->next; prev->next = idx->next;
}
/* Add to destination. */ /* Add to destination. */
idx->next = *dst; idx->next = *dst;
*dst = idx; *dst = idx;
} }
static dds_return_t static dds_return_t dds_waitset_wait_impl (dds_entity_t waitset, dds_attach_t *xs, size_t nxs, dds_time_t abstimeout)
dds_waitset_wait_impl(
dds_entity_t waitset,
dds_attach_t *xs,
size_t nxs,
dds_time_t abstimeout,
dds_time_t tnow)
{ {
dds_waitset *ws; dds_waitset *ws;
dds_return_t ret; dds_return_t ret;
dds_attachment *idx; dds_attachment *idx;
dds_attachment *next; dds_attachment *prev;
dds_attachment *prev;
if ((xs == NULL) && (nxs != 0)){ if (xs == NULL && nxs != 0)
DDS_ERROR("A size was given, but no array\n"); return DDS_RETCODE_BAD_PARAMETER;
return DDS_RETCODE_BAD_PARAMETER; if (xs != NULL && nxs == 0)
} return DDS_RETCODE_BAD_PARAMETER;
if ((xs != NULL) && (nxs == 0)){
DDS_ERROR("Array is given with an invalid size\n");
return DDS_RETCODE_BAD_PARAMETER;
}
/* Locking the waitset here will delay a possible deletion until it is
* unlocked. Even when the related mutex is unlocked by a conditioned wait. */
ret = dds_waitset_lock(waitset, &ws);
if (ret == DDS_RETCODE_OK) {
/* Check if any of any previous triggered entities has changed there status
* and thus it trigger value could be false now. */
idx = ws->triggered;
prev = NULL;
while (idx != NULL) {
next = idx->next;
if (idx->entity->m_trigger == 0) {
/* Move observed entity to triggered list. */
dds_waitset_swap(&(ws->observed), &(ws->triggered), prev, idx);
} else {
prev = idx;
}
idx = next;
}
/* Check if any of the entities have been triggered. */
idx = ws->observed;
prev = NULL;
while (idx != NULL) {
next = idx->next;
if (idx->entity->m_trigger > 0) {
/* Move observed entity to triggered list. */
dds_waitset_swap(&(ws->triggered), &(ws->observed), prev, idx);
} else {
prev = idx;
}
idx = next;
}
/* Only wait/keep waiting when whe have something to observer and there aren't any triggers yet. */
while ((ws->observed != NULL) && (ws->triggered == NULL) && (ret == DDS_RETCODE_OK)) {
if (abstimeout == DDS_NEVER) {
ddsrt_cond_wait(&ws->m_entity.m_cond, &ws->m_entity.m_mutex);
} else if (abstimeout <= tnow) {
ret = DDS_RETCODE_TIMEOUT;
} else {
dds_duration_t dt = abstimeout - tnow;
(void)ddsrt_cond_waitfor(&ws->m_entity.m_cond, &ws->m_entity.m_mutex, dt);
tnow = dds_time();
}
}
/* Get number of triggered entities
* - set attach array when needed
* - swap them back to observed */
if (ret == DDS_RETCODE_OK) {
ret = 0;
idx = ws->triggered;
while (idx != NULL) {
if ((uint32_t)ret < (uint32_t)nxs) {
xs[ret] = idx->arg;
}
ret++;
next = idx->next;
/* The idx is always the first in triggered, so no prev. */
dds_waitset_swap(&(ws->observed), &(ws->triggered), NULL, idx);
idx = next;
}
} else if (ret == DDS_RETCODE_TIMEOUT) {
ret = 0;
} else {
DDS_ERROR("Internal error");
}
dds_waitset_unlock(ws);
} else {
DDS_ERROR("Error occurred on locking waitset\n");
}
/* Locking the waitset here will delay a possible deletion until it is
* unlocked. Even when the related mutex is unlocked by a conditioned wait. */
if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK)
return ret; return ret;
/* Move any previously but no longer triggering entities back to the observed list */
idx = ws->triggered;
prev = NULL;
while (idx != NULL)
{
dds_attachment *next = idx->next;
if (idx->entity->m_trigger == 0)
dds_waitset_swap (&ws->observed, &ws->triggered, prev, idx);
else
prev = idx;
idx = next;
}
/* Check if any of the observed entities are currently triggered, moving them
to the triggered list */
idx = ws->observed;
prev = NULL;
while (idx != NULL)
{
dds_attachment *next = idx->next;
if (idx->entity->m_trigger > 0)
dds_waitset_swap (&ws->triggered, &ws->observed, prev, idx);
else
prev = idx;
idx = next;
}
/* Only wait/keep waiting when we have something to observe and there aren't any triggers yet. */
while (ws->observed != NULL && ws->triggered == NULL)
if (!ddsrt_cond_waituntil (&ws->m_entity.m_cond, &ws->m_entity.m_mutex, abstimeout))
break;
/* Get number of triggered entities
* - set attach array when needed
* - swap them back to observed */
ret = 0;
idx = ws->triggered;
while (idx != NULL)
{
if ((uint32_t) ret < (uint32_t) nxs)
xs[ret] = idx->arg;
ret++;
/* The idx is always the first in triggered, so no prev. */
dds_attachment *next = idx->next;
dds_waitset_swap (&ws->observed, &ws->triggered, NULL, idx);
idx = next;
}
dds_waitset_unlock (ws);
return ret;
} }
static void static void dds_waitset_close_list (dds_attachment **list, dds_entity_t waitset)
dds_waitset_close_list(
dds_attachment **list,
dds_entity_t waitset)
{ {
dds_attachment *idx = *list; dds_attachment *idx = *list;
dds_attachment *next; dds_attachment *next;
while (idx != NULL) { while (idx != NULL)
next = idx->next; {
(void)dds_entity_observer_unregister(idx->entity->m_hdllink.hdl, waitset); next = idx->next;
ddsrt_free(idx); (void) dds_entity_observer_unregister (idx->entity->m_hdllink.hdl, waitset);
idx = next; ddsrt_free (idx);
} idx = next;
*list = NULL; }
*list = NULL;
} }
static bool static bool dds_waitset_remove_from_list (dds_attachment **list, dds_entity_t observed)
dds_waitset_remove_from_list(
dds_attachment **list,
dds_entity_t observed)
{ {
dds_attachment *idx = *list; dds_attachment *idx, *prev;
dds_attachment *prev = NULL; for (idx = *list, prev = NULL; idx != NULL; prev = idx, idx = idx->next)
if (idx->entity->m_hdllink.hdl == observed)
while (idx != NULL) { break;
if (idx->entity->m_hdllink.hdl == observed) { if (idx == NULL)
if (prev == NULL) {
*list = idx->next;
} else {
prev->next = idx->next;
}
ddsrt_free(idx);
/* We're done. */
return true;
}
prev = idx;
idx = idx->next;
}
return false; return false;
if (prev == NULL)
*list = idx->next;
else
prev->next = idx->next;
ddsrt_free (idx);
return true;
} }
dds_return_t dds_return_t dds_waitset_close (struct dds_entity *e)
dds_waitset_close(
struct dds_entity *e)
{ {
dds_waitset *ws = (dds_waitset*)e; dds_waitset *ws = (dds_waitset *) e;
dds_waitset_close_list (&ws->observed, e->m_hdllink.hdl);
dds_waitset_close_list(&ws->observed, e->m_hdllink.hdl); dds_waitset_close_list (&ws->triggered, e->m_hdllink.hdl);
dds_waitset_close_list(&ws->triggered, e->m_hdllink.hdl); ddsrt_cond_broadcast (&e->m_cond);
return DDS_RETCODE_OK;
/* Trigger waitset to wake up. */
ddsrt_cond_broadcast(&e->m_cond);
return DDS_RETCODE_OK;
} }
DDS_EXPORT dds_entity_t dds_entity_t dds_create_waitset (dds_entity_t participant)
dds_create_waitset(
dds_entity_t participant)
{ {
dds_entity_t hdl; dds_entity_t hdl;
dds_entity *par; dds_participant *par;
dds_return_t rc; dds_return_t rc;
rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); if ((rc = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK)
if (rc == DDS_RETCODE_OK) { return rc;
dds_waitset *waitset = dds_alloc(sizeof(*waitset));
hdl = dds_entity_init(&waitset->m_entity, par, DDS_KIND_WAITSET, NULL, NULL, 0);
waitset->m_entity.m_deriver.close = dds_waitset_close;
waitset->observed = NULL;
waitset->triggered = NULL;
dds_entity_unlock(par);
} else {
hdl = rc;
}
return hdl; dds_waitset *waitset = dds_alloc (sizeof (*waitset));
hdl = dds_entity_init (&waitset->m_entity, &par->m_entity, DDS_KIND_WAITSET, NULL, NULL, 0);
waitset->m_entity.m_deriver.close = dds_waitset_close;
waitset->observed = NULL;
waitset->triggered = NULL;
dds_participant_unlock (par);
return hdl;
} }
DDS_EXPORT dds_return_t dds_return_t dds_waitset_get_entities (dds_entity_t waitset, dds_entity_t *entities, size_t size)
dds_waitset_get_entities(
dds_entity_t waitset,
dds_entity_t *entities,
size_t size)
{ {
dds_return_t ret; dds_return_t ret;
dds_waitset *ws; dds_waitset *ws;
ret = dds_waitset_lock(waitset, &ws);
if (ret == DDS_RETCODE_OK) {
dds_attachment* iter;
ret = 0;
iter = ws->observed;
while (iter) {
if (((size_t)ret < size) && (entities != NULL)) {
entities[ret] = iter->entity->m_hdllink.hdl;
}
ret++;
iter = iter->next;
}
iter = ws->triggered;
while (iter) {
if (((size_t)ret < size) && (entities != NULL)) {
entities[ret] = iter->entity->m_hdllink.hdl;
}
ret++;
iter = iter->next;
}
dds_waitset_unlock(ws);
} else {
DDS_ERROR("Error occurred on locking waitset\n");
}
if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK)
return ret; return ret;
ret = 0;
for (dds_attachment *iter = ws->observed; iter != NULL; iter = iter->next)
{
if ((size_t) ret < size && entities != NULL)
entities[ret] = iter->entity->m_hdllink.hdl;
ret++;
}
for (dds_attachment *iter = ws->triggered; iter != NULL; iter = iter->next)
{
if ((size_t) ret < size && entities != NULL)
entities[ret] = iter->entity->m_hdllink.hdl;
ret++;
}
dds_waitset_unlock(ws);
return ret;
} }
static void dds_waitset_move (dds_attachment **src, dds_attachment **dst, dds_entity_t entity)
static void
dds_waitset_move(
dds_attachment **src,
dds_attachment **dst,
dds_entity_t entity)
{ {
dds_attachment *idx = *src; dds_attachment *idx, *prev;
dds_attachment *prev = NULL; for (idx = *src, prev = NULL; idx != NULL; prev = idx, idx = idx->next)
while (idx != NULL) { if (idx->entity->m_hdllink.hdl == entity)
if (idx->entity->m_hdllink.hdl == entity) { break;
/* Swap idx from src to dst. */ if (idx != NULL)
dds_waitset_swap(dst, src, prev, idx); {
/* Swap idx from src to dst. */
/* We're done. */ dds_waitset_swap (dst, src, prev, idx);
return; }
}
prev = idx;
idx = idx->next;
}
} }
static void static void dds_waitset_remove (dds_waitset *ws, dds_entity_t observed)
dds_waitset_remove(
dds_waitset *ws,
dds_entity_t observed)
{ {
if (!dds_waitset_remove_from_list(&(ws->observed), observed)) { if (!dds_waitset_remove_from_list (&ws->observed, observed))
(void)dds_waitset_remove_from_list(&(ws->triggered), observed); (void) dds_waitset_remove_from_list (&ws->triggered, observed);
}
} }
/* This is called when the observed entity signals a status change. */ /* This is called when the observed entity signals a status change. */
void void dds_waitset_observer (dds_entity_t observer, dds_entity_t observed, uint32_t status)
dds_waitset_observer(
dds_entity_t observer,
dds_entity_t observed,
uint32_t status)
{ {
dds_waitset *ws; dds_waitset *ws;
if (dds_waitset_lock(observer, &ws) == DDS_RETCODE_OK) { if (dds_waitset_lock (observer, &ws) == DDS_RETCODE_OK) {
if (status & DDS_DELETING_STATUS) { if (status & DDS_DELETING_STATUS) {
/* Remove this observed entity, which is being deleted, from the waitset. */ /* Remove this observed entity, which is being deleted, from the waitset. */
dds_waitset_remove(ws, observed); dds_waitset_remove (ws, observed);
/* Our registration to this observed entity will be removed automatically. */ /* Our registration to this observed entity will be removed automatically. */
} else if (status != 0) { } else if (status != 0) {
/* Move observed entity to triggered list. */ /* Move observed entity to triggered list. */
dds_waitset_move(&(ws->observed), &(ws->triggered), observed); dds_waitset_move (&ws->observed, &ws->triggered, observed);
} else {
/* Remove observed entity from triggered list (which it possibly resides in). */
dds_waitset_move(&(ws->triggered), &(ws->observed), observed);
}
/* Trigger waitset to wake up. */
ddsrt_cond_broadcast(&ws->m_entity.m_cond);
dds_waitset_unlock(ws);
}
}
DDS_EXPORT dds_return_t
dds_waitset_attach(
dds_entity_t waitset,
dds_entity_t entity,
dds_attach_t x)
{
dds_entity *e = NULL;
dds_waitset *ws;
dds_return_t ret;
ret = dds_waitset_lock(waitset, &ws);
if (ret == DDS_RETCODE_OK) {
if (waitset != entity) {
ret = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e);
if (ret != DDS_RETCODE_OK) {
e = NULL;
}
} else {
e = &ws->m_entity;
}
/* This will fail if given entity is already attached (or deleted). */
if (ret == DDS_RETCODE_OK) {
ret = dds_entity_observer_register_nl(e, waitset, dds_waitset_observer);
}
if (ret == DDS_RETCODE_OK) {
dds_attachment *a = ddsrt_malloc(sizeof(dds_attachment));
a->arg = x;
a->entity = e;
if (e->m_trigger > 0) {
a->next = ws->triggered;
ws->triggered = a;
} else {
a->next = ws->observed;
ws->observed = a;
}
ret = DDS_RETCODE_OK;
} else if (ret != DDS_RETCODE_PRECONDITION_NOT_MET) {
DDS_ERROR("Entity is not valid\n");
ret = DDS_RETCODE_BAD_PARAMETER;
} else {
DDS_ERROR("Entity is already attached\n");
}
if ((e != NULL) && (waitset != entity)) {
dds_entity_unlock(e);
}
dds_waitset_unlock(ws);
} else { } else {
DDS_ERROR("Error occurred on locking waitset\n"); /* Remove observed entity from triggered list (which it possibly resides in). */
dds_waitset_move (&ws->triggered, &ws->observed, observed);
} }
/* Trigger waitset to wake up. */
return ret; ddsrt_cond_broadcast (&ws->m_entity.m_cond);
dds_waitset_unlock (ws);
}
} }
DDS_EXPORT dds_return_t dds_return_t dds_waitset_attach (dds_entity_t waitset, dds_entity_t entity, dds_attach_t x)
dds_waitset_detach(
dds_entity_t waitset,
dds_entity_t entity)
{ {
dds_waitset *ws; dds_entity *e;
dds_return_t ret; dds_waitset *ws;
dds_return_t ret;
ret = dds_waitset_lock(waitset, &ws);
if (ret == DDS_RETCODE_OK) {
/* Possibly fails when entity was not attached. */
if (waitset == entity) {
ret = dds_entity_observer_unregister_nl(&ws->m_entity, waitset);
} else {
ret = dds_entity_observer_unregister(entity, waitset);
}
if (ret == DDS_RETCODE_OK) {
dds_waitset_remove(ws, entity);
} else if (ret != DDS_RETCODE_PRECONDITION_NOT_MET) {
DDS_ERROR("The given entity to detach is invalid\n");
ret = DDS_RETCODE_BAD_PARAMETER;
} else {
DDS_ERROR("The given entity to detach was not attached previously\n");
}
dds_waitset_unlock(ws);
} else {
DDS_ERROR("Error occurred on locking waitset\n");
}
if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK)
return ret; return ret;
if (waitset == entity)
e = &ws->m_entity;
else if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK)
{
ret = DDS_RETCODE_BAD_PARAMETER;
goto err_waitset;
}
/* This will fail if given entity is already attached (or deleted). */
if ((ret = dds_entity_observer_register_nl (e, waitset, dds_waitset_observer)) != DDS_RETCODE_OK)
goto err_entity;
dds_attachment *a = ddsrt_malloc (sizeof (*a));
a->arg = x;
a->entity = e;
if (e->m_trigger > 0) {
a->next = ws->triggered;
ws->triggered = a;
} else {
a->next = ws->observed;
ws->observed = a;
}
err_entity:
if (e != &ws->m_entity)
dds_entity_unlock (e);
err_waitset:
dds_waitset_unlock (ws);
return ret;
} }
dds_return_t dds_return_t dds_waitset_detach (dds_entity_t waitset, dds_entity_t entity)
dds_waitset_wait_until(
dds_entity_t waitset,
dds_attach_t *xs,
size_t nxs,
dds_time_t abstimeout)
{ {
return dds_waitset_wait_impl(waitset, xs, nxs, abstimeout, dds_time()); dds_waitset *ws;
dds_return_t ret;
if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK)
return ret;
/* Possibly fails when entity was not attached. */
if (waitset == entity)
ret = dds_entity_observer_unregister_nl (&ws->m_entity, waitset);
else
ret = dds_entity_observer_unregister (entity, waitset);
if (ret == DDS_RETCODE_OK)
dds_waitset_remove (ws, entity);
else
{
if (ret != DDS_RETCODE_PRECONDITION_NOT_MET)
ret = DDS_RETCODE_BAD_PARAMETER;
}
dds_waitset_unlock (ws);
return ret;
} }
dds_return_t dds_return_t dds_waitset_wait_until (dds_entity_t waitset, dds_attach_t *xs, size_t nxs, dds_time_t abstimeout)
dds_waitset_wait(
dds_entity_t waitset,
dds_attach_t *xs,
size_t nxs,
dds_duration_t reltimeout)
{ {
dds_entity_t ret; return dds_waitset_wait_impl(waitset, xs, nxs, abstimeout);
}
if (reltimeout >= 0) { dds_return_t dds_waitset_wait (dds_entity_t waitset, dds_attach_t *xs, size_t nxs, dds_duration_t reltimeout)
dds_time_t tnow = dds_time(); {
dds_time_t abstimeout = (DDS_INFINITY - reltimeout <= tnow) ? DDS_NEVER : (tnow + reltimeout); if (reltimeout < 0)
ret = dds_waitset_wait_impl(waitset, xs, nxs, abstimeout, tnow); return DDS_RETCODE_BAD_PARAMETER;
} else{ const dds_time_t tnow = dds_time ();
DDS_ERROR("Negative timeout\n"); const dds_time_t abstimeout = (DDS_INFINITY - reltimeout <= tnow) ? DDS_NEVER : (tnow + reltimeout);
ret = DDS_RETCODE_BAD_PARAMETER; return dds_waitset_wait_impl (waitset, xs, nxs, abstimeout);
}
return ret;
} }
dds_return_t dds_waitset_set_trigger (dds_entity_t waitset, bool trigger) dds_return_t dds_waitset_set_trigger (dds_entity_t waitset, bool trigger)
@ -455,4 +327,3 @@ dds_return_t dds_waitset_set_trigger (dds_entity_t waitset, bool trigger)
dds_waitset_unlock (ws); dds_waitset_unlock (ws);
return DDS_RETCODE_OK; return DDS_RETCODE_OK;
} }

View file

@ -35,7 +35,7 @@ struct whc_node {
struct whc_node *next_seq; /* next in this interval */ struct whc_node *next_seq; /* next in this interval */
struct whc_node *prev_seq; /* prev in this interval */ struct whc_node *prev_seq; /* prev in this interval */
struct whc_idxnode *idxnode; /* NULL if not in index */ struct whc_idxnode *idxnode; /* NULL if not in index */
unsigned idxnode_pos; /* index in idxnode.hist */ uint32_t idxnode_pos; /* index in idxnode.hist */
seqno_t seq; seqno_t seq;
uint64_t total_bytes; /* cumulative number of bytes up to and including this node */ uint64_t total_bytes; /* cumulative number of bytes up to and including this node */
size_t size; size_t size;
@ -43,7 +43,7 @@ struct whc_node {
unsigned unacked: 1; /* counted in whc::unacked_bytes iff 1 */ unsigned unacked: 1; /* counted in whc::unacked_bytes iff 1 */
unsigned borrowed: 1; /* at most one can borrow it at any time */ unsigned borrowed: 1; /* at most one can borrow it at any time */
nn_mtime_t last_rexmit_ts; nn_mtime_t last_rexmit_ts;
unsigned rexmit_count; uint32_t rexmit_count;
struct ddsi_serdata *serdata; struct ddsi_serdata *serdata;
}; };
@ -59,7 +59,7 @@ struct whc_idxnode {
uint64_t iid; uint64_t iid;
seqno_t prune_seq; seqno_t prune_seq;
struct ddsi_tkmap_instance *tk; struct ddsi_tkmap_instance *tk;
unsigned headidx; uint32_t headidx;
#if __STDC_VERSION__ >= 199901L #if __STDC_VERSION__ >= 199901L
struct whc_node *hist[]; struct whc_node *hist[];
#else #else
@ -77,14 +77,14 @@ struct whc_seq_entry {
struct whc_impl { struct whc_impl {
struct whc common; struct whc common;
ddsrt_mutex_t lock; ddsrt_mutex_t lock;
unsigned seq_size; uint32_t seq_size;
size_t unacked_bytes; size_t unacked_bytes;
size_t sample_overhead; size_t sample_overhead;
uint64_t total_bytes; /* total number of bytes pushed in */ uint64_t total_bytes; /* total number of bytes pushed in */
unsigned is_transient_local: 1; unsigned is_transient_local: 1;
unsigned hdepth; /* 0 = unlimited */ uint32_t hdepth; /* 0 = unlimited */
unsigned tldepth; /* 0 = disabled/unlimited (no need to maintain an index if KEEP_ALL <=> is_transient_local + tldepth=0) */ uint32_t tldepth; /* 0 = disabled/unlimited (no need to maintain an index if KEEP_ALL <=> is_transient_local + tldepth=0) */
unsigned idxdepth; /* = max(hdepth, tldepth) */ uint32_t idxdepth; /* = max (hdepth, tldepth) */
seqno_t max_drop_seq; /* samples in whc with seq <= max_drop_seq => transient-local */ seqno_t max_drop_seq; /* samples in whc with seq <= max_drop_seq => transient-local */
struct whc_intvnode *open_intv; /* interval where next sample will go (usually) */ struct whc_intvnode *open_intv; /* interval where next sample will go (usually) */
struct whc_node *maxseq_node; /* NULL if empty; if not in open_intv, open_intv is empty */ struct whc_node *maxseq_node; /* NULL if empty; if not in open_intv, open_intv is empty */
@ -103,14 +103,12 @@ struct whc_sample_iter_impl {
}; };
/* check that our definition of whc_sample_iter fits in the type that callers allocate */ /* check that our definition of whc_sample_iter fits in the type that callers allocate */
struct whc_sample_iter_sizecheck { DDSRT_STATIC_ASSERT (sizeof (struct whc_sample_iter_impl) <= sizeof (struct whc_sample_iter));
char fits_in_generic_type[sizeof(struct whc_sample_iter_impl) <= sizeof(struct whc_sample_iter) ? 1 : -1];
};
/* Hash + interval tree adminitration of samples-by-sequence number /* Hash + interval tree adminitration of samples-by-sequence number
* - by definition contains all samples in WHC (unchanged from older versions) * - by definition contains all samples in WHC (unchanged from older versions)
* Circular array of samples per instance, inited to all 0 * Circular array of samples per instance, inited to all 0
* - length is max(durability_service.history_depth, history.depth), KEEP_ALL => as-if 0 * - length is max (durability_service.history_depth, history.depth), KEEP_ALL => as-if 0
* - no instance index if above length 0 * - no instance index if above length 0
* - each sample (i.e., whc_node): backpointer into index * - each sample (i.e., whc_node): backpointer into index
* - maintain index of latest sample, end of history then trivially follows from index arithmetic * - maintain index of latest sample, end of history then trivially follows from index arithmetic
@ -124,24 +122,24 @@ static void insert_whcn_in_hash (struct whc_impl *whc, struct whc_node *whcn);
static void whc_delete_one (struct whc_impl *whc, struct whc_node *whcn); static void whc_delete_one (struct whc_impl *whc, struct whc_node *whcn);
static int compare_seq (const void *va, const void *vb); static int compare_seq (const void *va, const void *vb);
static void free_deferred_free_list (struct whc_node *deferred_free_list); static void free_deferred_free_list (struct whc_node *deferred_free_list);
static void get_state_locked(const struct whc_impl *whc, struct whc_state *st); static void get_state_locked (const struct whc_impl *whc, struct whc_state *st);
static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list); static uint32_t whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list);
static unsigned whc_default_remove_acked_messages (struct whc *whc, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list); static uint32_t whc_default_remove_acked_messages (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_free_deferred_free_list (struct whc *whc, struct whc_node *deferred_free_list);
static void whc_default_get_state(const struct whc *whc, struct whc_state *st); static void whc_default_get_state (const struct whc *whc, struct whc_state *st);
static int whc_default_insert (struct whc *whc, seqno_t max_drop_seq, seqno_t seq, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); static 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 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 (const struct whc *whc, seqno_t seq, struct whc_borrowed_sample *sample);
static bool whc_default_borrow_sample_key (const struct whc *whc, const struct ddsi_serdata *serdata_key, struct whc_borrowed_sample *sample); static bool whc_default_borrow_sample_key (const struct whc *whc, const struct ddsi_serdata *serdata_key, struct whc_borrowed_sample *sample);
static void whc_default_return_sample (struct whc *whc, struct whc_borrowed_sample *sample, bool update_retransmit_info); static void whc_default_return_sample (struct whc *whc, struct whc_borrowed_sample *sample, bool update_retransmit_info);
static unsigned whc_default_downgrade_to_volatile (struct whc *whc, struct whc_state *st); static uint32_t whc_default_downgrade_to_volatile (struct whc *whc, struct whc_state *st);
static void whc_default_sample_iter_init (const struct whc *whc, struct whc_sample_iter *opaque_it); static void whc_default_sample_iter_init (const struct whc *whc, struct whc_sample_iter *opaque_it);
static bool whc_default_sample_iter_borrow_next (struct whc_sample_iter *opaque_it, struct whc_borrowed_sample *sample); static bool whc_default_sample_iter_borrow_next (struct whc_sample_iter *opaque_it, struct whc_borrowed_sample *sample);
static void whc_default_free (struct whc *whc); static void whc_default_free (struct whc *whc);
static const ddsrt_avl_treedef_t whc_seq_treedef = static const ddsrt_avl_treedef_t whc_seq_treedef =
DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct whc_intvnode, avlnode), offsetof (struct whc_intvnode, min), compare_seq, 0); DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct whc_intvnode, avlnode), offsetof (struct whc_intvnode, min), compare_seq, 0);
static const struct whc_ops whc_ops = { static const struct whc_ops whc_ops = {
.insert = whc_default_insert, .insert = whc_default_insert,
@ -159,12 +157,12 @@ static const struct whc_ops whc_ops = {
}; };
/* Number of instantiated WHCs and a global freelist for WHC nodes that gets /* Number of instantiated WHCs and a global freelist for WHC nodes that gets
initialized lazily and cleaned up automatically when the last WHC is freed. initialized lazily and cleaned up automatically when the last WHC is freed.
Protected by dds_global.m_mutex. Protected by dds_global.m_mutex.
sizeof (whc_node) on 64-bit machines ~ 100 bytes, so this is ~1MB sizeof (whc_node) on 64-bit machines ~ 100 bytes, so this is ~1MB
8k entries seems to be roughly the amount needed for minimum samples, 8k entries seems to be roughly the amount needed for minimum samples,
maximum message size and a short round-trip time */ maximum message size and a short round-trip time */
#define MAX_FREELIST_SIZE 8192 #define MAX_FREELIST_SIZE 8192
static uint32_t whc_count; static uint32_t whc_count;
static struct nn_freelist whc_node_freelist; static struct nn_freelist whc_node_freelist;
@ -175,9 +173,9 @@ static uint32_t whc_seq_entry_hash (const void *vn)
const struct whc_seq_entry *n = vn; const struct whc_seq_entry *n = vn;
/* we hash the lower 32 bits, on the assumption that with 4 billion /* we hash the lower 32 bits, on the assumption that with 4 billion
samples in between there won't be significant correlation */ samples in between there won't be significant correlation */
const uint64_t c = UINT64_C(16292676669999574021); const uint64_t c = UINT64_C (16292676669999574021);
const uint32_t x = (uint32_t) n->seq; const uint32_t x = (uint32_t) n->seq;
return (unsigned) ((x * c) >> 32); return (uint32_t) ((x * c) >> 32);
} }
static int whc_seq_entry_eq (const void *va, const void *vb) static int whc_seq_entry_eq (const void *va, const void *vb)
@ -192,9 +190,9 @@ static uint32_t whc_node_hash (const void *vn)
const struct whc_node *n = vn; const struct whc_node *n = vn;
/* we hash the lower 32 bits, on the assumption that with 4 billion /* we hash the lower 32 bits, on the assumption that with 4 billion
samples in between there won't be significant correlation */ samples in between there won't be significant correlation */
const uint64_t c = UINT64_C(16292676669999574021); const uint64_t c = UINT64_C (16292676669999574021);
const uint32_t x = (uint32_t) n->seq; const uint32_t x = (uint32_t) n->seq;
return (unsigned) ((x * c) >> 32); return (uint32_t) ((x * c) >> 32);
} }
static int whc_node_eq (const void *va, const void *vb) static int whc_node_eq (const void *va, const void *vb)
@ -245,10 +243,10 @@ static struct whc_node *whc_findmax_procedurally (const struct whc_impl *whc)
static void check_whc (const struct whc_impl *whc) static void check_whc (const struct whc_impl *whc)
{ {
/* there's much more we can check, but it gets expensive quite /* there's much more we can check, but it gets expensive quite
quickly: all nodes but open_intv non-empty, non-overlapping and quickly: all nodes but open_intv non-empty, non-overlapping and
non-contiguous; min & maxp1 of intervals correct; each interval non-contiguous; min & maxp1 of intervals correct; each interval
contiguous; all samples in seq & in seqhash; tlidx \subseteq seq; contiguous; all samples in seq & in seqhash; tlidx \subseteq seq;
seq-number ordered list correct; &c. */ seq-number ordered list correct; &c. */
assert (whc->open_intv != NULL); assert (whc->open_intv != NULL);
assert (whc->open_intv == ddsrt_avl_find_max (&whc_seq_treedef, &whc->seq)); assert (whc->open_intv == ddsrt_avl_find_max (&whc_seq_treedef, &whc->seq));
assert (ddsrt_avl_find_succ (&whc_seq_treedef, &whc->seq, whc->open_intv) == NULL); assert (ddsrt_avl_find_succ (&whc_seq_treedef, &whc->seq, whc->open_intv) == NULL);
@ -269,7 +267,7 @@ static void check_whc (const struct whc_impl *whc)
} }
assert (whc->maxseq_node == whc_findmax_procedurally (whc)); assert (whc->maxseq_node == whc_findmax_procedurally (whc));
#if !defined(NDEBUG) #if !defined (NDEBUG)
if (config.enabled_xchecks & DDS_XCHECK_WHC) if (config.enabled_xchecks & DDS_XCHECK_WHC)
{ {
struct whc_intvnode *firstintv; struct whc_intvnode *firstintv;
@ -295,10 +293,10 @@ static void insert_whcn_in_hash (struct whc_impl *whc, struct whc_node *whcn)
#if USE_EHH #if USE_EHH
struct whc_seq_entry e = { .seq = whcn->seq, .whcn = whcn }; struct whc_seq_entry e = { .seq = whcn->seq, .whcn = whcn };
if (!ddsrt_ehh_add (whc->seq_hash, &e)) if (!ddsrt_ehh_add (whc->seq_hash, &e))
assert(0); assert (0);
#else #else
if (!ddsrt_hh_add (whc->seq_hash, whcn)) if (!ddsrt_hh_add (whc->seq_hash, whcn))
assert(0); assert (0);
#endif #endif
} }
@ -307,11 +305,11 @@ static void remove_whcn_from_hash (struct whc_impl *whc, struct whc_node *whcn)
/* precondition: whcn is in hash */ /* precondition: whcn is in hash */
#if USE_EHH #if USE_EHH
struct whc_seq_entry e = { .seq = whcn->seq }; struct whc_seq_entry e = { .seq = whcn->seq };
if (!ddsrt_ehh_remove(whc->seq_hash, &e)) if (!ddsrt_ehh_remove (whc->seq_hash, &e))
assert(0); assert (0);
#else #else
if (!ddsrt_hh_remove(whc->seq_hash, whcn)) if (!ddsrt_hh_remove (whc->seq_hash, whcn))
assert(0); assert (0);
#endif #endif
} }
@ -319,14 +317,14 @@ static struct whc_node *whc_findseq (const struct whc_impl *whc, seqno_t seq)
{ {
#if USE_EHH #if USE_EHH
struct whc_seq_entry e = { .seq = seq }, *r; struct whc_seq_entry e = { .seq = seq }, *r;
if ((r = ddsrt_ehh_lookup(whc->seq_hash, &e)) != NULL) if ((r = ddsrt_ehh_lookup (whc->seq_hash, &e)) != NULL)
return r->whcn; return r->whcn;
else else
return NULL; return NULL;
#else #else
struct whc_node template; struct whc_node template;
template.seq = seq; template.seq = seq;
return ddsrt_hh_lookup(whc->seq_hash, &template); return ddsrt_hh_lookup (whc->seq_hash, &template);
#endif #endif
} }
@ -334,11 +332,11 @@ static struct whc_node *whc_findkey (const struct whc_impl *whc, const struct dd
{ {
union { union {
struct whc_idxnode idxn; struct whc_idxnode idxn;
char pad[sizeof(struct whc_idxnode) + sizeof(struct whc_node *)]; char pad[sizeof (struct whc_idxnode) + sizeof (struct whc_node *)];
} template; } template;
struct whc_idxnode *n; struct whc_idxnode *n;
check_whc (whc); check_whc (whc);
template.idxn.iid = ddsi_tkmap_lookup(gv.m_tkmap, serdata_key); template.idxn.iid = ddsi_tkmap_lookup (gv.m_tkmap, serdata_key);
n = ddsrt_hh_lookup (whc->idx_hash, &template.idxn); n = ddsrt_hh_lookup (whc->idx_hash, &template.idxn);
if (n == NULL) if (n == NULL)
return NULL; return NULL;
@ -349,13 +347,13 @@ static struct whc_node *whc_findkey (const struct whc_impl *whc, const struct dd
} }
} }
struct whc *whc_new (int is_transient_local, unsigned hdepth, unsigned tldepth) struct whc *whc_new (int is_transient_local, uint32_t hdepth, uint32_t tldepth)
{ {
size_t sample_overhead = 80; /* INFO_TS, DATA (estimate), inline QoS */ size_t sample_overhead = 80; /* INFO_TS, DATA (estimate), inline QoS */
struct whc_impl *whc; struct whc_impl *whc;
struct whc_intvnode *intv; struct whc_intvnode *intv;
assert((hdepth == 0 || tldepth <= hdepth) || is_transient_local); assert ((hdepth == 0 || tldepth <= hdepth) || is_transient_local);
whc = ddsrt_malloc (sizeof (*whc)); whc = ddsrt_malloc (sizeof (*whc));
whc->common.ops = &whc_ops; whc->common.ops = &whc_ops;
@ -372,11 +370,11 @@ struct whc *whc_new (int is_transient_local, unsigned hdepth, unsigned tldepth)
#if USE_EHH #if USE_EHH
whc->seq_hash = ddsrt_ehh_new (sizeof (struct whc_seq_entry), 32, whc_seq_entry_hash, whc_seq_entry_eq); whc->seq_hash = ddsrt_ehh_new (sizeof (struct whc_seq_entry), 32, whc_seq_entry_hash, whc_seq_entry_eq);
#else #else
whc->seq_hash = ddsrt_hh_new(32, whc_node_hash, whc_node_eq); whc->seq_hash = ddsrt_hh_new (32, whc_node_hash, whc_node_eq);
#endif #endif
if (whc->idxdepth > 0) if (whc->idxdepth > 0)
whc->idx_hash = ddsrt_hh_new(32, whc_idxnode_hash_key, whc_idxnode_eq_key); whc->idx_hash = ddsrt_hh_new (32, whc_idxnode_hash_key, whc_idxnode_eq_key);
else else
whc->idx_hash = NULL; whc->idx_hash = NULL;
@ -417,9 +415,9 @@ void whc_default_free (struct whc *whc_generic)
{ {
struct ddsrt_hh_iter it; struct ddsrt_hh_iter it;
struct whc_idxnode *n; struct whc_idxnode *n;
for (n = ddsrt_hh_iter_first(whc->idx_hash, &it); n != NULL; n = ddsrt_hh_iter_next(&it)) for (n = ddsrt_hh_iter_first (whc->idx_hash, &it); n != NULL; n = ddsrt_hh_iter_next (&it))
ddsrt_free(n); ddsrt_free (n);
ddsrt_hh_free(whc->idx_hash); ddsrt_hh_free (whc->idx_hash);
} }
{ {
@ -427,10 +425,10 @@ void whc_default_free (struct whc *whc_generic)
while (whcn) while (whcn)
{ {
struct whc_node *tmp = whcn; struct whc_node *tmp = whcn;
/* The compiler doesn't realize that whcn->prev_seq is always initialized. */ /* The compiler doesn't realize that whcn->prev_seq is always initialized. */
DDSRT_WARNING_MSVC_OFF(6001); DDSRT_WARNING_MSVC_OFF (6001);
whcn = whcn->prev_seq; whcn = whcn->prev_seq;
DDSRT_WARNING_MSVC_ON(6001); DDSRT_WARNING_MSVC_ON (6001);
free_whc_node_contents (tmp); free_whc_node_contents (tmp);
ddsrt_free (tmp); ddsrt_free (tmp);
} }
@ -452,7 +450,7 @@ DDSRT_WARNING_MSVC_ON(6001);
ddsrt_free (whc); ddsrt_free (whc);
} }
static void get_state_locked(const struct whc_impl *whc, struct whc_state *st) static void get_state_locked (const struct whc_impl *whc, struct whc_state *st)
{ {
if (whc->seq_size == 0) if (whc->seq_size == 0)
{ {
@ -473,12 +471,12 @@ static void get_state_locked(const struct whc_impl *whc, struct whc_state *st)
} }
} }
static void whc_default_get_state(const struct whc *whc_generic, struct whc_state *st) static void whc_default_get_state (const struct whc *whc_generic, struct whc_state *st)
{ {
const struct whc_impl * const whc = (const struct whc_impl *)whc_generic; const struct whc_impl * const whc = (const struct whc_impl *)whc_generic;
ddsrt_mutex_lock ((ddsrt_mutex_t *)&whc->lock); ddsrt_mutex_lock ((ddsrt_mutex_t *)&whc->lock);
check_whc (whc); check_whc (whc);
get_state_locked(whc, st); get_state_locked (whc, st);
ddsrt_mutex_unlock ((ddsrt_mutex_t *)&whc->lock); ddsrt_mutex_unlock ((ddsrt_mutex_t *)&whc->lock);
} }
@ -489,8 +487,8 @@ static struct whc_node *find_nextseq_intv (struct whc_intvnode **p_intv, const s
if ((n = whc_findseq (whc, seq)) == NULL) if ((n = whc_findseq (whc, seq)) == NULL)
{ {
/* don't know seq => lookup interval with min > seq (intervals are /* don't know seq => lookup interval with min > seq (intervals are
contiguous, so if we don't know seq, an interval [X,Y) with X < contiguous, so if we don't know seq, an interval [X,Y) with X <
SEQ < Y can't exist */ SEQ < Y can't exist */
#ifndef NDEBUG #ifndef NDEBUG
{ {
struct whc_intvnode *predintv = ddsrt_avl_lookup_pred_eq (&whc_seq_treedef, &whc->seq, &seq); struct whc_intvnode *predintv = ddsrt_avl_lookup_pred_eq (&whc_seq_treedef, &whc->seq, &seq);
@ -551,13 +549,12 @@ static void delete_one_sample_from_idx (struct whc_impl *whc, struct whc_node *w
else else
{ {
#ifndef NDEBUG #ifndef NDEBUG
unsigned i; for (uint32_t i = 0; i < whc->idxdepth; i++)
for (i = 0; i < whc->idxdepth; i++)
assert (i == idxn->headidx || idxn->hist[i] == NULL); assert (i == idxn->headidx || idxn->hist[i] == NULL);
#endif #endif
if (!ddsrt_hh_remove (whc->idx_hash, idxn)) if (!ddsrt_hh_remove (whc->idx_hash, idxn))
assert (0); assert (0);
ddsi_tkmap_instance_unref(idxn->tk); ddsi_tkmap_instance_unref (idxn->tk);
ddsrt_free (idxn); ddsrt_free (idxn);
} }
whcn->idxnode = NULL; whcn->idxnode = NULL;
@ -565,8 +562,7 @@ static void delete_one_sample_from_idx (struct whc_impl *whc, struct whc_node *w
static void free_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_idxnode *idxn) static void free_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_idxnode *idxn)
{ {
unsigned i; for (uint32_t i = 0; i < whc->idxdepth; i++)
for (i = 0; i < whc->idxdepth; i++)
{ {
if (idxn->hist[i]) if (idxn->hist[i])
{ {
@ -574,13 +570,13 @@ static void free_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_s
oldn->idxnode = NULL; oldn->idxnode = NULL;
if (oldn->seq <= max_drop_seq) if (oldn->seq <= max_drop_seq)
{ {
DDS_LOG(DDS_LC_WHC, " prune tl whcn %p\n", (void *)oldn); DDS_LOG (DDS_LC_WHC, " prune tl whcn %p\n", (void *)oldn);
assert(oldn != whc->maxseq_node); assert (oldn != whc->maxseq_node);
whc_delete_one (whc, oldn); whc_delete_one (whc, oldn);
} }
} }
} }
ddsrt_free(idxn); ddsrt_free (idxn);
} }
static void delete_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_idxnode *idxn) static void delete_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_idxnode *idxn)
@ -590,34 +586,34 @@ static void delete_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop
free_one_instance_from_idx (whc, max_drop_seq, idxn); free_one_instance_from_idx (whc, max_drop_seq, idxn);
} }
static int whcn_in_tlidx (const struct whc_impl *whc, const struct whc_idxnode *idxn, unsigned pos) static int whcn_in_tlidx (const struct whc_impl *whc, const struct whc_idxnode *idxn, uint32_t pos)
{ {
if (idxn == NULL) if (idxn == NULL)
return 0; return 0;
else else
{ {
unsigned d = (idxn->headidx + (pos > idxn->headidx ? whc->idxdepth : 0)) - pos; uint32_t d = (idxn->headidx + (pos > idxn->headidx ? whc->idxdepth : 0)) - pos;
assert (d < whc->idxdepth); assert (d < whc->idxdepth);
return d < whc->tldepth; return d < whc->tldepth;
} }
} }
static unsigned whc_default_downgrade_to_volatile (struct whc *whc_generic, struct whc_state *st) static uint32_t whc_default_downgrade_to_volatile (struct whc *whc_generic, struct whc_state *st)
{ {
struct whc_impl * const whc = (struct whc_impl *)whc_generic; struct whc_impl * const whc = (struct whc_impl *)whc_generic;
seqno_t old_max_drop_seq; seqno_t old_max_drop_seq;
struct whc_node *deferred_free_list; struct whc_node *deferred_free_list;
unsigned cnt; uint32_t cnt;
/* We only remove them from whc->tlidx: we don't remove them from /* We only remove them from whc->tlidx: we don't remove them from
whc->seq yet. That'll happen eventually. */ whc->seq yet. That'll happen eventually. */
ddsrt_mutex_lock (&whc->lock); ddsrt_mutex_lock (&whc->lock);
check_whc (whc); check_whc (whc);
if (whc->idxdepth == 0) if (whc->idxdepth == 0)
{ {
/* if not maintaining an index at all, this is nonsense */ /* if not maintaining an index at all, this is nonsense */
get_state_locked(whc, st); get_state_locked (whc, st);
ddsrt_mutex_unlock (&whc->lock); ddsrt_mutex_unlock (&whc->lock);
return 0; return 0;
} }
@ -625,29 +621,29 @@ static unsigned whc_default_downgrade_to_volatile (struct whc *whc_generic, stru
assert (!whc->is_transient_local); assert (!whc->is_transient_local);
if (whc->tldepth > 0) if (whc->tldepth > 0)
{ {
assert(whc->hdepth == 0 || whc->tldepth <= whc->hdepth); assert (whc->hdepth == 0 || whc->tldepth <= whc->hdepth);
whc->tldepth = 0; whc->tldepth = 0;
if (whc->hdepth == 0) if (whc->hdepth == 0)
{ {
struct ddsrt_hh_iter it; struct ddsrt_hh_iter it;
struct whc_idxnode *n; struct whc_idxnode *n;
for (n = ddsrt_hh_iter_first(whc->idx_hash, &it); n != NULL; n = ddsrt_hh_iter_next(&it)) for (n = ddsrt_hh_iter_first (whc->idx_hash, &it); n != NULL; n = ddsrt_hh_iter_next (&it))
free_one_instance_from_idx (whc, 0, n); free_one_instance_from_idx (whc, 0, n);
ddsrt_hh_free(whc->idx_hash); ddsrt_hh_free (whc->idx_hash);
whc->idxdepth = 0; whc->idxdepth = 0;
whc->idx_hash = NULL; whc->idx_hash = NULL;
} }
} }
/* Immediately drop them from the WHC (used to delay it until the /* Immediately drop them from the WHC (used to delay it until the
next ack); but need to make sure remove_acked_messages processes next ack); but need to make sure remove_acked_messages processes
them all. */ them all. */
old_max_drop_seq = whc->max_drop_seq; old_max_drop_seq = whc->max_drop_seq;
whc->max_drop_seq = 0; whc->max_drop_seq = 0;
cnt = whc_default_remove_acked_messages_full (whc, old_max_drop_seq, &deferred_free_list); cnt = whc_default_remove_acked_messages_full (whc, old_max_drop_seq, &deferred_free_list);
whc_default_free_deferred_free_list (whc_generic, deferred_free_list); whc_default_free_deferred_free_list (whc_generic, deferred_free_list);
assert (whc->max_drop_seq == old_max_drop_seq); assert (whc->max_drop_seq == old_max_drop_seq);
get_state_locked(whc, st); get_state_locked (whc, st);
ddsrt_mutex_unlock (&whc->lock); ddsrt_mutex_unlock (&whc->lock);
return cnt; return cnt;
} }
@ -661,14 +657,14 @@ static size_t whcn_size (const struct whc_impl *whc, const struct whc_node *whcn
static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_intv, struct whc_node **p_whcn) static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_intv, struct whc_node **p_whcn)
{ {
/* Removes *p_whcn, possibly deleting or splitting *p_intv, as the /* Removes *p_whcn, possibly deleting or splitting *p_intv, as the
case may be. Does *NOT* update whc->seq_size. *p_intv must be case may be. Does *NOT* update whc->seq_size. *p_intv must be
the interval containing *p_whcn (&& both must actually exist). the interval containing *p_whcn (&& both must actually exist).
Returns: Returns:
- 0 if delete failed (only possible cause is memory exhaustion), - 0 if delete failed (only possible cause is memory exhaustion),
in which case *p_intv & *p_whcn are undefined; in which case *p_intv & *p_whcn are undefined;
- 1 if successful, in which case *p_intv & *p_whcn are set - 1 if successful, in which case *p_intv & *p_whcn are set
correctly for the next sample in sequence number order */ correctly for the next sample in sequence number order */
struct whc_intvnode *intv = *p_intv; struct whc_intvnode *intv = *p_intv;
struct whc_node *whcn = *p_whcn; struct whc_node *whcn = *p_whcn;
assert (whcn->seq >= intv->min && whcn->seq < intv->maxp1); assert (whcn->seq >= intv->min && whcn->seq < intv->maxp1);
@ -685,13 +681,13 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i
} }
/* Take it out of seqhash; deleting it from the list ordered on /* Take it out of seqhash; deleting it from the list ordered on
sequence numbers is left to the caller (it has to be done unconditionally, sequence numbers is left to the caller (it has to be done unconditionally,
but remove_acked_messages defers it until the end or a skipped node). */ but remove_acked_messages defers it until the end or a skipped node). */
remove_whcn_from_hash (whc, whcn); remove_whcn_from_hash (whc, whcn);
/* We may have introduced a hole & have to split the interval /* We may have introduced a hole & have to split the interval
node, or we may have nibbled of the first one, or even the node, or we may have nibbled of the first one, or even the
last one. */ last one. */
if (whcn == intv->first) if (whcn == intv->first)
{ {
if (whcn == intv->last && intv != whc->open_intv) if (whcn == intv->last && intv != whc->open_intv)
@ -714,7 +710,7 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i
else if (whcn == intv->last) else if (whcn == intv->last)
{ {
/* well, at least it isn't the first one & so the interval is /* well, at least it isn't the first one & so the interval is
still non-empty and we don't have to drop the interval */ still non-empty and we don't have to drop the interval */
assert (intv->min < whcn->seq); assert (intv->min < whcn->seq);
assert (whcn->prev_seq); assert (whcn->prev_seq);
assert (whcn->prev_seq->seq + 1 == whcn->seq); assert (whcn->prev_seq->seq + 1 == whcn->seq);
@ -725,9 +721,9 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i
else else
{ {
/* somewhere in the middle => split the interval (ideally, /* somewhere in the middle => split the interval (ideally,
would split it lazily, but it really is a transient-local would split it lazily, but it really is a transient-local
issue only, and so we can (for now) get away with splitting issue only, and so we can (for now) get away with splitting
it greedily */ it greedily */
struct whc_intvnode *new_intv; struct whc_intvnode *new_intv;
ddsrt_avl_ipath_t path; ddsrt_avl_ipath_t path;
@ -746,7 +742,7 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i
assert (new_intv->min < new_intv->maxp1); assert (new_intv->min < new_intv->maxp1);
/* insert new node & continue the loop with intv set to the /* insert new node & continue the loop with intv set to the
new interval */ new interval */
if (ddsrt_avl_lookup_ipath (&whc_seq_treedef, &whc->seq, &new_intv->min, &path) != NULL) if (ddsrt_avl_lookup_ipath (&whc_seq_treedef, &whc->seq, &new_intv->min, &path) != NULL)
assert (0); assert (0);
ddsrt_avl_insert_ipath (&whc_seq_treedef, &whc->seq, new_intv, &path); ddsrt_avl_insert_ipath (&whc_seq_treedef, &whc->seq, new_intv, &path);
@ -801,11 +797,11 @@ static void whc_default_free_deferred_free_list (struct whc *whc_generic, struct
free_deferred_free_list (deferred_free_list); free_deferred_free_list (deferred_free_list);
} }
static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list) static uint32_t whc_default_remove_acked_messages_noidx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list)
{ {
struct whc_intvnode *intv; struct whc_intvnode *intv;
struct whc_node *whcn; struct whc_node *whcn;
unsigned ndropped = 0; uint32_t ndropped = 0;
/* In the trivial case of an empty WHC, get out quickly */ /* In the trivial case of an empty WHC, get out quickly */
if (max_drop_seq <= whc->max_drop_seq || whc->maxseq_node == NULL) if (max_drop_seq <= whc->max_drop_seq || whc->maxseq_node == NULL)
@ -817,7 +813,7 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s
} }
/* If simple, we have always dropped everything up to whc->max_drop_seq, /* If simple, we have always dropped everything up to whc->max_drop_seq,
and there can only be a single interval */ and there can only be a single interval */
#ifndef NDEBUG #ifndef NDEBUG
whcn = find_nextseq_intv (&intv, whc, whc->max_drop_seq); whcn = find_nextseq_intv (&intv, whc, whc->max_drop_seq);
assert (whcn == NULL || whcn->prev_seq == NULL); assert (whcn == NULL || whcn->prev_seq == NULL);
@ -826,14 +822,14 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s
intv = whc->open_intv; intv = whc->open_intv;
/* Drop everything up to and including max_drop_seq, or absent that one, /* Drop everything up to and including max_drop_seq, or absent that one,
the highest available sequence number (which then must be less) */ the highest available sequence number (which then must be less) */
if ((whcn = whc_findseq (whc, max_drop_seq)) == NULL) if ((whcn = whc_findseq (whc, max_drop_seq)) == NULL)
{ {
if (max_drop_seq < intv->min) if (max_drop_seq < intv->min)
{ {
/* at startup, whc->max_drop_seq = 0 and reader states have max ack'd seq taken from wr->seq; /* at startup, whc->max_drop_seq = 0 and reader states have max ack'd seq taken from wr->seq;
so if multiple readers are matched and the writer runs ahead of the readers, for the first so if multiple readers are matched and the writer runs ahead of the readers, for the first
ack, whc->max_drop_seq < max_drop_seq = MIN(readers max ack) < intv->min */ ack, whc->max_drop_seq < max_drop_seq = MIN (readers max ack) < intv->min */
if (max_drop_seq > whc->max_drop_seq) if (max_drop_seq > whc->max_drop_seq)
whc->max_drop_seq = max_drop_seq; whc->max_drop_seq = max_drop_seq;
*deferred_free_list = NULL; *deferred_free_list = NULL;
@ -847,7 +843,7 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s
} }
*deferred_free_list = intv->first; *deferred_free_list = intv->first;
ndropped = (unsigned) (whcn->seq - intv->min + 1); ndropped = (uint32_t) (whcn->seq - intv->min + 1);
intv->first = whcn->next_seq; intv->first = whcn->next_seq;
intv->min = max_drop_seq + 1; intv->min = max_drop_seq + 1;
@ -877,18 +873,18 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s
return ndropped; return ndropped;
} }
static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list) static uint32_t whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list)
{ {
struct whc_intvnode *intv; struct whc_intvnode *intv;
struct whc_node *whcn; struct whc_node *whcn;
struct whc_node *prev_seq; struct whc_node *prev_seq;
struct whc_node deferred_list_head, *last_to_free = &deferred_list_head; struct whc_node deferred_list_head, *last_to_free = &deferred_list_head;
unsigned ndropped = 0; uint32_t ndropped = 0;
if (whc->is_transient_local && whc->tldepth == 0) if (whc->is_transient_local && whc->tldepth == 0)
{ {
/* KEEP_ALL on transient local, so we can never ever delete anything */ /* KEEP_ALL on transient local, so we can never ever delete anything */
DDS_LOG(DDS_LC_WHC, " KEEP_ALL transient-local: do nothing\n"); DDS_LOG (DDS_LC_WHC, " KEEP_ALL transient-local: do nothing\n");
*deferred_free_list = NULL; *deferred_free_list = NULL;
return 0; return 0;
} }
@ -898,11 +894,11 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se
prev_seq = whcn ? whcn->prev_seq : NULL; prev_seq = whcn ? whcn->prev_seq : NULL;
while (whcn && whcn->seq <= max_drop_seq) while (whcn && whcn->seq <= max_drop_seq)
{ {
DDS_LOG(DDS_LC_WHC, " whcn %p %"PRId64, (void *) whcn, whcn->seq); DDS_LOG (DDS_LC_WHC, " whcn %p %"PRId64, (void *) whcn, whcn->seq);
if (whcn_in_tlidx(whc, whcn->idxnode, whcn->idxnode_pos)) if (whcn_in_tlidx (whc, whcn->idxnode, whcn->idxnode_pos))
{ {
/* quickly skip over samples in tlidx */ /* quickly skip over samples in tlidx */
DDS_LOG(DDS_LC_WHC, " tl:keep"); DDS_LOG (DDS_LC_WHC, " tl:keep");
if (whcn->unacked) if (whcn->unacked)
{ {
assert (whc->unacked_bytes >= whcn->size); assert (whc->unacked_bytes >= whcn->size);
@ -920,13 +916,13 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se
} }
else else
{ {
DDS_LOG(DDS_LC_WHC, " delete"); DDS_LOG (DDS_LC_WHC, " delete");
last_to_free->next_seq = whcn; last_to_free->next_seq = whcn;
last_to_free = last_to_free->next_seq; last_to_free = last_to_free->next_seq;
whc_delete_one_intv (whc, &intv, &whcn); whc_delete_one_intv (whc, &intv, &whcn);
ndropped++; ndropped++;
} }
DDS_LOG(DDS_LC_WHC, "\n"); DDS_LOG (DDS_LC_WHC, "\n");
} }
if (prev_seq) if (prev_seq)
prev_seq->next_seq = whcn; prev_seq->next_seq = whcn;
@ -936,32 +932,32 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se
*deferred_free_list = deferred_list_head.next_seq; *deferred_free_list = deferred_list_head.next_seq;
/* If the history is deeper than durability_service.history (but not KEEP_ALL), then there /* If the history is deeper than durability_service.history (but not KEEP_ALL), then there
may be old samples in this instance, samples that were retained because they were within may be old samples in this instance, samples that were retained because they were within
the T-L history but that are not anymore. Writing new samples will eventually push these the T-L history but that are not anymore. Writing new samples will eventually push these
out, but if the difference is large and the update rate low, it may take a long time. out, but if the difference is large and the update rate low, it may take a long time.
Thus, we had better prune them. */ Thus, we had better prune them. */
if (whc->tldepth > 0 && whc->idxdepth > whc->tldepth) if (whc->tldepth > 0 && whc->idxdepth > whc->tldepth)
{ {
assert(whc->hdepth == whc->idxdepth); assert (whc->hdepth == whc->idxdepth);
DDS_LOG(DDS_LC_WHC, " idxdepth %u > tldepth %u > 0 -- must prune\n", whc->idxdepth, whc->tldepth); DDS_LOG (DDS_LC_WHC, " idxdepth %"PRIu32" > tldepth %"PRIu32" > 0 -- must prune\n", whc->idxdepth, whc->tldepth);
/* Do a second pass over the sequence number range we just processed: this time we only /* Do a second pass over the sequence number range we just processed: this time we only
encounter samples that were retained because of the transient-local durability setting encounter samples that were retained because of the transient-local durability setting
(the rest has been dropped already) and we prune old samples in the instance */ (the rest has been dropped already) and we prune old samples in the instance */
whcn = find_nextseq_intv (&intv, whc, whc->max_drop_seq); whcn = find_nextseq_intv (&intv, whc, whc->max_drop_seq);
while (whcn && whcn->seq <= max_drop_seq) while (whcn && whcn->seq <= max_drop_seq)
{ {
struct whc_idxnode * const idxn = whcn->idxnode; struct whc_idxnode * const idxn = whcn->idxnode;
unsigned cnt, idx; uint32_t cnt, idx;
DDS_LOG(DDS_LC_WHC, " whcn %p %"PRId64" idxn %p prune_seq %"PRId64":", (void *)whcn, whcn->seq, (void *)idxn, idxn->prune_seq); DDS_LOG (DDS_LC_WHC, " whcn %p %"PRId64" idxn %p prune_seq %"PRId64":", (void *) whcn, whcn->seq, (void *) idxn, idxn->prune_seq);
assert(whcn_in_tlidx(whc, idxn, whcn->idxnode_pos)); assert (whcn_in_tlidx (whc, idxn, whcn->idxnode_pos));
assert (idxn->prune_seq <= max_drop_seq); assert (idxn->prune_seq <= max_drop_seq);
if (idxn->prune_seq == max_drop_seq) if (idxn->prune_seq == max_drop_seq)
{ {
DDS_LOG(DDS_LC_WHC, " already pruned\n"); DDS_LOG (DDS_LC_WHC, " already pruned\n");
whcn = whcn->next_seq; whcn = whcn->next_seq;
continue; continue;
} }
@ -977,27 +973,27 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se
if ((oldn = idxn->hist[idx]) != NULL) if ((oldn = idxn->hist[idx]) != NULL)
{ {
/* Delete it - but this may not result in deleting the index node as /* Delete it - but this may not result in deleting the index node as
there must still be a more recent one available */ there must still be a more recent one available */
#ifndef NDEBUG #ifndef NDEBUG
struct whc_node whcn_template; struct whc_node whcn_template;
union { union {
struct whc_idxnode idxn; struct whc_idxnode idxn;
char pad[sizeof(struct whc_idxnode) + sizeof(struct whc_node *)]; char pad[sizeof (struct whc_idxnode) + sizeof (struct whc_node *)];
} template; } template;
template.idxn.headidx = 0; template.idxn.headidx = 0;
template.idxn.hist[0] = &whcn_template; template.idxn.hist[0] = &whcn_template;
whcn_template.serdata = ddsi_serdata_ref(oldn->serdata); whcn_template.serdata = ddsi_serdata_ref (oldn->serdata);
assert(oldn->seq < whcn->seq); assert (oldn->seq < whcn->seq);
#endif #endif
DDS_LOG(DDS_LC_WHC, " del %p %"PRId64, (void *) oldn, oldn->seq); DDS_LOG (DDS_LC_WHC, " del %p %"PRId64, (void *) oldn, oldn->seq);
whc_delete_one (whc, oldn); whc_delete_one (whc, oldn);
#ifndef NDEBUG #ifndef NDEBUG
assert(ddsrt_hh_lookup(whc->idx_hash, &template) == idxn); assert (ddsrt_hh_lookup (whc->idx_hash, &template) == idxn);
ddsi_serdata_unref(whcn_template.serdata); ddsi_serdata_unref (whcn_template.serdata);
#endif #endif
} }
} }
DDS_LOG(DDS_LC_WHC, "\n"); DDS_LOG (DDS_LC_WHC, "\n");
whcn = whcn->next_seq; whcn = whcn->next_seq;
} }
} }
@ -1011,22 +1007,22 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se
return ndropped; return ndropped;
} }
static unsigned whc_default_remove_acked_messages (struct whc *whc_generic, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list) static uint32_t whc_default_remove_acked_messages (struct whc *whc_generic, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list)
{ {
struct whc_impl * const whc = (struct whc_impl *)whc_generic; struct whc_impl * const whc = (struct whc_impl *)whc_generic;
unsigned cnt; uint32_t cnt;
ddsrt_mutex_lock (&whc->lock); ddsrt_mutex_lock (&whc->lock);
assert (max_drop_seq < MAX_SEQ_NUMBER); assert (max_drop_seq < MAX_SEQ_NUMBER);
assert (max_drop_seq >= whc->max_drop_seq); assert (max_drop_seq >= whc->max_drop_seq);
if (dds_get_log_mask() & DDS_LC_WHC) if (dds_get_log_mask () & DDS_LC_WHC)
{ {
struct whc_state tmp; struct whc_state tmp;
get_state_locked(whc, &tmp); get_state_locked (whc, &tmp);
DDS_LOG(DDS_LC_WHC, "whc_default_remove_acked_messages(%p max_drop_seq %"PRId64")\n", (void *)whc, max_drop_seq); DDS_LOG (DDS_LC_WHC, "whc_default_remove_acked_messages(%p max_drop_seq %"PRId64")\n", (void *)whc, max_drop_seq);
DDS_LOG(DDS_LC_WHC, " whc: [%"PRId64",%"PRId64"] max_drop_seq %"PRId64" h %u tl %u\n", DDS_LOG (DDS_LC_WHC, " whc: [%"PRId64",%"PRId64"] max_drop_seq %"PRId64" h %"PRIu32" tl %"PRIu32"\n",
tmp.min_seq, tmp.max_seq, whc->max_drop_seq, whc->hdepth, whc->tldepth); tmp.min_seq, tmp.max_seq, whc->max_drop_seq, whc->hdepth, whc->tldepth);
} }
check_whc (whc); check_whc (whc);
@ -1035,7 +1031,7 @@ static unsigned whc_default_remove_acked_messages (struct whc *whc_generic, seqn
cnt = whc_default_remove_acked_messages_noidx (whc, max_drop_seq, deferred_free_list); cnt = whc_default_remove_acked_messages_noidx (whc, max_drop_seq, deferred_free_list);
else else
cnt = whc_default_remove_acked_messages_full (whc, max_drop_seq, deferred_free_list); cnt = whc_default_remove_acked_messages_full (whc, max_drop_seq, deferred_free_list);
get_state_locked(whc, whcst); get_state_locked (whc, whcst);
ddsrt_mutex_unlock (&whc->lock); ddsrt_mutex_unlock (&whc->lock);
return cnt; return cnt;
} }
@ -1108,38 +1104,39 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se
struct whc_idxnode *idxn; struct whc_idxnode *idxn;
union { union {
struct whc_idxnode idxn; struct whc_idxnode idxn;
char pad[sizeof(struct whc_idxnode) + sizeof(struct whc_node *)]; char pad[sizeof (struct whc_idxnode) + sizeof (struct whc_node *)];
} template; } template;
ddsrt_mutex_lock (&whc->lock); ddsrt_mutex_lock (&whc->lock);
check_whc (whc); check_whc (whc);
if (dds_get_log_mask() & DDS_LC_WHC) if (dds_get_log_mask () & DDS_LC_WHC)
{ {
struct whc_state whcst; struct whc_state whcst;
get_state_locked(whc, &whcst); get_state_locked (whc, &whcst);
DDS_LOG(DDS_LC_WHC, "whc_default_insert(%p max_drop_seq %"PRId64" seq %"PRId64" plist %p serdata %p:%"PRIx32")\n", (void *)whc, max_drop_seq, seq, (void*)plist, (void*)serdata, serdata->hash); DDS_LOG (DDS_LC_WHC, "whc_default_insert(%p max_drop_seq %"PRId64" seq %"PRId64" plist %p serdata %p:%"PRIx32")\n",
DDS_LOG(DDS_LC_WHC, " whc: [%"PRId64",%"PRId64"] max_drop_seq %"PRId64" h %u tl %u\n", (void *)whc, max_drop_seq, seq, (void*)plist, (void*)serdata, serdata->hash);
whcst.min_seq, whcst.max_seq, whc->max_drop_seq, whc->hdepth, whc->tldepth); DDS_LOG (DDS_LC_WHC, " whc: [%"PRId64",%"PRId64"] max_drop_seq %"PRId64" h %"PRIu32" tl %"PRIu32"\n",
whcst.min_seq, whcst.max_seq, whc->max_drop_seq, whc->hdepth, whc->tldepth);
} }
assert (max_drop_seq < MAX_SEQ_NUMBER); assert (max_drop_seq < MAX_SEQ_NUMBER);
assert (max_drop_seq >= whc->max_drop_seq); assert (max_drop_seq >= whc->max_drop_seq);
/* Seq must be greater than what is currently stored. Usually it'll /* Seq must be greater than what is currently stored. Usually it'll
be the next sequence number, but if there are no readers be the next sequence number, but if there are no readers
temporarily, a gap may be among the possibilities */ temporarily, a gap may be among the possibilities */
assert (whc->seq_size == 0 || seq > whc->maxseq_node->seq); assert (whc->seq_size == 0 || seq > whc->maxseq_node->seq);
/* Always insert in seq admin */ /* Always insert in seq admin */
newn = whc_default_insert_seq (whc, max_drop_seq, seq, plist, serdata); newn = whc_default_insert_seq (whc, max_drop_seq, seq, plist, serdata);
DDS_LOG(DDS_LC_WHC, " whcn %p:", (void*)newn); DDS_LOG (DDS_LC_WHC, " whcn %p:", (void*)newn);
/* Special case of empty data (such as commit messages) can't go into index, and if we're not maintaining an index, we're done, too */ /* Special case of empty data (such as commit messages) can't go into index, and if we're not maintaining an index, we're done, too */
if (serdata->kind == SDK_EMPTY || whc->idxdepth == 0) if (serdata->kind == SDK_EMPTY || whc->idxdepth == 0)
{ {
DDS_LOG(DDS_LC_WHC, " empty or no hist\n"); DDS_LOG (DDS_LC_WHC, " empty or no hist\n");
ddsrt_mutex_unlock (&whc->lock); ddsrt_mutex_unlock (&whc->lock);
return 0; return 0;
} }
@ -1148,15 +1145,15 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se
if ((idxn = ddsrt_hh_lookup (whc->idx_hash, &template)) != NULL) if ((idxn = ddsrt_hh_lookup (whc->idx_hash, &template)) != NULL)
{ {
/* Unregisters cause deleting of index entry, non-unregister of adding/overwriting in history */ /* Unregisters cause deleting of index entry, non-unregister of adding/overwriting in history */
DDS_LOG(DDS_LC_WHC, " idxn %p", (void *)idxn); DDS_LOG (DDS_LC_WHC, " idxn %p", (void *)idxn);
if (serdata->statusinfo & NN_STATUSINFO_UNREGISTER) if (serdata->statusinfo & NN_STATUSINFO_UNREGISTER)
{ {
DDS_LOG(DDS_LC_WHC, " unreg:delete\n"); DDS_LOG (DDS_LC_WHC, " unreg:delete\n");
delete_one_instance_from_idx (whc, max_drop_seq, idxn); delete_one_instance_from_idx (whc, max_drop_seq, idxn);
if (newn->seq <= max_drop_seq) if (newn->seq <= max_drop_seq)
{ {
struct whc_node *prev_seq = newn->prev_seq; struct whc_node *prev_seq = newn->prev_seq;
DDS_LOG(DDS_LC_WHC, " unreg:seq <= max_drop_seq: delete newn\n"); DDS_LOG (DDS_LC_WHC, " unreg:seq <= max_drop_seq: delete newn\n");
whc_delete_one (whc, newn); whc_delete_one (whc, newn);
whc->maxseq_node = prev_seq; whc->maxseq_node = prev_seq;
} }
@ -1168,7 +1165,7 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se
idxn->headidx = 0; idxn->headidx = 0;
if ((oldn = idxn->hist[idxn->headidx]) != NULL) if ((oldn = idxn->hist[idxn->headidx]) != NULL)
{ {
DDS_LOG(DDS_LC_WHC, " overwrite whcn %p", (void *)oldn); DDS_LOG (DDS_LC_WHC, " overwrite whcn %p", (void *)oldn);
oldn->idxnode = NULL; oldn->idxnode = NULL;
} }
idxn->hist[idxn->headidx] = newn; idxn->hist[idxn->headidx] = newn;
@ -1177,46 +1174,45 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se
if (oldn && (whc->hdepth > 0 || oldn->seq <= max_drop_seq)) if (oldn && (whc->hdepth > 0 || oldn->seq <= max_drop_seq))
{ {
DDS_LOG(DDS_LC_WHC, " prune whcn %p", (void *)oldn); DDS_LOG (DDS_LC_WHC, " prune whcn %p", (void *)oldn);
assert(oldn != whc->maxseq_node); assert (oldn != whc->maxseq_node);
whc_delete_one (whc, oldn); whc_delete_one (whc, oldn);
} }
/* Special case for dropping everything beyond T-L history when the new sample is being /* Special case for dropping everything beyond T-L history when the new sample is being
auto-acknowledged (for lack of reliable readers), and the keep-last T-L history is auto-acknowledged (for lack of reliable readers), and the keep-last T-L history is
shallower than the keep-last regular history (normal path handles this via pruning in shallower than the keep-last regular history (normal path handles this via pruning in
whc_default_remove_acked_messages, but that never happens when there are no readers). */ whc_default_remove_acked_messages, but that never happens when there are no readers). */
if (seq <= max_drop_seq && whc->tldepth > 0 && whc->idxdepth > whc->tldepth) if (seq <= max_drop_seq && whc->tldepth > 0 && whc->idxdepth > whc->tldepth)
{ {
unsigned pos = idxn->headidx + whc->idxdepth - whc->tldepth; uint32_t pos = idxn->headidx + whc->idxdepth - whc->tldepth;
if (pos >= whc->idxdepth) if (pos >= whc->idxdepth)
pos -= whc->idxdepth; pos -= whc->idxdepth;
if ((oldn = idxn->hist[pos]) != NULL) if ((oldn = idxn->hist[pos]) != NULL)
{ {
DDS_LOG(DDS_LC_WHC, " prune tl whcn %p", (void *)oldn); DDS_LOG (DDS_LC_WHC, " prune tl whcn %p", (void *)oldn);
assert(oldn != whc->maxseq_node); assert (oldn != whc->maxseq_node);
whc_delete_one (whc, oldn); whc_delete_one (whc, oldn);
} }
} }
DDS_LOG(DDS_LC_WHC, "\n"); DDS_LOG (DDS_LC_WHC, "\n");
} }
} }
else else
{ {
DDS_LOG(DDS_LC_WHC, " newkey"); DDS_LOG (DDS_LC_WHC, " newkey");
/* Ignore unregisters, but insert everything else */ /* Ignore unregisters, but insert everything else */
if (!(serdata->statusinfo & NN_STATUSINFO_UNREGISTER)) if (!(serdata->statusinfo & NN_STATUSINFO_UNREGISTER))
{ {
unsigned i;
idxn = ddsrt_malloc (sizeof (*idxn) + whc->idxdepth * sizeof (idxn->hist[0])); idxn = ddsrt_malloc (sizeof (*idxn) + whc->idxdepth * sizeof (idxn->hist[0]));
DDS_LOG(DDS_LC_WHC, " idxn %p", (void *)idxn); DDS_LOG (DDS_LC_WHC, " idxn %p", (void *)idxn);
ddsi_tkmap_instance_ref(tk); ddsi_tkmap_instance_ref (tk);
idxn->iid = tk->m_iid; idxn->iid = tk->m_iid;
idxn->tk = tk; idxn->tk = tk;
idxn->prune_seq = 0; idxn->prune_seq = 0;
idxn->headidx = 0; idxn->headidx = 0;
idxn->hist[0] = newn; idxn->hist[0] = newn;
for (i = 1; i < whc->idxdepth; i++) for (uint32_t i = 1; i < whc->idxdepth; i++)
idxn->hist[i] = NULL; idxn->hist[i] = NULL;
newn->idxnode = idxn; newn->idxnode = idxn;
newn->idxnode_pos = 0; newn->idxnode_pos = 0;
@ -1225,24 +1221,24 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se
} }
else else
{ {
DDS_LOG(DDS_LC_WHC, " unreg:skip"); DDS_LOG (DDS_LC_WHC, " unreg:skip");
if (newn->seq <= max_drop_seq) if (newn->seq <= max_drop_seq)
{ {
struct whc_node *prev_seq = newn->prev_seq; struct whc_node *prev_seq = newn->prev_seq;
DDS_LOG(DDS_LC_WHC, " unreg:seq <= max_drop_seq: delete newn\n"); DDS_LOG (DDS_LC_WHC, " unreg:seq <= max_drop_seq: delete newn\n");
whc_delete_one (whc, newn); whc_delete_one (whc, newn);
whc->maxseq_node = prev_seq; whc->maxseq_node = prev_seq;
} }
} }
DDS_LOG(DDS_LC_WHC, "\n"); DDS_LOG (DDS_LC_WHC, "\n");
} }
ddsrt_mutex_unlock (&whc->lock); ddsrt_mutex_unlock (&whc->lock);
return 0; return 0;
} }
static void make_borrowed_sample(struct whc_borrowed_sample *sample, struct whc_node *whcn) static void make_borrowed_sample (struct whc_borrowed_sample *sample, struct whc_node *whcn)
{ {
assert(!whcn->borrowed); assert (!whcn->borrowed);
whcn->borrowed = 1; whcn->borrowed = 1;
sample->seq = whcn->seq; sample->seq = whcn->seq;
sample->plist = whcn->plist; sample->plist = whcn->plist;
@ -1258,11 +1254,11 @@ static bool whc_default_borrow_sample (const struct whc *whc_generic, seqno_t se
struct whc_node *whcn; struct whc_node *whcn;
bool found; bool found;
ddsrt_mutex_lock ((ddsrt_mutex_t *)&whc->lock); ddsrt_mutex_lock ((ddsrt_mutex_t *)&whc->lock);
if ((whcn = whc_findseq(whc, seq)) == NULL) if ((whcn = whc_findseq (whc, seq)) == NULL)
found = false; found = false;
else else
{ {
make_borrowed_sample(sample, whcn); make_borrowed_sample (sample, whcn);
found = true; found = true;
} }
ddsrt_mutex_unlock ((ddsrt_mutex_t *)&whc->lock); ddsrt_mutex_unlock ((ddsrt_mutex_t *)&whc->lock);
@ -1275,11 +1271,11 @@ static bool whc_default_borrow_sample_key (const struct whc *whc_generic, const
struct whc_node *whcn; struct whc_node *whcn;
bool found; bool found;
ddsrt_mutex_lock ((ddsrt_mutex_t *)&whc->lock); ddsrt_mutex_lock ((ddsrt_mutex_t *)&whc->lock);
if ((whcn = whc_findkey(whc, serdata_key)) == NULL) if ((whcn = whc_findkey (whc, serdata_key)) == NULL)
found = false; found = false;
else else
{ {
make_borrowed_sample(sample, whcn); make_borrowed_sample (sample, whcn);
found = true; found = true;
} }
ddsrt_mutex_unlock ((ddsrt_mutex_t *)&whc->lock); ddsrt_mutex_unlock ((ddsrt_mutex_t *)&whc->lock);
@ -1293,14 +1289,15 @@ static void return_sample_locked (struct whc_impl *whc, struct whc_borrowed_samp
{ {
/* data no longer present in WHC - that means ownership for serdata, plist shifted to the borrowed copy and "returning" it really becomes "destroying" it */ /* data no longer present in WHC - that means ownership for serdata, plist shifted to the borrowed copy and "returning" it really becomes "destroying" it */
ddsi_serdata_unref (sample->serdata); ddsi_serdata_unref (sample->serdata);
if (sample->plist) { if (sample->plist)
{
nn_plist_fini (sample->plist); nn_plist_fini (sample->plist);
ddsrt_free (sample->plist); ddsrt_free (sample->plist);
} }
} }
else else
{ {
assert(whcn->borrowed); assert (whcn->borrowed);
whcn->borrowed = 0; whcn->borrowed = 0;
if (update_retransmit_info) if (update_retransmit_info)
{ {
@ -1338,7 +1335,7 @@ static bool whc_default_sample_iter_borrow_next (struct whc_sample_iter *opaque_
if (!it->first) if (!it->first)
{ {
seq = sample->seq; seq = sample->seq;
return_sample_locked(whc, sample, false); return_sample_locked (whc, sample, false);
} }
else else
{ {
@ -1349,7 +1346,7 @@ static bool whc_default_sample_iter_borrow_next (struct whc_sample_iter *opaque_
valid = false; valid = false;
else else
{ {
make_borrowed_sample(sample, whcn); make_borrowed_sample (sample, whcn);
valid = true; valid = true;
} }
ddsrt_mutex_unlock (&whc->lock); ddsrt_mutex_unlock (&whc->lock);

View file

@ -44,9 +44,7 @@ struct bwhc_iter {
}; };
/* check that our definition of whc_sample_iter fits in the type that callers allocate */ /* check that our definition of whc_sample_iter fits in the type that callers allocate */
struct bwhc_sample_iter_sizecheck { DDSRT_STATIC_ASSERT (sizeof (struct bwhc_iter) <= sizeof (struct whc_sample_iter));
char fits_in_generic_type[sizeof(struct bwhc_iter) <= sizeof(struct whc_sample_iter) ? 1 : -1];
};
static void bwhc_free (struct whc *whc_generic) static void bwhc_free (struct whc *whc_generic)
{ {

View file

@ -111,13 +111,13 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay
else else
{ {
/* When deleting, pwr is no longer accessible via the hash /* When deleting, pwr is no longer accessible via the hash
tables, and consequently, a reader may be deleted without tables, and consequently, a reader may be deleted without
it being possible to remove it from rdary. The primary it being possible to remove it from rdary. The primary
reason rdary exists is to avoid locking the proxy writer reason rdary exists is to avoid locking the proxy writer
but this is less of an issue when we are deleting it, so but this is less of an issue when we are deleting it, so
we fall back to using the GUIDs so that we can deliver all we fall back to using the GUIDs so that we can deliver all
samples we received from it. As writer being deleted any samples we received from it. As writer being deleted any
reliable samples that are rejected are simply discarded. */ reliable samples that are rejected are simply discarded. */
ddsrt_avl_iter_t it; ddsrt_avl_iter_t it;
struct pwr_rd_match *m; struct pwr_rd_match *m;
struct proxy_writer_info pwr_info; struct proxy_writer_info pwr_info;
@ -130,8 +130,8 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay
struct reader *rd; struct reader *rd;
if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL)
{ {
DDS_TRACE("reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid)); DDS_TRACE ("reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid));
/* Copied the return value ignore from DDSI deliver_user_data() function. */ /* Copied the return value ignore from DDSI deliver_user_data () function. */
if ((ret = try_store (rd->rhc, &pwr_info, payload, tk, &max_block_ms)) != DDS_RETCODE_OK) if ((ret = try_store (rd->rhc, &pwr_info, payload, tk, &max_block_ms)) != DDS_RETCODE_OK)
break; break;
} }
@ -152,40 +152,34 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam
int w_rc; int w_rc;
if (data == NULL) if (data == NULL)
{
DDS_ERROR("No data buffer provided\n");
return DDS_RETCODE_BAD_PARAMETER; return DDS_RETCODE_BAD_PARAMETER;
}
/* Check for topic filter */ /* Check for topic filter */
if (wr->m_topic->filter_fn && !writekey) if (wr->m_topic->filter_fn && !writekey)
if (!(wr->m_topic->filter_fn) (data, wr->m_topic->filter_ctx)) if (! wr->m_topic->filter_fn (data, wr->m_topic->filter_ctx))
return DDS_RETCODE_OK; return DDS_RETCODE_OK;
thread_state_awake (ts1); thread_state_awake (ts1);
/* Serialize and write data or key */ /* Serialize and write data or key */
d = ddsi_serdata_from_sample (ddsi_wr->topic, writekey ? SDK_KEY : SDK_DATA, data); d = ddsi_serdata_from_sample (ddsi_wr->topic, writekey ? SDK_KEY : SDK_DATA, data);
d->statusinfo = ((action & DDS_WR_DISPOSE_BIT) ? NN_STATUSINFO_DISPOSE : 0) | ((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0); d->statusinfo = (((action & DDS_WR_DISPOSE_BIT) ? NN_STATUSINFO_DISPOSE : 0) |
((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0));
d->timestamp.v = tstamp; d->timestamp.v = tstamp;
ddsi_serdata_ref (d); ddsi_serdata_ref (d);
tk = ddsi_tkmap_lookup_instance_ref (d); tk = ddsi_tkmap_lookup_instance_ref (d);
w_rc = write_sample_gc (ts1, wr->m_xp, ddsi_wr, d, tk); w_rc = write_sample_gc (ts1, wr->m_xp, ddsi_wr, d, tk);
if (w_rc >= 0) if (w_rc >= 0) {
{
/* Flush out write unless configured to batch */ /* Flush out write unless configured to batch */
if (!config.whc_batch) if (!config.whc_batch)
nn_xpack_send (wr->m_xp, false); nn_xpack_send (wr->m_xp, false);
ret = DDS_RETCODE_OK; ret = DDS_RETCODE_OK;
} else if (w_rc == DDS_RETCODE_TIMEOUT) { } else if (w_rc == DDS_RETCODE_TIMEOUT) {
DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n");
ret = DDS_RETCODE_TIMEOUT; ret = DDS_RETCODE_TIMEOUT;
} else if (w_rc == DDS_RETCODE_BAD_PARAMETER) { } else if (w_rc == DDS_RETCODE_BAD_PARAMETER) {
DDS_ERROR ("Invalid data provided\n");
ret = DDS_RETCODE_ERROR; ret = DDS_RETCODE_ERROR;
} else { } else {
DDS_ERROR ("Internal error\n");
ret = DDS_RETCODE_ERROR; ret = DDS_RETCODE_ERROR;
} }
if (ret == DDS_RETCODE_OK) if (ret == DDS_RETCODE_OK)
@ -213,13 +207,10 @@ dds_return_t dds_writecdr_impl_lowlevel (struct writer *ddsi_wr, struct nn_xpack
nn_xpack_send (xp, false); nn_xpack_send (xp, false);
ret = DDS_RETCODE_OK; ret = DDS_RETCODE_OK;
} else if (w_rc == DDS_RETCODE_TIMEOUT) { } else if (w_rc == DDS_RETCODE_TIMEOUT) {
DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n");
ret = DDS_RETCODE_TIMEOUT; ret = DDS_RETCODE_TIMEOUT;
} else if (w_rc == DDS_RETCODE_BAD_PARAMETER) { } else if (w_rc == DDS_RETCODE_BAD_PARAMETER) {
DDS_ERROR ("Invalid data provided\n");
ret = DDS_RETCODE_ERROR; ret = DDS_RETCODE_ERROR;
} else { } else {
DDS_ERROR ("Internal error\n");
ret = DDS_RETCODE_ERROR; ret = DDS_RETCODE_ERROR;
} }
@ -236,7 +227,8 @@ dds_return_t dds_writecdr_impl (dds_writer *wr, struct ddsi_serdata *d, dds_time
if (wr->m_topic->filter_fn) if (wr->m_topic->filter_fn)
abort (); abort ();
/* Set if disposing or unregistering */ /* Set if disposing or unregistering */
d->statusinfo = ((action & DDS_WR_DISPOSE_BIT) ? NN_STATUSINFO_DISPOSE : 0) | ((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0); d->statusinfo = (((action & DDS_WR_DISPOSE_BIT) ? NN_STATUSINFO_DISPOSE : 0) |
((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0));
d->timestamp.v = tstamp; d->timestamp.v = tstamp;
return dds_writecdr_impl_lowlevel (wr->m_wr, wr->m_xp, d); return dds_writecdr_impl_lowlevel (wr->m_wr, wr->m_xp, d);
} }
@ -252,9 +244,7 @@ void dds_write_flush (dds_entity_t writer)
dds_writer *wr; dds_writer *wr;
dds_return_t rc; dds_return_t rc;
thread_state_awake (ts1); thread_state_awake (ts1);
if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) if ((rc = dds_writer_lock (writer, &wr)) == DDS_RETCODE_OK)
DDS_ERROR ("Error occurred on locking writer\n");
else
{ {
nn_xpack_send (wr->m_xp, true); nn_xpack_send (wr->m_xp, true);
dds_writer_unlock (wr); dds_writer_unlock (wr);

View file

@ -24,40 +24,29 @@
#include "dds__init.h" #include "dds__init.h"
#include "dds__publisher.h" #include "dds__publisher.h"
#include "dds__topic.h" #include "dds__topic.h"
#include "dds__get_status.h"
#include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_tkmap.h"
#include "dds__whc.h" #include "dds__whc.h"
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_writer) DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_writer)
#define DDS_WRITER_STATUS_MASK \ #define DDS_WRITER_STATUS_MASK \
DDS_LIVELINESS_LOST_STATUS |\ (DDS_LIVELINESS_LOST_STATUS |\
DDS_OFFERED_DEADLINE_MISSED_STATUS |\ DDS_OFFERED_DEADLINE_MISSED_STATUS |\
DDS_OFFERED_INCOMPATIBLE_QOS_STATUS |\ DDS_OFFERED_INCOMPATIBLE_QOS_STATUS |\
DDS_PUBLICATION_MATCHED_STATUS DDS_PUBLICATION_MATCHED_STATUS)
static dds_return_t static dds_return_t dds_writer_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all;
dds_writer_instance_hdl(
dds_entity *e, static dds_return_t dds_writer_instance_hdl (dds_entity *e, dds_instance_handle_t *i)
dds_instance_handle_t *i)
{ {
assert(e); *i = writer_instance_id(&e->m_guid);
assert(i); return DDS_RETCODE_OK;
*i = (dds_instance_handle_t)writer_instance_id(&e->m_guid);
return DDS_RETCODE_OK;
} }
static dds_return_t static dds_return_t dds_writer_status_validate (uint32_t mask)
dds_writer_status_validate(
uint32_t mask)
{ {
dds_return_t ret = DDS_RETCODE_OK; return (mask & ~DDS_WRITER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK;
if (mask & ~(DDS_WRITER_STATUS_MASK)) {
DDS_ERROR("Invalid status mask\n");
ret = DDS_RETCODE_BAD_PARAMETER;
}
return ret;
} }
/* /*
@ -173,285 +162,217 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data)
ddsrt_mutex_unlock (&entity->m_observers_lock); ddsrt_mutex_unlock (&entity->m_observers_lock);
} }
static uint32_t static uint32_t get_bandwidth_limit (nn_transport_priority_qospolicy_t transport_priority)
get_bandwidth_limit(
nn_transport_priority_qospolicy_t transport_priority)
{ {
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS #ifdef DDSI_INCLUDE_NETWORK_CHANNELS
struct config_channel_listelem *channel = find_channel (transport_priority); struct config_channel_listelem *channel = find_channel (transport_priority);
return channel->data_bandwidth_limit; return channel->data_bandwidth_limit;
#else #else
(void)transport_priority; (void) transport_priority;
return 0; return 0;
#endif #endif
} }
static dds_return_t static dds_return_t dds_writer_close (dds_entity *e) ddsrt_nonnull_all;
dds_writer_close(
dds_entity *e)
{
dds_return_t ret = DDS_RETCODE_OK;
dds_writer *wr = (dds_writer*)e;
assert(e); static dds_return_t dds_writer_close (dds_entity *e)
{
dds_writer * const wr = (dds_writer *) e;
dds_return_t ret;
thread_state_awake (lookup_thread_state ());
nn_xpack_send (wr->m_xp, false);
if ((ret = delete_writer (&e->m_guid)) < 0)
ret = DDS_RETCODE_ERROR;
thread_state_asleep (lookup_thread_state ());
return ret;
}
static dds_return_t dds_writer_delete (dds_entity *e) ddsrt_nonnull_all;
static dds_return_t dds_writer_delete (dds_entity *e)
{
dds_writer * const wr = (dds_writer *) e;
dds_return_t ret;
/* FIXME: not freeing WHC here because it is owned by the DDSI entity */
thread_state_awake (lookup_thread_state ());
nn_xpack_free (wr->m_xp);
thread_state_asleep (lookup_thread_state ());
if ((ret = dds_delete (wr->m_topic->m_entity.m_hdllink.hdl)) == DDS_RETCODE_OK)
{
ret = dds_delete_impl (e->m_parent->m_hdllink.hdl, true);
if (ret == DDS_RETCODE_BAD_PARAMETER)
ret = DDS_RETCODE_OK;
}
return ret;
}
static dds_return_t dds_writer_qos_validate (const dds_qos_t *qos, bool enabled)
{
if (!dds_qos_validate_common(qos))
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_USER_DATA) && !validate_octetseq (&qos->user_data))
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy (&qos->durability_service) < 0)
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_LIFESPAN) && validate_duration (&qos->lifespan.duration) < 0)
return DDS_RETCODE_INCONSISTENT_POLICY;
if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits(&qos->history, &qos->resource_limits) < 0)
return DDS_RETCODE_INCONSISTENT_POLICY;
return enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK;
}
static dds_return_t dds_writer_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
{
/* FIXME: QoS changes */
dds_return_t ret;
if ((ret = dds_writer_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
return ret;
/* Sort-of support updating ownership strength */
if ((qos->present & QP_OWNERSHIP_STRENGTH) && (qos->present & ~QP_OWNERSHIP_STRENGTH) == 0)
{
dds_ownership_kind_t kind;
dds_qget_ownership (e->m_qos, &kind);
if (kind != DDS_OWNERSHIP_EXCLUSIVE)
return DDS_RETCODE_ERROR;
struct writer *ddsi_wr = ((dds_writer *) e)->m_wr;
dds_qset_ownership_strength (e->m_qos, qos->ownership_strength.value);
thread_state_awake (lookup_thread_state ()); thread_state_awake (lookup_thread_state ());
nn_xpack_send (wr->m_xp, false);
if (delete_writer (&e->m_guid) != 0) { /* FIXME: with QoS changes being unsupported by the underlying stack I wonder what will happen; locking the underlying DDSI writer is of doubtful value as well */
DDS_ERROR("Internal error"); ddsrt_mutex_lock (&ddsi_wr->e.lock);
ret = DDS_RETCODE_ERROR; ddsi_wr->xqos->ownership_strength.value = qos->ownership_strength.value;
} ddsrt_mutex_unlock (&ddsi_wr->e.lock);
thread_state_asleep (lookup_thread_state ()); thread_state_asleep (lookup_thread_state ());
return ret; }
else
{
if (enabled)
ret = DDS_RETCODE_UNSUPPORTED;
}
return ret;
} }
static dds_return_t static struct whc *make_whc (const dds_qos_t *qos)
dds_writer_delete(
dds_entity *e)
{
dds_writer *wr = (dds_writer*)e;
dds_return_t ret;
/* FIXME: not freeing WHC here because it is owned by the DDSI entity */
thread_state_awake (lookup_thread_state ());
nn_xpack_free(wr->m_xp);
thread_state_asleep (lookup_thread_state ());
ret = dds_delete(wr->m_topic->m_entity.m_hdllink.hdl);
if(ret == DDS_RETCODE_OK){
ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true);
if(ret == DDS_RETCODE_BAD_PARAMETER){
ret = DDS_RETCODE_OK;
}
}
return ret;
}
static dds_return_t
dds_writer_qos_validate(
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = DDS_RETCODE_OK;
assert(qos);
/* Check consistency. */
if(dds_qos_validate_common(qos) != true){
DDS_ERROR("Provided inconsistent QoS policy\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if((qos->present & QP_USER_DATA) && validate_octetseq(&qos->user_data) != true){
DDS_ERROR("User Data QoS policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy(&qos->durability_service) != 0){
DDS_ERROR("Durability service QoS policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if ((qos->present & QP_LIFESPAN) && validate_duration(&qos->lifespan.duration) != 0){
DDS_ERROR("Lifespan QoS policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits(&qos->history, &qos->resource_limits) != 0)){
DDS_ERROR("Resource limits QoS policy is inconsistent and caused an error\n");
ret = DDS_RETCODE_INCONSISTENT_POLICY;
}
if(ret == DDS_RETCODE_OK && enabled) {
ret = dds_qos_validate_mutable_common(qos);
}
return ret;
}
static dds_return_t
dds_writer_qos_set(
dds_entity *e,
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = dds_writer_qos_validate(qos, enabled);
if (ret == DDS_RETCODE_OK) {
/*
* TODO: CHAM-95: DDSI does not support changing QoS policies.
*
* Only Ownership is required for the minimum viable product. This seems
* to be the only QoS policy that DDSI supports changes on.
*/
if (qos->present & QP_OWNERSHIP_STRENGTH) {
dds_ownership_kind_t kind;
/* check for ownership before updating, ownership strength is applicable only if
* writer is exclusive */
dds_qget_ownership (e->m_qos, &kind);
if (kind == DDS_OWNERSHIP_EXCLUSIVE) {
struct writer * ddsi_wr = ((dds_writer*)e)->m_wr;
dds_qset_ownership_strength (e->m_qos, qos->ownership_strength.value);
thread_state_awake (lookup_thread_state ());
/* FIXME: with QoS changes being unsupported by the underlying stack I wonder what will happen; locking the underlying DDSI writer is of doubtful value as well */
ddsrt_mutex_lock (&ddsi_wr->e.lock);
if (qos->ownership_strength.value != ddsi_wr->xqos->ownership_strength.value) {
ddsi_wr->xqos->ownership_strength.value = qos->ownership_strength.value;
}
ddsrt_mutex_unlock (&ddsi_wr->e.lock);
thread_state_asleep (lookup_thread_state ());
} else {
DDS_ERROR("Setting ownership strength doesn't make sense when the ownership is shared\n");
ret = DDS_RETCODE_ERROR;
}
} else {
if (enabled) {
DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies yet\n");
ret = DDS_RETCODE_UNSUPPORTED;
}
}
}
return ret;
}
static struct whc *make_whc(const dds_qos_t *qos)
{ {
bool handle_as_transient_local; bool handle_as_transient_local;
unsigned hdepth, tldepth; uint32_t hdepth, tldepth;
/* Construct WHC -- if aggressive_keep_last1 is set, the WHC will /* Construct WHC -- if aggressive_keep_last1 is set, the WHC will
drop all samples for which a later update is available. This drop all samples for which a later update is available. This
forces it to maintain a tlidx. */ forces it to maintain a tlidx. */
handle_as_transient_local = (qos->durability.kind == NN_TRANSIENT_LOCAL_DURABILITY_QOS); handle_as_transient_local = (qos->durability.kind == NN_TRANSIENT_LOCAL_DURABILITY_QOS);
if (qos->history.kind == NN_KEEP_ALL_HISTORY_QOS) if (qos->history.kind == NN_KEEP_ALL_HISTORY_QOS)
hdepth = 0; hdepth = 0;
else else
hdepth = (unsigned)qos->history.depth; hdepth = (unsigned) qos->history.depth;
if (handle_as_transient_local) { if (!handle_as_transient_local)
tldepth = 0;
else
{
if (qos->durability_service.history.kind == NN_KEEP_ALL_HISTORY_QOS) if (qos->durability_service.history.kind == NN_KEEP_ALL_HISTORY_QOS)
tldepth = 0; tldepth = 0;
else else
tldepth = (unsigned)qos->durability_service.history.depth; tldepth = (unsigned) qos->durability_service.history.depth;
} else {
tldepth = 0;
} }
return whc_new (handle_as_transient_local, hdepth, tldepth); return whc_new (handle_as_transient_local, hdepth, tldepth);
} }
dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entity_t topic, const dds_qos_t *qos, const dds_listener_t *listener)
dds_entity_t
dds_create_writer(
dds_entity_t participant_or_publisher,
dds_entity_t topic,
const dds_qos_t *qos,
const dds_listener_t *listener)
{ {
dds_return_t rc; dds_return_t rc;
dds_qos_t * wqos; dds_qos_t *wqos;
dds_writer * wr; dds_writer *wr;
dds_entity_t writer; dds_entity_t writer;
dds_publisher * pub = NULL; dds_publisher *pub = NULL;
dds_topic * tp; dds_topic *tp;
dds_entity_t publisher; dds_entity_t publisher;
ddsi_tran_conn_t conn = gv.data_conn_uc; ddsi_tran_conn_t conn = gv.data_conn_uc;
dds_return_t ret;
{ {
dds_entity *p_or_p; dds_entity *p_or_p;
if ((rc = dds_entity_claim (participant_or_publisher, &p_or_p)) != DDS_RETCODE_OK) { if ((rc = dds_entity_claim (participant_or_publisher, &p_or_p)) != DDS_RETCODE_OK)
return rc; return rc;
} if (dds_entity_kind (p_or_p) == DDS_KIND_PARTICIPANT)
if (dds_entity_kind (p_or_p) == DDS_KIND_PARTICIPANT) { publisher = dds_create_publisher(participant_or_publisher, qos, NULL);
publisher = dds_create_publisher(participant_or_publisher, qos, NULL); else
} else { publisher = participant_or_publisher;
publisher = participant_or_publisher; dds_entity_release (p_or_p);
} }
dds_entity_release (p_or_p);
}
if ((rc = dds_publisher_lock(publisher, &pub)) != DDS_RETCODE_OK) { if ((rc = dds_publisher_lock (publisher, &pub)) != DDS_RETCODE_OK)
writer = rc; return rc;
goto err_pub_lock;
}
if (publisher != participant_or_publisher) { if (publisher != participant_or_publisher)
pub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT; pub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT;
}
rc = dds_topic_lock(topic, &tp); if ((rc = dds_topic_lock (topic, &tp)) != DDS_RETCODE_OK)
if (rc != DDS_RETCODE_OK) { goto err_tp_lock;
DDS_ERROR("Error occurred on locking topic\n");
writer = rc;
goto err_tp_lock;
}
assert(tp->m_stopic);
assert(pub->m_entity.m_domain == tp->m_entity.m_domain);
/* Merge Topic & Publisher qos */ assert (tp->m_stopic);
wqos = dds_create_qos(); assert (pub->m_entity.m_domain == tp->m_entity.m_domain);
if (qos) {
/* Only returns failure when one of the qos args is NULL, which
* is not the case here. */
(void)dds_copy_qos(wqos, qos);
}
if (pub->m_entity.m_qos) { /* Merge Topic & Publisher qos */
dds_merge_qos(wqos, pub->m_entity.m_qos); wqos = dds_create_qos ();
} if (qos)
(void) dds_copy_qos (wqos, qos);
if (pub->m_entity.m_qos)
dds_merge_qos (wqos, pub->m_entity.m_qos);
if (tp->m_entity.m_qos)
dds_merge_qos (wqos, tp->m_entity.m_qos);
nn_xqos_mergein_missing (wqos, &gv.default_xqos_wr);
if (tp->m_entity.m_qos) { if ((rc = dds_writer_qos_validate (wqos, false)) != DDS_RETCODE_OK)
/* merge topic qos data to writer qos */ {
dds_merge_qos(wqos, tp->m_entity.m_qos); dds_delete_qos(wqos);
} goto err_bad_qos;
nn_xqos_mergein_missing(wqos, &gv.default_xqos_wr); }
ret = dds_writer_qos_validate(wqos, false); /* Create writer */
if (ret != 0) { wr = dds_alloc (sizeof (*wr));
dds_delete_qos(wqos); writer = dds_entity_init (&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK);
writer = ret;
goto err_bad_qos;
}
/* Create writer */ wr->m_topic = tp;
wr = dds_alloc(sizeof (*wr)); dds_entity_add_ref_nolock (&tp->m_entity);
writer = dds_entity_init(&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK); wr->m_xp = nn_xpack_new (conn, get_bandwidth_limit (wqos->transport_priority), config.xpack_send_async);
wr->m_entity.m_deriver.close = dds_writer_close;
wr->m_entity.m_deriver.delete = dds_writer_delete;
wr->m_entity.m_deriver.set_qos = dds_writer_qos_set;
wr->m_entity.m_deriver.validate_status = dds_writer_status_validate;
wr->m_entity.m_deriver.get_instance_hdl = dds_writer_instance_hdl;
wr->m_whc = make_whc (wqos);
wr->m_topic = tp; /* Extra claim of this writer to make sure that the delete waits until DDSI
dds_entity_add_ref_nolock(&tp->m_entity); * has deleted its writer as well. This can be known through the callback. */
wr->m_xp = nn_xpack_new(conn, get_bandwidth_limit(wqos->transport_priority), config.xpack_send_async); dds_handle_claim_inc (&wr->m_entity.m_hdllink);
wr->m_entity.m_deriver.close = dds_writer_close;
wr->m_entity.m_deriver.delete = dds_writer_delete;
wr->m_entity.m_deriver.set_qos = dds_writer_qos_set;
wr->m_entity.m_deriver.validate_status = dds_writer_status_validate;
wr->m_entity.m_deriver.get_instance_hdl = dds_writer_instance_hdl;
wr->m_whc = make_whc (wqos);
/* Extra claim of this writer to make sure that the delete waits until DDSI ddsrt_mutex_unlock (&tp->m_entity.m_mutex);
* has deleted its writer as well. This can be known through the callback. */ ddsrt_mutex_unlock (&pub->m_entity.m_mutex);
dds_handle_claim_inc (&wr->m_entity.m_hdllink);
ddsrt_mutex_unlock (&tp->m_entity.m_mutex); thread_state_awake (lookup_thread_state ());
ddsrt_mutex_unlock (&pub->m_entity.m_mutex); rc = new_writer (&wr->m_wr, &wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr);
ddsrt_mutex_lock (&pub->m_entity.m_mutex);
thread_state_awake (lookup_thread_state ()); ddsrt_mutex_lock (&tp->m_entity.m_mutex);
ret = new_writer(&wr->m_wr, &wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); assert(rc == DDS_RETCODE_OK);
ddsrt_mutex_lock (&pub->m_entity.m_mutex); thread_state_asleep (lookup_thread_state ());
ddsrt_mutex_lock (&tp->m_entity.m_mutex); dds_topic_unlock (tp);
assert(ret == DDS_RETCODE_OK); dds_publisher_unlock (pub);
thread_state_asleep (lookup_thread_state ()); return writer;
dds_topic_unlock(tp);
dds_publisher_unlock(pub);
return writer;
err_bad_qos: err_bad_qos:
dds_topic_unlock(tp); dds_topic_unlock (tp);
err_tp_lock: err_tp_lock:
dds_publisher_unlock(pub); dds_publisher_unlock (pub);
if((pub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){ if ((pub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){
(void)dds_delete(publisher); (void )dds_delete (publisher);
} }
err_pub_lock: return rc;
return writer;
} }
dds_entity_t dds_entity_t dds_get_publisher (dds_entity_t writer)
dds_get_publisher(
dds_entity_t writer)
{ {
dds_entity *e; dds_entity *e;
dds_return_t rc; dds_return_t rc;
@ -472,115 +393,7 @@ dds_get_publisher(
} }
} }
dds_return_t DDS_GET_STATUS(writer, publication_matched, PUBLICATION_MATCHED, total_count_change, current_count_change)
dds_get_publication_matched_status ( DDS_GET_STATUS(writer, liveliness_lost, LIVELINESS_LOST, total_count_change)
dds_entity_t writer, DDS_GET_STATUS(writer, offered_deadline_missed, OFFERED_DEADLINE_MISSED, total_count_change)
dds_publication_matched_status_t * status) DDS_GET_STATUS(writer, offered_incompatible_qos, OFFERED_INCOMPATIBLE_QOS, total_count_change)
{
dds_writer *wr;
dds_return_t ret;
ret = dds_writer_lock(writer, &wr);
if (ret != DDS_RETCODE_OK) {
DDS_ERROR("Error occurred on locking writer\n");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = wr->m_publication_matched_status;
}
ddsrt_mutex_lock (&wr->m_entity.m_observers_lock);
if (wr->m_entity.m_status_enable & DDS_PUBLICATION_MATCHED_STATUS) {
wr->m_publication_matched_status.total_count_change = 0;
wr->m_publication_matched_status.current_count_change = 0;
dds_entity_status_reset(&wr->m_entity, DDS_PUBLICATION_MATCHED_STATUS);
}
ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock);
dds_writer_unlock(wr);
fail:
return ret;
}
dds_return_t
dds_get_liveliness_lost_status (
dds_entity_t writer,
dds_liveliness_lost_status_t * status)
{
dds_writer *wr;
dds_return_t ret;
ret = dds_writer_lock(writer, &wr);
if (ret != DDS_RETCODE_OK) {
DDS_ERROR("Error occurred on locking writer\n");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = wr->m_liveliness_lost_status;
}
ddsrt_mutex_lock (&wr->m_entity.m_observers_lock);
if (wr->m_entity.m_status_enable & DDS_LIVELINESS_LOST_STATUS) {
wr->m_liveliness_lost_status.total_count_change = 0;
dds_entity_status_reset(&wr->m_entity, DDS_LIVELINESS_LOST_STATUS);
}
ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock);
dds_writer_unlock(wr);
fail:
return ret;
}
dds_return_t
dds_get_offered_deadline_missed_status(
dds_entity_t writer,
dds_offered_deadline_missed_status_t *status)
{
dds_writer *wr;
dds_return_t ret;
ret = dds_writer_lock(writer, &wr);
if (ret != DDS_RETCODE_OK) {
DDS_ERROR("Error occurred on locking writer\n");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = wr->m_offered_deadline_missed_status;
}
ddsrt_mutex_lock (&wr->m_entity.m_observers_lock);
if (wr->m_entity.m_status_enable & DDS_OFFERED_DEADLINE_MISSED_STATUS) {
wr->m_offered_deadline_missed_status.total_count_change = 0;
dds_entity_status_reset(&wr->m_entity, DDS_OFFERED_DEADLINE_MISSED_STATUS);
}
ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock);
dds_writer_unlock(wr);
fail:
return ret;
}
dds_return_t
dds_get_offered_incompatible_qos_status (
dds_entity_t writer,
dds_offered_incompatible_qos_status_t * status)
{
dds_writer *wr;
dds_return_t ret;
ret = dds_writer_lock(writer, &wr);
if (ret != DDS_RETCODE_OK) {
DDS_ERROR("Error occurred on locking writer\n");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = wr->m_offered_incompatible_qos_status;
}
ddsrt_mutex_lock (&wr->m_entity.m_observers_lock);
if (wr->m_entity.m_status_enable & DDS_OFFERED_INCOMPATIBLE_QOS_STATUS) {
wr->m_offered_incompatible_qos_status.total_count_change = 0;
dds_entity_status_reset(&wr->m_entity, DDS_OFFERED_INCOMPATIBLE_QOS_STATUS);
}
ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock);
dds_writer_unlock(wr);
fail:
return ret;
}

View file

@ -105,7 +105,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi"
q_rtps.h q_rtps.h
q_security.h q_security.h
q_sockwaitset.h q_sockwaitset.h
q_static_assert.h
q_thread.h q_thread.h
q_time.h q_time.h
q_transmit.h q_transmit.h

View file

@ -467,17 +467,6 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e);
* - RTPS_PF_ONLY_LOCAL FIXME: not used, it seems * - RTPS_PF_ONLY_LOCAL FIXME: not used, it seems
* @param[in] plist * @param[in] plist
* Parameters/QoS for this participant * Parameters/QoS for this participant
* @param[out] dest
* Filled with the recognized parameters in the input if successful, otherwise
* initialized to an empty parameter list. Where possible, pointers alias the
* input (indicated by the "aliased" bits in the plist/xqos structures), but
* some things cannot be aliased (e.g., the array of pointers to strings for a
* sequence of strings).
* Generally, nn_plist_fini should be called when done with the parameter list,
* even when nn_plist_unlias or nn_xqos_unlias hasn't been called.
* @param[out] nextafterplist
* If non-NULL, *nextafterplist is set to the first byte following the parameter
* list sentinel on successful parse, or to NULL on failure
* *
* @returns A dds_return_t indicating success or failure. * @returns A dds_return_t indicating success or failure.
* *
@ -562,11 +551,11 @@ int writer_must_have_hb_scheduled (const struct writer *wr, const struct whc_sta
void writer_set_retransmitting (struct writer *wr); void writer_set_retransmitting (struct writer *wr);
void writer_clear_retransmitting (struct writer *wr); void writer_clear_retransmitting (struct writer *wr);
int delete_writer (const struct nn_guid *guid); dds_return_t delete_writer (const struct nn_guid *guid);
int delete_writer_nolinger (const struct nn_guid *guid); dds_return_t delete_writer_nolinger (const struct nn_guid *guid);
int delete_writer_nolinger_locked (struct writer *wr); dds_return_t delete_writer_nolinger_locked (struct writer *wr);
int delete_reader (const struct nn_guid *guid); dds_return_t delete_reader (const struct nn_guid *guid);
uint64_t reader_instance_id (const struct nn_guid *guid); uint64_t reader_instance_id (const struct nn_guid *guid);
struct local_orphan_writer { struct local_orphan_writer {

View file

@ -18,9 +18,7 @@ extern "C" {
struct nn_xqos; struct nn_xqos;
int partition_match_based_on_wildcard_in_left_operand (const struct nn_xqos *a, const struct nn_xqos *b, const char **realname);
int partitions_match_p (const struct nn_xqos *a, const struct nn_xqos *b); int partitions_match_p (const struct nn_xqos *a, const struct nn_xqos *b);
int is_wildcard_partition (const char *str);
/* Returns -1 on success, or QoS id of first mismatch (>=0) */ /* Returns -1 on success, or QoS id of first mismatch (>=0) */

View file

@ -17,7 +17,7 @@
#include "dds/ddsrt/atomics.h" #include "dds/ddsrt/atomics.h"
#include "dds/ddsrt/sync.h" #include "dds/ddsrt/sync.h"
#include "dds/ddsrt/threads.h" #include "dds/ddsrt/threads.h"
#include "dds/ddsi/q_static_assert.h" #include "dds/ddsrt/static_assert.h"
#if defined (__cplusplus) #if defined (__cplusplus)
extern "C" { extern "C" {
@ -125,7 +125,7 @@ DDS_EXPORT inline bool vtime_asleep_p (vtime_t vtime)
DDS_EXPORT inline bool vtime_gt (vtime_t vtime1, vtime_t vtime0) DDS_EXPORT inline bool vtime_gt (vtime_t vtime1, vtime_t vtime0)
{ {
Q_STATIC_ASSERT_CODE (sizeof (vtime_t) == sizeof (svtime_t)); DDSRT_STATIC_ASSERT_CODE (sizeof (vtime_t) == sizeof (svtime_t));
return (svtime_t) ((vtime1 & VTIME_TIME_MASK) - (vtime0 & VTIME_TIME_MASK)) > 0; return (svtime_t) ((vtime1 & VTIME_TIME_MASK) - (vtime0 & VTIME_TIME_MASK)) > 0;
} }

View file

@ -332,8 +332,9 @@ static enum ddsi_locator_from_string_result ddsi_raweth_address_from_string (dds
memset (loc->address, 0, sizeof (loc->address)); memset (loc->address, 0, sizeof (loc->address));
while (i < 6 && *str != 0) while (i < 6 && *str != 0)
{ {
int o, p; unsigned o;
if (sscanf (str, "%x%n", &o, &p) != 1 || o < 0 || o > 255) int p;
if (sscanf (str, "%x%n", &o, &p) != 1 || o > 255)
return AFSR_INVALID; return AFSR_INVALID;
loc->address[10 + i++] = (unsigned char) o; loc->address[10 + i++] = (unsigned char) o;
str += p; str += p;

View file

@ -127,12 +127,12 @@ static int add_addresses_to_addrset_1 (struct addrset *as, const char *ip, int p
return 0; return 0;
} }
DDSRT_WARNING_MSVC_OFF(4996);
int add_addresses_to_addrset (struct addrset *as, const char *addrs, int port_mode, const char *msgtag, int req_mc) int add_addresses_to_addrset (struct addrset *as, const char *addrs, int port_mode, const char *msgtag, int req_mc)
{ {
/* port_mode: -1 => take from string, if 0 & unicast, add for a range of participant indices; /* port_mode: -1 => take from string, if 0 & unicast, add for a range of participant indices;
port_mode >= 0 => always set port to port_mode port_mode >= 0 => always set port to port_mode
*/ */
DDSRT_WARNING_MSVC_OFF(4996);
char *addrs_copy, *ip, *cursor, *a; char *addrs_copy, *ip, *cursor, *a;
int retval = -1; int retval = -1;
addrs_copy = ddsrt_strdup (addrs); addrs_copy = ddsrt_strdup (addrs);
@ -179,8 +179,8 @@ int add_addresses_to_addrset (struct addrset *as, const char *addrs, int port_mo
ddsrt_free (ip); ddsrt_free (ip);
ddsrt_free (addrs_copy); ddsrt_free (addrs_copy);
return retval; return retval;
DDSRT_WARNING_MSVC_ON(4996);
} }
DDSRT_WARNING_MSVC_ON(4996);
int compare_locators (const nn_locator_t *a, const nn_locator_t *b) int compare_locators (const nn_locator_t *a, const nn_locator_t *b)
{ {

View file

@ -1335,9 +1335,9 @@ static void do_print_uint32_bitset (struct cfgst *cfgst, uint32_t mask, size_t n
cfg_logelem (cfgst, sources, "%s%s", res, suffix); cfg_logelem (cfgst, sources, "%s%s", res, suffix);
} }
DDSRT_WARNING_MSVC_OFF(4996);
static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *value, const struct unit *unittab, int64_t def_mult, int64_t min, int64_t max) static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *value, const struct unit *unittab, int64_t def_mult, int64_t min, int64_t max)
{ {
DDSRT_WARNING_MSVC_OFF(4996);
int pos; int pos;
double v_dbl; double v_dbl;
int64_t v_int; int64_t v_int;
@ -1364,8 +1364,8 @@ static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *valu
*elem = 0; /* some static analyzers don't "get it" */ *elem = 0; /* some static analyzers don't "get it" */
return cfg_error (cfgst, "%s: invalid value", value); return cfg_error (cfgst, "%s: invalid value", value);
} }
DDSRT_WARNING_MSVC_ON(4996);
} }
DDSRT_WARNING_MSVC_ON(4996);
static void pf_int64_unit (struct cfgst *cfgst, int64_t value, uint32_t sources, const struct unit *unittab, const char *zero_unit) static void pf_int64_unit (struct cfgst *cfgst, int64_t value, uint32_t sources, const struct unit *unittab, const char *zero_unit)
{ {
@ -1393,10 +1393,8 @@ static void pf_int64_unit (struct cfgst *cfgst, int64_t value, uint32_t sources,
} }
#define GENERIC_ENUM_CTYPE_UF(type_, c_type_) \ #define GENERIC_ENUM_CTYPE_UF(type_, c_type_) \
struct en_##type_##_vs_ms_check { \ DDSRT_STATIC_ASSERT (sizeof (en_##type_##_vs) / sizeof (*en_##type_##_vs) == \
char length_eq[(sizeof (en_##type_##_vs) / sizeof (*en_##type_##_vs) == \ sizeof (en_##type_##_ms) / sizeof (*en_##type_##_ms)); \
sizeof (en_##type_##_ms) / sizeof (*en_##type_##_ms)) ? 1 : -1]; \
}; \
\ \
static int uf_##type_ (struct cfgst *cfgst, void *parent, UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value) \ static int uf_##type_ (struct cfgst *cfgst, void *parent, UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value) \
{ \ { \
@ -1773,9 +1771,9 @@ static void pf_allow_multicast(struct cfgst *cfgst, void *parent, struct cfgelem
do_print_uint32_bitset (cfgst, *p, sizeof (allow_multicast_codes) / sizeof (*allow_multicast_codes), allow_multicast_names, allow_multicast_codes, sources, ""); do_print_uint32_bitset (cfgst, *p, sizeof (allow_multicast_codes) / sizeof (*allow_multicast_codes), allow_multicast_names, allow_multicast_codes, sources, "");
} }
DDSRT_WARNING_MSVC_OFF(4996);
static int uf_maybe_int32 (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) static int uf_maybe_int32 (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
{ {
DDSRT_WARNING_MSVC_OFF(4996);
struct config_maybe_int32 * const elem = cfg_address (cfgst, parent, cfgelem); struct config_maybe_int32 * const elem = cfg_address (cfgst, parent, cfgelem);
int pos; int pos;
if (ddsrt_strcasecmp (value, "default") == 0) { if (ddsrt_strcasecmp (value, "default") == 0) {
@ -1788,8 +1786,8 @@ static int uf_maybe_int32 (struct cfgst *cfgst, void *parent, struct cfgelem con
} else { } else {
return cfg_error (cfgst, "'%s': neither 'default' nor a decimal integer\n", value); return cfg_error (cfgst, "'%s': neither 'default' nor a decimal integer\n", value);
} }
DDSRT_WARNING_MSVC_ON(4996);
} }
DDSRT_WARNING_MSVC_ON(4996);
static void pf_maybe_int32 (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) static void pf_maybe_int32 (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
{ {
@ -1940,9 +1938,9 @@ static void pf_duration (struct cfgst *cfgst, void *parent, struct cfgelem const
pf_int64_unit (cfgst, *elem, sources, unittab_duration, "s"); pf_int64_unit (cfgst, *elem, sources, unittab_duration, "s");
} }
DDSRT_WARNING_MSVC_OFF(4996);
static int uf_domainId (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value) static int uf_domainId (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
{ {
DDSRT_WARNING_MSVC_OFF(4996);
struct config_maybe_int32 * const elem = cfg_address (cfgst, parent, cfgelem); struct config_maybe_int32 * const elem = cfg_address (cfgst, parent, cfgelem);
int pos; int pos;
if (ddsrt_strcasecmp (value, "any") == 0) { if (ddsrt_strcasecmp (value, "any") == 0) {
@ -1955,8 +1953,8 @@ static int uf_domainId (struct cfgst *cfgst, void *parent, struct cfgelem const
} else { } else {
return cfg_error (cfgst, "'%s': neither 'any' nor a decimal integer in 0 .. 230\n", value); return cfg_error (cfgst, "'%s': neither 'any' nor a decimal integer in 0 .. 230\n", value);
} }
DDSRT_WARNING_MSVC_ON(4996);
} }
DDSRT_WARNING_MSVC_ON(4996);
static void pf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) static void pf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
{ {

View file

@ -1099,10 +1099,10 @@ static void rebuild_make_locs_nrds(int **locs_nrds, int nreaders, int nlocs, con
if (covered[j * nlocs + i] >= 0) if (covered[j * nlocs + i] >= 0)
n++; n++;
/* The compiler doesn't realize that ln is large enough. */ /* The compiler doesn't realize that ln is large enough. */
DDSRT_WARNING_MSVC_OFF(6386); DDSRT_WARNING_MSVC_OFF(6386);
ln[i] = n; ln[i] = n;
DDSRT_WARNING_MSVC_ON(6386); DDSRT_WARNING_MSVC_ON(6386);
} }
*locs_nrds = ln; *locs_nrds = ln;
} }
@ -3002,7 +3002,7 @@ static void writer_set_state (struct writer *wr, enum writer_state newstate)
wr->state = newstate; wr->state = newstate;
} }
int delete_writer_nolinger_locked (struct writer *wr) dds_return_t delete_writer_nolinger_locked (struct writer *wr)
{ {
DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (wr->e.guid)); DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (wr->e.guid));
ASSERT_MUTEX_HELD (&wr->e.lock); ASSERT_MUTEX_HELD (&wr->e.lock);
@ -3014,7 +3014,7 @@ int delete_writer_nolinger_locked (struct writer *wr)
return 0; return 0;
} }
int delete_writer_nolinger (const struct nn_guid *guid) dds_return_t delete_writer_nolinger (const struct nn_guid *guid)
{ {
struct writer *wr; struct writer *wr;
/* We take no care to ensure application writers are not deleted /* We take no care to ensure application writers are not deleted
@ -3043,7 +3043,7 @@ void delete_local_orphan_writer (struct local_orphan_writer *lowr)
ddsrt_mutex_unlock (&lowr->wr.e.lock); ddsrt_mutex_unlock (&lowr->wr.e.lock);
} }
int delete_writer (const struct nn_guid *guid) dds_return_t delete_writer (const struct nn_guid *guid)
{ {
struct writer *wr; struct writer *wr;
struct whc_state whcst; struct whc_state whcst;
@ -3409,7 +3409,7 @@ static void gc_delete_reader (struct gcreq *gcreq)
ddsrt_free (rd); ddsrt_free (rd);
} }
int delete_reader (const struct nn_guid *guid) dds_return_t delete_reader (const struct nn_guid *guid)
{ {
struct reader *rd; struct reader *rd;
assert (!is_writer_entityid (guid->entityid)); assert (!is_writer_entityid (guid->entityid));

View file

@ -140,9 +140,9 @@ void nn_freelist_fini (struct nn_freelist *fl, void (*xfree) (void *))
xfree (fl->inner[i].m->x[j]); xfree (fl->inner[i].m->x[j]);
ddsrt_free(fl->inner[i].m); ddsrt_free(fl->inner[i].m);
} }
/* The compiler can't make sense of all these linked lists and doesn't /* The compiler can't make sense of all these linked lists and doesn't
* realize that the next pointers are always initialized here. */ * realize that the next pointers are always initialized here. */
DDSRT_WARNING_MSVC_OFF(6001); DDSRT_WARNING_MSVC_OFF(6001);
while ((m = fl->mlist) != NULL) while ((m = fl->mlist) != NULL)
{ {
fl->mlist = m->next; fl->mlist = m->next;
@ -155,7 +155,7 @@ DDSRT_WARNING_MSVC_OFF(6001);
fl->emlist = m->next; fl->emlist = m->next;
ddsrt_free (m); ddsrt_free (m);
} }
DDSRT_WARNING_MSVC_ON(6001); DDSRT_WARNING_MSVC_ON(6001);
} }
static ddsrt_atomic_uint32_t freelist_inner_idx_off = DDSRT_ATOMIC_UINT32_INIT(0); static ddsrt_atomic_uint32_t freelist_inner_idx_off = DDSRT_ATOMIC_UINT32_INIT(0);

View file

@ -415,43 +415,43 @@ static int check_thread_properties (void)
return ok; return ok;
} }
DDSRT_WARNING_MSVC_OFF(4996);
int rtps_config_open (void) int rtps_config_open (void)
{ {
int status; DDSRT_WARNING_MSVC_OFF(4996);
int status;
if (config.tracingOutputFileName == NULL || *config.tracingOutputFileName == 0 || config.enabled_logcats == 0) if (config.tracingOutputFileName == NULL || *config.tracingOutputFileName == 0 || config.enabled_logcats == 0)
{ {
config.enabled_logcats = 0; config.enabled_logcats = 0;
config.tracingOutputFile = NULL; config.tracingOutputFile = NULL;
status = 1; status = 1;
} }
else if (ddsrt_strcasecmp (config.tracingOutputFileName, "stdout") == 0) else if (ddsrt_strcasecmp (config.tracingOutputFileName, "stdout") == 0)
{ {
config.tracingOutputFile = stdout; config.tracingOutputFile = stdout;
status = 1; status = 1;
} }
else if (ddsrt_strcasecmp (config.tracingOutputFileName, "stderr") == 0) else if (ddsrt_strcasecmp (config.tracingOutputFileName, "stderr") == 0)
{ {
config.tracingOutputFile = stderr; config.tracingOutputFile = stderr;
status = 1; status = 1;
} }
else if ((config.tracingOutputFile = fopen (config.tracingOutputFileName, config.tracingAppendToFile ? "a" : "w")) == NULL) else if ((config.tracingOutputFile = fopen (config.tracingOutputFileName, config.tracingAppendToFile ? "a" : "w")) == NULL)
{ {
DDS_ERROR("%s: cannot open for writing\n", config.tracingOutputFileName); DDS_ERROR("%s: cannot open for writing\n", config.tracingOutputFileName);
status = 0; status = 0;
} }
else else
{ {
status = 1; status = 1;
} }
dds_set_log_mask(config.enabled_logcats); dds_set_log_mask(config.enabled_logcats);
dds_set_trace_file(config.tracingOutputFile); dds_set_trace_file(config.tracingOutputFile);
return status; return status;
DDSRT_WARNING_MSVC_ON(4996);
} }
DDSRT_WARNING_MSVC_ON(4996);
int rtps_config_prep (struct cfgst *cfgst) int rtps_config_prep (struct cfgst *cfgst)
{ {
@ -1654,10 +1654,10 @@ void rtps_fini (void)
while (gv.recvips) while (gv.recvips)
{ {
struct config_in_addr_node *n = gv.recvips; struct config_in_addr_node *n = gv.recvips;
/* The compiler doesn't realize that n->next is always initialized. */ /* The compiler doesn't realize that n->next is always initialized. */
DDSRT_WARNING_MSVC_OFF(6001); DDSRT_WARNING_MSVC_OFF(6001);
gv.recvips = n->next; gv.recvips = n->next;
DDSRT_WARNING_MSVC_ON(6001); DDSRT_WARNING_MSVC_ON(6001);
ddsrt_free (n); ddsrt_free (n);
} }

View file

@ -77,9 +77,9 @@ static const ipv4_hdr_t ipv4_hdr_template = {
#define IPV4_HDR_SIZE 20 #define IPV4_HDR_SIZE 20
#define UDP_HDR_SIZE 8 #define UDP_HDR_SIZE 8
DDSRT_WARNING_MSVC_OFF(4996);
FILE *new_pcap_file (const char *name) FILE *new_pcap_file (const char *name)
{ {
DDSRT_WARNING_MSVC_OFF(4996);
FILE *fp; FILE *fp;
pcap_hdr_t hdr; pcap_hdr_t hdr;
@ -99,8 +99,8 @@ FILE *new_pcap_file (const char *name)
fwrite (&hdr, sizeof (hdr), 1, fp); fwrite (&hdr, sizeof (hdr), 1, fp);
return fp; return fp;
DDSRT_WARNING_MSVC_ON(4996);
} }
DDSRT_WARNING_MSVC_ON(4996);
static void write_data (FILE *fp, const ddsrt_msghdr_t *msghdr, size_t sz) static void write_data (FILE *fp, const ddsrt_msghdr_t *msghdr, size_t sz)
{ {

View file

@ -17,6 +17,7 @@
#include "dds/ddsrt/log.h" #include "dds/ddsrt/log.h"
#include "dds/ddsrt/heap.h" #include "dds/ddsrt/heap.h"
#include "dds/ddsrt/static_assert.h"
#include "dds/ddsi/q_log.h" #include "dds/ddsi/q_log.h"
@ -30,7 +31,6 @@
#include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_globals.h"
#include "dds/ddsi/q_protocol.h" /* for NN_STATUSINFO_... */ #include "dds/ddsi/q_protocol.h" /* for NN_STATUSINFO_... */
#include "dds/ddsi/q_radmin.h" /* for nn_plist_quickscan */ #include "dds/ddsi/q_radmin.h" /* for nn_plist_quickscan */
#include "dds/ddsi/q_static_assert.h"
#include "dds/ddsrt/avl.h" #include "dds/ddsrt/avl.h"
#include "dds/ddsi/q_misc.h" /* for vendor_is_... */ #include "dds/ddsi/q_misc.h" /* for vendor_is_... */
@ -407,8 +407,8 @@ void nn_plist_fini (nn_plist_t *ps)
int i; int i;
nn_xqos_fini (&ps->qos); nn_xqos_fini (&ps->qos);
/* The compiler doesn't understand how offsetof is used in the arrays. */ /* The compiler doesn't understand how offsetof is used in the arrays. */
DDSRT_WARNING_MSVC_OFF(6001); DDSRT_WARNING_MSVC_OFF(6001);
for (i = 0; i < (int) (sizeof (simple) / sizeof (*simple)); i++) for (i = 0; i < (int) (sizeof (simple) / sizeof (*simple)); i++)
{ {
if ((ps->present & simple[i].fl) && !(ps->aliased & simple[i].fl)) if ((ps->present & simple[i].fl) && !(ps->aliased & simple[i].fl))
@ -422,7 +422,7 @@ DDSRT_WARNING_MSVC_OFF(6001);
if ((ps->present & locs[i].fl) && !(ps->aliased & locs[i].fl)) if ((ps->present & locs[i].fl) && !(ps->aliased & locs[i].fl))
free_locators ((nn_locators_t *) ((char *) ps + locs[i].off)); free_locators ((nn_locators_t *) ((char *) ps + locs[i].off));
} }
DDSRT_WARNING_MSVC_ON(6001); DDSRT_WARNING_MSVC_ON(6001);
ps->present = 0; ps->present = 0;
} }
@ -1943,7 +1943,7 @@ static dds_return_t init_one_parameter
if (dd->bufsz >= 2 * sizeof (dest->statusinfo) && vendor_is_eclipse_or_opensplice(dd->vendorid)) if (dd->bufsz >= 2 * sizeof (dest->statusinfo) && vendor_is_eclipse_or_opensplice(dd->vendorid))
{ {
uint32_t statusinfox; uint32_t statusinfox;
Q_STATIC_ASSERT_CODE (sizeof(statusinfox) == sizeof(dest->statusinfo)); DDSRT_STATIC_ASSERT_CODE (sizeof(statusinfox) == sizeof(dest->statusinfo));
memcpy (&statusinfox, dd->buf + sizeof (dest->statusinfo), sizeof (statusinfox)); memcpy (&statusinfox, dd->buf + sizeof (dest->statusinfo), sizeof (statusinfox));
statusinfox = fromBE4u (statusinfox); statusinfox = fromBE4u (statusinfox);
if (statusinfox & NN_STATUSINFOX_OSPL_AUTO) if (statusinfox & NN_STATUSINFOX_OSPL_AUTO)

View file

@ -17,7 +17,7 @@
#include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_misc.h"
#include "dds/ddsi/q_qosmatch.h" #include "dds/ddsi/q_qosmatch.h"
int is_wildcard_partition (const char *str) static int is_wildcard_partition (const char *str)
{ {
return strchr (str, '*') || strchr (str, '?'); return strchr (str, '*') || strchr (str, '?');
} }
@ -66,46 +66,6 @@ int partitions_match_p (const nn_xqos_t *a, const nn_xqos_t *b)
} }
} }
int partition_match_based_on_wildcard_in_left_operand (const nn_xqos_t *a, const nn_xqos_t *b, const char **realname)
{
assert (partitions_match_p (a, b));
if (!(a->present & QP_PARTITION) || a->partition.n == 0)
{
return 0;
}
else if (!(b->present & QP_PARTITION) || b->partition.n == 0)
{
/* Either A explicitly includes the default partition, or it is a
wildcard that matches it */
unsigned i;
for (i = 0; i < a->partition.n; i++)
if (strcmp (a->partition.strs[i], "") == 0)
return 0;
*realname = "";
return 1;
}
else
{
unsigned i, j;
int maybe_yes = 0;
for (i = 0; i < a->partition.n; i++)
for (j = 0; j < b->partition.n; j++)
{
if (partition_patmatch_p (a->partition.strs[i], b->partition.strs[j]))
{
if (!is_wildcard_partition (a->partition.strs[i]))
return 0;
else
{
*realname = b->partition.strs[j];
maybe_yes = 1;
}
}
}
return maybe_yes;
}
}
static int ddsi_duration_is_lt (nn_duration_t a0, nn_duration_t b0) static int ddsi_duration_is_lt (nn_duration_t a0, nn_duration_t b0)
{ {
/* inf counts as <= inf */ /* inf counts as <= inf */

View file

@ -19,6 +19,7 @@
#include "dds/ddsrt/md5.h" #include "dds/ddsrt/md5.h"
#include "dds/ddsrt/sync.h" #include "dds/ddsrt/sync.h"
#include "dds/ddsrt/string.h" #include "dds/ddsrt/string.h"
#include "dds/ddsrt/static_assert.h"
#include "dds/ddsrt/avl.h" #include "dds/ddsrt/avl.h"
#include "dds__stream.h" #include "dds__stream.h"
@ -46,7 +47,6 @@
#include "dds/ddsi/q_transmit.h" #include "dds/ddsi/q_transmit.h"
#include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_globals.h"
#include "dds/ddsi/q_static_assert.h"
#include "dds/ddsi/q_init.h" #include "dds/ddsi/q_init.h"
#include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_tkmap.h"
#include "dds/ddsi/ddsi_mcgroup.h" #include "dds/ddsi/ddsi_mcgroup.h"
@ -1613,7 +1613,7 @@ static int handle_one_gap (struct proxy_writer *pwr, struct pwr_rd_match *wn, se
anything useful, or there was insufficient memory to store it. anything useful, or there was insufficient memory to store it.
When the result is either ACCEPT or a sample chain, it clearly When the result is either ACCEPT or a sample chain, it clearly
meant something. */ meant something. */
Q_STATIC_ASSERT_CODE (NN_REORDER_ACCEPT == 0); DDSRT_STATIC_ASSERT_CODE (NN_REORDER_ACCEPT == 0);
if (res >= 0) if (res >= 0)
gap_was_valuable = 1; gap_was_valuable = 1;
@ -1877,7 +1877,7 @@ unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr)
case SMID_DATA_FRAG: case SMID_DATA_FRAG:
{ {
unsigned char common = smhdr->flags & DATA_FLAG_INLINE_QOS; unsigned char common = smhdr->flags & DATA_FLAG_INLINE_QOS;
Q_STATIC_ASSERT_CODE (DATA_FLAG_INLINE_QOS == DATAFRAG_FLAG_INLINE_QOS); DDSRT_STATIC_ASSERT_CODE (DATA_FLAG_INLINE_QOS == DATAFRAG_FLAG_INLINE_QOS);
if (smhdr->flags & DATAFRAG_FLAG_KEYFLAG) if (smhdr->flags & DATAFRAG_FLAG_KEYFLAG)
return common | DATA_FLAG_KEYFLAG; return common | DATA_FLAG_KEYFLAG;
else else

View file

@ -89,15 +89,15 @@ void thread_states_init (unsigned maxthreads)
thread_states.ts = thread_states.ts =
ddsrt_malloc_aligned_cacheline (maxthreads * sizeof (*thread_states.ts)); ddsrt_malloc_aligned_cacheline (maxthreads * sizeof (*thread_states.ts));
memset (thread_states.ts, 0, maxthreads * sizeof (*thread_states.ts)); memset (thread_states.ts, 0, maxthreads * sizeof (*thread_states.ts));
/* The compiler doesn't realize that ts is large enough. */ /* The compiler doesn't realize that ts is large enough. */
DDSRT_WARNING_MSVC_OFF(6386); DDSRT_WARNING_MSVC_OFF(6386);
for (i = 0; i < thread_states.nthreads; i++) for (i = 0; i < thread_states.nthreads; i++)
{ {
thread_states.ts[i].state = THREAD_STATE_ZERO; thread_states.ts[i].state = THREAD_STATE_ZERO;
thread_states.ts[i].vtime = 0u; thread_states.ts[i].vtime = 0u;
thread_states.ts[i].name = NULL; thread_states.ts[i].name = NULL;
} }
DDSRT_WARNING_MSVC_ON(6386); DDSRT_WARNING_MSVC_ON(6386);
} }
void thread_states_fini (void) void thread_states_fini (void)

View file

@ -14,6 +14,7 @@
#include "dds/ddsrt/heap.h" #include "dds/ddsrt/heap.h"
#include "dds/ddsrt/sync.h" #include "dds/ddsrt/sync.h"
#include "dds/ddsrt/static_assert.h"
#include "dds/ddsrt/avl.h" #include "dds/ddsrt/avl.h"
#include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_entity.h"
@ -30,7 +31,6 @@
#include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_unused.h"
#include "dds/ddsi/q_hbcontrol.h" #include "dds/ddsi/q_hbcontrol.h"
#include "dds/ddsi/q_static_assert.h"
#include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_tkmap.h"
#include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_serdata.h"
#include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/ddsi_sertopic.h"
@ -598,7 +598,7 @@ dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const stru
if (xmsg_kind == NN_XMSG_KIND_DATA_REXMIT) if (xmsg_kind == NN_XMSG_KIND_DATA_REXMIT)
nn_xmsg_set_data_readerId (*pmsg, &ddcmn->readerId); nn_xmsg_set_data_readerId (*pmsg, &ddcmn->readerId);
Q_STATIC_ASSERT_CODE (DATA_FLAG_INLINE_QOS == DATAFRAG_FLAG_INLINE_QOS); DDSRT_STATIC_ASSERT_CODE (DATA_FLAG_INLINE_QOS == DATAFRAG_FLAG_INLINE_QOS);
assert (!(ddcmn->smhdr.flags & DATAFRAG_FLAG_INLINE_QOS)); assert (!(ddcmn->smhdr.flags & DATAFRAG_FLAG_INLINE_QOS));
if (fragnum == 0) if (fragnum == 0)

View file

@ -111,7 +111,9 @@ list(APPEND headers
"${include_path}/dds/ddsrt/process.h" "${include_path}/dds/ddsrt/process.h"
"${include_path}/dds/ddsrt/strtod.h" "${include_path}/dds/ddsrt/strtod.h"
"${include_path}/dds/ddsrt/strtol.h" "${include_path}/dds/ddsrt/strtol.h"
"${include_path}/dds/ddsrt/types.h") "${include_path}/dds/ddsrt/types.h"
"${include_path}/dds/ddsrt/countargs.h"
"${include_path}/dds/ddsrt/static_assert.h")
list(APPEND sources list(APPEND sources
"${source_path}/io.c" "${source_path}/io.c"

View file

@ -157,46 +157,46 @@ inline void *ddsrt_atomic_addvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff
inline void ddsrt_atomic_sub32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { inline void ddsrt_atomic_sub32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
/* disable unary minus applied to unsigned type, result still unsigned */ /* disable unary minus applied to unsigned type, result still unsigned */
DDSRT_WARNING_MSVC_OFF(4146) DDSRT_WARNING_MSVC_OFF(4146)
InterlockedExchangeAdd (&x->v, -v); InterlockedExchangeAdd (&x->v, -v);
DDSRT_WARNING_MSVC_ON(4146) DDSRT_WARNING_MSVC_ON(4146)
} }
#if DDSRT_HAVE_ATOMIC64 #if DDSRT_HAVE_ATOMIC64
inline void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) { inline void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
/* disable unary minus applied to unsigned type, result still unsigned */ /* disable unary minus applied to unsigned type, result still unsigned */
DDSRT_WARNING_MSVC_OFF(4146) DDSRT_WARNING_MSVC_OFF(4146)
InterlockedExchangeAdd64 (&x->v, -v); InterlockedExchangeAdd64 (&x->v, -v);
DDSRT_WARNING_MSVC_ON(4146) DDSRT_WARNING_MSVC_ON(4146)
} }
#endif #endif
inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) { inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
/* disable unary minus applied to unsigned type, result still unsigned */ /* disable unary minus applied to unsigned type, result still unsigned */
DDSRT_WARNING_MSVC_OFF(4146) DDSRT_WARNING_MSVC_OFF(4146)
DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, -v); DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, -v);
DDSRT_WARNING_MSVC_ON(4146) DDSRT_WARNING_MSVC_ON(4146)
} }
inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) { inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
ddsrt_atomic_subptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v); ddsrt_atomic_subptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
} }
inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
/* disable unary minus applied to unsigned type, result still unsigned */ /* disable unary minus applied to unsigned type, result still unsigned */
DDSRT_WARNING_MSVC_OFF(4146) DDSRT_WARNING_MSVC_OFF(4146)
return InterlockedExchangeAdd (&x->v, -v) - v; return InterlockedExchangeAdd (&x->v, -v) - v;
DDSRT_WARNING_MSVC_ON(4146) DDSRT_WARNING_MSVC_ON(4146)
} }
#if DDSRT_HAVE_ATOMIC64 #if DDSRT_HAVE_ATOMIC64
inline uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) { inline uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
/* disable unary minus applied to unsigned type, result still unsigned */ /* disable unary minus applied to unsigned type, result still unsigned */
DDSRT_WARNING_MSVC_OFF(4146) DDSRT_WARNING_MSVC_OFF(4146)
return InterlockedExchangeAdd64 (&x->v, -v) - v; return InterlockedExchangeAdd64 (&x->v, -v) - v;
DDSRT_WARNING_MSVC_ON(4146) DDSRT_WARNING_MSVC_ON(4146)
} }
#endif #endif
inline uintptr_t ddsrt_atomic_subptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) { inline uintptr_t ddsrt_atomic_subptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
/* disable unary minus applied to unsigned type, result still unsigned */ /* disable unary minus applied to unsigned type, result still unsigned */
DDSRT_WARNING_MSVC_OFF(4146) DDSRT_WARNING_MSVC_OFF(4146)
return DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, -v) - v; return DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, -v) - v;
DDSRT_WARNING_MSVC_ON(4146) DDSRT_WARNING_MSVC_ON(4146)
} }
inline void *ddsrt_atomic_subvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) { inline void *ddsrt_atomic_subvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
return (void *) ddsrt_atomic_subptr_nv ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v); return (void *) ddsrt_atomic_subptr_nv ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
@ -280,10 +280,10 @@ inline void ddsrt_atomic_fence (void) {
/* 28113: accessing a local variable tmp via an Interlocked /* 28113: accessing a local variable tmp via an Interlocked
function: This is an unusual usage which could be reconsidered. function: This is an unusual usage which could be reconsidered.
It is too heavyweight, true, but it does the trick. */ It is too heavyweight, true, but it does the trick. */
DDSRT_WARNING_MSVC_OFF(28113) DDSRT_WARNING_MSVC_OFF(28113)
volatile LONG tmp = 0; volatile LONG tmp = 0;
InterlockedExchange (&tmp, 0); InterlockedExchange (&tmp, 0);
DDSRT_WARNING_MSVC_ON(28113) DDSRT_WARNING_MSVC_ON(28113)
} }
inline void ddsrt_atomic_fence_ldld (void) { inline void ddsrt_atomic_fence_ldld (void) {
#if !(defined _M_IX86 || defined _M_X64) #if !(defined _M_IX86 || defined _M_X64)

View file

@ -0,0 +1,20 @@
/*
* Copyright(c) 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef DDSRT_COUNTARGS_H
#define DDSRT_COUNTARGS_H
#define DDSRT_COUNT_ARGS_MSVC_WORKAROUND(x) x
#define DDSRT_COUNT_ARGS(...) DDSRT_COUNT_ARGS1 (__VA_ARGS__, 10,9,8,7,6,5,4,3,2,1,0)
#define DDSRT_COUNT_ARGS1(...) DDSRT_COUNT_ARGS_MSVC_WORKAROUND (DDSRT_COUNT_ARGS_ARGN (__VA_ARGS__))
#define DDSRT_COUNT_ARGS_ARGN(a,b,c,d,e,f,g,h,i,j,n,...) n
#endif

View file

@ -24,11 +24,7 @@ extern "C" {
* @brief Get value for environment variable. * @brief Get value for environment variable.
* *
* @param[in] name Environment variable name. * @param[in] name Environment variable name.
* @param[in] buf Buffer to write value to. * @param[out] value Alias to value of environment variable - must not be modified
* @param[in] sz Size of buffer.
* @param[out] reqsz Number of bytes written (excluding the terminating null
* byte), or would have been written would @buf have been
* sufficiently large enough.
* *
* @returns A dds_return_t indicating success or failure. * @returns A dds_return_t indicating success or failure.
* *

View file

@ -106,7 +106,7 @@ ddsrt_proc_create(
* See ddsrt_proc_waitpids() for waiting on all child processes. * See ddsrt_proc_waitpids() for waiting on all child processes.
* *
* @param[in] pid Process ID (PID) to get the exit code from. * @param[in] pid Process ID (PID) to get the exit code from.
* @param[in] timemout Time within the process is expected to finish. * @param[in] timeout Time within the process is expected to finish.
* @param[out] code The exit code of the process. * @param[out] code The exit code of the process.
* *
* @returns A dds_return_t indicating success or failure. * @returns A dds_return_t indicating success or failure.
@ -145,7 +145,7 @@ ddsrt_proc_waitpid(
* *
* See ddsrt_proc_waitpid() for waiting on a specific child process. * See ddsrt_proc_waitpid() for waiting on a specific child process.
* *
* @param[in] timemout Time within a process is expected to finish. * @param[in] timeout Time within a process is expected to finish.
* @param[out] pid Process ID (PID) of the finished process. * @param[out] pid Process ID (PID) of the finished process.
* @param[out] code The exit code of the process. * @param[out] code The exit code of the process.
* *

View file

@ -84,7 +84,7 @@ typedef int32_t dds_return_t;
/** /**
* @brief Takes the error value and outputs a string corresponding to it. * @brief Takes the error value and outputs a string corresponding to it.
* *
* @param[in] err Error value to be converted to a string * @param[in] ret Error value to be converted to a string
* *
* @returns String corresponding to the error value * @returns String corresponding to the error value
*/ */

View file

@ -247,7 +247,7 @@ typedef struct {
* *
* @param[in] name Host name to resolve. * @param[in] name Host name to resolve.
* @param[in] af Address family, either AF_INET, AF_INET6 or AF_UNSPEC. * @param[in] af Address family, either AF_INET, AF_INET6 or AF_UNSPEC.
* @param[out] hent Structure of type ddsrt_hostent_t. * @param[out] hentp Structure of type ddsrt_hostent_t.
* *
* @returns A dds_return_t indicating success or failure. * @returns A dds_return_t indicating success or failure.
* *

View file

@ -1,5 +1,5 @@
/* /*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others * Copyright(c) 2019 ADLINK Technology Limited and others
* *
* This program and the accompanying materials are made available under the * This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at * terms of the Eclipse Public License v. 2.0 which is available at
@ -9,29 +9,34 @@
* *
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/ */
#ifndef Q_STATIC_ASSERT_H #ifndef DDSRT_STATIC_ASSERT_H
#define Q_STATIC_ASSERT_H #define DDSRT_STATIC_ASSERT_H
/* There are many tricks to use a constant expression to yield an /* There are many tricks to use a constant expression to yield an
illegal type or expression at compile time, such as zero-sized illegal type or expression at compile time, such as zero-sized
arrays and duplicate case or enum labels. So this is but one of the arrays and duplicate case or enum labels. So this is but one of the
many tricks. */ many tricks. */
#define DDSRT_STATIC_ASSERT2(line, pred) \
struct static_assert_##line { \
char cond[(pred) ? 1 : -1]; \
}
#define DDSRT_STATIC_ASSERT1(line, pred) \
DDSRT_STATIC_ASSERT2 (line, pred)
#define DDSRT_STATIC_ASSERT(pred) \
DDSRT_STATIC_ASSERT1 (__LINE__, pred)
#ifndef _MSC_VER #ifndef _MSC_VER
#define DDSRT_STATIC_ASSERT_CODE(pred) do { switch(0) { case 0: case (pred): ; } } while (0)
#define Q_STATIC_ASSERT_CODE(pred) do { switch(0) { case 0: case pred: ; } } while (0)
#else #else
/* Temporarily disabling warning C6326: Potential comparison of a /* Temporarily disabling warning C6326: Potential comparison of a
constant with another constant. */ constant with another constant. */
#define Q_STATIC_ASSERT_CODE(pred) do { \ #define DDSRT_STATIC_ASSERT_CODE(pred) do { \
__pragma (warning (push)) \ __pragma (warning (push)) \
__pragma (warning (disable : 6326)) \ __pragma (warning (disable : 6326)) \
switch(0) { case 0: case pred: ; } \ switch(0) { case 0: case (pred): ; } \
__pragma (warning (pop)) \ __pragma (warning (pop)) \
} while (0) } while (0)
#endif #endif
#endif /* Q_STATIC_ASSERT_H */ #endif

View file

@ -57,7 +57,7 @@ ddsrt_nonnull((1,2));
* *
* @param[in] str String to split into tokens. * @param[in] str String to split into tokens.
* @param[in] delim Characters that delimit a token. * @param[in] delim Characters that delimit a token.
* @param[inout] saveptr Pointer to a char * used internally. * @param[in,out] saveptr Pointer to a char * used internally.
* *
* @returns The next token or NULL if there are no more tokens. * @returns The next token or NULL if there are no more tokens.
*/ */
@ -74,7 +74,7 @@ ddsrt_strtok_r(
* @delim. The delimiter is overwritten with a null byte, terminating the * @delim. The delimiter is overwritten with a null byte, terminating the
* token and @stringp is updated to point past the delimiter. * token and @stringp is updated to point past the delimiter.
* *
* @param[inout] stringp String to extract token from. * @param[in,out] stringp String to extract token from.
* @param[in] delim Characters that delimit a token. * @param[in] delim Characters that delimit a token.
* *
* @returns The original value of @stringp. * @returns The original value of @stringp.
@ -153,7 +153,7 @@ ddsrt_nonnull((1,2));
* string is truncated if there is not enough space. The resulting string * string is truncated if there is not enough space. The resulting string
* guaranteed to be null terminated if there is space. * guaranteed to be null terminated if there is space.
* *
* @param[inout] dest Destination buffer. * @param[in,out] dest Destination buffer.
* @param[in] src Null terminated string to append to dest. * @param[in] src Null terminated string to append to dest.
* @param[in] size Number of bytes available in dest. * @param[in] size Number of bytes available in dest.
* *

View file

@ -61,6 +61,7 @@
#include "dds/ddsrt/sync.h" #include "dds/ddsrt/sync.h"
#include "dds/ddsrt/time.h" #include "dds/ddsrt/time.h"
#include "dds/ddsrt/process.h" #include "dds/ddsrt/process.h"
#include "dds/ddsrt/static_assert.h"
#define N DDSRT_MT19937_N #define N DDSRT_MT19937_N
#define M 397 #define M 397
@ -186,9 +187,7 @@ void ddsrt_random_init (void)
if (!ddsrt_prng_makeseed (&seed)) if (!ddsrt_prng_makeseed (&seed))
{ {
/* Poor man's initialisation */ /* Poor man's initialisation */
struct lengthof_seed_large_enough { DDSRT_STATIC_ASSERT (sizeof (seed.key) / sizeof (seed.key[0]) >= 3);
char ok[sizeof (seed.key) / sizeof (seed.key[0]) >= 3 ? 1 : -1];
};
memset (&seed, 0, sizeof (seed)); memset (&seed, 0, sizeof (seed));
dds_time_t now = dds_time (); dds_time_t now = dds_time ();
seed.key[0] = (uint32_t) ddsrt_getpid (); seed.key[0] = (uint32_t) ddsrt_getpid ();

View file

@ -305,9 +305,9 @@ static char *unescape_into_utf8 (char *dst, unsigned cp)
return dst; return dst;
} }
DDSRT_WARNING_MSVC_OFF(4996);
static int unescape_insitu (char *buffer, size_t *n) static int unescape_insitu (char *buffer, size_t *n)
{ {
DDSRT_WARNING_MSVC_OFF(4996);
const char *src = buffer; const char *src = buffer;
char const * const srcend = buffer + *n; char const * const srcend = buffer + *n;
char *dst = buffer; char *dst = buffer;
@ -361,8 +361,8 @@ static int unescape_insitu (char *buffer, size_t *n)
} }
*n = (size_t) (dst - buffer); *n = (size_t) (dst - buffer);
return 0; return 0;
DDSRT_WARNING_MSVC_ON(4996);
} }
DDSRT_WARNING_MSVC_ON(4996);
static void discard_payload (struct ddsrt_xmlp_state *st) static void discard_payload (struct ddsrt_xmlp_state *st)
{ {