rework built-in topics again

Move details of built-in topics out of the DDSI core (so the only hooks
remain).  For this, rtps_term had to be split, so now it is "stop"
followed by "fini".

Add a notion of local writers that are not bound to a participant ("local
orphans"), so that the local built-in topic writers can be created during
initialization.  This eliminates the "builtin" participant.  This
uncovered in inconsistency in the unit tests: on the one hand, a newly
created participant is expected to have no child entities; on the other
hand, the built-in topics were expected to be returned by find_topic ...
This inconsistency has been resolved by creating them lazily and
accepting that find_topic can't return them until they have been
created.  Special code was in place in dds_create_reader anyway, so it
is not expected to have any real consequence for applications.

Use a special WHC implementation that regenerates the data on the fly
using the internal discovery tables of DDSI, so that the samples are only
stored by readers.  This eliminates the memory overhead of that existed
previously when the WHC of the writers stored the data.

No longer return topic name and type name in the built-in topics, they
have been extracted already and are not accessible through the normal
interface but do cause problems when comparing QoS.

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2019-01-06 13:10:24 +01:00
parent d6dcb0558d
commit 66076817e1
26 changed files with 876 additions and 919 deletions

View file

@ -37,6 +37,9 @@ PREPEND(srcs_ddsc "${CMAKE_CURRENT_LIST_DIR}/src"
dds_subscriber.c
dds_write.c
dds_whc.c
dds_whc_builtintopic.c
dds_serdata_builtintopic.c
dds_sertopic_builtintopic.c
)
PREPEND(hdrs_public_ddsc "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/ddsc>$<INSTALL_INTERFACE:include/ddsc>"
@ -73,6 +76,8 @@ PREPEND(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src"
dds__write.h
dds__writer.h
dds__whc.h
dds__whc_builtintopic.h
dds__serdata_builtintopic.h
)
configure_file(

View file

@ -1777,7 +1777,7 @@ dds_write_flush(
* @returns A dds_return_t indicating success or failure.
*/
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
DDS_EXPORT int
DDS_EXPORT dds_return_t
dds_writecdr(
dds_entity_t writer,
struct ddsi_serdata *serdata);

View file

@ -13,49 +13,31 @@
#define _DDS_BUILTIN_H_
#include "ddsi/q_time.h"
#include "ddsi/ddsi_serdata_builtin.h"
#if defined (__cplusplus)
extern "C"
{
#endif
/* Get actual topic in related participant related to topic 'id'. */
_Must_inspect_result_ dds_entity_t
dds__get_builtin_topic(
_In_ dds_entity_t e,
_In_ dds_entity_t topic);
/* Global publisher singleton (publishes only locally). */
_Must_inspect_result_ dds_entity_t
dds__get_builtin_publisher(
void);
dds_entity_t dds__get_builtin_topic ( dds_entity_t e, dds_entity_t topic);
/* Subscriber singleton within related participant. */
_Must_inspect_result_ dds_entity_t
dds__get_builtin_subscriber(
_In_ dds_entity_t e);
dds_entity_t dds__get_builtin_subscriber(dds_entity_t e);
/* Checks whether the reader QoS is valid for use with built-in topic TOPIC */
bool dds__validate_builtin_reader_qos(dds_entity_t topic, const dds_qos_t *qos);
/* Initialization and finalize functions. */
void
dds__builtin_init(
void);
struct entity_common;
struct nn_guid;
struct ddsi_tkmap_instance;
void
dds__builtin_fini(
void);
void
dds__builtin_write(
_In_ enum ddsi_sertopic_builtin_type type,
_In_ const nn_guid_t *guid,
_In_ nn_wctime_t timestamp,
_In_ bool alive);
void dds__builtin_init (void);
void dds__builtin_fini (void);
bool dds__builtin_is_visible (nn_entityid_t entityid, bool onlylocal, nn_vendorid_t vendorid);
struct ddsi_tkmap_instance *dds__builtin_get_tkmap_entry (const struct nn_guid *guid);
struct ddsi_serdata *dds__builtin_make_sample (const struct entity_common *e, nn_wctime_t timestamp, bool alive);
void dds__builtin_write (const struct entity_common *e, nn_wctime_t timestamp, bool alive);
#if defined (__cplusplus)
}

View file

@ -0,0 +1,41 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef DDSI_SERDATA_BUILTINTOPIC_H
#define DDSI_SERDATA_BUILTINTOPIC_H
#include "ddsi/q_xqos.h"
#include "ddsi/ddsi_serdata.h"
#include "ddsi/ddsi_sertopic.h"
struct ddsi_serdata_builtintopic {
struct ddsi_serdata c;
nn_guid_t key;
nn_xqos_t xqos;
};
enum ddsi_sertopic_builtintopic_type {
DSBT_PARTICIPANT,
DSBT_READER,
DSBT_WRITER
};
struct ddsi_sertopic_builtintopic {
struct ddsi_sertopic c;
enum ddsi_sertopic_builtintopic_type type;
};
extern const struct ddsi_sertopic_ops ddsi_sertopic_ops_builtintopic;
extern const struct ddsi_serdata_ops ddsi_serdata_ops_builtintopic;
struct ddsi_sertopic *new_sertopic_builtintopic (enum ddsi_sertopic_builtintopic_type type, const char *name, const char *typename);
#endif

View file

@ -52,7 +52,7 @@ struct rhc;
* Obviously, it is encouraged to use condition variables and such. But
* sometimes it wouldn't make that much of a difference and taking the
* easy route is somewhat pragmatic. */
#define DDS_HEADBANG_TIMEOUT_MS (10)
#define DDS_HEADBANG_TIMEOUT (DDS_MSECS (10))
typedef bool (*dds_querycondition_filter_with_ctx_fn) (const void * sample, const void *ctx);

View file

@ -0,0 +1,28 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef DDS_WHC_BUILTINTOPIC_H
#define DDS_WHC_BUILTINTOPIC_H
#include "ddsi/q_whc.h"
#include "dds__serdata_builtintopic.h"
#if defined (__cplusplus)
extern "C" {
#endif
struct whc *builtintopic_whc_new (enum ddsi_sertopic_builtintopic_type type);
#if defined (__cplusplus)
}
#endif
#endif /* Q_WHC_H */

View file

@ -22,28 +22,16 @@ extern "C" {
struct ddsi_serdata;
typedef enum
{
typedef enum {
DDS_WR_ACTION_WRITE = 0,
DDS_WR_ACTION_WRITE_DISPOSE = DDS_WR_DISPOSE_BIT,
DDS_WR_ACTION_DISPOSE = DDS_WR_KEY_BIT | DDS_WR_DISPOSE_BIT,
DDS_WR_ACTION_UNREGISTER = DDS_WR_KEY_BIT | DDS_WR_UNREGISTER_BIT
}
dds_write_action;
} dds_write_action;
int
dds_write_impl(
_In_ dds_writer *wr,
_In_ const void *data,
_In_ dds_time_t tstamp,
_In_ dds_write_action action);
int
dds_writecdr_impl(
_In_ dds_writer *wr,
_Inout_ struct ddsi_serdata *d,
_In_ dds_time_t tstamp,
_In_ dds_write_action action);
dds_return_t dds_write_impl (dds_writer *wr, const void *data, dds_time_t tstamp, dds_write_action action);
dds_return_t dds_writecdr_impl (dds_writer *wr, struct ddsi_serdata *d, dds_time_t tstamp, dds_write_action action);
dds_return_t dds_writecdr_impl_lowlevel (struct writer *ddsi_wr, struct nn_xpack *xp, struct ddsi_serdata *d);
#if defined (__cplusplus)
}

View file

@ -24,418 +24,216 @@
#include "dds__subscriber.h"
#include "dds__write.h"
#include "dds__writer.h"
#include "dds__whc_builtintopic.h"
#include "dds__serdata_builtintopic.h"
#include "ddsi/q_qosmatch.h"
#include "ddsi/ddsi_serdata_builtin.h"
#include "ddsi/ddsi_tkmap.h"
static dds_return_t
dds__delete_builtin_participant(
dds_entity *e);
static struct ddsi_sertopic *builtin_participant_topic;
static struct ddsi_sertopic *builtin_reader_topic;
static struct ddsi_sertopic *builtin_writer_topic;
static struct local_orphan_writer *builtintopic_writer_participant;
static struct local_orphan_writer *builtintopic_writer_publications;
static struct local_orphan_writer *builtintopic_writer_subscriptions;
static _Must_inspect_result_ dds_entity_t
dds__create_builtin_participant(
void);
static _Must_inspect_result_ dds_entity_t
dds__create_builtin_publisher(
_In_ dds_entity_t participant);
static dds_entity_t
dds__create_builtin_writer(
_In_ dds_entity_t topic);
static _Must_inspect_result_ dds_entity_t
dds__get_builtin_participant(
void);
static os_mutex g_builtin_mutex;
static os_atomic_uint32_t m_call_count = OS_ATOMIC_UINT32_INIT(0);
/* Singletons are used to publish builtin data locally. */
static dds_entity_t g_builtin_local_participant = 0;
static dds_entity_t g_builtin_local_publisher = 0;
static dds_entity_t g_builtin_local_writers[] = {
0, /* index DDS_BUILTIN_TOPIC_DCPSPARTICIPANT - DDS_KIND_INTERNAL - 1 */
0, /* index DDS_BUILTIN_TOPIC_DCPSTOPIC - DDS_KIND_INTERNAL - 1 */
0, /* index DDS_BUILTIN_TOPIC_DCPSPUBLICATION - DDS_KIND_INTERNAL - 1 */
0, /* index DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION - DDS_KIND_INTERNAL - 1 */
};
static _Must_inspect_result_ dds_qos_t *
dds__create_builtin_qos(
void)
static dds_qos_t *dds__create_builtin_qos (void)
{
const char *partition = "__BUILT-IN PARTITION__";
dds_qos_t *qos = dds_create_qos();
dds_qset_durability(qos, DDS_DURABILITY_TRANSIENT_LOCAL);
dds_qset_presentation(qos, DDS_PRESENTATION_TOPIC, false, false);
dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_MSECS(100));
dds_qset_partition(qos, 1, &partition);
return qos;
const char *partition = "__BUILT-IN PARTITION__";
dds_qos_t *qos = dds_create_qos ();
dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL);
dds_qset_presentation (qos, DDS_PRESENTATION_TOPIC, false, false);
dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_MSECS(100));
dds_qset_partition (qos, 1, &partition);
return qos;
}
static dds_return_t
dds__delete_builtin_participant(
dds_entity *e)
void dds__builtin_init (void)
{
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
dds_qos_t *qos = dds__create_builtin_qos ();
assert(e);
assert(thr);
assert(dds_entity_kind(e->m_hdl) == DDS_KIND_PARTICIPANT);
builtin_participant_topic = new_sertopic_builtintopic (DSBT_PARTICIPANT, "DCPSParticipant", "org::eclipse::cyclonedds::builtin::DCPSParticipant");
builtin_reader_topic = new_sertopic_builtintopic (DSBT_READER, "DCPSSubscription", "org::eclipse::cyclonedds::builtin::DCPSSubscription");
builtin_writer_topic = new_sertopic_builtintopic (DSBT_WRITER, "DCPSPublication", "org::eclipse::cyclonedds::builtin::DCPSPublication");
if (asleep) {
thread_state_awake(thr);
}
dds_domain_free(e->m_domain);
if (asleep) {
thread_state_asleep(thr);
}
builtintopic_writer_participant = new_local_orphan_writer (to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER), builtin_participant_topic, qos, builtintopic_whc_new (DSBT_PARTICIPANT));
builtintopic_writer_publications = new_local_orphan_writer (to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER), builtin_writer_topic, qos, builtintopic_whc_new (DSBT_WRITER));
builtintopic_writer_subscriptions = new_local_orphan_writer (to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER), builtin_reader_topic, qos, builtintopic_whc_new (DSBT_READER));
return DDS_RETCODE_OK;
dds_delete_qos (qos);
}
/*
* We don't use the 'normal' create participant.
*
* This way, the application is not able to access the local builtin writers.
* Also, we can indicate that it should be a 'local only' participant, which
* means that none of the entities under the hierarchy of this participant will
* be exposed to the outside world. This is what we want, because these builtin
* writers are only applicable to local user readers.
*/
static _Must_inspect_result_ dds_entity_t
dds__create_builtin_participant(
void)
void dds__builtin_fini (void)
{
int q_rc;
nn_plist_t plist;
struct thread_state1 * thr;
bool asleep;
nn_guid_t guid;
dds_entity_t participant;
dds_participant *pp;
/* No more sources for builtin topic samples */
struct thread_state1 * const self = lookup_thread_state ();
thread_state_awake (self);
delete_local_orphan_writer (builtintopic_writer_participant);
delete_local_orphan_writer (builtintopic_writer_publications);
delete_local_orphan_writer (builtintopic_writer_subscriptions);
thread_state_asleep (self);
nn_plist_init_empty (&plist);
thr = lookup_thread_state ();
asleep = !vtime_awake_p (thr->vtime);
if (asleep) {
thread_state_awake (thr);
}
q_rc = new_participant (&guid, RTPS_PF_NO_BUILTIN_WRITERS | RTPS_PF_NO_BUILTIN_READERS | RTPS_PF_ONLY_LOCAL, &plist);
if (asleep) {
thread_state_asleep (thr);
}
if (q_rc != 0) {
DDS_ERROR("Internal builtin error\n");
participant = DDS_ERRNO(DDS_RETCODE_ERROR);
goto fail;
}
pp = dds_alloc (sizeof (*pp));
participant = dds_entity_init (&pp->m_entity, NULL, DDS_KIND_PARTICIPANT, NULL, NULL, 0);
if (participant < 0) {
goto fail;
}
pp->m_entity.m_guid = guid;
pp->m_entity.m_domain = dds_domain_create (config.domainId.value);
pp->m_entity.m_domainid = config.domainId.value;
pp->m_entity.m_deriver.delete = dds__delete_builtin_participant;
fail:
return participant;
ddsi_sertopic_unref (builtin_participant_topic);
ddsi_sertopic_unref (builtin_reader_topic);
ddsi_sertopic_unref (builtin_writer_topic);
}
static _Must_inspect_result_ dds_entity_t
dds__create_builtin_publisher(
_In_ dds_entity_t participant)
dds_entity_t dds__get_builtin_topic (dds_entity_t e, dds_entity_t topic)
{
dds_qos_t *qos = dds__create_builtin_qos();
dds_entity_t pub = dds_create_publisher(participant, qos, NULL);
dds_delete_qos(qos);
return pub;
dds_entity_t pp;
dds_entity_t tp;
if ((pp = dds_get_participant (e)) <= 0)
return pp;
struct ddsi_sertopic *sertopic;
if (topic == DDS_BUILTIN_TOPIC_DCPSPARTICIPANT) {
sertopic = builtin_participant_topic;
} else if (topic == DDS_BUILTIN_TOPIC_DCPSPUBLICATION) {
sertopic = builtin_writer_topic;
} else if (topic == DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION) {
sertopic = builtin_reader_topic;
} else {
assert (0);
return DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER);
}
dds_qos_t *qos = dds__create_builtin_qos ();
tp = dds_create_topic_arbitrary (pp, sertopic, sertopic->name, qos, NULL, NULL);
dds_delete_qos (qos);
return tp;
}
static _Must_inspect_result_ dds_entity_t
dds__create_builtin_subscriber(
_In_ dds_entity *participant)
static bool qos_has_resource_limits (const dds_qos_t *qos)
{
dds_qos_t *qos = dds__create_builtin_qos();
dds_entity_t sub = dds__create_subscriber_l(participant, qos, NULL);
dds_delete_qos(qos);
return sub;
return (qos->resource_limits.max_samples != DDS_LENGTH_UNLIMITED ||
qos->resource_limits.max_instances != DDS_LENGTH_UNLIMITED ||
qos->resource_limits.max_samples_per_instance != DDS_LENGTH_UNLIMITED);
}
static dds_entity_t
dds__create_builtin_writer(
_In_ dds_entity_t topic)
bool dds__validate_builtin_reader_qos (dds_entity_t topic, const dds_qos_t *qos)
{
dds_entity_t wr;
dds_entity_t pub = dds__get_builtin_publisher();
if (pub > 0) {
dds_entity_t top = dds__get_builtin_topic(pub, topic);
if (top > 0) {
wr = dds_create_writer(pub, top, NULL, NULL);
(void)dds_delete(top);
} else {
wr = top;
}
if (qos == NULL)
/* default QoS inherited from topic is ok by definition */
return true;
else
{
/* failing writes on built-in topics are unwelcome complications, so we simply forbid the creation of
a reader matching a built-in topics writer that has resource limits */
struct local_orphan_writer *bwr;
if (topic == DDS_BUILTIN_TOPIC_DCPSPARTICIPANT) {
bwr = builtintopic_writer_participant;
} else if (topic == DDS_BUILTIN_TOPIC_DCPSPUBLICATION) {
bwr = builtintopic_writer_publications;
} else if (topic == DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION) {
bwr = builtintopic_writer_subscriptions;
} else {
wr = pub;
assert (0);
return false;
}
return wr;
return qos_match_p (qos, bwr->wr.xqos) && !qos_has_resource_limits (qos);
}
}
static _Must_inspect_result_ dds_entity_t
dds__get_builtin_participant(
void)
static dds_entity_t dds__create_builtin_subscriber (dds_entity *participant)
{
if (g_builtin_local_participant == 0) {
g_builtin_local_participant = dds__create_builtin_participant();
(void)dds__create_builtin_writer(DDS_BUILTIN_TOPIC_DCPSPARTICIPANT);
(void)dds__create_builtin_writer(DDS_BUILTIN_TOPIC_DCPSPUBLICATION);
(void)dds__create_builtin_writer(DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION);
}
return g_builtin_local_participant;
dds_qos_t *qos = dds__create_builtin_qos ();
dds_entity_t sub = dds__create_subscriber_l (participant, qos, NULL);
dds_delete_qos (qos);
return sub;
}
_Must_inspect_result_ dds_entity_t
dds__get_builtin_publisher(
void)
dds_entity_t dds__get_builtin_subscriber (dds_entity_t e)
{
if (g_builtin_local_publisher == 0) {
dds_entity_t par = dds__get_builtin_participant();
if (par > 0) {
g_builtin_local_publisher = dds__create_builtin_publisher(par);
}
}
return g_builtin_local_publisher;
}
dds_entity_t sub;
dds_return_t ret;
dds_entity_t pp;
dds_participant *p;
dds_entity *part_entity;
_Must_inspect_result_ dds_entity_t
dds__get_builtin_subscriber(
_In_ dds_entity_t e)
{
dds_entity_t sub;
dds_return_t ret;
dds_entity_t participant;
dds_participant *p;
dds_entity *part_entity;
participant = dds_get_participant(e);
if (participant <= 0) {
/* error already in participant error; no need to repeat error */
ret = participant;
goto error;
}
ret = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, (dds_entity **)&part_entity);
if (ret != DDS_RETCODE_OK) {
goto error;
}
p = (dds_participant *)part_entity;
if(p->m_builtin_subscriber <= 0) {
p->m_builtin_subscriber = dds__create_builtin_subscriber(part_entity);
}
sub = p->m_builtin_subscriber;
dds_entity_unlock(part_entity);
return sub;
/* Error handling */
error:
assert(ret < 0);
if ((pp = dds_get_participant (e)) <= 0)
return pp;
if ((ret = dds_entity_lock (pp, DDS_KIND_PARTICIPANT, &part_entity)) < 0)
return ret;
p = (dds_participant *) part_entity;
if (p->m_builtin_subscriber <= 0) {
p->m_builtin_subscriber = dds__create_builtin_subscriber (part_entity);
}
sub = p->m_builtin_subscriber;
dds_entity_unlock(part_entity);
return sub;
}
_Must_inspect_result_ dds_entity_t
dds__get_builtin_topic(
_In_ dds_entity_t e,
_In_ dds_entity_t topic)
bool dds__builtin_is_visible (nn_entityid_t entityid, bool onlylocal, nn_vendorid_t vendorid)
{
dds_entity_t participant;
dds_entity_t ret;
participant = dds_get_participant(e);
if (participant > 0) {
struct ddsi_sertopic *sertopic;
if (topic == DDS_BUILTIN_TOPIC_DCPSPARTICIPANT) {
sertopic = gv.builtin_participant_topic;
} else if (topic == DDS_BUILTIN_TOPIC_DCPSPUBLICATION) {
sertopic = gv.builtin_writer_topic;
} else if (topic == DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION) {
sertopic = gv.builtin_reader_topic;
} else {
DDS_ERROR("Invalid builtin-topic handle(%d)\n", topic);
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER);
goto err_invalid_topic;
}
ret = dds_find_topic (participant, sertopic->name);
if (ret < 0 && dds_err_nr(ret) == DDS_RETCODE_PRECONDITION_NOT_MET) {
dds_qos_t *qos = dds__create_builtin_qos();
ret = dds_create_topic_arbitrary(participant, sertopic, sertopic->name, qos, NULL, NULL);
dds_delete_qos(qos);
}
} else {
/* Failed to get participant of provided entity */
ret = participant;
}
err_invalid_topic:
return ret;
return !(onlylocal || is_builtin_endpoint (entityid, vendorid));
}
static _Must_inspect_result_ dds_entity_t
dds__get_builtin_writer(
_In_ dds_entity_t topic)
struct ddsi_tkmap_instance *dds__builtin_get_tkmap_entry (const struct nn_guid *guid)
{
dds_entity_t wr;
if ((topic >= DDS_BUILTIN_TOPIC_DCPSPARTICIPANT) && (topic <= DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION)) {
int index = (int)(topic - DDS_KIND_INTERNAL - 1);
os_mutexLock(&g_builtin_mutex);
wr = g_builtin_local_writers[index];
if (wr == 0) {
wr = dds__create_builtin_writer(topic);
if (wr > 0) {
g_builtin_local_writers[index] = wr;
}
}
os_mutexUnlock(&g_builtin_mutex);
} else {
DDS_ERROR("Given topic is not a builtin topic\n");
wr = DDS_ERRNO(DDS_RETCODE_ERROR);
}
return wr;
struct ddsi_tkmap_instance *tk;
struct ddsi_serdata *sd;
struct nn_keyhash kh;
memcpy (&kh, guid, sizeof (kh));
/* any random builtin topic will do (provided it has a GUID for a key), because what matters is the "class" of the topic, not the actual topic; also, this is called early in the initialisation of the entity with this GUID, which simply causes serdata_from_keyhash to create a key-only serdata because the key lookup fails. */
sd = ddsi_serdata_from_keyhash (builtin_participant_topic, &kh);
tk = ddsi_tkmap_find (sd, false, true);
ddsi_serdata_unref (sd);
return tk;
}
static dds_return_t
dds__builtin_write_int(
_In_ dds_entity_t topic,
_In_ const nn_guid_t *guid,
_In_ dds_time_t timestamp,
_In_ bool alive)
struct ddsi_serdata *dds__builtin_make_sample (const struct entity_common *e, nn_wctime_t timestamp, bool alive)
{
dds_return_t ret = DDS_RETCODE_OK;
if (os_atomic_inc32_nv(&m_call_count) > 1) {
dds_entity_t wr;
wr = dds__get_builtin_writer(topic);
if (wr > 0) {
struct ddsi_sertopic *sertopic;
struct ddsi_serdata *serdata;
struct nn_keyhash keyhash;
struct dds_writer *wraddr;
if (topic == DDS_BUILTIN_TOPIC_DCPSPARTICIPANT) {
sertopic = gv.builtin_participant_topic;
} else if (topic == DDS_BUILTIN_TOPIC_DCPSPUBLICATION) {
sertopic = gv.builtin_writer_topic;
} else if (topic == DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION) {
sertopic = gv.builtin_reader_topic;
} else {
sertopic = NULL;
assert (0);
}
memcpy (&keyhash, guid, sizeof (keyhash));
serdata = ddsi_serdata_from_keyhash(sertopic, &keyhash);
ret = dds_writer_lock(wr, &wraddr);
if (ret == DDS_RETCODE_OK) {
ret = dds_writecdr_impl (wraddr, serdata, timestamp, alive ? 0 : (DDS_WR_DISPOSE_BIT | DDS_WR_UNREGISTER_BIT));
dds_writer_unlock(wraddr);
}
} else {
ret = wr;
}
}
os_atomic_dec32(&m_call_count);
return ret;
/* initialize to avoid gcc warning ultimately caused by C's horrible type system */
struct ddsi_sertopic *topic = NULL;
struct ddsi_serdata *serdata;
struct nn_keyhash keyhash;
switch (e->kind)
{
case EK_PARTICIPANT:
case EK_PROXY_PARTICIPANT:
topic = builtin_participant_topic;
break;
case EK_WRITER:
case EK_PROXY_WRITER:
topic = builtin_writer_topic;
break;
case EK_READER:
case EK_PROXY_READER:
topic = builtin_reader_topic;
break;
}
assert (topic != NULL);
memcpy (&keyhash, &e->guid, sizeof (keyhash));
serdata = ddsi_serdata_from_keyhash (topic, &keyhash);
serdata->timestamp = timestamp;
serdata->statusinfo = alive ? 0 : NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER;
return serdata;
}
void
dds__builtin_write(
_In_ enum ddsi_sertopic_builtin_type type,
_In_ const nn_guid_t *guid,
_In_ nn_wctime_t timestamp,
_In_ bool alive)
void dds__builtin_write (const struct entity_common *e, nn_wctime_t timestamp, bool alive)
{
/* initialize to avoid compiler warning ultimately caused by C's horrible type system */
dds_entity_t topic = 0;
switch (type)
if (ddsi_plugin.builtintopic_is_visible (e->guid.entityid, e->onlylocal, get_entity_vendorid (e)))
{
/* initialize to avoid gcc warning ultimately caused by C's horrible type system */
struct local_orphan_writer *bwr = NULL;
struct ddsi_serdata *serdata = dds__builtin_make_sample (e, timestamp, alive);
assert (e->tk != NULL);
switch (e->kind)
{
case DSBT_PARTICIPANT:
topic = DDS_BUILTIN_TOPIC_DCPSPARTICIPANT;
break;
case DSBT_WRITER:
topic = DDS_BUILTIN_TOPIC_DCPSPUBLICATION;
break;
case DSBT_READER:
topic = DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION;
break;
case EK_PARTICIPANT:
case EK_PROXY_PARTICIPANT:
bwr = builtintopic_writer_participant;
break;
case EK_WRITER:
case EK_PROXY_WRITER:
bwr = builtintopic_writer_publications;
break;
case EK_READER:
case EK_PROXY_READER:
bwr = builtintopic_writer_subscriptions;
break;
}
assert(topic != 0);
(void)dds__builtin_write_int(topic, guid, timestamp.v, alive);
}
bool dds__validate_builtin_reader_qos(dds_entity_t topic, const dds_qos_t *qos)
{
if (qos == NULL) {
/* default QoS inherited from topic is ok by definition */
return true;
} else {
dds_entity_t wr = dds__get_builtin_writer(topic);
dds_qos_t *wrqos = dds_create_qos();
dds_return_t ret = dds_get_qos(wr, wrqos);
bool match;
assert (ret == DDS_RETCODE_OK);
(void)ret;
if (!qos_match_p (qos, wrqos)) {
match = false;
} else if (qos->resource_limits.max_samples != DDS_LENGTH_UNLIMITED ||
qos->resource_limits.max_instances != DDS_LENGTH_UNLIMITED ||
qos->resource_limits.max_samples_per_instance != DDS_LENGTH_UNLIMITED) {
/* this means a write on the built-in topic writer can't fail */
match = false;
} else {
match = true;
}
dds_delete_qos(wrqos);
return match;
}
}
void
dds__builtin_init(
void)
{
assert(os_atomic_ld32(&m_call_count) == 0);
os_mutexInit(&g_builtin_mutex);
os_atomic_inc32(&m_call_count);
}
void
dds__builtin_fini(
void)
{
assert(os_atomic_ld32(&m_call_count) > 0);
while (os_atomic_dec32_nv(&m_call_count) > 0) {
os_atomic_inc32_nv(&m_call_count);
dds_sleepfor(DDS_MSECS(10));
}
(void)dds_delete(g_builtin_local_participant);
g_builtin_local_participant = 0;
g_builtin_local_publisher = 0;
memset(g_builtin_local_writers, 0, sizeof(g_builtin_local_writers));
os_mutexDestroy(&g_builtin_mutex);
dds_writecdr_impl_lowlevel (&bwr->wr, NULL, serdata);
}
}

View file

@ -18,6 +18,7 @@
#include "dds__domain.h"
#include "dds__err.h"
#include "dds__builtin.h"
#include "dds__whc_builtintopic.h"
#include "ddsi/ddsi_iid.h"
#include "ddsi/ddsi_tkmap.h"
#include "ddsi/ddsi_serdata.h"
@ -106,8 +107,6 @@ dds_init(dds_domainid_t domain)
* main configured domain id is. */
dds_global.m_default_domain = config.domainId.value;
dds__builtin_init();
if (rtps_config_prep(dds_cfgst) != 0)
{
DDS_ERROR("Failed to configure RTPS\n");
@ -138,6 +137,8 @@ dds_init(dds_domainid_t domain)
goto fail_rtps_init;
}
dds__builtin_init ();
if (gv.servicelease && nn_servicelease_start_renewing(gv.servicelease) < 0)
{
DDS_ERROR("Failed to start the servicelease\n");
@ -172,7 +173,8 @@ skip:
fail_servicelease_start:
if (gv.servicelease)
nn_servicelease_stop_renewing (gv.servicelease);
rtps_term ();
rtps_stop ();
rtps_fini ();
fail_rtps_init:
if (gv.servicelease)
{
@ -182,7 +184,6 @@ fail_rtps_init:
fail_servicelease_new:
thread_states_fini();
fail_rtps_config:
dds__builtin_fini();
fail_config_domainid:
dds_global.m_default_domain = DDS_DOMAIN_DEFAULT;
config_fini (dds_cfgst);
@ -206,11 +207,11 @@ extern void dds_fini (void)
dds_global.m_init_count--;
if (dds_global.m_init_count == 0)
{
dds__builtin_fini();
if (gv.servicelease)
nn_servicelease_stop_renewing (gv.servicelease);
rtps_term ();
rtps_stop ();
dds__builtin_fini ();
rtps_fini ();
if (gv.servicelease)
nn_servicelease_free (gv.servicelease);
gv.servicelease = NULL;
@ -247,7 +248,9 @@ void ddsi_plugin_init (void)
ddsi_plugin.init_fn = dds__init_plugin;
ddsi_plugin.fini_fn = dds__fini_plugin;
ddsi_plugin.builtin_write = dds__builtin_write;
ddsi_plugin.builtintopic_is_visible = dds__builtin_is_visible;
ddsi_plugin.builtintopic_get_tkmap_entry = dds__builtin_get_tkmap_entry;
ddsi_plugin.builtintopic_write = dds__builtin_write;
ddsi_plugin.rhc_plugin.rhc_free_fn = dds_rhc_free;
ddsi_plugin.rhc_plugin.rhc_fini_fn = dds_rhc_fini;

View file

@ -18,6 +18,7 @@
#include "dds__domain.h"
#include "dds__participant.h"
#include "dds__err.h"
#include "dds__builtin.h"
#define DDS_PARTICIPANT_STATUS_MASK 0u

View file

@ -0,0 +1,294 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <stddef.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
#include "os/os.h"
#include "ddsi/q_md5.h"
#include "ddsi/q_bswap.h"
#include "ddsi/q_config.h"
#include "ddsi/q_freelist.h"
#include <assert.h>
#include <string.h>
#include "os/os.h"
#include "dds__key.h"
#include "dds__stream.h"
#include "dds__serdata_builtintopic.h"
#include "ddsi/ddsi_tkmap.h"
#include "ddsi/q_entity.h"
static const uint64_t unihashconsts[] = {
UINT64_C (16292676669999574021),
UINT64_C (10242350189706880077),
UINT64_C (12844332200329132887),
UINT64_C (16728792139623414127)
};
static uint32_t hash_guid (const nn_guid_t *g)
{
return
(uint32_t) (((((uint32_t) g->prefix.u[0] + unihashconsts[0]) *
((uint32_t) g->prefix.u[1] + unihashconsts[1])) +
(((uint32_t) g->prefix.u[2] + unihashconsts[2]) *
((uint32_t) g->entityid.u + unihashconsts[3])))
>> 32);
}
static struct ddsi_serdata *fix_serdata_builtin(struct ddsi_serdata_builtintopic *d, uint32_t basehash)
{
d->c.hash = hash_guid (&d->key) ^ basehash;
return &d->c;
}
static bool serdata_builtin_eqkey(const struct ddsi_serdata *acmn, const struct ddsi_serdata *bcmn)
{
const struct ddsi_serdata_builtintopic *a = (const struct ddsi_serdata_builtintopic *)acmn;
const struct ddsi_serdata_builtintopic *b = (const struct ddsi_serdata_builtintopic *)bcmn;
return memcmp (&a->key, &b->key, sizeof (a->key)) == 0;
}
static void serdata_builtin_free(struct ddsi_serdata *dcmn)
{
struct ddsi_serdata_builtintopic *d = (struct ddsi_serdata_builtintopic *)dcmn;
if (d->c.kind == SDK_DATA)
nn_xqos_fini (&d->xqos);
os_free (d);
}
static struct ddsi_serdata_builtintopic *serdata_builtin_new(const struct ddsi_sertopic_builtintopic *tp, enum ddsi_serdata_kind kind)
{
struct ddsi_serdata_builtintopic *d = os_malloc(sizeof (*d));
ddsi_serdata_init (&d->c, &tp->c, kind);
return d;
}
static void from_entity_pp (struct ddsi_serdata_builtintopic *d, const struct participant *pp)
{
nn_xqos_copy(&d->xqos, &pp->plist->qos);
}
static void from_entity_proxypp (struct ddsi_serdata_builtintopic *d, const struct proxy_participant *proxypp)
{
nn_xqos_copy(&d->xqos, &proxypp->plist->qos);
}
static void set_topic_type_from_sertopic (struct ddsi_serdata_builtintopic *d, const struct ddsi_sertopic *tp)
{
if (!(d->xqos.present & QP_TOPIC_NAME))
{
d->xqos.topic_name = dds_string_dup (tp->name);
d->xqos.present |= QP_TOPIC_NAME;
}
if (!(d->xqos.present & QP_TYPE_NAME))
{
d->xqos.type_name = dds_string_dup (tp->typename);
d->xqos.present |= QP_TYPE_NAME;
}
}
static void from_entity_rd (struct ddsi_serdata_builtintopic *d, const struct reader *rd)
{
nn_xqos_copy(&d->xqos, rd->xqos);
set_topic_type_from_sertopic(d, rd->topic);
}
static void from_entity_prd (struct ddsi_serdata_builtintopic *d, const struct proxy_reader *prd)
{
nn_xqos_copy(&d->xqos, prd->c.xqos);
assert (d->xqos.present & QP_TOPIC_NAME);
assert (d->xqos.present & QP_TYPE_NAME);
}
static void from_entity_wr (struct ddsi_serdata_builtintopic *d, const struct writer *wr)
{
nn_xqos_copy(&d->xqos, wr->xqos);
set_topic_type_from_sertopic(d, wr->topic);
}
static void from_entity_pwr (struct ddsi_serdata_builtintopic *d, const struct proxy_writer *pwr)
{
nn_xqos_copy(&d->xqos, pwr->c.xqos);
assert (d->xqos.present & QP_TOPIC_NAME);
assert (d->xqos.present & QP_TYPE_NAME);
}
struct ddsi_serdata *ddsi_serdata_builtin_from_keyhash (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash)
{
/* FIXME: not quite elegant to manage the creation of a serdata for a built-in topic via this function, but I also find it quite unelegant to let from_sample read straight from the underlying internal entity, and to_sample convert to the external format ... I could claim the internal entity is the "serialised form", but that forces wrapping it in a fragchain in one way or another, which, though possible, is also a bit lacking in elegance. */
const struct ddsi_sertopic_builtintopic *tp = (const struct ddsi_sertopic_builtintopic *)tpcmn;
/* keyhash must in host format (which the GUIDs always are internally) */
const struct entity_common *entity = ephash_lookup_guid_untyped ((const nn_guid_t *) keyhash->value);
struct ddsi_serdata_builtintopic *d = serdata_builtin_new(tp, entity ? SDK_DATA : SDK_KEY);
memcpy (&d->key, keyhash->value, sizeof (d->key));
if (entity)
{
switch (entity->kind)
{
case EK_PARTICIPANT:
assert (tp->type == DSBT_PARTICIPANT);
from_entity_pp (d, (const struct participant *) entity);
break;
case EK_READER:
assert (tp->type == DSBT_READER);
from_entity_rd (d, (const struct reader *) entity);
break;
case EK_WRITER:
assert (tp->type == DSBT_WRITER);
from_entity_wr (d, (const struct writer *) entity);
break;
case EK_PROXY_PARTICIPANT:
assert (tp->type == DSBT_PARTICIPANT);
from_entity_proxypp (d, (const struct proxy_participant *) entity);
break;
case EK_PROXY_READER:
assert (tp->type == DSBT_READER);
from_entity_prd (d, (const struct proxy_reader *) entity);
break;
case EK_PROXY_WRITER:
assert (tp->type == DSBT_WRITER);
from_entity_pwr (d, (const struct proxy_writer *) entity);
break;
}
}
return fix_serdata_builtin(d, tp->c.serdata_basehash);
}
static struct ddsi_serdata *serdata_builtin_to_topicless (const struct ddsi_serdata *serdata_common)
{
/* All built-in ones are currently topicless */
return ddsi_serdata_ref (serdata_common);
}
static void convkey (dds_builtintopic_guid_t *key, const nn_guid_t *guid)
{
nn_guid_t tmp;
tmp = nn_hton_guid (*guid);
memcpy (key, &tmp, sizeof (*key));
}
static char *dds_string_dup_reuse (char *old, const char *src)
{
size_t size = strlen (src) + 1;
char *new = dds_realloc(old, size);
return memcpy (new, src, size);
}
static dds_qos_t *dds_qos_from_xqos_reuse (dds_qos_t *old, const nn_xqos_t *src)
{
if (old == NULL)
{
old = os_malloc (sizeof (*old));
nn_xqos_init_empty (old);
old->present |= QP_TOPIC_NAME | QP_TYPE_NAME;
nn_xqos_mergein_missing (old, src);
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);
old->present &= ~(QP_TOPIC_NAME | QP_TYPE_NAME);
}
return old;
}
static bool to_sample_pp (const struct ddsi_serdata_builtintopic *d, struct dds_builtintopic_participant *sample)
{
convkey (&sample->key, &d->key);
if (d->c.kind == SDK_DATA)
{
sample->qos = dds_qos_from_xqos_reuse (sample->qos, &d->xqos);
}
return true;
}
static bool to_sample_endpoint (const struct ddsi_serdata_builtintopic *d, struct dds_builtintopic_endpoint *sample)
{
nn_guid_t ppguid;
convkey (&sample->key, &d->key);
ppguid = d->key;
ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
convkey (&sample->participant_key, &ppguid);
if (d->c.kind == SDK_DATA)
{
assert (d->xqos.present & QP_TOPIC_NAME);
assert (d->xqos.present & QP_TYPE_NAME);
sample->topic_name = dds_string_dup_reuse (sample->topic_name, d->xqos.topic_name);
sample->type_name = dds_string_dup_reuse (sample->type_name, d->xqos.type_name);
sample->qos = dds_qos_from_xqos_reuse (sample->qos, &d->xqos);
}
return true;
}
static bool serdata_builtin_topicless_to_sample (const struct ddsi_sertopic *topic, const struct ddsi_serdata *serdata_common, void *sample, void **bufptr, void *buflim)
{
const struct ddsi_serdata_builtintopic *d = (const struct ddsi_serdata_builtintopic *)serdata_common;
const struct ddsi_sertopic_builtintopic *tp = (const struct ddsi_sertopic_builtintopic *)topic;
if (bufptr) abort(); else { (void)buflim; } /* FIXME: haven't implemented that bit yet! */
/* FIXME: completing builtin topic support along these lines requires subscribers, publishers and topics to also become DDSI entities - which is probably a good thing anyway */
switch (tp->type)
{
case DSBT_PARTICIPANT:
return to_sample_pp (d, sample);
case DSBT_READER:
case DSBT_WRITER:
return to_sample_endpoint (d, sample);
}
assert (0);
return false;
}
static bool serdata_builtin_to_sample (const struct ddsi_serdata *serdata_common, void *sample, void **bufptr, void *buflim)
{
return serdata_builtin_topicless_to_sample (serdata_common->topic, serdata_common, sample, bufptr, buflim);
}
static uint32_t serdata_builtin_get_size (const struct ddsi_serdata *serdata_common)
{
(void)serdata_common;
return 0;
}
static void serdata_builtin_to_ser (const struct ddsi_serdata *serdata_common, size_t off, size_t sz, void *buf)
{
(void)serdata_common; (void)off; (void)sz; (void)buf;
}
static struct ddsi_serdata *serdata_builtin_to_ser_ref (const struct ddsi_serdata *serdata_common, size_t off, size_t sz, os_iovec_t *ref)
{
(void)serdata_common; (void)off; (void)sz; (void)ref;
return NULL;
}
static void serdata_builtin_to_ser_unref (struct ddsi_serdata *serdata_common, const os_iovec_t *ref)
{
(void)serdata_common; (void)ref;
}
const struct ddsi_serdata_ops ddsi_serdata_ops_builtintopic = {
.get_size = serdata_builtin_get_size,
.eqkey = serdata_builtin_eqkey,
.free = serdata_builtin_free,
.from_ser = 0,
.from_keyhash = ddsi_serdata_builtin_from_keyhash,
.from_sample = 0,
.to_ser = serdata_builtin_to_ser,
.to_sample = serdata_builtin_to_sample,
.to_ser_ref = serdata_builtin_to_ser_ref,
.to_ser_unref = serdata_builtin_to_ser_unref,
.to_topicless = serdata_builtin_to_topicless,
.topicless_to_sample = serdata_builtin_topicless_to_sample
};

View file

@ -0,0 +1,147 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <stddef.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
#include "os/os.h"
#include "ddsi/q_md5.h"
#include "ddsi/q_bswap.h"
#include "ddsi/q_config.h"
#include "ddsi/q_freelist.h"
#include "ddsi/ddsi_sertopic.h"
#include "ddsc/dds.h"
#include "dds__serdata_builtintopic.h"
/* FIXME: sertopic /= ddstopic so a lot of stuff needs to be moved here from dds_topic.c and the free function needs to be implemented properly */
struct ddsi_sertopic *new_sertopic_builtintopic (enum ddsi_sertopic_builtintopic_type type, const char *name, const char *typename)
{
struct ddsi_sertopic_builtintopic *tp = os_malloc (sizeof (*tp));
tp->c.iid = ddsi_iid_gen();
tp->c.name = dds_string_dup (name);
tp->c.typename = dds_string_dup (typename);
const size_t name_typename_size = strlen (tp->c.name) + 1 + strlen (tp->c.typename) + 1;
tp->c.name_typename = dds_alloc (name_typename_size);
snprintf (tp->c.name_typename, name_typename_size, "%s/%s", tp->c.name, tp->c.typename);
tp->c.ops = &ddsi_sertopic_ops_builtintopic;
tp->c.serdata_ops = &ddsi_serdata_ops_builtintopic;
tp->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (tp->c.serdata_ops);
tp->c.status_cb = 0;
tp->c.status_cb_entity = NULL;
os_atomic_st32 (&tp->c.refc, 1);
tp->type = type;
return &tp->c;
}
static void sertopic_builtin_deinit (struct ddsi_sertopic *tp)
{
(void)tp;
}
static void free_pp (void *vsample)
{
dds_builtintopic_participant_t *sample = vsample;
dds_delete_qos (sample->qos);
sample->qos = NULL;
}
static void free_endpoint (void *vsample)
{
dds_builtintopic_endpoint_t *sample = vsample;
dds_free (sample->topic_name);
dds_free (sample->type_name);
dds_delete_qos (sample->qos);
sample->topic_name = sample->type_name = NULL;
sample->qos = NULL;
}
static size_t get_size (enum ddsi_sertopic_builtintopic_type type)
{
switch (type)
{
case DSBT_PARTICIPANT:
return sizeof (dds_builtintopic_participant_t);
case DSBT_READER:
case DSBT_WRITER:
return sizeof (dds_builtintopic_endpoint_t);
}
assert (0);
return 0;
}
static void sertopic_builtin_zero_samples (const struct ddsi_sertopic *sertopic_common, void *samples, size_t count)
{
const struct ddsi_sertopic_builtintopic *tp = (const struct ddsi_sertopic_builtintopic *)sertopic_common;
size_t size = get_size (tp->type);
memset (samples, 0, size * count);
}
static void sertopic_builtin_realloc_samples (void **ptrs, const struct ddsi_sertopic *sertopic_common, void *old, size_t oldcount, size_t count)
{
const struct ddsi_sertopic_builtintopic *tp = (const struct ddsi_sertopic_builtintopic *)sertopic_common;
const size_t size = get_size (tp->type);
char *new = dds_realloc (old, size * count);
if (new && count > oldcount)
memset (new + size * oldcount, 0, size * (count - oldcount));
for (size_t i = 0; i < count; i++)
{
void *ptr = (char *) new + i * size;
ptrs[i] = ptr;
}
}
static void sertopic_builtin_free_samples (const struct ddsi_sertopic *sertopic_common, void **ptrs, size_t count, dds_free_op_t op)
{
if (count > 0)
{
const struct ddsi_sertopic_builtintopic *tp = (const struct ddsi_sertopic_builtintopic *)sertopic_common;
const size_t size = get_size (tp->type);
#ifndef NDEBUG
for (size_t i = 0, off = 0; i < count; i++, off += size)
assert ((char *)ptrs[i] == (char *)ptrs[0] + off);
#endif
if (op & DDS_FREE_CONTENTS_BIT)
{
void (*f) (void *) = 0;
char *ptr = ptrs[0];
switch (tp->type)
{
case DSBT_PARTICIPANT:
f = free_pp;
break;
case DSBT_READER:
case DSBT_WRITER:
f = free_endpoint;
break;
}
assert (f != 0);
for (size_t i = 0; i < count; i++)
{
f (ptr);
ptr += size;
}
}
if (op & DDS_FREE_ALL_BIT)
{
dds_free (ptrs[0]);
}
}
}
const struct ddsi_sertopic_ops ddsi_sertopic_ops_builtintopic = {
.deinit = sertopic_builtin_deinit,
.zero_samples = sertopic_builtin_zero_samples,
.realloc_samples = sertopic_builtin_realloc_samples,
.free_samples = sertopic_builtin_free_samples
};

View file

@ -0,0 +1,201 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include "os/os.h"
#include "ddsi/ddsi_serdata.h"
#include "ddsi/q_unused.h"
#include "ddsi/q_config.h"
#include "ddsi/q_ephash.h"
#include "ddsi/q_entity.h"
#include "ddsi/ddsi_tkmap.h"
#include "dds__serdata_builtintopic.h"
#include "dds__whc_builtintopic.h"
#include "dds__builtin.h"
struct bwhc {
struct whc common;
enum ddsi_sertopic_builtintopic_type type;
};
enum bwhc_iter_state {
BIS_INIT_LOCAL,
BIS_LOCAL,
BIS_INIT_PROXY,
BIS_PROXY
};
struct bwhc_iter {
struct whc_sample_iter_base c;
enum bwhc_iter_state st;
bool have_sample;
struct ephash_enum it;
};
/* 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];
};
static void bwhc_free (struct whc *whc_generic)
{
os_free (whc_generic);
}
static void bwhc_sample_iter_init (const struct whc *whc_generic, struct whc_sample_iter *opaque_it)
{
struct bwhc_iter *it = (struct bwhc_iter *) opaque_it;
it->c.whc = (struct whc *) whc_generic;
it->st = BIS_INIT_LOCAL;
it->have_sample = false;
}
static bool is_visible (const struct entity_common *e)
{
const nn_vendorid_t vendorid = get_entity_vendorid (e);
return ddsi_plugin.builtintopic_is_visible (e->guid.entityid, e->onlylocal, vendorid);
}
static bool bwhc_sample_iter_borrow_next (struct whc_sample_iter *opaque_it, struct whc_borrowed_sample *sample)
{
struct bwhc_iter * const it = (struct bwhc_iter *) opaque_it;
struct bwhc * const whc = (struct bwhc *) it->c.whc;
enum entity_kind kind = EK_PARTICIPANT; /* pacify gcc */
struct entity_common *entity;
if (it->have_sample)
{
ddsi_serdata_unref (sample->serdata);
it->have_sample = false;
}
/* most fields really don't matter, so memset */
memset (sample, 0, sizeof (*sample));
switch (it->st)
{
case BIS_INIT_LOCAL:
switch (whc->type) {
case DSBT_PARTICIPANT: kind = EK_PARTICIPANT; break;
case DSBT_WRITER: kind = EK_WRITER; break;
case DSBT_READER: kind = EK_READER; break;
}
assert (whc->type == DSBT_PARTICIPANT || kind != EK_PARTICIPANT);
ephash_enum_init (&it->it, kind);
it->st = BIS_LOCAL;
/* FALLS THROUGH */
case BIS_LOCAL:
while ((entity = ephash_enum_next (&it->it)) != NULL)
if (is_visible (entity))
break;
if (entity) {
sample->serdata = dds__builtin_make_sample (entity, entity->tupdate, true);
it->have_sample = true;
return true;
} else {
ephash_enum_fini (&it->it);
it->st = BIS_INIT_PROXY;
}
/* FALLS THROUGH */
case BIS_INIT_PROXY:
switch (whc->type) {
case DSBT_PARTICIPANT: kind = EK_PROXY_PARTICIPANT; break;
case DSBT_WRITER: kind = EK_PROXY_WRITER; break;
case DSBT_READER: kind = EK_PROXY_READER; break;
}
assert (kind != EK_PARTICIPANT);
ephash_enum_init (&it->it, kind);
it->st = BIS_PROXY;
/* FALLS THROUGH */
case BIS_PROXY:
while ((entity = ephash_enum_next (&it->it)) != NULL)
if (is_visible (entity))
break;
if (entity) {
sample->serdata = dds__builtin_make_sample (entity, entity->tupdate, true);
it->have_sample = true;
return true;
} else {
ephash_enum_fini (&it->it);
return false;
}
}
assert (0);
return false;
}
static void bwhc_get_state (const struct whc *whc, struct whc_state *st)
{
(void)whc;
st->max_seq = -1;
st->min_seq = -1;
st->unacked_bytes = 0;
}
static int bwhc_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)
{
(void)whc;
(void)max_drop_seq;
(void)seq;
(void)serdata;
(void)tk;
if (plist)
os_free (plist);
return 0;
}
static unsigned bwhc_downgrade_to_volatile (struct whc *whc, struct whc_state *st)
{
(void)whc;
(void)st;
return 0;
}
static unsigned bwhc_remove_acked_messages (struct whc *whc, seqno_t max_drop_seq, struct whc_state *whcst, struct whc_node **deferred_free_list)
{
(void)whc;
(void)max_drop_seq;
(void)whcst;
*deferred_free_list = NULL;
return 0;
}
static void bwhc_free_deferred_free_list (struct whc *whc, struct whc_node *deferred_free_list)
{
(void)whc;
(void)deferred_free_list;
}
static const struct whc_ops bwhc_ops = {
.insert = bwhc_insert,
.remove_acked_messages = bwhc_remove_acked_messages,
.free_deferred_free_list = bwhc_free_deferred_free_list,
.get_state = bwhc_get_state,
.next_seq = 0,
.borrow_sample = 0,
.borrow_sample_key = 0,
.return_sample = 0,
.sample_iter_init = bwhc_sample_iter_init,
.sample_iter_borrow_next = bwhc_sample_iter_borrow_next,
.downgrade_to_volatile = bwhc_downgrade_to_volatile,
.free = bwhc_free
};
struct whc *builtintopic_whc_new (enum ddsi_sertopic_builtintopic_type type)
{
struct bwhc *whc = os_malloc (sizeof (*whc));
whc->common.ops = &bwhc_ops;
whc->type = type;
return (struct whc *) whc;
}

