Add limited support for QoS changes

This commit adds support for changing all mutable QoS except those that
affect reader/writer matching (i.e., deadline, latency budget and
partition).  This is simply because the recalculation of the matches
hasn't been implemented yet, it is not a fundamental limitation.

Implementing this basically forced fixing up a bunch of inconsistencies
in handling QoS in entity creation.  A silly multi-process ping-pong
test built on changing the value of user data has been added.

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2019-06-04 20:47:08 +02:00 committed by eboasson
parent 11a1b9d6f9
commit a4d8aba4f9
32 changed files with 1225 additions and 361 deletions

View file

@ -12,14 +12,43 @@
#ifndef _DDS_QOS_H_
#define _DDS_QOS_H_
#include "dds__entity.h"
#include "dds/ddsi/q_xqos.h"
#if defined (__cplusplus)
extern "C" {
#endif
dds_return_t dds_qos_validate_mutable_common (const dds_qos_t *qos);
#define DDS_TOPIC_QOS_MASK \
(QP_TOPIC_DATA | QP_DURABILITY | QP_DURABILITY_SERVICE | \
QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_LIVELINESS | \
QP_RELIABILITY | QP_TRANSPORT_PRIORITY | QP_LIFESPAN | \
QP_DESTINATION_ORDER | QP_HISTORY | QP_RESOURCE_LIMITS)
#define DDS_PARTICIPANT_QOS_MASK \
(QP_USER_DATA | QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL)
#define DDS_PUBLISHER_QOS_MASK \
(QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | \
QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL)
#define DDS_READER_QOS_MASK \
(QP_USER_DATA | QP_DURABILITY | QP_DEADLINE | QP_LATENCY_BUDGET | \
QP_OWNERSHIP | QP_LIVELINESS | QP_TIME_BASED_FILTER | \
QP_RELIABILITY | QP_DESTINATION_ORDER | QP_HISTORY | \
QP_RESOURCE_LIMITS | QP_PRISMTECH_READER_DATA_LIFECYCLE | \
QP_CYCLONE_IGNORELOCAL)
#define DDS_SUBSCRIBER_QOS_MASK \
(QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | \
QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL)
#define DDS_WRITER_QOS_MASK \
(QP_USER_DATA | QP_DURABILITY | QP_DURABILITY_SERVICE | QP_DEADLINE | \
QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_OWNERSHIP_STRENGTH | \
QP_LIVELINESS | QP_RELIABILITY | QP_TRANSPORT_PRIORITY | \
QP_LIFESPAN | QP_DESTINATION_ORDER | QP_HISTORY | \
QP_RESOURCE_LIMITS | QP_PRISMTECH_WRITER_DATA_LIFECYCLE | \
QP_CYCLONE_IGNORELOCAL)
#if defined (__cplusplus)
}

View file

@ -17,7 +17,6 @@
#include "dds/ddsi/q_config.h"
#include "dds/ddsi/q_plist.h" /* for nn_keyhash */
#include "dds__init.h"
#include "dds__qos.h"
#include "dds__domain.h"
#include "dds__participant.h"
#include "dds__types.h"

View file

@ -19,6 +19,8 @@
#include "dds__writer.h"
#include "dds__reader.h"
#include "dds__listener.h"
#include "dds__qos.h"
#include "dds__topic.h"
#include "dds/version.h"
#include "dds/ddsi/q_xqos.h"
@ -339,6 +341,32 @@ dds_return_t dds_get_children (dds_entity_t entity, dds_entity_t *children, size
}
}
static uint64_t entity_kind_qos_mask (dds_entity_kind_t kind)
{
switch (kind)
{
case DDS_KIND_TOPIC:
return DDS_TOPIC_QOS_MASK;
case DDS_KIND_PARTICIPANT:
return DDS_PARTICIPANT_QOS_MASK;
case DDS_KIND_READER:
return DDS_READER_QOS_MASK;
case DDS_KIND_WRITER:
return DDS_WRITER_QOS_MASK;
case DDS_KIND_SUBSCRIBER:
return DDS_SUBSCRIBER_QOS_MASK;
case DDS_KIND_PUBLISHER:
return DDS_PUBLISHER_QOS_MASK;
case DDS_KIND_DONTCARE:
case DDS_KIND_COND_READ:
case DDS_KIND_COND_QUERY:
case DDS_KIND_COND_GUARD:
case DDS_KIND_WAITSET:
break;
}
return 0;
}
dds_return_t dds_get_qos (dds_entity_t entity, dds_qos_t *qos)
{
dds_entity *e;
@ -362,29 +390,159 @@ dds_return_t dds_get_qos (dds_entity_t entity, dds_qos_t *qos)
return ret;
}
static dds_return_t dds_set_qos_locked_impl (dds_entity *e, const dds_qos_t *qos, uint64_t mask)
{
dds_return_t ret;
dds_qos_t *newqos = dds_create_qos ();
nn_xqos_mergein_missing (newqos, qos, mask);
nn_xqos_mergein_missing (newqos, e->m_qos, ~(uint64_t)0);
if ((ret = nn_xqos_valid (newqos)) != DDS_RETCODE_OK)
; /* oops ... invalid or inconsistent */
else if (!(e->m_flags & DDS_ENTITY_ENABLED))
; /* do as you please while the entity is not enabled (perhaps we should even allow invalid ones?) */
else
{
const uint64_t delta = nn_xqos_delta (e->m_qos, newqos, ~(uint64_t)0);
if (delta == 0) /* no change */
ret = DDS_RETCODE_OK;
else if (delta & ~QP_CHANGEABLE_MASK)
ret = DDS_RETCODE_IMMUTABLE_POLICY;
else if (delta & (QP_RXO_MASK | QP_PARTITION))
ret = DDS_RETCODE_UNSUPPORTED; /* not yet supporting things that affect matching */
else
{
/* yay! */
}
}
if (ret != DDS_RETCODE_OK)
dds_delete_qos (newqos);
else if ((ret = e->m_deriver.set_qos (e, newqos, e->m_flags & DDS_ENTITY_ENABLED)) != DDS_RETCODE_OK)
dds_delete_qos (newqos);
else
{
dds_delete_qos (e->m_qos);
e->m_qos = newqos;
}
return ret;
}
static void pushdown_pubsub_qos (dds_entity_t entity)
{
dds_entity_t *cs = NULL;
int ncs, size = 0;
while ((ncs = dds_get_children (entity, cs, (size_t) size)) > size)
{
size = ncs;
cs = ddsrt_realloc (cs, (size_t) size * sizeof (*cs));
}
for (int i = 0; i < ncs; i++)
{
dds_entity *e;
if (dds_entity_lock (cs[i], DDS_KIND_DONTCARE, &e) == DDS_RETCODE_OK)
{
if (dds_entity_kind (e) == DDS_KIND_READER || dds_entity_kind (e) == DDS_KIND_WRITER)
{
dds_entity *pe;
if (dds_entity_lock (entity, DDS_KIND_DONTCARE, &pe) == DDS_RETCODE_OK)
{
dds_set_qos_locked_impl (e, pe->m_qos, QP_GROUP_DATA | QP_PARTITION);
dds_entity_unlock (pe);
}
}
dds_entity_unlock (e);
}
}
ddsrt_free (cs);
}
static void pushdown_topic_qos (dds_entity_t parent, dds_entity_t topic)
{
dds_entity_t *cs = NULL;
int ncs, size = 0;
while ((ncs = dds_get_children (parent, cs, (size_t) size)) > size)
{
size = ncs;
cs = ddsrt_realloc (cs, (size_t) size * sizeof (*cs));
}
for (int i = 0; i < ncs; i++)
{
dds_entity *e;
if (dds_entity_lock (cs[i], DDS_KIND_DONTCARE, &e) == DDS_RETCODE_OK)
{
enum { NOP, PROP, CHANGE } todo;
switch (dds_entity_kind (e))
{
case DDS_KIND_READER: {
dds_reader *rd = (dds_reader *) e;
todo = (rd->m_topic->m_entity.m_hdllink.hdl == topic) ? CHANGE : NOP;
break;
}
case DDS_KIND_WRITER: {
dds_writer *wr = (dds_writer *) e;
todo = (wr->m_topic->m_entity.m_hdllink.hdl == topic) ? CHANGE : NOP;
break;
case DDS_KIND_PUBLISHER:
case DDS_KIND_SUBSCRIBER:
todo = PROP;
break;
default:
todo = NOP;
break;
}
}
if (todo == CHANGE)
{
dds_topic *tp;
if (dds_topic_lock (topic, &tp) == DDS_RETCODE_OK)
{
dds_set_qos_locked_impl (e, tp->m_entity.m_qos, QP_TOPIC_DATA);
dds_topic_unlock (tp);
}
}
dds_entity_unlock (e);
if (todo == PROP)
{
pushdown_topic_qos (cs[i], topic);
}
}
}
ddsrt_free (cs);
}
dds_return_t dds_set_qos (dds_entity_t entity, const dds_qos_t *qos)
{
dds_entity *e;
dds_return_t ret;
if (qos == NULL)
return DDS_RETCODE_BAD_PARAMETER;
if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK)
else if ((ret = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK)
return ret;
if (e->m_deriver.set_qos == 0)
ret = DDS_RETCODE_ILLEGAL_OPERATION;
else
{
if ((ret = e->m_deriver.set_qos (e, qos, e->m_flags & DDS_ENTITY_ENABLED)) == DDS_RETCODE_OK)
const dds_entity_kind_t kind = dds_entity_kind (e);
dds_entity_t pphandle = e->m_participant->m_hdllink.hdl;
if (e->m_deriver.set_qos == 0)
ret = DDS_RETCODE_ILLEGAL_OPERATION;
else
ret = dds_set_qos_locked_impl (e, qos, entity_kind_qos_mask (kind));
dds_entity_unlock (e);
if (ret == DDS_RETCODE_OK)
{
if (e->m_qos == NULL)
e->m_qos = dds_create_qos ();
ret = dds_copy_qos (e->m_qos, qos);
switch (dds_entity_kind (e))
{
case DDS_KIND_TOPIC:
pushdown_topic_qos (pphandle, entity);
break;
case DDS_KIND_PUBLISHER:
case DDS_KIND_SUBSCRIBER:
pushdown_pubsub_qos (entity);
break;
default:
break;
}
}
}
dds_entity_unlock (e);
return ret;
}

View file

@ -21,7 +21,6 @@
#include "dds/ddsi/q_bswap.h"
#include "dds__writer.h"
#include "dds__reader.h"
#include "dds__qos.h"
#include "dds__topic.h"
dds_return_t dds_get_matched_subscriptions (dds_entity_t writer, dds_instance_handle_t *rds, size_t nrds)

View file

@ -16,16 +16,18 @@
#include "dds/ddsi/q_thread.h"
#include "dds/ddsi/q_config.h"
#include "dds/ddsi/q_plist.h"
#include "dds/ddsi/q_globals.h"
#include "dds__init.h"
#include "dds__qos.h"
#include "dds__domain.h"
#include "dds__participant.h"
#include "dds__builtin.h"
#include "dds__qos.h"
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_participant)
#define DDS_PARTICIPANT_STATUS_MASK (0u)
/* List of created participants */
static dds_entity *dds_pp_head = NULL;
@ -70,28 +72,24 @@ static dds_return_t dds_participant_instance_hdl (dds_entity *e, dds_instance_ha
return DDS_RETCODE_OK;
}
static dds_return_t dds_participant_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_participant_qos_validate (const dds_qos_t *qos, bool enabled)
{
dds_return_t ret;
(void)enabled;
if ((ret = nn_xqos_valid (qos)) < 0)
return ret;
return DDS_RETCODE_OK;
}
static dds_return_t dds_participant_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_participant_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
{
dds_return_t ret;
(void)e;
if ((ret = dds_participant_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
return ret;
if (enabled) /* FIXME: changing QoS */
return DDS_RETCODE_UNSUPPORTED;
return ret;
/* note: e->m_qos is still the old one to allow for failure here */
if (enabled)
{
struct participant *pp;
thread_state_awake (lookup_thread_state ());
if ((pp = ephash_lookup_participant_guid (&e->m_guid)) != NULL)
{
nn_plist_t plist;
nn_plist_init_empty (&plist);
plist.qos.present = plist.qos.aliased = qos->present;
plist.qos = *qos;
update_participant_plist (pp, &plist);
}
thread_state_asleep (lookup_thread_state ());
}
return DDS_RETCODE_OK;
}
dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_t *qos, const dds_listener_t *listener)
@ -110,13 +108,11 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_
if ((ret = dds__check_domain (domain)) != DDS_RETCODE_OK)
goto err_domain_check;
#define DDS_QOSMASK_PARTICIPANT (QP_USER_DATA | QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL)
new_qos = dds_create_qos ();
if (qos != NULL)
nn_xqos_mergein_missing (new_qos, qos, DDS_QOSMASK_PARTICIPANT);
/* Validate qos or use default if NULL */
if ((ret = dds_participant_qos_validate (new_qos, false)) != DDS_RETCODE_OK)
nn_xqos_mergein_missing (new_qos, qos, DDS_PARTICIPANT_QOS_MASK);
nn_xqos_mergein_missing (new_qos, &gv.default_plist_pp.qos, ~(uint64_t)0);
if ((ret = nn_xqos_valid (new_qos)) < 0)
goto err_qos_validation;
/* Translate qos */

View file

@ -29,34 +29,14 @@ static dds_return_t dds_publisher_instance_hdl (dds_entity *e, dds_instance_hand
static dds_return_t dds_publisher_instance_hdl (dds_entity *e, dds_instance_handle_t *i)
{
/* FIXME: Get/generate proper handle. */
(void) e;
(void) i;
(void) e; (void) i;
return DDS_RETCODE_UNSUPPORTED;
}
static dds_return_t dds_publisher_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_publisher_qos_validate (const dds_qos_t *qos, bool enabled)
{
dds_return_t ret;
if ((ret = nn_xqos_valid (qos)) < 0)
return ret;
/* FIXME: Improve/check immutable check. */
if (enabled && (qos->present & QP_PRESENTATION))
return DDS_RETCODE_IMMUTABLE_POLICY;
return DDS_RETCODE_OK;
}
static dds_return_t dds_publisher_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_publisher_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
{
dds_return_t ret;
(void)e;
if ((ret = dds_publisher_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
return ret;
if (enabled) /* FIXME: QoS changes. */
return DDS_RETCODE_UNSUPPORTED;
/* note: e->m_qos is still the old one to allow for failure here */
(void) e; (void) qos; (void) enabled;
return DDS_RETCODE_OK;
}
@ -73,12 +53,11 @@ dds_entity_t dds_create_publisher (dds_entity_t participant, const dds_qos_t *qo
dds_qos_t *new_qos;
dds_return_t ret;
#define DDS_QOSMASK_PUBLISHER (QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL)
new_qos = dds_create_qos ();
if (qos)
nn_xqos_mergein_missing (new_qos, qos, DDS_QOSMASK_PUBLISHER);
nn_xqos_mergein_missing (new_qos, qos, DDS_PUBLISHER_QOS_MASK);
nn_xqos_mergein_missing (new_qos, &gv.default_xqos_pub, ~(uint64_t)0);
if ((ret = dds_publisher_qos_validate (new_qos, false)) != DDS_RETCODE_OK)
if ((ret = nn_xqos_valid (new_qos)) != DDS_RETCODE_OK)
{
dds_delete_qos (new_qos);
return ret;

View file

@ -11,10 +11,11 @@
*/
#include <assert.h>
#include <string.h>
#include "dds__qos.h"
#include <stdbool.h>
#include "dds/dds.h"
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/string.h"
#include "dds/ddsi/q_config.h"
#include "dds/ddsi/q_plist.h"
static void dds_qos_data_copy_in (ddsi_octetseq_t *data, const void * __restrict value, size_t sz, bool overwrite)
{
@ -47,26 +48,6 @@ static bool dds_qos_data_copy_out (const ddsi_octetseq_t *data, void **value, si
return true;
}
dds_return_t dds_qos_validate_mutable_common (const dds_qos_t *qos)
{
/* FIXME: Check whether immutable QoS are changed should actually incorporate change to current QoS */
if (qos->present & QP_DEADLINE)
return DDS_RETCODE_IMMUTABLE_POLICY;
if (qos->present & QP_OWNERSHIP)
return DDS_RETCODE_IMMUTABLE_POLICY;
if (qos->present & QP_LIVELINESS)
return DDS_RETCODE_IMMUTABLE_POLICY;
if (qos->present & QP_RELIABILITY)
return DDS_RETCODE_IMMUTABLE_POLICY;
if (qos->present & QP_DESTINATION_ORDER)
return DDS_RETCODE_IMMUTABLE_POLICY;
if (qos->present & QP_HISTORY)
return DDS_RETCODE_IMMUTABLE_POLICY;
if (qos->present & QP_RESOURCE_LIMITS)
return DDS_RETCODE_IMMUTABLE_POLICY;
return DDS_RETCODE_OK;
}
dds_qos_t *dds_create_qos (void)
{
dds_qos_t *qos = ddsrt_malloc (sizeof (dds_qos_t));

View file

@ -17,11 +17,11 @@
#include "dds__subscriber.h"
#include "dds__reader.h"
#include "dds__listener.h"
#include "dds__qos.h"
#include "dds__init.h"
#include "dds__rhc.h"
#include "dds__topic.h"
#include "dds__get_status.h"
#include "dds__qos.h"
#include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_thread.h"
#include "dds/ddsi/q_globals.h"
@ -77,26 +77,18 @@ static dds_return_t dds_reader_delete (dds_entity *e)
return ret;
}
static dds_return_t dds_reader_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_reader_qos_validate (const dds_qos_t *qos, bool enabled)
{
dds_return_t ret;
if ((ret = nn_xqos_valid (qos)) < 0)
return ret;
return (enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK);
}
static dds_return_t dds_reader_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_reader_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
{
dds_return_t ret;
(void) e;
if ((ret = dds_reader_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
return ret;
/* FIXME: QoS changes. */
return (enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK);
/* note: e->m_qos is still the old one to allow for failure here */
if (enabled)
{
struct reader *rd;
thread_state_awake (lookup_thread_state ());
if ((rd = ephash_lookup_reader_guid (&e->m_guid)) != NULL)
update_reader_qos (rd, qos);
thread_state_asleep (lookup_thread_state ());
}
return DDS_RETCODE_OK;
}
static dds_return_t dds_reader_status_validate (uint32_t mask)
@ -363,17 +355,16 @@ dds_entity_t dds_create_reader (dds_entity_t participant_or_subscriber, dds_enti
/* Merge qos from topic and subscriber, dds_copy_qos only fails when it is passed a null
argument, but that isn't the case here */
#define DDS_QOSMASK_READER (QP_USER_DATA | QP_DURABILITY | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_LIVELINESS | QP_TIME_BASED_FILTER | QP_RELIABILITY | QP_DESTINATION_ORDER | QP_HISTORY | QP_RESOURCE_LIMITS | QP_PRISMTECH_READER_DATA_LIFECYCLE | QP_CYCLONE_IGNORELOCAL)
rqos = dds_create_qos ();
if (qos)
nn_xqos_mergein_missing (rqos, qos, DDS_QOSMASK_READER);
nn_xqos_mergein_missing (rqos, qos, DDS_READER_QOS_MASK);
if (sub->m_entity.m_qos)
nn_xqos_mergein_missing (rqos, sub->m_entity.m_qos, ~(uint64_t)0);
if (tp->m_entity.m_qos)
nn_xqos_mergein_missing (rqos, tp->m_entity.m_qos, ~(uint64_t)0);
nn_xqos_mergein_missing (rqos, &gv.default_xqos_rd, ~(uint64_t)0);
if ((ret = dds_reader_qos_validate (rqos, false)) != DDS_RETCODE_OK)
if ((ret = nn_xqos_valid (rqos)) != DDS_RETCODE_OK)
{
dds_delete_qos (rqos);
reader = ret;

View file

@ -190,21 +190,13 @@ static char *dds_string_dup_reuse (char *old, const char *src)
static dds_qos_t *dds_qos_from_xqos_reuse (dds_qos_t *old, const dds_qos_t *src)
{
if (old == NULL)
{
old = ddsrt_malloc (sizeof (*old));
nn_xqos_init_empty (old);
old->present |= QP_TOPIC_NAME | QP_TYPE_NAME;
nn_xqos_mergein_missing (old, src, ~(uint64_t)0);
old->present &= ~(QP_TOPIC_NAME | QP_TYPE_NAME);
}
else
{
nn_xqos_fini (old);
nn_xqos_init_empty (old);
old->present |= QP_TOPIC_NAME | QP_TYPE_NAME;
nn_xqos_mergein_missing (old, src, ~(uint64_t)0);
old->present &= ~(QP_TOPIC_NAME | QP_TYPE_NAME);
}
nn_xqos_init_empty (old);
nn_xqos_mergein_missing (old, src, ~(QP_TOPIC_NAME | QP_TYPE_NAME));
return old;
}

View file

@ -12,8 +12,8 @@
#include <string.h>
#include "dds__listener.h"
#include "dds__participant.h"
#include "dds__qos.h"
#include "dds__subscriber.h"
#include "dds__qos.h"
#include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_globals.h"
#include "dds/version.h"
@ -27,32 +27,16 @@ static dds_return_t dds_subscriber_instance_hdl (dds_entity *e, dds_instance_han
static dds_return_t dds_subscriber_instance_hdl (dds_entity *e, dds_instance_handle_t *i)
{
(void) e;
(void) i;
(void) e; (void) i;
/* FIXME: Get/generate proper handle. */
return DDS_RETCODE_UNSUPPORTED;
}
static dds_return_t dds__subscriber_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds__subscriber_qos_validate (const dds_qos_t *qos, bool enabled)
{
dds_return_t ret;
if ((ret = nn_xqos_valid (qos)) < 0)
return ret;
return (enabled && (qos->present & QP_PRESENTATION)) ? DDS_RETCODE_IMMUTABLE_POLICY : DDS_RETCODE_OK;
}
static dds_return_t dds_subscriber_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_subscriber_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
{
/* FIXME: QoS changes. */
dds_return_t ret;
(void) e;
if ((ret = dds__subscriber_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
return ret;
return (enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK);
/* note: e->m_qos is still the old one to allow for failure here */
(void) e; (void) qos; (void) enabled;
return DDS_RETCODE_OK;
}
static dds_return_t dds_subscriber_status_validate (uint32_t mask)
@ -68,12 +52,11 @@ dds_entity_t dds__create_subscriber_l (dds_participant *participant, const dds_q
dds_return_t ret;
dds_qos_t *new_qos;
#define DDS_QOSMASK_SUBSCRIBER (QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | QP_PRISMTECH_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL)
new_qos = dds_create_qos ();
if (qos)
nn_xqos_mergein_missing (new_qos, qos, DDS_QOSMASK_SUBSCRIBER);
nn_xqos_mergein_missing (new_qos, qos, DDS_SUBSCRIBER_QOS_MASK);
nn_xqos_mergein_missing (new_qos, &gv.default_xqos_sub, ~(uint64_t)0);
if ((ret = dds__subscriber_qos_validate (new_qos, false)) != DDS_RETCODE_OK)
if ((ret = nn_xqos_valid (new_qos)) != DDS_RETCODE_OK)
{
dds_delete_qos (new_qos);
return ret;

View file

@ -18,12 +18,12 @@
#include "dds/ddsrt/string.h"
#include "dds__topic.h"
#include "dds__listener.h"
#include "dds__qos.h"
#include "dds__participant.h"
#include "dds__stream.h"
#include "dds__init.h"
#include "dds__domain.h"
#include "dds__get_status.h"
#include "dds__qos.h"
#include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_thread.h"
#include "dds/ddsi/ddsi_sertopic.h"
@ -182,25 +182,11 @@ static dds_return_t dds_topic_delete (dds_entity *e)
return DDS_RETCODE_OK;
}
static dds_return_t dds_topic_qos_validate (const dds_qos_t *qos, bool enabled) ddsrt_nonnull_all;
static dds_return_t dds_topic_qos_validate (const dds_qos_t *qos, bool enabled)
{
dds_return_t ret;
if ((ret = nn_xqos_valid (qos)) < 0)
return ret;
return enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK;
}
static dds_return_t dds_topic_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
{
/* FIXME: QoS changes */
dds_return_t ret;
(void) e;
if ((ret = dds_topic_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
return ret;
return enabled ? DDS_RETCODE_UNSUPPORTED : DDS_RETCODE_OK;
/* note: e->m_qos is still the old one to allow for failure here */
(void) e; (void) qos; (void) enabled;
return DDS_RETCODE_OK;
}
static bool dupdef_qos_ok (const dds_qos_t *qos, const struct ddsi_sertopic *st)
@ -239,13 +225,25 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s
if (sertopic == NULL)
return DDS_RETCODE_BAD_PARAMETER;
if (qos && (rc = dds_topic_qos_validate (qos, false)) != DDS_RETCODE_OK)
return rc;
new_qos = dds_create_qos ();
if (qos)
nn_xqos_mergein_missing (new_qos, qos, DDS_TOPIC_QOS_MASK);
/* One would expect this:
*
* nn_xqos_mergein_missing (new_qos, &gv.default_xqos_tp, ~(uint64_t)0);
*
* but the crazy defaults of the DDS specification has a default settings
* for reliability that are dependent on the entity type: readers and
* topics default to best-effort, but writers to reliable.
*
* Leaving the topic QoS sparse means a default-default topic QoS of
* best-effort will do "the right thing" and let a writer still default to
* reliable ... (and keep behaviour unchanged) */
if ((rc = nn_xqos_valid (new_qos)) != DDS_RETCODE_OK)
goto err_invalid_qos;
if ((rc = dds_participant_lock (participant, &par)) != DDS_RETCODE_OK)
return rc;
/* FIXME: I find it weird that qos may be NULL in the entity */
goto err_lock_participant;
/* Check if topic already exists with same name */
ddsrt_mutex_lock (&dds_global.m_mutex);
@ -254,27 +252,22 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s
/* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */
rc = DDS_RETCODE_PRECONDITION_NOT_MET;
goto err_mismatch;
} else if (!dupdef_qos_ok(qos, stgeneric)) {
} else if (!dupdef_qos_ok (new_qos, stgeneric)) {
/* FIXME: should copy the type, perhaps? but then the pointers will no longer be the same */
rc = DDS_RETCODE_INCONSISTENT_POLICY;
goto err_mismatch;
} else {
/* FIXME: calling addref is wrong because the Cyclone library has no
knowledge of the reference and hence simply deleting the participant
won't make the ref count drop to 0. On the other hand, the DDS spec
says find_topic (and a second call to create_topic) return a new
proxy that must separately be deleted. */
knowledge of the reference and hence simply deleting the participant
won't make the ref count drop to 0. On the other hand, the DDS spec
says find_topic (and a second call to create_topic) return a new
proxy that must separately be deleted. */
dds_entity_add_ref (&stgeneric->status_cb_entity->m_entity);
hdl = stgeneric->status_cb_entity->m_entity.m_hdllink.hdl;
dds_delete_qos (new_qos);
}
ddsrt_mutex_unlock (&dds_global.m_mutex);
} else {
if (qos)
{
new_qos = dds_create_qos ();
(void)dds_copy_qos (new_qos, qos);
}
/* Create topic */
top = dds_alloc (sizeof (*top));
hdl = dds_entity_init (&top->m_entity, &par->m_entity, DDS_KIND_TOPIC, new_qos, listener, DDS_TOPIC_STATUS_MASK);
@ -293,7 +286,14 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s
ddsi_pp = ephash_lookup_participant_guid (&par->m_entity.m_guid);
assert (ddsi_pp);
if (sedp_plist)
sedp_write_topic (ddsi_pp, sedp_plist);
{
nn_plist_t plist;
nn_plist_init_empty (&plist);
nn_plist_mergein_missing (&plist, sedp_plist, ~(uint64_t)0, ~(uint64_t)0);
nn_xqos_mergein_missing (&plist.qos, new_qos, ~(uint64_t)0);
sedp_write_topic (ddsi_pp, &plist);
nn_plist_fini (&plist);
}
thread_state_asleep (lookup_thread_state ());
}
dds_participant_unlock (par);
@ -302,6 +302,9 @@ dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_s
err_mismatch:
ddsrt_mutex_unlock (&dds_global.m_mutex);
dds_participant_unlock (par);
err_lock_participant:
err_invalid_qos:
dds_delete_qos (new_qos);
return rc;
}
@ -310,7 +313,6 @@ dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descrip
char *key = NULL;
struct ddsi_sertopic_default *st;
const char *typename;
dds_qos_t *new_qos = NULL;
nn_plist_t plist;
dds_entity_t hdl;
size_t keysz;
@ -346,12 +348,7 @@ dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descrip
st->opt_size = dds_stream_check_optimize (desc);
}
#define DDS_QOSMASK_TOPIC (QP_TOPIC_DATA | QP_DURABILITY | QP_DURABILITY_SERVICE | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_LIVELINESS | QP_RELIABILITY | QP_TRANSPORT_PRIORITY | QP_LIFESPAN | QP_DESTINATION_ORDER | QP_HISTORY | QP_RESOURCE_LIMITS)
nn_plist_init_empty (&plist);
if (new_qos)
nn_xqos_mergein_missing (&plist.qos, new_qos, DDS_QOSMASK_TOPIC);
nn_xqos_mergein_missing (&plist.qos, &gv.default_xqos_tp, DDS_QOSMASK_TOPIC);
/* Set Topic meta data (for SEDP publication) */
plist.qos.topic_name = ddsrt_strdup (st->c.name);
plist.qos.type_name = ddsrt_strdup (st->c.type_name);

View file

@ -20,11 +20,11 @@
#include "dds/ddsi/q_xmsg.h"
#include "dds__writer.h"
#include "dds__listener.h"
#include "dds__qos.h"
#include "dds__init.h"
#include "dds__publisher.h"
#include "dds__topic.h"
#include "dds__get_status.h"
#include "dds__qos.h"
#include "dds/ddsi/ddsi_tkmap.h"
#include "dds__whc.h"
@ -206,48 +206,18 @@ static dds_return_t dds_writer_delete (dds_entity *e)
return ret;
}
static dds_return_t dds_writer_qos_validate (const dds_qos_t *qos, bool enabled)
{
dds_return_t ret;
if ((ret = nn_xqos_valid (qos)) < 0)
return ret;
return enabled ? dds_qos_validate_mutable_common (qos) : DDS_RETCODE_OK;
}
static dds_return_t dds_writer_qos_set (dds_entity *e, const dds_qos_t *qos, bool enabled)
{
/* FIXME: QoS changes */
dds_return_t ret;
if ((ret = dds_writer_qos_validate (qos, enabled)) != DDS_RETCODE_OK)
return ret;
/* Sort-of support updating ownership strength */
if ((qos->present & QP_OWNERSHIP_STRENGTH) && (qos->present & ~QP_OWNERSHIP_STRENGTH) == 0)
/* note: e->m_qos is still the old one to allow for failure here */
if (enabled)
{
dds_ownership_kind_t kind;
dds_qget_ownership (e->m_qos, &kind);
if (kind != DDS_OWNERSHIP_EXCLUSIVE)
return DDS_RETCODE_ERROR;
struct writer *ddsi_wr = ((dds_writer *) e)->m_wr;
dds_qset_ownership_strength (e->m_qos, qos->ownership_strength.value);
struct writer *wr;
thread_state_awake (lookup_thread_state ());
/* FIXME: with QoS changes being unsupported by the underlying stack I wonder what will happen; locking the underlying DDSI writer is of doubtful value as well */
ddsrt_mutex_lock (&ddsi_wr->e.lock);
ddsi_wr->xqos->ownership_strength.value = qos->ownership_strength.value;
ddsrt_mutex_unlock (&ddsi_wr->e.lock);
if ((wr = ephash_lookup_writer_guid (&e->m_guid)) != NULL)
update_writer_qos (wr, qos);
thread_state_asleep (lookup_thread_state ());
}
else
{
if (enabled)
ret = DDS_RETCODE_UNSUPPORTED;
}
return ret;
return DDS_RETCODE_OK;
}
static struct whc *make_whc (const dds_qos_t *qos)
@ -309,17 +279,16 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
assert (pub->m_entity.m_domain == tp->m_entity.m_domain);
/* Merge Topic & Publisher qos */
#define DDS_QOSMASK_WRITER (QP_USER_DATA | QP_DURABILITY | QP_DURABILITY_SERVICE | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_OWNERSHIP_STRENGTH | QP_LIVELINESS | QP_RELIABILITY | QP_TRANSPORT_PRIORITY | QP_LIFESPAN | QP_DESTINATION_ORDER | QP_HISTORY | QP_RESOURCE_LIMITS | QP_PRISMTECH_WRITER_DATA_LIFECYCLE | QP_CYCLONE_IGNORELOCAL)
wqos = dds_create_qos ();
if (qos)
nn_xqos_mergein_missing (wqos, qos, DDS_QOSMASK_WRITER);
nn_xqos_mergein_missing (wqos, qos, DDS_WRITER_QOS_MASK);
if (pub->m_entity.m_qos)
nn_xqos_mergein_missing (wqos, pub->m_entity.m_qos, ~(uint64_t)0);
if (tp->m_entity.m_qos)
nn_xqos_mergein_missing (wqos, tp->m_entity.m_qos, ~(uint64_t)0);
nn_xqos_mergein_missing (wqos, &gv.default_xqos_wr, ~(uint64_t)0);
if ((rc = dds_writer_qos_validate (wqos, false)) != DDS_RETCODE_OK)
if ((rc = nn_xqos_valid (wqos)) < 0)
{
dds_delete_qos(wqos);
goto err_bad_qos;

View file

@ -78,7 +78,7 @@ void entity_qos_get_set(dds_entity_t e, const char* info)
CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK);
status = dds_set_qos (e, qos); /* Doesn't change anything, so no need to forbid. But we return NOT_SUPPORTED anyway for now*/
CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_UNSUPPORTED);
CU_ASSERT_EQUAL_FATAL(status, DDS_RETCODE_OK);
dds_delete_qos(qos);
}

View file

@ -76,7 +76,7 @@ CU_Test(ddsc_unsupported, dds_begin_end_coherent, .init = setup, .fini = teardow
{BAD, DDS_RETCODE_BAD_PARAMETER}
};
for (int i=0; i < 5; i++) {
for (size_t i=0; i < sizeof (pars) / sizeof (pars[0]);i++) {
result = dds_begin_coherent(e[pars[i].index]);
CU_ASSERT_EQUAL(result, pars[i].exp_res);
result = dds_end_coherent(e[pars[i].index]);
@ -93,7 +93,7 @@ CU_Test(ddsc_unsupported, dds_wait_for_acks, .init = setup, .fini = teardown)
{BAD, DDS_RETCODE_BAD_PARAMETER}
};
for (int i=0; i< 3; i++) {
for (size_t i=0; i < sizeof (pars) / sizeof (pars[0]);i++) {
result = dds_wait_for_acks(e[pars[i].index], 0);
CU_ASSERT_EQUAL(result, pars[i].exp_res);
}
@ -108,7 +108,7 @@ CU_Test(ddsc_unsupported, dds_suspend_resume, .init = setup, .fini = teardown)
{BAD, DDS_RETCODE_BAD_PARAMETER}
};
for (int i=0; i< 3; i++) {
for (size_t i=0; i < sizeof (pars) / sizeof (pars[0]);i++) {
result = dds_suspend(e[pars[i].index]);
CU_ASSERT_EQUAL(result, pars[i].exp_res);
result = dds_resume(e[pars[i].index]);
@ -128,7 +128,7 @@ CU_Test(ddsc_unsupported, dds_get_instance_handle, .init = setup, .fini = teardo
{BAD, DDS_RETCODE_BAD_PARAMETER}
};
for (int i=0; i < 5; i++) {
for (size_t i=0; i < sizeof (pars) / sizeof (pars[0]);i++) {
result = dds_get_instance_handle(e[pars[i].index], &ih);
CU_ASSERT_EQUAL(result, pars[i].exp_res);
}
@ -139,18 +139,12 @@ CU_Test(ddsc_unsupported, dds_set_qos, .init = setup, .fini = teardown)
dds_return_t result;
dds_qos_t *qos;
static struct index_result pars[] = {
{PAR, DDS_RETCODE_UNSUPPORTED},
{TOP, DDS_RETCODE_UNSUPPORTED},
{PUB, DDS_RETCODE_UNSUPPORTED},
{WRI, DDS_RETCODE_UNSUPPORTED},
{SUB, DDS_RETCODE_UNSUPPORTED},
{REA, DDS_RETCODE_UNSUPPORTED},
{RCD, DDS_RETCODE_ILLEGAL_OPERATION},
{BAD, DDS_RETCODE_BAD_PARAMETER}
};
qos = dds_create_qos();
for (int i=0; i < 8;i++) {
for (size_t i=0; i < sizeof (pars) / sizeof (pars[0]);i++) {
result = dds_set_qos(e[pars[i].index], qos);
CU_ASSERT_EQUAL(result, pars[i].exp_res);
}