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:
		
							parent
							
								
									19aec98b8a
								
							
						
					
					
						commit
						13480616e0
					
				
					 56 changed files with 2856 additions and 4542 deletions
				
			
		| 
						 | 
				
			
			@ -74,6 +74,7 @@ PREPEND(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src"
 | 
			
		|||
    dds__whc.h
 | 
			
		||||
    dds__whc_builtintopic.h
 | 
			
		||||
    dds__serdata_builtintopic.h
 | 
			
		||||
    dds__get_status.h
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
generate_export_header(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -313,7 +313,7 @@ dds_delete(dds_entity_t entity);
 | 
			
		|||
 * For instance, it will return the Publisher that was used when
 | 
			
		||||
 * creating a DataWriter (when that DataWriter was provided here).
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  entity  Entity from which to get its publisher.
 | 
			
		||||
 * @param[in]  writer  Entity from which to get its publisher.
 | 
			
		||||
 *
 | 
			
		||||
 * @returns A valid entity or an error code.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -361,7 +361,7 @@ dds_get_subscriber(dds_entity_t entity);
 | 
			
		|||
 * For instance, it will return the DataReader that was used when
 | 
			
		||||
 * creating a ReadCondition (when that ReadCondition was provided here).
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  entity  Entity from which to get its datareader.
 | 
			
		||||
 * @param[in]  condition  Entity from which to get its datareader.
 | 
			
		||||
 *
 | 
			
		||||
 * @returns A valid reader handle or an error code.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -502,7 +502,7 @@ dds_get_status_changes(dds_entity_t entity, uint32_t *status);
 | 
			
		|||
 * This operation returns the status enabled on the entity
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  entity  Entity to get the status.
 | 
			
		||||
 * @param[out] status  Status set on the entity.
 | 
			
		||||
 * @param[out] mask    Mask of enabled statuses set on the entity.
 | 
			
		||||
 *
 | 
			
		||||
 * @returns A dds_return_t indicating success or failure.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -952,6 +952,8 @@ dds_create_topic(
 | 
			
		|||
  const dds_qos_t *qos,
 | 
			
		||||
  const dds_listener_t *listener);
 | 
			
		||||
 | 
			
		||||
struct ddsi_sertopic;
 | 
			
		||||
struct nn_plist;
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Creates a new topic with arbitrary type handling.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -972,8 +974,6 @@ dds_create_topic(
 | 
			
		|||
 *             Either participant, descriptor, name or qos is invalid.
 | 
			
		||||
 */
 | 
			
		||||
/* TODO: Check list of retcodes is complete. */
 | 
			
		||||
struct ddsi_sertopic;
 | 
			
		||||
struct nn_plist;
 | 
			
		||||
DDS_EXPORT dds_entity_t
 | 
			
		||||
dds_create_topic_arbitrary (
 | 
			
		||||
  dds_entity_t participant,
 | 
			
		||||
| 
						 | 
				
			
			@ -1650,8 +1650,7 @@ dds_write_flush(dds_entity_t writer);
 | 
			
		|||
 * @brief Write a CDR serialized value of a data instance
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  writer The writer entity.
 | 
			
		||||
 * @param[in]  cdr CDR serialized value to be written.
 | 
			
		||||
 * @param[in]  size Size (in bytes) of CDR encoded data to be written.
 | 
			
		||||
 * @param[in]  serdata CDR serialized value to be written.
 | 
			
		||||
 *
 | 
			
		||||
 * @returns A dds_return_t indicating success or failure.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -2604,7 +2603,7 @@ dds_take_mask_wl(
 | 
			
		|||
  uint32_t maxs,
 | 
			
		||||
  uint32_t mask);
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT int
 | 
			
		||||
DDS_EXPORT dds_return_t
 | 
			
		||||
dds_takecdr(
 | 
			
		||||
  dds_entity_t reader_or_condition,
 | 
			
		||||
  struct ddsi_serdata **buf,
 | 
			
		||||
| 
						 | 
				
			
			@ -2898,7 +2897,7 @@ dds_read_next_wl(
 | 
			
		|||
 * the memory is released so that the buffer can be reused during a successive read/take operation.
 | 
			
		||||
 * When a condition is provided, the reader to which the condition belongs is looked up.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] rd_or_cnd Reader or condition that belongs to a reader.
 | 
			
		||||
 * @param[in] reader_or_condition Reader or condition that belongs to a reader.
 | 
			
		||||
 * @param[in] buf An array of (pointers to) samples.
 | 
			
		||||
 * @param[in] bufsz The number of (pointers to) samples stored in buf.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -212,8 +212,8 @@ dds_qos_merge (dds_qos_t * __restrict dst, const dds_qos_t * __restrict src);
 | 
			
		|||
 *
 | 
			
		||||
 * Policies are copied from src to dst, unless src already has the policy set to a non-default value.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in,out] dst - Pointer to the destination qos structure
 | 
			
		||||
 * @param[in] src - Pointer to the source qos structure
 | 
			
		||||
 * @param[in,out] a - Pointer to the destination qos structure
 | 
			
		||||
 * @param[in] b - Pointer to the source qos structure
 | 
			
		||||
 */
 | 
			
		||||
DDS_EXPORT bool
 | 
			
		||||
dds_qos_equal (const dds_qos_t * __restrict a, const dds_qos_t * __restrict b);
 | 
			
		||||
| 
						 | 
				
			
			@ -448,7 +448,7 @@ dds_qset_destination_order (
 | 
			
		|||
 * @brief Set the writer data-lifecycle policy of a qos structure
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
 | 
			
		||||
 * @param[in] autodispose_unregistered_instances - Automatic disposal of unregistered instances
 | 
			
		||||
 * @param[in] autodispose - Automatic disposal of unregistered instances
 | 
			
		||||
 */
 | 
			
		||||
DDS_EXPORT void
 | 
			
		||||
dds_qset_writer_data_lifecycle (dds_qos_t * __restrict qos, bool autodispose);
 | 
			
		||||
| 
						 | 
				
			
			@ -738,7 +738,7 @@ dds_qget_destination_order (
 | 
			
		|||
 * @brief Get the writer data-lifecycle qos policy
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] qos - Pointer to a dds_qos_t structure storing the policy
 | 
			
		||||
 * @param[in,out] autodispose_unregistered_instances - Pointer that will store the autodispose unregistered instances enable value
 | 
			
		||||
 * @param[in,out] autodispose - Pointer that will store the autodispose unregistered instances enable value
 | 
			
		||||
 *
 | 
			
		||||
 * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										56
									
								
								src/core/ddsc/src/dds__get_status.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/core/ddsc/src/dds__get_status.h
									
										
									
									
									
										Normal 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
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +23,7 @@ DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_subscriber, DDS_KIND_SUBSCRIBER)
 | 
			
		|||
 | 
			
		||||
dds_entity_t
 | 
			
		||||
dds__create_subscriber_l(
 | 
			
		||||
  struct dds_entity *participant, /* entity-lock must be held */
 | 
			
		||||
  struct dds_participant *participant, /* entity-lock must be held */
 | 
			
		||||
  const dds_qos_t *qos,
 | 
			
		||||
  const dds_listener_t *listener);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,8 +21,8 @@ extern "C" {
 | 
			
		|||
 | 
			
		||||
DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_topic, DDS_KIND_TOPIC)
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT struct ddsi_sertopic * dds_topic_lookup (dds_domain * domain, const char * name);
 | 
			
		||||
DDS_EXPORT void dds_topic_free (dds_domainid_t domainid, struct ddsi_sertopic * st);
 | 
			
		||||
DDS_EXPORT struct ddsi_sertopic * dds_topic_lookup (dds_domain * domain, const char * name) ddsrt_nonnull_all;
 | 
			
		||||
DDS_EXPORT void dds_topic_free (dds_domainid_t domainid, struct ddsi_sertopic * st) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
#ifndef DDS_TOPIC_INTERN_FILTER_FN_DEFINED
 | 
			
		||||
#define DDS_TOPIC_INTERN_FILTER_FN_DEFINED
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,12 +104,12 @@ dds_domain;
 | 
			
		|||
struct dds_entity;
 | 
			
		||||
typedef struct dds_entity_deriver {
 | 
			
		||||
    /* Close can be used to terminate (blocking) actions on a entity before actually deleting it. */
 | 
			
		||||
    dds_return_t (*close)(struct dds_entity *e);
 | 
			
		||||
    dds_return_t (*close)(struct dds_entity *e) ddsrt_nonnull_all;
 | 
			
		||||
    /* Delete is used to actually free the entity. */
 | 
			
		||||
    dds_return_t (*delete)(struct dds_entity *e);
 | 
			
		||||
    dds_return_t (*set_qos)(struct dds_entity *e, const dds_qos_t *qos, bool enabled);
 | 
			
		||||
    dds_return_t (*delete)(struct dds_entity *e) ddsrt_nonnull_all;
 | 
			
		||||
    dds_return_t (*set_qos)(struct dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
 | 
			
		||||
    dds_return_t (*validate_status)(uint32_t mask);
 | 
			
		||||
    dds_return_t (*get_instance_hdl)(struct dds_entity *e, dds_instance_handle_t *i);
 | 
			
		||||
    dds_return_t (*get_instance_hdl)(struct dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all;
 | 
			
		||||
}
 | 
			
		||||
dds_entity_deriver;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -132,7 +132,7 @@ bool dds__validate_builtin_reader_qos (dds_entity_t topic, const dds_qos_t *qos)
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_entity_t dds__create_builtin_subscriber (dds_entity *participant)
 | 
			
		||||
static dds_entity_t dds__create_builtin_subscriber (dds_participant *participant)
 | 
			
		||||
{
 | 
			
		||||
  dds_qos_t *qos = dds__create_builtin_qos ();
 | 
			
		||||
  dds_entity_t sub = dds__create_subscriber_l (participant, qos, NULL);
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +153,7 @@ dds_entity_t dds__get_builtin_subscriber (dds_entity_t e)
 | 
			
		|||
    return ret;
 | 
			
		||||
 | 
			
		||||
  if (p->m_builtin_subscriber <= 0) {
 | 
			
		||||
    p->m_builtin_subscriber = dds__create_builtin_subscriber (&p->m_entity);
 | 
			
		||||
    p->m_builtin_subscriber = dds__create_builtin_subscriber (p);
 | 
			
		||||
  }
 | 
			
		||||
  sub = p->m_builtin_subscriber;
 | 
			
		||||
  dds_participant_unlock(p);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,17 +16,13 @@
 | 
			
		|||
#include "dds__subscriber.h"
 | 
			
		||||
#include "dds__publisher.h"
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_begin_coherent(
 | 
			
		||||
  dds_entity_t entity)
 | 
			
		||||
dds_return_t dds_begin_coherent (dds_entity_t entity)
 | 
			
		||||
{
 | 
			
		||||
  static const dds_entity_kind_t kinds[] = { DDS_KIND_READER, DDS_KIND_WRITER, DDS_KIND_PUBLISHER, DDS_KIND_SUBSCRIBER };
 | 
			
		||||
  return dds_generic_unimplemented_operation_manykinds (entity, sizeof (kinds) / sizeof (kinds[0]), kinds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_end_coherent(
 | 
			
		||||
  dds_entity_t entity)
 | 
			
		||||
dds_return_t dds_end_coherent (dds_entity_t entity)
 | 
			
		||||
{
 | 
			
		||||
  static const dds_entity_kind_t kinds[] = { DDS_KIND_READER, DDS_KIND_WRITER, DDS_KIND_PUBLISHER, DDS_KIND_SUBSCRIBER };
 | 
			
		||||
  return dds_generic_unimplemented_operation_manykinds (entity, sizeof (kinds) / sizeof (kinds[0]), kinds);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,27 +12,24 @@
 | 
			
		|||
#include "dds__domain.h"
 | 
			
		||||
#include "dds/ddsi/ddsi_tkmap.h"
 | 
			
		||||
 | 
			
		||||
static int dds_domain_compare (const int32_t * a, const int32_t * b)
 | 
			
		||||
static int dds_domain_compare (const void *va, const void *vb)
 | 
			
		||||
{
 | 
			
		||||
  const int32_t *a = va;
 | 
			
		||||
  const int32_t *b = vb;
 | 
			
		||||
  return (*a == *b) ? 0 : (*a < *b) ? -1 : 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ddsrt_avl_treedef_t dds_domaintree_def = DDSRT_AVL_TREEDEF_INITIALIZER
 | 
			
		||||
(
 | 
			
		||||
  offsetof (dds_domain, m_node),
 | 
			
		||||
  offsetof (dds_domain, m_id),
 | 
			
		||||
  (int (*) (const void *, const void *)) dds_domain_compare,
 | 
			
		||||
  0
 | 
			
		||||
);
 | 
			
		||||
const ddsrt_avl_treedef_t dds_domaintree_def = DDSRT_AVL_TREEDEF_INITIALIZER (
 | 
			
		||||
  offsetof (dds_domain, m_node), offsetof (dds_domain, m_id), dds_domain_compare, 0);
 | 
			
		||||
 | 
			
		||||
dds_domain * dds_domain_find_locked (dds_domainid_t id)
 | 
			
		||||
dds_domain *dds_domain_find_locked (dds_domainid_t id)
 | 
			
		||||
{
 | 
			
		||||
  return ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_domain * dds_domain_create (dds_domainid_t id)
 | 
			
		||||
dds_domain *dds_domain_create (dds_domainid_t id)
 | 
			
		||||
{
 | 
			
		||||
  dds_domain * domain;
 | 
			
		||||
  dds_domain *domain;
 | 
			
		||||
  ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
  domain = dds_domain_find_locked (id);
 | 
			
		||||
  if (domain == NULL)
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +44,7 @@ dds_domain * dds_domain_create (dds_domainid_t id)
 | 
			
		|||
  return domain;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dds_domain_free (dds_domain * domain)
 | 
			
		||||
void dds_domain_free (dds_domain *domain)
 | 
			
		||||
{
 | 
			
		||||
  ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
  if (--domain->m_refc == 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@
 | 
			
		|||
#include "dds/ddsi/q_entity.h"
 | 
			
		||||
#include "dds/ddsi/q_thread.h"
 | 
			
		||||
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_guardcond)
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_guardcond)
 | 
			
		||||
 | 
			
		||||
dds_entity_t dds_create_guardcondition (dds_entity_t participant)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,396 +23,307 @@
 | 
			
		|||
#include "dds/ddsi/q_thread.h"
 | 
			
		||||
#include "dds/ddsi/q_globals.h"
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_writedispose(
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    const void *data)
 | 
			
		||||
dds_return_t dds_writedispose (dds_entity_t writer, const void *data)
 | 
			
		||||
{
 | 
			
		||||
    return dds_writedispose_ts(writer, data, dds_time());
 | 
			
		||||
  return dds_writedispose_ts (writer, data, dds_time ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_dispose(
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    const void *data)
 | 
			
		||||
dds_return_t dds_dispose (dds_entity_t writer, const void *data)
 | 
			
		||||
{
 | 
			
		||||
    return dds_dispose_ts(writer, data, dds_time());
 | 
			
		||||
  return dds_dispose_ts (writer, data, dds_time ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_dispose_ih(
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    dds_instance_handle_t handle)
 | 
			
		||||
dds_return_t dds_dispose_ih (dds_entity_t writer, dds_instance_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    return dds_dispose_ih_ts(writer, handle, dds_time());
 | 
			
		||||
  return dds_dispose_ih_ts (writer, handle, dds_time ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct ddsi_tkmap_instance*
 | 
			
		||||
dds_instance_find(
 | 
			
		||||
    const dds_topic *topic,
 | 
			
		||||
    const void *data,
 | 
			
		||||
    const bool create)
 | 
			
		||||
static struct ddsi_tkmap_instance *dds_instance_find (const dds_topic *topic, const void *data, const bool create)
 | 
			
		||||
{
 | 
			
		||||
    struct ddsi_serdata *sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data);
 | 
			
		||||
    struct ddsi_tkmap_instance * inst = ddsi_tkmap_find (sd, false, create);
 | 
			
		||||
    ddsi_serdata_unref (sd);
 | 
			
		||||
    return inst;
 | 
			
		||||
  struct ddsi_serdata *sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data);
 | 
			
		||||
  struct ddsi_tkmap_instance *inst = ddsi_tkmap_find (sd, false, create);
 | 
			
		||||
  ddsi_serdata_unref (sd);
 | 
			
		||||
  return inst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
dds_instance_remove(
 | 
			
		||||
    const dds_topic *topic,
 | 
			
		||||
    const void *data,
 | 
			
		||||
    dds_instance_handle_t handle)
 | 
			
		||||
static void dds_instance_remove (const dds_topic *topic, const void *data, dds_instance_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    struct ddsi_tkmap_instance * inst;
 | 
			
		||||
 | 
			
		||||
    if (handle != DDS_HANDLE_NIL)
 | 
			
		||||
    {
 | 
			
		||||
        inst = ddsi_tkmap_find_by_id (gv.m_tkmap, handle);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
       assert (data);
 | 
			
		||||
       inst = dds_instance_find (topic, data, false);
 | 
			
		||||
    }
 | 
			
		||||
    if (inst)
 | 
			
		||||
    {
 | 
			
		||||
        ddsi_tkmap_instance_unref (inst);
 | 
			
		||||
    }
 | 
			
		||||
  struct ddsi_tkmap_instance *inst;
 | 
			
		||||
  if (handle != DDS_HANDLE_NIL)
 | 
			
		||||
    inst = ddsi_tkmap_find_by_id (gv.m_tkmap, handle);
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    assert (data);
 | 
			
		||||
    inst = dds_instance_find (topic, data, false);
 | 
			
		||||
  }
 | 
			
		||||
  if (inst)
 | 
			
		||||
  {
 | 
			
		||||
    ddsi_tkmap_instance_unref (inst);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const dds_topic *dds_instance_info (dds_entity *e)
 | 
			
		||||
{
 | 
			
		||||
    const dds_topic *topic;
 | 
			
		||||
    switch (dds_entity_kind (e))
 | 
			
		||||
    {
 | 
			
		||||
        case DDS_KIND_READER:
 | 
			
		||||
            topic = ((dds_reader*) e)->m_topic;
 | 
			
		||||
            break;
 | 
			
		||||
        case DDS_KIND_WRITER:
 | 
			
		||||
            topic = ((dds_writer*) e)->m_topic;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            assert (0);
 | 
			
		||||
            topic = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    return topic;
 | 
			
		||||
  const dds_topic *topic;
 | 
			
		||||
  switch (dds_entity_kind (e))
 | 
			
		||||
  {
 | 
			
		||||
    case DDS_KIND_READER:
 | 
			
		||||
      topic = ((dds_reader*) e)->m_topic;
 | 
			
		||||
      break;
 | 
			
		||||
    case DDS_KIND_WRITER:
 | 
			
		||||
      topic = ((dds_writer*) e)->m_topic;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      assert (0);
 | 
			
		||||
      topic = NULL;
 | 
			
		||||
  }
 | 
			
		||||
  return topic;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const dds_topic * dds_instance_info_by_hdl (dds_entity_t e)
 | 
			
		||||
static const dds_topic *dds_instance_info_by_hdl (dds_entity_t e)
 | 
			
		||||
{
 | 
			
		||||
    const dds_topic * topic = NULL;
 | 
			
		||||
    dds_return_t rc;
 | 
			
		||||
    dds_entity *w_or_r;
 | 
			
		||||
  const dds_topic *topic;
 | 
			
		||||
  dds_entity *w_or_r;
 | 
			
		||||
 | 
			
		||||
    rc = dds_entity_lock(e, DDS_KIND_WRITER, &w_or_r);
 | 
			
		||||
    if (rc == DDS_RETCODE_ILLEGAL_OPERATION)
 | 
			
		||||
    {
 | 
			
		||||
        rc = dds_entity_lock(e, DDS_KIND_READER, &w_or_r);
 | 
			
		||||
    }
 | 
			
		||||
    if (rc != DDS_RETCODE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    topic = dds_instance_info(w_or_r);
 | 
			
		||||
    dds_entity_unlock(w_or_r);
 | 
			
		||||
    return topic;
 | 
			
		||||
  if (dds_entity_lock (e, DDS_KIND_DONTCARE, &w_or_r) != DDS_RETCODE_OK)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  switch (dds_entity_kind (w_or_r))
 | 
			
		||||
  {
 | 
			
		||||
    case DDS_KIND_WRITER:
 | 
			
		||||
    case DDS_KIND_READER:
 | 
			
		||||
      topic = dds_instance_info (w_or_r);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      topic = NULL;
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  dds_entity_unlock (w_or_r);
 | 
			
		||||
  return topic;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_register_instance(
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    dds_instance_handle_t *handle,
 | 
			
		||||
    const void *data)
 | 
			
		||||
dds_return_t dds_register_instance (dds_entity_t writer, dds_instance_handle_t *handle, const void *data)
 | 
			
		||||
{
 | 
			
		||||
    struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
    struct ddsi_tkmap_instance * inst;
 | 
			
		||||
    dds_writer *wr;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
  struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
  dds_writer *wr;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    if(data == NULL){
 | 
			
		||||
        return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
    if(handle == NULL){
 | 
			
		||||
        return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
    ret = dds_writer_lock(writer, &wr);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
    thread_state_awake (ts1);
 | 
			
		||||
    inst = dds_instance_find (wr->m_topic, data, true);
 | 
			
		||||
    if(inst != NULL){
 | 
			
		||||
        *handle = inst->m_iid;
 | 
			
		||||
        ret = DDS_RETCODE_OK;
 | 
			
		||||
    } else {
 | 
			
		||||
        ret = DDS_RETCODE_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
    thread_state_asleep (ts1);
 | 
			
		||||
    dds_writer_unlock(wr);
 | 
			
		||||
err:
 | 
			
		||||
  if (data == NULL || handle == NULL)
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
 | 
			
		||||
  if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  thread_state_awake (ts1);
 | 
			
		||||
  struct ddsi_tkmap_instance * const inst = dds_instance_find (wr->m_topic, data, true);
 | 
			
		||||
  if (inst == NULL)
 | 
			
		||||
    ret = DDS_RETCODE_ERROR;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    *handle = inst->m_iid;
 | 
			
		||||
    ret = DDS_RETCODE_OK;
 | 
			
		||||
  }
 | 
			
		||||
  thread_state_asleep (ts1);
 | 
			
		||||
  dds_writer_unlock (wr);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_unregister_instance(
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    const void *data)
 | 
			
		||||
dds_return_t dds_unregister_instance (dds_entity_t writer, const void *data)
 | 
			
		||||
{
 | 
			
		||||
    return dds_unregister_instance_ts (writer, data, dds_time());
 | 
			
		||||
  return dds_unregister_instance_ts (writer, data, dds_time ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_unregister_instance_ih(
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    dds_instance_handle_t handle)
 | 
			
		||||
dds_return_t dds_unregister_instance_ih (dds_entity_t writer, dds_instance_handle_t handle)
 | 
			
		||||
{
 | 
			
		||||
    return dds_unregister_instance_ih_ts(writer, handle, dds_time());
 | 
			
		||||
  return dds_unregister_instance_ih_ts (writer, handle, dds_time ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_unregister_instance_ts(
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    const void *data,
 | 
			
		||||
    dds_time_t timestamp)
 | 
			
		||||
dds_return_t dds_unregister_instance_ts (dds_entity_t writer, const void *data, dds_time_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
    struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
    bool autodispose = true;
 | 
			
		||||
    dds_write_action action = DDS_WR_ACTION_UNREGISTER;
 | 
			
		||||
    dds_writer *wr;
 | 
			
		||||
  struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  bool autodispose = true;
 | 
			
		||||
  dds_write_action action = DDS_WR_ACTION_UNREGISTER;
 | 
			
		||||
  dds_writer *wr;
 | 
			
		||||
 | 
			
		||||
    if (data == NULL){
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
    if(timestamp < 0){
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
    ret = dds_writer_lock(writer, &wr);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
  if (data == NULL || timestamp < 0)
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
 | 
			
		||||
    if (wr->m_entity.m_qos) {
 | 
			
		||||
        dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose);
 | 
			
		||||
    }
 | 
			
		||||
    thread_state_awake (ts1);
 | 
			
		||||
    if (autodispose) {
 | 
			
		||||
        dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL);
 | 
			
		||||
        action |= DDS_WR_DISPOSE_BIT;
 | 
			
		||||
    }
 | 
			
		||||
    ret = dds_write_impl (wr, data, timestamp, action);
 | 
			
		||||
    thread_state_asleep (ts1);
 | 
			
		||||
    dds_writer_unlock(wr);
 | 
			
		||||
err:
 | 
			
		||||
  if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  if (wr->m_entity.m_qos)
 | 
			
		||||
    dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose);
 | 
			
		||||
 | 
			
		||||
  thread_state_awake (ts1);
 | 
			
		||||
  if (autodispose)
 | 
			
		||||
  {
 | 
			
		||||
    dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL);
 | 
			
		||||
    action |= DDS_WR_DISPOSE_BIT;
 | 
			
		||||
  }
 | 
			
		||||
  ret = dds_write_impl (wr, data, timestamp, action);
 | 
			
		||||
  thread_state_asleep (ts1);
 | 
			
		||||
  dds_writer_unlock (wr);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_unregister_instance_ih_ts(
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    dds_instance_handle_t handle,
 | 
			
		||||
    dds_time_t timestamp)
 | 
			
		||||
dds_return_t dds_unregister_instance_ih_ts (dds_entity_t writer, dds_instance_handle_t handle, dds_time_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
    struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
    bool autodispose = true;
 | 
			
		||||
    dds_write_action action = DDS_WR_ACTION_UNREGISTER;
 | 
			
		||||
    dds_writer *wr;
 | 
			
		||||
    struct ddsi_tkmap_instance *tk;
 | 
			
		||||
  struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
  dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
  bool autodispose = true;
 | 
			
		||||
  dds_write_action action = DDS_WR_ACTION_UNREGISTER;
 | 
			
		||||
  dds_writer *wr;
 | 
			
		||||
  struct ddsi_tkmap_instance *tk;
 | 
			
		||||
 | 
			
		||||
    ret = dds_writer_lock(writer, &wr);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (wr->m_entity.m_qos) {
 | 
			
		||||
        dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose);
 | 
			
		||||
    }
 | 
			
		||||
    thread_state_awake (ts1);
 | 
			
		||||
    if (autodispose) {
 | 
			
		||||
        dds_instance_remove (wr->m_topic, NULL, handle);
 | 
			
		||||
        action |= DDS_WR_DISPOSE_BIT;
 | 
			
		||||
    }
 | 
			
		||||
    tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle);
 | 
			
		||||
    if (tk) {
 | 
			
		||||
        struct ddsi_sertopic *tp = wr->m_topic->m_stopic;
 | 
			
		||||
        void *sample = ddsi_sertopic_alloc_sample (tp);
 | 
			
		||||
        ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL);
 | 
			
		||||
        ddsi_tkmap_instance_unref (tk);
 | 
			
		||||
        ret = dds_write_impl (wr, sample, timestamp, action);
 | 
			
		||||
        ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL);
 | 
			
		||||
    } else {
 | 
			
		||||
        ret = DDS_RETCODE_PRECONDITION_NOT_MET;
 | 
			
		||||
    }
 | 
			
		||||
    thread_state_asleep (ts1);
 | 
			
		||||
    dds_writer_unlock(wr);
 | 
			
		||||
err:
 | 
			
		||||
  if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  if (wr->m_entity.m_qos)
 | 
			
		||||
    dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose);
 | 
			
		||||
 | 
			
		||||
  thread_state_awake (ts1);
 | 
			
		||||
  if (autodispose)
 | 
			
		||||
  {
 | 
			
		||||
    dds_instance_remove (wr->m_topic, NULL, handle);
 | 
			
		||||
    action |= DDS_WR_DISPOSE_BIT;
 | 
			
		||||
  }
 | 
			
		||||
  if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle)) == NULL)
 | 
			
		||||
    ret = DDS_RETCODE_PRECONDITION_NOT_MET;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    struct ddsi_sertopic *tp = wr->m_topic->m_stopic;
 | 
			
		||||
    void *sample = ddsi_sertopic_alloc_sample (tp);
 | 
			
		||||
    ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL);
 | 
			
		||||
    ddsi_tkmap_instance_unref (tk);
 | 
			
		||||
    ret = dds_write_impl (wr, sample, timestamp, action);
 | 
			
		||||
    ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL);
 | 
			
		||||
  }
 | 
			
		||||
  thread_state_asleep (ts1);
 | 
			
		||||
  dds_writer_unlock (wr);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_writedispose_ts(
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    const void *data,
 | 
			
		||||
    dds_time_t timestamp)
 | 
			
		||||
dds_return_t dds_writedispose_ts (dds_entity_t writer, const void *data, dds_time_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
    struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
    dds_writer *wr;
 | 
			
		||||
 | 
			
		||||
    ret = dds_writer_lock(writer, &wr);
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        thread_state_awake (ts1);
 | 
			
		||||
        ret = dds_write_impl (wr, data, timestamp, DDS_WR_ACTION_WRITE_DISPOSE);
 | 
			
		||||
        if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
            dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL);
 | 
			
		||||
        }
 | 
			
		||||
        thread_state_asleep (ts1);
 | 
			
		||||
        dds_writer_unlock(wr);
 | 
			
		||||
    }
 | 
			
		||||
  struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  dds_writer *wr;
 | 
			
		||||
 | 
			
		||||
  if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  thread_state_awake (ts1);
 | 
			
		||||
  if ((ret = dds_write_impl (wr, data, timestamp, DDS_WR_ACTION_WRITE_DISPOSE)) == DDS_RETCODE_OK)
 | 
			
		||||
    dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL);
 | 
			
		||||
  thread_state_asleep (ts1);
 | 
			
		||||
  dds_writer_unlock (wr);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_dispose_impl(
 | 
			
		||||
    dds_writer *wr,
 | 
			
		||||
    const void *data,
 | 
			
		||||
    dds_instance_handle_t handle,
 | 
			
		||||
    dds_time_t timestamp)
 | 
			
		||||
static dds_return_t dds_dispose_impl (dds_writer *wr, const void *data, dds_instance_handle_t handle, dds_time_t timestamp) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_dispose_impl (dds_writer *wr, const void *data, dds_instance_handle_t handle, dds_time_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
    assert(thread_is_awake ());
 | 
			
		||||
    assert(wr);
 | 
			
		||||
    ret = dds_write_impl(wr, data, timestamp, DDS_WR_ACTION_DISPOSE);
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        dds_instance_remove (wr->m_topic, data, handle);
 | 
			
		||||
    }
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  assert (thread_is_awake ());
 | 
			
		||||
  if ((ret = dds_write_impl (wr, data, timestamp, DDS_WR_ACTION_DISPOSE)) == DDS_RETCODE_OK)
 | 
			
		||||
    dds_instance_remove (wr->m_topic, data, handle);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t dds_dispose_ts (dds_entity_t writer, const void *data, dds_time_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
  struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  dds_writer *wr;
 | 
			
		||||
 | 
			
		||||
  if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  thread_state_awake (ts1);
 | 
			
		||||
  ret = dds_dispose_impl (wr, data, DDS_HANDLE_NIL, timestamp);
 | 
			
		||||
  thread_state_asleep (ts1);
 | 
			
		||||
  dds_writer_unlock(wr);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_dispose_ts(
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    const void *data,
 | 
			
		||||
    dds_time_t timestamp)
 | 
			
		||||
dds_return_t dds_dispose_ih_ts (dds_entity_t writer, dds_instance_handle_t handle, dds_time_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
    struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
    dds_writer *wr;
 | 
			
		||||
 | 
			
		||||
    ret = dds_writer_lock(writer, &wr);
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        thread_state_awake (ts1);
 | 
			
		||||
        ret = dds_dispose_impl(wr, data, DDS_HANDLE_NIL, timestamp);
 | 
			
		||||
        thread_state_asleep (ts1);
 | 
			
		||||
        dds_writer_unlock(wr);
 | 
			
		||||
    }
 | 
			
		||||
  struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  dds_writer *wr;
 | 
			
		||||
 | 
			
		||||
  if ((ret = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  struct ddsi_tkmap_instance *tk;
 | 
			
		||||
  thread_state_awake (ts1);
 | 
			
		||||
  if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle)) == NULL)
 | 
			
		||||
    ret = DDS_RETCODE_PRECONDITION_NOT_MET;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    struct ddsi_sertopic *tp = wr->m_topic->m_stopic;
 | 
			
		||||
    void *sample = ddsi_sertopic_alloc_sample (tp);
 | 
			
		||||
    ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL);
 | 
			
		||||
    ddsi_tkmap_instance_unref (tk);
 | 
			
		||||
    ret = dds_dispose_impl (wr, sample, handle, timestamp);
 | 
			
		||||
    ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL);
 | 
			
		||||
  }
 | 
			
		||||
  thread_state_asleep (ts1);
 | 
			
		||||
  dds_writer_unlock (wr);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_dispose_ih_ts(
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    dds_instance_handle_t handle,
 | 
			
		||||
    dds_time_t timestamp)
 | 
			
		||||
dds_instance_handle_t dds_lookup_instance (dds_entity_t entity, const void *data)
 | 
			
		||||
{
 | 
			
		||||
    struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
    dds_writer *wr;
 | 
			
		||||
  struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
  dds_instance_handle_t ih = DDS_HANDLE_NIL;
 | 
			
		||||
  const dds_topic *topic;
 | 
			
		||||
  struct ddsi_serdata *sd;
 | 
			
		||||
 | 
			
		||||
    ret = dds_writer_lock(writer, &wr);
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        struct ddsi_tkmap_instance *tk;
 | 
			
		||||
        thread_state_awake (ts1);
 | 
			
		||||
        if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle)) != NULL) {
 | 
			
		||||
            struct ddsi_sertopic *tp = wr->m_topic->m_stopic;
 | 
			
		||||
            void *sample = ddsi_sertopic_alloc_sample (tp);
 | 
			
		||||
            ddsi_serdata_topicless_to_sample (tp, tk->m_sample, sample, NULL, NULL);
 | 
			
		||||
            ddsi_tkmap_instance_unref (tk);
 | 
			
		||||
            ret = dds_dispose_impl (wr, sample, handle, timestamp);
 | 
			
		||||
            ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL);
 | 
			
		||||
        } else {
 | 
			
		||||
            ret = DDS_RETCODE_PRECONDITION_NOT_MET;
 | 
			
		||||
        }
 | 
			
		||||
        thread_state_asleep (ts1);
 | 
			
		||||
        dds_writer_unlock(wr);
 | 
			
		||||
    }
 | 
			
		||||
  if (data == NULL)
 | 
			
		||||
    return DDS_HANDLE_NIL;
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
  if ((topic = dds_instance_info_by_hdl (entity)) == NULL)
 | 
			
		||||
    return DDS_HANDLE_NIL;
 | 
			
		||||
 | 
			
		||||
  thread_state_awake (ts1);
 | 
			
		||||
  sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data);
 | 
			
		||||
  ih = ddsi_tkmap_lookup (gv.m_tkmap, sd);
 | 
			
		||||
  ddsi_serdata_unref (sd);
 | 
			
		||||
  thread_state_asleep (ts1);
 | 
			
		||||
  return ih;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_instance_handle_t
 | 
			
		||||
dds_lookup_instance(
 | 
			
		||||
    dds_entity_t entity,
 | 
			
		||||
    const void *data)
 | 
			
		||||
dds_instance_handle_t dds_instance_lookup (dds_entity_t entity, const void *data)
 | 
			
		||||
{
 | 
			
		||||
    struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
    dds_instance_handle_t ih = DDS_HANDLE_NIL;
 | 
			
		||||
    const dds_topic * topic;
 | 
			
		||||
    struct ddsi_tkmap * map = gv.m_tkmap;
 | 
			
		||||
    struct ddsi_serdata *sd;
 | 
			
		||||
 | 
			
		||||
    if(data == NULL){
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    topic = dds_instance_info_by_hdl (entity);
 | 
			
		||||
    if (topic) {
 | 
			
		||||
        thread_state_awake (ts1);
 | 
			
		||||
        sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data);
 | 
			
		||||
        ih = ddsi_tkmap_lookup (map, sd);
 | 
			
		||||
        ddsi_serdata_unref (sd);
 | 
			
		||||
        thread_state_asleep (ts1);
 | 
			
		||||
    }
 | 
			
		||||
err:
 | 
			
		||||
    return ih;
 | 
			
		||||
  return dds_lookup_instance (entity, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_instance_handle_t
 | 
			
		||||
dds_instance_lookup (
 | 
			
		||||
    dds_entity_t entity,
 | 
			
		||||
    const void *data)
 | 
			
		||||
dds_return_t dds_instance_get_key (dds_entity_t entity, dds_instance_handle_t ih, void *data)
 | 
			
		||||
{
 | 
			
		||||
    return dds_lookup_instance(entity, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_instance_get_key(
 | 
			
		||||
    dds_entity_t entity,
 | 
			
		||||
    dds_instance_handle_t ih,
 | 
			
		||||
    void *data)
 | 
			
		||||
{
 | 
			
		||||
    struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
    const dds_topic * topic;
 | 
			
		||||
    struct ddsi_tkmap_instance * tk;
 | 
			
		||||
 | 
			
		||||
    if(data == NULL){
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    topic = dds_instance_info_by_hdl (entity);
 | 
			
		||||
    if(topic == NULL){
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
    thread_state_awake (ts1);
 | 
			
		||||
    if ((tk = ddsi_tkmap_find_by_id(gv.m_tkmap, ih)) != NULL) {
 | 
			
		||||
        ddsi_sertopic_zero_sample (topic->m_stopic, data);
 | 
			
		||||
        ddsi_serdata_topicless_to_sample (topic->m_stopic, tk->m_sample, data, NULL, NULL);
 | 
			
		||||
        ddsi_tkmap_instance_unref (tk);
 | 
			
		||||
        ret = DDS_RETCODE_OK;
 | 
			
		||||
    } else {
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
    thread_state_asleep (ts1);
 | 
			
		||||
err:
 | 
			
		||||
    return ret;
 | 
			
		||||
  struct thread_state1 * const ts1 = lookup_thread_state ();
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  const dds_topic *topic;
 | 
			
		||||
  struct ddsi_tkmap_instance *tk;
 | 
			
		||||
 | 
			
		||||
  if (data == NULL)
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
 | 
			
		||||
  if ((topic = dds_instance_info_by_hdl (entity)) == NULL)
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
 | 
			
		||||
  thread_state_awake (ts1);
 | 
			
		||||
  if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, ih)) == NULL)
 | 
			
		||||
    ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    ddsi_sertopic_zero_sample (topic->m_stopic, data);
 | 
			
		||||
    ddsi_serdata_topicless_to_sample (topic->m_stopic, tk->m_sample, data, NULL, NULL);
 | 
			
		||||
    ddsi_tkmap_instance_unref (tk);
 | 
			
		||||
    ret = DDS_RETCODE_OK;
 | 
			
		||||
  }
 | 
			
		||||
  thread_state_asleep (ts1);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -207,324 +207,169 @@ void dds_merge_listener (dds_listener_t * __restrict dst, const dds_listener_t *
 | 
			
		|||
 | 
			
		||||
void dds_listener_merge (dds_listener_t * __restrict dst, const dds_listener_t * __restrict src)
 | 
			
		||||
{
 | 
			
		||||
  dds_merge_listener(dst, src);
 | 
			
		||||
  dds_merge_listener (dst, src);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/************************************************************************************************
 | 
			
		||||
 *  Setters
 | 
			
		||||
 ************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lset_data_available (dds_listener_t * __restrict listener, dds_on_data_available_fn callback)
 | 
			
		||||
void dds_lset_data_available (dds_listener_t * __restrict listener, dds_on_data_available_fn callback)
 | 
			
		||||
{
 | 
			
		||||
    if (listener) {
 | 
			
		||||
        listener->on_data_available = callback;
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
    }
 | 
			
		||||
  if (listener)
 | 
			
		||||
    listener->on_data_available = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lset_data_on_readers (dds_listener_t * __restrict listener, dds_on_data_on_readers_fn callback)
 | 
			
		||||
void dds_lset_data_on_readers (dds_listener_t * __restrict listener, dds_on_data_on_readers_fn callback)
 | 
			
		||||
{
 | 
			
		||||
    if (listener) {
 | 
			
		||||
        listener->on_data_on_readers = callback;
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
    }
 | 
			
		||||
  if (listener)
 | 
			
		||||
    listener->on_data_on_readers = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lset_inconsistent_topic (dds_listener_t * __restrict listener, dds_on_inconsistent_topic_fn callback)
 | 
			
		||||
void dds_lset_inconsistent_topic (dds_listener_t * __restrict listener, dds_on_inconsistent_topic_fn callback)
 | 
			
		||||
{
 | 
			
		||||
    if (listener) {
 | 
			
		||||
        listener->on_inconsistent_topic = callback;
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
    }
 | 
			
		||||
  if (listener)
 | 
			
		||||
    listener->on_inconsistent_topic = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lset_liveliness_changed (dds_listener_t * __restrict listener, dds_on_liveliness_changed_fn callback)
 | 
			
		||||
void dds_lset_liveliness_changed (dds_listener_t * __restrict listener, dds_on_liveliness_changed_fn callback)
 | 
			
		||||
{
 | 
			
		||||
    if (listener) {
 | 
			
		||||
        listener->on_liveliness_changed = callback;
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
    }
 | 
			
		||||
  if (listener)
 | 
			
		||||
    listener->on_liveliness_changed = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lset_liveliness_lost (dds_listener_t * __restrict listener, dds_on_liveliness_lost_fn callback)
 | 
			
		||||
void dds_lset_liveliness_lost (dds_listener_t * __restrict listener, dds_on_liveliness_lost_fn callback)
 | 
			
		||||
{
 | 
			
		||||
    if (listener) {
 | 
			
		||||
        listener->on_liveliness_lost = callback;
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
    }
 | 
			
		||||
  if (listener)
 | 
			
		||||
    listener->on_liveliness_lost = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lset_offered_deadline_missed (dds_listener_t * __restrict listener, dds_on_offered_deadline_missed_fn callback)
 | 
			
		||||
void dds_lset_offered_deadline_missed (dds_listener_t * __restrict listener, dds_on_offered_deadline_missed_fn callback)
 | 
			
		||||
{
 | 
			
		||||
    if (listener) {
 | 
			
		||||
        listener->on_offered_deadline_missed = callback;
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
    }
 | 
			
		||||
  if (listener)
 | 
			
		||||
    listener->on_offered_deadline_missed = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lset_offered_incompatible_qos (dds_listener_t * __restrict listener, dds_on_offered_incompatible_qos_fn callback)
 | 
			
		||||
void dds_lset_offered_incompatible_qos (dds_listener_t * __restrict listener, dds_on_offered_incompatible_qos_fn callback)
 | 
			
		||||
{
 | 
			
		||||
    if (listener) {
 | 
			
		||||
        listener->on_offered_incompatible_qos = callback;
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
    }
 | 
			
		||||
  if (listener)
 | 
			
		||||
    listener->on_offered_incompatible_qos = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lset_publication_matched (dds_listener_t * __restrict listener, dds_on_publication_matched_fn callback)
 | 
			
		||||
void dds_lset_publication_matched (dds_listener_t * __restrict listener, dds_on_publication_matched_fn callback)
 | 
			
		||||
{
 | 
			
		||||
    if (listener) {
 | 
			
		||||
        listener->on_publication_matched = callback;
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL");
 | 
			
		||||
    }
 | 
			
		||||
  if (listener)
 | 
			
		||||
    listener->on_publication_matched = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lset_requested_deadline_missed (dds_listener_t * __restrict listener, dds_on_requested_deadline_missed_fn callback)
 | 
			
		||||
void dds_lset_requested_deadline_missed (dds_listener_t * __restrict listener, dds_on_requested_deadline_missed_fn callback)
 | 
			
		||||
{
 | 
			
		||||
    if (listener) {
 | 
			
		||||
        listener->on_requested_deadline_missed = callback;
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
    }
 | 
			
		||||
  if (listener)
 | 
			
		||||
    listener->on_requested_deadline_missed = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lset_requested_incompatible_qos (dds_listener_t * __restrict listener, dds_on_requested_incompatible_qos_fn callback)
 | 
			
		||||
void dds_lset_requested_incompatible_qos (dds_listener_t * __restrict listener, dds_on_requested_incompatible_qos_fn callback)
 | 
			
		||||
{
 | 
			
		||||
    if (listener) {
 | 
			
		||||
        listener->on_requested_incompatible_qos = callback;
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
    }
 | 
			
		||||
  if (listener)
 | 
			
		||||
    listener->on_requested_incompatible_qos = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lset_sample_lost (dds_listener_t * __restrict listener, dds_on_sample_lost_fn callback)
 | 
			
		||||
void dds_lset_sample_lost (dds_listener_t * __restrict listener, dds_on_sample_lost_fn callback)
 | 
			
		||||
{
 | 
			
		||||
    if (listener) {
 | 
			
		||||
        listener->on_sample_lost = callback;
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
    }
 | 
			
		||||
  if (listener)
 | 
			
		||||
    listener->on_sample_lost = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lset_sample_rejected (dds_listener_t * __restrict listener, dds_on_sample_rejected_fn callback)
 | 
			
		||||
void dds_lset_sample_rejected (dds_listener_t * __restrict listener, dds_on_sample_rejected_fn callback)
 | 
			
		||||
{
 | 
			
		||||
    if (listener) {
 | 
			
		||||
        listener->on_sample_rejected = callback;
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
    }
 | 
			
		||||
  if (listener)
 | 
			
		||||
    listener->on_sample_rejected = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lset_subscription_matched (dds_listener_t * __restrict listener, dds_on_subscription_matched_fn callback)
 | 
			
		||||
void dds_lset_subscription_matched (dds_listener_t * __restrict listener, dds_on_subscription_matched_fn callback)
 | 
			
		||||
{
 | 
			
		||||
    if (listener) {
 | 
			
		||||
        listener->on_subscription_matched = callback;
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
    }
 | 
			
		||||
  if (listener)
 | 
			
		||||
    listener->on_subscription_matched = callback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/************************************************************************************************
 | 
			
		||||
 *  Getters
 | 
			
		||||
 ************************************************************************************************/
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lget_data_available (const dds_listener_t * __restrict listener, dds_on_data_available_fn *callback)
 | 
			
		||||
void dds_lget_data_available (const dds_listener_t * __restrict listener, dds_on_data_available_fn *callback)
 | 
			
		||||
{
 | 
			
		||||
    if(!callback){
 | 
			
		||||
        DDS_ERROR("Argument callback is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
    if (!listener) {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
  if (callback && listener)
 | 
			
		||||
    *callback = listener->on_data_available;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lget_data_on_readers (const dds_listener_t * __restrict listener, dds_on_data_on_readers_fn *callback)
 | 
			
		||||
void dds_lget_data_on_readers (const dds_listener_t * __restrict listener, dds_on_data_on_readers_fn *callback)
 | 
			
		||||
{
 | 
			
		||||
    if(!callback){
 | 
			
		||||
        DDS_ERROR("Argument callback is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
    if (!listener) {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
  if (callback && listener)
 | 
			
		||||
    *callback = listener->on_data_on_readers;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dds_lget_inconsistent_topic (const dds_listener_t * __restrict listener, dds_on_inconsistent_topic_fn *callback)
 | 
			
		||||
{
 | 
			
		||||
    if(!callback){
 | 
			
		||||
        DDS_ERROR("Argument callback is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
    if (!listener) {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
  if (callback && listener)
 | 
			
		||||
    *callback = listener->on_inconsistent_topic;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lget_liveliness_changed (const dds_listener_t * __restrict listener, dds_on_liveliness_changed_fn *callback)
 | 
			
		||||
void dds_lget_liveliness_changed (const dds_listener_t * __restrict listener, dds_on_liveliness_changed_fn *callback)
 | 
			
		||||
{
 | 
			
		||||
    if(!callback){
 | 
			
		||||
        DDS_ERROR("Argument callback is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
    if (!listener) {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
  if (callback && listener)
 | 
			
		||||
    *callback = listener->on_liveliness_changed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lget_liveliness_lost (const dds_listener_t * __restrict listener, dds_on_liveliness_lost_fn *callback)
 | 
			
		||||
void dds_lget_liveliness_lost (const dds_listener_t * __restrict listener, dds_on_liveliness_lost_fn *callback)
 | 
			
		||||
{
 | 
			
		||||
    if(!callback){
 | 
			
		||||
        DDS_ERROR("Argument callback is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
    if (!listener) {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
  if (callback && listener)
 | 
			
		||||
    *callback = listener->on_liveliness_lost;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lget_offered_deadline_missed (const dds_listener_t * __restrict listener, dds_on_offered_deadline_missed_fn *callback)
 | 
			
		||||
void dds_lget_offered_deadline_missed (const dds_listener_t * __restrict listener, dds_on_offered_deadline_missed_fn *callback)
 | 
			
		||||
{
 | 
			
		||||
    if(!callback){
 | 
			
		||||
        DDS_ERROR("Argument callback is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
    if (!listener) {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
  if (callback && listener)
 | 
			
		||||
    *callback = listener->on_offered_deadline_missed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lget_offered_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_offered_incompatible_qos_fn *callback)
 | 
			
		||||
void dds_lget_offered_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_offered_incompatible_qos_fn *callback)
 | 
			
		||||
{
 | 
			
		||||
    if(!callback){
 | 
			
		||||
        DDS_ERROR("Argument callback is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
    if (!listener) {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
  if (callback && listener)
 | 
			
		||||
    *callback = listener->on_offered_incompatible_qos;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lget_publication_matched (const dds_listener_t * __restrict listener, dds_on_publication_matched_fn *callback)
 | 
			
		||||
void dds_lget_publication_matched (const dds_listener_t * __restrict listener, dds_on_publication_matched_fn *callback)
 | 
			
		||||
{
 | 
			
		||||
    if(!callback){
 | 
			
		||||
        DDS_ERROR("Argument callback is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
    if (!listener) {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
  if (callback && listener)
 | 
			
		||||
    *callback = listener->on_publication_matched;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lget_requested_deadline_missed (const dds_listener_t * __restrict listener, dds_on_requested_deadline_missed_fn *callback)
 | 
			
		||||
void dds_lget_requested_deadline_missed (const dds_listener_t * __restrict listener, dds_on_requested_deadline_missed_fn *callback)
 | 
			
		||||
{
 | 
			
		||||
    if(!callback) {
 | 
			
		||||
        DDS_ERROR("Argument callback is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
    if (!listener) {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
  if (callback && listener)
 | 
			
		||||
    *callback = listener->on_requested_deadline_missed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lget_requested_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_requested_incompatible_qos_fn *callback)
 | 
			
		||||
void dds_lget_requested_incompatible_qos (const dds_listener_t * __restrict listener, dds_on_requested_incompatible_qos_fn *callback)
 | 
			
		||||
{
 | 
			
		||||
    if(!callback) {
 | 
			
		||||
        DDS_ERROR("Argument callback is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
    if (!listener) {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
  if (callback && listener)
 | 
			
		||||
    *callback = listener->on_requested_incompatible_qos;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lget_sample_lost (const dds_listener_t *__restrict listener, dds_on_sample_lost_fn *callback)
 | 
			
		||||
void dds_lget_sample_lost (const dds_listener_t *__restrict listener, dds_on_sample_lost_fn *callback)
 | 
			
		||||
{
 | 
			
		||||
    if(!callback) {
 | 
			
		||||
        DDS_ERROR("Argument callback is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
    if (!listener) {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
  if (callback && listener)
 | 
			
		||||
    *callback = listener->on_sample_lost;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lget_sample_rejected (const dds_listener_t  *__restrict listener, dds_on_sample_rejected_fn *callback)
 | 
			
		||||
void dds_lget_sample_rejected (const dds_listener_t  *__restrict listener, dds_on_sample_rejected_fn *callback)
 | 
			
		||||
{
 | 
			
		||||
    if(!callback) {
 | 
			
		||||
        DDS_ERROR("Argument callback is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
    if (!listener) {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
  if (callback && listener)
 | 
			
		||||
    *callback = listener->on_sample_rejected;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_lget_subscription_matched (const dds_listener_t * __restrict listener, dds_on_subscription_matched_fn *callback)
 | 
			
		||||
void dds_lget_subscription_matched (const dds_listener_t * __restrict listener, dds_on_subscription_matched_fn *callback)
 | 
			
		||||
{
 | 
			
		||||
    if(!callback) {
 | 
			
		||||
        DDS_ERROR("Argument callback is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
    if (!listener) {
 | 
			
		||||
        DDS_ERROR("Argument listener is NULL\n");
 | 
			
		||||
        return ;
 | 
			
		||||
    }
 | 
			
		||||
  if (callback && listener)
 | 
			
		||||
    *callback = listener->on_subscription_matched;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,260 +21,183 @@
 | 
			
		|||
#include "dds__participant.h"
 | 
			
		||||
#include "dds__builtin.h"
 | 
			
		||||
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_participant)
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_participant)
 | 
			
		||||
 | 
			
		||||
#define DDS_PARTICIPANT_STATUS_MASK    0u
 | 
			
		||||
#define DDS_PARTICIPANT_STATUS_MASK    (0u)
 | 
			
		||||
 | 
			
		||||
/* List of created participants */
 | 
			
		||||
static dds_entity *dds_pp_head = NULL;
 | 
			
		||||
 | 
			
		||||
static dds_entity * dds_pp_head = NULL;
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_participant_status_validate(
 | 
			
		||||
    uint32_t mask)
 | 
			
		||||
static dds_return_t dds_participant_status_validate (uint32_t mask)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
 | 
			
		||||
    if (mask & ~(DDS_PARTICIPANT_STATUS_MASK)) {
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
  return (mask & ~DDS_PARTICIPANT_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_participant_delete(
 | 
			
		||||
    dds_entity *e)
 | 
			
		||||
static dds_return_t dds_participant_delete (dds_entity *e) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_participant_delete (dds_entity *e)
 | 
			
		||||
{
 | 
			
		||||
    dds_entity *prev = NULL;
 | 
			
		||||
    dds_entity *iter;
 | 
			
		||||
  assert (dds_entity_kind (e) == DDS_KIND_PARTICIPANT);
 | 
			
		||||
 | 
			
		||||
    assert(e);
 | 
			
		||||
    assert(dds_entity_kind(e) == DDS_KIND_PARTICIPANT);
 | 
			
		||||
  thread_state_awake (lookup_thread_state ());
 | 
			
		||||
  dds_domain_free (e->m_domain);
 | 
			
		||||
  ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
  dds_entity *prev, *iter;
 | 
			
		||||
  for (iter = dds_pp_head, prev = NULL; iter; prev = iter, iter = iter->m_next)
 | 
			
		||||
  {
 | 
			
		||||
    if (iter == e)
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  assert (iter);
 | 
			
		||||
  if (prev)
 | 
			
		||||
    prev->m_next = iter->m_next;
 | 
			
		||||
  else
 | 
			
		||||
    dds_pp_head = iter->m_next;
 | 
			
		||||
  ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
  thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
 | 
			
		||||
    thread_state_awake (lookup_thread_state ());
 | 
			
		||||
  /* Every dds_init needs a dds_fini. */
 | 
			
		||||
  dds_fini ();
 | 
			
		||||
  return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    dds_domain_free (e->m_domain);
 | 
			
		||||
static dds_return_t dds_participant_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_participant_instance_hdl (dds_entity *e, dds_instance_handle_t *i)
 | 
			
		||||
{
 | 
			
		||||
  *i = participant_instance_id (&e->m_guid);
 | 
			
		||||
  return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_participant_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_participant_qos_validate (const dds_qos_t *qos, bool enabled)
 | 
			
		||||
{
 | 
			
		||||
  (void)enabled;
 | 
			
		||||
 | 
			
		||||
  if ((qos->present & QP_USER_DATA) && !validate_octetseq (&qos->user_data))
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy (&qos->entity_factory))
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
 | 
			
		||||
  return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_participant_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_participant_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
 | 
			
		||||
{
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  (void)e;
 | 
			
		||||
  if ((ret = dds_participant_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
  if (enabled) /* FIXME: changing QoS */
 | 
			
		||||
    return DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_t *qos, const dds_listener_t *listener)
 | 
			
		||||
{
 | 
			
		||||
  dds_entity_t ret;
 | 
			
		||||
  nn_guid_t guid;
 | 
			
		||||
  dds_participant * pp;
 | 
			
		||||
  nn_plist_t plist;
 | 
			
		||||
  dds_qos_t *new_qos = NULL;
 | 
			
		||||
 | 
			
		||||
  /* Make sure DDS instance is initialized. */
 | 
			
		||||
  if ((ret = dds_init (domain)) != DDS_RETCODE_OK)
 | 
			
		||||
    goto err_dds_init;
 | 
			
		||||
 | 
			
		||||
  /* Check domain id */
 | 
			
		||||
  if ((ret = dds__check_domain (domain)) != DDS_RETCODE_OK)
 | 
			
		||||
    goto err_domain_check;
 | 
			
		||||
 | 
			
		||||
  /* Validate qos or use default if NULL */
 | 
			
		||||
  if (qos && (ret = dds_participant_qos_validate (qos, false)) != DDS_RETCODE_OK)
 | 
			
		||||
    goto err_qos_validation;
 | 
			
		||||
 | 
			
		||||
  new_qos = dds_create_qos ();
 | 
			
		||||
  if (qos != NULL)
 | 
			
		||||
    (void) dds_copy_qos (new_qos, qos);
 | 
			
		||||
 | 
			
		||||
  /* Translate qos */
 | 
			
		||||
  nn_plist_init_empty (&plist);
 | 
			
		||||
  dds_merge_qos (&plist.qos, new_qos);
 | 
			
		||||
 | 
			
		||||
  thread_state_awake (lookup_thread_state ());
 | 
			
		||||
  ret = new_participant (&guid, 0, &plist);
 | 
			
		||||
  thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
  nn_plist_fini (&plist);
 | 
			
		||||
  if (ret < 0)
 | 
			
		||||
  {
 | 
			
		||||
    ret = DDS_RETCODE_ERROR;
 | 
			
		||||
    goto err_new_participant;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pp = dds_alloc (sizeof (*pp));
 | 
			
		||||
  if ((ret = dds_entity_init (&pp->m_entity, NULL, DDS_KIND_PARTICIPANT, new_qos, listener, DDS_PARTICIPANT_STATUS_MASK)) < 0)
 | 
			
		||||
    goto err_entity_init;
 | 
			
		||||
 | 
			
		||||
  pp->m_entity.m_guid = guid;
 | 
			
		||||
  pp->m_entity.m_domain = dds_domain_create (dds_domain_default ());
 | 
			
		||||
  pp->m_entity.m_domainid = dds_domain_default ();
 | 
			
		||||
  pp->m_entity.m_deriver.delete = dds_participant_delete;
 | 
			
		||||
  pp->m_entity.m_deriver.set_qos = dds_participant_qos_set;
 | 
			
		||||
  pp->m_entity.m_deriver.get_instance_hdl = dds_participant_instance_hdl;
 | 
			
		||||
  pp->m_entity.m_deriver.validate_status = dds_participant_status_validate;
 | 
			
		||||
  pp->m_builtin_subscriber = 0;
 | 
			
		||||
 | 
			
		||||
  /* Add participant to extent */
 | 
			
		||||
  ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
  pp->m_entity.m_next = dds_pp_head;
 | 
			
		||||
  dds_pp_head = &pp->m_entity;
 | 
			
		||||
  ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
  return ret;
 | 
			
		||||
 | 
			
		||||
err_entity_init:
 | 
			
		||||
  dds_free (pp);
 | 
			
		||||
err_new_participant:
 | 
			
		||||
  dds_delete_qos (new_qos);
 | 
			
		||||
err_qos_validation:
 | 
			
		||||
err_domain_check:
 | 
			
		||||
  dds_fini ();
 | 
			
		||||
err_dds_init:
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_entity_t dds_lookup_participant (dds_domainid_t domain_id, dds_entity_t *participants, size_t size)
 | 
			
		||||
{
 | 
			
		||||
  ddsrt_mutex_t *init_mutex;
 | 
			
		||||
 | 
			
		||||
  ddsrt_init ();
 | 
			
		||||
  init_mutex = ddsrt_get_singleton_mutex ();
 | 
			
		||||
 | 
			
		||||
  if ((participants != NULL && (size <= 0 || size >= INT32_MAX)) || (participants == NULL && size != 0))
 | 
			
		||||
  {
 | 
			
		||||
    ddsrt_fini ();
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (participants)
 | 
			
		||||
    participants[0] = 0;
 | 
			
		||||
 | 
			
		||||
  dds_return_t ret = 0;
 | 
			
		||||
  ddsrt_mutex_lock (init_mutex);
 | 
			
		||||
  if (dds_global.m_init_count > 0)
 | 
			
		||||
  {
 | 
			
		||||
    ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
    iter = dds_pp_head;
 | 
			
		||||
    while (iter) {
 | 
			
		||||
        if (iter == e) {
 | 
			
		||||
            if (prev) {
 | 
			
		||||
                prev->m_next = iter->m_next;
 | 
			
		||||
            } else {
 | 
			
		||||
                  dds_pp_head = iter->m_next;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        prev = iter;
 | 
			
		||||
        iter = iter->m_next;
 | 
			
		||||
    for (dds_entity *iter = dds_pp_head; iter; iter = iter->m_next)
 | 
			
		||||
    {
 | 
			
		||||
      if (iter->m_domainid == domain_id)
 | 
			
		||||
      {
 | 
			
		||||
        if ((size_t) ret < size)
 | 
			
		||||
          participants[ret] = iter->m_hdllink.hdl;
 | 
			
		||||
        ret++;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
 | 
			
		||||
    assert (iter);
 | 
			
		||||
 | 
			
		||||
    thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
 | 
			
		||||
    /* Every dds_init needs a dds_fini. */
 | 
			
		||||
    dds_fini();
 | 
			
		||||
 | 
			
		||||
    return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_participant_instance_hdl(
 | 
			
		||||
    dds_entity *e,
 | 
			
		||||
    dds_instance_handle_t *i)
 | 
			
		||||
{
 | 
			
		||||
    assert(e);
 | 
			
		||||
    assert(i);
 | 
			
		||||
    *i = (dds_instance_handle_t)participant_instance_id(&e->m_guid);
 | 
			
		||||
    return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_participant_qos_validate(
 | 
			
		||||
    const dds_qos_t *qos,
 | 
			
		||||
    bool enabled)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
    assert(qos);
 | 
			
		||||
    (void)enabled;
 | 
			
		||||
 | 
			
		||||
    /* Check consistency. */
 | 
			
		||||
    if ((qos->present & QP_USER_DATA) && !validate_octetseq(&qos->user_data)) {
 | 
			
		||||
        DDS_ERROR("User data QoS policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)) {
 | 
			
		||||
        DDS_ERROR("Prismtech entity factory QoS policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_participant_qos_set(
 | 
			
		||||
    dds_entity *e,
 | 
			
		||||
    const dds_qos_t *qos,
 | 
			
		||||
    bool enabled)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = dds_participant_qos_validate(qos, enabled);
 | 
			
		||||
    (void)e;
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        if (enabled) {
 | 
			
		||||
            /* TODO: CHAM-95: DDSI does not support changing QoS policies. */
 | 
			
		||||
            DDS_ERROR("Changing the participant QoS is not supported\n");
 | 
			
		||||
            ret = DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_entity_t
 | 
			
		||||
dds_create_participant(
 | 
			
		||||
    const dds_domainid_t domain,
 | 
			
		||||
    const dds_qos_t *qos,
 | 
			
		||||
    const dds_listener_t *listener)
 | 
			
		||||
{
 | 
			
		||||
    int q_rc;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
    dds_entity_t e;
 | 
			
		||||
    nn_guid_t guid;
 | 
			
		||||
    dds_participant * pp;
 | 
			
		||||
    nn_plist_t plist;
 | 
			
		||||
    dds_qos_t * new_qos = NULL;
 | 
			
		||||
 | 
			
		||||
    /* Make sure DDS instance is initialized. */
 | 
			
		||||
    ret = dds_init(domain);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        e = (dds_entity_t)ret;
 | 
			
		||||
        goto fail_dds_init;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Check domain id */
 | 
			
		||||
    ret = dds__check_domain (domain);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        e = (dds_entity_t)ret;
 | 
			
		||||
        goto fail_domain_check;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Validate qos */
 | 
			
		||||
    if (qos) {
 | 
			
		||||
        ret = dds_participant_qos_validate (qos, false);
 | 
			
		||||
        if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
            e = (dds_entity_t)ret;
 | 
			
		||||
            goto fail_qos_validation;
 | 
			
		||||
        }
 | 
			
		||||
        new_qos = dds_create_qos ();
 | 
			
		||||
        /* Only returns failure when one of the qos args is NULL, which
 | 
			
		||||
         * is not the case here. */
 | 
			
		||||
        (void)dds_copy_qos(new_qos, qos);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Use default qos. */
 | 
			
		||||
        new_qos = dds_create_qos ();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Translate qos */
 | 
			
		||||
    nn_plist_init_empty(&plist);
 | 
			
		||||
    dds_merge_qos (&plist.qos, new_qos);
 | 
			
		||||
 | 
			
		||||
    thread_state_awake (lookup_thread_state ());
 | 
			
		||||
    q_rc = new_participant (&guid, 0, &plist);
 | 
			
		||||
    thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
    nn_plist_fini (&plist);
 | 
			
		||||
    if (q_rc != 0) {
 | 
			
		||||
        DDS_ERROR("Internal error");
 | 
			
		||||
        e = DDS_RETCODE_ERROR;
 | 
			
		||||
        goto fail_new_participant;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pp = dds_alloc (sizeof (*pp));
 | 
			
		||||
    e = dds_entity_init (&pp->m_entity, NULL, DDS_KIND_PARTICIPANT, new_qos, listener, DDS_PARTICIPANT_STATUS_MASK);
 | 
			
		||||
    if (e < 0) {
 | 
			
		||||
        goto fail_entity_init;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pp->m_entity.m_guid = guid;
 | 
			
		||||
    pp->m_entity.m_domain = dds_domain_create (dds_domain_default());
 | 
			
		||||
    pp->m_entity.m_domainid = dds_domain_default();
 | 
			
		||||
    pp->m_entity.m_deriver.delete = dds_participant_delete;
 | 
			
		||||
    pp->m_entity.m_deriver.set_qos = dds_participant_qos_set;
 | 
			
		||||
    pp->m_entity.m_deriver.get_instance_hdl = dds_participant_instance_hdl;
 | 
			
		||||
    pp->m_entity.m_deriver.validate_status = dds_participant_status_validate;
 | 
			
		||||
    pp->m_builtin_subscriber = 0;
 | 
			
		||||
 | 
			
		||||
    /* Add participant to extent */
 | 
			
		||||
    ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
    pp->m_entity.m_next = dds_pp_head;
 | 
			
		||||
    dds_pp_head = &pp->m_entity;
 | 
			
		||||
    ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
 | 
			
		||||
    return e;
 | 
			
		||||
 | 
			
		||||
fail_entity_init:
 | 
			
		||||
    dds_free(pp);
 | 
			
		||||
fail_new_participant:
 | 
			
		||||
    dds_delete_qos(new_qos);
 | 
			
		||||
fail_qos_validation:
 | 
			
		||||
fail_domain_check:
 | 
			
		||||
    dds_fini();
 | 
			
		||||
fail_dds_init:
 | 
			
		||||
    return e;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_entity_t
 | 
			
		||||
dds_lookup_participant(
 | 
			
		||||
    dds_domainid_t domain_id,
 | 
			
		||||
    dds_entity_t *participants,
 | 
			
		||||
    size_t size)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = 0;
 | 
			
		||||
    ddsrt_mutex_t *init_mutex;
 | 
			
		||||
 | 
			
		||||
    /* Be sure the DDS lifecycle resources are initialized. */
 | 
			
		||||
    ddsrt_init();
 | 
			
		||||
    init_mutex = ddsrt_get_singleton_mutex();
 | 
			
		||||
 | 
			
		||||
    if ((participants != NULL) && ((size <= 0) || (size >= INT32_MAX))) {
 | 
			
		||||
        DDS_ERROR("Array is given, but with invalid size\n");
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
    if ((participants == NULL) && (size != 0)) {
 | 
			
		||||
        DDS_ERROR("Size is given, but no array\n");
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(participants){
 | 
			
		||||
        participants[0] = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ddsrt_mutex_lock (init_mutex);
 | 
			
		||||
 | 
			
		||||
    /* Check if dds is intialized. */
 | 
			
		||||
    if (dds_global.m_init_count > 0) {
 | 
			
		||||
        dds_entity* iter;
 | 
			
		||||
        ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
        iter = dds_pp_head;
 | 
			
		||||
        while (iter) {
 | 
			
		||||
            if (iter->m_domainid == domain_id) {
 | 
			
		||||
                if ((size_t)ret < size) {
 | 
			
		||||
                    participants[ret] = iter->m_hdllink.hdl;
 | 
			
		||||
                }
 | 
			
		||||
                ret++;
 | 
			
		||||
            }
 | 
			
		||||
            iter = iter->m_next;
 | 
			
		||||
        }
 | 
			
		||||
        ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ddsrt_mutex_unlock (init_mutex);
 | 
			
		||||
 | 
			
		||||
err:
 | 
			
		||||
    ddsrt_fini();
 | 
			
		||||
    return ret;
 | 
			
		||||
  }
 | 
			
		||||
  ddsrt_mutex_unlock (init_mutex);
 | 
			
		||||
  ddsrt_fini ();
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,153 +13,102 @@
 | 
			
		|||
#include <string.h>
 | 
			
		||||
#include "dds/ddsrt/misc.h"
 | 
			
		||||
#include "dds__listener.h"
 | 
			
		||||
#include "dds__participant.h"
 | 
			
		||||
#include "dds__publisher.h"
 | 
			
		||||
#include "dds__qos.h"
 | 
			
		||||
#include "dds/ddsi/q_entity.h"
 | 
			
		||||
#include "dds/version.h"
 | 
			
		||||
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_publisher)
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_publisher)
 | 
			
		||||
 | 
			
		||||
#define DDS_PUBLISHER_STATUS_MASK   0u
 | 
			
		||||
#define DDS_PUBLISHER_STATUS_MASK   (0u)
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_publisher_instance_hdl(
 | 
			
		||||
    dds_entity *e,
 | 
			
		||||
    dds_instance_handle_t *i)
 | 
			
		||||
static dds_return_t dds_publisher_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_publisher_instance_hdl (dds_entity *e, dds_instance_handle_t *i)
 | 
			
		||||
{
 | 
			
		||||
    (void)e;
 | 
			
		||||
    (void)i;
 | 
			
		||||
    /* TODO: Get/generate proper handle. */
 | 
			
		||||
    DDS_ERROR("Getting publisher instance handle is not supported\n");
 | 
			
		||||
  /* FIXME: Get/generate proper handle. */
 | 
			
		||||
  (void) e;
 | 
			
		||||
  (void) i;
 | 
			
		||||
  return DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_publisher_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_publisher_qos_validate (const dds_qos_t *qos, bool enabled)
 | 
			
		||||
{
 | 
			
		||||
  if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data))
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_PRESENTATION) && validate_presentation_qospolicy (&qos->presentation) < 0)
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_PARTITION) && !validate_stringseq (&qos->partition))
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy (&qos->entity_factory))
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  /* FIXME: Improve/check immutable check. */
 | 
			
		||||
  if (enabled && (qos->present & QP_PRESENTATION))
 | 
			
		||||
    return DDS_RETCODE_IMMUTABLE_POLICY;
 | 
			
		||||
  return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_publisher_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_publisher_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
 | 
			
		||||
{
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  (void)e;
 | 
			
		||||
  if ((ret = dds_publisher_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
  if (enabled) /* FIXME: QoS changes. */
 | 
			
		||||
    return DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_publisher_qos_validate(
 | 
			
		||||
    const dds_qos_t *qos,
 | 
			
		||||
    bool enabled)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
    assert(qos);
 | 
			
		||||
 | 
			
		||||
    /* Check consistency. */
 | 
			
		||||
    if((qos->present & QP_GROUP_DATA) && !validate_octetseq(&qos->group_data)){
 | 
			
		||||
        DDS_ERROR("Group data policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if((qos->present & QP_PRESENTATION) && (validate_presentation_qospolicy(&qos->presentation) != 0)){
 | 
			
		||||
        DDS_ERROR("Presentation policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if((qos->present & QP_PARTITION) && !validate_stringseq(&qos->partition)){
 | 
			
		||||
        DDS_ERROR("Partition policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)){
 | 
			
		||||
        DDS_ERROR("Prismtech entity factory policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if(ret == DDS_RETCODE_OK && enabled && (qos->present & QP_PRESENTATION)){
 | 
			
		||||
        /* TODO: Improve/check immutable check. */
 | 
			
		||||
        DDS_ERROR("Presentation policy is immutable\n");
 | 
			
		||||
        ret = DDS_RETCODE_IMMUTABLE_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_publisher_qos_set(
 | 
			
		||||
    dds_entity *e,
 | 
			
		||||
    const dds_qos_t *qos,
 | 
			
		||||
    bool enabled)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = dds_publisher_qos_validate(qos, enabled);
 | 
			
		||||
    (void)e;
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        if (enabled) {
 | 
			
		||||
            /* TODO: CHAM-95: DDSI does not support changing QoS policies. */
 | 
			
		||||
            DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies yet\n");
 | 
			
		||||
            ret = DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
  return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_publisher_status_validate (uint32_t mask)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
  return (mask & ~DDS_PUBLISHER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    if (mask & ~(DDS_PUBLISHER_STATUS_MASK)) {
 | 
			
		||||
        DDS_ERROR("Invalid status mask\n");
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qos, const dds_listener_t *listener)
 | 
			
		||||
{
 | 
			
		||||
  dds_participant *par;
 | 
			
		||||
  dds_publisher *pub;
 | 
			
		||||
  dds_entity_t hdl;
 | 
			
		||||
  dds_qos_t *new_qos = NULL;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
  if (qos && (ret = dds_publisher_qos_validate (qos, false)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
  
 | 
			
		||||
  if ((ret = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  if (qos)
 | 
			
		||||
  {
 | 
			
		||||
    new_qos = dds_create_qos ();
 | 
			
		||||
    (void) dds_copy_qos (new_qos, qos);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pub = dds_alloc (sizeof (*pub));
 | 
			
		||||
  hdl = dds_entity_init (&pub->m_entity, &par->m_entity, DDS_KIND_PUBLISHER, new_qos, listener, DDS_PUBLISHER_STATUS_MASK);
 | 
			
		||||
  pub->m_entity.m_deriver.set_qos = dds_publisher_qos_set;
 | 
			
		||||
  pub->m_entity.m_deriver.get_instance_hdl = dds_publisher_instance_hdl;
 | 
			
		||||
  pub->m_entity.m_deriver.validate_status = dds_publisher_status_validate;
 | 
			
		||||
  dds_participant_unlock (par);
 | 
			
		||||
  return hdl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_entity_t
 | 
			
		||||
dds_create_publisher(
 | 
			
		||||
    dds_entity_t participant,
 | 
			
		||||
    const dds_qos_t *qos,
 | 
			
		||||
    const dds_listener_t *listener)
 | 
			
		||||
{
 | 
			
		||||
    dds_entity * par;
 | 
			
		||||
    dds_publisher * pub;
 | 
			
		||||
    dds_entity_t hdl;
 | 
			
		||||
    dds_qos_t * new_qos = NULL;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking participant\n");
 | 
			
		||||
        hdl = ret;
 | 
			
		||||
        goto lock_err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Validate qos */
 | 
			
		||||
    if (qos) {
 | 
			
		||||
        ret = dds_publisher_qos_validate(qos, false);
 | 
			
		||||
        if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
            hdl = ret;
 | 
			
		||||
            goto qos_err;
 | 
			
		||||
        }
 | 
			
		||||
        new_qos = dds_create_qos ();
 | 
			
		||||
        /* Only returns failure when one of the qos args is NULL, which
 | 
			
		||||
         * is not the case here. */
 | 
			
		||||
        (void)dds_copy_qos(new_qos, qos);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Create publisher */
 | 
			
		||||
    pub = dds_alloc (sizeof (*pub));
 | 
			
		||||
    hdl = dds_entity_init (&pub->m_entity, par, DDS_KIND_PUBLISHER, new_qos, listener, DDS_PUBLISHER_STATUS_MASK);
 | 
			
		||||
    pub->m_entity.m_deriver.set_qos = dds_publisher_qos_set;
 | 
			
		||||
    pub->m_entity.m_deriver.get_instance_hdl = dds_publisher_instance_hdl;
 | 
			
		||||
    pub->m_entity.m_deriver.validate_status = dds_publisher_status_validate;
 | 
			
		||||
 | 
			
		||||
qos_err:
 | 
			
		||||
    dds_entity_unlock(par);
 | 
			
		||||
lock_err:
 | 
			
		||||
    return hdl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT dds_return_t
 | 
			
		||||
dds_suspend(
 | 
			
		||||
    dds_entity_t publisher)
 | 
			
		||||
dds_return_t dds_suspend (dds_entity_t publisher)
 | 
			
		||||
{
 | 
			
		||||
  return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_resume(
 | 
			
		||||
    dds_entity_t publisher)
 | 
			
		||||
dds_return_t dds_resume (dds_entity_t publisher)
 | 
			
		||||
{
 | 
			
		||||
  return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_wait_for_acks(
 | 
			
		||||
    dds_entity_t publisher_or_writer,
 | 
			
		||||
    dds_duration_t timeout)
 | 
			
		||||
dds_return_t dds_wait_for_acks (dds_entity_t publisher_or_writer, dds_duration_t timeout)
 | 
			
		||||
{
 | 
			
		||||
  if (timeout < 0)
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
| 
						 | 
				
			
			@ -167,23 +116,12 @@ dds_wait_for_acks(
 | 
			
		|||
  return dds_generic_unimplemented_operation_manykinds (publisher_or_writer, sizeof (kinds) / sizeof (kinds[0]), kinds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_publisher_begin_coherent(
 | 
			
		||||
    dds_entity_t e)
 | 
			
		||||
dds_return_t dds_publisher_begin_coherent (dds_entity_t publisher)
 | 
			
		||||
{
 | 
			
		||||
    /* TODO: CHAM-124 Currently unsupported. */
 | 
			
		||||
    (void)e;
 | 
			
		||||
    DDS_ERROR("Using coherency to get a coherent data set is not being supported yet\n");
 | 
			
		||||
    return DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
  return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_publisher_end_coherent(
 | 
			
		||||
    dds_entity_t e)
 | 
			
		||||
dds_return_t dds_publisher_end_coherent (dds_entity_t publisher)
 | 
			
		||||
{
 | 
			
		||||
    /* TODO: CHAM-124 Currently unsupported. */
 | 
			
		||||
    (void)e;
 | 
			
		||||
    DDS_ERROR("Using coherency to get a coherent data set is not being supported yet\n");
 | 
			
		||||
    return DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
  return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -21,32 +21,27 @@
 | 
			
		|||
#include "dds/ddsi/ddsi_serdata.h"
 | 
			
		||||
#include "dds/ddsi/ddsi_sertopic.h"
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT dds_entity_t
 | 
			
		||||
dds_create_querycondition(
 | 
			
		||||
    dds_entity_t reader,
 | 
			
		||||
    uint32_t mask,
 | 
			
		||||
    dds_querycondition_filter_fn filter)
 | 
			
		||||
dds_entity_t dds_create_querycondition (dds_entity_t reader, uint32_t mask, dds_querycondition_filter_fn filter)
 | 
			
		||||
{
 | 
			
		||||
  dds_return_t rc;
 | 
			
		||||
  dds_reader *r;
 | 
			
		||||
 | 
			
		||||
  if ((rc = dds_reader_lock (reader, &r)) != DDS_RETCODE_OK)
 | 
			
		||||
    return rc;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    dds_entity_t hdl;
 | 
			
		||||
    dds_return_t rc;
 | 
			
		||||
    dds_reader *r;
 | 
			
		||||
 | 
			
		||||
    rc = dds_reader_lock(reader, &r);
 | 
			
		||||
    if (rc == DDS_RETCODE_OK) {
 | 
			
		||||
        dds_readcond *cond = dds_create_readcond(r, DDS_KIND_COND_QUERY, mask, filter);
 | 
			
		||||
        assert(cond);
 | 
			
		||||
        const bool success = (cond->m_entity.m_deriver.delete != 0);
 | 
			
		||||
        dds_reader_unlock(r);
 | 
			
		||||
        if (success) {
 | 
			
		||||
            hdl = cond->m_entity.m_hdllink.hdl;
 | 
			
		||||
        } else {
 | 
			
		||||
            dds_delete (cond->m_entity.m_hdllink.hdl);
 | 
			
		||||
            hdl = DDS_RETCODE_OUT_OF_RESOURCES;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking reader\n");
 | 
			
		||||
        hdl = rc;
 | 
			
		||||
    dds_readcond *cond = dds_create_readcond (r, DDS_KIND_COND_QUERY, mask, filter);
 | 
			
		||||
    assert (cond);
 | 
			
		||||
    const bool success = (cond->m_entity.m_deriver.delete != 0);
 | 
			
		||||
    dds_reader_unlock (r);
 | 
			
		||||
    if (success)
 | 
			
		||||
      hdl = cond->m_entity.m_hdllink.hdl;
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      dds_delete (cond->m_entity.m_hdllink.hdl);
 | 
			
		||||
      hdl = DDS_RETCODE_OUT_OF_RESOURCES;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return hdl;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -18,65 +18,56 @@
 | 
			
		|||
#include "dds/ddsi/q_entity.h"
 | 
			
		||||
#include "dds/ddsi/q_thread.h"
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_readcond_delete(
 | 
			
		||||
    dds_entity *e)
 | 
			
		||||
static dds_return_t dds_readcond_delete (dds_entity *e) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_readcond_delete (dds_entity *e)
 | 
			
		||||
{
 | 
			
		||||
    dds_rhc_remove_readcondition((dds_readcond*)e);
 | 
			
		||||
    return DDS_RETCODE_OK;
 | 
			
		||||
  dds_rhc_remove_readcondition ((dds_readcond *) e);
 | 
			
		||||
  return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_readcond*
 | 
			
		||||
dds_create_readcond(
 | 
			
		||||
    dds_reader *rd,
 | 
			
		||||
    dds_entity_kind_t kind,
 | 
			
		||||
    uint32_t mask,
 | 
			
		||||
    dds_querycondition_filter_fn filter)
 | 
			
		||||
dds_readcond *dds_create_readcond (dds_reader *rd, dds_entity_kind_t kind, uint32_t mask, dds_querycondition_filter_fn filter)
 | 
			
		||||
{
 | 
			
		||||
    dds_readcond * cond = dds_alloc(sizeof(*cond));
 | 
			
		||||
    assert((kind == DDS_KIND_COND_READ && filter == 0) || (kind == DDS_KIND_COND_QUERY && filter != 0));
 | 
			
		||||
    (void) dds_entity_init(&cond->m_entity, (dds_entity*)rd, kind, NULL, NULL, 0);
 | 
			
		||||
    cond->m_entity.m_deriver.delete = dds_readcond_delete;
 | 
			
		||||
    cond->m_rhc = rd->m_rd->rhc;
 | 
			
		||||
    cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE;
 | 
			
		||||
    cond->m_view_states = mask & DDS_ANY_VIEW_STATE;
 | 
			
		||||
    cond->m_instance_states = mask & DDS_ANY_INSTANCE_STATE;
 | 
			
		||||
    cond->m_rd_guid = rd->m_entity.m_guid;
 | 
			
		||||
    if (kind == DDS_KIND_COND_QUERY) {
 | 
			
		||||
        cond->m_query.m_filter = filter;
 | 
			
		||||
        cond->m_query.m_qcmask = 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (!dds_rhc_add_readcondition (cond)) {
 | 
			
		||||
        /* FIXME: current entity management code can't deal with an error late in the creation of the
 | 
			
		||||
           entity because it doesn't allow deleting it again ... instead use a hack to signal a problem
 | 
			
		||||
           to the caller and let that one handle it. */
 | 
			
		||||
        cond->m_entity.m_deriver.delete = 0;
 | 
			
		||||
    }
 | 
			
		||||
    return cond;
 | 
			
		||||
  dds_readcond *cond = dds_alloc (sizeof (*cond));
 | 
			
		||||
  assert ((kind == DDS_KIND_COND_READ && filter == 0) || (kind == DDS_KIND_COND_QUERY && filter != 0));
 | 
			
		||||
  (void) dds_entity_init (&cond->m_entity, &rd->m_entity, kind, NULL, NULL, 0);
 | 
			
		||||
  cond->m_entity.m_deriver.delete = dds_readcond_delete;
 | 
			
		||||
  cond->m_rhc = rd->m_rd->rhc;
 | 
			
		||||
  cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE;
 | 
			
		||||
  cond->m_view_states = mask & DDS_ANY_VIEW_STATE;
 | 
			
		||||
  cond->m_instance_states = mask & DDS_ANY_INSTANCE_STATE;
 | 
			
		||||
  cond->m_rd_guid = rd->m_entity.m_guid;
 | 
			
		||||
  if (kind == DDS_KIND_COND_QUERY)
 | 
			
		||||
  {
 | 
			
		||||
    cond->m_query.m_filter = filter;
 | 
			
		||||
    cond->m_query.m_qcmask = 0;
 | 
			
		||||
  }
 | 
			
		||||
  if (!dds_rhc_add_readcondition (cond))
 | 
			
		||||
  {
 | 
			
		||||
    /* FIXME: current entity management code can't deal with an error late in the creation of the
 | 
			
		||||
       entity because it doesn't allow deleting it again ... instead use a hack to signal a problem
 | 
			
		||||
       to the caller and let that one handle it. */
 | 
			
		||||
    cond->m_entity.m_deriver.delete = 0;
 | 
			
		||||
  }
 | 
			
		||||
  return cond;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_entity_t
 | 
			
		||||
dds_create_readcondition(
 | 
			
		||||
    dds_entity_t reader,
 | 
			
		||||
    uint32_t mask)
 | 
			
		||||
dds_entity_t dds_create_readcondition (dds_entity_t reader, uint32_t mask)
 | 
			
		||||
{
 | 
			
		||||
  dds_reader *rd;
 | 
			
		||||
  dds_return_t rc;
 | 
			
		||||
  if ((rc = dds_reader_lock (reader, &rd)) != DDS_RETCODE_OK)
 | 
			
		||||
    return rc;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    dds_entity_t hdl;
 | 
			
		||||
    dds_reader * rd;
 | 
			
		||||
    dds_return_t rc;
 | 
			
		||||
 | 
			
		||||
    rc = dds_reader_lock(reader, &rd);
 | 
			
		||||
    if (rc == DDS_RETCODE_OK) {
 | 
			
		||||
        dds_readcond *cond = dds_create_readcond(rd, DDS_KIND_COND_READ, mask, 0);
 | 
			
		||||
        assert(cond);
 | 
			
		||||
        assert(cond->m_entity.m_deriver.delete);
 | 
			
		||||
        hdl = cond->m_entity.m_hdllink.hdl;
 | 
			
		||||
        dds_reader_unlock(rd);
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking reader\n");
 | 
			
		||||
        hdl = rc;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dds_readcond *cond = dds_create_readcond(rd, DDS_KIND_COND_READ, mask, 0);
 | 
			
		||||
    assert (cond);
 | 
			
		||||
    assert (cond->m_entity.m_deriver.delete);
 | 
			
		||||
    hdl = cond->m_entity.m_hdllink.hdl;
 | 
			
		||||
    dds_reader_unlock (rd);
 | 
			
		||||
    return hdl;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_entity_t dds_get_datareader (dds_entity_t condition)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@
 | 
			
		|||
#include <string.h>
 | 
			
		||||
#include "dds/dds.h"
 | 
			
		||||
#include "dds/version.h"
 | 
			
		||||
#include "dds/ddsrt/static_assert.h"
 | 
			
		||||
#include "dds__subscriber.h"
 | 
			
		||||
#include "dds__reader.h"
 | 
			
		||||
#include "dds__listener.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -20,135 +21,96 @@
 | 
			
		|||
#include "dds__init.h"
 | 
			
		||||
#include "dds__rhc.h"
 | 
			
		||||
#include "dds__topic.h"
 | 
			
		||||
#include "dds__get_status.h"
 | 
			
		||||
#include "dds/ddsi/q_entity.h"
 | 
			
		||||
#include "dds/ddsi/q_thread.h"
 | 
			
		||||
#include "dds/ddsi/q_globals.h"
 | 
			
		||||
#include "dds__builtin.h"
 | 
			
		||||
#include "dds/ddsi/ddsi_sertopic.h"
 | 
			
		||||
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_reader)
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_reader)
 | 
			
		||||
 | 
			
		||||
#define DDS_READER_STATUS_MASK                                   \
 | 
			
		||||
                        DDS_SAMPLE_REJECTED_STATUS              |\
 | 
			
		||||
                        DDS_LIVELINESS_CHANGED_STATUS           |\
 | 
			
		||||
                        DDS_REQUESTED_DEADLINE_MISSED_STATUS    |\
 | 
			
		||||
                        DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS   |\
 | 
			
		||||
                        DDS_DATA_AVAILABLE_STATUS               |\
 | 
			
		||||
                        DDS_SAMPLE_LOST_STATUS                  |\
 | 
			
		||||
                        DDS_SUBSCRIPTION_MATCHED_STATUS
 | 
			
		||||
                        (DDS_SAMPLE_REJECTED_STATUS              |\
 | 
			
		||||
                         DDS_LIVELINESS_CHANGED_STATUS           |\
 | 
			
		||||
                         DDS_REQUESTED_DEADLINE_MISSED_STATUS    |\
 | 
			
		||||
                         DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS   |\
 | 
			
		||||
                         DDS_DATA_AVAILABLE_STATUS               |\
 | 
			
		||||
                         DDS_SAMPLE_LOST_STATUS                  |\
 | 
			
		||||
                         DDS_SUBSCRIPTION_MATCHED_STATUS)
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_reader_instance_hdl(
 | 
			
		||||
        dds_entity *e,
 | 
			
		||||
        dds_instance_handle_t *i)
 | 
			
		||||
static dds_return_t dds_reader_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_reader_instance_hdl (dds_entity *e, dds_instance_handle_t *i)
 | 
			
		||||
{
 | 
			
		||||
    assert(e);
 | 
			
		||||
    assert(i);
 | 
			
		||||
    *i = (dds_instance_handle_t)reader_instance_id(&e->m_guid);
 | 
			
		||||
    return DDS_RETCODE_OK;
 | 
			
		||||
  *i = reader_instance_id (&e->m_guid);
 | 
			
		||||
  return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_reader_close(
 | 
			
		||||
        dds_entity *e)
 | 
			
		||||
static dds_return_t dds_reader_close (dds_entity *e) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_reader_close (dds_entity *e)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
  dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
  thread_state_awake (lookup_thread_state ());
 | 
			
		||||
  if (delete_reader (&e->m_guid) != 0)
 | 
			
		||||
    ret = DDS_RETCODE_ERROR;
 | 
			
		||||
  thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    assert(e);
 | 
			
		||||
static dds_return_t dds_reader_delete (dds_entity *e) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
    thread_state_awake (lookup_thread_state ());
 | 
			
		||||
    if (delete_reader(&e->m_guid) != 0) {
 | 
			
		||||
        DDS_ERROR("Internal error");
 | 
			
		||||
        ret = DDS_RETCODE_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
    thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
static dds_return_t dds_reader_delete (dds_entity *e)
 | 
			
		||||
{
 | 
			
		||||
  dds_reader * const rd = (dds_reader *) e;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  if ((ret = dds_delete (rd->m_topic->m_entity.m_hdllink.hdl)) == DDS_RETCODE_OK)
 | 
			
		||||
  {
 | 
			
		||||
    /* Delete an implicitly created parent; for normal ones, this is expected
 | 
			
		||||
       to fail with BAD_PARAMETER - FIXME: there must be a cleaner way */
 | 
			
		||||
    ret = dds_delete_impl (e->m_parent->m_hdllink.hdl, true);
 | 
			
		||||
    if (ret == DDS_RETCODE_BAD_PARAMETER)
 | 
			
		||||
      ret = DDS_RETCODE_OK;
 | 
			
		||||
  }
 | 
			
		||||
  dds_free (rd->m_loan);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_reader_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_reader_qos_validate (const dds_qos_t *qos, bool enabled)
 | 
			
		||||
{
 | 
			
		||||
  if (!dds_qos_validate_common (qos))
 | 
			
		||||
    return DDS_RETCODE_ERROR;
 | 
			
		||||
  if ((qos->present & QP_USER_DATA) && !validate_octetseq (&qos->user_data))
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_PRISMTECH_READER_DATA_LIFECYCLE) && validate_reader_data_lifecycle (&qos->reader_data_lifecycle) < 0)
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_TIME_BASED_FILTER) && validate_duration (&qos->time_based_filter.minimum_separation) < 0)
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits (&qos->history, &qos->resource_limits) < 0)
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_TIME_BASED_FILTER) && (qos->present & QP_DEADLINE) && !validate_deadline_and_timebased_filter (qos->deadline.deadline, qos->time_based_filter.minimum_separation))
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  return (enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_reader_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_reader_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
 | 
			
		||||
{
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  (void) e;
 | 
			
		||||
  if ((ret = dds_reader_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
  /* FIXME: QoS changes. */
 | 
			
		||||
  return (enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_reader_delete(
 | 
			
		||||
        dds_entity *e)
 | 
			
		||||
static dds_return_t dds_reader_status_validate (uint32_t mask)
 | 
			
		||||
{
 | 
			
		||||
    dds_reader *rd = (dds_reader*)e;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
    assert(e);
 | 
			
		||||
    ret = dds_delete(rd->m_topic->m_entity.m_hdllink.hdl);
 | 
			
		||||
    if(ret == DDS_RETCODE_OK){
 | 
			
		||||
        ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true);
 | 
			
		||||
        if(ret == DDS_RETCODE_BAD_PARAMETER){
 | 
			
		||||
            ret = DDS_RETCODE_OK;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    dds_free(rd->m_loan);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_reader_qos_validate(
 | 
			
		||||
        const dds_qos_t *qos,
 | 
			
		||||
        bool enabled)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
 | 
			
		||||
    assert(qos);
 | 
			
		||||
 | 
			
		||||
    /* Check consistency. */
 | 
			
		||||
    if(!dds_qos_validate_common(qos)) {
 | 
			
		||||
        DDS_ERROR("Argument Qos is not valid\n");
 | 
			
		||||
        ret = DDS_RETCODE_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
    if((qos->present & QP_USER_DATA) && !(validate_octetseq (&qos->user_data))) {
 | 
			
		||||
        DDS_ERROR("User data policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if((qos->present & QP_PRISMTECH_READER_DATA_LIFECYCLE) && (validate_reader_data_lifecycle (&qos->reader_data_lifecycle) != 0)) {
 | 
			
		||||
        DDS_ERROR("Prismtech reader data lifecycle policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if((qos->present & QP_TIME_BASED_FILTER) && (validate_duration (&qos->time_based_filter.minimum_separation) != 0)) {
 | 
			
		||||
        DDS_ERROR("Time based filter policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits (&qos->history, &qos->resource_limits) != 0)) {
 | 
			
		||||
        DDS_ERROR("History and resource limits policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if((qos->present & QP_TIME_BASED_FILTER) && (qos->present & QP_DEADLINE) && !(validate_deadline_and_timebased_filter (qos->deadline.deadline, qos->time_based_filter.minimum_separation))) {
 | 
			
		||||
        DDS_ERROR("Time based filter and deadline policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if(ret == DDS_RETCODE_OK && enabled) {
 | 
			
		||||
        ret = dds_qos_validate_mutable_common(qos);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_reader_qos_set(
 | 
			
		||||
        dds_entity *e,
 | 
			
		||||
        const dds_qos_t *qos,
 | 
			
		||||
        bool enabled)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = dds_reader_qos_validate(qos, enabled);
 | 
			
		||||
    (void)e;
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        if (enabled) {
 | 
			
		||||
            /* TODO: CHAM-95: DDSI does not support changing QoS policies. */
 | 
			
		||||
            DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies\n");
 | 
			
		||||
            ret = DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_reader_status_validate(
 | 
			
		||||
        uint32_t mask)
 | 
			
		||||
{
 | 
			
		||||
    return (mask & ~(DDS_READER_STATUS_MASK)) ?
 | 
			
		||||
                     DDS_RETCODE_BAD_PARAMETER :
 | 
			
		||||
                     DDS_RETCODE_OK;
 | 
			
		||||
  return (mask & ~DDS_READER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dds_reader_data_available_cb (struct dds_reader *rd)
 | 
			
		||||
| 
						 | 
				
			
			@ -349,170 +311,157 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data)
 | 
			
		|||
  ddsrt_mutex_unlock (&entity->m_observers_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_entity_t
 | 
			
		||||
dds_create_reader(
 | 
			
		||||
    dds_entity_t participant_or_subscriber,
 | 
			
		||||
    dds_entity_t topic,
 | 
			
		||||
    const dds_qos_t *qos,
 | 
			
		||||
    const dds_listener_t *listener)
 | 
			
		||||
dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_entity_t topic, const dds_qos_t *qos, const dds_listener_t *listener)
 | 
			
		||||
{
 | 
			
		||||
    dds_qos_t * rqos;
 | 
			
		||||
    dds_subscriber * sub = NULL;
 | 
			
		||||
    dds_entity_t subscriber;
 | 
			
		||||
    dds_reader * rd;
 | 
			
		||||
    struct rhc * rhc;
 | 
			
		||||
    dds_topic * tp;
 | 
			
		||||
    dds_entity_t reader;
 | 
			
		||||
    dds_entity_t t;
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
    bool internal_topic;
 | 
			
		||||
  dds_qos_t *rqos;
 | 
			
		||||
  dds_subscriber *sub = NULL;
 | 
			
		||||
  dds_entity_t subscriber;
 | 
			
		||||
  dds_reader *rd;
 | 
			
		||||
  struct rhc *rhc;
 | 
			
		||||
  dds_topic *tp;
 | 
			
		||||
  dds_entity_t reader;
 | 
			
		||||
  dds_entity_t t;
 | 
			
		||||
  dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
  bool internal_topic;
 | 
			
		||||
 | 
			
		||||
    switch (topic) {
 | 
			
		||||
        case DDS_BUILTIN_TOPIC_DCPSPARTICIPANT:
 | 
			
		||||
        case DDS_BUILTIN_TOPIC_DCPSTOPIC:
 | 
			
		||||
        case DDS_BUILTIN_TOPIC_DCPSPUBLICATION:
 | 
			
		||||
        case DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION:
 | 
			
		||||
            internal_topic = true;
 | 
			
		||||
            subscriber = dds__get_builtin_subscriber(participant_or_subscriber);
 | 
			
		||||
            t = dds__get_builtin_topic (subscriber, topic);
 | 
			
		||||
            break;
 | 
			
		||||
  switch (topic)
 | 
			
		||||
  {
 | 
			
		||||
    case DDS_BUILTIN_TOPIC_DCPSPARTICIPANT:
 | 
			
		||||
    case DDS_BUILTIN_TOPIC_DCPSTOPIC:
 | 
			
		||||
    case DDS_BUILTIN_TOPIC_DCPSPUBLICATION:
 | 
			
		||||
    case DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION:
 | 
			
		||||
      internal_topic = true;
 | 
			
		||||
      subscriber = dds__get_builtin_subscriber (participant_or_subscriber);
 | 
			
		||||
      t = dds__get_builtin_topic (subscriber, topic);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
        default: {
 | 
			
		||||
            dds_entity *p_or_s;
 | 
			
		||||
            if ((ret = dds_entity_claim (participant_or_subscriber, &p_or_s)) != DDS_RETCODE_OK) {
 | 
			
		||||
                return ret;
 | 
			
		||||
            }
 | 
			
		||||
            if (dds_entity_kind (p_or_s) == DDS_KIND_PARTICIPANT) {
 | 
			
		||||
                subscriber = dds_create_subscriber(participant_or_subscriber, qos, NULL);
 | 
			
		||||
            } else {
 | 
			
		||||
                subscriber = participant_or_subscriber;
 | 
			
		||||
            }
 | 
			
		||||
            dds_entity_release (p_or_s);
 | 
			
		||||
            internal_topic = false;
 | 
			
		||||
            t = topic;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    default: {
 | 
			
		||||
      dds_entity *p_or_s;
 | 
			
		||||
      if ((ret = dds_entity_claim (participant_or_subscriber, &p_or_s)) != DDS_RETCODE_OK)
 | 
			
		||||
        return ret;
 | 
			
		||||
      if (dds_entity_kind (p_or_s) == DDS_KIND_PARTICIPANT)
 | 
			
		||||
        subscriber = dds_create_subscriber (participant_or_subscriber, qos, NULL);
 | 
			
		||||
      else
 | 
			
		||||
        subscriber = participant_or_subscriber;
 | 
			
		||||
      dds_entity_release (p_or_s);
 | 
			
		||||
      internal_topic = false;
 | 
			
		||||
      t = topic;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK) {
 | 
			
		||||
        reader = ret;
 | 
			
		||||
        goto err_sub_lock;
 | 
			
		||||
    }
 | 
			
		||||
  if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK)
 | 
			
		||||
  {
 | 
			
		||||
    reader = ret;
 | 
			
		||||
    goto err_sub_lock;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    if ((subscriber != participant_or_subscriber) && !internal_topic) {
 | 
			
		||||
        /* Delete implicit subscriber if reader creation fails */
 | 
			
		||||
        sub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT;
 | 
			
		||||
    }
 | 
			
		||||
  if (subscriber != participant_or_subscriber && !internal_topic)
 | 
			
		||||
  {
 | 
			
		||||
    /* Delete implicit subscriber if reader creation fails */
 | 
			
		||||
    sub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    ret = dds_topic_lock(t, &tp);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking topic\n");
 | 
			
		||||
        reader = ret;
 | 
			
		||||
        goto err_tp_lock;
 | 
			
		||||
    }
 | 
			
		||||
    assert (tp->m_stopic);
 | 
			
		||||
    assert (sub->m_entity.m_domain == tp->m_entity.m_domain);
 | 
			
		||||
  if ((ret = dds_topic_lock (t, &tp)) != DDS_RETCODE_OK)
 | 
			
		||||
  {
 | 
			
		||||
    reader = ret;
 | 
			
		||||
    goto err_tp_lock;
 | 
			
		||||
  }
 | 
			
		||||
  assert (tp->m_stopic);
 | 
			
		||||
  assert (sub->m_entity.m_domain == tp->m_entity.m_domain);
 | 
			
		||||
 | 
			
		||||
    /* Merge qos from topic and subscriber */
 | 
			
		||||
    rqos = dds_create_qos ();
 | 
			
		||||
    if (qos) {
 | 
			
		||||
        /* Only returns failure when one of the qos args is NULL, which
 | 
			
		||||
         * is not the case here. */
 | 
			
		||||
        (void)dds_copy_qos(rqos, qos);
 | 
			
		||||
    }
 | 
			
		||||
  /* Merge qos from topic and subscriber, dds_copy_qos only fails when it is passed a null
 | 
			
		||||
     argument, but that isn't the case here */
 | 
			
		||||
  rqos = dds_create_qos ();
 | 
			
		||||
  if (qos)
 | 
			
		||||
    (void) dds_copy_qos (rqos, qos);
 | 
			
		||||
 | 
			
		||||
    if(sub->m_entity.m_qos){
 | 
			
		||||
        dds_merge_qos (rqos, sub->m_entity.m_qos);
 | 
			
		||||
    }
 | 
			
		||||
  if (sub->m_entity.m_qos)
 | 
			
		||||
    dds_merge_qos (rqos, sub->m_entity.m_qos);
 | 
			
		||||
 | 
			
		||||
    if (tp->m_entity.m_qos) {
 | 
			
		||||
        dds_merge_qos (rqos, tp->m_entity.m_qos);
 | 
			
		||||
  if (tp->m_entity.m_qos)
 | 
			
		||||
  {
 | 
			
		||||
    dds_merge_qos (rqos, tp->m_entity.m_qos);
 | 
			
		||||
    /* reset the following qos policies if set during topic qos merge as they aren't applicable for reader */
 | 
			
		||||
    rqos->present &= ~(QP_DURABILITY_SERVICE | QP_TRANSPORT_PRIORITY | QP_LIFESPAN);
 | 
			
		||||
  }
 | 
			
		||||
  nn_xqos_mergein_missing (rqos, &gv.default_xqos_rd);
 | 
			
		||||
 | 
			
		||||
        /* reset the following qos policies if set during topic qos merge as they aren't applicable for reader */
 | 
			
		||||
        rqos->present &= ~(QP_DURABILITY_SERVICE | QP_TRANSPORT_PRIORITY | QP_LIFESPAN);
 | 
			
		||||
    }
 | 
			
		||||
    nn_xqos_mergein_missing (rqos, &gv.default_xqos_rd);
 | 
			
		||||
  if ((ret = dds_reader_qos_validate (rqos, false)) != DDS_RETCODE_OK)
 | 
			
		||||
  {
 | 
			
		||||
    dds_delete_qos (rqos);
 | 
			
		||||
    reader = ret;
 | 
			
		||||
    goto err_bad_qos;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    ret = dds_reader_qos_validate (rqos, false);
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        dds_delete_qos(rqos);
 | 
			
		||||
        reader = ret;
 | 
			
		||||
        goto err_bad_qos;
 | 
			
		||||
    }
 | 
			
		||||
  /* Additional checks required for built-in topics: we don't want to
 | 
			
		||||
     run into a resource limit on a built-in topic, it is a needless
 | 
			
		||||
     complication */
 | 
			
		||||
  if (internal_topic && !dds__validate_builtin_reader_qos (topic, qos))
 | 
			
		||||
  {
 | 
			
		||||
    dds_delete_qos (rqos);
 | 
			
		||||
    reader = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    goto err_bad_qos;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    /* Additional checks required for built-in topics */
 | 
			
		||||
    if (internal_topic && !dds__validate_builtin_reader_qos(topic, qos)) {
 | 
			
		||||
        dds_delete_qos(rqos);
 | 
			
		||||
        DDS_ERROR("Invalid QoS specified for built-in topic reader");
 | 
			
		||||
        reader = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
        goto err_bad_qos;
 | 
			
		||||
    }
 | 
			
		||||
  /* Create reader and associated read cache */
 | 
			
		||||
  rd = dds_alloc (sizeof (*rd));
 | 
			
		||||
  reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, rqos, listener, DDS_READER_STATUS_MASK);
 | 
			
		||||
  rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED;
 | 
			
		||||
  rd->m_topic = tp;
 | 
			
		||||
  rhc = dds_rhc_new (rd, tp->m_stopic);
 | 
			
		||||
  dds_entity_add_ref_nolock (&tp->m_entity);
 | 
			
		||||
  rd->m_entity.m_deriver.close = dds_reader_close;
 | 
			
		||||
  rd->m_entity.m_deriver.delete = dds_reader_delete;
 | 
			
		||||
  rd->m_entity.m_deriver.set_qos = dds_reader_qos_set;
 | 
			
		||||
  rd->m_entity.m_deriver.validate_status = dds_reader_status_validate;
 | 
			
		||||
  rd->m_entity.m_deriver.get_instance_hdl = dds_reader_instance_hdl;
 | 
			
		||||
 | 
			
		||||
    /* Create reader and associated read cache */
 | 
			
		||||
    rd = dds_alloc (sizeof (*rd));
 | 
			
		||||
    reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, rqos, listener, DDS_READER_STATUS_MASK);
 | 
			
		||||
    rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED;
 | 
			
		||||
    rd->m_topic = tp;
 | 
			
		||||
    rhc = dds_rhc_new (rd, tp->m_stopic);
 | 
			
		||||
    dds_entity_add_ref_nolock (&tp->m_entity);
 | 
			
		||||
    rd->m_entity.m_deriver.close = dds_reader_close;
 | 
			
		||||
    rd->m_entity.m_deriver.delete = dds_reader_delete;
 | 
			
		||||
    rd->m_entity.m_deriver.set_qos = dds_reader_qos_set;
 | 
			
		||||
    rd->m_entity.m_deriver.validate_status = dds_reader_status_validate;
 | 
			
		||||
    rd->m_entity.m_deriver.get_instance_hdl = dds_reader_instance_hdl;
 | 
			
		||||
  /* Extra claim of this reader to make sure that the delete waits until DDSI
 | 
			
		||||
     has deleted its reader as well. This can be known through the callback. */
 | 
			
		||||
  dds_handle_claim_inc (&rd->m_entity.m_hdllink);
 | 
			
		||||
 | 
			
		||||
    /* Extra claim of this reader to make sure that the delete waits until DDSI
 | 
			
		||||
     * has deleted its reader as well. This can be known through the callback. */
 | 
			
		||||
    dds_handle_claim_inc (&rd->m_entity.m_hdllink);
 | 
			
		||||
  ddsrt_mutex_unlock (&tp->m_entity.m_mutex);
 | 
			
		||||
  ddsrt_mutex_unlock (&sub->m_entity.m_mutex);
 | 
			
		||||
 | 
			
		||||
    ddsrt_mutex_unlock(&tp->m_entity.m_mutex);
 | 
			
		||||
    ddsrt_mutex_unlock(&sub->m_entity.m_mutex);
 | 
			
		||||
  thread_state_awake (lookup_thread_state ());
 | 
			
		||||
  ret = new_reader (&rd->m_rd, &rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, rqos, rhc, dds_reader_status_cb, rd);
 | 
			
		||||
  ddsrt_mutex_lock (&sub->m_entity.m_mutex);
 | 
			
		||||
  ddsrt_mutex_lock (&tp->m_entity.m_mutex);
 | 
			
		||||
  assert (ret == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */
 | 
			
		||||
  thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
 | 
			
		||||
    thread_state_awake (lookup_thread_state ());
 | 
			
		||||
    ret = new_reader(&rd->m_rd, &rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic,
 | 
			
		||||
                     rqos, rhc, dds_reader_status_cb, rd);
 | 
			
		||||
    ddsrt_mutex_lock(&sub->m_entity.m_mutex);
 | 
			
		||||
    ddsrt_mutex_lock(&tp->m_entity.m_mutex);
 | 
			
		||||
    assert (ret == DDS_RETCODE_OK);
 | 
			
		||||
    thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
  /* For persistent data register reader with durability */
 | 
			
		||||
  if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > NN_TRANSIENT_LOCAL_DURABILITY_QOS)) {
 | 
			
		||||
    (dds_global.m_dur_reader) (rd, rhc);
 | 
			
		||||
  }
 | 
			
		||||
  dds_topic_unlock (tp);
 | 
			
		||||
  dds_subscriber_unlock (sub);
 | 
			
		||||
 | 
			
		||||
    /* For persistent data register reader with durability */
 | 
			
		||||
    if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > NN_TRANSIENT_LOCAL_DURABILITY_QOS)) {
 | 
			
		||||
        (dds_global.m_dur_reader) (rd, rhc);
 | 
			
		||||
    }
 | 
			
		||||
    dds_topic_unlock(tp);
 | 
			
		||||
    dds_subscriber_unlock(sub);
 | 
			
		||||
 | 
			
		||||
    if (internal_topic) {
 | 
			
		||||
        /* If topic is builtin, then the topic entity is local and should
 | 
			
		||||
         * be deleted because the application won't. */
 | 
			
		||||
        dds_delete(t);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return reader;
 | 
			
		||||
  if (internal_topic)
 | 
			
		||||
  {
 | 
			
		||||
    /* If topic is builtin, then the topic entity is local and should be deleted because the application won't. */
 | 
			
		||||
    dds_delete (t);
 | 
			
		||||
  }
 | 
			
		||||
  return reader;
 | 
			
		||||
 | 
			
		||||
err_bad_qos:
 | 
			
		||||
    dds_topic_unlock(tp);
 | 
			
		||||
  dds_topic_unlock (tp);
 | 
			
		||||
err_tp_lock:
 | 
			
		||||
    dds_subscriber_unlock(sub);
 | 
			
		||||
    if((sub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){
 | 
			
		||||
        (void)dds_delete(subscriber);
 | 
			
		||||
    }
 | 
			
		||||
  dds_subscriber_unlock (sub);
 | 
			
		||||
  if ((sub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0)
 | 
			
		||||
    (void) dds_delete (subscriber);
 | 
			
		||||
err_sub_lock:
 | 
			
		||||
    if (internal_topic) {
 | 
			
		||||
        /* If topic is builtin, then the topic entity is local and should
 | 
			
		||||
         * be deleted because the application won't. */
 | 
			
		||||
        dds_delete(t);
 | 
			
		||||
    }
 | 
			
		||||
    return reader;
 | 
			
		||||
  if (internal_topic)
 | 
			
		||||
    dds_delete (t);
 | 
			
		||||
  return reader;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb, void *cbarg)
 | 
			
		||||
{
 | 
			
		||||
  dds_entity *dds_entity;
 | 
			
		||||
  if (dds_entity_claim(entity, &dds_entity) != DDS_RETCODE_OK)
 | 
			
		||||
  if (dds_entity_claim (entity, &dds_entity) != DDS_RETCODE_OK)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (dds_entity_kind (dds_entity) != DDS_KIND_READER)
 | 
			
		||||
  {
 | 
			
		||||
    dds_entity_release (dds_entity);
 | 
			
		||||
| 
						 | 
				
			
			@ -532,7 +481,7 @@ void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb
 | 
			
		|||
  while ((m = ddsrt_avl_lookup_succ_eq (&rd_writers_treedef, &rd->writers, &pwrguid)) != NULL)
 | 
			
		||||
  {
 | 
			
		||||
    /* have to be careful walking the tree -- pretty is different, but
 | 
			
		||||
     I want to check this before I write a lookup_succ function. */
 | 
			
		||||
       I want to check this before I write a lookup_succ function. */
 | 
			
		||||
    struct rd_pwr_match *m_next;
 | 
			
		||||
    nn_guid_t pwrguid_next;
 | 
			
		||||
    pwrguid = m->pwr_guid;
 | 
			
		||||
| 
						 | 
				
			
			@ -621,169 +570,12 @@ dds_entity_t dds_get_subscriber (dds_entity_t entity)
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_get_subscription_matched_status (
 | 
			
		||||
    dds_entity_t reader,
 | 
			
		||||
    dds_subscription_matched_status_t * status)
 | 
			
		||||
{
 | 
			
		||||
    dds_reader *rd;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
/* Reset sets everything (type) 0, including the reason field, verify that 0 is correct */
 | 
			
		||||
DDSRT_STATIC_ASSERT ((int) DDS_NOT_REJECTED == 0);
 | 
			
		||||
 | 
			
		||||
    ret = dds_reader_lock(reader, &rd);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking reader\n");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    /* status = NULL, application do not need the status, but reset the counter & triggered bit */
 | 
			
		||||
    if (status) {
 | 
			
		||||
        *status = rd->m_subscription_matched_status;
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
 | 
			
		||||
    if (rd->m_entity.m_status_enable & DDS_SUBSCRIPTION_MATCHED_STATUS) {
 | 
			
		||||
        rd->m_subscription_matched_status.total_count_change = 0;
 | 
			
		||||
        rd->m_subscription_matched_status.current_count_change = 0;
 | 
			
		||||
        dds_entity_status_reset(&rd->m_entity, DDS_SUBSCRIPTION_MATCHED_STATUS);
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
 | 
			
		||||
    dds_reader_unlock(rd);
 | 
			
		||||
fail:
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_get_liveliness_changed_status (
 | 
			
		||||
    dds_entity_t reader,
 | 
			
		||||
    dds_liveliness_changed_status_t * status)
 | 
			
		||||
{
 | 
			
		||||
    dds_reader *rd;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_reader_lock(reader, &rd);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking reader\n");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    /* status = NULL, application do not need the status, but reset the counter & triggered bit */
 | 
			
		||||
    if (status) {
 | 
			
		||||
        *status = rd->m_liveliness_changed_status;
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
 | 
			
		||||
    if (rd->m_entity.m_status_enable & DDS_LIVELINESS_CHANGED_STATUS) {
 | 
			
		||||
        rd->m_liveliness_changed_status.alive_count_change = 0;
 | 
			
		||||
        rd->m_liveliness_changed_status.not_alive_count_change = 0;
 | 
			
		||||
        dds_entity_status_reset(&rd->m_entity, DDS_LIVELINESS_CHANGED_STATUS);
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
 | 
			
		||||
    dds_reader_unlock(rd);
 | 
			
		||||
fail:
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t dds_get_sample_rejected_status (
 | 
			
		||||
    dds_entity_t reader,
 | 
			
		||||
    dds_sample_rejected_status_t * status)
 | 
			
		||||
{
 | 
			
		||||
    dds_reader *rd;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_reader_lock(reader, &rd);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking reader\n");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    /* status = NULL, application do not need the status, but reset the counter & triggered bit */
 | 
			
		||||
    if (status) {
 | 
			
		||||
        *status = rd->m_sample_rejected_status;
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
 | 
			
		||||
    if (rd->m_entity.m_status_enable & DDS_SAMPLE_REJECTED_STATUS) {
 | 
			
		||||
        rd->m_sample_rejected_status.total_count_change = 0;
 | 
			
		||||
        rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED;
 | 
			
		||||
        dds_entity_status_reset(&rd->m_entity, DDS_SAMPLE_REJECTED_STATUS);
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
 | 
			
		||||
    dds_reader_unlock(rd);
 | 
			
		||||
fail:
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t dds_get_sample_lost_status (
 | 
			
		||||
    dds_entity_t reader,
 | 
			
		||||
    dds_sample_lost_status_t * status)
 | 
			
		||||
{
 | 
			
		||||
    dds_reader *rd;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_reader_lock(reader, &rd);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking reader\n");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    /* status = NULL, application do not need the status, but reset the counter & triggered bit */
 | 
			
		||||
    if (status) {
 | 
			
		||||
        *status = rd->m_sample_lost_status;
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
 | 
			
		||||
    if (rd->m_entity.m_status_enable & DDS_SAMPLE_LOST_STATUS) {
 | 
			
		||||
        rd->m_sample_lost_status.total_count_change = 0;
 | 
			
		||||
        dds_entity_status_reset(&rd->m_entity, DDS_SAMPLE_LOST_STATUS);
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
 | 
			
		||||
    dds_reader_unlock(rd);
 | 
			
		||||
fail:
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t dds_get_requested_deadline_missed_status (
 | 
			
		||||
    dds_entity_t reader,
 | 
			
		||||
    dds_requested_deadline_missed_status_t * status)
 | 
			
		||||
{
 | 
			
		||||
    dds_reader *rd;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_reader_lock(reader, &rd);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking reader\n");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    /* status = NULL, application do not need the status, but reset the counter & triggered bit */
 | 
			
		||||
    if (status) {
 | 
			
		||||
        *status = rd->m_requested_deadline_missed_status;
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
 | 
			
		||||
    if (rd->m_entity.m_status_enable & DDS_REQUESTED_DEADLINE_MISSED_STATUS) {
 | 
			
		||||
        rd->m_requested_deadline_missed_status.total_count_change = 0;
 | 
			
		||||
        dds_entity_status_reset(&rd->m_entity, DDS_REQUESTED_DEADLINE_MISSED_STATUS);
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
 | 
			
		||||
    dds_reader_unlock(rd);
 | 
			
		||||
fail:
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t dds_get_requested_incompatible_qos_status (
 | 
			
		||||
    dds_entity_t reader,
 | 
			
		||||
    dds_requested_incompatible_qos_status_t * status)
 | 
			
		||||
{
 | 
			
		||||
    dds_reader *rd;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_reader_lock(reader, &rd);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking reader\n");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    /* status = NULL, application do not need the status, but reset the counter & triggered bit */
 | 
			
		||||
    if (status) {
 | 
			
		||||
        *status = rd->m_requested_incompatible_qos_status;
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_lock (&rd->m_entity.m_observers_lock);
 | 
			
		||||
    if (rd->m_entity.m_status_enable & DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS) {
 | 
			
		||||
        rd->m_requested_incompatible_qos_status.total_count_change = 0;
 | 
			
		||||
        dds_entity_status_reset(&rd->m_entity, DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS);
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock);
 | 
			
		||||
    dds_reader_unlock(rd);
 | 
			
		||||
fail:
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
DDS_GET_STATUS (reader, subscription_matched,       SUBSCRIPTION_MATCHED,       total_count_change, current_count_change)
 | 
			
		||||
DDS_GET_STATUS (reader, liveliness_changed,         LIVELINESS_CHANGED,         alive_count_change, not_alive_count_change)
 | 
			
		||||
DDS_GET_STATUS (reader, sample_rejected,            SAMPLE_REJECTED,            total_count_change, last_reason)
 | 
			
		||||
DDS_GET_STATUS (reader, sample_lost,                SAMPLE_LOST,                total_count_change)
 | 
			
		||||
DDS_GET_STATUS (reader, requested_deadline_missed,  REQUESTED_DEADLINE_MISSED,  total_count_change)
 | 
			
		||||
DDS_GET_STATUS (reader, requested_incompatible_qos, REQUESTED_INCOMPATIBLE_QOS, total_count_change)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -204,9 +204,7 @@ static void dds_os_put_bytes_aligned (dds_ostream_t * __restrict s, const void *
 | 
			
		|||
 | 
			
		||||
static uint32_t get_type_size (enum dds_stream_typecode type)
 | 
			
		||||
{
 | 
			
		||||
  struct check {
 | 
			
		||||
    char x[(DDS_OP_VAL_1BY == 1 && DDS_OP_VAL_2BY == 2 && DDS_OP_VAL_4BY == 3 && DDS_OP_VAL_8BY == 4) ? 1 : -1];
 | 
			
		||||
  };
 | 
			
		||||
  DDSRT_STATIC_ASSERT (DDS_OP_VAL_1BY == 1 && DDS_OP_VAL_2BY == 2 && DDS_OP_VAL_4BY == 3 && DDS_OP_VAL_8BY == 4);
 | 
			
		||||
  assert (type == DDS_OP_VAL_1BY || type == DDS_OP_VAL_2BY || type == DDS_OP_VAL_4BY || type == DDS_OP_VAL_8BY);
 | 
			
		||||
  return (uint32_t)1 << ((uint32_t) type - 1);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,199 +11,126 @@
 | 
			
		|||
 */
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "dds__listener.h"
 | 
			
		||||
#include "dds__participant.h"
 | 
			
		||||
#include "dds__qos.h"
 | 
			
		||||
#include "dds__subscriber.h"
 | 
			
		||||
#include "dds/ddsi/q_entity.h"
 | 
			
		||||
#include "dds/version.h"
 | 
			
		||||
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_subscriber)
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_subscriber)
 | 
			
		||||
 | 
			
		||||
#define DDS_SUBSCRIBER_STATUS_MASK                               \
 | 
			
		||||
                        DDS_DATA_ON_READERS_STATUS
 | 
			
		||||
                        (DDS_DATA_ON_READERS_STATUS)
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_subscriber_instance_hdl(
 | 
			
		||||
        dds_entity *e,
 | 
			
		||||
        dds_instance_handle_t *i)
 | 
			
		||||
static dds_return_t dds_subscriber_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_subscriber_instance_hdl (dds_entity *e, dds_instance_handle_t *i)
 | 
			
		||||
{
 | 
			
		||||
    (void)e;
 | 
			
		||||
    (void)i;
 | 
			
		||||
    /* TODO: Get/generate proper handle. */
 | 
			
		||||
    DDS_ERROR("Generating subscriber instance handle is not supported");
 | 
			
		||||
    return DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
  (void) e;
 | 
			
		||||
  (void) i;
 | 
			
		||||
  /* FIXME: Get/generate proper handle. */
 | 
			
		||||
  return DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds__subscriber_qos_validate(
 | 
			
		||||
        const dds_qos_t *qos,
 | 
			
		||||
        bool enabled)
 | 
			
		||||
static dds_return_t dds__subscriber_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds__subscriber_qos_validate (const dds_qos_t *qos, bool enabled)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
  if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data))
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_PARTITION) && !validate_stringseq (&qos->partition))
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_PRESENTATION) && validate_presentation_qospolicy (&qos->presentation) < 0)
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy (&qos->entity_factory))
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  /* FIXME: Improve/check immutable check. */
 | 
			
		||||
  return (enabled && (qos->present & QP_PRESENTATION)) ? DDS_RETCODE_IMMUTABLE_POLICY : DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    assert(qos);
 | 
			
		||||
 | 
			
		||||
    if((qos->present & QP_GROUP_DATA) && !validate_octetseq(&qos->group_data)) {
 | 
			
		||||
        DDS_ERROR("Group data policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if((qos->present & QP_PARTITION) && !validate_stringseq(&qos->partition)) {
 | 
			
		||||
        DDS_ERROR("Partition policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if((qos->present & QP_PRESENTATION) && validate_presentation_qospolicy(&qos->presentation)) {
 | 
			
		||||
        DDS_ERROR("Presentation policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)) {
 | 
			
		||||
        DDS_ERROR("Prismtech entity factory policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if(ret == DDS_RETCODE_OK && enabled && (qos->present & QP_PRESENTATION)) {
 | 
			
		||||
        /* TODO: Improve/check immutable check. */
 | 
			
		||||
        DDS_ERROR("Presentation QoS policy is immutable\n");
 | 
			
		||||
        ret = DDS_RETCODE_IMMUTABLE_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
static dds_return_t dds_subscriber_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_subscriber_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
 | 
			
		||||
{
 | 
			
		||||
  /* FIXME: QoS changes. */
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  (void) e;
 | 
			
		||||
  if ((ret = dds__subscriber_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
  return (enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_subscriber_qos_set(
 | 
			
		||||
        dds_entity *e,
 | 
			
		||||
        const dds_qos_t *qos,
 | 
			
		||||
        bool enabled)
 | 
			
		||||
static dds_return_t dds_subscriber_status_validate (uint32_t mask)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = dds__subscriber_qos_validate(qos, enabled);
 | 
			
		||||
    (void)e;
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        if (enabled) {
 | 
			
		||||
            /* TODO: CHAM-95: DDSI does not support changing QoS policies. */
 | 
			
		||||
            DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies yet\n");
 | 
			
		||||
            ret = DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  return (mask & ~DDS_SUBSCRIBER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_entity_t dds__create_subscriber_l (dds_participant *participant, const dds_qos_t *qos, const dds_listener_t *listener)
 | 
			
		||||
{
 | 
			
		||||
  /* participant entity lock must be held */
 | 
			
		||||
  dds_subscriber *sub;
 | 
			
		||||
  dds_entity_t subscriber;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  dds_qos_t *new_qos;
 | 
			
		||||
 | 
			
		||||
  /* Validate qos */
 | 
			
		||||
  if (qos && (ret = dds__subscriber_qos_validate (qos, false)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  if (qos == NULL)
 | 
			
		||||
    new_qos = NULL;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    new_qos = dds_create_qos ();
 | 
			
		||||
    (void) dds_copy_qos (new_qos, qos);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  sub = dds_alloc (sizeof (*sub));
 | 
			
		||||
  subscriber = dds_entity_init (&sub->m_entity, &participant->m_entity, DDS_KIND_SUBSCRIBER, new_qos, listener, DDS_SUBSCRIBER_STATUS_MASK);
 | 
			
		||||
  sub->m_entity.m_deriver.set_qos = dds_subscriber_qos_set;
 | 
			
		||||
  sub->m_entity.m_deriver.validate_status = dds_subscriber_status_validate;
 | 
			
		||||
  sub->m_entity.m_deriver.get_instance_hdl = dds_subscriber_instance_hdl;
 | 
			
		||||
  return subscriber;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_subscriber_status_validate(
 | 
			
		||||
        uint32_t mask)
 | 
			
		||||
dds_entity_t dds_create_subscriber (dds_entity_t participant, const dds_qos_t *qos, const dds_listener_t *listener)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
 | 
			
		||||
    if (mask & ~(DDS_SUBSCRIBER_STATUS_MASK)) {
 | 
			
		||||
        DDS_ERROR("Invalid status mask\n");
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  dds_participant *par;
 | 
			
		||||
  dds_entity_t hdl;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  if ((ret = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
  hdl = dds__create_subscriber_l (par, qos, listener);
 | 
			
		||||
  dds_participant_unlock (par);
 | 
			
		||||
  return hdl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_entity_t
 | 
			
		||||
dds__create_subscriber_l(
 | 
			
		||||
        dds_entity *participant, /* entity-lock must be held */
 | 
			
		||||
        const dds_qos_t *qos,
 | 
			
		||||
        const dds_listener_t *listener)
 | 
			
		||||
dds_return_t dds_notify_readers (dds_entity_t subscriber)
 | 
			
		||||
{
 | 
			
		||||
    dds_subscriber * sub;
 | 
			
		||||
    dds_entity_t subscriber;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
    dds_qos_t * new_qos;
 | 
			
		||||
  dds_subscriber *sub;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    /* Validate qos */
 | 
			
		||||
    if (qos) {
 | 
			
		||||
        if ((ret = dds__subscriber_qos_validate(qos, false)) != DDS_RETCODE_OK) {
 | 
			
		||||
            goto err_param;
 | 
			
		||||
        }
 | 
			
		||||
        new_qos = dds_create_qos();
 | 
			
		||||
        /* Only returns failure when one of the qos args is NULL, which
 | 
			
		||||
         * is not the case here. */
 | 
			
		||||
        (void)dds_copy_qos(new_qos, qos);
 | 
			
		||||
    } else {
 | 
			
		||||
        new_qos = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Create subscriber */
 | 
			
		||||
    sub = dds_alloc(sizeof(*sub));
 | 
			
		||||
    subscriber = dds_entity_init(&sub->m_entity, participant, DDS_KIND_SUBSCRIBER, new_qos, listener, DDS_SUBSCRIBER_STATUS_MASK);
 | 
			
		||||
    sub->m_entity.m_deriver.set_qos = dds_subscriber_qos_set;
 | 
			
		||||
    sub->m_entity.m_deriver.validate_status = dds_subscriber_status_validate;
 | 
			
		||||
    sub->m_entity.m_deriver.get_instance_hdl = dds_subscriber_instance_hdl;
 | 
			
		||||
 | 
			
		||||
    return subscriber;
 | 
			
		||||
 | 
			
		||||
    /* Error handling */
 | 
			
		||||
err_param:
 | 
			
		||||
  if ((ret = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  ret = DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
  for (dds_entity *iter = sub->m_entity.m_children; iter; iter = iter->m_next)
 | 
			
		||||
  {
 | 
			
		||||
    ddsrt_mutex_lock (&iter->m_mutex);
 | 
			
		||||
    // FIXME: check if reader has data available, call listener
 | 
			
		||||
    ddsrt_mutex_unlock(&iter->m_mutex);
 | 
			
		||||
  }
 | 
			
		||||
  dds_subscriber_unlock (sub);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_entity_t
 | 
			
		||||
dds_create_subscriber(
 | 
			
		||||
        dds_entity_t participant,
 | 
			
		||||
        const dds_qos_t *qos,
 | 
			
		||||
        const dds_listener_t *listener)
 | 
			
		||||
dds_return_t dds_subscriber_begin_coherent (dds_entity_t e)
 | 
			
		||||
{
 | 
			
		||||
    dds_entity * par;
 | 
			
		||||
    dds_entity_t hdl;
 | 
			
		||||
    dds_return_t errnr;
 | 
			
		||||
 | 
			
		||||
    errnr = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par);
 | 
			
		||||
    if (errnr != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking participant\n");
 | 
			
		||||
        hdl = errnr;
 | 
			
		||||
        return hdl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hdl = dds__create_subscriber_l(par, qos, listener);
 | 
			
		||||
    dds_entity_unlock(par);
 | 
			
		||||
 | 
			
		||||
    return hdl;
 | 
			
		||||
  return dds_generic_unimplemented_operation (e, DDS_KIND_SUBSCRIBER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_notify_readers(
 | 
			
		||||
        dds_entity_t subscriber)
 | 
			
		||||
dds_return_t dds_subscriber_end_coherent (dds_entity_t e)
 | 
			
		||||
{
 | 
			
		||||
    dds_entity *iter;
 | 
			
		||||
    dds_entity *sub;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_entity_lock(subscriber, DDS_KIND_SUBSCRIBER, &sub);
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        ret = DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
        DDS_ERROR("Unsupported operation\n");
 | 
			
		||||
        iter = sub->m_children;
 | 
			
		||||
        while (iter) {
 | 
			
		||||
            ddsrt_mutex_lock(&iter->m_mutex);
 | 
			
		||||
            // TODO: check if reader has data available, call listener
 | 
			
		||||
            ddsrt_mutex_unlock(&iter->m_mutex);
 | 
			
		||||
            iter = iter->m_next;
 | 
			
		||||
        }
 | 
			
		||||
        dds_entity_unlock(sub);
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking subscriber\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_subscriber_begin_coherent(
 | 
			
		||||
        dds_entity_t e)
 | 
			
		||||
{
 | 
			
		||||
    /* TODO: CHAM-124 Currently unsupported. */
 | 
			
		||||
    (void)e;
 | 
			
		||||
    DDS_ERROR("Using coherency to get a coherent data set is not currently being supported\n");
 | 
			
		||||
    return DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_subscriber_end_coherent(
 | 
			
		||||
        dds_entity_t e)
 | 
			
		||||
{
 | 
			
		||||
    /* TODO: CHAM-124 Currently unsupported. */
 | 
			
		||||
    (void)e;
 | 
			
		||||
    DDS_ERROR("Using coherency to get a coherent data set is not currently being supported\n");
 | 
			
		||||
    return DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
  return dds_generic_unimplemented_operation (e, DDS_KIND_SUBSCRIBER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,68 +17,53 @@
 | 
			
		|||
#include "dds__topic.h"
 | 
			
		||||
#include "dds__listener.h"
 | 
			
		||||
#include "dds__qos.h"
 | 
			
		||||
#include "dds__participant.h"
 | 
			
		||||
#include "dds__stream.h"
 | 
			
		||||
#include "dds__init.h"
 | 
			
		||||
#include "dds__domain.h"
 | 
			
		||||
#include "dds__get_status.h"
 | 
			
		||||
#include "dds/ddsi/q_entity.h"
 | 
			
		||||
#include "dds/ddsi/q_thread.h"
 | 
			
		||||
#include "dds/ddsi/ddsi_sertopic.h"
 | 
			
		||||
#include "dds/ddsi/q_ddsi_discovery.h"
 | 
			
		||||
#include "dds/ddsi/ddsi_iid.h"
 | 
			
		||||
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_topic)
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_topic)
 | 
			
		||||
 | 
			
		||||
#define DDS_TOPIC_STATUS_MASK                                    \
 | 
			
		||||
                        DDS_INCONSISTENT_TOPIC_STATUS
 | 
			
		||||
                        (DDS_INCONSISTENT_TOPIC_STATUS)
 | 
			
		||||
 | 
			
		||||
const ddsrt_avl_treedef_t dds_topictree_def = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY
 | 
			
		||||
(
 | 
			
		||||
  offsetof (struct ddsi_sertopic, avlnode),
 | 
			
		||||
  offsetof (struct ddsi_sertopic, name_type_name),
 | 
			
		||||
  (int (*) (const void *, const void *)) strcmp,
 | 
			
		||||
  0
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
is_valid_name(
 | 
			
		||||
    const char *name)
 | 
			
		||||
static int strcmp_wrapper (const void *va, const void *vb)
 | 
			
		||||
{
 | 
			
		||||
    bool valid = false;
 | 
			
		||||
    /* DDS Spec:
 | 
			
		||||
     *  |  TOPICNAME - A topic name is an identifier for a topic, and is defined as any series of characters
 | 
			
		||||
     *  |     'a', ..., 'z',
 | 
			
		||||
     *  |     'A', ..., 'Z',
 | 
			
		||||
     *  |     '0', ..., '9',
 | 
			
		||||
     *  |     '-' but may not start with a digit.
 | 
			
		||||
     * It is considered that '-' is an error in the spec and should say '_'. So, that's what we'll check for.
 | 
			
		||||
     *  |     '/' got added for ROS2
 | 
			
		||||
     */
 | 
			
		||||
    assert(name);
 | 
			
		||||
    if ((name[0] != '\0') && (!isdigit((unsigned char)name[0]))) {
 | 
			
		||||
        while (isalnum((unsigned char)*name) || (*name == '_') || (*name == '/')) {
 | 
			
		||||
            name++;
 | 
			
		||||
        }
 | 
			
		||||
        if (*name == '\0') {
 | 
			
		||||
            valid = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
   return valid;
 | 
			
		||||
  return strcmp (va, vb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ddsrt_avl_treedef_t dds_topictree_def = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct ddsi_sertopic, avlnode), offsetof (struct ddsi_sertopic, name_type_name), strcmp_wrapper, 0);
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_topic_status_validate(
 | 
			
		||||
    uint32_t mask)
 | 
			
		||||
static bool is_valid_name (const char *name) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static bool is_valid_name (const char *name)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
  /* DDS Spec:
 | 
			
		||||
   *  |  TOPICNAME - A topic name is an identifier for a topic, and is defined as any series of characters
 | 
			
		||||
   *  |     'a', ..., 'z',
 | 
			
		||||
   *  |     'A', ..., 'Z',
 | 
			
		||||
   *  |     '0', ..., '9',
 | 
			
		||||
   *  |     '-' but may not start with a digit.
 | 
			
		||||
   * It is considered that '-' is an error in the spec and should say '_'. So, that's what we'll check for.
 | 
			
		||||
   *  |     '/' got added for ROS2
 | 
			
		||||
   */
 | 
			
		||||
  if (name[0] == '\0' || isdigit ((unsigned char) name[0]))
 | 
			
		||||
    return false;
 | 
			
		||||
  for (size_t i = 0; name[i]; i++)
 | 
			
		||||
    if (!(isalnum ((unsigned char) name[i]) || name[i] == '_' || name[i] == '/'))
 | 
			
		||||
      return false;
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    if (mask & ~(DDS_TOPIC_STATUS_MASK)) {
 | 
			
		||||
        DDS_ERROR("Argument mask is invalid\n");
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
static dds_return_t dds_topic_status_validate (uint32_t mask)
 | 
			
		||||
{
 | 
			
		||||
  return (mask & ~DDS_TOPIC_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -100,191 +85,135 @@ static void dds_topic_status_cb (struct dds_topic *tp)
 | 
			
		|||
  if (lst->on_inconsistent_topic)
 | 
			
		||||
  {
 | 
			
		||||
    ddsrt_mutex_unlock (&tp->m_entity.m_observers_lock);
 | 
			
		||||
    dds_entity_invoke_listener(&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS_ID, &tp->m_inconsistent_topic_status);
 | 
			
		||||
    dds_entity_invoke_listener (&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS_ID, &tp->m_inconsistent_topic_status);
 | 
			
		||||
    ddsrt_mutex_lock (&tp->m_entity.m_observers_lock);
 | 
			
		||||
    tp->m_inconsistent_topic_status.total_count_change = 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  dds_entity_status_set(&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS);
 | 
			
		||||
  dds_entity_status_set (&tp->m_entity, DDS_INCONSISTENT_TOPIC_STATUS);
 | 
			
		||||
  tp->m_entity.m_cb_count--;
 | 
			
		||||
  ddsrt_cond_broadcast (&tp->m_entity.m_observers_cond);
 | 
			
		||||
  ddsrt_mutex_unlock (&tp->m_entity.m_observers_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct ddsi_sertopic *
 | 
			
		||||
dds_topic_lookup_locked(
 | 
			
		||||
        dds_domain *domain,
 | 
			
		||||
        const char *name)
 | 
			
		||||
struct ddsi_sertopic *dds_topic_lookup_locked (dds_domain *domain, const char *name) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
struct ddsi_sertopic *dds_topic_lookup_locked (dds_domain *domain, const char *name)
 | 
			
		||||
{
 | 
			
		||||
    struct ddsi_sertopic *st = NULL;
 | 
			
		||||
    ddsrt_avl_iter_t iter;
 | 
			
		||||
 | 
			
		||||
    assert (domain);
 | 
			
		||||
    assert (name);
 | 
			
		||||
 | 
			
		||||
    st = ddsrt_avl_iter_first (&dds_topictree_def, &domain->m_topics, &iter);
 | 
			
		||||
    while (st) {
 | 
			
		||||
        if (strcmp (st->name, name) == 0) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        st = ddsrt_avl_iter_next (&iter);
 | 
			
		||||
    }
 | 
			
		||||
    return st;
 | 
			
		||||
  ddsrt_avl_iter_t iter;
 | 
			
		||||
  for (struct ddsi_sertopic *st = ddsrt_avl_iter_first (&dds_topictree_def, &domain->m_topics, &iter); st; st = ddsrt_avl_iter_next (&iter))
 | 
			
		||||
    if (strcmp (st->name, name) == 0)
 | 
			
		||||
      return st;
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct ddsi_sertopic *
 | 
			
		||||
dds_topic_lookup(
 | 
			
		||||
        dds_domain *domain,
 | 
			
		||||
        const char *name)
 | 
			
		||||
struct ddsi_sertopic *dds_topic_lookup (dds_domain *domain, const char *name)
 | 
			
		||||
{
 | 
			
		||||
    struct ddsi_sertopic *st;
 | 
			
		||||
    ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
    st = dds_topic_lookup_locked(domain, name);
 | 
			
		||||
    ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
    return st;
 | 
			
		||||
  struct ddsi_sertopic *st;
 | 
			
		||||
  ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
  st = dds_topic_lookup_locked (domain, name);
 | 
			
		||||
  ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
  return st;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_topic_free(
 | 
			
		||||
        dds_domainid_t domainid,
 | 
			
		||||
        struct ddsi_sertopic *st)
 | 
			
		||||
void dds_topic_free (dds_domainid_t domainid, struct ddsi_sertopic *st)
 | 
			
		||||
{
 | 
			
		||||
    dds_domain *domain;
 | 
			
		||||
 | 
			
		||||
    assert (st);
 | 
			
		||||
 | 
			
		||||
    ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
    domain = ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &domainid);
 | 
			
		||||
    if (domain != NULL) {
 | 
			
		||||
        ddsrt_avl_delete (&dds_topictree_def, &domain->m_topics, st);
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
    st->status_cb_entity = NULL;
 | 
			
		||||
    ddsi_sertopic_unref (st);
 | 
			
		||||
  dds_domain *domain;
 | 
			
		||||
  ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
  domain = ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &domainid);
 | 
			
		||||
  if (domain != NULL)
 | 
			
		||||
  {
 | 
			
		||||
    assert (ddsrt_avl_lookup (&dds_topictree_def, &domain->m_topics, st->name_type_name) != NULL);
 | 
			
		||||
    ddsrt_avl_delete (&dds_topictree_def, &domain->m_topics, st);
 | 
			
		||||
  }
 | 
			
		||||
  ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
  st->status_cb_entity = NULL;
 | 
			
		||||
  ddsi_sertopic_unref (st);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
dds_topic_add_locked(
 | 
			
		||||
        dds_domainid_t id,
 | 
			
		||||
        struct ddsi_sertopic *st)
 | 
			
		||||
static void dds_topic_add_locked (dds_domainid_t id, struct ddsi_sertopic *st)
 | 
			
		||||
{
 | 
			
		||||
    dds_domain * dom;
 | 
			
		||||
    dom = dds_domain_find_locked (id);
 | 
			
		||||
    assert (dom);
 | 
			
		||||
    ddsrt_avl_insert (&dds_topictree_def, &dom->m_topics, st);
 | 
			
		||||
  dds_domain *dom = dds_domain_find_locked (id);
 | 
			
		||||
  assert (dom);
 | 
			
		||||
  assert (ddsrt_avl_lookup (&dds_topictree_def, &dom->m_topics, st->name_type_name) == NULL);
 | 
			
		||||
  ddsrt_avl_insert (&dds_topictree_def, &dom->m_topics, st);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT dds_entity_t
 | 
			
		||||
dds_find_topic(
 | 
			
		||||
    dds_entity_t participant,
 | 
			
		||||
    const char *name)
 | 
			
		||||
dds_entity_t dds_find_topic (dds_entity_t participant, const char *name)
 | 
			
		||||
{
 | 
			
		||||
    dds_entity_t tp;
 | 
			
		||||
    dds_entity *p = NULL;
 | 
			
		||||
    struct ddsi_sertopic *st;
 | 
			
		||||
    dds_return_t rc;
 | 
			
		||||
  dds_entity_t tp;
 | 
			
		||||
  dds_participant *p;
 | 
			
		||||
  struct ddsi_sertopic *st;
 | 
			
		||||
  dds_return_t rc;
 | 
			
		||||
 | 
			
		||||
    if (name) {
 | 
			
		||||
        rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &p);
 | 
			
		||||
        if (rc == DDS_RETCODE_OK) {
 | 
			
		||||
            ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
            st = dds_topic_lookup_locked (p->m_domain, name);
 | 
			
		||||
            if (st) {
 | 
			
		||||
                /* FIXME: calling addref is wrong because the Cyclone library has no
 | 
			
		||||
                   knowledge of the reference and hence simply deleting the participant
 | 
			
		||||
                   won't make the ref count drop to 0.  On the other hand, the DDS spec
 | 
			
		||||
                   says find_topic (and a second call to create_topic) return a new
 | 
			
		||||
                   proxy that must separately be deleted.  */
 | 
			
		||||
                dds_entity_add_ref (&st->status_cb_entity->m_entity);
 | 
			
		||||
                tp = st->status_cb_entity->m_entity.m_hdllink.hdl;
 | 
			
		||||
            } else {
 | 
			
		||||
                DDS_ERROR("Topic is not being created yet\n");
 | 
			
		||||
                tp = DDS_RETCODE_PRECONDITION_NOT_MET;
 | 
			
		||||
            }
 | 
			
		||||
            ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
            dds_entity_unlock(p);
 | 
			
		||||
        } else {
 | 
			
		||||
            tp = rc;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Argument name is not valid\n");
 | 
			
		||||
        tp = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
  if (name == NULL)
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
 | 
			
		||||
    return tp;
 | 
			
		||||
  if ((rc = dds_participant_lock (participant, &p)) != DDS_RETCODE_OK)
 | 
			
		||||
    return rc;
 | 
			
		||||
 | 
			
		||||
  ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
  if ((st = dds_topic_lookup_locked (p->m_entity.m_domain, name)) == NULL)
 | 
			
		||||
    tp = DDS_RETCODE_PRECONDITION_NOT_MET;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    /* FIXME: calling addref is wrong because the Cyclone library has no
 | 
			
		||||
       knowledge of the reference and hence simply deleting the participant
 | 
			
		||||
       won't make the ref count drop to 0.  On the other hand, the DDS spec
 | 
			
		||||
       says find_topic (and a second call to create_topic) return a new
 | 
			
		||||
       proxy that must separately be deleted.  */
 | 
			
		||||
    dds_entity_add_ref (&st->status_cb_entity->m_entity);
 | 
			
		||||
    tp = st->status_cb_entity->m_entity.m_hdllink.hdl;
 | 
			
		||||
  }
 | 
			
		||||
  ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
  dds_participant_unlock (p);
 | 
			
		||||
  return tp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_topic_delete(
 | 
			
		||||
        dds_entity *e)
 | 
			
		||||
static dds_return_t dds_topic_delete (dds_entity *e) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_topic_delete (dds_entity *e)
 | 
			
		||||
{
 | 
			
		||||
    dds_topic_free(e->m_domainid, ((dds_topic*) e)->m_stopic);
 | 
			
		||||
    return DDS_RETCODE_OK;
 | 
			
		||||
  dds_topic_free (e->m_domainid, ((dds_topic *) e)->m_stopic);
 | 
			
		||||
  return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_topic_qos_validate(
 | 
			
		||||
        const dds_qos_t *qos,
 | 
			
		||||
        bool enabled)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
    assert(qos);
 | 
			
		||||
static dds_return_t dds_topic_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
    /* Check consistency. */
 | 
			
		||||
    if (!dds_qos_validate_common(qos)) {
 | 
			
		||||
        DDS_ERROR("Argument QoS is not valid\n");
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
    if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data)) {
 | 
			
		||||
        DDS_ERROR("Group data QoS policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if ((qos->present & QP_DURABILITY_SERVICE) && (validate_durability_service_qospolicy(&qos->durability_service) != 0)) {
 | 
			
		||||
        DDS_ERROR("Durability service QoS policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if ((qos->present & QP_LIFESPAN) && (validate_duration(&qos->lifespan.duration) != 0)) {
 | 
			
		||||
        DDS_ERROR("Lifespan QoS policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if (qos->present & QP_HISTORY && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits(&qos->history, &qos->resource_limits) != 0)) {
 | 
			
		||||
        DDS_ERROR("Lifespan QoS policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if(ret == DDS_RETCODE_OK && enabled){
 | 
			
		||||
        ret = dds_qos_validate_mutable_common(qos);
 | 
			
		||||
    }
 | 
			
		||||
static dds_return_t dds_topic_qos_validate (const dds_qos_t *qos, bool enabled)
 | 
			
		||||
{
 | 
			
		||||
  if (!dds_qos_validate_common (qos))
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
  if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data))
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy(&qos->durability_service) < 0)
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_LIFESPAN) && validate_duration(&qos->lifespan.duration) < 0)
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits(&qos->history, &qos->resource_limits) < 0)
 | 
			
		||||
    return  DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  return enabled ? dds_qos_validate_mutable_common(qos) : DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_topic_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
 | 
			
		||||
{
 | 
			
		||||
  /* FIXME: QoS changes */
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  (void) e;
 | 
			
		||||
  if ((ret = dds_topic_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
  return enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_topic_qos_set(
 | 
			
		||||
        dds_entity *e,
 | 
			
		||||
        const dds_qos_t *qos,
 | 
			
		||||
        bool enabled)
 | 
			
		||||
static bool dupdef_qos_ok (const dds_qos_t *qos, const struct ddsi_sertopic *st)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = dds_topic_qos_validate(qos, enabled);
 | 
			
		||||
    (void)e;
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        if (enabled) {
 | 
			
		||||
            /* TODO: CHAM-95: DDSI does not support changing QoS policies. */
 | 
			
		||||
            DDS_ERROR("Changing the topic QoS is not supported\n");
 | 
			
		||||
            ret = DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool dupdef_qos_ok(const dds_qos_t *qos, const struct ddsi_sertopic *st)
 | 
			
		||||
{
 | 
			
		||||
    if ((qos == NULL) != (st->status_cb_entity->m_entity.m_qos == NULL)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    } else if (qos == NULL) {
 | 
			
		||||
        return true;
 | 
			
		||||
    } else {
 | 
			
		||||
        return dds_qos_equal(st->status_cb_entity->m_entity.m_qos, qos);
 | 
			
		||||
    }
 | 
			
		||||
  if ((qos == NULL) != (st->status_cb_entity->m_entity.m_qos == NULL))
 | 
			
		||||
    return false;
 | 
			
		||||
  else if (qos == NULL)
 | 
			
		||||
    return true;
 | 
			
		||||
  else
 | 
			
		||||
    return dds_qos_equal (st->status_cb_entity->m_entity.m_qos, qos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool sertopic_equivalent (const struct ddsi_sertopic *a, const struct ddsi_sertopic *b)
 | 
			
		||||
| 
						 | 
				
			
			@ -300,276 +229,213 @@ static bool sertopic_equivalent (const struct ddsi_sertopic *a, const struct dds
 | 
			
		|||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT dds_entity_t
 | 
			
		||||
dds_create_topic_arbitrary (
 | 
			
		||||
        dds_entity_t participant,
 | 
			
		||||
        struct ddsi_sertopic *sertopic,
 | 
			
		||||
        const dds_qos_t *qos,
 | 
			
		||||
        const dds_listener_t *listener,
 | 
			
		||||
        const nn_plist_t *sedp_plist)
 | 
			
		||||
dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_sertopic *sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const nn_plist_t *sedp_plist)
 | 
			
		||||
{
 | 
			
		||||
    struct ddsi_sertopic *stgeneric;
 | 
			
		||||
    dds_return_t rc;
 | 
			
		||||
    dds_entity *par;
 | 
			
		||||
    dds_topic *top;
 | 
			
		||||
    dds_qos_t *new_qos = NULL;
 | 
			
		||||
    dds_entity_t hdl;
 | 
			
		||||
    struct participant *ddsi_pp;
 | 
			
		||||
  struct ddsi_sertopic *stgeneric;
 | 
			
		||||
  dds_return_t rc;
 | 
			
		||||
  dds_participant *par;
 | 
			
		||||
  dds_topic *top;
 | 
			
		||||
  dds_qos_t *new_qos = NULL;
 | 
			
		||||
  dds_entity_t hdl;
 | 
			
		||||
  struct participant *ddsi_pp;
 | 
			
		||||
 | 
			
		||||
    if (sertopic == NULL){
 | 
			
		||||
        DDS_ERROR("Topic description is NULL\n");
 | 
			
		||||
        hdl = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto bad_param_err;
 | 
			
		||||
    }
 | 
			
		||||
  if (sertopic == NULL)
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
 | 
			
		||||
    rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par);
 | 
			
		||||
    if (rc != DDS_RETCODE_OK) {
 | 
			
		||||
        hdl = rc;
 | 
			
		||||
        goto lock_err;
 | 
			
		||||
    }
 | 
			
		||||
  if (qos && (rc = dds_topic_qos_validate (qos, false)) != DDS_RETCODE_OK)
 | 
			
		||||
    return rc;
 | 
			
		||||
 | 
			
		||||
    /* Validate qos */
 | 
			
		||||
    if (qos) {
 | 
			
		||||
        hdl = dds_topic_qos_validate (qos, false);
 | 
			
		||||
        if (hdl != DDS_RETCODE_OK) {
 | 
			
		||||
            goto qos_err;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  if ((rc = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK)
 | 
			
		||||
    return rc;
 | 
			
		||||
 | 
			
		||||
    /* FIXME: I find it weird that qos may be NULL in the entity */
 | 
			
		||||
  /* FIXME: I find it weird that qos may be NULL in the entity */
 | 
			
		||||
 | 
			
		||||
    /* Check if topic already exists with same name */
 | 
			
		||||
    ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
    if ((stgeneric = dds_topic_lookup_locked (par->m_domain, sertopic->name)) != NULL) {
 | 
			
		||||
        if (!sertopic_equivalent (stgeneric, sertopic)) {
 | 
			
		||||
            /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */
 | 
			
		||||
            DDS_ERROR("Create topic with mismatching type\n");
 | 
			
		||||
            hdl = DDS_RETCODE_PRECONDITION_NOT_MET;
 | 
			
		||||
        } else if (!dupdef_qos_ok(qos, stgeneric)) {
 | 
			
		||||
            /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */
 | 
			
		||||
            DDS_ERROR("Create topic with mismatching qos\n");
 | 
			
		||||
            hdl = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
        } else {
 | 
			
		||||
            /* FIXME: calling addref is wrong because the Cyclone library has no
 | 
			
		||||
               knowledge of the reference and hence simply deleting the participant
 | 
			
		||||
               won't make the ref count drop to 0.  On the other hand, the DDS spec
 | 
			
		||||
               says find_topic (and a second call to create_topic) return a new
 | 
			
		||||
               proxy that must separately be deleted.  */
 | 
			
		||||
            dds_entity_add_ref (&stgeneric->status_cb_entity->m_entity);
 | 
			
		||||
            hdl = stgeneric->status_cb_entity->m_entity.m_hdllink.hdl;
 | 
			
		||||
        }
 | 
			
		||||
        ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
  /* Check if topic already exists with same name */
 | 
			
		||||
  ddsrt_mutex_lock (&dds_global.m_mutex);
 | 
			
		||||
  if ((stgeneric = dds_topic_lookup_locked (par->m_entity.m_domain, sertopic->name)) != NULL) {
 | 
			
		||||
    if (!sertopic_equivalent (stgeneric, sertopic)) {
 | 
			
		||||
      /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */
 | 
			
		||||
      rc = DDS_RETCODE_PRECONDITION_NOT_MET;
 | 
			
		||||
      goto err_mismatch;
 | 
			
		||||
    } else if (!dupdef_qos_ok(qos, stgeneric)) {
 | 
			
		||||
      /* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */
 | 
			
		||||
      rc = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
      goto err_mismatch;
 | 
			
		||||
    } else {
 | 
			
		||||
        if (qos) {
 | 
			
		||||
            new_qos = dds_create_qos();
 | 
			
		||||
            /* Only returns failure when one of the qos args is NULL, which
 | 
			
		||||
             * is not the case here. */
 | 
			
		||||
            (void)dds_copy_qos(new_qos, qos);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Create topic */
 | 
			
		||||
        top = dds_alloc (sizeof (*top));
 | 
			
		||||
        hdl = dds_entity_init (&top->m_entity, par, DDS_KIND_TOPIC, new_qos, listener, DDS_TOPIC_STATUS_MASK);
 | 
			
		||||
        top->m_entity.m_deriver.delete = dds_topic_delete;
 | 
			
		||||
        top->m_entity.m_deriver.set_qos = dds_topic_qos_set;
 | 
			
		||||
        top->m_entity.m_deriver.validate_status = dds_topic_status_validate;
 | 
			
		||||
        top->m_stopic = ddsi_sertopic_ref (sertopic);
 | 
			
		||||
        sertopic->status_cb_entity = top;
 | 
			
		||||
 | 
			
		||||
        /* Add topic to extent */
 | 
			
		||||
        dds_topic_add_locked (par->m_domainid, sertopic);
 | 
			
		||||
        ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
 | 
			
		||||
        /* Publish Topic */
 | 
			
		||||
        thread_state_awake (lookup_thread_state ());
 | 
			
		||||
        ddsi_pp = ephash_lookup_participant_guid (&par->m_guid);
 | 
			
		||||
        assert (ddsi_pp);
 | 
			
		||||
        if (sedp_plist) {
 | 
			
		||||
            sedp_write_topic (ddsi_pp, sedp_plist);
 | 
			
		||||
        }
 | 
			
		||||
        thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
      /* FIXME: calling addref is wrong because the Cyclone library has no
 | 
			
		||||
       knowledge of the reference and hence simply deleting the participant
 | 
			
		||||
       won't make the ref count drop to 0.  On the other hand, the DDS spec
 | 
			
		||||
       says find_topic (and a second call to create_topic) return a new
 | 
			
		||||
       proxy that must separately be deleted.  */
 | 
			
		||||
      dds_entity_add_ref (&stgeneric->status_cb_entity->m_entity);
 | 
			
		||||
      hdl = stgeneric->status_cb_entity->m_entity.m_hdllink.hdl;
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
  } else {
 | 
			
		||||
    if (qos)
 | 
			
		||||
    {
 | 
			
		||||
      new_qos = dds_create_qos ();
 | 
			
		||||
      (void)dds_copy_qos (new_qos, qos);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
qos_err:
 | 
			
		||||
    dds_entity_unlock(par);
 | 
			
		||||
lock_err:
 | 
			
		||||
bad_param_err:
 | 
			
		||||
    return hdl;
 | 
			
		||||
    /* Create topic */
 | 
			
		||||
    top = dds_alloc (sizeof (*top));
 | 
			
		||||
    hdl = dds_entity_init (&top->m_entity, &par->m_entity, DDS_KIND_TOPIC, new_qos, listener, DDS_TOPIC_STATUS_MASK);
 | 
			
		||||
    top->m_entity.m_deriver.delete = dds_topic_delete;
 | 
			
		||||
    top->m_entity.m_deriver.set_qos = dds_topic_qos_set;
 | 
			
		||||
    top->m_entity.m_deriver.validate_status = dds_topic_status_validate;
 | 
			
		||||
    top->m_stopic = ddsi_sertopic_ref (sertopic);
 | 
			
		||||
    sertopic->status_cb_entity = top;
 | 
			
		||||
 | 
			
		||||
    /* Add topic to extent */
 | 
			
		||||
    dds_topic_add_locked (par->m_entity.m_domainid, sertopic);
 | 
			
		||||
    ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
 | 
			
		||||
    /* Publish Topic */
 | 
			
		||||
    thread_state_awake (lookup_thread_state ());
 | 
			
		||||
    ddsi_pp = ephash_lookup_participant_guid (&par->m_entity.m_guid);
 | 
			
		||||
    assert (ddsi_pp);
 | 
			
		||||
    if (sedp_plist)
 | 
			
		||||
      sedp_write_topic (ddsi_pp, sedp_plist);
 | 
			
		||||
    thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
  }
 | 
			
		||||
  dds_participant_unlock (par);
 | 
			
		||||
  return hdl;
 | 
			
		||||
 | 
			
		||||
err_mismatch:
 | 
			
		||||
  ddsrt_mutex_unlock (&dds_global.m_mutex);
 | 
			
		||||
  dds_participant_unlock (par);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT dds_entity_t
 | 
			
		||||
dds_create_topic(
 | 
			
		||||
        dds_entity_t participant,
 | 
			
		||||
        const dds_topic_descriptor_t *desc,
 | 
			
		||||
        const char *name,
 | 
			
		||||
        const dds_qos_t *qos,
 | 
			
		||||
        const dds_listener_t *listener)
 | 
			
		||||
dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descriptor_t *desc, const char *name, const dds_qos_t *qos, const dds_listener_t *listener)
 | 
			
		||||
{
 | 
			
		||||
    char *key = NULL;
 | 
			
		||||
    struct ddsi_sertopic_default *st;
 | 
			
		||||
    const char *typename;
 | 
			
		||||
    dds_qos_t *new_qos = NULL;
 | 
			
		||||
    nn_plist_t plist;
 | 
			
		||||
    dds_entity_t hdl;
 | 
			
		||||
    uint32_t index;
 | 
			
		||||
    size_t keysz;
 | 
			
		||||
  char *key = NULL;
 | 
			
		||||
  struct ddsi_sertopic_default *st;
 | 
			
		||||
  const char *typename;
 | 
			
		||||
  dds_qos_t *new_qos = NULL;
 | 
			
		||||
  nn_plist_t plist;
 | 
			
		||||
  dds_entity_t hdl;
 | 
			
		||||
  size_t keysz;
 | 
			
		||||
 | 
			
		||||
    if (desc == NULL){
 | 
			
		||||
        DDS_ERROR("Topic description is NULL");
 | 
			
		||||
        hdl = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto bad_param_err;
 | 
			
		||||
    }
 | 
			
		||||
  if (desc == NULL || name == NULL || !is_valid_name (name))
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
 | 
			
		||||
    if (name == NULL) {
 | 
			
		||||
        DDS_ERROR("Topic name is NULL");
 | 
			
		||||
        hdl = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto bad_param_err;
 | 
			
		||||
    }
 | 
			
		||||
  typename = desc->m_typename;
 | 
			
		||||
  keysz = strlen (name) + strlen (typename) + 2;
 | 
			
		||||
  key = dds_alloc (keysz);
 | 
			
		||||
  (void) snprintf (key, keysz, "%s/%s", name, typename);
 | 
			
		||||
 | 
			
		||||
    if (!is_valid_name(name)) {
 | 
			
		||||
        DDS_ERROR("Topic name contains characters that are not allowed.");
 | 
			
		||||
        hdl = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto bad_param_err;
 | 
			
		||||
    }
 | 
			
		||||
  st = dds_alloc (sizeof (*st));
 | 
			
		||||
 | 
			
		||||
    typename = desc->m_typename;
 | 
			
		||||
    keysz = strlen (name) + strlen (typename) + 2;
 | 
			
		||||
    key = (char*) dds_alloc (keysz);
 | 
			
		||||
    (void) snprintf(key, keysz, "%s/%s", name, typename);
 | 
			
		||||
  ddsrt_atomic_st32 (&st->c.refc, 1);
 | 
			
		||||
  st->c.iid = ddsi_iid_gen ();
 | 
			
		||||
  st->c.status_cb = dds_topic_status_cb;
 | 
			
		||||
  st->c.status_cb_entity = NULL; /* set by dds_create_topic_arbitrary */
 | 
			
		||||
  st->c.name_type_name = key;
 | 
			
		||||
  st->c.name = dds_string_dup (name);
 | 
			
		||||
  st->c.type_name = dds_string_dup (typename);
 | 
			
		||||
  st->c.ops = &ddsi_sertopic_ops_default;
 | 
			
		||||
  st->c.serdata_ops = desc->m_nkeys ? &ddsi_serdata_ops_cdr : &ddsi_serdata_ops_cdr_nokey;
 | 
			
		||||
  st->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (st->c.serdata_ops);
 | 
			
		||||
  st->native_encoding_identifier = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE);
 | 
			
		||||
 | 
			
		||||
    st = dds_alloc (sizeof (*st));
 | 
			
		||||
  st->type = (void*) desc;
 | 
			
		||||
  st->nkeys = desc->m_nkeys;
 | 
			
		||||
  st->keys = desc->m_keys;
 | 
			
		||||
 | 
			
		||||
    ddsrt_atomic_st32 (&st->c.refc, 1);
 | 
			
		||||
    st->c.iid = ddsi_iid_gen ();
 | 
			
		||||
    st->c.status_cb = dds_topic_status_cb;
 | 
			
		||||
    st->c.status_cb_entity = NULL; /* set by dds_create_topic_arbitrary */
 | 
			
		||||
    st->c.name_type_name = key;
 | 
			
		||||
    st->c.name = dds_string_dup (name);
 | 
			
		||||
    st->c.type_name = dds_string_dup (typename);
 | 
			
		||||
    st->c.ops = &ddsi_sertopic_ops_default;
 | 
			
		||||
    st->c.serdata_ops = desc->m_nkeys ? &ddsi_serdata_ops_cdr : &ddsi_serdata_ops_cdr_nokey;
 | 
			
		||||
    st->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (st->c.serdata_ops);
 | 
			
		||||
    st->native_encoding_identifier = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE);
 | 
			
		||||
  /* Check if topic cannot be optimised (memcpy marshal) */
 | 
			
		||||
  if (!(desc->m_flagset & DDS_TOPIC_NO_OPTIMIZE)) {
 | 
			
		||||
    st->opt_size = dds_stream_check_optimize (desc);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    st->type = (void*) desc;
 | 
			
		||||
    st->nkeys = desc->m_nkeys;
 | 
			
		||||
    st->keys = desc->m_keys;
 | 
			
		||||
  nn_plist_init_empty (&plist);
 | 
			
		||||
  if (new_qos)
 | 
			
		||||
    dds_merge_qos (&plist.qos, new_qos);
 | 
			
		||||
 | 
			
		||||
    /* Check if topic cannot be optimised (memcpy marshal) */
 | 
			
		||||
    if ((desc->m_flagset & DDS_TOPIC_NO_OPTIMIZE) == 0) {
 | 
			
		||||
        st->opt_size = dds_stream_check_optimize (desc);
 | 
			
		||||
    }
 | 
			
		||||
  /* Set Topic meta data (for SEDP publication) */
 | 
			
		||||
  plist.qos.topic_name = dds_string_dup (st->c.name);
 | 
			
		||||
  plist.qos.type_name = dds_string_dup (st->c.type_name);
 | 
			
		||||
  plist.qos.present |= (QP_TOPIC_NAME | QP_TYPE_NAME);
 | 
			
		||||
  if (desc->m_meta)
 | 
			
		||||
  {
 | 
			
		||||
    plist.type_description = dds_string_dup (desc->m_meta);
 | 
			
		||||
    plist.present |= PP_PRISMTECH_TYPE_DESCRIPTION;
 | 
			
		||||
  }
 | 
			
		||||
  if (desc->m_nkeys)
 | 
			
		||||
  {
 | 
			
		||||
    plist.qos.present |= QP_PRISMTECH_SUBSCRIPTION_KEYS;
 | 
			
		||||
    plist.qos.subscription_keys.use_key_list = 1;
 | 
			
		||||
    plist.qos.subscription_keys.key_list.n = desc->m_nkeys;
 | 
			
		||||
    plist.qos.subscription_keys.key_list.strs = dds_alloc (desc->m_nkeys * sizeof (char*));
 | 
			
		||||
    for (uint32_t index = 0; index < desc->m_nkeys; index++)
 | 
			
		||||
      plist.qos.subscription_keys.key_list.strs[index] = dds_string_dup (desc->m_keys[index].m_name);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    nn_plist_init_empty (&plist);
 | 
			
		||||
    if (new_qos) {
 | 
			
		||||
        dds_merge_qos (&plist.qos, new_qos);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Set Topic meta data (for SEDP publication) */
 | 
			
		||||
    plist.qos.topic_name = dds_string_dup (st->c.name);
 | 
			
		||||
    plist.qos.type_name = dds_string_dup (st->c.type_name);
 | 
			
		||||
    plist.qos.present |= (QP_TOPIC_NAME | QP_TYPE_NAME);
 | 
			
		||||
    if (desc->m_meta) {
 | 
			
		||||
        plist.type_description = dds_string_dup (desc->m_meta);
 | 
			
		||||
        plist.present |= PP_PRISMTECH_TYPE_DESCRIPTION;
 | 
			
		||||
    }
 | 
			
		||||
    if (desc->m_nkeys) {
 | 
			
		||||
        plist.qos.present |= QP_PRISMTECH_SUBSCRIPTION_KEYS;
 | 
			
		||||
        plist.qos.subscription_keys.use_key_list = 1;
 | 
			
		||||
        plist.qos.subscription_keys.key_list.n = desc->m_nkeys;
 | 
			
		||||
        plist.qos.subscription_keys.key_list.strs = dds_alloc (desc->m_nkeys * sizeof (char*));
 | 
			
		||||
        for (index = 0; index < desc->m_nkeys; index++) {
 | 
			
		||||
            plist.qos.subscription_keys.key_list.strs[index] = dds_string_dup (desc->m_keys[index].m_name);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hdl = dds_create_topic_arbitrary(participant, &st->c, qos, listener, &plist);
 | 
			
		||||
    ddsi_sertopic_unref (&st->c);
 | 
			
		||||
    nn_plist_fini (&plist);
 | 
			
		||||
 | 
			
		||||
bad_param_err:
 | 
			
		||||
    return hdl;
 | 
			
		||||
  hdl = dds_create_topic_arbitrary (participant, &st->c, qos, listener, &plist);
 | 
			
		||||
  ddsi_sertopic_unref (&st->c);
 | 
			
		||||
  nn_plist_fini (&plist);
 | 
			
		||||
  return hdl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
dds_topic_chaining_filter(
 | 
			
		||||
        const void *sample,
 | 
			
		||||
        void *ctx)
 | 
			
		||||
static bool dds_topic_chaining_filter (const void *sample, void *ctx)
 | 
			
		||||
{
 | 
			
		||||
    dds_topic_filter_fn realf = (dds_topic_filter_fn)ctx;
 | 
			
		||||
    return realf (sample);
 | 
			
		||||
  dds_topic_filter_fn realf = (dds_topic_filter_fn) ctx;
 | 
			
		||||
  return realf (sample);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
dds_topic_mod_filter(
 | 
			
		||||
        dds_entity_t topic,
 | 
			
		||||
        dds_topic_intern_filter_fn *filter,
 | 
			
		||||
        void **ctx,
 | 
			
		||||
        bool set)
 | 
			
		||||
static void dds_topic_mod_filter (dds_entity_t topic, dds_topic_intern_filter_fn *filter, void **ctx, bool set)
 | 
			
		||||
{
 | 
			
		||||
    dds_topic *t;
 | 
			
		||||
    if (dds_topic_lock(topic, &t) == DDS_RETCODE_OK) {
 | 
			
		||||
        if (set) {
 | 
			
		||||
            t->filter_fn = *filter;
 | 
			
		||||
            t->filter_ctx = *ctx;
 | 
			
		||||
        } else {
 | 
			
		||||
            *filter = t->filter_fn;
 | 
			
		||||
            *ctx = t->filter_ctx;
 | 
			
		||||
        }
 | 
			
		||||
        dds_topic_unlock(t);
 | 
			
		||||
  dds_topic *t;
 | 
			
		||||
  if (dds_topic_lock (topic, &t) == DDS_RETCODE_OK)
 | 
			
		||||
  {
 | 
			
		||||
    if (set) {
 | 
			
		||||
      t->filter_fn = *filter;
 | 
			
		||||
      t->filter_ctx = *ctx;
 | 
			
		||||
    } else {
 | 
			
		||||
        *filter = 0;
 | 
			
		||||
        *ctx = NULL;
 | 
			
		||||
      *filter = t->filter_fn;
 | 
			
		||||
      *ctx = t->filter_ctx;
 | 
			
		||||
    }
 | 
			
		||||
    dds_topic_unlock (t);
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    *filter = 0;
 | 
			
		||||
    *ctx = NULL;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_set_topic_filter(
 | 
			
		||||
        dds_entity_t topic,
 | 
			
		||||
        dds_topic_filter_fn filter)
 | 
			
		||||
void dds_set_topic_filter (dds_entity_t topic, dds_topic_filter_fn filter)
 | 
			
		||||
{
 | 
			
		||||
    dds_topic_intern_filter_fn chaining = dds_topic_chaining_filter;
 | 
			
		||||
    void *realf = (void *)filter;
 | 
			
		||||
    dds_topic_mod_filter (topic, &chaining, &realf, true);
 | 
			
		||||
  dds_topic_intern_filter_fn chaining = dds_topic_chaining_filter;
 | 
			
		||||
  void *realf = (void *) filter;
 | 
			
		||||
  dds_topic_mod_filter (topic, &chaining, &realf, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_topic_set_filter(
 | 
			
		||||
        dds_entity_t topic,
 | 
			
		||||
        dds_topic_filter_fn filter)
 | 
			
		||||
void dds_topic_set_filter (dds_entity_t topic, dds_topic_filter_fn filter)
 | 
			
		||||
{
 | 
			
		||||
    dds_set_topic_filter(topic, filter);
 | 
			
		||||
  dds_set_topic_filter (topic, filter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_topic_filter_fn
 | 
			
		||||
dds_get_topic_filter(
 | 
			
		||||
        dds_entity_t topic)
 | 
			
		||||
dds_topic_filter_fn dds_get_topic_filter (dds_entity_t topic)
 | 
			
		||||
{
 | 
			
		||||
    dds_topic_intern_filter_fn filter;
 | 
			
		||||
    void *ctx;
 | 
			
		||||
    dds_topic_mod_filter (topic, &filter, &ctx, false);
 | 
			
		||||
    return (filter == dds_topic_chaining_filter) ? (dds_topic_filter_fn)ctx : 0;
 | 
			
		||||
  dds_topic_intern_filter_fn filter;
 | 
			
		||||
  void *ctx;
 | 
			
		||||
  dds_topic_mod_filter (topic, &filter, &ctx, false);
 | 
			
		||||
  return (filter == dds_topic_chaining_filter) ? (dds_topic_filter_fn) ctx : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_topic_filter_fn
 | 
			
		||||
dds_topic_get_filter(
 | 
			
		||||
        dds_entity_t topic)
 | 
			
		||||
dds_topic_filter_fn dds_topic_get_filter (dds_entity_t topic)
 | 
			
		||||
{
 | 
			
		||||
    return dds_get_topic_filter(topic);
 | 
			
		||||
  return dds_get_topic_filter (topic);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dds_topic_set_filter_with_ctx(
 | 
			
		||||
        dds_entity_t topic,
 | 
			
		||||
        dds_topic_intern_filter_fn filter,
 | 
			
		||||
        void *ctx)
 | 
			
		||||
void dds_topic_set_filter_with_ctx (dds_entity_t topic, dds_topic_intern_filter_fn filter, void *ctx)
 | 
			
		||||
{
 | 
			
		||||
  dds_topic_mod_filter (topic, &filter, &ctx, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_topic_intern_filter_fn
 | 
			
		||||
dds_topic_get_filter_with_ctx(
 | 
			
		||||
        dds_entity_t topic)
 | 
			
		||||
dds_topic_intern_filter_fn dds_topic_get_filter_with_ctx (dds_entity_t topic)
 | 
			
		||||
{
 | 
			
		||||
  dds_topic_intern_filter_fn filter;
 | 
			
		||||
  void *ctx;
 | 
			
		||||
| 
						 | 
				
			
			@ -577,93 +443,32 @@ dds_topic_get_filter_with_ctx(
 | 
			
		|||
  return (filter == dds_topic_chaining_filter) ? 0 : filter;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT dds_return_t
 | 
			
		||||
dds_get_name(
 | 
			
		||||
        dds_entity_t topic,
 | 
			
		||||
        char *name,
 | 
			
		||||
        size_t size)
 | 
			
		||||
dds_return_t dds_get_name (dds_entity_t topic, char *name, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    dds_topic *t;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    if(size <= 0){
 | 
			
		||||
        DDS_ERROR("Argument size is smaller than 0\n");
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    if(name == NULL){
 | 
			
		||||
        DDS_ERROR("Argument name is NULL\n");
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    name[0] = '\0';
 | 
			
		||||
    ret = dds_topic_lock(topic, &t);
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        (void)snprintf(name, size, "%s", t->m_stopic->name);
 | 
			
		||||
        dds_topic_unlock(t);
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking topic\n");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
fail:
 | 
			
		||||
  dds_topic *t;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  if (size <= 0 || name == NULL)
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
  name[0] = '\0';
 | 
			
		||||
  if ((ret = dds_topic_lock (topic, &t)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
  (void) snprintf (name, size, "%s", t->m_stopic->name);
 | 
			
		||||
  dds_topic_unlock (t);
 | 
			
		||||
  return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT dds_return_t
 | 
			
		||||
dds_get_type_name(
 | 
			
		||||
        dds_entity_t topic,
 | 
			
		||||
        char *name,
 | 
			
		||||
        size_t size)
 | 
			
		||||
dds_return_t dds_get_type_name (dds_entity_t topic, char *name, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    dds_topic *t;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    if(size <= 0){
 | 
			
		||||
        DDS_ERROR("Argument size is smaller than 0\n");
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    if(name == NULL){
 | 
			
		||||
        DDS_ERROR("Argument name is NULL\n");
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    name[0] = '\0';
 | 
			
		||||
    ret = dds_topic_lock(topic, &t);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking topic\n");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    (void)snprintf(name, size, "%s", t->m_stopic->type_name);
 | 
			
		||||
    dds_topic_unlock(t);
 | 
			
		||||
fail:
 | 
			
		||||
  dds_topic *t;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  if (size <= 0 || name == NULL)
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
  name[0] = '\0';
 | 
			
		||||
  if ((ret = dds_topic_lock (topic, &t)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
  (void) snprintf (name, size, "%s", t->m_stopic->type_name);
 | 
			
		||||
  dds_topic_unlock (t);
 | 
			
		||||
  return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_get_inconsistent_topic_status(
 | 
			
		||||
        dds_entity_t topic,
 | 
			
		||||
        dds_inconsistent_topic_status_t *status)
 | 
			
		||||
{
 | 
			
		||||
    dds_topic *t;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_topic_lock(topic, &t);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking topic\n");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    /* status = NULL, application do not need the status, but reset the counter & triggered bit */
 | 
			
		||||
    if (status) {
 | 
			
		||||
        *status = t->m_inconsistent_topic_status;
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_lock (&t->m_entity.m_observers_lock);
 | 
			
		||||
    if (t->m_entity.m_status_enable & DDS_INCONSISTENT_TOPIC_STATUS) {
 | 
			
		||||
        t->m_inconsistent_topic_status.total_count_change = 0;
 | 
			
		||||
        dds_entity_status_reset(&t->m_entity, DDS_INCONSISTENT_TOPIC_STATUS);
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&t->m_entity.m_observers_lock);
 | 
			
		||||
    dds_topic_unlock(t);
 | 
			
		||||
fail:
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
DDS_GET_STATUS(topic, inconsistent_topic, INCONSISTENT_TOPIC, total_count_change)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,424 +14,296 @@
 | 
			
		|||
#include "dds/ddsrt/heap.h"
 | 
			
		||||
#include "dds/ddsrt/log.h"
 | 
			
		||||
#include "dds__entity.h"
 | 
			
		||||
#include "dds__participant.h"
 | 
			
		||||
#include "dds__querycond.h"
 | 
			
		||||
#include "dds__readcond.h"
 | 
			
		||||
#include "dds__rhc.h"
 | 
			
		||||
 | 
			
		||||
DEFINE_ENTITY_LOCK_UNLOCK(static, dds_waitset, DDS_KIND_WAITSET)
 | 
			
		||||
DEFINE_ENTITY_LOCK_UNLOCK (static, dds_waitset, DDS_KIND_WAITSET)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
dds_waitset_swap(
 | 
			
		||||
        dds_attachment **dst,
 | 
			
		||||
        dds_attachment **src,
 | 
			
		||||
        dds_attachment  *prev,
 | 
			
		||||
        dds_attachment  *idx)
 | 
			
		||||
static void dds_waitset_swap (dds_attachment **dst, dds_attachment **src, dds_attachment *prev, dds_attachment *idx)
 | 
			
		||||
{
 | 
			
		||||
    /* Remove from source. */
 | 
			
		||||
    if (prev == NULL) {
 | 
			
		||||
        *src = idx->next;
 | 
			
		||||
    } else {
 | 
			
		||||
        prev->next = idx->next;
 | 
			
		||||
    }
 | 
			
		||||
  /* Remove from source. */
 | 
			
		||||
  if (prev == NULL)
 | 
			
		||||
    *src = idx->next;
 | 
			
		||||
  else
 | 
			
		||||
    prev->next = idx->next;
 | 
			
		||||
 | 
			
		||||
    /* Add to destination. */
 | 
			
		||||
    idx->next = *dst;
 | 
			
		||||
    *dst = idx;
 | 
			
		||||
  /* Add to destination. */
 | 
			
		||||
  idx->next = *dst;
 | 
			
		||||
  *dst = idx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_waitset_wait_impl(
 | 
			
		||||
        dds_entity_t waitset,
 | 
			
		||||
        dds_attach_t *xs,
 | 
			
		||||
        size_t nxs,
 | 
			
		||||
        dds_time_t abstimeout,
 | 
			
		||||
        dds_time_t tnow)
 | 
			
		||||
static dds_return_t dds_waitset_wait_impl (dds_entity_t waitset, dds_attach_t *xs, size_t nxs, dds_time_t abstimeout)
 | 
			
		||||
{
 | 
			
		||||
    dds_waitset *ws;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
    dds_attachment *idx;
 | 
			
		||||
    dds_attachment *next;
 | 
			
		||||
    dds_attachment *prev;
 | 
			
		||||
  dds_waitset *ws;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  dds_attachment *idx;
 | 
			
		||||
  dds_attachment *prev;
 | 
			
		||||
 | 
			
		||||
    if ((xs == NULL) && (nxs != 0)){
 | 
			
		||||
        DDS_ERROR("A size was given, but no array\n");
 | 
			
		||||
        return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
    if ((xs != NULL) && (nxs == 0)){
 | 
			
		||||
        DDS_ERROR("Array is given with an invalid size\n");
 | 
			
		||||
        return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Locking the waitset here will delay a possible deletion until it is
 | 
			
		||||
     * unlocked. Even when the related mutex is unlocked by a conditioned wait. */
 | 
			
		||||
    ret = dds_waitset_lock(waitset, &ws);
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        /* Check if any of any previous triggered entities has changed there status
 | 
			
		||||
         * and thus it trigger value could be false now. */
 | 
			
		||||
        idx = ws->triggered;
 | 
			
		||||
        prev = NULL;
 | 
			
		||||
        while (idx != NULL) {
 | 
			
		||||
            next = idx->next;
 | 
			
		||||
            if (idx->entity->m_trigger == 0) {
 | 
			
		||||
                /* Move observed entity to triggered list. */
 | 
			
		||||
                dds_waitset_swap(&(ws->observed), &(ws->triggered), prev, idx);
 | 
			
		||||
            } else {
 | 
			
		||||
                prev = idx;
 | 
			
		||||
            }
 | 
			
		||||
            idx = next;
 | 
			
		||||
        }
 | 
			
		||||
        /* Check if any of the entities have been triggered. */
 | 
			
		||||
        idx = ws->observed;
 | 
			
		||||
        prev = NULL;
 | 
			
		||||
        while (idx != NULL) {
 | 
			
		||||
            next = idx->next;
 | 
			
		||||
            if (idx->entity->m_trigger > 0) {
 | 
			
		||||
                /* Move observed entity to triggered list. */
 | 
			
		||||
                dds_waitset_swap(&(ws->triggered), &(ws->observed), prev, idx);
 | 
			
		||||
            } else {
 | 
			
		||||
                prev = idx;
 | 
			
		||||
            }
 | 
			
		||||
            idx = next;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Only wait/keep waiting when whe have something to observer and there aren't any triggers yet. */
 | 
			
		||||
        while ((ws->observed != NULL) && (ws->triggered == NULL) && (ret == DDS_RETCODE_OK)) {
 | 
			
		||||
            if (abstimeout == DDS_NEVER) {
 | 
			
		||||
                ddsrt_cond_wait(&ws->m_entity.m_cond, &ws->m_entity.m_mutex);
 | 
			
		||||
            } else if (abstimeout <= tnow) {
 | 
			
		||||
                ret = DDS_RETCODE_TIMEOUT;
 | 
			
		||||
            } else {
 | 
			
		||||
                dds_duration_t dt = abstimeout - tnow;
 | 
			
		||||
                (void)ddsrt_cond_waitfor(&ws->m_entity.m_cond, &ws->m_entity.m_mutex, dt);
 | 
			
		||||
                tnow = dds_time();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Get number of triggered entities
 | 
			
		||||
         *   - set attach array when needed
 | 
			
		||||
         *   - swap them back to observed */
 | 
			
		||||
        if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
            ret = 0;
 | 
			
		||||
            idx = ws->triggered;
 | 
			
		||||
            while (idx != NULL) {
 | 
			
		||||
                if ((uint32_t)ret < (uint32_t)nxs) {
 | 
			
		||||
                    xs[ret] = idx->arg;
 | 
			
		||||
                }
 | 
			
		||||
                ret++;
 | 
			
		||||
 | 
			
		||||
                next = idx->next;
 | 
			
		||||
                /* The idx is always the first in triggered, so no prev. */
 | 
			
		||||
                dds_waitset_swap(&(ws->observed), &(ws->triggered), NULL, idx);
 | 
			
		||||
                idx = next;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (ret == DDS_RETCODE_TIMEOUT) {
 | 
			
		||||
            ret = 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            DDS_ERROR("Internal error");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        dds_waitset_unlock(ws);
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking waitset\n");
 | 
			
		||||
    }
 | 
			
		||||
  if (xs == NULL && nxs != 0)
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
  if (xs != NULL && nxs == 0)
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
 | 
			
		||||
  /* Locking the waitset here will delay a possible deletion until it is
 | 
			
		||||
   * unlocked. Even when the related mutex is unlocked by a conditioned wait. */
 | 
			
		||||
  if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  /* Move any previously but no longer triggering entities back to the observed list */
 | 
			
		||||
  idx = ws->triggered;
 | 
			
		||||
  prev = NULL;
 | 
			
		||||
  while (idx != NULL)
 | 
			
		||||
  {
 | 
			
		||||
    dds_attachment *next = idx->next;
 | 
			
		||||
    if (idx->entity->m_trigger == 0)
 | 
			
		||||
      dds_waitset_swap (&ws->observed, &ws->triggered, prev, idx);
 | 
			
		||||
    else
 | 
			
		||||
      prev = idx;
 | 
			
		||||
    idx = next;
 | 
			
		||||
  }
 | 
			
		||||
  /* Check if any of the observed entities are currently triggered, moving them
 | 
			
		||||
     to the triggered list */
 | 
			
		||||
  idx = ws->observed;
 | 
			
		||||
  prev = NULL;
 | 
			
		||||
  while (idx != NULL)
 | 
			
		||||
  {
 | 
			
		||||
    dds_attachment *next = idx->next;
 | 
			
		||||
    if (idx->entity->m_trigger > 0)
 | 
			
		||||
      dds_waitset_swap (&ws->triggered, &ws->observed, prev, idx);
 | 
			
		||||
    else
 | 
			
		||||
      prev = idx;
 | 
			
		||||
    idx = next;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Only wait/keep waiting when we have something to observe and there aren't any triggers yet. */
 | 
			
		||||
  while (ws->observed != NULL && ws->triggered == NULL)
 | 
			
		||||
    if (!ddsrt_cond_waituntil (&ws->m_entity.m_cond, &ws->m_entity.m_mutex, abstimeout))
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
  /* Get number of triggered entities
 | 
			
		||||
   *   - set attach array when needed
 | 
			
		||||
   *   - swap them back to observed */
 | 
			
		||||
  ret = 0;
 | 
			
		||||
  idx = ws->triggered;
 | 
			
		||||
  while (idx != NULL)
 | 
			
		||||
  {
 | 
			
		||||
    if ((uint32_t) ret < (uint32_t) nxs)
 | 
			
		||||
      xs[ret] = idx->arg;
 | 
			
		||||
    ret++;
 | 
			
		||||
 | 
			
		||||
    /* The idx is always the first in triggered, so no prev. */
 | 
			
		||||
    dds_attachment *next = idx->next;
 | 
			
		||||
    dds_waitset_swap (&ws->observed, &ws->triggered, NULL, idx);
 | 
			
		||||
    idx = next;
 | 
			
		||||
  }
 | 
			
		||||
  dds_waitset_unlock (ws);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
dds_waitset_close_list(
 | 
			
		||||
        dds_attachment **list,
 | 
			
		||||
        dds_entity_t waitset)
 | 
			
		||||
static void dds_waitset_close_list (dds_attachment **list, dds_entity_t waitset)
 | 
			
		||||
{
 | 
			
		||||
    dds_attachment *idx = *list;
 | 
			
		||||
    dds_attachment *next;
 | 
			
		||||
    while (idx != NULL) {
 | 
			
		||||
        next = idx->next;
 | 
			
		||||
        (void)dds_entity_observer_unregister(idx->entity->m_hdllink.hdl, waitset);
 | 
			
		||||
        ddsrt_free(idx);
 | 
			
		||||
        idx = next;
 | 
			
		||||
    }
 | 
			
		||||
    *list = NULL;
 | 
			
		||||
  dds_attachment *idx = *list;
 | 
			
		||||
  dds_attachment *next;
 | 
			
		||||
  while (idx != NULL)
 | 
			
		||||
  {
 | 
			
		||||
    next = idx->next;
 | 
			
		||||
    (void) dds_entity_observer_unregister (idx->entity->m_hdllink.hdl, waitset);
 | 
			
		||||
    ddsrt_free (idx);
 | 
			
		||||
    idx = next;
 | 
			
		||||
  }
 | 
			
		||||
  *list = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
dds_waitset_remove_from_list(
 | 
			
		||||
        dds_attachment **list,
 | 
			
		||||
        dds_entity_t observed)
 | 
			
		||||
static bool dds_waitset_remove_from_list (dds_attachment **list, dds_entity_t observed)
 | 
			
		||||
{
 | 
			
		||||
    dds_attachment *idx = *list;
 | 
			
		||||
    dds_attachment *prev = NULL;
 | 
			
		||||
 | 
			
		||||
    while (idx != NULL) {
 | 
			
		||||
        if (idx->entity->m_hdllink.hdl == observed) {
 | 
			
		||||
            if (prev == NULL) {
 | 
			
		||||
                *list = idx->next;
 | 
			
		||||
            } else {
 | 
			
		||||
                prev->next = idx->next;
 | 
			
		||||
            }
 | 
			
		||||
            ddsrt_free(idx);
 | 
			
		||||
 | 
			
		||||
            /* We're done. */
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        prev = idx;
 | 
			
		||||
        idx = idx->next;
 | 
			
		||||
    }
 | 
			
		||||
  dds_attachment *idx, *prev;
 | 
			
		||||
  for (idx = *list, prev = NULL; idx != NULL; prev = idx, idx = idx->next)
 | 
			
		||||
    if (idx->entity->m_hdllink.hdl == observed)
 | 
			
		||||
      break;
 | 
			
		||||
  if (idx == NULL)
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
  if (prev == NULL)
 | 
			
		||||
    *list = idx->next;
 | 
			
		||||
  else
 | 
			
		||||
    prev->next = idx->next;
 | 
			
		||||
  ddsrt_free (idx);
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_waitset_close(
 | 
			
		||||
        struct dds_entity *e)
 | 
			
		||||
dds_return_t dds_waitset_close (struct dds_entity *e)
 | 
			
		||||
{
 | 
			
		||||
    dds_waitset *ws = (dds_waitset*)e;
 | 
			
		||||
 | 
			
		||||
    dds_waitset_close_list(&ws->observed,  e->m_hdllink.hdl);
 | 
			
		||||
    dds_waitset_close_list(&ws->triggered, e->m_hdllink.hdl);
 | 
			
		||||
 | 
			
		||||
    /* Trigger waitset to wake up. */
 | 
			
		||||
    ddsrt_cond_broadcast(&e->m_cond);
 | 
			
		||||
 | 
			
		||||
    return DDS_RETCODE_OK;
 | 
			
		||||
  dds_waitset *ws = (dds_waitset *) e;
 | 
			
		||||
  dds_waitset_close_list (&ws->observed,  e->m_hdllink.hdl);
 | 
			
		||||
  dds_waitset_close_list (&ws->triggered, e->m_hdllink.hdl);
 | 
			
		||||
  ddsrt_cond_broadcast (&e->m_cond);
 | 
			
		||||
  return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT dds_entity_t
 | 
			
		||||
dds_create_waitset(
 | 
			
		||||
        dds_entity_t participant)
 | 
			
		||||
dds_entity_t dds_create_waitset (dds_entity_t participant)
 | 
			
		||||
{
 | 
			
		||||
    dds_entity_t hdl;
 | 
			
		||||
    dds_entity *par;
 | 
			
		||||
    dds_return_t rc;
 | 
			
		||||
  dds_entity_t hdl;
 | 
			
		||||
  dds_participant *par;
 | 
			
		||||
  dds_return_t rc;
 | 
			
		||||
 | 
			
		||||
    rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par);
 | 
			
		||||
    if (rc == DDS_RETCODE_OK) {
 | 
			
		||||
        dds_waitset *waitset = dds_alloc(sizeof(*waitset));
 | 
			
		||||
        hdl = dds_entity_init(&waitset->m_entity, par, DDS_KIND_WAITSET, NULL, NULL, 0);
 | 
			
		||||
        waitset->m_entity.m_deriver.close = dds_waitset_close;
 | 
			
		||||
        waitset->observed = NULL;
 | 
			
		||||
        waitset->triggered = NULL;
 | 
			
		||||
        dds_entity_unlock(par);
 | 
			
		||||
    } else {
 | 
			
		||||
        hdl = rc;
 | 
			
		||||
    }
 | 
			
		||||
  if ((rc = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK)
 | 
			
		||||
    return rc;
 | 
			
		||||
 | 
			
		||||
    return hdl;
 | 
			
		||||
  dds_waitset *waitset = dds_alloc (sizeof (*waitset));
 | 
			
		||||
  hdl = dds_entity_init (&waitset->m_entity, &par->m_entity, DDS_KIND_WAITSET, NULL, NULL, 0);
 | 
			
		||||
  waitset->m_entity.m_deriver.close = dds_waitset_close;
 | 
			
		||||
  waitset->observed = NULL;
 | 
			
		||||
  waitset->triggered = NULL;
 | 
			
		||||
  dds_participant_unlock (par);
 | 
			
		||||
  return hdl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT dds_return_t
 | 
			
		||||
dds_waitset_get_entities(
 | 
			
		||||
        dds_entity_t waitset,
 | 
			
		||||
        dds_entity_t *entities,
 | 
			
		||||
        size_t size)
 | 
			
		||||
dds_return_t dds_waitset_get_entities (dds_entity_t waitset, dds_entity_t *entities, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
    dds_waitset *ws;
 | 
			
		||||
 | 
			
		||||
    ret = dds_waitset_lock(waitset, &ws);
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        dds_attachment* iter;
 | 
			
		||||
 | 
			
		||||
        ret = 0;
 | 
			
		||||
        iter = ws->observed;
 | 
			
		||||
        while (iter) {
 | 
			
		||||
            if (((size_t)ret < size) && (entities != NULL)) {
 | 
			
		||||
                entities[ret] = iter->entity->m_hdllink.hdl;
 | 
			
		||||
            }
 | 
			
		||||
            ret++;
 | 
			
		||||
            iter = iter->next;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        iter = ws->triggered;
 | 
			
		||||
        while (iter) {
 | 
			
		||||
            if (((size_t)ret < size) && (entities != NULL)) {
 | 
			
		||||
                entities[ret] = iter->entity->m_hdllink.hdl;
 | 
			
		||||
            }
 | 
			
		||||
            ret++;
 | 
			
		||||
            iter = iter->next;
 | 
			
		||||
        }
 | 
			
		||||
        dds_waitset_unlock(ws);
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking waitset\n");
 | 
			
		||||
    }
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  dds_waitset *ws;
 | 
			
		||||
 | 
			
		||||
  if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  ret = 0;
 | 
			
		||||
  for (dds_attachment *iter = ws->observed; iter != NULL; iter = iter->next)
 | 
			
		||||
  {
 | 
			
		||||
    if ((size_t) ret < size && entities != NULL)
 | 
			
		||||
      entities[ret] = iter->entity->m_hdllink.hdl;
 | 
			
		||||
    ret++;
 | 
			
		||||
  }
 | 
			
		||||
  for (dds_attachment *iter = ws->triggered; iter != NULL; iter = iter->next)
 | 
			
		||||
  {
 | 
			
		||||
    if ((size_t) ret < size && entities != NULL)
 | 
			
		||||
      entities[ret] = iter->entity->m_hdllink.hdl;
 | 
			
		||||
    ret++;
 | 
			
		||||
  }
 | 
			
		||||
  dds_waitset_unlock(ws);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
dds_waitset_move(
 | 
			
		||||
        dds_attachment **src,
 | 
			
		||||
        dds_attachment **dst,
 | 
			
		||||
        dds_entity_t entity)
 | 
			
		||||
static void dds_waitset_move (dds_attachment **src, dds_attachment **dst, dds_entity_t entity)
 | 
			
		||||
{
 | 
			
		||||
    dds_attachment *idx = *src;
 | 
			
		||||
    dds_attachment *prev = NULL;
 | 
			
		||||
    while (idx != NULL) {
 | 
			
		||||
        if (idx->entity->m_hdllink.hdl == entity) {
 | 
			
		||||
            /* Swap idx from src to dst. */
 | 
			
		||||
            dds_waitset_swap(dst, src, prev, idx);
 | 
			
		||||
 | 
			
		||||
            /* We're done. */
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        prev = idx;
 | 
			
		||||
        idx = idx->next;
 | 
			
		||||
    }
 | 
			
		||||
  dds_attachment *idx, *prev;
 | 
			
		||||
  for (idx = *src, prev = NULL; idx != NULL; prev = idx, idx = idx->next)
 | 
			
		||||
    if (idx->entity->m_hdllink.hdl == entity)
 | 
			
		||||
      break;
 | 
			
		||||
  if (idx != NULL)
 | 
			
		||||
  {
 | 
			
		||||
    /* Swap idx from src to dst. */
 | 
			
		||||
    dds_waitset_swap (dst, src, prev, idx);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
dds_waitset_remove(
 | 
			
		||||
        dds_waitset *ws,
 | 
			
		||||
        dds_entity_t observed)
 | 
			
		||||
static void dds_waitset_remove (dds_waitset *ws, dds_entity_t observed)
 | 
			
		||||
{
 | 
			
		||||
    if (!dds_waitset_remove_from_list(&(ws->observed), observed)) {
 | 
			
		||||
        (void)dds_waitset_remove_from_list(&(ws->triggered), observed);
 | 
			
		||||
    }
 | 
			
		||||
  if (!dds_waitset_remove_from_list (&ws->observed, observed))
 | 
			
		||||
    (void) dds_waitset_remove_from_list (&ws->triggered, observed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is called when the observed entity signals a status change. */
 | 
			
		||||
void
 | 
			
		||||
dds_waitset_observer(
 | 
			
		||||
        dds_entity_t observer,
 | 
			
		||||
        dds_entity_t observed,
 | 
			
		||||
        uint32_t status)
 | 
			
		||||
void dds_waitset_observer (dds_entity_t observer, dds_entity_t observed, uint32_t status)
 | 
			
		||||
{
 | 
			
		||||
    dds_waitset *ws;
 | 
			
		||||
    if (dds_waitset_lock(observer, &ws) == DDS_RETCODE_OK) {
 | 
			
		||||
        if (status & DDS_DELETING_STATUS) {
 | 
			
		||||
            /* Remove this observed entity, which is being deleted, from the waitset. */
 | 
			
		||||
            dds_waitset_remove(ws, observed);
 | 
			
		||||
            /* Our registration to this observed entity will be removed automatically. */
 | 
			
		||||
        } else if (status != 0) {
 | 
			
		||||
            /* Move observed entity to triggered list. */
 | 
			
		||||
            dds_waitset_move(&(ws->observed), &(ws->triggered), observed);
 | 
			
		||||
        } else {
 | 
			
		||||
            /* Remove observed entity from triggered list (which it possibly resides in). */
 | 
			
		||||
            dds_waitset_move(&(ws->triggered), &(ws->observed), observed);
 | 
			
		||||
        }
 | 
			
		||||
        /* Trigger waitset to wake up. */
 | 
			
		||||
        ddsrt_cond_broadcast(&ws->m_entity.m_cond);
 | 
			
		||||
        dds_waitset_unlock(ws);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT dds_return_t
 | 
			
		||||
dds_waitset_attach(
 | 
			
		||||
        dds_entity_t waitset,
 | 
			
		||||
        dds_entity_t entity,
 | 
			
		||||
        dds_attach_t x)
 | 
			
		||||
{
 | 
			
		||||
    dds_entity  *e = NULL;
 | 
			
		||||
    dds_waitset *ws;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_waitset_lock(waitset, &ws);
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        if (waitset != entity) {
 | 
			
		||||
            ret = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e);
 | 
			
		||||
            if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
                e = NULL;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            e = &ws->m_entity;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* This will fail if given entity is already attached (or deleted). */
 | 
			
		||||
        if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
            ret = dds_entity_observer_register_nl(e, waitset, dds_waitset_observer);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
            dds_attachment *a = ddsrt_malloc(sizeof(dds_attachment));
 | 
			
		||||
            a->arg = x;
 | 
			
		||||
            a->entity = e;
 | 
			
		||||
            if (e->m_trigger > 0) {
 | 
			
		||||
                a->next = ws->triggered;
 | 
			
		||||
                ws->triggered = a;
 | 
			
		||||
            } else {
 | 
			
		||||
                a->next = ws->observed;
 | 
			
		||||
                ws->observed = a;
 | 
			
		||||
            }
 | 
			
		||||
            ret = DDS_RETCODE_OK;
 | 
			
		||||
        } else if (ret != DDS_RETCODE_PRECONDITION_NOT_MET) {
 | 
			
		||||
            DDS_ERROR("Entity is not valid\n");
 | 
			
		||||
            ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        } else {
 | 
			
		||||
            DDS_ERROR("Entity is already attached\n");
 | 
			
		||||
        }
 | 
			
		||||
        if ((e != NULL) && (waitset != entity)) {
 | 
			
		||||
            dds_entity_unlock(e);
 | 
			
		||||
        }
 | 
			
		||||
        dds_waitset_unlock(ws);
 | 
			
		||||
  dds_waitset *ws;
 | 
			
		||||
  if (dds_waitset_lock (observer, &ws) == DDS_RETCODE_OK) {
 | 
			
		||||
    if (status & DDS_DELETING_STATUS) {
 | 
			
		||||
      /* Remove this observed entity, which is being deleted, from the waitset. */
 | 
			
		||||
      dds_waitset_remove (ws, observed);
 | 
			
		||||
      /* Our registration to this observed entity will be removed automatically. */
 | 
			
		||||
    } else if (status != 0) {
 | 
			
		||||
      /* Move observed entity to triggered list. */
 | 
			
		||||
      dds_waitset_move (&ws->observed, &ws->triggered, observed);
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking waitset\n");
 | 
			
		||||
      /* Remove observed entity from triggered list (which it possibly resides in). */
 | 
			
		||||
      dds_waitset_move (&ws->triggered, &ws->observed, observed);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
    /* Trigger waitset to wake up. */
 | 
			
		||||
    ddsrt_cond_broadcast (&ws->m_entity.m_cond);
 | 
			
		||||
    dds_waitset_unlock (ws);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT dds_return_t
 | 
			
		||||
dds_waitset_detach(
 | 
			
		||||
        dds_entity_t waitset,
 | 
			
		||||
        dds_entity_t entity)
 | 
			
		||||
dds_return_t dds_waitset_attach (dds_entity_t waitset, dds_entity_t entity, dds_attach_t x)
 | 
			
		||||
{
 | 
			
		||||
    dds_waitset *ws;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_waitset_lock(waitset, &ws);
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        /* Possibly fails when entity was not attached. */
 | 
			
		||||
        if (waitset == entity) {
 | 
			
		||||
            ret = dds_entity_observer_unregister_nl(&ws->m_entity, waitset);
 | 
			
		||||
        } else {
 | 
			
		||||
            ret = dds_entity_observer_unregister(entity, waitset);
 | 
			
		||||
        }
 | 
			
		||||
        if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
            dds_waitset_remove(ws, entity);
 | 
			
		||||
        } else if (ret != DDS_RETCODE_PRECONDITION_NOT_MET) {
 | 
			
		||||
            DDS_ERROR("The given entity to detach is invalid\n");
 | 
			
		||||
            ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
        } else {
 | 
			
		||||
            DDS_ERROR("The given entity to detach was not attached previously\n");
 | 
			
		||||
        }
 | 
			
		||||
        dds_waitset_unlock(ws);
 | 
			
		||||
    } else {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking waitset\n");
 | 
			
		||||
    }
 | 
			
		||||
  dds_entity *e;
 | 
			
		||||
  dds_waitset *ws;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
  if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  if (waitset == entity)
 | 
			
		||||
    e = &ws->m_entity;
 | 
			
		||||
  else if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK)
 | 
			
		||||
  {
 | 
			
		||||
    ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    goto err_waitset;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* This will fail if given entity is already attached (or deleted). */
 | 
			
		||||
  if ((ret = dds_entity_observer_register_nl (e, waitset, dds_waitset_observer)) != DDS_RETCODE_OK)
 | 
			
		||||
    goto err_entity;
 | 
			
		||||
 | 
			
		||||
  dds_attachment *a = ddsrt_malloc (sizeof (*a));
 | 
			
		||||
  a->arg = x;
 | 
			
		||||
  a->entity = e;
 | 
			
		||||
  if (e->m_trigger > 0) {
 | 
			
		||||
    a->next = ws->triggered;
 | 
			
		||||
    ws->triggered = a;
 | 
			
		||||
  } else {
 | 
			
		||||
    a->next = ws->observed;
 | 
			
		||||
    ws->observed = a;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
err_entity:
 | 
			
		||||
  if (e != &ws->m_entity)
 | 
			
		||||
    dds_entity_unlock (e);
 | 
			
		||||
err_waitset:
 | 
			
		||||
  dds_waitset_unlock (ws);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_waitset_wait_until(
 | 
			
		||||
        dds_entity_t waitset,
 | 
			
		||||
        dds_attach_t *xs,
 | 
			
		||||
        size_t nxs,
 | 
			
		||||
        dds_time_t abstimeout)
 | 
			
		||||
dds_return_t dds_waitset_detach (dds_entity_t waitset, dds_entity_t entity)
 | 
			
		||||
{
 | 
			
		||||
    return dds_waitset_wait_impl(waitset, xs, nxs, abstimeout, dds_time());
 | 
			
		||||
  dds_waitset *ws;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
  if ((ret = dds_waitset_lock (waitset, &ws)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  /* Possibly fails when entity was not attached. */
 | 
			
		||||
  if (waitset == entity)
 | 
			
		||||
    ret = dds_entity_observer_unregister_nl (&ws->m_entity, waitset);
 | 
			
		||||
  else
 | 
			
		||||
    ret = dds_entity_observer_unregister (entity, waitset);
 | 
			
		||||
 | 
			
		||||
  if (ret == DDS_RETCODE_OK)
 | 
			
		||||
    dds_waitset_remove (ws, entity);
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    if (ret != DDS_RETCODE_PRECONDITION_NOT_MET)
 | 
			
		||||
      ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
  }
 | 
			
		||||
  dds_waitset_unlock (ws);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_waitset_wait(
 | 
			
		||||
        dds_entity_t waitset,
 | 
			
		||||
        dds_attach_t *xs,
 | 
			
		||||
        size_t nxs,
 | 
			
		||||
        dds_duration_t reltimeout)
 | 
			
		||||
dds_return_t dds_waitset_wait_until (dds_entity_t waitset, dds_attach_t *xs, size_t nxs, dds_time_t abstimeout)
 | 
			
		||||
{
 | 
			
		||||
    dds_entity_t ret;
 | 
			
		||||
  return dds_waitset_wait_impl(waitset, xs, nxs, abstimeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    if (reltimeout >= 0) {
 | 
			
		||||
        dds_time_t tnow = dds_time();
 | 
			
		||||
        dds_time_t abstimeout = (DDS_INFINITY - reltimeout <= tnow) ? DDS_NEVER : (tnow + reltimeout);
 | 
			
		||||
        ret = dds_waitset_wait_impl(waitset, xs, nxs, abstimeout, tnow);
 | 
			
		||||
    } else{
 | 
			
		||||
        DDS_ERROR("Negative timeout\n");
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
dds_return_t dds_waitset_wait (dds_entity_t waitset, dds_attach_t *xs, size_t nxs, dds_duration_t reltimeout)
 | 
			
		||||
{
 | 
			
		||||
  if (reltimeout < 0)
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
  const dds_time_t tnow = dds_time ();
 | 
			
		||||
  const dds_time_t abstimeout = (DDS_INFINITY - reltimeout <= tnow) ? DDS_NEVER : (tnow + reltimeout);
 | 
			
		||||
  return dds_waitset_wait_impl (waitset, xs, nxs, abstimeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t dds_waitset_set_trigger (dds_entity_t waitset, bool trigger)
 | 
			
		||||
| 
						 | 
				
			
			@ -455,4 +327,3 @@ dds_return_t dds_waitset_set_trigger (dds_entity_t waitset, bool trigger)
 | 
			
		|||
  dds_waitset_unlock (ws);
 | 
			
		||||
  return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ struct whc_node {
 | 
			
		|||
  struct whc_node *next_seq; /* next in this interval */
 | 
			
		||||
  struct whc_node *prev_seq; /* prev in this interval */
 | 
			
		||||
  struct whc_idxnode *idxnode; /* NULL if not in index */
 | 
			
		||||
  unsigned idxnode_pos; /* index in idxnode.hist */
 | 
			
		||||
  uint32_t idxnode_pos; /* index in idxnode.hist */
 | 
			
		||||
  seqno_t seq;
 | 
			
		||||
  uint64_t total_bytes; /* cumulative number of bytes up to and including this node */
 | 
			
		||||
  size_t size;
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ struct whc_node {
 | 
			
		|||
  unsigned unacked: 1; /* counted in whc::unacked_bytes iff 1 */
 | 
			
		||||
  unsigned borrowed: 1; /* at most one can borrow it at any time */
 | 
			
		||||
  nn_mtime_t last_rexmit_ts;
 | 
			
		||||
  unsigned rexmit_count;
 | 
			
		||||
  uint32_t rexmit_count;
 | 
			
		||||
  struct ddsi_serdata *serdata;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +59,7 @@ struct whc_idxnode {
 | 
			
		|||
  uint64_t iid;
 | 
			
		||||
  seqno_t prune_seq;
 | 
			
		||||
  struct ddsi_tkmap_instance *tk;
 | 
			
		||||
  unsigned headidx;
 | 
			
		||||
  uint32_t headidx;
 | 
			
		||||
#if __STDC_VERSION__ >= 199901L
 | 
			
		||||
  struct whc_node *hist[];
 | 
			
		||||
#else
 | 
			
		||||
| 
						 | 
				
			
			@ -77,14 +77,14 @@ struct whc_seq_entry {
 | 
			
		|||
struct whc_impl {
 | 
			
		||||
  struct whc common;
 | 
			
		||||
  ddsrt_mutex_t lock;
 | 
			
		||||
  unsigned seq_size;
 | 
			
		||||
  uint32_t seq_size;
 | 
			
		||||
  size_t unacked_bytes;
 | 
			
		||||
  size_t sample_overhead;
 | 
			
		||||
  uint64_t total_bytes; /* total number of bytes pushed in */
 | 
			
		||||
  unsigned is_transient_local: 1;
 | 
			
		||||
  unsigned hdepth; /* 0 = unlimited */
 | 
			
		||||
  unsigned tldepth; /* 0 = disabled/unlimited (no need to maintain an index if KEEP_ALL <=> is_transient_local + tldepth=0) */
 | 
			
		||||
  unsigned idxdepth; /* = max(hdepth, tldepth) */
 | 
			
		||||
  uint32_t hdepth; /* 0 = unlimited */
 | 
			
		||||
  uint32_t tldepth; /* 0 = disabled/unlimited (no need to maintain an index if KEEP_ALL <=> is_transient_local + tldepth=0) */
 | 
			
		||||
  uint32_t idxdepth; /* = max (hdepth, tldepth) */
 | 
			
		||||
  seqno_t max_drop_seq; /* samples in whc with seq <= max_drop_seq => transient-local */
 | 
			
		||||
  struct whc_intvnode *open_intv; /* interval where next sample will go (usually) */
 | 
			
		||||
  struct whc_node *maxseq_node; /* NULL if empty; if not in open_intv, open_intv is empty */
 | 
			
		||||
| 
						 | 
				
			
			@ -103,14 +103,12 @@ struct whc_sample_iter_impl {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
/* check that our definition of whc_sample_iter fits in the type that callers allocate */
 | 
			
		||||
struct whc_sample_iter_sizecheck {
 | 
			
		||||
  char fits_in_generic_type[sizeof(struct whc_sample_iter_impl) <= sizeof(struct whc_sample_iter) ? 1 : -1];
 | 
			
		||||
};
 | 
			
		||||
DDSRT_STATIC_ASSERT (sizeof (struct whc_sample_iter_impl) <= sizeof (struct whc_sample_iter));
 | 
			
		||||
 | 
			
		||||
/* Hash + interval tree adminitration of samples-by-sequence number
 | 
			
		||||
 * - by definition contains all samples in WHC (unchanged from older versions)
 | 
			
		||||
 * Circular array of samples per instance, inited to all 0
 | 
			
		||||
 * - length is max(durability_service.history_depth, history.depth), KEEP_ALL => as-if 0
 | 
			
		||||
 * - length is max (durability_service.history_depth, history.depth), KEEP_ALL => as-if 0
 | 
			
		||||
 * - no instance index if above length 0
 | 
			
		||||
 * - each sample (i.e., whc_node): backpointer into index
 | 
			
		||||
 * - maintain index of latest sample, end of history then trivially follows from index arithmetic
 | 
			
		||||
| 
						 | 
				
			
			@ -124,24 +122,24 @@ static void insert_whcn_in_hash (struct whc_impl *whc, struct whc_node *whcn);
 | 
			
		|||
static void whc_delete_one (struct whc_impl *whc, struct whc_node *whcn);
 | 
			
		||||
static int compare_seq (const void *va, const void *vb);
 | 
			
		||||
static void free_deferred_free_list (struct whc_node *deferred_free_list);
 | 
			
		||||
static void get_state_locked(const struct whc_impl *whc, struct whc_state *st);
 | 
			
		||||
static void get_state_locked (const struct whc_impl *whc, struct whc_state *st);
 | 
			
		||||
 | 
			
		||||
static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list);
 | 
			
		||||
static unsigned whc_default_remove_acked_messages (struct whc *whc, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list);
 | 
			
		||||
static uint32_t whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list);
 | 
			
		||||
static uint32_t whc_default_remove_acked_messages (struct whc *whc, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list);
 | 
			
		||||
static void whc_default_free_deferred_free_list (struct whc *whc, struct whc_node *deferred_free_list);
 | 
			
		||||
static void whc_default_get_state(const struct whc *whc, struct whc_state *st);
 | 
			
		||||
static void whc_default_get_state (const struct whc *whc, struct whc_state *st);
 | 
			
		||||
static int whc_default_insert (struct whc *whc, seqno_t max_drop_seq, seqno_t seq, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk);
 | 
			
		||||
static seqno_t whc_default_next_seq (const struct whc *whc, seqno_t seq);
 | 
			
		||||
static bool whc_default_borrow_sample (const struct whc *whc, seqno_t seq, struct whc_borrowed_sample *sample);
 | 
			
		||||
static bool whc_default_borrow_sample_key (const struct whc *whc, const struct ddsi_serdata *serdata_key, struct whc_borrowed_sample *sample);
 | 
			
		||||
static void whc_default_return_sample (struct whc *whc, struct whc_borrowed_sample *sample, bool update_retransmit_info);
 | 
			
		||||
static unsigned whc_default_downgrade_to_volatile (struct whc *whc, struct whc_state *st);
 | 
			
		||||
static uint32_t whc_default_downgrade_to_volatile (struct whc *whc, struct whc_state *st);
 | 
			
		||||
static void whc_default_sample_iter_init (const struct whc *whc, struct whc_sample_iter *opaque_it);
 | 
			
		||||
static bool whc_default_sample_iter_borrow_next (struct whc_sample_iter *opaque_it, struct whc_borrowed_sample *sample);
 | 
			
		||||
static void whc_default_free (struct whc *whc);
 | 
			
		||||
 | 
			
		||||
static const ddsrt_avl_treedef_t whc_seq_treedef =
 | 
			
		||||
  DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct whc_intvnode, avlnode), offsetof (struct whc_intvnode, min), compare_seq, 0);
 | 
			
		||||
DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct whc_intvnode, avlnode), offsetof (struct whc_intvnode, min), compare_seq, 0);
 | 
			
		||||
 | 
			
		||||
static const struct whc_ops whc_ops = {
 | 
			
		||||
  .insert = whc_default_insert,
 | 
			
		||||
| 
						 | 
				
			
			@ -159,12 +157,12 @@ static const struct whc_ops whc_ops = {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
/* Number of instantiated WHCs and a global freelist for WHC nodes that gets
 | 
			
		||||
   initialized lazily and cleaned up automatically when the last WHC is freed.
 | 
			
		||||
   Protected by dds_global.m_mutex.
 | 
			
		||||
 initialized lazily and cleaned up automatically when the last WHC is freed.
 | 
			
		||||
 Protected by dds_global.m_mutex.
 | 
			
		||||
 | 
			
		||||
   sizeof (whc_node) on 64-bit machines ~ 100 bytes, so this is ~1MB
 | 
			
		||||
   8k entries seems to be roughly the amount needed for minimum samples,
 | 
			
		||||
   maximum message size and a short round-trip time */
 | 
			
		||||
 sizeof (whc_node) on 64-bit machines ~ 100 bytes, so this is ~1MB
 | 
			
		||||
 8k entries seems to be roughly the amount needed for minimum samples,
 | 
			
		||||
 maximum message size and a short round-trip time */
 | 
			
		||||
#define MAX_FREELIST_SIZE 8192
 | 
			
		||||
static uint32_t whc_count;
 | 
			
		||||
static struct nn_freelist whc_node_freelist;
 | 
			
		||||
| 
						 | 
				
			
			@ -175,9 +173,9 @@ static uint32_t whc_seq_entry_hash (const void *vn)
 | 
			
		|||
  const struct whc_seq_entry *n = vn;
 | 
			
		||||
  /* we hash the lower 32 bits, on the assumption that with 4 billion
 | 
			
		||||
   samples in between there won't be significant correlation */
 | 
			
		||||
  const uint64_t c = UINT64_C(16292676669999574021);
 | 
			
		||||
  const uint64_t c = UINT64_C (16292676669999574021);
 | 
			
		||||
  const uint32_t x = (uint32_t) n->seq;
 | 
			
		||||
  return (unsigned) ((x * c) >> 32);
 | 
			
		||||
  return (uint32_t) ((x * c) >> 32);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int whc_seq_entry_eq (const void *va, const void *vb)
 | 
			
		||||
| 
						 | 
				
			
			@ -192,9 +190,9 @@ static uint32_t whc_node_hash (const void *vn)
 | 
			
		|||
  const struct whc_node *n = vn;
 | 
			
		||||
  /* we hash the lower 32 bits, on the assumption that with 4 billion
 | 
			
		||||
   samples in between there won't be significant correlation */
 | 
			
		||||
  const uint64_t c = UINT64_C(16292676669999574021);
 | 
			
		||||
  const uint64_t c = UINT64_C (16292676669999574021);
 | 
			
		||||
  const uint32_t x = (uint32_t) n->seq;
 | 
			
		||||
  return (unsigned) ((x * c) >> 32);
 | 
			
		||||
  return (uint32_t) ((x * c) >> 32);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int whc_node_eq (const void *va, const void *vb)
 | 
			
		||||
| 
						 | 
				
			
			@ -245,10 +243,10 @@ static struct whc_node *whc_findmax_procedurally (const struct whc_impl *whc)
 | 
			
		|||
static void check_whc (const struct whc_impl *whc)
 | 
			
		||||
{
 | 
			
		||||
  /* there's much more we can check, but it gets expensive quite
 | 
			
		||||
     quickly: all nodes but open_intv non-empty, non-overlapping and
 | 
			
		||||
     non-contiguous; min & maxp1 of intervals correct; each interval
 | 
			
		||||
     contiguous; all samples in seq & in seqhash; tlidx \subseteq seq;
 | 
			
		||||
     seq-number ordered list correct; &c. */
 | 
			
		||||
   quickly: all nodes but open_intv non-empty, non-overlapping and
 | 
			
		||||
   non-contiguous; min & maxp1 of intervals correct; each interval
 | 
			
		||||
   contiguous; all samples in seq & in seqhash; tlidx \subseteq seq;
 | 
			
		||||
   seq-number ordered list correct; &c. */
 | 
			
		||||
  assert (whc->open_intv != NULL);
 | 
			
		||||
  assert (whc->open_intv == ddsrt_avl_find_max (&whc_seq_treedef, &whc->seq));
 | 
			
		||||
  assert (ddsrt_avl_find_succ (&whc_seq_treedef, &whc->seq, whc->open_intv) == NULL);
 | 
			
		||||
| 
						 | 
				
			
			@ -269,7 +267,7 @@ static void check_whc (const struct whc_impl *whc)
 | 
			
		|||
  }
 | 
			
		||||
  assert (whc->maxseq_node == whc_findmax_procedurally (whc));
 | 
			
		||||
 | 
			
		||||
#if !defined(NDEBUG)
 | 
			
		||||
#if !defined (NDEBUG)
 | 
			
		||||
  if (config.enabled_xchecks & DDS_XCHECK_WHC)
 | 
			
		||||
  {
 | 
			
		||||
    struct whc_intvnode *firstintv;
 | 
			
		||||
| 
						 | 
				
			
			@ -295,10 +293,10 @@ static void insert_whcn_in_hash (struct whc_impl *whc, struct whc_node *whcn)
 | 
			
		|||
#if USE_EHH
 | 
			
		||||
  struct whc_seq_entry e = { .seq = whcn->seq, .whcn = whcn };
 | 
			
		||||
  if (!ddsrt_ehh_add (whc->seq_hash, &e))
 | 
			
		||||
    assert(0);
 | 
			
		||||
    assert (0);
 | 
			
		||||
#else
 | 
			
		||||
  if (!ddsrt_hh_add (whc->seq_hash, whcn))
 | 
			
		||||
    assert(0);
 | 
			
		||||
    assert (0);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -307,11 +305,11 @@ static void remove_whcn_from_hash (struct whc_impl *whc, struct whc_node *whcn)
 | 
			
		|||
  /* precondition: whcn is in hash */
 | 
			
		||||
#if USE_EHH
 | 
			
		||||
  struct whc_seq_entry e = { .seq = whcn->seq };
 | 
			
		||||
  if (!ddsrt_ehh_remove(whc->seq_hash, &e))
 | 
			
		||||
    assert(0);
 | 
			
		||||
  if (!ddsrt_ehh_remove (whc->seq_hash, &e))
 | 
			
		||||
    assert (0);
 | 
			
		||||
#else
 | 
			
		||||
  if (!ddsrt_hh_remove(whc->seq_hash, whcn))
 | 
			
		||||
    assert(0);
 | 
			
		||||
  if (!ddsrt_hh_remove (whc->seq_hash, whcn))
 | 
			
		||||
    assert (0);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -319,14 +317,14 @@ static struct whc_node *whc_findseq (const struct whc_impl *whc, seqno_t seq)
 | 
			
		|||
{
 | 
			
		||||
#if USE_EHH
 | 
			
		||||
  struct whc_seq_entry e = { .seq = seq }, *r;
 | 
			
		||||
  if ((r = ddsrt_ehh_lookup(whc->seq_hash, &e)) != NULL)
 | 
			
		||||
  if ((r = ddsrt_ehh_lookup (whc->seq_hash, &e)) != NULL)
 | 
			
		||||
    return r->whcn;
 | 
			
		||||
  else
 | 
			
		||||
    return NULL;
 | 
			
		||||
#else
 | 
			
		||||
  struct whc_node template;
 | 
			
		||||
  template.seq = seq;
 | 
			
		||||
  return ddsrt_hh_lookup(whc->seq_hash, &template);
 | 
			
		||||
  return ddsrt_hh_lookup (whc->seq_hash, &template);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -334,11 +332,11 @@ static struct whc_node *whc_findkey (const struct whc_impl *whc, const struct dd
 | 
			
		|||
{
 | 
			
		||||
  union {
 | 
			
		||||
    struct whc_idxnode idxn;
 | 
			
		||||
    char pad[sizeof(struct whc_idxnode) + sizeof(struct whc_node *)];
 | 
			
		||||
    char pad[sizeof (struct whc_idxnode) + sizeof (struct whc_node *)];
 | 
			
		||||
  } template;
 | 
			
		||||
  struct whc_idxnode *n;
 | 
			
		||||
  check_whc (whc);
 | 
			
		||||
  template.idxn.iid = ddsi_tkmap_lookup(gv.m_tkmap, serdata_key);
 | 
			
		||||
  template.idxn.iid = ddsi_tkmap_lookup (gv.m_tkmap, serdata_key);
 | 
			
		||||
  n = ddsrt_hh_lookup (whc->idx_hash, &template.idxn);
 | 
			
		||||
  if (n == NULL)
 | 
			
		||||
    return NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -349,13 +347,13 @@ static struct whc_node *whc_findkey (const struct whc_impl *whc, const struct dd
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct whc *whc_new (int is_transient_local, unsigned hdepth, unsigned tldepth)
 | 
			
		||||
struct whc *whc_new (int is_transient_local, uint32_t hdepth, uint32_t tldepth)
 | 
			
		||||
{
 | 
			
		||||
  size_t sample_overhead = 80; /* INFO_TS, DATA (estimate), inline QoS */
 | 
			
		||||
  struct whc_impl *whc;
 | 
			
		||||
  struct whc_intvnode *intv;
 | 
			
		||||
 | 
			
		||||
  assert((hdepth == 0 || tldepth <= hdepth) || is_transient_local);
 | 
			
		||||
  assert ((hdepth == 0 || tldepth <= hdepth) || is_transient_local);
 | 
			
		||||
 | 
			
		||||
  whc = ddsrt_malloc (sizeof (*whc));
 | 
			
		||||
  whc->common.ops = &whc_ops;
 | 
			
		||||
| 
						 | 
				
			
			@ -372,11 +370,11 @@ struct whc *whc_new (int is_transient_local, unsigned hdepth, unsigned tldepth)
 | 
			
		|||
#if USE_EHH
 | 
			
		||||
  whc->seq_hash = ddsrt_ehh_new (sizeof (struct whc_seq_entry), 32, whc_seq_entry_hash, whc_seq_entry_eq);
 | 
			
		||||
#else
 | 
			
		||||
  whc->seq_hash = ddsrt_hh_new(32, whc_node_hash, whc_node_eq);
 | 
			
		||||
  whc->seq_hash = ddsrt_hh_new (32, whc_node_hash, whc_node_eq);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (whc->idxdepth > 0)
 | 
			
		||||
    whc->idx_hash = ddsrt_hh_new(32, whc_idxnode_hash_key, whc_idxnode_eq_key);
 | 
			
		||||
    whc->idx_hash = ddsrt_hh_new (32, whc_idxnode_hash_key, whc_idxnode_eq_key);
 | 
			
		||||
  else
 | 
			
		||||
    whc->idx_hash = NULL;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -417,9 +415,9 @@ void whc_default_free (struct whc *whc_generic)
 | 
			
		|||
  {
 | 
			
		||||
    struct ddsrt_hh_iter it;
 | 
			
		||||
    struct whc_idxnode *n;
 | 
			
		||||
    for (n = ddsrt_hh_iter_first(whc->idx_hash, &it); n != NULL; n = ddsrt_hh_iter_next(&it))
 | 
			
		||||
      ddsrt_free(n);
 | 
			
		||||
    ddsrt_hh_free(whc->idx_hash);
 | 
			
		||||
    for (n = ddsrt_hh_iter_first (whc->idx_hash, &it); n != NULL; n = ddsrt_hh_iter_next (&it))
 | 
			
		||||
      ddsrt_free (n);
 | 
			
		||||
    ddsrt_hh_free (whc->idx_hash);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			@ -427,10 +425,10 @@ void whc_default_free (struct whc *whc_generic)
 | 
			
		|||
    while (whcn)
 | 
			
		||||
    {
 | 
			
		||||
      struct whc_node *tmp = whcn;
 | 
			
		||||
/* The compiler doesn't realize that whcn->prev_seq is always initialized. */
 | 
			
		||||
DDSRT_WARNING_MSVC_OFF(6001);
 | 
			
		||||
      /* The compiler doesn't realize that whcn->prev_seq is always initialized. */
 | 
			
		||||
      DDSRT_WARNING_MSVC_OFF (6001);
 | 
			
		||||
      whcn = whcn->prev_seq;
 | 
			
		||||
DDSRT_WARNING_MSVC_ON(6001);
 | 
			
		||||
      DDSRT_WARNING_MSVC_ON (6001);
 | 
			
		||||
      free_whc_node_contents (tmp);
 | 
			
		||||
      ddsrt_free (tmp);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -452,7 +450,7 @@ DDSRT_WARNING_MSVC_ON(6001);
 | 
			
		|||
  ddsrt_free (whc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void get_state_locked(const struct whc_impl *whc, struct whc_state *st)
 | 
			
		||||
static void get_state_locked (const struct whc_impl *whc, struct whc_state *st)
 | 
			
		||||
{
 | 
			
		||||
  if (whc->seq_size == 0)
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			@ -473,12 +471,12 @@ static void get_state_locked(const struct whc_impl *whc, struct whc_state *st)
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void whc_default_get_state(const struct whc *whc_generic, struct whc_state *st)
 | 
			
		||||
static void whc_default_get_state (const struct whc *whc_generic, struct whc_state *st)
 | 
			
		||||
{
 | 
			
		||||
  const struct whc_impl * const whc = (const struct whc_impl *)whc_generic;
 | 
			
		||||
  ddsrt_mutex_lock ((ddsrt_mutex_t *)&whc->lock);
 | 
			
		||||
  check_whc (whc);
 | 
			
		||||
  get_state_locked(whc, st);
 | 
			
		||||
  get_state_locked (whc, st);
 | 
			
		||||
  ddsrt_mutex_unlock ((ddsrt_mutex_t *)&whc->lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -489,8 +487,8 @@ static struct whc_node *find_nextseq_intv (struct whc_intvnode **p_intv, const s
 | 
			
		|||
  if ((n = whc_findseq (whc, seq)) == NULL)
 | 
			
		||||
  {
 | 
			
		||||
    /* don't know seq => lookup interval with min > seq (intervals are
 | 
			
		||||
       contiguous, so if we don't know seq, an interval [X,Y) with X <
 | 
			
		||||
       SEQ < Y can't exist */
 | 
			
		||||
     contiguous, so if we don't know seq, an interval [X,Y) with X <
 | 
			
		||||
     SEQ < Y can't exist */
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
    {
 | 
			
		||||
      struct whc_intvnode *predintv = ddsrt_avl_lookup_pred_eq (&whc_seq_treedef, &whc->seq, &seq);
 | 
			
		||||
| 
						 | 
				
			
			@ -551,13 +549,12 @@ static void delete_one_sample_from_idx (struct whc_impl *whc, struct whc_node *w
 | 
			
		|||
  else
 | 
			
		||||
  {
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
    unsigned i;
 | 
			
		||||
    for (i = 0; i < whc->idxdepth; i++)
 | 
			
		||||
    for (uint32_t i = 0; i < whc->idxdepth; i++)
 | 
			
		||||
      assert (i == idxn->headidx || idxn->hist[i] == NULL);
 | 
			
		||||
#endif
 | 
			
		||||
    if (!ddsrt_hh_remove (whc->idx_hash, idxn))
 | 
			
		||||
      assert (0);
 | 
			
		||||
    ddsi_tkmap_instance_unref(idxn->tk);
 | 
			
		||||
    ddsi_tkmap_instance_unref (idxn->tk);
 | 
			
		||||
    ddsrt_free (idxn);
 | 
			
		||||
  }
 | 
			
		||||
  whcn->idxnode = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -565,8 +562,7 @@ static void delete_one_sample_from_idx (struct whc_impl *whc, struct whc_node *w
 | 
			
		|||
 | 
			
		||||
static void free_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_idxnode *idxn)
 | 
			
		||||
{
 | 
			
		||||
  unsigned i;
 | 
			
		||||
  for (i = 0; i < whc->idxdepth; i++)
 | 
			
		||||
  for (uint32_t i = 0; i < whc->idxdepth; i++)
 | 
			
		||||
  {
 | 
			
		||||
    if (idxn->hist[i])
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -574,13 +570,13 @@ static void free_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_s
 | 
			
		|||
      oldn->idxnode = NULL;
 | 
			
		||||
      if (oldn->seq <= max_drop_seq)
 | 
			
		||||
      {
 | 
			
		||||
        DDS_LOG(DDS_LC_WHC, "  prune tl whcn %p\n", (void *)oldn);
 | 
			
		||||
        assert(oldn != whc->maxseq_node);
 | 
			
		||||
        DDS_LOG (DDS_LC_WHC, "  prune tl whcn %p\n", (void *)oldn);
 | 
			
		||||
        assert (oldn != whc->maxseq_node);
 | 
			
		||||
        whc_delete_one (whc, oldn);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  ddsrt_free(idxn);
 | 
			
		||||
  ddsrt_free (idxn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void delete_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_idxnode *idxn)
 | 
			
		||||
| 
						 | 
				
			
			@ -590,34 +586,34 @@ static void delete_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop
 | 
			
		|||
  free_one_instance_from_idx (whc, max_drop_seq, idxn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int whcn_in_tlidx (const struct whc_impl *whc, const struct whc_idxnode *idxn, unsigned pos)
 | 
			
		||||
static int whcn_in_tlidx (const struct whc_impl *whc, const struct whc_idxnode *idxn, uint32_t pos)
 | 
			
		||||
{
 | 
			
		||||
  if (idxn == NULL)
 | 
			
		||||
    return 0;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    unsigned d = (idxn->headidx + (pos > idxn->headidx ? whc->idxdepth : 0)) - pos;
 | 
			
		||||
    uint32_t d = (idxn->headidx + (pos > idxn->headidx ? whc->idxdepth : 0)) - pos;
 | 
			
		||||
    assert (d < whc->idxdepth);
 | 
			
		||||
    return d < whc->tldepth;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned whc_default_downgrade_to_volatile (struct whc *whc_generic, struct whc_state *st)
 | 
			
		||||
static uint32_t whc_default_downgrade_to_volatile (struct whc *whc_generic, struct whc_state *st)
 | 
			
		||||
{
 | 
			
		||||
  struct whc_impl * const whc = (struct whc_impl *)whc_generic;
 | 
			
		||||
  seqno_t old_max_drop_seq;
 | 
			
		||||
  struct whc_node *deferred_free_list;
 | 
			
		||||
  unsigned cnt;
 | 
			
		||||
  uint32_t cnt;
 | 
			
		||||
 | 
			
		||||
  /* We only remove them from whc->tlidx: we don't remove them from
 | 
			
		||||
     whc->seq yet.  That'll happen eventually.  */
 | 
			
		||||
   whc->seq yet.  That'll happen eventually.  */
 | 
			
		||||
  ddsrt_mutex_lock (&whc->lock);
 | 
			
		||||
  check_whc (whc);
 | 
			
		||||
 | 
			
		||||
  if (whc->idxdepth == 0)
 | 
			
		||||
  {
 | 
			
		||||
    /* if not maintaining an index at all, this is nonsense */
 | 
			
		||||
    get_state_locked(whc, st);
 | 
			
		||||
    get_state_locked (whc, st);
 | 
			
		||||
    ddsrt_mutex_unlock (&whc->lock);
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -625,29 +621,29 @@ static unsigned whc_default_downgrade_to_volatile (struct whc *whc_generic, stru
 | 
			
		|||
  assert (!whc->is_transient_local);
 | 
			
		||||
  if (whc->tldepth > 0)
 | 
			
		||||
  {
 | 
			
		||||
    assert(whc->hdepth == 0 || whc->tldepth <= whc->hdepth);
 | 
			
		||||
    assert (whc->hdepth == 0 || whc->tldepth <= whc->hdepth);
 | 
			
		||||
    whc->tldepth = 0;
 | 
			
		||||
    if (whc->hdepth == 0)
 | 
			
		||||
    {
 | 
			
		||||
      struct ddsrt_hh_iter it;
 | 
			
		||||
      struct whc_idxnode *n;
 | 
			
		||||
      for (n = ddsrt_hh_iter_first(whc->idx_hash, &it); n != NULL; n = ddsrt_hh_iter_next(&it))
 | 
			
		||||
      for (n = ddsrt_hh_iter_first (whc->idx_hash, &it); n != NULL; n = ddsrt_hh_iter_next (&it))
 | 
			
		||||
        free_one_instance_from_idx (whc, 0, n);
 | 
			
		||||
      ddsrt_hh_free(whc->idx_hash);
 | 
			
		||||
      ddsrt_hh_free (whc->idx_hash);
 | 
			
		||||
      whc->idxdepth = 0;
 | 
			
		||||
      whc->idx_hash = NULL;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Immediately drop them from the WHC (used to delay it until the
 | 
			
		||||
     next ack); but need to make sure remove_acked_messages processes
 | 
			
		||||
     them all. */
 | 
			
		||||
   next ack); but need to make sure remove_acked_messages processes
 | 
			
		||||
   them all. */
 | 
			
		||||
  old_max_drop_seq = whc->max_drop_seq;
 | 
			
		||||
  whc->max_drop_seq = 0;
 | 
			
		||||
  cnt = whc_default_remove_acked_messages_full (whc, old_max_drop_seq, &deferred_free_list);
 | 
			
		||||
  whc_default_free_deferred_free_list (whc_generic, deferred_free_list);
 | 
			
		||||
  assert (whc->max_drop_seq == old_max_drop_seq);
 | 
			
		||||
  get_state_locked(whc, st);
 | 
			
		||||
  get_state_locked (whc, st);
 | 
			
		||||
  ddsrt_mutex_unlock (&whc->lock);
 | 
			
		||||
  return cnt;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -661,14 +657,14 @@ static size_t whcn_size (const struct whc_impl *whc, const struct whc_node *whcn
 | 
			
		|||
static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_intv, struct whc_node **p_whcn)
 | 
			
		||||
{
 | 
			
		||||
  /* Removes *p_whcn, possibly deleting or splitting *p_intv, as the
 | 
			
		||||
     case may be.  Does *NOT* update whc->seq_size.  *p_intv must be
 | 
			
		||||
     the interval containing *p_whcn (&& both must actually exist).
 | 
			
		||||
   case may be.  Does *NOT* update whc->seq_size.  *p_intv must be
 | 
			
		||||
   the interval containing *p_whcn (&& both must actually exist).
 | 
			
		||||
 | 
			
		||||
     Returns:
 | 
			
		||||
     - 0 if delete failed (only possible cause is memory exhaustion),
 | 
			
		||||
     in which case *p_intv & *p_whcn are undefined;
 | 
			
		||||
     - 1 if successful, in which case *p_intv & *p_whcn are set
 | 
			
		||||
     correctly for the next sample in sequence number order */
 | 
			
		||||
   Returns:
 | 
			
		||||
   - 0 if delete failed (only possible cause is memory exhaustion),
 | 
			
		||||
   in which case *p_intv & *p_whcn are undefined;
 | 
			
		||||
   - 1 if successful, in which case *p_intv & *p_whcn are set
 | 
			
		||||
   correctly for the next sample in sequence number order */
 | 
			
		||||
  struct whc_intvnode *intv = *p_intv;
 | 
			
		||||
  struct whc_node *whcn = *p_whcn;
 | 
			
		||||
  assert (whcn->seq >= intv->min && whcn->seq < intv->maxp1);
 | 
			
		||||
| 
						 | 
				
			
			@ -685,13 +681,13 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  /* Take it out of seqhash; deleting it from the list ordered on
 | 
			
		||||
     sequence numbers is left to the caller (it has to be done unconditionally,
 | 
			
		||||
     but remove_acked_messages defers it until the end or a skipped node). */
 | 
			
		||||
   sequence numbers is left to the caller (it has to be done unconditionally,
 | 
			
		||||
   but remove_acked_messages defers it until the end or a skipped node). */
 | 
			
		||||
  remove_whcn_from_hash (whc, whcn);
 | 
			
		||||
 | 
			
		||||
  /* We may have introduced a hole & have to split the interval
 | 
			
		||||
     node, or we may have nibbled of the first one, or even the
 | 
			
		||||
     last one. */
 | 
			
		||||
   node, or we may have nibbled of the first one, or even the
 | 
			
		||||
   last one. */
 | 
			
		||||
  if (whcn == intv->first)
 | 
			
		||||
  {
 | 
			
		||||
    if (whcn == intv->last && intv != whc->open_intv)
 | 
			
		||||
| 
						 | 
				
			
			@ -714,7 +710,7 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i
 | 
			
		|||
  else if (whcn == intv->last)
 | 
			
		||||
  {
 | 
			
		||||
    /* well, at least it isn't the first one & so the interval is
 | 
			
		||||
       still non-empty and we don't have to drop the interval */
 | 
			
		||||
     still non-empty and we don't have to drop the interval */
 | 
			
		||||
    assert (intv->min < whcn->seq);
 | 
			
		||||
    assert (whcn->prev_seq);
 | 
			
		||||
    assert (whcn->prev_seq->seq + 1 == whcn->seq);
 | 
			
		||||
| 
						 | 
				
			
			@ -725,9 +721,9 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i
 | 
			
		|||
  else
 | 
			
		||||
  {
 | 
			
		||||
    /* somewhere in the middle => split the interval (ideally,
 | 
			
		||||
       would split it lazily, but it really is a transient-local
 | 
			
		||||
       issue only, and so we can (for now) get away with splitting
 | 
			
		||||
       it greedily */
 | 
			
		||||
     would split it lazily, but it really is a transient-local
 | 
			
		||||
     issue only, and so we can (for now) get away with splitting
 | 
			
		||||
     it greedily */
 | 
			
		||||
    struct whc_intvnode *new_intv;
 | 
			
		||||
    ddsrt_avl_ipath_t path;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -746,7 +742,7 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i
 | 
			
		|||
    assert (new_intv->min < new_intv->maxp1);
 | 
			
		||||
 | 
			
		||||
    /* insert new node & continue the loop with intv set to the
 | 
			
		||||
       new interval */
 | 
			
		||||
     new interval */
 | 
			
		||||
    if (ddsrt_avl_lookup_ipath (&whc_seq_treedef, &whc->seq, &new_intv->min, &path) != NULL)
 | 
			
		||||
      assert (0);
 | 
			
		||||
    ddsrt_avl_insert_ipath (&whc_seq_treedef, &whc->seq, new_intv, &path);
 | 
			
		||||
| 
						 | 
				
			
			@ -801,11 +797,11 @@ static void whc_default_free_deferred_free_list (struct whc *whc_generic, struct
 | 
			
		|||
  free_deferred_free_list (deferred_free_list);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list)
 | 
			
		||||
static uint32_t whc_default_remove_acked_messages_noidx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list)
 | 
			
		||||
{
 | 
			
		||||
  struct whc_intvnode *intv;
 | 
			
		||||
  struct whc_node *whcn;
 | 
			
		||||
  unsigned ndropped = 0;
 | 
			
		||||
  uint32_t ndropped = 0;
 | 
			
		||||
 | 
			
		||||
  /* In the trivial case of an empty WHC, get out quickly */
 | 
			
		||||
  if (max_drop_seq <= whc->max_drop_seq || whc->maxseq_node == NULL)
 | 
			
		||||
| 
						 | 
				
			
			@ -817,7 +813,7 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  /* If simple, we have always dropped everything up to whc->max_drop_seq,
 | 
			
		||||
     and there can only be a single interval */
 | 
			
		||||
   and there can only be a single interval */
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
  whcn = find_nextseq_intv (&intv, whc, whc->max_drop_seq);
 | 
			
		||||
  assert (whcn == NULL || whcn->prev_seq == NULL);
 | 
			
		||||
| 
						 | 
				
			
			@ -826,14 +822,14 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s
 | 
			
		|||
  intv = whc->open_intv;
 | 
			
		||||
 | 
			
		||||
  /* Drop everything up to and including max_drop_seq, or absent that one,
 | 
			
		||||
     the highest available sequence number (which then must be less) */
 | 
			
		||||
   the highest available sequence number (which then must be less) */
 | 
			
		||||
  if ((whcn = whc_findseq (whc, max_drop_seq)) == NULL)
 | 
			
		||||
  {
 | 
			
		||||
    if (max_drop_seq < intv->min)
 | 
			
		||||
    {
 | 
			
		||||
      /* at startup, whc->max_drop_seq = 0 and reader states have max ack'd seq taken from wr->seq;
 | 
			
		||||
         so if multiple readers are matched and the writer runs ahead of the readers, for the first
 | 
			
		||||
         ack, whc->max_drop_seq < max_drop_seq = MIN(readers max ack) < intv->min */
 | 
			
		||||
       so if multiple readers are matched and the writer runs ahead of the readers, for the first
 | 
			
		||||
       ack, whc->max_drop_seq < max_drop_seq = MIN (readers max ack) < intv->min */
 | 
			
		||||
      if (max_drop_seq > whc->max_drop_seq)
 | 
			
		||||
        whc->max_drop_seq = max_drop_seq;
 | 
			
		||||
      *deferred_free_list = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -847,7 +843,7 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  *deferred_free_list = intv->first;
 | 
			
		||||
  ndropped = (unsigned) (whcn->seq - intv->min + 1);
 | 
			
		||||
  ndropped = (uint32_t) (whcn->seq - intv->min + 1);
 | 
			
		||||
 | 
			
		||||
  intv->first = whcn->next_seq;
 | 
			
		||||
  intv->min = max_drop_seq + 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -877,18 +873,18 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s
 | 
			
		|||
  return ndropped;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list)
 | 
			
		||||
static uint32_t whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list)
 | 
			
		||||
{
 | 
			
		||||
  struct whc_intvnode *intv;
 | 
			
		||||
  struct whc_node *whcn;
 | 
			
		||||
  struct whc_node *prev_seq;
 | 
			
		||||
  struct whc_node deferred_list_head, *last_to_free = &deferred_list_head;
 | 
			
		||||
  unsigned ndropped = 0;
 | 
			
		||||
  uint32_t ndropped = 0;
 | 
			
		||||
 | 
			
		||||
  if (whc->is_transient_local && whc->tldepth == 0)
 | 
			
		||||
  {
 | 
			
		||||
    /* KEEP_ALL on transient local, so we can never ever delete anything */
 | 
			
		||||
    DDS_LOG(DDS_LC_WHC, "  KEEP_ALL transient-local: do nothing\n");
 | 
			
		||||
    DDS_LOG (DDS_LC_WHC, "  KEEP_ALL transient-local: do nothing\n");
 | 
			
		||||
    *deferred_free_list = NULL;
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -898,11 +894,11 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se
 | 
			
		|||
  prev_seq = whcn ? whcn->prev_seq : NULL;
 | 
			
		||||
  while (whcn && whcn->seq <= max_drop_seq)
 | 
			
		||||
  {
 | 
			
		||||
    DDS_LOG(DDS_LC_WHC, "  whcn %p %"PRId64, (void *) whcn, whcn->seq);
 | 
			
		||||
    if (whcn_in_tlidx(whc, whcn->idxnode, whcn->idxnode_pos))
 | 
			
		||||
    DDS_LOG (DDS_LC_WHC, "  whcn %p %"PRId64, (void *) whcn, whcn->seq);
 | 
			
		||||
    if (whcn_in_tlidx (whc, whcn->idxnode, whcn->idxnode_pos))
 | 
			
		||||
    {
 | 
			
		||||
      /* quickly skip over samples in tlidx */
 | 
			
		||||
      DDS_LOG(DDS_LC_WHC, " tl:keep");
 | 
			
		||||
      DDS_LOG (DDS_LC_WHC, " tl:keep");
 | 
			
		||||
      if (whcn->unacked)
 | 
			
		||||
      {
 | 
			
		||||
        assert (whc->unacked_bytes >= whcn->size);
 | 
			
		||||
| 
						 | 
				
			
			@ -920,13 +916,13 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se
 | 
			
		|||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      DDS_LOG(DDS_LC_WHC, " delete");
 | 
			
		||||
      DDS_LOG (DDS_LC_WHC, " delete");
 | 
			
		||||
      last_to_free->next_seq = whcn;
 | 
			
		||||
      last_to_free = last_to_free->next_seq;
 | 
			
		||||
      whc_delete_one_intv (whc, &intv, &whcn);
 | 
			
		||||
      ndropped++;
 | 
			
		||||
    }
 | 
			
		||||
    DDS_LOG(DDS_LC_WHC, "\n");
 | 
			
		||||
    DDS_LOG (DDS_LC_WHC, "\n");
 | 
			
		||||
  }
 | 
			
		||||
  if (prev_seq)
 | 
			
		||||
    prev_seq->next_seq = whcn;
 | 
			
		||||
| 
						 | 
				
			
			@ -936,32 +932,32 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se
 | 
			
		|||
  *deferred_free_list = deferred_list_head.next_seq;
 | 
			
		||||
 | 
			
		||||
  /* If the history is deeper than durability_service.history (but not KEEP_ALL), then there
 | 
			
		||||
     may be old samples in this instance, samples that were retained because they were within
 | 
			
		||||
     the T-L history but that are not anymore. Writing new samples will eventually push these
 | 
			
		||||
     out, but if the difference is large and the update rate low, it may take a long time.
 | 
			
		||||
     Thus, we had better prune them. */
 | 
			
		||||
   may be old samples in this instance, samples that were retained because they were within
 | 
			
		||||
   the T-L history but that are not anymore. Writing new samples will eventually push these
 | 
			
		||||
   out, but if the difference is large and the update rate low, it may take a long time.
 | 
			
		||||
   Thus, we had better prune them. */
 | 
			
		||||
  if (whc->tldepth > 0 && whc->idxdepth > whc->tldepth)
 | 
			
		||||
  {
 | 
			
		||||
    assert(whc->hdepth == whc->idxdepth);
 | 
			
		||||
    DDS_LOG(DDS_LC_WHC, "  idxdepth %u > tldepth %u > 0 -- must prune\n", whc->idxdepth, whc->tldepth);
 | 
			
		||||
    assert (whc->hdepth == whc->idxdepth);
 | 
			
		||||
    DDS_LOG (DDS_LC_WHC, "  idxdepth %"PRIu32" > tldepth %"PRIu32" > 0 -- must prune\n", whc->idxdepth, whc->tldepth);
 | 
			
		||||
 | 
			
		||||
    /* Do a second pass over the sequence number range we just processed: this time we only
 | 
			
		||||
       encounter samples that were retained because of the transient-local durability setting
 | 
			
		||||
       (the rest has been dropped already) and we prune old samples in the instance */
 | 
			
		||||
     encounter samples that were retained because of the transient-local durability setting
 | 
			
		||||
     (the rest has been dropped already) and we prune old samples in the instance */
 | 
			
		||||
    whcn = find_nextseq_intv (&intv, whc, whc->max_drop_seq);
 | 
			
		||||
    while (whcn && whcn->seq <= max_drop_seq)
 | 
			
		||||
    {
 | 
			
		||||
      struct whc_idxnode * const idxn = whcn->idxnode;
 | 
			
		||||
      unsigned cnt, idx;
 | 
			
		||||
      uint32_t cnt, idx;
 | 
			
		||||
 | 
			
		||||
      DDS_LOG(DDS_LC_WHC, "  whcn %p %"PRId64" idxn %p prune_seq %"PRId64":", (void *)whcn, whcn->seq, (void *)idxn, idxn->prune_seq);
 | 
			
		||||
      DDS_LOG (DDS_LC_WHC, "  whcn %p %"PRId64" idxn %p prune_seq %"PRId64":", (void *) whcn, whcn->seq, (void *) idxn, idxn->prune_seq);
 | 
			
		||||
 | 
			
		||||
      assert(whcn_in_tlidx(whc, idxn, whcn->idxnode_pos));
 | 
			
		||||
      assert (whcn_in_tlidx (whc, idxn, whcn->idxnode_pos));
 | 
			
		||||
      assert (idxn->prune_seq <= max_drop_seq);
 | 
			
		||||
 | 
			
		||||
      if (idxn->prune_seq == max_drop_seq)
 | 
			
		||||
      {
 | 
			
		||||
        DDS_LOG(DDS_LC_WHC, " already pruned\n");
 | 
			
		||||
        DDS_LOG (DDS_LC_WHC, " already pruned\n");
 | 
			
		||||
        whcn = whcn->next_seq;
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -977,27 +973,27 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se
 | 
			
		|||
        if ((oldn = idxn->hist[idx]) != NULL)
 | 
			
		||||
        {
 | 
			
		||||
          /* Delete it - but this may not result in deleting the index node as
 | 
			
		||||
             there must still be a more recent one available */
 | 
			
		||||
           there must still be a more recent one available */
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
          struct whc_node whcn_template;
 | 
			
		||||
          union {
 | 
			
		||||
            struct whc_idxnode idxn;
 | 
			
		||||
            char pad[sizeof(struct whc_idxnode) + sizeof(struct whc_node *)];
 | 
			
		||||
            char pad[sizeof (struct whc_idxnode) + sizeof (struct whc_node *)];
 | 
			
		||||
          } template;
 | 
			
		||||
          template.idxn.headidx = 0;
 | 
			
		||||
          template.idxn.hist[0] = &whcn_template;
 | 
			
		||||
          whcn_template.serdata = ddsi_serdata_ref(oldn->serdata);
 | 
			
		||||
          assert(oldn->seq < whcn->seq);
 | 
			
		||||
          whcn_template.serdata = ddsi_serdata_ref (oldn->serdata);
 | 
			
		||||
          assert (oldn->seq < whcn->seq);
 | 
			
		||||
#endif
 | 
			
		||||
          DDS_LOG(DDS_LC_WHC, " del %p %"PRId64, (void *) oldn, oldn->seq);
 | 
			
		||||
          DDS_LOG (DDS_LC_WHC, " del %p %"PRId64, (void *) oldn, oldn->seq);
 | 
			
		||||
          whc_delete_one (whc, oldn);
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
          assert(ddsrt_hh_lookup(whc->idx_hash, &template) == idxn);
 | 
			
		||||
          ddsi_serdata_unref(whcn_template.serdata);
 | 
			
		||||
          assert (ddsrt_hh_lookup (whc->idx_hash, &template) == idxn);
 | 
			
		||||
          ddsi_serdata_unref (whcn_template.serdata);
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      DDS_LOG(DDS_LC_WHC, "\n");
 | 
			
		||||
      DDS_LOG (DDS_LC_WHC, "\n");
 | 
			
		||||
      whcn = whcn->next_seq;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -1011,22 +1007,22 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se
 | 
			
		|||
  return ndropped;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned whc_default_remove_acked_messages (struct whc *whc_generic, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list)
 | 
			
		||||
static uint32_t whc_default_remove_acked_messages (struct whc *whc_generic, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list)
 | 
			
		||||
{
 | 
			
		||||
  struct whc_impl * const whc = (struct whc_impl *)whc_generic;
 | 
			
		||||
  unsigned cnt;
 | 
			
		||||
  uint32_t cnt;
 | 
			
		||||
 | 
			
		||||
  ddsrt_mutex_lock (&whc->lock);
 | 
			
		||||
  assert (max_drop_seq < MAX_SEQ_NUMBER);
 | 
			
		||||
  assert (max_drop_seq >= whc->max_drop_seq);
 | 
			
		||||
 | 
			
		||||
  if (dds_get_log_mask() & DDS_LC_WHC)
 | 
			
		||||
  if (dds_get_log_mask () & DDS_LC_WHC)
 | 
			
		||||
  {
 | 
			
		||||
    struct whc_state tmp;
 | 
			
		||||
    get_state_locked(whc, &tmp);
 | 
			
		||||
    DDS_LOG(DDS_LC_WHC, "whc_default_remove_acked_messages(%p max_drop_seq %"PRId64")\n", (void *)whc, max_drop_seq);
 | 
			
		||||
    DDS_LOG(DDS_LC_WHC, "  whc: [%"PRId64",%"PRId64"] max_drop_seq %"PRId64" h %u tl %u\n",
 | 
			
		||||
               tmp.min_seq, tmp.max_seq, whc->max_drop_seq, whc->hdepth, whc->tldepth);
 | 
			
		||||
    get_state_locked (whc, &tmp);
 | 
			
		||||
    DDS_LOG (DDS_LC_WHC, "whc_default_remove_acked_messages(%p max_drop_seq %"PRId64")\n", (void *)whc, max_drop_seq);
 | 
			
		||||
    DDS_LOG (DDS_LC_WHC, "  whc: [%"PRId64",%"PRId64"] max_drop_seq %"PRId64" h %"PRIu32" tl %"PRIu32"\n",
 | 
			
		||||
             tmp.min_seq, tmp.max_seq, whc->max_drop_seq, whc->hdepth, whc->tldepth);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  check_whc (whc);
 | 
			
		||||
| 
						 | 
				
			
			@ -1035,7 +1031,7 @@ static unsigned whc_default_remove_acked_messages (struct whc *whc_generic, seqn
 | 
			
		|||
    cnt = whc_default_remove_acked_messages_noidx (whc, max_drop_seq, deferred_free_list);
 | 
			
		||||
  else
 | 
			
		||||
    cnt = whc_default_remove_acked_messages_full (whc, max_drop_seq, deferred_free_list);
 | 
			
		||||
  get_state_locked(whc, whcst);
 | 
			
		||||
  get_state_locked (whc, whcst);
 | 
			
		||||
  ddsrt_mutex_unlock (&whc->lock);
 | 
			
		||||
  return cnt;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1108,38 +1104,39 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se
 | 
			
		|||
  struct whc_idxnode *idxn;
 | 
			
		||||
  union {
 | 
			
		||||
    struct whc_idxnode idxn;
 | 
			
		||||
    char pad[sizeof(struct whc_idxnode) + sizeof(struct whc_node *)];
 | 
			
		||||
    char pad[sizeof (struct whc_idxnode) + sizeof (struct whc_node *)];
 | 
			
		||||
  } template;
 | 
			
		||||
 | 
			
		||||
  ddsrt_mutex_lock (&whc->lock);
 | 
			
		||||
  check_whc (whc);
 | 
			
		||||
 | 
			
		||||
  if (dds_get_log_mask() & DDS_LC_WHC)
 | 
			
		||||
  if (dds_get_log_mask () & DDS_LC_WHC)
 | 
			
		||||
  {
 | 
			
		||||
    struct whc_state whcst;
 | 
			
		||||
    get_state_locked(whc, &whcst);
 | 
			
		||||
    DDS_LOG(DDS_LC_WHC, "whc_default_insert(%p max_drop_seq %"PRId64" seq %"PRId64" plist %p serdata %p:%"PRIx32")\n", (void *)whc, max_drop_seq, seq, (void*)plist, (void*)serdata, serdata->hash);
 | 
			
		||||
    DDS_LOG(DDS_LC_WHC, "  whc: [%"PRId64",%"PRId64"] max_drop_seq %"PRId64" h %u tl %u\n",
 | 
			
		||||
               whcst.min_seq, whcst.max_seq, whc->max_drop_seq, whc->hdepth, whc->tldepth);
 | 
			
		||||
    get_state_locked (whc, &whcst);
 | 
			
		||||
    DDS_LOG (DDS_LC_WHC, "whc_default_insert(%p max_drop_seq %"PRId64" seq %"PRId64" plist %p serdata %p:%"PRIx32")\n",
 | 
			
		||||
             (void *)whc, max_drop_seq, seq, (void*)plist, (void*)serdata, serdata->hash);
 | 
			
		||||
    DDS_LOG (DDS_LC_WHC, "  whc: [%"PRId64",%"PRId64"] max_drop_seq %"PRId64" h %"PRIu32" tl %"PRIu32"\n",
 | 
			
		||||
             whcst.min_seq, whcst.max_seq, whc->max_drop_seq, whc->hdepth, whc->tldepth);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  assert (max_drop_seq < MAX_SEQ_NUMBER);
 | 
			
		||||
  assert (max_drop_seq >= whc->max_drop_seq);
 | 
			
		||||
 | 
			
		||||
  /* Seq must be greater than what is currently stored. Usually it'll
 | 
			
		||||
     be the next sequence number, but if there are no readers
 | 
			
		||||
     temporarily, a gap may be among the possibilities */
 | 
			
		||||
   be the next sequence number, but if there are no readers
 | 
			
		||||
   temporarily, a gap may be among the possibilities */
 | 
			
		||||
  assert (whc->seq_size == 0 || seq > whc->maxseq_node->seq);
 | 
			
		||||
 | 
			
		||||
  /* Always insert in seq admin */
 | 
			
		||||
  newn = whc_default_insert_seq (whc, max_drop_seq, seq, plist, serdata);
 | 
			
		||||
 | 
			
		||||
  DDS_LOG(DDS_LC_WHC, "  whcn %p:", (void*)newn);
 | 
			
		||||
  DDS_LOG (DDS_LC_WHC, "  whcn %p:", (void*)newn);
 | 
			
		||||
 | 
			
		||||
  /* Special case of empty data (such as commit messages) can't go into index, and if we're not maintaining an index, we're done, too */
 | 
			
		||||
  if (serdata->kind == SDK_EMPTY || whc->idxdepth == 0)
 | 
			
		||||
  {
 | 
			
		||||
    DDS_LOG(DDS_LC_WHC, " empty or no hist\n");
 | 
			
		||||
    DDS_LOG (DDS_LC_WHC, " empty or no hist\n");
 | 
			
		||||
    ddsrt_mutex_unlock (&whc->lock);
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -1148,15 +1145,15 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se
 | 
			
		|||
  if ((idxn = ddsrt_hh_lookup (whc->idx_hash, &template)) != NULL)
 | 
			
		||||
  {
 | 
			
		||||
    /* Unregisters cause deleting of index entry, non-unregister of adding/overwriting in history */
 | 
			
		||||
    DDS_LOG(DDS_LC_WHC, " idxn %p", (void *)idxn);
 | 
			
		||||
    DDS_LOG (DDS_LC_WHC, " idxn %p", (void *)idxn);
 | 
			
		||||
    if (serdata->statusinfo & NN_STATUSINFO_UNREGISTER)
 | 
			
		||||
    {
 | 
			
		||||
      DDS_LOG(DDS_LC_WHC, " unreg:delete\n");
 | 
			
		||||
      DDS_LOG (DDS_LC_WHC, " unreg:delete\n");
 | 
			
		||||
      delete_one_instance_from_idx (whc, max_drop_seq, idxn);
 | 
			
		||||
      if (newn->seq <= max_drop_seq)
 | 
			
		||||
      {
 | 
			
		||||
        struct whc_node *prev_seq = newn->prev_seq;
 | 
			
		||||
        DDS_LOG(DDS_LC_WHC, " unreg:seq <= max_drop_seq: delete newn\n");
 | 
			
		||||
        DDS_LOG (DDS_LC_WHC, " unreg:seq <= max_drop_seq: delete newn\n");
 | 
			
		||||
        whc_delete_one (whc, newn);
 | 
			
		||||
        whc->maxseq_node = prev_seq;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -1168,7 +1165,7 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se
 | 
			
		|||
        idxn->headidx = 0;
 | 
			
		||||
      if ((oldn = idxn->hist[idxn->headidx]) != NULL)
 | 
			
		||||
      {
 | 
			
		||||
        DDS_LOG(DDS_LC_WHC, " overwrite whcn %p", (void *)oldn);
 | 
			
		||||
        DDS_LOG (DDS_LC_WHC, " overwrite whcn %p", (void *)oldn);
 | 
			
		||||
        oldn->idxnode = NULL;
 | 
			
		||||
      }
 | 
			
		||||
      idxn->hist[idxn->headidx] = newn;
 | 
			
		||||
| 
						 | 
				
			
			@ -1177,46 +1174,45 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se
 | 
			
		|||
 | 
			
		||||
      if (oldn && (whc->hdepth > 0 || oldn->seq <= max_drop_seq))
 | 
			
		||||
      {
 | 
			
		||||
        DDS_LOG(DDS_LC_WHC, " prune whcn %p", (void *)oldn);
 | 
			
		||||
        assert(oldn != whc->maxseq_node);
 | 
			
		||||
        DDS_LOG (DDS_LC_WHC, " prune whcn %p", (void *)oldn);
 | 
			
		||||
        assert (oldn != whc->maxseq_node);
 | 
			
		||||
        whc_delete_one (whc, oldn);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /* Special case for dropping everything beyond T-L history when the new sample is being
 | 
			
		||||
         auto-acknowledged (for lack of reliable readers), and the keep-last T-L history is
 | 
			
		||||
         shallower than the keep-last regular history (normal path handles this via pruning in
 | 
			
		||||
         whc_default_remove_acked_messages, but that never happens when there are no readers). */
 | 
			
		||||
       auto-acknowledged (for lack of reliable readers), and the keep-last T-L history is
 | 
			
		||||
       shallower than the keep-last regular history (normal path handles this via pruning in
 | 
			
		||||
       whc_default_remove_acked_messages, but that never happens when there are no readers). */
 | 
			
		||||
      if (seq <= max_drop_seq && whc->tldepth > 0 && whc->idxdepth > whc->tldepth)
 | 
			
		||||
      {
 | 
			
		||||
        unsigned pos = idxn->headidx + whc->idxdepth - whc->tldepth;
 | 
			
		||||
        uint32_t pos = idxn->headidx + whc->idxdepth - whc->tldepth;
 | 
			
		||||
        if (pos >= whc->idxdepth)
 | 
			
		||||
          pos -= whc->idxdepth;
 | 
			
		||||
        if ((oldn = idxn->hist[pos]) != NULL)
 | 
			
		||||
        {
 | 
			
		||||
          DDS_LOG(DDS_LC_WHC, " prune tl whcn %p", (void *)oldn);
 | 
			
		||||
          assert(oldn != whc->maxseq_node);
 | 
			
		||||
          DDS_LOG (DDS_LC_WHC, " prune tl whcn %p", (void *)oldn);
 | 
			
		||||
          assert (oldn != whc->maxseq_node);
 | 
			
		||||
          whc_delete_one (whc, oldn);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      DDS_LOG(DDS_LC_WHC, "\n");
 | 
			
		||||
      DDS_LOG (DDS_LC_WHC, "\n");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    DDS_LOG(DDS_LC_WHC, " newkey");
 | 
			
		||||
    DDS_LOG (DDS_LC_WHC, " newkey");
 | 
			
		||||
    /* Ignore unregisters, but insert everything else */
 | 
			
		||||
    if (!(serdata->statusinfo & NN_STATUSINFO_UNREGISTER))
 | 
			
		||||
    {
 | 
			
		||||
      unsigned i;
 | 
			
		||||
      idxn = ddsrt_malloc (sizeof (*idxn) + whc->idxdepth * sizeof (idxn->hist[0]));
 | 
			
		||||
      DDS_LOG(DDS_LC_WHC, " idxn %p", (void *)idxn);
 | 
			
		||||
      ddsi_tkmap_instance_ref(tk);
 | 
			
		||||
      DDS_LOG (DDS_LC_WHC, " idxn %p", (void *)idxn);
 | 
			
		||||
      ddsi_tkmap_instance_ref (tk);
 | 
			
		||||
      idxn->iid = tk->m_iid;
 | 
			
		||||
      idxn->tk = tk;
 | 
			
		||||
      idxn->prune_seq = 0;
 | 
			
		||||
      idxn->headidx = 0;
 | 
			
		||||
      idxn->hist[0] = newn;
 | 
			
		||||
      for (i = 1; i < whc->idxdepth; i++)
 | 
			
		||||
      for (uint32_t i = 1; i < whc->idxdepth; i++)
 | 
			
		||||
        idxn->hist[i] = NULL;
 | 
			
		||||
      newn->idxnode = idxn;
 | 
			
		||||
      newn->idxnode_pos = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1225,24 +1221,24 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se
 | 
			
		|||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      DDS_LOG(DDS_LC_WHC, " unreg:skip");
 | 
			
		||||
      DDS_LOG (DDS_LC_WHC, " unreg:skip");
 | 
			
		||||
      if (newn->seq <= max_drop_seq)
 | 
			
		||||
      {
 | 
			
		||||
        struct whc_node *prev_seq = newn->prev_seq;
 | 
			
		||||
        DDS_LOG(DDS_LC_WHC, " unreg:seq <= max_drop_seq: delete newn\n");
 | 
			
		||||
        DDS_LOG (DDS_LC_WHC, " unreg:seq <= max_drop_seq: delete newn\n");
 | 
			
		||||
        whc_delete_one (whc, newn);
 | 
			
		||||
        whc->maxseq_node = prev_seq;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    DDS_LOG(DDS_LC_WHC, "\n");
 | 
			
		||||
    DDS_LOG (DDS_LC_WHC, "\n");
 | 
			
		||||
  }
 | 
			
		||||
  ddsrt_mutex_unlock (&whc->lock);
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void make_borrowed_sample(struct whc_borrowed_sample *sample, struct whc_node *whcn)
 | 
			
		||||
static void make_borrowed_sample (struct whc_borrowed_sample *sample, struct whc_node *whcn)
 | 
			
		||||
{
 | 
			
		||||
  assert(!whcn->borrowed);
 | 
			
		||||
  assert (!whcn->borrowed);
 | 
			
		||||
  whcn->borrowed = 1;
 | 
			
		||||
  sample->seq = whcn->seq;
 | 
			
		||||
  sample->plist = whcn->plist;
 | 
			
		||||
| 
						 | 
				
			
			@ -1258,11 +1254,11 @@ static bool whc_default_borrow_sample (const struct whc *whc_generic, seqno_t se
 | 
			
		|||
  struct whc_node *whcn;
 | 
			
		||||
  bool found;
 | 
			
		||||
  ddsrt_mutex_lock ((ddsrt_mutex_t *)&whc->lock);
 | 
			
		||||
  if ((whcn = whc_findseq(whc, seq)) == NULL)
 | 
			
		||||
  if ((whcn = whc_findseq (whc, seq)) == NULL)
 | 
			
		||||
    found = false;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    make_borrowed_sample(sample, whcn);
 | 
			
		||||
    make_borrowed_sample (sample, whcn);
 | 
			
		||||
    found = true;
 | 
			
		||||
  }
 | 
			
		||||
  ddsrt_mutex_unlock ((ddsrt_mutex_t *)&whc->lock);
 | 
			
		||||
| 
						 | 
				
			
			@ -1275,11 +1271,11 @@ static bool whc_default_borrow_sample_key (const struct whc *whc_generic, const
 | 
			
		|||
  struct whc_node *whcn;
 | 
			
		||||
  bool found;
 | 
			
		||||
  ddsrt_mutex_lock ((ddsrt_mutex_t *)&whc->lock);
 | 
			
		||||
  if ((whcn = whc_findkey(whc, serdata_key)) == NULL)
 | 
			
		||||
  if ((whcn = whc_findkey (whc, serdata_key)) == NULL)
 | 
			
		||||
    found = false;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    make_borrowed_sample(sample, whcn);
 | 
			
		||||
    make_borrowed_sample (sample, whcn);
 | 
			
		||||
    found = true;
 | 
			
		||||
  }
 | 
			
		||||
  ddsrt_mutex_unlock ((ddsrt_mutex_t *)&whc->lock);
 | 
			
		||||
| 
						 | 
				
			
			@ -1293,14 +1289,15 @@ static void return_sample_locked (struct whc_impl *whc, struct whc_borrowed_samp
 | 
			
		|||
  {
 | 
			
		||||
    /* data no longer present in WHC - that means ownership for serdata, plist shifted to the borrowed copy and "returning" it really becomes "destroying" it */
 | 
			
		||||
    ddsi_serdata_unref (sample->serdata);
 | 
			
		||||
    if (sample->plist) {
 | 
			
		||||
    if (sample->plist)
 | 
			
		||||
    {
 | 
			
		||||
      nn_plist_fini (sample->plist);
 | 
			
		||||
      ddsrt_free (sample->plist);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    assert(whcn->borrowed);
 | 
			
		||||
    assert (whcn->borrowed);
 | 
			
		||||
    whcn->borrowed = 0;
 | 
			
		||||
    if (update_retransmit_info)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -1338,7 +1335,7 @@ static bool whc_default_sample_iter_borrow_next (struct whc_sample_iter *opaque_
 | 
			
		|||
  if (!it->first)
 | 
			
		||||
  {
 | 
			
		||||
    seq = sample->seq;
 | 
			
		||||
    return_sample_locked(whc, sample, false);
 | 
			
		||||
    return_sample_locked (whc, sample, false);
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			@ -1349,7 +1346,7 @@ static bool whc_default_sample_iter_borrow_next (struct whc_sample_iter *opaque_
 | 
			
		|||
    valid = false;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    make_borrowed_sample(sample, whcn);
 | 
			
		||||
    make_borrowed_sample (sample, whcn);
 | 
			
		||||
    valid = true;
 | 
			
		||||
  }
 | 
			
		||||
  ddsrt_mutex_unlock (&whc->lock);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,9 +44,7 @@ struct bwhc_iter {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
/* check that our definition of whc_sample_iter fits in the type that callers allocate */
 | 
			
		||||
struct bwhc_sample_iter_sizecheck {
 | 
			
		||||
  char fits_in_generic_type[sizeof(struct bwhc_iter) <= sizeof(struct whc_sample_iter) ? 1 : -1];
 | 
			
		||||
};
 | 
			
		||||
DDSRT_STATIC_ASSERT (sizeof (struct bwhc_iter) <= sizeof (struct whc_sample_iter));
 | 
			
		||||
 | 
			
		||||
static void bwhc_free (struct whc *whc_generic)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -111,13 +111,13 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay
 | 
			
		|||
  else
 | 
			
		||||
  {
 | 
			
		||||
    /* When deleting, pwr is no longer accessible via the hash
 | 
			
		||||
     tables, and consequently, a reader may be deleted without
 | 
			
		||||
     it being possible to remove it from rdary. The primary
 | 
			
		||||
     reason rdary exists is to avoid locking the proxy writer
 | 
			
		||||
     but this is less of an issue when we are deleting it, so
 | 
			
		||||
     we fall back to using the GUIDs so that we can deliver all
 | 
			
		||||
     samples we received from it. As writer being deleted any
 | 
			
		||||
     reliable samples that are rejected are simply discarded. */
 | 
			
		||||
       tables, and consequently, a reader may be deleted without
 | 
			
		||||
       it being possible to remove it from rdary. The primary
 | 
			
		||||
       reason rdary exists is to avoid locking the proxy writer
 | 
			
		||||
       but this is less of an issue when we are deleting it, so
 | 
			
		||||
       we fall back to using the GUIDs so that we can deliver all
 | 
			
		||||
       samples we received from it. As writer being deleted any
 | 
			
		||||
       reliable samples that are rejected are simply discarded. */
 | 
			
		||||
    ddsrt_avl_iter_t it;
 | 
			
		||||
    struct pwr_rd_match *m;
 | 
			
		||||
    struct proxy_writer_info pwr_info;
 | 
			
		||||
| 
						 | 
				
			
			@ -130,8 +130,8 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay
 | 
			
		|||
      struct reader *rd;
 | 
			
		||||
      if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL)
 | 
			
		||||
      {
 | 
			
		||||
        DDS_TRACE("reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid));
 | 
			
		||||
        /* Copied the return value ignore from DDSI deliver_user_data() function. */
 | 
			
		||||
        DDS_TRACE ("reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid));
 | 
			
		||||
        /* Copied the return value ignore from DDSI deliver_user_data () function. */
 | 
			
		||||
        if ((ret = try_store (rd->rhc, &pwr_info, payload, tk, &max_block_ms)) != DDS_RETCODE_OK)
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -152,40 +152,34 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam
 | 
			
		|||
  int w_rc;
 | 
			
		||||
 | 
			
		||||
  if (data == NULL)
 | 
			
		||||
  {
 | 
			
		||||
    DDS_ERROR("No data buffer provided\n");
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Check for topic filter */
 | 
			
		||||
  if (wr->m_topic->filter_fn && !writekey)
 | 
			
		||||
    if (!(wr->m_topic->filter_fn) (data, wr->m_topic->filter_ctx))
 | 
			
		||||
    if (! wr->m_topic->filter_fn (data, wr->m_topic->filter_ctx))
 | 
			
		||||
      return DDS_RETCODE_OK;
 | 
			
		||||
 | 
			
		||||
  thread_state_awake (ts1);
 | 
			
		||||
 | 
			
		||||
  /* Serialize and write data or key */
 | 
			
		||||
  d = ddsi_serdata_from_sample (ddsi_wr->topic, writekey ? SDK_KEY : SDK_DATA, data);
 | 
			
		||||
  d->statusinfo = ((action & DDS_WR_DISPOSE_BIT) ? NN_STATUSINFO_DISPOSE : 0) | ((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0);
 | 
			
		||||
  d->statusinfo = (((action & DDS_WR_DISPOSE_BIT) ? NN_STATUSINFO_DISPOSE : 0) |
 | 
			
		||||
                   ((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0));
 | 
			
		||||
  d->timestamp.v = tstamp;
 | 
			
		||||
  ddsi_serdata_ref (d);
 | 
			
		||||
  tk = ddsi_tkmap_lookup_instance_ref (d);
 | 
			
		||||
  w_rc = write_sample_gc (ts1, wr->m_xp, ddsi_wr, d, tk);
 | 
			
		||||
 | 
			
		||||
  if (w_rc >= 0)
 | 
			
		||||
  {
 | 
			
		||||
  if (w_rc >= 0) {
 | 
			
		||||
    /* Flush out write unless configured to batch */
 | 
			
		||||
    if (!config.whc_batch)
 | 
			
		||||
      nn_xpack_send (wr->m_xp, false);
 | 
			
		||||
    ret = DDS_RETCODE_OK;
 | 
			
		||||
  } else if (w_rc == DDS_RETCODE_TIMEOUT) {
 | 
			
		||||
    DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n");
 | 
			
		||||
    ret = DDS_RETCODE_TIMEOUT;
 | 
			
		||||
  } else if (w_rc == DDS_RETCODE_BAD_PARAMETER) {
 | 
			
		||||
    DDS_ERROR ("Invalid data provided\n");
 | 
			
		||||
    ret = DDS_RETCODE_ERROR;
 | 
			
		||||
  } else {
 | 
			
		||||
    DDS_ERROR ("Internal error\n");
 | 
			
		||||
    ret = DDS_RETCODE_ERROR;
 | 
			
		||||
  }
 | 
			
		||||
  if (ret == DDS_RETCODE_OK)
 | 
			
		||||
| 
						 | 
				
			
			@ -213,13 +207,10 @@ dds_return_t dds_writecdr_impl_lowlevel (struct writer *ddsi_wr, struct nn_xpack
 | 
			
		|||
      nn_xpack_send (xp, false);
 | 
			
		||||
    ret = DDS_RETCODE_OK;
 | 
			
		||||
  } else if (w_rc == DDS_RETCODE_TIMEOUT) {
 | 
			
		||||
    DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n");
 | 
			
		||||
    ret = DDS_RETCODE_TIMEOUT;
 | 
			
		||||
  } else if (w_rc == DDS_RETCODE_BAD_PARAMETER) {
 | 
			
		||||
    DDS_ERROR ("Invalid data provided\n");
 | 
			
		||||
    ret = DDS_RETCODE_ERROR;
 | 
			
		||||
  } else {
 | 
			
		||||
    DDS_ERROR ("Internal error\n");
 | 
			
		||||
    ret = DDS_RETCODE_ERROR;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -236,7 +227,8 @@ dds_return_t dds_writecdr_impl (dds_writer *wr, struct ddsi_serdata *d, dds_time
 | 
			
		|||
  if (wr->m_topic->filter_fn)
 | 
			
		||||
    abort ();
 | 
			
		||||
  /* Set if disposing or unregistering */
 | 
			
		||||
  d->statusinfo = ((action & DDS_WR_DISPOSE_BIT) ? NN_STATUSINFO_DISPOSE : 0) | ((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0);
 | 
			
		||||
  d->statusinfo = (((action & DDS_WR_DISPOSE_BIT) ? NN_STATUSINFO_DISPOSE : 0) |
 | 
			
		||||
                   ((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0));
 | 
			
		||||
  d->timestamp.v = tstamp;
 | 
			
		||||
  return dds_writecdr_impl_lowlevel (wr->m_wr, wr->m_xp, d);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -252,9 +244,7 @@ void dds_write_flush (dds_entity_t writer)
 | 
			
		|||
  dds_writer *wr;
 | 
			
		||||
  dds_return_t rc;
 | 
			
		||||
  thread_state_awake (ts1);
 | 
			
		||||
  if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
 | 
			
		||||
    DDS_ERROR ("Error occurred on locking writer\n");
 | 
			
		||||
  else
 | 
			
		||||
  if ((rc = dds_writer_lock (writer, &wr)) == DDS_RETCODE_OK)
 | 
			
		||||
  {
 | 
			
		||||
    nn_xpack_send (wr->m_xp, true);
 | 
			
		||||
    dds_writer_unlock (wr);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,40 +24,29 @@
 | 
			
		|||
#include "dds__init.h"
 | 
			
		||||
#include "dds__publisher.h"
 | 
			
		||||
#include "dds__topic.h"
 | 
			
		||||
#include "dds__get_status.h"
 | 
			
		||||
#include "dds/ddsi/ddsi_tkmap.h"
 | 
			
		||||
#include "dds__whc.h"
 | 
			
		||||
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_writer)
 | 
			
		||||
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_writer)
 | 
			
		||||
 | 
			
		||||
#define DDS_WRITER_STATUS_MASK                                   \
 | 
			
		||||
                        DDS_LIVELINESS_LOST_STATUS              |\
 | 
			
		||||
                        DDS_OFFERED_DEADLINE_MISSED_STATUS      |\
 | 
			
		||||
                        DDS_OFFERED_INCOMPATIBLE_QOS_STATUS     |\
 | 
			
		||||
                        DDS_PUBLICATION_MATCHED_STATUS
 | 
			
		||||
                        (DDS_LIVELINESS_LOST_STATUS              |\
 | 
			
		||||
                         DDS_OFFERED_DEADLINE_MISSED_STATUS      |\
 | 
			
		||||
                         DDS_OFFERED_INCOMPATIBLE_QOS_STATUS     |\
 | 
			
		||||
                         DDS_PUBLICATION_MATCHED_STATUS)
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_writer_instance_hdl(
 | 
			
		||||
        dds_entity *e,
 | 
			
		||||
        dds_instance_handle_t *i)
 | 
			
		||||
static dds_return_t dds_writer_instance_hdl (dds_entity *e, dds_instance_handle_t *i) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_writer_instance_hdl (dds_entity *e, dds_instance_handle_t *i)
 | 
			
		||||
{
 | 
			
		||||
    assert(e);
 | 
			
		||||
    assert(i);
 | 
			
		||||
    *i = (dds_instance_handle_t)writer_instance_id(&e->m_guid);
 | 
			
		||||
    return DDS_RETCODE_OK;
 | 
			
		||||
  *i = writer_instance_id(&e->m_guid);
 | 
			
		||||
  return DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_writer_status_validate(
 | 
			
		||||
        uint32_t mask)
 | 
			
		||||
static dds_return_t dds_writer_status_validate (uint32_t mask)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
 | 
			
		||||
    if (mask & ~(DDS_WRITER_STATUS_MASK)) {
 | 
			
		||||
        DDS_ERROR("Invalid status mask\n");
 | 
			
		||||
        ret = DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
  return (mask & ~DDS_WRITER_STATUS_MASK) ? DDS_RETCODE_BAD_PARAMETER : DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -173,285 +162,217 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data)
 | 
			
		|||
  ddsrt_mutex_unlock (&entity->m_observers_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t
 | 
			
		||||
get_bandwidth_limit(
 | 
			
		||||
        nn_transport_priority_qospolicy_t transport_priority)
 | 
			
		||||
static uint32_t get_bandwidth_limit (nn_transport_priority_qospolicy_t transport_priority)
 | 
			
		||||
{
 | 
			
		||||
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
 | 
			
		||||
  struct config_channel_listelem *channel = find_channel (transport_priority);
 | 
			
		||||
  return channel->data_bandwidth_limit;
 | 
			
		||||
#else
 | 
			
		||||
  (void)transport_priority;
 | 
			
		||||
  (void) transport_priority;
 | 
			
		||||
  return 0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_writer_close(
 | 
			
		||||
        dds_entity *e)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
    dds_writer *wr = (dds_writer*)e;
 | 
			
		||||
static dds_return_t dds_writer_close (dds_entity *e) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
    assert(e);
 | 
			
		||||
static dds_return_t dds_writer_close (dds_entity *e)
 | 
			
		||||
{
 | 
			
		||||
  dds_writer * const wr = (dds_writer *) e;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  thread_state_awake (lookup_thread_state ());
 | 
			
		||||
  nn_xpack_send (wr->m_xp, false);
 | 
			
		||||
  if ((ret = delete_writer (&e->m_guid)) < 0)
 | 
			
		||||
    ret = DDS_RETCODE_ERROR;
 | 
			
		||||
  thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_writer_delete (dds_entity *e) ddsrt_nonnull_all;
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_writer_delete (dds_entity *e)
 | 
			
		||||
{
 | 
			
		||||
  dds_writer * const wr = (dds_writer *) e;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  /* FIXME: not freeing WHC here because it is owned by the DDSI entity */
 | 
			
		||||
  thread_state_awake (lookup_thread_state ());
 | 
			
		||||
  nn_xpack_free (wr->m_xp);
 | 
			
		||||
  thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
  if ((ret = dds_delete (wr->m_topic->m_entity.m_hdllink.hdl)) == DDS_RETCODE_OK)
 | 
			
		||||
  {
 | 
			
		||||
    ret = dds_delete_impl (e->m_parent->m_hdllink.hdl, true);
 | 
			
		||||
    if (ret == DDS_RETCODE_BAD_PARAMETER)
 | 
			
		||||
      ret = DDS_RETCODE_OK;
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_writer_qos_validate (const dds_qos_t *qos, bool enabled)
 | 
			
		||||
{
 | 
			
		||||
  if (!dds_qos_validate_common(qos))
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_USER_DATA) && !validate_octetseq (&qos->user_data))
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy (&qos->durability_service) < 0)
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_LIFESPAN) && validate_duration (&qos->lifespan.duration) < 0)
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && validate_history_and_resource_limits(&qos->history, &qos->resource_limits) < 0)
 | 
			
		||||
    return DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
  return enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t dds_writer_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
 | 
			
		||||
{
 | 
			
		||||
  /* FIXME: QoS changes */
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
  if ((ret = dds_writer_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  /* Sort-of support updating ownership strength */
 | 
			
		||||
  if ((qos->present & QP_OWNERSHIP_STRENGTH) && (qos->present & ~QP_OWNERSHIP_STRENGTH) == 0)
 | 
			
		||||
  {
 | 
			
		||||
    dds_ownership_kind_t kind;
 | 
			
		||||
    dds_qget_ownership (e->m_qos, &kind);
 | 
			
		||||
 | 
			
		||||
    if (kind != DDS_OWNERSHIP_EXCLUSIVE)
 | 
			
		||||
      return DDS_RETCODE_ERROR;
 | 
			
		||||
 | 
			
		||||
    struct writer *ddsi_wr = ((dds_writer *) e)->m_wr;
 | 
			
		||||
    dds_qset_ownership_strength (e->m_qos, qos->ownership_strength.value);
 | 
			
		||||
 | 
			
		||||
    thread_state_awake (lookup_thread_state ());
 | 
			
		||||
    nn_xpack_send (wr->m_xp, false);
 | 
			
		||||
    if (delete_writer (&e->m_guid) != 0) {
 | 
			
		||||
        DDS_ERROR("Internal error");
 | 
			
		||||
        ret = DDS_RETCODE_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* FIXME: with QoS changes being unsupported by the underlying stack I wonder what will happen; locking the underlying DDSI writer is of doubtful value as well */
 | 
			
		||||
    ddsrt_mutex_lock (&ddsi_wr->e.lock);
 | 
			
		||||
    ddsi_wr->xqos->ownership_strength.value = qos->ownership_strength.value;
 | 
			
		||||
    ddsrt_mutex_unlock (&ddsi_wr->e.lock);
 | 
			
		||||
    thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
    return ret;
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    if (enabled)
 | 
			
		||||
      ret = DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_writer_delete(
 | 
			
		||||
        dds_entity *e)
 | 
			
		||||
{
 | 
			
		||||
    dds_writer *wr = (dds_writer*)e;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
    /* FIXME: not freeing WHC here because it is owned by the DDSI entity */
 | 
			
		||||
    thread_state_awake (lookup_thread_state ());
 | 
			
		||||
    nn_xpack_free(wr->m_xp);
 | 
			
		||||
    thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
    ret = dds_delete(wr->m_topic->m_entity.m_hdllink.hdl);
 | 
			
		||||
    if(ret == DDS_RETCODE_OK){
 | 
			
		||||
        ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true);
 | 
			
		||||
        if(ret == DDS_RETCODE_BAD_PARAMETER){
 | 
			
		||||
            ret = DDS_RETCODE_OK;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_writer_qos_validate(
 | 
			
		||||
        const dds_qos_t *qos,
 | 
			
		||||
        bool enabled)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
 | 
			
		||||
    assert(qos);
 | 
			
		||||
 | 
			
		||||
    /* Check consistency. */
 | 
			
		||||
    if(dds_qos_validate_common(qos) != true){
 | 
			
		||||
        DDS_ERROR("Provided inconsistent QoS policy\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if((qos->present & QP_USER_DATA) && validate_octetseq(&qos->user_data) != true){
 | 
			
		||||
        DDS_ERROR("User Data QoS policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy(&qos->durability_service) != 0){
 | 
			
		||||
        DDS_ERROR("Durability service QoS policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if ((qos->present & QP_LIFESPAN) && validate_duration(&qos->lifespan.duration) != 0){
 | 
			
		||||
        DDS_ERROR("Lifespan QoS policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits(&qos->history, &qos->resource_limits) != 0)){
 | 
			
		||||
        DDS_ERROR("Resource limits QoS policy is inconsistent and caused an error\n");
 | 
			
		||||
        ret = DDS_RETCODE_INCONSISTENT_POLICY;
 | 
			
		||||
    }
 | 
			
		||||
    if(ret == DDS_RETCODE_OK && enabled) {
 | 
			
		||||
        ret = dds_qos_validate_mutable_common(qos);
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t
 | 
			
		||||
dds_writer_qos_set(
 | 
			
		||||
        dds_entity *e,
 | 
			
		||||
        const dds_qos_t *qos,
 | 
			
		||||
        bool enabled)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t ret = dds_writer_qos_validate(qos, enabled);
 | 
			
		||||
    if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        /*
 | 
			
		||||
         * TODO: CHAM-95: DDSI does not support changing QoS policies.
 | 
			
		||||
         *
 | 
			
		||||
         * Only Ownership is required for the minimum viable product. This seems
 | 
			
		||||
         * to be the only QoS policy that DDSI supports changes on.
 | 
			
		||||
         */
 | 
			
		||||
        if (qos->present & QP_OWNERSHIP_STRENGTH) {
 | 
			
		||||
            dds_ownership_kind_t kind;
 | 
			
		||||
            /* check for ownership before updating, ownership strength is applicable only if
 | 
			
		||||
             * writer is exclusive */
 | 
			
		||||
            dds_qget_ownership (e->m_qos, &kind);
 | 
			
		||||
 | 
			
		||||
            if (kind == DDS_OWNERSHIP_EXCLUSIVE) {
 | 
			
		||||
                struct writer * ddsi_wr = ((dds_writer*)e)->m_wr;
 | 
			
		||||
 | 
			
		||||
                dds_qset_ownership_strength (e->m_qos, qos->ownership_strength.value);
 | 
			
		||||
 | 
			
		||||
                thread_state_awake (lookup_thread_state ());
 | 
			
		||||
 | 
			
		||||
                /* FIXME: with QoS changes being unsupported by the underlying stack I wonder what will happen; locking the underlying DDSI writer is of doubtful value as well */
 | 
			
		||||
                ddsrt_mutex_lock (&ddsi_wr->e.lock);
 | 
			
		||||
                if (qos->ownership_strength.value != ddsi_wr->xqos->ownership_strength.value) {
 | 
			
		||||
                    ddsi_wr->xqos->ownership_strength.value = qos->ownership_strength.value;
 | 
			
		||||
                }
 | 
			
		||||
                ddsrt_mutex_unlock (&ddsi_wr->e.lock);
 | 
			
		||||
                thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
            } else {
 | 
			
		||||
                DDS_ERROR("Setting ownership strength doesn't make sense when the ownership is shared\n");
 | 
			
		||||
                ret = DDS_RETCODE_ERROR;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            if (enabled) {
 | 
			
		||||
                DDS_ERROR(DDS_PROJECT_NAME" does not support changing QoS policies yet\n");
 | 
			
		||||
                ret = DDS_RETCODE_UNSUPPORTED;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct whc *make_whc(const dds_qos_t *qos)
 | 
			
		||||
static struct whc *make_whc (const dds_qos_t *qos)
 | 
			
		||||
{
 | 
			
		||||
  bool handle_as_transient_local;
 | 
			
		||||
  unsigned hdepth, tldepth;
 | 
			
		||||
  uint32_t hdepth, tldepth;
 | 
			
		||||
  /* Construct WHC -- if aggressive_keep_last1 is set, the WHC will
 | 
			
		||||
    drop all samples for which a later update is available.  This
 | 
			
		||||
    forces it to maintain a tlidx.  */
 | 
			
		||||
     drop all samples for which a later update is available.  This
 | 
			
		||||
     forces it to maintain a tlidx.  */
 | 
			
		||||
  handle_as_transient_local = (qos->durability.kind == NN_TRANSIENT_LOCAL_DURABILITY_QOS);
 | 
			
		||||
  if (qos->history.kind == NN_KEEP_ALL_HISTORY_QOS)
 | 
			
		||||
    hdepth = 0;
 | 
			
		||||
  else
 | 
			
		||||
    hdepth = (unsigned)qos->history.depth;
 | 
			
		||||
  if (handle_as_transient_local) {
 | 
			
		||||
    hdepth = (unsigned) qos->history.depth;
 | 
			
		||||
  if (!handle_as_transient_local)
 | 
			
		||||
    tldepth = 0;
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    if (qos->durability_service.history.kind == NN_KEEP_ALL_HISTORY_QOS)
 | 
			
		||||
      tldepth = 0;
 | 
			
		||||
    else
 | 
			
		||||
      tldepth = (unsigned)qos->durability_service.history.depth;
 | 
			
		||||
  } else {
 | 
			
		||||
    tldepth = 0;
 | 
			
		||||
      tldepth = (unsigned) qos->durability_service.history.depth;
 | 
			
		||||
  }
 | 
			
		||||
  return whc_new (handle_as_transient_local, hdepth, tldepth);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
dds_entity_t
 | 
			
		||||
dds_create_writer(
 | 
			
		||||
    dds_entity_t participant_or_publisher,
 | 
			
		||||
    dds_entity_t topic,
 | 
			
		||||
    const dds_qos_t *qos,
 | 
			
		||||
    const dds_listener_t *listener)
 | 
			
		||||
dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entity_t topic, const dds_qos_t *qos, const dds_listener_t *listener)
 | 
			
		||||
{
 | 
			
		||||
    dds_return_t rc;
 | 
			
		||||
    dds_qos_t * wqos;
 | 
			
		||||
    dds_writer * wr;
 | 
			
		||||
    dds_entity_t writer;
 | 
			
		||||
    dds_publisher * pub = NULL;
 | 
			
		||||
    dds_topic * tp;
 | 
			
		||||
    dds_entity_t publisher;
 | 
			
		||||
    ddsi_tran_conn_t conn = gv.data_conn_uc;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
  dds_return_t rc;
 | 
			
		||||
  dds_qos_t *wqos;
 | 
			
		||||
  dds_writer *wr;
 | 
			
		||||
  dds_entity_t writer;
 | 
			
		||||
  dds_publisher *pub = NULL;
 | 
			
		||||
  dds_topic *tp;
 | 
			
		||||
  dds_entity_t publisher;
 | 
			
		||||
  ddsi_tran_conn_t conn = gv.data_conn_uc;
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        dds_entity *p_or_p;
 | 
			
		||||
        if ((rc = dds_entity_claim (participant_or_publisher, &p_or_p)) != DDS_RETCODE_OK) {
 | 
			
		||||
            return rc;
 | 
			
		||||
        }
 | 
			
		||||
        if (dds_entity_kind (p_or_p) == DDS_KIND_PARTICIPANT) {
 | 
			
		||||
            publisher = dds_create_publisher(participant_or_publisher, qos, NULL);
 | 
			
		||||
        } else {
 | 
			
		||||
            publisher = participant_or_publisher;
 | 
			
		||||
        }
 | 
			
		||||
        dds_entity_release (p_or_p);
 | 
			
		||||
    }
 | 
			
		||||
  {
 | 
			
		||||
    dds_entity *p_or_p;
 | 
			
		||||
    if ((rc = dds_entity_claim (participant_or_publisher, &p_or_p)) != DDS_RETCODE_OK)
 | 
			
		||||
      return rc;
 | 
			
		||||
    if (dds_entity_kind (p_or_p) == DDS_KIND_PARTICIPANT)
 | 
			
		||||
      publisher = dds_create_publisher(participant_or_publisher, qos, NULL);
 | 
			
		||||
    else
 | 
			
		||||
      publisher = participant_or_publisher;
 | 
			
		||||
    dds_entity_release (p_or_p);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    if ((rc = dds_publisher_lock(publisher, &pub)) != DDS_RETCODE_OK) {
 | 
			
		||||
        writer = rc;
 | 
			
		||||
        goto err_pub_lock;
 | 
			
		||||
    }
 | 
			
		||||
  if ((rc = dds_publisher_lock (publisher, &pub)) != DDS_RETCODE_OK)
 | 
			
		||||
    return rc;
 | 
			
		||||
 | 
			
		||||
    if (publisher != participant_or_publisher) {
 | 
			
		||||
        pub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT;
 | 
			
		||||
    }
 | 
			
		||||
  if (publisher != participant_or_publisher)
 | 
			
		||||
    pub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT;
 | 
			
		||||
 | 
			
		||||
    rc = dds_topic_lock(topic, &tp);
 | 
			
		||||
    if (rc != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking topic\n");
 | 
			
		||||
        writer = rc;
 | 
			
		||||
        goto err_tp_lock;
 | 
			
		||||
    }
 | 
			
		||||
    assert(tp->m_stopic);
 | 
			
		||||
    assert(pub->m_entity.m_domain == tp->m_entity.m_domain);
 | 
			
		||||
  if ((rc = dds_topic_lock (topic, &tp)) != DDS_RETCODE_OK)
 | 
			
		||||
    goto err_tp_lock;
 | 
			
		||||
 | 
			
		||||
    /* Merge Topic & Publisher qos */
 | 
			
		||||
    wqos = dds_create_qos();
 | 
			
		||||
    if (qos) {
 | 
			
		||||
        /* Only returns failure when one of the qos args is NULL, which
 | 
			
		||||
         * is not the case here. */
 | 
			
		||||
        (void)dds_copy_qos(wqos, qos);
 | 
			
		||||
    }
 | 
			
		||||
  assert (tp->m_stopic);
 | 
			
		||||
  assert (pub->m_entity.m_domain == tp->m_entity.m_domain);
 | 
			
		||||
 | 
			
		||||
    if (pub->m_entity.m_qos) {
 | 
			
		||||
        dds_merge_qos(wqos, pub->m_entity.m_qos);
 | 
			
		||||
    }
 | 
			
		||||
  /* Merge Topic & Publisher qos */
 | 
			
		||||
  wqos = dds_create_qos ();
 | 
			
		||||
  if (qos)
 | 
			
		||||
    (void) dds_copy_qos (wqos, qos);
 | 
			
		||||
  if (pub->m_entity.m_qos)
 | 
			
		||||
    dds_merge_qos (wqos, pub->m_entity.m_qos);
 | 
			
		||||
  if (tp->m_entity.m_qos)
 | 
			
		||||
    dds_merge_qos (wqos, tp->m_entity.m_qos);
 | 
			
		||||
  nn_xqos_mergein_missing (wqos, &gv.default_xqos_wr);
 | 
			
		||||
 | 
			
		||||
    if (tp->m_entity.m_qos) {
 | 
			
		||||
        /* merge topic qos data to writer qos */
 | 
			
		||||
        dds_merge_qos(wqos, tp->m_entity.m_qos);
 | 
			
		||||
    }
 | 
			
		||||
    nn_xqos_mergein_missing(wqos, &gv.default_xqos_wr);
 | 
			
		||||
  if ((rc = dds_writer_qos_validate (wqos, false)) != DDS_RETCODE_OK)
 | 
			
		||||
  {
 | 
			
		||||
    dds_delete_qos(wqos);
 | 
			
		||||
    goto err_bad_qos;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    ret = dds_writer_qos_validate(wqos, false);
 | 
			
		||||
    if (ret != 0) {
 | 
			
		||||
        dds_delete_qos(wqos);
 | 
			
		||||
        writer = ret;
 | 
			
		||||
        goto err_bad_qos;
 | 
			
		||||
    }
 | 
			
		||||
  /* Create writer */
 | 
			
		||||
  wr = dds_alloc (sizeof (*wr));
 | 
			
		||||
  writer = dds_entity_init (&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK);
 | 
			
		||||
 | 
			
		||||
    /* Create writer */
 | 
			
		||||
    wr = dds_alloc(sizeof (*wr));
 | 
			
		||||
    writer = dds_entity_init(&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK);
 | 
			
		||||
  wr->m_topic = tp;
 | 
			
		||||
  dds_entity_add_ref_nolock (&tp->m_entity);
 | 
			
		||||
  wr->m_xp = nn_xpack_new (conn, get_bandwidth_limit (wqos->transport_priority), config.xpack_send_async);
 | 
			
		||||
  wr->m_entity.m_deriver.close = dds_writer_close;
 | 
			
		||||
  wr->m_entity.m_deriver.delete = dds_writer_delete;
 | 
			
		||||
  wr->m_entity.m_deriver.set_qos = dds_writer_qos_set;
 | 
			
		||||
  wr->m_entity.m_deriver.validate_status = dds_writer_status_validate;
 | 
			
		||||
  wr->m_entity.m_deriver.get_instance_hdl = dds_writer_instance_hdl;
 | 
			
		||||
  wr->m_whc = make_whc (wqos);
 | 
			
		||||
 | 
			
		||||
    wr->m_topic = tp;
 | 
			
		||||
    dds_entity_add_ref_nolock(&tp->m_entity);
 | 
			
		||||
    wr->m_xp = nn_xpack_new(conn, get_bandwidth_limit(wqos->transport_priority), config.xpack_send_async);
 | 
			
		||||
    wr->m_entity.m_deriver.close = dds_writer_close;
 | 
			
		||||
    wr->m_entity.m_deriver.delete = dds_writer_delete;
 | 
			
		||||
    wr->m_entity.m_deriver.set_qos = dds_writer_qos_set;
 | 
			
		||||
    wr->m_entity.m_deriver.validate_status = dds_writer_status_validate;
 | 
			
		||||
    wr->m_entity.m_deriver.get_instance_hdl = dds_writer_instance_hdl;
 | 
			
		||||
    wr->m_whc = make_whc (wqos);
 | 
			
		||||
  /* Extra claim of this writer to make sure that the delete waits until DDSI
 | 
			
		||||
   * has deleted its writer as well. This can be known through the callback. */
 | 
			
		||||
  dds_handle_claim_inc (&wr->m_entity.m_hdllink);
 | 
			
		||||
 | 
			
		||||
    /* Extra claim of this writer to make sure that the delete waits until DDSI
 | 
			
		||||
     * has deleted its writer as well. This can be known through the callback. */
 | 
			
		||||
    dds_handle_claim_inc (&wr->m_entity.m_hdllink);
 | 
			
		||||
  ddsrt_mutex_unlock (&tp->m_entity.m_mutex);
 | 
			
		||||
  ddsrt_mutex_unlock (&pub->m_entity.m_mutex);
 | 
			
		||||
 | 
			
		||||
    ddsrt_mutex_unlock (&tp->m_entity.m_mutex);
 | 
			
		||||
    ddsrt_mutex_unlock (&pub->m_entity.m_mutex);
 | 
			
		||||
 | 
			
		||||
    thread_state_awake (lookup_thread_state ());
 | 
			
		||||
    ret = new_writer(&wr->m_wr, &wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr);
 | 
			
		||||
    ddsrt_mutex_lock (&pub->m_entity.m_mutex);
 | 
			
		||||
    ddsrt_mutex_lock (&tp->m_entity.m_mutex);
 | 
			
		||||
    assert(ret == DDS_RETCODE_OK);
 | 
			
		||||
    thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
    dds_topic_unlock(tp);
 | 
			
		||||
    dds_publisher_unlock(pub);
 | 
			
		||||
    return writer;
 | 
			
		||||
  thread_state_awake (lookup_thread_state ());
 | 
			
		||||
  rc = new_writer (&wr->m_wr, &wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr);
 | 
			
		||||
  ddsrt_mutex_lock (&pub->m_entity.m_mutex);
 | 
			
		||||
  ddsrt_mutex_lock (&tp->m_entity.m_mutex);
 | 
			
		||||
  assert(rc == DDS_RETCODE_OK);
 | 
			
		||||
  thread_state_asleep (lookup_thread_state ());
 | 
			
		||||
  dds_topic_unlock (tp);
 | 
			
		||||
  dds_publisher_unlock (pub);
 | 
			
		||||
  return writer;
 | 
			
		||||
 | 
			
		||||
err_bad_qos:
 | 
			
		||||
    dds_topic_unlock(tp);
 | 
			
		||||
  dds_topic_unlock (tp);
 | 
			
		||||
err_tp_lock:
 | 
			
		||||
    dds_publisher_unlock(pub);
 | 
			
		||||
    if((pub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){
 | 
			
		||||
        (void)dds_delete(publisher);
 | 
			
		||||
    }
 | 
			
		||||
err_pub_lock:
 | 
			
		||||
    return writer;
 | 
			
		||||
  dds_publisher_unlock (pub);
 | 
			
		||||
  if ((pub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){
 | 
			
		||||
    (void )dds_delete (publisher);
 | 
			
		||||
  }
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_entity_t
 | 
			
		||||
dds_get_publisher(
 | 
			
		||||
    dds_entity_t writer)
 | 
			
		||||
dds_entity_t dds_get_publisher (dds_entity_t writer)
 | 
			
		||||
{
 | 
			
		||||
  dds_entity *e;
 | 
			
		||||
  dds_return_t rc;
 | 
			
		||||
| 
						 | 
				
			
			@ -472,115 +393,7 @@ dds_get_publisher(
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_get_publication_matched_status (
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    dds_publication_matched_status_t * status)
 | 
			
		||||
{
 | 
			
		||||
    dds_writer *wr;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_writer_lock(writer, &wr);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking writer\n");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    /* status = NULL, application do not need the status, but reset the counter & triggered bit */
 | 
			
		||||
    if (status) {
 | 
			
		||||
        *status = wr->m_publication_matched_status;
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_lock (&wr->m_entity.m_observers_lock);
 | 
			
		||||
    if (wr->m_entity.m_status_enable & DDS_PUBLICATION_MATCHED_STATUS) {
 | 
			
		||||
        wr->m_publication_matched_status.total_count_change = 0;
 | 
			
		||||
        wr->m_publication_matched_status.current_count_change = 0;
 | 
			
		||||
        dds_entity_status_reset(&wr->m_entity, DDS_PUBLICATION_MATCHED_STATUS);
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock);
 | 
			
		||||
    dds_writer_unlock(wr);
 | 
			
		||||
fail:
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_get_liveliness_lost_status (
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    dds_liveliness_lost_status_t * status)
 | 
			
		||||
{
 | 
			
		||||
    dds_writer *wr;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_writer_lock(writer, &wr);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking writer\n");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    /* status = NULL, application do not need the status, but reset the counter & triggered bit */
 | 
			
		||||
    if (status) {
 | 
			
		||||
      *status = wr->m_liveliness_lost_status;
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_lock (&wr->m_entity.m_observers_lock);
 | 
			
		||||
    if (wr->m_entity.m_status_enable & DDS_LIVELINESS_LOST_STATUS) {
 | 
			
		||||
      wr->m_liveliness_lost_status.total_count_change = 0;
 | 
			
		||||
      dds_entity_status_reset(&wr->m_entity, DDS_LIVELINESS_LOST_STATUS);
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock);
 | 
			
		||||
    dds_writer_unlock(wr);
 | 
			
		||||
fail:
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_get_offered_deadline_missed_status(
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    dds_offered_deadline_missed_status_t *status)
 | 
			
		||||
{
 | 
			
		||||
    dds_writer *wr;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_writer_lock(writer, &wr);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking writer\n");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    /* status = NULL, application do not need the status, but reset the counter & triggered bit */
 | 
			
		||||
    if (status) {
 | 
			
		||||
      *status = wr->m_offered_deadline_missed_status;
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_lock (&wr->m_entity.m_observers_lock);
 | 
			
		||||
    if (wr->m_entity.m_status_enable & DDS_OFFERED_DEADLINE_MISSED_STATUS) {
 | 
			
		||||
      wr->m_offered_deadline_missed_status.total_count_change = 0;
 | 
			
		||||
      dds_entity_status_reset(&wr->m_entity, DDS_OFFERED_DEADLINE_MISSED_STATUS);
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock);
 | 
			
		||||
    dds_writer_unlock(wr);
 | 
			
		||||
fail:
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
dds_get_offered_incompatible_qos_status (
 | 
			
		||||
    dds_entity_t writer,
 | 
			
		||||
    dds_offered_incompatible_qos_status_t * status)
 | 
			
		||||
{
 | 
			
		||||
    dds_writer *wr;
 | 
			
		||||
    dds_return_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = dds_writer_lock(writer, &wr);
 | 
			
		||||
    if (ret != DDS_RETCODE_OK) {
 | 
			
		||||
        DDS_ERROR("Error occurred on locking writer\n");
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    /* status = NULL, application do not need the status, but reset the counter & triggered bit */
 | 
			
		||||
    if (status) {
 | 
			
		||||
      *status = wr->m_offered_incompatible_qos_status;
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_lock (&wr->m_entity.m_observers_lock);
 | 
			
		||||
    if (wr->m_entity.m_status_enable & DDS_OFFERED_INCOMPATIBLE_QOS_STATUS) {
 | 
			
		||||
      wr->m_offered_incompatible_qos_status.total_count_change = 0;
 | 
			
		||||
      dds_entity_status_reset(&wr->m_entity, DDS_OFFERED_INCOMPATIBLE_QOS_STATUS);
 | 
			
		||||
    }
 | 
			
		||||
    ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock);
 | 
			
		||||
    dds_writer_unlock(wr);
 | 
			
		||||
fail:
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
DDS_GET_STATUS(writer, publication_matched, PUBLICATION_MATCHED, total_count_change, current_count_change)
 | 
			
		||||
DDS_GET_STATUS(writer, liveliness_lost, LIVELINESS_LOST, total_count_change)
 | 
			
		||||
DDS_GET_STATUS(writer, offered_deadline_missed, OFFERED_DEADLINE_MISSED, total_count_change)
 | 
			
		||||
DDS_GET_STATUS(writer, offered_incompatible_qos, OFFERED_INCOMPATIBLE_QOS, total_count_change)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue