Liveliness local readers
This commit adds support for liveliness QoS when using local readers. The implementation for (liveliness) expiration of writers used here is similar to that used with proxy writers, and it also supports the three liveliness kinds (1) automatic, which is trivial when using a local reader and writer, (2) manual-by-participant and (3) manual-by-topic. In addition, these changes and fixes are included in this commit: - Fixed a bug in heartbeat handling in the reader: for manual-by- participant writers the lease was not updated on reception of a heartbeat message with liveliness flag set. This is fixed and a test-case is added. - Include the liveliness flag in a heartbeat message to the trace - Trace all lease renewals, including liveliness leases - Replaced liveliness changed state 'twitch' by 2 subsequent calls to the status callback - Added a test for liveliness duration 0 and 1ns (for both local and remote readers) Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
This commit is contained in:
parent
bb76798492
commit
9410753076
9 changed files with 610 additions and 203 deletions
|
@ -254,9 +254,8 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data)
|
||||||
LIVELINESS_CHANGED_REMOVE_NOT_ALIVE < LIVELINESS_CHANGED_REMOVE_ALIVE &&
|
LIVELINESS_CHANGED_REMOVE_NOT_ALIVE < LIVELINESS_CHANGED_REMOVE_ALIVE &&
|
||||||
LIVELINESS_CHANGED_REMOVE_ALIVE < LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE &&
|
LIVELINESS_CHANGED_REMOVE_ALIVE < LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE &&
|
||||||
LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE < LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE &&
|
LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE < LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE &&
|
||||||
LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE < LIVELINESS_CHANGED_TWITCH &&
|
(uint32_t) LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE < UINT32_MAX);
|
||||||
(uint32_t) LIVELINESS_CHANGED_TWITCH < UINT32_MAX);
|
assert (data->extra <= (uint32_t) LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE);
|
||||||
assert (data->extra <= (uint32_t) LIVELINESS_CHANGED_TWITCH);
|
|
||||||
switch ((enum liveliness_changed_data_extra) data->extra)
|
switch ((enum liveliness_changed_data_extra) data->extra)
|
||||||
{
|
{
|
||||||
case LIVELINESS_CHANGED_ADD_ALIVE:
|
case LIVELINESS_CHANGED_ADD_ALIVE:
|
||||||
|
@ -287,8 +286,6 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data)
|
||||||
st->alive_count++;
|
st->alive_count++;
|
||||||
st->alive_count_change++;
|
st->alive_count_change++;
|
||||||
break;
|
break;
|
||||||
case LIVELINESS_CHANGED_TWITCH:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
st->last_publication_handle = data->handle;
|
st->last_publication_handle = data->handle;
|
||||||
invoke = (lst->on_liveliness_changed != 0);
|
invoke = (lst->on_liveliness_changed != 0);
|
||||||
|
|
|
@ -153,10 +153,11 @@ CU_TheoryDataPoints(ddsc_liveliness, pmd_count) = {
|
||||||
#undef MT
|
#undef MT
|
||||||
#undef MP
|
#undef MP
|
||||||
#undef A
|
#undef A
|
||||||
CU_Theory((dds_liveliness_kind_t kind, uint32_t ldur, double mult), ddsc_liveliness, pmd_count, .init = liveliness_init, .fini = liveliness_fini, .timeout = 30)
|
|
||||||
|
static void test_pmd_count(dds_liveliness_kind_t kind, uint32_t ldur, double mult, bool remote_reader)
|
||||||
{
|
{
|
||||||
dds_entity_t pub_topic;
|
dds_entity_t pub_topic;
|
||||||
dds_entity_t sub_topic;
|
dds_entity_t sub_topic = 0;
|
||||||
dds_entity_t reader;
|
dds_entity_t reader;
|
||||||
dds_entity_t writer;
|
dds_entity_t writer;
|
||||||
seqno_t start_seqno, end_seqno;
|
seqno_t start_seqno, end_seqno;
|
||||||
|
@ -169,9 +170,9 @@ CU_Theory((dds_liveliness_kind_t kind, uint32_t ldur, double mult), ddsc_livelin
|
||||||
dds_time_t t;
|
dds_time_t t;
|
||||||
|
|
||||||
t = dds_time();
|
t = dds_time();
|
||||||
printf("%d.%06d running test: kind %s, lease duration %d, delay %d\n",
|
printf("%d.%06d running test: kind %s, lease duration %d, delay %d, %s reader\n",
|
||||||
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000,
|
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000,
|
||||||
kind == 0 ? "A" : "MP", ldur, (int32_t)(mult * ldur));
|
kind == 0 ? "A" : "MP", ldur, (int32_t)(mult * ldur), remote_reader ? "remote" : "local");
|
||||||
|
|
||||||
/* wait for initial PMD to be sent by the participant */
|
/* wait for initial PMD to be sent by the participant */
|
||||||
while (get_pmd_seqno(g_pub_participant) < 1)
|
while (get_pmd_seqno(g_pub_participant) < 1)
|
||||||
|
@ -180,17 +181,18 @@ CU_Theory((dds_liveliness_kind_t kind, uint32_t ldur, double mult), ddsc_livelin
|
||||||
/* topics */
|
/* topics */
|
||||||
create_topic_name("ddsc_liveliness_pmd_count", g_topic_nr++, name, sizeof name);
|
create_topic_name("ddsc_liveliness_pmd_count", g_topic_nr++, name, sizeof name);
|
||||||
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||||
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
if (remote_reader)
|
||||||
|
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||||
|
|
||||||
/* reader */
|
/* reader */
|
||||||
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
||||||
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||||
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
|
CU_ASSERT_FATAL((reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_topic, rqos, NULL)) > 0);
|
||||||
dds_delete_qos(rqos);
|
dds_delete_qos(rqos);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||||
|
|
||||||
/* waitset on reader */
|
/* waitset on reader */
|
||||||
CU_ASSERT_FATAL((waitset = dds_create_waitset(g_sub_participant)) > 0);
|
CU_ASSERT_FATAL((waitset = dds_create_waitset(remote_reader ? g_sub_participant : g_pub_participant)) > 0);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
||||||
|
|
||||||
/* writer */
|
/* writer */
|
||||||
|
@ -221,12 +223,19 @@ CU_Theory((dds_liveliness_kind_t kind, uint32_t ldur, double mult), ddsc_livelin
|
||||||
CU_ASSERT(get_pmd_seqno(g_pub_participant) - start_seqno < mult)
|
CU_ASSERT(get_pmd_seqno(g_pub_participant) - start_seqno < mult)
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
if (remote_reader)
|
||||||
|
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(writer), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(writer), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CU_Theory((dds_liveliness_kind_t kind, uint32_t ldur, double mult), ddsc_liveliness, pmd_count, .init = liveliness_init, .fini = liveliness_fini, .timeout = 30)
|
||||||
|
{
|
||||||
|
test_pmd_count(kind, ldur, mult, false);
|
||||||
|
test_pmd_count(kind, ldur, mult, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that the expected number of proxy writers expires (set to not-alive)
|
* Test that the expected number of proxy writers expires (set to not-alive)
|
||||||
* after a certain delay for various combinations of writers with different
|
* after a certain delay for various combinations of writers with different
|
||||||
|
@ -239,10 +248,11 @@ CU_TheoryDataPoints(ddsc_liveliness, expire_liveliness_kinds) = {
|
||||||
CU_DataPoints(uint32_t, 1, 1, 2, 2, 0, 0, 0, 1, 0, 2, 2, 5, 10, 0, 15), /* number of writers with manual-by-participant liveliness */
|
CU_DataPoints(uint32_t, 1, 1, 2, 2, 0, 0, 0, 1, 0, 2, 2, 5, 10, 0, 15), /* number of writers with manual-by-participant liveliness */
|
||||||
CU_DataPoints(uint32_t, 1, 1, 2, 2, 1, 1, 1, 1, 0, 1, 1, 2, 5, 0, 10), /* number of writers with manual-by-topic liveliness */
|
CU_DataPoints(uint32_t, 1, 1, 2, 2, 1, 1, 1, 1, 0, 1, 1, 2, 5, 0, 10), /* number of writers with manual-by-topic liveliness */
|
||||||
};
|
};
|
||||||
CU_Theory((uint32_t ldur, double mult, uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp), ddsc_liveliness, expire_liveliness_kinds, .init = liveliness_init, .fini = liveliness_fini, .timeout = 120)
|
|
||||||
|
static void test_expire_liveliness_kinds(uint32_t ldur, double mult, uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp, bool remote_reader)
|
||||||
{
|
{
|
||||||
dds_entity_t pub_topic;
|
dds_entity_t pub_topic;
|
||||||
dds_entity_t sub_topic;
|
dds_entity_t sub_topic = 0;
|
||||||
dds_entity_t reader;
|
dds_entity_t reader;
|
||||||
dds_entity_t *writers;
|
dds_entity_t *writers;
|
||||||
dds_qos_t *rqos, *wqos_auto, *wqos_man_pp, *wqos_man_tp;
|
dds_qos_t *rqos, *wqos_auto, *wqos_man_pp, *wqos_man_tp;
|
||||||
|
@ -257,19 +267,20 @@ CU_Theory((uint32_t ldur, double mult, uint32_t wr_cnt_auto, uint32_t wr_cnt_man
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
tstart = dds_time();
|
tstart = dds_time();
|
||||||
printf("%d.%06d running test: lease duration %d, delay %f, auto/man-by-part/man-by-topic %u/%u/%u\n",
|
printf("%d.%06d running test: lease duration %d, delay %f, auto/man-by-part/man-by-topic %u/%u/%u\n, %s reader",
|
||||||
(int32_t)(tstart / DDS_NSECS_IN_SEC), (int32_t)(tstart % DDS_NSECS_IN_SEC) / 1000,
|
(int32_t)(tstart / DDS_NSECS_IN_SEC), (int32_t)(tstart % DDS_NSECS_IN_SEC) / 1000,
|
||||||
ldur, mult, wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp);
|
ldur, mult, wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, remote_reader ? "remote" : "local");
|
||||||
|
|
||||||
/* topics */
|
/* topics */
|
||||||
create_topic_name("ddsc_liveliness_expire_kinds", g_topic_nr++, name, sizeof name);
|
create_topic_name("ddsc_liveliness_expire_kinds", g_topic_nr++, name, sizeof name);
|
||||||
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||||
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
if (remote_reader)
|
||||||
|
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||||
|
|
||||||
/* reader */
|
/* reader */
|
||||||
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
||||||
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||||
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
|
CU_ASSERT_FATAL((reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_topic, rqos, NULL)) > 0);
|
||||||
dds_delete_qos(rqos);
|
dds_delete_qos(rqos);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||||
|
|
||||||
|
@ -281,7 +292,7 @@ CU_Theory((uint32_t ldur, double mult, uint32_t wr_cnt_auto, uint32_t wr_cnt_man
|
||||||
CU_ASSERT_FATAL((wqos_man_tp = dds_create_qos()) != NULL);
|
CU_ASSERT_FATAL((wqos_man_tp = dds_create_qos()) != NULL);
|
||||||
dds_qset_liveliness(wqos_man_tp, DDS_LIVELINESS_MANUAL_BY_TOPIC, DDS_MSECS(ldur));
|
dds_qset_liveliness(wqos_man_tp, DDS_LIVELINESS_MANUAL_BY_TOPIC, DDS_MSECS(ldur));
|
||||||
|
|
||||||
CU_ASSERT_FATAL((waitset = dds_create_waitset(g_sub_participant)) > 0);
|
CU_ASSERT_FATAL((waitset = dds_create_waitset(remote_reader ? g_sub_participant : g_pub_participant)) > 0);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
||||||
|
|
||||||
writers = dds_alloc(wr_cnt * sizeof(dds_entity_t));
|
writers = dds_alloc(wr_cnt * sizeof(dds_entity_t));
|
||||||
|
@ -347,7 +358,8 @@ CU_Theory((uint32_t ldur, double mult, uint32_t wr_cnt_auto, uint32_t wr_cnt_man
|
||||||
for (n = 0; n < wr_cnt; n++)
|
for (n = 0; n < wr_cnt; n++)
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(writers[n]), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(writers[n]), DDS_RETCODE_OK);
|
||||||
dds_free(writers);
|
dds_free(writers);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
if (remote_reader)
|
||||||
|
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
||||||
|
|
||||||
|
@ -369,14 +381,21 @@ CU_Theory((uint32_t ldur, double mult, uint32_t wr_cnt_auto, uint32_t wr_cnt_man
|
||||||
} while (!test_finished);
|
} while (!test_finished);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_and_check_writer(dds_liveliness_kind_t kind, dds_duration_t ldur, dds_entity_t *writer, dds_entity_t topic, dds_entity_t reader)
|
CU_Theory((uint32_t ldur, double mult, uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp), ddsc_liveliness, expire_liveliness_kinds, .init = liveliness_init, .fini = liveliness_fini, .timeout = 120)
|
||||||
|
{
|
||||||
|
test_expire_liveliness_kinds (ldur, mult, wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, false);
|
||||||
|
test_expire_liveliness_kinds (ldur, mult, wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void add_and_check_writer(dds_liveliness_kind_t kind, dds_duration_t ldur, dds_entity_t *writer, dds_entity_t topic, dds_entity_t reader, bool remote_reader)
|
||||||
{
|
{
|
||||||
dds_entity_t waitset;
|
dds_entity_t waitset;
|
||||||
dds_qos_t *wqos;
|
dds_qos_t *wqos;
|
||||||
dds_attach_t triggered;
|
dds_attach_t triggered;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
|
|
||||||
CU_ASSERT_FATAL((waitset = dds_create_waitset(g_sub_participant)) > 0);
|
CU_ASSERT_FATAL((waitset = dds_create_waitset(remote_reader ? g_sub_participant : g_pub_participant)) > 0);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
||||||
|
|
||||||
CU_ASSERT_FATAL((wqos = dds_create_qos()) != NULL);
|
CU_ASSERT_FATAL((wqos = dds_create_qos()) != NULL);
|
||||||
|
@ -424,22 +443,22 @@ CU_Test(ddsc_liveliness, lease_duration, .init = liveliness_init, .fini = liveli
|
||||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), get_ldur_config(g_pub_participant));
|
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), get_ldur_config(g_pub_participant));
|
||||||
|
|
||||||
/* create writers and check pmd interval in publishing participant */
|
/* create writers and check pmd interval in publishing participant */
|
||||||
add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(1000), &writers[wr_cnt++], pub_topic, reader);
|
add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(1000), &writers[wr_cnt++], pub_topic, reader, true);
|
||||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(1000));
|
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(1000));
|
||||||
|
|
||||||
add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(2000), &writers[wr_cnt++], pub_topic, reader);
|
add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(2000), &writers[wr_cnt++], pub_topic, reader, true);
|
||||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(1000));
|
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(1000));
|
||||||
|
|
||||||
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(2000), &writers[wr_cnt++], pub_topic, reader);
|
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(2000), &writers[wr_cnt++], pub_topic, reader, true);
|
||||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(1000));
|
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(1000));
|
||||||
|
|
||||||
add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(500), &writers[wr_cnt++], pub_topic, reader);
|
add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(500), &writers[wr_cnt++], pub_topic, reader, true);
|
||||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(500));
|
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(500));
|
||||||
|
|
||||||
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(100), &writers[wr_cnt++], pub_topic, reader);
|
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(100), &writers[wr_cnt++], pub_topic, reader, true);
|
||||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(500));
|
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(500));
|
||||||
|
|
||||||
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_TOPIC, DDS_MSECS(100), &writers[wr_cnt++], pub_topic, reader);
|
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_TOPIC, DDS_MSECS(100), &writers[wr_cnt++], pub_topic, reader, true);
|
||||||
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(500));
|
CU_ASSERT_EQUAL_FATAL(get_pmd_interval(g_pub_participant), DDS_MSECS(500));
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
|
@ -454,10 +473,10 @@ CU_Test(ddsc_liveliness, lease_duration, .init = liveliness_init, .fini = liveli
|
||||||
/**
|
/**
|
||||||
* Check that the correct lease duration is set in the matched
|
* Check that the correct lease duration is set in the matched
|
||||||
* publications in the readers. */
|
* publications in the readers. */
|
||||||
CU_Test(ddsc_liveliness, lease_duration_pwr, .init = liveliness_init, .fini = liveliness_fini)
|
static void test_lease_duration_pwr(bool remote_reader)
|
||||||
{
|
{
|
||||||
dds_entity_t pub_topic;
|
dds_entity_t pub_topic;
|
||||||
dds_entity_t sub_topic;
|
dds_entity_t sub_topic = 0;
|
||||||
dds_entity_t reader;
|
dds_entity_t reader;
|
||||||
dds_entity_t writer;
|
dds_entity_t writer;
|
||||||
char name[100];
|
char name[100];
|
||||||
|
@ -467,15 +486,18 @@ CU_Test(ddsc_liveliness, lease_duration_pwr, .init = liveliness_init, .fini = li
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
dds_duration_t ldur;
|
dds_duration_t ldur;
|
||||||
|
|
||||||
|
printf("running test lease_duration_pwr: %s reader\n", remote_reader ? "remote" : "local");
|
||||||
|
|
||||||
/* topics */
|
/* topics */
|
||||||
create_topic_name("ddsc_liveliness_ldurpwr", 1, name, sizeof name);
|
create_topic_name("ddsc_liveliness_ldurpwr", 1, name, sizeof name);
|
||||||
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||||
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
if (remote_reader)
|
||||||
|
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||||
|
|
||||||
/* reader */
|
/* reader */
|
||||||
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
||||||
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||||
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
|
CU_ASSERT_FATAL((reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_topic, rqos, NULL)) > 0);
|
||||||
dds_delete_qos(rqos);
|
dds_delete_qos(rqos);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||||
|
|
||||||
|
@ -486,7 +508,7 @@ CU_Test(ddsc_liveliness, lease_duration_pwr, .init = liveliness_init, .fini = li
|
||||||
CU_ASSERT_FATAL((writer = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
|
CU_ASSERT_FATAL((writer = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
|
||||||
|
|
||||||
/* wait for writer to be alive */
|
/* wait for writer to be alive */
|
||||||
CU_ASSERT_FATAL((waitset = dds_create_waitset(g_sub_participant)) > 0);
|
CU_ASSERT_FATAL((waitset = dds_create_waitset(remote_reader ? g_sub_participant : g_pub_participant)) > 0);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_MSECS(1000)), 1);
|
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_MSECS(1000)), 1);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_take_status(reader, &status, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_take_status(reader, &status, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||||
|
@ -509,11 +531,18 @@ CU_Test(ddsc_liveliness, lease_duration_pwr, .init = liveliness_init, .fini = li
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_detach(waitset, reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_waitset_detach(waitset, reader), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(waitset), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(waitset), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(writer), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(writer), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
if (remote_reader)
|
||||||
|
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CU_Test(ddsc_liveliness, lease_duration_pwr, .init = liveliness_init, .fini = liveliness_fini)
|
||||||
|
{
|
||||||
|
test_lease_duration_pwr(false);
|
||||||
|
test_lease_duration_pwr(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a relative large number of writers with liveliness kinds automatic and
|
* Create a relative large number of writers with liveliness kinds automatic and
|
||||||
* manual-by-participant and with decreasing lease duration, and check that all
|
* manual-by-participant and with decreasing lease duration, and check that all
|
||||||
|
@ -521,10 +550,11 @@ CU_Test(ddsc_liveliness, lease_duration_pwr, .init = liveliness_init, .fini = li
|
||||||
* is deleted immediately after creating.
|
* is deleted immediately after creating.
|
||||||
*/
|
*/
|
||||||
#define MAX_WRITERS 100
|
#define MAX_WRITERS 100
|
||||||
CU_Test(ddsc_liveliness, create_delete_writer_stress, .init = liveliness_init, .fini = liveliness_fini, .timeout = 15)
|
|
||||||
|
static void test_create_delete_writer_stress(bool remote_reader)
|
||||||
{
|
{
|
||||||
dds_entity_t pub_topic;
|
dds_entity_t pub_topic;
|
||||||
dds_entity_t sub_topic;
|
dds_entity_t sub_topic = 0;
|
||||||
dds_entity_t reader;
|
dds_entity_t reader;
|
||||||
dds_entity_t writers[MAX_WRITERS];
|
dds_entity_t writers[MAX_WRITERS];
|
||||||
dds_entity_t waitset;
|
dds_entity_t waitset;
|
||||||
|
@ -538,18 +568,21 @@ CU_Test(ddsc_liveliness, create_delete_writer_stress, .init = liveliness_init, .
|
||||||
Space_Type1 sample = {0, 0, 0};
|
Space_Type1 sample = {0, 0, 0};
|
||||||
int64_t ldur = 1000;
|
int64_t ldur = 1000;
|
||||||
|
|
||||||
|
printf("running test create_delete_writer_stress: %s reader\n", remote_reader ? "remote" : "local");
|
||||||
|
|
||||||
/* topics */
|
/* topics */
|
||||||
create_topic_name("ddsc_liveliness_wr_stress", 1, name, sizeof name);
|
create_topic_name("ddsc_liveliness_wr_stress", 1, name, sizeof name);
|
||||||
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||||
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
if (remote_reader)
|
||||||
|
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||||
|
|
||||||
/* reader and waitset */
|
/* reader and waitset */
|
||||||
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
||||||
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||||
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
|
CU_ASSERT_FATAL((reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_topic, rqos, NULL)) > 0);
|
||||||
dds_delete_qos(rqos);
|
dds_delete_qos(rqos);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_FATAL((waitset = dds_create_waitset(g_sub_participant)) > 0);
|
CU_ASSERT_FATAL((waitset = dds_create_waitset(remote_reader ? g_sub_participant : g_pub_participant)) > 0);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
||||||
|
|
||||||
/* create 1st writer and wait for it to become alive */
|
/* create 1st writer and wait for it to become alive */
|
||||||
|
@ -604,42 +637,53 @@ CU_Test(ddsc_liveliness, create_delete_writer_stress, .init = liveliness_init, .
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_detach(waitset, reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_waitset_detach(waitset, reader), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(waitset), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(waitset), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
if (remote_reader)
|
||||||
|
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CU_Test(ddsc_liveliness, create_delete_writer_stress, .init = liveliness_init, .fini = liveliness_fini, .timeout = 15)
|
||||||
|
{
|
||||||
|
test_create_delete_writer_stress(false);
|
||||||
|
test_create_delete_writer_stress(true);
|
||||||
|
}
|
||||||
#undef MAX_WRITERS
|
#undef MAX_WRITERS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the counts in liveliness_changed_status result.
|
* Check the counts in liveliness_changed_status result.
|
||||||
*/
|
*/
|
||||||
CU_Test(ddsc_liveliness, status_counts, .init = liveliness_init, .fini = liveliness_fini)
|
static void test_status_counts(bool remote_reader)
|
||||||
{
|
{
|
||||||
dds_entity_t pub_topic;
|
dds_entity_t pub_topic;
|
||||||
dds_entity_t sub_topic;
|
dds_entity_t sub_topic = 0;
|
||||||
dds_entity_t reader;
|
dds_entity_t reader;
|
||||||
dds_entity_t writer;
|
dds_entity_t writer;
|
||||||
dds_entity_t waitset;
|
dds_entity_t waitset;
|
||||||
dds_qos_t *rqos;
|
dds_qos_t *rqos;
|
||||||
dds_qos_t *wqos;
|
dds_qos_t *wqos;
|
||||||
dds_attach_t triggered;
|
dds_attach_t triggered;
|
||||||
struct dds_liveliness_changed_status lstatus;
|
struct dds_liveliness_changed_status lcstatus;
|
||||||
|
struct dds_liveliness_lost_status llstatus;
|
||||||
struct dds_subscription_matched_status sstatus;
|
struct dds_subscription_matched_status sstatus;
|
||||||
char name[100];
|
char name[100];
|
||||||
dds_duration_t ldur = DDS_MSECS(500);
|
dds_duration_t ldur = DDS_MSECS(500);
|
||||||
Space_Type1 sample = {1, 0, 0};
|
Space_Type1 sample = {1, 0, 0};
|
||||||
|
|
||||||
|
printf("running test status_counts: %s reader\n", remote_reader ? "remote" : "local");
|
||||||
|
|
||||||
/* topics */
|
/* topics */
|
||||||
create_topic_name("ddsc_liveliness_status_counts", g_topic_nr++, name, sizeof name);
|
create_topic_name("ddsc_liveliness_status_counts", g_topic_nr++, name, sizeof name);
|
||||||
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||||
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
if (remote_reader)
|
||||||
|
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||||
|
|
||||||
/* reader */
|
/* reader */
|
||||||
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
||||||
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||||
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
|
CU_ASSERT_FATAL((reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_topic, rqos, NULL)) > 0);
|
||||||
dds_delete_qos(rqos);
|
dds_delete_qos(rqos);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_FATAL((waitset = dds_create_waitset(g_sub_participant)) > 0);
|
CU_ASSERT_FATAL((waitset = dds_create_waitset(remote_reader ? g_sub_participant : g_pub_participant)) > 0);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_waitset_attach(waitset, reader, reader), DDS_RETCODE_OK);
|
||||||
|
|
||||||
/* writer */
|
/* writer */
|
||||||
|
@ -647,56 +691,72 @@ CU_Test(ddsc_liveliness, status_counts, .init = liveliness_init, .fini = livelin
|
||||||
dds_qset_liveliness(wqos, DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, ldur);
|
dds_qset_liveliness(wqos, DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, ldur);
|
||||||
CU_ASSERT_FATAL((writer = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
|
CU_ASSERT_FATAL((writer = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
|
||||||
dds_delete_qos(wqos);
|
dds_delete_qos(wqos);
|
||||||
|
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(writer, DDS_LIVELINESS_LOST_STATUS), DDS_RETCODE_OK);
|
||||||
|
|
||||||
/* wait for writer to be alive */
|
/* wait for writer to be alive */
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
|
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
|
||||||
|
|
||||||
/* check status counts before proxy writer is expired */
|
/* check status counts before proxy writer is expired */
|
||||||
dds_get_liveliness_changed_status(reader, &lstatus);
|
dds_get_liveliness_changed_status(reader, &lcstatus);
|
||||||
CU_ASSERT_EQUAL_FATAL(lstatus.alive_count, 1);
|
CU_ASSERT_EQUAL_FATAL(lcstatus.alive_count, 1);
|
||||||
dds_get_subscription_matched_status(reader, &sstatus);
|
dds_get_subscription_matched_status(reader, &sstatus);
|
||||||
CU_ASSERT_EQUAL_FATAL(sstatus.current_count, 1);
|
CU_ASSERT_EQUAL_FATAL(sstatus.current_count, 1);
|
||||||
|
dds_get_liveliness_lost_status(writer, &llstatus);
|
||||||
|
CU_ASSERT_EQUAL_FATAL(llstatus.total_count, 0);
|
||||||
|
|
||||||
/* sleep for more than lease duration, writer should be set not-alive but subscription still matched */
|
/* sleep for more than lease duration, writer should be set not-alive but subscription still matched */
|
||||||
dds_sleepfor(ldur + DDS_MSECS(100));
|
dds_sleepfor(ldur + DDS_MSECS(100));
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
|
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
|
||||||
|
|
||||||
dds_get_liveliness_changed_status(reader, &lstatus);
|
dds_get_liveliness_changed_status(reader, &lcstatus);
|
||||||
CU_ASSERT_EQUAL_FATAL(lstatus.alive_count, 0);
|
CU_ASSERT_EQUAL_FATAL(lcstatus.alive_count, 0);
|
||||||
dds_get_subscription_matched_status(reader, &sstatus);
|
dds_get_subscription_matched_status(reader, &sstatus);
|
||||||
CU_ASSERT_EQUAL_FATAL(sstatus.current_count, 1);
|
CU_ASSERT_EQUAL_FATAL(sstatus.current_count, 1);
|
||||||
|
dds_get_liveliness_lost_status(writer, &llstatus);
|
||||||
|
CU_ASSERT_EQUAL_FATAL(llstatus.total_count, 1);
|
||||||
|
CU_ASSERT_EQUAL_FATAL(llstatus.total_count_change, 1);
|
||||||
|
|
||||||
/* write sample and re-check status counts */
|
/* write sample and re-check status counts */
|
||||||
dds_write(writer, &sample);
|
dds_write(writer, &sample);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
|
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
|
||||||
|
|
||||||
dds_get_liveliness_changed_status(reader, &lstatus);
|
dds_get_liveliness_changed_status(reader, &lcstatus);
|
||||||
CU_ASSERT_EQUAL_FATAL(lstatus.alive_count, 1);
|
CU_ASSERT_EQUAL_FATAL(lcstatus.alive_count, 1);
|
||||||
dds_get_subscription_matched_status(reader, &sstatus);
|
dds_get_subscription_matched_status(reader, &sstatus);
|
||||||
CU_ASSERT_EQUAL_FATAL(sstatus.current_count, 1);
|
CU_ASSERT_EQUAL_FATAL(sstatus.current_count, 1);
|
||||||
|
dds_get_liveliness_lost_status(writer, &llstatus);
|
||||||
|
CU_ASSERT_EQUAL_FATAL(llstatus.total_count_change, 0);
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_waitset_detach(waitset, reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_waitset_detach(waitset, reader), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(waitset), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(waitset), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(writer), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(writer), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
if (remote_reader)
|
||||||
|
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CU_Test(ddsc_liveliness, status_counts, .init = liveliness_init, .fini = liveliness_fini)
|
||||||
|
{
|
||||||
|
test_status_counts(false);
|
||||||
|
test_status_counts(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that dds_assert_liveliness works as expected for liveliness
|
* Test that dds_assert_liveliness works as expected for liveliness
|
||||||
* kinds manual-by-participant and manual-by-topic.
|
* kinds manual-by-participant and manual-by-topic.
|
||||||
*/
|
*/
|
||||||
#define MAX_WRITERS 100
|
#define MAX_WRITERS 100
|
||||||
CU_TheoryDataPoints(ddsc_liveliness, assert_liveliness) = {
|
CU_TheoryDataPoints(ddsc_liveliness, assert_liveliness) = {
|
||||||
CU_DataPoints(uint32_t, 1, 0, 0, 1), /* number of writers with automatic liveliness */
|
CU_DataPoints(uint32_t, 1, 0, 0, 1, 0, 1, 2), /* number of writers with automatic liveliness */
|
||||||
CU_DataPoints(uint32_t, 1, 1, 0, 0), /* number of writers with manual-by-participant liveliness */
|
CU_DataPoints(uint32_t, 0, 1, 0, 1, 1, 0, 2), /* number of writers with manual-by-participant liveliness */
|
||||||
CU_DataPoints(uint32_t, 1, 1, 1, 2), /* number of writers with manual-by-topic liveliness */
|
CU_DataPoints(uint32_t, 0, 0, 1, 1, 2, 2, 0), /* number of writers with manual-by-topic liveliness */
|
||||||
};
|
};
|
||||||
CU_Theory((uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp), ddsc_liveliness, assert_liveliness, .init = liveliness_init, .fini = liveliness_fini, .timeout = 60)
|
|
||||||
|
static void test_assert_liveliness(uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp, bool remote_reader)
|
||||||
{
|
{
|
||||||
dds_entity_t pub_topic, sub_topic, reader, writers[MAX_WRITERS];
|
dds_entity_t pub_topic, sub_topic = 0, reader, writers[MAX_WRITERS];
|
||||||
dds_qos_t *rqos;
|
dds_qos_t *rqos;
|
||||||
struct dds_liveliness_changed_status lstatus;
|
struct dds_liveliness_changed_status lstatus;
|
||||||
char name[100];
|
char name[100];
|
||||||
|
@ -708,29 +768,30 @@ CU_Theory((uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp)
|
||||||
{
|
{
|
||||||
wr_cnt = 0;
|
wr_cnt = 0;
|
||||||
assert(wr_cnt_auto + wr_cnt_man_pp + wr_cnt_man_tp < MAX_WRITERS);
|
assert(wr_cnt_auto + wr_cnt_man_pp + wr_cnt_man_tp < MAX_WRITERS);
|
||||||
printf("running test assert_liveliness: auto/man-by-part/man-by-topic %u/%u/%u with ldur %d\n",
|
printf("running test assert_liveliness: auto/man-by-part/man-by-topic %u/%u/%u with ldur %d, %s reader\n",
|
||||||
wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, ldur);
|
wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, ldur, remote_reader ? "remote" : "local");
|
||||||
|
|
||||||
/* topics */
|
/* topics */
|
||||||
create_topic_name("ddsc_liveliness_assert", g_topic_nr++, name, sizeof name);
|
create_topic_name("ddsc_liveliness_assert", g_topic_nr++, name, sizeof name);
|
||||||
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||||
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
if (remote_reader)
|
||||||
|
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
|
||||||
|
|
||||||
/* reader */
|
/* reader */
|
||||||
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
|
||||||
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||||
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
|
CU_ASSERT_FATAL((reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_topic, rqos, NULL)) > 0);
|
||||||
dds_delete_qos(rqos);
|
dds_delete_qos(rqos);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
|
||||||
|
|
||||||
/* writers */
|
/* writers */
|
||||||
for (size_t n = 0; n < wr_cnt_auto; n++)
|
for (size_t n = 0; n < wr_cnt_auto; n++)
|
||||||
add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(ldur), &writers[wr_cnt++], pub_topic, reader);
|
add_and_check_writer(DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(ldur), &writers[wr_cnt++], pub_topic, reader, remote_reader);
|
||||||
tstart = dds_time();
|
tstart = dds_time();
|
||||||
for (size_t n = 0; n < wr_cnt_man_pp; n++)
|
for (size_t n = 0; n < wr_cnt_man_pp; n++)
|
||||||
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(ldur), &writers[wr_cnt++], pub_topic, reader);
|
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(ldur), &writers[wr_cnt++], pub_topic, reader, remote_reader);
|
||||||
for (size_t n = 0; n < wr_cnt_man_tp; n++)
|
for (size_t n = 0; n < wr_cnt_man_tp; n++)
|
||||||
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_TOPIC, DDS_MSECS(ldur), &writers[wr_cnt++], pub_topic, reader);
|
add_and_check_writer(DDS_LIVELINESS_MANUAL_BY_TOPIC, DDS_MSECS(ldur), &writers[wr_cnt++], pub_topic, reader, remote_reader);
|
||||||
t = dds_time();
|
t = dds_time();
|
||||||
if (t - tstart > DDS_MSECS(0.5 * ldur))
|
if (t - tstart > DDS_MSECS(0.5 * ldur))
|
||||||
{
|
{
|
||||||
|
@ -750,13 +811,13 @@ CU_Theory((uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp)
|
||||||
stopped = 0;
|
stopped = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
for (size_t n = wr_cnt - wr_cnt_man_tp; n < wr_cnt; n++)
|
for (size_t n = wr_cnt_auto; n < wr_cnt; n++)
|
||||||
dds_assert_liveliness(writers[n]);
|
CU_ASSERT_EQUAL_FATAL(dds_assert_liveliness(writers[n]), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
|
||||||
stopped += (uint32_t)lstatus.not_alive_count_change;
|
stopped += (uint32_t)lstatus.not_alive_count_change;
|
||||||
dds_sleepfor(DDS_MSECS(50));
|
dds_sleepfor(DDS_MSECS(50));
|
||||||
} while (dds_time() < tstop);
|
} while (dds_time() < tstop);
|
||||||
dds_get_liveliness_changed_status(reader, &lstatus);
|
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
|
||||||
printf("writers alive with dds_assert_liveliness on all writers: %d, writers stopped: %d\n", lstatus.alive_count, stopped);
|
printf("writers alive with dds_assert_liveliness on all writers: %d, writers stopped: %d\n", lstatus.alive_count, stopped);
|
||||||
if (lstatus.alive_count != wr_cnt_auto + wr_cnt_man_pp + wr_cnt_man_tp || stopped != 0)
|
if (lstatus.alive_count != wr_cnt_auto + wr_cnt_man_pp + wr_cnt_man_tp || stopped != 0)
|
||||||
{
|
{
|
||||||
|
@ -795,7 +856,8 @@ CU_Theory((uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp)
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
|
||||||
for (size_t n = 0; n < wr_cnt; n++)
|
for (size_t n = 0; n < wr_cnt; n++)
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(writers[n]), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(writers[n]), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
if (remote_reader)
|
||||||
|
CU_ASSERT_EQUAL_FATAL(dds_delete(sub_topic), DDS_RETCODE_OK);
|
||||||
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
CU_ASSERT_EQUAL_FATAL(dds_delete(pub_topic), DDS_RETCODE_OK);
|
||||||
|
|
||||||
if (!test_finished)
|
if (!test_finished)
|
||||||
|
@ -813,6 +875,12 @@ CU_Theory((uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp)
|
||||||
}
|
}
|
||||||
} while (!test_finished);
|
} while (!test_finished);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CU_Theory((uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp), ddsc_liveliness, assert_liveliness, .init = liveliness_init, .fini = liveliness_fini, .timeout = 60)
|
||||||
|
{
|
||||||
|
test_assert_liveliness(wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, false);
|
||||||
|
test_assert_liveliness(wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, true);
|
||||||
|
}
|
||||||
#undef MAX_WRITERS
|
#undef MAX_WRITERS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -883,31 +951,47 @@ static void liveliness_changed_listener (dds_entity_t rd, const dds_liveliness_c
|
||||||
st->weirdness = true;
|
st->weirdness = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("liveliness_changed_listener: alive_count_change = 0 && not_alive_count_change = 0\n");
|
||||||
|
st->weirdness = true;
|
||||||
|
}
|
||||||
ddsrt_mutex_unlock (&st->lock);
|
ddsrt_mutex_unlock (&st->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_and_check_status (dds_entity_t reader, dds_entity_t writer_active)
|
#define STATUS_UNSYNCED 0
|
||||||
|
#define STATUS_SYNCED 1
|
||||||
|
#define STATUS_DATA 2
|
||||||
|
static unsigned get_and_check_status (dds_entity_t reader, dds_entity_t writer_active)
|
||||||
{
|
{
|
||||||
struct dds_liveliness_changed_status lstatus;
|
struct dds_liveliness_changed_status lstatus;
|
||||||
struct dds_subscription_matched_status sstatus;
|
struct dds_subscription_matched_status sstatus;
|
||||||
struct dds_publication_matched_status pstatus;
|
struct dds_publication_matched_status pstatus;
|
||||||
|
uint32_t dstatus;
|
||||||
|
uint32_t result = STATUS_UNSYNCED;
|
||||||
dds_return_t rc;
|
dds_return_t rc;
|
||||||
rc = dds_get_subscription_matched_status(reader, &sstatus);
|
rc = dds_get_subscription_matched_status(reader, &sstatus);
|
||||||
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
rc = dds_get_liveliness_changed_status(reader, &lstatus);
|
rc = dds_get_liveliness_changed_status(reader, &lstatus);
|
||||||
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
rc = dds_take_status(reader, &dstatus, DDS_DATA_AVAILABLE_STATUS);
|
||||||
|
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||||
rc = dds_get_publication_matched_status(writer_active, &pstatus);
|
rc = dds_get_publication_matched_status(writer_active, &pstatus);
|
||||||
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
CU_ASSERT_FATAL(lstatus.alive_count + lstatus.not_alive_count <= 2);
|
CU_ASSERT_FATAL(lstatus.alive_count + lstatus.not_alive_count <= 2);
|
||||||
printf ("%d %d %d %d\n", (int)sstatus.current_count, (int)lstatus.alive_count, (int)lstatus.not_alive_count, (int)pstatus.current_count);
|
printf ("sub %d | alive %d | not-alive %d | pub %d | data %d\n", (int)sstatus.current_count, (int)lstatus.alive_count, (int)lstatus.not_alive_count, (int)pstatus.current_count, dstatus != 0);
|
||||||
return (sstatus.current_count == 2 && lstatus.not_alive_count == 2 && pstatus.current_count == 1);
|
if (dstatus)
|
||||||
|
result |= STATUS_DATA;
|
||||||
|
if (sstatus.current_count == 2 && lstatus.not_alive_count == 2 && pstatus.current_count == 1)
|
||||||
|
result |= STATUS_SYNCED;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_liveliness_kind_t lkind, dds_duration_t ldur)
|
static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_liveliness_kind_t lkind, dds_duration_t ldur, bool remote_reader)
|
||||||
{
|
{
|
||||||
const uint32_t nsamples = (sleep <= DDS_MSECS(10)) ? 100 : 10;
|
const uint32_t nsamples = (sleep <= DDS_MSECS(10)) ? 50 : 5;
|
||||||
dds_entity_t pub_topic;
|
dds_entity_t pub_topic;
|
||||||
dds_entity_t sub_topic;
|
dds_entity_t sub_topic = 0;
|
||||||
dds_entity_t reader;
|
dds_entity_t reader;
|
||||||
dds_entity_t writer_active; /* writing */
|
dds_entity_t writer_active; /* writing */
|
||||||
dds_entity_t writer_inactive; /* not writing, liveliness should still toggle */
|
dds_entity_t writer_inactive; /* not writing, liveliness should still toggle */
|
||||||
|
@ -937,14 +1021,17 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines
|
||||||
create_topic_name("ddsc_liveliness_lease_duration_zero", g_topic_nr++, name, sizeof name);
|
create_topic_name("ddsc_liveliness_lease_duration_zero", g_topic_nr++, name, sizeof name);
|
||||||
pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, qos, NULL);
|
pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, qos, NULL);
|
||||||
CU_ASSERT_FATAL(pub_topic > 0);
|
CU_ASSERT_FATAL(pub_topic > 0);
|
||||||
sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, qos, NULL);
|
if (remote_reader)
|
||||||
CU_ASSERT_FATAL(sub_topic > 0);
|
{
|
||||||
|
sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, qos, NULL);
|
||||||
|
CU_ASSERT_FATAL(sub_topic > 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* reader liveliness is always automatic/infinity */
|
/* reader liveliness is always automatic/infinity */
|
||||||
dds_qset_liveliness(qos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
dds_qset_liveliness(qos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||||
reader = dds_create_reader(g_sub_participant, sub_topic, qos, NULL);
|
reader = dds_create_reader(remote_reader ? g_sub_participant : g_pub_participant, remote_reader ? sub_topic : pub_topic, qos, NULL);
|
||||||
CU_ASSERT_FATAL(reader > 0);
|
CU_ASSERT_FATAL(reader > 0);
|
||||||
rc = dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS | DDS_SUBSCRIPTION_MATCHED_STATUS);
|
rc = dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS | DDS_SUBSCRIPTION_MATCHED_STATUS | DDS_DATA_AVAILABLE_STATUS);
|
||||||
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
rc = dds_waitset_attach(waitset, reader, reader);
|
rc = dds_waitset_attach(waitset, reader, reader);
|
||||||
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
@ -964,15 +1051,29 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines
|
||||||
|
|
||||||
/* wait for writers to be discovered and to have lost their liveliness, and for
|
/* wait for writers to be discovered and to have lost their liveliness, and for
|
||||||
writer_active to have discovered the reader */
|
writer_active to have discovered the reader */
|
||||||
while (!get_and_check_status (reader, writer_active))
|
unsigned status = STATUS_UNSYNCED;
|
||||||
|
bool initial_sample_written = false, initial_sample_received = false;
|
||||||
|
do
|
||||||
{
|
{
|
||||||
|
status = get_and_check_status (reader, writer_active);
|
||||||
|
if (status & STATUS_DATA)
|
||||||
|
initial_sample_received = true;
|
||||||
|
if (status & STATUS_SYNCED && !initial_sample_written)
|
||||||
|
{
|
||||||
|
rc = dds_write(writer_active, &sample);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
initial_sample_written = true;
|
||||||
|
}
|
||||||
|
if (status & STATUS_SYNCED && initial_sample_received)
|
||||||
|
break;
|
||||||
|
|
||||||
rc = dds_waitset_wait(waitset, NULL, 0, DDS_SECS(5));
|
rc = dds_waitset_wait(waitset, NULL, 0, DDS_SECS(5));
|
||||||
if (rc < 1)
|
if (rc < 1)
|
||||||
{
|
{
|
||||||
get_and_check_status (reader, writer_active);
|
get_and_check_status (reader, writer_active);
|
||||||
CU_ASSERT_FATAL(rc >= 1);
|
CU_ASSERT_FATAL(rc >= 1);
|
||||||
}
|
}
|
||||||
}
|
} while (1);
|
||||||
|
|
||||||
/* switch to using a listener: those allow us to observe all events */
|
/* switch to using a listener: those allow us to observe all events */
|
||||||
listener = dds_create_listener (&listener_state);
|
listener = dds_create_listener (&listener_state);
|
||||||
|
@ -1002,7 +1103,7 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines
|
||||||
uint32_t cnt = 0;
|
uint32_t cnt = 0;
|
||||||
while (dds_take(reader, raw, &si, 1, 1) == 1)
|
while (dds_take(reader, raw, &si, 1, 1) == 1)
|
||||||
cnt++;
|
cnt++;
|
||||||
CU_ASSERT(cnt == nsamples);
|
CU_ASSERT(cnt == nsamples + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* transition to not alive is not necessarily immediate */
|
/* transition to not alive is not necessarily immediate */
|
||||||
|
@ -1028,21 +1129,15 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines
|
||||||
printf("late liveliness changed status: alive %"PRId32" not-alive %"PRId32"\n", lstatus.alive_count, lstatus.not_alive_count);
|
printf("late liveliness changed status: alive %"PRId32" not-alive %"PRId32"\n", lstatus.alive_count, lstatus.not_alive_count);
|
||||||
printf("final w0 %"PRIx64" alive %"PRId32" not-alive %"PRId32"\n", listener_state.w0_handle, listener_state.w0_alive, listener_state.w0_not_alive);
|
printf("final w0 %"PRIx64" alive %"PRId32" not-alive %"PRId32"\n", listener_state.w0_handle, listener_state.w0_alive, listener_state.w0_not_alive);
|
||||||
CU_ASSERT(listener_state.w0_alive == listener_state.w0_not_alive);
|
CU_ASSERT(listener_state.w0_alive == listener_state.w0_not_alive);
|
||||||
|
uint32_t exp_alive;
|
||||||
if (sleep == 0)
|
if (sleep == 0)
|
||||||
{
|
exp_alive = 1; /* if not sleeping, it's ok if the transition happens only once */
|
||||||
/* if not sleeping, it's ok if the transition happens only once */
|
|
||||||
CU_ASSERT(listener_state.w0_alive > 0);
|
|
||||||
}
|
|
||||||
else if (sleep <= DDS_MSECS(10))
|
else if (sleep <= DDS_MSECS(10))
|
||||||
{
|
exp_alive = nsamples / 3; /* if sleeping briefly, expect the a good number of writes to toggle liveliness */
|
||||||
/* if sleeping briefly, expect the a good number of writes to toggle liveliness */
|
|
||||||
CU_ASSERT(listener_state.w0_alive >= nsamples / 3);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
exp_alive = nsamples - nsamples / 5; /* if sleeping, expect the vast majority (80%) of the writes to toggle liveliness */
|
||||||
/* if sleeping, expect the vast majority (90%) of the writes to toggle liveliness */
|
printf("check w0_alive %d >= %d\n", listener_state.w0_alive, exp_alive);
|
||||||
CU_ASSERT(listener_state.w0_alive >= nsamples - nsamples / 10);
|
CU_ASSERT(listener_state.w0_alive >= exp_alive);
|
||||||
}
|
|
||||||
ddsrt_mutex_unlock(&listener_state.lock);
|
ddsrt_mutex_unlock(&listener_state.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1055,8 +1150,11 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines
|
||||||
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
rc = dds_delete(writer_inactive);
|
rc = dds_delete(writer_inactive);
|
||||||
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
rc = dds_delete(sub_topic);
|
if (remote_reader)
|
||||||
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
{
|
||||||
|
rc = dds_delete(sub_topic);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
}
|
||||||
rc = dds_delete(pub_topic);
|
rc = dds_delete(pub_topic);
|
||||||
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
|
||||||
|
@ -1065,20 +1163,26 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines
|
||||||
|
|
||||||
CU_Test(ddsc_liveliness, lease_duration_zero_or_one, .init = liveliness_init, .fini = liveliness_fini, .timeout = 30)
|
CU_Test(ddsc_liveliness, lease_duration_zero_or_one, .init = liveliness_init, .fini = liveliness_fini, .timeout = 30)
|
||||||
{
|
{
|
||||||
|
static const bool remote_rd[] = { false, true };
|
||||||
static const dds_duration_t sleep[] = { 0, DDS_MSECS(10), DDS_MSECS(100) };
|
static const dds_duration_t sleep[] = { 0, DDS_MSECS(10), DDS_MSECS(100) };
|
||||||
static const dds_liveliness_kind_t lkind[] = { DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_LIVELINESS_MANUAL_BY_TOPIC };
|
static const dds_liveliness_kind_t lkind[] = { DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_LIVELINESS_MANUAL_BY_TOPIC };
|
||||||
static const dds_duration_t ldur[] = { 0, 1 };
|
static const dds_duration_t ldur[] = { 0, 1 };
|
||||||
for (size_t sleep_idx = 0; sleep_idx < sizeof (sleep) / sizeof (sleep[0]); sleep_idx++)
|
for (size_t remote_rd_idx = 0; remote_rd_idx < sizeof (remote_rd) / sizeof (remote_rd[0]); remote_rd_idx++)
|
||||||
{
|
{
|
||||||
for (size_t lkind_idx = 0; lkind_idx < sizeof (lkind) / sizeof (lkind[0]); lkind_idx++)
|
for (size_t sleep_idx = 0; sleep_idx < sizeof (sleep) / sizeof (sleep[0]); sleep_idx++)
|
||||||
{
|
{
|
||||||
for (size_t ldur_idx = 0; ldur_idx < sizeof (ldur) / sizeof (ldur[0]); ldur_idx++)
|
for (size_t lkind_idx = 0; lkind_idx < sizeof (lkind) / sizeof (lkind[0]); lkind_idx++)
|
||||||
{
|
{
|
||||||
dds_duration_t s = sleep[sleep_idx];
|
for (size_t ldur_idx = 0; ldur_idx < sizeof (ldur) / sizeof (ldur[0]); ldur_idx++)
|
||||||
dds_liveliness_kind_t k = lkind[lkind_idx];
|
{
|
||||||
dds_duration_t d = ldur[ldur_idx];
|
bool rrd = remote_rd[remote_rd_idx];
|
||||||
printf ("lease_duration_zero_or_one: sleep = %"PRId64" lkind = %d ldur = %"PRId64"\n", s, (int) k, d);
|
dds_duration_t s = sleep[sleep_idx];
|
||||||
lease_duration_zero_or_one_impl (s, k, d);
|
dds_liveliness_kind_t k = lkind[lkind_idx];
|
||||||
|
dds_duration_t d = ldur[ldur_idx];
|
||||||
|
printf ("### lease_duration_zero_or_one: sleep = %"PRId64" lkind = %d ldur = %"PRId64" reader = %s\n", s, (int) k, d, rrd ? "remote" : "local");
|
||||||
|
lease_duration_zero_or_one_impl (s, k, d, rrd);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,8 +64,7 @@ enum liveliness_changed_data_extra {
|
||||||
LIVELINESS_CHANGED_REMOVE_NOT_ALIVE,
|
LIVELINESS_CHANGED_REMOVE_NOT_ALIVE,
|
||||||
LIVELINESS_CHANGED_REMOVE_ALIVE,
|
LIVELINESS_CHANGED_REMOVE_ALIVE,
|
||||||
LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE,
|
LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE,
|
||||||
LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE,
|
LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE
|
||||||
LIVELINESS_CHANGED_TWITCH
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct status_cb_data
|
typedef struct status_cb_data
|
||||||
|
@ -102,6 +101,8 @@ struct wr_rd_match {
|
||||||
struct rd_wr_match {
|
struct rd_wr_match {
|
||||||
ddsrt_avl_node_t avlnode;
|
ddsrt_avl_node_t avlnode;
|
||||||
ddsi_guid_t wr_guid;
|
ddsi_guid_t wr_guid;
|
||||||
|
unsigned wr_alive: 1; /* tracks wr's alive state */
|
||||||
|
uint32_t wr_alive_vclock; /* used to ensure progress */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wr_prd_match {
|
struct wr_prd_match {
|
||||||
|
@ -208,6 +209,8 @@ struct participant
|
||||||
int32_t builtin_refc; /* number of built-in endpoints in this participant [refc_lock] */
|
int32_t builtin_refc; /* number of built-in endpoints in this participant [refc_lock] */
|
||||||
int builtins_deleted; /* whether deletion of built-in endpoints has been initiated [refc_lock] */
|
int builtins_deleted; /* whether deletion of built-in endpoints has been initiated [refc_lock] */
|
||||||
ddsrt_fibheap_t ldur_auto_wr; /* Heap that contains lease duration for writers with automatic liveliness in this participant */
|
ddsrt_fibheap_t ldur_auto_wr; /* Heap that contains lease duration for writers with automatic liveliness in this participant */
|
||||||
|
ddsrt_atomic_voidp_t minl_man; /* lease object for shortest manual-by-participant liveliness writer's lease */
|
||||||
|
ddsrt_fibheap_t leaseheap_man; /* keeps leases for this participant's writers (with liveliness manual-by-participant) */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct endpoint_common {
|
struct endpoint_common {
|
||||||
|
@ -255,10 +258,12 @@ struct writer
|
||||||
unsigned handle_as_transient_local: 1; /* controls whether data is retained in WHC */
|
unsigned handle_as_transient_local: 1; /* controls whether data is retained in WHC */
|
||||||
unsigned include_keyhash: 1; /* iff 1, this writer includes a keyhash; keyless topics => include_keyhash = 0 */
|
unsigned include_keyhash: 1; /* iff 1, this writer includes a keyhash; keyless topics => include_keyhash = 0 */
|
||||||
unsigned retransmitting: 1; /* iff 1, this writer is currently retransmitting */
|
unsigned retransmitting: 1; /* iff 1, this writer is currently retransmitting */
|
||||||
|
unsigned alive: 1; /* iff 1, the writer is alive (lease for this writer is not expired); field may be modified only when holding both wr->e.lock and wr->c.pp->e.lock */
|
||||||
#ifdef DDSI_INCLUDE_SSM
|
#ifdef DDSI_INCLUDE_SSM
|
||||||
unsigned supports_ssm: 1;
|
unsigned supports_ssm: 1;
|
||||||
struct addrset *ssm_as;
|
struct addrset *ssm_as;
|
||||||
#endif
|
#endif
|
||||||
|
uint32_t alive_vclock; /* virtual clock counting transitions between alive/not-alive */
|
||||||
const struct ddsi_sertopic * topic; /* topic, but may be NULL for built-ins */
|
const struct ddsi_sertopic * topic; /* topic, but may be NULL for built-ins */
|
||||||
struct addrset *as; /* set of addresses to publish to */
|
struct addrset *as; /* set of addresses to publish to */
|
||||||
struct addrset *as_group; /* alternate case, used for SPDP, when using Cloud with multiple bootstrap locators */
|
struct addrset *as_group; /* alternate case, used for SPDP, when using Cloud with multiple bootstrap locators */
|
||||||
|
@ -282,6 +287,7 @@ struct writer
|
||||||
uint32_t rexmit_lost_count; /* cum samples lost but retransmit requested (also counting events) */
|
uint32_t rexmit_lost_count; /* cum samples lost but retransmit requested (also counting events) */
|
||||||
struct xeventq *evq; /* timed event queue to be used by this writer */
|
struct xeventq *evq; /* timed event queue to be used by this writer */
|
||||||
struct local_reader_ary rdary; /* LOCAL readers for fast-pathing; if not fast-pathed, fall back to scanning local_readers */
|
struct local_reader_ary rdary; /* LOCAL readers for fast-pathing; if not fast-pathed, fall back to scanning local_readers */
|
||||||
|
struct lease *lease; /* for liveliness administration (writer can only become inactive when using manual liveliness) */
|
||||||
};
|
};
|
||||||
|
|
||||||
inline seqno_t writer_read_seq_xmit (const struct writer *wr) {
|
inline seqno_t writer_read_seq_xmit (const struct writer *wr) {
|
||||||
|
@ -620,6 +626,9 @@ struct local_orphan_writer {
|
||||||
struct local_orphan_writer *new_local_orphan_writer (struct q_globals *gv, ddsi_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc);
|
struct local_orphan_writer *new_local_orphan_writer (struct q_globals *gv, ddsi_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc);
|
||||||
void delete_local_orphan_writer (struct local_orphan_writer *wr);
|
void delete_local_orphan_writer (struct local_orphan_writer *wr);
|
||||||
|
|
||||||
|
void writer_set_alive_may_unlock (struct writer *wr, bool notify);
|
||||||
|
int writer_set_notalive (struct writer *wr, bool notify);
|
||||||
|
|
||||||
/* To create or delete a new proxy participant: "guid" MUST have the
|
/* To create or delete a new proxy participant: "guid" MUST have the
|
||||||
pre-defined participant entity id. Unlike delete_participant(),
|
pre-defined participant entity id. Unlike delete_participant(),
|
||||||
deleting a proxy participant will automatically delete all its
|
deleting a proxy participant will automatically delete all its
|
||||||
|
|
|
@ -49,12 +49,17 @@ static void debug_print_rawdata (const struct q_globals *gv, const char *msg, co
|
||||||
void write_pmd_message_guid (struct q_globals * const gv, struct ddsi_guid *pp_guid, unsigned pmd_kind)
|
void write_pmd_message_guid (struct q_globals * const gv, struct ddsi_guid *pp_guid, unsigned pmd_kind)
|
||||||
{
|
{
|
||||||
struct thread_state1 * const ts1 = lookup_thread_state ();
|
struct thread_state1 * const ts1 = lookup_thread_state ();
|
||||||
|
struct lease *lease;
|
||||||
thread_state_awake (ts1, gv);
|
thread_state_awake (ts1, gv);
|
||||||
struct participant *pp = entidx_lookup_participant_guid (gv->entity_index, pp_guid);
|
struct participant *pp = entidx_lookup_participant_guid (gv->entity_index, pp_guid);
|
||||||
if (pp == NULL)
|
if (pp == NULL)
|
||||||
GVTRACE ("write_pmd_message("PGUIDFMT") - builtin pmd writer not found\n", PGUID (*pp_guid));
|
GVTRACE ("write_pmd_message("PGUIDFMT") - builtin pmd writer not found\n", PGUID (*pp_guid));
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if ((lease = ddsrt_atomic_ldvoidp (&pp->minl_man)) != NULL)
|
||||||
|
lease_renew (lease, now_et());
|
||||||
write_pmd_message (ts1, NULL, pp, pmd_kind);
|
write_pmd_message (ts1, NULL, pp, pmd_kind);
|
||||||
|
}
|
||||||
thread_state_asleep (ts1);
|
thread_state_asleep (ts1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ struct deleted_participants_admin {
|
||||||
int64_t delay;
|
int64_t delay;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct proxy_writer_alive_state {
|
struct alive_state {
|
||||||
bool alive;
|
bool alive;
|
||||||
uint32_t vclock;
|
uint32_t vclock;
|
||||||
};
|
};
|
||||||
|
@ -197,6 +197,18 @@ bool is_local_orphan_endpoint (const struct entity_common *e)
|
||||||
is_builtin_endpoint (e->guid.entityid, NN_VENDORID_ECLIPSE));
|
is_builtin_endpoint (e->guid.entityid, NN_VENDORID_ECLIPSE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int compare_ldur (const void *va, const void *vb)
|
||||||
|
{
|
||||||
|
const struct ldur_fhnode *a = va;
|
||||||
|
const struct ldur_fhnode *b = vb;
|
||||||
|
return (a->ldur == b->ldur) ? 0 : (a->ldur < b->ldur) ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* used in participant for keeping writer liveliness renewal */
|
||||||
|
const ddsrt_fibheap_def_t ldur_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct ldur_fhnode, heapnode), compare_ldur);
|
||||||
|
/* used in (proxy)participant for writer liveliness monitoring */
|
||||||
|
const ddsrt_fibheap_def_t lease_fhdef_pp = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct lease, pp_heapnode), compare_lease_tdur);
|
||||||
|
|
||||||
static void entity_common_init (struct entity_common *e, struct q_globals *gv, const struct ddsi_guid *guid, const char *name, enum entity_kind kind, nn_wctime_t tcreate, nn_vendorid_t vendorid, bool onlylocal)
|
static void entity_common_init (struct entity_common *e, struct q_globals *gv, const struct ddsi_guid *guid, const char *name, enum entity_kind kind, nn_wctime_t tcreate, nn_vendorid_t vendorid, bool onlylocal)
|
||||||
{
|
{
|
||||||
e->guid = *guid;
|
e->guid = *guid;
|
||||||
|
@ -413,17 +425,6 @@ static void remove_deleted_participant_guid (struct deleted_participants_admin *
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PARTICIPANT ------------------------------------------------------ */
|
/* PARTICIPANT ------------------------------------------------------ */
|
||||||
|
|
||||||
static int compare_ldur (const void *va, const void *vb)
|
|
||||||
{
|
|
||||||
const struct ldur_fhnode *a = va;
|
|
||||||
const struct ldur_fhnode *b = vb;
|
|
||||||
return (a->ldur == b->ldur) ? 0 : (a->ldur < b->ldur) ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* used in participant for keeping writer liveliness renewal */
|
|
||||||
const ddsrt_fibheap_def_t ldur_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct ldur_fhnode, heapnode), compare_ldur);
|
|
||||||
|
|
||||||
static bool update_qos_locked (struct entity_common *e, dds_qos_t *ent_qos, const dds_qos_t *xqos, nn_wctime_t timestamp)
|
static bool update_qos_locked (struct entity_common *e, dds_qos_t *ent_qos, const dds_qos_t *xqos, nn_wctime_t timestamp)
|
||||||
{
|
{
|
||||||
uint64_t mask;
|
uint64_t mask;
|
||||||
|
@ -482,6 +483,81 @@ static void pp_release_entityid(struct participant *pp, ddsi_entityid_t id)
|
||||||
ddsrt_mutex_unlock (&pp->e.lock);
|
ddsrt_mutex_unlock (&pp->e.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gc_participant_lease (struct gcreq *gcreq)
|
||||||
|
{
|
||||||
|
lease_free (gcreq->arg);
|
||||||
|
gcreq_free (gcreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void participant_replace_minl (struct participant *pp, struct lease *lnew)
|
||||||
|
{
|
||||||
|
/* By loading/storing the pointer atomically, we ensure we always
|
||||||
|
read a valid (or once valid) lease. By delaying freeing the lease
|
||||||
|
through the garbage collector, we ensure whatever lease update
|
||||||
|
occurs in parallel completes before the memory is released. */
|
||||||
|
struct gcreq *gcreq = gcreq_new (pp->e.gv->gcreq_queue, gc_participant_lease);
|
||||||
|
struct lease *lease_old = ddsrt_atomic_ldvoidp (&pp->minl_man);
|
||||||
|
assert (lease_old != NULL);
|
||||||
|
lease_unregister (lease_old); /* ensures lease will not expire while it is replaced */
|
||||||
|
gcreq->arg = lease_old;
|
||||||
|
gcreq_enqueue (gcreq);
|
||||||
|
ddsrt_atomic_stvoidp (&pp->minl_man, lnew);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void participant_add_wr_lease_locked (struct participant * pp, const struct writer * wr)
|
||||||
|
{
|
||||||
|
struct lease *minl_prev;
|
||||||
|
struct lease *minl_new;
|
||||||
|
|
||||||
|
assert (wr->lease != NULL);
|
||||||
|
minl_prev = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man);
|
||||||
|
ddsrt_fibheap_insert (&lease_fhdef_pp, &pp->leaseheap_man, wr->lease);
|
||||||
|
minl_new = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man);
|
||||||
|
/* if inserted lease is new shortest lease */
|
||||||
|
if (minl_prev != minl_new)
|
||||||
|
{
|
||||||
|
nn_etime_t texp = add_duration_to_etime (now_et (), minl_new->tdur);
|
||||||
|
struct lease *lnew = lease_new (texp, minl_new->tdur, minl_new->entity);
|
||||||
|
if (minl_prev == NULL)
|
||||||
|
{
|
||||||
|
assert (ddsrt_atomic_ldvoidp (&pp->minl_man) == NULL);
|
||||||
|
ddsrt_atomic_stvoidp (&pp->minl_man, lnew);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
participant_replace_minl (pp, lnew);
|
||||||
|
}
|
||||||
|
lease_register (lnew);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void participant_remove_wr_lease_locked (struct participant * pp, struct writer * wr)
|
||||||
|
{
|
||||||
|
struct lease *minl;
|
||||||
|
|
||||||
|
assert (wr->lease != NULL);
|
||||||
|
assert (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT);
|
||||||
|
minl = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man);
|
||||||
|
ddsrt_fibheap_delete (&lease_fhdef_pp, &pp->leaseheap_man, wr->lease);
|
||||||
|
/* if writer with min lease is removed: update participant lease to use new minimal duration */
|
||||||
|
if (wr->lease == minl)
|
||||||
|
{
|
||||||
|
if ((minl = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man)) != NULL)
|
||||||
|
{
|
||||||
|
dds_duration_t trem = minl->tdur - wr->lease->tdur;
|
||||||
|
assert (trem >= 0);
|
||||||
|
nn_etime_t texp = add_duration_to_etime (now_et(), trem);
|
||||||
|
struct lease *lnew = lease_new (texp, minl->tdur, minl->entity);
|
||||||
|
participant_replace_minl (pp, lnew);
|
||||||
|
lease_register (lnew);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
participant_replace_minl (pp, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist)
|
dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist)
|
||||||
{
|
{
|
||||||
struct participant *pp;
|
struct participant *pp;
|
||||||
|
@ -559,6 +635,9 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals *
|
||||||
pp->m_conn = NULL;
|
pp->m_conn = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ddsrt_fibheap_init (&lease_fhdef_pp, &pp->leaseheap_man);
|
||||||
|
ddsrt_atomic_stvoidp (&pp->minl_man, NULL);
|
||||||
|
|
||||||
/* Before we create endpoints -- and may call unref_participant if
|
/* Before we create endpoints -- and may call unref_participant if
|
||||||
things go wrong -- we must initialize all that unref_participant
|
things go wrong -- we must initialize all that unref_participant
|
||||||
depends on. */
|
depends on. */
|
||||||
|
@ -1394,13 +1473,26 @@ static void free_wr_rd_match (struct wr_rd_match *m)
|
||||||
if (m) ddsrt_free (m);
|
if (m) ddsrt_free (m);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void proxy_writer_get_alive_state_locked (struct proxy_writer *pwr, struct proxy_writer_alive_state *st)
|
static void writer_get_alive_state_locked (struct writer *wr, struct alive_state *st)
|
||||||
|
{
|
||||||
|
st->alive = wr->alive;
|
||||||
|
st->vclock = wr->alive_vclock;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writer_get_alive_state (struct writer *wr, struct alive_state *st)
|
||||||
|
{
|
||||||
|
ddsrt_mutex_lock (&wr->e.lock);
|
||||||
|
writer_get_alive_state_locked (wr, st);
|
||||||
|
ddsrt_mutex_unlock (&wr->e.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void proxy_writer_get_alive_state_locked (struct proxy_writer *pwr, struct alive_state *st)
|
||||||
{
|
{
|
||||||
st->alive = pwr->alive;
|
st->alive = pwr->alive;
|
||||||
st->vclock = pwr->alive_vclock;
|
st->vclock = pwr->alive_vclock;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void proxy_writer_get_alive_state (struct proxy_writer *pwr, struct proxy_writer_alive_state *st)
|
static void proxy_writer_get_alive_state (struct proxy_writer *pwr, struct alive_state *st)
|
||||||
{
|
{
|
||||||
ddsrt_mutex_lock (&pwr->e.lock);
|
ddsrt_mutex_lock (&pwr->e.lock);
|
||||||
proxy_writer_get_alive_state_locked (pwr, st);
|
proxy_writer_get_alive_state_locked (pwr, st);
|
||||||
|
@ -1464,7 +1556,73 @@ static void writer_drop_local_connection (const struct ddsi_guid *wr_guid, struc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reader_update_notify_pwr_alive_state (struct reader *rd, const struct proxy_writer *pwr, const struct proxy_writer_alive_state *alive_state)
|
static void reader_update_notify_alive_state_invoke_cb (struct reader *rd, uint64_t iid, bool notify, int delta, const struct alive_state *alive_state)
|
||||||
|
{
|
||||||
|
/* Liveliness changed events can race each other and can, potentially, be delivered
|
||||||
|
in a different order. */
|
||||||
|
if (notify && rd->status_cb)
|
||||||
|
{
|
||||||
|
status_cb_data_t data;
|
||||||
|
data.handle = iid;
|
||||||
|
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
||||||
|
if (delta < 0) {
|
||||||
|
data.extra = (uint32_t) LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE;
|
||||||
|
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||||
|
} else if (delta > 0) {
|
||||||
|
data.extra = (uint32_t) LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE;
|
||||||
|
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||||
|
} else {
|
||||||
|
/* Twitch: the resulting (proxy)writer state is unchanged, but there has been
|
||||||
|
a transition to another state and back to the current state. So we'll call
|
||||||
|
the callback twice in this case. */
|
||||||
|
static const enum liveliness_changed_data_extra x[] = {
|
||||||
|
LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE,
|
||||||
|
LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE
|
||||||
|
};
|
||||||
|
data.extra = (uint32_t) x[alive_state->alive];
|
||||||
|
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||||
|
data.extra = (uint32_t) x[!alive_state->alive];
|
||||||
|
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reader_update_notify_wr_alive_state (struct reader *rd, const struct writer *wr, const struct alive_state *alive_state)
|
||||||
|
{
|
||||||
|
struct rd_wr_match *m;
|
||||||
|
bool notify = false;
|
||||||
|
int delta = 0; /* -1: alive -> not_alive; 0: unchanged; 1: not_alive -> alive */
|
||||||
|
ddsrt_mutex_lock (&rd->e.lock);
|
||||||
|
if ((m = ddsrt_avl_lookup (&rd_local_writers_treedef, &rd->local_writers, &wr->e.guid)) != NULL)
|
||||||
|
{
|
||||||
|
if ((int32_t) (alive_state->vclock - m->wr_alive_vclock) > 0)
|
||||||
|
{
|
||||||
|
delta = (int) alive_state->alive - (int) m->wr_alive;
|
||||||
|
notify = true;
|
||||||
|
m->wr_alive = alive_state->alive;
|
||||||
|
m->wr_alive_vclock = alive_state->vclock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ddsrt_mutex_unlock (&rd->e.lock);
|
||||||
|
|
||||||
|
if (delta < 0 && rd->rhc)
|
||||||
|
{
|
||||||
|
struct ddsi_writer_info wrinfo;
|
||||||
|
ddsi_make_writer_info (&wrinfo, &wr->e, wr->xqos, NN_STATUSINFO_UNREGISTER);
|
||||||
|
ddsi_rhc_unregister_wr (rd->rhc, &wrinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader_update_notify_alive_state_invoke_cb (rd, wr->e.iid, notify, delta, alive_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reader_update_notify_wr_alive_state_guid (const struct ddsi_guid *rd_guid, const struct writer *wr, const struct alive_state *alive_state)
|
||||||
|
{
|
||||||
|
struct reader *rd;
|
||||||
|
if ((rd = entidx_lookup_reader_guid (wr->e.gv->entity_index, rd_guid)) != NULL)
|
||||||
|
reader_update_notify_wr_alive_state (rd, wr, alive_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reader_update_notify_pwr_alive_state (struct reader *rd, const struct proxy_writer *pwr, const struct alive_state *alive_state)
|
||||||
{
|
{
|
||||||
struct rd_pwr_match *m;
|
struct rd_pwr_match *m;
|
||||||
bool notify = false;
|
bool notify = false;
|
||||||
|
@ -1489,24 +1647,10 @@ static void reader_update_notify_pwr_alive_state (struct reader *rd, const struc
|
||||||
ddsi_rhc_unregister_wr (rd->rhc, &wrinfo);
|
ddsi_rhc_unregister_wr (rd->rhc, &wrinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Liveliness changed events can race each other and can, potentially, be delivered
|
reader_update_notify_alive_state_invoke_cb (rd, pwr->e.iid, notify, delta, alive_state);
|
||||||
in a different order. */
|
|
||||||
if (notify && rd->status_cb)
|
|
||||||
{
|
|
||||||
status_cb_data_t data;
|
|
||||||
data.handle = pwr->e.iid;
|
|
||||||
if (delta == 0)
|
|
||||||
data.extra = (uint32_t) LIVELINESS_CHANGED_TWITCH;
|
|
||||||
else if (delta < 0)
|
|
||||||
data.extra = (uint32_t) LIVELINESS_CHANGED_ALIVE_TO_NOT_ALIVE;
|
|
||||||
else
|
|
||||||
data.extra = (uint32_t) LIVELINESS_CHANGED_NOT_ALIVE_TO_ALIVE;
|
|
||||||
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
|
||||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reader_update_notify_pwr_alive_state_guid (const struct ddsi_guid *rd_guid, const struct proxy_writer *pwr, const struct proxy_writer_alive_state *alive_state)
|
static void reader_update_notify_pwr_alive_state_guid (const struct ddsi_guid *rd_guid, const struct proxy_writer *pwr, const struct alive_state *alive_state)
|
||||||
{
|
{
|
||||||
struct reader *rd;
|
struct reader *rd;
|
||||||
if ((rd = entidx_lookup_reader_guid (pwr->e.gv->entity_index, rd_guid)) != NULL)
|
if ((rd = entidx_lookup_reader_guid (pwr->e.gv->entity_index, rd_guid)) != NULL)
|
||||||
|
@ -1573,7 +1717,7 @@ static void reader_drop_local_connection (const struct ddsi_guid *rd_guid, const
|
||||||
status_cb_data_t data;
|
status_cb_data_t data;
|
||||||
data.handle = wr->e.iid;
|
data.handle = wr->e.iid;
|
||||||
data.add = false;
|
data.add = false;
|
||||||
data.extra = (uint32_t) LIVELINESS_CHANGED_REMOVE_ALIVE;
|
data.extra = (uint32_t) (m->wr_alive ? LIVELINESS_CHANGED_REMOVE_ALIVE : LIVELINESS_CHANGED_REMOVE_NOT_ALIVE);
|
||||||
|
|
||||||
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
data.raw_status_id = (int) DDS_LIVELINESS_CHANGED_STATUS_ID;
|
||||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||||
|
@ -1812,7 +1956,7 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, nn_count_t *init_count, const struct proxy_writer_alive_state *alive_state)
|
static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, nn_count_t *init_count, const struct alive_state *alive_state)
|
||||||
{
|
{
|
||||||
struct rd_pwr_match *m = ddsrt_malloc (sizeof (*m));
|
struct rd_pwr_match *m = ddsrt_malloc (sizeof (*m));
|
||||||
ddsrt_avl_ipath_t path;
|
ddsrt_avl_ipath_t path;
|
||||||
|
@ -1886,12 +2030,14 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reader_add_local_connection (struct reader *rd, struct writer *wr)
|
static void reader_add_local_connection (struct reader *rd, struct writer *wr, const struct alive_state *alive_state)
|
||||||
{
|
{
|
||||||
struct rd_wr_match *m = ddsrt_malloc (sizeof (*m));
|
struct rd_wr_match *m = ddsrt_malloc (sizeof (*m));
|
||||||
ddsrt_avl_ipath_t path;
|
ddsrt_avl_ipath_t path;
|
||||||
|
|
||||||
m->wr_guid = wr->e.guid;
|
m->wr_guid = wr->e.guid;
|
||||||
|
m->wr_alive = alive_state->alive;
|
||||||
|
m->wr_alive_vclock = alive_state->vclock;
|
||||||
|
|
||||||
ddsrt_mutex_lock (&rd->e.lock);
|
ddsrt_mutex_lock (&rd->e.lock);
|
||||||
|
|
||||||
|
@ -1914,7 +2060,7 @@ static void reader_add_local_connection (struct reader *rd, struct writer *wr)
|
||||||
status_cb_data_t data;
|
status_cb_data_t data;
|
||||||
data.handle = wr->e.iid;
|
data.handle = wr->e.iid;
|
||||||
data.add = true;
|
data.add = true;
|
||||||
data.extra = (uint32_t) LIVELINESS_CHANGED_ADD_ALIVE;
|
data.extra = (uint32_t) (alive_state->alive ? LIVELINESS_CHANGED_ADD_ALIVE : LIVELINESS_CHANGED_ADD_NOT_ALIVE);
|
||||||
|
|
||||||
data.raw_status_id = (int) DDS_SUBSCRIPTION_MATCHED_STATUS_ID;
|
data.raw_status_id = (int) DDS_SUBSCRIPTION_MATCHED_STATUS_ID;
|
||||||
(rd->status_cb) (rd->status_cb_entity, &data);
|
(rd->status_cb) (rd->status_cb_entity, &data);
|
||||||
|
@ -2190,7 +2336,7 @@ static void connect_proxy_writer_with_reader (struct proxy_writer *pwr, struct r
|
||||||
const int isb1 = (is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) != 0);
|
const int isb1 = (is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) != 0);
|
||||||
dds_qos_policy_id_t reason;
|
dds_qos_policy_id_t reason;
|
||||||
nn_count_t init_count;
|
nn_count_t init_count;
|
||||||
struct proxy_writer_alive_state alive_state;
|
struct alive_state alive_state;
|
||||||
if (isb0 != isb1)
|
if (isb0 != isb1)
|
||||||
return;
|
return;
|
||||||
if (rd->e.onlylocal)
|
if (rd->e.onlylocal)
|
||||||
|
@ -2242,6 +2388,7 @@ static bool ignore_local_p (const ddsi_guid_t *guid1, const ddsi_guid_t *guid2,
|
||||||
static void connect_writer_with_reader (struct writer *wr, struct reader *rd, nn_mtime_t tnow)
|
static void connect_writer_with_reader (struct writer *wr, struct reader *rd, nn_mtime_t tnow)
|
||||||
{
|
{
|
||||||
dds_qos_policy_id_t reason;
|
dds_qos_policy_id_t reason;
|
||||||
|
struct alive_state alive_state;
|
||||||
(void)tnow;
|
(void)tnow;
|
||||||
if (!is_local_orphan_endpoint (&wr->e) && (is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE) || is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE)))
|
if (!is_local_orphan_endpoint (&wr->e) && (is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE) || is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE)))
|
||||||
return;
|
return;
|
||||||
|
@ -2253,8 +2400,17 @@ static void connect_writer_with_reader (struct writer *wr, struct reader *rd, nn
|
||||||
reader_qos_mismatch (rd, reason);
|
reader_qos_mismatch (rd, reason);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
reader_add_local_connection (rd, wr);
|
/* Initialze the reader's tracking information for the writer liveliness state to something
|
||||||
|
sensible, but that may be outdated by the time the reader gets added to the writer's list
|
||||||
|
of matching readers. */
|
||||||
|
writer_get_alive_state (wr, &alive_state);
|
||||||
|
reader_add_local_connection (rd, wr, &alive_state);
|
||||||
writer_add_local_connection (wr, rd);
|
writer_add_local_connection (wr, rd);
|
||||||
|
|
||||||
|
/* Once everything is set up: update with the latest state, any updates to the alive state
|
||||||
|
happening in parallel will cause this to become a no-op. */
|
||||||
|
writer_get_alive_state (wr, &alive_state);
|
||||||
|
reader_update_notify_wr_alive_state (rd, wr, &alive_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void connect_writer_with_proxy_reader_wrapper (struct entity_common *vwr, struct entity_common *vprd, nn_mtime_t tnow)
|
static void connect_writer_with_proxy_reader_wrapper (struct entity_common *vwr, struct entity_common *vprd, nn_mtime_t tnow)
|
||||||
|
@ -2702,6 +2858,91 @@ unsigned remove_acked_messages (struct writer *wr, struct whc_state *whcst, stru
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void writer_notify_liveliness_change_may_unlock (struct writer *wr)
|
||||||
|
{
|
||||||
|
struct alive_state alive_state;
|
||||||
|
writer_get_alive_state_locked (wr, &alive_state);
|
||||||
|
|
||||||
|
struct ddsi_guid rdguid;
|
||||||
|
struct pwr_rd_match *m;
|
||||||
|
memset (&rdguid, 0, sizeof (rdguid));
|
||||||
|
while (wr->alive_vclock == alive_state.vclock &&
|
||||||
|
(m = ddsrt_avl_lookup_succ (&wr_local_readers_treedef, &wr->local_readers, &rdguid)) != NULL)
|
||||||
|
{
|
||||||
|
rdguid = m->rd_guid;
|
||||||
|
ddsrt_mutex_unlock (&wr->e.lock);
|
||||||
|
/* unlocking pwr means alive state may have changed already; we break out of the loop once we
|
||||||
|
detect this but there for the reader in the current iteration, anything is possible */
|
||||||
|
reader_update_notify_wr_alive_state_guid (&rdguid, wr, &alive_state);
|
||||||
|
ddsrt_mutex_lock (&wr->e.lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writer_set_alive_may_unlock (struct writer *wr, bool notify)
|
||||||
|
{
|
||||||
|
/* Caller has wr->e.lock, so we can safely read wr->alive. Updating wr->alive requires
|
||||||
|
also taking wr->c.pp->e.lock because wr->alive <=> (wr->lease in pp's lease heap). */
|
||||||
|
assert (!wr->alive);
|
||||||
|
|
||||||
|
/* check that writer still exists (when deleting it is removed from guid hash) */
|
||||||
|
if (entidx_lookup_writer_guid (wr->e.gv->entity_index, &wr->e.guid) == NULL)
|
||||||
|
{
|
||||||
|
ELOGDISC (wr, "writer_set_alive_may_unlock("PGUIDFMT") - not in entity index, wr deleting\n", PGUID (wr->e.guid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ddsrt_mutex_lock (&wr->c.pp->e.lock);
|
||||||
|
wr->alive = true;
|
||||||
|
wr->alive_vclock++;
|
||||||
|
if (wr->xqos->liveliness.lease_duration != T_NEVER)
|
||||||
|
{
|
||||||
|
if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT)
|
||||||
|
participant_add_wr_lease_locked (wr->c.pp, wr);
|
||||||
|
else if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_TOPIC)
|
||||||
|
lease_set_expiry (wr->lease, add_duration_to_etime (now_et (), wr->lease->tdur));
|
||||||
|
}
|
||||||
|
ddsrt_mutex_unlock (&wr->c.pp->e.lock);
|
||||||
|
|
||||||
|
if (notify)
|
||||||
|
writer_notify_liveliness_change_may_unlock (wr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int writer_set_notalive_locked (struct writer *wr, bool notify)
|
||||||
|
{
|
||||||
|
if (!wr->alive)
|
||||||
|
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||||
|
|
||||||
|
/* To update wr->alive, both wr->e.lock and wr->c.pp->e.lock
|
||||||
|
should be taken */
|
||||||
|
ddsrt_mutex_lock (&wr->c.pp->e.lock);
|
||||||
|
wr->alive = false;
|
||||||
|
wr->alive_vclock++;
|
||||||
|
if (wr->xqos->liveliness.lease_duration != T_NEVER && wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT)
|
||||||
|
participant_remove_wr_lease_locked (wr->c.pp, wr);
|
||||||
|
ddsrt_mutex_unlock (&wr->c.pp->e.lock);
|
||||||
|
|
||||||
|
if (notify)
|
||||||
|
{
|
||||||
|
if (wr->status_cb)
|
||||||
|
{
|
||||||
|
status_cb_data_t data;
|
||||||
|
data.handle = wr->e.iid;
|
||||||
|
data.raw_status_id = (int) DDS_LIVELINESS_LOST_STATUS_ID;
|
||||||
|
(wr->status_cb) (wr->status_cb_entity, &data);
|
||||||
|
}
|
||||||
|
writer_notify_liveliness_change_may_unlock (wr);
|
||||||
|
}
|
||||||
|
return DDS_RETCODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int writer_set_notalive (struct writer *wr, bool notify)
|
||||||
|
{
|
||||||
|
ddsrt_mutex_lock (&wr->e.lock);
|
||||||
|
int ret = writer_set_notalive_locked(wr, notify);
|
||||||
|
ddsrt_mutex_unlock (&wr->e.lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc, status_cb_t status_cb, void * status_entity)
|
static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc, status_cb_t status_cb, void * status_entity)
|
||||||
{
|
{
|
||||||
ddsrt_cond_init (&wr->throttle_cond);
|
ddsrt_cond_init (&wr->throttle_cond);
|
||||||
|
@ -2723,6 +2964,8 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se
|
||||||
wr->throttle_tracing = 0;
|
wr->throttle_tracing = 0;
|
||||||
wr->rexmit_count = 0;
|
wr->rexmit_count = 0;
|
||||||
wr->rexmit_lost_count = 0;
|
wr->rexmit_lost_count = 0;
|
||||||
|
wr->alive = 1;
|
||||||
|
wr->alive_vclock = 0;
|
||||||
|
|
||||||
wr->status_cb = status_cb;
|
wr->status_cb = status_cb;
|
||||||
wr->status_cb_entity = status_entity;
|
wr->status_cb_entity = status_entity;
|
||||||
|
@ -2835,7 +3078,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se
|
||||||
}
|
}
|
||||||
|
|
||||||
assert (wr->xqos->present & QP_LIVELINESS);
|
assert (wr->xqos->present & QP_LIVELINESS);
|
||||||
if (wr->xqos->liveliness.kind == DDS_LIVELINESS_AUTOMATIC && wr->xqos->liveliness.lease_duration != T_NEVER)
|
if (wr->xqos->liveliness.lease_duration != T_NEVER)
|
||||||
{
|
{
|
||||||
wr->lease_duration = ddsrt_malloc (sizeof(*wr->lease_duration));
|
wr->lease_duration = ddsrt_malloc (sizeof(*wr->lease_duration));
|
||||||
wr->lease_duration->ldur = wr->xqos->liveliness.lease_duration;
|
wr->lease_duration->ldur = wr->xqos->liveliness.lease_duration;
|
||||||
|
@ -2913,16 +3156,32 @@ static dds_return_t new_writer_guid (struct writer **wr_out, const struct ddsi_g
|
||||||
if (wr->lease_duration != NULL)
|
if (wr->lease_duration != NULL)
|
||||||
{
|
{
|
||||||
assert (wr->lease_duration->ldur != T_NEVER);
|
assert (wr->lease_duration->ldur != T_NEVER);
|
||||||
assert (wr->xqos->liveliness.kind == DDS_LIVELINESS_AUTOMATIC);
|
|
||||||
assert (!is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE));
|
assert (!is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE));
|
||||||
|
if (wr->xqos->liveliness.kind == DDS_LIVELINESS_AUTOMATIC)
|
||||||
|
{
|
||||||
|
/* Store writer lease duration in participant's heap in case of automatic liveliness */
|
||||||
|
ddsrt_mutex_lock (&pp->e.lock);
|
||||||
|
ddsrt_fibheap_insert (&ldur_fhdef, &pp->ldur_auto_wr, wr->lease_duration);
|
||||||
|
ddsrt_mutex_unlock (&pp->e.lock);
|
||||||
|
|
||||||
/* Store writer lease duration in participant's heap in case of automatic liveliness */
|
/* Trigger pmd update */
|
||||||
ddsrt_mutex_lock (&pp->e.lock);
|
(void) resched_xevent_if_earlier (pp->pmd_update_xevent, now_mt ());
|
||||||
ddsrt_fibheap_insert (&ldur_fhdef, &pp->ldur_auto_wr, wr->lease_duration);
|
}
|
||||||
ddsrt_mutex_unlock (&pp->e.lock);
|
else
|
||||||
|
{
|
||||||
/* Trigger pmd update */
|
nn_etime_t texpire = add_duration_to_etime (now_et (), wr->lease_duration->ldur);
|
||||||
(void) resched_xevent_if_earlier (pp->pmd_update_xevent, now_mt ());
|
wr->lease = lease_new (texpire, wr->lease_duration->ldur, &wr->e);
|
||||||
|
if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT)
|
||||||
|
{
|
||||||
|
ddsrt_mutex_lock (&pp->e.lock);
|
||||||
|
participant_add_wr_lease_locked (pp, wr);
|
||||||
|
ddsrt_mutex_unlock (&pp->e.lock);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lease_register (wr->lease);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3019,6 +3278,8 @@ static void gc_delete_writer (struct gcreq *gcreq)
|
||||||
{
|
{
|
||||||
assert (wr->lease_duration->ldur == DDS_DURATION_INVALID);
|
assert (wr->lease_duration->ldur == DDS_DURATION_INVALID);
|
||||||
ddsrt_free (wr->lease_duration);
|
ddsrt_free (wr->lease_duration);
|
||||||
|
if (wr->xqos->liveliness.kind != DDS_LIVELINESS_AUTOMATIC)
|
||||||
|
lease_free (wr->lease);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do last gasp on SEDP and free writer. */
|
/* Do last gasp on SEDP and free writer. */
|
||||||
|
@ -3113,11 +3374,21 @@ dds_return_t delete_writer_nolinger_locked (struct writer *wr)
|
||||||
entidx_remove_writer_guid (wr->e.gv->entity_index, wr);
|
entidx_remove_writer_guid (wr->e.gv->entity_index, wr);
|
||||||
writer_set_state (wr, WRST_DELETING);
|
writer_set_state (wr, WRST_DELETING);
|
||||||
if (wr->lease_duration != NULL) {
|
if (wr->lease_duration != NULL) {
|
||||||
ddsrt_mutex_lock (&wr->c.pp->e.lock);
|
|
||||||
ddsrt_fibheap_delete (&ldur_fhdef, &wr->c.pp->ldur_auto_wr, wr->lease_duration);
|
|
||||||
ddsrt_mutex_unlock (&wr->c.pp->e.lock);
|
|
||||||
wr->lease_duration->ldur = DDS_DURATION_INVALID;
|
wr->lease_duration->ldur = DDS_DURATION_INVALID;
|
||||||
resched_xevent_if_earlier (wr->c.pp->pmd_update_xevent, now_mt ());
|
if (wr->xqos->liveliness.kind == DDS_LIVELINESS_AUTOMATIC)
|
||||||
|
{
|
||||||
|
ddsrt_mutex_lock (&wr->c.pp->e.lock);
|
||||||
|
ddsrt_fibheap_delete (&ldur_fhdef, &wr->c.pp->ldur_auto_wr, wr->lease_duration);
|
||||||
|
ddsrt_mutex_unlock (&wr->c.pp->e.lock);
|
||||||
|
resched_xevent_if_earlier (wr->c.pp->pmd_update_xevent, now_mt ());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_TOPIC)
|
||||||
|
lease_unregister (wr->lease);
|
||||||
|
if (writer_set_notalive_locked (wr, false) != DDS_RETCODE_OK)
|
||||||
|
ELOGDISC (wr, "writer_set_notalive failed for "PGUIDFMT"\n", PGUID (wr->e.guid));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
gcreq_writer (wr);
|
gcreq_writer (wr);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3541,21 +3812,13 @@ void update_reader_qos (struct reader *rd, const dds_qos_t *xqos)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PROXY-PARTICIPANT ------------------------------------------------ */
|
/* PROXY-PARTICIPANT ------------------------------------------------ */
|
||||||
const ddsrt_fibheap_def_t lease_fhdef_proxypp = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct lease, pp_heapnode), compare_lease_tdur);
|
|
||||||
|
|
||||||
static void gc_proxy_participant_lease (struct gcreq *gcreq)
|
|
||||||
{
|
|
||||||
lease_free (gcreq->arg);
|
|
||||||
gcreq_free (gcreq);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void proxy_participant_replace_minl (struct proxy_participant *proxypp, bool manbypp, struct lease *lnew)
|
static void proxy_participant_replace_minl (struct proxy_participant *proxypp, bool manbypp, struct lease *lnew)
|
||||||
{
|
{
|
||||||
/* By loading/storing the pointer atomically, we ensure we always
|
/* By loading/storing the pointer atomically, we ensure we always
|
||||||
read a valid (or once valid) lease. By delaying freeing the lease
|
read a valid (or once valid) lease. By delaying freeing the lease
|
||||||
through the garbage collector, we ensure whatever lease update
|
through the garbage collector, we ensure whatever lease update
|
||||||
occurs in parallel completes before the memory is released. */
|
occurs in parallel completes before the memory is released. */
|
||||||
struct gcreq *gcreq = gcreq_new (proxypp->e.gv->gcreq_queue, gc_proxy_participant_lease);
|
struct gcreq *gcreq = gcreq_new (proxypp->e.gv->gcreq_queue, gc_participant_lease);
|
||||||
struct lease *lease_old = ddsrt_atomic_ldvoidp (manbypp ? &proxypp->minl_man : &proxypp->minl_auto);
|
struct lease *lease_old = ddsrt_atomic_ldvoidp (manbypp ? &proxypp->minl_man : &proxypp->minl_auto);
|
||||||
lease_unregister (lease_old); /* ensures lease will not expire while it is replaced */
|
lease_unregister (lease_old); /* ensures lease will not expire while it is replaced */
|
||||||
gcreq->arg = lease_old;
|
gcreq->arg = lease_old;
|
||||||
|
@ -3568,11 +3831,11 @@ void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct
|
||||||
ddsrt_mutex_lock (&proxypp->e.lock);
|
ddsrt_mutex_lock (&proxypp->e.lock);
|
||||||
if (proxypp->owns_lease)
|
if (proxypp->owns_lease)
|
||||||
{
|
{
|
||||||
struct lease *minl = ddsrt_fibheap_min (&lease_fhdef_proxypp, &proxypp->leaseheap_auto);
|
struct lease *minl = ddsrt_fibheap_min (&lease_fhdef_pp, &proxypp->leaseheap_auto);
|
||||||
ddsrt_fibheap_delete (&lease_fhdef_proxypp, &proxypp->leaseheap_auto, proxypp->lease);
|
ddsrt_fibheap_delete (&lease_fhdef_pp, &proxypp->leaseheap_auto, proxypp->lease);
|
||||||
if (minl == proxypp->lease)
|
if (minl == proxypp->lease)
|
||||||
{
|
{
|
||||||
if ((minl = ddsrt_fibheap_min (&lease_fhdef_proxypp, &proxypp->leaseheap_auto)) != NULL)
|
if ((minl = ddsrt_fibheap_min (&lease_fhdef_pp, &proxypp->leaseheap_auto)) != NULL)
|
||||||
{
|
{
|
||||||
dds_duration_t trem = minl->tdur - proxypp->lease->tdur;
|
dds_duration_t trem = minl->tdur - proxypp->lease->tdur;
|
||||||
assert (trem >= 0);
|
assert (trem >= 0);
|
||||||
|
@ -3599,7 +3862,7 @@ void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct
|
||||||
|
|
||||||
The lease_unregister call ensures the lease will never expire
|
The lease_unregister call ensures the lease will never expire
|
||||||
while we are messing with it. */
|
while we are messing with it. */
|
||||||
struct gcreq *gcreq = gcreq_new (proxypp->e.gv->gcreq_queue, gc_proxy_participant_lease);
|
struct gcreq *gcreq = gcreq_new (proxypp->e.gv->gcreq_queue, gc_participant_lease);
|
||||||
lease_unregister (proxypp->lease);
|
lease_unregister (proxypp->lease);
|
||||||
gcreq->arg = proxypp->lease;
|
gcreq->arg = proxypp->lease;
|
||||||
gcreq_enqueue (gcreq);
|
gcreq_enqueue (gcreq);
|
||||||
|
@ -3620,9 +3883,9 @@ static void proxy_participant_add_pwr_lease_locked (struct proxy_participant * p
|
||||||
assert (pwr->lease != NULL);
|
assert (pwr->lease != NULL);
|
||||||
manbypp = (pwr->c.xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT);
|
manbypp = (pwr->c.xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT);
|
||||||
lh = manbypp ? &proxypp->leaseheap_man : &proxypp->leaseheap_auto;
|
lh = manbypp ? &proxypp->leaseheap_man : &proxypp->leaseheap_auto;
|
||||||
minl_prev = ddsrt_fibheap_min (&lease_fhdef_proxypp, lh);
|
minl_prev = ddsrt_fibheap_min (&lease_fhdef_pp, lh);
|
||||||
ddsrt_fibheap_insert (&lease_fhdef_proxypp, lh, pwr->lease);
|
ddsrt_fibheap_insert (&lease_fhdef_pp, lh, pwr->lease);
|
||||||
minl_new = ddsrt_fibheap_min (&lease_fhdef_proxypp, lh);
|
minl_new = ddsrt_fibheap_min (&lease_fhdef_pp, lh);
|
||||||
/* if inserted lease is new shortest lease */
|
/* if inserted lease is new shortest lease */
|
||||||
if (proxypp->owns_lease && minl_prev != minl_new)
|
if (proxypp->owns_lease && minl_prev != minl_new)
|
||||||
{
|
{
|
||||||
|
@ -3651,12 +3914,12 @@ static void proxy_participant_remove_pwr_lease_locked (struct proxy_participant
|
||||||
assert (pwr->lease != NULL);
|
assert (pwr->lease != NULL);
|
||||||
manbypp = (pwr->c.xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT);
|
manbypp = (pwr->c.xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT);
|
||||||
lh = manbypp ? &proxypp->leaseheap_man : &proxypp->leaseheap_auto;
|
lh = manbypp ? &proxypp->leaseheap_man : &proxypp->leaseheap_auto;
|
||||||
minl = ddsrt_fibheap_min (&lease_fhdef_proxypp, lh);
|
minl = ddsrt_fibheap_min (&lease_fhdef_pp, lh);
|
||||||
ddsrt_fibheap_delete (&lease_fhdef_proxypp, lh, pwr->lease);
|
ddsrt_fibheap_delete (&lease_fhdef_pp, lh, pwr->lease);
|
||||||
/* if pwr with min lease is removed: update proxypp lease to use new minimal duration */
|
/* if pwr with min lease is removed: update proxypp lease to use new minimal duration */
|
||||||
if (proxypp->owns_lease && pwr->lease == minl)
|
if (proxypp->owns_lease && pwr->lease == minl)
|
||||||
{
|
{
|
||||||
if ((minl = ddsrt_fibheap_min (&lease_fhdef_proxypp, lh)) != NULL)
|
if ((minl = ddsrt_fibheap_min (&lease_fhdef_pp, lh)) != NULL)
|
||||||
{
|
{
|
||||||
dds_duration_t trem = minl->tdur - pwr->lease->tdur;
|
dds_duration_t trem = minl->tdur - pwr->lease->tdur;
|
||||||
assert (trem >= 0);
|
assert (trem >= 0);
|
||||||
|
@ -3716,8 +3979,8 @@ void new_proxy_participant (struct q_globals *gv, const struct ddsi_guid *ppguid
|
||||||
struct proxy_participant *privpp;
|
struct proxy_participant *privpp;
|
||||||
privpp = entidx_lookup_proxy_participant_guid (gv->entity_index, &proxypp->privileged_pp_guid);
|
privpp = entidx_lookup_proxy_participant_guid (gv->entity_index, &proxypp->privileged_pp_guid);
|
||||||
|
|
||||||
ddsrt_fibheap_init (&lease_fhdef_proxypp, &proxypp->leaseheap_auto);
|
ddsrt_fibheap_init (&lease_fhdef_pp, &proxypp->leaseheap_auto);
|
||||||
ddsrt_fibheap_init (&lease_fhdef_proxypp, &proxypp->leaseheap_man);
|
ddsrt_fibheap_init (&lease_fhdef_pp, &proxypp->leaseheap_man);
|
||||||
ddsrt_atomic_stvoidp (&proxypp->minl_man, NULL);
|
ddsrt_atomic_stvoidp (&proxypp->minl_man, NULL);
|
||||||
|
|
||||||
if (privpp != NULL && privpp->is_ddsi2_pp)
|
if (privpp != NULL && privpp->is_ddsi2_pp)
|
||||||
|
@ -3743,7 +4006,7 @@ void new_proxy_participant (struct q_globals *gv, const struct ddsi_guid *ppguid
|
||||||
|
|
||||||
/* Add the proxypp lease to heap so that monitoring liveliness will include this lease
|
/* Add the proxypp lease to heap so that monitoring liveliness will include this lease
|
||||||
and uses the shortest duration for proxypp and all its pwr's (with automatic liveliness) */
|
and uses the shortest duration for proxypp and all its pwr's (with automatic liveliness) */
|
||||||
ddsrt_fibheap_insert (&lease_fhdef_proxypp, &proxypp->leaseheap_auto, proxypp->lease);
|
ddsrt_fibheap_insert (&lease_fhdef_pp, &proxypp->leaseheap_auto, proxypp->lease);
|
||||||
|
|
||||||
/* Set the shortest lease for auto liveliness: clone proxypp's lease and store the clone in
|
/* Set the shortest lease for auto liveliness: clone proxypp's lease and store the clone in
|
||||||
proxypp->minl_auto. As there are no pwr's at this point, the proxy pp's lease is the
|
proxypp->minl_auto. As there are no pwr's at this point, the proxy pp's lease is the
|
||||||
|
@ -3933,9 +4196,9 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p
|
||||||
if (proxypp->owns_lease)
|
if (proxypp->owns_lease)
|
||||||
{
|
{
|
||||||
struct lease * minl_auto = ddsrt_atomic_ldvoidp (&proxypp->minl_auto);
|
struct lease * minl_auto = ddsrt_atomic_ldvoidp (&proxypp->minl_auto);
|
||||||
ddsrt_fibheap_delete (&lease_fhdef_proxypp, &proxypp->leaseheap_auto, proxypp->lease);
|
ddsrt_fibheap_delete (&lease_fhdef_pp, &proxypp->leaseheap_auto, proxypp->lease);
|
||||||
assert (ddsrt_fibheap_min (&lease_fhdef_proxypp, &proxypp->leaseheap_auto) == NULL);
|
assert (ddsrt_fibheap_min (&lease_fhdef_pp, &proxypp->leaseheap_auto) == NULL);
|
||||||
assert (ddsrt_fibheap_min (&lease_fhdef_proxypp, &proxypp->leaseheap_man) == NULL);
|
assert (ddsrt_fibheap_min (&lease_fhdef_pp, &proxypp->leaseheap_man) == NULL);
|
||||||
assert (ddsrt_atomic_ldvoidp (&proxypp->minl_man) == NULL);
|
assert (ddsrt_atomic_ldvoidp (&proxypp->minl_man) == NULL);
|
||||||
assert (!compare_guid (&minl_auto->entity->guid, &proxypp->e.guid));
|
assert (!compare_guid (&minl_auto->entity->guid, &proxypp->e.guid));
|
||||||
lease_unregister (minl_auto);
|
lease_unregister (minl_auto);
|
||||||
|
@ -4445,7 +4708,7 @@ int delete_proxy_writer (struct q_globals *gv, const struct ddsi_guid *guid, nn_
|
||||||
|
|
||||||
static void proxy_writer_notify_liveliness_change_may_unlock (struct proxy_writer *pwr)
|
static void proxy_writer_notify_liveliness_change_may_unlock (struct proxy_writer *pwr)
|
||||||
{
|
{
|
||||||
struct proxy_writer_alive_state alive_state;
|
struct alive_state alive_state;
|
||||||
proxy_writer_get_alive_state_locked (pwr, &alive_state);
|
proxy_writer_get_alive_state_locked (pwr, &alive_state);
|
||||||
|
|
||||||
struct ddsi_guid rdguid;
|
struct ddsi_guid rdguid;
|
||||||
|
|
|
@ -144,6 +144,22 @@ void lease_free (struct lease *l)
|
||||||
ddsrt_free (l);
|
ddsrt_free (l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void trace_lease_renew (const struct lease *l, const char *tag, nn_etime_t tend_new)
|
||||||
|
{
|
||||||
|
struct q_globals const * gv = l->entity->gv;
|
||||||
|
if (gv->logconfig.c.mask & DDS_LC_TRACE)
|
||||||
|
{
|
||||||
|
int32_t tsec, tusec;
|
||||||
|
GVTRACE (" L(%s", tag);
|
||||||
|
if (l->entity->guid.entityid.u == NN_ENTITYID_PARTICIPANT)
|
||||||
|
GVTRACE (":%"PRIx32, l->entity->guid.entityid.u);
|
||||||
|
else
|
||||||
|
GVTRACE (""PGUIDFMT"", PGUID (l->entity->guid));
|
||||||
|
etime_to_sec_usec (&tsec, &tusec, tend_new);
|
||||||
|
GVTRACE (" %"PRId32".%06"PRId32")", tsec, tusec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void lease_renew (struct lease *l, nn_etime_t tnowE)
|
void lease_renew (struct lease *l, nn_etime_t tnowE)
|
||||||
{
|
{
|
||||||
nn_etime_t tend_new = add_duration_to_etime (tnowE, l->tdur);
|
nn_etime_t tend_new = add_duration_to_etime (tnowE, l->tdur);
|
||||||
|
@ -160,18 +176,7 @@ void lease_renew (struct lease *l, nn_etime_t tnowE)
|
||||||
* lease (i.e. the entity still exists). In cases where dereferencing l->entity->gv
|
* lease (i.e. the entity still exists). In cases where dereferencing l->entity->gv
|
||||||
* is not safe (e.g. the deletion of entities), the early out in the loop above
|
* is not safe (e.g. the deletion of entities), the early out in the loop above
|
||||||
* will be the case because tend is set to T_NEVER. */
|
* will be the case because tend is set to T_NEVER. */
|
||||||
struct q_globals const * gv = l->entity->gv;
|
trace_lease_renew (l, "", tend_new);
|
||||||
if (gv->logconfig.c.mask & DDS_LC_TRACE)
|
|
||||||
{
|
|
||||||
int32_t tsec, tusec;
|
|
||||||
GVTRACE (" L(");
|
|
||||||
if (l->entity->guid.entityid.u == NN_ENTITYID_PARTICIPANT)
|
|
||||||
GVTRACE (":%"PRIx32, l->entity->guid.entityid.u);
|
|
||||||
else
|
|
||||||
GVTRACE (""PGUIDFMT"", PGUID (l->entity->guid));
|
|
||||||
etime_to_sec_usec (&tsec, &tusec, tend_new);
|
|
||||||
GVTRACE (" %"PRId32".%06"PRId32")", tsec, tusec);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lease_set_expiry (struct lease *l, nn_etime_t when)
|
void lease_set_expiry (struct lease *l, nn_etime_t when)
|
||||||
|
@ -189,6 +194,7 @@ void lease_set_expiry (struct lease *l, nn_etime_t when)
|
||||||
TSCHED_NOT_ON_HEAP == INT64_MIN) */
|
TSCHED_NOT_ON_HEAP == INT64_MIN) */
|
||||||
l->tsched = when;
|
l->tsched = when;
|
||||||
ddsrt_fibheap_decrease_key (&lease_fhdef, &gv->leaseheap, l);
|
ddsrt_fibheap_decrease_key (&lease_fhdef, &gv->leaseheap, l);
|
||||||
|
trace_lease_renew (l, "earlier ", when);
|
||||||
trigger = true;
|
trigger = true;
|
||||||
}
|
}
|
||||||
else if (l->tsched.v == TSCHED_NOT_ON_HEAP && when.v < T_NEVER)
|
else if (l->tsched.v == TSCHED_NOT_ON_HEAP && when.v < T_NEVER)
|
||||||
|
@ -196,6 +202,7 @@ void lease_set_expiry (struct lease *l, nn_etime_t when)
|
||||||
/* not currently scheduled, with a finite new expiry time */
|
/* not currently scheduled, with a finite new expiry time */
|
||||||
l->tsched = when;
|
l->tsched = when;
|
||||||
ddsrt_fibheap_insert (&lease_fhdef, &gv->leaseheap, l);
|
ddsrt_fibheap_insert (&lease_fhdef, &gv->leaseheap, l);
|
||||||
|
trace_lease_renew (l, "insert ", when);
|
||||||
trigger = true;
|
trigger = true;
|
||||||
}
|
}
|
||||||
ddsrt_mutex_unlock (&gv->leaseheap_lock);
|
ddsrt_mutex_unlock (&gv->leaseheap_lock);
|
||||||
|
@ -283,9 +290,11 @@ int64_t check_and_handle_lease_expiration (struct q_globals *gv, nn_etime_t tnow
|
||||||
case EK_PROXY_WRITER:
|
case EK_PROXY_WRITER:
|
||||||
proxy_writer_set_notalive ((struct proxy_writer *) l->entity, true);
|
proxy_writer_set_notalive ((struct proxy_writer *) l->entity, true);
|
||||||
break;
|
break;
|
||||||
|
case EK_WRITER:
|
||||||
|
writer_set_notalive ((struct writer *) l->entity, true);
|
||||||
|
break;
|
||||||
case EK_PARTICIPANT:
|
case EK_PARTICIPANT:
|
||||||
case EK_READER:
|
case EK_READER:
|
||||||
case EK_WRITER:
|
|
||||||
case EK_PROXY_READER:
|
case EK_PROXY_READER:
|
||||||
assert (false);
|
assert (false);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1121,7 +1121,8 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct
|
||||||
dst.prefix = rst->dst_guid_prefix;
|
dst.prefix = rst->dst_guid_prefix;
|
||||||
dst.entityid = msg->readerId;
|
dst.entityid = msg->readerId;
|
||||||
|
|
||||||
RSTTRACE ("HEARTBEAT(%s#%"PRId32":%"PRId64"..%"PRId64" ", msg->smhdr.flags & HEARTBEAT_FLAG_FINAL ? "F" : "", msg->count, firstseq, lastseq);
|
RSTTRACE ("HEARTBEAT(%s%s#%"PRId32":%"PRId64"..%"PRId64" ", msg->smhdr.flags & HEARTBEAT_FLAG_FINAL ? "F" : "",
|
||||||
|
msg->smhdr.flags & HEARTBEAT_FLAG_LIVELINESS ? "L" : "", msg->count, firstseq, lastseq);
|
||||||
|
|
||||||
if (!rst->forme)
|
if (!rst->forme)
|
||||||
{
|
{
|
||||||
|
@ -1139,7 +1140,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct
|
||||||
RSTTRACE (PGUIDFMT" -> "PGUIDFMT":", PGUID (src), PGUID (dst));
|
RSTTRACE (PGUIDFMT" -> "PGUIDFMT":", PGUID (src), PGUID (dst));
|
||||||
ddsrt_mutex_lock (&pwr->e.lock);
|
ddsrt_mutex_lock (&pwr->e.lock);
|
||||||
if (msg->smhdr.flags & HEARTBEAT_FLAG_LIVELINESS &&
|
if (msg->smhdr.flags & HEARTBEAT_FLAG_LIVELINESS &&
|
||||||
pwr->c.xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_TOPIC &&
|
pwr->c.xqos->liveliness.kind != DDS_LIVELINESS_AUTOMATIC &&
|
||||||
pwr->c.xqos->liveliness.lease_duration != T_NEVER)
|
pwr->c.xqos->liveliness.lease_duration != T_NEVER)
|
||||||
{
|
{
|
||||||
if ((lease = ddsrt_atomic_ldvoidp (&pwr->c.proxypp->minl_man)) != NULL)
|
if ((lease = ddsrt_atomic_ldvoidp (&pwr->c.proxypp->minl_man)) != NULL)
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "dds/ddsi/q_entity.h"
|
#include "dds/ddsi/q_entity.h"
|
||||||
#include "dds/ddsi/q_unused.h"
|
#include "dds/ddsi/q_unused.h"
|
||||||
#include "dds/ddsi/q_hbcontrol.h"
|
#include "dds/ddsi/q_hbcontrol.h"
|
||||||
|
#include "dds/ddsi/q_lease.h"
|
||||||
#include "dds/ddsi/ddsi_tkmap.h"
|
#include "dds/ddsi/ddsi_tkmap.h"
|
||||||
#include "dds/ddsi/ddsi_serdata.h"
|
#include "dds/ddsi/ddsi_serdata.h"
|
||||||
#include "dds/ddsi/ddsi_sertopic.h"
|
#include "dds/ddsi/ddsi_sertopic.h"
|
||||||
|
@ -675,6 +676,8 @@ dds_return_t write_hb_liveliness (struct q_globals * const gv, struct ddsi_guid
|
||||||
struct nn_xmsg *msg = NULL;
|
struct nn_xmsg *msg = NULL;
|
||||||
struct whc_state whcst;
|
struct whc_state whcst;
|
||||||
struct thread_state1 * const ts1 = lookup_thread_state ();
|
struct thread_state1 * const ts1 = lookup_thread_state ();
|
||||||
|
struct lease *lease;
|
||||||
|
|
||||||
thread_state_awake (ts1, gv);
|
thread_state_awake (ts1, gv);
|
||||||
struct writer *wr = entidx_lookup_writer_guid (gv->entity_index, wr_guid);
|
struct writer *wr = entidx_lookup_writer_guid (gv->entity_index, wr_guid);
|
||||||
if (wr == NULL)
|
if (wr == NULL)
|
||||||
|
@ -682,6 +685,12 @@ dds_return_t write_hb_liveliness (struct q_globals * const gv, struct ddsi_guid
|
||||||
GVTRACE ("write_hb_liveliness("PGUIDFMT") - writer not found\n", PGUID (*wr_guid));
|
GVTRACE ("write_hb_liveliness("PGUIDFMT") - writer not found\n", PGUID (*wr_guid));
|
||||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT && ((lease = ddsrt_atomic_ldvoidp (&wr->c.pp->minl_man)) != NULL))
|
||||||
|
lease_renew (lease, now_et());
|
||||||
|
else if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_TOPIC && wr->lease != NULL)
|
||||||
|
lease_renew (wr->lease, now_et());
|
||||||
|
|
||||||
if ((msg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, sizeof (InfoTS_t) + sizeof (Heartbeat_t), NN_XMSG_KIND_CONTROL)) == NULL)
|
if ((msg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, sizeof (InfoTS_t) + sizeof (Heartbeat_t), NN_XMSG_KIND_CONTROL)) == NULL)
|
||||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||||
ddsrt_mutex_lock (&wr->e.lock);
|
ddsrt_mutex_lock (&wr->e.lock);
|
||||||
|
@ -1081,6 +1090,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack *
|
||||||
int r;
|
int r;
|
||||||
seqno_t seq;
|
seqno_t seq;
|
||||||
nn_mtime_t tnow;
|
nn_mtime_t tnow;
|
||||||
|
struct lease *lease;
|
||||||
|
|
||||||
/* If GC not allowed, we must be sure to never block when writing. That is only the case for (true, aggressive) KEEP_LAST writers, and also only if there is no limit to how much unacknowledged data the WHC may contain. */
|
/* If GC not allowed, we must be sure to never block when writing. That is only the case for (true, aggressive) KEEP_LAST writers, and also only if there is no limit to how much unacknowledged data the WHC may contain. */
|
||||||
assert (gc_allowed || (wr->xqos->history.kind == DDS_HISTORY_KEEP_LAST && wr->whc_low == INT32_MAX));
|
assert (gc_allowed || (wr->xqos->history.kind == DDS_HISTORY_KEEP_LAST && wr->whc_low == INT32_MAX));
|
||||||
|
@ -1102,8 +1112,16 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack *
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT && ((lease = ddsrt_atomic_ldvoidp (&wr->c.pp->minl_man)) != NULL))
|
||||||
|
lease_renew (lease, now_et());
|
||||||
|
else if (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_TOPIC && wr->lease != NULL)
|
||||||
|
lease_renew (wr->lease, now_et());
|
||||||
|
|
||||||
ddsrt_mutex_lock (&wr->e.lock);
|
ddsrt_mutex_lock (&wr->e.lock);
|
||||||
|
|
||||||
|
if (!wr->alive)
|
||||||
|
writer_set_alive_may_unlock (wr, true);
|
||||||
|
|
||||||
if (end_of_txn)
|
if (end_of_txn)
|
||||||
{
|
{
|
||||||
wr->cs_seq = 0;
|
wr->cs_seq = 0;
|
||||||
|
|
|
@ -36,6 +36,7 @@ for (@showopts) {
|
||||||
my $topfmt = "%${topcolwidth}.${topcolwidth}s";
|
my $topfmt = "%${topcolwidth}.${topcolwidth}s";
|
||||||
my $guidre = "[0-9a-f]+(?::[0-9a-f]+){3}";
|
my $guidre = "[0-9a-f]+(?::[0-9a-f]+){3}";
|
||||||
my $gidre = "[0-9a-f]+(?::[0-9a-f]+){2}";
|
my $gidre = "[0-9a-f]+(?::[0-9a-f]+){2}";
|
||||||
|
my $leasere = "(?:L\\((?:[a-z]+ )?[0-9a-f:]+\\s+[0-9.]+\\)\\s*)+";
|
||||||
my %opstr = ("00" => "R ", "01" => "W ", # index by $stinfo.$dflag
|
my %opstr = ("00" => "R ", "01" => "W ", # index by $stinfo.$dflag
|
||||||
"10" => " D ", "11" => "WD ",
|
"10" => " D ", "11" => "WD ",
|
||||||
"20" => " U", "21" => "W U",
|
"20" => " U", "21" => "W U",
|
||||||
|
@ -258,7 +259,7 @@ while(<>) {
|
||||||
# decent proxy for that.
|
# decent proxy for that.
|
||||||
#
|
#
|
||||||
# FIXME: find a way of dealing with decimal representation ...
|
# FIXME: find a way of dealing with decimal representation ...
|
||||||
if (/: ACKNACK\(F?#\d+:(\d+)\/(\d+):[01]* (?:L\([0-9a-f:]+\s+[0-9.]+\)\s*)?([0-9a-f]+(?::[0-9a-f]+){2}:[234]c7) -\> ([0-9a-f]+(?::[0-9a-f]+){2}:[234]c2) .*?(happy-now)?/) {
|
if (/: ACKNACK\(F?#\d+:(\d+)\/(\d+):[01]* (?:$leasere)?([0-9a-f]+(?::[0-9a-f]+){2}:[234]c7) -\> ([0-9a-f]+(?::[0-9a-f]+){2}:[234]c2) .*?(happy-now)?/) {
|
||||||
if (defined $5 || ($1 > 1 && $2 == 0 && version_at_least(6,6,4))) {
|
if (defined $5 || ($1 > 1 && $2 == 0 && version_at_least(6,6,4))) {
|
||||||
# happy-now should be enough, but historically DDSI2 advertised only data present in the WHC,
|
# happy-now should be enough, but historically DDSI2 advertised only data present in the WHC,
|
||||||
# which caused happy-now to not show up if the historical data ended on an unregister, because
|
# which caused happy-now to not show up if the historical data ended on an unregister, because
|
||||||
|
@ -266,7 +267,7 @@ while(<>) {
|
||||||
# last one written (that is, unregistered) (fixed in 6.6.4)
|
# last one written (that is, unregistered) (fixed in 6.6.4)
|
||||||
check_disccomplete("A", $3);
|
check_disccomplete("A", $3);
|
||||||
}
|
}
|
||||||
} elsif (/: HEARTBEAT\(F?#\d+:(\d+)\.\.(\d+)\s+(?:L\([0-9a-f:]+\s+[0-9.]+\)\s*)?([0-9a-f]+(?::[0-9a-f]+){2}:[234]c2)/) {
|
} elsif (/: HEARTBEAT\(F?L?#\d+:(\d+)\.\.(\d+)\s+(?:$leasere)?([0-9a-f]+(?::[0-9a-f]+){2}:[234]c2)/) {
|
||||||
check_disccomplete("H", $3);
|
check_disccomplete("H", $3);
|
||||||
# if there is no data and final is set there might be no ACK
|
# if there is no data and final is set there might be no ACK
|
||||||
check_disccomplete("B", $3) if $2 < $1;
|
check_disccomplete("B", $3) if $2 < $1;
|
||||||
|
@ -745,7 +746,7 @@ while(<>) {
|
||||||
if $nlost > 0 && $shows{rematch};
|
if $nlost > 0 && $shows{rematch};
|
||||||
delete $prd->{matches}->{$wrguid}->{seqp1del};
|
delete $prd->{matches}->{$wrguid}->{seqp1del};
|
||||||
}
|
}
|
||||||
} elsif (/ACKNACK\(F?#\d+:(\d+)\/\d+:([01]*) (?:L\(:1c1 [0-9.]+\) )?($guidre) -> ($guidre)(\??)/o) {
|
} elsif (/ACKNACK\(F?#\d+:(\d+)\/\d+:([01]*) (?:$leasere)?($guidre) -> ($guidre)(\??)/o) {
|
||||||
my $seqp1 = $1; my $nackset = $2; my $prdguid = hexify($3); my $wrguid = hexify($4); my $wrknown = ($5 eq "");
|
my $seqp1 = $1; my $nackset = $2; my $prdguid = hexify($3); my $wrguid = hexify($4); my $wrknown = ($5 eq "");
|
||||||
my $wr = $wr{$wrguid};
|
my $wr = $wr{$wrguid};
|
||||||
my $cnt = ($nackset =~ y/1//);
|
my $cnt = ($nackset =~ y/1//);
|
||||||
|
@ -904,7 +905,7 @@ while(<>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elsif (/HEARTBEAT\(F?#\d+:(\d+)\.\.(\d+) ($guidre)/o) {
|
} elsif (/HEARTBEAT\(F?L?#\d+:(\d+)\.\.(\d+) ($guidre)/o) {
|
||||||
my $prdguid = hexify($3);
|
my $prdguid = hexify($3);
|
||||||
(my $ppguid = $prdguid) =~ s/:[0-9a-f]+$/:1c1/;
|
(my $ppguid = $prdguid) =~ s/:[0-9a-f]+$/:1c1/;
|
||||||
$proxypp{$ppguid}->{non_spdp_seen} = 1 if exists $proxypp{$ppguid} && !defined $proxypp{$ppguid}->{tdel};
|
$proxypp{$ppguid}->{non_spdp_seen} = 1 if exists $proxypp{$ppguid} && !defined $proxypp{$ppguid}->{tdel};
|
||||||
|
@ -1475,7 +1476,7 @@ not necessarily the 4th field in, say, AWK):
|
||||||
EOT
|
EOT
|
||||||
;
|
;
|
||||||
exit 1;
|
exit 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub fmtblurb {
|
sub fmtblurb {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue