cyclonedds/src/core/ddsc/tests/liveliness.c

1194 lines
49 KiB
C
Raw Normal View History

Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <limits.h>
#include "dds/dds.h"
#include "CUnit/Theory.h"
#include "Space.h"
#include "config_env.h"
#include "dds/version.h"
#include "dds__entity.h"
#include "dds/ddsi/q_entity.h"
#include "dds/ddsi/ddsi_entity_index.h"
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
#include "dds/ddsrt/cdtors.h"
#include "dds/ddsrt/misc.h"
#include "dds/ddsrt/process.h"
#include "dds/ddsrt/threads.h"
#include "dds/ddsrt/environ.h"
#include "dds/ddsrt/atomics.h"
#include "dds/ddsrt/time.h"
#define DDS_DOMAINID_PUB 0
#define DDS_DOMAINID_SUB 1
#define DDS_CONFIG_NO_PORT_GAIN "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}<Discovery><ExternalDomainId>0</ExternalDomainId></Discovery>"
#define DDS_CONFIG_NO_PORT_GAIN_LOG "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}<Tracing><OutputFile>cyclonedds_liveliness_tests.${CYCLONEDDS_DOMAIN_ID}.${CYCLONEDDS_PID}.log</OutputFile><Verbosity>finest</Verbosity></Tracing><Discovery><ExternalDomainId>0</ExternalDomainId></Discovery>"
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
uint32_t g_topic_nr = 0;
static dds_entity_t g_pub_domain = 0;
static dds_entity_t g_pub_participant = 0;
static dds_entity_t g_pub_publisher = 0;
static dds_entity_t g_sub_domain = 0;
static dds_entity_t g_sub_participant = 0;
static dds_entity_t g_sub_subscriber = 0;
static char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size)
{
/* Get unique g_topic name. */
ddsrt_pid_t pid = ddsrt_getpid();
ddsrt_tid_t tid = ddsrt_gettid();
(void)snprintf(name, size, "%s%d_pid%" PRIdPID "_tid%" PRIdTID "", prefix, nr, pid, tid);
return name;
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
}
static void liveliness_init(void)
{
/* Domains for pub and sub use a different domain id, but the portgain setting
* in configuration is 0, so that both domains will map to the same port number.
* This allows to create two domains in a single test process. */
char *conf_pub = ddsrt_expand_envvars(DDS_CONFIG_NO_PORT_GAIN, DDS_DOMAINID_PUB);
char *conf_sub = ddsrt_expand_envvars(DDS_CONFIG_NO_PORT_GAIN, DDS_DOMAINID_SUB);
g_pub_domain = dds_create_domain(DDS_DOMAINID_PUB, conf_pub);
g_sub_domain = dds_create_domain(DDS_DOMAINID_SUB, conf_sub);
dds_free(conf_pub);
dds_free(conf_sub);
g_pub_participant = dds_create_participant(DDS_DOMAINID_PUB, NULL, NULL);
CU_ASSERT_FATAL(g_pub_participant > 0);
g_sub_participant = dds_create_participant(DDS_DOMAINID_SUB, NULL, NULL);
CU_ASSERT_FATAL(g_sub_participant > 0);
g_pub_publisher = dds_create_publisher(g_pub_participant, NULL, NULL);
CU_ASSERT_FATAL(g_pub_publisher > 0);
g_sub_subscriber = dds_create_subscriber(g_sub_participant, NULL, NULL);
CU_ASSERT_FATAL(g_sub_subscriber > 0);
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
}
static void liveliness_fini(void)
{
dds_delete(g_sub_subscriber);
dds_delete(g_pub_publisher);
dds_delete(g_sub_participant);
dds_delete(g_pub_participant);
dds_delete(g_sub_domain);
dds_delete(g_pub_domain);
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
}
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
/**
* Gets the current PMD sequence number for the participant. This
* can be used to count the number of PMD messages that is sent by
* the participant.
*/
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
static seqno_t get_pmd_seqno(dds_entity_t participant)
{
seqno_t seqno;
struct dds_entity *pp_entity;
struct participant *pp;
struct writer *wr;
CU_ASSERT_EQUAL_FATAL(dds_entity_pin(participant, &pp_entity), 0);
thread_state_awake(lookup_thread_state(), &pp_entity->m_domain->gv);
pp = entidx_lookup_participant_guid(pp_entity->m_domain->gv.entity_index, &pp_entity->m_guid);
wr = get_builtin_writer(pp, NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER);
CU_ASSERT_FATAL(wr != NULL);
assert(wr != NULL); /* for Clang's static analyzer */
seqno = wr->seq;
thread_state_asleep(lookup_thread_state());
dds_entity_unpin(pp_entity);
return seqno;
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
}
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
/**
* Gets the current PMD interval for the participant
*/
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
static dds_duration_t get_pmd_interval(dds_entity_t participant)
{
dds_duration_t intv;
struct dds_entity *pp_entity;
struct participant *pp;
CU_ASSERT_EQUAL_FATAL(dds_entity_pin(participant, &pp_entity), 0);
thread_state_awake(lookup_thread_state(), &pp_entity->m_domain->gv);
pp = entidx_lookup_participant_guid(pp_entity->m_domain->gv.entity_index, &pp_entity->m_guid);
intv = pp_get_pmd_interval(pp);
thread_state_asleep(lookup_thread_state());
dds_entity_unpin(pp_entity);
return intv;
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
}
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
/**
* Gets the current lease duration for the participant
*/
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
static dds_duration_t get_ldur_config(dds_entity_t participant)
{
struct dds_entity *pp_entity;
dds_duration_t ldur;
CU_ASSERT_EQUAL_FATAL(dds_entity_pin(participant, &pp_entity), 0);
ldur = (dds_duration_t)pp_entity->m_domain->gv.config.lease_duration;
dds_entity_unpin(pp_entity);
return ldur;
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
}
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
/**
* Test that the correct number of PMD messages is sent for
* the various liveliness kinds.
*/
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
#define A DDS_LIVELINESS_AUTOMATIC
#define MP DDS_LIVELINESS_MANUAL_BY_PARTICIPANT
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
#define MT DDS_LIVELINESS_MANUAL_BY_TOPIC
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
CU_TheoryDataPoints(ddsc_liveliness, pmd_count) = {
CU_DataPoints(dds_liveliness_kind_t, A, A, MP, MT), /* liveliness kind */
CU_DataPoints(uint32_t, 200, 500, 100, 100), /* lease duration */
CU_DataPoints(double, 10, 5, 5, 5), /* delay (n times lease duration) */
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
};
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
#undef MT
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
#undef MP
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
#undef A
static void test_pmd_count(dds_liveliness_kind_t kind, uint32_t ldur, double mult, bool remote_reader)
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
{
dds_entity_t pub_topic;
dds_entity_t sub_topic = 0;
dds_entity_t reader;
dds_entity_t writer;
seqno_t start_seqno, end_seqno;
dds_qos_t *rqos;
dds_qos_t *wqos;
dds_entity_t waitset;
dds_attach_t triggered;
uint32_t status;
char name[100];
dds_time_t t;
t = dds_time();
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,
kind == 0 ? "A" : "MP", ldur, (int32_t)(mult * ldur), remote_reader ? "remote" : "local");
/* wait for initial PMD to be sent by the participant */
while (get_pmd_seqno(g_pub_participant) < 1)
dds_sleepfor(DDS_MSECS(50));
/* topics */
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);
if (remote_reader)
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
/* reader */
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
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);
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
/* waitset on reader */
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);
/* writer */
CU_ASSERT_FATAL((wqos = dds_create_qos()) != NULL);
dds_qset_liveliness(wqos, kind, DDS_MSECS(ldur));
CU_ASSERT_FATAL((writer = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
dds_delete_qos(wqos);
/* wait for writer to be alive */
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(1)), 1);
CU_ASSERT_EQUAL_FATAL(dds_take_status(reader, &status, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
/* check no of PMD messages sent */
start_seqno = get_pmd_seqno(g_pub_participant);
dds_sleepfor(DDS_MSECS((dds_duration_t)(mult * ldur)));
end_seqno = get_pmd_seqno(g_pub_participant);
t = dds_time();
printf("%d.%06d PMD sequence no: start %" PRId64 " -> end %" PRId64 "\n",
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000,
start_seqno, end_seqno);
/* End-start should be mult - 1 under ideal circumstances, but consider the test successful
when at least 50% of the expected PMD's was sent. This checks that the frequency for sending
PMDs was increased when the writer was added. */
CU_ASSERT_FATAL(end_seqno - start_seqno >= (kind == DDS_LIVELINESS_AUTOMATIC ? (50 * (mult - 1)) / 100 : 0))
if (kind != DDS_LIVELINESS_AUTOMATIC)
CU_ASSERT_FATAL(get_pmd_seqno(g_pub_participant) - start_seqno < mult)
/* cleanup */
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(writer), DDS_RETCODE_OK);
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
}
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);
}
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
/**
* Test that the expected number of proxy writers expires (set to not-alive)
* after a certain delay for various combinations of writers with different
* liveliness kinds.
*/
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
CU_TheoryDataPoints(ddsc_liveliness, expire_liveliness_kinds) = {
CU_DataPoints(uint32_t, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200), /* lease duration for initial test run (increased for each retry when test fails) */
CU_DataPoints(double, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 2, 2, 2, 2, 2, 2, 2, 2, 2), /* delay (n times lease duration) */
CU_DataPoints(uint32_t, 1, 0, 2, 0, 1, 0, 0, 1, 1, 2, 0, 5, 0, 15, 15), /* number of writers with automatic 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 */
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
};
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)
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
{
dds_entity_t pub_topic;
dds_entity_t sub_topic = 0;
dds_entity_t reader;
dds_entity_t *writers;
dds_qos_t *rqos, *wqos_auto, *wqos_man_pp, *wqos_man_tp;
dds_entity_t waitset;
dds_attach_t triggered;
struct dds_liveliness_changed_status lstatus;
uint32_t status, n, run = 1, wr_cnt = wr_cnt_auto + wr_cnt_man_pp + wr_cnt_man_tp;
char name[100];
dds_time_t tstart, t;
bool test_finished = false;
do
{
tstart = dds_time();
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,
ldur, mult, wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, remote_reader ? "remote" : "local");
/* topics */
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);
if (remote_reader)
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
/* reader */
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
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);
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
/* writers */
CU_ASSERT_FATAL((wqos_auto = dds_create_qos()) != NULL);
dds_qset_liveliness(wqos_auto, DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(ldur));
CU_ASSERT_FATAL((wqos_man_pp = dds_create_qos()) != NULL);
dds_qset_liveliness(wqos_man_pp, DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(ldur));
CU_ASSERT_FATAL((wqos_man_tp = dds_create_qos()) != NULL);
dds_qset_liveliness(wqos_man_tp, DDS_LIVELINESS_MANUAL_BY_TOPIC, DDS_MSECS(ldur));
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);
writers = dds_alloc(wr_cnt * sizeof(dds_entity_t));
for (n = 0; n < wr_cnt; n++)
{
dds_qos_t *wqos;
wqos = n < wr_cnt_auto ? wqos_auto : (n < (wr_cnt_auto + wr_cnt_man_pp) ? wqos_man_pp : wqos_man_tp);
CU_ASSERT_FATAL((writers[n] = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
CU_ASSERT_EQUAL_FATAL(dds_take_status(reader, &status, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
}
dds_delete_qos(wqos_auto);
dds_delete_qos(wqos_man_pp);
dds_delete_qos(wqos_man_tp);
t = dds_time();
if (t - tstart > DDS_MSECS(0.5 * ldur))
{
ldur *= 10 / (run + 1);
printf("%d.%06d failed to create writers in time\n",
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000);
}
else
{
/* check alive count before proxy writers are expired */
dds_get_liveliness_changed_status(reader, &lstatus);
printf("%d.%06d writers alive: %d\n", (int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000, lstatus.alive_count);
CU_ASSERT_EQUAL_FATAL(lstatus.alive_count, wr_cnt);
dds_time_t tstop = tstart + DDS_MSECS((dds_duration_t)(mult * ldur));
uint32_t stopped = 0;
do
{
dds_duration_t w = tstop - dds_time();
CU_ASSERT_FATAL((dds_waitset_wait(waitset, &triggered, 1, w > 0 ? w : 0)) >= 0);
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
stopped += (uint32_t)lstatus.not_alive_count_change;
} while (dds_time() < tstop);
t = dds_time();
printf("%d.%06d writers stopped: %u\n",
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000, stopped);
size_t exp_stopped = mult < 1 ? 0 : (wr_cnt_man_pp + wr_cnt_man_tp);
if (stopped != exp_stopped)
{
ldur *= 10 / (run + 1);
printf("%d.%06d incorrect number of stopped writers\n",
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000);
}
else
{
/* check alive count */
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
CU_ASSERT_EQUAL(lstatus.alive_count, mult < 1 ? wr_cnt : wr_cnt_auto);
test_finished = true;
}
}
/* cleanup */
CU_ASSERT_EQUAL_FATAL(dds_waitset_detach(waitset, reader), DDS_RETCODE_OK);
CU_ASSERT_EQUAL_FATAL(dds_delete(waitset), DDS_RETCODE_OK);
for (n = 0; n < wr_cnt; n++)
CU_ASSERT_EQUAL_FATAL(dds_delete(writers[n]), DDS_RETCODE_OK);
dds_free(writers);
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(reader), DDS_RETCODE_OK);
if (!test_finished)
{
if (++run > 3)
{
printf("%d.%06d run limit reached, test failed\n", (int32_t)(tstart / DDS_NSECS_IN_SEC), (int32_t)(tstart % DDS_NSECS_IN_SEC) / 1000);
CU_FAIL_FATAL("Run limit reached");
test_finished = true;
continue;
}
else
{
printf("%d.%06d restarting test with ldur %d\n",
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000, ldur);
}
}
} while (!test_finished);
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
}
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)
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
{
dds_entity_t waitset;
dds_qos_t *wqos;
dds_attach_t triggered;
uint32_t status;
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
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);
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
CU_ASSERT_FATAL((wqos = dds_create_qos()) != NULL);
dds_qset_liveliness(wqos, kind, ldur);
CU_ASSERT_FATAL((*writer = dds_create_writer(g_pub_participant, topic, wqos, NULL)) > 0);
dds_delete_qos(wqos);
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
/* wait for writer to be alive */
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);
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
CU_ASSERT_EQUAL_FATAL(dds_waitset_detach(waitset, reader), DDS_RETCODE_OK);
CU_ASSERT_EQUAL_FATAL(dds_delete(waitset), DDS_RETCODE_OK);
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
}
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
/**
* Test that the correct PMD interval is set for the participant
* based on the lease duration of the writers.
*/
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
#define MAX_WRITERS 10
CU_Test(ddsc_liveliness, lease_duration, .init = liveliness_init, .fini = liveliness_fini)
{
dds_entity_t pub_topic;
dds_entity_t sub_topic;
dds_entity_t reader;
dds_entity_t writers[MAX_WRITERS];
uint32_t wr_cnt = 0;
char name[100];
dds_qos_t *rqos;
uint32_t n;
/* topics */
create_topic_name("ddsc_liveliness_ldur", 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((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
/* reader and waitset */
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
CU_ASSERT_FATAL((reader = dds_create_reader(g_sub_participant, sub_topic, rqos, NULL)) > 0);
dds_delete_qos(rqos);
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
/* check if pmd defaults to configured duration */
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 */
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));
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));
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));
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));
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));
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));
/* cleanup */
for (n = 0; n < wr_cnt; n++)
CU_ASSERT_EQUAL_FATAL(dds_delete(writers[n]), DDS_RETCODE_OK);
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(reader), DDS_RETCODE_OK);
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
}
#undef MAX_WRITERS
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
/**
* Check that the correct lease duration is set in the matched
* publications in the readers. */
static void test_lease_duration_pwr(bool remote_reader)
Liveliness QoS implementation for auto and manual-by-participant This commit adds support for the liveliness QoS for the liveliness kinds automatic and manual-by-participant. It also implements the lease_duration from this QoS, which was ignored until now. In the api the function dds_assert_liveliness is added to assert liveliness on a participant, which can be used when using liveliness kind manual-by-participant. Liveliness kind manual-by-topic is not yet supported, this will be added in a later commit. * Proxy participants now have 2 fibheaps to keep leases: one for leases of pwrs with automatic liveliness and one for leases of the pwrs with manual-by-participant liveliness (both protected by the proxypp lock). The minl_auto and minl_man members represent the shortest lease from these fibheaps and these leases are renewed when receiving data. Replacing the minl_ leases is now done by replacing the lease object (atomic ptr) with delayed deletion of the old lease using the gc. * Proxy writers are set not-alive when the lease expired, and reset to alive then data is received. When data is received by a pwr, the other pwrs in the proxypp might also be set alive. I think the specification is not clear at this point, and for now I have not implemented this * I refactored out the counter for man-by-pp proxy writers and improved locking when updating the min-leases on the proxy participant, so I think this fixes the race conditions. Some additional tests are required, e.g. to test the not-alive->alive transition for pwrs. I will add these in short term, as well as the implementation of the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-10-09 10:28:19 +02:00
{
dds_entity_t pub_topic;
dds_entity_t sub_topic = 0;
dds_entity_t reader;
dds_entity_t writer;
char name[100];
dds_qos_t *rqos, *wqos;
dds_entity_t waitset;
dds_attach_t triggered;
uint32_t status;
dds_duration_t ldur;
printf("running test lease_duration_pwr: %s reader\n", remote_reader ? "remote" : "local");
/* topics */
create_topic_name("ddsc_liveliness_ldurpwr", g_topic_nr++, name, sizeof name);
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_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 */
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
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);
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
/* writer */
ldur = 1000;
CU_ASSERT_FATAL((wqos = dds_create_qos()) != NULL);
dds_qset_liveliness(wqos, DDS_LIVELINESS_AUTOMATIC, DDS_MSECS(ldur));
CU_ASSERT_FATAL((writer = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
/* wait for writer to be alive */
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_wait(waitset, &triggered, 1, DDS_MSECS(1000)), 1);
CU_ASSERT_EQUAL_FATAL(dds_take_status(reader, &status, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
/* check pwr lease duration in matched publication */
dds_instance_handle_t wrs[1];
CU_ASSERT_EQUAL_FATAL(dds_get_matched_publications(reader, wrs, 1), 1);
dds_builtintopic_endpoint_t *ep;
ep = dds_get_matched_publication_data(reader, wrs[0]);
CU_ASSERT_FATAL(ep != NULL);
assert(ep != NULL); /* for Clang's static analyzer */
CU_ASSERT_EQUAL_FATAL(ep->qos->liveliness.lease_duration, DDS_MSECS(ldur));
dds_delete_qos(ep->qos);
dds_free(ep->topic_name);
dds_free(ep->type_name);
dds_free(ep);
/* cleanup */
dds_delete_qos(wqos);
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(writer), 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(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);
}
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
/**
* Create a relative large number of writers with liveliness kinds automatic and
* manual-by-participant and with decreasing lease duration, and check that all
* writers become alive. During the writer creation loop, every third writer
* is deleted immediately after creating.
*/
#define MAX_WRITERS 100
static void test_create_delete_writer_stress(bool remote_reader)
{
dds_entity_t pub_topic;
dds_entity_t sub_topic = 0;
dds_entity_t reader;
dds_entity_t writers[MAX_WRITERS];
dds_entity_t waitset;
dds_qos_t *wqos;
struct dds_liveliness_changed_status lstatus;
uint32_t alive_writers_auto = 0, alive_writers_man = 0;
char name[100];
dds_qos_t *rqos;
dds_attach_t triggered;
uint32_t n;
Space_Type1 sample = {0, 0, 0};
int64_t ldur = 1000;
printf("running test create_delete_writer_stress: %s reader\n", remote_reader ? "remote" : "local");
/* topics */
create_topic_name("ddsc_liveliness_wr_stress", g_topic_nr++, name, sizeof name);
CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_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 */
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
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);
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
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);
/* create 1st writer and wait for it to become alive */
CU_ASSERT_FATAL((wqos = dds_create_qos()) != NULL);
dds_qset_liveliness(wqos, DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(ldur));
CU_ASSERT_FATAL((writers[0] = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_MSECS(1000)), 1);
alive_writers_man++;
/* create writers */
for (n = 1; n < MAX_WRITERS; n++)
{
dds_qset_liveliness(wqos, n % 2 ? DDS_LIVELINESS_AUTOMATIC : DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_MSECS(n % 3 ? ldur + n : ldur - n) + ((n % 3) == 2 ? 1 : 0));
CU_ASSERT_FATAL((writers[n] = dds_create_writer(g_pub_participant, pub_topic, wqos, NULL)) > 0);
CU_ASSERT_EQUAL_FATAL(dds_write(writers[n], &sample), DDS_RETCODE_OK);
if (n % 3 == 2)
dds_delete(writers[n]);
else if (n % 2)
alive_writers_auto++;
else
alive_writers_man++;
}
dds_delete_qos(wqos);
printf("alive_writers_auto: %d, alive_writers_man: %d\n", alive_writers_auto, alive_writers_man);
/* wait for auto liveliness writers to become alive and manual-by-pp writers to become not-alive */
do
{
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
printf("alive: %d, not-alive: %d\n", lstatus.alive_count, lstatus.not_alive_count);
dds_sleepfor(DDS_MSECS(50));
} while (lstatus.alive_count != alive_writers_auto || lstatus.not_alive_count != alive_writers_man);
/* check that counts are stable after a delay */
dds_sleepfor(DDS_MSECS(ldur / 2));
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
CU_ASSERT_FATAL(lstatus.alive_count == alive_writers_auto && lstatus.not_alive_count == alive_writers_man);
/* cleanup remaining writers */
for (n = 0; n < MAX_WRITERS; n++)
{
if (n % 3 != 2)
CU_ASSERT_EQUAL_FATAL(dds_delete(writers[n]), DDS_RETCODE_OK);
}
/* wait for alive_count and not_alive_count to become 0 */
do
{
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
printf("alive: %d, not: %d\n", lstatus.alive_count, lstatus.not_alive_count);
dds_sleepfor(DDS_MSECS(ldur / 10));
} while (lstatus.alive_count > 0 || lstatus.not_alive_count > 0);
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(reader), 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_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
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
/**
* Check the counts in liveliness_changed_status result.
*/
static void test_status_counts(bool remote_reader)
{
dds_entity_t pub_topic;
dds_entity_t sub_topic = 0;
dds_entity_t reader;
dds_entity_t writer;
dds_entity_t waitset;
dds_qos_t *rqos;
dds_qos_t *wqos;
dds_attach_t triggered;
struct dds_liveliness_changed_status lcstatus;
struct dds_liveliness_lost_status llstatus;
struct dds_subscription_matched_status sstatus;
char name[100];
dds_duration_t ldur = DDS_MSECS(500);
Space_Type1 sample = {1, 0, 0};
printf("running test status_counts: %s reader\n", remote_reader ? "remote" : "local");
/* topics */
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);
if (remote_reader)
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
/* reader */
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
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);
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
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);
/* writer */
CU_ASSERT_FATAL((wqos = dds_create_qos()) != NULL);
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);
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 */
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
/* check status counts before proxy writer is expired */
dds_get_liveliness_changed_status(reader, &lcstatus);
CU_ASSERT_EQUAL_FATAL(lcstatus.alive_count, 1);
dds_get_subscription_matched_status(reader, &sstatus);
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 */
dds_sleepfor(ldur + DDS_MSECS(100));
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
dds_get_liveliness_changed_status(reader, &lcstatus);
CU_ASSERT_EQUAL_FATAL(lcstatus.alive_count, 0);
dds_get_subscription_matched_status(reader, &sstatus);
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 */
CU_ASSERT_EQUAL_FATAL(dds_write(writer, &sample), DDS_RETCODE_OK);
CU_ASSERT_EQUAL_FATAL(dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(5)), 1);
dds_get_liveliness_changed_status(reader, &lcstatus);
CU_ASSERT_EQUAL_FATAL(lcstatus.alive_count, 1);
dds_get_subscription_matched_status(reader, &sstatus);
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 */
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(reader), DDS_RETCODE_OK);
CU_ASSERT_EQUAL_FATAL(dds_delete(writer), 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);
}
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
CU_Test(ddsc_liveliness, status_counts, .init = liveliness_init, .fini = liveliness_fini)
{
test_status_counts(false);
test_status_counts(true);
}
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
/**
* Test that dds_assert_liveliness works as expected for liveliness
* kinds manual-by-participant and manual-by-topic.
*/
#define MAX_WRITERS 100
CU_TheoryDataPoints(ddsc_liveliness, assert_liveliness) = {
CU_DataPoints(uint32_t, 1, 0, 0, 1, 0, 1, 2), /* number of writers with automatic liveliness */
CU_DataPoints(uint32_t, 0, 1, 0, 1, 1, 0, 2), /* number of writers with manual-by-participant liveliness */
CU_DataPoints(uint32_t, 0, 0, 1, 1, 2, 2, 0), /* number of writers with manual-by-topic liveliness */
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
};
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)
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
{
dds_entity_t pub_topic, sub_topic = 0, reader, writers[MAX_WRITERS];
dds_qos_t *rqos;
struct dds_liveliness_changed_status lstatus;
char name[100];
uint32_t ldur = 100, wr_cnt, run = 1, stopped;
dds_time_t tstart, tstop, t;
bool test_finished = false;
do
{
wr_cnt = 0;
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, %s reader\n",
wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, ldur, remote_reader ? "remote" : "local");
/* topics */
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);
if (remote_reader)
CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0);
/* reader */
CU_ASSERT_FATAL((rqos = dds_create_qos()) != NULL);
dds_qset_liveliness(rqos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
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);
CU_ASSERT_EQUAL_FATAL(dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS), DDS_RETCODE_OK);
/* writers */
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, remote_reader);
tstart = dds_time();
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, remote_reader);
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, remote_reader);
t = dds_time();
if (t - tstart > DDS_MSECS(0.5 * ldur))
{
ldur *= 10 / (run + 1);
printf("%d.%06d failed to create writers with non-automatic liveliness kind in time\n",
(int32_t)(t / DDS_NSECS_IN_SEC), (int32_t)(t % DDS_NSECS_IN_SEC) / 1000);
}
else
{
/* check status counts before proxy writer is expired */
dds_get_liveliness_changed_status(reader, &lstatus);
CU_ASSERT_EQUAL_FATAL(lstatus.alive_count, wr_cnt_auto + wr_cnt_man_pp + wr_cnt_man_tp);
/* delay for more than lease duration and assert liveliness on writers:
all writers (including man-by-pp) should be kept alive */
tstop = dds_time() + 4 * DDS_MSECS(ldur) / 3;
stopped = 0;
do
{
for (size_t n = wr_cnt_auto; n < wr_cnt; 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);
stopped += (uint32_t)lstatus.not_alive_count_change;
dds_sleepfor(DDS_MSECS(50));
} while (dds_time() < tstop);
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);
if (lstatus.alive_count != wr_cnt_auto + wr_cnt_man_pp + wr_cnt_man_tp || stopped != 0)
{
ldur *= 10 / (run + 1);
printf("incorrect number of writers alive or stopped writers\n");
}
else
{
/* delay for more than lease duration and assert liveliness on participant:
writers with liveliness man-by-pp should be kept alive, man-by-topic writers
should stop */
tstop = dds_time() + 4 * DDS_MSECS(ldur) / 3;
stopped = 0;
do
{
dds_assert_liveliness(g_pub_participant);
CU_ASSERT_EQUAL_FATAL(dds_get_liveliness_changed_status(reader, &lstatus), DDS_RETCODE_OK);
stopped += (uint32_t)lstatus.not_alive_count_change;
dds_sleepfor(DDS_MSECS(50));
} while (dds_time() < tstop);
dds_get_liveliness_changed_status(reader, &lstatus);
printf("writers alive with dds_assert_liveliness on participant: %d, writers stopped: %d\n", lstatus.alive_count, stopped);
if (lstatus.alive_count != wr_cnt_auto + wr_cnt_man_pp || stopped != wr_cnt_man_tp)
{
ldur *= 10 / (run + 1);
printf("incorrect number of writers alive or stopped writers\n");
}
else
{
test_finished = true;
}
}
}
/* cleanup */
CU_ASSERT_EQUAL_FATAL(dds_delete(reader), DDS_RETCODE_OK);
for (size_t n = 0; n < wr_cnt; n++)
CU_ASSERT_EQUAL_FATAL(dds_delete(writers[n]), 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);
if (!test_finished)
{
if (++run > 3)
{
CU_FAIL_FATAL("Run limit reached");
test_finished = true;
continue;
}
else
{
printf("restarting test with ldur %d\n", ldur);
}
}
} while (!test_finished);
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
}
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);
}
Liveliness QoS implementation for kind manual_by_topic This commit adds the implementation for the liveliness kind manual-by-topic. With these changes, the api function dds_assert_liveliness now accepts a writer as entity. Asserting liveliness on a writer triggers sending a heartbeat message with the liveliness flag set. The code for handling reception of a heartbeat message checks for this flag and if set the lease for the proxy writer is renewed (and the shortest manual-by-participant lease on the proxy participant as well, because the message also indicates that the remote participant is alive). Receiving data (handle_regular) also renews the lease on the proxy writer in case it has the manual-by-topic liveliness kind. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Refactored locking for pwr->alive so that locking order is consistent (locking pwr->c.proxypp->e.lock while holding pwr->e.lock is the expected order). And processed other review comments: removed lock for ephash_lookup, added additional comments, set pwr->lease to null if not initialised. Because of intermittent timing issues with liveliness expiry test in Travis, I've increase the time-out and retry limit for this test. Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Check that proxy writer is still alive (could be not-alive due to deleting) in code path for proxy writer's lease expiry Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Some additional refactoring in locking for pwr->alive for liveliness qos, moved lease free to gc_delete_pwr, refactored the set pwr alive/not alive functions and some minor changes in liveliness tests Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com> Fixed building liveliness tests on Windows and some cleaning up in liveliness test code Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
2019-11-13 16:32:21 +01:00
#undef MAX_WRITERS
/**
* Check that manual-by-participant/topic writers with lease duration 0ns and 1ns work.
*/
struct liveliness_changed_state {
ddsrt_mutex_t lock;
dds_instance_handle_t w0_handle;
bool weirdness;
uint32_t w0_alive, w0_not_alive;
};
static void liveliness_changed_listener (dds_entity_t rd, const dds_liveliness_changed_status_t status, void *arg)
{
struct liveliness_changed_state *st = arg;
(void) rd;
ddsrt_mutex_lock (&st->lock);
if (status.last_publication_handle != st->w0_handle)
{
if (st->w0_handle == 0)
{
printf ("liveliness_changed_listener: w0 = %"PRIx64"\n", status.last_publication_handle);
st->w0_handle = status.last_publication_handle;
}
else
{
printf ("liveliness_changed_listener: too many writer handles\n");
st->weirdness = true;
}
}
if (status.alive_count_change != 0 || status.not_alive_count_change != 0)
{
switch (status.alive_count_change)
{
case -1:
break;
case 1:
if (status.last_publication_handle == st->w0_handle)
st->w0_alive++;
else
{
printf ("liveliness_changed_listener: alive_count_change = %d: unrecognized writer\n", status.alive_count_change);
st->weirdness = true;
}
break;
default:
printf ("liveliness_changed_listener: alive_count_change = %d\n", status.alive_count_change);
st->weirdness = true;
}
switch (status.not_alive_count_change)
{
case -1:
break;
case 1:
if (status.last_publication_handle == st->w0_handle)
st->w0_not_alive++;
else
{
printf ("liveliness_changed_listener: not_alive_count_change = %d: unrecognized writer\n", status.not_alive_count_change);
st->weirdness = true;
}
break;
default:
printf ("liveliness_changed_listener: not_alive_count_change = %d\n", status.not_alive_count_change);
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);
}
#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_subscription_matched_status sstatus;
struct dds_publication_matched_status pstatus;
uint32_t dstatus;
uint32_t result = STATUS_UNSYNCED;
dds_return_t rc;
rc = dds_get_subscription_matched_status(reader, &sstatus);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
rc = dds_get_liveliness_changed_status(reader, &lstatus);
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);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
CU_ASSERT_FATAL(lstatus.alive_count + lstatus.not_alive_count <= 2);
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);
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, bool remote_reader)
{
const uint32_t nsamples = (sleep <= DDS_MSECS(10)) ? 50 : 5;
dds_entity_t pub_topic;
dds_entity_t sub_topic = 0;
dds_entity_t reader;
dds_entity_t writer_active; /* writing */
dds_entity_t writer_inactive; /* not writing, liveliness should still toggle */
dds_entity_t waitset;
dds_listener_t *listener;
dds_qos_t *qos;
dds_return_t rc;
struct dds_liveliness_changed_status lstatus;
char name[100];
Space_Type1 sample = {1, 0, 0};
struct liveliness_changed_state listener_state = {
.weirdness = false,
.w0_handle = 0,
.w0_alive = 0,
.w0_not_alive = 0,
};
ddsrt_mutex_init (&listener_state.lock);
waitset = dds_create_waitset(DDS_CYCLONEDDS_HANDLE);
CU_ASSERT_FATAL(waitset > 0);
qos = dds_create_qos();
CU_ASSERT_FATAL(qos != NULL);
dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY);
dds_qset_history(qos, DDS_HISTORY_KEEP_ALL, 0);
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);
CU_ASSERT_FATAL(pub_topic > 0);
if (remote_reader)
{
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 */
dds_qset_liveliness(qos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
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);
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);
rc = dds_waitset_attach(waitset, reader, reader);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
/* writer liveliness varies */
dds_qset_liveliness(qos, lkind, ldur);
writer_active = dds_create_writer(g_pub_participant, pub_topic, qos, NULL);
CU_ASSERT_FATAL(writer_active > 0);
writer_inactive = dds_create_writer(g_pub_participant, pub_topic, qos, NULL);
CU_ASSERT_FATAL(writer_inactive > 0);
rc = dds_set_status_mask(writer_active, DDS_PUBLICATION_MATCHED_STATUS);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
rc = dds_waitset_attach(waitset, writer_active, writer_active);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
dds_delete_qos(qos);
/* wait for writers to be discovered and to have lost their liveliness, and for
writer_active to have discovered the reader */
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));
if (rc < 1)
{
get_and_check_status (reader, writer_active);
CU_ASSERT_FATAL(rc >= 1);
}
} while (1);
/* switch to using a listener: those allow us to observe all events */
listener = dds_create_listener (&listener_state);
dds_lset_liveliness_changed(listener, liveliness_changed_listener);
rc = dds_set_listener (reader, listener);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
dds_delete_listener (listener);
/* write as fast as possible - we don't expect this to cause the writers
to gain and lose liveliness once for each sample, but it should have
become alive at least once and fall back to not alive afterward */
for (uint32_t i = 0; i < nsamples; i++)
{
rc = dds_write(writer_active, &sample);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
if (sleep && i < nsamples - 1)
dds_sleepfor(sleep);
}
rc = dds_wait_for_acks(writer_active, DDS_SECS(5));
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
/* verify the reader received all samples */
void *raw[] = { &sample };
dds_sample_info_t si;
uint32_t cnt = 0;
do
{
rc = dds_waitset_wait(waitset, NULL, 0, DDS_SECS(5));
CU_ASSERT_FATAL(rc >= 1);
while (dds_take(reader, raw, &si, 1, 1) == 1 && si.valid_data)
cnt++;
}
while (cnt < nsamples + 1);
CU_ASSERT_FATAL(cnt == nsamples + 1);
/* transition to not alive is not necessarily immediate */
{
int retries = 100;
rc = dds_get_liveliness_changed_status(reader, &lstatus);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
printf("early liveliness changed status: alive %"PRId32" not-alive %"PRId32"\n", lstatus.alive_count, lstatus.not_alive_count);
ddsrt_mutex_lock (&listener_state.lock);
printf("early w0 %"PRIx64" alive %"PRId32" not-alive %"PRId32"\n", listener_state.w0_handle, listener_state.w0_alive, listener_state.w0_not_alive);
CU_ASSERT_FATAL(!listener_state.weirdness);
CU_ASSERT_FATAL(listener_state.w0_handle != 0);
while (listener_state.w0_not_alive < listener_state.w0_alive && retries-- > 0)
{
ddsrt_mutex_unlock(&listener_state.lock);
dds_sleepfor(DDS_MSECS(10));
rc = dds_get_liveliness_changed_status(reader, &lstatus);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
ddsrt_mutex_lock(&listener_state.lock);
}
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);
CU_ASSERT_FATAL(listener_state.w0_alive == listener_state.w0_not_alive);
uint32_t exp_alive;
if (sleep == 0)
exp_alive = 1; /* if not sleeping, it's ok if the transition happens only once */
else if (sleep <= DDS_MSECS(10))
exp_alive = nsamples / 3; /* if sleeping briefly, expect the a good number of writes to toggle liveliness */
else
exp_alive = nsamples - nsamples / 5; /* if sleeping, expect the vast majority (80%) of the writes to toggle liveliness */
printf("check w0_alive %d >= %d\n", listener_state.w0_alive, exp_alive);
CU_ASSERT_FATAL(listener_state.w0_alive >= exp_alive);
ddsrt_mutex_unlock(&listener_state.lock);
}
/* cleanup */
rc = dds_delete(waitset);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
rc = dds_delete(reader);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
rc = dds_delete(writer_active);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
rc = dds_delete(writer_inactive);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
if (remote_reader)
{
rc = dds_delete(sub_topic);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
}
rc = dds_delete(pub_topic);
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
ddsrt_mutex_destroy(&listener_state.lock);
}
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_liveliness_kind_t lkind[] = { DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_LIVELINESS_MANUAL_BY_TOPIC };
static const dds_duration_t ldur[] = { 0, 1 };
for (size_t remote_rd_idx = 0; remote_rd_idx < sizeof (remote_rd) / sizeof (remote_rd[0]); remote_rd_idx++)
{
for (size_t sleep_idx = 0; sleep_idx < sizeof (sleep) / sizeof (sleep[0]); sleep_idx++)
{
for (size_t lkind_idx = 0; lkind_idx < sizeof (lkind) / sizeof (lkind[0]); lkind_idx++)
{
for (size_t ldur_idx = 0; ldur_idx < sizeof (ldur) / sizeof (ldur[0]); ldur_idx++)
{
bool rrd = remote_rd[remote_rd_idx];
dds_duration_t s = sleep[sleep_idx];
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");
}
}
}
}
}