View file

@ -26,327 +26,259 @@
#include "ddsi/q_entity.h"
#include "ddsi/q_radmin.h"
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_write(
_In_ dds_entity_t writer,
_In_ const void *data)
dds_return_t dds_write (dds_entity_t writer, const void *data)
{
dds_return_t ret;
dds__retcode_t rc;
dds_writer *wr;
dds_return_t ret;
dds__retcode_t rc;
dds_writer *wr;
if (data != NULL) {
rc = dds_writer_lock(writer, &wr);
if (rc == DDS_RETCODE_OK) {
ret = dds_write_impl(wr, data, dds_time(), 0);
dds_writer_unlock(wr);
} else {
DDS_ERROR("Error occurred on locking entity\n");
ret = DDS_ERRNO(rc);
}
} else {
DDS_ERROR("No data buffer provided\n");
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER);
}
if (data == NULL)
return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER);
return ret;
if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
return DDS_ERRNO (rc);
ret = dds_write_impl (wr, data, dds_time (), 0);
dds_writer_unlock (wr);
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
int
dds_writecdr(
dds_entity_t writer,
struct ddsi_serdata *serdata)
dds_return_t dds_writecdr (dds_entity_t writer, struct ddsi_serdata *serdata)
{
dds_return_t ret;
dds__retcode_t rc;
dds_writer *wr;
if (serdata != NULL) {
rc = dds_writer_lock(writer, &wr);
if (rc == DDS_RETCODE_OK) {
ret = dds_writecdr_impl (wr, serdata, dds_time (), 0);
dds_writer_unlock(wr);
} else {
DDS_ERROR("Error occurred on locking writer\n");
ret = DDS_ERRNO(rc);
}
} else{
DDS_ERROR("Given cdr has NULL value\n");
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER);
}
return ret;
dds_return_t ret;
dds__retcode_t rc;
dds_writer *wr;
if (serdata == NULL)
return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER);
if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
return DDS_ERRNO (rc);
ret = dds_writecdr_impl (wr, serdata, dds_time (), 0);
dds_writer_unlock (wr);
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_write_ts(
_In_ dds_entity_t writer,
_In_ const void *data,
_In_ dds_time_t timestamp)
dds_return_t dds_write_ts (dds_entity_t writer, const void *data, dds_time_t timestamp)
{
dds_return_t ret;
dds__retcode_t rc;
dds_writer *wr;
dds_return_t ret;
dds__retcode_t rc;
dds_writer *wr;
if(data == NULL){
DDS_ERROR("Argument data has NULL value\n");
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER);
goto err;
}
if(timestamp < 0){
DDS_ERROR("Argument timestamp has negative value\n");
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER);
goto err;
}
rc = dds_writer_lock(writer, &wr);
if (rc == DDS_RETCODE_OK) {
ret = dds_write_impl(wr, data, timestamp, 0);
dds_writer_unlock(wr);
} else {
DDS_ERROR("Error occurred on locking writer\n");
ret = DDS_ERRNO(rc);
}
err:
return ret;
if (data == NULL || timestamp < 0)
return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER);
if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
return DDS_ERRNO (rc);
ret = dds_write_impl (wr, data, timestamp, 0);
dds_writer_unlock (wr);
return ret;
}
static int
deliver_locally(
_In_ struct writer *wr,
_In_ struct ddsi_serdata *payload,
_In_ struct ddsi_tkmap_instance *tk)
static dds_return_t try_store (struct rhc *rhc, const struct proxy_writer_info *pwr_info, struct ddsi_serdata *payload, struct ddsi_tkmap_instance *tk, dds_duration_t *max_block_ms)
{
dds_return_t ret = DDS_RETCODE_OK;
os_mutexLock (&wr->rdary.rdary_lock);
if (wr->rdary.fastpath_ok) {
struct reader ** const rdary = wr->rdary.rdary;
if (rdary[0]) {
struct proxy_writer_info pwr_info;
unsigned i;
make_proxy_writer_info(&pwr_info, &wr->e, wr->xqos);
for (i = 0; rdary[i]; i++) {
bool stored;
DDS_TRACE("reader %x:%x:%x:%x\n", PGUID (rdary[i]->e.guid));
dds_duration_t max_block_ms = nn_from_ddsi_duration(wr->xqos->reliability.max_blocking_time) / DDS_NSECS_IN_MSEC;
do {
stored = (ddsi_plugin.rhc_plugin.rhc_store_fn) (rdary[i]->rhc, &pwr_info, payload, tk);
if (!stored) {
if (max_block_ms <= 0) {
DDS_ERROR("The writer could not deliver data on time, probably due to a local reader resources being full\n");
ret = DDS_ERRNO(DDS_RETCODE_TIMEOUT);
} else {
dds_sleepfor(DDS_MSECS(DDS_HEADBANG_TIMEOUT_MS));
}
/* Decreasing the block time after the sleep, let's us possibly
* wait a bit too long. But that's preferable compared to waiting
* a bit too short. */
max_block_ms -= DDS_HEADBANG_TIMEOUT_MS;
}
} while ((!stored) && (ret == DDS_RETCODE_OK));
}
}
os_mutexUnlock (&wr->rdary.rdary_lock);
} else {
/* When deleting, pwr is no longer accessible via the hash
tables, and consequently, a reader may be deleted without
it being possible to remove it from rdary. The primary
reason rdary exists is to avoid locking the proxy writer
but this is less of an issue when we are deleting it, so
we fall back to using the GUIDs so that we can deliver all
samples we received from it. As writer being deleted any
reliable samples that are rejected are simply discarded. */
ut_avlIter_t it;
struct pwr_rd_match *m;
struct proxy_writer_info pwr_info;
os_mutexUnlock (&wr->rdary.rdary_lock);
make_proxy_writer_info(&pwr_info, &wr->e, wr->xqos);
os_mutexLock (&wr->e.lock);
for (m = ut_avlIterFirst (&wr_local_readers_treedef, &wr->local_readers, &it); m != NULL; m = ut_avlIterNext (&it)) {
struct reader *rd;
if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) {
DDS_TRACE("reader-via-guid %x:%x:%x:%x\n", PGUID (rd->e.guid));
/* Copied the return value ignore from DDSI deliver_user_data() function. */
(void)(ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk);
}
}
os_mutexUnlock (&wr->e.lock);
while (!(ddsi_plugin.rhc_plugin.rhc_store_fn) (rhc, pwr_info, payload, tk))
{
if (*max_block_ms > 0)
{
dds_sleepfor (DDS_HEADBANG_TIMEOUT);
*max_block_ms -= DDS_HEADBANG_TIMEOUT;
}
return ret;
else
{
DDS_ERROR ("The writer could not deliver data on time, probably due to a local reader resources being full\n");
return DDS_ERRNO (DDS_RETCODE_TIMEOUT);
}
}
return DDS_RETCODE_OK;
}
int
dds_write_impl(
_In_ dds_writer *wr,
_In_ const void * data,
_In_ dds_time_t tstamp,
_In_ dds_write_action action)
static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *payload, struct ddsi_tkmap_instance *tk)
{
dds_return_t ret = DDS_RETCODE_OK;
int w_rc;
assert (wr);
assert (dds_entity_kind(((dds_entity*)wr)->m_hdl) == DDS_KIND_WRITER);
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
const bool writekey = action & DDS_WR_KEY_BIT;
dds_writer * writer = (dds_writer*) wr;
struct writer * ddsi_wr = writer->m_wr;
struct ddsi_tkmap_instance * tk;
struct ddsi_serdata *d;
if (data == NULL) {
DDS_ERROR("No data buffer provided\n");
return DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER);
dds_return_t ret = DDS_RETCODE_OK;
os_mutexLock (&wr->rdary.rdary_lock);
if (wr->rdary.fastpath_ok)
{
struct reader ** const rdary = wr->rdary.rdary;
if (rdary[0])
{
dds_duration_t max_block_ms = nn_from_ddsi_duration (wr->xqos->reliability.max_blocking_time);
struct proxy_writer_info pwr_info;
unsigned i;
make_proxy_writer_info (&pwr_info, &wr->e, wr->xqos);
for (i = 0; rdary[i]; i++) {
DDS_TRACE ("reader %x:%x:%x:%x\n", PGUID (rdary[i]->e.guid));
if ((ret = try_store (rdary[i]->rhc, &pwr_info, payload, tk, &max_block_ms)) != DDS_RETCODE_OK)
break;
}
}
/* Check for topic filter */
if (wr->m_topic->filter_fn && ! writekey) {
if (!(wr->m_topic->filter_fn) (data, wr->m_topic->filter_ctx)) {
return DDS_RETCODE_OK;
}
os_mutexUnlock (&wr->rdary.rdary_lock);
}
else
{
/* When deleting, pwr is no longer accessible via the hash
tables, and consequently, a reader may be deleted without
it being possible to remove it from rdary. The primary
reason rdary exists is to avoid locking the proxy writer
but this is less of an issue when we are deleting it, so
we fall back to using the GUIDs so that we can deliver all
samples we received from it. As writer being deleted any
reliable samples that are rejected are simply discarded. */
ut_avlIter_t it;
struct pwr_rd_match *m;
struct proxy_writer_info pwr_info;
dds_duration_t max_block_ms = nn_from_ddsi_duration (wr->xqos->reliability.max_blocking_time);
os_mutexUnlock (&wr->rdary.rdary_lock);
make_proxy_writer_info (&pwr_info, &wr->e, wr->xqos);
os_mutexLock (&wr->e.lock);
for (m = ut_avlIterFirst (&wr_local_readers_treedef, &wr->local_readers, &it); m != NULL; m = ut_avlIterNext (&it))
{
struct reader *rd;
if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL)
{
DDS_TRACE("reader-via-guid %x:%x:%x:%x\n", PGUID (rd->e.guid));
/* 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;
}
}
if (asleep) {
thread_state_awake (thr);
}
/* Serialize and write data or key */
d = ddsi_serdata_from_sample (ddsi_wr->topic, writekey ? SDK_KEY : SDK_DATA, data);
/* 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->timestamp.v = tstamp;
ddsi_serdata_ref(d);
tk = ddsi_tkmap_lookup_instance_ref(d);
w_rc = write_sample_gc (writer->m_xp, ddsi_wr, d, tk);
if (w_rc >= 0) {
/* Flush out write unless configured to batch */
if (! config.whc_batch){
nn_xpack_send (writer->m_xp, false);
}
ret = DDS_RETCODE_OK;
} else if (w_rc == ERR_TIMEOUT) {
DDS_ERROR("The writer could not deliver data on time, probably due to a reader resources being full\n");
ret = DDS_ERRNO(DDS_RETCODE_TIMEOUT);
} else if (w_rc == ERR_INVALID_DATA) {
DDS_ERROR("Invalid data provided\n");
ret = DDS_ERRNO(DDS_RETCODE_ERROR);
} else {
DDS_ERROR("Internal error\n");
ret = DDS_ERRNO(DDS_RETCODE_ERROR);
}
if (ret == DDS_RETCODE_OK) {
ret = deliver_locally (ddsi_wr, d, tk);
}
ddsi_serdata_unref(d);
ddsi_tkmap_instance_unref(tk);
if (asleep) {
thread_state_asleep (thr);
}
return ret;
os_mutexUnlock (&wr->e.lock);
}
return ret;
}
int
dds_writecdr_impl(
_In_ dds_writer *wr,
_Inout_ struct ddsi_serdata *d,
_In_ dds_time_t tstamp,
_In_ dds_write_action action)
dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstamp, dds_write_action action)
{
int ret = DDS_RETCODE_OK;
int w_rc;
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
const bool writekey = action & DDS_WR_KEY_BIT;
struct writer *ddsi_wr = wr->m_wr;
struct ddsi_tkmap_instance *tk;
struct ddsi_serdata *d;
dds_return_t ret = DDS_RETCODE_OK;
int w_rc;
assert (wr);
if (data == NULL)
{
DDS_ERROR("No data buffer provided\n");
return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER);
}
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
struct writer * ddsi_wr = wr->m_wr;
struct ddsi_tkmap_instance * tk;
/* Check for topic filter */
if (wr->m_topic->filter_fn && !writekey)
if (!(wr->m_topic->filter_fn) (data, wr->m_topic->filter_ctx))
return DDS_RETCODE_OK;
if (wr->m_topic->filter_fn) {
abort();
}
if (asleep)
thread_state_awake (thr);
if (asleep) {
thread_state_awake (thr);
}
/* 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->timestamp.v = tstamp;
ddsi_serdata_ref (d);
tk = ddsi_tkmap_lookup_instance_ref (d);
w_rc = write_sample_gc (wr->m_xp, ddsi_wr, d, tk);
/* 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->timestamp.v = tstamp;
ddsi_serdata_ref(d);
tk = ddsi_tkmap_lookup_instance_ref(d);
w_rc = write_sample_gc (wr->m_xp, ddsi_wr, d, tk);
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 == ERR_TIMEOUT) {
DDS_ERROR("The writer could not deliver data on time, probably due to a reader resources being full\n");
ret = DDS_ERRNO(DDS_RETCODE_TIMEOUT);
} else if (w_rc == ERR_INVALID_DATA) {
DDS_ERROR("Invalid data provided\n");
ret = DDS_ERRNO(DDS_RETCODE_ERROR);
} else {
DDS_ERROR("Internal error\n");
ret = DDS_ERRNO(DDS_RETCODE_ERROR);
}
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 == ERR_TIMEOUT) {
DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n");
ret = DDS_ERRNO (DDS_RETCODE_TIMEOUT);
} else if (w_rc == ERR_INVALID_DATA) {
DDS_ERROR ("Invalid data provided\n");
ret = DDS_ERRNO (DDS_RETCODE_ERROR);
} else {
DDS_ERROR ("Internal error\n");
ret = DDS_ERRNO (DDS_RETCODE_ERROR);
}
if (ret == DDS_RETCODE_OK)
ret = deliver_locally (ddsi_wr, d, tk);
ddsi_serdata_unref (d);
ddsi_tkmap_instance_unref (tk);
if (ret == DDS_RETCODE_OK) {
ret = deliver_locally (ddsi_wr, d, tk);
}
ddsi_serdata_unref(d);
ddsi_tkmap_instance_unref(tk);
if (asleep) {
thread_state_asleep (thr);
}
return ret;
if (asleep)
thread_state_asleep (thr);
return ret;
}
void
dds_write_set_batch(
bool enable)
dds_return_t dds_writecdr_impl_lowlevel (struct writer *ddsi_wr, struct nn_xpack *xp, struct ddsi_serdata *d)
{
config.whc_batch = enable ? 1 : 0;
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
struct ddsi_tkmap_instance * tk;
int ret = DDS_RETCODE_OK;
int w_rc;
if (asleep)
thread_state_awake (thr);
ddsi_serdata_ref (d);
tk = ddsi_tkmap_lookup_instance_ref (d);
w_rc = write_sample_gc (xp, ddsi_wr, d, tk);
if (w_rc >= 0) {
/* Flush out write unless configured to batch */
if (!config.whc_batch && xp != NULL)
nn_xpack_send (xp, false);
ret = DDS_RETCODE_OK;
} else if (w_rc == ERR_TIMEOUT) {
DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n");
ret = DDS_ERRNO(DDS_RETCODE_TIMEOUT);
} else if (w_rc == ERR_INVALID_DATA) {
DDS_ERROR ("Invalid data provided\n");
ret = DDS_ERRNO (DDS_RETCODE_ERROR);
} else {
DDS_ERROR ("Internal error\n");
ret = DDS_ERRNO (DDS_RETCODE_ERROR);
}
if (ret == DDS_RETCODE_OK)
ret = deliver_locally (ddsi_wr, d, tk);
ddsi_serdata_unref (d);
ddsi_tkmap_instance_unref (tk);
if (asleep)
thread_state_asleep (thr);
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
void
dds_write_flush(
dds_entity_t writer)
dds_return_t dds_writecdr_impl (dds_writer *wr, struct ddsi_serdata *d, dds_time_t tstamp, dds_write_action action)
{
dds__retcode_t rc;
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
dds_writer *wr;
if (asleep) {
thread_state_awake (thr);
}
rc = dds_writer_lock(writer, &wr);
if (rc == DDS_RETCODE_OK) {
nn_xpack_send (wr->m_xp, true);
dds_writer_unlock(wr);
} else{
DDS_ERROR("Error occurred on locking writer\n");
}
if (asleep) {
thread_state_asleep (thr);
}
return ;
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->timestamp.v = tstamp;
return dds_writecdr_impl_lowlevel (wr->m_wr, wr->m_xp, d);
}
void dds_write_set_batch (bool enable)
{
config.whc_batch = enable ? 1 : 0;
}
void dds_write_flush (dds_entity_t writer)
{
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
dds_writer *wr;
dds__retcode_t rc;
if (asleep)
thread_state_awake (thr);
if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
DDS_ERROR ("Error occurred on locking writer\n");
else
{
nn_xpack_send (wr->m_xp, true);
dds_writer_unlock (wr);
}
if (asleep)
thread_state_asleep (thr);
return;
}

View file

@ -147,20 +147,21 @@ check_default_qos_of_builtin_entity(dds_entity_t entity)
CU_Test(ddsc_builtin_topics, availability_builtin_topics, .init = setup, .fini = teardown)
{
/* FIXME: Successful lookup doesn't rhyme with them not being returned when looking at the children of the participant ... */
dds_entity_t topic;
topic = dds_find_topic(g_participant, "DCPSParticipant");
CU_ASSERT_FATAL(topic > 0);
dds_delete(topic);
CU_ASSERT_FATAL(topic < 0);
//dds_delete(topic);
topic = dds_find_topic(g_participant, "DCPSTopic");
CU_ASSERT_FATAL(topic < 0);
//TODO CHAM-347: dds_delete(topic);
//dds_delete(topic);
topic = dds_find_topic(g_participant, "DCPSSubscription");
CU_ASSERT_FATAL(topic > 0);
dds_delete(topic);
CU_ASSERT_FATAL(topic < 0);
//dds_delete(topic);
topic = dds_find_topic(g_participant, "DCPSPublication");
CU_ASSERT_FATAL(topic > 0);
dds_delete(topic);
CU_ASSERT_FATAL(topic < 0);
//dds_delete(topic);
}
CU_Test(ddsc_builtin_topics, read_publication_data, .init = setup, .fini = teardown)