@@ -30,23 +31,26 @@
#include "dds/ddsi/q_misc.h"
#include "dds/ddsi/q_addrset.h"
#include "dds/ddsi/q_nwif.h"
-#include "dds/ddsi/q_error.h"
#include "dds/ddsrt/xmlparser.h"
#include "dds/version.h"
-#define WARN_DEPRECATED_ALIAS 1
-#define WARN_DEPRECATED_UNIT 1
#define MAX_PATH_DEPTH 10 /* max nesting level of configuration elements */
struct cfgelem;
struct cfgst;
-typedef int(*init_fun_t) (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem);
-typedef int(*update_fun_t) (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value);
-typedef void(*free_fun_t) (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem);
-typedef void(*print_fun_t) (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default);
+enum update_result {
+ URES_SUCCESS, /* value processed successfully */
+ URES_ERROR, /* invalid value, reject configuration */
+ URES_SKIP_ELEMENT /* entire subtree should be ignored */
+};
+
+typedef int (*init_fun_t) (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem);
+typedef enum update_result (*update_fun_t) (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value);
+typedef void (*free_fun_t) (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem);
+typedef void (*print_fun_t) (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources);
#ifdef DDSI_INCLUDE_SECURITY
struct q_security_plugins q_security_plugin = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
@@ -74,22 +78,55 @@ struct cfgelem {
struct cfgst_nodekey {
const struct cfgelem *e;
+ void *p;
};
struct cfgst_node {
ddsrt_avl_node_t avlnode;
struct cfgst_nodekey key;
int count;
+ uint32_t sources;
int failed;
- int is_default;
+};
+
+enum implicit_toplevel {
+ ITL_DISALLOWED = -1,
+ ITL_ALLOWED = 0,
+ ITL_INSERTED_1 = 1,
+ ITL_INSERTED_2 = 2
};
struct cfgst {
ddsrt_avl_tree_t found;
struct config *cfg;
+ const struct ddsrt_log_cfg *logcfg; /* for LOG_LC_CONFIG */
/* error flag set so that we can continue parsing for some errors and still fail properly */
int error;
+ /* Whether this is the first element in this source: used to reject about configurations
+ where the deprecated Domain/Id element is used but is set after some other things
+ have been set. The underlying reason being that the configuration handling can't
+ backtrack and so needs to reject a configuration for an unrelated domain before
+ anything is set.
+
+ The new form, where the id is an attribute of the Domain element, avoids this
+ by guaranteeing that the id comes first. It seems most likely that the Domain/Id
+ was either not set or at the start of the file and that this is therefore good
+ enough. */
+ bool first_data_in_source;
+
+ /* Whether inserting an implicit CycloneDDS is allowed (for making it easier to hack
+ a configuration through the environment variables, and if allowed, whether it has
+ been inserted */
+ enum implicit_toplevel implicit_toplevel;
+
+ /* current input, mask with 1 bit set */
+ uint32_t source;
+
+ /* ~ current input and line number */
+ char *input;
+ int line;
+
/* path_depth, isattr and path together control the formatting of
error messages by cfg_error() */
int path_depth;
@@ -98,32 +135,12 @@ struct cfgst {
void *parent[MAX_PATH_DEPTH];
};
-/* "trace" is special: it enables (nearly) everything */
-static const char *logcat_names[] = {
- "fatal", "error", "warning", "info", "config", "discovery", "data", "radmin", "timing", "traffic", "topic", "tcp", "plist", "whc", "throttle", "rhc", "trace", NULL
-};
-static const uint32_t logcat_codes[] = {
- DDS_LC_FATAL, DDS_LC_ERROR, DDS_LC_WARNING, DDS_LC_INFO, DDS_LC_CONFIG, DDS_LC_DISCOVERY, DDS_LC_DATA, DDS_LC_RADMIN, DDS_LC_TIMING, DDS_LC_TRAFFIC, DDS_LC_TOPIC, DDS_LC_TCP, DDS_LC_PLIST, DDS_LC_WHC, DDS_LC_THROTTLE, DDS_LC_RHC, DDS_LC_ALL
-};
-
-/* "trace" is special: it enables (nearly) everything */
-static const char *xcheck_names[] = {
- "whc", "rhc", "all", NULL
-};
-static const uint32_t xcheck_codes[] = {
- DDS_XCHECK_WHC, DDS_XCHECK_RHC, ~(uint32_t)0
-};
-
-/* We want the tracing/verbosity settings to be fixed while parsing
- the configuration, so we update this variable instead. */
-static uint32_t enabled_logcats;
-
static int cfgst_node_cmp(const void *va, const void *vb);
static const ddsrt_avl_treedef_t cfgst_found_treedef =
DDSRT_AVL_TREEDEF_INITIALIZER(offsetof(struct cfgst_node, avlnode), offsetof(struct cfgst_node, key), cfgst_node_cmp, 0);
-#define DU(fname) static int uf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
-#define PF(fname) static void pf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
+#define DU(fname) static enum update_result uf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
+#define PF(fname) static void pf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
#define DUPF(fname) DU(fname) ; PF(fname)
PF(nop);
DUPF(networkAddress);
@@ -138,7 +155,7 @@ PF(boolean_default);
DUPF(string);
DU(tracingOutputFileName);
DU(verbosity);
-DUPF(logcat);
+DUPF(tracemask);
DUPF(xcheck);
DUPF(int);
DUPF(uint);
@@ -216,7 +233,7 @@ DI(if_thread_properties);
#define MGROUP(name, children, attrs) name, children, attrs
#define ATTR(name) name, NULL, NULL
#define DEPRECATED_ATTR(name) "|" name, NULL, NULL
-/* MOVED: whereto must be a path relative to DDSI2Service, may not be used in/for lists and only for elements, may not be chained */
+/* MOVED: whereto must be a path starting with CycloneDDS, may not be used in/for lists and only for elements, may not be chained */
#define MOVED(name, whereto) ">" name, NULL, NULL, 0, whereto, 0, 0, 0, 0, 0, 0, NULL
#if 0
#define BLURB(text) text
@@ -240,15 +257,18 @@ static const struct cfgelem general_cfgelems[] = {
BLURB("This element allows explicitly overruling the network address DDSI2E advertises in the discovery protocol, which by default is the address of the preferred network interface (General/NetworkInterfaceAddress), to allow DDSI2E to communicate across a Network Address Translation (NAT) device.
") },
{ LEAF("ExternalNetworkMask"), 1, "0.0.0.0", ABSOFF(externalMaskString), 0, uf_string, ff_free, pf_string,
BLURB("This element specifies the network mask of the external network address. This element is relevant only when an external network address (General/ExternalNetworkAddress) is explicitly configured. In this case locators received via the discovery protocol that are within the same external subnet (as defined by this mask) will be translated to an internal address by replacing the network portion of the external address with the corresponding portion of the preferred network interface address. This option is IPv4-only.
") },
- { LEAF("AllowMulticast"), 1, "true", ABSOFF(allowMulticast), 0, uf_allow_multicast, 0, pf_allow_multicast,
+ { LEAF("AllowMulticast"), 1, "default", ABSOFF(allowMulticast), 0, uf_allow_multicast, 0, pf_allow_multicast,
BLURB("This element controls whether DDSI2E uses multicasts for data traffic.
\n\
-It is a comma-separated list of some of the following keywords: \"spdp\", \"asm\", \"ssm\", or either of \"false\" or \"true\".
\n\
+It is a comma-separated list of some of the following keywords: \"spdp\", \"asm\", \"ssm\", or either of \"false\" or \"true\", or \"default\".
\n\
\n\
- spdp: enables the use of ASM (any-source multicast) for participant discovery, joining the multicast group on the discovery socket, transmitting SPDP messages to this group, but never advertising nor using any multicast address in any discovery message, thus forcing unicast communications for all endpoint discovery and user data.
\n\
- asm: enables the use of ASM for all traffic, including receiving SPDP but not transmitting SPDP messages via multicast
\n\
- ssm: enables the use of SSM (source-specific multicast) for all non-SPDP traffic (if supported)
\n\
\n\
-When set to \"false\" all multicasting is disabled. The default, \"true\" enables full use of multicasts. Listening for multicasts can be controlled by General/MulticastRecvNetworkInterfaceAddresses.
") },
+When set to \"false\" all multicasting is disabled. The default, \"true\" enables full use of multicasts. Listening for multicasts can be controlled by General/MulticastRecvNetworkInterfaceAddresses.
\n\
+\"default\" maps on spdp if the network is a WiFi network, on true if it is a wired network
") },
+ { LEAF("PreferMulticast"), 1, "false", ABSOFF(prefer_multicast), 0, uf_boolean, 0, pf_boolean,
+ BLURB("When false (default) Cyclone DDS uses unicast for data whenever there a single unicast suffices. Setting this to true makes it prefer multicasting data, falling back to unicast only when no multicast address is available.
") },
{ LEAF("MulticastTimeToLive"), 1, "32", ABSOFF(multicast_ttl), 0, uf_natint_255, 0, pf_int,
BLURB("This element specifies the time-to-live setting for outgoing multicast packets.
") },
{ LEAF("DontRoute"), 1, "false", ABSOFF(dontRoute), 0, uf_boolean, 0, pf_boolean,
@@ -288,7 +308,7 @@ static const struct cfgelem securityprofile_cfgattrs[] = {
};
static const struct cfgelem security_cfgelems[] = {
- { LEAF_W_ATTRS("SecurityProfile", securityprofile_cfgattrs), 0, 0, ABSOFF(securityProfiles), if_security_profile, 0, 0, 0,
+ { LEAF_W_ATTRS("SecurityProfile", securityprofile_cfgattrs), INT_MAX, 0, ABSOFF(securityProfiles), if_security_profile, 0, 0, 0,
BLURB("This element defines a DDSI2E security profile.
") },
END_MARKER
};
@@ -310,7 +330,7 @@ static const struct cfgelem networkpartition_cfgattrs[] = {
};
static const struct cfgelem networkpartitions_cfgelems[] = {
- { LEAF_W_ATTRS("NetworkPartition", networkpartition_cfgattrs), 0, 0, ABSOFF(networkPartitions), if_network_partition, 0, 0, 0,
+ { LEAF_W_ATTRS("NetworkPartition", networkpartition_cfgattrs), INT_MAX, 0, ABSOFF(networkPartitions), if_network_partition, 0, 0, 0,
BLURB("This element defines a DDSI2E network partition.
") },
END_MARKER
};
@@ -322,7 +342,7 @@ static const struct cfgelem ignoredpartitions_cfgattrs[] = {
};
static const struct cfgelem ignoredpartitions_cfgelems[] = {
- { LEAF_W_ATTRS("IgnoredPartition", ignoredpartitions_cfgattrs), 0, 0, ABSOFF(ignoredPartitions), if_ignored_partition, 0, 0, 0,
+ { LEAF_W_ATTRS("IgnoredPartition", ignoredpartitions_cfgattrs), INT_MAX, 0, ABSOFF(ignoredPartitions), if_ignored_partition, 0, 0, 0,
BLURB("This element can be used to prevent certain combinations of DCPS partition and topic from being transmitted over the network. DDSI2E will complete ignore readers and writers for which all DCPS partitions as well as their topic is ignored, not even creating DDSI readers and writers to mirror the DCPS ones.
") },
END_MARKER
};
@@ -336,7 +356,7 @@ static const struct cfgelem partitionmappings_cfgattrs[] = {
};
static const struct cfgelem partitionmappings_cfgelems[] = {
- { LEAF_W_ATTRS("PartitionMapping", partitionmappings_cfgattrs), 0, 0, ABSOFF(partitionMappings), if_partition_mapping, 0, 0, 0,
+ { LEAF_W_ATTRS("PartitionMapping", partitionmappings_cfgattrs), INT_MAX, 0, ABSOFF(partitionMappings), if_partition_mapping, 0, 0, 0,
BLURB("This element defines a mapping from a DCPS partition/topic combination to a DDSI2E network partition. This allows partitioning data flows by using special multicast addresses for part of the data and possibly also encrypting the data flow.
") },
END_MARKER
};
@@ -381,7 +401,7 @@ static const struct cfgelem channel_cfgattrs[] = {
};
static const struct cfgelem channels_cfgelems[] = {
- { MGROUP("Channel", channel_cfgelems, channel_cfgattrs), 42, 0, ABSOFF(channels), if_channel, 0, 0, 0,
+ { MGROUP("Channel", channel_cfgelems, channel_cfgattrs), INT_MAX, 0, ABSOFF(channels), if_channel, 0, 0, 0,
BLURB("This element defines a channel.
") },
END_MARKER
};
@@ -418,7 +438,7 @@ static const struct cfgelem thread_properties_cfgelems[] = {
};
static const struct cfgelem threads_cfgelems[] = {
- { MGROUP("Thread", thread_properties_cfgelems, thread_properties_cfgattrs), 1000, 0, ABSOFF(thread_properties), if_thread_properties, 0, 0, 0,
+ { MGROUP("Thread", thread_properties_cfgelems, thread_properties_cfgattrs), INT_MAX, 0, ABSOFF(thread_properties), if_thread_properties, 0, 0, 0,
BLURB("This element is used to set thread properties.
") },
END_MARKER
};
@@ -436,8 +456,6 @@ static const struct cfgelem compatibility_cfgelems[] = {
{ LEAF ("ManySocketsMode"), 1, "single", ABSOFF (many_sockets_mode), 0, uf_many_sockets_mode, 0, pf_many_sockets_mode,
BLURB("This option specifies whether a network socket will be created for each domain participant on a host. The specification seems to assume that each participant has a unique address, and setting this option will ensure this to be the case. This is not the defeault.
\n\
Disabling it slightly improves performance and reduces network traffic somewhat. It also causes the set of port numbers needed by DDSI2E to become predictable, which may be useful for firewall and NAT configuration.
") },
- { LEAF("ArrivalOfDataAssertsPpAndEpLiveliness"), 1, "true", ABSOFF(arrival_of_data_asserts_pp_and_ep_liveliness), 0, uf_boolean, 0, pf_boolean,
- BLURB("When set to true, arrival of a message from a peer asserts liveliness of that peer. When set to false, only SPDP and explicit lease renewals have this effect.
") },
{ LEAF("AssumeRtiHasPmdEndpoints"), 1, "false", ABSOFF(assume_rti_has_pmd_endpoints), 0, uf_boolean, 0, pf_boolean,
BLURB("This option assumes ParticipantMessageData endpoints required by the liveliness protocol are present in RTI participants even when not properly advertised by the participant discovery protocol.
") },
END_MARKER
@@ -512,9 +530,9 @@ static const struct cfgelem unsupp_cfgelems[] = {
{ MOVED("FragmentSize", "CycloneDDS/General/FragmentSize") },
{ LEAF("DeliveryQueueMaxSamples"), 1, "256", ABSOFF(delivery_queue_maxsamples), 0, uf_uint, 0, pf_uint,
BLURB("This element controls the Maximum size of a delivery queue, expressed in samples. Once a delivery queue is full, incoming samples destined for that queue are dropped until space becomes available again.
") },
- { LEAF("PrimaryReorderMaxSamples"), 1, "64", ABSOFF(primary_reorder_maxsamples), 0, uf_uint, 0, pf_uint,
+ { LEAF("PrimaryReorderMaxSamples"), 1, "128", ABSOFF(primary_reorder_maxsamples), 0, uf_uint, 0, pf_uint,
BLURB("This element sets the maximum size in samples of a primary re-order administration. Each proxy writer has one primary re-order administration to buffer the packet flow in case some packets arrive out of order. Old samples are forwarded to secondary re-order administrations associated with readers in need of historical data.
") },
- { LEAF("SecondaryReorderMaxSamples"), 1, "16", ABSOFF(secondary_reorder_maxsamples), 0, uf_uint, 0, pf_uint,
+ { LEAF("SecondaryReorderMaxSamples"), 1, "128", ABSOFF(secondary_reorder_maxsamples), 0, uf_uint, 0, pf_uint,
BLURB("This element sets the maximum size in samples of a secondary re-order administration. The secondary re-order administration is per reader in need of historical data.
") },
{ LEAF("DefragUnreliableMaxSamples"), 1, "4", ABSOFF(defrag_unreliable_maxsamples), 0, uf_uint, 0, pf_uint,
BLURB("This element sets the maximum number of samples that can be defragmented simultaneously for a best-effort writers.
") },
@@ -526,9 +544,6 @@ static const struct cfgelem unsupp_cfgelems[] = {
writers: all participants have the writers, but just one has the readers;\n\
minimal: only one participant has built-in endpoints.\n\
The default is writers, as this is thought to be compliant and reasonably efficient. Minimal may or may not be compliant but is most efficient, and full is inefficient but certain to be compliant. See also Internal/ConservativeBuiltinReaderStartup.
") },
- { LEAF("ConservativeBuiltinReaderStartup"), 1, "false", ABSOFF(conservative_builtin_reader_startup), 0, uf_boolean, 0, pf_boolean,
- BLURB("This element forces all DDSI2E built-in discovery-related readers to request all historical data, instead of just one for each \"topic\". There is no indication that any of the current DDSI implementations requires changing of this setting, but it is conceivable that an implementation might track which participants have been informed of the existence of endpoints and which have not been, refusing communication with those that have \"can't\" know.
\n\
-Should it be necessary to hide DDSI2E's shared discovery behaviour, set this to true and Internal/BuiltinEndpointSet to full.
") },
{ LEAF("MeasureHbToAckLatency"), 1, "false", ABSOFF(meas_hb_to_ack_latency), 0, uf_boolean, 0, pf_boolean,
BLURB("This element enables heartbeat-to-ack latency among DDSI2E services by prepending timestamps to Heartbeat and AckNack messages and calculating round trip times. This is non-standard behaviour. The measured latencies are quite noisy and are currently not used anywhere.
") },
{ LEAF("UnicastResponseToSPDPMessages"), 1, "true", ABSOFF(unicast_response_to_spdp_messages), 0, uf_boolean, 0, pf_boolean,
@@ -541,12 +556,12 @@ static const struct cfgelem unsupp_cfgelems[] = {
BLURB("This elements configures the maximum number of DCPS domain participants this DDSI2E instance is willing to service. 0 is unlimited.
") },
{ LEAF("AccelerateRexmitBlockSize"), 1, "0", ABSOFF(accelerate_rexmit_block_size), 0, uf_uint, 0, pf_uint,
BLURB("Proxy readers that are assumed to sill be retrieving historical data get this many samples retransmitted when they NACK something, even if some of these samples have sequence numbers outside the set covered by the NACK.
") },
- { LEAF("RetransmitMerging"), 1, "adaptive", ABSOFF(retransmit_merging), 0, uf_retransmit_merging, 0, pf_retransmit_merging,
+ { LEAF("RetransmitMerging"), 1, "never", ABSOFF(retransmit_merging), 0, uf_retransmit_merging, 0, pf_retransmit_merging,
BLURB("This elements controls the addressing and timing of retransmits. Possible values are:
\n\
- never: retransmit only to the NACK-ing reader;
\n \
- adaptive: attempt to combine retransmits needed for reliability, but send historical (transient-local) data to the requesting reader only;
\n\
- always: do not distinguish between different causes, always try to merge.
\n\
-The default is adaptive. See also Internal/RetransmitMergingPeriod.
") },
+The default is never. See also Internal/RetransmitMergingPeriod.
") },
{ LEAF("RetransmitMergingPeriod"), 1, "5 ms", ABSOFF(retransmit_merging_period), 0, uf_duration_us_1s, 0, pf_duration,
BLURB("This setting determines the size of the time window in which a NACK of some sample is ignored because a retransmit of that sample has been multicasted too recently. This setting has no effect on unicasted retransmits.
\n\
See also Internal/RetransmitMerging.
") },
@@ -632,19 +647,19 @@ static const struct cfgelem sizing_cfgelems[] = {
};
static const struct cfgelem discovery_ports_cfgelems[] = {
- { LEAF("Base"), 1, "7400", ABSOFF(port_base), 0, uf_port, 0, pf_int,
+ { LEAF("Base"), 1, "7400", ABSOFF(port_base), 0, uf_port, 0, pf_uint,
BLURB("This element specifies the base port number (refer to the DDSI 2.1 specification, section 9.6.1, constant PB).
") },
- { LEAF("DomainGain"), 1, "250", ABSOFF(port_dg), 0, uf_int, 0, pf_int,
+ { LEAF("DomainGain"), 1, "250", ABSOFF(port_dg), 0, uf_uint, 0, pf_uint,
BLURB("This element specifies the domain gain, relating domain ids to sets of port numbers (refer to the DDSI 2.1 specification, section 9.6.1, constant DG).
") },
- { LEAF("ParticipantGain"), 1, "2", ABSOFF(port_pg), 0, uf_int, 0, pf_int,
+ { LEAF("ParticipantGain"), 1, "2", ABSOFF(port_pg), 0, uf_uint, 0, pf_uint,
BLURB("This element specifies the participant gain, relating p0, articipant index to sets of port numbers (refer to the DDSI 2.1 specification, section 9.6.1, constant PG).
") },
- { LEAF("MulticastMetaOffset"), 1, "0", ABSOFF(port_d0), 0, uf_int, 0, pf_int,
+ { LEAF("MulticastMetaOffset"), 1, "0", ABSOFF(port_d0), 0, uf_uint, 0, pf_uint,
BLURB("This element specifies the port number for multicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d0).
") },
- { LEAF("UnicastMetaOffset"), 1, "10", ABSOFF(port_d1), 0, uf_int, 0, pf_int,
+ { LEAF("UnicastMetaOffset"), 1, "10", ABSOFF(port_d1), 0, uf_uint, 0, pf_uint,
BLURB("This element specifies the port number for unicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d1).
") },
- { LEAF("MulticastDataOffset"), 1, "1", ABSOFF(port_d2), 0, uf_int, 0, pf_int,
+ { LEAF("MulticastDataOffset"), 1, "1", ABSOFF(port_d2), 0, uf_uint, 0, pf_uint,
BLURB("This element specifies the port number for multicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d2).
") },
- { LEAF("UnicastDataOffset"), 1, "11", ABSOFF(port_d3), 0, uf_int, 0, pf_int,
+ { LEAF("UnicastDataOffset"), 1, "11", ABSOFF(port_d3), 0, uf_uint, 0, pf_uint,
BLURB("This element specifies the port number for unicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d3).
") },
END_MARKER
};
@@ -706,13 +721,13 @@ static const struct cfgelem discovery_peer_cfgattrs[] = {
};
static const struct cfgelem discovery_peers_group_cfgelems[] = {
- { MGROUP("Peer", NULL, discovery_peer_cfgattrs), 0, NULL, ABSOFF(peers_group), if_peer, 0, 0, 0,
+ { MGROUP("Peer", NULL, discovery_peer_cfgattrs), INT_MAX, NULL, ABSOFF(peers_group), if_peer, 0, 0, 0,
BLURB("This element statically configures an addresses for discovery.
") },
END_MARKER
};
static const struct cfgelem discovery_peers_cfgelems[] = {
- { MGROUP("Peer", NULL, discovery_peer_cfgattrs), 0, NULL, ABSOFF(peers), if_peer, 0, 0, 0,
+ { MGROUP("Peer", NULL, discovery_peer_cfgattrs), INT_MAX, NULL, ABSOFF(peers), if_peer, 0, 0, 0,
BLURB("This element statically configures an addresses for discovery.
") },
{ GROUP("Group", discovery_peers_group_cfgelems),
BLURB("This element statically configures a fault tolerant group of addresses for discovery. Each member of the group is tried in sequence until one succeeds.
") },
@@ -746,7 +761,7 @@ static const struct cfgelem discovery_cfgelems[] = {
};
static const struct cfgelem tracing_cfgelems[] = {
- { LEAF("EnableCategory"), 1, "", 0, 0, 0, uf_logcat, 0, pf_logcat,
+ { LEAF("EnableCategory"), 1, "", 0, 0, 0, uf_tracemask, 0, pf_tracemask,
BLURB("This element enables individual logging categories. These are enabled in addition to those enabled by Tracing/Verbosity. Recognised categories are:
\n\
- fatal: all fatal errors, errors causing immediate termination
\n\
- error: failures probably impacting correctness but not necessarily causing immediate termination
\n\
@@ -776,7 +791,7 @@ static const struct cfgelem tracing_cfgelems[] = {
- finest: finer + trace
\n\
While none prevents any message from being written to a DDSI2 log file.
\n\
The categorisation of tracing output is incomplete and hence most of the verbosity levels and categories are not of much use in the current release. This is an ongoing process and here we describe the target situation rather than the current situation. Currently, the most useful verbosity levels are config, fine and finest.
") },
- { LEAF("OutputFile"), 1, DDS_PROJECT_NAME_NOSPACE_SMALL".log", ABSOFF(tracingOutputFileName), 0, uf_tracingOutputFileName, ff_free, pf_string,
+ { LEAF("OutputFile"), 1, "cyclonedds.log", ABSOFF(tracefile), 0, uf_tracingOutputFileName, ff_free, pf_string,
BLURB("This option specifies where the logging is printed to. Note that stdout and stderr are treated as special values, representing \"standard out\" and \"standard error\" respectively. No file is created unless logging categories are enabled using the Tracing/Verbosity or Tracing/EnabledCategory settings.
") },
{ LEAF("AppendToFile"), 1, "false", ABSOFF(tracingAppendToFile), 0, uf_boolean, 0, pf_boolean,
BLURB("This option specifies whether the output is to be appended to an existing log file. The default is to create a new log file each time, which is generally the best option if a detailed log is generated.
") },
@@ -785,14 +800,14 @@ static const struct cfgelem tracing_cfgelems[] = {
END_MARKER
};
-static const struct cfgelem domain_cfgelems[] = {
- { LEAF("Id"), 1, "any", ABSOFF(domainId), 0, uf_domainId, 0, pf_domainId, NULL },
+static const struct cfgelem domain_cfgattrs[] = {
+ { LEAF("Id"), 0, "any", ABSOFF(domainId), 0, uf_domainId, 0, pf_domainId,
+ BLURB("Domain id this configuration applies to, or \"any\" if it applies to all domain ids.
") },
END_MARKER
};
-static const struct cfgelem root_cfgelems[] = {
- { GROUP("Domain", domain_cfgelems),
- BLURB("The General element specifying Domain related settings.
") },
+static const struct cfgelem domain_cfgelems[] = {
+ { MOVED("Id", "CycloneDDS/Domain[@Id]") },
{ GROUP("General", general_cfgelems),
BLURB("The General element specifies overall DDSI2E service settings.
") },
#ifdef DDSI_INCLUDE_ENCRYPTION
@@ -827,12 +842,39 @@ static const struct cfgelem root_cfgelems[] = {
{ GROUP("SSL", ssl_cfgelems),
BLURB("The SSL element allows specifying various parameters related to using SSL/TLS for DDSI over TCP.
") },
#endif
- { MOVED("DDSI2E|DDSI2", "CycloneDDS") },
+ END_MARKER
+};
+
+static const struct cfgelem root_cfgelems[] = {
+ { GROUP_W_ATTRS("Domain", domain_cfgelems, domain_cfgattrs),
+ BLURB("The General element specifying Domain related settings.
") },
+ { MOVED("General", "CycloneDDS/Domain/General") },
+#ifdef DDSI_INCLUDE_ENCRYPTION
+ { MOVED("Security", "CycloneDDS/Domain/Security") },
+#endif
+#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
+ { MOVED("Partitioning", "CycloneDDS/Domain/Partitioning") },
+#endif
+#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
+ { MOVED("Channels", "CycloneDDS/Domain/Channels") },
+#endif
+ { MOVED("Threads", "CycloneDDS/Domain/Threads") },
+ { MOVED("Sizing", "CycloneDDS/Domain/Sizing") },
+ { MOVED("Compatibility", "CycloneDDS/Domain/Compatibility") },
+ { MOVED("Discovery", "CycloneDDS/Domain/Discovery") },
+ { MOVED("Tracing", "CycloneDDS/Domain/Tracing") },
+ { MOVED("Internal|Unsupported", "CycloneDDS/Domain/Internal") },
+ { MOVED("TCP", "CycloneDDS/Domain/TCP") },
+ { MOVED("ThreadPool", "CycloneDDS/Domain/ThreadPool") },
+#ifdef DDSI_INCLUDE_SSL
+ { MOVED("SSL", "CycloneDDS/Domain/SSL") },
+#endif
+ { MOVED("DDSI2E|DDSI2", "CycloneDDS/Domain") },
END_MARKER
};
static const struct cfgelem cyclonedds_root_cfgelems[] = {
- { DDS_PROJECT_NAME_NOSPACE, root_cfgelems, NULL, NODATA, NULL },
+ { "CycloneDDS", root_cfgelems, NULL, NODATA, BLURB("CycloneDDS configuration") },
END_MARKER
};
@@ -851,9 +893,6 @@ static const struct cfgelem root_cfgelem = {
#undef ABSOFF
#undef CO
-struct config config;
-struct ddsi_plugin ddsi_plugin;
-
static const struct unit unittab_duration[] = {
{ "ns", 1 },
{ "us", 1000 },
@@ -909,7 +948,11 @@ static const struct unit unittab_bandwidth_Bps[] = {
};
#endif
-static void cfgst_push(struct cfgst *cfgst, int isattr, const struct cfgelem *elem, void *parent)
+static void free_configured_elements (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem);
+static void free_configured_element (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem);
+static const struct cfgelem *lookup_element (const char *target, bool *isattr);
+
+static void cfgst_push (struct cfgst *cfgst, int isattr, const struct cfgelem *elem, void *parent)
{
assert(cfgst->path_depth < MAX_PATH_DEPTH);
assert(isattr == 0 || isattr == 1);
@@ -919,19 +962,26 @@ static void cfgst_push(struct cfgst *cfgst, int isattr, const struct cfgelem *el
cfgst->path_depth++;
}
-static void cfgst_pop(struct cfgst *cfgst)
+static void cfgst_pop (struct cfgst *cfgst)
{
assert(cfgst->path_depth > 0);
cfgst->path_depth--;
}
-static const struct cfgelem *cfgst_tos(const struct cfgst *cfgst)
+static const struct cfgelem *cfgst_tos_w_isattr (const struct cfgst *cfgst, bool *isattr)
{
assert(cfgst->path_depth > 0);
+ *isattr = cfgst->isattr[cfgst->path_depth - 1];
return cfgst->path[cfgst->path_depth - 1];
}
-static void *cfgst_parent(const struct cfgst *cfgst)
+static const struct cfgelem *cfgst_tos (const struct cfgst *cfgst)
+{
+ bool dummy_isattr;
+ return cfgst_tos_w_isattr (cfgst, &dummy_isattr);
+}
+
+static void *cfgst_parent (const struct cfgst *cfgst)
{
assert(cfgst->path_depth > 0);
return cfgst->parent[cfgst->path_depth - 1];
@@ -943,46 +993,47 @@ struct cfg_note_buf {
char *buf;
};
-static size_t cfg_note_vsnprintf(struct cfg_note_buf *bb, const char *fmt, va_list ap)
+static size_t cfg_note_vsnprintf (struct cfg_note_buf *bb, const char *fmt, va_list ap)
{
int x;
x = vsnprintf(bb->buf + bb->bufpos, bb->bufsize - bb->bufpos, fmt, ap);
- if ( x >= 0 && (size_t) x >= bb->bufsize - bb->bufpos ) {
+ if (x >= 0 && (size_t) x >= bb->bufsize - bb->bufpos)
+ {
size_t nbufsize = ((bb->bufsize + (size_t) x + 1) + 1023) & (size_t) (-1024);
- char *nbuf = ddsrt_realloc(bb->buf, nbufsize);
+ char *nbuf = ddsrt_realloc (bb->buf, nbufsize);
bb->buf = nbuf;
bb->bufsize = nbufsize;
return nbufsize;
}
- if ( x < 0 )
+ if (x < 0)
DDS_FATAL("cfg_note_vsnprintf: vsnprintf failed\n");
else
bb->bufpos += (size_t) x;
return 0;
}
-static void cfg_note_snprintf(struct cfg_note_buf *bb, const char *fmt, ...)
+static void cfg_note_snprintf (struct cfg_note_buf *bb, const char *fmt, ...)
{
/* The reason the 2nd call to os_vsnprintf is here and not inside
cfg_note_vsnprintf is because I somehow doubt that all platforms
implement va_copy() */
va_list ap;
size_t r;
- va_start(ap, fmt);
- r = cfg_note_vsnprintf(bb, fmt, ap);
- va_end(ap);
- if ( r > 0 ) {
+ va_start (ap, fmt);
+ r = cfg_note_vsnprintf (bb, fmt, ap);
+ va_end (ap);
+ if (r > 0) {
int s;
- va_start(ap, fmt);
- s = vsnprintf(bb->buf + bb->bufpos, bb->bufsize - bb->bufpos, fmt, ap);
- if ( s < 0 || (size_t) s >= bb->bufsize - bb->bufpos )
- DDS_FATAL("cfg_note_snprintf: vsnprintf failed\n");
- va_end(ap);
+ va_start (ap, fmt);
+ s = vsnprintf (bb->buf + bb->bufpos, bb->bufsize - bb->bufpos, fmt, ap);
+ if (s < 0 || (size_t) s >= bb->bufsize - bb->bufpos)
+ DDS_FATAL ("cfg_note_snprintf: vsnprintf failed\n");
+ va_end (ap);
bb->bufpos += (size_t) s;
}
}
-static size_t cfg_note(struct cfgst *cfgst, uint32_t cat, size_t bsz, const char *fmt, va_list ap)
+static size_t cfg_note (struct cfgst *cfgst, uint32_t cat, size_t bsz, const char *fmt, const char *suffix, va_list ap)
{
/* Have to snprintf our way to a single string so we can OS_REPORT
as well as nn_log. Otherwise configuration errors will be lost
@@ -993,177 +1044,196 @@ static size_t cfg_note(struct cfgst *cfgst, uint32_t cat, size_t bsz, const char
int i, sidx;
size_t r;
- if (cat & DDS_LC_ERROR) {
+ if (cat & DDS_LC_ERROR)
cfgst->error = 1;
- }
bb.bufpos = 0;
bb.bufsize = (bsz == 0) ? 1024 : bsz;
- if ( (bb.buf = ddsrt_malloc(bb.bufsize)) == NULL )
- DDS_FATAL("cfg_note: out of memory\n");
+ if ((bb.buf = ddsrt_malloc(bb.bufsize)) == NULL)
+ DDS_FATAL ("cfg_note: out of memory\n");
- cfg_note_snprintf(&bb, "config: ");
+ cfg_note_snprintf (&bb, "config: ");
/* Path to element/attribute causing the error. Have to stop once an
attribute is reached: a NULL marker may have been pushed onto the
stack afterward in the default handling. */
sidx = 0;
- while ( sidx < cfgst->path_depth && cfgst->path[sidx]->name == NULL )
+ while (sidx < cfgst->path_depth && cfgst->path[sidx]->name == NULL)
sidx++;
const struct cfgelem *prev_path = NULL;
- for ( i = sidx; i < cfgst->path_depth && (i == sidx || !cfgst->isattr[i - 1]); i++ ) {
- if ( cfgst->path[i] == NULL ) {
+ for (i = sidx; i < cfgst->path_depth && (i == sidx || !cfgst->isattr[i - 1]); i++)
+ {
+ if (cfgst->path[i] == NULL)
+ {
assert(i > sidx);
- cfg_note_snprintf(&bb, "/#text");
- } else if ( cfgst->isattr[i] ) {
- cfg_note_snprintf(&bb, "[@%s]", cfgst->path[i]->name);
- } else if (cfgst->path[i] == prev_path) {
+ cfg_note_snprintf (&bb, "/#text");
+ }
+ else if (cfgst->isattr[i])
+ {
+ cfg_note_snprintf (&bb, "[@%s]", cfgst->path[i]->name);
+ }
+ else if (cfgst->path[i] == prev_path)
+ {
/* skip printing this level: it means a group contained an element indicating that
it was moved to the first group (i.e., stripping a level) -- this is currently
only used for stripping out the DDSI2E level, and the sole purpose of this
special case is making any warnings from elements contained within it look
reasonable by always printing the new location */
- } else {
+ }
+ else
+ {
/* first character is '>' means it was moved, so print what follows instead */
const char *name = cfgst->path[i]->name + ((cfgst->path[i]->name[0] == '>') ? 1 : 0);
- const char *p = strchr(name, '|');
+ const char *p = strchr (name, '|');
int n = p ? (int) (p - name) : (int) strlen(name);
- cfg_note_snprintf(&bb, "%s%*.*s", (i == sidx) ? "" : "/", n, n, name);
+ cfg_note_snprintf (&bb, "%s%*.*s", (i == sidx) ? "" : "/", n, n, name);
}
prev_path = cfgst->path[i];
}
- cfg_note_snprintf(&bb, ": ");
- if ( (r = cfg_note_vsnprintf(&bb, fmt, ap)) > 0 ) {
+ cfg_note_snprintf (&bb, ": ");
+ if ((r = cfg_note_vsnprintf (&bb, fmt, ap)) > 0)
+ {
/* Can't reset ap ... and va_copy isn't widely available - so
instead abort and hope the caller tries again with a larger
initial buffer */
- ddsrt_free(bb.buf);
+ ddsrt_free (bb.buf);
return r;
}
- switch ( cat ) {
- case DDS_LC_CONFIG:
- DDS_LOG(cat, "%s\n", bb.buf);
- break;
- case DDS_LC_WARNING:
- DDS_WARNING("%s\n", bb.buf);
- break;
- case DDS_LC_ERROR:
- DDS_ERROR("%s\n", bb.buf);
- break;
- default:
- DDS_FATAL("cfg_note unhandled category %u for message %s\n", (unsigned) cat, bb.buf);
- break;
+ cfg_note_snprintf (&bb, "%s", suffix);
+
+ if (cat & (DDS_LC_WARNING | DDS_LC_ERROR))
+ {
+ if (cfgst->input == NULL)
+ cfg_note_snprintf (&bb, " (line %d)", cfgst->line);
+ else
+ {
+ cfg_note_snprintf (&bb, " (%s line %d)", cfgst->input, cfgst->line);
+ cfgst->input = NULL;
+ }
}
- ddsrt_free(bb.buf);
+ if (cfgst->logcfg)
+ DDS_CLOG (cat, cfgst->logcfg, "%s\n", bb.buf);
+ else
+ DDS_ILOG (cat, cfgst->cfg->domainId, "%s\n", bb.buf);
+
+ ddsrt_free (bb.buf);
return 0;
}
-#if WARN_DEPRECATED_ALIAS || WARN_DEPRECATED_UNIT
-static void cfg_warning(struct cfgst *cfgst, const char *fmt, ...)
+static void cfg_warning (struct cfgst *cfgst, const char *fmt, ...)
{
va_list ap;
size_t bsz = 0;
do {
- va_start(ap, fmt);
- bsz = cfg_note(cfgst, DDS_LC_WARNING, bsz, fmt, ap);
- va_end(ap);
- } while ( bsz > 0 );
+ va_start (ap, fmt);
+ bsz = cfg_note (cfgst, DDS_LC_WARNING, bsz, fmt, "", ap);
+ va_end (ap);
+ } while (bsz > 0);
}
-#endif
-static int cfg_error(struct cfgst *cfgst, const char *fmt, ...)
+static enum update_result cfg_error (struct cfgst *cfgst, const char *fmt, ...)
{
va_list ap;
size_t bsz = 0;
do {
- va_start(ap, fmt);
- bsz = cfg_note(cfgst, DDS_LC_ERROR, bsz, fmt, ap);
- va_end(ap);
- } while ( bsz > 0 );
- return 0;
+ va_start (ap, fmt);
+ bsz = cfg_note (cfgst, DDS_LC_ERROR, bsz, fmt, "", ap);
+ va_end (ap);
+ } while (bsz > 0);
+ return URES_ERROR;
}
-static int cfg_log(struct cfgst *cfgst, const char *fmt, ...)
+static void cfg_logelem (struct cfgst *cfgst, uint32_t sources, const char *fmt, ...)
{
+ /* 89 = 1 + 2 + 31 + 1 + 10 + 2*22: the number of characters in
+ a string formed by concatenating all numbers from 0 .. 31 in decimal notation,
+ 31 separators, a opening and closing brace pair, a terminating 0, and a leading
+ space */
+ char srcinfo[89];
va_list ap;
size_t bsz = 0;
+ srcinfo[0] = ' ';
+ srcinfo[1] = '{';
+ int pos = 2;
+ for (uint32_t i = 0, m = 1; i < 32; i++, m <<= 1)
+ if (sources & m)
+ pos += snprintf (srcinfo + pos, sizeof (srcinfo) - (size_t) pos, "%s%"PRIu32, (pos == 2) ? "" : ",", i);
+ srcinfo[pos] = '}';
+ srcinfo[pos + 1] = 0;
+ assert ((size_t) pos <= sizeof (srcinfo) - 2);
do {
- va_start(ap, fmt);
- bsz = cfg_note(cfgst, DDS_LC_CONFIG, bsz, fmt, ap);
- va_end(ap);
- } while ( bsz > 0 );
- return 0;
+ va_start (ap, fmt);
+ bsz = cfg_note (cfgst, DDS_LC_CONFIG, bsz, fmt, srcinfo, ap);
+ va_end (ap);
+ } while (bsz > 0);
}
-static int list_index(const char *list[], const char *elem)
+static int list_index (const char *list[], const char *elem)
{
- int i;
- for ( i = 0; list[i] != NULL; i++ ) {
- if ( ddsrt_strcasecmp(list[i], elem) == 0 )
+ for (int i = 0; list[i] != NULL; i++)
+ if (ddsrt_strcasecmp (list[i], elem) == 0)
return i;
- }
return -1;
}
-static int64_t lookup_multiplier(struct cfgst *cfgst, const struct unit *unittab, const char *value, int unit_pos, int value_is_zero, int64_t def_mult, int err_on_unrecognised)
+static int64_t lookup_multiplier (struct cfgst *cfgst, const struct unit *unittab, const char *value, int unit_pos, int value_is_zero, int64_t def_mult, int err_on_unrecognised)
{
- assert(0 <= unit_pos && (size_t) unit_pos <= strlen(value));
- while ( value[unit_pos] == ' ' )
+ assert (0 <= unit_pos && (size_t) unit_pos <= strlen(value));
+ while (value[unit_pos] == ' ')
unit_pos++;
- if ( value[unit_pos] == 0 ) {
- if ( value_is_zero ) {
+ if (value[unit_pos] == 0)
+ {
+ if (value_is_zero) {
/* No matter what unit, 0 remains just that. For convenience,
always allow 0 to be specified without a unit */
return 1;
- } else if ( def_mult == 0 && err_on_unrecognised ) {
- cfg_error(cfgst, "%s: unit is required", value);
+ } else if (def_mult == 0 && err_on_unrecognised) {
+ cfg_error (cfgst, "%s: unit is required", value);
return 0;
} else {
-#if WARN_DEPRECATED_UNIT
- cfg_warning(cfgst, "%s: use of default unit is deprecated", value);
-#endif
+ cfg_warning (cfgst, "%s: use of default unit is deprecated", value);
return def_mult;
}
- } else {
- int i;
- for ( i = 0; unittab[i].name != NULL; i++ ) {
- if ( strcmp(unittab[i].name, value + unit_pos) == 0 )
+ }
+ else
+ {
+ for (int i = 0; unittab[i].name != NULL; i++)
+ if (strcmp(unittab[i].name, value + unit_pos) == 0)
return unittab[i].multiplier;
- }
- if ( err_on_unrecognised )
+ if (err_on_unrecognised)
cfg_error(cfgst, "%s: unrecognised unit", value + unit_pos);
return 0;
}
}
-static void *cfg_address(UNUSED_ARG(struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem)
+static void *cfg_address (UNUSED_ARG (struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem)
{
- assert(cfgelem->multiplicity == 1);
+ assert (cfgelem->multiplicity <= 1);
return (char *) parent + cfgelem->elem_offset;
}
-static void *cfg_deref_address(UNUSED_ARG(struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem)
+static void *cfg_deref_address (UNUSED_ARG (struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem)
{
- assert(cfgelem->multiplicity != 1);
+ assert (cfgelem->multiplicity > 1);
return *((void **) ((char *) parent + cfgelem->elem_offset));
}
-static void *if_common(UNUSED_ARG(struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem, unsigned size)
+static void *if_common (UNUSED_ARG (struct cfgst *cfgst), void *parent, struct cfgelem const * const cfgelem, unsigned size)
{
struct config_listelem **current = (struct config_listelem **) ((char *) parent + cfgelem->elem_offset);
- struct config_listelem *new = ddsrt_malloc(size);
+ struct config_listelem *new = ddsrt_malloc (size);
new->next = *current;
*current = new;
return new;
}
-static int if_thread_properties(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
+static int if_thread_properties (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
{
- struct config_thread_properties_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(*new));
- if ( new == NULL )
+ struct config_thread_properties_listelem *new = if_common (cfgst, parent, cfgelem, sizeof(*new));
+ if (new == NULL)
return -1;
new->name = NULL;
return 0;
@@ -1172,8 +1242,8 @@ static int if_thread_properties(struct cfgst *cfgst, void *parent, struct cfgele
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
static int if_channel(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
{
- struct config_channel_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(*new));
- if ( new == NULL )
+ struct config_channel_listelem *new = if_common (cfgst, parent, cfgelem, sizeof(*new));
+ if (new == NULL)
return -1;
new->name = NULL;
new->channel_reader_ts = NULL;
@@ -1186,19 +1256,19 @@ static int if_channel(struct cfgst *cfgst, void *parent, struct cfgelem const *
#endif /* DDSI_INCLUDE_NETWORK_CHANNELS */
#ifdef DDSI_INCLUDE_ENCRYPTION
-static int if_security_profile(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
+static int if_security_profile (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
{
- if ( if_common(cfgst, parent, cfgelem, sizeof(struct config_securityprofile_listelem)) == NULL )
+ if (if_common (cfgst, parent, cfgelem, sizeof (struct config_securityprofile_listelem)) == NULL)
return -1;
return 0;
}
#endif /* DDSI_INCLUDE_ENCRYPTION */
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
-static int if_network_partition(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
+static int if_network_partition (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
{
- struct config_networkpartition_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(*new));
- if ( new == NULL )
+ struct config_networkpartition_listelem *new = if_common (cfgst, parent, cfgelem, sizeof(*new));
+ if (new == NULL)
return -1;
new->address_string = NULL;
#ifdef DDSI_INCLUDE_ENCRYPTION
@@ -1208,990 +1278,56 @@ static int if_network_partition(struct cfgst *cfgst, void *parent, struct cfgele
return 0;
}
-static int if_ignored_partition(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
+static int if_ignored_partition (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
{
- if ( if_common(cfgst, parent, cfgelem, sizeof(struct config_ignoredpartition_listelem)) == NULL )
+ if (if_common (cfgst, parent, cfgelem, sizeof (struct config_ignoredpartition_listelem)) == NULL)
return -1;
return 0;
}
-static int if_partition_mapping(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
+static int if_partition_mapping (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
{
- if ( if_common(cfgst, parent, cfgelem, sizeof(struct config_partitionmapping_listelem)) == NULL )
+ if (if_common (cfgst, parent, cfgelem, sizeof (struct config_partitionmapping_listelem)) == NULL)
return -1;
return 0;
}
#endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */
-static int if_peer(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
+static int if_peer (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
{
- struct config_peer_listelem *new = if_common(cfgst, parent, cfgelem, sizeof(struct config_peer_listelem));
- if ( new == NULL )
+ struct config_peer_listelem *new = if_common (cfgst, parent, cfgelem, sizeof (struct config_peer_listelem));
+ if (new == NULL)
return -1;
new->peer = NULL;
return 0;
}
-static void ff_free(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
+static void ff_free (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
{
- void **elem = cfg_address(cfgst, parent, cfgelem);
- ddsrt_free(*elem);
+ void ** const elem = cfg_address (cfgst, parent, cfgelem);
+ ddsrt_free (*elem);
}
-static int uf_boolean(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
+static void pf_nop (UNUSED_ARG (struct cfgst *cfgst), UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (uint32_t sources))
{
- static const char *vs[] = { "false", "true", NULL };
- int *elem = cfg_address(cfgst, parent, cfgelem);
- int idx = list_index(vs, value);
- if ( idx < 0 )
- return cfg_error(cfgst, "'%s': undefined value", value);
- else {
- *elem = idx;
- return 1;
- }
}
-static int uf_boolean_default (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+static enum update_result do_uint32_bitset (struct cfgst *cfgst, uint32_t *cats, const char **names, const uint32_t *codes, const char *value)
{
- static const char *vs[] = { "default", "false", "true", NULL };
- static const enum boolean_default ms[] = {
- BOOLDEF_DEFAULT, BOOLDEF_FALSE, BOOLDEF_TRUE, 0,
- };
- enum boolean_default *elem = cfg_address (cfgst, parent, cfgelem);
- int idx = list_index (vs, value);
- assert (sizeof (vs) / sizeof (*vs) == sizeof (ms) / sizeof (*ms));
- if (idx < 0)
- return cfg_error (cfgst, "'%s': undefined value", value);
- *elem = ms[idx];
- return 1;
-}
-
-#if 0
-static void pf_boolean_default (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- enum besmode *p = cfg_address (cfgst, parent, cfgelem);
- const char *str = "INVALID";
- switch (*p)
+ char *copy = ddsrt_strdup (value), *cursor = copy, *tok;
+ while ((tok = ddsrt_strsep (&cursor, ",")) != NULL)
{
- case BOOLDEF_DEFAULT: str = "default"; break;
- case BOOLDEF_FALSE: str = "false"; break;
- case BOOLDEF_TRUE: str = "true"; break;
- }
- cfg_log (cfgst, "%s%s", str, is_default ? " [def]" : "");
-}
-#endif
-
-static int do_uint32_bitset(struct cfgst *cfgst, uint32_t *cats, const char **names, const uint32_t *codes, const char *value)
-{
- char *copy = ddsrt_strdup(value), *cursor = copy, *tok;
- while ( (tok = ddsrt_strsep(&cursor, ",")) != NULL ) {
- int idx = list_index(names, tok);
- if ( idx < 0 ) {
- int ret = cfg_error(cfgst, "'%s' in '%s' undefined", tok, value);
- ddsrt_free(copy);
+ const int idx = list_index (names, tok);
+ if (idx < 0)
+ {
+ const enum update_result ret = cfg_error (cfgst, "'%s' in '%s' undefined", tok, value);
+ ddsrt_free (copy);
return ret;
}
*cats |= codes[idx];
}
- ddsrt_free(copy);
- return 1;
-}
-
-static int uf_logcat(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value)
-{
- return do_uint32_bitset (cfgst, &enabled_logcats, logcat_names, logcat_codes, value);
-}
-
-static int uf_xcheck(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- uint32_t *elem = cfg_address(cfgst, parent, cfgelem);
- return do_uint32_bitset (cfgst, elem, xcheck_names, xcheck_codes, value);
-}
-
-static int uf_verbosity(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value)
-{
- static const char *vs[] = {
- "finest", "finer", "fine", "config", "info", "warning", "severe", "none", NULL
- };
- static const uint32_t lc[] = {
- DDS_LC_ALL, DDS_LC_TRAFFIC | DDS_LC_TIMING, DDS_LC_DISCOVERY | DDS_LC_THROTTLE, DDS_LC_CONFIG, DDS_LC_INFO, DDS_LC_WARNING, DDS_LC_ERROR | DDS_LC_FATAL, 0, 0
- };
- int idx = list_index(vs, value);
- assert(sizeof(vs) / sizeof(*vs) == sizeof(lc) / sizeof(*lc));
- if ( idx < 0 )
- return cfg_error(cfgst, "'%s': undefined value", value);
- else {
- int i;
- for ( i = (int) (sizeof(vs) / sizeof(*vs)) - 1; i >= idx; i-- )
- enabled_logcats |= lc[i];
- return 1;
- }
-}
-
-static int uf_besmode(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value)
-{
- static const char *vs[] = {
- "full", "writers", "minimal", NULL
- };
- static const enum besmode ms[] = {
- BESMODE_FULL, BESMODE_WRITERS, BESMODE_MINIMAL, 0,
- };
- int idx = list_index(vs, value);
- enum besmode *elem = cfg_address(cfgst, parent, cfgelem);
- assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms));
- if ( idx < 0 )
- return cfg_error(cfgst, "'%s': undefined value", value);
- *elem = ms[idx];
- return 1;
-}
-
-static void pf_besmode(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- enum besmode *p = cfg_address(cfgst, parent, cfgelem);
- const char *str = "INVALID";
- switch ( *p ) {
- case BESMODE_FULL: str = "full"; break;
- case BESMODE_WRITERS: str = "writers"; break;
- case BESMODE_MINIMAL: str = "minimal"; break;
- }
- cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : "");
-}
-
-#ifdef DDSI_INCLUDE_SSL
-static int uf_min_tls_version(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value)
-{
- static const char *vs[] = {
- "1.2", "1.3", NULL
- };
- static const struct ssl_min_version ms[] = {
- {1,2}, {1,3}, {0,0}
- };
- int idx = list_index(vs, value);
- struct ssl_min_version *elem = cfg_address(cfgst, parent, cfgelem);
- assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms));
- if ( idx < 0 )
- return cfg_error(cfgst, "'%s': undefined value", value);
- *elem = ms[idx];
- return 1;
-}
-
-static void pf_min_tls_version(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- struct ssl_min_version *p = cfg_address(cfgst, parent, cfgelem);
- cfg_log(cfgst, "%d.%d%s", p->major, p->minor, is_default ? " [def]" : "");
-}
-#endif
-
-static int uf_retransmit_merging(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value)
-{
- static const char *vs[] = {
- "never", "adaptive", "always", NULL
- };
- static const enum retransmit_merging ms[] = {
- REXMIT_MERGE_NEVER, REXMIT_MERGE_ADAPTIVE, REXMIT_MERGE_ALWAYS, 0,
- };
- int idx = list_index(vs, value);
- enum retransmit_merging *elem = cfg_address(cfgst, parent, cfgelem);
- assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms));
- if ( idx < 0 )
- return cfg_error(cfgst, "'%s': undefined value", value);
- *elem = ms[idx];
- return 1;
-}
-
-static void pf_retransmit_merging(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- enum retransmit_merging *p = cfg_address(cfgst, parent, cfgelem);
- const char *str = "INVALID";
- switch ( *p ) {
- case REXMIT_MERGE_NEVER: str = "never"; break;
- case REXMIT_MERGE_ADAPTIVE: str = "adaptive"; break;
- case REXMIT_MERGE_ALWAYS: str = "always"; break;
- }
- cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : "");
-}
-
-static int uf_string(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- char **elem = cfg_address(cfgst, parent, cfgelem);
- *elem = ddsrt_strdup(value);
- return 1;
-}
-
-DDSRT_WARNING_MSVC_OFF(4996);
-static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *value, const struct unit *unittab, int64_t def_mult, int64_t min, int64_t max)
-{
- int pos;
- double v_dbl;
- int64_t v_int;
- int64_t mult;
- /* try convert as integer + optional unit; if that fails, try
- floating point + optional unit (round, not truncate, to integer) */
- if ( *value == 0 ) {
- *elem = 0; /* some static analyzers don't "get it" */
- return cfg_error(cfgst, "%s: empty string is not a valid value", value);
- } else if ( sscanf(value, "%lld%n", (long long int *) &v_int, &pos) == 1 && (mult = lookup_multiplier(cfgst, unittab, value, pos, v_int == 0, def_mult, 0)) != 0 ) {
- assert(mult > 0);
- if ( v_int < 0 || v_int > max / mult || mult * v_int < min)
- return cfg_error(cfgst, "%s: value out of range", value);
- *elem = mult * v_int;
- return 1;
- } else if ( sscanf(value, "%lf%n", &v_dbl, &pos) == 1 && (mult = lookup_multiplier(cfgst, unittab, value, pos, v_dbl == 0, def_mult, 1)) != 0 ) {
- double dmult = (double) mult;
- assert(dmult > 0);
- if ( (int64_t) (v_dbl * dmult + 0.5) < min || (int64_t) (v_dbl * dmult + 0.5) > max )
- return cfg_error(cfgst, "%s: value out of range", value);
- *elem = (int64_t) (v_dbl * dmult + 0.5);
- return 1;
- } else {
- *elem = 0; /* some static analyzers don't "get it" */
- return cfg_error(cfgst, "%s: invalid value", value);
- }
-}
-DDSRT_WARNING_MSVC_ON(4996);
-
-#ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING
-static int uf_bandwidth(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- int64_t bandwidth_bps = 0;
- if ( strncmp(value, "inf", 3) == 0 ) {
- /* special case: inf needs no unit */
- int *elem = cfg_address(cfgst, parent, cfgelem);
- if ( strspn(value + 3, " ") != strlen(value + 3) &&
- lookup_multiplier(cfgst, unittab_bandwidth_bps, value, 3, 1, 8, 1) == 0 )
- return 0;
- *elem = 0;
- return 1;
- } else if ( !uf_natint64_unit(cfgst, &bandwidth_bps, value, unittab_bandwidth_bps, 8, INT64_MAX) ) {
- return 0;
- } else if ( bandwidth_bps / 8 > INT_MAX ) {
- return cfg_error(cfgst, "%s: value out of range", value);
- } else {
- uint32_t *elem = cfg_address(cfgst, parent, cfgelem);
- *elem = (uint32_t) (bandwidth_bps / 8);
- return 1;
- }
-}
-#endif
-
-static int uf_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- int64_t size = 0;
- if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) )
- return 0;
- else {
- uint32_t *elem = cfg_address(cfgst, parent, cfgelem);
- *elem = (uint32_t) size;
- return 1;
- }
-}
-
-#ifdef DDSI_INCLUDE_ENCRYPTION
-static int uf_cipher(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- if ( q_security_plugin.cipher_type_from_string ) {
- q_cipherType *elem = cfg_address(cfgst, parent, cfgelem);
- if ( (q_security_plugin.cipher_type_from_string) (value, elem) ) {
- return 1;
- } else {
- return cfg_error(cfgst, "%s: undefined value", value);
- }
- }
- return 1;
-}
-#endif /* DDSI_INCLUDE_ENCRYPTION */
-
-
-static int uf_tracingOutputFileName(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value)
-{
- struct config *cfg = cfgst->cfg;
- {
- cfg->tracingOutputFileName = ddsrt_strdup(value);
- }
- return 1;
-}
-
-static int uf_ipv4(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
-{
- /* Not actually doing any checking yet */
- return uf_string(cfgst, parent, cfgelem, first, value);
-}
-
-static int uf_networkAddress(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
-{
- if ( ddsrt_strcasecmp(value, "auto") != 0 )
- return uf_ipv4(cfgst, parent, cfgelem, first, value);
- else {
- char **elem = cfg_address(cfgst, parent, cfgelem);
- *elem = NULL;
- return 1;
- }
-}
-
-static void ff_networkAddresses(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
-{
- char ***elem = cfg_address(cfgst, parent, cfgelem);
- int i;
- for ( i = 0; (*elem)[i]; i++ )
- ddsrt_free((*elem)[i]);
- ddsrt_free(*elem);
-}
-
-static int uf_networkAddresses_simple(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- char ***elem = cfg_address(cfgst, parent, cfgelem);
- if ( (*elem = ddsrt_malloc(2 * sizeof(char *))) == NULL )
- return cfg_error(cfgst, "out of memory");
- if ( ((*elem)[0] = ddsrt_strdup(value)) == NULL ) {
- ddsrt_free(*elem);
- *elem = NULL;
- return cfg_error(cfgst, "out of memory");
- }
- (*elem)[1] = NULL;
- return 1;
-}
-
-static int uf_networkAddresses(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
-{
- /* Check for keywords first */
- {
- static const char *keywords[] = { "all", "any", "none" };
- int i;
- for ( i = 0; i < (int) (sizeof(keywords) / sizeof(*keywords)); i++ ) {
- if ( ddsrt_strcasecmp(value, keywords[i]) == 0 )
- return uf_networkAddresses_simple(cfgst, parent, cfgelem, first, keywords[i]);
- }
- }
-
- /* If not keyword, then comma-separated list of addresses */
- {
- char ***elem = cfg_address(cfgst, parent, cfgelem);
- char *copy;
- unsigned count;
-
- /* First count how many addresses we have - but do it stupidly by
- counting commas and adding one (so two commas in a row are both
- counted) */
- {
- const char *scan = value;
- count = 1;
- while ( *scan )
- count += (*scan++ == ',');
- }
-
- copy = ddsrt_strdup(value);
-
- /* Allocate an array of address strings (which may be oversized a
- bit because of the counting of the commas) */
- *elem = ddsrt_malloc((count + 1) * sizeof(char *));
-
- {
- char *cursor = copy, *tok;
- unsigned idx = 0;
- while ( (tok = ddsrt_strsep(&cursor, ",")) != NULL ) {
- assert(idx < count);
- (*elem)[idx] = ddsrt_strdup(tok);
- idx++;
- }
- (*elem)[idx] = NULL;
- }
- ddsrt_free(copy);
- }
- return 1;
-}
-
-static int uf_allow_multicast(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
-#ifdef DDSI_INCLUDE_SSM
- static const char *vs[] = { "false", "spdp", "asm", "ssm", "true", NULL };
- static const unsigned bs[] = { AMC_FALSE, AMC_SPDP, AMC_ASM, AMC_SSM, AMC_TRUE };
-#else
- static const char *vs[] = { "false", "spdp", "asm", "true", NULL };
- static const unsigned bs[] = { AMC_FALSE, AMC_SPDP, AMC_ASM, AMC_TRUE };
-#endif
- char *copy = ddsrt_strdup(value), *cursor = copy, *tok;
- unsigned *elem = cfg_address(cfgst, parent, cfgelem);
- if ( copy == NULL )
- return cfg_error(cfgst, "out of memory");
- *elem = 0;
- while ( (tok = ddsrt_strsep(&cursor, ",")) != NULL ) {
- int idx = list_index(vs, tok);
- if ( idx < 0 ) {
- int ret = cfg_error(cfgst, "'%s' in '%s' undefined", tok, value);
- ddsrt_free(copy);
- return ret;
- }
- *elem |= bs[idx];
- }
- ddsrt_free(copy);
- return 1;
-}
-
-static void pf_allow_multicast(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- unsigned *p = cfg_address(cfgst, parent, cfgelem);
- const char *str = "INVALID";
- switch ( *p ) {
- case AMC_FALSE: str = "false"; break;
- case AMC_SPDP: str = "spdp"; break;
- case AMC_ASM: str = "asm"; break;
-#ifdef DDSI_INCLUDE_SSM
- case AMC_SSM: str = "ssm"; break;
- case (AMC_SPDP | AMC_ASM): str = "spdp,asm"; break;
- case (AMC_SPDP | AMC_SSM): str = "spdp,ssm"; break;
-#endif
- case AMC_TRUE: str = "true"; break;
- }
- cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : "");
-}
-
-static int uf_sched_class(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- static const char *vs[] = { "realtime", "timeshare", "default" };
- static const ddsrt_sched_t ms[] = { DDSRT_SCHED_REALTIME, DDSRT_SCHED_TIMESHARE, DDSRT_SCHED_DEFAULT };
- int idx = list_index(vs, value);
- ddsrt_sched_t *elem = cfg_address(cfgst, parent, cfgelem);
- assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms));
- if ( idx < 0 )
- return cfg_error(cfgst, "'%s': undefined value", value);
- *elem = ms[idx];
- return 1;
-}
-
-static void pf_sched_class(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- ddsrt_sched_t *p = cfg_address(cfgst, parent, cfgelem);
- const char *str = "INVALID";
- switch ( *p ) {
- case DDSRT_SCHED_DEFAULT: str = "default"; break;
- case DDSRT_SCHED_TIMESHARE: str = "timeshare"; break;
- case DDSRT_SCHED_REALTIME: str = "realtime"; break;
- }
- cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : "");
-}
-
-DDSRT_WARNING_MSVC_OFF(4996);
-static int uf_maybe_int32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- struct config_maybe_int32 *elem = cfg_address(cfgst, parent, cfgelem);
- int pos;
- if ( ddsrt_strcasecmp(value, "default") == 0 ) {
- elem->isdefault = 1;
- elem->value = 0;
- return 1;
- } else if ( sscanf(value, "%"PRId32"%n", &elem->value, &pos) == 1 && value[pos] == 0 ) {
- elem->isdefault = 0;
- return 1;
- } else {
- return cfg_error(cfgst, "'%s': neither 'default' nor a decimal integer\n", value);
- }
-}
-DDSRT_WARNING_MSVC_ON(4996);
-
-static int uf_maybe_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- struct config_maybe_uint32 *elem = cfg_address(cfgst, parent, cfgelem);
- int64_t size = 0;
- if ( ddsrt_strcasecmp(value, "default") == 0 ) {
- elem->isdefault = 1;
- elem->value = 0;
- return 1;
- } else if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) ) {
- return 0;
- } else {
- elem->isdefault = 0;
- elem->value = (uint32_t) size;
- return 1;
- }
-}
-
-static int uf_int(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- int *elem = cfg_address(cfgst, parent, cfgelem);
- char *endptr;
- long v = strtol(value, &endptr, 10);
- if ( *value == 0 || *endptr != 0 )
- return cfg_error(cfgst, "%s: not a decimal integer", value);
- if ( v != (int) v )
- return cfg_error(cfgst, "%s: value out of range", value);
- *elem = (int) v;
- return 1;
-}
-
-static int uf_duration_gen(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, const char *value, int64_t def_mult, int64_t min_ns, int64_t max_ns)
-{
- return uf_natint64_unit(cfgst, cfg_address(cfgst, parent, cfgelem), value, unittab_duration, def_mult, min_ns, max_ns);
-}
-
-static int uf_duration_inf(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- if ( ddsrt_strcasecmp(value, "inf") == 0 ) {
- int64_t *elem = cfg_address(cfgst, parent, cfgelem);
- *elem = T_NEVER;
- return 1;
- } else {
- return uf_duration_gen(cfgst, parent, cfgelem, value, 0, 0, T_NEVER - 1);
- }
-}
-
-static int uf_duration_ms_1hr(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 0, 3600 * T_SECOND);
-}
-
-static int uf_duration_ms_1s(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 0, T_SECOND);
-}
-
-static int uf_duration_us_1s(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- return uf_duration_gen(cfgst, parent, cfgelem, value, 1000, 0, T_SECOND);
-}
-
-static int uf_duration_100ms_1hr(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- return uf_duration_gen(cfgst, parent, cfgelem, value, 0, 100 * T_MILLISECOND, 3600 * T_SECOND);
-}
-
-#if 0
-static int uf_int32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- int32_t *elem = cfg_address(cfgst, parent, cfgelem);
- char *endptr;
- long v = strtol(value, &endptr, 10);
- if ( *value == 0 || *endptr != 0 )
- return cfg_error(cfgst, "%s: not a decimal integer", value);
- if ( v != (int32_t) v )
- return cfg_error(cfgst, "%s: value out of range", value);
- *elem = (int32_t) v;
- return 1;
-}
-#endif
-
-#if 0
-static int uf_uint32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- uint32_t *elem = cfg_address(cfgst, parent, cfgelem);
- char *endptr;
- unsigned long v = strtoul(value, &endptr, 10);
- if ( *value == 0 || *endptr != 0 )
- return cfg_error(cfgst, "%s: not a decimal integer", value);
- if ( v != (uint32_t) v )
- return cfg_error(cfgst, "%s: value out of range", value);
- *elem = (uint32_t) v;
- return 1;
-}
-#endif
-
-static int uf_uint(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- unsigned *elem = cfg_address(cfgst, parent, cfgelem);
- char *endptr;
- unsigned long v = strtoul(value, &endptr, 10);
- if ( *value == 0 || *endptr != 0 )
- return cfg_error(cfgst, "%s: not a decimal integer", value);
- if ( v != (unsigned) v )
- return cfg_error(cfgst, "%s: value out of range", value);
- *elem = (unsigned) v;
- return 1;
-}
-
-static int uf_int_min_max(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value, int min, int max)
-{
- int *elem = cfg_address(cfgst, parent, cfgelem);
- if ( !uf_int(cfgst, parent, cfgelem, first, value) )
- return 0;
- else if ( *elem < min || *elem > max )
- return cfg_error(cfgst, "%s: out of range", value);
- else
- return 1;
-}
-
-DDSRT_WARNING_MSVC_OFF(4996);
-static int uf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- struct config_maybe_int32 *elem = cfg_address(cfgst, parent, cfgelem);
- int pos;
- if (ddsrt_strcasecmp(value, "any") == 0) {
- elem->isdefault = 1;
- elem->value = 0;
- return 1;
- } else if (sscanf(value, "%"PRId32"%n", &elem->value, &pos) == 1 && value[pos] == 0 && elem->value >= 0 && elem->value <= 230) {
- elem->isdefault = 0;
- return 1;
- } else {
- return cfg_error(cfgst, "'%s': neither 'any' nor a decimal integer in 0 .. 230\n", value);
- }
-}
-DDSRT_WARNING_MSVC_ON(4996);
-
-static int uf_participantIndex(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
-{
- int *elem = cfg_address(cfgst, parent, cfgelem);
- if ( ddsrt_strcasecmp(value, "auto") == 0 ) {
- *elem = PARTICIPANT_INDEX_AUTO;
- return 1;
- } else if ( ddsrt_strcasecmp(value, "none") == 0 ) {
- *elem = PARTICIPANT_INDEX_NONE;
- return 1;
- } else {
- return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, 120);
- }
-}
-
-static int uf_port(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
-{
- return uf_int_min_max(cfgst, parent, cfgelem, first, value, 1, 65535);
-}
-
-static int uf_dyn_port(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
-{
- return uf_int_min_max(cfgst, parent, cfgelem, first, value, -1, 65535);
-}
-
-static int uf_natint(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
-{
- return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, INT32_MAX);
-}
-
-static int uf_natint_255(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
-{
- return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, 255);
-}
-
-static int uf_transport_selector (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
-{
- static const char *vs[] = { "default", "udp", "udp6", "tcp", "tcp6", "raweth", NULL };
- static const enum transport_selector ms[] = {
- TRANS_DEFAULT, TRANS_UDP, TRANS_UDP6, TRANS_TCP, TRANS_TCP6, TRANS_RAWETH, 0,
- };
- enum transport_selector *elem = cfg_address (cfgst, parent, cfgelem);
- int idx = list_index (vs, value);
- assert (sizeof (vs) / sizeof (*vs) == sizeof (ms) / sizeof (*ms));
- if (idx < 0)
- return cfg_error (cfgst, "'%s': undefined value", value);
- *elem = ms[idx];
- return 1;
-}
-
-static void pf_transport_selector (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- enum transport_selector *p = cfg_address (cfgst, parent, cfgelem);
- const char *str = "INVALID";
- switch (*p)
- {
- case TRANS_DEFAULT: str = "default"; break;
- case TRANS_UDP: str = "udp"; break;
- case TRANS_UDP6: str = "udp6"; break;
- case TRANS_TCP: str = "tcp"; break;
- case TRANS_TCP6: str = "tcp6"; break;
- case TRANS_RAWETH: str = "raweth"; break;
- }
- cfg_log (cfgst, "%s%s", str, is_default ? " [def]" : "");
-}
-
-static int uf_many_sockets_mode (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
-{
- static const char *vs[] = { "false", "true", "single", "none", "many", NULL };
- static const enum many_sockets_mode ms[] = {
- MSM_SINGLE_UNICAST, MSM_MANY_UNICAST, MSM_SINGLE_UNICAST, MSM_NO_UNICAST, MSM_MANY_UNICAST, 0,
- };
- enum many_sockets_mode *elem = cfg_address (cfgst, parent, cfgelem);
- int idx = list_index (vs, value);
- assert (sizeof (vs) / sizeof (*vs) == sizeof (ms) / sizeof (*ms));
- if (idx < 0)
- return cfg_error (cfgst, "'%s': undefined value", value);
- *elem = ms[idx];
- return 1;
-}
-
-static void pf_many_sockets_mode (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- enum many_sockets_mode *p = cfg_address (cfgst, parent, cfgelem);
- const char *str = "INVALID";
- switch (*p)
- {
- case MSM_SINGLE_UNICAST: str = "single"; break;
- case MSM_MANY_UNICAST: str = "many"; break;
- case MSM_NO_UNICAST: str = "none"; break;
- }
- cfg_log (cfgst, "%s%s", str, is_default ? " [def]" : "");
-}
-
-static int uf_deaf_mute (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
-{
- return uf_boolean (cfgst, parent, cfgelem, first, value);
-}
-
-static int do_update(struct cfgst *cfgst, update_fun_t upd, void *parent, struct cfgelem const * const cfgelem, const char *value, int is_default)
-{
- struct cfgst_node *n;
- struct cfgst_nodekey key;
- ddsrt_avl_ipath_t np;
- int ok;
- key.e = cfgelem;
- if ( (n = ddsrt_avl_lookup_ipath(&cfgst_found_treedef, &cfgst->found, &key, &np)) == NULL ) {
- if ( (n = ddsrt_malloc(sizeof(*n))) == NULL )
- return cfg_error(cfgst, "out of memory");
-
- n->key = key;
- n->count = 0;
- n->failed = 0;
- n->is_default = is_default;
- ddsrt_avl_insert_ipath(&cfgst_found_treedef, &cfgst->found, n, &np);
- }
- if ( cfgelem->multiplicity == 0 || n->count < cfgelem->multiplicity )
- ok = upd(cfgst, parent, cfgelem, (n->count == n->failed), value);
- else
- ok = cfg_error(cfgst, "only %d instance%s allowed", cfgelem->multiplicity, (cfgelem->multiplicity == 1) ? "" : "s");
- n->count++;
- if ( !ok ) {
- n->failed++;
- }
- return ok;
-}
-
-static int set_default(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
-{
- if ( cfgelem->defvalue == NULL )
- return cfg_error(cfgst, "element missing in configuration");
- return do_update(cfgst, cfgelem->update, parent, cfgelem, cfgelem->defvalue, 1);
-}
-
-static int set_defaults(struct cfgst *cfgst, void *parent, int isattr, struct cfgelem const * const cfgelem, int clear_found)
-{
- const struct cfgelem *ce;
- int ok = 1;
- for ( ce = cfgelem; ce && ce->name; ce++ ) {
- struct cfgst_node *n;
- struct cfgst_nodekey key;
- key.e = ce;
- cfgst_push(cfgst, isattr, ce, parent);
- if ( ce->multiplicity == 1 ) {
- if ( ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key) == NULL ) {
- if ( ce->update ) {
- int ok1;
- cfgst_push(cfgst, 0, NULL, NULL);
- ok1 = set_default(cfgst, parent, ce);
- cfgst_pop(cfgst);
- ok = ok && ok1;
- }
- }
- if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) {
- if ( clear_found ) {
- ddsrt_avl_delete(&cfgst_found_treedef, &cfgst->found, n);
- ddsrt_free(n);
- }
- }
- if ( ce->children ) {
- int ok1 = set_defaults(cfgst, parent, 0, ce->children, clear_found);
- ok = ok && ok1;
- }
- if ( ce->attributes ) {
- int ok1 = set_defaults(cfgst, parent, 1, ce->attributes, clear_found);
- ok = ok && ok1;
- }
- }
- cfgst_pop(cfgst);
- }
- return ok;
-}
-
-static void pf_nop(UNUSED_ARG(struct cfgst *cfgst), UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int is_default))
-{
-}
-
-static void pf_string(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- char **p = cfg_address(cfgst, parent, cfgelem);
- cfg_log(cfgst, "%s%s", *p ? *p : "(null)", is_default ? " [def]" : "");
-}
-
-static void pf_int64_unit(struct cfgst *cfgst, int64_t value, int is_default, const struct unit *unittab, const char *zero_unit)
-{
- if ( value == 0 ) {
- /* 0s is a bit of a special case: we don't want to print 0hr (or
- whatever unit will have the greatest multiplier), so hard-code
- as 0s */
- cfg_log(cfgst, "0 %s%s", zero_unit, is_default ? " [def]" : "");
- } else {
- int64_t m = 0;
- const char *unit = NULL;
- int i;
- for ( i = 0; unittab[i].name != NULL; i++ ) {
- if ( unittab[i].multiplier > m && (value % unittab[i].multiplier) == 0 ) {
- m = unittab[i].multiplier;
- unit = unittab[i].name;
- }
- }
- assert(m > 0);
- assert(unit != NULL);
- cfg_log(cfgst, "%lld %s%s", value / m, unit, is_default ? " [def]" : "");
- }
-}
-
-#ifdef DDSI_INCLUDE_ENCRYPTION
-static void pf_key(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int is_default))
-{
- cfg_log(cfgst, "");
-}
-
-static void pf_cipher(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- q_cipherType *p = cfg_address(cfgst, parent, cfgelem);
- if ( q_security_plugin.cipher_type ) {
- cfg_log(cfgst, "%s%s", (q_security_plugin.cipher_type) (*p), is_default ? " [def]" : "");
- }
-}
-#endif /* DDSI_INCLUDE_ENCRYPTION */
-
-static void pf_networkAddress(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- char **p = cfg_address(cfgst, parent, cfgelem);
- cfg_log(cfgst, "%s%s", *p ? *p : "auto", is_default ? " [def]" : "");
-}
-
-static void pf_participantIndex(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- int *p = cfg_address(cfgst, parent, cfgelem);
- switch ( *p ) {
- case PARTICIPANT_INDEX_NONE:
- cfg_log(cfgst, "none%s", is_default ? " [def]" : "");
- break;
- case PARTICIPANT_INDEX_AUTO:
- cfg_log(cfgst, "auto%s", is_default ? " [def]" : "");
- break;
- default:
- cfg_log(cfgst, "%d%s", *p, is_default ? " [def]" : "");
- break;
- }
-}
-
-static void pf_networkAddresses(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- int i;
- char ***p = cfg_address(cfgst, parent, cfgelem);
- for ( i = 0; (*p)[i] != NULL; i++ )
- cfg_log(cfgst, "%s%s", (*p)[i], is_default ? " [def]" : "");
-}
-
-static void pf_int(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- int *p = cfg_address(cfgst, parent, cfgelem);
- cfg_log(cfgst, "%d%s", *p, is_default ? " [def]" : "");
-}
-
-static void pf_uint(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- unsigned *p = cfg_address(cfgst, parent, cfgelem);
- cfg_log(cfgst, "%u%s", *p, is_default ? " [def]" : "");
-}
-
-static void pf_duration(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- const int64_t *elem = cfg_address(cfgst, parent, cfgelem);
- if ( *elem == T_NEVER )
- cfg_log(cfgst, "inf%s", is_default ? " [def]" : "");
- else
- pf_int64_unit(cfgst, *elem, is_default, unittab_duration, "s");
-}
-
-#ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING
-static void pf_bandwidth(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- const uint32_t *elem = cfg_address(cfgst, parent, cfgelem);
- if ( *elem == 0 )
- cfg_log(cfgst, "inf%s", is_default ? " [def]" : "");
- else
- pf_int64_unit(cfgst, *elem, is_default, unittab_bandwidth_Bps, "B/s");
-}
-#endif
-
-static void pf_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- const int *elem = cfg_address(cfgst, parent, cfgelem);
- pf_int64_unit(cfgst, *elem, is_default, unittab_memsize, "B");
-}
-
-#if 0
-static void pf_int32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- int32_t *p = cfg_address(cfgst, parent, cfgelem);
- cfg_log(cfgst, "%d%s", *p, is_default ? " [def]" : "");
-}
-#endif
-
-#if 0
-static void pf_uint32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- uint32_t *p = cfg_address(cfgst, parent, cfgelem);
- cfg_log(cfgst, "%u%s", *p, is_default ? " [def]" : "");
-}
-#endif
-
-static void pf_maybe_int32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- struct config_maybe_int32 *p = cfg_address(cfgst, parent, cfgelem);
- if ( p->isdefault )
- cfg_log(cfgst, "default%s", is_default ? " [def]" : "");
- else
- cfg_log(cfgst, "%d%s", p->value, is_default ? " [def]" : "");
-}
-
-static void pf_maybe_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- struct config_maybe_uint32 *p = cfg_address(cfgst, parent, cfgelem);
- if ( p->isdefault )
- cfg_log(cfgst, "default%s", is_default ? " [def]" : "");
- else
- pf_int64_unit(cfgst, p->value, is_default, unittab_memsize, "B");
-}
-
-static void pf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- struct config_maybe_int32 *p = cfg_address(cfgst, parent, cfgelem);
- if ( p->isdefault )
- cfg_log(cfgst, "any (%d)%s", p->value, is_default ? " [def]" : "");
- else
- cfg_log(cfgst, "%d%s", p->value, is_default ? " [def]" : "");
-}
-
-static void pf_boolean(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- int *p = cfg_address(cfgst, parent, cfgelem);
- cfg_log(cfgst, "%s%s", *p ? "true" : "false", is_default ? " [def]" : "");
-}
-
-static int uf_standards_conformance(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
-{
- static const char *vs[] = {
- "pedantic", "strict", "lax", NULL
- };
- static const uint32_t lc[] = {
- NN_SC_PEDANTIC, NN_SC_STRICT, NN_SC_LAX, 0
- };
- enum nn_standards_conformance *elem = cfg_address(cfgst, parent, cfgelem);
- int idx = list_index(vs, value);
- assert(sizeof(vs) / sizeof(*vs) == sizeof(lc) / sizeof(*lc));
- if ( idx < 0 )
- return cfg_error(cfgst, "'%s': undefined value", value);
- else {
- *elem = lc[idx];
- return 1;
- }
-}
-
-static void pf_standards_conformance(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
-{
- enum nn_standards_conformance *p = cfg_address(cfgst, parent, cfgelem);
- const char *str = "INVALID";
- switch ( *p ) {
- case NN_SC_PEDANTIC: str = "pedantic"; break;
- case NN_SC_STRICT: str = "strict"; break;
- case NN_SC_LAX: str = "lax"; break;
- }
- cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : "");
+ ddsrt_free (copy);
+ return URES_SUCCESS;
}
static unsigned uint32_popcnt (uint32_t x)
@@ -2205,376 +1341,1262 @@ static unsigned uint32_popcnt (uint32_t x)
return n;
}
-static void do_print_uint32_bitset (struct cfgst *cfgst, uint32_t mask, size_t ncodes, const char **names, const uint32_t *codes, const char *suffix)
+static void do_print_uint32_bitset (struct cfgst *cfgst, uint32_t mask, size_t ncodes, const char **names, const uint32_t *codes, uint32_t sources, const char *suffix)
{
char res[256] = "", *resp = res;
const char *prefix = "";
#ifndef NDEBUG
{
size_t max = 0;
- for (size_t i = 0; i < ncodes; i++ )
- max += 1 + strlen(names[i]);
+ for (size_t i = 0; i < ncodes; i++)
+ max += 1 + strlen (names[i]);
max += 11; /* ,0x%x */
max += 1; /* \0 */
- assert(max <= sizeof(res));
+ assert (max <= sizeof (res));
}
#endif
- while (mask) {
+ while (mask)
+ {
size_t i_best = 0;
unsigned pc_best = 0;
- for (size_t i = 0; i < ncodes; i++) {
+ for (size_t i = 0; i < ncodes; i++)
+ {
uint32_t m = mask & codes[i];
- if (m == codes[i]) {
+ if (m == codes[i])
+ {
unsigned pc = uint32_popcnt (m);
- if (pc > pc_best) {
+ if (pc > pc_best)
+ {
i_best = i;
pc_best = pc;
}
}
}
- if (pc_best != 0) {
- resp += snprintf(resp, 256, "%s%s", prefix, names[i_best]);
+ if (pc_best != 0)
+ {
+ resp += snprintf (resp, 256, "%s%s", prefix, names[i_best]);
mask &= ~codes[i_best];
prefix = ",";
- } else {
+ }
+ else
+ {
resp += snprintf (resp, 256, "%s0x%x", prefix, (unsigned) mask);
mask = 0;
}
}
- assert (resp <= res + sizeof(res));
- cfg_log (cfgst, "%s%s", res, suffix);
+ assert (resp <= res + sizeof (res));
+ cfg_logelem (cfgst, sources, "%s%s", res, suffix);
}
-static void pf_logcat(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int is_default))
+static enum update_result uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *value, const struct unit *unittab, int64_t def_mult, int64_t min, int64_t max)
{
- /* can't do default indicator: user may have specified Verbosity, in
- which case EnableCategory is at default, but for these two
- settings, I don't mind. */
- do_print_uint32_bitset (cfgst, config.enabled_logcats, sizeof(logcat_codes) / sizeof(*logcat_codes), logcat_names, logcat_codes, "");
+ DDSRT_WARNING_MSVC_OFF(4996);
+ int pos;
+ double v_dbl;
+ int64_t v_int;
+ int64_t mult;
+ /* try convert as integer + optional unit; if that fails, try
+ floating point + optional unit (round, not truncate, to integer) */
+ if (*value == 0) {
+ *elem = 0; /* some static analyzers don't "get it" */
+ return cfg_error(cfgst, "%s: empty string is not a valid value", value);
+ } else if (sscanf (value, "%lld%n", (long long int *) &v_int, &pos) == 1 && (mult = lookup_multiplier (cfgst, unittab, value, pos, v_int == 0, def_mult, 0)) != 0) {
+ assert(mult > 0);
+ if (v_int < 0 || v_int > max / mult || mult * v_int < min)
+ return cfg_error (cfgst, "%s: value out of range", value);
+ *elem = mult * v_int;
+ return URES_SUCCESS;
+ } else if (sscanf(value, "%lf%n", &v_dbl, &pos) == 1 && (mult = lookup_multiplier (cfgst, unittab, value, pos, v_dbl == 0, def_mult, 1)) != 0) {
+ double dmult = (double) mult;
+ assert (dmult > 0);
+ if ((int64_t) (v_dbl * dmult + 0.5) < min || (int64_t) (v_dbl * dmult + 0.5) > max)
+ return cfg_error(cfgst, "%s: value out of range", value);
+ *elem = (int64_t) (v_dbl * dmult + 0.5);
+ return URES_SUCCESS;
+ } else {
+ *elem = 0; /* some static analyzers don't "get it" */
+ return cfg_error (cfgst, "%s: invalid value", value);
+ }
+ DDSRT_WARNING_MSVC_ON(4996);
}
-static void pf_xcheck(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
+static void pf_int64_unit (struct cfgst *cfgst, int64_t value, uint32_t sources, const struct unit *unittab, const char *zero_unit)
{
- const uint32_t *p = cfg_address(cfgst, parent, cfgelem);
+ if (value == 0) {
+ /* 0s is a bit of a special case: we don't want to print 0hr (or
+ whatever unit will have the greatest multiplier), so hard-code
+ as 0s */
+ cfg_logelem (cfgst, sources, "0 %s", zero_unit);
+ } else {
+ int64_t m = 0;
+ const char *unit = NULL;
+ int i;
+ for (i = 0; unittab[i].name != NULL; i++)
+ {
+ if (unittab[i].multiplier > m && (value % unittab[i].multiplier) == 0)
+ {
+ m = unittab[i].multiplier;
+ unit = unittab[i].name;
+ }
+ }
+ assert (m > 0);
+ assert (unit != NULL);
+ cfg_logelem (cfgst, sources, "%lld %s", value / m, unit);
+ }
+}
+
+#define GENERIC_ENUM_CTYPE_UF(type_, c_type_) \
+ DDSRT_STATIC_ASSERT (sizeof (en_##type_##_vs) / sizeof (*en_##type_##_vs) == \
+ sizeof (en_##type_##_ms) / sizeof (*en_##type_##_ms)); \
+ \
+ static enum update_result uf_##type_ (struct cfgst *cfgst, void *parent, UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value) \
+ { \
+ const int idx = list_index (en_##type_##_vs, value); \
+ c_type_ * const elem = cfg_address (cfgst, parent, cfgelem); \
+ /* idx >= length of ms check is to shut up clang's static analyzer */ \
+ if (idx < 0 || idx >= (int) (sizeof (en_##type_##_ms) / sizeof (en_##type_##_ms[0]))) \
+ return cfg_error (cfgst, "'%s': undefined value", value); \
+ *elem = en_##type_##_ms[idx]; \
+ return URES_SUCCESS; \
+ }
+#define GENERIC_ENUM_CTYPE_PF(type_, c_type_) \
+ static void pf_##type_ (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources) \
+ { \
+ c_type_ const * const p = cfg_address (cfgst, parent, cfgelem); \
+ const char *str = "INVALID"; \
+ /* i < length of ms check is to shut up clang's static analyzer */ \
+ for (int i = 0; en_##type_##_vs[i] != NULL && i < (int) (sizeof (en_##type_##_ms) / sizeof (en_##type_##_ms[0])); i++) { \
+ if (en_##type_##_ms[i] == *p) \
+ { \
+ str = en_##type_##_vs[i]; \
+ break; \
+ } \
+ } \
+ cfg_logelem(cfgst, sources, "%s", str); \
+ }
+#define GENERIC_ENUM_CTYPE(type_, c_type_) \
+ GENERIC_ENUM_CTYPE_UF(type_, c_type_) \
+ GENERIC_ENUM_CTYPE_PF(type_, c_type_)
+#define GENERIC_ENUM_UF(type_) GENERIC_ENUM_CTYPE_UF(type_, enum type_)
+#define GENERIC_ENUM(type_) GENERIC_ENUM_CTYPE(type_, enum type_)
+
+static const char *en_boolean_vs[] = { "false", "true", NULL };
+static const int en_boolean_ms[] = { 0, 1, 0 };
+GENERIC_ENUM_CTYPE (boolean, int)
+
+static const char *en_boolean_default_vs[] = { "default", "false", "true", NULL };
+static const enum boolean_default en_boolean_default_ms[] = { BOOLDEF_DEFAULT, BOOLDEF_FALSE, BOOLDEF_TRUE, 0 };
+GENERIC_ENUM_UF (boolean_default)
+
+static const char *en_besmode_vs[] = { "full", "writers", "minimal", NULL };
+static const enum besmode en_besmode_ms[] = { BESMODE_FULL, BESMODE_WRITERS, BESMODE_MINIMAL, 0 };
+GENERIC_ENUM (besmode)
+
+static const char *en_retransmit_merging_vs[] = { "never", "adaptive", "always", NULL };
+static const enum retransmit_merging en_retransmit_merging_ms[] = { REXMIT_MERGE_NEVER, REXMIT_MERGE_ADAPTIVE, REXMIT_MERGE_ALWAYS, 0 };
+GENERIC_ENUM (retransmit_merging)
+
+static const char *en_sched_class_vs[] = { "realtime", "timeshare", "default", NULL };
+static const ddsrt_sched_t en_sched_class_ms[] = { DDSRT_SCHED_REALTIME, DDSRT_SCHED_TIMESHARE, DDSRT_SCHED_DEFAULT, 0 };
+GENERIC_ENUM_CTYPE (sched_class, ddsrt_sched_t)
+
+static const char *en_transport_selector_vs[] = { "default", "udp", "udp6", "tcp", "tcp6", "raweth", NULL };
+static const enum transport_selector en_transport_selector_ms[] = { TRANS_DEFAULT, TRANS_UDP, TRANS_UDP6, TRANS_TCP, TRANS_TCP6, TRANS_RAWETH, 0 };
+GENERIC_ENUM (transport_selector)
+
+/* by putting the "true" and "false" aliases at the end, they won't come out of the
+ generic printing function */
+static const char *en_many_sockets_mode_vs[] = { "single", "none", "many", "false", "true", NULL };
+static const enum many_sockets_mode en_many_sockets_mode_ms[] = {
+ MSM_SINGLE_UNICAST, MSM_NO_UNICAST, MSM_MANY_UNICAST, MSM_SINGLE_UNICAST, MSM_MANY_UNICAST, 0 };
+GENERIC_ENUM (many_sockets_mode)
+
+static const char *en_standards_conformance_vs[] = { "pedantic", "strict", "lax", NULL };
+static const enum nn_standards_conformance en_standards_conformance_ms[] = { NN_SC_PEDANTIC, NN_SC_STRICT, NN_SC_LAX, 0 };
+GENERIC_ENUM_CTYPE (standards_conformance, enum nn_standards_conformance)
+
+/* "trace" is special: it enables (nearly) everything */
+static const char *tracemask_names[] = {
+ "fatal", "error", "warning", "info", "config", "discovery", "data", "radmin", "timing", "traffic", "topic", "tcp", "plist", "whc", "throttle", "rhc", "trace", NULL
+};
+static const uint32_t tracemask_codes[] = {
+ DDS_LC_FATAL, DDS_LC_ERROR, DDS_LC_WARNING, DDS_LC_INFO, DDS_LC_CONFIG, DDS_LC_DISCOVERY, DDS_LC_DATA, DDS_LC_RADMIN, DDS_LC_TIMING, DDS_LC_TRAFFIC, DDS_LC_TOPIC, DDS_LC_TCP, DDS_LC_PLIST, DDS_LC_WHC, DDS_LC_THROTTLE, DDS_LC_RHC, DDS_LC_ALL
+};
+
+static enum update_result uf_tracemask (struct cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value)
+{
+ return do_uint32_bitset (cfgst, &cfgst->cfg->tracemask, tracemask_names, tracemask_codes, value);
+}
+
+static enum update_result uf_verbosity (struct cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value)
+{
+ static const char *vs[] = {
+ "finest", "finer", "fine", "config", "info", "warning", "severe", "none", NULL
+ };
+ static const uint32_t lc[] = {
+ DDS_LC_ALL, DDS_LC_TRAFFIC | DDS_LC_TIMING, DDS_LC_DISCOVERY | DDS_LC_THROTTLE, DDS_LC_CONFIG, DDS_LC_INFO, DDS_LC_WARNING, DDS_LC_ERROR | DDS_LC_FATAL, 0, 0
+ };
+ const int idx = list_index (vs, value);
+ assert (sizeof (vs) / sizeof (*vs) == sizeof (lc) / sizeof (*lc));
+ if (idx < 0)
+ return cfg_error (cfgst, "'%s': undefined value", value);
+ for (int i = (int) (sizeof (vs) / sizeof (*vs)) - 1; i >= idx; i--)
+ cfgst->cfg->tracemask |= lc[i];
+ return URES_SUCCESS;
+}
+
+static void pf_tracemask (struct cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), uint32_t sources)
+{
+ /* EnableCategory is also (and often) set by Verbosity, so make an effort to locate the sources for verbosity and merge them in */
+ struct cfgst_node *n;
+ struct cfgst_nodekey key;
+ bool isattr;
+ key.e = lookup_element ("CycloneDDS/Domain/Tracing/Verbosity", &isattr);
+ key.p = NULL;
+ assert (key.e != NULL);
+ if ((n = ddsrt_avl_lookup_succ_eq (&cfgst_found_treedef, &cfgst->found, &key)) != NULL && n->key.e == key.e)
+ sources |= n->sources;
+ do_print_uint32_bitset (cfgst, cfgst->cfg->tracemask, sizeof (tracemask_codes) / sizeof (*tracemask_codes), tracemask_names, tracemask_codes, sources, "");
+}
+
+static const char *xcheck_names[] = {
+ "whc", "rhc", "all", NULL
+};
+static const uint32_t xcheck_codes[] = {
+ DDS_XCHECK_WHC, DDS_XCHECK_RHC, ~(uint32_t) 0
+};
+
+static enum update_result uf_xcheck (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ uint32_t * const elem = cfg_address (cfgst, parent, cfgelem);
+ return do_uint32_bitset (cfgst, elem, xcheck_names, xcheck_codes, value);
+}
+
+static void pf_xcheck (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ const uint32_t * const p = cfg_address (cfgst, parent, cfgelem);
#ifndef NDEBUG
- const char *suffix = is_default ? " [def]" : "";
+ const char *suffix = "";
#else
const char *suffix = " [ignored]";
- (void)is_default;
#endif
- do_print_uint32_bitset (cfgst, *p, sizeof(xcheck_codes) / sizeof(*xcheck_codes), xcheck_names, xcheck_codes, suffix);
+ do_print_uint32_bitset (cfgst, *p, sizeof (xcheck_codes) / sizeof (*xcheck_codes), xcheck_names, xcheck_codes, sources, suffix);
}
-static void print_configitems(struct cfgst *cfgst, void *parent, int isattr, struct cfgelem const * const cfgelem, int unchecked)
+#ifdef DDSI_INCLUDE_SSL
+static enum update_result uf_min_tls_version (struct cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value)
{
- const struct cfgelem *ce;
- for ( ce = cfgelem; ce && ce->name; ce++ ) {
- struct cfgst_nodekey key;
+ static const char *vs[] = {
+ "1.2", "1.3", NULL
+ };
+ static const struct ssl_min_version ms[] = {
+ {1,2}, {1,3}, {0,0}
+ };
+ const int idx = list_index (vs, value);
+ struct ssl_min_version * const elem = cfg_address (cfgst, parent, cfgelem);
+ assert (sizeof (vs) / sizeof (*vs) == sizeof (ms) / sizeof (*ms));
+ if (idx < 0)
+ return cfg_error(cfgst, "'%s': undefined value", value);
+ *elem = ms[idx];
+ return URES_SUCCESS;
+}
+
+static void pf_min_tls_version (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ struct ssl_min_version * const p = cfg_address (cfgst, parent, cfgelem);
+ cfg_logelem (cfgst, sources, "%d.%d", p->major, p->minor);
+}
+#endif
+
+static enum update_result uf_string (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ char ** const elem = cfg_address (cfgst, parent, cfgelem);
+ *elem = ddsrt_strdup (value);
+ return URES_SUCCESS;
+}
+
+static void pf_string (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ char ** const p = cfg_address (cfgst, parent, cfgelem);
+ cfg_logelem (cfgst, sources, "%s", *p ? *p : "(null)");
+}
+
+#ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING
+static enum update_result uf_bandwidth (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ int64_t bandwidth_bps = 0;
+ if (strncmp (value, "inf", 3) == 0) {
+ /* special case: inf needs no unit */
+ uint32_t * const elem = cfg_address (cfgst, parent, cfgelem);
+ if (strspn (value + 3, " ") != strlen (value + 3) &&
+ lo.up_multiplier (cfgst, unittab_bandwidth_bps, value, 3, 1, 8, 1) == 0)
+ return URES_ERROR;
+ *elem = 0;
+ return URES_SUCCESS;
+ } else if (uf_natint64_unit (cfgst, &bandwidth_bps, value, unittab_bandwidth_bps, 8, INT64_MAX) != URES_SUCCESS) {
+ return URES_ERROR;
+ } else if (bandwidth_bps / 8 > INT_MAX) {
+ return cfg_error (cfgst, "%s: value out of range", value);
+ } else {
+ uint32_t * const elem = cfg_address (cfgst, parent, cfgelem);
+ *elem = (uint32_t) (bandwidth_bps / 8);
+ return URES_SUCCESS;
+ }
+}
+
+static void pf_bandwidth(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ uint32_t const * const elem = cfg_address (cfgst, parent, cfgelem);
+ if (*elem == 0)
+ cfg_logelem (cfgst, sources, "inf");
+ else
+ pf_int64_unit (cfgst, *elem, sources, unittab_bandwidth_Bps, "B/s");
+}
+#endif
+
+static enum update_result uf_memsize (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ int64_t size = 0;
+ if (uf_natint64_unit (cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) != URES_SUCCESS)
+ return URES_ERROR;
+ else {
+ uint32_t * const elem = cfg_address (cfgst, parent, cfgelem);
+ *elem = (uint32_t) size;
+ return URES_SUCCESS;
+ }
+}
+
+static void pf_memsize (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ int const * const elem = cfg_address (cfgst, parent, cfgelem);
+ pf_int64_unit (cfgst, *elem, sources, unittab_memsize, "B");
+}
+
+#ifdef DDSI_INCLUDE_ENCRYPTION
+static enum update_result uf_cipher(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
+{
+ if (q_security_plugin.cipher_type_from_string)
+ {
+ q_cipherType * const elem = cfg_address (cfgst, parent, cfgelem);
+ if (! q_security_plugin.cipher_type_from_string (value, elem))
+ return cfg_error (cfgst, "%s: undefined value", value);
+ }
+ return URES_SUCCESS;
+}
+
+static void pf_cipher (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ q_cipherType const * const p = cfg_address (cfgst, parent, cfgelem);
+ if (q_security_plugin.cipher_type)
+ cfg_logelem (cfgst, sources, "%s", (q_security_plugin.cipher_type) (*p));
+}
+
+static void pf_key (struct cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), uint32_t sources)
+{
+ cfg_logelem (cfgst, sources, "");
+}
+#endif /* DDSI_INCLUDE_ENCRYPTION */
+
+static enum update_result uf_tracingOutputFileName (struct cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), UNUSED_ARG (int first), const char *value)
+{
+ struct config * const cfg = cfgst->cfg;
+ cfg->tracefile = ddsrt_strdup (value);
+ return URES_SUCCESS;
+}
+
+static enum update_result uf_ipv4 (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
+{
+ /* Not actually doing any checking yet */
+ return uf_string (cfgst, parent, cfgelem, first, value);
+}
+
+static enum update_result uf_networkAddress (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
+{
+ if (ddsrt_strcasecmp (value, "auto") != 0)
+ return uf_ipv4 (cfgst, parent, cfgelem, first, value);
+ else
+ {
+ char ** const elem = cfg_address (cfgst, parent, cfgelem);
+ *elem = NULL;
+ return URES_SUCCESS;
+ }
+}
+
+static void pf_networkAddress (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ char ** const p = cfg_address (cfgst, parent, cfgelem);
+ cfg_logelem (cfgst, sources, "%s", *p ? *p : "auto");
+}
+
+static enum update_result uf_networkAddresses_simple (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ char *** const elem = cfg_address (cfgst, parent, cfgelem);
+ if ((*elem = ddsrt_malloc (2 * sizeof(char *))) == NULL)
+ return cfg_error (cfgst, "out of memory");
+ if (((*elem)[0] = ddsrt_strdup (value)) == NULL) {
+ ddsrt_free (*elem);
+ *elem = NULL;
+ return cfg_error (cfgst, "out of memory");
+ }
+ (*elem)[1] = NULL;
+ return URES_SUCCESS;
+}
+
+static enum update_result uf_networkAddresses (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
+{
+ /* Check for keywords first */
+ {
+ static const char *keywords[] = { "all", "any", "none" };
+ for (int i = 0; i < (int) (sizeof (keywords) / sizeof (*keywords)); i++) {
+ if (ddsrt_strcasecmp (value, keywords[i]) == 0)
+ return uf_networkAddresses_simple (cfgst, parent, cfgelem, first, keywords[i]);
+ }
+ }
+
+ /* If not keyword, then comma-separated list of addresses */
+ {
+ char *** const elem = cfg_address (cfgst, parent, cfgelem);
+ char *copy;
+ uint32_t count;
+
+ /* First count how many addresses we have - but do it stupidly by
+ counting commas and adding one (so two commas in a row are both
+ counted) */
+ {
+ const char *scan = value;
+ count = 1;
+ while (*scan)
+ count += (*scan++ == ',');
+ }
+
+ copy = ddsrt_strdup (value);
+
+ /* Allocate an array of address strings (which may be oversized a
+ bit because of the counting of the commas) */
+ *elem = ddsrt_malloc ((count + 1) * sizeof(char *));
+
+ {
+ char *cursor = copy, *tok;
+ uint32_t idx = 0;
+ while ((tok = ddsrt_strsep (&cursor, ",")) != NULL) {
+ assert (idx < count);
+ (*elem)[idx] = ddsrt_strdup (tok);
+ idx++;
+ }
+ (*elem)[idx] = NULL;
+ }
+ ddsrt_free (copy);
+ }
+ return URES_SUCCESS;
+}
+
+static void pf_networkAddresses (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ char *** const p = cfg_address (cfgst, parent, cfgelem);
+ for (int i = 0; (*p)[i] != NULL; i++)
+ cfg_logelem (cfgst, sources, "%s", (*p)[i]);
+}
+
+static void ff_networkAddresses (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
+{
+ char *** const elem = cfg_address (cfgst, parent, cfgelem);
+ for (int i = 0; (*elem)[i]; i++)
+ ddsrt_free ((*elem)[i]);
+ ddsrt_free (*elem);
+}
+
+#ifdef DDSI_INCLUDE_SSM
+static const char *allow_multicast_names[] = { "false", "spdp", "asm", "ssm", "true", NULL };
+static const uint32_t allow_multicast_codes[] = { AMC_FALSE, AMC_SPDP, AMC_ASM, AMC_SSM, AMC_TRUE };
+#else
+static const char *allow_multicast_names[] = { "false", "spdp", "asm", "true", NULL };
+static const uint32_t allow_multicast_codes[] = { AMC_FALSE, AMC_SPDP, AMC_ASM, AMC_TRUE };
+#endif
+
+static enum update_result uf_allow_multicast (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value)
+{
+ uint32_t * const elem = cfg_address (cfgst, parent, cfgelem);
+ if (ddsrt_strcasecmp (value, "default") == 0)
+ {
+ *elem = AMC_DEFAULT;
+ return URES_SUCCESS;
+ }
+ else
+ {
+ *elem = 0;
+ return do_uint32_bitset (cfgst, elem, allow_multicast_names, allow_multicast_codes, value);
+ }
+}
+
+static void pf_allow_multicast(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ uint32_t *p = cfg_address (cfgst, parent, cfgelem);
+ if (*p == AMC_DEFAULT)
+ {
+ cfg_logelem (cfgst, sources, "default");
+ }
+ else
+ {
+ do_print_uint32_bitset (cfgst, *p, sizeof (allow_multicast_codes) / sizeof (*allow_multicast_codes), allow_multicast_names, allow_multicast_codes, sources, "");
+ }
+}
+
+static enum update_result uf_maybe_int32 (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ DDSRT_WARNING_MSVC_OFF(4996);
+ struct config_maybe_int32 * const elem = cfg_address (cfgst, parent, cfgelem);
+ int pos;
+ if (ddsrt_strcasecmp (value, "default") == 0) {
+ elem->isdefault = 1;
+ elem->value = 0;
+ return URES_SUCCESS;
+ } else if (sscanf (value, "%"SCNd32"%n", &elem->value, &pos) == 1 && value[pos] == 0) {
+ elem->isdefault = 0;
+ return URES_SUCCESS;
+ } else {
+ return cfg_error (cfgst, "'%s': neither 'default' nor a decimal integer\n", value);
+ }
+ DDSRT_WARNING_MSVC_ON(4996);
+}
+
+static void pf_maybe_int32 (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ struct config_maybe_int32 const * const p = cfg_address (cfgst, parent, cfgelem);
+ if (p->isdefault)
+ cfg_logelem (cfgst, sources, "default");
+ else
+ cfg_logelem (cfgst, sources, "%d", p->value);
+}
+
+static enum update_result uf_maybe_memsize (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ struct config_maybe_uint32 * const elem = cfg_address (cfgst, parent, cfgelem);
+ int64_t size = 0;
+ if (ddsrt_strcasecmp (value, "default") == 0) {
+ elem->isdefault = 1;
+ elem->value = 0;
+ return URES_SUCCESS;
+ } else if (uf_natint64_unit (cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) != URES_SUCCESS) {
+ return URES_ERROR;
+ } else {
+ elem->isdefault = 0;
+ elem->value = (uint32_t) size;
+ return URES_SUCCESS;
+ }
+}
+
+static void pf_maybe_memsize (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ struct config_maybe_uint32 const * const p = cfg_address (cfgst, parent, cfgelem);
+ if (p->isdefault)
+ cfg_logelem (cfgst, sources, "default");
+ else
+ pf_int64_unit (cfgst, p->value, sources, unittab_memsize, "B");
+}
+
+static enum update_result uf_int (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ int * const elem = cfg_address (cfgst, parent, cfgelem);
+ char *endptr;
+ long v = strtol (value, &endptr, 10);
+ if (*value == 0 || *endptr != 0)
+ return cfg_error (cfgst, "%s: not a decimal integer", value);
+ if (v != (int) v)
+ return cfg_error (cfgst, "%s: value out of range", value);
+ *elem = (int) v;
+ return URES_SUCCESS;
+}
+
+static enum update_result uf_int_min_max (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value, int min, int max)
+{
+ int *elem = cfg_address (cfgst, parent, cfgelem);
+ if (uf_int (cfgst, parent, cfgelem, first, value) != URES_SUCCESS)
+ return URES_ERROR;
+ else if (*elem < min || *elem > max)
+ return cfg_error (cfgst, "%s: out of range", value);
+ else
+ return URES_SUCCESS;
+}
+
+static void pf_int (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ int const * const p = cfg_address (cfgst, parent, cfgelem);
+ cfg_logelem (cfgst, sources, "%d", *p);
+}
+
+static enum update_result uf_dyn_port(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
+{
+ return uf_int_min_max(cfgst, parent, cfgelem, first, value, -1, 65535);
+}
+
+static enum update_result uf_natint(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
+{
+ return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, INT32_MAX);
+}
+
+static enum update_result uf_natint_255(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
+{
+ return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, 255);
+}
+
+static enum update_result uf_uint (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ unsigned * const elem = cfg_address (cfgst, parent, cfgelem);
+ char *endptr;
+ unsigned long v = strtoul (value, &endptr, 10);
+ if (*value == 0 || *endptr != 0)
+ return cfg_error (cfgst, "%s: not a decimal integer", value);
+ if (v != (unsigned) v)
+ return cfg_error (cfgst, "%s: value out of range", value);
+ *elem = (unsigned) v;
+ return URES_SUCCESS;
+}
+
+static void pf_uint (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ unsigned const * const p = cfg_address (cfgst, parent, cfgelem);
+ cfg_logelem (cfgst, sources, "%u", *p);
+}
+
+static enum update_result uf_port(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
+{
+ int *elem = cfg_address (cfgst, parent, cfgelem);
+ if (uf_uint (cfgst, parent, cfgelem, first, value) != URES_SUCCESS)
+ return URES_ERROR;
+ else if (*elem < 1 || *elem > 65535)
+ return cfg_error (cfgst, "%s: out of range", value);
+ else
+ return URES_SUCCESS;
+}
+
+static enum update_result uf_duration_gen (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, const char *value, int64_t def_mult, int64_t min_ns, int64_t max_ns)
+{
+ return uf_natint64_unit (cfgst, cfg_address (cfgst, parent, cfgelem), value, unittab_duration, def_mult, min_ns, max_ns);
+}
+
+static enum update_result uf_duration_inf (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ if (ddsrt_strcasecmp (value, "inf") == 0) {
+ int64_t * const elem = cfg_address (cfgst, parent, cfgelem);
+ *elem = T_NEVER;
+ return URES_SUCCESS;
+ } else {
+ return uf_duration_gen (cfgst, parent, cfgelem, value, 0, 0, T_NEVER - 1);
+ }
+}
+
+static enum update_result uf_duration_ms_1hr (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ return uf_duration_gen (cfgst, parent, cfgelem, value, T_MILLISECOND, 0, 3600 * T_SECOND);
+}
+
+static enum update_result uf_duration_ms_1s (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ return uf_duration_gen (cfgst, parent, cfgelem, value, T_MILLISECOND, 0, T_SECOND);
+}
+
+static enum update_result uf_duration_us_1s (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ return uf_duration_gen (cfgst, parent, cfgelem, value, 1000, 0, T_SECOND);
+}
+
+static enum update_result uf_duration_100ms_1hr (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ return uf_duration_gen (cfgst, parent, cfgelem, value, 0, 100 * T_MILLISECOND, 3600 * T_SECOND);
+}
+
+static void pf_duration (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ int64_t const * const elem = cfg_address (cfgst, parent, cfgelem);
+ if (*elem == T_NEVER)
+ cfg_logelem (cfgst, sources, "inf");
+ else
+ pf_int64_unit (cfgst, *elem, sources, unittab_duration, "s");
+}
+
+static enum update_result uf_domainId (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
+{
+ DDSRT_WARNING_MSVC_OFF(4996);
+ uint32_t * const elem = cfg_address (cfgst, parent, cfgelem);
+ uint32_t tmpval;
+ int pos;
+ if (ddsrt_strcasecmp (value, "any") == 0) {
+ return URES_SUCCESS;
+ } else if (sscanf (value, "%"SCNu32"%n", &tmpval, &pos) == 1 && value[pos] == 0 && tmpval != UINT32_MAX) {
+ if (*elem == UINT32_MAX || *elem == tmpval)
+ {
+ if (!cfgst->first_data_in_source)
+ cfg_warning (cfgst, "not the first data in this source for compatible domain id");
+ *elem = tmpval;
+ return URES_SUCCESS;
+ }
+ else if (!cfgst->first_data_in_source)
+ {
+ /* something has been set and we can't undo any earlier assignments, so this is an error */
+ return cfg_error (cfgst, "not the first data in this source for incompatible domain id");
+ }
+ else
+ {
+ //cfg_warning (cfgst, "%"PRIu32" is incompatible with domain id being configured (%"PRIu32"), skipping", tmpval, elem->value);
+ return URES_SKIP_ELEMENT;
+ }
+ } else {
+ return cfg_error (cfgst, "'%s': neither 'any' nor a less than 2**32-1", value);
+ }
+ DDSRT_WARNING_MSVC_ON(4996);
+}
+
+static void pf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ uint32_t const * const p = cfg_address (cfgst, parent, cfgelem);
+ if (*p == UINT32_MAX)
+ cfg_logelem (cfgst, sources, "any");
+ else
+ cfg_logelem (cfgst, sources, "%"PRIu32, *p);
+}
+
+static enum update_result uf_participantIndex (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
+{
+ int * const elem = cfg_address (cfgst, parent, cfgelem);
+ if (ddsrt_strcasecmp (value, "auto") == 0) {
+ *elem = PARTICIPANT_INDEX_AUTO;
+ return URES_SUCCESS;
+ } else if (ddsrt_strcasecmp (value, "none") == 0) {
+ *elem = PARTICIPANT_INDEX_NONE;
+ return URES_SUCCESS;
+ } else {
+ return uf_int_min_max (cfgst, parent, cfgelem, first, value, 0, 120);
+ }
+}
+
+static void pf_participantIndex (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
+{
+ int const * const p = cfg_address (cfgst, parent, cfgelem);
+ switch (*p)
+ {
+ case PARTICIPANT_INDEX_NONE:
+ cfg_logelem (cfgst, sources, "none");
+ break;
+ case PARTICIPANT_INDEX_AUTO:
+ cfg_logelem (cfgst, sources, "auto");
+ break;
+ default:
+ cfg_logelem (cfgst, sources, "%d", *p);
+ break;
+ }
+}
+
+static enum update_result uf_deaf_mute (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
+{
+ return uf_boolean (cfgst, parent, cfgelem, first, value);
+}
+
+static struct cfgst_node *lookup_or_create_elem_record (struct cfgst *cfgst, struct cfgelem const * const cfgelem, void *parent, uint32_t source)
+{
+ struct cfgst_node *n;
+ struct cfgst_nodekey key;
+ ddsrt_avl_ipath_t np;
+ key.e = cfgelem;
+ key.p = parent;
+ if ((n = ddsrt_avl_lookup_ipath (&cfgst_found_treedef, &cfgst->found, &key, &np)) == NULL)
+ {
+ if ((n = ddsrt_malloc (sizeof (*n))) == NULL)
+ {
+ cfg_error (cfgst, "out of memory");
+ return NULL;
+ }
+ n->key = key;
+ n->count = 0;
+ n->failed = 0;
+ n->sources = source;
+ ddsrt_avl_insert_ipath (&cfgst_found_treedef, &cfgst->found, n, &np);
+ }
+ return n;
+}
+
+static enum update_result do_update (struct cfgst *cfgst, update_fun_t upd, void *parent, struct cfgelem const * const cfgelem, const char *value, uint32_t source)
+{
+ struct cfgst_node *n;
+ enum update_result res;
+ n = lookup_or_create_elem_record (cfgst, cfgelem, parent, source);
+ if (cfgelem->multiplicity == 1 && n->count == 1 && source > n->sources)
+ free_configured_element (cfgst, parent, cfgelem);
+ if (cfgelem->multiplicity == 0 || n->count < cfgelem->multiplicity)
+ res = upd (cfgst, parent, cfgelem, (n->count == n->failed), value);
+ else
+ res = cfg_error (cfgst, "only %d instance%s allowed", cfgelem->multiplicity, (cfgelem->multiplicity == 1) ? "" : "s");
+ n->count++;
+ n->sources |= source;
+ /* deciding to skip an entire subtree in the config is not an error */
+ if (res == URES_ERROR)
+ n->failed++;
+ return res;
+}
+
+static int set_default (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
+{
+ enum update_result res;
+ if (cfgelem->defvalue == NULL)
+ {
+ cfg_error (cfgst, "element missing in configuration");
+ return 0;
+ }
+ res = do_update (cfgst, cfgelem->update, parent, cfgelem, cfgelem->defvalue, 0);
+ return (res != URES_ERROR);
+}
+
+static int set_defaults (struct cfgst *cfgst, void *parent, int isattr, struct cfgelem const * const cfgelem)
+{
+ int ok = 1;
+ for (const struct cfgelem *ce = cfgelem; ce && ce->name; ce++)
+ {
struct cfgst_node *n;
- if ( ce->name[0] == '>' || ce->name[0] == '|') /* moved or deprecated, so don't care */
- continue;
+ struct cfgst_nodekey key;
key.e = ce;
- cfgst_push(cfgst, isattr, ce, parent);
- if ( ce->multiplicity == 1 ) {
- if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) {
- cfgst_push(cfgst, 0, NULL, NULL);
- ce->print(cfgst, parent, ce, n->is_default);
- cfgst_pop(cfgst);
- } else {
- if ( unchecked && ce->print ) {
- cfgst_push(cfgst, 0, NULL, NULL);
- ce->print(cfgst, parent, ce, 0);
- cfgst_pop(cfgst);
+ key.p = parent;
+ cfgst_push (cfgst, isattr, ce, parent);
+ if (ce->multiplicity <= 1)
+ {
+ if ((n = ddsrt_avl_lookup (&cfgst_found_treedef, &cfgst->found, &key)) == NULL)
+ {
+ if (ce->update)
+ {
+ int ok1;
+ cfgst_push (cfgst, 0, NULL, NULL);
+ ok1 = set_default (cfgst, parent, ce);
+ cfgst_pop (cfgst);
+ ok = ok && ok1;
}
}
-
- if ( ce->children )
- print_configitems(cfgst, parent, 0, ce->children, unchecked);
- if ( ce->attributes )
- print_configitems(cfgst, parent, 1, ce->attributes, unchecked);
- } else {
- struct config_listelem *p = cfg_deref_address(cfgst, parent, ce);
- while ( p ) {
- cfgst_push(cfgst, 0, NULL, NULL);
- if ( ce->print ) {
- ce->print(cfgst, p, ce, 0);
- }
- cfgst_pop(cfgst);
- if ( ce->attributes )
- print_configitems(cfgst, p, 1, ce->attributes, 1);
- if ( ce->children )
- print_configitems(cfgst, p, 0, ce->children, 1);
- p = p->next;
- }
+ if (ce->children)
+ ok = ok && set_defaults (cfgst, parent, 0, ce->children);
+ if (ce->attributes)
+ ok = ok && set_defaults (cfgst, parent, 1, ce->attributes);
}
- cfgst_pop(cfgst);
+ cfgst_pop (cfgst);
}
+ return ok;
}
-static void free_all_elements(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
+static void print_configitems (struct cfgst *cfgst, void *parent, int isattr, struct cfgelem const * const cfgelem, uint32_t sources)
{
- const struct cfgelem *ce;
-
- for ( ce = cfgelem; ce && ce->name; ce++ ) {
- if ( ce->name[0] == '>' ) /* moved, so don't care */
- continue;
-
- if ( ce->free )
- ce->free(cfgst, parent, ce);
-
- if ( ce->multiplicity == 1 ) {
- if ( ce->children )
- free_all_elements(cfgst, parent, ce->children);
- if ( ce->attributes )
- free_all_elements(cfgst, parent, ce->attributes);
- } else {
- struct config_listelem *p = cfg_deref_address(cfgst, parent, ce);
- struct config_listelem *r;
- while ( p ) {
- if ( ce->attributes )
- free_all_elements(cfgst, p, ce->attributes);
- if ( ce->children )
- free_all_elements(cfgst, p, ce->children);
- r = p;
- p = p->next;
- ddsrt_free(r);
- }
- }
- }
-}
-
-static void free_configured_elements(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
-{
- const struct cfgelem *ce;
- for ( ce = cfgelem; ce && ce->name; ce++ ) {
+ for (const struct cfgelem *ce = cfgelem; ce && ce->name; ce++)
+ {
struct cfgst_nodekey key;
struct cfgst_node *n;
- if ( ce->name[0] == '>' ) /* moved, so don't care */
+ if (ce->name[0] == '>' || ce->name[0] == '|') /* moved or deprecated, so don't care */
continue;
key.e = ce;
- if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) {
- if ( ce->free && n->count > n->failed )
- ce->free(cfgst, parent, ce);
- }
+ key.p = parent;
+ cfgst_push (cfgst, isattr, ce, parent);
+ if ((n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL)
+ sources = n->sources;
- if ( ce->multiplicity == 1 ) {
- if ( ce->children )
- free_configured_elements(cfgst, parent, ce->children);
- if ( ce->attributes )
- free_configured_elements(cfgst, parent, ce->attributes);
- } else {
- struct config_listelem *p = cfg_deref_address(cfgst, parent, ce);
- struct config_listelem *r;
- while ( p ) {
- if ( ce->attributes )
- free_all_elements(cfgst, p, ce->attributes);
- if ( ce->children )
- free_all_elements(cfgst, p, ce->children);
- r = p;
+ if (ce->multiplicity <= 1)
+ {
+ cfgst_push (cfgst, 0, NULL, NULL);
+ if (ce->print)
+ ce->print (cfgst, parent, ce, sources);
+ cfgst_pop (cfgst);
+ if (ce->children)
+ print_configitems (cfgst, parent, 0, ce->children, sources);
+ if (ce->attributes)
+ print_configitems (cfgst, parent, 1, ce->attributes, sources);
+ }
+ else
+ {
+ struct config_listelem *p = cfg_deref_address (cfgst, parent, ce);
+ while (p)
+ {
+ cfgst_push (cfgst, 0, NULL, NULL);
+ if (ce->print)
+ ce->print (cfgst, p, ce, sources);
+ cfgst_pop(cfgst);
+ if (ce->attributes)
+ print_configitems (cfgst, p, 1, ce->attributes, sources);
+ if (ce->children)
+ print_configitems (cfgst, p, 0, ce->children, sources);
p = p->next;
- ddsrt_free(r);
+ }
+ }
+ cfgst_pop (cfgst);
+ }
+}
+
+
+static void free_all_elements (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
+{
+ for (const struct cfgelem *ce = cfgelem; ce && ce->name; ce++)
+ {
+ if (ce->name[0] == '>') /* moved, so don't care */
+ continue;
+
+ if (ce->free)
+ ce->free (cfgst, parent, ce);
+
+ if (ce->multiplicity <= 1) {
+ if (ce->children)
+ free_all_elements (cfgst, parent, ce->children);
+ if (ce->attributes)
+ free_all_elements (cfgst, parent, ce->attributes);
+ } else {
+ struct config_listelem *p = cfg_deref_address (cfgst, parent, ce);
+ while (p) {
+ struct config_listelem *p1 = p->next;
+ if (ce->attributes)
+ free_all_elements (cfgst, p, ce->attributes);
+ if (ce->children)
+ free_all_elements (cfgst, p, ce->children);
+ ddsrt_free (p);
+ p = p1;
}
}
}
}
-static int matching_name_index(const char *name_w_aliases, const char *name)
+static void free_configured_element (struct cfgst *cfgst, void *parent, struct cfgelem const * const ce)
{
- const char *ns = name_w_aliases, *p = strchr(ns, '|');
+ struct cfgst_nodekey key;
+ struct cfgst_node *n;
+ if (ce->name[0] == '>') /* moved, so don't care */
+ return;
+ key.e = ce;
+ key.p = parent;
+ if ((n = ddsrt_avl_lookup (&cfgst_found_treedef, &cfgst->found, &key)) != NULL)
+ {
+ if (ce->free && n->count > n->failed)
+ ce->free (cfgst, parent, ce);
+ n->count = n->failed = 0;
+ }
+
+ if (ce->multiplicity <= 1)
+ {
+ if (ce->children)
+ free_configured_elements (cfgst, parent, ce->children);
+ if (ce->attributes)
+ free_configured_elements (cfgst, parent, ce->attributes);
+ }
+ else
+ {
+ /* FIXME: this used to require free_all_elements because there would be no record stored for
+ configuration elements within lists, but with that changed, I think this can now just use
+ free_configured_elements */
+ struct config_listelem *p = cfg_deref_address (cfgst, parent, ce);
+ while (p) {
+ struct config_listelem * const p1 = p->next;
+ if (ce->attributes)
+ free_all_elements (cfgst, p, ce->attributes);
+ if (ce->children)
+ free_all_elements (cfgst, p, ce->children);
+ ddsrt_free (p);
+ p = p1;
+ }
+ }
+}
+
+static void free_configured_elements (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
+{
+ for (const struct cfgelem *ce = cfgelem; ce && ce->name; ce++)
+ free_configured_element (cfgst, parent, ce);
+}
+
+static int matching_name_index (const char *name_w_aliases, const char *name)
+{
+ const char *ns = name_w_aliases, *p = strchr (ns, '|');
int idx = 0;
- while ( p ) {
- if ( ddsrt_strncasecmp(ns, name, (size_t) (p - ns)) == 0 && name[p - ns] == 0 ) {
+ while (p)
+ {
+ if (ddsrt_strncasecmp (ns, name, (size_t) (p - ns)) == 0 && name[p - ns] == 0)
+ {
/* ns upto the pipe symbol is a prefix of name, and name is terminated at that point */
return idx;
}
/* If primary name followed by '||' instead of '|', aliases are non-warning */
ns = p + 1 + (idx == 0 && p[1] == '|');
- p = strchr(ns, '|');
+ p = strchr (ns, '|');
idx++;
}
- return (ddsrt_strcasecmp(ns, name) == 0) ? idx : -1;
+ return (ddsrt_strcasecmp (ns, name) == 0) ? idx : -1;
}
-static const struct cfgelem *lookup_redirect(const char *target)
+static const struct cfgelem *lookup_element (const char *target, bool *isattr)
{
const struct cfgelem *cfgelem = cyclonedds_root_cfgelems;
- char *target_copy = ddsrt_strdup(target), *p1;
- const char *p = target_copy;
- while ( p ) {
- p1 = strchr(p, '/');
- if ( p1 ) *p1++ = 0;
- for ( ; cfgelem->name; cfgelem++ ) {
- /* not supporting multiple redirects */
- assert(cfgelem->name[0] != '>');
- if ( matching_name_index(cfgelem->name, p) >= 0 )
+ char *target_copy = ddsrt_strdup (target);
+ char *p = target_copy;
+ *isattr = false;
+ while (p)
+ {
+ char *p1 = p + strcspn (p, "/[");
+ switch (*p1)
+ {
+ case '\0':
+ p1 = NULL;
break;
+ case '/':
+ *p1++ = 0;
+ break;
+ case '[':
+ assert (p1[1] == '@' && p1[strlen (p1) - 1] == ']');
+ p1[strlen (p1) - 1] = 0;
+ *p1 = 0; p1 += 2;
+ *isattr = true;
+ break;
+ default:
+ assert (0);
}
- if ( p1 ) {
- cfgelem = cfgelem->children;
+ for (; cfgelem->name; cfgelem++)
+ {
+ if (matching_name_index (cfgelem->name, p) >= 0)
+ {
+ /* not supporting chained redirects */
+ assert (cfgelem->name[0] != '>');
+ break;
+ }
}
+ if (p1)
+ cfgelem = *isattr ? cfgelem->attributes : cfgelem->children;
p = p1;
}
- ddsrt_free(target_copy);
+ ddsrt_free (target_copy);
return cfgelem;
}
-static int proc_elem_open(void *varg, UNUSED_ARG(uintptr_t parentinfo), UNUSED_ARG(uintptr_t *eleminfo), const char *name)
+static int proc_elem_open (void *varg, UNUSED_ARG (uintptr_t parentinfo), UNUSED_ARG (uintptr_t *eleminfo), const char *name, int line)
{
struct cfgst * const cfgst = varg;
- const struct cfgelem *cfgelem = cfgst_tos(cfgst);
+
+ cfgst->line = line;
+ if (cfgst->implicit_toplevel == ITL_ALLOWED)
+ {
+ if (ddsrt_strcasecmp (name, "CycloneDDS") == 0)
+ cfgst->implicit_toplevel = ITL_DISALLOWED;
+ else
+ {
+ cfgst_push (cfgst, 0, &cyclonedds_root_cfgelems[0], cfgst_parent (cfgst));
+ /* Most likely one would want to override some domain settings without bothering,
+ so also allow an implicit "Domain" */
+ cfgst->implicit_toplevel = ITL_INSERTED_1;
+ if (ddsrt_strcasecmp (name, "Domain") != 0)
+ {
+ cfgst_push (cfgst, 0, &root_cfgelems[0], cfgst_parent (cfgst));
+ cfgst->implicit_toplevel = ITL_INSERTED_2;
+ }
+ }
+ }
+
+ const struct cfgelem *cfgelem = cfgst_tos (cfgst);
const struct cfgelem *cfg_subelem;
int moved = 0;
- if ( cfgelem == NULL ) {
+
+ if (cfgelem == NULL)
+ {
/* Ignoring, but do track the structure so we can know when to stop ignoring */
- cfgst_push(cfgst, 0, NULL, NULL);
+ cfgst_push (cfgst, 0, NULL, NULL);
return 1;
}
- for ( cfg_subelem = cfgelem->children; cfg_subelem && cfg_subelem->name && strcmp(cfg_subelem->name, "*") != 0; cfg_subelem++ ) {
+ for (cfg_subelem = cfgelem->children; cfg_subelem && cfg_subelem->name && strcmp (cfg_subelem->name, "*") != 0; cfg_subelem++)
+ {
const char *csename = cfg_subelem->name;
int idx;
moved = (csename[0] == '>');
- if ( moved )
+ if (moved)
csename++;
- idx = matching_name_index(csename, name);
-#if WARN_DEPRECATED_ALIAS
- if ( idx > 0 ) {
- if (csename[0] == '|') {
- cfg_warning(cfgst, "'%s': deprecated setting", name);
- } else {
- int n = (int) (strchr(csename, '|') - csename);
- if ( csename[n + 1] != '|' ) {
- cfg_warning(cfgst, "'%s': deprecated alias for '%*.*s'", name, n, n, csename);
+ idx = matching_name_index (csename, name);
+ if (idx > 0)
+ {
+ if (csename[0] == '|')
+ cfg_warning (cfgst, "'%s': deprecated setting", name);
+ else
+ {
+ int n = (int) (strchr (csename, '|') - csename);
+ if (csename[n + 1] != '|') {
+ cfg_warning (cfgst, "'%s': deprecated alias for '%*.*s'", name, n, n, csename);
}
}
}
-#endif
- if ( idx >= 0 ) {
+ if (idx >= 0)
break;
- }
}
- if ( cfg_subelem == NULL || cfg_subelem->name == NULL ) {
- cfgst_push(cfgst, 0, NULL, NULL);
- return cfg_error(cfgst, "%s: unknown element", name);
- } else if ( strcmp(cfg_subelem->name, "*") == 0 ) {
+ if (cfg_subelem == NULL || cfg_subelem->name == NULL)
+ {
+ cfg_error (cfgst, "%s: unknown element", name);
+ cfgst_push (cfgst, 0, NULL, NULL);
+ return 0;
+ }
+ else if (strcmp (cfg_subelem->name, "*") == 0)
+ {
/* Push a marker that we are to ignore this part of the DOM tree */
- cfgst_push(cfgst, 0, NULL, NULL);
+ cfgst_push (cfgst, 0, NULL, NULL);
return 1;
- } else {
+ }
+ else
+ {
void *parent, *dynparent;
- if ( moved ) {
+ if (moved)
+ {
struct cfgelem const * const cfg_subelem_orig = cfg_subelem;
- cfg_subelem = lookup_redirect(cfg_subelem->defvalue);
-#if WARN_DEPRECATED_ALIAS
- cfgst_push(cfgst, 0, cfg_subelem_orig, NULL);
- cfg_warning(cfgst, "setting%s moved to //%s", cfg_subelem->children ? "s" : "", cfg_subelem_orig->defvalue);
- cfgst_pop(cfgst);
-#endif
+ bool isattr;
+ cfg_subelem = lookup_element (cfg_subelem->defvalue, &isattr);
+ cfgst_push (cfgst, 0, cfg_subelem_orig, NULL);
+ cfg_warning (cfgst, "setting%s moved to //%s", cfg_subelem->children ? "s" : "", cfg_subelem_orig->defvalue);
+ cfgst_pop (cfgst);
}
- parent = cfgst_parent(cfgst);
- assert(cfgelem->init || cfgelem->multiplicity == 1); /*multi-items must have an init-func */
- if ( cfg_subelem->init ) {
- if ( cfg_subelem->init(cfgst, parent, cfg_subelem) < 0 )
+ parent = cfgst_parent (cfgst);
+ assert (cfgelem->init || cfgelem->multiplicity == 1); /* multi-items must have an init-func */
+ if (cfg_subelem->init)
+ {
+ if (cfg_subelem->init (cfgst, parent, cfg_subelem) < 0)
return 0;
}
- if ( cfg_subelem->multiplicity != 1 )
- dynparent = cfg_deref_address(cfgst, parent, cfg_subelem);
- else
+ if (cfg_subelem->multiplicity <= 1)
dynparent = parent;
+ else
+ dynparent = cfg_deref_address (cfgst, parent, cfg_subelem);
- cfgst_push(cfgst, 0, cfg_subelem, dynparent);
+ cfgst_push (cfgst, 0, cfg_subelem, dynparent);
+
+ if (cfg_subelem == &cyclonedds_root_cfgelems[0])
+ {
+ cfgst->source = (cfgst->source == 0) ? 1 : cfgst->source << 1;
+ cfgst->first_data_in_source = true;
+ }
+ else if (cfg_subelem >= &root_cfgelems[0] && cfg_subelem < &root_cfgelems[0] + sizeof (root_cfgelems) / sizeof (root_cfgelems[0]))
+ {
+ if (!cfgst->first_data_in_source)
+ cfgst->source = (cfgst->source == 0) ? 1 : cfgst->source << 1;
+ cfgst->first_data_in_source = true;
+ }
return 1;
}
}
-static int proc_attr(void *varg, UNUSED_ARG(uintptr_t eleminfo), const char *name, const char *value)
+static int proc_update_cfgelem (struct cfgst *cfgst, const struct cfgelem *ce, const char *value, bool isattr)
+{
+ void *parent = cfgst_parent (cfgst);
+ char *xvalue = ddsrt_expand_envvars (value, cfgst->cfg->domainId);
+ enum update_result res;
+ cfgst_push (cfgst, isattr, isattr ? ce : NULL, parent);
+ res = do_update (cfgst, ce->update, parent, ce, xvalue, cfgst->source);
+ cfgst_pop (cfgst);
+ ddsrt_free (xvalue);
+
+ /* Push a marker that we are to ignore this part of the DOM tree -- see the
+ handling of WILDCARD ("*"). This is currently only used for domain ids,
+ and there it is either:
+ - , in which case the element at the top of the stack is
+ Domain, which is the element to ignore, or:
+ - X, in which case the element at the top of the stack Id,
+ and we need to strip ignore the one that is one down.
+
+ The configuration processing doesn't allow an element to contain text and
+ have children at the same time, and with that restriction it never makes
+ sense to ignore just the TOS element if it is text: that would be better
+ done in the update function itself.
+
+ So replacing the top stack entry for an attribute and the top two entries
+ if it's text is a reasonable interpretation of SKIP. And it seems quite
+ likely that it won't be used for anything else ... */
+ if (res == URES_SKIP_ELEMENT)
+ {
+ cfgst_pop (cfgst);
+ if (!isattr)
+ {
+ cfgst_pop (cfgst);
+ cfgst_push (cfgst, 0, NULL, NULL);
+ }
+ cfgst_push (cfgst, 0, NULL, NULL);
+ }
+ else
+ {
+ cfgst->first_data_in_source = false;
+ }
+ return res != URES_ERROR;
+}
+
+static int proc_attr (void *varg, UNUSED_ARG (uintptr_t eleminfo), const char *name, const char *value, int line)
{
/* All attributes are processed immediately after opening the element */
struct cfgst * const cfgst = varg;
- const struct cfgelem *cfgelem = cfgst_tos(cfgst);
+ const struct cfgelem *cfgelem = cfgst_tos (cfgst);
const struct cfgelem *cfg_attr;
- if ( cfgelem == NULL )
+ cfgst->line = line;
+ if (cfgelem == NULL)
return 1;
- for ( cfg_attr = cfgelem->attributes; cfg_attr && cfg_attr->name; cfg_attr++ ) {
- if ( ddsrt_strcasecmp(cfg_attr->name, name) == 0 )
+ for (cfg_attr = cfgelem->attributes; cfg_attr && cfg_attr->name; cfg_attr++)
+ if (ddsrt_strcasecmp(cfg_attr->name, name) == 0)
break;
- }
- if ( cfg_attr == NULL || cfg_attr->name == NULL )
- return cfg_error(cfgst, "%s: unknown attribute", name);
- else {
- void *parent = cfgst_parent(cfgst);
- char *xvalue = ddsrt_expand_envvars(value);
- int ok;
- cfgst_push(cfgst, 1, cfg_attr, parent);
- ok = do_update(cfgst, cfg_attr->update, parent, cfg_attr, xvalue, 0);
- cfgst_pop(cfgst);
- ddsrt_free(xvalue);
- return ok;
+ if (cfg_attr != NULL && cfg_attr->name != NULL)
+ return proc_update_cfgelem (cfgst, cfg_attr, value, true);
+ else
+ {
+ cfg_error (cfgst, "%s: unknown attribute", name);
+ return 0;
}
}
-static int proc_elem_data(void *varg, UNUSED_ARG(uintptr_t eleminfo), const char *value)
+static int proc_elem_data (void *varg, UNUSED_ARG (uintptr_t eleminfo), const char *value, int line)
{
struct cfgst * const cfgst = varg;
- const struct cfgelem *cfgelem = cfgst_tos(cfgst);
- if ( cfgelem == NULL )
+ bool isattr; /* elem may have been moved to an attr */
+ const struct cfgelem *cfgelem = cfgst_tos_w_isattr (cfgst, &isattr);
+ cfgst->line = line;
+ if (cfgelem == NULL)
return 1;
- if ( cfgelem->update == 0 )
- return cfg_error(cfgst, "%s: no data expected", value);
- else {
- void *parent = cfgst_parent(cfgst);
- char *xvalue = ddsrt_expand_envvars(value);
- int ok;
- cfgst_push(cfgst, 0, NULL, parent);
- ok = do_update(cfgst, cfgelem->update, parent, cfgelem, xvalue, 0);
- cfgst_pop(cfgst);
- ddsrt_free(xvalue);
- return ok;
+ if (cfgelem->update != 0)
+ return proc_update_cfgelem (cfgst, cfgelem, value, isattr);
+ else
+ {
+ cfg_error (cfgst, "%s: no data expected", value);
+ return 0;
}
}
-static int proc_elem_close(void *varg, UNUSED_ARG(uintptr_t eleminfo))
+static int proc_elem_close (void *varg, UNUSED_ARG (uintptr_t eleminfo), int line)
{
struct cfgst * const cfgst = varg;
- const struct cfgelem * cfgelem = cfgst_tos(cfgst);
+ const struct cfgelem * cfgelem = cfgst_tos (cfgst);
int ok = 1;
- if ( cfgelem && cfgelem->multiplicity != 1 ) {
- void *parent = cfgst_parent(cfgst);
+ cfgst->line = line;
+ if (cfgelem && cfgelem->multiplicity > 1)
+ {
+ void *parent = cfgst_parent (cfgst);
int ok1;
- ok1 = set_defaults(cfgst, parent, 1, cfgelem->attributes, 1);
+ ok1 = set_defaults (cfgst, parent, 1, cfgelem->attributes);
ok = ok && ok1;
- ok1 = set_defaults(cfgst, parent, 0, cfgelem->children, 1);
+ ok1 = set_defaults (cfgst, parent, 0, cfgelem->children);
ok = ok && ok1;
}
- cfgst_pop(cfgst);
+ cfgst_pop (cfgst);
return ok;
}
-static void proc_error(void *varg, const char *msg, int line)
+static void proc_error (void *varg, const char *msg, int line)
{
struct cfgst * const cfgst = varg;
- cfg_error(cfgst, "parser error %s at line %d", msg, line);
+ cfg_error (cfgst, "parser error %s at line %d", msg, line);
}
-
-static int cfgst_node_cmp(const void *va, const void *vb)
+static int cfgst_node_cmp (const void *va, const void *vb)
{
- return memcmp(va, vb, sizeof(struct cfgst_nodekey));
+ return memcmp (va, vb, sizeof (struct cfgst_nodekey));
}
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
-static int set_default_channel(struct config *cfg)
+static int set_default_channel (struct config *cfg)
{
- if ( cfg->channels == NULL ) {
+ if (cfg->channels == NULL)
+ {
/* create one default channel if none configured */
struct config_channel_listelem *c;
- if ( (c = ddsrt_malloc(sizeof(*c))) == NULL )
+ if ((c = ddsrt_malloc (sizeof (*c))) == NULL)
return ERR_OUT_OF_MEMORY;
c->next = NULL;
- c->name = ddsrt_strdup("user");
+ c->name = ddsrt_strdup ("user");
c->priority = 0;
c->resolution = 1 * T_MILLISECOND;
#ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING
@@ -2592,83 +2614,111 @@ static int set_default_channel(struct config *cfg)
return 0;
}
-static int sort_channels_cmp(const void *va, const void *vb)
+static int sort_channels_cmp (const void *va, const void *vb)
{
const struct config_channel_listelem * const *a = va;
const struct config_channel_listelem * const *b = vb;
return ((*a)->priority == (*b)->priority) ? 0 : ((*a)->priority < (*b)->priority) ? -1 : 1;
}
-static int sort_channels_check_nodups(struct config *cfg)
+static int sort_channels_check_nodups (struct config *cfg, uint32_t domid)
{
/* Selecting a channel is much easier & more elegant if the channels
are sorted on descending priority. While we do retain the list
structure, sorting is much easier in an array, and hence we
convert back and forth. */
struct config_channel_listelem **ary, *c;
- unsigned i, n;
+ uint32_t i, n;
int result;
n = 0;
- for ( c = cfg->channels; c; c = c->next )
+ for (c = cfg->channels; c; c = c->next)
n++;
assert(n > 0);
- ary = ddsrt_malloc(n * sizeof(*ary));
+ ary = ddsrt_malloc (n * sizeof (*ary));
i = 0;
- for ( c = cfg->channels; c; c = c->next )
+ for (c = cfg->channels; c; c = c->next)
ary[i++] = c;
- qsort(ary, n, sizeof(*ary), sort_channels_cmp);
+ qsort (ary, n, sizeof (*ary), sort_channels_cmp);
result = 0;
- for ( i = 0; i < n - 1; i++ ) {
- if ( ary[i]->priority == ary[i + 1]->priority ) {
- DDS_ERROR("config: duplicate channel definition for priority %u: channels %s and %s\n",
+ for (i = 0; i < n - 1; i++) {
+ if (ary[i]->priority == ary[i + 1]->priority) {
+ DDS_ILOG (DDS_LC_ERROR, domid, "config: duplicate channel definition for priority %u: channels %s and %s\n",
ary[i]->priority, ary[i]->name, ary[i + 1]->name);
result = ERR_ENTITY_EXISTS;
}
}
- if ( result == 0 ) {
+ if (result == 0)
+ {
cfg->channels = ary[0];
- for ( i = 0; i < n - 1; i++ )
+ for (i = 0; i < n - 1; i++)
ary[i]->next = ary[i + 1];
ary[i]->next = NULL;
cfg->max_channel = ary[i];
}
- ddsrt_free(ary);
+ ddsrt_free (ary);
return result;
}
#endif /* DDSI_INCLUDE_NETWORK_CHANNELS */
-struct cfgst * config_init (const char *configfile)
+static FILE *config_open_file (char *tok, char **cursor, uint32_t domid)
+{
+ assert (*tok && !(isspace ((unsigned char) *tok) || *tok == ','));
+ FILE *fp;
+ char *comma;
+ if ((comma = strchr (tok, ',')) == NULL)
+ *cursor = NULL;
+ else
+ {
+ *comma = 0;
+ *cursor = comma + 1;
+ }
+ DDSRT_WARNING_MSVC_OFF(4996);
+ if ((fp = fopen (tok, "r")) == NULL)
+ {
+ if (strncmp (tok, "file://", 7) != 0 || (fp = fopen (tok + 7, "r")) == NULL)
+ {
+ DDS_ILOG (DDS_LC_ERROR, domid, "can't open configuration file %s\n", tok);
+ return NULL;
+ }
+ }
+ DDSRT_WARNING_MSVC_ON(4996);
+ return fp;
+}
+
+struct cfgst *config_init (const char *configfile, struct config *cfg, uint32_t domid)
{
int ok = 1;
struct cfgst *cfgst;
- memset(&config, 0, sizeof(config));
+ memset (cfg, 0, sizeof (*cfg));
- config.tracingOutputFile = stderr;
- config.enabled_logcats = DDS_LC_ERROR | DDS_LC_WARNING;
+ cfgst = ddsrt_malloc (sizeof (*cfgst));
+ memset (cfgst, 0, sizeof (*cfgst));
+ ddsrt_avl_init (&cfgst_found_treedef, &cfgst->found);
+ cfgst->cfg = cfg;
+ cfgst->error = 0;
+ cfgst->source = 0;
+ cfgst->logcfg = NULL;
+ cfgst->first_data_in_source = true;
+ cfgst->input = "init";
+ cfgst->line = 1;
/* eventually, we domainId.value will be the real domain id selected, even if it was configured
to the default of "any" and has "isdefault" set; initializing it to the default-default
value of 0 means "any" in the config & DDS_DOMAIN_DEFAULT in create participant automatically
ends up on the right value */
- config.domainId.value = 0;
-
- cfgst = ddsrt_malloc(sizeof(*cfgst));
- memset(cfgst, 0, sizeof(*cfgst));
-
- ddsrt_avl_init(&cfgst_found_treedef, &cfgst->found);
- cfgst->cfg = &config;
- cfgst->error = 0;
+ cfgst->cfg->domainId = domid;
/* configfile == NULL will get you the default configuration */
if (configfile) {
- char *copy = ddsrt_strdup(configfile), *cursor = copy;
+ char env_input[32];
+ char *copy = ddsrt_strdup (configfile), *cursor = copy;
struct ddsrt_xmlp_callbacks cb;
cb.attr = proc_attr;
@@ -2677,64 +2727,71 @@ struct cfgst * config_init (const char *configfile)
cb.elem_open = proc_elem_open;
cb.error = proc_error;
- while (ok && cursor && cursor[0]) {
+ while (*cursor && (isspace ((unsigned char) *cursor) || *cursor == ','))
+ cursor++;
+ while (ok && cursor && cursor[0])
+ {
struct ddsrt_xmlp_state *qx;
FILE *fp;
char *tok;
tok = cursor;
- if (tok[0] == '<') {
+ if (tok[0] == '<')
+ {
/* Read XML directly from input string */
qx = ddsrt_xmlp_new_string (tok, cfgst, &cb);
- ddsrt_xmlp_set_options (qx, DDSRT_XMLP_ANONYMOUS_CLOSE_TAG);
+ ddsrt_xmlp_set_options (qx, DDSRT_XMLP_ANONYMOUS_CLOSE_TAG | DDSRT_XMLP_MISSING_CLOSE_AS_EOF);
fp = NULL;
- } else {
- char *comma;
- if ((comma = strchr (cursor, ',')) == NULL) {
- cursor = NULL;
- } else {
- *comma = 0;
- cursor = comma + 1;
- }
- DDSRT_WARNING_MSVC_OFF(4996);
- if ((fp = fopen(tok, "r")) == NULL) {
- if (strncmp(tok, "file://", 7) != 0 || (fp = fopen(tok + 7, "r")) == NULL) {
- DDS_ERROR("can't open configuration file %s\n", tok);
- ddsrt_free(copy);
- ddsrt_free(cfgst);
- return NULL;
- }
- }
- DDSRT_WARNING_MSVC_ON(4996);
- qx = ddsrt_xmlp_new_file(fp, cfgst, &cb);
+ snprintf (env_input, sizeof (env_input), "CYCLONEDDS_URI+%u", (unsigned) (tok - copy));
+ cfgst->input = env_input;
+ cfgst->line = 1;
+ }
+ else if ((fp = config_open_file (tok, &cursor, domid)) == NULL)
+ {
+ ddsrt_free (copy);
+ goto error;
+ }
+ else
+ {
+ qx = ddsrt_xmlp_new_file (fp, cfgst, &cb);
+ cfgst->input = tok;
+ cfgst->line = 1;
}
- cfgst_push(cfgst, 0, &root_cfgelem, &config);
- ok = (ddsrt_xmlp_parse(qx) >= 0) && !cfgst->error;
+ cfgst->implicit_toplevel = (fp == NULL) ? ITL_ALLOWED : ITL_DISALLOWED;
+ cfgst->first_data_in_source = true;
+ cfgst_push (cfgst, 0, &root_cfgelem, cfgst->cfg);
+ ok = (ddsrt_xmlp_parse (qx) >= 0) && !cfgst->error;
+ assert (!ok ||
+ (cfgst->path_depth == 1 && cfgst->implicit_toplevel == ITL_DISALLOWED) ||
+ (cfgst->path_depth == 1 + (int) cfgst->implicit_toplevel));
/* Pop until stack empty: error handling is rather brutal */
- assert(!ok || cfgst->path_depth == 1);
- while (cfgst->path_depth > 0) {
- cfgst_pop(cfgst);
- }
- if (fp) {
- fclose(fp);
- } else if (ok) {
+ while (cfgst->path_depth > 0)
+ cfgst_pop (cfgst);
+ if (fp != NULL)
+ fclose (fp);
+ else if (ok)
cursor = tok + ddsrt_xmlp_get_bufpos (qx);
- }
- ddsrt_xmlp_free(qx);
- while (cursor && cursor[0] == ',') {
- cursor++;
+ ddsrt_xmlp_free (qx);
+ assert (fp == NULL || cfgst->implicit_toplevel <= ITL_ALLOWED);
+ if (cursor)
+ {
+ while (*cursor && (isspace ((unsigned char) cursor[0]) || cursor[0] == ','))
+ cursor++;
}
}
- ddsrt_free(copy);
+ ddsrt_free (copy);
}
/* Set defaults for everything not set that we have a default value
for, signal errors for things unset but without a default. */
- {
- int ok1 = set_defaults(cfgst, cfgst->cfg, 0, root_cfgelems, 0);
- ok = ok && ok1;
- }
+ ok = ok && set_defaults (cfgst, cfgst->cfg, 0, root_cfgelems);
+ /* Domain id UINT32_MAX can only happen if the application specified DDS_DOMAIN_DEFAULT
+ and the configuration has "any" (either explicitly or as a default). In that case,
+ default to 0. (Leaving it as UINT32_MAX while reading the config has the advantage
+ of warnings/errors being output without a domain id present. */
+ if (cfgst->cfg->domainId == UINT32_MAX)
+ cfgst->cfg->domainId = 0;
/* Compatibility settings of IPv6, TCP -- a bit too complicated for
the poor framework */
@@ -2744,9 +2801,9 @@ struct cfgst * config_init (const char *configfile)
{
case TRANS_DEFAULT:
if (cfgst->cfg->compat_tcp_enable == BOOLDEF_TRUE)
- cfgst->cfg->transport_selector = (config.compat_use_ipv6 == BOOLDEF_TRUE) ? TRANS_TCP6 : TRANS_TCP;
+ cfgst->cfg->transport_selector = (cfgst->cfg->compat_use_ipv6 == BOOLDEF_TRUE) ? TRANS_TCP6 : TRANS_TCP;
else
- cfgst->cfg->transport_selector = (config.compat_use_ipv6 == BOOLDEF_TRUE) ? TRANS_UDP6 : TRANS_UDP;
+ cfgst->cfg->transport_selector = (cfgst->cfg->compat_use_ipv6 == BOOLDEF_TRUE) ? TRANS_UDP6 : TRANS_UDP;
break;
case TRANS_TCP:
ok1 = !(cfgst->cfg->compat_tcp_enable == BOOLDEF_FALSE || cfgst->cfg->compat_use_ipv6 == BOOLDEF_TRUE);
@@ -2765,7 +2822,7 @@ struct cfgst * config_init (const char *configfile)
break;
}
if (!ok1)
- DDS_ERROR("config: invalid combination of Transport, IPv6, TCP\n");
+ DDS_ILOG (DDS_LC_ERROR, domid, "config: invalid combination of Transport, IPv6, TCP\n");
ok = ok && ok1;
cfgst->cfg->compat_use_ipv6 = (cfgst->cfg->transport_selector == TRANS_UDP6 || cfgst->cfg->transport_selector == TRANS_TCP6) ? BOOLDEF_TRUE : BOOLDEF_FALSE;
cfgst->cfg->compat_tcp_enable = (cfgst->cfg->transport_selector == TRANS_TCP || cfgst->cfg->transport_selector == TRANS_TCP6) ? BOOLDEF_TRUE : BOOLDEF_FALSE;
@@ -2774,36 +2831,37 @@ struct cfgst * config_init (const char *configfile)
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
/* Default channel gets set outside set_defaults -- a bit too
complicated for the poor framework */
-
- if ( set_default_channel(cfgst->cfg) < 0 ) {
+ if (set_default_channel (cfgst->cfg) < 0)
ok = 0;
- }
- if ( cfgst->cfg->channels && sort_channels_check_nodups(cfgst->cfg) < 0 ) {
+ if (cfgst->cfg->channels && sort_channels_check_nodups (cfgst->cfg) < 0)
ok = 0;
- }
#endif
#ifdef DDSI_INCLUDE_ENCRYPTION
/* Check security profiles */
{
- struct config_securityprofile_listelem *s = config.securityProfiles;
- while ( s ) {
- switch ( s->cipher ) {
+ struct config_securityprofile_listelem *s = cfgst->cfg->securityProfiles;
+ while (s)
+ {
+ switch (s->cipher)
+ {
case Q_CIPHER_UNDEFINED:
case Q_CIPHER_NULL:
/* nop */
- if ( s->key && strlen(s->key) > 0 ) {
- DDS_INFO("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: %s: cipher key not required\n", s->key);
- }
+ if (s->key && strlen(s->key) > 0)
+ DDS_ILOG (DDS_LC_INFO, domid, "config: DDSI2Service/Security/SecurityProfile[@cipherkey]: %s: cipher key not required\n", s->key);
break;
default:
/* read the cipherkey if present */
- if ( !s->key || strlen(s->key) == 0 ) {
- DDS_ERROR("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: cipher key missing\n");
+ if (!s->key || strlen(s->key) == 0)
+ {
+ DDS_ILOG (DDS_LC_ERROR, domid, "config: DDSI2Service/Security/SecurityProfile[@cipherkey]: cipher key missing\n");
ok = 0;
- } else if ( q_security_plugin.valid_uri && !(q_security_plugin.valid_uri) (s->cipher, s->key) ) {
- DDS_ERROR("config: DDSI2Service/Security/SecurityProfile[@cipherkey]: %s : incorrect key\n", s->key);
+ }
+ else if (q_security_plugin.valid_uri && !(q_security_plugin.valid_uri) (s->cipher, s->key))
+ {
+ DDS_ILOG (DDS_LC_ERROR, domid, "config: DDSI2Service/Security/SecurityProfile[@cipherkey]: %s : incorrect key\n", s->key);
ok = 0;
}
}
@@ -2819,30 +2877,33 @@ struct cfgst * config_init (const char *configfile)
securityProfiles and signal errors if profiles do not exist */
#endif /* DDSI_INCLUDE_ENCRYPTION */
{
- struct config_networkpartition_listelem *p = config.networkPartitions;
- config.nof_networkPartitions = 0;
- while ( p ) {
+ struct config_networkpartition_listelem *p = cfgst->cfg->networkPartitions;
+ cfgst->cfg->nof_networkPartitions = 0;
+ while (p)
+ {
#ifdef DDSI_INCLUDE_ENCRYPTION
- if ( ddsrt_strcasecmp(p->profileName, "null") == 0 )
+ if (ddsrt_strcasecmp(p->profileName, "null") == 0)
p->securityProfile = NULL;
- else {
- struct config_securityprofile_listelem *s = config.securityProfiles;
- while ( s && ddsrt_strcasecmp(p->profileName, s->name) != 0 )
+ else
+ {
+ struct config_securityprofile_listelem *s = cfgst->cfg->securityProfiles;
+ while (s && ddsrt_strcasecmp(p->profileName, s->name) != 0)
s = s->next;
- if ( s )
+ if (s)
p->securityProfile = s;
- else {
- DDS_ERROR("config: DDSI2Service/Partitioning/NetworkPartitions/NetworkPartition[@securityprofile]: %s: unknown securityprofile\n", p->profileName);
+ else
+ {
+ DDS_ILOG (DDS_LC_ERROR, domid, "config: DDSI2Service/Partitioning/NetworkPartitions/NetworkPartition[@securityprofile]: %s: unknown securityprofile\n", p->profileName);
ok = 0;
}
}
#endif /* DDSI_INCLUDE_ENCRYPTION */
- config.nof_networkPartitions++;
+ cfgst->cfg->nof_networkPartitions++;
/* also use crc32 just like native nw and ordinary ddsi2e, only
for interoperability because it is asking for trouble &
forces us to include a crc32 routine when we have md5
available anyway */
- p->partitionId = config.nof_networkPartitions; /* starting at 1 */
+ p->partitionId = cfgst->cfg->nof_networkPartitions; /* starting at 1 */
p->partitionHash = crc32_calc(p->name, strlen(p->name));
p = p->next;
}
@@ -2851,16 +2912,17 @@ struct cfgst * config_init (const char *configfile)
/* Create links from the partitionmappings to the network partitions
and signal errors if partitions do not exist */
{
- struct config_partitionmapping_listelem * m = config.partitionMappings;
- while ( m ) {
- struct config_networkpartition_listelem * p = config.networkPartitions;
- while ( p && ddsrt_strcasecmp(m->networkPartition, p->name) != 0 ) {
+ struct config_partitionmapping_listelem * m = cfgst->cfg->partitionMappings;
+ while (m)
+ {
+ struct config_networkpartition_listelem * p = cfgst->cfg->networkPartitions;
+ while (p && ddsrt_strcasecmp(m->networkPartition, p->name) != 0)
p = p->next;
- }
- if ( p ) {
+ if (p)
m->partition = p;
- } else {
- DDS_ERROR("config: DDSI2Service/Partitioning/PartitionMappings/PartitionMapping[@networkpartition]: %s: unknown partition\n", m->networkPartition);
+ else
+ {
+ DDS_ILOG (DDS_LC_ERROR, domid, "config: DDSI2Service/Partitioning/PartitionMappings/PartitionMapping[@networkpartition]: %s: unknown partition\n", m->networkPartition);
ok = 0;
}
m = m->next;
@@ -2868,104 +2930,107 @@ struct cfgst * config_init (const char *configfile)
}
#endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */
- /* Now switch to configured tracing settings */
- config.enabled_logcats = enabled_logcats;
-
- if ( !ok ) {
- free_configured_elements(cfgst, cfgst->cfg, root_cfgelems);
- }
-
- if ( ok ) {
- config.valid = 1;
+ if (ok)
+ {
+ cfgst->cfg->valid = 1;
return cfgst;
- } else {
- ddsrt_avl_free(&cfgst_found_treedef, &cfgst->found, ddsrt_free);
- ddsrt_free(cfgst);
- return NULL;
}
+
+error:
+ free_configured_elements (cfgst, cfgst->cfg, root_cfgelems);
+ ddsrt_avl_free (&cfgst_found_treedef, &cfgst->found, ddsrt_free);
+ ddsrt_free (cfgst);
+ return NULL;
}
-void config_print_cfgst(struct cfgst *cfgst)
+void config_print_cfgst (struct cfgst *cfgst, const struct ddsrt_log_cfg *logcfg)
{
- if ( cfgst == NULL )
+ if (cfgst == NULL)
return;
- print_configitems(cfgst, cfgst->cfg, 0, root_cfgelems, 0);
+ assert (cfgst->logcfg == NULL);
+ cfgst->logcfg = logcfg;
+ print_configitems (cfgst, cfgst->cfg, 0, root_cfgelems, 0);
}
-void config_fini(struct cfgst *cfgst)
+void config_free_source_info (struct cfgst *cfgst)
{
- assert(cfgst);
- assert(cfgst->cfg == &config);
- assert(config.valid);
+ assert (!cfgst->error);
+ ddsrt_avl_free (&cfgst_found_treedef, &cfgst->found, ddsrt_free);
+}
- free_all_elements(cfgst, cfgst->cfg, root_cfgelems);
- dds_set_log_file(stderr);
- dds_set_trace_file(stderr);
- if (config.tracingOutputFile && config.tracingOutputFile != stdout && config.tracingOutputFile != stderr) {
- fclose(config.tracingOutputFile);
+void config_fini (struct cfgst *cfgst)
+{
+ assert (cfgst);
+ assert (cfgst->cfg != NULL);
+ assert (cfgst->cfg->valid);
+
+ free_all_elements (cfgst, cfgst->cfg, root_cfgelems);
+ dds_set_log_file (stderr);
+ dds_set_trace_file (stderr);
+ if (cfgst->cfg->tracefp && cfgst->cfg->tracefp != stdout && cfgst->cfg->tracefp != stderr) {
+ fclose(cfgst->cfg->tracefp);
}
- memset(&config, 0, sizeof(config));
- config.valid = 0;
-
- ddsrt_avl_free(&cfgst_found_treedef, &cfgst->found, ddsrt_free);
- ddsrt_free(cfgst);
+ memset (cfgst->cfg, 0, sizeof (*cfgst->cfg));
+ ddsrt_avl_free (&cfgst_found_treedef, &cfgst->found, ddsrt_free);
+ ddsrt_free (cfgst);
}
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
-static char *get_partition_search_pattern(const char *partition, const char *topic)
+static char *get_partition_search_pattern (const char *partition, const char *topic)
{
- size_t sz = strlen(partition) + strlen(topic) + 2;
- char *pt = ddsrt_malloc(sz);
- snprintf(pt, sz, "%s.%s", partition, topic);
+ size_t sz = strlen (partition) + strlen (topic) + 2;
+ char *pt = ddsrt_malloc (sz);
+ snprintf (pt, sz, "%s.%s", partition, topic);
return pt;
}
-struct config_partitionmapping_listelem *find_partitionmapping(const char *partition, const char *topic)
+struct config_partitionmapping_listelem *find_partitionmapping (const struct config *cfg, const char *partition, const char *topic)
{
- char *pt = get_partition_search_pattern(partition, topic);
+ char *pt = get_partition_search_pattern (partition, topic);
struct config_partitionmapping_listelem *pm;
- for ( pm = config.partitionMappings; pm; pm = pm->next )
- if ( WildcardOverlap(pt, pm->DCPSPartitionTopic) )
+ for (pm = cfg->partitionMappings; pm; pm = pm->next)
+ if (WildcardOverlap (pt, pm->DCPSPartitionTopic))
break;
- ddsrt_free(pt);
+ ddsrt_free (pt);
return pm;
}
-struct config_networkpartition_listelem *find_networkpartition_by_id(uint32_t id)
+struct config_networkpartition_listelem *find_networkpartition_by_id (const struct config *cfg, uint32_t id)
{
struct config_networkpartition_listelem *np;
- for ( np = config.networkPartitions; np; np = np->next )
- if ( np->partitionId == id )
+ for (np = cfg->networkPartitions; np; np = np->next)
+ if (np->partitionId == id)
return np;
return 0;
}
-int is_ignored_partition(const char *partition, const char *topic)
+int is_ignored_partition (const struct config *cfg, const char *partition, const char *topic)
{
- char *pt = get_partition_search_pattern(partition, topic);
+ char *pt = get_partition_search_pattern (partition, topic);
struct config_ignoredpartition_listelem *ip;
- for ( ip = config.ignoredPartitions; ip; ip = ip->next )
- if ( WildcardOverlap(pt, ip->DCPSPartitionTopic) )
+ for (ip = cfg->ignoredPartitions; ip; ip = ip->next)
+ if (WildcardOverlap(pt, ip->DCPSPartitionTopic))
break;
- ddsrt_free(pt);
+ ddsrt_free (pt);
return ip != NULL;
}
#endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
-struct config_channel_listelem *find_channel(nn_transport_priority_qospolicy_t transport_priority)
+struct config_channel_listelem *find_channel (const struct config *cfg, nn_transport_priority_qospolicy_t transport_priority)
{
struct config_channel_listelem *c;
/* Channel selection is to use the channel with the lowest priority
not less than transport_priority, or else the one with the
highest priority. */
- assert(config.channels != NULL);
- assert(config.max_channel != NULL);
- for ( c = config.channels; c; c = c->next ) {
+ assert(cfg->channels != NULL);
+ assert(cfg->max_channel != NULL);
+ for (c = cfg->channels; c; c = c->next)
+ {
assert(c->next == NULL || c->next->priority > c->priority);
- if ( transport_priority.value <= c->priority )
+ if (transport_priority.value <= c->priority)
return c;
}
- return config.max_channel;
+ return cfg->max_channel;
}
#endif /* DDSI_INCLUDE_NETWORK_CHANNELS */
diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c
index 8a75416..227c961 100644
--- a/src/core/ddsi/src/q_ddsi_discovery.c
+++ b/src/core/ddsi/src/q_ddsi_discovery.c
@@ -40,11 +40,10 @@
#include "dds/ddsi/q_bswap.h"
#include "dds/ddsi/q_transmit.h"
#include "dds/ddsi/q_lease.h"
-#include "dds/ddsi/q_error.h"
#include "dds/ddsi/ddsi_serdata_default.h"
#include "dds/ddsi/q_feature_check.h"
-static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_same_subnet)
+static int get_locator (const struct q_globals *gv, nn_locator_t *loc, const nn_locators_t *locs, int uc_same_subnet)
{
struct nn_locators_one *l;
nn_locator_t first, samenet;
@@ -53,7 +52,7 @@ static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_sam
memset (&samenet, 0, sizeof (samenet));
/* Special case UDPv4 MC address generators - there is a bit of an type mismatch between an address generator (i.e., a set of addresses) and an address ... Whoever uses them is supposed to know that that is what he wants, so we simply given them priority. */
- if (ddsi_factory_supports (gv.m_factory, NN_LOCATOR_KIND_UDPv4))
+ if (ddsi_factory_supports (gv->m_factory, NN_LOCATOR_KIND_UDPv4))
{
for (l = locs->first; l != NULL; l = l->next)
{
@@ -72,20 +71,20 @@ static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_sam
{
/* Skip locators of the wrong kind */
- if (! ddsi_factory_supports (gv.m_factory, l->loc.kind))
+ if (! ddsi_factory_supports (gv->m_factory, l->loc.kind))
{
continue;
}
- if (l->loc.kind == NN_LOCATOR_KIND_UDPv4 && gv.extmask.kind != NN_LOCATOR_KIND_INVALID)
+ if (l->loc.kind == NN_LOCATOR_KIND_UDPv4 && gv->extmask.kind != NN_LOCATOR_KIND_INVALID)
{
/* If the examined locator is in the same subnet as our own
external IP address, this locator will be translated into one
in the same subnet as our own local ip and selected. */
struct in_addr tmp4 = *((struct in_addr *) (l->loc.address + 12));
- const struct in_addr ownip = *((struct in_addr *) (gv.ownloc.address + 12));
- const struct in_addr extip = *((struct in_addr *) (gv.extloc.address + 12));
- const struct in_addr extmask = *((struct in_addr *) (gv.extmask.address + 12));
+ const struct in_addr ownip = *((struct in_addr *) (gv->ownloc.address + 12));
+ const struct in_addr extip = *((struct in_addr *) (gv->extloc.address + 12));
+ const struct in_addr extmask = *((struct in_addr *) (gv->extmask.address + 12));
if ((tmp4.s_addr & extmask.s_addr) == (extip.s_addr & extmask.s_addr))
{
@@ -105,7 +104,7 @@ static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_sam
addresses unles we're in "link-local" mode ourselves. Then
we just hope for the best. */
const struct in6_addr *ip6 = (const struct in6_addr *) l->loc.address;
- if (!gv.ipv6_link_local && IN6_IS_ADDR_LINKLOCAL (ip6))
+ if (!gv->ipv6_link_local && IN6_IS_ADDR_LINKLOCAL (ip6))
continue;
}
#endif
@@ -116,7 +115,7 @@ static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_sam
first_set = 1;
}
- switch (ddsi_is_nearby_address(&l->loc, (size_t)gv.n_interfaces, gv.interfaces))
+ switch (ddsi_is_nearby_address(gv, &l->loc, &gv->ownloc, (size_t) gv->n_interfaces, gv->interfaces))
{
case DNAR_DISTANT:
break;
@@ -158,14 +157,14 @@ static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_sam
***
*****************************************************************************/
-static void maybe_add_pp_as_meta_to_as_disc (const struct addrset *as_meta)
+static void maybe_add_pp_as_meta_to_as_disc (struct q_globals *gv, const struct addrset *as_meta)
{
- if (addrset_empty_mc (as_meta) || !(config.allowMulticast & AMC_SPDP))
+ if (addrset_empty_mc (as_meta) || !(gv->config.allowMulticast & AMC_SPDP))
{
nn_locator_t loc;
if (addrset_any_uc (as_meta, &loc))
{
- add_to_addrset (gv.as_disc, &loc);
+ add_to_addrset (gv, gv->as_disc, &loc);
}
}
}
@@ -176,7 +175,7 @@ static int write_mpayload (struct writer *wr, int alive, nn_parameterid_t keypar
struct ddsi_plist_sample plist_sample;
struct ddsi_serdata *serdata;
nn_xmsg_payload_to_plistsample (&plist_sample, keyparam, mpayload);
- serdata = ddsi_serdata_from_sample (gv.plist_topic, alive ? SDK_DATA : SDK_KEY, &plist_sample);
+ serdata = ddsi_serdata_from_sample (wr->e.gv->plist_topic, alive ? SDK_DATA : SDK_KEY, &plist_sample);
serdata->statusinfo = alive ? 0 : NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER;
serdata->timestamp = now ();
return write_sample_nogc_notk (ts1, NULL, wr, serdata);
@@ -198,11 +197,11 @@ int spdp_write (struct participant *pp)
return 0;
}
- DDS_TRACE("spdp_write("PGUIDFMT")\n", PGUID (pp->e.guid));
+ ETRACE (pp, "spdp_write("PGUIDFMT")\n", PGUID (pp->e.guid));
if ((wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL)
{
- DDS_TRACE("spdp_write("PGUIDFMT") - builtin participant writer not found\n", PGUID (pp->e.guid));
+ ETRACE (pp, "spdp_write("PGUIDFMT") - builtin participant writer not found\n", PGUID (pp->e.guid));
return 0;
}
@@ -212,7 +211,7 @@ int spdp_write (struct participant *pp)
terribly important, the msg will grow as needed, address space is
essentially meaningless because we only use the message to
construct the payload. */
- mpayload = nn_xmsg_new (gv.xmsgpool, &pp->e.guid.prefix, 0, NN_XMSG_KIND_DATA);
+ mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid.prefix, 0, NN_XMSG_KIND_DATA);
nn_plist_init_empty (&ps);
ps.present |= PP_PARTICIPANT_GUID | PP_BUILTIN_ENDPOINT_SET |
@@ -236,24 +235,24 @@ int spdp_write (struct participant *pp)
def_uni_loc_one.next = NULL;
meta_uni_loc_one.next = NULL;
- if (config.many_sockets_mode == MSM_MANY_UNICAST)
+ if (pp->e.gv->config.many_sockets_mode == MSM_MANY_UNICAST)
{
def_uni_loc_one.loc = pp->m_locator;
meta_uni_loc_one.loc = pp->m_locator;
}
else
{
- def_uni_loc_one.loc = gv.loc_default_uc;
- meta_uni_loc_one.loc = gv.loc_meta_uc;
+ def_uni_loc_one.loc = pp->e.gv->loc_default_uc;
+ meta_uni_loc_one.loc = pp->e.gv->loc_meta_uc;
}
- if (config.publish_uc_locators)
+ if (pp->e.gv->config.publish_uc_locators)
{
ps.present |= PP_DEFAULT_UNICAST_LOCATOR | PP_METATRAFFIC_UNICAST_LOCATOR;
ps.aliased |= PP_DEFAULT_UNICAST_LOCATOR | PP_METATRAFFIC_UNICAST_LOCATOR;
}
- if (config.allowMulticast)
+ if (pp->e.gv->config.allowMulticast)
{
int include = 0;
#ifdef DDSI_INCLUDE_SSM
@@ -261,12 +260,12 @@ int spdp_write (struct participant *pp)
we will simply advertise it. The recipients better understand
it means the writers will publish to address and the readers
favour SSM. */
- if (ddsi_is_ssm_mcaddr (&gv.loc_default_mc))
- include = (config.allowMulticast & AMC_SSM) != 0;
+ if (ddsi_is_ssm_mcaddr (pp->e.gv, &pp->e.gv->loc_default_mc))
+ include = (pp->e.gv->config.allowMulticast & AMC_SSM) != 0;
else
- include = (config.allowMulticast & AMC_ASM) != 0;
+ include = (pp->e.gv->config.allowMulticast & AMC_ASM) != 0;
#else
- if (config.allowMulticast & AMC_ASM)
+ if (pp->e.gv->config.allowMulticast & AMC_ASM)
include = 1;
#endif
if (include)
@@ -280,39 +279,40 @@ int spdp_write (struct participant *pp)
ps.metatraffic_multicast_locators.first =
ps.metatraffic_multicast_locators.last = &meta_multi_loc_one;
def_multi_loc_one.next = NULL;
- def_multi_loc_one.loc = gv.loc_default_mc;
+ def_multi_loc_one.loc = pp->e.gv->loc_default_mc;
meta_multi_loc_one.next = NULL;
- meta_multi_loc_one.loc = gv.loc_meta_mc;
+ meta_multi_loc_one.loc = pp->e.gv->loc_meta_mc;
}
}
- ps.participant_lease_duration = nn_to_ddsi_duration (pp->lease_duration);
+ ps.participant_lease_duration = pp->lease_duration;
/* Add PrismTech specific version information */
{
ps.present |= PP_PRISMTECH_PARTICIPANT_VERSION_INFO;
+ memset (&ps.prismtech_participant_version_info, 0, sizeof (ps.prismtech_participant_version_info));
ps.prismtech_participant_version_info.version = 0;
ps.prismtech_participant_version_info.flags =
NN_PRISMTECH_FL_DDSI2_PARTICIPANT_FLAG |
NN_PRISMTECH_FL_PTBES_FIXED_0 |
NN_PRISMTECH_FL_SUPPORTS_STATUSINFOX;
- if (config.besmode == BESMODE_MINIMAL)
+ if (pp->e.gv->config.besmode == BESMODE_MINIMAL)
ps.prismtech_participant_version_info.flags |= NN_PRISMTECH_FL_MINIMAL_BES_MODE;
- ddsrt_mutex_lock (&gv.privileged_pp_lock);
+ ddsrt_mutex_lock (&pp->e.gv->privileged_pp_lock);
if (pp->is_ddsi2_pp)
ps.prismtech_participant_version_info.flags |= NN_PRISMTECH_FL_PARTICIPANT_IS_DDSI2;
- ddsrt_mutex_unlock (&gv.privileged_pp_lock);
+ ddsrt_mutex_unlock (&pp->e.gv->privileged_pp_lock);
ddsrt_gethostname(node, sizeof(node)-1);
node[sizeof(node)-1] = '\0';
size = strlen(node) + strlen(DDS_VERSION) + strlen(DDS_HOST_NAME) + strlen(DDS_TARGET_NAME) + 4; /* + ///'\0' */
ps.prismtech_participant_version_info.internals = ddsrt_malloc(size);
(void) snprintf(ps.prismtech_participant_version_info.internals, size, "%s/%s/%s/%s", node, DDS_VERSION, DDS_HOST_NAME, DDS_TARGET_NAME);
- DDS_TRACE("spdp_write("PGUIDFMT") - internals: %s\n", PGUID (pp->e.guid), ps.prismtech_participant_version_info.internals);
+ ETRACE (pp, "spdp_write("PGUIDFMT") - internals: %s\n", PGUID (pp->e.guid), ps.prismtech_participant_version_info.internals);
}
/* Participant QoS's insofar as they are set, different from the default, and mapped to the SPDP data, rather than to the PrismTech-specific CMParticipant endpoint. Currently, that means just USER_DATA. */
- qosdiff = nn_xqos_delta (&pp->plist->qos, &gv.default_plist_pp.qos, QP_USER_DATA);
- if (config.explicitly_publish_qos_set_to_default)
+ qosdiff = nn_xqos_delta (&pp->plist->qos, &pp->e.gv->default_plist_pp.qos, QP_USER_DATA);
+ if (pp->e.gv->config.explicitly_publish_qos_set_to_default)
qosdiff |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK;
assert (ps.qos.present == 0);
@@ -335,11 +335,11 @@ int spdp_dispose_unregister (struct participant *pp)
if ((wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL)
{
- DDS_TRACE("spdp_dispose_unregister("PGUIDFMT") - builtin participant writer not found\n", PGUID (pp->e.guid));
+ ETRACE (pp, "spdp_dispose_unregister("PGUIDFMT") - builtin participant writer not found\n", PGUID (pp->e.guid));
return 0;
}
- mpayload = nn_xmsg_new (gv.xmsgpool, &pp->e.guid.prefix, 0, NN_XMSG_KIND_DATA);
+ mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid.prefix, 0, NN_XMSG_KIND_DATA);
nn_plist_init_empty (&ps);
ps.present |= PP_PARTICIPANT_GUID;
ps.participant_guid = pp->e.guid;
@@ -381,84 +381,85 @@ static unsigned pseudo_random_delay (const nn_guid_t *x, const nn_guid_t *y, nn_
return (unsigned) (m >> 32);
}
-static void respond_to_spdp (const nn_guid_t *dest_proxypp_guid)
+static void respond_to_spdp (const struct q_globals *gv, const nn_guid_t *dest_proxypp_guid)
{
struct ephash_enum_participant est;
struct participant *pp;
nn_mtime_t tnow = now_mt ();
- ephash_enum_participant_init (&est);
+ ephash_enum_participant_init (&est, gv->guid_hash);
while ((pp = ephash_enum_participant_next (&est)) != NULL)
{
/* delay_base has 32 bits, so delay_norm is approximately 1s max;
- delay_max <= 1s by config checks */
+ delay_max <= 1s by gv.config checks */
unsigned delay_base = pseudo_random_delay (&pp->e.guid, dest_proxypp_guid, tnow);
unsigned delay_norm = delay_base >> 2;
- int64_t delay_max_ms = config.spdp_response_delay_max / 1000000;
+ int64_t delay_max_ms = gv->config.spdp_response_delay_max / 1000000;
int64_t delay = (int64_t) delay_norm * delay_max_ms / 1000;
nn_mtime_t tsched = add_duration_to_mtime (tnow, delay);
- DDS_TRACE(" %"PRId64, delay);
- if (!config.unicast_response_to_spdp_messages)
+ GVTRACE (" %"PRId64, delay);
+ if (!pp->e.gv->config.unicast_response_to_spdp_messages)
/* pp can't reach gc_delete_participant => can safely reschedule */
resched_xevent_if_earlier (pp->spdp_xevent, tsched);
else
- qxev_spdp (tsched, &pp->e.guid, dest_proxypp_guid);
+ qxev_spdp (gv->xevents, tsched, &pp->e.guid, dest_proxypp_guid);
}
ephash_enum_participant_fini (&est);
}
static int handle_SPDP_dead (const struct receiver_state *rst, nn_wctime_t timestamp, const nn_plist_t *datap, unsigned statusinfo)
{
+ struct q_globals * const gv = rst->gv;
nn_guid_t guid;
- if (!(dds_get_log_mask() & DDS_LC_DISCOVERY))
- DDS_LOG(DDS_LC_DISCOVERY, "SPDP ST%x", statusinfo);
+ if (!(gv->logconfig.c.mask & DDS_LC_DISCOVERY))
+ GVLOGDISC ("SPDP ST%x", statusinfo);
if (datap->present & PP_PARTICIPANT_GUID)
{
guid = datap->participant_guid;
- DDS_LOG(DDS_LC_DISCOVERY, " %"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32, PGUID (guid));
+ GVLOGDISC (" %"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32, PGUID (guid));
assert (guid.entityid.u == NN_ENTITYID_PARTICIPANT);
- if (delete_proxy_participant_by_guid (&guid, timestamp, 0) < 0)
+ if (delete_proxy_participant_by_guid (gv, &guid, timestamp, 0) < 0)
{
- DDS_LOG(DDS_LC_DISCOVERY, " unknown");
+ GVLOGDISC (" unknown");
}
else
{
- DDS_LOG(DDS_LC_DISCOVERY, " delete");
+ GVLOGDISC (" delete");
}
}
else
{
- DDS_WARNING("data (SPDP, vendor %u.%u): no/invalid payload\n", rst->vendor.id[0], rst->vendor.id[1]);
+ GVWARNING ("data (SPDP, vendor %u.%u): no/invalid payload\n", rst->vendor.id[0], rst->vendor.id[1]);
}
return 1;
}
-static void allowmulticast_aware_add_to_addrset (struct addrset *as, const nn_locator_t *loc)
+static void allowmulticast_aware_add_to_addrset (const struct q_globals *gv, uint32_t allow_multicast, struct addrset *as, const nn_locator_t *loc)
{
#if DDSI_INCLUDE_SSM
- if (ddsi_is_ssm_mcaddr (loc))
+ if (ddsi_is_ssm_mcaddr (gv, loc))
{
- if (!(config.allowMulticast & AMC_SSM))
+ if (!(allow_multicast & AMC_SSM))
return;
}
- else if (ddsi_is_mcaddr (loc))
+ else if (ddsi_is_mcaddr (gv, loc))
{
- if (!(config.allowMulticast & AMC_ASM))
+ if (!(allow_multicast & AMC_ASM))
return;
}
#else
- if (ddsi_is_mcaddr (loc) && !(config.allowMulticast & AMC_ASM))
+ if (ddsi_is_mcaddr (gv, loc) && !(allow_multicast & AMC_ASM))
return;
#endif
- add_to_addrset (as, loc);
+ add_to_addrset (gv, as, loc);
}
-static struct proxy_participant *find_ddsi2_proxy_participant (const nn_guid_t *ppguid)
+static struct proxy_participant *find_ddsi2_proxy_participant (const struct ephash *guid_hash, const nn_guid_t *ppguid)
{
struct ephash_enum_proxy_participant it;
struct proxy_participant *pp;
- ephash_enum_proxy_participant_init (&it);
+ ephash_enum_proxy_participant_init (&it, guid_hash);
while ((pp = ephash_enum_proxy_participant_next (&it)) != NULL)
{
if (vendor_is_eclipse_or_opensplice (pp->vendor) && pp->e.guid.prefix.u[0] == ppguid->prefix.u[0] && pp->is_ddsi2_pp)
@@ -468,27 +469,27 @@ static struct proxy_participant *find_ddsi2_proxy_participant (const nn_guid_t *
return pp;
}
-static void make_participants_dependent_on_ddsi2 (const nn_guid_t *ddsi2guid, nn_wctime_t timestamp)
+static void make_participants_dependent_on_ddsi2 (struct q_globals *gv, const nn_guid_t *ddsi2guid, nn_wctime_t timestamp)
{
struct ephash_enum_proxy_participant it;
struct proxy_participant *pp, *d2pp;
struct lease *d2pp_lease;
- if ((d2pp = ephash_lookup_proxy_participant_guid (ddsi2guid)) == NULL)
+ if ((d2pp = ephash_lookup_proxy_participant_guid (gv->guid_hash, ddsi2guid)) == NULL)
return;
d2pp_lease = ddsrt_atomic_ldvoidp (&d2pp->lease);
- ephash_enum_proxy_participant_init (&it);
+ ephash_enum_proxy_participant_init (&it, gv->guid_hash);
while ((pp = ephash_enum_proxy_participant_next (&it)) != NULL)
{
if (vendor_is_eclipse_or_opensplice (pp->vendor) && pp->e.guid.prefix.u[0] == ddsi2guid->prefix.u[0] && !pp->is_ddsi2_pp)
{
- DDS_TRACE("proxy participant "PGUIDFMT" depends on ddsi2 "PGUIDFMT, PGUID (pp->e.guid), PGUID (*ddsi2guid));
+ GVTRACE ("proxy participant "PGUIDFMT" depends on ddsi2 "PGUIDFMT, PGUID (pp->e.guid), PGUID (*ddsi2guid));
ddsrt_mutex_lock (&pp->e.lock);
pp->privileged_pp_guid = *ddsi2guid;
ddsrt_mutex_unlock (&pp->e.lock);
proxy_participant_reassign_lease (pp, d2pp_lease);
- DDS_TRACE("\n");
+ GVTRACE ("\n");
- if (ephash_lookup_proxy_participant_guid (ddsi2guid) == NULL)
+ if (ephash_lookup_proxy_participant_guid (gv->guid_hash, ddsi2guid) == NULL)
{
/* If DDSI2 has been deleted here (i.e., very soon after
having been created), we don't know whether pp will be
@@ -501,13 +502,14 @@ static void make_participants_dependent_on_ddsi2 (const nn_guid_t *ddsi2guid, nn
if (pp != NULL)
{
- DDS_TRACE("make_participants_dependent_on_ddsi2: ddsi2 "PGUIDFMT" is no more, delete "PGUIDFMT"\n", PGUID (*ddsi2guid), PGUID (pp->e.guid));
- delete_proxy_participant_by_guid (&pp->e.guid, timestamp, 1);
+ GVTRACE ("make_participants_dependent_on_ddsi2: ddsi2 "PGUIDFMT" is no more, delete "PGUIDFMT"\n", PGUID (*ddsi2guid), PGUID (pp->e.guid));
+ delete_proxy_participant_by_guid (gv, &pp->e.guid, timestamp, 1);
}
}
-static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t timestamp, const nn_plist_t *datap)
+static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_wctime_t timestamp, const nn_plist_t *datap)
{
+ struct q_globals * const gv = rst->gv;
const unsigned bes_sedp_announcer_mask =
NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER |
NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER;
@@ -516,12 +518,12 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time
unsigned builtin_endpoint_set;
unsigned prismtech_builtin_endpoint_set;
nn_guid_t privileged_pp_guid;
- nn_duration_t lease_duration;
+ dds_duration_t lease_duration;
unsigned custom_flags = 0;
if (!(datap->present & PP_PARTICIPANT_GUID) || !(datap->present & PP_BUILTIN_ENDPOINT_SET))
{
- DDS_WARNING("data (SPDP, vendor %u.%u): no/invalid payload\n", rst->vendor.id[0], rst->vendor.id[1]);
+ GVWARNING ("data (SPDP, vendor %u.%u): no/invalid payload\n", rst->vendor.id[0], rst->vendor.id[1]);
return 1;
}
@@ -537,10 +539,10 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time
NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER))
!= (NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER |
NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER)) &&
- config.assume_rti_has_pmd_endpoints)
+ gv->config.assume_rti_has_pmd_endpoints)
{
- DDS_LOG(DDS_LC_DISCOVERY, "data (SPDP, vendor %u.%u): assuming unadvertised PMD endpoints do exist\n",
- rst->vendor.id[0], rst->vendor.id[1]);
+ GVLOGDISC ("data (SPDP, vendor %u.%u): assuming unadvertised PMD endpoints do exist\n",
+ rst->vendor.id[0], rst->vendor.id[1]);
builtin_endpoint_set |=
NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER |
NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER;
@@ -554,7 +556,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time
but it would cause problems with cases where we would be happy with only
(say) CM participant. Have to do a backwards-compatible fix because it has
already been released with the flags all aliased to bits 0 and 1 ... */
- DDS_LOG(DDS_LC_DISCOVERY, " (ptbes_fixed_0 %x)", prismtech_builtin_endpoint_set);
+ GVLOGDISC (" (ptbes_fixed_0 %x)", prismtech_builtin_endpoint_set);
if (prismtech_builtin_endpoint_set & NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_READER)
prismtech_builtin_endpoint_set |= NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_READER | NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_READER;
if (prismtech_builtin_endpoint_set & NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_WRITER)
@@ -567,43 +569,46 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time
consequently the looped back packet may appear to be from an
unknown participant. So we handle that, too. */
- if (is_deleted_participant_guid (&datap->participant_guid, DPG_REMOTE))
+ if (is_deleted_participant_guid (gv->deleted_participants, &datap->participant_guid, DPG_REMOTE))
{
- DDS_LOG(DDS_LC_TRACE, "SPDP ST0 "PGUIDFMT" (recently deleted)", PGUID (datap->participant_guid));
+ RSTTRACE ("SPDP ST0 "PGUIDFMT" (recently deleted)", PGUID (datap->participant_guid));
return 1;
}
{
int islocal = 0;
- if (ephash_lookup_participant_guid (&datap->participant_guid))
+ if (ephash_lookup_participant_guid (gv->guid_hash, &datap->participant_guid))
islocal = 1;
if (islocal)
{
- DDS_LOG(DDS_LC_TRACE, "SPDP ST0 "PGUIDFMT" (local %d)", PGUID (datap->participant_guid), islocal);
+ RSTTRACE ("SPDP ST0 "PGUIDFMT" (local %d)", PGUID (datap->participant_guid), islocal);
return 0;
}
}
- if ((proxypp = ephash_lookup_proxy_participant_guid (&datap->participant_guid)) != NULL)
+ if ((proxypp = ephash_lookup_proxy_participant_guid (gv->guid_hash, &datap->participant_guid)) != NULL)
{
/* SPDP processing is so different from normal processing that we
are even skipping the automatic lease renewal. Therefore do it
regardless of
- config.arrival_of_data_asserts_pp_and_ep_liveliness. */
- DDS_LOG(DDS_LC_TRACE, "SPDP ST0 "PGUIDFMT" (known)", PGUID (datap->participant_guid));
+ gv.config.arrival_of_data_asserts_pp_and_ep_liveliness. */
+ RSTTRACE ("SPDP ST0 "PGUIDFMT" (known)", PGUID (datap->participant_guid));
lease_renew (ddsrt_atomic_ldvoidp (&proxypp->lease), now_et ());
ddsrt_mutex_lock (&proxypp->e.lock);
- if (proxypp->implicitly_created)
+ if (proxypp->implicitly_created || seq > proxypp->seq)
{
- DDS_LOG(DDS_LC_DISCOVERY, " (NEW was-implicitly-created)");
+ if (proxypp->implicitly_created)
+ GVLOGDISC (" (NEW was-implicitly-created)");
+ else
+ GVLOGDISC (" (update)");
proxypp->implicitly_created = 0;
- update_proxy_participant_plist_locked (proxypp, datap, UPD_PROXYPP_SPDP, timestamp);
+ update_proxy_participant_plist_locked (proxypp, seq, datap, UPD_PROXYPP_SPDP, timestamp);
}
ddsrt_mutex_unlock (&proxypp->e.lock);
return 0;
}
- DDS_LOG(DDS_LC_DISCOVERY, "SPDP ST0 "PGUIDFMT" bes %x ptbes %x NEW", PGUID (datap->participant_guid), builtin_endpoint_set, prismtech_builtin_endpoint_set);
+ GVLOGDISC ("SPDP ST0 "PGUIDFMT" bes %x ptbes %x NEW", PGUID (datap->participant_guid), builtin_endpoint_set, prismtech_builtin_endpoint_set);
if (datap->present & PP_PARTICIPANT_LEASE_DURATION)
{
@@ -611,8 +616,8 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time
}
else
{
- DDS_LOG(DDS_LC_DISCOVERY, " (PARTICIPANT_LEASE_DURATION defaulting to 100s)");
- lease_duration = nn_to_ddsi_duration (100 * T_SECOND);
+ GVLOGDISC (" (PARTICIPANT_LEASE_DURATION defaulting to 100s)");
+ lease_duration = 100 * T_SECOND;
}
if (datap->present & PP_PRISMTECH_PARTICIPANT_VERSION_INFO) {
@@ -623,13 +628,13 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time
(datap->prismtech_participant_version_info.flags & NN_PRISMTECH_FL_PARTICIPANT_IS_DDSI2))
custom_flags |= CF_PARTICIPANT_IS_DDSI2;
- DDS_LOG(DDS_LC_DISCOVERY, " (0x%08x-0x%08x-0x%08x-0x%08x-0x%08x %s)",
- datap->prismtech_participant_version_info.version,
- datap->prismtech_participant_version_info.flags,
- datap->prismtech_participant_version_info.unused[0],
- datap->prismtech_participant_version_info.unused[1],
- datap->prismtech_participant_version_info.unused[2],
- datap->prismtech_participant_version_info.internals);
+ GVLOGDISC (" (0x%08x-0x%08x-0x%08x-0x%08x-0x%08x %s)",
+ datap->prismtech_participant_version_info.version,
+ datap->prismtech_participant_version_info.flags,
+ datap->prismtech_participant_version_info.unused[0],
+ datap->prismtech_participant_version_info.unused[1],
+ datap->prismtech_participant_version_info.unused[2],
+ datap->prismtech_participant_version_info.internals);
}
/* If any of the SEDP announcer are missing AND the guid prefix of
@@ -643,23 +648,23 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time
if ((builtin_endpoint_set & bes_sedp_announcer_mask) != bes_sedp_announcer_mask &&
memcmp (&privileged_pp_guid, &datap->participant_guid, sizeof (nn_guid_t)) != 0)
{
- DDS_LOG(DDS_LC_DISCOVERY, " (depends on "PGUIDFMT")", PGUID (privileged_pp_guid));
+ GVLOGDISC (" (depends on "PGUIDFMT")", PGUID (privileged_pp_guid));
/* never expire lease for this proxy: it won't actually expire
until the "privileged" one expires anyway */
- lease_duration = nn_to_ddsi_duration (T_NEVER);
+ lease_duration = T_NEVER;
}
else if (vendor_is_eclipse_or_opensplice (rst->vendor) && !(custom_flags & CF_PARTICIPANT_IS_DDSI2))
{
/* Non-DDSI2 participants are made dependent on DDSI2 (but DDSI2
itself need not be discovered yet) */
struct proxy_participant *ddsi2;
- if ((ddsi2 = find_ddsi2_proxy_participant (&datap->participant_guid)) == NULL)
+ if ((ddsi2 = find_ddsi2_proxy_participant (gv->guid_hash, &datap->participant_guid)) == NULL)
memset (&privileged_pp_guid.prefix, 0, sizeof (privileged_pp_guid.prefix));
else
{
privileged_pp_guid.prefix = ddsi2->e.guid.prefix;
- lease_duration = nn_to_ddsi_duration (T_NEVER);
- DDS_LOG(DDS_LC_DISCOVERY, " (depends on "PGUIDFMT")", PGUID (privileged_pp_guid));
+ lease_duration = T_NEVER;
+ GVLOGDISC (" (depends on "PGUIDFMT")", PGUID (privileged_pp_guid));
}
}
else
@@ -675,60 +680,61 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time
as_default = new_addrset ();
as_meta = new_addrset ();
- if ((datap->present & PP_DEFAULT_MULTICAST_LOCATOR) && (get_locator (&loc, &datap->default_multicast_locators, 0)))
- allowmulticast_aware_add_to_addrset (as_default, &loc);
- if ((datap->present & PP_METATRAFFIC_MULTICAST_LOCATOR) && (get_locator (&loc, &datap->metatraffic_multicast_locators, 0)))
- allowmulticast_aware_add_to_addrset (as_meta, &loc);
+ if ((datap->present & PP_DEFAULT_MULTICAST_LOCATOR) && (get_locator (gv, &loc, &datap->default_multicast_locators, 0)))
+ allowmulticast_aware_add_to_addrset (gv, gv->config.allowMulticast, as_default, &loc);
+ if ((datap->present & PP_METATRAFFIC_MULTICAST_LOCATOR) && (get_locator (gv, &loc, &datap->metatraffic_multicast_locators, 0)))
+ allowmulticast_aware_add_to_addrset (gv, gv->config.allowMulticast, as_meta, &loc);
/* If no multicast locators or multicast TTL > 1, assume IP (multicast) routing can be relied upon to reach
the remote participant, else only accept nodes with an advertised unicast address in the same subnet to
protect against multicasts being received over an unexpected interface (which sometimes appears to occur) */
if (addrset_empty_mc (as_default) && addrset_empty_mc (as_meta))
uc_same_subnet = 0;
- else if (config.multicast_ttl > 1)
+ else if (gv->config.multicast_ttl > 1)
uc_same_subnet = 0;
else
{
uc_same_subnet = 1;
- DDS_LOG(DDS_LC_DISCOVERY, " subnet-filter");
+ GVLOGDISC (" subnet-filter");
}
/* If unicast locators not present, then try to obtain from connection */
- if (!config.tcp_use_peeraddr_for_unicast && (datap->present & PP_DEFAULT_UNICAST_LOCATOR) && (get_locator (&loc, &datap->default_unicast_locators, uc_same_subnet)))
- add_to_addrset (as_default, &loc);
+ if (!gv->config.tcp_use_peeraddr_for_unicast && (datap->present & PP_DEFAULT_UNICAST_LOCATOR) && (get_locator (gv, &loc, &datap->default_unicast_locators, uc_same_subnet)))
+ add_to_addrset (gv, as_default, &loc);
else {
- DDS_LOG(DDS_LC_DISCOVERY, " (srclocD)");
- add_to_addrset (as_default, &rst->srcloc);
+ GVLOGDISC (" (srclocD)");
+ add_to_addrset (gv, as_default, &rst->srcloc);
}
- if (!config.tcp_use_peeraddr_for_unicast && (datap->present & PP_METATRAFFIC_UNICAST_LOCATOR) && (get_locator (&loc, &datap->metatraffic_unicast_locators, uc_same_subnet)))
- add_to_addrset (as_meta, &loc);
+ if (!gv->config.tcp_use_peeraddr_for_unicast && (datap->present & PP_METATRAFFIC_UNICAST_LOCATOR) && (get_locator (gv, &loc, &datap->metatraffic_unicast_locators, uc_same_subnet)))
+ add_to_addrset (gv, as_meta, &loc);
else {
- DDS_LOG(DDS_LC_DISCOVERY, " (srclocM)");
- add_to_addrset (as_meta, &rst->srcloc);
+ GVLOGDISC (" (srclocM)");
+ add_to_addrset (gv, as_meta, &rst->srcloc);
}
- nn_log_addrset(DDS_LC_DISCOVERY, " (data", as_default);
- nn_log_addrset(DDS_LC_DISCOVERY, " meta", as_meta);
- DDS_LOG(DDS_LC_DISCOVERY, ")");
+ nn_log_addrset (gv, DDS_LC_DISCOVERY, " (data", as_default);
+ nn_log_addrset (gv, DDS_LC_DISCOVERY, " meta", as_meta);
+ GVLOGDISC (")");
}
if (addrset_empty_uc (as_default) || addrset_empty_uc (as_meta))
{
- DDS_LOG(DDS_LC_DISCOVERY, " (no unicast address");
+ GVLOGDISC (" (no unicast address");
unref_addrset (as_default);
unref_addrset (as_meta);
return 1;
}
- DDS_LOG(DDS_LC_DISCOVERY, " QOS={");
- nn_log_xqos(DDS_LC_DISCOVERY, &datap->qos);
- DDS_LOG(DDS_LC_DISCOVERY, "}\n");
+ GVLOGDISC (" QOS={");
+ nn_log_xqos (DDS_LC_DISCOVERY, &gv->logconfig, &datap->qos);
+ GVLOGDISC ("}\n");
- maybe_add_pp_as_meta_to_as_disc (as_meta);
+ maybe_add_pp_as_meta_to_as_disc (gv, as_meta);
new_proxy_participant
(
+ gv,
&datap->participant_guid,
builtin_endpoint_set,
prismtech_builtin_endpoint_set,
@@ -736,10 +742,11 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time
as_default,
as_meta,
datap,
- nn_from_ddsi_duration (lease_duration),
+ lease_duration,
rst->vendor,
custom_flags,
- timestamp
+ timestamp,
+ seq
);
/* Force transmission of SPDP messages - we're not very careful
@@ -750,12 +757,12 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time
(rst->dst_guid_prefix.u[0] != 0 || rst->dst_guid_prefix.u[1] != 0 || rst->dst_guid_prefix.u[2] != 0);
if (!have_dst)
{
- DDS_LOG(DDS_LC_DISCOVERY, "broadcasted SPDP packet -> answering");
- respond_to_spdp (&datap->participant_guid);
+ GVLOGDISC ("broadcasted SPDP packet -> answering");
+ respond_to_spdp (gv, &datap->participant_guid);
}
else
{
- DDS_LOG(DDS_LC_DISCOVERY, "directed SPDP packet -> not responding\n");
+ GVLOGDISC ("directed SPDP packet -> not responding\n");
}
}
@@ -763,29 +770,31 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time
{
/* If we just discovered DDSI2, make sure any existing
participants served by it are made dependent on it */
- make_participants_dependent_on_ddsi2 (&datap->participant_guid, timestamp);
+ make_participants_dependent_on_ddsi2 (gv, &datap->participant_guid, timestamp);
}
else if (privileged_pp_guid.prefix.u[0] || privileged_pp_guid.prefix.u[1] || privileged_pp_guid.prefix.u[2])
{
/* If we just created a participant dependent on DDSI2, make sure
DDSI2 still exists. There is a risk of racing the lease expiry
of DDSI2. */
- if (ephash_lookup_proxy_participant_guid (&privileged_pp_guid) == NULL)
+ if (ephash_lookup_proxy_participant_guid (gv->guid_hash, &privileged_pp_guid) == NULL)
{
- DDS_LOG(DDS_LC_DISCOVERY, "make_participants_dependent_on_ddsi2: ddsi2 "PGUIDFMT" is no more, delete "PGUIDFMT"\n", PGUID (privileged_pp_guid), PGUID (datap->participant_guid));
- delete_proxy_participant_by_guid (&datap->participant_guid, timestamp, 1);
+ GVLOGDISC ("make_participants_dependent_on_ddsi2: ddsi2 "PGUIDFMT" is no more, delete "PGUIDFMT"\n",
+ PGUID (privileged_pp_guid), PGUID (datap->participant_guid));
+ delete_proxy_participant_by_guid (gv, &datap->participant_guid, timestamp, 1);
}
}
return 1;
}
-static void handle_SPDP (const struct receiver_state *rst, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len)
+static void handle_SPDP (const struct receiver_state *rst, seqno_t seq, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len)
{
+ struct q_globals * const gv = rst->gv;
const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */
- DDS_TRACE("SPDP ST%x", statusinfo);
+ RSTTRACE("SPDP ST%x", statusinfo);
if (data == NULL)
{
- DDS_TRACE(" no payload?\n");
+ RSTTRACE(" no payload?\n");
return;
}
else
@@ -793,23 +802,26 @@ static void handle_SPDP (const struct receiver_state *rst, nn_wctime_t timestamp
nn_plist_t decoded_data;
nn_plist_src_t src;
int interesting = 0;
- int plist_ret;
+ dds_return_t plist_ret;
src.protocol_version = rst->protocol_version;
src.vendorid = rst->vendor;
src.encoding = data->identifier;
src.buf = (unsigned char *) data + 4;
src.bufsz = len - 4;
+ src.strict = NN_STRICT_P (gv->config);
+ src.factory = gv->m_factory;
+ src.logconfig = &gv->logconfig;
if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0)
{
- if (plist_ret != Q_ERR_INCOMPATIBLE)
- DDS_WARNING("SPDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]);
+ if (plist_ret != DDS_RETCODE_UNSUPPORTED)
+ GVWARNING ("SPDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]);
return;
}
switch (statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER))
{
case 0:
- interesting = handle_SPDP_alive (rst, timestamp, &decoded_data);
+ interesting = handle_SPDP_alive (rst, seq, timestamp, &decoded_data);
break;
case NN_STATUSINFO_DISPOSE:
@@ -820,13 +832,18 @@ static void handle_SPDP (const struct receiver_state *rst, nn_wctime_t timestamp
}
nn_plist_fini (&decoded_data);
- DDS_LOG(interesting ? DDS_LC_DISCOVERY : DDS_LC_TRACE, "\n");
+ GVLOG (interesting ? DDS_LC_DISCOVERY : DDS_LC_TRACE, "\n");
}
}
-static void add_locator_to_ps (const nn_locator_t *loc, void *arg)
+struct add_locator_to_ps_arg {
+ struct q_globals *gv;
+ nn_plist_t *ps;
+};
+
+static void add_locator_to_ps (const nn_locator_t *loc, void *varg)
{
- nn_plist_t *ps = (nn_plist_t *) arg;
+ struct add_locator_to_ps_arg *arg = varg;
struct nn_locators_one *elem = ddsrt_malloc (sizeof (struct nn_locators_one));
struct nn_locators *locs;
unsigned present_flag;
@@ -834,19 +851,19 @@ static void add_locator_to_ps (const nn_locator_t *loc, void *arg)
elem->loc = *loc;
elem->next = NULL;
- if (ddsi_is_mcaddr (loc)) {
- locs = &ps->multicast_locators;
+ if (ddsi_is_mcaddr (arg->gv, loc)) {
+ locs = &arg->ps->multicast_locators;
present_flag = PP_MULTICAST_LOCATOR;
} else {
- locs = &ps->unicast_locators;
+ locs = &arg->ps->unicast_locators;
present_flag = PP_UNICAST_LOCATOR;
}
- if (!(ps->present & present_flag))
+ if (!(arg->ps->present & present_flag))
{
locs->n = 0;
locs->first = locs->last = NULL;
- ps->present |= present_flag;
+ arg->ps->present |= present_flag;
}
locs->n++;
if (locs->first)
@@ -866,9 +883,10 @@ static int sedp_write_endpoint
(
struct writer *wr, int alive, const nn_guid_t *epguid,
const struct entity_common *common, const struct endpoint_common *epcommon,
- const nn_xqos_t *xqos, struct addrset *as)
+ const dds_qos_t *xqos, struct addrset *as)
{
- const nn_xqos_t *defqos = is_writer_entityid (epguid->entityid) ? &gv.default_xqos_wr : &gv.default_xqos_rd;
+ struct q_globals * const gv = wr->e.gv;
+ const dds_qos_t *defqos = is_writer_entityid (epguid->entityid) ? &gv->default_xqos_wr : &gv->default_xqos_rd;
struct nn_xmsg *mpayload;
uint64_t qosdiff;
nn_plist_t ps;
@@ -913,7 +931,7 @@ static int sedp_write_endpoint
the default. */
if (!is_writer_entityid (epguid->entityid))
{
- const struct reader *rd = ephash_lookup_reader_guid (epguid);
+ const struct reader *rd = ephash_lookup_reader_guid (gv->guid_hash, epguid);
assert (rd);
if (rd->favours_ssm)
{
@@ -924,12 +942,15 @@ static int sedp_write_endpoint
#endif
qosdiff = nn_xqos_delta (xqos, defqos, ~(uint64_t)0);
- if (config.explicitly_publish_qos_set_to_default)
+ if (gv->config.explicitly_publish_qos_set_to_default)
qosdiff |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK;
if (as)
{
- addrset_forall (as, add_locator_to_ps, &ps);
+ struct add_locator_to_ps_arg arg;
+ arg.gv = gv;
+ arg.ps = &ps;
+ addrset_forall (as, add_locator_to_ps, &arg);
}
}
@@ -937,13 +958,13 @@ static int sedp_write_endpoint
the QoS and other settings. So the header fields aren't really
important, except that they need to be set to reasonable things
or it'll crash */
- mpayload = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA);
+ mpayload = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA);
nn_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0);
if (xqos) nn_xqos_addtomsg (mpayload, xqos, qosdiff);
nn_xmsg_addpar_sentinel (mpayload);
nn_plist_fini (&ps);
- DDS_LOG(DDS_LC_DISCOVERY, "sedp: write for "PGUIDFMT" via "PGUIDFMT"\n", PGUID (*epguid), PGUID (wr->e.guid));
+ GVLOGDISC ("sedp: write for "PGUIDFMT" via "PGUIDFMT"\n", PGUID (*epguid), PGUID (wr->e.guid));
ret = write_mpayload (wr, alive, PID_ENDPOINT_GUID, mpayload);
nn_xmsg_free (mpayload);
return ret;
@@ -953,7 +974,7 @@ static struct writer *get_sedp_writer (const struct participant *pp, unsigned en
{
struct writer *sedp_wr = get_builtin_writer (pp, entityid);
if (sedp_wr == NULL)
- DDS_FATAL("sedp_write_writer: no SEDP builtin writer %x for "PGUIDFMT"\n", entityid, PGUID (pp->e.guid));
+ DDS_FATAL ("sedp_write_writer: no SEDP builtin writer %x for "PGUIDFMT"\n", entityid, PGUID (pp->e.guid));
return sedp_wr;
}
@@ -1007,19 +1028,19 @@ int sedp_dispose_unregister_reader (struct reader *rd)
return 0;
}
-static const char *durability_to_string (nn_durability_kind_t k)
+static const char *durability_to_string (dds_durability_kind_t k)
{
switch (k)
{
- case NN_VOLATILE_DURABILITY_QOS: return "volatile";
- case NN_TRANSIENT_LOCAL_DURABILITY_QOS: return "transient-local";
- case NN_TRANSIENT_DURABILITY_QOS: return "transient";
- case NN_PERSISTENT_DURABILITY_QOS: return "persistent";
+ case DDS_DURABILITY_VOLATILE: return "volatile";
+ case DDS_DURABILITY_TRANSIENT_LOCAL: return "transient-local";
+ case DDS_DURABILITY_TRANSIENT: return "transient";
+ case DDS_DURABILITY_PERSISTENT: return "persistent";
}
return "undefined-durability";
}
-static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppguid, nn_plist_t *datap /* note: potentially modifies datap */, const nn_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp)
+static struct proxy_participant *implicitly_create_proxypp (struct q_globals *gv, const nn_guid_t *ppguid, nn_plist_t *datap /* note: potentially modifies datap */, const nn_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp, seqno_t seq)
{
nn_guid_t privguid;
nn_plist_t pp_plist;
@@ -1036,14 +1057,14 @@ static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppg
{
nn_vendorid_t actual_vendorid;
/* Some endpoint that we discovered through the DS, but then it must have at least some locators */
- DDS_TRACE(" from-DS %"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32, PGUID (privguid));
+ GVTRACE (" from-DS %"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32, PGUID (privguid));
/* avoid "no address" case, so we never create the proxy participant for nothing (FIXME: rework some of this) */
if (!(datap->present & (PP_UNICAST_LOCATOR | PP_MULTICAST_LOCATOR)))
{
- DDS_TRACE(" data locator absent\n");
+ GVTRACE (" data locator absent\n");
goto err;
}
- DDS_TRACE(" new-proxypp "PGUIDFMT"\n", PGUID (*ppguid));
+ GVTRACE (" new-proxypp "PGUIDFMT"\n", PGUID (*ppguid));
/* We need to handle any source of entities, but we really want to try to keep the GIDs (and
certainly the systemId component) unchanged for OSPL. The new proxy participant will take
the GID from the GUID if it is from a "modern" OSPL that advertises it includes all GIDs in
@@ -1056,7 +1077,7 @@ static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppg
doing anything about (1). That means we fall back to the legacy mode of locally generating
GIDs but leaving the system id unchanged if the remote is OSPL. */
actual_vendorid = (datap->present & PP_VENDORID) ? datap->vendorid : vendorid;
- new_proxy_participant(ppguid, 0, 0, &privguid, new_addrset(), new_addrset(), &pp_plist, T_NEVER, actual_vendorid, CF_IMPLICITLY_CREATED_PROXYPP, timestamp);
+ new_proxy_participant(gv, ppguid, 0, 0, &privguid, new_addrset(), new_addrset(), &pp_plist, T_NEVER, actual_vendorid, CF_IMPLICITLY_CREATED_PROXYPP, timestamp, seq);
}
else if (ppguid->prefix.u[0] == src_guid_prefix->u[0] && vendor_is_eclipse_or_opensplice (vendorid))
{
@@ -1064,19 +1085,19 @@ static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppg
readers or writers, only if remote ddsi2 is provably running
with a minimal built-in endpoint set */
struct proxy_participant *privpp;
- if ((privpp = ephash_lookup_proxy_participant_guid (&privguid)) == NULL) {
- DDS_TRACE(" unknown-src-proxypp?\n");
+ if ((privpp = ephash_lookup_proxy_participant_guid (gv->guid_hash, &privguid)) == NULL) {
+ GVTRACE (" unknown-src-proxypp?\n");
goto err;
} else if (!privpp->is_ddsi2_pp) {
- DDS_TRACE(" src-proxypp-not-ddsi2?\n");
+ GVTRACE (" src-proxypp-not-ddsi2?\n");
goto err;
} else if (!privpp->minimal_bes_mode) {
- DDS_TRACE(" src-ddsi2-not-minimal-bes-mode?\n");
+ GVTRACE (" src-ddsi2-not-minimal-bes-mode?\n");
goto err;
} else {
struct addrset *as_default, *as_meta;
nn_plist_t tmp_plist;
- DDS_TRACE(" from-ddsi2 "PGUIDFMT, PGUID (privguid));
+ GVTRACE (" from-ddsi2 "PGUIDFMT, PGUID (privguid));
nn_plist_init_empty (&pp_plist);
ddsrt_mutex_lock (&privpp->e.lock);
@@ -1086,27 +1107,28 @@ static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppg
tmp_plist = *privpp->plist;
tmp_plist.present = PP_PARTICIPANT_GUID | PP_PRISMTECH_PARTICIPANT_VERSION_INFO;
tmp_plist.participant_guid = *ppguid;
- nn_plist_mergein_missing (&pp_plist, &tmp_plist);
+ nn_plist_mergein_missing (&pp_plist, &tmp_plist, ~(uint64_t)0, ~(uint64_t)0);
ddsrt_mutex_unlock (&privpp->e.lock);
pp_plist.prismtech_participant_version_info.flags &= ~NN_PRISMTECH_FL_PARTICIPANT_IS_DDSI2;
- new_proxy_participant (ppguid, 0, 0, &privguid, as_default, as_meta, &pp_plist, T_NEVER, vendorid, CF_IMPLICITLY_CREATED_PROXYPP | CF_PROXYPP_NO_SPDP, timestamp);
+ new_proxy_participant (gv, ppguid, 0, 0, &privguid, as_default, as_meta, &pp_plist, T_NEVER, vendorid, CF_IMPLICITLY_CREATED_PROXYPP | CF_PROXYPP_NO_SPDP, timestamp, seq);
}
}
err:
nn_plist_fini (&pp_plist);
- return ephash_lookup_proxy_participant_guid (ppguid);
+ return ephash_lookup_proxy_participant_guid (gv->guid_hash, ppguid);
}
-static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *datap /* note: potentially modifies datap */, const nn_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp)
+static void handle_SEDP_alive (const struct receiver_state *rst, seqno_t seq, nn_plist_t *datap /* note: potentially modifies datap */, const nn_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp)
{
-#define E(msg, lbl) do { DDS_LOG(DDS_LC_DISCOVERY, msg); goto lbl; } while (0)
+#define E(msg, lbl) do { GVLOGDISC (msg); goto lbl; } while (0)
+ struct q_globals * const gv = rst->gv;
struct proxy_participant *pp;
struct proxy_writer * pwr = NULL;
struct proxy_reader * prd = NULL;
nn_guid_t ppguid;
- nn_xqos_t *xqos;
+ dds_qos_t *xqos;
int reliable;
struct addrset *as;
int is_writer;
@@ -1118,14 +1140,14 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat
if (!(datap->present & PP_ENDPOINT_GUID))
E (" no guid?\n", err);
- DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT, PGUID (datap->endpoint_guid));
+ GVLOGDISC (" "PGUIDFMT, PGUID (datap->endpoint_guid));
ppguid.prefix = datap->endpoint_guid.prefix;
ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
- if (is_deleted_participant_guid (&ppguid, DPG_REMOTE))
+ if (is_deleted_participant_guid (gv->deleted_participants, &ppguid, DPG_REMOTE))
E (" local dead pp?\n", err);
- if (ephash_lookup_participant_guid (&ppguid) != NULL)
+ if (ephash_lookup_participant_guid (gv->guid_hash, &ppguid) != NULL)
E (" local pp?\n", err);
if (is_builtin_entityid (datap->endpoint_guid.entityid, vendorid))
@@ -1135,23 +1157,23 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat
if (!(datap->qos.present & QP_TYPE_NAME))
E (" no typename?\n", err);
- if ((pp = ephash_lookup_proxy_participant_guid (&ppguid)) == NULL)
+ if ((pp = ephash_lookup_proxy_participant_guid (gv->guid_hash, &ppguid)) == NULL)
{
- DDS_LOG(DDS_LC_DISCOVERY, " unknown-proxypp");
- if ((pp = implicitly_create_proxypp (&ppguid, datap, src_guid_prefix, vendorid, timestamp)) == NULL)
+ GVLOGDISC (" unknown-proxypp");
+ if ((pp = implicitly_create_proxypp (gv, &ppguid, datap, src_guid_prefix, vendorid, timestamp, 0)) == NULL)
E ("?\n", err);
/* Repeat regular SEDP trace for convenience */
- DDS_LOG(DDS_LC_DISCOVERY, "SEDP ST0 "PGUIDFMT" (cont)", PGUID (datap->endpoint_guid));
+ GVLOGDISC ("SEDP ST0 "PGUIDFMT" (cont)", PGUID (datap->endpoint_guid));
}
xqos = &datap->qos;
is_writer = is_writer_entityid (datap->endpoint_guid.entityid);
if (!is_writer)
- nn_xqos_mergein_missing (xqos, &gv.default_xqos_rd);
+ nn_xqos_mergein_missing (xqos, &gv->default_xqos_rd, ~(uint64_t)0);
else if (vendor_is_eclipse_or_prismtech(vendorid))
- nn_xqos_mergein_missing (xqos, &gv.default_xqos_wr);
+ nn_xqos_mergein_missing (xqos, &gv->default_xqos_wr, ~(uint64_t)0);
else
- nn_xqos_mergein_missing (xqos, &gv.default_xqos_wr_nad);
+ nn_xqos_mergein_missing (xqos, &gv->default_xqos_wr_nad, ~(uint64_t)0);
/* After copy + merge, should have at least the ones present in the
input. Also verify reliability and durability are present,
@@ -1159,16 +1181,16 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat
assert ((xqos->present & datap->qos.present) == datap->qos.present);
assert (xqos->present & QP_RELIABILITY);
assert (xqos->present & QP_DURABILITY);
- reliable = (xqos->reliability.kind == NN_RELIABLE_RELIABILITY_QOS);
+ reliable = (xqos->reliability.kind == DDS_RELIABILITY_RELIABLE);
- DDS_LOG(DDS_LC_DISCOVERY, " %s %s %s: %s%s.%s/%s",
- reliable ? "reliable" : "best-effort",
- durability_to_string (xqos->durability.kind),
- is_writer ? "writer" : "reader",
- ((!(xqos->present & QP_PARTITION) || xqos->partition.n == 0 || *xqos->partition.strs[0] == '\0')
- ? "(default)" : xqos->partition.strs[0]),
- ((xqos->present & QP_PARTITION) && xqos->partition.n > 1) ? "+" : "",
- xqos->topic_name, xqos->type_name);
+ GVLOGDISC (" %s %s %s: %s%s.%s/%s",
+ reliable ? "reliable" : "best-effort",
+ durability_to_string (xqos->durability.kind),
+ is_writer ? "writer" : "reader",
+ ((!(xqos->present & QP_PARTITION) || xqos->partition.n == 0 || *xqos->partition.strs[0] == '\0')
+ ? "(default)" : xqos->partition.strs[0]),
+ ((xqos->present & QP_PARTITION) && xqos->partition.n > 1) ? "+" : "",
+ xqos->topic_name, xqos->type_name);
if (! is_writer && (datap->present & PP_EXPECTS_INLINE_QOS) && datap->expects_inline_qos)
{
@@ -1177,60 +1199,52 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat
if (is_writer)
{
- pwr = ephash_lookup_proxy_writer_guid (&datap->endpoint_guid);
+ pwr = ephash_lookup_proxy_writer_guid (gv->guid_hash, &datap->endpoint_guid);
}
else
{
- prd = ephash_lookup_proxy_reader_guid (&datap->endpoint_guid);
+ prd = ephash_lookup_proxy_reader_guid (gv->guid_hash, &datap->endpoint_guid);
}
if (pwr || prd)
{
- /* Cloud load balances by updating participant endpoints */
-
- if (! vendor_is_cloud (vendorid))
- {
- DDS_LOG(DDS_LC_DISCOVERY, " known\n");
- goto err;
- }
-
/* Re-bind the proxy participant to the discovery service - and do this if it is currently
bound to another DS instance, because that other DS instance may have already failed and
with a new one taking over, without our noticing it. */
- DDS_LOG(DDS_LC_DISCOVERY, " known-DS");
+ GVLOGDISC (" known%s", vendor_is_cloud (vendorid) ? "-DS" : "");
if (vendor_is_cloud (vendorid) && pp->implicitly_created && memcmp(&pp->privileged_pp_guid.prefix, src_guid_prefix, sizeof(pp->privileged_pp_guid.prefix)) != 0)
{
nn_etime_t never = { T_NEVER };
- DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT" attach-to-DS "PGUIDFMT, PGUID(pp->e.guid), PGUIDPREFIX(*src_guid_prefix), pp->privileged_pp_guid.entityid.u);
+ GVLOGDISC (" "PGUIDFMT" attach-to-DS "PGUIDFMT, PGUID(pp->e.guid), PGUIDPREFIX(*src_guid_prefix), pp->privileged_pp_guid.entityid.u);
ddsrt_mutex_lock (&pp->e.lock);
pp->privileged_pp_guid.prefix = *src_guid_prefix;
lease_set_expiry(ddsrt_atomic_ldvoidp(&pp->lease), never);
ddsrt_mutex_unlock (&pp->e.lock);
}
- DDS_LOG(DDS_LC_DISCOVERY, "\n");
+ GVLOGDISC ("\n");
}
else
{
- DDS_LOG(DDS_LC_DISCOVERY, " NEW");
+ GVLOGDISC (" NEW");
}
{
nn_locator_t loc;
as = new_addrset ();
- if (!config.tcp_use_peeraddr_for_unicast && (datap->present & PP_UNICAST_LOCATOR) && get_locator (&loc, &datap->unicast_locators, 0))
- add_to_addrset (as, &loc);
- else if (config.tcp_use_peeraddr_for_unicast)
+ if (!gv->config.tcp_use_peeraddr_for_unicast && (datap->present & PP_UNICAST_LOCATOR) && get_locator (gv, &loc, &datap->unicast_locators, 0))
+ add_to_addrset (gv, as, &loc);
+ else if (gv->config.tcp_use_peeraddr_for_unicast)
{
- DDS_LOG(DDS_LC_DISCOVERY, " (srcloc)");
- add_to_addrset (as, &rst->srcloc);
+ GVLOGDISC (" (srcloc)");
+ add_to_addrset (gv, as, &rst->srcloc);
}
else
{
- copy_addrset_into_addrset_uc (as, pp->as_default);
+ copy_addrset_into_addrset_uc (gv, as, pp->as_default);
}
- if ((datap->present & PP_MULTICAST_LOCATOR) && get_locator (&loc, &datap->multicast_locators, 0))
- allowmulticast_aware_add_to_addrset (as, &loc);
+ if ((datap->present & PP_MULTICAST_LOCATOR) && get_locator (gv, &loc, &datap->multicast_locators, 0))
+ allowmulticast_aware_add_to_addrset (gv, gv->config.allowMulticast, as, &loc);
else
- copy_addrset_into_addrset_mc (as, pp->as_default);
+ copy_addrset_into_addrset_mc (gv, as, pp->as_default);
}
if (addrset_empty (as))
{
@@ -1238,22 +1252,22 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat
E (" no address", err);
}
- nn_log_addrset(DDS_LC_DISCOVERY, " (as", as);
+ nn_log_addrset(gv, DDS_LC_DISCOVERY, " (as", as);
#ifdef DDSI_INCLUDE_SSM
ssm = 0;
if (is_writer)
- ssm = addrset_contains_ssm (as);
+ ssm = addrset_contains_ssm (gv, as);
else if (datap->present & PP_READER_FAVOURS_SSM)
ssm = (datap->reader_favours_ssm.state != 0);
- DDS_LOG(DDS_LC_DISCOVERY, " ssm=%u", ssm);
+ GVLOGDISC (" ssm=%u", ssm);
#endif
- DDS_LOG(DDS_LC_DISCOVERY, ") QOS={");
- nn_log_xqos(DDS_LC_DISCOVERY, xqos);
- DDS_LOG(DDS_LC_DISCOVERY, "}\n");
+ GVLOGDISC (") QOS={");
+ nn_log_xqos (DDS_LC_DISCOVERY, &gv->logconfig, xqos);
+ GVLOGDISC ("}\n");
if ((datap->endpoint_guid.entityid.u & NN_ENTITYID_SOURCE_MASK) == NN_ENTITYID_SOURCE_VENDOR && !vendor_is_eclipse_or_prismtech (vendorid))
{
- DDS_LOG(DDS_LC_DISCOVERY, "ignoring vendor-specific endpoint "PGUIDFMT"\n", PGUID (datap->endpoint_guid));
+ GVLOGDISC ("ignoring vendor-specific endpoint "PGUIDFMT"\n", PGUID (datap->endpoint_guid));
}
else
{
@@ -1261,7 +1275,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat
{
if (pwr)
{
- update_proxy_writer (pwr, as);
+ update_proxy_writer (pwr, seq, as, xqos, timestamp);
}
else
{
@@ -1269,11 +1283,11 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat
assert (!is_builtin_entityid (datap->endpoint_guid.entityid, vendorid));
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
{
- struct config_channel_listelem *channel = find_channel (xqos->transport_priority);
- new_proxy_writer (&ppguid, &datap->endpoint_guid, as, datap, channel->dqueue, channel->evq ? channel->evq : gv.xevents, timestamp);
+ struct config_channel_listelem *channel = find_channel (&gv->config, xqos->transport_priority);
+ new_proxy_writer (&ppguid, &datap->endpoint_guid, as, datap, channel->dqueue, channel->evq ? channel->evq : gv->xevents, timestamp);
}
#else
- new_proxy_writer (&ppguid, &datap->endpoint_guid, as, datap, gv.user_dqueue, gv.xevents, timestamp);
+ new_proxy_writer (gv, &ppguid, &datap->endpoint_guid, as, datap, gv->user_dqueue, gv->xevents, timestamp, seq);
#endif
}
}
@@ -1281,14 +1295,14 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat
{
if (prd)
{
- update_proxy_reader (prd, as);
+ update_proxy_reader (prd, seq, as, xqos, timestamp);
}
else
{
#ifdef DDSI_INCLUDE_SSM
- new_proxy_reader (&ppguid, &datap->endpoint_guid, as, datap, timestamp, ssm);
+ new_proxy_reader (gv, &ppguid, &datap->endpoint_guid, as, datap, timestamp, seq, ssm);
#else
- new_proxy_reader (&ppguid, &datap->endpoint_guid, as, datap, timestamp);
+ new_proxy_reader (gv, &ppguid, &datap->endpoint_guid, as, datap, timestamp, seq);
#endif
}
}
@@ -1302,62 +1316,67 @@ err:
#undef E
}
-static void handle_SEDP_dead (nn_plist_t *datap, nn_wctime_t timestamp)
+static void handle_SEDP_dead (const struct receiver_state *rst, nn_plist_t *datap, nn_wctime_t timestamp)
{
+ struct q_globals * const gv = rst->gv;
int res;
if (!(datap->present & PP_ENDPOINT_GUID))
{
- DDS_LOG(DDS_LC_DISCOVERY, " no guid?\n");
+ GVLOGDISC (" no guid?\n");
return;
}
- DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT, PGUID (datap->endpoint_guid));
+ GVLOGDISC (" "PGUIDFMT, PGUID (datap->endpoint_guid));
if (is_writer_entityid (datap->endpoint_guid.entityid))
{
- res = delete_proxy_writer (&datap->endpoint_guid, timestamp, 0);
+ res = delete_proxy_writer (gv, &datap->endpoint_guid, timestamp, 0);
}
else
{
- res = delete_proxy_reader (&datap->endpoint_guid, timestamp, 0);
+ res = delete_proxy_reader (gv, &datap->endpoint_guid, timestamp, 0);
}
- DDS_LOG(DDS_LC_DISCOVERY, " %s\n", (res < 0) ? " unknown" : " delete");
+ GVLOGDISC (" %s\n", (res < 0) ? " unknown" : " delete");
}
-static void handle_SEDP (const struct receiver_state *rst, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len)
+static void handle_SEDP (const struct receiver_state *rst, seqno_t seq, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len)
{
+ struct q_globals * const gv = rst->gv;
const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */
- DDS_LOG(DDS_LC_DISCOVERY, "SEDP ST%x", statusinfo);
+ GVLOGDISC ("SEDP ST%x", statusinfo);
if (data == NULL)
{
- DDS_LOG(DDS_LC_DISCOVERY, " no payload?\n");
+ GVLOGDISC (" no payload?\n");
return;
}
else
{
nn_plist_t decoded_data;
nn_plist_src_t src;
- int plist_ret;
+ dds_return_t plist_ret;
src.protocol_version = rst->protocol_version;
src.vendorid = rst->vendor;
src.encoding = data->identifier;
src.buf = (unsigned char *) data + 4;
src.bufsz = len - 4;
+ src.strict = NN_STRICT_P (gv->config);
+ src.factory = gv->m_factory;
+ src.logconfig = &gv->logconfig;
if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0)
{
- if (plist_ret != Q_ERR_INCOMPATIBLE)
- DDS_WARNING("SEDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]);
+ if (plist_ret != DDS_RETCODE_UNSUPPORTED)
+ GVWARNING ("SEDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]);
return;
}
switch (statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER))
{
case 0:
- handle_SEDP_alive (rst, &decoded_data, &rst->src_guid_prefix, rst->vendor, timestamp);
+ handle_SEDP_alive (rst, seq, &decoded_data, &rst->src_guid_prefix, rst->vendor, timestamp);
break;
case NN_STATUSINFO_DISPOSE:
case NN_STATUSINFO_UNREGISTER:
case (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER):
- handle_SEDP_dead (&decoded_data, timestamp);
+ handle_SEDP_dead (rst, &decoded_data, timestamp);
break;
}
@@ -1387,14 +1406,14 @@ int sedp_write_topic (struct participant *pp, const struct nn_plist *datap)
sedp_wr = get_sedp_writer (pp, NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER);
- mpayload = nn_xmsg_new (gv.xmsgpool, &sedp_wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA);
- delta = nn_xqos_delta (&datap->qos, &gv.default_xqos_tp, ~(uint64_t)0);
- if (config.explicitly_publish_qos_set_to_default)
+ mpayload = nn_xmsg_new (sedp_wr->e.gv->xmsgpool, &sedp_wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA);
+ delta = nn_xqos_delta (&datap->qos, &sedp_wr->e.gv->default_xqos_tp, ~(uint64_t)0);
+ if (sedp_wr->e.gv->config.explicitly_publish_qos_set_to_default)
delta |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK;
nn_plist_addtomsg (mpayload, datap, ~(uint64_t)0, delta);
nn_xmsg_addpar_sentinel (mpayload);
- DDS_TRACE("sedp: write topic %s via "PGUIDFMT"\n", datap->qos.topic_name, PGUID (sedp_wr->e.guid));
+ ETRACE (pp, "sedp: write topic %s via "PGUIDFMT"\n", datap->qos.topic_name, PGUID (sedp_wr->e.guid));
ret = write_mpayload (sedp_wr, 1, PID_TOPIC_NAME, mpayload);
nn_xmsg_free (mpayload);
return ret;
@@ -1425,7 +1444,7 @@ int sedp_write_cm_participant (struct participant *pp, int alive)
the QoS and other settings. So the header fields aren't really
important, except that they need to be set to reasonable things
or it'll crash */
- mpayload = nn_xmsg_new (gv.xmsgpool, &sedp_wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA);
+ mpayload = nn_xmsg_new (sedp_wr->e.gv->xmsgpool, &sedp_wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA);
nn_plist_init_empty (&ps);
ps.present = PP_PARTICIPANT_GUID;
ps.participant_guid = pp->e.guid;
@@ -1435,44 +1454,47 @@ int sedp_write_cm_participant (struct participant *pp, int alive)
{
nn_plist_addtomsg (mpayload, pp->plist,
PP_PRISMTECH_NODE_NAME | PP_PRISMTECH_EXEC_NAME | PP_PRISMTECH_PROCESS_ID |
- PP_PRISMTECH_WATCHDOG_SCHEDULING | PP_PRISMTECH_LISTENER_SCHEDULING |
- PP_PRISMTECH_SERVICE_TYPE | PP_ENTITY_NAME,
+ PP_ENTITY_NAME,
QP_PRISMTECH_ENTITY_FACTORY);
}
nn_xmsg_addpar_sentinel (mpayload);
- DDS_TRACE("sedp: write CMParticipant ST%x for "PGUIDFMT" via "PGUIDFMT"\n",
+ ETRACE (pp, "sedp: write CMParticipant ST%x for "PGUIDFMT" via "PGUIDFMT"\n",
alive ? 0 : NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER, PGUID (pp->e.guid), PGUID (sedp_wr->e.guid));
ret = write_mpayload (sedp_wr, alive, PID_PARTICIPANT_GUID, mpayload);
nn_xmsg_free (mpayload);
return ret;
}
-static void handle_SEDP_CM (const struct receiver_state *rst, nn_entityid_t wr_entity_id, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len)
+static void handle_SEDP_CM (const struct receiver_state *rst, nn_entityid_t wr_entity_id, nn_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len)
{
+ struct q_globals * const gv = rst->gv;
const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */
- DDS_LOG(DDS_LC_DISCOVERY, "SEDP_CM ST%x", statusinfo);
+ GVLOGDISC ("SEDP_CM ST%x", statusinfo);
assert (wr_entity_id.u == NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER);
(void) wr_entity_id;
if (data == NULL)
{
- DDS_LOG(DDS_LC_DISCOVERY, " no payload?\n");
+ GVLOGDISC (" no payload?\n");
return;
}
else
{
nn_plist_t decoded_data;
nn_plist_src_t src;
- int plist_ret;
+ dds_return_t plist_ret;
src.protocol_version = rst->protocol_version;
src.vendorid = rst->vendor;
src.encoding = data->identifier;
src.buf = (unsigned char *) data + 4;
src.bufsz = len - 4;
+ src.strict = NN_STRICT_P (gv->config);
+ src.factory = gv->m_factory;
+ src.logconfig = &gv->logconfig;
if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0)
{
- if (plist_ret != Q_ERR_INCOMPATIBLE)
- DDS_WARNING("SEDP_CM (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]);
+ if (plist_ret != DDS_RETCODE_UNSUPPORTED)
+ GVWARNING ("SEDP_CM (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]);
return;
}
@@ -1481,178 +1503,19 @@ static void handle_SEDP_CM (const struct receiver_state *rst, nn_entityid_t wr_e
{
struct proxy_participant *proxypp;
if (!(decoded_data.present & PP_PARTICIPANT_GUID))
- DDS_WARNING("SEDP_CM (vendor %u.%u): missing participant GUID\n", src.vendorid.id[0], src.vendorid.id[1]);
+ GVWARNING ("SEDP_CM (vendor %u.%u): missing participant GUID\n", src.vendorid.id[0], src.vendorid.id[1]);
else
{
- if ((proxypp = ephash_lookup_proxy_participant_guid (&decoded_data.participant_guid)) == NULL)
- proxypp = implicitly_create_proxypp (&decoded_data.participant_guid, &decoded_data, &rst->src_guid_prefix, rst->vendor, timestamp);
+ if ((proxypp = ephash_lookup_proxy_participant_guid (gv->guid_hash, &decoded_data.participant_guid)) == NULL)
+ proxypp = implicitly_create_proxypp (gv, &decoded_data.participant_guid, &decoded_data, &rst->src_guid_prefix, rst->vendor, timestamp, 0);
if (proxypp != NULL)
- update_proxy_participant_plist (proxypp, &decoded_data, UPD_PROXYPP_CM, timestamp);
+ update_proxy_participant_plist (proxypp, 0, &decoded_data, UPD_PROXYPP_CM, timestamp);
}
}
nn_plist_fini (&decoded_data);
}
- DDS_LOG(DDS_LC_DISCOVERY, "\n");
-}
-
-static struct participant *group_guid_to_participant (const nn_guid_t *group_guid)
-{
- nn_guid_t ppguid;
- ppguid.prefix = group_guid->prefix;
- ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
- return ephash_lookup_participant_guid (&ppguid);
-}
-
-int sedp_write_cm_publisher (const struct nn_plist *datap, int alive)
-{
- struct participant *pp;
- struct writer *sedp_wr;
- struct nn_xmsg *mpayload;
- uint64_t delta;
- int ret;
-
- if ((pp = group_guid_to_participant (&datap->group_guid)) == NULL)
- {
- DDS_TRACE("sedp: write CMPublisher alive:%d for "PGUIDFMT" dropped: no participant\n",
- alive, PGUID (datap->group_guid));
- return 0;
- }
- sedp_wr = get_sedp_writer (pp, NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER);
-
- /* The message is only a temporary thing, used only for encoding
- the QoS and other settings. So the header fields aren't really
- important, except that they need to be set to reasonable things
- or it'll crash */
- mpayload = nn_xmsg_new (gv.xmsgpool, &sedp_wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA);
- if (!alive)
- delta = 0;
- else
- {
- delta = nn_xqos_delta (&datap->qos, &gv.default_xqos_pub, ~(uint64_t)0);
- if (!config.explicitly_publish_qos_set_to_default)
- delta |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK;
- }
- nn_plist_addtomsg (mpayload, datap, ~(uint64_t)0, delta);
- nn_xmsg_addpar_sentinel (mpayload);
- ret = write_mpayload (sedp_wr, alive, PID_GROUP_GUID ,mpayload);
- nn_xmsg_free (mpayload);
- return ret;
-}
-
-int sedp_write_cm_subscriber (const struct nn_plist *datap, int alive)
-{
- struct participant *pp;
- struct writer *sedp_wr;
- struct nn_xmsg *mpayload;
- uint64_t delta;
- int ret;
-
- if ((pp = group_guid_to_participant (&datap->group_guid)) == NULL)
- {
- DDS_LOG(DDS_LC_DISCOVERY, "sedp: write CMSubscriber alive:%d for "PGUIDFMT" dropped: no participant\n",
- alive, PGUID (datap->group_guid));
- return 0;
- }
- sedp_wr = get_sedp_writer (pp, NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER);
-
- /* The message is only a temporary thing, used only for encoding
- the QoS and other settings. So the header fields aren't really
- important, except that they need to be set to reasonable things
- or it'll crash */
- mpayload = nn_xmsg_new (gv.xmsgpool, &sedp_wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA);
- if (!alive)
- delta = 0;
- else
- {
- delta = nn_xqos_delta (&datap->qos, &gv.default_xqos_sub, ~(uint64_t)0);
- if (!config.explicitly_publish_qos_set_to_default)
- delta |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK;
- }
- nn_plist_addtomsg (mpayload, datap, ~(uint64_t)0, delta);
- nn_xmsg_addpar_sentinel (mpayload);
- ret = write_mpayload (sedp_wr, alive, PID_GROUP_GUID, mpayload);
- nn_xmsg_free (mpayload);
- return ret;
-}
-
-static void handle_SEDP_GROUP_alive (nn_plist_t *datap /* note: potentially modifies datap */, nn_wctime_t timestamp)
-{
-#define E(msg, lbl) do { DDS_LOG(DDS_LC_DISCOVERY, msg); goto lbl; } while (0)
- nn_guid_t ppguid;
-
- if (!(datap->present & PP_GROUP_GUID))
- E (" no guid?\n", err);
- DDS_LOG(DDS_LC_DISCOVERY, " %"PRIx32"%"PRIx32"%"PRIx32"%"PRIx32, PGUID (datap->group_guid));
-
- ppguid.prefix = datap->group_guid.prefix;
- ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
- if (ephash_lookup_proxy_participant_guid (&ppguid) == NULL)
- E (" unknown proxy pp?\n", err);
-
- DDS_LOG(DDS_LC_DISCOVERY, " alive\n");
-
- {
- char *name = (datap->present & PP_ENTITY_NAME) ? datap->entity_name : "";
- new_proxy_group (&datap->group_guid, name, &datap->qos, timestamp);
- }
-err:
- return;
-#undef E
-}
-
-static void handle_SEDP_GROUP_dead (nn_plist_t *datap, nn_wctime_t timestamp)
-{
- if (!(datap->present & PP_GROUP_GUID))
- {
- DDS_LOG(DDS_LC_DISCOVERY, " no guid?\n");
- return;
- }
- DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT"\n", PGUID (datap->group_guid));
- delete_proxy_group (&datap->group_guid, timestamp, 0);
-}
-
-static void handle_SEDP_GROUP (const struct receiver_state *rst, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len)
-{
- const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */
- DDS_LOG(DDS_LC_DISCOVERY, "SEDP_GROUP ST%x", statusinfo);
- if (data == NULL)
- {
- DDS_LOG(DDS_LC_DISCOVERY, " no payload?\n");
- return;
- }
- else
- {
- nn_plist_t decoded_data;
- nn_plist_src_t src;
- int plist_ret;
- src.protocol_version = rst->protocol_version;
- src.vendorid = rst->vendor;
- src.encoding = data->identifier;
- src.buf = (unsigned char *) data + 4;
- src.bufsz = len - 4;
- if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0)
- {
- if (plist_ret != Q_ERR_INCOMPATIBLE)
- DDS_WARNING("SEDP_GROUP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]);
- return;
- }
-
- switch (statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER))
- {
- case 0:
- handle_SEDP_GROUP_alive (&decoded_data, timestamp);
- break;
-
- case NN_STATUSINFO_DISPOSE:
- case NN_STATUSINFO_UNREGISTER:
- case (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER):
- handle_SEDP_GROUP_dead (&decoded_data, timestamp);
- break;
- }
-
- nn_plist_fini (&decoded_data);
- }
+ GVLOGDISC ("\n");
}
/******************************************************************************
@@ -1691,6 +1554,7 @@ static int defragment (unsigned char **datap, const struct nn_rdata *fragchain,
int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, UNUSED_ARG (const nn_guid_t *rdguid), UNUSED_ARG (void *qarg))
{
+ struct q_globals * const gv = sampleinfo->rst->gv;
struct proxy_writer *pwr;
struct {
struct CDRHeader cdr;
@@ -1748,17 +1612,20 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str
{
nn_plist_src_t src;
size_t qos_offset = NN_RDATA_SUBMSG_OFF (fragchain) + offsetof (Data_DataFrag_common_t, octetsToInlineQos) + sizeof (msg->octetsToInlineQos) + msg->octetsToInlineQos;
- int plist_ret;
+ dds_return_t plist_ret;
src.protocol_version = sampleinfo->rst->protocol_version;
src.vendorid = sampleinfo->rst->vendor;
src.encoding = (msg->smhdr.flags & SMFLAG_ENDIANNESS) ? PL_CDR_LE : PL_CDR_BE;
src.buf = NN_RMSG_PAYLOADOFF (fragchain->rmsg, qos_offset);
src.bufsz = NN_RDATA_PAYLOAD_OFF (fragchain) - qos_offset;
+ src.strict = NN_STRICT_P (gv->config);
+ src.factory = gv->m_factory;
+ src.logconfig = &gv->logconfig;
if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH, 0, &src)) < 0)
{
- if (plist_ret != Q_ERR_INCOMPATIBLE)
- DDS_WARNING("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n",
- src.vendorid.id[0], src.vendorid.id[1], PGUID (srcguid), sampleinfo->seq);
+ if (plist_ret != DDS_RETCODE_UNSUPPORTED)
+ GVWARNING ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n",
+ src.vendorid.id[0], src.vendorid.id[1], PGUID (srcguid), sampleinfo->seq);
goto done_upd_deliv;
}
/* Complex qos bit also gets set when statusinfo bits other than
@@ -1781,10 +1648,9 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str
{
if (datasz == 0 || !(data_smhdr_flags & DATA_FLAG_DATAFLAG))
{
- DDS_WARNING("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": "
- "built-in data but no payload\n",
- sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
- PGUID (srcguid), sampleinfo->seq);
+ GVWARNING ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": built-in data but no payload\n",
+ sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
+ PGUID (srcguid), sampleinfo->seq);
goto done_upd_deliv;
}
}
@@ -1795,14 +1661,13 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str
hasn't been checked fully yet. */
if (!(data_smhdr_flags & DATA_FLAG_KEYFLAG))
{
- DDS_WARNING("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": "
- "dispose/unregister of built-in data but payload not just key\n",
- sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
- PGUID (srcguid), sampleinfo->seq);
+ GVWARNING ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": dispose/unregister of built-in data but payload not just key\n",
+ sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
+ PGUID (srcguid), sampleinfo->seq);
goto done_upd_deliv;
}
}
- else if ((qos.present & PP_KEYHASH) && !NN_STRICT_P)
+ else if ((qos.present & PP_KEYHASH) && !NN_STRICT_P(gv->config))
{
/* For SPDP/SEDP, fake a parameter list with just a keyhash. For
PMD, just use the keyhash directly. Too hard to fix everything
@@ -1837,9 +1702,9 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str
pid = PID_ENDPOINT_GUID;
break;
default:
- DDS_LOG(DDS_LC_DISCOVERY, "data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": mapping keyhash to ENDPOINT_GUID",
- sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
- PGUID (srcguid), sampleinfo->seq);
+ GVLOGDISC ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": mapping keyhash to ENDPOINT_GUID",
+ sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
+ PGUID (srcguid), sampleinfo->seq);
pid = PID_ENDPOINT_GUID;
break;
}
@@ -1854,22 +1719,24 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str
}
else
{
- DDS_WARNING("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": "
- "dispose/unregister with no content\n",
- sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
- PGUID (srcguid), sampleinfo->seq);
+ GVWARNING ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": dispose/unregister with no content\n",
+ sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
+ PGUID (srcguid), sampleinfo->seq);
goto done_upd_deliv;
}
- timestamp = valid_ddsi_timestamp(sampleinfo->timestamp) ? nn_wctime_from_ddsi_time(sampleinfo->timestamp): now();
+ if (sampleinfo->timestamp.v != NN_WCTIME_INVALID.v)
+ timestamp = sampleinfo->timestamp;
+ else
+ timestamp = now ();
switch (srcguid.entityid.u)
{
case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER:
- handle_SPDP (sampleinfo->rst, timestamp, statusinfo, datap, datasz);
+ handle_SPDP (sampleinfo->rst, sampleinfo->seq, timestamp, statusinfo, datap, datasz);
break;
case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER:
case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER:
- handle_SEDP (sampleinfo->rst, timestamp, statusinfo, datap, datasz);
+ handle_SEDP (sampleinfo->rst, sampleinfo->seq, timestamp, statusinfo, datap, datasz);
break;
case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER:
handle_PMD (sampleinfo->rst, timestamp, statusinfo, datap, datasz);
@@ -1877,14 +1744,10 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str
case NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER:
handle_SEDP_CM (sampleinfo->rst, srcguid.entityid, timestamp, statusinfo, datap, datasz);
break;
- case NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER:
- case NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER:
- handle_SEDP_GROUP (sampleinfo->rst, timestamp, statusinfo, datap, datasz);
- break;
default:
- DDS_LOG (DDS_LC_DISCOVERY, "data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": not handled\n",
- sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
- PGUID (srcguid), sampleinfo->seq);
+ GVLOGDISC ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": not handled\n",
+ sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
+ PGUID (srcguid), sampleinfo->seq);
break;
}
diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c
index 35ed218..9012f7b 100644
--- a/src/core/ddsi/src/q_debmon.c
+++ b/src/core/ddsi/src/q_debmon.c
@@ -33,7 +33,6 @@
#include "dds/ddsi/q_ddsi_discovery.h"
#include "dds/ddsi/q_protocol.h" /* NN_ENTITYID_... */
#include "dds/ddsi/q_unused.h"
-#include "dds/ddsi/q_error.h"
#include "dds/ddsi/q_debmon.h"
#include "dds/ddsi/ddsi_serdata.h"
#include "dds/ddsi/ddsi_tran.h"
@@ -53,6 +52,7 @@ struct debug_monitor {
ddsi_tran_listener_t servsock;
ddsrt_mutex_t lock;
ddsrt_cond_t cond;
+ struct q_globals *gv;
struct plugin *plugins;
int stop;
};
@@ -86,7 +86,7 @@ static void print_address (const nn_locator_t *n, void *varg)
{
struct print_address_arg *arg = varg;
char buf[DDSI_LOCSTRLEN];
- arg->count += cpf (arg->conn, " %s", ddsi_locator_to_string (buf, sizeof(buf), n));
+ arg->count += cpf (arg->conn, " %s", ddsi_locator_to_string (arg->conn->m_base.gv, buf, sizeof(buf), n));
}
static int print_addrset (ddsi_tran_conn_t conn, const char *prefix, struct addrset *as, const char *suffix)
@@ -108,15 +108,14 @@ static int print_addrset_if_notempty (ddsi_tran_conn_t conn, const char *prefix,
}
static int print_any_endpoint_common (ddsi_tran_conn_t conn, const char *label, const struct entity_common *e,
- const struct nn_xqos *xqos, const struct ddsi_sertopic *topic)
+ const struct dds_qos *xqos, const struct ddsi_sertopic *topic)
{
int x = 0;
x += cpf (conn, " %s %x:%x:%x:%x ", label, PGUID (e->guid));
if (xqos->present & QP_PARTITION)
{
- unsigned i;
if (xqos->partition.n > 1) cpf (conn, "{");
- for (i = 0; i < xqos->partition.n; i++)
+ for (uint32_t i = 0; i < xqos->partition.n; i++)
x += cpf (conn, "%s%s", i == 0 ? "" : ",", xqos->partition.strs[i]);
if (xqos->partition.n > 1) cpf (conn, "}");
x += cpf (conn, ".%s/%s",
@@ -127,7 +126,7 @@ static int print_any_endpoint_common (ddsi_tran_conn_t conn, const char *label,
return x;
}
-static int print_endpoint_common (ddsi_tran_conn_t conn, const char *label, const struct entity_common *e, const struct endpoint_common *c, const struct nn_xqos *xqos, const struct ddsi_sertopic *topic)
+static int print_endpoint_common (ddsi_tran_conn_t conn, const char *label, const struct entity_common *e, const struct endpoint_common *c, const struct dds_qos *xqos, const struct ddsi_sertopic *topic)
{
DDSRT_UNUSED_ARG (c);
return print_any_endpoint_common (conn, label, e, xqos, topic);
@@ -142,13 +141,13 @@ static int print_proxy_endpoint_common (ddsi_tran_conn_t conn, const char *label
}
-static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_t conn)
+static int print_participants (struct thread_state1 * const ts1, struct q_globals *gv, ddsi_tran_conn_t conn)
{
struct ephash_enum_participant e;
struct participant *p;
int x = 0;
- thread_state_awake (ts1);
- ephash_enum_participant_init (&e);
+ thread_state_awake_fixed_domain (ts1);
+ ephash_enum_participant_init (&e, gv->guid_hash);
while ((p = ephash_enum_participant_next (&e)) != NULL)
{
ddsrt_mutex_lock (&p->e.lock);
@@ -158,7 +157,7 @@ static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_
{
struct ephash_enum_reader er;
struct reader *r;
- ephash_enum_reader_init (&er);
+ ephash_enum_reader_init (&er, gv->guid_hash);
while ((r = ephash_enum_reader_next (&er)) != NULL)
{
ddsrt_avl_iter_t writ;
@@ -180,7 +179,7 @@ static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_
{
struct ephash_enum_writer ew;
struct writer *w;
- ephash_enum_writer_init (&ew);
+ ephash_enum_writer_init (&ew, gv->guid_hash);
while ((w = ephash_enum_writer_next (&ew)) != NULL)
{
ddsrt_avl_iter_t rdit;
@@ -227,13 +226,13 @@ static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_
return x;
}
-static int print_proxy_participants (struct thread_state1 * const ts1, ddsi_tran_conn_t conn)
+static int print_proxy_participants (struct thread_state1 * const ts1, struct q_globals *gv, ddsi_tran_conn_t conn)
{
struct ephash_enum_proxy_participant e;
struct proxy_participant *p;
int x = 0;
- thread_state_awake (ts1);
- ephash_enum_proxy_participant_init (&e);
+ thread_state_awake_fixed_domain (ts1);
+ ephash_enum_proxy_participant_init (&e, gv->guid_hash);
while ((p = ephash_enum_proxy_participant_next (&e)) != NULL)
{
ddsrt_mutex_lock (&p->e.lock);
@@ -245,7 +244,7 @@ static int print_proxy_participants (struct thread_state1 * const ts1, ddsi_tran
{
struct ephash_enum_proxy_reader er;
struct proxy_reader *r;
- ephash_enum_proxy_reader_init (&er);
+ ephash_enum_proxy_reader_init (&er, gv->guid_hash);
while ((r = ephash_enum_proxy_reader_next (&er)) != NULL)
{
ddsrt_avl_iter_t writ;
@@ -264,7 +263,7 @@ static int print_proxy_participants (struct thread_state1 * const ts1, ddsi_tran
{
struct ephash_enum_proxy_writer ew;
struct proxy_writer *w;
- ephash_enum_proxy_writer_init (&ew);
+ ephash_enum_proxy_writer_init (&ew, gv->guid_hash);
while ((w = ephash_enum_proxy_writer_next (&ew)) != NULL)
{
ddsrt_avl_iter_t rdit;
@@ -286,7 +285,7 @@ static int print_proxy_participants (struct thread_state1 * const ts1, ddsi_tran
x += cpf (conn, " tl-catchup end_of_tl_seq %lld\n", m->u.not_in_sync.end_of_tl_seq);
break;
case PRMSS_OUT_OF_SYNC:
- x += cpf (conn, " out-of-sync end_of_tl_seq %lld end_of_out_of_sync_seq %lld\n", m->u.not_in_sync.end_of_tl_seq, m->u.not_in_sync.end_of_out_of_sync_seq);
+ x += cpf (conn, " out-of-sync end_of_tl_seq %lld\n", m->u.not_in_sync.end_of_tl_seq);
break;
}
}
@@ -305,9 +304,9 @@ static void debmon_handle_connection (struct debug_monitor *dm, ddsi_tran_conn_t
struct thread_state1 * const ts1 = lookup_thread_state ();
struct plugin *p;
int r = 0;
- r += print_participants (ts1, conn);
+ r += print_participants (ts1, dm->gv, conn);
if (r == 0)
- r += print_proxy_participants (ts1, conn);
+ r += print_proxy_participants (ts1, dm->gv, conn);
/* Note: can only add plugins (at the tail) */
ddsrt_mutex_lock (&dm->lock);
@@ -346,25 +345,26 @@ static uint32_t debmon_main (void *vdm)
return 0;
}
-struct debug_monitor *new_debug_monitor (int port)
+struct debug_monitor *new_debug_monitor (struct q_globals *gv, int port)
{
struct debug_monitor *dm;
- if (config.monitor_port < 0)
+ if (gv->config.monitor_port < 0)
return NULL;
- if (ddsi_tcp_init () < 0)
+ if (ddsi_tcp_init (gv) < 0)
return NULL;
dm = ddsrt_malloc (sizeof (*dm));
+ dm->gv = gv;
dm->plugins = NULL;
- if ((dm->tran_factory = ddsi_factory_find ("tcp")) == NULL)
- dm->tran_factory = ddsi_factory_find ("tcp6");
+ if ((dm->tran_factory = ddsi_factory_find (gv, "tcp")) == NULL)
+ dm->tran_factory = ddsi_factory_find (gv, "tcp6");
dm->servsock = ddsi_factory_create_listener (dm->tran_factory, port, NULL);
if (dm->servsock == NULL)
{
- DDS_WARNING("debmon: can't create socket\n");
+ GVWARNING ("debmon: can't create socket\n");
goto err_servsock;
}
@@ -372,7 +372,7 @@ struct debug_monitor *new_debug_monitor (int port)
nn_locator_t loc;
char buf[DDSI_LOCSTRLEN];
(void) ddsi_listener_locator(dm->servsock, &loc);
- DDS_LOG(DDS_LC_CONFIG, "debmon at %s\n", ddsi_locator_to_string (buf, sizeof(buf), &loc));
+ GVLOG (DDS_LC_CONFIG, "debmon at %s\n", ddsi_locator_to_string (gv, buf, sizeof(buf), &loc));
}
ddsrt_mutex_init (&dm->lock);
@@ -380,7 +380,7 @@ struct debug_monitor *new_debug_monitor (int port)
if (ddsi_listener_listen (dm->servsock) < 0)
goto err_listen;
dm->stop = 0;
- create_thread(&dm->servts, "debmon", debmon_main, dm);
+ create_thread (&dm->servts, gv, "debmon", debmon_main, dm);
return dm;
err_listen:
diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c
index 53c0bc6..06afbbf 100644
--- a/src/core/ddsi/src/q_entity.c
+++ b/src/core/ddsi/src/q_entity.c
@@ -38,10 +38,11 @@
#include "dds/ddsi/q_radmin.h"
#include "dds/ddsi/q_protocol.h" /* NN_ENTITYID_... */
#include "dds/ddsi/q_unused.h"
-#include "dds/ddsi/q_error.h"
#include "dds/ddsi/ddsi_serdata_default.h"
#include "dds/ddsi/ddsi_mcgroup.h"
#include "dds/ddsi/q_receive.h"
+#include "dds/ddsi/ddsi_udp.h" /* nn_mc4gen_address_t */
+#include "dds/ddsi/q_rhc.h"
#include "dds/ddsi/sysdeps.h"
#include "dds__whc.h"
@@ -55,8 +56,11 @@ struct deleted_participant {
nn_mtime_t t_prune;
};
-static ddsrt_mutex_t deleted_participants_lock;
-static ddsrt_avl_tree_t deleted_participants;
+struct deleted_participants_admin {
+ ddsrt_mutex_t deleted_participants_lock;
+ ddsrt_avl_tree_t deleted_participants;
+ int64_t delay;
+};
static int compare_guid (const void *va, const void *vb);
static void augment_wr_prd_match (void *vnode, const void *vleft, const void *vright);
@@ -88,11 +92,10 @@ static const unsigned prismtech_builtin_writers_besmask =
NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER |
NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER;
-static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_cbarg);
-static dds_retcode_t new_reader_guid (struct reader **rd_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc *rhc, status_cb_t status_cb, void *status_cbarg);
+static dds_return_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc, status_cb_t status_cb, void *status_cbarg);
+static dds_return_t new_reader_guid (struct reader **rd_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct rhc *rhc, status_cb_t status_cb, void *status_cbarg);
static struct participant *ref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity);
static void unref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity);
-static void delete_proxy_group_locked (struct proxy_group *pgroup, nn_wctime_t timestamp, int isimplicit);
static int gcreq_participant (struct participant *pp);
static int gcreq_writer (struct writer *wr);
@@ -101,6 +104,11 @@ static int gcreq_proxy_participant (struct proxy_participant *proxypp);
static int gcreq_proxy_writer (struct proxy_writer *pwr);
static int gcreq_proxy_reader (struct proxy_reader *prd);
+extern inline bool builtintopic_is_visible (const struct ddsi_builtin_topic_interface *btif, const struct nn_guid *guid, nn_vendorid_t vendorid);
+extern inline bool builtintopic_is_builtintopic (const struct ddsi_builtin_topic_interface *btif, const struct ddsi_sertopic *topic);
+extern inline struct ddsi_tkmap_instance *builtintopic_get_tkmap_entry (const struct ddsi_builtin_topic_interface *btif, const struct nn_guid *guid);
+extern inline void builtintopic_write (const struct ddsi_builtin_topic_interface *btif, const struct entity_common *e, nn_wctime_t timestamp, bool alive);
+
static int compare_guid (const void *va, const void *vb)
{
return memcmp (va, vb, sizeof (nn_guid_t));
@@ -137,6 +145,21 @@ int is_reader_entityid (nn_entityid_t id)
}
}
+int is_keyed_endpoint_entityid (nn_entityid_t id)
+{
+ switch (id.u & NN_ENTITYID_KIND_MASK)
+ {
+ case NN_ENTITYID_KIND_READER_WITH_KEY:
+ case NN_ENTITYID_KIND_WRITER_WITH_KEY:
+ return 1;
+ case NN_ENTITYID_KIND_READER_NO_KEY:
+ case NN_ENTITYID_KIND_WRITER_NO_KEY:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
int is_builtin_entityid (nn_entityid_t id, nn_vendorid_t vendorid)
{
if ((id.u & NN_ENTITYID_SOURCE_MASK) == NN_ENTITYID_SOURCE_BUILTIN)
@@ -163,17 +186,19 @@ bool is_local_orphan_endpoint (const struct entity_common *e)
is_builtin_endpoint (e->guid.entityid, NN_VENDORID_ECLIPSE));
}
-static void entity_common_init (struct entity_common *e, const struct nn_guid *guid, const char *name, enum entity_kind kind, nn_wctime_t tcreate, nn_vendorid_t vendorid, bool onlylocal)
+static void entity_common_init (struct entity_common *e, struct q_globals *gv, const struct nn_guid *guid, const char *name, enum entity_kind kind, nn_wctime_t tcreate, nn_vendorid_t vendorid, bool onlylocal)
{
e->guid = *guid;
e->kind = kind;
e->tupdate = tcreate;
e->name = ddsrt_strdup (name ? name : "");
e->onlylocal = onlylocal;
+ e->gv = gv;
ddsrt_mutex_init (&e->lock);
- if (ddsi_plugin.builtintopic_is_visible (guid->entityid, onlylocal, vendorid))
+ ddsrt_mutex_init (&e->qos_lock);
+ if (builtintopic_is_visible (gv->builtin_topic_interface, guid, vendorid))
{
- e->tk = ddsi_plugin.builtintopic_get_tkmap_entry (guid);
+ e->tk = builtintopic_get_tkmap_entry (gv->builtin_topic_interface, guid);
e->iid = e->tk->m_iid;
}
else
@@ -186,12 +211,13 @@ static void entity_common_init (struct entity_common *e, const struct nn_guid *g
static void entity_common_fini (struct entity_common *e)
{
if (e->tk)
- ddsi_tkmap_instance_unref (e->tk);
+ ddsi_tkmap_instance_unref (e->gv->m_tkmap, e->tk);
ddsrt_free (e->name);
+ ddsrt_mutex_destroy (&e->qos_lock);
ddsrt_mutex_destroy (&e->lock);
}
-void local_reader_ary_init (struct local_reader_ary *x)
+static void local_reader_ary_init (struct local_reader_ary *x)
{
ddsrt_mutex_init (&x->rdary_lock);
x->valid = 1;
@@ -201,13 +227,13 @@ void local_reader_ary_init (struct local_reader_ary *x)
x->rdary[0] = NULL;
}
-void local_reader_ary_fini (struct local_reader_ary *x)
+static void local_reader_ary_fini (struct local_reader_ary *x)
{
ddsrt_free (x->rdary);
ddsrt_mutex_destroy (&x->rdary_lock);
}
-void local_reader_ary_insert (struct local_reader_ary *x, struct reader *rd)
+static void local_reader_ary_insert (struct local_reader_ary *x, struct reader *rd)
{
ddsrt_mutex_lock (&x->rdary_lock);
x->n_readers++;
@@ -217,9 +243,9 @@ void local_reader_ary_insert (struct local_reader_ary *x, struct reader *rd)
ddsrt_mutex_unlock (&x->rdary_lock);
}
-void local_reader_ary_remove (struct local_reader_ary *x, struct reader *rd)
+static void local_reader_ary_remove (struct local_reader_ary *x, struct reader *rd)
{
- unsigned i;
+ uint32_t i;
ddsrt_mutex_lock (&x->rdary_lock);
for (i = 0; i < x->n_readers; i++)
{
@@ -235,7 +261,15 @@ void local_reader_ary_remove (struct local_reader_ary *x, struct reader *rd)
ddsrt_mutex_unlock (&x->rdary_lock);
}
-void local_reader_ary_setinvalid (struct local_reader_ary *x)
+void local_reader_ary_setfastpath_ok (struct local_reader_ary *x, bool fastpath_ok)
+{
+ ddsrt_mutex_lock (&x->rdary_lock);
+ if (x->valid)
+ x->fastpath_ok = fastpath_ok;
+ ddsrt_mutex_unlock (&x->rdary_lock);
+}
+
+static void local_reader_ary_setinvalid (struct local_reader_ary *x)
{
ddsrt_mutex_lock (&x->rdary_lock);
x->valid = 0;
@@ -264,111 +298,126 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e)
/* DELETED PARTICIPANTS --------------------------------------------- */
-int deleted_participants_admin_init (void)
+struct deleted_participants_admin *deleted_participants_admin_new (int64_t delay)
{
- ddsrt_mutex_init (&deleted_participants_lock);
- ddsrt_avl_init (&deleted_participants_treedef, &deleted_participants);
- return 0;
+ struct deleted_participants_admin *admin = ddsrt_malloc (sizeof (*admin));
+ ddsrt_mutex_init (&admin->deleted_participants_lock);
+ ddsrt_avl_init (&deleted_participants_treedef, &admin->deleted_participants);
+ admin->delay = delay;
+ return admin;
}
-void deleted_participants_admin_fini (void)
+void deleted_participants_admin_free (struct deleted_participants_admin *admin)
{
- ddsrt_avl_free (&deleted_participants_treedef, &deleted_participants, ddsrt_free);
- ddsrt_mutex_destroy (&deleted_participants_lock);
+ ddsrt_avl_free (&deleted_participants_treedef, &admin->deleted_participants, ddsrt_free);
+ ddsrt_mutex_destroy (&admin->deleted_participants_lock);
+ ddsrt_free (admin);
}
-static void prune_deleted_participant_guids_unlocked (nn_mtime_t tnow)
+static void prune_deleted_participant_guids_unlocked (struct deleted_participants_admin *admin, nn_mtime_t tnow)
{
/* Could do a better job of finding prunable ones efficiently under
all circumstances, but I expect the tree to be very small at all
times, so a full scan is fine, too ... */
struct deleted_participant *dpp;
- dpp = ddsrt_avl_find_min (&deleted_participants_treedef, &deleted_participants);
+ dpp = ddsrt_avl_find_min (&deleted_participants_treedef, &admin->deleted_participants);
while (dpp)
{
- struct deleted_participant *dpp1 = ddsrt_avl_find_succ (&deleted_participants_treedef, &deleted_participants, dpp);
+ struct deleted_participant *dpp1 = ddsrt_avl_find_succ (&deleted_participants_treedef, &admin->deleted_participants, dpp);
if (dpp->t_prune.v < tnow.v)
{
- ddsrt_avl_delete (&deleted_participants_treedef, &deleted_participants, dpp);
+ ddsrt_avl_delete (&deleted_participants_treedef, &admin->deleted_participants, dpp);
ddsrt_free (dpp);
}
dpp = dpp1;
}
}
-static void prune_deleted_participant_guids (nn_mtime_t tnow)
+static void prune_deleted_participant_guids (struct deleted_participants_admin *admin, nn_mtime_t tnow)
{
- ddsrt_mutex_lock (&deleted_participants_lock);
- prune_deleted_participant_guids_unlocked (tnow);
- ddsrt_mutex_unlock (&deleted_participants_lock);
+ ddsrt_mutex_lock (&admin->deleted_participants_lock);
+ prune_deleted_participant_guids_unlocked (admin, tnow);
+ ddsrt_mutex_unlock (&admin->deleted_participants_lock);
}
-static void remember_deleted_participant_guid (const struct nn_guid *guid)
+static void remember_deleted_participant_guid (struct deleted_participants_admin *admin, const struct nn_guid *guid)
{
struct deleted_participant *n;
ddsrt_avl_ipath_t path;
- ddsrt_mutex_lock (&deleted_participants_lock);
- if (ddsrt_avl_lookup_ipath (&deleted_participants_treedef, &deleted_participants, guid, &path) == NULL)
+ ddsrt_mutex_lock (&admin->deleted_participants_lock);
+ if (ddsrt_avl_lookup_ipath (&deleted_participants_treedef, &admin->deleted_participants, guid, &path) == NULL)
{
if ((n = ddsrt_malloc (sizeof (*n))) != NULL)
{
n->guid = *guid;
n->t_prune.v = T_NEVER;
n->for_what = DPG_LOCAL | DPG_REMOTE;
- ddsrt_avl_insert_ipath (&deleted_participants_treedef, &deleted_participants, n, &path);
+ ddsrt_avl_insert_ipath (&deleted_participants_treedef, &admin->deleted_participants, n, &path);
}
}
- ddsrt_mutex_unlock (&deleted_participants_lock);
+ ddsrt_mutex_unlock (&admin->deleted_participants_lock);
}
-int is_deleted_participant_guid (const struct nn_guid *guid, unsigned for_what)
+int is_deleted_participant_guid (struct deleted_participants_admin *admin, const struct nn_guid *guid, unsigned for_what)
{
struct deleted_participant *n;
int known;
- ddsrt_mutex_lock (&deleted_participants_lock);
- prune_deleted_participant_guids_unlocked (now_mt());
- if ((n = ddsrt_avl_lookup (&deleted_participants_treedef, &deleted_participants, guid)) == NULL)
+ ddsrt_mutex_lock (&admin->deleted_participants_lock);
+ prune_deleted_participant_guids_unlocked (admin, now_mt ());
+ if ((n = ddsrt_avl_lookup (&deleted_participants_treedef, &admin->deleted_participants, guid)) == NULL)
known = 0;
else
known = ((n->for_what & for_what) != 0);
- ddsrt_mutex_unlock (&deleted_participants_lock);
+ ddsrt_mutex_unlock (&admin->deleted_participants_lock);
return known;
}
-static void remove_deleted_participant_guid (const struct nn_guid *guid, unsigned for_what)
+static void remove_deleted_participant_guid (ddsrt_log_cfg_t *logcfg, struct deleted_participants_admin *admin, const struct nn_guid *guid, unsigned for_what)
{
struct deleted_participant *n;
- DDS_LOG(DDS_LC_DISCOVERY, "remove_deleted_participant_guid("PGUIDFMT" for_what=%x)\n", PGUID (*guid), for_what);
- ddsrt_mutex_lock (&deleted_participants_lock);
- if ((n = ddsrt_avl_lookup (&deleted_participants_treedef, &deleted_participants, guid)) != NULL)
- {
- if (config.prune_deleted_ppant.enforce_delay)
- {
- n->t_prune = add_duration_to_mtime (now_mt (), config.prune_deleted_ppant.delay);
- }
- else
- {
- n->for_what &= ~for_what;
- if (n->for_what != 0)
- {
- /* For local participants (remove called with LOCAL, leaving
- REMOTE blacklisted, and has to do with network briding) */
- n->t_prune = add_duration_to_mtime (now_mt (), config.prune_deleted_ppant.delay);
- }
- else
- {
- ddsrt_avl_delete (&deleted_participants_treedef, &deleted_participants, n);
- ddsrt_free (n);
- }
- }
- }
- ddsrt_mutex_unlock (&deleted_participants_lock);
+ DDS_CLOG (DDS_LC_DISCOVERY, logcfg, "remove_deleted_participant_guid("PGUIDFMT" for_what=%x)\n", PGUID (*guid), for_what);
+ ddsrt_mutex_lock (&admin->deleted_participants_lock);
+ if ((n = ddsrt_avl_lookup (&deleted_participants_treedef, &admin->deleted_participants, guid)) != NULL)
+ n->t_prune = add_duration_to_mtime (now_mt (), admin->delay);
+ ddsrt_mutex_unlock (&admin->deleted_participants_lock);
}
/* PARTICIPANT ------------------------------------------------------ */
-int pp_allocate_entityid(nn_entityid_t *id, unsigned kind, struct participant *pp)
+static bool update_qos_locked (struct entity_common *e, dds_qos_t *ent_qos, const dds_qos_t *xqos, nn_wctime_t timestamp)
+{
+ uint64_t mask;
+
+ mask = nn_xqos_delta (ent_qos, xqos, QP_CHANGEABLE_MASK & ~(QP_RXO_MASK | QP_PARTITION)) & xqos->present;
+#if 0
+ int a = (ent_qos->present & QP_TOPIC_DATA) ? (int) ent_qos->topic_data.length : 6;
+ int b = (xqos->present & QP_TOPIC_DATA) ? (int) xqos->topic_data.length : 6;
+ char *astr = (ent_qos->present & QP_TOPIC_DATA) ? (char *) ent_qos->topic_data.value : "(null)";
+ char *bstr = (xqos->present & QP_TOPIC_DATA) ? (char *) xqos->topic_data.value : "(null)";
+ printf ("%d: "PGUIDFMT" ent_qos %d \"%*.*s\" xqos %d \"%*.*s\" => mask %d\n",
+ (int) getpid (), PGUID (e->guid),
+ !!(ent_qos->present & QP_TOPIC_DATA), a, a, astr,
+ !!(xqos->present & QP_TOPIC_DATA), b, b, bstr,
+ !!(mask & QP_TOPIC_DATA));
+#endif
+ EELOGDISC (e, "update_qos_locked "PGUIDFMT" delta=%"PRIu64" QOS={", PGUID(e->guid), mask);
+ nn_log_xqos (DDS_LC_DISCOVERY, &e->gv->logconfig, xqos);
+ EELOGDISC (e, "}\n");
+
+ if (mask == 0)
+ /* no change, or an as-yet unsupported one */
+ return false;
+
+ ddsrt_mutex_lock (&e->qos_lock);
+ nn_xqos_fini_mask (ent_qos, mask);
+ nn_xqos_mergein_missing (ent_qos, xqos, mask);
+ ddsrt_mutex_unlock (&e->qos_lock);
+ builtintopic_write (e->gv->builtin_topic_interface, e, timestamp, true);
+ return true;
+}
+
+static dds_return_t pp_allocate_entityid(nn_entityid_t *id, uint32_t kind, struct participant *pp)
{
uint32_t id1;
int ret = 0;
@@ -380,21 +429,21 @@ int pp_allocate_entityid(nn_entityid_t *id, unsigned kind, struct participant *p
}
else
{
- DDS_ERROR("pp_allocate_entityid("PGUIDFMT"): all ids in use\n", PGUID(pp->e.guid));
- ret = Q_ERR_OUT_OF_IDS;
+ DDS_CERROR (&pp->e.gv->logconfig, "pp_allocate_entityid("PGUIDFMT"): all ids in use\n", PGUID(pp->e.guid));
+ ret = DDS_RETCODE_OUT_OF_RESOURCES;
}
ddsrt_mutex_unlock (&pp->e.lock);
return ret;
}
-void pp_release_entityid(struct participant *pp, nn_entityid_t id)
+static void pp_release_entityid(struct participant *pp, nn_entityid_t id)
{
ddsrt_mutex_lock (&pp->e.lock);
inverse_uint32_set_free(&pp->avail_entityids.x, id.u / NN_ENTITYID_ALLOCSTEP);
ddsrt_mutex_unlock (&pp->e.lock);
}
-int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plist_t *plist)
+dds_return_t new_participant_guid (const nn_guid_t *ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist)
{
struct participant *pp;
nn_guid_t subguid, group_guid;
@@ -404,64 +453,64 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis
/* privileged participant MUST have builtin readers and writers */
assert (!(flags & RTPS_PF_PRIVILEGED_PP) || (flags & (RTPS_PF_NO_BUILTIN_READERS | RTPS_PF_NO_BUILTIN_WRITERS)) == 0);
- prune_deleted_participant_guids (now_mt ());
+ prune_deleted_participant_guids (gv->deleted_participants, now_mt ());
/* FIXME: FULL LOCKING AROUND NEW_XXX FUNCTIONS, JUST SO EXISTENCE TESTS ARE PRECISE */
/* Participant may not exist yet, but this test is imprecise: if it
used to exist, but is currently being deleted and we're trying to
recreate it. */
- if (ephash_lookup_participant_guid (ppguid) != NULL)
- return Q_ERR_ENTITY_EXISTS;
+ if (ephash_lookup_participant_guid (gv->guid_hash, ppguid) != NULL)
+ return DDS_RETCODE_PRECONDITION_NOT_MET;
- if (config.max_participants == 0)
+ if (gv->config.max_participants == 0)
{
- ddsrt_mutex_lock (&gv.participant_set_lock);
- ++gv.nparticipants;
- ddsrt_mutex_unlock (&gv.participant_set_lock);
+ ddsrt_mutex_lock (&gv->participant_set_lock);
+ ++gv->nparticipants;
+ ddsrt_mutex_unlock (&gv->participant_set_lock);
}
else
{
- ddsrt_mutex_lock (&gv.participant_set_lock);
- if (gv.nparticipants < config.max_participants)
+ ddsrt_mutex_lock (&gv->participant_set_lock);
+ if (gv->nparticipants < gv->config.max_participants)
{
- ++gv.nparticipants;
- ddsrt_mutex_unlock (&gv.participant_set_lock);
+ ++gv->nparticipants;
+ ddsrt_mutex_unlock (&gv->participant_set_lock);
}
else
{
- ddsrt_mutex_unlock (&gv.participant_set_lock);
- DDS_ERROR("new_participant("PGUIDFMT", %x) failed: max participants reached\n", PGUID (*ppguid), flags);
- return Q_ERR_OUT_OF_IDS;
+ ddsrt_mutex_unlock (&gv->participant_set_lock);
+ GVERROR ("new_participant("PGUIDFMT", %x) failed: max participants reached\n", PGUID (*ppguid), flags);
+ return DDS_RETCODE_OUT_OF_RESOURCES;
}
}
- DDS_LOG(DDS_LC_DISCOVERY, "new_participant("PGUIDFMT", %x)\n", PGUID (*ppguid), flags);
+ GVLOGDISC ("new_participant("PGUIDFMT", %x)\n", PGUID (*ppguid), flags);
pp = ddsrt_malloc (sizeof (*pp));
- entity_common_init (&pp->e, ppguid, "", EK_PARTICIPANT, now (), NN_VENDORID_ECLIPSE, ((flags & RTPS_PF_ONLY_LOCAL) != 0));
+ entity_common_init (&pp->e, gv, ppguid, "", EK_PARTICIPANT, now (), NN_VENDORID_ECLIPSE, ((flags & RTPS_PF_ONLY_LOCAL) != 0));
pp->user_refc = 1;
pp->builtin_refc = 0;
pp->builtins_deleted = 0;
pp->is_ddsi2_pp = (flags & (RTPS_PF_PRIVILEGED_PP | RTPS_PF_IS_DDSI2_PP)) ? 1 : 0;
ddsrt_mutex_init (&pp->refc_lock);
inverse_uint32_set_init(&pp->avail_entityids.x, 1, UINT32_MAX / NN_ENTITYID_ALLOCSTEP);
- pp->lease_duration = config.lease_duration;
+ pp->lease_duration = gv->config.lease_duration;
pp->plist = ddsrt_malloc (sizeof (*pp->plist));
nn_plist_copy (pp->plist, plist);
- nn_plist_mergein_missing (pp->plist, &gv.default_plist_pp);
+ nn_plist_mergein_missing (pp->plist, &gv->default_local_plist_pp, ~(uint64_t)0, ~(uint64_t)0);
- if (dds_get_log_mask() & DDS_LC_DISCOVERY)
+ if (gv->logconfig.c.mask & DDS_LC_DISCOVERY)
{
- DDS_LOG(DDS_LC_DISCOVERY, "PARTICIPANT "PGUIDFMT" QOS={", PGUID (pp->e.guid));
- nn_log_xqos(DDS_LC_DISCOVERY, &pp->plist->qos);
- DDS_LOG(DDS_LC_DISCOVERY, "}\n");
+ GVLOGDISC ("PARTICIPANT "PGUIDFMT" QOS={", PGUID (pp->e.guid));
+ nn_log_xqos (DDS_LC_DISCOVERY, &gv->logconfig, &pp->plist->qos);
+ GVLOGDISC ("}\n");
}
- if (config.many_sockets_mode == MSM_MANY_UNICAST)
+ if (gv->config.many_sockets_mode == MSM_MANY_UNICAST)
{
- pp->m_conn = ddsi_factory_create_conn (gv.m_factory, 0, NULL);
+ pp->m_conn = ddsi_factory_create_conn (gv->m_factory, 0, NULL);
ddsi_conn_locator (pp->m_conn, &pp->m_locator);
}
else
@@ -488,54 +537,54 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis
if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS))
{
subguid.entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER);
- new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.spdp_endpoint_xqos, whc_new(1, 1, 1), LAST_WR_PARAMS);
+ new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->spdp_endpoint_xqos, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS);
/* But we need the as_disc address set for SPDP, because we need to
send it to everyone regardless of the existence of readers. */
{
- struct writer *wr = ephash_lookup_writer_guid (&subguid);
+ struct writer *wr = ephash_lookup_writer_guid (gv->guid_hash, &subguid);
assert (wr != NULL);
ddsrt_mutex_lock (&wr->e.lock);
unref_addrset (wr->as);
unref_addrset (wr->as_group);
- wr->as = ref_addrset (gv.as_disc);
- wr->as_group = ref_addrset (gv.as_disc_group);
+ wr->as = ref_addrset (gv->as_disc);
+ wr->as_group = ref_addrset (gv->as_disc_group);
ddsrt_mutex_unlock (&wr->e.lock);
}
pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER;
}
/* Make it globally visible, else the endpoint matching won't work. */
- ephash_insert_participant_guid (pp);
+ ephash_insert_participant_guid (gv->guid_hash, pp);
/* SEDP writers: */
if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS))
{
subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER);
- new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS);
+ new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS);
pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER;
subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER);
- new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS);
+ new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS);
pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER;
subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER);
- new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS);
+ new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS);
pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_WRITER;
subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER);
- new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS);
+ new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS);
pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER;
subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER);
- new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS);
+ new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS);
pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER;
}
- if (config.do_topic_discovery)
+ if (gv->config.do_topic_discovery)
{
/* TODO: make this one configurable, we don't want all participants to publish all topics (or even just those that they use themselves) */
subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER);
- new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS);
+ new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS);
pp->bes |= NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER;
}
@@ -543,7 +592,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis
if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS))
{
subguid.entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER);
- new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS);
+ new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS);
pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER;
}
@@ -551,31 +600,31 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis
if (!(flags & RTPS_PF_NO_BUILTIN_READERS))
{
subguid.entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER);
- new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.spdp_endpoint_xqos, NULL, NULL, NULL);
+ new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->spdp_endpoint_xqos, NULL, NULL, NULL);
pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR;
subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER);
- new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL);
+ new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL);
pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_DETECTOR;
subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER);
- new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL);
+ new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL);
pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_DETECTOR;
subguid.entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER);
- new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL);
+ new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL);
pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER;
subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_READER);
- new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL);
+ new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL);
pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_READER;
subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_READER);
- new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL);
+ new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL);
pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_READER;
subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_READER);
- new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL);
+ new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL);
pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_READER;
}
@@ -588,38 +637,38 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis
pointing to it.
Except when the participant is only locally available. */
if (!(flags & RTPS_PF_ONLY_LOCAL)) {
- ddsrt_mutex_lock (&gv.privileged_pp_lock);
+ ddsrt_mutex_lock (&gv->privileged_pp_lock);
if ((pp->bes & builtin_writers_besmask) != builtin_writers_besmask ||
(pp->prismtech_bes & prismtech_builtin_writers_besmask) != prismtech_builtin_writers_besmask)
{
/* Simply crash when the privileged participant doesn't exist when
it is needed. Its existence is a precondition, and this is not
a public API */
- assert (gv.privileged_pp != NULL);
- ref_participant (gv.privileged_pp, &pp->e.guid);
+ assert (gv->privileged_pp != NULL);
+ ref_participant (gv->privileged_pp, &pp->e.guid);
}
if (flags & RTPS_PF_PRIVILEGED_PP)
{
/* Crash when two privileged participants are created -- this is
not a public API. */
- assert (gv.privileged_pp == NULL);
- gv.privileged_pp = pp;
+ assert (gv->privileged_pp == NULL);
+ gv->privileged_pp = pp;
}
- ddsrt_mutex_unlock (&gv.privileged_pp_lock);
+ ddsrt_mutex_unlock (&gv->privileged_pp_lock);
}
/* Make it globally visible, then signal receive threads if
necessary. Must do in this order, or the receive thread won't
find the new participant */
- if (config.many_sockets_mode == MSM_MANY_UNICAST)
+ if (gv->config.many_sockets_mode == MSM_MANY_UNICAST)
{
ddsrt_atomic_fence ();
- ddsrt_atomic_inc32 (&gv.participant_set_generation);
- trigger_recv_threads ();
+ ddsrt_atomic_inc32 (&gv->participant_set_generation);
+ trigger_recv_threads (gv);
}
- ddsi_plugin.builtintopic_write (&pp->e, now(), true);
+ builtintopic_write (gv->builtin_topic_interface, &pp->e, now(), true);
/* SPDP periodic broadcast uses the retransmit path, so the initial
publication must be done differently. Must be later than making
@@ -635,7 +684,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis
fire before the calls return. If the initial sample wasn't
accepted, all is lost, but we continue nonetheless, even though
the participant won't be able to discover or be discovered. */
- pp->spdp_xevent = qxev_spdp (add_duration_to_mtime (now_mt (), 100 * T_MILLISECOND), &pp->e.guid, NULL);
+ pp->spdp_xevent = qxev_spdp (gv->xevents, add_duration_to_mtime (now_mt (), 100 * T_MILLISECOND), &pp->e.guid, NULL);
}
/* Also write the CM data - this one being transient local, we only
@@ -645,38 +694,46 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis
{
nn_mtime_t tsched;
tsched.v = (pp->lease_duration == T_NEVER) ? T_NEVER : 0;
- pp->pmd_update_xevent = qxev_pmd_update (tsched, &pp->e.guid);
+ pp->pmd_update_xevent = qxev_pmd_update (gv->xevents, tsched, &pp->e.guid);
}
return 0;
}
-int new_participant (nn_guid_t *p_ppguid, unsigned flags, const nn_plist_t *plist)
+dds_return_t new_participant (nn_guid_t *p_ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist)
{
nn_guid_t ppguid;
- ddsrt_mutex_lock (&gv.privileged_pp_lock);
- ppguid = gv.next_ppguid;
- if (gv.next_ppguid.prefix.u[2]++ == ~0u)
+ ddsrt_mutex_lock (&gv->privileged_pp_lock);
+ ppguid = gv->next_ppguid;
+ if (gv->next_ppguid.prefix.u[2]++ == ~0u)
{
- ddsrt_mutex_unlock (&gv.privileged_pp_lock);
- return Q_ERR_OUT_OF_IDS;
+ ddsrt_mutex_unlock (&gv->privileged_pp_lock);
+ return DDS_RETCODE_OUT_OF_RESOURCES;
}
- ddsrt_mutex_unlock (&gv.privileged_pp_lock);
+ ddsrt_mutex_unlock (&gv->privileged_pp_lock);
*p_ppguid = ppguid;
- return new_participant_guid (p_ppguid, flags, plist);
+ return new_participant_guid (p_ppguid, gv, flags, plist);
}
-static void delete_builtin_endpoint (const struct nn_guid *ppguid, unsigned entityid)
+void update_participant_plist (struct participant *pp, const nn_plist_t *plist)
+{
+ ddsrt_mutex_lock (&pp->e.lock);
+ if (update_qos_locked (&pp->e, &pp->plist->qos, &plist->qos, now ()))
+ spdp_write (pp);
+ ddsrt_mutex_unlock (&pp->e.lock);
+}
+
+static void delete_builtin_endpoint (struct q_globals *gv, const struct nn_guid *ppguid, unsigned entityid)
{
nn_guid_t guid;
guid.prefix = ppguid->prefix;
guid.entityid.u = entityid;
assert (is_builtin_entityid (to_entityid (entityid), NN_VENDORID_ECLIPSE));
if (is_writer_entityid (to_entityid (entityid)))
- delete_writer_nolinger (&guid);
+ delete_writer_nolinger (gv, &guid);
else
- (void)delete_reader (&guid);
+ (void)delete_reader (gv, &guid);
}
static struct participant *ref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity)
@@ -692,8 +749,8 @@ static struct participant *ref_participant (struct participant *pp, const struct
stguid = *guid_of_refing_entity;
else
memset (&stguid, 0, sizeof (stguid));
- DDS_LOG(DDS_LC_DISCOVERY, "ref_participant("PGUIDFMT" @ %p <- "PGUIDFMT" @ %p) user %"PRId32" builtin %"PRId32"\n",
- PGUID (pp->e.guid), (void*)pp, PGUID (stguid), (void*)guid_of_refing_entity, pp->user_refc, pp->builtin_refc);
+ ELOGDISC (pp, "ref_participant("PGUIDFMT" @ %p <- "PGUIDFMT" @ %p) user %"PRId32" builtin %"PRId32"\n",
+ PGUID (pp->e.guid), (void*)pp, PGUID (stguid), (void*)guid_of_refing_entity, pp->user_refc, pp->builtin_refc);
ddsrt_mutex_unlock (&pp->refc_lock);
return pp;
}
@@ -733,8 +790,8 @@ static void unref_participant (struct participant *pp, const struct nn_guid *gui
stguid = *guid_of_refing_entity;
else
memset (&stguid, 0, sizeof (stguid));
- DDS_LOG(DDS_LC_DISCOVERY, "unref_participant("PGUIDFMT" @ %p <- "PGUIDFMT" @ %p) user %"PRId32" builtin %"PRId32"\n",
- PGUID (pp->e.guid), (void*)pp, PGUID (stguid), (void*)guid_of_refing_entity, pp->user_refc, pp->builtin_refc);
+ ELOGDISC (pp, "unref_participant("PGUIDFMT" @ %p <- "PGUIDFMT" @ %p) user %"PRId32" builtin %"PRId32"\n",
+ PGUID (pp->e.guid), (void*)pp, PGUID (stguid), (void*)guid_of_refing_entity, pp->user_refc, pp->builtin_refc);
if (pp->user_refc == 0 && (pp->bes != 0 || pp->prismtech_bes != 0) && !pp->builtins_deleted)
{
@@ -776,13 +833,13 @@ static void unref_participant (struct participant *pp, const struct nn_guid *gui
sedp_write_cm_participant (pp, 0);
/* If this happens to be the privileged_pp, clear it */
- ddsrt_mutex_lock (&gv.privileged_pp_lock);
- if (pp == gv.privileged_pp)
- gv.privileged_pp = NULL;
- ddsrt_mutex_unlock (&gv.privileged_pp_lock);
+ ddsrt_mutex_lock (&pp->e.gv->privileged_pp_lock);
+ if (pp == pp->e.gv->privileged_pp)
+ pp->e.gv->privileged_pp = NULL;
+ ddsrt_mutex_unlock (&pp->e.gv->privileged_pp_lock);
for (i = 0; i < (int) (sizeof (builtin_endpoints_tab) / sizeof (builtin_endpoints_tab[0])); i++)
- delete_builtin_endpoint (&pp->e.guid, builtin_endpoints_tab[i]);
+ delete_builtin_endpoint (pp->e.gv, &pp->e.guid, builtin_endpoints_tab[i]);
}
else if (pp->user_refc == 0 && pp->builtin_refc == 0)
{
@@ -805,23 +862,23 @@ static void unref_participant (struct participant *pp, const struct nn_guid *gui
the unref_participant, because we may trigger a clean-up of
it. */
struct participant *ppp;
- ddsrt_mutex_lock (&gv.privileged_pp_lock);
- ppp = gv.privileged_pp;
- ddsrt_mutex_unlock (&gv.privileged_pp_lock);
+ ddsrt_mutex_lock (&pp->e.gv->privileged_pp_lock);
+ ppp = pp->e.gv->privileged_pp;
+ ddsrt_mutex_unlock (&pp->e.gv->privileged_pp_lock);
assert (ppp != NULL);
unref_participant (ppp, &pp->e.guid);
}
}
- ddsrt_mutex_lock (&gv.participant_set_lock);
- assert (gv.nparticipants > 0);
- if (--gv.nparticipants == 0)
- ddsrt_cond_broadcast (&gv.participant_set_cond);
- ddsrt_mutex_unlock (&gv.participant_set_lock);
- if (config.many_sockets_mode == MSM_MANY_UNICAST)
+ ddsrt_mutex_lock (&pp->e.gv->participant_set_lock);
+ assert (pp->e.gv->nparticipants > 0);
+ if (--pp->e.gv->nparticipants == 0)
+ ddsrt_cond_broadcast (&pp->e.gv->participant_set_cond);
+ ddsrt_mutex_unlock (&pp->e.gv->participant_set_lock);
+ if (pp->e.gv->config.many_sockets_mode == MSM_MANY_UNICAST)
{
ddsrt_atomic_fence_rel ();
- ddsrt_atomic_inc32 (&gv.participant_set_generation);
+ ddsrt_atomic_inc32 (&pp->e.gv->participant_set_generation);
/* Deleting the socket will usually suffice to wake up the
receiver threads, but in general, no one cares if it takes a
@@ -832,7 +889,7 @@ static void unref_participant (struct participant *pp, const struct nn_guid *gui
ddsrt_free (pp->plist);
ddsrt_mutex_destroy (&pp->refc_lock);
entity_common_fini (&pp->e);
- remove_deleted_participant_guid (&pp->e.guid, DPG_LOCAL);
+ remove_deleted_participant_guid (&pp->e.gv->logconfig, pp->e.gv->deleted_participants, &pp->e.guid, DPG_LOCAL);
inverse_uint32_set_fini(&pp->avail_entityids.x);
ddsrt_free (pp);
}
@@ -845,19 +902,19 @@ static void unref_participant (struct participant *pp, const struct nn_guid *gui
static void gc_delete_participant (struct gcreq *gcreq)
{
struct participant *pp = gcreq->arg;
- DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_participant(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pp->e.guid));
+ ELOGDISC (pp, "gc_delete_participant(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pp->e.guid));
gcreq_free (gcreq);
unref_participant (pp, NULL);
}
-int delete_participant (const struct nn_guid *ppguid)
+dds_return_t delete_participant (struct q_globals *gv, const struct nn_guid *ppguid)
{
struct participant *pp;
- if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL)
- return Q_ERR_UNKNOWN_ENTITY;
- ddsi_plugin.builtintopic_write (&pp->e, now(), false);
- remember_deleted_participant_guid (&pp->e.guid);
- ephash_remove_participant_guid (pp);
+ if ((pp = ephash_lookup_participant_guid (gv->guid_hash, ppguid)) == NULL)
+ return DDS_RETCODE_BAD_PARAMETER;
+ builtintopic_write (gv->builtin_topic_interface, &pp->e, now(), false);
+ remember_deleted_participant_guid (gv->deleted_participants, &pp->e.guid);
+ ephash_remove_participant_guid (gv->guid_hash, pp);
gcreq_participant (pp);
return 0;
}
@@ -921,14 +978,14 @@ struct writer *get_builtin_writer (const struct participant *pp, unsigned entity
who deletes it early! Lock's not really needed but provides
the memory barriers that guarantee visibility of the correct
value of privileged_pp. */
- ddsrt_mutex_lock (&gv.privileged_pp_lock);
- assert (gv.privileged_pp != NULL);
- bwr_guid.prefix = gv.privileged_pp->e.guid.prefix;
- ddsrt_mutex_unlock (&gv.privileged_pp_lock);
+ ddsrt_mutex_lock (&pp->e.gv->privileged_pp_lock);
+ assert (pp->e.gv->privileged_pp != NULL);
+ bwr_guid.prefix = pp->e.gv->privileged_pp->e.guid.prefix;
+ ddsrt_mutex_unlock (&pp->e.gv->privileged_pp_lock);
bwr_guid.entityid.u = entityid;
}
- return ephash_lookup_writer_guid (&bwr_guid);
+ return ephash_lookup_writer_guid (pp->e.gv->guid_hash, &bwr_guid);
}
/* WRITER/READER/PROXY-WRITER/PROXY-READER CONNECTION ---------------
@@ -970,20 +1027,21 @@ static int rebuild_compare_locs(const void *va, const void *vb)
static struct addrset *rebuild_make_all_addrs (int *nreaders, struct writer *wr)
{
struct addrset *all_addrs = new_addrset();
+ struct ephash *gh = wr->e.gv->guid_hash;
struct wr_prd_match *m;
ddsrt_avl_iter_t it;
#ifdef DDSI_INCLUDE_SSM
if (wr->supports_ssm && wr->ssm_as)
- copy_addrset_into_addrset_mc (all_addrs, wr->ssm_as);
+ copy_addrset_into_addrset_mc (wr->e.gv, all_addrs, wr->ssm_as);
#endif
*nreaders = 0;
for (m = ddsrt_avl_iter_first (&wr_readers_treedef, &wr->readers, &it); m; m = ddsrt_avl_iter_next (&it))
{
struct proxy_reader *prd;
- if ((prd = ephash_lookup_proxy_reader_guid (&m->prd_guid)) == NULL)
+ if ((prd = ephash_lookup_proxy_reader_guid (gh, &m->prd_guid)) == NULL)
continue;
(*nreaders)++;
- copy_addrset_into_addrset(all_addrs, prd->c.as);
+ copy_addrset_into_addrset(wr->e.gv, all_addrs, prd->c.as);
}
if (addrset_empty(all_addrs) || *nreaders == 0)
{
@@ -996,7 +1054,7 @@ static struct addrset *rebuild_make_all_addrs (int *nreaders, struct writer *wr)
}
}
-static void rebuild_make_locs(int *p_nlocs, nn_locator_t **p_locs, struct addrset *all_addrs)
+static void rebuild_make_locs(const struct ddsrt_log_cfg *logcfg, int *p_nlocs, nn_locator_t **p_locs, struct addrset *all_addrs)
{
struct rebuild_flatten_locs_arg flarg;
int nlocs;
@@ -1021,7 +1079,7 @@ static void rebuild_make_locs(int *p_nlocs, nn_locator_t **p_locs, struct addrse
j++;
}
nlocs = i+1;
- DDS_LOG(DDS_LC_DISCOVERY, "reduced nlocs=%d\n", nlocs);
+ DDS_CLOG (DDS_LC_DISCOVERY, logcfg, "reduced nlocs=%d\n", nlocs);
*p_nlocs = nlocs;
*p_locs = locs;
}
@@ -1029,6 +1087,7 @@ static void rebuild_make_locs(int *p_nlocs, nn_locator_t **p_locs, struct addrse
static void rebuild_make_covered(int8_t **covered, const struct writer *wr, int *nreaders, int nlocs, const nn_locator_t *locs)
{
struct rebuild_flatten_locs_arg flarg;
+ struct ephash *gh = wr->e.gv->guid_hash;
struct wr_prd_match *m;
ddsrt_avl_iter_t it;
int rdidx, i, j;
@@ -1044,7 +1103,7 @@ static void rebuild_make_covered(int8_t **covered, const struct writer *wr, int
{
struct proxy_reader *prd;
struct addrset *ass[] = { NULL, NULL, NULL };
- if ((prd = ephash_lookup_proxy_reader_guid (&m->prd_guid)) == NULL)
+ if ((prd = ephash_lookup_proxy_reader_guid (gh, &m->prd_guid)) == NULL)
continue;
ass[0] = prd->c.as;
#ifdef DDSI_INCLUDE_SSM
@@ -1092,45 +1151,47 @@ static void rebuild_make_locs_nrds(int **locs_nrds, int nreaders, int nlocs, con
if (covered[j * nlocs + i] >= 0)
n++;
-/* The compiler doesn't realize that ln is large enough. */
-DDSRT_WARNING_MSVC_OFF(6386);
+ /* The compiler doesn't realize that ln is large enough. */
+ DDSRT_WARNING_MSVC_OFF(6386);
ln[i] = n;
-DDSRT_WARNING_MSVC_ON(6386);
+ DDSRT_WARNING_MSVC_ON(6386);
}
*locs_nrds = ln;
}
-static void rebuild_trace_covered(int nreaders, int nlocs, const nn_locator_t *locs, const int *locs_nrds, const int8_t *covered)
+static void rebuild_trace_covered(const struct q_globals *gv, int nreaders, int nlocs, const nn_locator_t *locs, const int *locs_nrds, const int8_t *covered)
{
int i, j;
for (i = 0; i < nlocs; i++)
{
char buf[DDSI_LOCATORSTRLEN];
- ddsi_locator_to_string(buf, sizeof(buf), &locs[i]);
- DDS_LOG(DDS_LC_DISCOVERY, " loc %2d = %-20s %2d {", i, buf, locs_nrds[i]);
+ ddsi_locator_to_string(gv, buf, sizeof(buf), &locs[i]);
+ GVLOGDISC (" loc %2d = %-30s %2d {", i, buf, locs_nrds[i]);
for (j = 0; j < nreaders; j++)
if (covered[j * nlocs + i] >= 0)
- DDS_LOG(DDS_LC_DISCOVERY, " %d", covered[j * nlocs + i]);
+ GVLOGDISC (" %d", covered[j * nlocs + i]);
else
- DDS_LOG(DDS_LC_DISCOVERY, " .");
- DDS_LOG(DDS_LC_DISCOVERY, " }\n");
+ GVLOGDISC (" .");
+ GVLOGDISC (" }\n");
}
}
-static int rebuild_select(int nlocs, const nn_locator_t *locs, const int *locs_nrds)
+static int rebuild_select(const struct q_globals *gv, int nlocs, const nn_locator_t *locs, const int *locs_nrds, bool prefer_multicast)
{
int i, j;
if (nlocs == 0)
return -1;
for (j = 0, i = 1; i < nlocs; i++) {
- if (locs_nrds[i] > locs_nrds[j])
+ if (prefer_multicast && locs_nrds[i] > 0 && ddsi_is_mcaddr(gv, &locs[i]) && !ddsi_is_mcaddr(gv, &locs[j]))
+ j = i; /* obviously first step must be to try and avoid unicast if configuration says so */
+ else if (locs_nrds[i] > locs_nrds[j])
j = i; /* better coverage */
else if (locs_nrds[i] == locs_nrds[j])
{
- if (locs_nrds[i] == 1 && !ddsi_is_mcaddr(&locs[i]))
+ if (locs_nrds[i] == 1 && !ddsi_is_mcaddr(gv, &locs[i]))
j = i; /* prefer unicast for single nodes */
#if DDSI_INCLUDE_SSM
- else if (ddsi_is_ssm_mcaddr(&locs[i]))
+ else if (ddsi_is_ssm_mcaddr(gv, &locs[i]))
j = i; /* "reader favours SSM": all else being equal, use SSM */
#endif
}
@@ -1138,14 +1199,14 @@ static int rebuild_select(int nlocs, const nn_locator_t *locs, const int *locs_n
return (locs_nrds[j] > 0) ? j : -1;
}
-static void rebuild_add(struct addrset *newas, int locidx, int nreaders, int nlocs, const nn_locator_t *locs, const int8_t *covered)
+static void rebuild_add(const struct q_globals *gv, struct addrset *newas, int locidx, int nreaders, int nlocs, const nn_locator_t *locs, const int8_t *covered)
{
char str[DDSI_LOCATORSTRLEN];
if (locs[locidx].kind != NN_LOCATOR_KIND_UDPv4MCGEN)
{
- ddsi_locator_to_string(str, sizeof(str), &locs[locidx]);
- DDS_LOG(DDS_LC_DISCOVERY, " simple %s\n", str);
- add_to_addrset(newas, &locs[locidx]);
+ ddsi_locator_to_string(gv, str, sizeof(str), &locs[locidx]);
+ GVLOGDISC (" simple %s\n", str);
+ add_to_addrset(gv, newas, &locs[locidx]);
}
else /* convert MC gen to the correct multicast address */
{
@@ -1162,9 +1223,9 @@ static void rebuild_add(struct addrset *newas, int locidx, int nreaders, int nlo
iph |= 1u << covered[i * nlocs + locidx];
ipn = htonl(iph);
memcpy(l.address + 12, &ipn, 4);
- ddsi_locator_to_string(str, sizeof(str), &l);
- DDS_LOG(DDS_LC_DISCOVERY, " mcgen %s\n", str);
- add_to_addrset(newas, &l);
+ ddsi_locator_to_string(gv, str, sizeof(str), &l);
+ GVLOGDISC (" mcgen %s\n", str);
+ add_to_addrset(gv, newas, &l);
}
}
@@ -1188,6 +1249,7 @@ static void rebuild_drop(int locidx, int nreaders, int nlocs, int *locs_nrds, in
static void rebuild_writer_addrset_setcover(struct addrset *newas, struct writer *wr)
{
+ bool prefer_multicast = wr->e.gv->config.prefer_multicast;
struct addrset *all_addrs;
int nreaders, nlocs;
nn_locator_t *locs;
@@ -1196,19 +1258,19 @@ static void rebuild_writer_addrset_setcover(struct addrset *newas, struct writer
int best;
if ((all_addrs = rebuild_make_all_addrs(&nreaders, wr)) == NULL)
return;
- nn_log_addrset(DDS_LC_DISCOVERY, "setcover: all_addrs", all_addrs);
- DDS_LOG(DDS_LC_DISCOVERY, "\n");
- rebuild_make_locs(&nlocs, &locs, all_addrs);
+ nn_log_addrset(wr->e.gv, DDS_LC_DISCOVERY, "setcover: all_addrs", all_addrs);
+ ELOGDISC (wr, "\n");
+ rebuild_make_locs(&wr->e.gv->logconfig, &nlocs, &locs, all_addrs);
unref_addrset(all_addrs);
rebuild_make_covered(&covered, wr, &nreaders, nlocs, locs);
if (nreaders == 0)
goto done;
rebuild_make_locs_nrds(&locs_nrds, nreaders, nlocs, covered);
- while ((best = rebuild_select(nlocs, locs, locs_nrds)) >= 0)
+ while ((best = rebuild_select(wr->e.gv, nlocs, locs, locs_nrds, prefer_multicast)) >= 0)
{
- rebuild_trace_covered(nreaders, nlocs, locs, locs_nrds, covered);
- DDS_LOG(DDS_LC_DISCOVERY, " best = %d\n", best);
- rebuild_add(newas, best, nreaders, nlocs, locs, covered);
+ rebuild_trace_covered(wr->e.gv, nreaders, nlocs, locs, locs_nrds, covered);
+ ELOGDISC (wr, " best = %d\n", best);
+ rebuild_add(wr->e.gv, newas, best, nreaders, nlocs, locs, covered);
rebuild_drop(best, nreaders, nlocs, locs_nrds, covered);
assert (locs_nrds[best] == 0);
}
@@ -1235,19 +1297,18 @@ static void rebuild_writer_addrset (struct writer *wr)
wr->as = newas;
unref_addrset (oldas);
- DDS_LOG(DDS_LC_DISCOVERY, "rebuild_writer_addrset("PGUIDFMT"):", PGUID (wr->e.guid));
- nn_log_addrset(DDS_LC_DISCOVERY, "", wr->as);
- DDS_LOG(DDS_LC_DISCOVERY, "\n");
+ ELOGDISC (wr, "rebuild_writer_addrset("PGUIDFMT"):", PGUID (wr->e.guid));
+ nn_log_addrset(wr->e.gv, DDS_LC_DISCOVERY, "", wr->as);
+ ELOGDISC (wr, "\n");
}
-void rebuild_or_clear_writer_addrsets(int rebuild)
+void rebuild_or_clear_writer_addrsets (struct q_globals *gv, int rebuild)
{
struct ephash_enum_writer est;
struct writer *wr;
struct addrset *empty = rebuild ? NULL : new_addrset();
- DDS_LOG(DDS_LC_DISCOVERY, "rebuild_or_delete_writer_addrsets(%d)\n", rebuild);
- ephash_enum_writer_init (&est);
- ddsrt_rwlock_read (&gv.qoslock);
+ GVLOGDISC ("rebuild_or_delete_writer_addrsets(%d)\n", rebuild);
+ ephash_enum_writer_init (&est, gv->guid_hash);
while ((wr = ephash_enum_writer_next (&est)) != NULL)
{
ddsrt_mutex_lock (&wr->e.lock);
@@ -1265,16 +1326,15 @@ void rebuild_or_clear_writer_addrsets(int rebuild)
empty one. */
unref_addrset(wr->as);
if (rebuild)
- wr->as = ref_addrset(gv.as_disc);
+ wr->as = ref_addrset(gv->as_disc);
else
wr->as = ref_addrset(empty);
}
ddsrt_mutex_unlock (&wr->e.lock);
}
- ddsrt_rwlock_unlock (&gv.qoslock);
ephash_enum_writer_fini (&est);
unref_addrset(empty);
- DDS_LOG(DDS_LC_DISCOVERY, "rebuild_or_delete_writer_addrsets(%d) done\n", rebuild);
+ GVLOGDISC ("rebuild_or_delete_writer_addrsets(%d) done\n", rebuild);
}
static void free_wr_prd_match (struct wr_prd_match *m)
@@ -1286,18 +1346,20 @@ static void free_wr_prd_match (struct wr_prd_match *m)
}
}
-static void free_rd_pwr_match (struct rd_pwr_match *m)
+static void free_rd_pwr_match (struct q_globals *gv, struct rd_pwr_match *m)
{
if (m)
{
#ifdef DDSI_INCLUDE_SSM
if (!is_unspec_locator (&m->ssm_mc_loc))
{
- assert (ddsi_is_mcaddr (&m->ssm_mc_loc));
+ assert (ddsi_is_mcaddr (gv, &m->ssm_mc_loc));
assert (!is_unspec_locator (&m->ssm_src_loc));
- if (ddsi_leave_mc (gv.data_conn_mc, &m->ssm_src_loc, &m->ssm_mc_loc) < 0)
- DDS_WARNING("failed to leave network partition ssm group\n");
+ if (ddsi_leave_mc (gv, gv->mship, gv->data_conn_mc, &m->ssm_src_loc, &m->ssm_mc_loc) < 0)
+ GVWARNING ("failed to leave network partition ssm group\n");
}
+#else
+ (void) gv;
#endif
ddsrt_free (m);
}
@@ -1329,10 +1391,10 @@ static void free_wr_rd_match (struct wr_rd_match *m)
if (m) ddsrt_free (m);
}
-static void writer_drop_connection (const struct nn_guid * wr_guid, const struct proxy_reader * prd)
+static void writer_drop_connection (const struct nn_guid *wr_guid, const struct proxy_reader *prd)
{
struct writer *wr;
- if ((wr = ephash_lookup_writer_guid (wr_guid)) != NULL)
+ if ((wr = ephash_lookup_writer_guid (prd->e.gv->guid_hash, wr_guid)) != NULL)
{
struct whc_node *deferred_free_list = NULL;
struct wr_prd_match *m;
@@ -1363,7 +1425,7 @@ static void writer_drop_local_connection (const struct nn_guid *wr_guid, struct
{
/* Only called by gc_delete_reader, so we actually have a reader pointer */
struct writer *wr;
- if ((wr = ephash_lookup_writer_guid (wr_guid)) != NULL)
+ if ((wr = ephash_lookup_writer_guid (rd->e.gv->guid_hash, wr_guid)) != NULL)
{
struct wr_rd_match *m;
@@ -1386,23 +1448,23 @@ static void writer_drop_local_connection (const struct nn_guid *wr_guid, struct
}
}
-static void reader_drop_connection (const struct nn_guid *rd_guid, const struct proxy_writer * pwr)
+static void reader_drop_connection (const struct nn_guid *rd_guid, const struct proxy_writer *pwr)
{
struct reader *rd;
- if ((rd = ephash_lookup_reader_guid (rd_guid)) != NULL)
+ if ((rd = ephash_lookup_reader_guid (pwr->e.gv->guid_hash, rd_guid)) != NULL)
{
struct rd_pwr_match *m;
ddsrt_mutex_lock (&rd->e.lock);
if ((m = ddsrt_avl_lookup (&rd_writers_treedef, &rd->writers, &pwr->e.guid)) != NULL)
ddsrt_avl_delete (&rd_writers_treedef, &rd->writers, m);
ddsrt_mutex_unlock (&rd->e.lock);
- free_rd_pwr_match (m);
+ free_rd_pwr_match (pwr->e.gv, m);
if (rd->rhc)
{
struct proxy_writer_info pwr_info;
make_proxy_writer_info(&pwr_info, &pwr->e, pwr->c.xqos);
- (ddsi_plugin.rhc_plugin.rhc_unregister_wr_fn) (rd->rhc, &pwr_info);
+ rhc_unregister_wr (rd->rhc, &pwr_info);
}
if (rd->status_cb)
{
@@ -1420,10 +1482,10 @@ static void reader_drop_connection (const struct nn_guid *rd_guid, const struct
}
}
-static void reader_drop_local_connection (const struct nn_guid *rd_guid, const struct writer * wr)
+static void reader_drop_local_connection (const struct nn_guid *rd_guid, const struct writer *wr)
{
struct reader *rd;
- if ((rd = ephash_lookup_reader_guid (rd_guid)) != NULL)
+ if ((rd = ephash_lookup_reader_guid (wr->e.gv->guid_hash, rd_guid)) != NULL)
{
struct rd_wr_match *m;
ddsrt_mutex_lock (&rd->e.lock);
@@ -1437,7 +1499,7 @@ static void reader_drop_local_connection (const struct nn_guid *rd_guid, const s
/* FIXME: */
struct proxy_writer_info pwr_info;
make_proxy_writer_info(&pwr_info, &wr->e, wr->xqos);
- (ddsi_plugin.rhc_plugin.rhc_unregister_wr_fn) (rd->rhc, &pwr_info);
+ rhc_unregister_wr (rd->rhc, &pwr_info);
}
if (rd->status_cb)
{
@@ -1455,25 +1517,25 @@ static void reader_drop_local_connection (const struct nn_guid *rd_guid, const s
}
}
-static void update_reader_init_acknack_count (const struct nn_guid *rd_guid, nn_count_t count)
+static void update_reader_init_acknack_count (const ddsrt_log_cfg_t *logcfg, const struct ephash *guid_hash, const struct nn_guid *rd_guid, nn_count_t count)
{
struct reader *rd;
/* Update the initial acknack sequence number for the reader. See
also reader_add_connection(). */
- DDS_LOG(DDS_LC_DISCOVERY, "update_reader_init_acknack_count ("PGUIDFMT", %"PRId32"): ", PGUID (*rd_guid), count);
- if ((rd = ephash_lookup_reader_guid (rd_guid)) != NULL)
+ DDS_CLOG (DDS_LC_DISCOVERY, logcfg, "update_reader_init_acknack_count ("PGUIDFMT", %"PRId32"): ", PGUID (*rd_guid), count);
+ if ((rd = ephash_lookup_reader_guid (guid_hash, rd_guid)) != NULL)
{
ddsrt_mutex_lock (&rd->e.lock);
- DDS_LOG(DDS_LC_DISCOVERY, "%"PRId32" -> ", rd->init_acknack_count);
+ DDS_CLOG (DDS_LC_DISCOVERY, logcfg, "%"PRId32" -> ", rd->init_acknack_count);
if (count > rd->init_acknack_count)
rd->init_acknack_count = count;
- DDS_LOG(DDS_LC_DISCOVERY, "%"PRId32"\n", count);
+ DDS_CLOG (DDS_LC_DISCOVERY, logcfg, "%"PRId32"\n", count);
ddsrt_mutex_unlock (&rd->e.lock);
}
else
{
- DDS_LOG(DDS_LC_DISCOVERY, "reader no longer exists\n");
+ DDS_CLOG (DDS_LC_DISCOVERY, logcfg, "reader no longer exists\n");
}
}
@@ -1481,7 +1543,7 @@ static void proxy_writer_drop_connection (const struct nn_guid *pwr_guid, struct
{
/* Only called by gc_delete_reader, so we actually have a reader pointer */
struct proxy_writer *pwr;
- if ((pwr = ephash_lookup_proxy_writer_guid (pwr_guid)) != NULL)
+ if ((pwr = ephash_lookup_proxy_writer_guid (rd->e.gv->guid_hash, pwr_guid)) != NULL)
{
struct pwr_rd_match *m;
@@ -1490,25 +1552,32 @@ static void proxy_writer_drop_connection (const struct nn_guid *pwr_guid, struct
{
ddsrt_avl_delete (&pwr_readers_treedef, &pwr->readers, m);
if (m->in_sync != PRMSS_SYNC)
- pwr->n_readers_out_of_sync--;
+ {
+ if (--pwr->n_readers_out_of_sync == 0)
+ local_reader_ary_setfastpath_ok (&pwr->rdary, true);
+ }
if (rd->reliable)
pwr->n_reliable_readers--;
+ /* If no reliable readers left, there is no reason to believe the heartbeats will keep
+ coming and therefore reset have_seen_heartbeat so the next reader to be created
+ doesn't get initialised based on stale data */
+ if (pwr->n_reliable_readers == 0)
+ pwr->have_seen_heartbeat = 0;
local_reader_ary_remove (&pwr->rdary, rd);
}
ddsrt_mutex_unlock (&pwr->e.lock);
if (m != NULL)
{
- update_reader_init_acknack_count (&rd->e.guid, m->count);
+ update_reader_init_acknack_count (&rd->e.gv->logconfig, rd->e.gv->guid_hash, &rd->e.guid, m->count);
}
free_pwr_rd_match (m);
}
}
-static void proxy_reader_drop_connection
- (const struct nn_guid *prd_guid, struct writer * wr)
+static void proxy_reader_drop_connection (const struct nn_guid *prd_guid, struct writer *wr)
{
struct proxy_reader *prd;
- if ((prd = ephash_lookup_proxy_reader_guid (prd_guid)) != NULL)
+ if ((prd = ephash_lookup_proxy_reader_guid (wr->e.gv->guid_hash, prd_guid)) != NULL)
{
struct prd_wr_match *m;
ddsrt_mutex_lock (&prd->e.lock);
@@ -1528,8 +1597,8 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd)
ddsrt_avl_ipath_t path;
int pretend_everything_acked;
m->prd_guid = prd->e.guid;
- m->is_reliable = (prd->c.xqos->reliability.kind > NN_BEST_EFFORT_RELIABILITY_QOS);
- m->assumed_in_sync = (config.retransmit_merging == REXMIT_MERGE_ALWAYS);
+ m->is_reliable = (prd->c.xqos->reliability.kind > DDS_RELIABILITY_BEST_EFFORT);
+ m->assumed_in_sync = (wr->e.gv->config.retransmit_merging == REXMIT_MERGE_ALWAYS);
m->has_replied_to_hb = !m->is_reliable;
m->all_have_replied_to_hb = 0;
m->non_responsive_count = 0;
@@ -1538,8 +1607,8 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd)
ddsrt_mutex_lock (&prd->e.lock);
if (prd->deleting)
{
- DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - prd is being deleted\n",
- PGUID (wr->e.guid), PGUID (prd->e.guid));
+ ELOGDISC (wr, " writer_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - prd is being deleted\n",
+ PGUID (wr->e.guid), PGUID (prd->e.guid));
pretend_everything_acked = 1;
}
else if (!m->is_reliable)
@@ -1566,14 +1635,16 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd)
m->seq = wr->seq;
if (ddsrt_avl_lookup_ipath (&wr_readers_treedef, &wr->readers, &prd->e.guid, &path))
{
- DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - already connected\n", PGUID (wr->e.guid), PGUID (prd->e.guid));
+ ELOGDISC (wr, " writer_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - already connected\n",
+ PGUID (wr->e.guid), PGUID (prd->e.guid));
ddsrt_mutex_unlock (&wr->e.lock);
nn_lat_estim_fini (&m->hb_to_ack_latency);
ddsrt_free (m);
}
else
{
- DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - ack seq %"PRId64"\n", PGUID (wr->e.guid), PGUID (prd->e.guid), m->seq);
+ ELOGDISC (wr, " writer_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - ack seq %"PRId64"\n",
+ PGUID (wr->e.guid), PGUID (prd->e.guid), m->seq);
ddsrt_avl_insert_ipath (&wr_readers_treedef, &wr->readers, m, &path);
rebuild_writer_addrset (wr);
wr->num_reliable_readers += m->is_reliable;
@@ -1623,13 +1694,15 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd)
ddsrt_mutex_lock (&wr->e.lock);
if (ddsrt_avl_lookup_ipath (&wr_local_readers_treedef, &wr->local_readers, &rd->e.guid, &path))
{
- DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT") - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid));
+ ELOGDISC (wr, " writer_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT") - already connected\n",
+ PGUID (wr->e.guid), PGUID (rd->e.guid));
ddsrt_mutex_unlock (&wr->e.lock);
ddsrt_free (m);
return;
}
- DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT")", PGUID (wr->e.guid), PGUID (rd->e.guid));
+ ELOGDISC (wr, " writer_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT")",
+ PGUID (wr->e.guid), PGUID (rd->e.guid));
m->rd_guid = rd->e.guid;
ddsrt_avl_insert_ipath (&wr_local_readers_treedef, &wr->local_readers, m, &path);
local_reader_ary_insert (&wr->rdary, rd);
@@ -1638,8 +1711,9 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd)
historical data for best-effort data over the wire, so also not locally).
FIXME: should limit ourselves to what it is available because of durability history,
not writer history */
- if (rd->xqos->reliability.kind > NN_BEST_EFFORT_RELIABILITY_QOS && rd->xqos->durability.kind > NN_VOLATILE_DURABILITY_QOS)
+ if (rd->xqos->reliability.kind > DDS_RELIABILITY_BEST_EFFORT && rd->xqos->durability.kind > DDS_DURABILITY_VOLATILE)
{
+ struct ddsi_tkmap *tkmap = rd->e.gv->m_tkmap;
struct whc_sample_iter it;
struct whc_borrowed_sample sample;
whc_sample_iter_init(wr->whc, &it);
@@ -1648,16 +1722,16 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd)
struct proxy_writer_info pwr_info;
struct ddsi_serdata *payload = sample.serdata;
/* FIXME: whc has tk reference in its index nodes, which is what we really should be iterating over anyway, and so we don't really have to look them up anymore */
- struct ddsi_tkmap_instance *tk = ddsi_tkmap_lookup_instance_ref(payload);
- make_proxy_writer_info(&pwr_info, &wr->e, wr->xqos);
- (void)(ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk);
- ddsi_tkmap_instance_unref(tk);
+ struct ddsi_tkmap_instance *tk = ddsi_tkmap_lookup_instance_ref (tkmap, payload);
+ make_proxy_writer_info (&pwr_info, &wr->e, wr->xqos);
+ (void) rhc_store (rd->rhc, &pwr_info, payload, tk);
+ ddsi_tkmap_instance_unref (tkmap, tk);
}
}
ddsrt_mutex_unlock (&wr->e.lock);
- DDS_LOG(DDS_LC_DISCOVERY, "\n");
+ ELOGDISC (wr, "\n");
if (wr->status_cb)
{
@@ -1684,20 +1758,21 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr,
writer will always see monotonically increasing sequence numbers
from one particular reader. This is then used for the
pwr_rd_match initialization */
- DDS_LOG(DDS_LC_DISCOVERY, " reader "PGUIDFMT" init_acknack_count = %"PRId32"\n", PGUID (rd->e.guid), rd->init_acknack_count);
+ ELOGDISC (rd, " reader "PGUIDFMT" init_acknack_count = %"PRId32"\n",
+ PGUID (rd->e.guid), rd->init_acknack_count);
*init_count = rd->init_acknack_count;
if (ddsrt_avl_lookup_ipath (&rd_writers_treedef, &rd->writers, &pwr->e.guid, &path))
{
- DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT") - already connected\n",
- PGUID (pwr->e.guid), PGUID (rd->e.guid));
+ ELOGDISC (rd, " reader_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT") - already connected\n",
+ PGUID (pwr->e.guid), PGUID (rd->e.guid));
ddsrt_mutex_unlock (&rd->e.lock);
ddsrt_free (m);
}
else
{
- DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT")\n",
- PGUID (pwr->e.guid), PGUID (rd->e.guid));
+ ELOGDISC (rd, " reader_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT")\n",
+ PGUID (pwr->e.guid), PGUID (rd->e.guid));
ddsrt_avl_insert_ipath (&rd_writers_treedef, &rd->writers, m, &path);
ddsrt_mutex_unlock (&rd->e.lock);
@@ -1708,12 +1783,12 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr,
any_ssm must succeed. */
if (!addrset_any_uc (pwr->c.as, &m->ssm_src_loc))
assert (0);
- if (!addrset_any_ssm (pwr->c.as, &m->ssm_mc_loc))
+ if (!addrset_any_ssm (rd->e.gv, pwr->c.as, &m->ssm_mc_loc))
assert (0);
/* FIXME: for now, assume that the ports match for datasock_mc --
't would be better to dynamically create and destroy sockets on
an as needed basis. */
- ddsi_join_mc (gv.data_conn_mc, &m->ssm_src_loc, &m->ssm_mc_loc);
+ ddsi_join_mc (rd->e.gv, rd->e.gv->mship, rd->e.gv->data_conn_mc, &m->ssm_src_loc, &m->ssm_mc_loc);
}
else
{
@@ -1744,13 +1819,15 @@ static void reader_add_local_connection (struct reader *rd, struct writer *wr)
if (ddsrt_avl_lookup_ipath (&rd_local_writers_treedef, &rd->local_writers, &wr->e.guid, &path))
{
- DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT") - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid));
+ ELOGDISC (rd, " reader_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT") - already connected\n",
+ PGUID (wr->e.guid), PGUID (rd->e.guid));
ddsrt_mutex_unlock (&rd->e.lock);
ddsrt_free (m);
}
else
{
- DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT")\n", PGUID (wr->e.guid), PGUID (rd->e.guid));
+ ELOGDISC (rd, " reader_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT")\n",
+ PGUID (wr->e.guid), PGUID (rd->e.guid));
ddsrt_avl_insert_ipath (&rd_local_writers_treedef, &rd->local_writers, m, &path);
ddsrt_mutex_unlock (&rd->e.lock);
@@ -1773,7 +1850,6 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader
{
struct pwr_rd_match *m = ddsrt_malloc (sizeof (*m));
ddsrt_avl_ipath_t path;
- seqno_t last_deliv_seq;
ddsrt_mutex_lock (&pwr->e.lock);
if (ddsrt_avl_lookup_ipath (&pwr_readers_treedef, &pwr->readers, &rd->e.guid, &path))
@@ -1787,12 +1863,11 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader
pwr->ddsi2direct_cbarg = rd->ddsi2direct_cbarg;
}
- DDS_LOG(DDS_LC_DISCOVERY, " proxy_writer_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT")",
- PGUID (pwr->e.guid), PGUID (rd->e.guid));
+ ELOGDISC (pwr, " proxy_writer_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT")",
+ PGUID (pwr->e.guid), PGUID (rd->e.guid));
m->rd_guid = rd->e.guid;
m->tcreate = now_mt ();
-
/* We track the last heartbeat count value per reader--proxy-writer
pair, so that we can correctly handle directed heartbeats. The
only reason to bother is to prevent a directed heartbeat (with
@@ -1811,34 +1886,61 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader
/* These can change as a consequence of handling data and/or
discovery activities. The safe way of dealing with them is to
lock the proxy writer */
- last_deliv_seq = nn_reorder_next_seq (pwr->reorder) - 1;
- if (!rd->handle_as_transient_local)
+ if (is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) && !ddsrt_avl_is_empty (&pwr->readers))
{
+ /* builtins really don't care about multiple copies or anything */
m->in_sync = PRMSS_SYNC;
}
- else if (!config.conservative_builtin_reader_startup && is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) && !ddsrt_avl_is_empty (&pwr->readers))
+ else if (!pwr->have_seen_heartbeat)
{
- /* builtins really don't care about multiple copies */
+ /* Proxy writer hasn't seen a heartbeat yet: means we have no
+ clue from what sequence number to start accepting data, nor
+ where historical data ends and live data begins.
+
+ A transient-local reader should always get all historical
+ data, and so can always start-out as "out-of-sync". Cyclone
+ refuses to retransmit already ACK'd samples to a Cyclone
+ reader, so if the other side is Cyclone, we can always start
+ from sequence number 1.
+
+ For non-Cyclone, if the reader is volatile, we have to just
+ start from the most recent sample, even though that means
+ the first samples written after matching the reader may be
+ lost. The alternative not only gets too much historical data
+ but may also result in "sample lost" notifications because the
+ writer is (may not be) retaining samples on behalf of this
+ reader for the oldest samples and so this reader may end up
+ with a partial set of old-ish samples. Even when both are
+ using KEEP_ALL and the connection doesn't fail ... */
+ if (rd->handle_as_transient_local)
+ m->in_sync = PRMSS_OUT_OF_SYNC;
+ else if (vendor_is_eclipse (pwr->c.vendor))
+ m->in_sync = PRMSS_OUT_OF_SYNC;
+ else
+ m->in_sync = PRMSS_SYNC;
+ m->u.not_in_sync.end_of_tl_seq = MAX_SEQ_NUMBER;
+ }
+ else if (!rd->handle_as_transient_local)
+ {
+ /* volatile reader, writer has seen a heartbeat: it's in sync
+ (there is a risk of it getting some historical data: that
+ happens to be cached in the writer's reorder admin at this
+ point) */
m->in_sync = PRMSS_SYNC;
}
else
{
- /* normal transient-local, reader is behind proxy writer */
+ /* transient-local reader; range of sequence numbers is already
+ known */
m->in_sync = PRMSS_OUT_OF_SYNC;
- if (last_deliv_seq == 0)
- {
- m->u.not_in_sync.end_of_out_of_sync_seq = MAX_SEQ_NUMBER;
- m->u.not_in_sync.end_of_tl_seq = MAX_SEQ_NUMBER;
- }
- else
- {
- m->u.not_in_sync.end_of_tl_seq = pwr->last_seq;
- m->u.not_in_sync.end_of_out_of_sync_seq = last_deliv_seq;
- }
- DDS_LOG(DDS_LC_DISCOVERY, " - out-of-sync %"PRId64, m->u.not_in_sync.end_of_out_of_sync_seq);
+ m->u.not_in_sync.end_of_tl_seq = pwr->last_seq;
}
if (m->in_sync != PRMSS_SYNC)
+ {
+ ELOGDISC (pwr, " - out-of-sync");
pwr->n_readers_out_of_sync++;
+ local_reader_ary_setfastpath_ok (&pwr->rdary, false);
+ }
m->count = init_count;
/* Spec says we may send a pre-emptive AckNack (8.4.2.3.4), hence we
schedule it for the configured delay * T_MILLISECOND. From then
@@ -1848,16 +1950,16 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader
difference in practice.) */
if (rd->reliable)
{
- m->acknack_xevent = qxev_acknack (pwr->evq, add_duration_to_mtime (tnow, config.preemptive_ack_delay), &pwr->e.guid, &rd->e.guid);
+ m->acknack_xevent = qxev_acknack (pwr->evq, add_duration_to_mtime (tnow, pwr->e.gv->config.preemptive_ack_delay), &pwr->e.guid, &rd->e.guid);
m->u.not_in_sync.reorder =
- nn_reorder_new (NN_REORDER_MODE_NORMAL, config.secondary_reorder_maxsamples);
+ nn_reorder_new (&pwr->e.gv->logconfig, NN_REORDER_MODE_NORMAL, pwr->e.gv->config.secondary_reorder_maxsamples, pwr->e.gv->config.late_ack_mode);
pwr->n_reliable_readers++;
}
else
{
m->acknack_xevent = NULL;
m->u.not_in_sync.reorder =
- nn_reorder_new (NN_REORDER_MODE_MONOTONICALLY_INCREASING, config.secondary_reorder_maxsamples);
+ nn_reorder_new (&pwr->e.gv->logconfig, NN_REORDER_MODE_MONOTONICALLY_INCREASING, pwr->e.gv->config.secondary_reorder_maxsamples, pwr->e.gv->config.late_ack_mode);
}
ddsrt_avl_insert_ipath (&pwr_readers_treedef, &pwr->readers, m, &path);
@@ -1865,7 +1967,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader
ddsrt_mutex_unlock (&pwr->e.lock);
qxev_pwr_entityid (pwr, &rd->e.guid.prefix);
- DDS_LOG(DDS_LC_DISCOVERY, "\n");
+ ELOGDISC (pwr, "\n");
if (rd->status_cb)
{
@@ -1880,8 +1982,8 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader
already_matched:
assert (is_builtin_entityid (pwr->e.guid.entityid, pwr->c.vendor) ? (pwr->c.topic == NULL) : (pwr->c.topic != NULL));
- DDS_LOG(DDS_LC_DISCOVERY, " proxy_writer_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT") - already connected\n",
- PGUID (pwr->e.guid), PGUID (rd->e.guid));
+ ELOGDISC (pwr, " proxy_writer_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT") - already connected\n",
+ PGUID (pwr->e.guid), PGUID (rd->e.guid));
ddsrt_mutex_unlock (&pwr->e.lock);
ddsrt_free (m);
return;
@@ -1898,15 +2000,15 @@ static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer
prd->c.topic = ddsi_sertopic_ref (wr->topic);
if (ddsrt_avl_lookup_ipath (&prd_writers_treedef, &prd->writers, &wr->e.guid, &path))
{
- DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - already connected\n",
- PGUID (wr->e.guid), PGUID (prd->e.guid));
+ ELOGDISC (prd, " proxy_reader_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - already connected\n",
+ PGUID (wr->e.guid), PGUID (prd->e.guid));
ddsrt_mutex_unlock (&prd->e.lock);
ddsrt_free (m);
}
else
{
- DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr "PGUIDFMT" prd "PGUIDFMT")\n",
- PGUID (wr->e.guid), PGUID (prd->e.guid));
+ ELOGDISC (prd, " proxy_reader_add_connection(wr "PGUIDFMT" prd "PGUIDFMT")\n",
+ PGUID (wr->e.guid), PGUID (prd->e.guid));
ddsrt_avl_insert_ipath (&prd_writers_treedef, &prd->writers, m, &path);
ddsrt_mutex_unlock (&prd->e.lock);
qxev_prd_entityid (prd, &wr->e.guid.prefix);
@@ -1979,60 +2081,64 @@ static nn_entityid_t builtin_entityid_match (nn_entityid_t x)
return res;
}
-static void writer_qos_mismatch (struct writer * wr, uint32_t reason)
+static void writer_qos_mismatch (struct writer * wr, dds_qos_policy_id_t reason)
{
/* When the reason is DDS_INVALID_QOS_POLICY_ID, it means that we compared
* readers/writers from different topics: ignore that. */
- if (reason != DDS_INVALID_QOS_POLICY_ID)
+ if (reason != DDS_INVALID_QOS_POLICY_ID && wr->status_cb)
{
- if (wr->topic->status_cb) {
- /* Handle INCONSISTENT_TOPIC on topic */
- (wr->topic->status_cb) (wr->topic->status_cb_entity);
- }
- if (wr->status_cb)
- {
- status_cb_data_t data;
- data.raw_status_id = (int) DDS_OFFERED_INCOMPATIBLE_QOS_STATUS_ID;
- data.extra = reason;
- (wr->status_cb) (wr->status_cb_entity, &data);
- }
+ status_cb_data_t data;
+ data.raw_status_id = (int) DDS_OFFERED_INCOMPATIBLE_QOS_STATUS_ID;
+ data.extra = reason;
+ (wr->status_cb) (wr->status_cb_entity, &data);
}
}
-static void reader_qos_mismatch (struct reader * rd, uint32_t reason)
+static void reader_qos_mismatch (struct reader * rd, dds_qos_policy_id_t reason)
{
/* When the reason is DDS_INVALID_QOS_POLICY_ID, it means that we compared
* readers/writers from different topics: ignore that. */
- if (reason != DDS_INVALID_QOS_POLICY_ID)
+ if (reason != DDS_INVALID_QOS_POLICY_ID && rd->status_cb)
{
- if (rd->topic->status_cb)
- {
- /* Handle INCONSISTENT_TOPIC on topic */
- (rd->topic->status_cb) (rd->topic->status_cb_entity);
- }
- if (rd->status_cb)
- {
- status_cb_data_t data;
- data.raw_status_id = (int) DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS_ID;
- data.extra = reason;
- (rd->status_cb) (rd->status_cb_entity, &data);
- }
+ status_cb_data_t data;
+ data.raw_status_id = (int) DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS_ID;
+ data.extra = reason;
+ (rd->status_cb) (rd->status_cb_entity, &data);
}
}
+static bool topickind_qos_match_p_lock (struct entity_common *rd, const dds_qos_t *rdqos, struct entity_common *wr, const dds_qos_t *wrqos, dds_qos_policy_id_t *reason)
+{
+ assert (is_reader_entityid (rd->guid.entityid));
+ assert (is_writer_entityid (wr->guid.entityid));
+ if (is_keyed_endpoint_entityid (rd->guid.entityid) != is_keyed_endpoint_entityid (wr->guid.entityid))
+ {
+ *reason = DDS_INVALID_QOS_POLICY_ID;
+ return false;
+ }
+ ddsrt_mutex_t * const locks[] = { &rd->qos_lock, &wr->qos_lock, &rd->qos_lock };
+ const int shift = (uintptr_t) rd > (uintptr_t) wr;
+ for (int i = 0; i < 2; i++)
+ ddsrt_mutex_lock (locks[i + shift]);
+ bool ret = qos_match_p (rdqos, wrqos, reason);
+ for (int i = 0; i < 2; i++)
+ ddsrt_mutex_unlock (locks[i + shift]);
+ return ret;
+}
+
static void connect_writer_with_proxy_reader (struct writer *wr, struct proxy_reader *prd, nn_mtime_t tnow)
{
const int isb0 = (is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE) != 0);
const int isb1 = (is_builtin_entityid (prd->e.guid.entityid, prd->c.vendor) != 0);
- int32_t reason;
+ dds_qos_policy_id_t reason;
DDSRT_UNUSED_ARG(tnow);
if (isb0 != isb1)
return;
if (wr->e.onlylocal)
return;
- if (!isb0 && (reason = qos_match_p (prd->c.xqos, wr->xqos)) >= 0)
+ if (!isb0 && !topickind_qos_match_p_lock (&prd->e, prd->c.xqos, &wr->e, wr->xqos, &reason))
{
- writer_qos_mismatch (wr, (uint32_t)reason);
+ writer_qos_mismatch (wr, reason);
return;
}
proxy_reader_add_connection (prd, wr);
@@ -2043,41 +2149,41 @@ static void connect_proxy_writer_with_reader (struct proxy_writer *pwr, struct r
{
const int isb0 = (is_builtin_entityid (pwr->e.guid.entityid, pwr->c.vendor) != 0);
const int isb1 = (is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) != 0);
- int32_t reason;
+ dds_qos_policy_id_t reason;
nn_count_t init_count;
if (isb0 != isb1)
return;
if (rd->e.onlylocal)
return;
- if (!isb0 && (reason = qos_match_p (rd->xqos, pwr->c.xqos)) >= 0)
+ if (!isb0 && !topickind_qos_match_p_lock (&rd->e, rd->xqos, &pwr->e, pwr->c.xqos, &reason))
{
- reader_qos_mismatch (rd, (uint32_t)reason);
+ reader_qos_mismatch (rd, reason);
return;
}
reader_add_connection (rd, pwr, &init_count);
proxy_writer_add_connection (pwr, rd, tnow, init_count);
}
-static bool ignore_local_p (const nn_guid_t *guid1, const nn_guid_t *guid2, const struct nn_xqos *xqos1, const struct nn_xqos *xqos2)
+static bool ignore_local_p (const nn_guid_t *guid1, const nn_guid_t *guid2, const struct dds_qos *xqos1, const struct dds_qos *xqos2)
{
assert (xqos1->present & QP_CYCLONE_IGNORELOCAL);
assert (xqos2->present & QP_CYCLONE_IGNORELOCAL);
switch (xqos1->ignorelocal.value)
{
- case NN_NONE_IGNORELOCAL_QOS:
+ case DDS_IGNORELOCAL_NONE:
break;
- case NN_PARTICIPANT_IGNORELOCAL_QOS:
+ case DDS_IGNORELOCAL_PARTICIPANT:
return memcmp (&guid1->prefix, &guid2->prefix, sizeof (guid1->prefix)) == 0;
- case NN_PROCESS_IGNORELOCAL_QOS:
+ case DDS_IGNORELOCAL_PROCESS:
return true;
}
switch (xqos2->ignorelocal.value)
{
- case NN_NONE_IGNORELOCAL_QOS:
+ case DDS_IGNORELOCAL_NONE:
break;
- case NN_PARTICIPANT_IGNORELOCAL_QOS:
+ case DDS_IGNORELOCAL_PARTICIPANT:
return memcmp (&guid1->prefix, &guid2->prefix, sizeof (guid1->prefix)) == 0;
- case NN_PROCESS_IGNORELOCAL_QOS:
+ case DDS_IGNORELOCAL_PROCESS:
return true;
}
return false;
@@ -2085,16 +2191,16 @@ static bool ignore_local_p (const nn_guid_t *guid1, const nn_guid_t *guid2, cons
static void connect_writer_with_reader (struct writer *wr, struct reader *rd, nn_mtime_t tnow)
{
- int32_t reason;
+ dds_qos_policy_id_t reason;
(void)tnow;
if (!is_local_orphan_endpoint (&wr->e) && (is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE) || is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE)))
return;
if (ignore_local_p (&wr->e.guid, &rd->e.guid, wr->xqos, rd->xqos))
return;
- if ((reason = qos_match_p (rd->xqos, wr->xqos)) >= 0)
+ if (!topickind_qos_match_p_lock (&rd->e, rd->xqos, &wr->e, wr->xqos, &reason))
{
- writer_qos_mismatch (wr, (uint32_t)reason);
- reader_qos_mismatch (rd, (uint32_t)reason);
+ writer_qos_mismatch (wr, reason);
+ reader_qos_mismatch (rd, reason);
return;
}
reader_add_local_connection (rd, wr);
@@ -2254,25 +2360,24 @@ static void generic_do_local_match_connect (struct entity_common *e, struct enti
static void generic_do_match (struct entity_common *e, nn_mtime_t tnow)
{
+ struct ephash * const guid_hash = e->gv->guid_hash;
struct ephash_enum est;
struct entity_common *em;
enum entity_kind mkind = generic_do_match_mkind(e->kind);
if (!is_builtin_entityid (e->guid.entityid, NN_VENDORID_ECLIPSE))
{
- DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s "PGUIDFMT") scanning all %ss\n",
- generic_do_match_kindstr_us (e->kind), generic_do_match_kindstr_us (mkind),
- generic_do_match_kindabbrev (e->kind), PGUID (e->guid),
- generic_do_match_kindstr(mkind));
+ EELOGDISC (e, "match_%s_with_%ss(%s "PGUIDFMT") scanning all %ss\n",
+ generic_do_match_kindstr_us (e->kind), generic_do_match_kindstr_us (mkind),
+ generic_do_match_kindabbrev (e->kind), PGUID (e->guid),
+ generic_do_match_kindstr(mkind));
/* Note: we visit at least all proxies that existed when we called
init (with the -- possible -- exception of ones that were
deleted between our calling init and our reaching it while
enumerating), but we may visit a single proxy reader multiple
times. */
- ephash_enum_init (&est, mkind);
- ddsrt_rwlock_read (&gv.qoslock);
+ ephash_enum_init (&est, guid_hash, mkind);
while ((em = ephash_enum_next (&est)) != NULL)
generic_do_match_connect(e, em, tnow);
- ddsrt_rwlock_unlock (&gv.qoslock);
ephash_enum_fini (&est);
}
else
@@ -2280,21 +2385,21 @@ static void generic_do_match (struct entity_common *e, nn_mtime_t tnow)
/* Built-ins have fixed QoS */
nn_entityid_t tgt_ent = builtin_entityid_match (e->guid.entityid);
enum entity_kind pkind = generic_do_match_isproxy (e) ? EK_PARTICIPANT : EK_PROXY_PARTICIPANT;
- DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s "PGUIDFMT") scanning %sparticipants tgt=%"PRIx32"\n",
- generic_do_match_kindstr_us (e->kind), generic_do_match_kindstr_us (mkind),
- generic_do_match_kindabbrev (e->kind), PGUID (e->guid),
- generic_do_match_isproxy (e) ? "" : "proxy ",
- tgt_ent.u);
+ EELOGDISC (e, "match_%s_with_%ss(%s "PGUIDFMT") scanning %sparticipants tgt=%"PRIx32"\n",
+ generic_do_match_kindstr_us (e->kind), generic_do_match_kindstr_us (mkind),
+ generic_do_match_kindabbrev (e->kind), PGUID (e->guid),
+ generic_do_match_isproxy (e) ? "" : "proxy ",
+ tgt_ent.u);
if (tgt_ent.u != NN_ENTITYID_UNKNOWN)
{
struct entity_common *ep;
- ephash_enum_init (&est, pkind);
+ ephash_enum_init (&est, guid_hash, pkind);
while ((ep = ephash_enum_next (&est)) != NULL)
{
nn_guid_t tgt_guid;
tgt_guid.prefix = ep->guid.prefix;
tgt_guid.entityid = tgt_ent;
- if ((em = ephash_lookup_guid (&tgt_guid, mkind)) != NULL)
+ if ((em = ephash_lookup_guid (guid_hash, &tgt_guid, mkind)) != NULL)
generic_do_match_connect(e, em, tnow);
}
ephash_enum_fini (&est);
@@ -2310,21 +2415,19 @@ static void generic_do_local_match (struct entity_common *e, nn_mtime_t tnow)
if (is_builtin_entityid (e->guid.entityid, NN_VENDORID_ECLIPSE) && !is_local_orphan_endpoint (e))
/* never a need for local matches on discovery endpoints */
return;
- mkind = generic_do_local_match_mkind(e->kind);
- DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s "PGUIDFMT") scanning all %ss\n",
- generic_do_match_kindstr_us (e->kind), generic_do_match_kindstr_us (mkind),
- generic_do_match_kindabbrev (e->kind), PGUID (e->guid),
- generic_do_match_kindstr(mkind));
+ mkind = generic_do_local_match_mkind (e->kind);
+ EELOGDISC (e, "match_%s_with_%ss(%s "PGUIDFMT") scanning all %ss\n",
+ generic_do_match_kindstr_us (e->kind), generic_do_match_kindstr_us (mkind),
+ generic_do_match_kindabbrev (e->kind), PGUID (e->guid),
+ generic_do_match_kindstr(mkind));
/* Note: we visit at least all proxies that existed when we called
init (with the -- possible -- exception of ones that were
deleted between our calling init and our reaching it while
enumerating), but we may visit a single proxy reader multiple
times. */
- ephash_enum_init (&est, mkind);
- ddsrt_rwlock_read (&gv.qoslock);
+ ephash_enum_init (&est, e->gv->guid_hash, mkind);
while ((em = ephash_enum_next (&est)) != NULL)
- generic_do_local_match_connect(e, em, tnow);
- ddsrt_rwlock_unlock (&gv.qoslock);
+ generic_do_local_match_connect (e, em, tnow);
ephash_enum_fini (&est);
}
@@ -2360,7 +2463,7 @@ static void match_proxy_reader_with_writers (struct proxy_reader *prd, nn_mtime_
/* ENDPOINT --------------------------------------------------------- */
-static void new_reader_writer_common (const struct nn_guid *guid, const struct ddsi_sertopic * topic, const struct nn_xqos *xqos)
+static void new_reader_writer_common (const struct ddsrt_log_cfg *logcfg, const struct nn_guid *guid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos)
{
const char *partition = "(default)";
const char *partition_suffix = "";
@@ -2378,17 +2481,17 @@ static void new_reader_writer_common (const struct nn_guid *guid, const struct d
if (xqos->partition.n > 1)
partition_suffix = "+";
}
- DDS_LOG(DDS_LC_DISCOVERY, "new_%s(guid "PGUIDFMT", %s%s.%s/%s)\n",
- is_writer_entityid (guid->entityid) ? "writer" : "reader",
- PGUID (*guid),
- partition, partition_suffix,
- topic ? topic->name : "(null)",
- topic ? topic->type_name : "(null)");
+ DDS_CLOG (DDS_LC_DISCOVERY, logcfg, "new_%s(guid "PGUIDFMT", %s%s.%s/%s)\n",
+ is_writer_entityid (guid->entityid) ? "writer" : "reader",
+ PGUID (*guid),
+ partition, partition_suffix,
+ topic ? topic->name : "(null)",
+ topic ? topic->type_name : "(null)");
}
-static void endpoint_common_init (struct entity_common *e, struct endpoint_common *c, enum entity_kind kind, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp)
+static void endpoint_common_init (struct entity_common *e, struct endpoint_common *c, struct q_globals *gv, enum entity_kind kind, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, bool onlylocal)
{
- entity_common_init (e, guid, NULL, kind, now (), NN_VENDORID_ECLIPSE, pp->e.onlylocal);
+ entity_common_init (e, gv, guid, NULL, kind, now (), NN_VENDORID_ECLIPSE, pp->e.onlylocal || onlylocal);
c->pp = ref_participant (pp, &e->guid);
if (group_guid)
c->group_guid = *group_guid;
@@ -2410,7 +2513,7 @@ static void endpoint_common_fini (struct entity_common *e, struct endpoint_commo
entity_common_fini (e);
}
-static int set_topic_type_name (nn_xqos_t *xqos, const struct ddsi_sertopic * topic)
+static int set_topic_type_name (dds_qos_t *xqos, const struct ddsi_sertopic * topic)
{
if (!(xqos->present & QP_TYPE_NAME) && topic)
{
@@ -2428,14 +2531,14 @@ static int set_topic_type_name (nn_xqos_t *xqos, const struct ddsi_sertopic * to
/* WRITER ----------------------------------------------------------- */
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
-static uint32_t get_partitionid_from_mapping (const char *partition, const char *topic)
+static uint32_t get_partitionid_from_mapping (const struct ddsrt_log_cfg *logcfg, const struct config *config, const char *partition, const char *topic)
{
struct config_partitionmapping_listelem *pm;
- if ((pm = find_partitionmapping (partition, topic)) == NULL)
+ if ((pm = find_partitionmapping (config, partition, topic)) == NULL)
return 0;
else
{
- DDS_LOG(DDS_LC_DISCOVERY, "matched writer for topic \"%s\" in partition \"%s\" to networkPartition \"%s\"\n", topic, partition, pm->networkPartition);
+ DDS_CLOG (DDS_LC_DISCOVERY, logcfg, "matched writer for topic \"%s\" in partition \"%s\" to networkPartition \"%s\"\n", topic, partition, pm->networkPartition);
return pm->partition->partitionId;
}
}
@@ -2579,7 +2682,7 @@ void writer_set_retransmitting (struct writer *wr)
{
assert (!wr->retransmitting);
wr->retransmitting = 1;
- if (config.whc_adaptive && wr->whc_high > wr->whc_low)
+ if (wr->e.gv->config.whc_adaptive && wr->whc_high > wr->whc_low)
{
uint32_t m = 8 * wr->whc_high / 10;
wr->whc_high = (m > wr->whc_low) ? m : wr->whc_low;
@@ -2607,13 +2710,13 @@ unsigned remove_acked_messages (struct writer *wr, struct whc_state *whcst, stru
writer_clear_retransmitting (wr);
if (wr->state == WRST_LINGERING && whcst->unacked_bytes == 0)
{
- DDS_LOG(DDS_LC_DISCOVERY, "remove_acked_messages: deleting lingering writer "PGUIDFMT"\n", PGUID (wr->e.guid));
+ ELOGDISC (wr, "remove_acked_messages: deleting lingering writer "PGUIDFMT"\n", PGUID (wr->e.guid));
delete_writer_nolinger_locked (wr);
}
return n;
}
-static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void * status_entity)
+static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc, status_cb_t status_cb, void * status_entity)
{
ddsrt_cond_init (&wr->throttle_cond);
wr->seq = 0;
@@ -2642,41 +2745,38 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se
wr->xqos = ddsrt_malloc (sizeof (*wr->xqos));
nn_xqos_copy (wr->xqos, xqos);
- nn_xqos_mergein_missing (wr->xqos, &gv.default_xqos_wr);
+ nn_xqos_mergein_missing (wr->xqos, &wr->e.gv->default_xqos_wr, ~(uint64_t)0);
assert (wr->xqos->aliased == 0);
set_topic_type_name (wr->xqos, topic);
- DDS_LOG(DDS_LC_DISCOVERY, "WRITER "PGUIDFMT" QOS={", PGUID (wr->e.guid));
- nn_log_xqos (DDS_LC_DISCOVERY, wr->xqos);
- DDS_LOG(DDS_LC_DISCOVERY, "}\n");
+ ELOGDISC (wr, "WRITER "PGUIDFMT" QOS={", PGUID (wr->e.guid));
+ nn_log_xqos (DDS_LC_DISCOVERY, &wr->e.gv->logconfig, wr->xqos);
+ ELOGDISC (wr, "}\n");
assert (wr->xqos->present & QP_RELIABILITY);
- wr->reliable = (wr->xqos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS);
+ wr->reliable = (wr->xqos->reliability.kind != DDS_RELIABILITY_BEST_EFFORT);
assert (wr->xqos->present & QP_DURABILITY);
if (is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE))
{
- assert (wr->xqos->history.kind == NN_KEEP_LAST_HISTORY_QOS);
- assert (wr->xqos->durability.kind == NN_TRANSIENT_LOCAL_DURABILITY_QOS);
+ assert (wr->xqos->history.kind == DDS_HISTORY_KEEP_LAST);
+ assert (wr->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL);
}
- wr->handle_as_transient_local = (wr->xqos->durability.kind == NN_TRANSIENT_LOCAL_DURABILITY_QOS);
+ wr->handle_as_transient_local = (wr->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL);
wr->include_keyhash =
- config.generate_keyhash &&
+ wr->e.gv->config.generate_keyhash &&
((wr->e.guid.entityid.u & NN_ENTITYID_KIND_MASK) == NN_ENTITYID_KIND_WRITER_WITH_KEY);
wr->topic = ddsi_sertopic_ref (topic);
wr->as = new_addrset ();
wr->as_group = NULL;
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
- {
- unsigned i;
- /* This is an open issue how to encrypt mesages send for various
- partitions that match multiple network partitions. From a safety
- point of view a wierd configuration. Here we chose the first one
- that we find */
- wr->partition_id = 0;
- for (i = 0; i < wr->xqos->partition.n && wr->partition_id == 0; i++)
- wr->partition_id = get_partitionid_from_mapping (wr->xqos->partition.strs[i], wr->xqos->topic_name);
- }
+ /* This is an open issue how to encrypt mesages send for various
+ partitions that match multiple network partitions. From a safety
+ point of view a wierd configuration. Here we chose the first one
+ that we find */
+ wr->partition_id = 0;
+ for (uint32_t i = 0; i < wr->xqos->partition.n && wr->partition_id == 0; i++)
+ wr->partition_id = get_partitionid_from_mapping (&wr->e.gv->logconfig, &wr->e.gv->config, wr->xqos->partition.strs[i], wr->xqos->topic_name);
#endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */
#ifdef DDSI_INCLUDE_SSM
@@ -2686,33 +2786,33 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se
to advertise. */
wr->supports_ssm = 0;
wr->ssm_as = NULL;
- if (config.allowMulticast & AMC_SSM)
+ if (wr->e.gv->config.allowMulticast & AMC_SSM)
{
nn_locator_t loc;
int have_loc = 0;
if (wr->partition_id == 0)
{
- if (ddsi_is_ssm_mcaddr (&gv.loc_default_mc))
+ if (ddsi_is_ssm_mcaddr (wr->e.gv, &wr->e.gv->loc_default_mc))
{
- loc = gv.loc_default_mc;
+ loc = wr->e.gv->loc_default_mc;
have_loc = 1;
}
}
else
{
- const struct config_networkpartition_listelem *np = find_networkpartition_by_id (wr->partition_id);
+ const struct config_networkpartition_listelem *np = find_networkpartition_by_id (&wr->e.gv->config, wr->partition_id);
assert (np);
- if (addrset_any_ssm (np->as, &loc))
+ if (addrset_any_ssm (wr->e.gv, np->as, &loc))
have_loc = 1;
}
if (have_loc)
{
wr->supports_ssm = 1;
wr->ssm_as = new_addrset ();
- add_to_addrset (wr->ssm_as, &loc);
- DDS_LOG(DDS_LC_DISCOVERY, "writer "PGUIDFMT": ssm=%d", PGUID (wr->e.guid), wr->supports_ssm);
- nn_log_addrset (DDS_LC_DISCOVERY, "", wr->ssm_as);
- DDS_LOG(DDS_LC_DISCOVERY, "\n");
+ add_to_addrset (wr->e.gv, wr->ssm_as, &loc);
+ ELOGDISC (wr, "writer "PGUIDFMT": ssm=%d", PGUID (wr->e.guid), wr->supports_ssm);
+ nn_log_addrset (wr->e.gv, DDS_LC_DISCOVERY, "", wr->ssm_as);
+ ELOGDISC (wr, "\n");
}
}
#endif
@@ -2722,15 +2822,15 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
if (!is_builtin_entityid (wr->e.guid.entityid, ownvendorid))
{
- struct config_channel_listelem *channel = find_channel (wr->xqos->transport_priority);
- DDS_LOG(DDS_LC_DISCOVERY, "writer "PGUIDFMT": transport priority %d => channel '%s' priority %d\n",
- PGUID (wr->e.guid), wr->xqos->transport_priority.value, channel->name, channel->priority);
- wr->evq = channel->evq ? channel->evq : gv.xevents;
+ struct config_channel_listelem *channel = find_channel (&wr->e.gv->config, wr->xqos->transport_priority);
+ ELOGDISC (wr, "writer "PGUIDFMT": transport priority %d => channel '%s' priority %d\n",
+ PGUID (wr->e.guid), wr->xqos->transport_priority.value, channel->name, channel->priority);
+ wr->evq = channel->evq ? channel->evq : wr->e.gv->xevents;
}
else
#endif
{
- wr->evq = gv.xevents;
+ wr->evq = wr->e.gv->xevents;
}
/* heartbeat event will be deleted when the handler can't find a
@@ -2748,15 +2848,15 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se
wr->heartbeat_xevent = NULL;
}
assert (wr->xqos->present & QP_LIVELINESS);
- if (wr->xqos->liveliness.kind != NN_AUTOMATIC_LIVELINESS_QOS ||
- nn_from_ddsi_duration (wr->xqos->liveliness.lease_duration) != T_NEVER)
+ if (wr->xqos->liveliness.kind != DDS_LIVELINESS_AUTOMATIC || wr->xqos->liveliness.lease_duration != T_NEVER)
{
- DDS_LOG(DDS_LC_DISCOVERY, "writer "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (wr->e.guid), (int) wr->xqos->liveliness.kind, nn_from_ddsi_duration (wr->xqos->liveliness.lease_duration));
+ ELOGDISC (wr, "writer "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n",
+ PGUID (wr->e.guid), (int) wr->xqos->liveliness.kind, wr->xqos->liveliness.lease_duration);
}
wr->lease_duration = T_NEVER; /* FIXME */
wr->whc = whc;
- if (wr->xqos->history.kind == NN_KEEP_LAST_HISTORY_QOS)
+ if (wr->xqos->history.kind == DDS_HISTORY_KEEP_LAST)
{
/* hdepth > 0 => "aggressive keep last", and in that case: why
bother blocking for a slow receiver when the entire point of
@@ -2766,8 +2866,8 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se
}
else
{
- wr->whc_low = config.whc_lowwater_mark;
- wr->whc_high = config.whc_init_highwater_mark.value;
+ wr->whc_low = wr->e.gv->config.whc_lowwater_mark;
+ wr->whc_high = wr->e.gv->config.whc_init_highwater_mark.value;
}
assert (!is_builtin_entityid(wr->e.guid.entityid, NN_VENDORID_ECLIPSE) || (wr->whc_low == wr->whc_high && wr->whc_low == INT32_MAX));
@@ -2778,16 +2878,16 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se
local_reader_ary_init (&wr->rdary);
}
-static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_entity)
+static dds_return_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc, status_cb_t status_cb, void *status_entity)
{
struct writer *wr;
nn_mtime_t tnow = now_mt ();
assert (is_writer_entityid (guid->entityid));
- assert (ephash_lookup_writer_guid (guid) == NULL);
+ assert (ephash_lookup_writer_guid (pp->e.gv->guid_hash, guid) == NULL);
assert (memcmp (&guid->prefix, &pp->e.guid.prefix, sizeof (guid->prefix)) == 0);
- new_reader_writer_common (guid, topic, xqos);
+ new_reader_writer_common (&pp->e.gv->logconfig, guid, topic, xqos);
wr = ddsrt_malloc (sizeof (*wr));
if (wr_out)
*wr_out = wr;
@@ -2796,7 +2896,8 @@ static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_gu
delete_participant won't interfere with our ability to address
the participant */
- endpoint_common_init (&wr->e, &wr->c, EK_WRITER, guid, group_guid, pp);
+ const bool onlylocal = topic && builtintopic_is_builtintopic (pp->e.gv->builtin_topic_interface, topic);
+ endpoint_common_init (&wr->e, &wr->c, pp->e.gv, EK_WRITER, guid, group_guid, pp, onlylocal);
new_writer_guid_common_init(wr, topic, xqos, whc, status_cb, status_entity);
/* guid_hash needed for protocol handling, so add it before we send
@@ -2805,8 +2906,8 @@ static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_gu
neither of two endpoints being created in parallel can discover
the other. */
ddsrt_mutex_lock (&wr->e.lock);
- ephash_insert_writer_guid (wr);
- ddsi_plugin.builtintopic_write (&wr->e, now(), true);
+ ephash_insert_writer_guid (pp->e.gv->guid_hash, wr);
+ builtintopic_write (wr->e.gv->builtin_topic_interface, &wr->e, now(), true);
ddsrt_mutex_unlock (&wr->e.lock);
/* once it exists, match it with proxy writers and broadcast
@@ -2825,54 +2926,66 @@ static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_gu
resched_xevent_if_earlier (pp->pmd_update_xevent, tsched);
}
- return DDS_RETCODE_OK;
+ return 0;
}
-dds_retcode_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg)
+dds_return_t new_writer (struct writer **wr_out, struct q_globals *gv, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg)
{
struct participant *pp;
+ dds_return_t rc;
+ uint32_t kind;
- if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL)
+ if ((pp = ephash_lookup_participant_guid (gv->guid_hash, ppguid)) == NULL)
{
- DDS_LOG(DDS_LC_DISCOVERY, "new_writer - participant "PGUIDFMT" not found\n", PGUID (*ppguid));
- return DDS_RETCODE_NOT_FOUND;
+ GVLOGDISC ("new_writer - participant "PGUIDFMT" not found\n", PGUID (*ppguid));
+ return DDS_RETCODE_BAD_PARAMETER;
}
+
/* participant can't be freed while we're mucking around cos we are
awake and do not touch the thread's vtime (ephash_lookup already
verifies we're awake) */
wrguid->prefix = pp->e.guid.prefix;
- if (pp_allocate_entityid (&wrguid->entityid, NN_ENTITYID_KIND_WRITER_WITH_KEY, pp) < 0)
- return DDS_RETCODE_OUT_OF_RESOURCES;
+ kind = topic->topickind_no_key ? NN_ENTITYID_KIND_WRITER_NO_KEY : NN_ENTITYID_KIND_WRITER_WITH_KEY;
+ if ((rc = pp_allocate_entityid (&wrguid->entityid, kind, pp)) < 0)
+ return rc;
return new_writer_guid (wr_out, wrguid, group_guid, pp, topic, xqos, whc, status_cb, status_cb_arg);
}
-struct local_orphan_writer *new_local_orphan_writer (nn_entityid_t entityid, struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc)
+struct local_orphan_writer *new_local_orphan_writer (struct q_globals *gv, nn_entityid_t entityid, struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc *whc)
{
nn_guid_t guid;
struct local_orphan_writer *lowr;
struct writer *wr;
nn_mtime_t tnow = now_mt ();
- DDS_LOG(DDS_LC_DISCOVERY, "new_local_orphan_writer(%s/%s)\n", topic->name, topic->type_name);
+ GVLOGDISC ("new_local_orphan_writer(%s/%s)\n", topic->name, topic->type_name);
lowr = ddsrt_malloc (sizeof (*lowr));
wr = &lowr->wr;
memset (&guid.prefix, 0, sizeof (guid.prefix));
guid.entityid = entityid;
- entity_common_init (&wr->e, &guid, NULL, EK_WRITER, now (), NN_VENDORID_ECLIPSE, true);
+ entity_common_init (&wr->e, gv, &guid, NULL, EK_WRITER, now (), NN_VENDORID_ECLIPSE, true);
wr->c.pp = NULL;
memset (&wr->c.group_guid, 0, sizeof (wr->c.group_guid));
new_writer_guid_common_init (wr, topic, xqos, whc, 0, NULL);
- ephash_insert_writer_guid (wr);
- ddsi_plugin.builtintopic_write (&wr->e, now(), true);
+ ephash_insert_writer_guid (gv->guid_hash, wr);
+ builtintopic_write (gv->builtin_topic_interface, &wr->e, now(), true);
match_writer_with_local_readers (wr, tnow);
return lowr;
}
+void update_writer_qos (struct writer *wr, const dds_qos_t *xqos)
+{
+ ddsrt_mutex_lock (&wr->e.lock);
+ if (update_qos_locked (&wr->e, wr->xqos, xqos, now ()))
+ sedp_write_writer (wr);
+ ddsrt_mutex_unlock (&wr->e.lock);
+}
+
static void gc_delete_writer (struct gcreq *gcreq)
{
struct writer *wr = gcreq->arg;
- DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_writer(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (wr->e.guid));
+ ELOGDISC (wr, "gc_delete_writer(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (wr->e.guid));
gcreq_free (gcreq);
/* We now allow GC while blocked on a full WHC, but we still don't allow deleting a writer while blocked on it. The writer's state must be DELETING by the time we get here, and that means the transmit path is no longer blocked. It doesn't imply that the write thread is no longer in throttle_writer(), just that if it is, it will soon return from there. Therefore, block until it isn't throttling anymore. We can safely lock the writer, as we're on the separate GC thread. */
@@ -2931,7 +3044,7 @@ static void gc_delete_writer (struct gcreq *gcreq)
static void gc_delete_writer_throttlewait (struct gcreq *gcreq)
{
struct writer *wr = gcreq->arg;
- DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_writer_throttlewait(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (wr->e.guid));
+ ELOGDISC (wr, "gc_delete_writer_throttlewait(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (wr->e.guid));
/* We now allow GC while blocked on a full WHC, but we still don't allow deleting a writer while blocked on it. The writer's state must be DELETING by the time we get here, and that means the transmit path is no longer blocked. It doesn't imply that the write thread is no longer in throttle_writer(), just that if it is, it will soon return from there. Therefore, block until it isn't throttling anymore. We can safely lock the writer, as we're on the separate GC thread. */
assert (wr->state == WRST_DELETING);
ddsrt_mutex_lock (&wr->e.lock);
@@ -2944,7 +3057,7 @@ static void gc_delete_writer_throttlewait (struct gcreq *gcreq)
static void writer_set_state (struct writer *wr, enum writer_state newstate)
{
ASSERT_MUTEX_HELD (&wr->e.lock);
- DDS_LOG(DDS_LC_DISCOVERY, "writer_set_state("PGUIDFMT") state transition %d -> %d\n", PGUID (wr->e.guid), wr->state, newstate);
+ ELOGDISC (wr, "writer_set_state("PGUIDFMT") state transition %d -> %d\n", PGUID (wr->e.guid), wr->state, newstate);
assert (newstate > wr->state);
if (wr->state == WRST_OPERATIONAL)
{
@@ -2959,19 +3072,19 @@ static void writer_set_state (struct writer *wr, enum writer_state newstate)
wr->state = newstate;
}
-int delete_writer_nolinger_locked (struct writer *wr)
+dds_return_t delete_writer_nolinger_locked (struct writer *wr)
{
- DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (wr->e.guid));
+ ELOGDISC (wr, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (wr->e.guid));
ASSERT_MUTEX_HELD (&wr->e.lock);
- ddsi_plugin.builtintopic_write (&wr->e, now(), false);
+ builtintopic_write (wr->e.gv->builtin_topic_interface, &wr->e, now(), false);
local_reader_ary_setinvalid (&wr->rdary);
- ephash_remove_writer_guid (wr);
+ ephash_remove_writer_guid (wr->e.gv->guid_hash, wr);
writer_set_state (wr, WRST_DELETING);
gcreq_writer (wr);
return 0;
}
-int delete_writer_nolinger (const struct nn_guid *guid)
+dds_return_t delete_writer_nolinger (struct q_globals *gv, const struct nn_guid *guid)
{
struct writer *wr;
/* We take no care to ensure application writers are not deleted
@@ -2981,12 +3094,12 @@ int delete_writer_nolinger (const struct nn_guid *guid)
DDSI participants. But it would be somewhat more elegant to do it
differently. */
assert (is_writer_entityid (guid->entityid));
- if ((wr = ephash_lookup_writer_guid (guid)) == NULL)
+ if ((wr = ephash_lookup_writer_guid (gv->guid_hash, guid)) == NULL)
{
- DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid));
- return Q_ERR_UNKNOWN_ENTITY;
+ GVLOGDISC ("delete_writer_nolinger(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid));
+ return DDS_RETCODE_BAD_PARAMETER;
}
- DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (*guid));
+ GVLOGDISC ("delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (*guid));
ddsrt_mutex_lock (&wr->e.lock);
delete_writer_nolinger_locked (wr);
ddsrt_mutex_unlock (&wr->e.lock);
@@ -3000,16 +3113,16 @@ void delete_local_orphan_writer (struct local_orphan_writer *lowr)
ddsrt_mutex_unlock (&lowr->wr.e.lock);
}
-int delete_writer (const struct nn_guid *guid)
+dds_return_t delete_writer (struct q_globals *gv, const struct nn_guid *guid)
{
struct writer *wr;
struct whc_state whcst;
- if ((wr = ephash_lookup_writer_guid (guid)) == NULL)
+ if ((wr = ephash_lookup_writer_guid (gv->guid_hash, guid)) == NULL)
{
- DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid));
- return Q_ERR_UNKNOWN_ENTITY;
+ GVLOGDISC ("delete_writer(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid));
+ return DDS_RETCODE_BAD_PARAMETER;
}
- DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") ...\n", PGUID (*guid));
+ GVLOGDISC ("delete_writer(guid "PGUIDFMT") ...\n", PGUID (*guid));
ddsrt_mutex_lock (&wr->e.lock);
/* If no unack'ed data, don't waste time or resources (expected to
@@ -3019,7 +3132,7 @@ int delete_writer (const struct nn_guid *guid)
whc_get_state(wr->whc, &whcst);
if (whcst.unacked_bytes == 0)
{
- DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") - no unack'ed samples\n", PGUID (*guid));
+ GVLOGDISC ("delete_writer(guid "PGUIDFMT") - no unack'ed samples\n", PGUID (*guid));
delete_writer_nolinger_locked (wr);
ddsrt_mutex_unlock (&wr->e.lock);
}
@@ -3029,55 +3142,48 @@ int delete_writer (const struct nn_guid *guid)
int32_t tsec, tusec;
writer_set_state (wr, WRST_LINGERING);
ddsrt_mutex_unlock (&wr->e.lock);
- tsched = add_duration_to_mtime (now_mt (), config.writer_linger_duration);
+ tsched = add_duration_to_mtime (now_mt (), wr->e.gv->config.writer_linger_duration);
mtime_to_sec_usec (&tsec, &tusec, tsched);
- DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") - unack'ed samples, will delete when ack'd or at t = %"PRId32".%06"PRId32"\n",
- PGUID (*guid), tsec, tusec);
- qxev_delete_writer (tsched, &wr->e.guid);
+ GVLOGDISC ("delete_writer(guid "PGUIDFMT") - unack'ed samples, will delete when ack'd or at t = %"PRId32".%06"PRId32"\n",
+ PGUID (*guid), tsec, tusec);
+ qxev_delete_writer (gv->xevents, tsched, &wr->e.guid);
}
return 0;
}
-uint64_t writer_instance_id (const struct nn_guid *guid)
-{
- struct entity_common *e;
- e = (struct entity_common*)ephash_lookup_writer_guid(guid);
- if (e) {
- return e->iid;
- }
- e = (struct entity_common*)ephash_lookup_proxy_writer_guid(guid);
- if (e) {
- return e->iid;
- }
- return 0;
-}
-
/* READER ----------------------------------------------------------- */
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
-static struct addrset * get_as_from_mapping (const char *partition, const char *topic)
+static struct addrset *get_as_from_mapping (const struct q_globals *gv, const char *partition, const char *topic)
{
struct config_partitionmapping_listelem *pm;
struct addrset *as = new_addrset ();
- if ((pm = find_partitionmapping (partition, topic)) != NULL)
+ if ((pm = find_partitionmapping (&gv->config, partition, topic)) != NULL)
{
- DDS_LOG(DDS_LC_DISCOVERY, "matched reader for topic \"%s\" in partition \"%s\" to networkPartition \"%s\"\n", topic, partition, pm->networkPartition);
+ GVLOGDISC ("matched reader for topic \"%s\" in partition \"%s\" to networkPartition \"%s\"\n",
+ topic, partition, pm->networkPartition);
assert (pm->partition->as);
- copy_addrset_into_addrset (as, pm->partition->as);
+ copy_addrset_into_addrset (gv, as, pm->partition->as);
}
return as;
}
-static void join_mcast_helper (const nn_locator_t *n, void * varg)
+struct join_leave_mcast_helper_arg {
+ ddsi_tran_conn_t conn;
+ struct q_globals *gv;
+};
+
+static void join_mcast_helper (const nn_locator_t *n, void *varg)
{
- ddsi_tran_conn_t conn = (ddsi_tran_conn_t) varg;
- if (ddsi_is_mcaddr (n))
+ struct join_leave_mcast_helper_arg *arg = varg;
+ struct q_globals *gv = arg->gv;
+ if (ddsi_is_mcaddr (gv, n))
{
if (n->kind != NN_LOCATOR_KIND_UDPv4MCGEN)
{
- if (ddsi_join_mc (conn, NULL, n) < 0)
+ if (ddsi_join_mc (gv, arg->gv->mship, arg->conn, NULL, n) < 0)
{
- DDS_LOG(DDS_LC_WARNING, "failed to join network partition multicast group\n");
+ GVWARNING ("failed to join network partition multicast group\n");
}
}
else /* join all addresses that include this node */
@@ -3086,12 +3192,11 @@ static void join_mcast_helper (const nn_locator_t *n, void * varg)
nn_locator_t l = *n;
nn_udpv4mcgen_address_t l1;
uint32_t iph;
- unsigned i;
memcpy(&l1, l.address, sizeof(l1));
l.kind = NN_LOCATOR_KIND_UDPv4;
memset(l.address, 0, 12);
iph = ntohl(l1.ipv4.s_addr);
- for (i = 1; i < (1u << l1.count); i++)
+ for (uint32_t i = 1; i < ((uint32_t)1 << l1.count); i++)
{
uint32_t ipn, iph1 = iph;
if (i & (1u << l1.idx))
@@ -3099,9 +3204,9 @@ static void join_mcast_helper (const nn_locator_t *n, void * varg)
iph1 |= (i << l1.base);
ipn = htonl(iph1);
memcpy(l.address + 12, &ipn, 4);
- if (ddsi_join_mc (conn, NULL, &l) < 0)
+ if (ddsi_join_mc (gv, gv->mship, arg->conn, NULL, &l) < 0)
{
- DDS_LOG(DDS_LC_WARNING, "failed to join network partition multicast group\n");
+ GVWARNING ("failed to join network partition multicast group\n");
}
}
}
@@ -3110,16 +3215,17 @@ static void join_mcast_helper (const nn_locator_t *n, void * varg)
}
}
-static void leave_mcast_helper (const nn_locator_t *n, void * varg)
+static void leave_mcast_helper (const nn_locator_t *n, void *varg)
{
- ddsi_tran_conn_t conn = (ddsi_tran_conn_t) varg;
- if (ddsi_is_mcaddr (n))
+ struct join_leave_mcast_helper_arg *arg = varg;
+ struct q_globals *gv = arg->gv;
+ if (ddsi_is_mcaddr (gv, n))
{
if (n->kind != NN_LOCATOR_KIND_UDPv4MCGEN)
{
- if (ddsi_leave_mc (conn, NULL, n) < 0)
+ if (ddsi_leave_mc (gv, gv->mship, arg->conn, NULL, n) < 0)
{
- DDS_LOG(DDS_LC_WARNING, "failed to leave network partition multicast group\n");
+ GVWARNING ("failed to leave network partition multicast group\n");
}
}
else /* join all addresses that include this node */
@@ -3128,12 +3234,11 @@ static void leave_mcast_helper (const nn_locator_t *n, void * varg)
nn_locator_t l = *n;
nn_udpv4mcgen_address_t l1;
uint32_t iph;
- unsigned i;
memcpy(&l1, l.address, sizeof(l1));
l.kind = NN_LOCATOR_KIND_UDPv4;
memset(l.address, 0, 12);
iph = ntohl(l1.ipv4.s_addr);
- for (i = 1; i < (1u << l1.count); i++)
+ for (uint32_t i = 1; i < ((uint32_t)1 << l1.count); i++)
{
uint32_t ipn, iph1 = iph;
if (i & (1u << l1.idx))
@@ -3141,9 +3246,9 @@ static void leave_mcast_helper (const nn_locator_t *n, void * varg)
iph1 |= (i << l1.base);
ipn = htonl(iph1);
memcpy(l.address + 12, &ipn, 4);
- if (ddsi_leave_mc (conn, NULL, &l) < 0)
+ if (ddsi_leave_mc (gv, arg->gv->mship, arg->conn, NULL, &l) < 0)
{
- DDS_LOG(DDS_LC_WARNING, "failed to leave network partition multicast group\n");
+ GVWARNING ("failed to leave network partition multicast group\n");
}
}
}
@@ -3153,14 +3258,14 @@ static void leave_mcast_helper (const nn_locator_t *n, void * varg)
}
#endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */
-static dds_retcode_t new_reader_guid
+static dds_return_t new_reader_guid
(
struct reader **rd_out,
const struct nn_guid *guid,
const struct nn_guid *group_guid,
struct participant *pp,
const struct ddsi_sertopic *topic,
- const struct nn_xqos *xqos,
+ const struct dds_qos *xqos,
struct rhc *rhc,
status_cb_t status_cb,
void * status_entity
@@ -3168,37 +3273,38 @@ static dds_retcode_t new_reader_guid
{
/* see new_writer_guid for commenets */
- struct reader * rd;
+ struct reader *rd;
nn_mtime_t tnow = now_mt ();
assert (!is_writer_entityid (guid->entityid));
- assert (ephash_lookup_reader_guid (guid) == NULL);
+ assert (ephash_lookup_reader_guid (pp->e.gv->guid_hash, guid) == NULL);
assert (memcmp (&guid->prefix, &pp->e.guid.prefix, sizeof (guid->prefix)) == 0);
- new_reader_writer_common (guid, topic, xqos);
+ new_reader_writer_common (&pp->e.gv->logconfig, guid, topic, xqos);
rd = ddsrt_malloc (sizeof (*rd));
if (rd_out)
*rd_out = rd;
- endpoint_common_init (&rd->e, &rd->c, EK_READER, guid, group_guid, pp);
+ const bool onlylocal = topic && builtintopic_is_builtintopic (pp->e.gv->builtin_topic_interface, topic);
+ endpoint_common_init (&rd->e, &rd->c, pp->e.gv, EK_READER, guid, group_guid, pp, onlylocal);
/* Copy QoS, merging in defaults */
rd->xqos = ddsrt_malloc (sizeof (*rd->xqos));
nn_xqos_copy (rd->xqos, xqos);
- nn_xqos_mergein_missing (rd->xqos, &gv.default_xqos_rd);
+ nn_xqos_mergein_missing (rd->xqos, &pp->e.gv->default_xqos_rd, ~(uint64_t)0);
assert (rd->xqos->aliased == 0);
set_topic_type_name (rd->xqos, topic);
- if (dds_get_log_mask() & DDS_LC_DISCOVERY)
+ if (rd->e.gv->logconfig.c.mask & DDS_LC_DISCOVERY)
{
- DDS_LOG(DDS_LC_DISCOVERY, "READER "PGUIDFMT" QOS={", PGUID (rd->e.guid));
- nn_log_xqos (DDS_LC_DISCOVERY, rd->xqos);
- DDS_LOG(DDS_LC_DISCOVERY, "}\n");
+ ELOGDISC (rd, "READER "PGUIDFMT" QOS={", PGUID (rd->e.guid));
+ nn_log_xqos (DDS_LC_DISCOVERY, &rd->e.gv->logconfig, rd->xqos);
+ ELOGDISC (rd, "}\n");
}
assert (rd->xqos->present & QP_RELIABILITY);
- rd->reliable = (rd->xqos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS);
+ rd->reliable = (rd->xqos->reliability.kind != DDS_RELIABILITY_BEST_EFFORT);
assert (rd->xqos->present & QP_DURABILITY);
- rd->handle_as_transient_local = (rd->xqos->durability.kind == NN_TRANSIENT_LOCAL_DURABILITY_QOS);
+ rd->handle_as_transient_local = (rd->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL);
rd->topic = ddsi_sertopic_ref (topic);
rd->ddsi2direct_cb = 0;
rd->ddsi2direct_cbarg = 0;
@@ -3216,33 +3322,31 @@ static dds_retcode_t new_reader_guid
/* set rhc qos for reader */
if (rhc)
{
- (ddsi_plugin.rhc_plugin.rhc_set_qos_fn) (rd->rhc, rd->xqos);
+ rhc_set_qos (rd->rhc, rd->xqos);
}
assert (rd->xqos->present & QP_LIVELINESS);
- if (rd->xqos->liveliness.kind != NN_AUTOMATIC_LIVELINESS_QOS ||
- nn_from_ddsi_duration (rd->xqos->liveliness.lease_duration) != T_NEVER)
+ if (rd->xqos->liveliness.kind != DDS_LIVELINESS_AUTOMATIC || rd->xqos->liveliness.lease_duration != T_NEVER)
{
- DDS_LOG(DDS_LC_DISCOVERY, "reader "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (rd->e.guid), (int) rd->xqos->liveliness.kind, nn_from_ddsi_duration (rd->xqos->liveliness.lease_duration));
+ ELOGDISC (rd, "reader "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n",
+ PGUID (rd->e.guid), (int) rd->xqos->liveliness.kind, rd->xqos->liveliness.lease_duration);
}
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
rd->as = new_addrset ();
- if (config.allowMulticast & ~AMC_SPDP)
+ if (pp->e.gv->config.allowMulticast & ~AMC_SPDP)
{
- unsigned i;
-
/* compile address set from the mapped network partitions */
- for (i = 0; i < rd->xqos->partition.n; i++)
+ for (uint32_t i = 0; i < rd->xqos->partition.n; i++)
{
- struct addrset *pas = get_as_from_mapping (rd->xqos->partition.strs[i], rd->xqos->topic_name);
+ struct addrset *pas = get_as_from_mapping (pp->e.gv, rd->xqos->partition.strs[i], rd->xqos->topic_name);
if (pas)
{
#ifdef DDSI_INCLUDE_SSM
- copy_addrset_into_addrset_no_ssm (rd->as, pas);
- if (addrset_contains_ssm (pas) && config.allowMulticast & AMC_SSM)
+ copy_addrset_into_addrset_no_ssm (pp->e.gv, rd->as, pas);
+ if (addrset_contains_ssm (pp->e.gv, pas) && rd->e.gv->config.allowMulticast & AMC_SSM)
rd->favours_ssm = 1;
#else
- copy_addrset_into_addrset (rd->as, pas);
+ copy_addrset_into_addrset (pp->e.gv, rd->as, pas);
#endif
unref_addrset (pas);
}
@@ -3253,12 +3357,15 @@ static dds_retcode_t new_reader_guid
* - Set the correct portnumbers
* - Join the socket if a multicast address
*/
- addrset_forall (rd->as, join_mcast_helper, gv.data_conn_mc);
- if (dds_get_log_mask() & DDS_LC_DISCOVERY)
+ struct join_leave_mcast_helper_arg arg;
+ arg.conn = pp->e.gv->data_conn_mc;
+ arg.gv = pp->e.gv;
+ addrset_forall (rd->as, join_mcast_helper, &arg);
+ if (pp->e.gv->logconfig.c.mask & DDS_LC_DISCOVERY)
{
- DDS_LOG(DDS_LC_DISCOVERY, "READER "PGUIDFMT" locators={", PGUID (rd->e.guid));
- nn_log_addrset(DDS_LC_DISCOVERY, "", rd->as);
- DDS_LOG(DDS_LC_DISCOVERY, "}\n");
+ ELOGDISC (pp, "READER "PGUIDFMT" locators={", PGUID (rd->e.guid));
+ nn_log_addrset(pp->e.gv, DDS_LC_DISCOVERY, "", rd->as);
+ ELOGDISC (pp, "}\n");
}
}
#ifdef DDSI_INCLUDE_SSM
@@ -3267,14 +3374,14 @@ static dds_retcode_t new_reader_guid
/* Note: SSM requires NETWORK_PARTITIONS; if network partitions
do not override the default, we should check whether the
default is an SSM address. */
- if (ddsi_is_ssm_mcaddr (&gv.loc_default_mc) && config.allowMulticast & AMC_SSM)
+ if (ddsi_is_ssm_mcaddr (pp->e.gv, &pp->e.gv->loc_default_mc) && pp->e.gv->config.allowMulticast & AMC_SSM)
rd->favours_ssm = 1;
}
#endif
}
#ifdef DDSI_INCLUDE_SSM
if (rd->favours_ssm)
- DDS_LOG(DDS_LC_DISCOVERY, "READER "PGUIDFMT" ssm=%d\n", PGUID (rd->e.guid), rd->favours_ssm);
+ ELOGDISC (pp, "READER "PGUIDFMT" ssm=%d\n", PGUID (rd->e.guid), rd->favours_ssm);
#endif
#endif
@@ -3282,39 +3389,43 @@ static dds_retcode_t new_reader_guid
ddsrt_avl_init (&rd_local_writers_treedef, &rd->local_writers);
ddsrt_mutex_lock (&rd->e.lock);
- ephash_insert_reader_guid (rd);
- ddsi_plugin.builtintopic_write (&rd->e, now(), true);
+ ephash_insert_reader_guid (pp->e.gv->guid_hash, rd);
+ builtintopic_write (pp->e.gv->builtin_topic_interface, &rd->e, now(), true);
ddsrt_mutex_unlock (&rd->e.lock);
match_reader_with_proxy_writers (rd, tnow);
match_reader_with_local_writers (rd, tnow);
sedp_write_reader (rd);
- return DDS_RETCODE_OK;
+ return 0;
}
-dds_retcode_t new_reader
+dds_return_t new_reader
(
struct reader **rd_out,
+ struct q_globals *gv,
struct nn_guid *rdguid,
const struct nn_guid *group_guid,
const struct nn_guid *ppguid,
const struct ddsi_sertopic *topic,
- const struct nn_xqos *xqos,
+ const struct dds_qos *xqos,
struct rhc * rhc,
status_cb_t status_cb,
void * status_cbarg
)
{
struct participant * pp;
+ dds_return_t rc;
+ uint32_t kind;
- if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL)
+ if ((pp = ephash_lookup_participant_guid (gv->guid_hash, ppguid)) == NULL)
{
- DDS_LOG(DDS_LC_DISCOVERY, "new_reader - participant "PGUIDFMT" not found\n", PGUID (*ppguid));
- return DDS_RETCODE_NOT_FOUND;
+ GVLOGDISC ("new_reader - participant "PGUIDFMT" not found\n", PGUID (*ppguid));
+ return DDS_RETCODE_BAD_PARAMETER;
}
rdguid->prefix = pp->e.guid.prefix;
- if (pp_allocate_entityid (&rdguid->entityid, NN_ENTITYID_KIND_READER_WITH_KEY, pp) < 0)
- return DDS_RETCODE_OUT_OF_RESOURCES;
+ kind = topic->topickind_no_key ? NN_ENTITYID_KIND_READER_NO_KEY : NN_ENTITYID_KIND_READER_WITH_KEY;
+ if ((rc = pp_allocate_entityid (&rdguid->entityid, kind, pp)) < 0)
+ return rc;
return new_reader_guid (rd_out, rdguid, group_guid, pp, topic, xqos, rhc, status_cb, status_cbarg);
}
@@ -3322,7 +3433,7 @@ static void gc_delete_reader (struct gcreq *gcreq)
{
/* see gc_delete_writer for comments */
struct reader *rd = gcreq->arg;
- DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_reader(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (rd->e.guid));
+ ELOGDISC (rd, "gc_delete_reader(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (rd->e.guid));
gcreq_free (gcreq);
while (!ddsrt_avl_is_empty (&rd->writers))
@@ -3330,7 +3441,7 @@ static void gc_delete_reader (struct gcreq *gcreq)
struct rd_pwr_match *m = ddsrt_avl_root_non_empty (&rd_writers_treedef, &rd->writers);
ddsrt_avl_delete (&rd_writers_treedef, &rd->writers, m);
proxy_writer_drop_connection (&m->pwr_guid, rd);
- free_rd_pwr_match (m);
+ free_rd_pwr_match (rd->e.gv, m);
}
while (!ddsrt_avl_is_empty (&rd->local_writers))
{
@@ -3343,11 +3454,16 @@ static void gc_delete_reader (struct gcreq *gcreq)
if (!is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE))
sedp_dispose_unregister_reader (rd);
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
- addrset_forall (rd->as, leave_mcast_helper, gv.data_conn_mc);
+ {
+ struct join_leave_mcast_helper_arg arg;
+ arg.conn = rd->e.gv->data_conn_mc;
+ arg.gv = rd->e.gv;
+ addrset_forall (rd->as, leave_mcast_helper, &arg);
+ }
#endif
if (rd->rhc)
{
- (ddsi_plugin.rhc_plugin.rhc_free_fn) (rd->rhc);
+ rhc_free (rd->rhc);
}
if (rd->status_cb)
{
@@ -3365,37 +3481,30 @@ static void gc_delete_reader (struct gcreq *gcreq)
ddsrt_free (rd);
}
-int delete_reader (const struct nn_guid *guid)
+dds_return_t delete_reader (struct q_globals *gv, const struct nn_guid *guid)
{
struct reader *rd;
assert (!is_writer_entityid (guid->entityid));
- if ((rd = ephash_lookup_reader_guid (guid)) == NULL)
+ if ((rd = ephash_lookup_reader_guid (gv->guid_hash, guid)) == NULL)
{
- DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid));
- return Q_ERR_UNKNOWN_ENTITY;
+ GVLOGDISC ("delete_reader_guid(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid));
+ return DDS_RETCODE_BAD_PARAMETER;
}
- DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid "PGUIDFMT") ...\n", PGUID (*guid));
- ddsi_plugin.builtintopic_write (&rd->e, now(), false);
- ephash_remove_reader_guid (rd);
+ GVLOGDISC ("delete_reader_guid(guid "PGUIDFMT") ...\n", PGUID (*guid));
+ builtintopic_write (rd->e.gv->builtin_topic_interface, &rd->e, now(), false);
+ ephash_remove_reader_guid (gv->guid_hash, rd);
gcreq_reader (rd);
return 0;
}
-uint64_t reader_instance_id (const struct nn_guid *guid)
+void update_reader_qos (struct reader *rd, const dds_qos_t *xqos)
{
- struct entity_common *e;
- e = (struct entity_common*)ephash_lookup_reader_guid(guid);
- if (e) {
- return e->iid;
- }
- e = (struct entity_common*)ephash_lookup_proxy_reader_guid(guid);
- if (e) {
- return e->iid;
- }
- return 0;
+ ddsrt_mutex_lock (&rd->e.lock);
+ if (update_qos_locked (&rd->e, rd->xqos, xqos, now ()))
+ sedp_write_reader (rd);
+ ddsrt_mutex_unlock (&rd->e.lock);
}
-
/* PROXY-PARTICIPANT ------------------------------------------------ */
static void gc_proxy_participant_lease (struct gcreq *gcreq)
{
@@ -3421,7 +3530,7 @@ void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct
if (proxypp->owns_lease)
{
const nn_etime_t never = { T_NEVER };
- struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, gc_proxy_participant_lease);
+ struct gcreq *gcreq = gcreq_new (proxypp->e.gv->gcreq_queue, gc_proxy_participant_lease);
struct lease *oldlease = ddsrt_atomic_ldvoidp (&proxypp->lease);
lease_renew (oldlease, never);
gcreq->arg = oldlease;
@@ -3434,6 +3543,7 @@ void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct
void new_proxy_participant
(
+ struct q_globals *gv,
const struct nn_guid *ppguid,
unsigned bes,
unsigned prismtech_bes,
@@ -3441,10 +3551,11 @@ void new_proxy_participant
struct addrset *as_default,
struct addrset *as_meta,
const nn_plist_t *plist,
- int64_t tlease_dur,
+ dds_duration_t tlease_dur,
nn_vendorid_t vendor,
unsigned custom_flags,
- nn_wctime_t timestamp
+ nn_wctime_t timestamp,
+ seqno_t seq
)
{
/* No locking => iff all participants use unique guids, and sedp
@@ -3453,19 +3564,20 @@ void new_proxy_participant
struct proxy_participant *proxypp;
assert (ppguid->entityid.u == NN_ENTITYID_PARTICIPANT);
- assert (ephash_lookup_proxy_participant_guid (ppguid) == NULL);
+ assert (ephash_lookup_proxy_participant_guid (gv->guid_hash, ppguid) == NULL);
assert (privileged_pp_guid == NULL || privileged_pp_guid->entityid.u == NN_ENTITYID_PARTICIPANT);
- prune_deleted_participant_guids (now_mt ());
+ prune_deleted_participant_guids (gv->deleted_participants, now_mt ());
proxypp = ddsrt_malloc (sizeof (*proxypp));
- entity_common_init (&proxypp->e, ppguid, "", EK_PROXY_PARTICIPANT, timestamp, vendor, false);
+ entity_common_init (&proxypp->e, gv, ppguid, "", EK_PROXY_PARTICIPANT, timestamp, vendor, false);
proxypp->refc = 1;
proxypp->lease_expired = 0;
proxypp->vendor = vendor;
proxypp->bes = bes;
proxypp->prismtech_bes = prismtech_bes;
+ proxypp->seq = seq;
if (privileged_pp_guid) {
proxypp->privileged_pp_guid = *privileged_pp_guid;
} else {
@@ -3486,7 +3598,7 @@ void new_proxy_participant
{
struct proxy_participant *privpp;
- privpp = ephash_lookup_proxy_participant_guid (&proxypp->privileged_pp_guid);
+ privpp = ephash_lookup_proxy_participant_guid (gv->guid_hash, &proxypp->privileged_pp_guid);
if (privpp != NULL && privpp->is_ddsi2_pp)
{
ddsrt_atomic_stvoidp (&proxypp->lease, ddsrt_atomic_ldvoidp (&privpp->lease));
@@ -3496,7 +3608,7 @@ void new_proxy_participant
{
/* Lease duration is meaningless when the lease never expires, but when proxy participants are created implicitly because of endpoint discovery from a cloud service, we do want the lease to expire eventually when the cloud discovery service disappears and never reappears. The normal data path renews the lease, so if the lease expiry is changed after the DS disappears but data continues to flow (even if it is only a single sample) the proxy participant would immediately go back to a non-expiring lease with no further triggers for deleting it. Instead, we take tlease_dur == NEVER as a special value meaning a lease that doesn't expire now and that has a "reasonable" lease duration. That way the lease renewal in the data path is fine, and we only need to do something special in SEDP handling. */
nn_etime_t texp = add_duration_to_etime (now_et(), tlease_dur);
- int64_t dur = (tlease_dur == T_NEVER) ? config.lease_duration : tlease_dur;
+ dds_duration_t dur = (tlease_dur == T_NEVER) ? gv->config.lease_duration : tlease_dur;
ddsrt_atomic_stvoidp (&proxypp->lease, lease_new (texp, dur, &proxypp->e));
proxypp->owns_lease = 1;
}
@@ -3506,9 +3618,9 @@ void new_proxy_participant
proxypp->as_meta = as_meta;
proxypp->endpoints = NULL;
proxypp->plist = nn_plist_dup (plist);
+ nn_xqos_mergein_missing (&proxypp->plist->qos, &gv->default_plist_pp.qos, ~(uint64_t)0);
ddsrt_avl_init (&proxypp_groups_treedef, &proxypp->groups);
-
if (custom_flags & CF_INC_KERNEL_SEQUENCE_NUMBERS)
proxypp->kernel_sequence_numbers = 1;
else
@@ -3533,7 +3645,7 @@ void new_proxy_participant
/* Proxy participant must be in the hash tables for
new_proxy_{writer,reader} to work */
- ephash_insert_proxy_participant_guid (proxypp);
+ ephash_insert_proxy_participant_guid (gv->guid_hash, proxypp);
/* Add proxy endpoints based on the advertised (& possibly augmented
...) built-in endpoint set. */
@@ -3577,8 +3689,8 @@ void new_proxy_participant
coherency */
nn_plist_init_empty (&plist_wr);
nn_plist_init_empty (&plist_rd);
- nn_xqos_copy (&plist_wr.qos, &gv.builtin_endpoint_xqos_wr);
- nn_xqos_copy (&plist_rd.qos, &gv.builtin_endpoint_xqos_rd);
+ nn_xqos_copy (&plist_wr.qos, &gv->builtin_endpoint_xqos_wr);
+ nn_xqos_copy (&plist_rd.qos, &gv->builtin_endpoint_xqos_rd);
for (i = 0; i < (int) (sizeof (bestab) / sizeof (*bestab)); i++)
{
const struct bestab *te = &bestab[i];
@@ -3590,15 +3702,15 @@ void new_proxy_participant
assert (is_builtin_entityid (guid1.entityid, proxypp->vendor));
if (is_writer_entityid (guid1.entityid))
{
- new_proxy_writer (ppguid, &guid1, proxypp->as_meta, &plist_wr, gv.builtins_dqueue, gv.xevents, timestamp);
+ new_proxy_writer (gv, ppguid, &guid1, proxypp->as_meta, &plist_wr, gv->builtins_dqueue, gv->xevents, timestamp, 0);
}
else
{
#ifdef DDSI_INCLUDE_SSM
- const int ssm = addrset_contains_ssm (proxypp->as_meta);
- new_proxy_reader (ppguid, &guid1, proxypp->as_meta, &plist_rd, timestamp, ssm);
+ const int ssm = addrset_contains_ssm (gv, proxypp->as_meta);
+ new_proxy_reader (gv, ppguid, &guid1, proxypp->as_meta, &plist_rd, timestamp, 0, ssm);
#else
- new_proxy_reader (ppguid, &guid1, proxypp->as_meta, &plist_rd, timestamp);
+ new_proxy_reader (gv, ppguid, &guid1, proxypp->as_meta, &plist_rd, timestamp, 0);
#endif
}
}
@@ -3616,56 +3728,43 @@ void new_proxy_participant
if (proxypp->owns_lease)
lease_register (ddsrt_atomic_ldvoidp (&proxypp->lease));
- ddsi_plugin.builtintopic_write (&proxypp->e, timestamp, true);
+ builtintopic_write (gv->builtin_topic_interface, &proxypp->e, timestamp, true);
ddsrt_mutex_unlock (&proxypp->e.lock);
}
-int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, const struct nn_plist *datap, enum update_proxy_participant_source source, nn_wctime_t timestamp)
+int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, enum update_proxy_participant_source source, nn_wctime_t timestamp)
{
- /* Currently, built-in processing is single-threaded, and it is only through this function and the proxy participant deletion (which necessarily happens when no-one else potentially references the proxy participant anymore). So at the moment, the lock is superfluous. */
- nn_plist_t *new_plist;
+ nn_plist_t *new_plist = ddsrt_malloc (sizeof (*new_plist));
+ nn_plist_init_empty (new_plist);
+ nn_plist_mergein_missing (new_plist, datap, PP_PRISMTECH_NODE_NAME | PP_PRISMTECH_EXEC_NAME | PP_PRISMTECH_PROCESS_ID | PP_ENTITY_NAME, QP_USER_DATA);
+ nn_plist_mergein_missing (new_plist, &proxypp->e.gv->default_plist_pp, ~(uint64_t)0, ~(uint64_t)0);
- new_plist = nn_plist_dup (datap);
- nn_plist_mergein_missing (new_plist, proxypp->plist);
- nn_plist_fini (proxypp->plist);
- ddsrt_free (proxypp->plist);
- proxypp->plist = new_plist;
+ if (seq > proxypp->seq)
+ proxypp->seq = seq;
switch (source)
{
case UPD_PROXYPP_SPDP:
- ddsi_plugin.builtintopic_write (&proxypp->e, timestamp, true);
+ update_qos_locked (&proxypp->e, &proxypp->plist->qos, &new_plist->qos, timestamp);
+ nn_plist_fini (new_plist);
+ ddsrt_free (new_plist);
proxypp->proxypp_have_spdp = 1;
break;
+
case UPD_PROXYPP_CM:
+ nn_plist_fini (proxypp->plist);
+ ddsrt_free (proxypp->plist);
+ proxypp->plist = new_plist;
proxypp->proxypp_have_cm = 1;
break;
}
-
return 0;
}
-int update_proxy_participant_plist (struct proxy_participant *proxypp, const struct nn_plist *datap, enum update_proxy_participant_source source, nn_wctime_t timestamp)
+int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, enum update_proxy_participant_source source, nn_wctime_t timestamp)
{
- nn_plist_t tmp;
-
- /* FIXME: find a better way of restricting which bits can get updated */
ddsrt_mutex_lock (&proxypp->e.lock);
- switch (source)
- {
- case UPD_PROXYPP_SPDP:
- update_proxy_participant_plist_locked (proxypp, datap, source, timestamp);
- break;
- case UPD_PROXYPP_CM:
- tmp = *datap;
- tmp.present &=
- PP_PRISMTECH_NODE_NAME | PP_PRISMTECH_EXEC_NAME | PP_PRISMTECH_PROCESS_ID |
- PP_PRISMTECH_WATCHDOG_SCHEDULING | PP_PRISMTECH_LISTENER_SCHEDULING |
- PP_PRISMTECH_SERVICE_TYPE | PP_ENTITY_NAME;
- tmp.qos.present &= QP_PRISMTECH_ENTITY_FACTORY;
- update_proxy_participant_plist_locked (proxypp, &tmp, source, timestamp);
- break;
- }
+ update_proxy_participant_plist_locked (proxypp, seq, datap, source, timestamp);
ddsrt_mutex_unlock (&proxypp->e.lock);
return 0;
}
@@ -3708,9 +3807,7 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p
{
assert (proxypp->endpoints == NULL);
ddsrt_mutex_unlock (&proxypp->e.lock);
- DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant("PGUIDFMT"): refc=0, freeing\n", PGUID (proxypp->e.guid));
-
-
+ ELOGDISC (proxypp, "unref_proxy_participant("PGUIDFMT"): refc=0, freeing\n", PGUID (proxypp->e.guid));
unref_addrset (proxypp->as_default);
unref_addrset (proxypp->as_meta);
nn_plist_fini (proxypp->plist);
@@ -3718,15 +3815,16 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p
if (proxypp->owns_lease)
lease_free (ddsrt_atomic_ldvoidp (&proxypp->lease));
entity_common_fini (&proxypp->e);
- remove_deleted_participant_guid (&proxypp->e.guid, DPG_LOCAL | DPG_REMOTE);
+ remove_deleted_participant_guid (&proxypp->e.gv->logconfig, proxypp->e.gv->deleted_participants, &proxypp->e.guid, DPG_LOCAL | DPG_REMOTE);
ddsrt_free (proxypp);
}
else if (proxypp->endpoints == NULL && proxypp->implicitly_created)
{
assert (refc == 1);
ddsrt_mutex_unlock (&proxypp->e.lock);
- DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant("PGUIDFMT"): refc=%u, no endpoints, implicitly created, deleting\n", PGUID (proxypp->e.guid), (unsigned) refc);
- delete_proxy_participant_by_guid(&proxypp->e.guid, tnow, 1);
+ ELOGDISC (proxypp, "unref_proxy_participant("PGUIDFMT"): refc=%u, no endpoints, implicitly created, deleting\n",
+ PGUID (proxypp->e.guid), (unsigned) refc);
+ delete_proxy_participant_by_guid(proxypp->e.gv, &proxypp->e.guid, tnow, 1);
/* Deletion is still (and has to be) asynchronous. A parallel endpoint creation may or may not
succeed, and if it succeeds it will be deleted along with the proxy participant. So "your
mileage may vary". Also, the proxy participant may be blacklisted for a little ... */
@@ -3734,14 +3832,14 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p
else
{
ddsrt_mutex_unlock (&proxypp->e.lock);
- DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant("PGUIDFMT"): refc=%u\n", PGUID (proxypp->e.guid), (unsigned) refc);
+ ELOGDISC (proxypp, "unref_proxy_participant("PGUIDFMT"): refc=%u\n", PGUID (proxypp->e.guid), (unsigned) refc);
}
}
static void gc_delete_proxy_participant (struct gcreq *gcreq)
{
struct proxy_participant *proxypp = gcreq->arg;
- DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_participant(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (proxypp->e.guid));
+ ELOGDISC (proxypp, "gc_delete_proxy_participant(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (proxypp->e.guid));
gcreq_free (gcreq);
unref_proxy_participant (proxypp, NULL);
}
@@ -3768,30 +3866,30 @@ static void delete_or_detach_dependent_pp (struct proxy_participant *p, struct p
{
/* DDSI2 minimal participant mode -- but really, anything not discovered via Cloud gets deleted */
ddsrt_mutex_unlock (&p->e.lock);
- (void) delete_proxy_participant_by_guid (&p->e.guid, timestamp, isimplicit);
+ (void) delete_proxy_participant_by_guid (p->e.gv, &p->e.guid, timestamp, isimplicit);
}
else
{
- nn_etime_t texp = add_duration_to_etime (now_et(), config.ds_grace_period);
+ nn_etime_t texp = add_duration_to_etime (now_et(), p->e.gv->config.ds_grace_period);
/* Clear dependency (but don't touch entity id, which must be 0x1c1) and set the lease ticking */
- DDS_LOG(DDS_LC_DISCOVERY, PGUIDFMT" detach-from-DS "PGUIDFMT"\n", PGUID(p->e.guid), PGUID(proxypp->e.guid));
+ ELOGDISC (p, PGUIDFMT" detach-from-DS "PGUIDFMT"\n", PGUID(p->e.guid), PGUID(proxypp->e.guid));
memset (&p->privileged_pp_guid.prefix, 0, sizeof (p->privileged_pp_guid.prefix));
lease_set_expiry (ddsrt_atomic_ldvoidp (&p->lease), texp);
ddsrt_mutex_unlock (&p->e.lock);
}
}
-static void delete_ppt (struct proxy_participant * proxypp, nn_wctime_t timestamp, int isimplicit)
+static void delete_ppt (struct proxy_participant *proxypp, nn_wctime_t timestamp, int isimplicit)
{
struct proxy_endpoint_common * c;
int ret;
/* if any proxy participants depend on this participant, delete them */
- DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt("PGUIDFMT") - deleting dependent proxy participants\n", PGUID (proxypp->e.guid));
+ ELOGDISC (proxypp, "delete_ppt("PGUIDFMT") - deleting dependent proxy participants\n", PGUID (proxypp->e.guid));
{
struct ephash_enum_proxy_participant est;
struct proxy_participant *p;
- ephash_enum_proxy_participant_init (&est);
+ ephash_enum_proxy_participant_init (&est, proxypp->e.gv->guid_hash);
while ((p = ephash_enum_proxy_participant_next (&est)) != NULL)
delete_or_detach_dependent_pp(p, proxypp, timestamp, isimplicit);
ephash_enum_proxy_participant_fini (&est);
@@ -3804,22 +3902,18 @@ static void delete_ppt (struct proxy_participant * proxypp, nn_wctime_t timestam
if (isimplicit)
proxypp->lease_expired = 1;
- DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt("PGUIDFMT") - deleting groups\n", PGUID (proxypp->e.guid));
- while (!ddsrt_avl_is_empty (&proxypp->groups))
- delete_proxy_group_locked (ddsrt_avl_root (&proxypp_groups_treedef, &proxypp->groups), timestamp, isimplicit);
-
- DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt("PGUIDFMT") - deleting endpoints\n", PGUID (proxypp->e.guid));
+ ELOGDISC (proxypp, "delete_ppt("PGUIDFMT") - deleting endpoints\n", PGUID (proxypp->e.guid));
c = proxypp->endpoints;
while (c)
{
struct entity_common *e = entity_common_from_proxy_endpoint_common (c);
if (is_writer_entityid (e->guid.entityid))
{
- ret = delete_proxy_writer (&e->guid, timestamp, isimplicit);
+ ret = delete_proxy_writer (proxypp->e.gv, &e->guid, timestamp, isimplicit);
}
else
{
- ret = delete_proxy_reader (&e->guid, timestamp, isimplicit);
+ ret = delete_proxy_reader (proxypp->e.gv, &e->guid, timestamp, isimplicit);
}
(void) ret;
c = c->next_ep;
@@ -3839,10 +3933,10 @@ static void purge_helper (const nn_locator_t *n, void * varg)
{
proxy_purge_data_t data = (proxy_purge_data_t) varg;
if (compare_locators (n, data->loc) == 0)
- delete_proxy_participant_by_guid (&data->proxypp->e.guid, data->timestamp, 1);
+ delete_proxy_participant_by_guid (data->proxypp->e.gv, &data->proxypp->e.guid, data->timestamp, 1);
}
-void purge_proxy_participants (const nn_locator_t *loc, bool delete_from_as_disc)
+void purge_proxy_participants (struct q_globals *gv, const nn_locator_t *loc, bool delete_from_as_disc)
{
/* FIXME: check whether addr:port can't be reused for a new connection by the time we get here. */
/* NOTE: This function exists for the sole purpose of cleaning up after closing a TCP connection in ddsi_tcp_close_conn and the state of the calling thread could be anything at this point. Because of that we do the unspeakable and toggle the thread state conditionally. We can't afford to have it in "asleep", as that causes a race with the garbage collector. */
@@ -3850,165 +3944,59 @@ void purge_proxy_participants (const nn_locator_t *loc, bool delete_from_as_disc
struct ephash_enum_proxy_participant est;
struct proxy_purge_data data;
- thread_state_awake (ts1);
+ thread_state_awake_fixed_domain (ts1);
data.loc = loc;
data.timestamp = now();
- ephash_enum_proxy_participant_init (&est);
+ ephash_enum_proxy_participant_init (&est, gv->guid_hash);
while ((data.proxypp = ephash_enum_proxy_participant_next (&est)) != NULL)
addrset_forall (data.proxypp->as_meta, purge_helper, &data);
ephash_enum_proxy_participant_fini (&est);
/* Shouldn't try to keep pinging clients once they're gone */
if (delete_from_as_disc)
- remove_from_addrset (gv.as_disc, loc);
+ remove_from_addrset (gv, gv->as_disc, loc);
thread_state_asleep (ts1);
}
-int delete_proxy_participant_by_guid (const struct nn_guid * guid, nn_wctime_t timestamp, int isimplicit)
+int delete_proxy_participant_by_guid (struct q_globals *gv, const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit)
{
- struct proxy_participant * ppt;
+ struct proxy_participant *ppt;
- DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_participant_by_guid("PGUIDFMT") ", PGUID (*guid));
- ddsrt_mutex_lock (&gv.lock);
- ppt = ephash_lookup_proxy_participant_guid (guid);
+ GVLOGDISC ("delete_proxy_participant_by_guid("PGUIDFMT") ", PGUID (*guid));
+ ddsrt_mutex_lock (&gv->lock);
+ ppt = ephash_lookup_proxy_participant_guid (gv->guid_hash, guid);
if (ppt == NULL)
{
- ddsrt_mutex_unlock (&gv.lock);
- DDS_LOG(DDS_LC_DISCOVERY, "- unknown\n");
- return Q_ERR_UNKNOWN_ENTITY;
+ ddsrt_mutex_unlock (&gv->lock);
+ GVLOGDISC ("- unknown\n");
+ return DDS_RETCODE_BAD_PARAMETER;
}
- DDS_LOG(DDS_LC_DISCOVERY, "- deleting\n");
- ddsi_plugin.builtintopic_write (&ppt->e, timestamp, false);
- remember_deleted_participant_guid (&ppt->e.guid);
- ephash_remove_proxy_participant_guid (ppt);
- ddsrt_mutex_unlock (&gv.lock);
+ GVLOGDISC ("- deleting\n");
+ builtintopic_write (gv->builtin_topic_interface, &ppt->e, timestamp, false);
+ remember_deleted_participant_guid (gv->deleted_participants, &ppt->e.guid);
+ ephash_remove_proxy_participant_guid (gv->guid_hash, ppt);
+ ddsrt_mutex_unlock (&gv->lock);
delete_ppt (ppt, timestamp, isimplicit);
return 0;
}
-uint64_t participant_instance_id (const struct nn_guid *guid)
+uint64_t get_entity_instance_id (const struct q_globals *gv, const struct nn_guid *guid)
{
- struct entity_common *e;
- e = (struct entity_common*)ephash_lookup_participant_guid(guid);
- if (e) {
- return e->iid;
- }
- e = (struct entity_common*)ephash_lookup_proxy_participant_guid(guid);
- if (e) {
- return e->iid;
- }
- return 0;
-}
-
-/* PROXY-GROUP --------------------------------------------------- */
-
-int new_proxy_group (const struct nn_guid *guid, const char *name, const struct nn_xqos *xqos, nn_wctime_t timestamp)
-{
- struct proxy_participant *proxypp;
- nn_guid_t ppguid;
- (void)timestamp;
- ppguid.prefix = guid->prefix;
- ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
- if ((proxypp = ephash_lookup_proxy_participant_guid (&ppguid)) == NULL)
- {
- DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group("PGUIDFMT") - unknown participant\n", PGUID (*guid));
- return 0;
- }
- else
- {
- struct proxy_group *pgroup;
- ddsrt_avl_ipath_t ipath;
- int is_sub;
- switch (guid->entityid.u & (NN_ENTITYID_SOURCE_MASK | NN_ENTITYID_KIND_MASK))
- {
- case NN_ENTITYID_SOURCE_VENDOR | NN_ENTITYID_KIND_PRISMTECH_PUBLISHER:
- is_sub = 0;
- break;
- case NN_ENTITYID_SOURCE_VENDOR | NN_ENTITYID_KIND_PRISMTECH_SUBSCRIBER:
- is_sub = 1;
- break;
- default:
- DDS_WARNING("new_proxy_group: unrecognised entityid: %"PRIx32"\n", guid->entityid.u);
- return Q_ERR_INVALID_DATA;
- }
- ddsrt_mutex_lock (&proxypp->e.lock);
- if ((pgroup = ddsrt_avl_lookup_ipath (&proxypp_groups_treedef, &proxypp->groups, guid, &ipath)) != NULL)
- {
- /* Complete proxy group definition if it was a partial
- definition made by creating a proxy reader or writer,
- otherwise ignore this call */
- if (pgroup->name != NULL)
- goto out;
- }
- else
- {
- /* Always have a guid, may not have a gid */
- DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group("PGUIDFMT"): new\n", PGUID (*guid));
- pgroup = ddsrt_malloc (sizeof (*pgroup));
- pgroup->guid = *guid;
- pgroup->proxypp = proxypp;
- pgroup->name = NULL;
- pgroup->xqos = NULL;
- ddsrt_avl_insert_ipath (&proxypp_groups_treedef, &proxypp->groups, pgroup, &ipath);
- }
- if (name)
- {
- assert (xqos != NULL);
- DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group("PGUIDFMT"): setting name (%s) and qos\n", PGUID (*guid), name);
- pgroup->name = ddsrt_strdup (name);
- pgroup->xqos = nn_xqos_dup (xqos);
- nn_xqos_mergein_missing (pgroup->xqos, is_sub ? &gv.default_xqos_sub : &gv.default_xqos_pub);
- }
- out:
- ddsrt_mutex_unlock (&proxypp->e.lock);
- DDS_LOG(DDS_LC_DISCOVERY, "\n");
- return 0;
- }
-}
-
-static void delete_proxy_group_locked (struct proxy_group *pgroup, nn_wctime_t timestamp, int isimplicit)
-{
- struct proxy_participant *proxypp = pgroup->proxypp;
- (void)timestamp;
- (void)isimplicit;
- assert ((pgroup->xqos != NULL) == (pgroup->name != NULL));
- DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_group_locked "PGUIDFMT"\n", PGUID (pgroup->guid));
- ddsrt_avl_delete (&proxypp_groups_treedef, &proxypp->groups, pgroup);
- /* Publish corresponding built-in topic only if it is not a place
- holder: in that case we haven't announced its presence and
- therefore don't need to dispose it, and this saves us from having
- to handle null pointers for name and QoS in the built-in topic
- generation */
- if (pgroup->name)
- {
- nn_xqos_fini (pgroup->xqos);
- ddsrt_free (pgroup->xqos);
- ddsrt_free (pgroup->name);
- }
- ddsrt_free (pgroup);
-}
-
-void delete_proxy_group (const nn_guid_t *guid, nn_wctime_t timestamp, int isimplicit)
-{
- struct proxy_participant *proxypp;
- nn_guid_t ppguid;
- ppguid.prefix = guid->prefix;
- ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
- if ((proxypp = ephash_lookup_proxy_participant_guid (&ppguid)) != NULL)
- {
- struct proxy_group *pgroup;
- ddsrt_mutex_lock (&proxypp->e.lock);
- if ((pgroup = ddsrt_avl_lookup (&proxypp_groups_treedef, &proxypp->groups, guid)) != NULL)
- delete_proxy_group_locked (pgroup, timestamp, isimplicit);
- ddsrt_mutex_unlock (&proxypp->e.lock);
- }
+ struct thread_state1 *ts1 = lookup_thread_state ();
+ struct entity_common *e;
+ uint64_t iid = 0;
+ thread_state_awake (ts1, gv);
+ if ((e = ephash_lookup_guid_untyped (gv->guid_hash, guid)) != NULL)
+ iid = e->iid;
+ thread_state_asleep (ts1);
+ return iid;
}
/* PROXY-ENDPOINT --------------------------------------------------- */
-static void proxy_endpoint_common_init (struct entity_common *e, struct proxy_endpoint_common *c, enum entity_kind kind, const struct nn_guid *guid, nn_wctime_t tcreate, struct proxy_participant *proxypp, struct addrset *as, const nn_plist_t *plist)
+static void proxy_endpoint_common_init (struct entity_common *e, struct proxy_endpoint_common *c, enum entity_kind kind, const struct nn_guid *guid, nn_wctime_t tcreate, seqno_t seq, struct proxy_participant *proxypp, struct addrset *as, const nn_plist_t *plist)
{
const char *name;
@@ -4018,18 +4006,18 @@ static void proxy_endpoint_common_init (struct entity_common *e, struct proxy_en
assert ((plist->qos.present & (QP_TOPIC_NAME | QP_TYPE_NAME)) == (QP_TOPIC_NAME | QP_TYPE_NAME));
name = (plist->present & PP_ENTITY_NAME) ? plist->entity_name : "";
- entity_common_init (e, guid, name, kind, tcreate, proxypp->vendor, false);
+ entity_common_init (e, proxypp->e.gv, guid, name, kind, tcreate, proxypp->vendor, false);
c->xqos = nn_xqos_dup (&plist->qos);
c->as = ref_addrset (as);
c->topic = NULL; /* set from first matching reader/writer */
c->vendor = proxypp->vendor;
+ c->seq = seq;
if (plist->present & PP_GROUP_GUID)
c->group_guid = plist->group_guid;
else
memset (&c->group_guid, 0, sizeof (c->group_guid));
-
ref_proxy_participant (proxypp, c);
}
@@ -4047,7 +4035,7 @@ static void proxy_endpoint_common_fini (struct entity_common *e, struct proxy_en
/* PROXY-WRITER ----------------------------------------------------- */
-int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, struct addrset *as, const nn_plist_t *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp)
+int new_proxy_writer (struct q_globals *gv, const struct nn_guid *ppguid, const struct nn_guid *guid, struct addrset *as, const nn_plist_t *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp, seqno_t seq)
{
struct proxy_participant *proxypp;
struct proxy_writer *pwr;
@@ -4055,16 +4043,16 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid,
nn_mtime_t tnow = now_mt ();
assert (is_writer_entityid (guid->entityid));
- assert (ephash_lookup_proxy_writer_guid (guid) == NULL);
+ assert (ephash_lookup_proxy_writer_guid (gv->guid_hash, guid) == NULL);
- if ((proxypp = ephash_lookup_proxy_participant_guid (ppguid)) == NULL)
+ if ((proxypp = ephash_lookup_proxy_participant_guid (gv->guid_hash, ppguid)) == NULL)
{
- DDS_WARNING("new_proxy_writer("PGUIDFMT"): proxy participant unknown\n", PGUID (*guid));
- return Q_ERR_UNKNOWN_ENTITY;
+ GVWARNING ("new_proxy_writer("PGUIDFMT"): proxy participant unknown\n", PGUID (*guid));
+ return DDS_RETCODE_BAD_PARAMETER;
}
pwr = ddsrt_malloc (sizeof (*pwr));
- proxy_endpoint_common_init (&pwr->e, &pwr->c, EK_PROXY_WRITER, guid, timestamp, proxypp, as, plist);
+ proxy_endpoint_common_init (&pwr->e, &pwr->c, EK_PROXY_WRITER, guid, timestamp, seq, proxypp, as, plist);
ddsrt_avl_init (&pwr_readers_treedef, &pwr->readers);
pwr->n_reliable_readers = 0;
@@ -4078,8 +4066,8 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid,
/* The DDSI built-in proxy writers always deliver
asynchronously */
pwr->deliver_synchronously = 0;
- } else if (nn_from_ddsi_duration (pwr->c.xqos->latency_budget.duration) <= config.synchronous_delivery_latency_bound &&
- pwr->c.xqos->transport_priority.value >= config.synchronous_delivery_priority_threshold) {
+ } else if (pwr->c.xqos->latency_budget.duration <= gv->config.synchronous_delivery_latency_bound &&
+ pwr->c.xqos->transport_priority.value >= gv->config.synchronous_delivery_priority_threshold) {
/* Regular proxy-writers with a sufficiently low latency_budget
and a sufficiently high transport_priority deliver
synchronously */
@@ -4088,26 +4076,21 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid,
pwr->deliver_synchronously = 0;
}
/* Pretend we have seen a heartbeat if the proxy writer is a best-effort one */
- isreliable = (pwr->c.xqos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS);
+ isreliable = (pwr->c.xqos->reliability.kind != DDS_RELIABILITY_BEST_EFFORT);
pwr->have_seen_heartbeat = !isreliable;
pwr->local_matching_inprogress = 1;
#ifdef DDSI_INCLUDE_SSM
- pwr->supports_ssm = (addrset_contains_ssm (as) && config.allowMulticast & AMC_SSM) ? 1 : 0;
+ pwr->supports_ssm = (addrset_contains_ssm (gv, as) && gv->config.allowMulticast & AMC_SSM) ? 1 : 0;
#endif
- /* Only assert PP lease on receipt of data if enabled (duh) and the proxy participant is a
- "real" participant, rather than the thing we use for endpoints discovered via the DS */
- pwr->assert_pp_lease =
- (unsigned) !!config.arrival_of_data_asserts_pp_and_ep_liveliness;
-
assert (pwr->c.xqos->present & QP_LIVELINESS);
- if (pwr->c.xqos->liveliness.kind != NN_AUTOMATIC_LIVELINESS_QOS)
- DDS_LOG(DDS_LC_DISCOVERY, " FIXME: only AUTOMATIC liveliness supported");
+ if (pwr->c.xqos->liveliness.kind != DDS_LIVELINESS_AUTOMATIC)
+ GVLOGDISC (" FIXME: only AUTOMATIC liveliness supported");
#if 0
pwr->tlease_dur = nn_from_ddsi_duration (pwr->c.xqos->liveliness.lease_duration);
if (pwr->tlease_dur == 0)
{
- DDS_LOG(DDS_LC_DISCOVERY, " FIXME: treating lease_duration=0 as inf");
+ GVLOGDISC (" FIXME: treating lease_duration=0 as inf");
pwr->tlease_dur = T_NEVER;
}
pwr->tlease_end = add_duration_to_wctime (tnow, pwr->tlease_dur);
@@ -4115,13 +4098,13 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid,
if (isreliable)
{
- pwr->defrag = nn_defrag_new (NN_DEFRAG_DROP_LATEST, config.defrag_reliable_maxsamples);
- pwr->reorder = nn_reorder_new (NN_REORDER_MODE_NORMAL, config.primary_reorder_maxsamples);
+ pwr->defrag = nn_defrag_new (&gv->logconfig, NN_DEFRAG_DROP_LATEST, gv->config.defrag_reliable_maxsamples);
+ pwr->reorder = nn_reorder_new (&gv->logconfig, NN_REORDER_MODE_NORMAL, gv->config.primary_reorder_maxsamples, gv->config.late_ack_mode);
}
else
{
- pwr->defrag = nn_defrag_new (NN_DEFRAG_DROP_OLDEST, config.defrag_unreliable_maxsamples);
- pwr->reorder = nn_reorder_new (NN_REORDER_MODE_MONOTONICALLY_INCREASING, config.primary_reorder_maxsamples);
+ pwr->defrag = nn_defrag_new (&gv->logconfig, NN_DEFRAG_DROP_OLDEST, gv->config.defrag_unreliable_maxsamples);
+ pwr->reorder = nn_reorder_new (&gv->logconfig, NN_REORDER_MODE_MONOTONICALLY_INCREASING, gv->config.primary_reorder_maxsamples, gv->config.late_ack_mode);
}
pwr->dqueue = dqueue;
pwr->evq = evq;
@@ -4132,8 +4115,8 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid,
/* locking the entity prevents matching while the built-in topic hasn't been published yet */
ddsrt_mutex_lock (&pwr->e.lock);
- ephash_insert_proxy_writer_guid (pwr);
- ddsi_plugin.builtintopic_write (&pwr->e, timestamp, true);
+ ephash_insert_proxy_writer_guid (gv->guid_hash, pwr);
+ builtintopic_write (gv->builtin_topic_interface, &pwr->e, timestamp, true);
ddsrt_mutex_unlock (&pwr->e.lock);
match_proxy_writer_with_readers (pwr, tnow);
@@ -4145,38 +4128,44 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid,
return 0;
}
-void update_proxy_writer (struct proxy_writer * pwr, struct addrset * as)
+void update_proxy_writer (struct proxy_writer *pwr, seqno_t seq, struct addrset *as, const struct dds_qos *xqos, nn_wctime_t timestamp)
{
struct reader * rd;
- struct pwr_rd_match * m;
+ struct pwr_rd_match * m;
ddsrt_avl_iter_t iter;
/* Update proxy writer endpoints (from SEDP alive) */
ddsrt_mutex_lock (&pwr->e.lock);
- if (! addrset_eq_onesidederr (pwr->c.as, as))
+ if (seq > pwr->c.seq)
{
-#ifdef DDSI_INCLUDE_SSM
- pwr->supports_ssm = (addrset_contains_ssm (as) && config.allowMulticast & AMC_SSM) ? 1 : 0;
-#endif
- unref_addrset (pwr->c.as);
- ref_addrset (as);
- pwr->c.as = as;
- m = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &iter);
- while (m)
+ pwr->c.seq = seq;
+ if (! addrset_eq_onesidederr (pwr->c.as, as))
{
- rd = ephash_lookup_reader_guid (&m->rd_guid);
- if (rd)
+#ifdef DDSI_INCLUDE_SSM
+ pwr->supports_ssm = (addrset_contains_ssm (pwr->e.gv, as) && pwr->e.gv->config.allowMulticast & AMC_SSM) ? 1 : 0;
+#endif
+ unref_addrset (pwr->c.as);
+ ref_addrset (as);
+ pwr->c.as = as;
+ m = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &iter);
+ while (m)
{
- qxev_pwr_entityid (pwr, &rd->e.guid.prefix);
+ rd = ephash_lookup_reader_guid (pwr->e.gv->guid_hash, &m->rd_guid);
+ if (rd)
+ {
+ qxev_pwr_entityid (pwr, &rd->e.guid.prefix);
+ }
+ m = ddsrt_avl_iter_next (&iter);
}
- m = ddsrt_avl_iter_next (&iter);
}
+
+ update_qos_locked (&pwr->e, pwr->c.xqos, xqos, timestamp);
}
ddsrt_mutex_unlock (&pwr->e.lock);
}
-void update_proxy_reader (struct proxy_reader * prd, struct addrset * as)
+void update_proxy_reader (struct proxy_reader *prd, seqno_t seq, struct addrset *as, const struct dds_qos *xqos, nn_wctime_t timestamp)
{
struct prd_wr_match * m;
nn_guid_t wrguid;
@@ -4184,46 +4173,52 @@ void update_proxy_reader (struct proxy_reader * prd, struct addrset * as)
memset (&wrguid, 0, sizeof (wrguid));
ddsrt_mutex_lock (&prd->e.lock);
- if (! addrset_eq_onesidederr (prd->c.as, as))
+ if (seq > prd->c.seq)
{
- /* Update proxy reader endpoints (from SEDP alive) */
-
- unref_addrset (prd->c.as);
- ref_addrset (as);
- prd->c.as = as;
-
- /* Rebuild writer endpoints */
-
- while ((m = ddsrt_avl_lookup_succ_eq (&prd_writers_treedef, &prd->writers, &wrguid)) != NULL)
+ prd->c.seq = seq;
+ if (! addrset_eq_onesidederr (prd->c.as, as))
{
- struct prd_wr_match *next;
- nn_guid_t guid_next;
- struct writer * wr;
+ /* Update proxy reader endpoints (from SEDP alive) */
- wrguid = m->wr_guid;
- next = ddsrt_avl_find_succ (&prd_writers_treedef, &prd->writers, m);
- if (next)
- {
- guid_next = next->wr_guid;
- }
- else
- {
- memset (&guid_next, 0xff, sizeof (guid_next));
- guid_next.entityid.u = (guid_next.entityid.u & ~(unsigned)0xff) | NN_ENTITYID_KIND_WRITER_NO_KEY;
- }
+ unref_addrset (prd->c.as);
+ ref_addrset (as);
+ prd->c.as = as;
- ddsrt_mutex_unlock (&prd->e.lock);
- wr = ephash_lookup_writer_guid (&wrguid);
- if (wr)
+ /* Rebuild writer endpoints */
+
+ while ((m = ddsrt_avl_lookup_succ_eq (&prd_writers_treedef, &prd->writers, &wrguid)) != NULL)
{
- ddsrt_mutex_lock (&wr->e.lock);
- rebuild_writer_addrset (wr);
- ddsrt_mutex_unlock (&wr->e.lock);
- qxev_prd_entityid (prd, &wr->e.guid.prefix);
+ struct prd_wr_match *next;
+ nn_guid_t guid_next;
+ struct writer * wr;
+
+ wrguid = m->wr_guid;
+ next = ddsrt_avl_find_succ (&prd_writers_treedef, &prd->writers, m);
+ if (next)
+ {
+ guid_next = next->wr_guid;
+ }
+ else
+ {
+ memset (&guid_next, 0xff, sizeof (guid_next));
+ guid_next.entityid.u = (guid_next.entityid.u & ~(unsigned)0xff) | NN_ENTITYID_KIND_WRITER_NO_KEY;
+ }
+
+ ddsrt_mutex_unlock (&prd->e.lock);
+ wr = ephash_lookup_writer_guid (prd->e.gv->guid_hash, &wrguid);
+ if (wr)
+ {
+ ddsrt_mutex_lock (&wr->e.lock);
+ rebuild_writer_addrset (wr);
+ ddsrt_mutex_unlock (&wr->e.lock);
+ qxev_prd_entityid (prd, &wr->e.guid.prefix);
+ }
+ wrguid = guid_next;
+ ddsrt_mutex_lock (&prd->e.lock);
}
- wrguid = guid_next;
- ddsrt_mutex_lock (&prd->e.lock);
}
+
+ update_qos_locked (&prd->e, prd->c.xqos, xqos, timestamp);
}
ddsrt_mutex_unlock (&prd->e.lock);
}
@@ -4231,7 +4226,7 @@ void update_proxy_reader (struct proxy_reader * prd, struct addrset * as)
static void gc_delete_proxy_writer (struct gcreq *gcreq)
{
struct proxy_writer *pwr = gcreq->arg;
- DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pwr->e.guid));
+ ELOGDISC (pwr, "gc_delete_proxy_writer(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pwr->e.guid));
gcreq_free (gcreq);
while (!ddsrt_avl_is_empty (&pwr->readers))
@@ -4239,7 +4234,7 @@ static void gc_delete_proxy_writer (struct gcreq *gcreq)
struct pwr_rd_match *m = ddsrt_avl_root_non_empty (&pwr_readers_treedef, &pwr->readers);
ddsrt_avl_delete (&pwr_readers_treedef, &pwr->readers, m);
reader_drop_connection (&m->rd_guid, pwr);
- update_reader_init_acknack_count (&m->rd_guid, m->count);
+ update_reader_init_acknack_count (&pwr->e.gv->logconfig, pwr->e.gv->guid_hash, &m->rd_guid, m->count);
free_pwr_rd_match (m);
}
local_reader_ary_fini (&pwr->rdary);
@@ -4249,34 +4244,34 @@ static void gc_delete_proxy_writer (struct gcreq *gcreq)
ddsrt_free (pwr);
}
-int delete_proxy_writer (const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit)
+int delete_proxy_writer (struct q_globals *gv, const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit)
{
struct proxy_writer *pwr;
(void)isimplicit;
- DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_writer ("PGUIDFMT") ", PGUID (*guid));
- ddsrt_mutex_lock (&gv.lock);
- if ((pwr = ephash_lookup_proxy_writer_guid (guid)) == NULL)
+ GVLOGDISC ("delete_proxy_writer ("PGUIDFMT") ", PGUID (*guid));
+ ddsrt_mutex_lock (&gv->lock);
+ if ((pwr = ephash_lookup_proxy_writer_guid (gv->guid_hash, guid)) == NULL)
{
- ddsrt_mutex_unlock (&gv.lock);
- DDS_LOG(DDS_LC_DISCOVERY, "- unknown\n");
- return Q_ERR_UNKNOWN_ENTITY;
+ ddsrt_mutex_unlock (&gv->lock);
+ GVLOGDISC ("- unknown\n");
+ return DDS_RETCODE_BAD_PARAMETER;
}
/* Set "deleting" flag in particular for Lite, to signal to the receive path it can't
trust rdary[] anymore, which is because removing the proxy writer from the hash
table will prevent the readers from looking up the proxy writer, and consequently
from removing themselves from the proxy writer's rdary[]. */
local_reader_ary_setinvalid (&pwr->rdary);
- DDS_LOG(DDS_LC_DISCOVERY, "- deleting\n");
- ddsi_plugin.builtintopic_write (&pwr->e, timestamp, false);
- ephash_remove_proxy_writer_guid (pwr);
- ddsrt_mutex_unlock (&gv.lock);
+ GVLOGDISC ("- deleting\n");
+ builtintopic_write (gv->builtin_topic_interface, &pwr->e, timestamp, false);
+ ephash_remove_proxy_writer_guid (gv->guid_hash, pwr);
+ ddsrt_mutex_unlock (&gv->lock);
gcreq_proxy_writer (pwr);
return 0;
}
/* PROXY-READER ----------------------------------------------------- */
-int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, struct addrset *as, const nn_plist_t *plist, nn_wctime_t timestamp
+int new_proxy_reader (struct q_globals *gv, const struct nn_guid *ppguid, const struct nn_guid *guid, struct addrset *as, const nn_plist_t *plist, nn_wctime_t timestamp, seqno_t seq
#ifdef DDSI_INCLUDE_SSM
, int favours_ssm
#endif
@@ -4287,32 +4282,29 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid,
nn_mtime_t tnow = now_mt ();
assert (!is_writer_entityid (guid->entityid));
- assert (ephash_lookup_proxy_reader_guid (guid) == NULL);
+ assert (ephash_lookup_proxy_reader_guid (gv->guid_hash, guid) == NULL);
- if ((proxypp = ephash_lookup_proxy_participant_guid (ppguid)) == NULL)
+ if ((proxypp = ephash_lookup_proxy_participant_guid (gv->guid_hash, ppguid)) == NULL)
{
- DDS_WARNING("new_proxy_reader("PGUIDFMT"): proxy participant unknown\n", PGUID (*guid));
- return Q_ERR_UNKNOWN_ENTITY;
+ GVWARNING ("new_proxy_reader("PGUIDFMT"): proxy participant unknown\n", PGUID (*guid));
+ return DDS_RETCODE_BAD_PARAMETER;
}
prd = ddsrt_malloc (sizeof (*prd));
- proxy_endpoint_common_init (&prd->e, &prd->c, EK_PROXY_READER, guid, timestamp, proxypp, as, plist);
+ proxy_endpoint_common_init (&prd->e, &prd->c, EK_PROXY_READER, guid, timestamp, seq, proxypp, as, plist);
prd->deleting = 0;
#ifdef DDSI_INCLUDE_SSM
- prd->favours_ssm = (favours_ssm && config.allowMulticast & AMC_SSM) ? 1 : 0;
+ prd->favours_ssm = (favours_ssm && gv->config.allowMulticast & AMC_SSM) ? 1 : 0;
#endif
prd->is_fict_trans_reader = 0;
- /* Only assert PP lease on receipt of data if enabled (duh) and the proxy participant is a
- "real" participant, rather than the thing we use for endpoints discovered via the DS */
- prd->assert_pp_lease = (unsigned) !!config.arrival_of_data_asserts_pp_and_ep_liveliness;
ddsrt_avl_init (&prd_writers_treedef, &prd->writers);
/* locking the entity prevents matching while the built-in topic hasn't been published yet */
ddsrt_mutex_lock (&prd->e.lock);
- ephash_insert_proxy_reader_guid (prd);
- ddsi_plugin.builtintopic_write (&prd->e, timestamp, true);
+ ephash_insert_proxy_reader_guid (gv->guid_hash, prd);
+ builtintopic_write (gv->builtin_topic_interface, &prd->e, timestamp, true);
ddsrt_mutex_unlock (&prd->e.lock);
match_proxy_reader_with_writers (prd, tnow);
@@ -4344,7 +4336,7 @@ static void proxy_reader_set_delete_and_ack_all_messages (struct proxy_reader *p
}
ddsrt_mutex_unlock (&prd->e.lock);
- if ((wr = ephash_lookup_writer_guid (&wrguid)) != NULL)
+ if ((wr = ephash_lookup_writer_guid (prd->e.gv->guid_hash, &wrguid)) != NULL)
{
struct whc_node *deferred_free_list = NULL;
struct wr_prd_match *m_wr;
@@ -4370,7 +4362,7 @@ static void proxy_reader_set_delete_and_ack_all_messages (struct proxy_reader *p
static void gc_delete_proxy_reader (struct gcreq *gcreq)
{
struct proxy_reader *prd = gcreq->arg;
- DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_reader(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (prd->e.guid));
+ ELOGDISC (prd, "gc_delete_proxy_reader(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (prd->e.guid));
gcreq_free (gcreq);
while (!ddsrt_avl_is_empty (&prd->writers))
@@ -4385,22 +4377,22 @@ static void gc_delete_proxy_reader (struct gcreq *gcreq)
ddsrt_free (prd);
}
-int delete_proxy_reader (const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit)
+int delete_proxy_reader (struct q_globals *gv, const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit)
{
struct proxy_reader *prd;
(void)isimplicit;
- DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_reader ("PGUIDFMT") ", PGUID (*guid));
- ddsrt_mutex_lock (&gv.lock);
- if ((prd = ephash_lookup_proxy_reader_guid (guid)) == NULL)
+ GVLOGDISC ("delete_proxy_reader ("PGUIDFMT") ", PGUID (*guid));
+ ddsrt_mutex_lock (&gv->lock);
+ if ((prd = ephash_lookup_proxy_reader_guid (gv->guid_hash, guid)) == NULL)
{
- ddsrt_mutex_unlock (&gv.lock);
- DDS_LOG(DDS_LC_DISCOVERY, "- unknown\n");
- return Q_ERR_UNKNOWN_ENTITY;
+ ddsrt_mutex_unlock (&gv->lock);
+ GVLOGDISC ("- unknown\n");
+ return DDS_RETCODE_BAD_PARAMETER;
}
- ddsi_plugin.builtintopic_write (&prd->e, timestamp, false);
- ephash_remove_proxy_reader_guid (prd);
- ddsrt_mutex_unlock (&gv.lock);
- DDS_LOG(DDS_LC_DISCOVERY, "- deleting\n");
+ builtintopic_write (gv->builtin_topic_interface, &prd->e, timestamp, false);
+ ephash_remove_proxy_reader_guid (gv->guid_hash, prd);
+ ddsrt_mutex_unlock (&gv->lock);
+ GVLOGDISC ("- deleting\n");
/* If the proxy reader is reliable, pretend it has just acked all
messages: this allows a throttled writer to once again make
@@ -4416,7 +4408,7 @@ int delete_proxy_reader (const struct nn_guid *guid, nn_wctime_t timestamp, int
static int gcreq_participant (struct participant *pp)
{
- struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, gc_delete_participant);
+ struct gcreq *gcreq = gcreq_new (pp->e.gv->gcreq_queue, gc_delete_participant);
gcreq->arg = pp;
gcreq_enqueue (gcreq);
return 0;
@@ -4424,7 +4416,7 @@ static int gcreq_participant (struct participant *pp)
static int gcreq_writer (struct writer *wr)
{
- struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, wr->throttling ? gc_delete_writer_throttlewait : gc_delete_writer);
+ struct gcreq *gcreq = gcreq_new (wr->e.gv->gcreq_queue, wr->throttling ? gc_delete_writer_throttlewait : gc_delete_writer);
gcreq->arg = wr;
gcreq_enqueue (gcreq);
return 0;
@@ -4432,7 +4424,7 @@ static int gcreq_writer (struct writer *wr)
static int gcreq_reader (struct reader *rd)
{
- struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, gc_delete_reader);
+ struct gcreq *gcreq = gcreq_new (rd->e.gv->gcreq_queue, gc_delete_reader);
gcreq->arg = rd;
gcreq_enqueue (gcreq);
return 0;
@@ -4440,7 +4432,7 @@ static int gcreq_reader (struct reader *rd)
static int gcreq_proxy_participant (struct proxy_participant *proxypp)
{
- struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, gc_delete_proxy_participant);
+ struct gcreq *gcreq = gcreq_new (proxypp->e.gv->gcreq_queue, gc_delete_proxy_participant);
gcreq->arg = proxypp;
gcreq_enqueue (gcreq);
return 0;
@@ -4450,7 +4442,7 @@ static void gc_delete_proxy_writer_dqueue_bubble_cb (struct gcreq *gcreq)
{
/* delete proxy_writer, phase 3 */
struct proxy_writer *pwr = gcreq->arg;
- DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer_dqueue_bubble(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pwr->e.guid));
+ ELOGDISC (pwr, "gc_delete_proxy_writer_dqueue_bubble(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pwr->e.guid));
gcreq_requeue (gcreq, gc_delete_proxy_writer);
}
@@ -4459,13 +4451,13 @@ static void gc_delete_proxy_writer_dqueue (struct gcreq *gcreq)
/* delete proxy_writer, phase 2 */
struct proxy_writer *pwr = gcreq->arg;
struct nn_dqueue *dqueue = pwr->dqueue;
- DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer_dqueue(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pwr->e.guid));
+ ELOGDISC (pwr, "gc_delete_proxy_writer_dqueue(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pwr->e.guid));
nn_dqueue_enqueue_callback (dqueue, (void (*) (void *)) gc_delete_proxy_writer_dqueue_bubble_cb, gcreq);
}
static int gcreq_proxy_writer (struct proxy_writer *pwr)
{
- struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, gc_delete_proxy_writer_dqueue);
+ struct gcreq *gcreq = gcreq_new (pwr->e.gv->gcreq_queue, gc_delete_proxy_writer_dqueue);
gcreq->arg = pwr;
gcreq_enqueue (gcreq);
return 0;
@@ -4473,7 +4465,7 @@ static int gcreq_proxy_writer (struct proxy_writer *pwr)
static int gcreq_proxy_reader (struct proxy_reader *prd)
{
- struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, gc_delete_proxy_reader);
+ struct gcreq *gcreq = gcreq_new (prd->e.gv->gcreq_queue, gc_delete_proxy_reader);
gcreq->arg = prd;
gcreq_enqueue (gcreq);
return 0;
diff --git a/src/core/ddsi/src/q_ephash.c b/src/core/ddsi/src/q_ephash.c
index d02fcba..0a106be 100644
--- a/src/core/ddsi/src/q_ephash.c
+++ b/src/core/ddsi/src/q_ephash.c
@@ -69,18 +69,19 @@ static void gc_buckets_cb (struct gcreq *gcreq)
ddsrt_free (bs);
}
-static void gc_buckets (void *bs)
+static void gc_buckets (void *bs, void *varg)
{
- struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, gc_buckets_cb);
+ struct q_globals *gv = varg;
+ struct gcreq *gcreq = gcreq_new (gv->gcreq_queue, gc_buckets_cb);
gcreq->arg = bs;
gcreq_enqueue (gcreq);
}
-struct ephash *ephash_new (void)
+struct ephash *ephash_new (struct q_globals *gv)
{
struct ephash *ephash;
ephash = ddsrt_malloc (sizeof (*ephash));
- ephash->hash = ddsrt_chh_new (32, hash_entity_guid_wrapper, entity_guid_eq_wrapper, gc_buckets);
+ ephash->hash = ddsrt_chh_new (32, hash_entity_guid_wrapper, entity_guid_eq_wrapper, gc_buckets, gv);
if (ephash->hash == NULL) {
ddsrt_free (ephash);
return NULL;
@@ -96,194 +97,190 @@ void ephash_free (struct ephash *ephash)
ddsrt_free (ephash);
}
-static void ephash_guid_insert (struct entity_common *e)
+static void ephash_guid_insert (struct ephash *gh, struct entity_common *e)
{
int x;
- assert(gv.guid_hash);
- assert(gv.guid_hash->hash);
- x = ddsrt_chh_add (gv.guid_hash->hash, e);
+ x = ddsrt_chh_add (gh->hash, e);
(void)x;
assert (x);
}
-static void ephash_guid_remove (struct entity_common *e)
+static void ephash_guid_remove (struct ephash *gh, struct entity_common *e)
{
int x;
- assert(gv.guid_hash);
- assert(gv.guid_hash->hash);
- x = ddsrt_chh_remove (gv.guid_hash->hash, e);
+ x = ddsrt_chh_remove (gh->hash, e);
(void)x;
assert (x);
}
-void *ephash_lookup_guid_untyped (const struct nn_guid *guid)
+void *ephash_lookup_guid_untyped (const struct ephash *gh, const struct nn_guid *guid)
{
/* FIXME: could (now) require guid to be first in entity_common; entity_common already is first in entity */
struct entity_common e;
e.guid = *guid;
- return ddsrt_chh_lookup (gv.guid_hash->hash, &e);
+ assert (thread_is_awake ());
+ return ddsrt_chh_lookup (gh->hash, &e);
}
-static void *ephash_lookup_guid_int (const struct ephash *ephash, const struct nn_guid *guid, enum entity_kind kind)
+static void *ephash_lookup_guid_int (const struct ephash *gh, const struct nn_guid *guid, enum entity_kind kind)
{
struct entity_common *res;
- (void)ephash;
- if ((res = ephash_lookup_guid_untyped (guid)) != NULL && res->kind == kind)
+ if ((res = ephash_lookup_guid_untyped (gh, guid)) != NULL && res->kind == kind)
return res;
else
return NULL;
}
-void *ephash_lookup_guid (const struct nn_guid *guid, enum entity_kind kind)
+void *ephash_lookup_guid (const struct ephash *gh, const struct nn_guid *guid, enum entity_kind kind)
{
- return ephash_lookup_guid_int (NULL, guid, kind);
+ return ephash_lookup_guid_int (gh, guid, kind);
}
-void ephash_insert_participant_guid (struct participant *pp)
+void ephash_insert_participant_guid (struct ephash *gh, struct participant *pp)
{
- ephash_guid_insert (&pp->e);
+ ephash_guid_insert (gh, &pp->e);
}
-void ephash_insert_proxy_participant_guid (struct proxy_participant *proxypp)
+void ephash_insert_proxy_participant_guid (struct ephash *gh, struct proxy_participant *proxypp)
{
- ephash_guid_insert (&proxypp->e);
+ ephash_guid_insert (gh, &proxypp->e);
}
-void ephash_insert_writer_guid (struct writer *wr)
+void ephash_insert_writer_guid (struct ephash *gh, struct writer *wr)
{
- ephash_guid_insert (&wr->e);
+ ephash_guid_insert (gh, &wr->e);
}
-void ephash_insert_reader_guid (struct reader *rd)
+void ephash_insert_reader_guid (struct ephash *gh, struct reader *rd)
{
- ephash_guid_insert (&rd->e);
+ ephash_guid_insert (gh, &rd->e);
}
-void ephash_insert_proxy_writer_guid (struct proxy_writer *pwr)
+void ephash_insert_proxy_writer_guid (struct ephash *gh, struct proxy_writer *pwr)
{
- ephash_guid_insert (&pwr->e);
+ ephash_guid_insert (gh, &pwr->e);
}
-void ephash_insert_proxy_reader_guid (struct proxy_reader *prd)
+void ephash_insert_proxy_reader_guid (struct ephash *gh, struct proxy_reader *prd)
{
- ephash_guid_insert (&prd->e);
+ ephash_guid_insert (gh, &prd->e);
}
-void ephash_remove_participant_guid (struct participant *pp)
+void ephash_remove_participant_guid (struct ephash *gh, struct participant *pp)
{
- ephash_guid_remove (&pp->e);
+ ephash_guid_remove (gh, &pp->e);
}
-void ephash_remove_proxy_participant_guid (struct proxy_participant *proxypp)
+void ephash_remove_proxy_participant_guid (struct ephash *gh, struct proxy_participant *proxypp)
{
- ephash_guid_remove (&proxypp->e);
+ ephash_guid_remove (gh, &proxypp->e);
}
-void ephash_remove_writer_guid (struct writer *wr)
+void ephash_remove_writer_guid (struct ephash *gh, struct writer *wr)
{
- ephash_guid_remove (&wr->e);
+ ephash_guid_remove (gh, &wr->e);
}
-void ephash_remove_reader_guid (struct reader *rd)
+void ephash_remove_reader_guid (struct ephash *gh, struct reader *rd)
{
- ephash_guid_remove (&rd->e);
+ ephash_guid_remove (gh, &rd->e);
}
-void ephash_remove_proxy_writer_guid (struct proxy_writer *pwr)
+void ephash_remove_proxy_writer_guid (struct ephash *gh, struct proxy_writer *pwr)
{
- ephash_guid_remove (&pwr->e);
+ ephash_guid_remove (gh, &pwr->e);
}
-void ephash_remove_proxy_reader_guid (struct proxy_reader *prd)
+void ephash_remove_proxy_reader_guid (struct ephash *gh, struct proxy_reader *prd)
{
- ephash_guid_remove (&prd->e);
+ ephash_guid_remove (gh, &prd->e);
}
-struct participant *ephash_lookup_participant_guid (const struct nn_guid *guid)
+struct participant *ephash_lookup_participant_guid (const struct ephash *gh, const struct nn_guid *guid)
{
assert (guid->entityid.u == NN_ENTITYID_PARTICIPANT);
assert (offsetof (struct participant, e) == 0);
- return ephash_lookup_guid_int (gv.guid_hash, guid, EK_PARTICIPANT);
+ return ephash_lookup_guid_int (gh, guid, EK_PARTICIPANT);
}
-struct proxy_participant *ephash_lookup_proxy_participant_guid (const struct nn_guid *guid)
+struct proxy_participant *ephash_lookup_proxy_participant_guid (const struct ephash *gh, const struct nn_guid *guid)
{
assert (guid->entityid.u == NN_ENTITYID_PARTICIPANT);
assert (offsetof (struct proxy_participant, e) == 0);
- return ephash_lookup_guid_int (gv.guid_hash, guid, EK_PROXY_PARTICIPANT);
+ return ephash_lookup_guid_int (gh, guid, EK_PROXY_PARTICIPANT);
}
-struct writer *ephash_lookup_writer_guid (const struct nn_guid *guid)
+struct writer *ephash_lookup_writer_guid (const struct ephash *gh, const struct nn_guid *guid)
{
assert (is_writer_entityid (guid->entityid));
assert (offsetof (struct writer, e) == 0);
- return ephash_lookup_guid_int (gv.guid_hash, guid, EK_WRITER);
+ return ephash_lookup_guid_int (gh, guid, EK_WRITER);
}
-struct reader *ephash_lookup_reader_guid (const struct nn_guid *guid)
+struct reader *ephash_lookup_reader_guid (const struct ephash *gh, const struct nn_guid *guid)
{
assert (is_reader_entityid (guid->entityid));
assert (offsetof (struct reader, e) == 0);
- return ephash_lookup_guid_int (gv.guid_hash, guid, EK_READER);
+ return ephash_lookup_guid_int (gh, guid, EK_READER);
}
-struct proxy_writer *ephash_lookup_proxy_writer_guid (const struct nn_guid *guid)
+struct proxy_writer *ephash_lookup_proxy_writer_guid (const struct ephash *gh, const struct nn_guid *guid)
{
assert (is_writer_entityid (guid->entityid));
assert (offsetof (struct proxy_writer, e) == 0);
- return ephash_lookup_guid_int (gv.guid_hash, guid, EK_PROXY_WRITER);
+ return ephash_lookup_guid_int (gh, guid, EK_PROXY_WRITER);
}
-struct proxy_reader *ephash_lookup_proxy_reader_guid (const struct nn_guid *guid)
+struct proxy_reader *ephash_lookup_proxy_reader_guid (const struct ephash *gh, const struct nn_guid *guid)
{
assert (is_reader_entityid (guid->entityid));
assert (offsetof (struct proxy_reader, e) == 0);
- return ephash_lookup_guid_int (gv.guid_hash, guid, EK_PROXY_READER);
+ return ephash_lookup_guid_int (gh, guid, EK_PROXY_READER);
}
/* Enumeration */
-static void ephash_enum_init_int (struct ephash_enum *st, struct ephash *ephash, enum entity_kind kind)
+static void ephash_enum_init_int (struct ephash_enum *st, const struct ephash *gh, enum entity_kind kind)
{
st->kind = kind;
- st->cur = ddsrt_chh_iter_first (ephash->hash, &st->it);
+ st->cur = ddsrt_chh_iter_first (gh->hash, &st->it);
while (st->cur && st->cur->kind != st->kind)
st->cur = ddsrt_chh_iter_next (&st->it);
}
-void ephash_enum_init (struct ephash_enum *st, enum entity_kind kind)
+void ephash_enum_init (struct ephash_enum *st, const struct ephash *gh, enum entity_kind kind)
{
- ephash_enum_init_int(st, gv.guid_hash, kind);
+ ephash_enum_init_int(st, gh, kind);
}
-void ephash_enum_writer_init (struct ephash_enum_writer *st)
+void ephash_enum_writer_init (struct ephash_enum_writer *st, const struct ephash *gh)
{
- ephash_enum_init (&st->st, EK_WRITER);
+ ephash_enum_init (&st->st, gh, EK_WRITER);
}
-void ephash_enum_reader_init (struct ephash_enum_reader *st)
+void ephash_enum_reader_init (struct ephash_enum_reader *st, const struct ephash *gh)
{
- ephash_enum_init (&st->st, EK_READER);
+ ephash_enum_init (&st->st, gh, EK_READER);
}
-void ephash_enum_proxy_writer_init (struct ephash_enum_proxy_writer *st)
+void ephash_enum_proxy_writer_init (struct ephash_enum_proxy_writer *st, const struct ephash *gh)
{
- ephash_enum_init (&st->st, EK_PROXY_WRITER);
+ ephash_enum_init (&st->st, gh, EK_PROXY_WRITER);
}
-void ephash_enum_proxy_reader_init (struct ephash_enum_proxy_reader *st)
+void ephash_enum_proxy_reader_init (struct ephash_enum_proxy_reader *st, const struct ephash *gh)
{
- ephash_enum_init (&st->st, EK_PROXY_READER);
+ ephash_enum_init (&st->st, gh, EK_PROXY_READER);
}
-void ephash_enum_participant_init (struct ephash_enum_participant *st)
+void ephash_enum_participant_init (struct ephash_enum_participant *st, const struct ephash *gh)
{
- ephash_enum_init (&st->st, EK_PARTICIPANT);
+ ephash_enum_init (&st->st, gh, EK_PARTICIPANT);
}
-void ephash_enum_proxy_participant_init (struct ephash_enum_proxy_participant *st)
+void ephash_enum_proxy_participant_init (struct ephash_enum_proxy_participant *st, const struct ephash *gh)
{
- ephash_enum_init (&st->st, EK_PROXY_PARTICIPANT);
+ ephash_enum_init (&st->st, gh, EK_PROXY_PARTICIPANT);
}
void *ephash_enum_next (struct ephash_enum *st)
diff --git a/src/core/ddsi/src/q_freelist.c b/src/core/ddsi/src/q_freelist.c
index fd7aef7..9d1a1bc 100644
--- a/src/core/ddsi/src/q_freelist.c
+++ b/src/core/ddsi/src/q_freelist.c
@@ -140,9 +140,9 @@ void nn_freelist_fini (struct nn_freelist *fl, void (*xfree) (void *))
xfree (fl->inner[i].m->x[j]);
ddsrt_free(fl->inner[i].m);
}
-/* The compiler can't make sense of all these linked lists and doesn't
- * realize that the next pointers are always initialized here. */
-DDSRT_WARNING_MSVC_OFF(6001);
+ /* The compiler can't make sense of all these linked lists and doesn't
+ * realize that the next pointers are always initialized here. */
+ DDSRT_WARNING_MSVC_OFF(6001);
while ((m = fl->mlist) != NULL)
{
fl->mlist = m->next;
@@ -155,7 +155,7 @@ DDSRT_WARNING_MSVC_OFF(6001);
fl->emlist = m->next;
ddsrt_free (m);
}
-DDSRT_WARNING_MSVC_ON(6001);
+ DDSRT_WARNING_MSVC_ON(6001);
}
static ddsrt_atomic_uint32_t freelist_inner_idx_off = DDSRT_ATOMIC_UINT32_INIT(0);
diff --git a/src/core/ddsi/src/q_gc.c b/src/core/ddsi/src/q_gc.c
index 42fc0ef..054485c 100644
--- a/src/core/ddsi/src/q_gc.c
+++ b/src/core/ddsi/src/q_gc.c
@@ -25,6 +25,7 @@
#include "dds/ddsi/q_unused.h"
#include "dds/ddsi/q_lease.h"
#include "dds/ddsi/q_globals.h" /* for mattr, cattr */
+#include "dds/ddsi/q_receive.h" /* for trigger_receive_threads */
#include "dds/ddsi/q_rtps.h" /* for guid_hash */
@@ -35,35 +36,45 @@ struct gcreq_queue {
ddsrt_cond_t cond;
int terminate;
int32_t count;
+ struct q_globals *gv;
struct thread_state1 *ts;
};
-static void threads_vtime_gather_for_wait (unsigned *nivs, struct idx_vtime *ivs)
+static void threads_vtime_gather_for_wait (const struct q_globals *gv, unsigned *nivs, struct idx_vtime *ivs)
{
/* copy vtimes of threads, skipping those that are sleeping */
- unsigned i, j;
+ uint32_t i, j;
for (i = j = 0; i < thread_states.nthreads; i++)
{
- vtime_t vtime = thread_states.ts[i].vtime;
+ vtime_t vtime = ddsrt_atomic_ld32 (&thread_states.ts[i].vtime);
if (vtime_awake_p (vtime))
{
- ivs[j].idx = i;
- ivs[j].vtime = vtime;
- ++j;
+ ddsrt_atomic_fence_ldld ();
+ /* ts[i].gv is set before ts[i].vtime indicates the thread is awake, so if the thread hasn't
+ gone through another sleep/wake cycle since loading ts[i].vtime, ts[i].gv is correct; if
+ instead it has gone through another cycle since loading ts[i].vtime, then the thread will
+ be dropped from the live threads on the next check. So it won't ever wait with unknown
+ duration for progres of threads stuck in another domain */
+ if (gv == ddsrt_atomic_ldvoidp (&thread_states.ts[i].gv))
+ {
+ ivs[j].idx = i;
+ ivs[j].vtime = vtime;
+ ++j;
+ }
}
}
*nivs = j;
}
-static int threads_vtime_check (unsigned *nivs, struct idx_vtime *ivs)
+static int threads_vtime_check (uint32_t *nivs, struct idx_vtime *ivs)
{
/* check all threads in ts have made progress those that have are
removed from the set */
- unsigned i = 0;
+ uint32_t i = 0;
while (i < *nivs)
{
- unsigned thridx = ivs[i].idx;
- vtime_t vtime = thread_states.ts[thridx].vtime;
+ uint32_t thridx = ivs[i].idx;
+ vtime_t vtime = ddsrt_atomic_ld32 (&thread_states.ts[thridx].vtime);
assert (vtime_awake_p (ivs[i].vtime));
if (!vtime_gt (vtime, ivs[i].vtime))
++i;
@@ -81,14 +92,28 @@ static uint32_t gcreq_queue_thread (struct gcreq_queue *q)
{
struct thread_state1 * const ts1 = lookup_thread_state ();
nn_mtime_t next_thread_cputime = { 0 };
- dds_time_t shortsleep = 1 * T_MILLISECOND;
+ nn_mtime_t t_trigger_recv_threads = { 0 };
+ int64_t shortsleep = 1 * T_MILLISECOND;
int64_t delay = T_MILLISECOND; /* force evaluation after startup */
struct gcreq *gcreq = NULL;
int trace_shortsleep = 1;
ddsrt_mutex_lock (&q->lock);
while (!(q->terminate && q->count == 0))
{
- LOG_THREAD_CPUTIME (next_thread_cputime);
+ LOG_THREAD_CPUTIME (&q->gv->logconfig, next_thread_cputime);
+
+ /* While deaf, we need to make sure the receive thread wakes up
+ every now and then to try recreating sockets & rejoining multicast
+ groups. Do rate-limit it a bit. */
+ if (q->gv->deaf)
+ {
+ nn_mtime_t tnow_mt = now_mt ();
+ if (tnow_mt.v > t_trigger_recv_threads.v)
+ {
+ trigger_recv_threads (q->gv);
+ t_trigger_recv_threads.v = tnow_mt.v + DDS_MSECS (100);
+ }
+ }
/* If we are waiting for a gcreq to become ready, don't bother
looking at the queue; if we aren't, wait for a request to come
@@ -100,14 +125,15 @@ static uint32_t gcreq_queue_thread (struct gcreq_queue *q)
if (q->first == NULL)
{
/* FIXME: use absolute timeouts */
+ /* avoid overflows; ensure periodic wakeups of receive thread if deaf */
+ const int64_t maxdelay = q->gv->deaf ? DDS_MSECS (100) : DDS_SECS (1000);
dds_time_t to;
- if (delay >= 1000 * T_SECOND) {
- /* avoid overflow */
- to = DDS_SECS(1000);
+ if (delay >= maxdelay) {
+ to = maxdelay;
} else {
to = delay;
}
- ddsrt_cond_waitfor(&q->cond, &q->lock, to);
+ ddsrt_cond_waitfor (&q->cond, &q->lock, to);
}
if (q->first)
{
@@ -124,8 +150,8 @@ static uint32_t gcreq_queue_thread (struct gcreq_queue *q)
very little impact on its primary purpose and be less of a
burden on the system than having a separate thread or adding it
to the workload of the data handling threads. */
- thread_state_awake (ts1);
- delay = check_and_handle_lease_expiration (now_et ());
+ thread_state_awake_fixed_domain (ts1);
+ delay = check_and_handle_lease_expiration (q->gv, now_et ());
thread_state_asleep (ts1);
if (gcreq)
@@ -139,7 +165,7 @@ static uint32_t gcreq_queue_thread (struct gcreq_queue *q)
reasonable. */
if (trace_shortsleep)
{
- DDS_TRACE("gc %p: not yet, shortsleep\n", (void*)gcreq);
+ DDS_CTRACE (&q->gv->logconfig, "gc %p: not yet, shortsleep\n", (void *) gcreq);
trace_shortsleep = 0;
}
dds_sleepfor (shortsleep);
@@ -150,8 +176,8 @@ static uint32_t gcreq_queue_thread (struct gcreq_queue *q)
it; the callback is responsible for requeueing (if complex
multi-phase delete) or freeing the delete request. Reset
the current gcreq as this one obviously is no more. */
- DDS_TRACE("gc %p: deleting\n", (void*)gcreq);
- thread_state_awake (ts1);
+ DDS_CTRACE (&q->gv->logconfig, "gc %p: deleting\n", (void *) gcreq);
+ thread_state_awake_fixed_domain (ts1);
gcreq->cb (gcreq);
thread_state_asleep (ts1);
gcreq = NULL;
@@ -165,16 +191,17 @@ static uint32_t gcreq_queue_thread (struct gcreq_queue *q)
return 0;
}
-struct gcreq_queue *gcreq_queue_new (void)
+struct gcreq_queue *gcreq_queue_new (struct q_globals *gv)
{
struct gcreq_queue *q = ddsrt_malloc (sizeof (*q));
q->first = q->last = NULL;
q->terminate = 0;
q->count = 0;
+ q->gv = gv;
ddsrt_mutex_init (&q->lock);
ddsrt_cond_init (&q->cond);
- if (create_thread (&q->ts, "gc", (uint32_t (*) (void *)) gcreq_queue_thread, q) == DDS_RETCODE_OK)
+ if (create_thread (&q->ts, gv, "gc", (uint32_t (*) (void *)) gcreq_queue_thread, q) == DDS_RETCODE_OK)
return q;
else
{
@@ -229,7 +256,7 @@ struct gcreq *gcreq_new (struct gcreq_queue *q, gcreq_cb_t cb)
gcreq = ddsrt_malloc (offsetof (struct gcreq, vtimes) + thread_states.nthreads * sizeof (*gcreq->vtimes));
gcreq->cb = cb;
gcreq->queue = q;
- threads_vtime_gather_for_wait (&gcreq->nvtimes, gcreq->vtimes);
+ threads_vtime_gather_for_wait (q->gv, &gcreq->nvtimes, gcreq->vtimes);
ddsrt_mutex_lock (&q->lock);
q->count++;
ddsrt_mutex_unlock (&q->lock);
diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c
index 2c4601d..54601d9 100644
--- a/src/core/ddsi/src/q_init.c
+++ b/src/core/ddsi/src/q_init.c
@@ -36,7 +36,6 @@
#include "dds/ddsi/q_addrset.h"
#include "dds/ddsi/q_ddsi_discovery.h"
#include "dds/ddsi/q_radmin.h"
-#include "dds/ddsi/q_error.h"
#include "dds/ddsi/q_thread.h"
#include "dds/ddsi/q_ephash.h"
#include "dds/ddsi/q_lease.h"
@@ -50,6 +49,7 @@
#include "dds/ddsi/q_feature_check.h"
#include "dds/ddsi/q_debmon.h"
#include "dds/ddsi/q_init.h"
+#include "dds/ddsi/ddsi_threadmon.h"
#include "dds/ddsi/ddsi_tran.h"
#include "dds/ddsi/ddsi_udp.h"
@@ -62,22 +62,22 @@
#include "dds__whc.h"
#include "dds/ddsi/ddsi_iid.h"
-static void add_peer_addresses (struct addrset *as, const struct config_peer_listelem *list)
+static void add_peer_addresses (const struct q_globals *gv, struct addrset *as, const struct config_peer_listelem *list)
{
while (list)
{
- add_addresses_to_addrset (as, list->peer, -1, "add_peer_addresses", 0);
+ add_addresses_to_addrset (gv, as, list->peer, -1, "add_peer_addresses", 0);
list = list->next;
}
}
-static int make_uc_sockets (uint32_t * pdisc, uint32_t * pdata, int ppid)
+static int make_uc_sockets (struct q_globals *gv, uint32_t * pdisc, uint32_t * pdata, int ppid)
{
- if (config.many_sockets_mode == MSM_NO_UNICAST)
+ if (gv->config.many_sockets_mode == MSM_NO_UNICAST)
{
assert (ppid == PARTICIPANT_INDEX_NONE);
- *pdata = *pdisc = (uint32_t) (config.port_base + config.port_dg * config.domainId.value);
- if (config.allowMulticast)
+ *pdata = *pdisc = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId);
+ if (gv->config.allowMulticast)
{
/* FIXME: ugly hack - but we'll fix up after creating the multicast sockets */
return 0;
@@ -87,9 +87,9 @@ static int make_uc_sockets (uint32_t * pdisc, uint32_t * pdata, int ppid)
if (ppid >= 0)
{
/* FIXME: verify port numbers are in range instead of truncating them like this */
- int base = config.port_base + (config.port_dg * config.domainId.value) + (ppid * config.port_pg);
- *pdisc = (uint32_t) (base + config.port_d1);
- *pdata = (uint32_t) (base + config.port_d3);
+ uint32_t base = gv->config.port_base + (gv->config.port_dg * gv->config.domainId) + ((uint32_t) ppid * gv->config.port_pg);
+ *pdisc = base + gv->config.port_d1;
+ *pdata = base + gv->config.port_d3;
}
else if (ppid == PARTICIPANT_INDEX_NONE)
{
@@ -98,135 +98,135 @@ static int make_uc_sockets (uint32_t * pdisc, uint32_t * pdata, int ppid)
}
else
{
- DDS_FATAL("make_uc_sockets: invalid participant index %d\n", ppid);
+ DDS_FATAL ("make_uc_sockets: invalid participant index %d\n", ppid);
return -1;
}
- gv.disc_conn_uc = ddsi_factory_create_conn (gv.m_factory, *pdisc, NULL);
- if (gv.disc_conn_uc)
+ gv->disc_conn_uc = ddsi_factory_create_conn (gv->m_factory, *pdisc, NULL);
+ if (gv->disc_conn_uc)
{
/* Check not configured to use same unicast port for data and discovery */
if (*pdata != 0 && (*pdata != *pdisc))
{
- gv.data_conn_uc = ddsi_factory_create_conn (gv.m_factory, *pdata, NULL);
+ gv->data_conn_uc = ddsi_factory_create_conn (gv->m_factory, *pdata, NULL);
}
else
{
- gv.data_conn_uc = gv.disc_conn_uc;
+ gv->data_conn_uc = gv->disc_conn_uc;
}
- if (gv.data_conn_uc == NULL)
+ if (gv->data_conn_uc == NULL)
{
- ddsi_conn_free (gv.disc_conn_uc);
- gv.disc_conn_uc = NULL;
+ ddsi_conn_free (gv->disc_conn_uc);
+ gv->disc_conn_uc = NULL;
}
else
{
/* Set unicast locators */
- ddsi_conn_locator (gv.disc_conn_uc, &gv.loc_meta_uc);
- ddsi_conn_locator (gv.data_conn_uc, &gv.loc_default_uc);
+ ddsi_conn_locator (gv->disc_conn_uc, &gv->loc_meta_uc);
+ ddsi_conn_locator (gv->data_conn_uc, &gv->loc_default_uc);
}
}
- return gv.data_conn_uc ? 0 : -1;
+ return gv->data_conn_uc ? 0 : -1;
}
-static void make_builtin_endpoint_xqos (nn_xqos_t *q, const nn_xqos_t *template)
+static void make_builtin_endpoint_xqos (dds_qos_t *q, const dds_qos_t *template)
{
nn_xqos_copy (q, template);
- q->reliability.kind = NN_RELIABLE_RELIABILITY_QOS;
- q->reliability.max_blocking_time = nn_to_ddsi_duration (100 * T_MILLISECOND);
- q->durability.kind = NN_TRANSIENT_LOCAL_DURABILITY_QOS;
+ q->reliability.kind = DDS_RELIABILITY_RELIABLE;
+ q->reliability.max_blocking_time = 100 * T_MILLISECOND;
+ q->durability.kind = DDS_DURABILITY_TRANSIENT_LOCAL;
}
-static int set_recvips (void)
+static int set_recvips (struct q_globals *gv)
{
- gv.recvips = NULL;
+ gv->recvips = NULL;
- if (config.networkRecvAddressStrings)
+ if (gv->config.networkRecvAddressStrings)
{
- if (ddsrt_strcasecmp (config.networkRecvAddressStrings[0], "all") == 0)
+ if (ddsrt_strcasecmp (gv->config.networkRecvAddressStrings[0], "all") == 0)
{
#if DDSRT_HAVE_IPV6
- if (gv.ipv6_link_local)
+ if (gv->ipv6_link_local)
{
- DDS_WARNING("DDSI2EService/General/MulticastRecvNetworkInterfaceAddresses: using 'preferred' instead of 'all' because of IPv6 link-local address\n");
- gv.recvips_mode = RECVIPS_MODE_PREFERRED;
+ GVWARNING ("DDSI2EService/General/MulticastRecvNetworkInterfaceAddresses: using 'preferred' instead of 'all' because of IPv6 link-local address\n");
+ gv->recvips_mode = RECVIPS_MODE_PREFERRED;
}
else
#endif
{
- gv.recvips_mode = RECVIPS_MODE_ALL;
+ gv->recvips_mode = RECVIPS_MODE_ALL;
}
}
- else if (ddsrt_strcasecmp (config.networkRecvAddressStrings[0], "any") == 0)
+ else if (ddsrt_strcasecmp (gv->config.networkRecvAddressStrings[0], "any") == 0)
{
#if DDSRT_HAVE_IPV6
- if (gv.ipv6_link_local)
+ if (gv->ipv6_link_local)
{
- DDS_ERROR("DDSI2EService/General/MulticastRecvNetworkInterfaceAddresses: 'any' is unsupported in combination with an IPv6 link-local address\n");
+ GVERROR ("DDSI2EService/General/MulticastRecvNetworkInterfaceAddresses: 'any' is unsupported in combination with an IPv6 link-local address\n");
return -1;
}
#endif
- gv.recvips_mode = RECVIPS_MODE_ANY;
+ gv->recvips_mode = RECVIPS_MODE_ANY;
}
- else if (ddsrt_strcasecmp (config.networkRecvAddressStrings[0], "preferred") == 0)
+ else if (ddsrt_strcasecmp (gv->config.networkRecvAddressStrings[0], "preferred") == 0)
{
- gv.recvips_mode = RECVIPS_MODE_PREFERRED;
+ gv->recvips_mode = RECVIPS_MODE_PREFERRED;
}
- else if (ddsrt_strcasecmp (config.networkRecvAddressStrings[0], "none") == 0)
+ else if (ddsrt_strcasecmp (gv->config.networkRecvAddressStrings[0], "none") == 0)
{
- gv.recvips_mode = RECVIPS_MODE_NONE;
+ gv->recvips_mode = RECVIPS_MODE_NONE;
}
#if DDSRT_HAVE_IPV6
- else if (gv.ipv6_link_local)
+ else if (gv->ipv6_link_local)
{
/* If the configuration explicitly includes the selected
interface, treat it as "preferred", else as "none"; warn if
interfaces other than the selected one are included. */
int i, have_selected = 0, have_others = 0;
- for (i = 0; config.networkRecvAddressStrings[i] != NULL; i++)
+ for (i = 0; gv->config.networkRecvAddressStrings[i] != NULL; i++)
{
nn_locator_t loc;
- if (ddsi_locator_from_string(&loc, config.networkRecvAddressStrings[i]) != AFSR_OK)
+ if (ddsi_locator_from_string(gv, &loc, gv->config.networkRecvAddressStrings[i], gv->m_factory) != AFSR_OK)
{
- DDS_ERROR("%s: not a valid address in DDSI2EService/General/MulticastRecvNetworkInterfaceAddresses\n", config.networkRecvAddressStrings[i]);
+ GVERROR ("%s: not a valid address in DDSI2EService/General/MulticastRecvNetworkInterfaceAddresses\n", gv->config.networkRecvAddressStrings[i]);
return -1;
}
- if (compare_locators(&loc, &gv.interfaces[gv.selected_interface].loc) == 0)
+ if (compare_locators(&loc, &gv->interfaces[gv->selected_interface].loc) == 0)
have_selected = 1;
else
have_others = 1;
}
- gv.recvips_mode = have_selected ? RECVIPS_MODE_PREFERRED : RECVIPS_MODE_NONE;
+ gv->recvips_mode = have_selected ? RECVIPS_MODE_PREFERRED : RECVIPS_MODE_NONE;
if (have_others)
{
- DDS_WARNING("DDSI2EService/General/MulticastRecvNetworkInterfaceAddresses: using 'preferred' because of IPv6 local address\n");
+ GVWARNING ("DDSI2EService/General/MulticastRecvNetworkInterfaceAddresses: using 'preferred' because of IPv6 local address\n");
}
}
#endif
else
{
- struct config_in_addr_node **recvnode = &gv.recvips;
+ struct config_in_addr_node **recvnode = &gv->recvips;
int i, j;
- gv.recvips_mode = RECVIPS_MODE_SOME;
- for (i = 0; config.networkRecvAddressStrings[i] != NULL; i++)
+ gv->recvips_mode = RECVIPS_MODE_SOME;
+ for (i = 0; gv->config.networkRecvAddressStrings[i] != NULL; i++)
{
nn_locator_t loc;
- if (ddsi_locator_from_string(&loc, config.networkRecvAddressStrings[i]) != AFSR_OK)
+ if (ddsi_locator_from_string(gv, &loc, gv->config.networkRecvAddressStrings[i], gv->m_factory) != AFSR_OK)
{
- DDS_ERROR("%s: not a valid address in DDSI2EService/General/MulticastRecvNetworkInterfaceAddresses\n", config.networkRecvAddressStrings[i]);
+ GVERROR ("%s: not a valid address in DDSI2EService/General/MulticastRecvNetworkInterfaceAddresses\n", gv->config.networkRecvAddressStrings[i]);
return -1;
}
- for (j = 0; j < gv.n_interfaces; j++)
+ for (j = 0; j < gv->n_interfaces; j++)
{
- if (compare_locators(&loc, &gv.interfaces[j].loc) == 0)
+ if (compare_locators(&loc, &gv->interfaces[j].loc) == 0)
break;
}
- if (j == gv.n_interfaces)
+ if (j == gv->n_interfaces)
{
- DDS_ERROR("No interface bound to requested address '%s'\n", config.networkRecvAddressStrings[i]);
+ GVERROR ("No interface bound to requested address '%s'\n", gv->config.networkRecvAddressStrings[i]);
return -1;
}
*recvnode = ddsrt_malloc (sizeof (struct config_in_addr_node));
@@ -245,25 +245,25 @@ static int set_recvips (void)
* return -1 : ddsi is unicast, but 'mc' indicates it expects multicast
* return 0 : ddsi is multicast, but 'mc' indicates it expects unicast
* The return 0 means that the possible changes in 'loc' can be ignored. */
-static int string_to_default_locator (nn_locator_t *loc, const char *string, uint32_t port, int mc, const char *tag)
+static int string_to_default_locator (const struct q_globals *gv, nn_locator_t *loc, const char *string, uint32_t port, int mc, const char *tag)
{
if (strspn (string, " \t") == strlen (string))
{
/* string consisting of just spaces and/or tabs (that includes the empty string) is ignored */
return 0;
}
- switch (ddsi_locator_from_string(loc, string))
+ switch (ddsi_locator_from_string(gv, loc, string, gv->m_factory))
{
case AFSR_OK:
break;
case AFSR_INVALID:
- DDS_ERROR("%s: not a valid address (%s)\n", string, tag);
+ GVERROR ("%s: not a valid address (%s)\n", string, tag);
return -1;
case AFSR_UNKNOWN:
- DDS_ERROR("%s: address name resolution failure (%s)\n", string, tag);
+ GVERROR ("%s: address name resolution failure (%s)\n", string, tag);
return -1;
case AFSR_MISMATCH:
- DDS_ERROR("%s: invalid address kind (%s)\n", string, tag);
+ GVERROR ("%s: invalid address kind (%s)\n", string, tag);
return -1;
}
if (port != 0 && !is_unspec_locator(loc))
@@ -274,28 +274,28 @@ static int string_to_default_locator (nn_locator_t *loc, const char *string, uin
if (mc >= 0)
{
const char *rel = mc ? "must" : "may not";
- const int ismc = is_unspec_locator (loc) || ddsi_is_mcaddr (loc);
+ const int ismc = is_unspec_locator (loc) || ddsi_is_mcaddr (gv, loc);
if (mc != ismc)
{
- DDS_ERROR("%s: %s %s be the unspecified address or a multicast address\n", string, tag, rel);
+ GVERROR ("%s: %s %s be the unspecified address or a multicast address\n", string, tag, rel);
return -1;
}
}
return 1;
}
-static int set_spdp_address (void)
+static int set_spdp_address (struct q_globals *gv)
{
- const uint32_t port = (uint32_t) (config.port_base + config.port_dg * config.domainId.value + config.port_d0);
+ const uint32_t port = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d0);
int rc = 0;
/* FIXME: FIXME: FIXME: */
- gv.loc_spdp_mc.kind = NN_LOCATOR_KIND_INVALID;
- if (strcmp (config.spdpMulticastAddressString, "239.255.0.1") != 0)
+ gv->loc_spdp_mc.kind = NN_LOCATOR_KIND_INVALID;
+ if (strcmp (gv->config.spdpMulticastAddressString, "239.255.0.1") != 0)
{
- if ((rc = string_to_default_locator (&gv.loc_spdp_mc, config.spdpMulticastAddressString, port, 1, "SPDP address")) < 0)
+ if ((rc = string_to_default_locator (gv, &gv->loc_spdp_mc, gv->config.spdpMulticastAddressString, port, 1, "SPDP address")) < 0)
return rc;
}
- if (rc == 0 && gv.m_factory->m_connless) /* FIXME: connless the right one? */
+ if (rc == 0 && gv->m_factory->m_connless) /* FIXME: connless the right one? */
{
/* There isn't a standard IPv6 multicast group for DDSI. For
some reason, node-local multicast addresses seem to be
@@ -303,80 +303,80 @@ static int set_spdp_address (void)
instead do link-local. I suppose we could use the hop limit
to make it node-local. If other hosts reach us in some way,
we'll of course respond. */
- rc = string_to_default_locator (&gv.loc_spdp_mc, gv.m_factory->m_default_spdp_address, port, 1, "SPDP address");
+ rc = string_to_default_locator (gv, &gv->loc_spdp_mc, gv->m_factory->m_default_spdp_address, port, 1, "SPDP address");
assert (rc > 0);
}
#ifdef DDSI_INCLUDE_SSM
- if (gv.loc_spdp_mc.kind != NN_LOCATOR_KIND_INVALID && ddsi_is_ssm_mcaddr (&gv.loc_spdp_mc))
+ if (gv->loc_spdp_mc.kind != NN_LOCATOR_KIND_INVALID && ddsi_is_ssm_mcaddr (gv, &gv->loc_spdp_mc))
{
- DDS_ERROR("%s: SPDP address may not be an SSM address\n", config.spdpMulticastAddressString);
+ GVERROR ("%s: SPDP address may not be an SSM address\n", gv->config.spdpMulticastAddressString);
return -1;
}
#endif
return 0;
}
-static int set_default_mc_address (void)
+static int set_default_mc_address (struct q_globals *gv)
{
- const uint32_t port = (uint32_t) (config.port_base + config.port_dg * config.domainId.value + config.port_d2);
+ const uint32_t port = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d2);
int rc;
- if (!config.defaultMulticastAddressString)
- gv.loc_default_mc = gv.loc_spdp_mc;
- else if ((rc = string_to_default_locator (&gv.loc_default_mc, config.defaultMulticastAddressString, port, 1, "default multicast address")) < 0)
+ if (!gv->config.defaultMulticastAddressString)
+ gv->loc_default_mc = gv->loc_spdp_mc;
+ else if ((rc = string_to_default_locator (gv, &gv->loc_default_mc, gv->config.defaultMulticastAddressString, port, 1, "default multicast address")) < 0)
return rc;
else if (rc == 0)
- gv.loc_default_mc = gv.loc_spdp_mc;
- gv.loc_meta_mc = gv.loc_default_mc;
+ gv->loc_default_mc = gv->loc_spdp_mc;
+ gv->loc_meta_mc = gv->loc_default_mc;
return 0;
}
-static int set_ext_address_and_mask (void)
+static int set_ext_address_and_mask (struct q_globals *gv)
{
nn_locator_t loc;
int rc;
- if (!config.externalAddressString)
- gv.extloc = gv.ownloc;
- else if ((rc = string_to_default_locator (&loc, config.externalAddressString, 0, 0, "external address")) < 0)
+ if (!gv->config.externalAddressString)
+ gv->extloc = gv->ownloc;
+ else if ((rc = string_to_default_locator (gv, &loc, gv->config.externalAddressString, 0, 0, "external address")) < 0)
return rc;
else if (rc == 0) {
- DDS_WARNING("Ignoring ExternalNetworkAddress %s\n", config.externalAddressString);
- gv.extloc = gv.ownloc;
+ GVWARNING ("Ignoring ExternalNetworkAddress %s\n", gv->config.externalAddressString);
+ gv->extloc = gv->ownloc;
} else {
- gv.extloc = loc;
+ gv->extloc = loc;
}
- if (!config.externalMaskString || strcmp (config.externalMaskString, "0.0.0.0") == 0)
+ if (!gv->config.externalMaskString || strcmp (gv->config.externalMaskString, "0.0.0.0") == 0)
{
- memset(&gv.extmask.address, 0, sizeof(gv.extmask.address));
- gv.extmask.kind = NN_LOCATOR_KIND_INVALID;
- gv.extmask.port = NN_LOCATOR_PORT_INVALID;
+ memset(&gv->extmask.address, 0, sizeof(gv->extmask.address));
+ gv->extmask.kind = NN_LOCATOR_KIND_INVALID;
+ gv->extmask.port = NN_LOCATOR_PORT_INVALID;
}
- else if (config.transport_selector != TRANS_UDP)
+ else if (gv->config.transport_selector != TRANS_UDP)
{
- DDS_ERROR("external network masks only supported in IPv4 mode\n");
+ GVERROR ("external network masks only supported in IPv4 mode\n");
return -1;
}
else
{
- if ((rc = string_to_default_locator (&gv.extmask, config.externalMaskString, 0, -1, "external mask")) < 0)
+ if ((rc = string_to_default_locator (gv, &gv->extmask, gv->config.externalMaskString, 0, -1, "external mask")) < 0)
return rc;
}
return 0;
}
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
-static int known_channel_p (const char *name)
+static int known_channel_p (const struct q_globals *gv, const char *name)
{
const struct config_channel_listelem *c;
- for (c = config.channels; c; c = c->next)
+ for (c = gv->config.channels; c; c = c->next)
if (strcmp (name, c->name) == 0)
return 1;
return 0;
}
#endif
-static int check_thread_properties (void)
+static int check_thread_properties (const struct q_globals *gv)
{
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
static const char *fixed[] = { "recv", "tev", "gc", "lease", "dq.builtins", "debmon", NULL };
@@ -386,7 +386,7 @@ static int check_thread_properties (void)
#endif
const struct config_thread_properties_listelem *e;
int ok = 1, i;
- for (e = config.thread_properties; e; e = e->next)
+ for (e = gv->config.thread_properties; e; e = e->next)
{
for (i = 0; fixed[i]; i++)
if (strcmp (fixed[i], e->name) == 0)
@@ -399,16 +399,16 @@ static int check_thread_properties (void)
for (i = 0; chanprefix[i]; i++)
{
size_t n = strlen (chanprefix[i]);
- if (strncmp (chanprefix[i], e->name, n) == 0 && known_channel_p (e->name + n))
+ if (strncmp (chanprefix[i], e->name, n) == 0 && known_channel_p (gv, e->name + n))
break;
}
if (chanprefix[i] == NULL)
{
- DDS_ERROR("config: DDSI2Service/Threads/Thread[@name=\"%s\"]: unknown thread\n", e->name);
+ DDS_ILOG (DDS_LC_ERROR, gv->config.domainId, "config: DDSI2Service/Threads/Thread[@name=\"%s\"]: unknown thread\n", e->name);
ok = 0;
}
#else
- DDS_ERROR("config: DDSI2Service/Threads/Thread[@name=\"%s\"]: unknown thread\n", e->name);
+ DDS_ILOG (DDS_LC_ERROR, gv->config.domainId, "config: DDSI2Service/Threads/Thread[@name=\"%s\"]: unknown thread\n", e->name);
ok = 0;
#endif /* DDSI_INCLUDE_NETWORK_CHANNELS */
}
@@ -416,45 +416,43 @@ static int check_thread_properties (void)
return ok;
}
-DDSRT_WARNING_MSVC_OFF(4996);
-int rtps_config_open (void)
+int rtps_config_open_trace (struct q_globals *gv)
{
- int status;
+ DDSRT_WARNING_MSVC_OFF(4996);
+ int status;
- if (config.tracingOutputFileName == NULL || *config.tracingOutputFileName == 0 || config.enabled_logcats == 0)
- {
- config.enabled_logcats = 0;
- config.tracingOutputFile = NULL;
- status = 1;
- }
- else if (ddsrt_strcasecmp (config.tracingOutputFileName, "stdout") == 0)
- {
- config.tracingOutputFile = stdout;
- status = 1;
- }
- else if (ddsrt_strcasecmp (config.tracingOutputFileName, "stderr") == 0)
- {
- config.tracingOutputFile = stderr;
- status = 1;
- }
- else if ((config.tracingOutputFile = fopen (config.tracingOutputFileName, config.tracingAppendToFile ? "a" : "w")) == NULL)
- {
- DDS_ERROR("%s: cannot open for writing\n", config.tracingOutputFileName);
- status = 0;
- }
- else
- {
- status = 1;
- }
+ if (gv->config.tracefile == NULL || *gv->config.tracefile == 0 || gv->config.tracemask == 0)
+ {
+ gv->config.tracemask = 0;
+ gv->config.tracefp = NULL;
+ status = 1;
+ }
+ else if (ddsrt_strcasecmp (gv->config.tracefile, "stdout") == 0)
+ {
+ gv->config.tracefp = stdout;
+ status = 1;
+ }
+ else if (ddsrt_strcasecmp (gv->config.tracefile, "stderr") == 0)
+ {
+ gv->config.tracefp = stderr;
+ status = 1;
+ }
+ else if ((gv->config.tracefp = fopen (gv->config.tracefile, gv->config.tracingAppendToFile ? "a" : "w")) == NULL)
+ {
+ DDS_ILOG (DDS_LC_ERROR, gv->config.domainId, "%s: cannot open for writing\n", gv->config.tracefile);
+ status = 0;
+ }
+ else
+ {
+ status = 1;
+ }
- dds_set_log_mask(config.enabled_logcats);
- dds_set_trace_file(config.tracingOutputFile);
-
- return status;
+ dds_log_cfg_init (&gv->logconfig, gv->config.domainId, gv->config.tracemask, stderr, gv->config.tracefp);
+ return status;
+ DDSRT_WARNING_MSVC_ON(4996);
}
-DDSRT_WARNING_MSVC_ON(4996);
-int rtps_config_prep (struct cfgst *cfgst)
+int rtps_config_prep (struct q_globals *gv, struct cfgst *cfgst)
{
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
unsigned num_channels = 0;
@@ -462,17 +460,17 @@ int rtps_config_prep (struct cfgst *cfgst)
#endif
/* retry_on_reject_duration default is dependent on late_ack_mode and responsiveness timeout, so fix up */
- if (config.whc_init_highwater_mark.isdefault)
- config.whc_init_highwater_mark.value = config.whc_lowwater_mark;
- if (config.whc_highwater_mark < config.whc_lowwater_mark ||
- config.whc_init_highwater_mark.value < config.whc_lowwater_mark ||
- config.whc_init_highwater_mark.value > config.whc_highwater_mark)
+ if (gv->config.whc_init_highwater_mark.isdefault)
+ gv->config.whc_init_highwater_mark.value = gv->config.whc_lowwater_mark;
+ if (gv->config.whc_highwater_mark < gv->config.whc_lowwater_mark ||
+ gv->config.whc_init_highwater_mark.value < gv->config.whc_lowwater_mark ||
+ gv->config.whc_init_highwater_mark.value > gv->config.whc_highwater_mark)
{
- DDS_ERROR("Invalid watermark settings\n");
+ DDS_ILOG (DDS_LC_ERROR, gv->config.domainId, "Invalid watermark settings\n");
goto err_config_late_error;
}
- if (config.besmode == BESMODE_MINIMAL && config.many_sockets_mode == MSM_MANY_UNICAST)
+ if (gv->config.besmode == BESMODE_MINIMAL && gv->config.many_sockets_mode == MSM_MANY_UNICAST)
{
/* These two are incompatible because minimal bes mode can result
in implicitly creating proxy participants inheriting the
@@ -480,41 +478,40 @@ int rtps_config_prep (struct cfgst *cfgst)
inherited by readers/writers), but in many sockets mode each
participant has its own socket, and therefore unique address
set */
- DDS_ERROR ("Minimal built-in endpoint set mode and ManySocketsMode are incompatible\n");
+ DDS_ILOG (DDS_LC_ERROR, gv->config.domainId, "Minimal built-in endpoint set mode and ManySocketsMode are incompatible\n");
goto err_config_late_error;
}
/* Dependencies between default values is not handled
- automatically by the config processing (yet) */
- if (config.many_sockets_mode == MSM_MANY_UNICAST)
+ automatically by the gv->config processing (yet) */
+ if (gv->config.many_sockets_mode == MSM_MANY_UNICAST)
{
- if (config.max_participants == 0)
- config.max_participants = 100;
+ if (gv->config.max_participants == 0)
+ gv->config.max_participants = 100;
}
- if (config.max_queued_rexmit_bytes == 0)
+ if (gv->config.max_queued_rexmit_bytes == 0)
{
#ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING
- if (config.auxiliary_bandwidth_limit == 0)
- config.max_queued_rexmit_bytes = 2147483647u;
+ if (gv->config.auxiliary_bandwidth_limit == 0)
+ gv->config.max_queued_rexmit_bytes = 2147483647u;
else
{
- double max = (double) config.auxiliary_bandwidth_limit * ((double) config.nack_delay / 1e9);
+ double max = (double) gv->config.auxiliary_bandwidth_limit * ((double) gv->config.nack_delay / 1e9);
if (max < 0)
{
- DDS_ERROR ("AuxiliaryBandwidthLimit * NackDelay = %g bytes is insane\n", max);
+ DDS_ILOG (DDS_LC_ERROR, gv->config.domainId.value, "AuxiliaryBandwidthLimit * NackDelay = %g bytes is insane\n", max);
goto err_config_late_error;
}
- config.max_queued_rexmit_bytes = max > 2147483647.0 ? 2147483647u : (unsigned) max;
+ gv->config.max_queued_rexmit_bytes = max > 2147483647.0 ? 2147483647u : (unsigned) max;
}
#else
- config.max_queued_rexmit_bytes = 2147483647u;
+ gv->config.max_queued_rexmit_bytes = 2147483647u;
#endif /* DDSI_INCLUDE_BANDWIDTH_LIMITING */
}
/* Verify thread properties refer to defined threads */
- if (!check_thread_properties ())
+ if (!check_thread_properties (gv))
{
- DDS_TRACE ("Could not initialise configuration\n");
goto err_config_late_error;
}
@@ -524,7 +521,7 @@ int rtps_config_prep (struct cfgst *cfgst)
determine the correct number of threads. Also fix fields if
at default, and check for some known IPv4/IPv6
"compatibility" issues */
- struct config_channel_listelem *chptr = config.channels;
+ struct config_channel_listelem *chptr = gv->config.channels;
int error = 0;
while (chptr)
@@ -536,9 +533,9 @@ int rtps_config_prep (struct cfgst *cfgst)
num_channels++;
num_channel_threads += 2; /* xmit and dqueue */
- if (config.transport_selector != TRANS_UDP && chptr->diffserv_field != 0)
+ if (gv->config.transport_selector != TRANS_UDP && chptr->diffserv_field != 0)
{
- DDS_ERROR ("channel %s specifies IPv4 DiffServ settings which is incompatible with IPv6 use\n", chptr->name);
+ DDS_ILOG (DDS_LC_ERROR, gv->config.domainId.value, "channel %s specifies IPv4 DiffServ settings which is incompatible with IPv6 use\n", chptr->name);
error = 1;
}
@@ -557,11 +554,9 @@ int rtps_config_prep (struct cfgst *cfgst)
}
#endif /* DDSI_INCLUDE_NETWORK_CHANNELS */
- /* Open tracing file after all possible config errors have been
- printed */
- if (! rtps_config_open ())
+ /* Open tracing file after all possible config errors have been printed */
+ if (! rtps_config_open_trace (gv))
{
- DDS_TRACE ("Could not initialise configuration\n");
goto err_config_late_error;
}
@@ -570,22 +565,25 @@ int rtps_config_prep (struct cfgst *cfgst)
lease, gc, debmon; once thread state admin has been inited, upgrade the
main thread one participating in the thread tracking stuff as
if it had been created using create_thread(). */
-
+#if 0 /* FIXME: threads are per-process, not per-domain */
{
/* Temporary: thread states for each application thread is managed using thread_states structure
*/
#define USER_MAX_THREADS 50
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
- const unsigned max_threads = 9 + USER_MAX_THREADS + num_channel_threads + config.ddsi2direct_max_threads;
+ const unsigned max_threads = 9 + USER_MAX_THREADS + num_channel_threads + gv->config.ddsi2direct_max_threads;
#else
- const unsigned max_threads = 11 + USER_MAX_THREADS + config.ddsi2direct_max_threads;
+ const unsigned max_threads = 11 + USER_MAX_THREADS + gv->config.ddsi2direct_max_threads;
#endif
thread_states_init (max_threads);
}
+#endif
- /* Now the per-thread-log-buffers are set up, so print the configuration */
- config_print_cfgst (cfgst);
+ /* Now the per-thread-log-buffers are set up, so print the configuration. After this there
+ is no value to the source information for the various configuration elements, so free those. */
+ config_print_cfgst (cfgst, &gv->logconfig);
+ config_free_source_info (cfgst);
return 0;
err_config_late_error:
@@ -593,6 +591,7 @@ err_config_late_error:
}
struct joinleave_spdp_defmcip_helper_arg {
+ struct q_globals *gv;
int errcount;
int dojoin;
};
@@ -600,44 +599,47 @@ struct joinleave_spdp_defmcip_helper_arg {
static void joinleave_spdp_defmcip_helper (const nn_locator_t *loc, void *varg)
{
struct joinleave_spdp_defmcip_helper_arg *arg = varg;
- if (!ddsi_is_mcaddr (loc))
+ if (!ddsi_is_mcaddr (arg->gv, loc))
return;
#ifdef DDSI_INCLUDE_SSM
/* Can't join SSM until we actually have a source */
- if (ddsi_is_ssm_mcaddr (loc))
+ if (ddsi_is_ssm_mcaddr (arg->gv, loc))
return;
#endif
if (arg->dojoin) {
- if (ddsi_join_mc (gv.disc_conn_mc, NULL, loc) < 0 || ddsi_join_mc (gv.data_conn_mc, NULL, loc) < 0)
+ if (ddsi_join_mc (arg->gv, arg->gv->mship, arg->gv->disc_conn_mc, NULL, loc) < 0 ||
+ ddsi_join_mc (arg->gv, arg->gv->mship, arg->gv->data_conn_mc, NULL, loc) < 0)
arg->errcount++;
} else {
- if (ddsi_leave_mc (gv.disc_conn_mc, NULL, loc) < 0 || ddsi_leave_mc (gv.data_conn_mc, NULL, loc) < 0)
+ if (ddsi_leave_mc (arg->gv, arg->gv->mship, arg->gv->disc_conn_mc, NULL, loc) < 0 ||
+ ddsi_leave_mc (arg->gv, arg->gv->mship, arg->gv->data_conn_mc, NULL, loc) < 0)
arg->errcount++;
}
}
-int joinleave_spdp_defmcip (int dojoin)
+int joinleave_spdp_defmcip (struct q_globals *gv, int dojoin)
{
/* Addrset provides an easy way to filter out duplicates */
struct joinleave_spdp_defmcip_helper_arg arg;
struct addrset *as = new_addrset ();
+ arg.gv = gv;
arg.errcount = 0;
arg.dojoin = dojoin;
- if (config.allowMulticast & AMC_SPDP)
- add_to_addrset (as, &gv.loc_spdp_mc);
- if (config.allowMulticast & ~AMC_SPDP)
- add_to_addrset (as, &gv.loc_default_mc);
+ if (gv->config.allowMulticast & AMC_SPDP)
+ add_to_addrset (gv, as, &gv->loc_spdp_mc);
+ if (gv->config.allowMulticast & ~AMC_SPDP)
+ add_to_addrset (gv, as, &gv->loc_default_mc);
addrset_forall (as, joinleave_spdp_defmcip_helper, &arg);
unref_addrset (as);
if (arg.errcount)
{
- DDS_ERROR("rtps_init: failed to join multicast groups for domain %"PRId32" participant %d\n", config.domainId.value, config.participantIndex);
+ GVERROR ("rtps_init: failed to join multicast groups for domain %"PRIu32" participant %d\n", gv->config.domainId, gv->config.participantIndex);
return -1;
}
return 0;
}
-int create_multicast_sockets(void)
+int create_multicast_sockets (struct q_globals *gv)
{
ddsi_tran_qos_t qos = ddsi_tran_create_qos ();
ddsi_tran_conn_t disc, data;
@@ -645,26 +647,26 @@ int create_multicast_sockets(void)
qos->m_multicast = 1;
/* FIXME: should check for overflow */
- port = (uint32_t) (config.port_base + config.port_dg * config.domainId.value + config.port_d0);
- if ((disc = ddsi_factory_create_conn (gv.m_factory, port, qos)) == NULL)
+ port = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d0);
+ if ((disc = ddsi_factory_create_conn (gv->m_factory, port, qos)) == NULL)
goto err_disc;
- if (config.many_sockets_mode == MSM_NO_UNICAST)
+ if (gv->config.many_sockets_mode == MSM_NO_UNICAST)
{
/* FIXME: not quite logical to tie this to "no unicast" */
data = disc;
}
else
{
- port = (uint32_t) (config.port_base + config.port_dg * config.domainId.value + config.port_d2);
- if ((data = ddsi_factory_create_conn (gv.m_factory, port, qos)) == NULL)
+ port = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d2);
+ if ((data = ddsi_factory_create_conn (gv->m_factory, port, qos)) == NULL)
goto err_data;
}
ddsi_tran_free_qos (qos);
- gv.disc_conn_mc = disc;
- gv.data_conn_mc = data;
- DDS_TRACE("Multicast Ports: discovery %"PRIu32" data %"PRIu32" \n",
- ddsi_conn_port (gv.disc_conn_mc), ddsi_conn_port (gv.data_conn_mc));
+ gv->disc_conn_mc = disc;
+ gv->data_conn_mc = data;
+ GVTRACE ("Multicast Ports: discovery %"PRIu32" data %"PRIu32" \n",
+ ddsi_conn_port (gv->disc_conn_mc), ddsi_conn_port (gv->data_conn_mc));
return 1;
err_data:
@@ -674,53 +676,54 @@ err_disc:
return 0;
}
-static void rtps_term_prep (void)
+static void rtps_term_prep (struct q_globals *gv)
{
/* Stop all I/O */
- ddsrt_mutex_lock (&gv.lock);
- if (gv.rtps_keepgoing)
+ ddsrt_mutex_lock (&gv->lock);
+ if (ddsrt_atomic_ld32 (&gv->rtps_keepgoing))
{
- gv.rtps_keepgoing = 0; /* so threads will stop once they get round to checking */
+ ddsrt_atomic_st32 (&gv->rtps_keepgoing, 0); /* so threads will stop once they get round to checking */
ddsrt_atomic_fence ();
/* can't wake up throttle_writer, currently, but it'll check every few seconds */
- trigger_recv_threads ();
+ trigger_recv_threads (gv);
}
- ddsrt_mutex_unlock (&gv.lock);
+ ddsrt_mutex_unlock (&gv->lock);
}
struct wait_for_receive_threads_helper_arg {
+ struct q_globals *gv;
unsigned count;
};
static void wait_for_receive_threads_helper (struct xevent *xev, void *varg, nn_mtime_t tnow)
{
struct wait_for_receive_threads_helper_arg * const arg = varg;
- if (arg->count++ == config.recv_thread_stop_maxretries)
+ if (arg->count++ == arg->gv->config.recv_thread_stop_maxretries)
abort ();
- trigger_recv_threads ();
+ trigger_recv_threads (arg->gv);
resched_xevent_if_earlier (xev, add_duration_to_mtime (tnow, T_SECOND));
}
-static void wait_for_receive_threads (void)
+static void wait_for_receive_threads (struct q_globals *gv)
{
struct xevent *trigev;
- unsigned i;
struct wait_for_receive_threads_helper_arg cbarg;
+ cbarg.gv = gv;
cbarg.count = 0;
- if ((trigev = qxev_callback (add_duration_to_mtime (now_mt (), T_SECOND), wait_for_receive_threads_helper, &cbarg)) == NULL)
+ if ((trigev = qxev_callback (gv->xevents, add_duration_to_mtime (now_mt (), T_SECOND), wait_for_receive_threads_helper, &cbarg)) == NULL)
{
/* retrying is to deal a packet geting lost because the socket buffer is full or because the
macOS firewall (and perhaps others) likes to ask if the process is allowed to receive data,
dropping the packets until the user approves. */
- DDS_WARNING("wait_for_receive_threads: failed to schedule periodic triggering of the receive threads to deal with packet loss\n");
+ GVWARNING ("wait_for_receive_threads: failed to schedule periodic triggering of the receive threads to deal with packet loss\n");
}
- for (i = 0; i < gv.n_recv_threads; i++)
+ for (uint32_t i = 0; i < gv->n_recv_threads; i++)
{
- if (gv.recv_threads[i].ts)
+ if (gv->recv_threads[i].ts)
{
- join_thread (gv.recv_threads[i].ts);
+ join_thread (gv->recv_threads[i].ts);
/* setting .ts to NULL helps in sanity checking */
- gv.recv_threads[i].ts = NULL;
+ gv->recv_threads[i].ts = NULL;
}
}
if (trigev)
@@ -729,7 +732,7 @@ static void wait_for_receive_threads (void)
}
}
-static struct ddsi_sertopic *make_special_topic (uint16_t enc_id, const struct ddsi_serdata_ops *ops)
+static struct ddsi_sertopic *make_special_topic (struct serdatapool *serpool, uint16_t enc_id, const struct ddsi_serdata_ops *ops)
{
/* FIXME: two things (at least)
- it claims there is a key, but the underlying type description is missing
@@ -741,91 +744,88 @@ static struct ddsi_sertopic *make_special_topic (uint16_t enc_id, const struct d
(kinda natural if they stop being "default" ones) */
struct ddsi_sertopic_default *st = ddsrt_malloc (sizeof (*st));
memset (st, 0, sizeof (*st));
- ddsrt_atomic_st32 (&st->c.refc, 1);
- st->c.ops = &ddsi_sertopic_ops_default;
- st->c.serdata_ops = ops;
- st->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (st->c.serdata_ops);
- st->c.iid = ddsi_iid_gen ();
+ ddsi_sertopic_init_anon (&st->c, &ddsi_sertopic_ops_default, ops, false);
st->native_encoding_identifier = enc_id;
+ st->serpool = serpool;
st->nkeys = 1;
- return (struct ddsi_sertopic *)st;
+ return (struct ddsi_sertopic *) st;
}
-static void make_special_topics (void)
+static void make_special_topics (struct q_globals *gv)
{
- gv.plist_topic = make_special_topic (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? PL_CDR_LE : PL_CDR_BE, &ddsi_serdata_ops_plist);
- gv.rawcdr_topic = make_special_topic (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE, &ddsi_serdata_ops_rawcdr);
+ gv->plist_topic = make_special_topic (gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? PL_CDR_LE : PL_CDR_BE, &ddsi_serdata_ops_plist);
+ gv->rawcdr_topic = make_special_topic (gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE, &ddsi_serdata_ops_rawcdr);
}
-static void free_special_topics (void)
+static void free_special_topics (struct q_globals *gv)
{
- ddsi_sertopic_unref (gv.plist_topic);
- ddsi_sertopic_unref (gv.rawcdr_topic);
+ ddsi_sertopic_unref (gv->plist_topic);
+ ddsi_sertopic_unref (gv->rawcdr_topic);
}
-static int setup_and_start_recv_threads (void)
+static int setup_and_start_recv_threads (struct q_globals *gv)
{
- unsigned i;
- for (i = 0; i < MAX_RECV_THREADS; i++)
+ for (uint32_t i = 0; i < MAX_RECV_THREADS; i++)
{
- gv.recv_threads[i].ts = NULL;
- gv.recv_threads[i].arg.mode = RTM_SINGLE;
- gv.recv_threads[i].arg.rbpool = NULL;
- gv.recv_threads[i].arg.u.single.loc = NULL;
- gv.recv_threads[i].arg.u.single.conn = NULL;
+ gv->recv_threads[i].ts = NULL;
+ gv->recv_threads[i].arg.mode = RTM_SINGLE;
+ gv->recv_threads[i].arg.rbpool = NULL;
+ gv->recv_threads[i].arg.gv = gv;
+ gv->recv_threads[i].arg.u.single.loc = NULL;
+ gv->recv_threads[i].arg.u.single.conn = NULL;
}
/* First thread always uses a waitset and gobbles up all sockets not handled by dedicated threads - FIXME: MSM_NO_UNICAST mode with UDP probably doesn't even need this one to use a waitset */
- gv.n_recv_threads = 1;
- gv.recv_threads[0].name = "recv";
- gv.recv_threads[0].arg.mode = RTM_MANY;
- if (gv.m_factory->m_connless && config.many_sockets_mode != MSM_NO_UNICAST && config.multiple_recv_threads)
+ gv->n_recv_threads = 1;
+ gv->recv_threads[0].name = "recv";
+ gv->recv_threads[0].arg.mode = RTM_MANY;
+ if (gv->m_factory->m_connless && gv->config.many_sockets_mode != MSM_NO_UNICAST && gv->config.multiple_recv_threads)
{
- if (ddsi_is_mcaddr (&gv.loc_default_mc) && !ddsi_is_ssm_mcaddr (&gv.loc_default_mc) && (config.allowMulticast & AMC_ASM))
+ if (ddsi_is_mcaddr (gv, &gv->loc_default_mc) && !ddsi_is_ssm_mcaddr (gv, &gv->loc_default_mc) && (gv->config.allowMulticast & AMC_ASM))
{
/* Multicast enabled, but it isn't an SSM address => handle data multicasts on a separate thread (the trouble with SSM addresses is that we only join matching writers, which our own sockets typically would not be) */
- gv.recv_threads[gv.n_recv_threads].name = "recvMC";
- gv.recv_threads[gv.n_recv_threads].arg.mode = RTM_SINGLE;
- gv.recv_threads[gv.n_recv_threads].arg.u.single.conn = gv.data_conn_mc;
- gv.recv_threads[gv.n_recv_threads].arg.u.single.loc = &gv.loc_default_mc;
- ddsi_conn_disable_multiplexing (gv.data_conn_mc);
- gv.n_recv_threads++;
+ gv->recv_threads[gv->n_recv_threads].name = "recvMC";
+ gv->recv_threads[gv->n_recv_threads].arg.mode = RTM_SINGLE;
+ gv->recv_threads[gv->n_recv_threads].arg.u.single.conn = gv->data_conn_mc;
+ gv->recv_threads[gv->n_recv_threads].arg.u.single.loc = &gv->loc_default_mc;
+ ddsi_conn_disable_multiplexing (gv->data_conn_mc);
+ gv->n_recv_threads++;
}
- if (config.many_sockets_mode == MSM_SINGLE_UNICAST)
+ if (gv->config.many_sockets_mode == MSM_SINGLE_UNICAST)
{
/* No per-participant sockets => handle data unicasts on a separate thread as well */
- gv.recv_threads[gv.n_recv_threads].name = "recvUC";
- gv.recv_threads[gv.n_recv_threads].arg.mode = RTM_SINGLE;
- gv.recv_threads[gv.n_recv_threads].arg.u.single.conn = gv.data_conn_uc;
- gv.recv_threads[gv.n_recv_threads].arg.u.single.loc = &gv.loc_default_uc;
- ddsi_conn_disable_multiplexing (gv.data_conn_uc);
- gv.n_recv_threads++;
+ gv->recv_threads[gv->n_recv_threads].name = "recvUC";
+ gv->recv_threads[gv->n_recv_threads].arg.mode = RTM_SINGLE;
+ gv->recv_threads[gv->n_recv_threads].arg.u.single.conn = gv->data_conn_uc;
+ gv->recv_threads[gv->n_recv_threads].arg.u.single.loc = &gv->loc_default_uc;
+ ddsi_conn_disable_multiplexing (gv->data_conn_uc);
+ gv->n_recv_threads++;
}
}
- assert (gv.n_recv_threads <= MAX_RECV_THREADS);
+ assert (gv->n_recv_threads <= MAX_RECV_THREADS);
/* For each thread, create rbufpool and waitset if needed, then start it */
- for (i = 0; i < gv.n_recv_threads; i++)
+ for (uint32_t i = 0; i < gv->n_recv_threads; i++)
{
/* We create the rbufpool for the receive thread, and so we'll
become the initial owner thread. The receive thread will change
it before it does anything with it. */
- if ((gv.recv_threads[i].arg.rbpool = nn_rbufpool_new (config.rbuf_size, config.rmsg_chunk_size)) == NULL)
+ if ((gv->recv_threads[i].arg.rbpool = nn_rbufpool_new (&gv->logconfig, gv->config.rbuf_size, gv->config.rmsg_chunk_size)) == NULL)
{
- DDS_ERROR("rtps_init: can't allocate receive buffer pool for thread %s\n", gv.recv_threads[i].name);
+ GVERROR ("rtps_init: can't allocate receive buffer pool for thread %s\n", gv->recv_threads[i].name);
goto fail;
}
- if (gv.recv_threads[i].arg.mode == RTM_MANY)
+ if (gv->recv_threads[i].arg.mode == RTM_MANY)
{
- if ((gv.recv_threads[i].arg.u.many.ws = os_sockWaitsetNew ()) == NULL)
+ if ((gv->recv_threads[i].arg.u.many.ws = os_sockWaitsetNew ()) == NULL)
{
- DDS_ERROR("rtps_init: can't allocate sock waitset for thread %s\n", gv.recv_threads[i].name);
+ GVERROR ("rtps_init: can't allocate sock waitset for thread %s\n", gv->recv_threads[i].name);
goto fail;
}
}
- if (create_thread (&gv.recv_threads[i].ts, gv.recv_threads[i].name, recv_thread, &gv.recv_threads[i].arg) != DDS_RETCODE_OK)
+ if (create_thread (&gv->recv_threads[i].ts, gv, gv->recv_threads[i].name, recv_thread, &gv->recv_threads[i].arg) != DDS_RETCODE_OK)
{
- DDS_ERROR("rtps_init: failed to start thread %s\n", gv.recv_threads[i].name);
+ GVERROR ("rtps_init: failed to start thread %s\n", gv->recv_threads[i].name);
goto fail;
}
}
@@ -833,142 +833,156 @@ static int setup_and_start_recv_threads (void)
fail:
/* to trigger any threads we already started to stop - xevent thread has already been started */
- rtps_term_prep ();
- wait_for_receive_threads ();
- for (i = 0; i < gv.n_recv_threads; i++)
+ rtps_term_prep (gv);
+ wait_for_receive_threads (gv);
+ for (uint32_t i = 0; i < gv->n_recv_threads; i++)
{
- if (gv.recv_threads[i].arg.mode == RTM_MANY && gv.recv_threads[i].arg.u.many.ws)
- os_sockWaitsetFree (gv.recv_threads[i].arg.u.many.ws);
- if (gv.recv_threads[i].arg.rbpool)
- nn_rbufpool_free (gv.recv_threads[i].arg.rbpool);
+ if (gv->recv_threads[i].arg.mode == RTM_MANY && gv->recv_threads[i].arg.u.many.ws)
+ os_sockWaitsetFree (gv->recv_threads[i].arg.u.many.ws);
+ if (gv->recv_threads[i].arg.rbpool)
+ nn_rbufpool_free (gv->recv_threads[i].arg.rbpool);
}
return -1;
}
-int rtps_init (void)
+int rtps_init (struct q_globals *gv)
{
uint32_t port_disc_uc = 0;
uint32_t port_data_uc = 0;
bool mc_available = true;
- ddsi_plugin_init ();
- ddsi_iid_init ();
+ gv->tstart = now (); /* wall clock time, used in logs */
- gv.tstart = now (); /* wall clock time, used in logs */
+ nn_plist_init_tables ();
- gv.disc_conn_uc = NULL;
- gv.data_conn_uc = NULL;
- gv.disc_conn_mc = NULL;
- gv.data_conn_mc = NULL;
- gv.tev_conn = NULL;
- gv.listener = NULL;
- gv.thread_pool = NULL;
- gv.debmon = NULL;
+ gv->disc_conn_uc = NULL;
+ gv->data_conn_uc = NULL;
+ gv->disc_conn_mc = NULL;
+ gv->data_conn_mc = NULL;
+ gv->tev_conn = NULL;
+ gv->listener = NULL;
+ gv->thread_pool = NULL;
+ gv->debmon = NULL;
- /* Print start time for referencing relative times in the remainder
- of the DDS_LOG. */
+ /* Print start time for referencing relative times in the remainder of the DDS_LOG. */
{
- int sec = (int) (gv.tstart.v / 1000000000);
- int usec = (int) (gv.tstart.v % 1000000000) / 1000;
- char str[DDSRT_RFC3339STRLEN];
- ddsrt_ctime(gv.tstart.v, str, sizeof(str));
- DDS_LOG(DDS_LC_CONFIG, "started at %d.06%d -- %s\n", sec, usec, str);
+ int sec = (int) (gv->tstart.v / 1000000000);
+ int usec = (int) (gv->tstart.v % 1000000000) / 1000;
+ char str[DDSRT_RFC3339STRLEN+1];
+ ddsrt_ctime(gv->tstart.v, str, sizeof(str));
+ GVLOG (DDS_LC_CONFIG, "started at %d.06%d -- %s\n", sec, usec, str);
}
/* Initialize thread pool */
-
- if (config.tp_enable)
+ if (gv->config.tp_enable)
{
- gv.thread_pool = ddsrt_thread_pool_new
- (config.tp_threads, config.tp_max_threads, 0, NULL);
+ gv->thread_pool = ddsrt_thread_pool_new (gv->config.tp_threads, gv->config.tp_max_threads, 0, NULL);
}
/* Initialize UDP or TCP transport and resolve factory */
- switch (config.transport_selector)
+ switch (gv->config.transport_selector)
{
case TRANS_DEFAULT:
assert(0);
case TRANS_UDP:
case TRANS_UDP6:
- config.publish_uc_locators = 1;
- config.enable_uc_locators = 1;
- if (ddsi_udp_init () < 0)
+ gv->config.publish_uc_locators = 1;
+ gv->config.enable_uc_locators = 1;
+ if (ddsi_udp_init (gv) < 0)
goto err_udp_tcp_init;
- gv.m_factory = ddsi_factory_find (config.transport_selector == TRANS_UDP ? "udp" : "udp6");
+ gv->m_factory = ddsi_factory_find (gv, gv->config.transport_selector == TRANS_UDP ? "udp" : "udp6");
break;
case TRANS_TCP:
case TRANS_TCP6:
- config.publish_uc_locators = (config.tcp_port != -1);
- config.enable_uc_locators = 1;
+ gv->config.publish_uc_locators = (gv->config.tcp_port != -1);
+ gv->config.enable_uc_locators = 1;
/* TCP affects what features are supported/required */
- config.many_sockets_mode = MSM_SINGLE_UNICAST;
- config.allowMulticast = AMC_FALSE;
- if (ddsi_tcp_init () < 0)
+ gv->config.many_sockets_mode = MSM_SINGLE_UNICAST;
+ gv->config.allowMulticast = AMC_FALSE;
+ if (ddsi_tcp_init (gv) < 0)
goto err_udp_tcp_init;
- gv.m_factory = ddsi_factory_find (config.transport_selector == TRANS_TCP ? "tcp" : "tcp6");
+ gv->m_factory = ddsi_factory_find (gv, gv->config.transport_selector == TRANS_TCP ? "tcp" : "tcp6");
break;
case TRANS_RAWETH:
- config.publish_uc_locators = 1;
- config.enable_uc_locators = 0;
- config.participantIndex = PARTICIPANT_INDEX_NONE;
- config.many_sockets_mode = MSM_NO_UNICAST;
- if (ddsi_raweth_init () < 0)
+ gv->config.publish_uc_locators = 1;
+ gv->config.enable_uc_locators = 0;
+ gv->config.participantIndex = PARTICIPANT_INDEX_NONE;
+ gv->config.many_sockets_mode = MSM_NO_UNICAST;
+ if (ddsi_raweth_init (gv) < 0)
goto err_udp_tcp_init;
- gv.m_factory = ddsi_factory_find ("raweth");
+ gv->m_factory = ddsi_factory_find (gv, "raweth");
break;
}
- if (!find_own_ip (config.networkAddressString))
+ if (!find_own_ip (gv, gv->config.networkAddressString))
{
/* find_own_ip already logs a more informative error message */
- DDS_LOG(DDS_LC_CONFIG, "No network interface selected\n");
+ GVLOG (DDS_LC_CONFIG, "No network interface selected\n");
goto err_find_own_ip;
}
- if (config.allowMulticast)
+ if (gv->config.allowMulticast)
{
- if (!gv.interfaces[gv.selected_interface].mc_capable)
+ if (!gv->interfaces[gv->selected_interface].mc_capable)
{
- DDS_WARNING("selected interface is not multicast-capable: disabling multicast\n");
- config.allowMulticast = AMC_FALSE;
+ GVWARNING ("selected interface is not multicast-capable: disabling multicast\n");
+ gv->config.allowMulticast = AMC_FALSE;
/* ensure discovery can work: firstly, that the process will be reachable on a "well-known" port
number, and secondly, that the local interface's IP address gets added to the discovery
address set */
- config.participantIndex = PARTICIPANT_INDEX_AUTO;
+ gv->config.participantIndex = PARTICIPANT_INDEX_AUTO;
mc_available = false;
}
+ else if (gv->config.allowMulticast & AMC_DEFAULT)
+ {
+ /* default is dependent on network interface type: if multicast is believed to be flaky,
+ use multicast only for SPDP packets */
+ assert ((gv->config.allowMulticast & ~AMC_DEFAULT) == 0);
+ if (gv->interfaces[gv->selected_interface].mc_flaky)
+ {
+ gv->config.allowMulticast = AMC_SPDP;
+ GVLOG (DDS_LC_CONFIG, "presumed flaky multicast, use for SPDP only\n");
+ }
+ else
+ {
+ GVLOG (DDS_LC_CONFIG, "presumed robust multicast support, use for everything\n");
+ gv->config.allowMulticast = AMC_TRUE;
+ }
+ }
}
- if (set_recvips () < 0)
+
+ assert ((gv->config.allowMulticast & AMC_DEFAULT) == 0);
+ if (set_recvips (gv) < 0)
goto err_set_recvips;
- if (set_spdp_address () < 0)
+ if (set_spdp_address (gv) < 0)
goto err_set_ext_address;
- if (set_default_mc_address () < 0)
+ if (set_default_mc_address (gv) < 0)
goto err_set_ext_address;
- if (set_ext_address_and_mask () < 0)
+ if (set_ext_address_and_mask (gv) < 0)
goto err_set_ext_address;
{
char buf[DDSI_LOCSTRLEN];
/* the "ownip", "extip" labels in the trace have been there for so long, that it seems worthwhile to retain them even though they need not be IP any longer */
- DDS_LOG(DDS_LC_CONFIG, "ownip: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv.ownloc));
- DDS_LOG(DDS_LC_CONFIG, "extip: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv.extloc));
- DDS_LOG(DDS_LC_CONFIG, "extmask: %s%s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv.extmask), gv.m_factory->m_kind != NN_LOCATOR_KIND_UDPv4 ? " (not applicable)" : "");
- DDS_LOG(DDS_LC_CONFIG, "networkid: 0x%lx\n", (unsigned long) gv.myNetworkId);
- DDS_LOG(DDS_LC_CONFIG, "SPDP MC: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv.loc_spdp_mc));
- DDS_LOG(DDS_LC_CONFIG, "default MC: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv.loc_default_mc));
+ GVLOG (DDS_LC_CONFIG, "ownip: %s\n", ddsi_locator_to_string_no_port (gv, buf, sizeof(buf), &gv->ownloc));
+ GVLOG (DDS_LC_CONFIG, "extip: %s\n", ddsi_locator_to_string_no_port (gv, buf, sizeof(buf), &gv->extloc));
+ GVLOG (DDS_LC_CONFIG, "extmask: %s%s\n", ddsi_locator_to_string_no_port (gv, buf, sizeof(buf), &gv->extmask), gv->m_factory->m_kind != NN_LOCATOR_KIND_UDPv4 ? " (not applicable)" : "");
+ GVLOG (DDS_LC_CONFIG, "networkid: 0x%lx\n", (unsigned long) gv->myNetworkId);
+ GVLOG (DDS_LC_CONFIG, "SPDP MC: %s\n", ddsi_locator_to_string_no_port (gv, buf, sizeof(buf), &gv->loc_spdp_mc));
+ GVLOG (DDS_LC_CONFIG, "default MC: %s\n", ddsi_locator_to_string_no_port (gv, buf, sizeof(buf), &gv->loc_default_mc));
#ifdef DDSI_INCLUDE_SSM
- DDS_LOG(DDS_LC_CONFIG, "SSM support included\n");
+ GVLOG (DDS_LC_CONFIG, "SSM support included\n");
#endif
}
- if (gv.ownloc.kind != gv.extloc.kind)
- DDS_FATAL("mismatch between network address kinds\n");
+ if (gv->ownloc.kind != gv->extloc.kind)
+ DDS_FATAL ("mismatch between network address kinds\n");
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
/* Convert address sets in partition mappings from string to address sets */
{
- const int port = config.port_base + config.port_dg * config.domainId.value + config.port_d2;
+ const uint32_t port = gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d2;
struct config_networkpartition_listelem *np;
- for (np = config.networkPartitions; np; np = np->next)
+ for (np = gv->config.networkPartitions; np; np = np->next)
{
static const char msgtag_fixed[] = ": partition address";
size_t slen = strlen (np->name) + sizeof (msgtag_fixed);
@@ -976,7 +990,7 @@ int rtps_init (void)
int rc;
snprintf (msgtag, slen, "%s%s", np->name, msgtag_fixed);
np->as = new_addrset ();
- rc = add_addresses_to_addrset (np->as, np->address_string, port, msgtag, 1);
+ rc = add_addresses_to_addrset (gv, np->as, np->address_string, (int) port, msgtag, 1);
ddsrt_free (msgtag);
if (rc < 0)
goto err_network_partition_addrset;
@@ -984,175 +998,174 @@ int rtps_init (void)
}
#endif
- (ddsi_plugin.init_fn) ();
-
- gv.xmsgpool = nn_xmsgpool_new ();
- gv.serpool = ddsi_serdatapool_new ();
+ gv->xmsgpool = nn_xmsgpool_new ();
+ gv->serpool = ddsi_serdatapool_new ();
#ifdef DDSI_INCLUDE_ENCRYPTION
if (q_security_plugin.new_decoder)
{
- gv.recvSecurityCodec = (q_security_plugin.new_decoder) ();
- DDS_LOG(DDS_LC_CONFIG, "decoderset created\n");
+ gv->recvSecurityCodec = (q_security_plugin.new_decoder) ();
+ GVLOG (DDS_LC_CONFIG, "decoderset created\n");
}
#endif
- nn_plist_init_default_participant (&gv.default_plist_pp);
- nn_xqos_init_default_reader (&gv.default_xqos_rd);
- nn_xqos_init_default_writer (&gv.default_xqos_wr);
- nn_xqos_init_default_writer_noautodispose (&gv.default_xqos_wr_nad);
- nn_xqos_init_default_topic (&gv.default_xqos_tp);
- nn_xqos_init_default_subscriber (&gv.default_xqos_sub);
- nn_xqos_init_default_publisher (&gv.default_xqos_pub);
- nn_xqos_copy (&gv.spdp_endpoint_xqos, &gv.default_xqos_rd);
- gv.spdp_endpoint_xqos.durability.kind = NN_TRANSIENT_LOCAL_DURABILITY_QOS;
- make_builtin_endpoint_xqos (&gv.builtin_endpoint_xqos_rd, &gv.default_xqos_rd);
- make_builtin_endpoint_xqos (&gv.builtin_endpoint_xqos_wr, &gv.default_xqos_wr);
+ nn_plist_init_default_participant (&gv->default_plist_pp);
+ nn_plist_init_default_participant (&gv->default_local_plist_pp);
+ nn_xqos_init_default_reader (&gv->default_xqos_rd);
+ nn_xqos_init_default_writer (&gv->default_xqos_wr);
+ nn_xqos_init_default_writer_noautodispose (&gv->default_xqos_wr_nad);
+ nn_xqos_init_default_topic (&gv->default_xqos_tp);
+ nn_xqos_init_default_subscriber (&gv->default_xqos_sub);
+ nn_xqos_init_default_publisher (&gv->default_xqos_pub);
+ nn_xqos_copy (&gv->spdp_endpoint_xqos, &gv->default_xqos_rd);
+ gv->spdp_endpoint_xqos.durability.kind = DDS_DURABILITY_TRANSIENT_LOCAL;
+ make_builtin_endpoint_xqos (&gv->builtin_endpoint_xqos_rd, &gv->default_xqos_rd);
+ make_builtin_endpoint_xqos (&gv->builtin_endpoint_xqos_wr, &gv->default_xqos_wr);
- make_special_topics ();
+ make_special_topics (gv);
- ddsrt_mutex_init (&gv.participant_set_lock);
- ddsrt_cond_init (&gv.participant_set_cond);
- lease_management_init ();
- deleted_participants_admin_init ();
- gv.guid_hash = ephash_new ();
+ ddsrt_mutex_init (&gv->participant_set_lock);
+ ddsrt_cond_init (&gv->participant_set_cond);
+ lease_management_init (gv);
+ gv->deleted_participants = deleted_participants_admin_new (gv->config.prune_deleted_ppant.delay);
+ gv->guid_hash = ephash_new (gv);
- ddsrt_mutex_init (&gv.privileged_pp_lock);
- gv.privileged_pp = NULL;
+ ddsrt_mutex_init (&gv->privileged_pp_lock);
+ gv->privileged_pp = NULL;
/* Template PP guid -- protected by privileged_pp_lock for simplicity */
- gv.next_ppguid.prefix.u[0] = locator_to_hopefully_unique_uint32 (&gv.ownloc);
- gv.next_ppguid.prefix.u[1] = (unsigned) ddsrt_getpid ();
- gv.next_ppguid.prefix.u[2] = 1;
- gv.next_ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
+ gv->next_ppguid.prefix.u[0] = locator_to_hopefully_unique_uint32 (&gv->ownloc);
+ gv->next_ppguid.prefix.u[1] = (unsigned) ddsrt_getpid ();
+ gv->next_ppguid.prefix.u[2] = 1;
+ gv->next_ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
- ddsrt_mutex_init (&gv.lock);
- ddsrt_mutex_init (&gv.spdp_lock);
- gv.spdp_defrag = nn_defrag_new (NN_DEFRAG_DROP_OLDEST, config.defrag_unreliable_maxsamples);
- gv.spdp_reorder = nn_reorder_new (NN_REORDER_MODE_ALWAYS_DELIVER, config.primary_reorder_maxsamples);
+ ddsrt_mutex_init (&gv->lock);
+ ddsrt_mutex_init (&gv->spdp_lock);
+ gv->spdp_defrag = nn_defrag_new (&gv->logconfig, NN_DEFRAG_DROP_OLDEST, gv->config.defrag_unreliable_maxsamples);
+ gv->spdp_reorder = nn_reorder_new (&gv->logconfig, NN_REORDER_MODE_ALWAYS_DELIVER, gv->config.primary_reorder_maxsamples, false);
- gv.m_tkmap = ddsi_tkmap_new ();
+ gv->m_tkmap = ddsi_tkmap_new (gv);
- if (gv.m_factory->m_connless)
+ if (gv->m_factory->m_connless)
{
- if (config.participantIndex >= 0 || config.participantIndex == PARTICIPANT_INDEX_NONE)
+ if (gv->config.participantIndex >= 0 || gv->config.participantIndex == PARTICIPANT_INDEX_NONE)
{
- if (make_uc_sockets (&port_disc_uc, &port_data_uc, config.participantIndex) < 0)
+ if (make_uc_sockets (gv, &port_disc_uc, &port_data_uc, gv->config.participantIndex) < 0)
{
- DDS_ERROR("rtps_init: failed to create unicast sockets for domain %"PRId32" participant %d\n", config.domainId.value, config.participantIndex);
+ GVERROR ("rtps_init: failed to create unicast sockets for domain %"PRId32" participant %d\n", gv->config.domainId, gv->config.participantIndex);
goto err_unicast_sockets;
}
}
- else if (config.participantIndex == PARTICIPANT_INDEX_AUTO)
+ else if (gv->config.participantIndex == PARTICIPANT_INDEX_AUTO)
{
- /* try to find a free one, and update config.participantIndex */
+ /* try to find a free one, and update gv->config.participantIndex */
int ppid;
- DDS_LOG(DDS_LC_CONFIG, "rtps_init: trying to find a free participant index\n");
- for (ppid = 0; ppid <= config.maxAutoParticipantIndex; ppid++)
+ GVLOG (DDS_LC_CONFIG, "rtps_init: trying to find a free participant index\n");
+ for (ppid = 0; ppid <= gv->config.maxAutoParticipantIndex; ppid++)
{
- int r = make_uc_sockets (&port_disc_uc, &port_data_uc, ppid);
+ int r = make_uc_sockets (gv, &port_disc_uc, &port_data_uc, ppid);
if (r == 0) /* Success! */
break;
else if (r == -1) /* Try next one */
continue;
else /* Oops! */
{
- DDS_ERROR("rtps_init: failed to create unicast sockets for domain %"PRId32" participant %d\n", config.domainId.value, ppid);
+ GVERROR ("rtps_init: failed to create unicast sockets for domain %"PRId32" participant %d\n", gv->config.domainId, ppid);
goto err_unicast_sockets;
}
}
- if (ppid > config.maxAutoParticipantIndex)
+ if (ppid > gv->config.maxAutoParticipantIndex)
{
- DDS_ERROR("rtps_init: failed to find a free participant index for domain %"PRId32"\n", config.domainId.value);
+ GVERROR ("rtps_init: failed to find a free participant index for domain %"PRId32"\n", gv->config.domainId);
goto err_unicast_sockets;
}
- config.participantIndex = ppid;
+ gv->config.participantIndex = ppid;
}
else
{
assert(0);
}
- DDS_LOG(DDS_LC_CONFIG, "rtps_init: uc ports: disc %"PRIu32" data %"PRIu32"\n", port_disc_uc, port_data_uc);
+ GVLOG (DDS_LC_CONFIG, "rtps_init: uc ports: disc %"PRIu32" data %"PRIu32"\n", port_disc_uc, port_data_uc);
}
- DDS_LOG(DDS_LC_CONFIG, "rtps_init: domainid %"PRId32" participantid %d\n", config.domainId.value, config.participantIndex);
+ GVLOG (DDS_LC_CONFIG, "rtps_init: domainid %"PRId32" participantid %d\n", gv->config.domainId, gv->config.participantIndex);
- if (config.pcap_file && *config.pcap_file)
+ if (gv->config.pcap_file && *gv->config.pcap_file)
{
- gv.pcap_fp = new_pcap_file (config.pcap_file);
- if (gv.pcap_fp)
+ gv->pcap_fp = new_pcap_file (&gv->logconfig, gv->config.pcap_file);
+ if (gv->pcap_fp)
{
- ddsrt_mutex_init (&gv.pcap_lock);
+ ddsrt_mutex_init (&gv->pcap_lock);
}
}
else
{
- gv.pcap_fp = NULL;
+ gv->pcap_fp = NULL;
}
- gv.mship = new_group_membership();
+ gv->mship = new_group_membership();
- if (gv.m_factory->m_connless)
+ if (gv->m_factory->m_connless)
{
- if (!(config.many_sockets_mode == MSM_NO_UNICAST && config.allowMulticast))
- DDS_TRACE("Unicast Ports: discovery %"PRIu32" data %"PRIu32"\n", ddsi_conn_port (gv.disc_conn_uc), ddsi_conn_port (gv.data_conn_uc));
+ if (!(gv->config.many_sockets_mode == MSM_NO_UNICAST && gv->config.allowMulticast))
+ GVTRACE ("Unicast Ports: discovery %"PRIu32" data %"PRIu32"\n", ddsi_conn_port (gv->disc_conn_uc), ddsi_conn_port (gv->data_conn_uc));
- if (config.allowMulticast)
+ if (gv->config.allowMulticast)
{
- if (!create_multicast_sockets())
+ if (!create_multicast_sockets (gv))
goto err_mc_conn;
- if (config.many_sockets_mode == MSM_NO_UNICAST)
+ if (gv->config.many_sockets_mode == MSM_NO_UNICAST)
{
- gv.data_conn_uc = gv.data_conn_mc;
- gv.disc_conn_uc = gv.disc_conn_mc;
+ gv->data_conn_uc = gv->data_conn_mc;
+ gv->disc_conn_uc = gv->disc_conn_mc;
}
/* Set multicast locators */
- if (!is_unspec_locator(&gv.loc_spdp_mc))
- gv.loc_spdp_mc.port = ddsi_conn_port (gv.disc_conn_mc);
- if (!is_unspec_locator(&gv.loc_meta_mc))
- gv.loc_meta_mc.port = ddsi_conn_port (gv.disc_conn_mc);
- if (!is_unspec_locator(&gv.loc_default_mc))
- gv.loc_default_mc.port = ddsi_conn_port (gv.data_conn_mc);
+ if (!is_unspec_locator(&gv->loc_spdp_mc))
+ gv->loc_spdp_mc.port = ddsi_conn_port (gv->disc_conn_mc);
+ if (!is_unspec_locator(&gv->loc_meta_mc))
+ gv->loc_meta_mc.port = ddsi_conn_port (gv->disc_conn_mc);
+ if (!is_unspec_locator(&gv->loc_default_mc))
+ gv->loc_default_mc.port = ddsi_conn_port (gv->data_conn_mc);
- if (joinleave_spdp_defmcip (1) < 0)
+ if (joinleave_spdp_defmcip (gv, 1) < 0)
goto err_mc_conn;
}
}
else
{
/* Must have a data_conn_uc/tev_conn/transmit_conn */
- gv.data_conn_uc = ddsi_factory_create_conn (gv.m_factory, 0, NULL);
+ gv->data_conn_uc = ddsi_factory_create_conn (gv->m_factory, 0, NULL);
- if (config.tcp_port != -1)
+ if (gv->config.tcp_port != -1)
{
- gv.listener = ddsi_factory_create_listener (gv.m_factory, config.tcp_port, NULL);
- if (gv.listener == NULL || ddsi_listener_listen (gv.listener) != 0)
+ gv->listener = ddsi_factory_create_listener (gv->m_factory, gv->config.tcp_port, NULL);
+ if (gv->listener == NULL || ddsi_listener_listen (gv->listener) != 0)
{
- DDS_ERROR("Failed to create %s listener\n", gv.m_factory->m_typename);
- if (gv.listener)
- ddsi_listener_free(gv.listener);
+ GVERROR ("Failed to create %s listener\n", gv->m_factory->m_typename);
+ if (gv->listener)
+ ddsi_listener_free(gv->listener);
goto err_mc_conn;
}
/* Set unicast locators from listener */
- set_unspec_locator (&gv.loc_spdp_mc);
- set_unspec_locator (&gv.loc_meta_mc);
- set_unspec_locator (&gv.loc_default_mc);
+ set_unspec_locator (&gv->loc_spdp_mc);
+ set_unspec_locator (&gv->loc_meta_mc);
+ set_unspec_locator (&gv->loc_default_mc);
- ddsi_listener_locator (gv.listener, &gv.loc_meta_uc);
- ddsi_listener_locator (gv.listener, &gv.loc_default_uc);
+ ddsi_listener_locator (gv->listener, &gv->loc_meta_uc);
+ ddsi_listener_locator (gv->listener, &gv->loc_default_uc);
}
}
/* Create shared transmit connection */
- gv.tev_conn = gv.data_conn_uc;
- DDS_TRACE("Timed event transmit port: %d\n", (int) ddsi_conn_port (gv.tev_conn));
+ gv->tev_conn = gv->data_conn_uc;
+ GVTRACE ("Timed event transmit port: %d\n", (int) ddsi_conn_port (gv->tev_conn));
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
{
- struct config_channel_listelem *chptr = config.channels;
+ struct config_channel_listelem *chptr = gv->config.channels;
while (chptr)
{
size_t slen = strlen (chptr->name) + 5;
@@ -1165,18 +1178,18 @@ int rtps_init (void)
{
ddsi_tran_qos_t qos = ddsi_tran_create_qos ();
qos->m_diffserv = chptr->diffserv_field;
- chptr->transmit_conn = ddsi_factory_create_conn (gv.m_factory, 0, qos);
+ chptr->transmit_conn = ddsi_factory_create_conn (gv->m_factory, 0, qos);
ddsi_tran_free_qos (qos);
if (chptr->transmit_conn == NULL)
{
- DDS_FATAL("failed to create transmit connection for channel %s\n", chptr->name);
+ DDS_FATAL ("failed to create transmit connection for channel %s\n", chptr->name);
}
}
else
{
- chptr->transmit_conn = gv.data_conn_uc;
+ chptr->transmit_conn = gv->data_conn_uc;
}
- DDS_TRACE("channel %s: transmit port %d\n", chptr->name, (int) ddsi_tran_port (chptr->transmit_conn));
+ GVTRACE ("channel %s: transmit port %d\n", chptr->name, (int) ddsi_tran_port (chptr->transmit_conn));
#ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING
if (chptr->auxiliary_bandwidth_limit > 0 || lookup_thread_properties (tname))
@@ -1184,8 +1197,8 @@ int rtps_init (void)
chptr->evq = xeventq_new
(
chptr->transmit_conn,
- config.max_queued_rexmit_bytes,
- config.max_queued_rexmit_msgs,
+ gv->config.max_queued_rexmit_bytes,
+ gv->config.max_queued_rexmit_msgs,
chptr->auxiliary_bandwidth_limit
);
}
@@ -1195,8 +1208,8 @@ int rtps_init (void)
chptr->evq = xeventq_new
(
chptr->transmit_conn,
- config.max_queued_rexmit_bytes,
- config.max_queued_rexmit_msgs,
+ gv->config.max_queued_rexmit_bytes,
+ gv->config.max_queued_rexmit_msgs,
0
);
}
@@ -1209,21 +1222,21 @@ int rtps_init (void)
/* Create event queues */
- gv.xevents = xeventq_new
+ gv->xevents = xeventq_new
(
- gv.tev_conn,
- config.max_queued_rexmit_bytes,
- config.max_queued_rexmit_msgs,
+ gv->tev_conn,
+ gv->config.max_queued_rexmit_bytes,
+ gv->config.max_queued_rexmit_msgs,
#ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING
- config.auxiliary_bandwidth_limit
+ gv->config.auxiliary_bandwidth_limit
#else
0
#endif
);
- gv.as_disc = new_addrset ();
- if (config.allowMulticast & AMC_SPDP)
- add_to_addrset (gv.as_disc, &gv.loc_spdp_mc);
+ gv->as_disc = new_addrset ();
+ if (gv->config.allowMulticast & AMC_SPDP)
+ add_to_addrset (gv, gv->as_disc, &gv->loc_spdp_mc);
/* If multicast was enabled but not available, always add the local interface to the discovery address set.
Conversion via string and add_peer_addresses has the benefit that the port number expansion happens
automatically. */
@@ -1231,160 +1244,158 @@ int rtps_init (void)
{
struct config_peer_listelem peer_local;
char local_addr[DDSI_LOCSTRLEN];
- ddsi_locator_to_string_no_port (local_addr, sizeof (local_addr), &gv.interfaces[gv.selected_interface].loc);
+ ddsi_locator_to_string_no_port (gv, local_addr, sizeof (local_addr), &gv->interfaces[gv->selected_interface].loc);
peer_local.next = NULL;
peer_local.peer = local_addr;
- add_peer_addresses (gv.as_disc, &peer_local);
+ add_peer_addresses (gv, gv->as_disc, &peer_local);
}
- if (config.peers)
+ if (gv->config.peers)
{
- add_peer_addresses (gv.as_disc, config.peers);
+ add_peer_addresses (gv, gv->as_disc, gv->config.peers);
}
- if (config.peers_group)
+ if (gv->config.peers_group)
{
- gv.as_disc_group = new_addrset ();
- add_peer_addresses (gv.as_disc_group, config.peers_group);
+ gv->as_disc_group = new_addrset ();
+ add_peer_addresses (gv, gv->as_disc_group, gv->config.peers_group);
}
else
{
- gv.as_disc_group = NULL;
+ gv->as_disc_group = NULL;
}
- gv.gcreq_queue = gcreq_queue_new ();
+ gv->gcreq_queue = gcreq_queue_new (gv);
- gv.rtps_keepgoing = 1;
- ddsrt_rwlock_init (&gv.qoslock);
+ ddsrt_atomic_st32 (&gv->rtps_keepgoing, 1);
- if (config.xpack_send_async)
+ if (gv->config.xpack_send_async)
{
- nn_xpack_sendq_init();
- nn_xpack_sendq_start();
+ nn_xpack_sendq_init (gv);
+ nn_xpack_sendq_start (gv);
}
- gv.builtins_dqueue = nn_dqueue_new ("builtins", config.delivery_queue_maxsamples, builtins_dqueue_handler, NULL);
+ gv->builtins_dqueue = nn_dqueue_new ("builtins", gv, gv->config.delivery_queue_maxsamples, builtins_dqueue_handler, NULL);
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
- for (struct config_channel_listelem *chptr = config.channels; chptr; chptr = chptr->next)
- chptr->dqueue = nn_dqueue_new (chptr->name, config.delivery_queue_maxsamples, user_dqueue_handler, NULL);
+ for (struct config_channel_listelem *chptr = gv->config.channels; chptr; chptr = chptr->next)
+ chptr->dqueue = nn_dqueue_new (chptr->name, &gv->config, gv->config.delivery_queue_maxsamples, user_dqueue_handler, NULL);
#else
- gv.user_dqueue = nn_dqueue_new ("user", config.delivery_queue_maxsamples, user_dqueue_handler, NULL);
+ gv->user_dqueue = nn_dqueue_new ("user", gv, gv->config.delivery_queue_maxsamples, user_dqueue_handler, NULL);
#endif
return 0;
err_mc_conn:
- if (gv.disc_conn_mc)
- ddsi_conn_free (gv.disc_conn_mc);
- if (gv.data_conn_mc && gv.data_conn_mc != gv.disc_conn_mc)
- ddsi_conn_free (gv.data_conn_mc);
- if (gv.pcap_fp)
- ddsrt_mutex_destroy (&gv.pcap_lock);
- if (gv.disc_conn_uc != gv.disc_conn_mc)
- ddsi_conn_free (gv.disc_conn_uc);
- if (gv.data_conn_uc != gv.disc_conn_uc)
- ddsi_conn_free (gv.data_conn_uc);
- free_group_membership(gv.mship);
+ if (gv->disc_conn_mc)
+ ddsi_conn_free (gv->disc_conn_mc);
+ if (gv->data_conn_mc && gv->data_conn_mc != gv->disc_conn_mc)
+ ddsi_conn_free (gv->data_conn_mc);
+ if (gv->pcap_fp)
+ ddsrt_mutex_destroy (&gv->pcap_lock);
+ if (gv->disc_conn_uc != gv->disc_conn_mc)
+ ddsi_conn_free (gv->disc_conn_uc);
+ if (gv->data_conn_uc != gv->disc_conn_uc)
+ ddsi_conn_free (gv->data_conn_uc);
+ free_group_membership (gv->mship);
err_unicast_sockets:
- ddsi_tkmap_free (gv.m_tkmap);
- nn_reorder_free (gv.spdp_reorder);
- nn_defrag_free (gv.spdp_defrag);
- ddsrt_mutex_destroy (&gv.spdp_lock);
- ddsrt_mutex_destroy (&gv.lock);
- ddsrt_mutex_destroy (&gv.privileged_pp_lock);
- ephash_free (gv.guid_hash);
- gv.guid_hash = NULL;
- deleted_participants_admin_fini ();
- lease_management_term ();
- ddsrt_cond_destroy (&gv.participant_set_cond);
- ddsrt_mutex_destroy (&gv.participant_set_lock);
- free_special_topics ();
+ ddsi_tkmap_free (gv->m_tkmap);
+ nn_reorder_free (gv->spdp_reorder);
+ nn_defrag_free (gv->spdp_defrag);
+ ddsrt_mutex_destroy (&gv->spdp_lock);
+ ddsrt_mutex_destroy (&gv->lock);
+ ddsrt_mutex_destroy (&gv->privileged_pp_lock);
+ ephash_free (gv->guid_hash);
+ gv->guid_hash = NULL;
+ deleted_participants_admin_free (gv->deleted_participants);
+ lease_management_term (gv);
+ ddsrt_cond_destroy (&gv->participant_set_cond);
+ ddsrt_mutex_destroy (&gv->participant_set_lock);
+ free_special_topics (gv);
#ifdef DDSI_INCLUDE_ENCRYPTION
if (q_security_plugin.free_decoder)
- q_security_plugin.free_decoder (gv.recvSecurityCodec);
+ q_security_plugin.free_decoder (gv->recvSecurityCodec);
#endif
- nn_xqos_fini (&gv.builtin_endpoint_xqos_wr);
- nn_xqos_fini (&gv.builtin_endpoint_xqos_rd);
- nn_xqos_fini (&gv.spdp_endpoint_xqos);
- nn_xqos_fini (&gv.default_xqos_pub);
- nn_xqos_fini (&gv.default_xqos_sub);
- nn_xqos_fini (&gv.default_xqos_tp);
- nn_xqos_fini (&gv.default_xqos_wr_nad);
- nn_xqos_fini (&gv.default_xqos_wr);
- nn_xqos_fini (&gv.default_xqos_rd);
- nn_plist_fini (&gv.default_plist_pp);
- ddsi_serdatapool_free (gv.serpool);
- nn_xmsgpool_free (gv.xmsgpool);
- ddsi_iid_fini ();
- (ddsi_plugin.fini_fn) ();
+ nn_xqos_fini (&gv->builtin_endpoint_xqos_wr);
+ nn_xqos_fini (&gv->builtin_endpoint_xqos_rd);
+ nn_xqos_fini (&gv->spdp_endpoint_xqos);
+ nn_xqos_fini (&gv->default_xqos_pub);
+ nn_xqos_fini (&gv->default_xqos_sub);
+ nn_xqos_fini (&gv->default_xqos_tp);
+ nn_xqos_fini (&gv->default_xqos_wr_nad);
+ nn_xqos_fini (&gv->default_xqos_wr);
+ nn_xqos_fini (&gv->default_xqos_rd);
+ nn_plist_fini (&gv->default_local_plist_pp);
+ nn_plist_fini (&gv->default_plist_pp);
+ ddsi_serdatapool_free (gv->serpool);
+ nn_xmsgpool_free (gv->xmsgpool);
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
err_network_partition_addrset:
- for (struct config_networkpartition_listelem *np = config.networkPartitions; np; np = np->next)
+ for (struct config_networkpartition_listelem *np = gv->config.networkPartitions; np; np = np->next)
unref_addrset (np->as);
#endif
err_set_ext_address:
- while (gv.recvips)
+ while (gv->recvips)
{
- struct config_in_addr_node *n = gv.recvips;
- gv.recvips = n->next;
+ struct config_in_addr_node *n = gv->recvips;
+ gv->recvips = n->next;
ddsrt_free (n);
}
err_set_recvips:
- {
- int i;
- for (i = 0; i < gv.n_interfaces; i++)
- ddsrt_free (gv.interfaces[i].name);
- }
err_find_own_ip:
- ddsi_tran_factories_fini ();
+ for (int i = 0; i < gv->n_interfaces; i++)
+ ddsrt_free (gv->interfaces[i].name);
+ ddsi_tran_factories_fini (gv);
err_udp_tcp_init:
- if (config.tp_enable)
- ddsrt_thread_pool_free (gv.thread_pool);
+ if (gv->config.tp_enable)
+ ddsrt_thread_pool_free (gv->thread_pool);
return -1;
}
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
static void stop_all_xeventq_upto (struct config_channel_listelem *chptr)
{
- for (struct config_channel_listelem *chptr1 = config.channels; chptr1 != chptr; chptr1 = chptr1->next)
+ for (struct config_channel_listelem *chptr1 = gv->config.channels; chptr1 != chptr; chptr1 = chptr1->next)
if (chptr1->evq)
xeventq_stop (chptr1->evq);
}
#endif
-int rtps_start (void)
+int rtps_start (struct q_globals *gv)
{
- if (xeventq_start (gv.xevents, NULL) < 0)
+ if (xeventq_start (gv->xevents, NULL) < 0)
return -1;
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
- for (struct config_channel_listelem *chptr = config.channels; chptr; chptr = chptr->next)
+ for (struct config_channel_listelem *chptr = gv->config.channels; chptr; chptr = chptr->next)
{
if (chptr->evq)
{
if (xeventq_start (chptr->evq, chptr->name) < 0)
{
stop_all_xeventq_upto (chptr);
- xeventq_stop (gv.xevents);
+ xeventq_stop (gv->xevents);
return -1;
}
}
}
#endif
- if (setup_and_start_recv_threads () < 0)
+ if (setup_and_start_recv_threads (gv) < 0)
{
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
stop_all_xeventq_upto (NULL);
#endif
- xeventq_stop (gv.xevents);
+ xeventq_stop (gv->xevents);
return -1;
}
- if (gv.listener)
+ if (gv->listener)
{
- create_thread (&gv.listen_ts, "listen", (uint32_t (*) (void *)) listen_thread, gv.listener);
+ create_thread (&gv->listen_ts, gv, "listen", (uint32_t (*) (void *)) listen_thread, gv->listener);
+ /* FIXME: error handling */
}
- if (config.monitor_port >= 0)
+ if (gv->config.monitor_port >= 0)
{
- gv.debmon = new_debug_monitor (config.monitor_port);
+ gv->debmon = new_debug_monitor (gv, gv->config.monitor_port);
+ /* FIXME: clean up */
}
+
return 0;
}
@@ -1403,7 +1414,7 @@ static void builtins_dqueue_ready_cb (void *varg)
ddsrt_mutex_unlock (&arg->lock);
}
-void rtps_stop (void)
+void rtps_stop (struct q_globals *gv)
{
struct thread_state1 * const ts1 = lookup_thread_state ();
@@ -1411,26 +1422,26 @@ void rtps_stop (void)
struct config_channel_listelem * chptr;
#endif
- if (gv.debmon)
+ if (gv->debmon)
{
- free_debug_monitor (gv.debmon);
- gv.debmon = NULL;
+ free_debug_monitor (gv->debmon);
+ gv->debmon = NULL;
}
/* Stop all I/O */
- rtps_term_prep ();
- wait_for_receive_threads ();
+ rtps_term_prep (gv);
+ wait_for_receive_threads (gv);
- if (gv.listener)
+ if (gv->listener)
{
- ddsi_listener_unblock(gv.listener);
- join_thread (gv.listen_ts);
- ddsi_listener_free(gv.listener);
+ ddsi_listener_unblock(gv->listener);
+ join_thread (gv->listen_ts);
+ ddsi_listener_free(gv->listener);
}
- xeventq_stop (gv.xevents);
+ xeventq_stop (gv->xevents);
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
- for (chptr = config.channels; chptr; chptr = chptr->next)
+ for (chptr = gv->config.channels; chptr; chptr = chptr->next)
{
if (chptr->evq)
xeventq_stop (chptr->evq);
@@ -1445,7 +1456,7 @@ void rtps_stop (void)
ddsrt_mutex_init (&arg.lock);
ddsrt_cond_init (&arg.cond);
arg.ready = 0;
- nn_dqueue_enqueue_callback(gv.builtins_dqueue, builtins_dqueue_ready_cb, &arg);
+ nn_dqueue_enqueue_callback(gv->builtins_dqueue, builtins_dqueue_ready_cb, &arg);
ddsrt_mutex_lock (&arg.lock);
while (!arg.ready)
ddsrt_cond_wait (&arg.cond, &arg.lock);
@@ -1456,13 +1467,13 @@ void rtps_stop (void)
/* Once the receive threads have stopped, defragmentation and
reorder state can't change anymore, and can be freed safely. */
- nn_reorder_free (gv.spdp_reorder);
- nn_defrag_free (gv.spdp_defrag);
- ddsrt_mutex_destroy (&gv.spdp_lock);
+ nn_reorder_free (gv->spdp_reorder);
+ nn_defrag_free (gv->spdp_defrag);
+ ddsrt_mutex_destroy (&gv->spdp_lock);
#ifdef DDSI_INCLUDE_ENCRYPTION
if (q_security_plugin.free_decoder)
{
- (q_security_plugin.free_decoder) (gv.recvSecurityCodec);
+ (q_security_plugin.free_decoder) (gv->recvSecurityCodec);
}
#endif /* DDSI_INCLUDE_ENCRYPTION */
@@ -1473,11 +1484,11 @@ void rtps_stop (void)
/* Clean up proxy readers, proxy writers and proxy
participants. Deleting a proxy participants deletes all its
readers and writers automatically */
- thread_state_awake (ts1);
- ephash_enum_proxy_participant_init (&est);
+ thread_state_awake (ts1, gv);
+ ephash_enum_proxy_participant_init (&est, gv->guid_hash);
while ((proxypp = ephash_enum_proxy_participant_next (&est)) != NULL)
{
- delete_proxy_participant_by_guid(&proxypp->e.guid, tnow, 1);
+ delete_proxy_participant_by_guid (gv, &proxypp->e.guid, tnow, 1);
}
ephash_enum_proxy_participant_fini (&est);
thread_state_asleep (ts1);
@@ -1495,27 +1506,27 @@ void rtps_stop (void)
rwriters to get all SEDP and SPDP dispose+unregister messages
out. FIXME: need to keep xevent thread alive for a while
longer. */
- thread_state_awake (ts1);
- ephash_enum_writer_init (&est_wr);
+ thread_state_awake (ts1, gv);
+ ephash_enum_writer_init (&est_wr, gv->guid_hash);
while ((wr = ephash_enum_writer_next (&est_wr)) != NULL)
{
if (!is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE))
- delete_writer_nolinger (&wr->e.guid);
+ delete_writer_nolinger (gv, &wr->e.guid);
}
ephash_enum_writer_fini (&est_wr);
thread_state_awake_to_awake_no_nest (ts1);
- ephash_enum_reader_init (&est_rd);
+ ephash_enum_reader_init (&est_rd, gv->guid_hash);
while ((rd = ephash_enum_reader_next (&est_rd)) != NULL)
{
if (!is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE))
- (void)delete_reader (&rd->e.guid);
+ delete_reader (gv, &rd->e.guid);
}
ephash_enum_reader_fini (&est_rd);
thread_state_awake_to_awake_no_nest (ts1);
- ephash_enum_participant_init (&est_pp);
+ ephash_enum_participant_init (&est_pp, gv->guid_hash);
while ((pp = ephash_enum_participant_next (&est_pp)) != NULL)
{
- delete_participant (&pp->e.guid);
+ delete_participant (gv, &pp->e.guid);
}
ephash_enum_participant_fini (&est_pp);
thread_state_asleep (ts1);
@@ -1524,60 +1535,60 @@ void rtps_stop (void)
/* Wait until all participants are really gone => by then we can be
certain that no new GC requests will be added, short of what we
do here */
- ddsrt_mutex_lock (&gv.participant_set_lock);
- while (gv.nparticipants > 0)
- ddsrt_cond_wait (&gv.participant_set_cond, &gv.participant_set_lock);
- ddsrt_mutex_unlock (&gv.participant_set_lock);
+ ddsrt_mutex_lock (&gv->participant_set_lock);
+ while (gv->nparticipants > 0)
+ ddsrt_cond_wait (&gv->participant_set_cond, &gv->participant_set_lock);
+ ddsrt_mutex_unlock (&gv->participant_set_lock);
/* Wait until no more GC requests are outstanding -- not really
necessary, but it allows us to claim the stack is quiescent
at this point */
- gcreq_queue_drain (gv.gcreq_queue);
+ gcreq_queue_drain (gv->gcreq_queue);
/* Clean up privileged_pp -- it must be NULL now (all participants
are gone), but the lock still needs to be destroyed */
- assert (gv.privileged_pp == NULL);
- ddsrt_mutex_destroy (&gv.privileged_pp_lock);
+ assert (gv->privileged_pp == NULL);
+ ddsrt_mutex_destroy (&gv->privileged_pp_lock);
}
-void rtps_fini (void)
+void rtps_fini (struct q_globals *gv)
{
/* Shut down the GC system -- no new requests will be added */
- gcreq_queue_free (gv.gcreq_queue);
+ gcreq_queue_free (gv->gcreq_queue);
/* No new data gets added to any admin, all synchronous processing
has ended, so now we can drain the delivery queues to end up with
the expected reference counts all over the radmin thingummies. */
- nn_dqueue_free (gv.builtins_dqueue);
+ nn_dqueue_free (gv->builtins_dqueue);
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
- chptr = config.channels;
+ chptr = gv->config.channels;
while (chptr)
{
nn_dqueue_free (chptr->dqueue);
chptr = chptr->next;
}
#else
- nn_dqueue_free (gv.user_dqueue);
+ nn_dqueue_free (gv->user_dqueue);
#endif
- xeventq_free (gv.xevents);
+ xeventq_free (gv->xevents);
- if (config.xpack_send_async)
+ if (gv->config.xpack_send_async)
{
- nn_xpack_sendq_stop();
- nn_xpack_sendq_fini();
+ nn_xpack_sendq_stop (gv);
+ nn_xpack_sendq_fini (gv);
}
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
- chptr = config.channels;
+ chptr = gv->config.channels;
while (chptr)
{
if (chptr->evq)
{
xeventq_free (chptr->evq);
}
- if (chptr->transmit_conn != gv.data_conn_uc)
+ if (chptr->transmit_conn != gv->data_conn_uc)
{
ddsi_conn_free (chptr->transmit_conn);
}
@@ -1585,93 +1596,85 @@ void rtps_fini (void)
}
#endif
- ddsrt_thread_pool_free (gv.thread_pool);
+ ddsrt_thread_pool_free (gv->thread_pool);
- (void) joinleave_spdp_defmcip (0);
+ (void) joinleave_spdp_defmcip (gv, 0);
- ddsi_conn_free (gv.disc_conn_mc);
- if (gv.data_conn_mc != gv.disc_conn_mc)
- ddsi_conn_free (gv.data_conn_mc);
- if (gv.disc_conn_uc != gv.disc_conn_mc)
- ddsi_conn_free (gv.disc_conn_uc);
- if (gv.data_conn_uc != gv.disc_conn_uc)
- ddsi_conn_free (gv.data_conn_uc);
+ ddsi_conn_free (gv->disc_conn_mc);
+ if (gv->data_conn_mc != gv->disc_conn_mc)
+ ddsi_conn_free (gv->data_conn_mc);
+ if (gv->disc_conn_uc != gv->disc_conn_mc)
+ ddsi_conn_free (gv->disc_conn_uc);
+ if (gv->data_conn_uc != gv->disc_conn_uc)
+ ddsi_conn_free (gv->data_conn_uc);
- /* Not freeing gv.tev_conn: it aliases data_conn_uc */
+ /* Not freeing gv->tev_conn: it aliases data_conn_uc */
- free_group_membership(gv.mship);
- ddsi_tran_factories_fini ();
+ free_group_membership(gv->mship);
+ ddsi_tran_factories_fini (gv);
- if (gv.pcap_fp)
+ if (gv->pcap_fp)
{
- ddsrt_mutex_destroy (&gv.pcap_lock);
- fclose (gv.pcap_fp);
+ ddsrt_mutex_destroy (&gv->pcap_lock);
+ fclose (gv->pcap_fp);
}
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
- for (struct config_networkpartition_listelem *np = config.networkPartitions; np; np = np->next)
+ for (struct config_networkpartition_listelem *np = gv->config.networkPartitions; np; np = np->next)
unref_addrset (np->as);
#endif
- unref_addrset (gv.as_disc);
- unref_addrset (gv.as_disc_group);
+ unref_addrset (gv->as_disc);
+ unref_addrset (gv->as_disc_group);
/* Must delay freeing of rbufpools until after *all* references have
been dropped, which only happens once all receive threads have
stopped, defrags and reorders have been freed, and all delivery
queues been drained. I.e., until very late in the game. */
+ for (uint32_t i = 0; i < gv->n_recv_threads; i++)
{
- unsigned i;
- for (i = 0; i < gv.n_recv_threads; i++)
- {
- if (gv.recv_threads[i].arg.mode == RTM_MANY)
- os_sockWaitsetFree (gv.recv_threads[i].arg.u.many.ws);
- nn_rbufpool_free (gv.recv_threads[i].arg.rbpool);
- }
+ if (gv->recv_threads[i].arg.mode == RTM_MANY)
+ os_sockWaitsetFree (gv->recv_threads[i].arg.u.many.ws);
+ nn_rbufpool_free (gv->recv_threads[i].arg.rbpool);
}
- ddsi_tkmap_free (gv.m_tkmap);
+ ddsi_tkmap_free (gv->m_tkmap);
- ephash_free (gv.guid_hash);
- gv.guid_hash = NULL;
- deleted_participants_admin_fini ();
- lease_management_term ();
- ddsrt_mutex_destroy (&gv.participant_set_lock);
- ddsrt_cond_destroy (&gv.participant_set_cond);
- free_special_topics ();
+ ephash_free (gv->guid_hash);
+ gv->guid_hash = NULL;
+ deleted_participants_admin_free (gv->deleted_participants);
+ lease_management_term (gv);
+ ddsrt_mutex_destroy (&gv->participant_set_lock);
+ ddsrt_cond_destroy (&gv->participant_set_cond);
+ free_special_topics (gv);
- nn_xqos_fini (&gv.builtin_endpoint_xqos_wr);
- nn_xqos_fini (&gv.builtin_endpoint_xqos_rd);
- nn_xqos_fini (&gv.spdp_endpoint_xqos);
- nn_xqos_fini (&gv.default_xqos_pub);
- nn_xqos_fini (&gv.default_xqos_sub);
- nn_xqos_fini (&gv.default_xqos_tp);
- nn_xqos_fini (&gv.default_xqos_wr_nad);
- nn_xqos_fini (&gv.default_xqos_wr);
- nn_xqos_fini (&gv.default_xqos_rd);
- nn_plist_fini (&gv.default_plist_pp);
+ nn_xqos_fini (&gv->builtin_endpoint_xqos_wr);
+ nn_xqos_fini (&gv->builtin_endpoint_xqos_rd);
+ nn_xqos_fini (&gv->spdp_endpoint_xqos);
+ nn_xqos_fini (&gv->default_xqos_pub);
+ nn_xqos_fini (&gv->default_xqos_sub);
+ nn_xqos_fini (&gv->default_xqos_tp);
+ nn_xqos_fini (&gv->default_xqos_wr_nad);
+ nn_xqos_fini (&gv->default_xqos_wr);
+ nn_xqos_fini (&gv->default_xqos_rd);
+ nn_plist_fini (&gv->default_local_plist_pp);
+ nn_plist_fini (&gv->default_plist_pp);
- ddsrt_mutex_destroy (&gv.lock);
- ddsrt_rwlock_destroy (&gv.qoslock);
+ ddsrt_mutex_destroy (&gv->lock);
- while (gv.recvips)
+ while (gv->recvips)
{
- struct config_in_addr_node *n = gv.recvips;
-/* The compiler doesn't realize that n->next is always initialized. */
-DDSRT_WARNING_MSVC_OFF(6001);
- gv.recvips = n->next;
-DDSRT_WARNING_MSVC_ON(6001);
+ struct config_in_addr_node *n = gv->recvips;
+ /* The compiler doesn't realize that n->next is always initialized. */
+ DDSRT_WARNING_MSVC_OFF(6001);
+ gv->recvips = n->next;
+ DDSRT_WARNING_MSVC_ON(6001);
ddsrt_free (n);
}
- {
- int i;
- for (i = 0; i < (int) gv.n_interfaces; i++)
- ddsrt_free (gv.interfaces[i].name);
- }
+ for (int i = 0; i < (int) gv->n_interfaces; i++)
+ ddsrt_free (gv->interfaces[i].name);
- ddsi_serdatapool_free (gv.serpool);
- nn_xmsgpool_free (gv.xmsgpool);
- ddsi_iid_fini ();
- (ddsi_plugin.fini_fn) ();
- DDS_LOG(DDS_LC_CONFIG, "Finis.\n");
+ ddsi_serdatapool_free (gv->serpool);
+ nn_xmsgpool_free (gv->xmsgpool);
+ GVLOG (DDS_LC_CONFIG, "Finis.\n");
}
diff --git a/src/core/ddsi/src/q_lat_estim.c b/src/core/ddsi/src/q_lat_estim.c
index 2302b32..d451b41 100644
--- a/src/core/ddsi/src/q_lat_estim.c
+++ b/src/core/ddsi/src/q_lat_estim.c
@@ -56,7 +56,7 @@ void nn_lat_estim_update (struct nn_lat_estim *le, int64_t est)
le->smoothed = (1.0f - alpha) * le->smoothed + alpha * med;
}
-int nn_lat_estim_log (uint32_t logcat, const char *tag, const struct nn_lat_estim *le)
+int nn_lat_estim_log (uint32_t logcat, const struct ddsrt_log_cfg *logcfg, const char *tag, const struct nn_lat_estim *le)
{
if (le->smoothed == 0.0f)
return 0;
@@ -67,12 +67,12 @@ int nn_lat_estim_log (uint32_t logcat, const char *tag, const struct nn_lat_esti
memcpy (tmp, le->window, sizeof (tmp));
qsort (tmp, NN_LAT_ESTIM_MEDIAN_WINSZ, sizeof (tmp[0]), (int (*) (const void *, const void *)) cmpfloat);
if (tag)
- DDS_LOG(logcat, " LAT(%s: %e {", tag, le->smoothed);
+ DDS_CLOG (logcat, logcfg, " LAT(%s: %e {", tag, le->smoothed);
else
- DDS_LOG(logcat, " LAT(%e {", le->smoothed);
+ DDS_CLOG (logcat, logcfg, " LAT(%e {", le->smoothed);
for (i = 0; i < NN_LAT_ESTIM_MEDIAN_WINSZ; i++)
- DDS_LOG(logcat, "%s%e", (i > 0) ? "," : "", tmp[i]);
- DDS_LOG(logcat, "})");
+ DDS_CLOG (logcat, logcfg, "%s%e", (i > 0) ? "," : "", tmp[i]);
+ DDS_CLOG (logcat, logcfg, "})");
return 1;
}
}
diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c
index 4ec8892..85ccc92 100644
--- a/src/core/ddsi/src/q_lease.c
+++ b/src/core/ddsi/src/q_lease.c
@@ -45,9 +45,9 @@
struct lease {
ddsrt_fibheap_node_t heapnode;
- nn_etime_t tsched; /* access guarded by leaseheap_lock */
- nn_etime_t tend; /* access guarded by lock_lease/unlock_lease */
- int64_t tdur; /* constant (renew depends on it) */
+ nn_etime_t tsched; /* access guarded by leaseheap_lock */
+ ddsrt_atomic_uint64_t tend; /* really an nn_etime_t */
+ dds_duration_t tdur; /* constant (renew depends on it) */
struct entity_common *entity; /* constant */
};
@@ -55,9 +55,9 @@ static int compare_lease_tsched (const void *va, const void *vb);
static const ddsrt_fibheap_def_t lease_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct lease, heapnode), compare_lease_tsched);
-static void force_lease_check (void)
+static void force_lease_check (struct gcreq_queue *gcreq_queue)
{
- gcreq_enqueue(gcreq_new(gv.gcreq_queue, gcreq_free));
+ gcreq_enqueue (gcreq_new (gcreq_queue, gcreq_free));
}
static int compare_lease_tsched (const void *va, const void *vb)
@@ -67,173 +67,148 @@ static int compare_lease_tsched (const void *va, const void *vb)
return (a->tsched.v == b->tsched.v) ? 0 : (a->tsched.v < b->tsched.v) ? -1 : 1;
}
-void lease_management_init (void)
+void lease_management_init (struct q_globals *gv)
{
- int i;
- ddsrt_mutex_init (&gv.leaseheap_lock);
- for (i = 0; i < N_LEASE_LOCKS; i++)
- ddsrt_mutex_init (&gv.lease_locks[i]);
- ddsrt_fibheap_init (&lease_fhdef, &gv.leaseheap);
+ ddsrt_mutex_init (&gv->leaseheap_lock);
+ ddsrt_fibheap_init (&lease_fhdef, &gv->leaseheap);
}
-void lease_management_term (void)
+void lease_management_term (struct q_globals *gv)
{
- int i;
- assert (ddsrt_fibheap_min (&lease_fhdef, &gv.leaseheap) == NULL);
- for (i = 0; i < N_LEASE_LOCKS; i++)
- ddsrt_mutex_destroy (&gv.lease_locks[i]);
- ddsrt_mutex_destroy (&gv.leaseheap_lock);
+ assert (ddsrt_fibheap_min (&lease_fhdef, &gv->leaseheap) == NULL);
+ ddsrt_mutex_destroy (&gv->leaseheap_lock);
}
-static ddsrt_mutex_t *lock_lease_addr (struct lease const * const l)
-{
- uint32_t u = (uint16_t) ((uintptr_t) l >> 3);
- uint32_t v = u * 0xb4817365;
- unsigned idx = v >> (32 - N_LEASE_LOCKS_LG2);
- return &gv.lease_locks[idx];
-}
-
-static void lock_lease (const struct lease *l)
-{
- ddsrt_mutex_lock (lock_lease_addr (l));
-}
-
-static void unlock_lease (const struct lease *l)
-{
- ddsrt_mutex_unlock (lock_lease_addr (l));
-}
-
-struct lease *lease_new (nn_etime_t texpire, int64_t tdur, struct entity_common *e)
+struct lease *lease_new (nn_etime_t texpire, dds_duration_t tdur, struct entity_common *e)
{
struct lease *l;
if ((l = ddsrt_malloc (sizeof (*l))) == NULL)
return NULL;
- DDS_TRACE("lease_new(tdur %"PRId64" guid "PGUIDFMT") @ %p\n", tdur, PGUID (e->guid), (void *) l);
+ EETRACE (e, "lease_new(tdur %"PRId64" guid "PGUIDFMT") @ %p\n", tdur, PGUID (e->guid), (void *) l);
l->tdur = tdur;
- l->tend = texpire;
+ ddsrt_atomic_st64 (&l->tend, (uint64_t) texpire.v);
l->tsched.v = TSCHED_NOT_ON_HEAP;
l->entity = e;
return l;
}
-void lease_register (struct lease *l)
+void lease_register (struct lease *l) /* FIXME: make lease admin struct */
{
- DDS_TRACE("lease_register(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid));
- ddsrt_mutex_lock (&gv.leaseheap_lock);
- lock_lease (l);
+ struct q_globals * const gv = l->entity->gv;
+ GVTRACE ("lease_register(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid));
+ ddsrt_mutex_lock (&gv->leaseheap_lock);
assert (l->tsched.v == TSCHED_NOT_ON_HEAP);
- if (l->tend.v != T_NEVER)
+ int64_t tend = (int64_t) ddsrt_atomic_ld64 (&l->tend);
+ if (tend != T_NEVER)
{
- l->tsched = l->tend;
- ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l);
+ l->tsched.v = tend;
+ ddsrt_fibheap_insert (&lease_fhdef, &gv->leaseheap, l);
}
- unlock_lease (l);
- ddsrt_mutex_unlock (&gv.leaseheap_lock);
+ ddsrt_mutex_unlock (&gv->leaseheap_lock);
/* check_and_handle_lease_expiration runs on GC thread and the only way to be sure that it wakes up in time is by forcing re-evaluation (strictly speaking only needed if this is the first lease to expire, but this operation is quite rare anyway) */
- force_lease_check();
+ force_lease_check (gv->gcreq_queue);
}
void lease_free (struct lease *l)
{
- DDS_TRACE("lease_free(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid));
- ddsrt_mutex_lock (&gv.leaseheap_lock);
+ struct q_globals * const gv = l->entity->gv;
+ GVTRACE ("lease_free(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid));
+ ddsrt_mutex_lock (&gv->leaseheap_lock);
if (l->tsched.v != TSCHED_NOT_ON_HEAP)
- ddsrt_fibheap_delete (&lease_fhdef, &gv.leaseheap, l);
- ddsrt_mutex_unlock (&gv.leaseheap_lock);
+ ddsrt_fibheap_delete (&lease_fhdef, &gv->leaseheap, l);
+ ddsrt_mutex_unlock (&gv->leaseheap_lock);
ddsrt_free (l);
/* see lease_register() */
- force_lease_check();
+ force_lease_check (gv->gcreq_queue);
}
void lease_renew (struct lease *l, nn_etime_t tnowE)
{
+ struct q_globals const * const gv = l->entity->gv;
nn_etime_t tend_new = add_duration_to_etime (tnowE, l->tdur);
- int did_update;
- lock_lease (l);
- /* do not touch tend if moving forward or if already expired */
- if (tend_new.v <= l->tend.v || tnowE.v >= l->tend.v)
- did_update = 0;
- else
- {
- l->tend = tend_new;
- did_update = 1;
- }
- unlock_lease (l);
- if (did_update && (dds_get_log_mask() & DDS_LC_TRACE))
+ /* do not touch tend if moving forward or if already expired */
+ int64_t tend;
+ do {
+ tend = (int64_t) ddsrt_atomic_ld64 (&l->tend);
+ if (tend_new.v <= tend || tnowE.v >= tend)
+ return;
+ } while (!ddsrt_atomic_cas64 (&l->tend, (uint64_t) tend, (uint64_t) tend_new.v));
+
+ if (gv->logconfig.c.mask & DDS_LC_TRACE)
{
int32_t tsec, tusec;
- DDS_TRACE(" L(");
+ GVTRACE (" L(");
if (l->entity->guid.entityid.u == NN_ENTITYID_PARTICIPANT)
- DDS_TRACE(":%"PRIx32, l->entity->guid.entityid.u);
+ GVTRACE (":%"PRIx32, l->entity->guid.entityid.u);
else
- DDS_TRACE(""PGUIDFMT"", PGUID (l->entity->guid));
+ GVTRACE (""PGUIDFMT"", PGUID (l->entity->guid));
etime_to_sec_usec (&tsec, &tusec, tend_new);
- DDS_TRACE(" %"PRId32".%06"PRId32")", tsec, tusec);
+ GVTRACE (" %"PRId32".%06"PRId32")", tsec, tusec);
}
}
void lease_set_expiry (struct lease *l, nn_etime_t when)
{
+ struct q_globals * const gv = l->entity->gv;
bool trigger = false;
assert (when.v >= 0);
- ddsrt_mutex_lock (&gv.leaseheap_lock);
- lock_lease (l);
- l->tend = when;
- if (l->tend.v < l->tsched.v)
+ ddsrt_mutex_lock (&gv->leaseheap_lock);
+ /* only possible concurrent action is to move tend into the future (renew_lease),
+ all other operations occur with leaseheap_lock held */
+ ddsrt_atomic_st64 (&l->tend, (uint64_t) when.v);
+ if (when.v < l->tsched.v)
{
/* moved forward and currently scheduled (by virtue of
TSCHED_NOT_ON_HEAP == INT64_MIN) */
- l->tsched = l->tend;
- ddsrt_fibheap_decrease_key (&lease_fhdef, &gv.leaseheap, l);
+ l->tsched = when;
+ ddsrt_fibheap_decrease_key (&lease_fhdef, &gv->leaseheap, l);
trigger = true;
}
- else if (l->tsched.v == TSCHED_NOT_ON_HEAP && l->tend.v < T_NEVER)
+ else if (l->tsched.v == TSCHED_NOT_ON_HEAP && when.v < T_NEVER)
{
/* not currently scheduled, with a finite new expiry time */
- l->tsched = l->tend;
- ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l);
+ l->tsched = when;
+ ddsrt_fibheap_insert (&lease_fhdef, &gv->leaseheap, l);
trigger = true;
}
- unlock_lease (l);
- ddsrt_mutex_unlock (&gv.leaseheap_lock);
+ ddsrt_mutex_unlock (&gv->leaseheap_lock);
/* see lease_register() */
if (trigger)
- force_lease_check();
+ force_lease_check (gv->gcreq_queue);
}
-int64_t check_and_handle_lease_expiration (nn_etime_t tnowE)
+int64_t check_and_handle_lease_expiration (struct q_globals *gv, nn_etime_t tnowE)
{
struct lease *l;
int64_t delay;
- ddsrt_mutex_lock (&gv.leaseheap_lock);
- while ((l = ddsrt_fibheap_min (&lease_fhdef, &gv.leaseheap)) != NULL && l->tsched.v <= tnowE.v)
+ ddsrt_mutex_lock (&gv->leaseheap_lock);
+ while ((l = ddsrt_fibheap_min (&lease_fhdef, &gv->leaseheap)) != NULL && l->tsched.v <= tnowE.v)
{
nn_guid_t g = l->entity->guid;
enum entity_kind k = l->entity->kind;
assert (l->tsched.v != TSCHED_NOT_ON_HEAP);
- ddsrt_fibheap_extract_min (&lease_fhdef, &gv.leaseheap);
-
- lock_lease (l);
- if (tnowE.v < l->tend.v)
+ ddsrt_fibheap_extract_min (&lease_fhdef, &gv->leaseheap);
+ /* only possible concurrent action is to move tend into the future (renew_lease),
+ all other operations occur with leaseheap_lock held */
+ int64_t tend = (int64_t) ddsrt_atomic_ld64 (&l->tend);
+ if (tnowE.v < tend)
{
- if (l->tend.v == T_NEVER) {
+ if (tend == T_NEVER) {
/* don't reinsert if it won't expire */
l->tsched.v = TSCHED_NOT_ON_HEAP;
- unlock_lease (l);
} else {
- l->tsched = l->tend;
- unlock_lease (l);
- ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l);
+ l->tsched.v = tend;
+ ddsrt_fibheap_insert (&lease_fhdef, &gv->leaseheap, l);
}
continue;
}
- DDS_LOG(DDS_LC_DISCOVERY, "lease expired: l %p guid "PGUIDFMT" tend %"PRId64" < now %"PRId64"\n", (void *) l, PGUID (g), l->tend.v, tnowE.v);
+ GVLOGDISC ("lease expired: l %p guid "PGUIDFMT" tend %"PRId64" < now %"PRId64"\n", (void *) l, PGUID (g), tend, tnowE.v);
/* If the proxy participant is relying on another participant for
writing its discovery data (on the privileged participant,
@@ -263,108 +238,105 @@ int64_t check_and_handle_lease_expiration (nn_etime_t tnowE)
if (k == EK_PROXY_PARTICIPANT)
{
struct proxy_participant *proxypp;
- if ((proxypp = ephash_lookup_proxy_participant_guid (&g)) != NULL &&
- ephash_lookup_proxy_participant_guid (&proxypp->privileged_pp_guid) != NULL)
+ if ((proxypp = ephash_lookup_proxy_participant_guid (gv->guid_hash, &g)) != NULL &&
+ ephash_lookup_proxy_participant_guid (gv->guid_hash, &proxypp->privileged_pp_guid) != NULL)
{
- DDS_LOG(DDS_LC_DISCOVERY, "but postponing because privileged pp "PGUIDFMT" is still live\n",
- PGUID (proxypp->privileged_pp_guid));
- l->tsched = l->tend = add_duration_to_etime (tnowE, 200 * T_MILLISECOND);
- unlock_lease (l);
- ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l);
+ GVLOGDISC ("but postponing because privileged pp "PGUIDFMT" is still live\n", PGUID (proxypp->privileged_pp_guid));
+ l->tsched = add_duration_to_etime (tnowE, 200 * T_MILLISECOND);
+ ddsrt_fibheap_insert (&lease_fhdef, &gv->leaseheap, l);
continue;
}
}
- unlock_lease (l);
-
l->tsched.v = TSCHED_NOT_ON_HEAP;
- ddsrt_mutex_unlock (&gv.leaseheap_lock);
+ ddsrt_mutex_unlock (&gv->leaseheap_lock);
switch (k)
{
case EK_PARTICIPANT:
- delete_participant (&g);
+ delete_participant (gv, &g);
break;
case EK_PROXY_PARTICIPANT:
- delete_proxy_participant_by_guid (&g, now(), 1);
+ delete_proxy_participant_by_guid (gv, &g, now(), 1);
break;
case EK_WRITER:
- delete_writer_nolinger (&g);
+ delete_writer_nolinger (gv, &g);
break;
case EK_PROXY_WRITER:
- delete_proxy_writer (&g, now(), 1);
+ delete_proxy_writer (gv, &g, now(), 1);
break;
case EK_READER:
- (void)delete_reader (&g);
+ delete_reader (gv, &g);
break;
case EK_PROXY_READER:
- delete_proxy_reader (&g, now(), 1);
+ delete_proxy_reader (gv, &g, now(), 1);
break;
}
- ddsrt_mutex_lock (&gv.leaseheap_lock);
+ ddsrt_mutex_lock (&gv->leaseheap_lock);
}
delay = (l == NULL) ? T_NEVER : (l->tsched.v - tnowE.v);
- ddsrt_mutex_unlock (&gv.leaseheap_lock);
+ ddsrt_mutex_unlock (&gv->leaseheap_lock);
return delay;
}
/******/
-static void debug_print_rawdata (const char *msg, const void *data, size_t len)
+static void debug_print_rawdata (const struct q_globals *gv, const char *msg, const void *data, size_t len)
{
const unsigned char *c = data;
size_t i;
- DDS_TRACE("%s<", msg);
+ GVTRACE ("%s<", msg);
for (i = 0; i < len; i++)
{
if (32 < c[i] && c[i] <= 127)
- DDS_TRACE("%s%c", (i > 0 && (i%4) == 0) ? " " : "", c[i]);
+ GVTRACE ("%s%c", (i > 0 && (i%4) == 0) ? " " : "", c[i]);
else
- DDS_TRACE("%s\\x%02x", (i > 0 && (i%4) == 0) ? " " : "", c[i]);
+ GVTRACE ("%s\\x%02x", (i > 0 && (i%4) == 0) ? " " : "", c[i]);
}
- DDS_TRACE(">");
+ GVTRACE (">");
}
-void handle_PMD (UNUSED_ARG (const struct receiver_state *rst), nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len)
+void handle_PMD (const struct receiver_state *rst, nn_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len)
{
const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */
const int bswap = (data->identifier == CDR_LE) ^ (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN);
struct proxy_participant *pp;
nn_guid_t ppguid;
- DDS_TRACE(" PMD ST%x", statusinfo);
+ RSTTRACE (" PMD ST%x", statusinfo);
if (data->identifier != CDR_LE && data->identifier != CDR_BE)
{
- DDS_TRACE(" PMD data->identifier %u !?\n", ntohs (data->identifier));
+ RSTTRACE (" PMD data->identifier %u !?\n", ntohs (data->identifier));
return;
}
switch (statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER))
{
case 0:
if (offsetof (ParticipantMessageData_t, value) > len - sizeof (struct CDRHeader))
- debug_print_rawdata (" SHORT1", data, len);
+ debug_print_rawdata (rst->gv, " SHORT1", data, len);
else
{
const ParticipantMessageData_t *pmd = (ParticipantMessageData_t *) (data + 1);
nn_guid_prefix_t p = nn_ntoh_guid_prefix (pmd->participantGuidPrefix);
- unsigned kind = ntohl (pmd->kind);
- unsigned length = bswap ? bswap4u (pmd->length) : pmd->length;
- DDS_TRACE(" pp %"PRIx32":%"PRIx32":%"PRIx32" kind %u data %u", p.u[0], p.u[1], p.u[2], kind, length);
+ uint32_t kind = ntohl (pmd->kind);
+ uint32_t length = bswap ? bswap4u (pmd->length) : pmd->length;
+ RSTTRACE (" pp %"PRIx32":%"PRIx32":%"PRIx32" kind %u data %u", p.u[0], p.u[1], p.u[2], kind, length);
if (len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value) < length)
- debug_print_rawdata (" SHORT2", pmd->value, len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value));
+ debug_print_rawdata (rst->gv, " SHORT2", pmd->value, len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value));
else
- debug_print_rawdata ("", pmd->value, length);
+ debug_print_rawdata (rst->gv, "", pmd->value, length);
ppguid.prefix = p;
ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
- if ((pp = ephash_lookup_proxy_participant_guid (&ppguid)) == NULL)
- DDS_TRACE(" PPunknown");
+ if ((pp = ephash_lookup_proxy_participant_guid (rst->gv->guid_hash, &ppguid)) == NULL)
+ RSTTRACE (" PPunknown");
else
{
/* Renew lease if arrival of this message didn't already do so, also renew the lease
of the virtual participant used for DS-discovered endpoints */
- if (!config.arrival_of_data_asserts_pp_and_ep_liveliness)
- lease_renew (ddsrt_atomic_ldvoidp (&pp->lease), now_et ());
+#if 0 // FIXME: superfluous ... receipt of the message already did it */
+ lease_renew (ddsrt_atomic_ldvoidp (&pp->lease), now_et ());
+#endif
}
}
break;
@@ -374,18 +346,18 @@ void handle_PMD (UNUSED_ARG (const struct receiver_state *rst), nn_wctime_t time
case NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER:
/* Serialized key; BE or LE doesn't matter as both fields are
defined as octets. */
- if (len < (int) (sizeof (struct CDRHeader) + sizeof (nn_guid_prefix_t)))
- debug_print_rawdata (" SHORT3", data, len);
+ if (len < sizeof (struct CDRHeader) + sizeof (nn_guid_prefix_t))
+ debug_print_rawdata (rst->gv, " SHORT3", data, len);
else
{
ppguid.prefix = nn_ntoh_guid_prefix (*((nn_guid_prefix_t *) (data + 1)));
ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
- if (delete_proxy_participant_by_guid (&ppguid, timestamp, 0) < 0)
- DDS_TRACE(" unknown");
+ if (delete_proxy_participant_by_guid (rst->gv, &ppguid, timestamp, 0) < 0)
+ RSTTRACE (" unknown");
else
- DDS_TRACE(" delete");
+ RSTTRACE (" delete");
}
break;
}
- DDS_TRACE("\n");
+ RSTTRACE ("\n");
}
diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c
index 3f5ac27..bed0449 100644
--- a/src/core/ddsi/src/q_nwif.c
+++ b/src/core/ddsi/src/q_nwif.c
@@ -33,14 +33,14 @@
#include "dds/ddsi/ddsi_ipaddr.h"
#include "dds/ddsrt/avl.h"
-static void print_sockerror (const char *msg)
+static void print_sockerror (const struct ddsrt_log_cfg *logcfg, const char *msg)
{
- DDS_ERROR("SOCKET %s\n", msg);
+ DDS_CERROR (logcfg, "SOCKET %s\n", msg);
}
-unsigned locator_to_hopefully_unique_uint32 (const nn_locator_t *src)
+uint32_t locator_to_hopefully_unique_uint32 (const nn_locator_t *src)
{
- unsigned id = 0;
+ uint32_t id = 0;
if (src->kind == NN_LOCATOR_KIND_UDPv4 || src->kind == NN_LOCATOR_KIND_TCPv4)
memcpy (&id, src->address + 12, sizeof (id));
else
@@ -53,56 +53,62 @@ unsigned locator_to_hopefully_unique_uint32 (const nn_locator_t *src)
ddsrt_md5_finish (&st, digest);
memcpy (&id, digest, sizeof (id));
#else
- DDS_FATAL("IPv6 unavailable\n");
+ DDS_FATAL ("IPv6 unavailable\n");
#endif
}
return id;
}
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
-void set_socket_diffserv (ddsrt_socket_t sock, int diffserv)
+void set_socket_diffserv (const struct ddsrt_log_cfg *logcfg, ddsrt_socket_t sock, int diffserv)
{
if (ddsrt_setsockopt (sock, IPPROTO_IP, IP_TOS, (char*) &diffserv, sizeof (diffserv)) != DDS_RETCODE_OK)
{
- print_sockerror ("IP_TOS");
+ print_sockerror (logcfg, "IP_TOS");
}
}
#endif
#ifdef SO_NOSIGPIPE
-static void set_socket_nosigpipe (ddsrt_socket_t sock)
+static void set_socket_nosigpipe (const struct ddsrt_log_cfg *logcfg, ddsrt_socket_t sock)
{
int val = 1;
if (ddsrt_setsockopt (sock, SOL_SOCKET, SO_NOSIGPIPE, (char*) &val, sizeof (val)) != DDS_RETCODE_OK)
{
- print_sockerror ("SO_NOSIGPIPE");
+ print_sockerror (logcfg, "SO_NOSIGPIPE");
}
}
#endif
#ifdef TCP_NODELAY
-static void set_socket_nodelay (ddsrt_socket_t sock)
+static void set_socket_nodelay (const struct ddsrt_log_cfg *logcfg, ddsrt_socket_t sock)
{
int val = 1;
if (ddsrt_setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, (char*) &val, sizeof (val)) != DDS_RETCODE_OK)
{
- print_sockerror ("TCP_NODELAY");
+ print_sockerror (logcfg, "TCP_NODELAY");
}
}
#endif
-static int set_rcvbuf (ddsrt_socket_t socket)
+static int set_rcvbuf (const struct ddsrt_log_cfg *logcfg, ddsrt_socket_t socket, const struct config_maybe_uint32 *min_size)
{
uint32_t ReceiveBufferSize;
socklen_t optlen = (socklen_t) sizeof (ReceiveBufferSize);
uint32_t socket_min_rcvbuf_size;
- if (config.socket_min_rcvbuf_size.isdefault)
+ dds_return_t rc;
+ if (min_size->isdefault)
socket_min_rcvbuf_size = 1048576;
else
- socket_min_rcvbuf_size = config.socket_min_rcvbuf_size.value;
- if (ddsrt_getsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) &ReceiveBufferSize, &optlen) != DDS_RETCODE_OK)
- {
- print_sockerror ("get SO_RCVBUF");
+ socket_min_rcvbuf_size = min_size->value;
+ rc = ddsrt_getsockopt(
+ socket, SOL_SOCKET, SO_RCVBUF, (char *) &ReceiveBufferSize, &optlen);
+ /* TCP/IP stack may not support SO_RCVBUF. */
+ if (rc == DDS_RETCODE_BAD_PARAMETER) {
+ DDS_CLOG (DDS_LC_CONFIG, logcfg, "cannot retrieve socket receive buffer size\n");
+ return 0;
+ } else if (rc != DDS_RETCODE_OK) {
+ print_sockerror (logcfg, "get SO_RCVBUF");
return -2;
}
if (ReceiveBufferSize < socket_min_rcvbuf_size)
@@ -116,69 +122,73 @@ static int set_rcvbuf (ddsrt_socket_t socket)
the option value back and check it is now set correctly. */
if (ddsrt_getsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) &ReceiveBufferSize, &optlen) != DDS_RETCODE_OK)
{
- print_sockerror ("get SO_RCVBUF");
+ print_sockerror (logcfg, "get SO_RCVBUF");
return -2;
}
if (ReceiveBufferSize < socket_min_rcvbuf_size)
{
/* NN_ERROR does more than just DDS_ERROR(), hence the duplication */
- if (config.socket_min_rcvbuf_size.isdefault)
- DDS_LOG(DDS_LC_CONFIG, "failed to increase socket receive buffer size to %"PRIu32" bytes, continuing with %"PRIu32" bytes\n", socket_min_rcvbuf_size, ReceiveBufferSize);
- else
- DDS_ERROR("failed to increase socket receive buffer size to %"PRIu32" bytes, continuing with %"PRIu32" bytes\n", socket_min_rcvbuf_size, ReceiveBufferSize);
+ DDS_CLOG (min_size->isdefault ? DDS_LC_CONFIG : DDS_LC_ERROR, logcfg,
+ "failed to increase socket receive buffer size to %"PRIu32" bytes, continuing with %"PRIu32" bytes\n",
+ socket_min_rcvbuf_size, ReceiveBufferSize);
}
else
{
- DDS_LOG(DDS_LC_CONFIG, "socket receive buffer size set to %"PRIu32" bytes\n", ReceiveBufferSize);
+ DDS_CLOG (DDS_LC_CONFIG, logcfg, "socket receive buffer size set to %"PRIu32" bytes\n", ReceiveBufferSize);
}
}
return 0;
}
-static int set_sndbuf (ddsrt_socket_t socket)
+static int set_sndbuf (const struct ddsrt_log_cfg *logcfg, ddsrt_socket_t socket, uint32_t min_size)
{
unsigned SendBufferSize;
socklen_t optlen = (socklen_t) sizeof(SendBufferSize);
- if (ddsrt_getsockopt(socket, SOL_SOCKET, SO_SNDBUF,(char *)&SendBufferSize, &optlen) != DDS_RETCODE_OK)
- {
- print_sockerror ("get SO_SNDBUF");
+ dds_return_t rc;
+ rc = ddsrt_getsockopt(
+ socket, SOL_SOCKET, SO_SNDBUF,(char *)&SendBufferSize, &optlen);
+ if (rc == DDS_RETCODE_BAD_PARAMETER) {
+ DDS_CLOG (DDS_LC_CONFIG, logcfg, "cannot retrieve socket send buffer size\n");
+ return 0;
+ } else if (rc != DDS_RETCODE_OK) {
+ print_sockerror (logcfg, "get SO_SNDBUF");
return -2;
}
- if (SendBufferSize < config.socket_min_sndbuf_size )
+ if (SendBufferSize < min_size )
{
/* make sure the send buffersize is at least the minimum required */
- SendBufferSize = config.socket_min_sndbuf_size;
+ SendBufferSize = min_size;
if (ddsrt_setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (const char *)&SendBufferSize, sizeof (SendBufferSize)) != DDS_RETCODE_OK)
{
- print_sockerror ("SO_SNDBUF");
+ print_sockerror (logcfg, "SO_SNDBUF");
return -2;
}
}
return 0;
}
-static int maybe_set_dont_route (ddsrt_socket_t socket)
+static int maybe_set_dont_route (const struct ddsrt_log_cfg *logcfg, ddsrt_socket_t socket, const struct config *config)
{
- if (config.dontRoute)
+ if (config->dontRoute)
{
#if DDSRT_HAVE_IPV6
- if (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6)
+ if (config->transport_selector == TRANS_TCP6 || config->transport_selector == TRANS_UDP6)
{
unsigned ipv6Flag = 1;
if (ddsrt_setsockopt (socket, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ipv6Flag, sizeof (ipv6Flag)) != DDS_RETCODE_OK)
{
- print_sockerror ("IPV6_UNICAST_HOPS");
+ print_sockerror (logcfg, "IPV6_UNICAST_HOPS");
return -2;
}
}
else
#endif
- if (config.transport_selector == TRANS_TCP || config.transport_selector == TRANS_UDP)
+ if (config->transport_selector == TRANS_TCP || config->transport_selector == TRANS_UDP)
{
int one = 1;
if (ddsrt_setsockopt (socket, SOL_SOCKET, SO_DONTROUTE, (char *) &one, sizeof (one)) != DDS_RETCODE_OK)
{
- print_sockerror ("SO_DONTROUTE");
+ print_sockerror (logcfg, "SO_DONTROUTE");
return -2;
}
}
@@ -186,26 +196,30 @@ static int maybe_set_dont_route (ddsrt_socket_t socket)
return 0;
}
-static int set_reuse_options (ddsrt_socket_t socket)
+static int set_reuse_options (const struct ddsrt_log_cfg *logcfg, ddsrt_socket_t socket)
{
/* Set REUSEADDR (if available on platform) for
multicast sockets, leave unicast sockets alone. */
int one = 1;
-
- if (ddsrt_setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof (one)) != DDS_RETCODE_OK)
- {
- print_sockerror ("SO_REUSEADDR");
+ dds_return_t rc = ddsrt_setsockopt (
+ socket, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof (one));
+ if (rc == DDS_RETCODE_BAD_PARAMETER) {
+ DDS_CLOG (DDS_LC_CONFIG, logcfg, "cannot enable address reuse on socket\n");
+ return 0;
+ } else if (rc != DDS_RETCODE_OK) {
+ print_sockerror (logcfg, "SO_REUSEADDR");
return -2;
}
+
return 0;
}
-static int bind_socket (ddsrt_socket_t socket, unsigned short port)
+static int bind_socket (ddsrt_socket_t socket, unsigned short port, const struct q_globals *gv)
{
- dds_retcode_t rc = DDS_RETCODE_ERROR;
+ dds_return_t rc = DDS_RETCODE_ERROR;
#if DDSRT_HAVE_IPV6
- if (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6)
+ if (gv->config.transport_selector == TRANS_TCP6 || gv->config.transport_selector == TRANS_UDP6)
{
struct sockaddr_in6 socketname;
memset (&socketname, 0, sizeof (socketname));
@@ -213,13 +227,13 @@ static int bind_socket (ddsrt_socket_t socket, unsigned short port)
socketname.sin6_port = htons (port);
socketname.sin6_addr = ddsrt_in6addr_any;
if (IN6_IS_ADDR_LINKLOCAL (&socketname.sin6_addr)) {
- socketname.sin6_scope_id = gv.interfaceNo;
+ socketname.sin6_scope_id = gv->interfaceNo;
}
rc = ddsrt_bind (socket, (struct sockaddr *) &socketname, sizeof (socketname));
}
else
#endif
- if (config.transport_selector == TRANS_TCP || config.transport_selector == TRANS_UDP)
+ if (gv->config.transport_selector == TRANS_TCP || gv->config.transport_selector == TRANS_UDP)
{
struct sockaddr_in socketname;
socketname.sin_family = AF_INET;
@@ -229,94 +243,94 @@ static int bind_socket (ddsrt_socket_t socket, unsigned short port)
}
if (rc != DDS_RETCODE_OK && rc != DDS_RETCODE_PRECONDITION_NOT_MET)
{
- print_sockerror ("bind");
+ print_sockerror (&gv->logconfig, "bind");
}
return (rc == DDS_RETCODE_OK) ? 0 : -1;
}
#if DDSRT_HAVE_IPV6
-static int set_mc_options_transmit_ipv6 (ddsrt_socket_t socket)
+static int set_mc_options_transmit_ipv6 (ddsrt_socket_t socket, const struct q_globals *gv)
{
- unsigned interfaceNo = gv.interfaceNo;
- unsigned ttl = (unsigned) config.multicast_ttl;
+ unsigned interfaceNo = gv->interfaceNo;
+ unsigned ttl = (unsigned) gv->config.multicast_ttl;
unsigned loop;
if (ddsrt_setsockopt (socket, IPPROTO_IPV6, IPV6_MULTICAST_IF, &interfaceNo, sizeof (interfaceNo)) != DDS_RETCODE_OK)
{
- print_sockerror ("IPV6_MULTICAST_IF");
+ print_sockerror (&gv->logconfig, "IPV6_MULTICAST_IF");
return -2;
}
if (ddsrt_setsockopt (socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &ttl, sizeof (ttl)) != DDS_RETCODE_OK)
{
- print_sockerror ("IPV6_MULTICAST_HOPS");
+ print_sockerror (&gv->logconfig, "IPV6_MULTICAST_HOPS");
return -2;
}
- loop = (unsigned) !!config.enableMulticastLoopback;
+ loop = (unsigned) !!gv->config.enableMulticastLoopback;
if (ddsrt_setsockopt (socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof (loop)) != DDS_RETCODE_OK)
{
- print_sockerror ("IPV6_MULTICAST_LOOP");
+ print_sockerror (&gv->logconfig, "IPV6_MULTICAST_LOOP");
return -2;
}
return 0;
}
#endif
-static int set_mc_options_transmit_ipv4 (ddsrt_socket_t socket)
+static int set_mc_options_transmit_ipv4 (ddsrt_socket_t socket, const struct q_globals *gv)
{
- unsigned char ttl = (unsigned char) config.multicast_ttl;
+ unsigned char ttl = (unsigned char) gv->config.multicast_ttl;
unsigned char loop;
- dds_retcode_t ret;
+ dds_return_t ret;
-#if defined __linux || defined __APPLE__
- if (config.use_multicast_if_mreqn)
+#if (defined(__linux) || defined(__APPLE__)) && !LWIP_SOCKET
+ if (gv->config.use_multicast_if_mreqn)
{
struct ip_mreqn mreqn;
memset (&mreqn, 0, sizeof (mreqn));
/* looks like imr_multiaddr is not relevant, not sure about imr_address */
mreqn.imr_multiaddr.s_addr = htonl (INADDR_ANY);
- if (config.use_multicast_if_mreqn > 1)
- memcpy (&mreqn.imr_address.s_addr, gv.ownloc.address + 12, 4);
+ if (gv->config.use_multicast_if_mreqn > 1)
+ memcpy (&mreqn.imr_address.s_addr, gv->ownloc.address + 12, 4);
else
mreqn.imr_address.s_addr = htonl (INADDR_ANY);
- mreqn.imr_ifindex = (int) gv.interfaceNo;
+ mreqn.imr_ifindex = (int) gv->interfaceNo;
ret = ddsrt_setsockopt (socket, IPPROTO_IP, IP_MULTICAST_IF, &mreqn, sizeof (mreqn));
}
else
#endif
{
- ret = ddsrt_setsockopt (socket, IPPROTO_IP, IP_MULTICAST_IF, gv.ownloc.address + 12, 4);
+ ret = ddsrt_setsockopt (socket, IPPROTO_IP, IP_MULTICAST_IF, gv->ownloc.address + 12, 4);
}
if (ret != DDS_RETCODE_OK)
{
- print_sockerror ("IP_MULTICAST_IF");
+ print_sockerror (&gv->logconfig, "IP_MULTICAST_IF");
return -2;
}
if (ddsrt_setsockopt (socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &ttl, sizeof (ttl)) != DDS_RETCODE_OK)
{
- print_sockerror ("IP_MULICAST_TTL");
+ print_sockerror (&gv->logconfig, "IP_MULICAST_TTL");
return -2;
}
- loop = (unsigned char) config.enableMulticastLoopback;
+ loop = (unsigned char) gv->config.enableMulticastLoopback;
if (ddsrt_setsockopt (socket, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof (loop)) != DDS_RETCODE_OK)
{
- print_sockerror ("IP_MULTICAST_LOOP");
+ print_sockerror (&gv->logconfig, "IP_MULTICAST_LOOP");
return -2;
}
return 0;
}
-static int set_mc_options_transmit (ddsrt_socket_t socket)
+static int set_mc_options_transmit (ddsrt_socket_t socket, const struct q_globals *gv)
{
#if DDSRT_HAVE_IPV6
- if (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6)
+ if (gv->config.transport_selector == TRANS_TCP6 || gv->config.transport_selector == TRANS_UDP6)
{
- return set_mc_options_transmit_ipv6 (socket);
+ return set_mc_options_transmit_ipv6 (socket, gv);
}
else
#endif
- if (config.transport_selector == TRANS_TCP || config.transport_selector == TRANS_UDP)
+ if (gv->config.transport_selector == TRANS_TCP || gv->config.transport_selector == TRANS_UDP)
{
- return set_mc_options_transmit_ipv4 (socket);
+ return set_mc_options_transmit_ipv4 (socket, gv);
}
else
{
@@ -324,25 +338,20 @@ static int set_mc_options_transmit (ddsrt_socket_t socket)
}
}
-int make_socket
-(
- ddsrt_socket_t * sock,
- unsigned short port,
- bool stream,
- bool reuse
-)
+int make_socket (ddsrt_socket_t *sock, uint16_t port, bool stream, bool reuse, const struct q_globals *gv)
{
+ /* FIXME: this stuff has to move to the transports */
int rc = -2;
- dds_retcode_t ret;
+ dds_return_t ret;
#if DDSRT_HAVE_IPV6
- if (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6)
+ if (gv->config.transport_selector == TRANS_TCP6 || gv->config.transport_selector == TRANS_UDP6)
{
ret = ddsrt_socket(sock, AF_INET6, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
}
else
#endif
- if (config.transport_selector == TRANS_TCP || config.transport_selector == TRANS_UDP)
+ if (gv->config.transport_selector == TRANS_TCP || gv->config.transport_selector == TRANS_UDP)
{
ret = ddsrt_socket(sock, AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
}
@@ -353,21 +362,21 @@ int make_socket
if (ret != DDS_RETCODE_OK)
{
- print_sockerror ("socket");
+ print_sockerror (&gv->logconfig, "socket");
return rc;
}
- if (port && reuse && ((rc = set_reuse_options (*sock)) < 0))
+ if (port && reuse && ((rc = set_reuse_options (&gv->logconfig, *sock)) < 0))
{
goto fail;
}
if
(
- (rc = set_rcvbuf (*sock) < 0) ||
- (rc = set_sndbuf (*sock) < 0) ||
- ((rc = maybe_set_dont_route (*sock)) < 0) ||
- ((rc = bind_socket (*sock, port)) < 0)
+ (rc = set_rcvbuf (&gv->logconfig, *sock, &gv->config.socket_min_rcvbuf_size) < 0) ||
+ (rc = set_sndbuf (&gv->logconfig, *sock, gv->config.socket_min_sndbuf_size) < 0) ||
+ ((rc = maybe_set_dont_route (&gv->logconfig, *sock, &gv->config)) < 0) ||
+ ((rc = bind_socket (*sock, port, gv)) < 0)
)
{
goto fail;
@@ -375,7 +384,7 @@ int make_socket
if (! stream)
{
- if ((rc = set_mc_options_transmit (*sock)) < 0)
+ if ((rc = set_mc_options_transmit (*sock, gv)) < 0)
{
goto fail;
}
@@ -384,12 +393,12 @@ int make_socket
if (stream)
{
#ifdef SO_NOSIGPIPE
- set_socket_nosigpipe (*sock);
+ set_socket_nosigpipe (&gv->logconfig, *sock);
#endif
#ifdef TCP_NODELAY
- if (config.tcp_nodelay)
+ if (gv->config.tcp_nodelay)
{
- set_socket_nodelay (*sock);
+ set_socket_nodelay (&gv->logconfig, *sock);
}
#endif
}
@@ -403,9 +412,9 @@ fail:
return rc;
}
-static int multicast_override(const char *ifname)
+static int multicast_override(const char *ifname, const struct config *config)
{
- char *copy = ddsrt_strdup (config.assumeMulticastCapable), *cursor = copy, *tok;
+ char *copy = ddsrt_strdup (config->assumeMulticastCapable), *cursor = copy, *tok;
int match = 0;
if (copy != NULL)
{
@@ -424,7 +433,7 @@ static int multicast_override(const char *ifname)
#include
#endif
-int find_own_ip (const char *requested_address)
+int find_own_ip (struct q_globals *gv, const char *requested_address)
{
const char *sep = " ";
char last_if_name[80] = "";
@@ -437,18 +446,18 @@ int find_own_ip (const char *requested_address)
int selected_idx = -1;
char addrbuf[DDSI_LOCSTRLEN];
- DDS_LOG(DDS_LC_CONFIG, "interfaces:");
+ GVLOG (DDS_LC_CONFIG, "interfaces:");
{
int ret;
- ret = ddsi_enumerate_interfaces(gv.m_factory, &ifa_root);
+ ret = ddsi_enumerate_interfaces(gv->m_factory, gv->config.transport_selector, &ifa_root);
if (ret < 0) {
- DDS_ERROR("ddsi_enumerate_interfaces(%s): %d\n", gv.m_factory->m_typename, ret);
+ GVERROR ("ddsi_enumerate_interfaces(%s): %d\n", gv->m_factory->m_typename, ret);
return 0;
}
}
- gv.n_interfaces = 0;
+ gv->n_interfaces = 0;
last_if_name[0] = 0;
for (ifa = ifa_root; ifa != NULL; ifa = ifa->next)
{
@@ -458,23 +467,35 @@ int find_own_ip (const char *requested_address)
ddsrt_strlcpy(if_name, ifa->name, sizeof(if_name));
if (strcmp (if_name, last_if_name))
- DDS_LOG(DDS_LC_CONFIG, "%s%s", sep, if_name);
+ GVLOG (DDS_LC_CONFIG, "%s%s", sep, if_name);
ddsrt_strlcpy(last_if_name, if_name, sizeof(last_if_name));
/* interface must be up */
if ((ifa->flags & IFF_UP) == 0) {
- DDS_LOG(DDS_LC_CONFIG, " (interface down)");
+ GVLOG (DDS_LC_CONFIG, " (interface down)");
continue;
} else if (ddsrt_sockaddr_isunspecified(ifa->addr)) {
- DDS_LOG(DDS_LC_CONFIG, " (address unspecified)");
+ GVLOG (DDS_LC_CONFIG, " (address unspecified)");
continue;
}
-#ifdef __linux
+ switch (ifa->type)
+ {
+ case DDSRT_IFTYPE_WIFI:
+ DDS_LOG(DDS_LC_CONFIG, " wireless");
+ break;
+ case DDSRT_IFTYPE_WIRED:
+ DDS_LOG(DDS_LC_CONFIG, " wired");
+ break;
+ case DDSRT_IFTYPE_UNKNOWN:
+ break;
+ }
+
+#if defined(__linux) && !LWIP_SOCKET
if (ifa->addr->sa_family == AF_PACKET)
{
/* FIXME: weirdo warning warranted */
- nn_locator_t *l = &gv.interfaces[gv.n_interfaces].loc;
+ nn_locator_t *l = &gv->interfaces[gv->n_interfaces].loc;
l->kind = NN_LOCATOR_KIND_RAWETH;
l->port = NN_LOCATOR_PORT_INVALID;
memset(l->address, 0, 10);
@@ -483,14 +504,14 @@ int find_own_ip (const char *requested_address)
else
#endif
{
- ddsi_ipaddr_to_loc(&gv.interfaces[gv.n_interfaces].loc, ifa->addr, gv.m_factory->m_kind);
+ ddsi_ipaddr_to_loc(&gv->interfaces[gv->n_interfaces].loc, ifa->addr, gv->m_factory->m_kind);
}
- ddsi_locator_to_string_no_port(addrbuf, sizeof(addrbuf), &gv.interfaces[gv.n_interfaces].loc);
- DDS_LOG(DDS_LC_CONFIG, " %s(", addrbuf);
+ ddsi_locator_to_string_no_port(gv, addrbuf, sizeof(addrbuf), &gv->interfaces[gv->n_interfaces].loc);
+ GVLOG (DDS_LC_CONFIG, " %s(", addrbuf);
- if (!(ifa->flags & IFF_MULTICAST) && multicast_override (if_name))
+ if (!(ifa->flags & IFF_MULTICAST) && multicast_override (if_name, &gv->config))
{
- DDS_LOG(DDS_LC_CONFIG, "assume-mc:");
+ GVLOG (DDS_LC_CONFIG, "assume-mc:");
ifa->flags |= IFF_MULTICAST;
}
@@ -533,13 +554,13 @@ int find_own_ip (const char *requested_address)
q += 2;
}
- DDS_LOG(DDS_LC_CONFIG, "q%d)", q);
+ GVLOG (DDS_LC_CONFIG, "q%d)", q);
if (q == quality) {
- maxq_list[maxq_count] = gv.n_interfaces;
+ maxq_list[maxq_count] = gv->n_interfaces;
maxq_strlen += 2 + strlen (if_name);
maxq_count++;
} else if (q > quality) {
- maxq_list[0] = gv.n_interfaces;
+ maxq_list[0] = gv->n_interfaces;
maxq_strlen += 2 + strlen (if_name);
maxq_count = 1;
quality = q;
@@ -547,21 +568,22 @@ int find_own_ip (const char *requested_address)
if (ifa->addr->sa_family == AF_INET && ifa->netmask)
{
- ddsi_ipaddr_to_loc(&gv.interfaces[gv.n_interfaces].netmask, ifa->netmask, gv.m_factory->m_kind);
+ ddsi_ipaddr_to_loc(&gv->interfaces[gv->n_interfaces].netmask, ifa->netmask, gv->m_factory->m_kind);
}
else
{
- gv.interfaces[gv.n_interfaces].netmask.kind = gv.m_factory->m_kind;
- gv.interfaces[gv.n_interfaces].netmask.port = NN_LOCATOR_PORT_INVALID;
- memset(&gv.interfaces[gv.n_interfaces].netmask.address, 0, sizeof(gv.interfaces[gv.n_interfaces].netmask.address));
+ gv->interfaces[gv->n_interfaces].netmask.kind = gv->m_factory->m_kind;
+ gv->interfaces[gv->n_interfaces].netmask.port = NN_LOCATOR_PORT_INVALID;
+ memset(&gv->interfaces[gv->n_interfaces].netmask.address, 0, sizeof(gv->interfaces[gv->n_interfaces].netmask.address));
}
- gv.interfaces[gv.n_interfaces].mc_capable = ((ifa->flags & IFF_MULTICAST) != 0);
- gv.interfaces[gv.n_interfaces].point_to_point = ((ifa->flags & IFF_POINTOPOINT) != 0);
- gv.interfaces[gv.n_interfaces].if_index = ifa->index;
- gv.interfaces[gv.n_interfaces].name = ddsrt_strdup (if_name);
- gv.n_interfaces++;
+ gv->interfaces[gv->n_interfaces].mc_capable = ((ifa->flags & IFF_MULTICAST) != 0);
+ gv->interfaces[gv->n_interfaces].mc_flaky = ((ifa->type == DDSRT_IFTYPE_WIFI) != 0);
+ gv->interfaces[gv->n_interfaces].point_to_point = ((ifa->flags & IFF_POINTOPOINT) != 0);
+ gv->interfaces[gv->n_interfaces].if_index = ifa->index;
+ gv->interfaces[gv->n_interfaces].name = ddsrt_strdup (if_name);
+ gv->n_interfaces++;
}
- DDS_LOG(DDS_LC_CONFIG, "\n");
+ GVLOG (DDS_LC_CONFIG, "\n");
ddsrt_freeifaddrs (ifa_root);
if (requested_address == NULL)
@@ -571,51 +593,51 @@ int find_own_ip (const char *requested_address)
const int idx = maxq_list[0];
char *names;
int p;
- ddsi_locator_to_string_no_port (addrbuf, sizeof(addrbuf), &gv.interfaces[idx].loc);
+ ddsi_locator_to_string_no_port (gv, addrbuf, sizeof(addrbuf), &gv->interfaces[idx].loc);
names = ddsrt_malloc (maxq_strlen + 1);
p = 0;
for (i = 0; i < maxq_count && (size_t) p < maxq_strlen; i++)
- p += snprintf (names + p, maxq_strlen - (size_t) p, ", %s", gv.interfaces[maxq_list[i]].name);
- DDS_WARNING("using network interface %s (%s) selected arbitrarily from: %s\n",
- gv.interfaces[idx].name, addrbuf, names + 2);
+ p += snprintf (names + p, maxq_strlen - (size_t) p, ", %s", gv->interfaces[maxq_list[i]].name);
+ GVWARNING ("using network interface %s (%s) selected arbitrarily from: %s\n",
+ gv->interfaces[idx].name, addrbuf, names + 2);
ddsrt_free (names);
}
if (maxq_count > 0)
selected_idx = maxq_list[0];
else
- DDS_ERROR("failed to determine default own IP address\n");
+ GVERROR ("failed to determine default own IP address\n");
}
else
{
nn_locator_t req;
/* Presumably an interface name */
- for (i = 0; i < gv.n_interfaces; i++)
+ for (i = 0; i < gv->n_interfaces; i++)
{
- if (strcmp (gv.interfaces[i].name, config.networkAddressString) == 0)
+ if (strcmp (gv->interfaces[i].name, gv->config.networkAddressString) == 0)
break;
}
- if (i < gv.n_interfaces)
+ if (i < gv->n_interfaces)
; /* got a match */
- else if (ddsi_locator_from_string(&req, config.networkAddressString) != AFSR_OK)
- ; /* not good, i = gv.n_interfaces, so error handling will kick in */
+ else if (ddsi_locator_from_string(gv, &req, gv->config.networkAddressString, gv->m_factory) != AFSR_OK)
+ ; /* not good, i = gv->n_interfaces, so error handling will kick in */
else
{
/* Try an exact match on the address */
- for (i = 0; i < gv.n_interfaces; i++)
- if (compare_locators(&gv.interfaces[i].loc, &req) == 0)
+ for (i = 0; i < gv->n_interfaces; i++)
+ if (compare_locators(&gv->interfaces[i].loc, &req) == 0)
break;
- if (i == gv.n_interfaces && req.kind == NN_LOCATOR_KIND_UDPv4)
+ if (i == gv->n_interfaces && req.kind == NN_LOCATOR_KIND_UDPv4)
{
/* Try matching on network portion only, where the network
portion is based on the netmask of the interface under
consideration */
- for (i = 0; i < gv.n_interfaces; i++)
+ for (i = 0; i < gv->n_interfaces; i++)
{
uint32_t req1, ip1, nm1;
memcpy (&req1, req.address + 12, sizeof (req1));
- memcpy (&ip1, gv.interfaces[i].loc.address + 12, sizeof (ip1));
- memcpy (&nm1, gv.interfaces[i].netmask.address + 12, sizeof (nm1));
+ memcpy (&ip1, gv->interfaces[i].loc.address + 12, sizeof (ip1));
+ memcpy (&nm1, gv->interfaces[i].netmask.address + 12, sizeof (nm1));
/* If the host portion of the requested address is non-zero,
skip this interface */
@@ -628,33 +650,33 @@ int find_own_ip (const char *requested_address)
}
}
- if (i < gv.n_interfaces)
+ if (i < gv->n_interfaces)
selected_idx = i;
else
- DDS_ERROR("%s: does not match an available interface\n", config.networkAddressString);
+ GVERROR ("%s: does not match an available interface\n", gv->config.networkAddressString);
}
if (selected_idx < 0)
return 0;
else
{
- gv.ownloc = gv.interfaces[selected_idx].loc;
- gv.selected_interface = selected_idx;
- gv.interfaceNo = gv.interfaces[selected_idx].if_index;
+ gv->ownloc = gv->interfaces[selected_idx].loc;
+ gv->selected_interface = selected_idx;
+ gv->interfaceNo = gv->interfaces[selected_idx].if_index;
#if DDSRT_HAVE_IPV6
- if (gv.extloc.kind == NN_LOCATOR_KIND_TCPv6 || gv.extloc.kind == NN_LOCATOR_KIND_UDPv6)
+ if (gv->extloc.kind == NN_LOCATOR_KIND_TCPv6 || gv->extloc.kind == NN_LOCATOR_KIND_UDPv6)
{
struct sockaddr_in6 addr;
- memcpy(&addr.sin6_addr, gv.ownloc.address, sizeof(addr.sin6_addr));
- gv.ipv6_link_local = IN6_IS_ADDR_LINKLOCAL (&addr.sin6_addr) != 0;
+ memcpy(&addr.sin6_addr, gv->ownloc.address, sizeof(addr.sin6_addr));
+ gv->ipv6_link_local = IN6_IS_ADDR_LINKLOCAL (&addr.sin6_addr) != 0;
}
else
{
- gv.ipv6_link_local = 0;
+ gv->ipv6_link_local = 0;
}
#endif
- DDS_LOG(DDS_LC_CONFIG, "selected interface: %s (index %u)\n",
- gv.interfaces[selected_idx].name, gv.interfaceNo);
+ GVLOG (DDS_LC_CONFIG, "selected interface: %s (index %u)\n",
+ gv->interfaces[selected_idx].name, gv->interfaceNo);
return 1;
}
diff --git a/src/core/ddsi/src/q_pcap.c b/src/core/ddsi/src/q_pcap.c
index c48e636..3fb0e68 100644
--- a/src/core/ddsi/src/q_pcap.c
+++ b/src/core/ddsi/src/q_pcap.c
@@ -77,15 +77,15 @@ static const ipv4_hdr_t ipv4_hdr_template = {
#define IPV4_HDR_SIZE 20
#define UDP_HDR_SIZE 8
-DDSRT_WARNING_MSVC_OFF(4996);
-FILE *new_pcap_file (const char *name)
+FILE *new_pcap_file (const struct ddsrt_log_cfg *logcfg, const char *name)
{
+ DDSRT_WARNING_MSVC_OFF(4996);
FILE *fp;
pcap_hdr_t hdr;
if ((fp = fopen (name, "wb")) == NULL)
{
- DDS_WARNING ("packet capture disabled: file %s could not be opened for writing\n", name);
+ DDS_CWARNING (logcfg, "packet capture disabled: file %s could not be opened for writing\n", name);
return NULL;
}
@@ -99,8 +99,8 @@ FILE *new_pcap_file (const char *name)
fwrite (&hdr, sizeof (hdr), 1, fp);
return fp;
+ DDSRT_WARNING_MSVC_ON(4996);
}
-DDSRT_WARNING_MSVC_ON(4996);
static void write_data (FILE *fp, const ddsrt_msghdr_t *msghdr, size_t sz)
{
@@ -127,17 +127,9 @@ static uint16_t calc_ipv4_checksum (const uint16_t *x)
return (uint16_t) ~s;
}
-void write_pcap_received
-(
- FILE * fp,
- nn_wctime_t tstamp,
- const struct sockaddr_storage * src,
- const struct sockaddr_storage * dst,
- unsigned char * buf,
- size_t sz
-)
+void write_pcap_received (struct q_globals *gv, nn_wctime_t tstamp, const struct sockaddr_storage *src, const struct sockaddr_storage *dst, unsigned char *buf, size_t sz)
{
- if (config.transport_selector == TRANS_UDP)
+ if (gv->config.transport_selector == TRANS_UDP)
{
pcaprec_hdr_t pcap_hdr;
union {
@@ -147,37 +139,30 @@ void write_pcap_received
udp_hdr_t udp_hdr;
size_t sz_ud = sz + UDP_HDR_SIZE;
size_t sz_iud = sz_ud + IPV4_HDR_SIZE;
- ddsrt_mutex_lock (&gv.pcap_lock);
+ ddsrt_mutex_lock (&gv->pcap_lock);
wctime_to_sec_usec (&pcap_hdr.ts_sec, &pcap_hdr.ts_usec, tstamp);
pcap_hdr.incl_len = pcap_hdr.orig_len = (uint32_t) sz_iud;
- fwrite (&pcap_hdr, sizeof (pcap_hdr), 1, fp);
+ fwrite (&pcap_hdr, sizeof (pcap_hdr), 1, gv->pcap_fp);
u.ipv4_hdr = ipv4_hdr_template;
u.ipv4_hdr.totallength = toBE2u ((unsigned short) sz_iud);
u.ipv4_hdr.ttl = 128;
u.ipv4_hdr.srcip = ((struct sockaddr_in*) src)->sin_addr.s_addr;
u.ipv4_hdr.dstip = ((struct sockaddr_in*) dst)->sin_addr.s_addr;
u.ipv4_hdr.checksum = calc_ipv4_checksum (u.x);
- fwrite (&u.ipv4_hdr, sizeof (u.ipv4_hdr), 1, fp);
+ fwrite (&u.ipv4_hdr, sizeof (u.ipv4_hdr), 1, gv->pcap_fp);
udp_hdr.srcport = ((struct sockaddr_in*) src)->sin_port;
udp_hdr.dstport = ((struct sockaddr_in*) dst)->sin_port;
udp_hdr.length = toBE2u ((unsigned short) sz_ud);
udp_hdr.checksum = 0; /* don't have to compute a checksum for UDPv4 */
- fwrite (&udp_hdr, sizeof (udp_hdr), 1, fp);
- fwrite (buf, sz, 1, fp);
- ddsrt_mutex_unlock (&gv.pcap_lock);
+ fwrite (&udp_hdr, sizeof (udp_hdr), 1, gv->pcap_fp);
+ fwrite (buf, sz, 1, gv->pcap_fp);
+ ddsrt_mutex_unlock (&gv->pcap_lock);
}
}
-void write_pcap_sent
-(
- FILE * fp,
- nn_wctime_t tstamp,
- const struct sockaddr_storage * src,
- const ddsrt_msghdr_t * hdr,
- size_t sz
-)
+void write_pcap_sent (struct q_globals *gv, nn_wctime_t tstamp, const struct sockaddr_storage *src, const ddsrt_msghdr_t *hdr, size_t sz)
{
- if (config.transport_selector == TRANS_UDP)
+ if (gv->config.transport_selector == TRANS_UDP)
{
pcaprec_hdr_t pcap_hdr;
union {
@@ -187,23 +172,23 @@ void write_pcap_sent
udp_hdr_t udp_hdr;
size_t sz_ud = sz + UDP_HDR_SIZE;
size_t sz_iud = sz_ud + IPV4_HDR_SIZE;
- ddsrt_mutex_lock (&gv.pcap_lock);
+ ddsrt_mutex_lock (&gv->pcap_lock);
wctime_to_sec_usec (&pcap_hdr.ts_sec, &pcap_hdr.ts_usec, tstamp);
pcap_hdr.incl_len = pcap_hdr.orig_len = (uint32_t) sz_iud;
- fwrite (&pcap_hdr, sizeof (pcap_hdr), 1, fp);
+ fwrite (&pcap_hdr, sizeof (pcap_hdr), 1, gv->pcap_fp);
u.ipv4_hdr = ipv4_hdr_template;
u.ipv4_hdr.totallength = toBE2u ((unsigned short) sz_iud);
u.ipv4_hdr.ttl = 255;
u.ipv4_hdr.srcip = ((struct sockaddr_in*) src)->sin_addr.s_addr;
u.ipv4_hdr.dstip = ((struct sockaddr_in*) hdr->msg_name)->sin_addr.s_addr;
u.ipv4_hdr.checksum = calc_ipv4_checksum (u.x);
- fwrite (&u.ipv4_hdr, sizeof (u.ipv4_hdr), 1, fp);
+ fwrite (&u.ipv4_hdr, sizeof (u.ipv4_hdr), 1, gv->pcap_fp);
udp_hdr.srcport = ((struct sockaddr_in*) src)->sin_port;
udp_hdr.dstport = ((struct sockaddr_in*) hdr->msg_name)->sin_port;
udp_hdr.length = toBE2u ((unsigned short) sz_ud);
udp_hdr.checksum = 0; /* don't have to compute a checksum for UDPv4 */
- fwrite (&udp_hdr, sizeof (udp_hdr), 1, fp);
- write_data (fp, hdr, sz);
- ddsrt_mutex_unlock (&gv.pcap_lock);
+ fwrite (&udp_hdr, sizeof (udp_hdr), 1, gv->pcap_fp);
+ write_data (gv->pcap_fp, hdr, sz);
+ ddsrt_mutex_unlock (&gv->pcap_lock);
}
}
diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c
index a83f9f9..6714bda 100644
--- a/src/core/ddsi/src/q_plist.c
+++ b/src/core/ddsi/src/q_plist.c
@@ -17,25 +17,32 @@
#include "dds/ddsrt/log.h"
#include "dds/ddsrt/heap.h"
+#include "dds/ddsrt/string.h"
+#include "dds/ddsrt/static_assert.h"
#include "dds/ddsi/q_log.h"
#include "dds/ddsi/q_bswap.h"
#include "dds/ddsi/q_unused.h"
-#include "dds/ddsi/q_error.h"
#include "dds/ddsi/q_plist.h"
#include "dds/ddsi/q_time.h"
#include "dds/ddsi/q_xmsg.h"
+#include "dds/ddsi/ddsi_vendor.h"
+#include "dds/ddsi/ddsi_udp.h" /* nn_mc4gen_address_t */
#include "dds/ddsi/q_config.h"
#include "dds/ddsi/q_globals.h"
#include "dds/ddsi/q_protocol.h" /* for NN_STATUSINFO_... */
#include "dds/ddsi/q_radmin.h" /* for nn_plist_quickscan */
-#include "dds/ddsi/q_static_assert.h"
#include "dds/ddsrt/avl.h"
#include "dds/ddsi/q_misc.h" /* for vendor_is_... */
+/* I am tempted to change LENGTH_UNLIMITED to 0 in the API (with -1
+ supported for backwards compatibility) ... on the wire however
+ it must be -1 */
+DDSRT_STATIC_ASSERT(DDS_LENGTH_UNLIMITED == -1);
+
/* These are internal to the parameter list processing. We never
generate them, and we never want to do see them anywhere outside
the actual parsing of an incoming parameter list. (There are
@@ -51,7 +58,7 @@
#define PPTMP_METATRAFFIC_MULTICAST_PORT (1 << 6)
typedef struct nn_ipaddress_params_tmp {
- unsigned present;
+ uint32_t present;
nn_ipv4address_t multicast_ipaddress;
nn_ipv4address_t default_unicast_ipaddress;
@@ -68,538 +75,1486 @@ struct dd {
unsigned bswap: 1;
nn_protocol_version_t protocol_version;
nn_vendorid_t vendorid;
+ ddsi_tran_factory_t factory;
};
-struct cdroctetseq {
- unsigned len;
- unsigned char value[1];
+#define PDF_QOS 1 /* part of dds_qos_t */
+#define PDF_FUNCTION 2 /* use special functions */
+#define PDF_ALLOWMULTI 4 /* allow multiple copies -- do not use with Z or memory will leak */
+
+struct flagset {
+ uint64_t *present;
+ uint64_t *aliased;
+ uint64_t wanted;
};
-static void log_octetseq (uint32_t cat, unsigned n, const unsigned char *xs);
+/* Instructions for the generic serializer (&c) that handles most parameters.
+ The "packed" attribute means single-byte instructions on GCC and Clang. */
+enum pserop {
+ XSTOP,
+ XO, /* octet sequence */
+ XS, /* string */
+ XZ, /* string sequence */
+ XE1, XE2, XE3, /* enum 0..1, 0..2, 0..3 */
+ Xl, /* length, int32_t, -1 or >= 1 */
+ Xi, Xix2, Xix3, Xix4, /* int32_t, 1 .. 4 in a row */
+ Xu, Xux2, Xux3, Xux4, Xux5, /* uint32_t, 1 .. 5 in a row */
+ XD, XDx2, /* duration, 1 .. 2 in a row */
+ Xo, Xox2, /* octet, 1 .. 2 in a row */
+ Xb, Xbx2, /* boolean, 1 .. 2 in a row */
+ XbCOND, /* boolean: compare to ignore remainder if false (for use_... flags) */
+ XG, /* GUID */
+ XK /* keyhash */
+} ddsrt_attribute_packed;
-static size_t align4u (size_t x)
+struct piddesc {
+ nn_parameterid_t pid; /* parameter id or PID_PAD if strictly local */
+ uint16_t flags; /* see PDF_xxx flags */
+ uint64_t present_flag; /* flag in plist.present / plist.qos.present */
+ const char *name; /* name for reporting invalid input */
+ size_t plist_offset; /* offset from start of nn_plist_t */
+ size_t size; /* in-memory size for copying */
+ union {
+ /* descriptor for generic code: 4 is enough for the current set of
+ parameters, compiler will warn if one ever tries to use more than
+ will fit; on non-GCC/Clang and 32-bits machines */
+ const enum pserop desc[4];
+ struct {
+ dds_return_t (*deser) (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff);
+ dds_return_t (*ser) (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff);
+ dds_return_t (*unalias) (void * __restrict dst, size_t * __restrict dstoff);
+ dds_return_t (*fini) (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag);
+ dds_return_t (*valid) (const void *src, size_t srcoff);
+ bool (*equal) (const void *srcx, const void *srcy, size_t srcoff);
+ } f;
+ } op;
+ dds_return_t (*deser_validate_xform) (void * __restrict dst, const struct dd * __restrict dd);
+};
+
+static void log_octetseq (uint32_t cat, const struct ddsrt_log_cfg *logcfg, uint32_t n, const unsigned char *xs);
+static dds_return_t validate_history_qospolicy (const dds_history_qospolicy_t *q);
+static dds_return_t validate_resource_limits_qospolicy (const dds_resource_limits_qospolicy_t *q);
+static dds_return_t validate_history_and_resource_limits (const dds_history_qospolicy_t *qh, const dds_resource_limits_qospolicy_t *qr);
+static dds_return_t validate_external_duration (const ddsi_duration_t *d);
+static dds_return_t validate_durability_service_qospolicy_acceptzero (const dds_durability_service_qospolicy_t *q, bool acceptzero);
+static dds_return_t do_locator (nn_locators_t *ls, uint64_t *present, uint64_t wanted, uint64_t fl, const struct dd *dd, const struct ddsi_tran_factory *factory);
+static dds_return_t final_validation_qos (const dds_qos_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid, bool *dursvc_accepted_allzero, bool strict);
+static int partitions_equal (const dds_partition_qospolicy_t *a, const dds_partition_qospolicy_t *b);
+static dds_return_t nn_xqos_valid_strictness (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos, bool strict);
+
+static size_t align4size (size_t x)
{
- return (x + 3u) & ~(size_t)3;
+ return (x + 3) & ~(size_t)3;
}
+static void *deser_generic_dst (void * __restrict dst, size_t *dstoff, size_t align)
+{
+ *dstoff = (*dstoff + align - 1) & ~(align - 1);
+ return (char *) dst + *dstoff;
+}
+
+static const void *deser_generic_src (const void * __restrict src, size_t *srcoff, size_t align)
+{
+ *srcoff = (*srcoff + align - 1) & ~(align - 1);
+ return (const char *) src + *srcoff;
+}
+
+static void *ser_generic_align4 (char * __restrict p, size_t * __restrict off)
+{
+ const size_t off1 = align4size (*off);
+ size_t pad = off1 - *off;
+ char *dst = p + *off;
+ *off = off1;
+ while (pad--)
+ *dst++ = 0;
+ return dst;
+}
+
+static dds_return_t deser_uint32 (uint32_t *dst, const struct dd * __restrict dd, size_t * __restrict off)
+{
+ size_t off1 = (*off + 3) & ~(size_t)3;
+ uint32_t tmp;
+ if (off1 + 4 > dd->bufsz)
+ return DDS_RETCODE_BAD_PARAMETER;
+ tmp = *((uint32_t *) (dd->buf + off1));
+ if (dd->bswap)
+ tmp = bswap4u (tmp);
+ *dst = tmp;
+ *off = off1 + 4;
+ return 0;
+}
+
+#define alignof(type_) offsetof (struct { char c; type_ d; }, d)
+
+static dds_return_t deser_reliability (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff)
+{
+ DDSRT_STATIC_ASSERT (DDS_EXTERNAL_RELIABILITY_BEST_EFFORT == 1 && DDS_EXTERNAL_RELIABILITY_RELIABLE == 2 &&
+ DDS_RELIABILITY_BEST_EFFORT == 0 && DDS_RELIABILITY_RELIABLE == 1);
+ dds_reliability_qospolicy_t * const x = deser_generic_dst (dst, dstoff, alignof (dds_reliability_qospolicy_t));
+ uint32_t kind, mbtsec, mbtfrac;
+ ddsi_duration_t mbt;
+ if (deser_uint32 (&kind, dd, srcoff) < 0 || deser_uint32 (&mbtsec, dd, srcoff) < 0 || deser_uint32 (&mbtfrac, dd, srcoff) < 0)
+ return DDS_RETCODE_BAD_PARAMETER;
+ if (kind < 1 || kind > 2)
+ return DDS_RETCODE_BAD_PARAMETER;
+ mbt.seconds = (int32_t) mbtsec;
+ mbt.fraction = mbtfrac;
+ if (validate_external_duration (&mbt) < 0)
+ return DDS_RETCODE_BAD_PARAMETER;
+ x->kind = (enum dds_reliability_kind) (kind - 1);
+ x->max_blocking_time = nn_from_ddsi_duration (mbt);
+ *dstoff += sizeof (*x);
+ *flagset->present |= flag;
+ return 0;
+}
+
+static dds_return_t ser_reliability (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff)
+{
+ DDSRT_STATIC_ASSERT (DDS_EXTERNAL_RELIABILITY_BEST_EFFORT == 1 && DDS_EXTERNAL_RELIABILITY_RELIABLE == 2 &&
+ DDS_RELIABILITY_BEST_EFFORT == 0 && DDS_RELIABILITY_RELIABLE == 1);
+ dds_reliability_qospolicy_t const * const x = deser_generic_src (src, &srcoff, alignof (dds_reliability_qospolicy_t));
+ ddsi_duration_t mbt = nn_to_ddsi_duration (x->max_blocking_time);
+ uint32_t * const p = nn_xmsg_addpar (xmsg, pid, 3 * sizeof (uint32_t));
+ p[0] = 1 + (uint32_t) x->kind;
+ p[1] = (uint32_t) mbt.seconds;
+ p[2] = mbt.fraction;
+ return 0;
+}
+
+static dds_return_t valid_reliability (const void *src, size_t srcoff)
+{
+ dds_reliability_qospolicy_t const * const x = deser_generic_src (src, &srcoff, alignof (dds_reliability_qospolicy_t));
+ if ((x->kind == DDS_RELIABILITY_BEST_EFFORT || x->kind == DDS_RELIABILITY_RELIABLE) && x->max_blocking_time >= 0)
+ return 0;
+ else
+ return DDS_RETCODE_BAD_PARAMETER;
+}
+
+static bool equal_reliability (const void *srcx, const void *srcy, size_t srcoff)
+{
+ dds_reliability_qospolicy_t const * const x = deser_generic_src (srcx, &srcoff, alignof (dds_reliability_qospolicy_t));
+ dds_reliability_qospolicy_t const * const y = deser_generic_src (srcy, &srcoff, alignof (dds_reliability_qospolicy_t));
+ return x->kind == y->kind && x->max_blocking_time == y->max_blocking_time;
+}
+
+static dds_return_t deser_statusinfo (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff)
+{
+ uint32_t * const x = deser_generic_dst (dst, dstoff, alignof (dds_reliability_qospolicy_t));
+ size_t srcoff1 = (*srcoff + 3) & ~(size_t)3;
+ if (srcoff1 + 4 > dd->bufsz)
+ return DDS_RETCODE_BAD_PARAMETER;
+ /* status info is always in BE format (it is an array of 4 octets according to the spec) --
+ fortunately we have 4 byte alignment anyway -- and can have bits set we don't grok
+ (which we discard) */
+ *x = fromBE4u (*((uint32_t *) (dd->buf + srcoff1))) & NN_STATUSINFO_STANDARDIZED;
+ *dstoff += sizeof (*x);
+ *srcoff = srcoff1 + 4;
+ *flagset->present |= flag;
+ return 0;
+}
+
+static dds_return_t ser_statusinfo (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff)
+{
+ uint32_t const * const x = deser_generic_src (src, &srcoff, alignof (uint32_t));
+ uint32_t * const p = nn_xmsg_addpar (xmsg, pid, sizeof (uint32_t));
+ *p = toBE4u (*x);
+ return 0;
+}
+
+static dds_return_t deser_locator (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff)
+{
+ nn_locators_t * const x = deser_generic_dst (dst, dstoff, alignof (nn_locators_t));
+ /* FIXME: don't want to modify do_locator just yet, and don't want to require that a
+ locator is the only thing in the descriptor string (even though it actually always is),
+ so do alignment explicitly, fake a temporary input buffer and advance the source buffer */
+ *srcoff = (*srcoff + 3) & ~(size_t)3;
+ if (*srcoff > dd->bufsz || dd->bufsz - *srcoff < 24)
+ return DDS_RETCODE_BAD_PARAMETER;
+ struct dd tmpdd = *dd;
+ tmpdd.buf += *srcoff;
+ tmpdd.bufsz -= *srcoff;
+ if (do_locator (x, flagset->present, flagset->wanted, flag, &tmpdd, dd->factory) < 0)
+ return DDS_RETCODE_BAD_PARAMETER;
+ *srcoff += 24;
+ *dstoff += sizeof (*x);
+ *flagset->present |= flag;
+ return 0;
+}
+
+static dds_return_t ser_locator (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff)
+{
+ nn_locators_t const * const x = deser_generic_src (src, &srcoff, alignof (nn_locators_t));
+ for (const struct nn_locators_one *l = x->first; l != NULL; l = l->next)
+ {
+ char * const p = nn_xmsg_addpar (xmsg, pid, sizeof (nn_locator_t));
+ memcpy (p, &l->loc, sizeof (nn_locator_t));
+ }
+ return 0;
+}
+
+static dds_return_t unalias_locator (void * __restrict dst, size_t * __restrict dstoff)
+{
+ nn_locators_t * const x = deser_generic_dst (dst, dstoff, alignof (nn_locators_t));
+ nn_locators_t newlocs = { .n = x->n, .first = NULL, .last = NULL };
+ struct nn_locators_one **pnext = &newlocs.first;
+ for (const struct nn_locators_one *lold = x->first; lold != NULL; lold = lold->next)
+ {
+ struct nn_locators_one *n = ddsrt_memdup (lold, sizeof (*n));
+ *pnext = n;
+ pnext = &n->next;
+ }
+ newlocs.last = *pnext;
+ *pnext = NULL;
+ *x = newlocs;
+ *dstoff += sizeof (*x);
+ return 0;
+}
+
+static dds_return_t fini_locator (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag)
+{
+ nn_locators_t * const x = deser_generic_dst (dst, dstoff, alignof (nn_locators_t));
+ if (!(*flagset->aliased &flag))
+ {
+ while (x->first)
+ {
+ struct nn_locators_one *l = x->first;
+ x->first = l->next;
+ ddsrt_free (l);
+ }
+ }
+ return 0;
+}
+
+static void fini_generic_partial (void * __restrict dst, size_t * __restrict dstoff, const enum pserop *desc, const enum pserop * const desc_end, bool aliased)
+{
+#define COMPLEX(basecase_, type_, cleanup_unaliased_, cleanup_always_) do { \
+ type_ *x = deser_generic_dst (dst, dstoff, alignof (type_)); \
+ const uint32_t cnt = 1 + (uint32_t) (*desc - (basecase_)); \
+ for (uint32_t xi = 0; xi < cnt; xi++, x++) { \
+ if (!aliased) do { cleanup_unaliased_; } while (0); \
+ do { cleanup_always_; } while (0); \
+ } \
+ *dstoff += cnt * sizeof (*x); \
+ } while (0)
+#define SIMPLE(basecase_, type_) COMPLEX (basecase_, type_, (void) 0, (void) 0)
+ while (desc != desc_end)
+ {
+ switch (*desc)
+ {
+ case XSTOP: return;
+ case XO: COMPLEX (XO, ddsi_octetseq_t, ddsrt_free (x->value), (void) 0); break;
+ case XS: COMPLEX (XS, char *, ddsrt_free (*x), (void) 0); break;
+ case XZ: COMPLEX (XZ, ddsi_stringseq_t, { for (uint32_t i = 0; i < x->n; i++) ddsrt_free (x->strs[i]); }, ddsrt_free (x->strs)); break;
+ case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, (void) 0, (void) 0); break;
+ case Xi: case Xix2: case Xix3: case Xix4: SIMPLE (Xi, int32_t); break;
+ case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE (Xu, uint32_t); break;
+ case Xl: SIMPLE (Xl, int32_t); break;
+ case XD: case XDx2: SIMPLE (XD, dds_duration_t); break;
+ case Xo: case Xox2: SIMPLE (Xo, unsigned char); break;
+ case Xb: case Xbx2: SIMPLE (Xb, unsigned char); break;
+ case XbCOND: SIMPLE (XbCOND, unsigned char); break;
+ case XG: SIMPLE (XG, nn_guid_t); break;
+ case XK: SIMPLE (XK, nn_keyhash_t); break;
+ }
+ desc++;
+ }
+#undef SIMPLE
+#undef COMPLEX
+}
+
+static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff, const enum pserop * __restrict desc)
+{
+ enum pserop const * const desc_in = desc;
+ size_t dstoff_in = *dstoff;
+ /* very large buffers run a risk with alignment calculations; such buffers basically
+ do not occur for discovery data, so checking makes sense */
+ if (dd->bufsz >= SIZE_MAX - 8)
+ return DDS_RETCODE_BAD_PARAMETER;
+ while (true)
+ {
+ assert (*srcoff <= dd->bufsz);
+ switch (*desc)
+ {
+ case XSTOP:
+ *flagset->present |= flag;
+ return 0;
+ case XO: { /* octet sequence */
+ ddsi_octetseq_t * const x = deser_generic_dst (dst, dstoff, alignof (ddsi_octetseq_t));
+ if (deser_uint32 (&x->length, dd, srcoff) < 0 || dd->bufsz - *srcoff < x->length)
+ goto fail;
+ x->value = x->length ? (unsigned char *) (dd->buf + *srcoff) : NULL;
+ *srcoff += x->length;
+ *dstoff += sizeof (*x);
+ *flagset->aliased |= flag;
+ break;
+ }
+ case XS: { /* string: alias as-if octet sequence, do additional checks and store as string */
+ char ** const x = deser_generic_dst (dst, dstoff, alignof (char *));
+ ddsi_octetseq_t tmp;
+ size_t tmpoff = 0;
+ if (deser_generic (&tmp, &tmpoff, flagset, flag, dd, srcoff, (enum pserop []) { XO, XSTOP }) < 0)
+ goto fail;
+ if (tmp.length < 1 || tmp.value[tmp.length - 1] != 0)
+ goto fail;
+ *x = (char *) tmp.value;
+ *dstoff += sizeof (*x);
+ break;
+ }
+ case XZ: { /* string sequence: repeatedly read a string */
+ ddsi_stringseq_t * const x = deser_generic_dst (dst, dstoff, alignof (ddsi_stringseq_t));
+ /* sequence of string: length length ..., where each length is aligned
+ to a multiple of 4 bytes and the lengths are all at least 1, therefore all but the
+ last entry need 8 bytes and the final one at least 5; checking this protects us
+ against allocating large amount of memory */
+ if (deser_uint32 (&x->n, dd, srcoff) < 0 || x->n > (dd->bufsz - *srcoff + 7) / 8)
+ goto fail;
+ x->strs = x->n ? ddsrt_malloc (x->n * sizeof (*x->strs)) : NULL;
+ size_t tmpoff = 0;
+ for (uint32_t i = 0; i < x->n; i++)
+ if (deser_generic (x->strs, &tmpoff, flagset, flag, dd, srcoff, (enum pserop []) { XS, XSTOP }) < 0)
+ goto fail;
+ *dstoff += sizeof (*x);
+ break;
+ }
+ case XE1: case XE2: case XE3: { /* enum with max allowed value */
+ unsigned * const x = deser_generic_dst (dst, dstoff, alignof (int));
+ const uint32_t maxval = 1 + (uint32_t) (*desc - XE1);
+ uint32_t tmp;
+ if (deser_uint32 (&tmp, dd, srcoff) < 0 || tmp > maxval)
+ goto fail;
+ *x = (unsigned) tmp;
+ *dstoff += sizeof (*x);
+ break;
+ }
+ case Xi: case Xix2: case Xix3: case Xix4: { /* int32_t(s) */
+ uint32_t * const x = deser_generic_dst (dst, dstoff, alignof (uint32_t));
+ const uint32_t cnt = 1 + (uint32_t) (*desc - Xi);
+ for (uint32_t i = 0; i < cnt; i++)
+ if (deser_uint32 (&x[i], dd, srcoff) < 0)
+ goto fail;
+ *dstoff += cnt * sizeof (*x);
+ break;
+ }
+ case Xu: case Xux2: case Xux3: case Xux4: case Xux5: { /* uint32_t(s): treated the same */
+ uint32_t * const x = deser_generic_dst (dst, dstoff, alignof (uint32_t));
+ const uint32_t cnt = 1 + (uint32_t) (*desc - Xu);
+ for (uint32_t i = 0; i < cnt; i++)
+ if (deser_uint32 (&x[i], dd, srcoff) < 0)
+ goto fail;
+ *dstoff += cnt * sizeof (*x);
+ break;
+ }
+ case Xl: { /* length(s): int32_t, -1 or >= 1 */
+ int32_t * const x = deser_generic_dst (dst, dstoff, alignof (uint32_t));
+ const uint32_t cnt = 1 + (uint32_t) (*desc - Xl);
+ for (uint32_t i = 0; i < cnt; i++)
+ if (deser_uint32 ((uint32_t *) &x[i], dd, srcoff) < 0 || (x[i] < 1 && x[i] != DDS_LENGTH_UNLIMITED))
+ goto fail;
+ *dstoff += cnt * sizeof (*x);
+ break;
+ }
+ case XD: case XDx2: { /* duration(s): int64_t <=> int32_t.uint32_t (seconds.fraction) */
+ dds_duration_t * const x = deser_generic_dst (dst, dstoff, alignof (dds_duration_t));
+ const uint32_t cnt = 1 + (uint32_t) (*desc - XD);
+ for (uint32_t i = 0; i < cnt; i++)
+ {
+ ddsi_duration_t tmp;
+ if (deser_uint32 ((uint32_t *) &tmp.seconds, dd, srcoff) < 0 || deser_uint32 (&tmp.fraction, dd, srcoff) < 0)
+ goto fail;
+ if (validate_external_duration (&tmp))
+ goto fail;
+ x[i] = nn_from_ddsi_duration (tmp);
+ }
+ *dstoff += cnt * sizeof (*x);
+ break;
+ }
+ case Xo: case Xox2: { /* octet(s) */
+ unsigned char * const x = deser_generic_dst (dst, dstoff, alignof (unsigned char));
+ const uint32_t cnt = 1 + (uint32_t) (*desc - Xo);
+ if (dd->bufsz - *srcoff < cnt)
+ goto fail;
+ memcpy (x, dd->buf + *srcoff, cnt);
+ *srcoff += cnt;
+ *dstoff += cnt * sizeof (*x);
+ break;
+ }
+ case Xb: case Xbx2: case XbCOND: { /* boolean(s) */
+ unsigned char * const x = deser_generic_dst (dst, dstoff, alignof (unsigned char));
+ const uint32_t cnt = (*desc == Xbx2) ? 2 : 1; /* <<<< beware! */
+ if (dd->bufsz - *srcoff < cnt)
+ goto fail;
+ memcpy (x, dd->buf + *srcoff, cnt);
+ for (uint32_t i = 0; i < cnt; i++)
+ if (x[i] > 1)
+ goto fail;
+ *srcoff += cnt;
+ *dstoff += cnt * sizeof (*x);
+ break;
+ }
+ case XG: { /* GUID */
+ nn_guid_t * const x = deser_generic_dst (dst, dstoff, alignof (nn_guid_t));
+ if (dd->bufsz - *srcoff < sizeof (*x))
+ goto fail;
+ memcpy (x, dd->buf + *srcoff, sizeof (*x));
+ *x = nn_ntoh_guid (*x);
+ *srcoff += sizeof (*x);
+ *dstoff += sizeof (*x);
+ break;
+ }
+ case XK: { /* keyhash */
+ nn_keyhash_t * const x = deser_generic_dst (dst, dstoff, alignof (nn_keyhash_t));
+ if (dd->bufsz - *srcoff < sizeof (*x))
+ goto fail;
+ memcpy (x, dd->buf + *srcoff, sizeof (*x));
+ *srcoff += sizeof (*x);
+ *dstoff += sizeof (*x);
+ break;
+ }
+ }
+ desc++;
+ }
+
+fail:
+ fini_generic_partial (dst, &dstoff_in, desc_in, desc, *flagset->aliased & flag);
+ *flagset->present &= ~flag;
+ *flagset->aliased &= ~flag;
+ return DDS_RETCODE_BAD_PARAMETER;
+}
+
+static size_t ser_generic_size (const void *src, size_t srcoff, const enum pserop * __restrict desc)
+{
+ size_t dstoff = 0;
+#define COMPLEX(basecase_, type_, dstoff_update_) do { \
+ type_ const *x = deser_generic_src (src, &srcoff, alignof (type_)); \
+ const uint32_t cnt = 1 + (uint32_t) (*desc - (basecase_)); \
+ for (uint32_t xi = 0; xi < cnt; xi++, x++) { dstoff_update_; } \
+ srcoff += cnt * sizeof (*x); \
+ } while (0)
+#define SIMPLE1(basecase_, type_) COMPLEX (basecase_, type_, dstoff = dstoff + sizeof (*x))
+#define SIMPLE4(basecase_, type_) COMPLEX (basecase_, type_, dstoff = align4size (dstoff) + sizeof (*x))
+ while (true)
+ {
+ switch (*desc)
+ {
+ case XSTOP: return dstoff;
+ case XO: COMPLEX (XO, ddsi_octetseq_t, dstoff = align4size (dstoff) + 4 + x->length); break;
+ case XS: COMPLEX (XS, const char *, dstoff = align4size (dstoff) + 4 + strlen (*x) + 1); break;
+ case XZ: COMPLEX (XZ, ddsi_stringseq_t, {
+ dstoff = align4size (dstoff) + 4;
+ for (uint32_t i = 0; i < x->n; i++)
+ dstoff = align4size (dstoff) + 4 + strlen (x->strs[i]) + 1;
+ }); break;
+ case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, dstoff = align4size (dstoff) + 4); break;
+ case Xi: case Xix2: case Xix3: case Xix4: SIMPLE4 (Xi, int32_t); break;
+ case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE4 (Xu, uint32_t); break;
+ case Xl: SIMPLE4 (Xl, int32_t); break;
+ case XD: case XDx2: SIMPLE4 (XD, dds_duration_t); break;
+ case Xo: case Xox2: SIMPLE1 (Xo, unsigned char); break;
+ case Xb: case Xbx2: SIMPLE1 (Xb, unsigned char); break;
+ case XbCOND: SIMPLE1 (XbCOND, unsigned char); break;
+ case XG: SIMPLE1 (XG, nn_guid_t); break;
+ case XK: SIMPLE1 (XK, nn_keyhash_t); break;
+ }
+ desc++;
+ }
+#undef SIMPLE
+#undef COMPLEX
+}
+
+static dds_return_t ser_generic (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff, const enum pserop * __restrict desc)
+{
+ char * const data = nn_xmsg_addpar (xmsg, pid, ser_generic_size (src, srcoff, desc));
+ size_t dstoff = 0;
+ while (true)
+ {
+ switch (*desc)
+ {
+ case XSTOP:
+ return 0;
+ case XO: { /* octet sequence */
+ ddsi_octetseq_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_octetseq_t));
+ char * const p = ser_generic_align4 (data, &dstoff);
+ *((uint32_t *) p) = x->length;
+ if (x->length) memcpy (p + 4, x->value, x->length);
+ dstoff += 4 + x->length;
+ srcoff += sizeof (*x);
+ break;
+ }
+ case XS: { /* string */
+ char const * const * const x = deser_generic_src (src, &srcoff, alignof (char *));
+ const uint32_t size = (uint32_t) (strlen (*x) + 1);
+ char * const p = ser_generic_align4 (data, &dstoff);
+ *((uint32_t *) p) = size;
+ memcpy (p + 4, *x, size);
+ dstoff += 4 + size;
+ srcoff += sizeof (*x);
+ break;
+ }
+ case XZ: { /* string sequence */
+ ddsi_stringseq_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_stringseq_t));
+ char * const p = ser_generic_align4 (data, &dstoff);
+ *((uint32_t *) p) = x->n;
+ dstoff += 4;
+ for (uint32_t i = 0; i < x->n; i++)
+ {
+ char * const q = ser_generic_align4 (data, &dstoff);
+ const uint32_t size = (uint32_t) (strlen (x->strs[i]) + 1);
+ *((uint32_t *) q) = size;
+ memcpy (q + 4, x->strs[i], size);
+ dstoff += 4 + size;
+ }
+ srcoff += sizeof (*x);
+ break;
+ }
+ case XE1: case XE2: case XE3: { /* enum */
+ unsigned const * const x = deser_generic_src (src, &srcoff, alignof (unsigned));
+ uint32_t * const p = ser_generic_align4 (data, &dstoff);
+ *p = (uint32_t) *x;
+ dstoff += 4;
+ srcoff += sizeof (*x);
+ break;
+ }
+ case Xi: case Xix2: case Xix3: case Xix4: { /* int32_t(s) */
+ int32_t const * const x = deser_generic_src (src, &srcoff, alignof (int32_t));
+ const uint32_t cnt = 1 + (uint32_t) (*desc - Xi);
+ int32_t * const p = ser_generic_align4 (data, &dstoff);
+ for (uint32_t i = 0; i < cnt; i++)
+ p[i] = x[i];
+ dstoff += cnt * sizeof (*x);
+ srcoff += cnt * sizeof (*x);
+ break;
+ }
+
+ case Xu: case Xux2: case Xux3: case Xux4: case Xux5: { /* uint32_t(s) */
+ uint32_t const * const x = deser_generic_src (src, &srcoff, alignof (uint32_t));
+ const uint32_t cnt = 1 + (uint32_t) (*desc - Xu);
+ uint32_t * const p = ser_generic_align4 (data, &dstoff);
+ for (uint32_t i = 0; i < cnt; i++)
+ p[i] = x[i];
+ dstoff += cnt * sizeof (*x);
+ srcoff += cnt * sizeof (*x);
+ break;
+ }
+
+ case Xl: { /* int32_t(s) */
+ int32_t const * const x = deser_generic_src (src, &srcoff, alignof (uint32_t));
+ const uint32_t cnt = 1 + (uint32_t) (*desc - Xu);
+ int32_t * const p = ser_generic_align4 (data, &dstoff);
+ for (uint32_t i = 0; i < cnt; i++)
+ p[i] = x[i];
+ dstoff += cnt * sizeof (*x);
+ srcoff += cnt * sizeof (*x);
+ break;
+ }
+ case XD: case XDx2: { /* duration(s): int64_t <=> int32_t.uint32_t (seconds.fraction) */
+ dds_duration_t const * const x = deser_generic_src (src, &srcoff, alignof (dds_duration_t));
+ const uint32_t cnt = 1 + (uint32_t) (*desc - XD);
+ uint32_t * const p = ser_generic_align4 (data, &dstoff);
+ for (uint32_t i = 0; i < cnt; i++)
+ {
+ ddsi_duration_t tmp = nn_to_ddsi_duration (x[i]);
+ p[2 * i + 0] = (uint32_t) tmp.seconds;
+ p[2 * i + 1] = tmp.fraction;
+ }
+ dstoff += 2 * cnt * sizeof (uint32_t);
+ srcoff += cnt * sizeof (*x);
+ break;
+ }
+ case Xo: case Xox2: { /* octet(s) */
+ unsigned char const * const x = deser_generic_src (src, &srcoff, alignof (unsigned char));
+ const uint32_t cnt = 1 + (uint32_t) (*desc - Xo);
+ char * const p = data + dstoff;
+ memcpy (p, x, cnt);
+ dstoff += cnt;
+ srcoff += cnt * sizeof (*x);
+ break;
+ }
+ case Xb: case Xbx2: case XbCOND: { /* boolean(s) */
+ unsigned char const * const x = deser_generic_src (src, &srcoff, alignof (unsigned char));
+ const uint32_t cnt = (*desc == Xbx2) ? 2 : 1; /* <<<< beware! */
+ char * const p = data + dstoff;
+ memcpy (p, x, cnt);
+ dstoff += cnt;
+ srcoff += cnt * sizeof (*x);
+ break;
+ }
+ case XG: { /* GUID */
+ nn_guid_t const * const x = deser_generic_src (src, &srcoff, alignof (nn_guid_t));
+ const nn_guid_t xn = nn_hton_guid (*x);
+ char * const p = data + dstoff;
+ memcpy (p, &xn, sizeof (xn));
+ dstoff += sizeof (xn);
+ srcoff += sizeof (*x);
+ break;
+ }
+ case XK: { /* keyhash */
+ nn_keyhash_t const * const x = deser_generic_src (src, &srcoff, alignof (nn_keyhash_t));
+ char * const p = data + dstoff;
+ memcpy (p, x, sizeof (*x));
+ dstoff += sizeof (*x);
+ srcoff += sizeof (*x);
+ break;
+ }
+ }
+ desc++;
+ }
+}
+
+static dds_return_t unalias_generic (void * __restrict dst, size_t * __restrict dstoff, const enum pserop * __restrict desc)
+{
+#define COMPLEX(basecase_, type_, ...) do { \
+ type_ *x = deser_generic_dst (dst, dstoff, alignof (type_)); \
+ const uint32_t cnt = 1 + (uint32_t) (*desc - basecase_); \
+ for (uint32_t xi = 0; xi < cnt; xi++, x++) { __VA_ARGS__; } \
+ *dstoff += cnt * sizeof (*x); \
+ } while (0)
+#define SIMPLE(basecase_, type_) COMPLEX (basecase_, type_, (void) 0)
+ while (true)
+ {
+ switch (*desc)
+ {
+ case XSTOP:
+ return 0;
+ case XO: COMPLEX (XO, ddsi_octetseq_t, if (x->value) { x->value = ddsrt_memdup (x->value, x->length); }); break;
+ case XS: COMPLEX (XS, char *, if (*x) { *x = ddsrt_strdup (*x); }); break;
+ case XZ: COMPLEX (XZ, ddsi_stringseq_t, if (x->n) {
+ x->strs = ddsrt_memdup (x->strs, x->n * sizeof (*x->strs));
+ for (uint32_t i = 0; i < x->n; i++)
+ x->strs[i] = ddsrt_strdup (x->strs[i]);
+ }); break;
+ case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, (void) 0); break;
+ case Xi: case Xix2: case Xix3: case Xix4: SIMPLE (Xi, int32_t); break;
+ case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE (Xu, uint32_t); break;
+ case Xl: SIMPLE (Xl, int32_t); break;
+ case XD: case XDx2: SIMPLE (XD, dds_duration_t); break;
+ case Xo: case Xox2: SIMPLE (Xo, unsigned char); break;
+ case Xb: case Xbx2: SIMPLE (Xb, unsigned char); break;
+ case XbCOND: SIMPLE (XbCOND, unsigned char); break;
+ case XG: SIMPLE (XG, nn_guid_t); break;
+ case XK: SIMPLE (XK, nn_keyhash_t); break;
+ }
+ desc++;
+ }
+#undef SIMPLE
+#undef COMPLEX
+}
+
+static bool unalias_generic_required (const enum pserop * __restrict desc)
+{
+ while (*desc != XSTOP)
+ {
+ switch (*desc++)
+ {
+ case XO: case XS: case XZ:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+static bool fini_generic_required (const enum pserop * __restrict desc)
+{
+ /* the two happen to be the same */
+ return unalias_generic_required (desc);
+}
+
+static dds_return_t fini_generic (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const enum pserop * __restrict desc)
+{
+ fini_generic_partial (dst, dstoff, desc, NULL, *flagset->aliased & flag);
+ return 0;
+}
+
+static dds_return_t valid_generic (const void *src, size_t srcoff, const enum pserop * __restrict desc)
+{
+#define COMPLEX(basecase_, type_, cond_stmts_) do { \
+ type_ const *x = deser_generic_src (src, &srcoff, alignof (type_)); \
+ const uint32_t cnt = 1 + (uint32_t) (*desc - (basecase_)); \
+ for (uint32_t xi = 0; xi < cnt; xi++, x++) { cond_stmts_; } \
+ srcoff += cnt * sizeof (*x); \
+ } while (0)
+#define SIMPLE(basecase_, type_, cond_) COMPLEX (basecase_, type_, if (!(cond_)) return DDS_RETCODE_BAD_PARAMETER)
+#define TRIVIAL(basecase_, type_) COMPLEX (basecase_, type_, (void) 0)
+ while (true)
+ {
+ switch (*desc)
+ {
+ case XSTOP: return 0;
+ case XO: SIMPLE (XO, ddsi_octetseq_t, (x->length == 0) == (x->value == NULL)); break;
+ case XS: SIMPLE (XS, const char *, *x != NULL); break;
+ case XZ: COMPLEX (XZ, ddsi_stringseq_t, {
+ if ((x->n == 0) != (x->strs == NULL))
+ return DDS_RETCODE_BAD_PARAMETER;
+ for (uint32_t i = 0; i < x->n; i++)
+ if (x->strs[i] == NULL)
+ return DDS_RETCODE_BAD_PARAMETER;
+ }); break;
+ case XE1: case XE2: case XE3: SIMPLE (*desc, unsigned, *x <= 1 + (unsigned) *desc - XE1); break;
+ case Xi: case Xix2: case Xix3: case Xix4: TRIVIAL (Xi, int32_t); break;
+ case Xu: case Xux2: case Xux3: case Xux4: case Xux5: TRIVIAL (Xu, uint32_t); break;
+ case Xl: SIMPLE (Xl, int32_t, *x == DDS_LENGTH_UNLIMITED || *x > 1); break;
+ case XD: case XDx2: SIMPLE (XD, dds_duration_t, *x >= 0); break;
+ case Xo: case Xox2: TRIVIAL (Xo, unsigned char); break;
+ case Xb: case Xbx2: SIMPLE (Xb, unsigned char, *x == 0 || *x == 1); break;
+ case XbCOND: SIMPLE (XbCOND, unsigned char, *x == 0 || *x == 1); break;
+ case XG: TRIVIAL (XG, nn_guid_t); break;
+ case XK: TRIVIAL (XK, nn_keyhash_t); break;
+ }
+ desc++;
+ }
+#undef TRIVIAL
+#undef SIMPLE
+#undef COMPLEX
+}
+
+static bool equal_generic (const void *srcx, const void *srcy, size_t srcoff, const enum pserop * __restrict desc)
+{
+#define COMPLEX(basecase_, type_, cond_stmts_) do { \
+ type_ const *x = deser_generic_src (srcx, &srcoff, alignof (type_)); \
+ type_ const *y = deser_generic_src (srcy, &srcoff, alignof (type_)); \
+ const uint32_t cnt = 1 + (uint32_t) (*desc - (basecase_)); \
+ for (uint32_t xi = 0; xi < cnt; xi++, x++, y++) { cond_stmts_; } \
+ srcoff += cnt * sizeof (*x); \
+ } while (0)
+#define SIMPLE(basecase_, type_, cond_) COMPLEX (basecase_, type_, if (!(cond_)) return false)
+#define TRIVIAL(basecase_, type_) SIMPLE (basecase_, type_, *x == *y)
+ while (true)
+ {
+ switch (*desc)
+ {
+ case XSTOP:
+ return true;
+ case XO:
+ SIMPLE (XO, ddsi_octetseq_t,
+ (x->length == y->length) &&
+ (x->length == 0 || memcmp (x->value, y->value, x->length) == 0));
+ break;
+ case XS:
+ SIMPLE (XS, const char *, strcmp (*x, *y) == 0);
+ break;
+ case XZ:
+ COMPLEX (XZ, ddsi_stringseq_t, {
+ if (x->n != y->n)
+ return false;
+ for (uint32_t i = 0; i < x->n; i++)
+ if (strcmp (x->strs[i], y->strs[i]) != 0)
+ return false;
+ });
+ break;
+ case XE1: case XE2: case XE3: TRIVIAL (*desc, unsigned); break;
+ case Xi: case Xix2: case Xix3: case Xix4: TRIVIAL (Xi, int32_t); break;
+ case Xu: case Xux2: case Xux3: case Xux4: case Xux5: TRIVIAL (Xu, uint32_t); break;
+ case Xl: TRIVIAL (Xl, int32_t); break;
+ case XD: case XDx2: TRIVIAL (XD, dds_duration_t); break;
+ case Xo: case Xox2: TRIVIAL (Xo, unsigned char); break;
+ case Xb: case Xbx2: TRIVIAL (Xb, unsigned char); break;
+ case XbCOND:
+ COMPLEX (XbCOND, unsigned char, {
+ if (*x != *y)
+ return false;
+ if (*x == false)
+ return true;
+ });
+ break;
+ case XG: SIMPLE (XG, nn_guid_t, memcmp (x, y, sizeof (*x))); break;
+ case XK: SIMPLE (XK, nn_keyhash_t, memcmp (x, y, sizeof (*x))); break;
+ }
+ desc++;
+ }
+#undef TRIVIAL
+#undef SIMPLE
+#undef COMPLEX
+}
+
+#define membersize(type, member) sizeof (((type *) 0)->member)
+#define ENTRY(PFX_, NAME_, member_, flag_, validate_, ...) \
+ { PID_##NAME_, flag_, PFX_##_##NAME_, #NAME_, offsetof (struct nn_plist, member_), \
+ membersize (struct nn_plist, member_), { .desc = { __VA_ARGS__, XSTOP } }, validate_ \
+ }
+#define QPV(NAME_, name_, ...) ENTRY(QP, NAME_, qos.name_, PDF_QOS, dvx_##name_, __VA_ARGS__)
+#define PPV(NAME_, name_, ...) ENTRY(PP, NAME_, name_, 0, dvx_##name_, __VA_ARGS__)
+#define QP(NAME_, name_, ...) ENTRY(QP, NAME_, qos.name_, PDF_QOS, 0, __VA_ARGS__)
+#define PP(NAME_, name_, ...) ENTRY(PP, NAME_, name_, 0, 0, __VA_ARGS__)
+#define PPM(NAME_, name_, ...) ENTRY(PP, NAME_, name_, PDF_ALLOWMULTI, 0, __VA_ARGS__)
+
static int protocol_version_is_newer (nn_protocol_version_t pv)
{
return (pv.major < RTPS_MAJOR) ? 0 : (pv.major > RTPS_MAJOR) ? 1 : (pv.minor > RTPS_MINOR);
}
-static int validate_string (const struct dd *dd, size_t *len)
+static dds_return_t dvx_durability_service (void * __restrict dst, const struct dd * __restrict dd)
{
- const struct cdrstring *x = (const struct cdrstring *) dd->buf;
- if (dd->bufsz < sizeof (struct cdrstring))
- {
- DDS_TRACE("plist/validate_string: buffer too small (header)\n");
- return Q_ERR_INVALID;
- }
- *len = dd->bswap ? bswap4u (x->length) : x->length;
- if (*len < 1 || *len > dd->bufsz - offsetof (struct cdrstring, contents))
- {
- DDS_TRACE("plist/validate_string: length %" PRIuSIZE " out of range\n", *len);
- return Q_ERR_INVALID;
- }
- if (x->contents[*len-1] != 0)
- {
- DDS_TRACE("plist/validate_string: terminator missing\n");
- return Q_ERR_INVALID;
- }
- return 0;
+ /* Accept all zero durability because of CoreDX, final_validation is more strict */
+ (void) dd;
+ return validate_durability_service_qospolicy_acceptzero (dst, true);
}
-static int alias_string (const unsigned char **ptr, const struct dd *dd, size_t *len)
+static dds_return_t dvx_history (void * __restrict dst, const struct dd * __restrict dd)
{
- int rc;
- if ((rc = validate_string (dd, len)) < 0)
- return rc;
+ (void) dd;
+ return validate_history_qospolicy (dst);
+}
+
+static dds_return_t dvx_resource_limits (void * __restrict dst, const struct dd * __restrict dd)
+{
+ (void) dd;
+ return validate_resource_limits_qospolicy (dst);
+}
+
+static dds_return_t dvx_participant_guid (void * __restrict dst, const struct dd * __restrict dd)
+{
+ const nn_guid_t *g = dst;
+ (void) dd;
+ if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0)
+ return (g->entityid.u == 0) ? 0 : DDS_RETCODE_BAD_PARAMETER;
else
- {
- const struct cdrstring *x = (const struct cdrstring *) dd->buf;
- *ptr = x->contents;
- return 0;
- }
+ return (g->entityid.u == NN_ENTITYID_PARTICIPANT) ? 0 : DDS_RETCODE_BAD_PARAMETER;
}
-static void unalias_string (char **str, int bswap)
+static dds_return_t dvx_group_guid (void * __restrict dst, const struct dd * __restrict dd)
{
- const char *alias = *str;
- unsigned len;
- if (bswap == 0 || bswap == 1)
- {
- const unsigned *plen = (const unsigned *) alias - 1;
- len = bswap ? bswap4u (*plen) : *plen;
- }
+ const nn_guid_t *g = dst;
+ (void) dd;
+ if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0)
+ return (g->entityid.u == 0) ? 0 : DDS_RETCODE_BAD_PARAMETER;
else
- {
- len = (unsigned) strlen (alias) + 1;
- }
- *str = ddsrt_malloc (len);
- memcpy (*str, alias, len);
+ return (g->entityid.u != 0) ? 0 : DDS_RETCODE_BAD_PARAMETER;
}
-static int validate_octetseq (const struct dd *dd, size_t *len)
+static dds_return_t dvx_endpoint_guid (void * __restrict dst, const struct dd * __restrict dd)
{
- const struct cdroctetseq *x = (const struct cdroctetseq *) dd->buf;
- if (dd->bufsz < offsetof (struct cdroctetseq, value))
- return Q_ERR_INVALID;
- *len = dd->bswap ? bswap4u (x->len) : x->len;
- if (*len > dd->bufsz - offsetof (struct cdroctetseq, value) || *len >= UINT32_MAX)
- return Q_ERR_INVALID;
+ nn_guid_t *g = dst;
+ if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0)
+ return (g->entityid.u == 0) ? 0 : DDS_RETCODE_BAD_PARAMETER;
+ switch (g->entityid.u & NN_ENTITYID_KIND_MASK)
+ {
+ case NN_ENTITYID_KIND_WRITER_WITH_KEY:
+ case NN_ENTITYID_KIND_WRITER_NO_KEY:
+ case NN_ENTITYID_KIND_READER_NO_KEY:
+ case NN_ENTITYID_KIND_READER_WITH_KEY:
+ return 0;
+ default:
+ return (protocol_version_is_newer (dd->protocol_version) ? 0 : DDS_RETCODE_BAD_PARAMETER);
+ }
+}
+
+#ifdef DDSI_INCLUDE_SSM
+static dds_return_t dvx_reader_favours_ssm (void * __restrict dst, const struct dd * __restrict dd)
+{
+ uint32_t * const favours_ssm = dst;
+ (void) dd;
+ /* any unrecognized state: avoid SSM */
+ if (*favours_ssm != 0 && *favours_ssm != 1)
+ *favours_ssm = 0;
return 0;
}
-
-static int alias_octetseq (nn_octetseq_t *oseq, const struct dd *dd)
-{
- size_t len;
- int rc;
- if ((rc = validate_octetseq (dd, &len)) < 0)
- return rc;
- else
- {
- const struct cdroctetseq *x = (const struct cdroctetseq *) dd->buf;
- assert(len < UINT32_MAX); /* it really is an uint32_t on the wire */
- oseq->length = (uint32_t)len;
- oseq->value = (len == 0) ? NULL : (unsigned char *) x->value;
- return 0;
- }
-}
-
-static int alias_blob (nn_octetseq_t *oseq, const struct dd *dd)
-{
- assert (dd->bufsz < UINT32_MAX);
- oseq->length = (uint32_t)dd->bufsz;
- oseq->value = (oseq->length == 0) ? NULL : (unsigned char *) dd->buf;
- return 0;
-}
-
-static void unalias_octetseq (nn_octetseq_t *oseq, UNUSED_ARG (int bswap))
-{
- if (oseq->length != 0)
- {
- unsigned char *vs;
- vs = ddsrt_malloc (oseq->length);
- memcpy (vs, oseq->value, oseq->length);
- oseq->value = vs;
- }
-}
-
-static int validate_stringseq (const struct dd *dd)
-{
- const unsigned char *seq = dd->buf;
- const unsigned char *seqend = seq + dd->bufsz;
- struct dd dd1 = *dd;
- int i, n;
- if (dd->bufsz < sizeof (int))
- {
- DDS_TRACE("plist/validate_stringseq: buffer too small (header)\n");
- return Q_ERR_INVALID;
- }
- memcpy (&n, seq, sizeof (n));
- if (dd->bswap)
- n = bswap4 (n);
- seq += sizeof (int);
- if (n < 0)
- {
- DDS_TRACE("plist/validate_stringseq: length %d out of range\n", n);
- return Q_ERR_INVALID;
- }
- else if (n == 0)
- {
- return 0;
- }
- else
- {
- for (i = 0; i < n && seq <= seqend; i++)
- {
- size_t len1;
- int rc;
- dd1.buf = seq;
- dd1.bufsz = (size_t) (seqend - seq);
- if ((rc = validate_string (&dd1, &len1)) < 0)
- {
- DDS_TRACE("plist/validate_stringseq: invalid string\n");
- return rc;
- }
- seq += sizeof (uint32_t) + align4u (len1);
- }
- if (i < n)
- {
- DDS_TRACE("plist/validate_stringseq: buffer too small (contents)\n");
- return Q_ERR_INVALID;
- }
- }
- /* Should I worry about junk between the last string & the end of
- the parameter? */
- return 0;
-}
-
-static int alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd)
-{
- /* Not truly an alias: it allocates an array of pointers that alias
- the individual null-terminated strings. Also: see
- validate_stringseq */
- const unsigned char *seq = dd->buf;
- const unsigned char *seqend = seq + dd->bufsz;
- struct dd dd1 = *dd;
- char **strs;
- unsigned i;
- int result;
- if (dd->bufsz < sizeof (int))
- {
- DDS_TRACE("plist/alias_stringseq: buffer too small (header)\n");
- return Q_ERR_INVALID;
- }
- memcpy (&strseq->n, seq, sizeof (strseq->n));
- if (dd->bswap)
- strseq->n = bswap4u (strseq->n);
- seq += sizeof (uint32_t);
- if (strseq->n >= UINT_MAX / sizeof(*strs))
- {
- DDS_TRACE("plist/alias_stringseq: length %"PRIu32" out of range\n", strseq->n);
- return Q_ERR_INVALID;
- }
- else if (strseq->n == 0)
- {
- strseq->strs = NULL;
- }
- else
- {
- strs = ddsrt_malloc (strseq->n * sizeof (*strs));
- for (i = 0; i < strseq->n && seq <= seqend; i++)
- {
- size_t len1;
- dd1.buf = seq;
- dd1.bufsz = (size_t)(seqend - seq);
- /* (const char **) to silence the compiler, unfortunately strseq
- can't have a const char **strs, that would require a const
- and a non-const version of it. */
- if ((result = alias_string ((const unsigned char **) &strs[i], &dd1, &len1)) < 0)
- {
- DDS_TRACE("plist/alias_stringseq: invalid string\n");
- goto fail;
- }
- seq += sizeof (uint32_t) + align4u (len1);
- }
- if (i != strseq->n)
- {
- DDS_TRACE("plist/validate_stringseq: buffer too small (contents)\n");
- result = Q_ERR_INVALID;
- goto fail;
- }
- strseq->strs = strs;
- }
- return 0;
- fail:
- ddsrt_free (strs);
- return result;
-}
-
-static void free_stringseq (nn_stringseq_t *strseq)
-{
- unsigned i;
- for (i = 0; i < strseq->n; i++)
- {
- if (strseq->strs[i])
- {
- ddsrt_free (strseq->strs[i]);
- }
- }
- ddsrt_free (strseq->strs);
-}
-
-static int unalias_stringseq (nn_stringseq_t *strseq, int bswap)
-{
- unsigned i;
- char **strs;
- if (strseq->n != 0)
- {
- strs = ddsrt_malloc (strseq->n * sizeof (*strs));
- for (i = 0; i < strseq->n; i++)
- {
- strs[i] = strseq->strs[i];
- unalias_string (&strs[i], bswap);
- }
- ddsrt_free (strseq->strs);
- strseq->strs = strs;
- }
- return 0;
-}
-
-static void duplicate_stringseq (nn_stringseq_t *dest, const nn_stringseq_t *src)
-{
- unsigned i;
- dest->n = src->n;
-assert (dest->strs == NULL);
- if (dest->n == 0)
- {
- dest->strs = NULL;
- return;
- }
- dest->strs = ddsrt_malloc (dest->n * sizeof (*dest->strs));
- for (i = 0; i < dest->n; i++)
- {
- dest->strs[i] = src->strs[i];
- unalias_string (&dest->strs[i], -1);
- }
-}
-
-static void free_locators (nn_locators_t *locs)
-{
- while (locs->first)
- {
- struct nn_locators_one *l = locs->first;
- locs->first = l->next;
- ddsrt_free (l);
- }
-}
-
-static void unalias_locators (nn_locators_t *locs, UNUSED_ARG (int bswap))
-{
- nn_locators_t newlocs;
- struct nn_locators_one *lold;
- /* Copy it, without reversing the order. On failure, free the copy,
- on success overwrite *locs. */
- newlocs.n = locs->n;
- newlocs.first = NULL;
- newlocs.last = NULL;
- for (lold = locs->first; lold != NULL; lold = lold->next)
- {
- struct nn_locators_one *n;
- n = ddsrt_malloc (sizeof (*n));
- n->next = NULL;
- n->loc = lold->loc;
- if (newlocs.first == NULL)
- newlocs.first = n;
- else
- newlocs.last->next = n;
- newlocs.last = n;
- }
- *locs = newlocs;
-}
-
-static void unalias_eotinfo (nn_prismtech_eotinfo_t *txnid, UNUSED_ARG (int bswap))
-{
- if (txnid->n > 0)
- {
- nn_prismtech_eotgroup_tid_t *vs;
- vs = ddsrt_malloc (txnid->n * sizeof (*vs));
- memcpy (vs, txnid->tids, txnid->n * sizeof (*vs));
- txnid->tids = vs;
- }
-}
-
-void nn_plist_fini (nn_plist_t *ps)
-{
- struct t { uint64_t fl; size_t off; };
- static const struct t simple[] = {
- { PP_ENTITY_NAME, offsetof (nn_plist_t, entity_name) },
- { PP_PRISMTECH_NODE_NAME, offsetof (nn_plist_t, node_name) },
- { PP_PRISMTECH_EXEC_NAME, offsetof (nn_plist_t, exec_name) },
- { PP_PRISMTECH_PARTICIPANT_VERSION_INFO, offsetof (nn_plist_t, prismtech_participant_version_info.internals) },
- { PP_PRISMTECH_TYPE_DESCRIPTION, offsetof (nn_plist_t, type_description) },
- { PP_PRISMTECH_EOTINFO, offsetof (nn_plist_t, eotinfo.tids) }
- };
- static const struct t locs[] = {
- { PP_UNICAST_LOCATOR, offsetof (nn_plist_t, unicast_locators) },
- { PP_MULTICAST_LOCATOR, offsetof (nn_plist_t, multicast_locators) },
- { PP_DEFAULT_UNICAST_LOCATOR, offsetof (nn_plist_t, default_unicast_locators) },
- { PP_DEFAULT_MULTICAST_LOCATOR, offsetof (nn_plist_t, default_multicast_locators) },
- { PP_METATRAFFIC_UNICAST_LOCATOR, offsetof (nn_plist_t, metatraffic_unicast_locators) },
- { PP_METATRAFFIC_MULTICAST_LOCATOR, offsetof (nn_plist_t, metatraffic_multicast_locators) }
- };
- int i;
- nn_xqos_fini (&ps->qos);
-
-/* The compiler doesn't understand how offsetof is used in the arrays. */
-DDSRT_WARNING_MSVC_OFF(6001);
- for (i = 0; i < (int) (sizeof (simple) / sizeof (*simple)); i++)
- {
- if ((ps->present & simple[i].fl) && !(ps->aliased & simple[i].fl))
- {
- void **pp = (void **) ((char *) ps + simple[i].off);
- ddsrt_free (*pp);
- }
- }
- for (i = 0; i < (int) (sizeof (locs) / sizeof (*locs)); i++)
- {
- if ((ps->present & locs[i].fl) && !(ps->aliased & locs[i].fl))
- free_locators ((nn_locators_t *) ((char *) ps + locs[i].off));
- }
-DDSRT_WARNING_MSVC_ON(6001);
-
- ps->present = 0;
-}
-
-#if 0 /* not currently needed */
-void nn_plist_unalias (nn_plist_t *ps)
-{
-#define P(name_, func_, field_) do { \
- if ((ps->present & PP_##name_) && (ps->aliased & PP_##name_)) { \
- unalias_##func_ (&ps->field_, -1); \
- ps->aliased &= ~PP_##name_; \
- } \
- } while (0)
- nn_xqos_unalias (&ps->qos);
- P (ENTITY_NAME, string, entity_name);
- P (UNICAST_LOCATOR, locators, unicast_locators);
- P (MULTICAST_LOCATOR, locators, multicast_locators);
- P (DEFAULT_UNICAST_LOCATOR, locators, default_unicast_locators);
- P (DEFAULT_MULTICAST_LOCATOR, locators, default_multicast_locators);
- P (METATRAFFIC_UNICAST_LOCATOR, locators, metatraffic_unicast_locators);
- P (METATRAFFIC_MULTICAST_LOCATOR, locators, metatraffic_multicast_locators);
- P (PRISMTECH_NODE_NAME, string, node_name);
- P (PRISMTECH_EXEC_NAME, string, exec_name);
- P (PRISMTECH_TYPE_DESCRIPTION, string, type_description);
- P (PRISMTECH_EOTINFO, eotinfo, eotinfo);
-#undef P
- if ((ps->present & PP_PRISMTECH_PARTICIPANT_VERSION_INFO) &&
- (ps->aliased & PP_PRISMTECH_PARTICIPANT_VERSION_INFO))
- {
- unalias_string (&ps->prismtech_participant_version_info.internals, -1);
- ps->aliased &= ~PP_PRISMTECH_PARTICIPANT_VERSION_INFO;
- }
-
- assert (ps->aliased == 0);
-}
#endif
-static int do_octetseq (nn_octetseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd)
+/* Standardized parameters -- QoS _MUST_ come first (nn_plist_init_tables verifies this) because
+ it allows early-out when processing a dds_qos_t instead of an nn_plist_t */
+static const struct piddesc piddesc_omg[] = {
+ QP (USER_DATA, user_data, XO),
+ QP (TOPIC_NAME, topic_name, XS),
+ QP (TYPE_NAME, type_name, XS),
+ QP (TOPIC_DATA, topic_data, XO),
+ QP (GROUP_DATA, group_data, XO),
+ QP (DURABILITY, durability, XE3),
+ /* CoreDX's use of all-zero durability service QoS means we can't use l; interdependencies between QoS
+ values means we must validate the combination anyway */
+ QPV (DURABILITY_SERVICE, durability_service, XD, XE1, Xix4),
+ QP (DEADLINE, deadline, XD),
+ QP (LATENCY_BUDGET, latency_budget, XD),
+ QP (LIVELINESS, liveliness, XE2, XD),
+ /* Reliability encoding does not follow the rules (best-effort/reliable map to 1/2 instead of 0/1 */
+ { PID_RELIABILITY, PDF_QOS | PDF_FUNCTION, QP_RELIABILITY, "RELIABILITY",
+ offsetof (struct nn_plist, qos.reliability), membersize (struct nn_plist, qos.reliability),
+ { .f = { .deser = deser_reliability, .ser = ser_reliability, .valid = valid_reliability, .equal = equal_reliability } }, 0 },
+ QP (LIFESPAN, lifespan, XD),
+ QP (DESTINATION_ORDER, destination_order, XE1),
+ /* History depth is ignored when kind = KEEP_ALL, and must be >= 1 when KEEP_LAST, so can't use "l" */
+ QPV (HISTORY, history, XE1, Xi),
+ QPV (RESOURCE_LIMITS, resource_limits, Xix3),
+ QP (OWNERSHIP, ownership, XE1),
+ QP (OWNERSHIP_STRENGTH, ownership_strength, Xi),
+ QP (PRESENTATION, presentation, XE2, Xbx2),
+ QP (PARTITION, partition, XZ),
+ QP (TIME_BASED_FILTER, time_based_filter, XD),
+ QP (TRANSPORT_PRIORITY, transport_priority, Xi),
+ PP (PROTOCOL_VERSION, protocol_version, Xox2),
+ PP (VENDORID, vendorid, Xox2),
+ PP (EXPECTS_INLINE_QOS, expects_inline_qos, Xb),
+ PP (PARTICIPANT_MANUAL_LIVELINESS_COUNT, participant_manual_liveliness_count, Xi),
+ PP (PARTICIPANT_BUILTIN_ENDPOINTS, participant_builtin_endpoints, Xu),
+ PP (PARTICIPANT_LEASE_DURATION, participant_lease_duration, XD),
+ PPV (PARTICIPANT_GUID, participant_guid, XG),
+ PPV (GROUP_GUID, group_guid, XG),
+ PP (BUILTIN_ENDPOINT_SET, builtin_endpoint_set, Xu),
+ PP (ENTITY_NAME, entity_name, XS),
+ PP (KEYHASH, keyhash, XK),
+ PPV (ENDPOINT_GUID, endpoint_guid, XG),
+#ifdef DDSI_INCLUDE_SSM
+ PPV (READER_FAVOURS_SSM, reader_favours_ssm, Xu),
+#endif
+ { PID_STATUSINFO, PDF_FUNCTION, PP_STATUSINFO, "STATUSINFO",
+ offsetof (struct nn_plist, statusinfo), membersize (struct nn_plist, statusinfo),
+ { .f = { .deser = deser_statusinfo, .ser = ser_statusinfo } }, 0 },
+ /* Locators are difficult to deal with because they can occur multi times to represent a set;
+ that is manageable for deser, unalias and fini, but it breaks ser because that one only
+ generates a single parameter header */
+ { PID_UNICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI,
+ PP_UNICAST_LOCATOR, "UNICAST_LOCATOR",
+ offsetof (struct nn_plist, unicast_locators), membersize (struct nn_plist, unicast_locators),
+ { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator } }, 0 },
+ { PID_MULTICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI,
+ PP_MULTICAST_LOCATOR, "MULTICAST_LOCATOR",
+ offsetof (struct nn_plist, multicast_locators), membersize (struct nn_plist, multicast_locators),
+ { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator } }, 0 },
+ { PID_DEFAULT_UNICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI,
+ PP_DEFAULT_UNICAST_LOCATOR, "DEFAULT_UNICAST_LOCATOR",
+ offsetof (struct nn_plist, default_unicast_locators), membersize (struct nn_plist, default_unicast_locators),
+ { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator } }, 0 },
+ { PID_DEFAULT_MULTICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI,
+ PP_DEFAULT_MULTICAST_LOCATOR, "DEFAULT_MULTICAST_LOCATOR",
+ offsetof (struct nn_plist, default_multicast_locators), membersize (struct nn_plist, default_multicast_locators),
+ { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator } }, 0 },
+ { PID_METATRAFFIC_UNICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI,
+ PP_METATRAFFIC_UNICAST_LOCATOR, "METATRAFFIC_UNICAST_LOCATOR",
+ offsetof (struct nn_plist, metatraffic_unicast_locators), membersize (struct nn_plist, metatraffic_unicast_locators),
+ { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator } }, 0 },
+ { PID_METATRAFFIC_MULTICAST_LOCATOR, PDF_FUNCTION | PDF_ALLOWMULTI,
+ PP_METATRAFFIC_MULTICAST_LOCATOR, "METATRAFFIC_MULTICAST_LOCATOR",
+ offsetof (struct nn_plist, metatraffic_multicast_locators), membersize (struct nn_plist, metatraffic_multicast_locators),
+ { .f = { .deser = deser_locator, .ser = ser_locator, .unalias = unalias_locator, .fini = fini_locator } }, 0 },
+ /* PID_..._{IPADDRESS,PORT} is impossible to deal with and are never generated, only accepted.
+ The problem is that there one needs additional state (and even then there is no clear
+ interpretation) ... So they'll have to be special-cased */
+ { PID_SENTINEL, 0, 0, NULL, 0, 0, { .desc = { XSTOP } }, 0 }
+};
+
+/* Understood parameters for Eclipse Foundation (Cyclone DDS) vendor code */
+static const struct piddesc piddesc_eclipse[] = {
+ QP (PRISMTECH_ENTITY_FACTORY, entity_factory, Xb),
+ QP (PRISMTECH_READER_LIFESPAN, reader_lifespan, Xb, XD),
+ QP (PRISMTECH_WRITER_DATA_LIFECYCLE, writer_data_lifecycle, Xb),
+ QP (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle, XDx2),
+ QP (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys, XbCOND, XZ),
+ { PID_PAD, PDF_QOS, QP_CYCLONE_IGNORELOCAL, "CYCLONE_IGNORELOCAL",
+ offsetof (struct nn_plist, qos.ignorelocal), membersize (struct nn_plist, qos.ignorelocal),
+ { .desc = { XE2, XSTOP } }, 0 },
+ PP (PRISMTECH_BUILTIN_ENDPOINT_SET, prismtech_builtin_endpoint_set, Xu),
+ PP (PRISMTECH_PARTICIPANT_VERSION_INFO, prismtech_participant_version_info, Xux5, XS),
+ PP (PRISMTECH_EXEC_NAME, exec_name, XS),
+ PP (PRISMTECH_PROCESS_ID, process_id, Xu),
+ PP (PRISMTECH_NODE_NAME, node_name, XS),
+ PP (PRISMTECH_TYPE_DESCRIPTION, type_description, XS),
+ { PID_SENTINEL, 0, 0, NULL, 0, 0, { .desc = { XSTOP } }, 0 }
+};
+
+/* Understood parameters for PrismTech vendor code */
+static const struct piddesc piddesc_prismtech[] = {
+ QP (PRISMTECH_ENTITY_FACTORY, entity_factory, Xb),
+ QP (PRISMTECH_READER_LIFESPAN, reader_lifespan, Xb, XD),
+ QP (PRISMTECH_WRITER_DATA_LIFECYCLE, writer_data_lifecycle, Xb),
+ QP (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle, XDx2),
+ QP (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys, XbCOND, XZ),
+ PP (PRISMTECH_BUILTIN_ENDPOINT_SET, prismtech_builtin_endpoint_set, Xu),
+ PP (PRISMTECH_PARTICIPANT_VERSION_INFO, prismtech_participant_version_info, Xux5, XS),
+ PP (PRISMTECH_EXEC_NAME, exec_name, XS),
+ PP (PRISMTECH_PROCESS_ID, process_id, Xu),
+ PP (PRISMTECH_NODE_NAME, node_name, XS),
+ PP (PRISMTECH_TYPE_DESCRIPTION, type_description, XS),
+ { PID_SENTINEL, 0, 0, NULL, 0, 0, { .desc = { XSTOP } }, 0 }
+};
+
+#undef PPM
+#undef PP
+#undef QP
+#undef PPV
+#undef QPV
+#undef ENTRY
+#undef membersize
+
+/* Parameters to be included in messages we generate */
+static const struct piddesc *piddesc_tables_output[] = {
+ piddesc_omg,
+ piddesc_eclipse
+};
+
+/* All known parameters -- this can potentially include
+ parameters from other vendors that we never generate
+ but that we do recognize on input and store for some
+ purpose other than the internal workings of Cyclone,
+ and that require fini/unalias processing */
+static const struct piddesc *piddesc_tables_all[] = {
+ piddesc_omg,
+ piddesc_eclipse
+};
+
+struct piddesc_index {
+ size_t index_max;
+ const struct piddesc **index;
+ /* include source table for generating the index --
+ it's easier to generate the index at startup then
+ to maintain in the source */
+ const struct piddesc *table;
+};
+
+/* Vendor code to vendor-specific table mapping, with index
+ vendor codes are currently of the form 1.x with x a small
+ number > 0 (and that's not likely to change) so we have
+ a table for major = 1 and use index 0 for the standard
+ ones.
+
+ Sizes are such that the highest PID (without flags) in
+ table are the last entry in the array. Checked by
+ nn_plist_init_tables.
+
+ FIXME: should compute them at build-time */
+#ifdef DDSI_INCLUDE_SSM
+static const struct piddesc *piddesc_omg_index[115];
+#else /* status info is the highest */
+static const struct piddesc *piddesc_omg_index[114];
+#endif
+static const struct piddesc *piddesc_eclipse_index[19];
+static const struct piddesc *piddesc_prismtech_index[19];
+
+#define INDEX_ANY(vendorid_, tab_) [vendorid_] = { \
+ .index_max = sizeof (piddesc_##tab_##_index) / sizeof (piddesc_##tab_##_index[0]) - 1, \
+ .index = (const struct piddesc **) piddesc_##tab_##_index, \
+ .table = piddesc_##tab_ }
+#define INDEX(VENDOR_, tab_) INDEX_ANY (NN_VENDORID_MINOR_##VENDOR_, tab_)
+
+static const struct piddesc_index piddesc_vendor_index[] = {
+ INDEX_ANY (0, omg),
+ INDEX (ECLIPSE, eclipse),
+ INDEX (PRISMTECH_OSPL, prismtech),
+ INDEX (PRISMTECH_JAVA, prismtech),
+ INDEX (PRISMTECH_LITE, prismtech),
+ INDEX (PRISMTECH_GATEWAY, prismtech),
+ INDEX (PRISMTECH_CLOUD, prismtech)
+};
+
+#undef INDEX
+#undef INDEX_ANY
+
+/* List of entries that require unalias, fini processing;
+ initialized by nn_plist_init_tables; will assert when
+ table too small or too large */
+static const struct piddesc *piddesc_unalias[18];
+static const struct piddesc *piddesc_fini[18];
+static ddsrt_once_t table_init_control = DDSRT_ONCE_INIT;
+
+static nn_parameterid_t pid_without_flags (nn_parameterid_t pid)
{
- int res;
- size_t len;
- if (!(wanted & fl))
- return NN_STRICT_P ? validate_octetseq (dd, &len) : 0;
- if ((res = alias_octetseq (dst, dd)) >= 0)
+ return (nn_parameterid_t) (pid & ~(PID_VENDORSPECIFIC_FLAG | PID_UNRECOGNIZED_INCOMPATIBLE_FLAG));
+}
+
+static int piddesc_cmp_qos_addr (const void *va, const void *vb)
+{
+ struct piddesc const * const *a = (struct piddesc const * const *) va;
+ struct piddesc const * const *b = (struct piddesc const * const *) vb;
+ /* QoS go first, then address */
+ if (((*a)->flags & PDF_QOS) != ((*b)->flags & PDF_QOS))
+ return ((*a)->flags & PDF_QOS) ? -1 : 1;
+ else
+ return ((uintptr_t) *a == (uintptr_t) *b) ? 0 : ((uintptr_t) *a < (uintptr_t) *b) ? -1 : 1;
+}
+
+static void nn_plist_init_tables_real (void)
+{
+ /* make index of pid -> entry */
+ for (size_t i = 0; i < sizeof (piddesc_vendor_index) / sizeof (piddesc_vendor_index[0]); i++)
{
- *present |= fl;
- *aliased |= fl;
+ const struct piddesc *table = piddesc_vendor_index[i].table;
+ if (table == NULL)
+ continue;
+ struct piddesc const **index = piddesc_vendor_index[i].index;
+#ifndef NDEBUG
+ nn_parameterid_t maxpid = 0;
+ bool only_qos_seen = true;
+#endif
+ for (size_t j = 0; table[j].pid != PID_SENTINEL; j++)
+ {
+ nn_parameterid_t pid = pid_without_flags (table[j].pid);
+#ifndef NDEBUG
+ /* Table must first list QoS, then other parameters */
+ assert (only_qos_seen || !(table[j].flags & PDF_QOS));
+ if (!(table[j].flags & PDF_QOS))
+ only_qos_seen = false;
+ /* Track max PID so we can verify the table is no larger
+ than necessary */
+ if (pid > maxpid)
+ maxpid = pid;
+#endif
+ /* PAD is used for entries that are never visible on the wire
+ and the decoder assumes the PAD entries will be skipped
+ because they don't map to an entry */
+ if (pid == PID_PAD)
+ continue;
+ assert (pid <= piddesc_vendor_index[i].index_max);
+ assert (index[pid] == NULL || index[pid] == &table[j]);
+ index[pid] = &table[j];
+ }
+ assert (maxpid == piddesc_vendor_index[i].index_max);
}
- return res;
-}
-static int do_blob (nn_octetseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd)
-{
- int res;
- if (!(wanted & fl))
- return 0;
- if ((res = alias_blob (dst, dd)) >= 0)
+ /* PIDs requiring unalias; there is overlap between the tables
+ (because of different vendor codes mapping to the same entry
+ in qos/plist). Use the "present" flags to filter out
+ duplicates. */
+ uint64_t pf = 0, qf = 0;
+ size_t unalias_index = 0;
+ size_t fini_index = 0;
+ for (size_t i = 0; i < sizeof (piddesc_vendor_index) / sizeof (piddesc_vendor_index[0]); i++)
{
- *present |= fl;
- *aliased |= fl;
+ const struct piddesc *table = piddesc_vendor_index[i].table;
+ if (table == NULL)
+ continue;
+ for (size_t j = 0; table[j].pid != PID_SENTINEL; j++)
+ {
+ uint64_t * const f = (table[j].flags & PDF_QOS) ? &qf : &pf;
+ if (*f & table[j].present_flag)
+ continue;
+ *f |= table[j].present_flag;
+ if (((table[j].flags & PDF_FUNCTION) && table[j].op.f.unalias) ||
+ (!(table[j].flags & PDF_FUNCTION) && unalias_generic_required (table[j].op.desc)))
+ {
+ assert (unalias_index < sizeof (piddesc_unalias) / sizeof (piddesc_unalias[0]));
+ piddesc_unalias[unalias_index++] = &table[j];
+ }
+ if (((table[j].flags & PDF_FUNCTION) && table[j].op.f.fini) ||
+ (!(table[j].flags & PDF_FUNCTION) && fini_generic_required (table[j].op.desc)))
+ {
+ assert (fini_index < sizeof (piddesc_fini) / sizeof (piddesc_fini[0]));
+ piddesc_fini[fini_index++] = &table[j];
+ }
+ }
}
- return res;
-}
-
-static int do_string (char **dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd)
-{
- int res;
- size_t len;
- if (!(wanted & fl))
- return NN_STRICT_P ? validate_string (dd, &len) : 0;
- if ((res = alias_string ((const unsigned char **) dst, dd, &len)) >= 0)
+ assert (unalias_index == sizeof (piddesc_unalias) / sizeof (piddesc_unalias[0]) &&
+ fini_index == sizeof (piddesc_fini) / sizeof (piddesc_fini[0]));
+ qsort ((void *) piddesc_unalias, unalias_index, sizeof (piddesc_unalias[0]), piddesc_cmp_qos_addr);
+ qsort ((void *) piddesc_fini, fini_index, sizeof (piddesc_fini[0]), piddesc_cmp_qos_addr);
+#ifndef NDEBUG
{
- *present |= fl;
- *aliased |= fl;
+ size_t i;
+ for (i = 0; i < unalias_index; i++)
+ if (!(piddesc_unalias[i]->flags & PDF_QOS))
+ break;
+ for (; i < unalias_index; i++)
+ assert (!(piddesc_unalias[i]->flags & PDF_QOS));
+ for (i = 0; i < fini_index; i++)
+ if (!(piddesc_fini[i]->flags & PDF_QOS))
+ break;
+ for (; i < fini_index; i++)
+ assert (!(piddesc_fini[i]->flags & PDF_QOS));
}
- return res;
+#endif
}
-static int do_stringseq (nn_stringseq_t *dst, uint64_t *present, uint64_t *aliased, uint64_t wanted, uint64_t fl, const struct dd *dd)
+void nn_plist_init_tables (void)
{
- int res;
- if (!(wanted & fl))
- return NN_STRICT_P ? validate_stringseq (dd) : 0;
- if ((res = alias_stringseq (dst, dd)) >= 0)
+ ddsrt_once (&table_init_control, nn_plist_init_tables_real);
+}
+
+static void plist_or_xqos_fini (void * __restrict dst, size_t shift, uint64_t pmask, uint64_t qmask)
+{
+ /* shift == 0: plist, shift > 0: just qos */
+ struct flagset pfs, qfs;
+ /* DDS manipulation can be done without creating a participant, so we may
+ have to initialize tables just-in-time */
+ if (piddesc_fini[0] == NULL)
+ nn_plist_init_tables ();
+ if (shift > 0)
{
- *present |= fl;
- *aliased |= fl;
+ dds_qos_t *qos = dst;
+ pfs = (struct flagset) { 0 };
+ qfs = (struct flagset) { .present = &qos->present, .aliased = &qos->aliased };
}
- return res;
-}
-
-static void bswap_time (nn_ddsi_time_t *t)
-{
- t->seconds = bswap4 (t->seconds);
- t->fraction = bswap4u (t->fraction);
-}
-
-static int validate_time (const nn_ddsi_time_t *t)
-{
- /* Accepter are zero, positive, infinite or invalid as defined in
- the DDS 2.1 spec, table 9.4. */
- if (t->seconds >= 0)
- return 0;
- else if (t->seconds == -1 && t->fraction == UINT32_MAX)
- return 0;
else
{
- DDS_TRACE("plist/validate_time: invalid timestamp (%08x.%08x)\n", t->seconds, t->fraction);
- return Q_ERR_INVALID;
+ nn_plist_t *plist = dst;
+ pfs = (struct flagset) { .present = &plist->present, .aliased = &plist->aliased };
+ qfs = (struct flagset) { .present = &plist->qos.present, .aliased = &plist->qos.aliased };
}
-}
-
-static void bswap_duration (nn_duration_t *d)
-{
- bswap_time (d);
-}
-
-int validate_duration (const nn_duration_t *d)
-{
- return validate_time (d);
-}
-
-static int do_duration (nn_duration_t *q, uint64_t *present, uint64_t fl, const struct dd *dd)
-{
- int res;
- if (dd->bufsz < sizeof (*q))
+ for (size_t i = 0; i < sizeof (piddesc_fini) / sizeof (piddesc_fini[0]); i++)
{
- DDS_TRACE("plist/do_duration: buffer too small\n");
- return Q_ERR_INVALID;
- }
- memcpy (q, dd->buf, sizeof (*q));
- if (dd->bswap)
- bswap_duration (q);
- if ((res = validate_duration (q)) < 0)
- return res;
- *present |= fl;
- return 0;
-}
-
-static void bswap_durability_qospolicy (nn_durability_qospolicy_t *q)
-{
- q->kind = bswap4u (q->kind);
-}
-
-int validate_durability_qospolicy (const nn_durability_qospolicy_t *q)
-{
- switch (q->kind)
- {
- case NN_VOLATILE_DURABILITY_QOS:
- case NN_TRANSIENT_LOCAL_DURABILITY_QOS:
- case NN_TRANSIENT_DURABILITY_QOS:
- case NN_PERSISTENT_DURABILITY_QOS:
+ struct piddesc const * const entry = piddesc_fini[i];
+ if (shift > 0 && !(entry->flags & PDF_QOS))
break;
- default:
- DDS_TRACE("plist/validate_durability_qospolicy: invalid kind (%d)\n", (int) q->kind);
- return Q_ERR_INVALID;
+ assert (entry->plist_offset >= shift);
+ assert (shift == 0 || entry->plist_offset - shift < sizeof (dds_qos_t));
+ size_t dstoff = entry->plist_offset - shift;
+ struct flagset * const fs = (entry->flags & PDF_QOS) ? &qfs : &pfs;
+ uint64_t mask = (entry->flags & PDF_QOS) ? qmask : pmask;
+ if (*fs->present & entry->present_flag & mask)
+ {
+ if (!(entry->flags & PDF_FUNCTION))
+ fini_generic (dst, &dstoff, fs, entry->present_flag, entry->op.desc);
+ else if (entry->op.f.fini)
+ entry->op.f.fini (dst, &dstoff, fs, entry->present_flag);
+ }
}
- return 0;
+ if (pfs.present) { *pfs.present &= ~pmask; *pfs.aliased &= ~pmask; }
+ *qfs.present &= ~qmask; *qfs.aliased &= ~qmask;
}
-static void bswap_history_qospolicy (nn_history_qospolicy_t *q)
+static void plist_or_xqos_unalias (void * __restrict dst, size_t shift)
{
- q->kind = bswap4u (q->kind);
- q->depth = bswap4 (q->depth);
+ /* shift == 0: plist, shift > 0: just qos */
+ struct flagset pfs, qfs;
+ /* DDS manipulation can be done without creating a participant, so we may
+ have to initialize tables just-in-time */
+ if (piddesc_unalias[0] == NULL)
+ nn_plist_init_tables ();
+ if (shift > 0)
+ {
+ dds_qos_t *qos = dst;
+ pfs = (struct flagset) { 0 };
+ qfs = (struct flagset) { .present = &qos->present, .aliased = &qos->aliased };
+ }
+ else
+ {
+ nn_plist_t *plist = dst;
+ pfs = (struct flagset) { .present = &plist->present, .aliased = &plist->aliased };
+ qfs = (struct flagset) { .present = &plist->qos.present, .aliased = &plist->qos.aliased };
+ }
+ for (size_t i = 0; i < sizeof (piddesc_unalias) / sizeof (piddesc_unalias[0]); i++)
+ {
+ struct piddesc const * const entry = piddesc_unalias[i];
+ if (shift > 0 && !(entry->flags & PDF_QOS))
+ break;
+ assert (entry->plist_offset >= shift);
+ assert (shift == 0 || entry->plist_offset - shift < sizeof (dds_qos_t));
+ size_t dstoff = entry->plist_offset - shift;
+ struct flagset * const fs = (entry->flags & PDF_QOS) ? &qfs : &pfs;
+ if ((*fs->present & entry->present_flag) && (*fs->aliased & entry->present_flag))
+ {
+ if (!(entry->flags & PDF_FUNCTION))
+ unalias_generic (dst, &dstoff, entry->op.desc);
+ else if (entry->op.f.unalias)
+ entry->op.f.unalias (dst, &dstoff);
+ *fs->aliased &= ~entry->present_flag;
+ }
+ }
+ assert (pfs.aliased == NULL || *pfs.aliased == 0);
+ assert (*qfs.aliased == 0);
}
-static int history_qospolicy_allzero (const nn_history_qospolicy_t *q)
+static void plist_or_xqos_mergein_missing (void * __restrict dst, const void * __restrict src, size_t shift, uint64_t pmask, uint64_t qmask)
{
- return q->kind == NN_KEEP_LAST_HISTORY_QOS && q->depth == 0;
+ /* shift == 0: plist, shift > 0: just qos */
+ struct flagset pfs_src, qfs_src;
+ struct flagset pfs_dst, qfs_dst;
+#ifndef NDEBUG
+ const uint64_t aliased_dst_inp = (shift == 0) ? ((nn_plist_t *) dst)->aliased : 0;
+ const uint64_t aliased_dst_inq = (shift == 0) ? ((nn_plist_t *) dst)->qos.aliased : ((dds_qos_t *) dst)->aliased;
+#endif
+ if (shift > 0)
+ {
+ dds_qos_t *qos_dst = dst;
+ const dds_qos_t *qos_src = src;
+ pfs_dst = (struct flagset) { 0 };
+ qfs_dst = (struct flagset) { .present = &qos_dst->present, .aliased = &qos_dst->aliased };
+ pfs_src = (struct flagset) { 0 };
+ qfs_src = (struct flagset) { .present = (uint64_t *) &qos_src->present, .aliased = (uint64_t *) &qos_src->aliased };
+ }
+ else
+ {
+ nn_plist_t *plist_dst = dst;
+ const nn_plist_t *plist_src = src;
+ pfs_dst = (struct flagset) { .present = &plist_dst->present, .aliased = &plist_dst->aliased };
+ qfs_dst = (struct flagset) { .present = &plist_dst->qos.present, .aliased = &plist_dst->qos.aliased };
+ pfs_src = (struct flagset) { .present = (uint64_t *) &plist_src->present, .aliased = (uint64_t *) &plist_src->aliased };
+ qfs_src = (struct flagset) { .present = (uint64_t *) &plist_src->qos.present, .aliased = (uint64_t *) &plist_src->qos.aliased };
+ }
+ /* aliased may never have any bits set that are clear in present */
+ assert (pfs_dst.present == NULL || (aliased_dst_inp & ~ *pfs_dst.present) == 0);
+ assert ((aliased_dst_inq & ~ *qfs_dst.present) == 0);
+ for (size_t k = 0; k < sizeof (piddesc_tables_all) / sizeof (piddesc_tables_all[0]); k++)
+ {
+ struct piddesc const * const table = piddesc_tables_all[k];
+ for (uint32_t i = 0; table[i].pid != PID_SENTINEL; i++)
+ {
+ struct piddesc const * const entry = &table[i];
+ if (shift > 0 && !(entry->flags & PDF_QOS))
+ break;
+ assert (entry->plist_offset >= shift);
+ assert (shift == 0 || entry->plist_offset - shift < sizeof (dds_qos_t));
+ size_t dstoff = entry->plist_offset - shift;
+ struct flagset * const fs_dst = (entry->flags & PDF_QOS) ? &qfs_dst : &pfs_dst;
+ struct flagset * const fs_src = (entry->flags & PDF_QOS) ? &qfs_src : &pfs_src;
+ uint64_t const mask = (entry->flags & PDF_QOS) ? qmask : pmask;
+ /* skip if already present in dst or absent in src */
+ if (!(*fs_dst->present & entry->present_flag) && (*fs_src->present & mask & entry->present_flag))
+ {
+ /* bitwise copy, mark as aliased & unalias; have to unalias fields one-by-one rather than
+ do this for all fields and call "unalias" on the entire object because fields that are
+ already present may be aliased, and it would be somewhat impolite to change that.
+
+ Note: dst & src have the same type, so offset in src is the same;
+ Note: unalias may have to look at */
+ memcpy ((char *) dst + dstoff, (const char *) src + dstoff, entry->size);
+ *fs_dst->present |= entry->present_flag;
+ if (!(entry->flags & PDF_FUNCTION))
+ unalias_generic (dst, &dstoff, entry->op.desc);
+ else if (entry->op.f.unalias)
+ entry->op.f.unalias (dst, &dstoff);
+ }
+ }
+ }
+ /* all entries in src should be present in dst (but there may be more) */
+ assert (pfs_dst.present == NULL || (*pfs_src.present & pmask & ~ *pfs_dst.present) == 0);
+ assert ((*qfs_src.present & qmask & ~ *qfs_dst.present) == 0);
+ /* the only aliased entries in dst may be ones that were aliased on input */
+ assert (pfs_dst.aliased == NULL || (*pfs_dst.aliased & ~ aliased_dst_inp) == 0);
+ assert ((*qfs_dst.aliased & ~ aliased_dst_inq) == 0);
}
-int validate_history_qospolicy (const nn_history_qospolicy_t *q)
+static void plist_or_xqos_addtomsg (struct nn_xmsg *xmsg, const void * __restrict src, size_t shift, uint64_t pwanted, uint64_t qwanted)
+{
+ /* shift == 0: plist, shift > 0: just qos */
+ uint64_t pw, qw;
+ if (shift > 0)
+ {
+ const dds_qos_t *qos = src;
+ pw = 0;
+ qw = qos->present & qwanted;
+ }
+ else
+ {
+ const nn_plist_t *plist = src;
+ pw = plist->present & pwanted;
+ qw = plist->qos.present & qwanted;
+ }
+ for (size_t k = 0; k < sizeof (piddesc_tables_output) / sizeof (piddesc_tables_output[0]); k++)
+ {
+ struct piddesc const * const table = piddesc_tables_output[k];
+ for (uint32_t i = 0; table[i].pid != PID_SENTINEL; i++)
+ {
+ struct piddesc const * const entry = &table[i];
+ if (entry->pid == PID_PAD)
+ continue;
+ if (((entry->flags & PDF_QOS) ? qw : pw) & entry->present_flag)
+ {
+ assert (entry->plist_offset >= shift);
+ assert (shift == 0 || entry->plist_offset - shift < sizeof (dds_qos_t));
+ size_t srcoff = entry->plist_offset - shift;
+ if (!(entry->flags & PDF_FUNCTION))
+ ser_generic (xmsg, entry->pid, src, srcoff, entry->op.desc);
+ else
+ entry->op.f.ser (xmsg, entry->pid, src, srcoff);
+ }
+ }
+ }
+}
+
+void nn_plist_fini (nn_plist_t *plist)
+{
+ plist_or_xqos_fini (plist, 0, ~(uint64_t)0, ~(uint64_t)0);
+}
+
+void nn_plist_unalias (nn_plist_t *plist)
+{
+ plist_or_xqos_unalias (plist, 0);
+}
+
+static dds_return_t nn_xqos_valid_strictness (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos, bool strict)
+{
+ dds_return_t ret;
+ if (piddesc_unalias[0] == NULL)
+ nn_plist_init_tables ();
+ for (size_t k = 0; k < sizeof (piddesc_tables_all) / sizeof (piddesc_tables_all[0]); k++)
+ {
+ struct piddesc const * const table = piddesc_tables_all[k];
+ for (uint32_t i = 0; table[i].pid != PID_SENTINEL; i++)
+ {
+ struct piddesc const * const entry = &table[i];
+ if (!(entry->flags & PDF_QOS))
+ break;
+ if (xqos->present & entry->present_flag)
+ {
+ const size_t srcoff = entry->plist_offset - offsetof (nn_plist_t, qos);
+ if (!(entry->flags & PDF_FUNCTION))
+ ret = valid_generic (xqos, srcoff, entry->op.desc);
+ else
+ ret = entry->op.f.valid (xqos, srcoff);
+ if (ret < 0)
+ {
+ DDS_CLOG (DDS_LC_PLIST, logcfg, "nn_xqos_valid: %s invalid\n", entry->name);
+ return ret;
+ }
+ }
+ }
+ }
+ if ((ret = final_validation_qos (xqos, (nn_protocol_version_t) { RTPS_MAJOR, RTPS_MINOR }, NN_VENDORID_ECLIPSE, NULL, strict)) < 0)
+ {
+ DDS_CLOG (DDS_LC_PLIST, logcfg, "nn_xqos_valid: final validation failed\n");
+ }
+ return ret;
+}
+
+dds_return_t nn_xqos_valid (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos)
+{
+ return nn_xqos_valid_strictness (logcfg, xqos, true);
+}
+
+uint64_t nn_xqos_delta (const dds_qos_t *x, const dds_qos_t *y, uint64_t mask)
+{
+ if (piddesc_unalias[0] == NULL)
+ nn_plist_init_tables ();
+ /* Returns QP_... set for settings where x differs from y; if
+ present in x but not in y (or in y but not in x) it counts as a
+ difference. */
+ uint64_t delta = (x->present ^ y->present) & mask;
+ const uint64_t check = (x->present & y->present) & mask;
+ for (size_t k = 0; k < sizeof (piddesc_tables_all) / sizeof (piddesc_tables_all[0]); k++)
+ {
+ struct piddesc const * const table = piddesc_tables_all[k];
+ for (uint32_t i = 0; table[i].pid != PID_SENTINEL; i++)
+ {
+ struct piddesc const * const entry = &table[i];
+ if (!(entry->flags & PDF_QOS))
+ break;
+ if (check & entry->present_flag)
+ {
+ const size_t srcoff = entry->plist_offset - offsetof (nn_plist_t, qos);
+ bool equal;
+ /* Partition is special-cased because it is a set (with a special rules
+ for empty sets and empty strings to boot), and normal string sequence
+ comparison requires the ordering to be the same */
+ if (entry->pid == PID_PARTITION)
+ equal = partitions_equal (&x->partition, &y->partition);
+ else if (!(entry->flags & PDF_FUNCTION))
+ equal = equal_generic (x, y, srcoff, entry->op.desc);
+ else
+ equal = entry->op.f.equal (x, y, srcoff);
+ if (!equal)
+ delta |= entry->present_flag;
+ }
+ }
+ }
+ return delta;
+}
+
+static dds_return_t validate_external_duration (const ddsi_duration_t *d)
+{
+ /* Accepted are zero, positive, infinite or invalid as defined in
+ the DDS 2.1 spec, table 9.4. */
+ if (d->seconds >= 0)
+ return 0;
+ else if (d->seconds == -1 && d->fraction == UINT32_MAX)
+ return 0;
+ else
+ return DDS_RETCODE_BAD_PARAMETER;
+}
+
+static int history_qospolicy_allzero (const dds_history_qospolicy_t *q)
+{
+ return q->kind == DDS_HISTORY_KEEP_LAST && q->depth == 0;
+}
+
+static dds_return_t validate_history_qospolicy (const dds_history_qospolicy_t *q)
{
/* Validity of history setting and of resource limits are dependent,
but we don't have access to the resource limits here ... the
@@ -610,304 +1565,87 @@ int validate_history_qospolicy (const nn_history_qospolicy_t *q)
n possibly unlimited. */
switch (q->kind)
{
- case NN_KEEP_LAST_HISTORY_QOS:
- case NN_KEEP_ALL_HISTORY_QOS:
+ case DDS_HISTORY_KEEP_LAST:
+ case DDS_HISTORY_KEEP_ALL:
break;
default:
- DDS_TRACE("plist/validate_history_qospolicy: invalid kind (%d)\n", (int) q->kind);
- return Q_ERR_INVALID;
+ return DDS_RETCODE_BAD_PARAMETER;
}
/* Accept all values for depth if kind = ALL */
- if (q->kind == NN_KEEP_LAST_HISTORY_QOS)
- {
- if (q->depth < 1)
- {
- DDS_TRACE("plist/validate_history_qospolicy: invalid depth (%d)\n", (int) q->depth);
- return Q_ERR_INVALID;
- }
- }
+ if (q->kind == DDS_HISTORY_KEEP_LAST && q->depth < 1)
+ return DDS_RETCODE_BAD_PARAMETER;
return 0;
}
-static void bswap_resource_limits_qospolicy (nn_resource_limits_qospolicy_t *q)
-{
- q->max_samples = bswap4 (q->max_samples);
- q->max_instances = bswap4 (q->max_instances);
- q->max_samples_per_instance = bswap4 (q->max_samples_per_instance);
-}
-
-static int resource_limits_qospolicy_allzero (const nn_resource_limits_qospolicy_t *q)
+static int resource_limits_qospolicy_allzero (const dds_resource_limits_qospolicy_t *q)
{
return q->max_samples == 0 && q->max_instances == 0 && q->max_samples_per_instance == 0;
}
-int validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q)
+static dds_return_t validate_resource_limits_qospolicy (const dds_resource_limits_qospolicy_t *q)
{
- const int unlimited = NN_DDS_LENGTH_UNLIMITED;
/* Note: dependent on history setting as well (see
validate_history_qospolicy). Verifying only the internal
consistency of the resource limits. */
- if (q->max_samples < 1 && q->max_samples != unlimited)
- {
- DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples invalid (%d)\n", (int) q->max_samples);
- return Q_ERR_INVALID;
- }
- if (q->max_instances < 1 && q->max_instances != unlimited)
- {
- DDS_TRACE("plist/validate_resource_limits_qospolicy: max_instances invalid (%d)\n", (int) q->max_instances);
- return Q_ERR_INVALID;
- }
- if (q->max_samples_per_instance < 1 && q->max_samples_per_instance != unlimited)
- {
- DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples_per_instance invalid (%d)\n", (int) q->max_samples_per_instance);
- return Q_ERR_INVALID;
- }
- if (q->max_samples != unlimited && q->max_samples_per_instance != unlimited)
+ if (q->max_samples < 1 && q->max_samples != DDS_LENGTH_UNLIMITED)
+ return DDS_RETCODE_BAD_PARAMETER;
+ if (q->max_instances < 1 && q->max_instances != DDS_LENGTH_UNLIMITED)
+ return DDS_RETCODE_BAD_PARAMETER;
+ if (q->max_samples_per_instance < 1 && q->max_samples_per_instance != DDS_LENGTH_UNLIMITED)
+ return DDS_RETCODE_BAD_PARAMETER;
+ if (q->max_samples != DDS_LENGTH_UNLIMITED && q->max_samples_per_instance != DDS_LENGTH_UNLIMITED)
{
/* Interpreting 7.1.3.19 as if "unlimited" is meant to mean "don't
care" and any conditions related to it must be ignored. */
if (q->max_samples < q->max_samples_per_instance)
- {
- DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples (%d) and max_samples_per_instance (%d) incompatible\n", (int) q->max_samples, (int) q->max_samples_per_instance);
- return Q_ERR_INVALID;
- }
+ return DDS_RETCODE_INCONSISTENT_POLICY;
}
return 0;
}
-int validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, const nn_resource_limits_qospolicy_t *qr)
+static dds_return_t validate_history_and_resource_limits (const dds_history_qospolicy_t *qh, const dds_resource_limits_qospolicy_t *qr)
{
- const int unlimited = NN_DDS_LENGTH_UNLIMITED;
- int res;
+ dds_return_t res;
if ((res = validate_history_qospolicy (qh)) < 0)
- {
- DDS_TRACE("plist/validate_history_and_resource_limits: history policy invalid\n");
return res;
- }
if ((res = validate_resource_limits_qospolicy (qr)) < 0)
- {
- DDS_TRACE("plist/validate_history_and_resource_limits: resource_limits policy invalid\n");
return res;
- }
switch (qh->kind)
{
- case NN_KEEP_ALL_HISTORY_QOS:
+ case DDS_HISTORY_KEEP_ALL:
#if 0 /* See comment in validate_resource_limits, ref'ing 7.1.3.19 */
- if (qr->max_samples_per_instance != unlimited)
- {
- DDS_TRACE("plist/validate_history_and_resource_limits: max_samples_per_instance (%d) incompatible with KEEP_ALL policy\n", (int) qr->max_samples_per_instance);
- return Q_ERR_INVALID;
- }
+ if (qr->max_samples_per_instance != DDS_LENGTH_UNLIMITED)
+ return DDS_RETCODE_BAD_PARAMETER;
#endif
break;
- case NN_KEEP_LAST_HISTORY_QOS:
- if (qr->max_samples_per_instance != unlimited && qh->depth > qr->max_samples_per_instance)
- {
- DDS_TRACE("plist/validate_history_and_resource_limits: depth (%d) and max_samples_per_instance (%d) incompatible with KEEP_LAST policy\n", (int) qh->depth, (int) qr->max_samples_per_instance);
- return Q_ERR_INVALID;
- }
+ case DDS_HISTORY_KEEP_LAST:
+ if (qr->max_samples_per_instance != DDS_LENGTH_UNLIMITED && qh->depth > qr->max_samples_per_instance)
+ return DDS_RETCODE_INCONSISTENT_POLICY;
break;
}
return 0;
}
-static void bswap_durability_service_qospolicy (nn_durability_service_qospolicy_t *q)
-{
- bswap_duration (&q->service_cleanup_delay);
- bswap_history_qospolicy (&q->history);
- bswap_resource_limits_qospolicy (&q->resource_limits);
-}
-
-static int durability_service_qospolicy_allzero (const nn_durability_service_qospolicy_t *q)
+static int durability_service_qospolicy_allzero (const dds_durability_service_qospolicy_t *q)
{
return (history_qospolicy_allzero (&q->history) &&
resource_limits_qospolicy_allzero (&q->resource_limits) &&
- q->service_cleanup_delay.seconds == 0 && q->service_cleanup_delay.fraction == 0);
+ q->service_cleanup_delay == 0);
}
-static int validate_durability_service_qospolicy_acceptzero (const nn_durability_service_qospolicy_t *q, bool acceptzero)
+static dds_return_t validate_durability_service_qospolicy_acceptzero (const dds_durability_service_qospolicy_t *q, bool acceptzero)
{
- int res;
+ dds_return_t res;
if (acceptzero && durability_service_qospolicy_allzero (q))
return 0;
- if ((res = validate_duration (&q->service_cleanup_delay)) < 0)
- {
- DDS_TRACE("plist/validate_durability_service_qospolicy: duration invalid\n");
- return res;
- }
+ if (q->service_cleanup_delay < 0)
+ return DDS_RETCODE_BAD_PARAMETER;
if ((res = validate_history_and_resource_limits (&q->history, &q->resource_limits)) < 0)
- {
- DDS_TRACE("plist/validate_durability_service_qospolicy: invalid history and/or resource limits\n");
return res;
- }
return 0;
}
-int validate_durability_service_qospolicy (const nn_durability_service_qospolicy_t *q)
-{
- return validate_durability_service_qospolicy_acceptzero (q, false);
-}
-
-static void bswap_liveliness_qospolicy (nn_liveliness_qospolicy_t *q)
-{
- q->kind = bswap4u (q->kind);
- bswap_duration (&q->lease_duration);
-}
-
-int validate_liveliness_qospolicy (const nn_liveliness_qospolicy_t *q)
-{
- int res;
- switch (q->kind)
- {
- case NN_AUTOMATIC_LIVELINESS_QOS:
- case NN_MANUAL_BY_PARTICIPANT_LIVELINESS_QOS:
- case NN_MANUAL_BY_TOPIC_LIVELINESS_QOS:
- if ((res = validate_duration (&q->lease_duration)) < 0)
- DDS_TRACE("plist/validate_liveliness_qospolicy: invalid lease duration\n");
- return res;
- default:
- DDS_TRACE("plist/validate_liveliness_qospolicy: invalid kind (%d)\n", (int) q->kind);
- return Q_ERR_INVALID;
- }
-}
-
-static void bswap_external_reliability_qospolicy (nn_external_reliability_qospolicy_t *qext)
-{
- qext->kind = bswap4u (qext->kind);
- bswap_duration (&qext->max_blocking_time);
-}
-
-static int validate_xform_reliability_qospolicy (nn_reliability_qospolicy_t *qdst, const nn_external_reliability_qospolicy_t *qext)
-{
- int res;
- qdst->max_blocking_time = qext->max_blocking_time;
- if (NN_PEDANTIC_P)
- {
- switch (qext->kind)
- {
- case NN_PEDANTIC_BEST_EFFORT_RELIABILITY_QOS:
- qdst->kind = NN_BEST_EFFORT_RELIABILITY_QOS;
- return 0;
- case NN_PEDANTIC_RELIABLE_RELIABILITY_QOS:
- qdst->kind = NN_RELIABLE_RELIABILITY_QOS;
- if ((res = validate_duration (&qdst->max_blocking_time)) < 0)
- DDS_TRACE("plist/validate_xform_reliability_qospolicy[pedantic]: max_blocking_time invalid\n");
- return res;
- default:
- DDS_TRACE("plist/validate_xform_reliability_qospolicy[pedantic]: invalid kind (%d)\n", (int) qext->kind);
- return Q_ERR_INVALID;
- }
- }
- else
- {
- switch (qext->kind)
- {
- case NN_INTEROP_BEST_EFFORT_RELIABILITY_QOS:
- qdst->kind = NN_BEST_EFFORT_RELIABILITY_QOS;
- return 0;
- case NN_INTEROP_RELIABLE_RELIABILITY_QOS:
- qdst->kind = NN_RELIABLE_RELIABILITY_QOS;
- if ((res = validate_duration (&qdst->max_blocking_time)) < 0)
- DDS_TRACE("plist/validate_xform_reliability_qospolicy[!pedantic]: max_blocking time invalid\n");
- return res;
- default:
- DDS_TRACE("plist/validate_xform_reliability_qospolicy[!pedantic]: invalid kind (%d)\n", (int) qext->kind);
- return Q_ERR_INVALID;
- }
- }
-}
-
-static void bswap_destination_order_qospolicy (nn_destination_order_qospolicy_t *q)
-{
- q->kind = bswap4u (q->kind);
-}
-
-int validate_destination_order_qospolicy (const nn_destination_order_qospolicy_t *q)
-{
- switch (q->kind)
- {
- case NN_BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS:
- case NN_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS:
- return 0;
- default:
- DDS_TRACE("plist/validate_destination_order_qospolicy: invalid kind (%d)\n", (int) q->kind);
- return Q_ERR_INVALID;
- }
-}
-
-static void bswap_ownership_qospolicy (nn_ownership_qospolicy_t *q)
-{
- q->kind = bswap4u (q->kind);
-}
-
-int validate_ownership_qospolicy (const nn_ownership_qospolicy_t *q)
-{
- switch (q->kind)
- {
- case NN_SHARED_OWNERSHIP_QOS:
- case NN_EXCLUSIVE_OWNERSHIP_QOS:
- return 0;
- default:
- DDS_TRACE("plist/validate_ownership_qospolicy: invalid kind (%d)\n", (int) q->kind);
- return Q_ERR_INVALID;
- }
-}
-
-static void bswap_ownership_strength_qospolicy (nn_ownership_strength_qospolicy_t *q)
-{
- q->value = bswap4 (q->value);
-}
-
-int validate_ownership_strength_qospolicy (UNUSED_ARG (const nn_ownership_strength_qospolicy_t *q))
-{
- return 1;
-}
-
-static void bswap_presentation_qospolicy (nn_presentation_qospolicy_t *q)
-{
- q->access_scope = bswap4u (q->access_scope);
-}
-
-int validate_presentation_qospolicy (const nn_presentation_qospolicy_t *q)
-{
- switch (q->access_scope)
- {
- case NN_INSTANCE_PRESENTATION_QOS:
- case NN_TOPIC_PRESENTATION_QOS:
- case NN_GROUP_PRESENTATION_QOS:
- break;
- default:
- DDS_TRACE("plist/validate_presentation_qospolicy: invalid access_scope (%d)\n", (int) q->access_scope);
- return Q_ERR_INVALID;
- }
- /* Bools must be 0 or 1, i.e., only the lsb may be set */
- if (q->coherent_access & ~1)
- {
- DDS_TRACE("plist/validate_presentation_qospolicy: coherent_access invalid (%d)\n", (int) q->coherent_access);
- return Q_ERR_INVALID;
- }
- if (q->ordered_access & ~1)
- {
- DDS_TRACE("plist/validate_presentation_qospolicy: ordered_access invalid (%d)\n", (int) q->ordered_access);
- return Q_ERR_INVALID;
- }
- /* coherent_access & ordered_access are a bit irrelevant for
- instance presentation qos, but it appears as if their values are
- not prescribed in that case. */
- return 0;
-}
-
-static void bswap_transport_priority_qospolicy (nn_transport_priority_qospolicy_t *q)
-{
- q->value = bswap4 (q->value);
-}
-
-int validate_transport_priority_qospolicy (UNUSED_ARG (const nn_transport_priority_qospolicy_t *q))
-{
- return 1;
-}
-
-static int add_locator (nn_locators_t *ls, uint64_t *present, uint64_t wanted, uint64_t fl, const nn_locator_t *loc)
+static dds_return_t add_locator (nn_locators_t *ls, uint64_t *present, uint64_t wanted, uint64_t fl, const nn_locator_t *loc)
{
if (wanted & fl)
{
@@ -940,33 +1678,24 @@ static int locator_address_prefix12_zero (const nn_locator_t *loc)
/* loc has has 32 bit ints preceding the address, hence address is
4-byte aligned; reading char* as unsigneds isn't illegal type
punning */
- const unsigned *u = (const unsigned *) loc->address;
+ const uint32_t *u = (const uint32_t *) loc->address;
return (u[0] == 0 && u[1] == 0 && u[2] == 0);
}
static int locator_address_zero (const nn_locator_t *loc)
{
/* see locator_address_prefix12_zero */
- const unsigned *u = (const unsigned *) loc->address;
+ const uint32_t *u = (const uint32_t *) loc->address;
return (u[0] == 0 && u[1] == 0 && u[2] == 0 && u[3] == 0);
}
-static int do_locator
-(
- nn_locators_t *ls,
- uint64_t *present,
- uint64_t wanted,
- uint64_t fl,
- const struct dd *dd
-)
+static dds_return_t do_locator (nn_locators_t *ls, uint64_t *present, uint64_t wanted, uint64_t fl, const struct dd *dd, const struct ddsi_tran_factory *factory)
{
nn_locator_t loc;
if (dd->bufsz < sizeof (loc))
- {
- DDS_TRACE("plist/do_locator: buffer too small\n");
- return Q_ERR_INVALID;
- }
+ return DDS_RETCODE_BAD_PARAMETER;
+
memcpy (&loc, dd->buf, sizeof (loc));
if (dd->bswap)
{
@@ -978,83 +1707,58 @@ static int do_locator
case NN_LOCATOR_KIND_UDPv4:
case NN_LOCATOR_KIND_TCPv4:
if (loc.port <= 0 || loc.port > 65535)
- {
- DDS_TRACE("plist/do_locator[kind=IPv4]: invalid port (%d)\n", (int) loc.port);
- return Q_ERR_INVALID;
- }
+ return DDS_RETCODE_BAD_PARAMETER;
if (!locator_address_prefix12_zero (&loc))
- {
- DDS_TRACE("plist/do_locator[kind=IPv4]: junk in address prefix\n");
- return Q_ERR_INVALID;
- }
+ return DDS_RETCODE_BAD_PARAMETER;
break;
case NN_LOCATOR_KIND_UDPv6:
case NN_LOCATOR_KIND_TCPv6:
if (loc.port <= 0 || loc.port > 65535)
- {
- DDS_TRACE("plist/do_locator[kind=IPv6]: invalid port (%d)\n", (int) loc.port);
- return Q_ERR_INVALID;
- }
+ return DDS_RETCODE_BAD_PARAMETER;
break;
case NN_LOCATOR_KIND_UDPv4MCGEN: {
const nn_udpv4mcgen_address_t *x = (const nn_udpv4mcgen_address_t *) loc.address;
- if (!ddsi_factory_supports(gv.m_factory, NN_LOCATOR_KIND_UDPv4))
+ if (!ddsi_factory_supports (factory, NN_LOCATOR_KIND_UDPv4))
return 0;
if (loc.port <= 0 || loc.port > 65536)
- {
- DDS_TRACE("plist/do_locator[kind=IPv4MCGEN]: invalid port (%d)\n", (int) loc.port);
- return Q_ERR_INVALID;
- }
- if ((int)x->base + x->count >= 28 || x->count == 0 || x->idx >= x->count)
- {
- DDS_TRACE("plist/do_locator[kind=IPv4MCGEN]: invalid base/count/idx (%u,%u,%u)\n", x->base, x->count, x->idx);
- return Q_ERR_INVALID;
- }
+ return DDS_RETCODE_BAD_PARAMETER;
+ if ((uint32_t) x->base + x->count >= 28 || x->count == 0 || x->idx >= x->count)
+ return DDS_RETCODE_BAD_PARAMETER;
break;
}
case NN_LOCATOR_KIND_INVALID:
if (!locator_address_zero (&loc))
- {
- DDS_TRACE("plist/do_locator[kind=INVALID]: junk in address\n");
- return Q_ERR_INVALID;
- }
+ return DDS_RETCODE_BAD_PARAMETER;
if (loc.port != 0)
- {
- DDS_TRACE("plist/do_locator[kind=INVALID]: junk in port\n");
- return Q_ERR_INVALID;
- }
+ return DDS_RETCODE_BAD_PARAMETER;
/* silently dropped correctly formatted "invalid" locators. */
return 0;
case NN_LOCATOR_KIND_RESERVED:
/* silently dropped "reserved" locators. */
return 0;
default:
- DDS_TRACE("plist/do_locator: invalid kind (%d)\n", (int) loc.kind);
- return NN_PEDANTIC_P ? Q_ERR_INVALID : 0;
+ return 0;
}
return add_locator (ls, present, wanted, fl, &loc);
}
-static void locator_from_ipv4address_port (nn_locator_t *loc, const nn_ipv4address_t *a, const nn_port_t *p)
+static void locator_from_ipv4address_port (nn_locator_t *loc, const nn_ipv4address_t *a, const nn_port_t *p, ddsi_tran_factory_t factory)
{
- loc->kind = gv.m_factory->m_connless ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_TCPv4;
+ loc->kind = factory->m_connless ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_TCPv4;
loc->port = *p;
memset (loc->address, 0, 12);
memcpy (loc->address + 12, a, 4);
}
-static int do_ipv4address (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t wanted, unsigned fl_tmp, const struct dd *dd)
+static dds_return_t do_ipv4address (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t wanted, uint32_t fl_tmp, const struct dd *dd, ddsi_tran_factory_t factory)
{
nn_ipv4address_t *a;
nn_port_t *p;
nn_locators_t *ls;
- unsigned fl1_tmp;
+ uint32_t fl1_tmp;
uint64_t fldest;
if (dd->bufsz < sizeof (*a))
- {
- DDS_TRACE("plist/do_ipv4address: buffer too small\n");
- return Q_ERR_INVALID;
- }
+ return DDS_RETCODE_BAD_PARAMETER;
switch (fl_tmp)
{
case PPTMP_MULTICAST_IPADDRESS:
@@ -1103,7 +1807,7 @@ static int do_ipv4address (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp
allows adding another pair. */
nn_locator_t loc;
- locator_from_ipv4address_port (&loc, a, p);
+ locator_from_ipv4address_port (&loc, a, p, factory);
dest_tmp->present &= ~(fl_tmp | fl1_tmp);
return add_locator (ls, &dest->present, wanted, fldest, &loc);
}
@@ -1113,18 +1817,15 @@ static int do_ipv4address (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp
}
}
-static int do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t wanted, unsigned fl_tmp, const struct dd *dd)
+static dds_return_t do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t wanted, uint32_t fl_tmp, const struct dd *dd, ddsi_tran_factory_t factory)
{
nn_ipv4address_t *a;
nn_port_t *p;
nn_locators_t *ls;
uint64_t fldest;
- unsigned fl1_tmp;
+ uint32_t fl1_tmp;
if (dd->bufsz < sizeof (*p))
- {
- DDS_TRACE("plist/do_port: buffer too small\n");
- return Q_ERR_INVALID;
- }
+ return DDS_RETCODE_BAD_PARAMETER;
switch (fl_tmp)
{
case PPTMP_DEFAULT_UNICAST_PORT:
@@ -1155,10 +1856,7 @@ static int do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint6
if (dd->bswap)
*p = bswap4u (*p);
if (*p <= 0 || *p > 65535)
- {
- DDS_TRACE("plist/do_port: invalid port (%d)\n", (int) *p);
- return Q_ERR_INVALID;
- }
+ return DDS_RETCODE_BAD_PARAMETER;
dest_tmp->present |= fl_tmp;
if ((dest_tmp->present & (fl_tmp | fl1_tmp)) == (fl_tmp | fl1_tmp))
{
@@ -1166,7 +1864,7 @@ static int do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint6
both address & port from the set of present plist: this
allows adding another pair. */
nn_locator_t loc;
- locator_from_ipv4address_port (&loc, a, p);
+ locator_from_ipv4address_port (&loc, a, p, factory);
dest_tmp->present &= ~(fl_tmp | fl1_tmp);
return add_locator (ls, &dest->present, wanted, fldest, &loc);
}
@@ -1176,1118 +1874,133 @@ static int do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint6
}
}
-static int valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd))
+static dds_return_t return_unrecognized_pid (nn_plist_t *plist, nn_parameterid_t pid)
{
- /* All 0 is GUID_UNKNOWN, which is a defined GUID */
- if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0)
- {
- if (g->entityid.u == 0)
- return 0;
- else
- {
- DDS_TRACE("plist/valid_participant_guid: prefix is 0 but entityid is not (%"PRIu32")\n", g->entityid.u);
- return Q_ERR_INVALID;
- }
- }
- else if (g->entityid.u == NN_ENTITYID_PARTICIPANT)
- {
+ if (!(pid & PID_UNRECOGNIZED_INCOMPATIBLE_FLAG))
return 0;
- }
else
{
- DDS_TRACE("plist/valid_participant_guid: entityid not a participant entityid (%"PRIu32")\n", g->entityid.u);
- return Q_ERR_INVALID;
+ plist->present |= PP_INCOMPATIBLE;
+ return DDS_RETCODE_UNSUPPORTED;
}
}
-static int valid_group_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd))
+static dds_return_t init_one_parameter (nn_plist_t *plist, nn_ipaddress_params_tmp_t *dest_tmp, uint64_t pwanted, uint64_t qwanted, uint16_t pid, const struct dd *dd, ddsi_tran_factory_t factory, const ddsrt_log_cfg_t *logcfg)
{
- /* All 0 is GUID_UNKNOWN, which is a defined GUID */
- if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0)
- {
- if (g->entityid.u == 0)
- return 0;
- else
- {
- DDS_TRACE("plist/valid_group_guid: prefix is 0 but entityid is not (%"PRIu32")\n", g->entityid.u);
- return Q_ERR_INVALID;
- }
- }
- else if (g->entityid.u != 0)
- {
- /* accept any entity id */
- return 0;
- }
- else
- {
- DDS_TRACE("plist/valid_group_guid: entityid is 0\n");
- return Q_ERR_INVALID;
- }
-}
-
-static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd)
-{
- /* All 0 is GUID_UNKNOWN, which is a defined GUID */
- if (g->prefix.u[0] == 0 && g->prefix.u[1] == 0 && g->prefix.u[2] == 0)
- {
- if (g->entityid.u == 0)
- return 0;
- else
- {
- DDS_TRACE("plist/valid_endpoint_guid: prefix is 0 but entityid is not (%"PRIx32")\n", g->entityid.u);
- return Q_ERR_INVALID;
- }
- }
- switch (g->entityid.u & NN_ENTITYID_SOURCE_MASK)
- {
- case NN_ENTITYID_SOURCE_USER:
- switch (g->entityid.u & NN_ENTITYID_KIND_MASK)
- {
- case NN_ENTITYID_KIND_WRITER_WITH_KEY:
- case NN_ENTITYID_KIND_WRITER_NO_KEY:
- case NN_ENTITYID_KIND_READER_NO_KEY:
- case NN_ENTITYID_KIND_READER_WITH_KEY:
- return 0;
- default:
- if (protocol_version_is_newer (dd->protocol_version))
- return 0;
- else
- {
- DDS_TRACE("plist/valid_endpoint_guid[src=USER,proto=%u.%u]: invalid kind (%"PRIx32")\n",
- dd->protocol_version.major, dd->protocol_version.minor,
- g->entityid.u & NN_ENTITYID_KIND_MASK);
- return Q_ERR_INVALID;
- }
- }
- case NN_ENTITYID_SOURCE_BUILTIN:
- switch (g->entityid.u)
- {
- case NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER:
- case NN_ENTITYID_SEDP_BUILTIN_TOPIC_READER:
- case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER:
- case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER:
- case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER:
- case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER:
- case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER:
- case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER:
- case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER:
- case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER:
- return 0;
- default:
- if (protocol_version_is_newer (dd->protocol_version))
- return 0;
- else
- {
- DDS_TRACE("plist/valid_endpoint_guid[src=BUILTIN,proto=%u.%u]: invalid entityid (%"PRIx32")\n",
- dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u);
- return Q_ERR_INVALID;
- }
- }
- case NN_ENTITYID_SOURCE_VENDOR:
- if (!vendor_is_eclipse (dd->vendorid))
- return 0;
- else
- {
- switch (g->entityid.u)
- {
- case NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER:
- case NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_READER:
- case NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER:
- case NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_READER:
- case NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER:
- case NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_READER:
- return 0;
- default:
- if (protocol_version_is_newer (dd->protocol_version))
- return 0;
- else
- {
- DDS_TRACE("plist/valid_endpoint_guid[src=VENDOR,proto=%u.%u]: unexpected entityid (%"PRIx32")\n",
- dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u);
- return 0;
- }
- }
- }
- default:
- DDS_TRACE("plist/valid_endpoint_guid: invalid source (%"PRIx32")\n", g->entityid.u);
- return Q_ERR_INVALID;
- }
-}
-
-static int do_guid (nn_guid_t *dst, uint64_t *present, uint64_t fl, int (*valid) (const nn_guid_t *g, const struct dd *dd), const struct dd *dd)
-{
- if (dd->bufsz < sizeof (*dst))
- {
- DDS_TRACE("plist/do_guid: buffer too small\n");
- return Q_ERR_INVALID;
- }
- memcpy (dst, dd->buf, sizeof (*dst));
- *dst = nn_ntoh_guid (*dst);
- if (valid (dst, dd) < 0)
- {
- /* CoreDX once upon a time used to send out PARTICIPANT_GUID parameters with a 0 entity id, but it
- that has long since changed (even if I don't know exactly when) */
- if (fl == PP_PARTICIPANT_GUID && vendor_is_twinoaks (dd->vendorid) && dst->entityid.u == 0 && ! NN_STRICT_P)
- {
- DDS_LOG(DDS_LC_DISCOVERY, "plist(vendor %u.%u): rewriting invalid participant guid "PGUIDFMT,
- dd->vendorid.id[0], dd->vendorid.id[1], PGUID (*dst));
- dst->entityid.u = NN_ENTITYID_PARTICIPANT;
- }
- else
- {
- return Q_ERR_INVALID;
- }
- }
- *present |= fl;
- return 0;
-}
-
-
-static void bswap_prismtech_participant_version_info (nn_prismtech_participant_version_info_t *pvi)
-{
- int i;
- pvi->version = bswap4u (pvi->version);
- pvi->flags = bswap4u (pvi->flags);
- for (i = 0; i < 3; i++)
- pvi->unused[i] = bswap4u (pvi->unused[i]);
-}
-
-static int do_prismtech_participant_version_info (nn_prismtech_participant_version_info_t *pvi, uint64_t *present, uint64_t *aliased, const struct dd *dd)
-{
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- else if (dd->bufsz < NN_PRISMTECH_PARTICIPANT_VERSION_INFO_FIXED_CDRSIZE)
- {
- DDS_TRACE("plist/do_prismtech_participant_version_info[pid=PRISMTECH_PARTICIPANT_VERSION_INFO]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- else
- {
- int res;
- unsigned sz = NN_PRISMTECH_PARTICIPANT_VERSION_INFO_FIXED_CDRSIZE - sizeof(uint32_t);
- uint32_t *pu = (uint32_t *)dd->buf;
- size_t len;
- struct dd dd1 = *dd;
-
- memcpy (pvi, dd->buf, sz);
- if (dd->bswap)
- bswap_prismtech_participant_version_info(pvi);
-
- dd1.buf = (unsigned char *) &pu[5];
- dd1.bufsz = dd->bufsz - sz;
- if ((res = alias_string ((const unsigned char **) &pvi->internals, &dd1, &len)) >= 0) {
- *present |= PP_PRISMTECH_PARTICIPANT_VERSION_INFO;
- *aliased |= PP_PRISMTECH_PARTICIPANT_VERSION_INFO;
- res = 0;
- }
-
- return res;
- }
-}
-
-
-
-static int do_subscription_keys_qospolicy (nn_subscription_keys_qospolicy_t *q, uint64_t *present, uint64_t *aliased, uint64_t fl, const struct dd *dd)
-{
- struct dd dd1;
- int res;
- if (dd->bufsz < 4)
- {
- DDS_TRACE("plist/do_subscription_keys: buffer too small\n");
- return Q_ERR_INVALID;
- }
- q->use_key_list = (unsigned char) dd->buf[0];
- if (q->use_key_list != 0 && q->use_key_list != 1)
- {
- DDS_TRACE("plist/do_subscription_keys: invalid use_key_list (%d)\n", (int) q->use_key_list);
- return Q_ERR_INVALID;
- }
- dd1 = *dd;
- dd1.buf += 4;
- dd1.bufsz -= 4;
- if ((res = alias_stringseq (&q->key_list, &dd1)) >= 0)
- {
- *present |= fl;
- *aliased |= fl;
- }
- return res;
-}
-
-static int unalias_subscription_keys_qospolicy (nn_subscription_keys_qospolicy_t *q, int bswap)
-{
- return unalias_stringseq (&q->key_list, bswap);
-}
-
-static int do_reader_lifespan_qospolicy (nn_reader_lifespan_qospolicy_t *q, uint64_t *present, uint64_t fl, const struct dd *dd)
-{
- int res;
- if (dd->bufsz < sizeof (*q))
- {
- DDS_TRACE("plist/do_reader_lifespan: buffer too small\n");
- return Q_ERR_INVALID;
- }
- *q = *((nn_reader_lifespan_qospolicy_t *) dd->buf);
- if (dd->bswap)
- bswap_duration (&q->duration);
- if (q->use_lifespan != 0 && q->use_lifespan != 1)
- {
- DDS_TRACE("plist/do_reader_lifespan: invalid use_lifespan (%d)\n", (int) q->use_lifespan);
- return Q_ERR_INVALID;
- }
- if ((res = validate_duration (&q->duration)) >= 0)
- *present |= fl;
- return res;
-}
-
-static int do_entity_factory_qospolicy (nn_entity_factory_qospolicy_t *q, uint64_t *present, uint64_t fl, const struct dd *dd)
-{
- if (dd->bufsz < sizeof (*q))
- {
- DDS_TRACE("plist/do_entity_factory: buffer too small\n");
- return Q_ERR_INVALID;
- }
- q->autoenable_created_entities = dd->buf[0];
- if (q->autoenable_created_entities != 0 && q->autoenable_created_entities != 1)
- {
- DDS_TRACE("plist/do_entity_factory: invalid autoenable_created_entities (%d)\n", (int) q->autoenable_created_entities);
- return Q_ERR_INVALID;
- }
- *present |= fl;
- return 0;
-}
-
-int validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t *q)
-{
- if (validate_duration (&q->autopurge_nowriter_samples_delay) < 0 ||
- validate_duration (&q->autopurge_disposed_samples_delay) < 0)
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid autopurge_nowriter_sample_delay or autopurge_disposed_samples_delay\n");
- return Q_ERR_INVALID;
- }
- if (q->autopurge_dispose_all != 0 && q->autopurge_dispose_all != 1)
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid autopurge_dispose_all\n");
- return Q_ERR_INVALID;
- }
- if (q->enable_invalid_samples != 0 && q->enable_invalid_samples != 1)
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid enable_invalid_samples\n");
- return Q_ERR_INVALID;
- }
- /* Don't check consistency between enable_invalid_samples and invalid_samples_mode (yet) */
- switch (q->invalid_sample_visibility)
- {
- case NN_NO_INVALID_SAMPLE_VISIBILITY_QOS:
- case NN_MINIMUM_INVALID_SAMPLE_VISIBILITY_QOS:
- case NN_ALL_INVALID_SAMPLE_VISIBILITY_QOS:
- break;
- default:
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid invalid_sample_visibility\n");
- return Q_ERR_INVALID;
- }
- return 0;
-}
-
-static int do_reader_data_lifecycle_v0 (nn_reader_data_lifecycle_qospolicy_t *q, const struct dd *dd)
-{
- memcpy (q, dd->buf, 2 * sizeof (nn_duration_t));
- q->autopurge_dispose_all = 0;
- q->enable_invalid_samples = 1;
- q->invalid_sample_visibility = NN_MINIMUM_INVALID_SAMPLE_VISIBILITY_QOS;
- if (dd->bswap)
- {
- bswap_duration (&q->autopurge_nowriter_samples_delay);
- bswap_duration (&q->autopurge_disposed_samples_delay);
- }
- return validate_reader_data_lifecycle (q);
-}
-
-static int do_reader_data_lifecycle_v1 (nn_reader_data_lifecycle_qospolicy_t *q, const struct dd *dd)
-{
- memcpy (q, dd->buf, sizeof (*q));
- if (dd->bswap)
- {
- bswap_duration (&q->autopurge_nowriter_samples_delay);
- bswap_duration (&q->autopurge_disposed_samples_delay);
- q->invalid_sample_visibility = (nn_invalid_sample_visibility_kind_t) bswap4u ((unsigned) q->invalid_sample_visibility);
- }
- return validate_reader_data_lifecycle (q);
-}
-
-static int init_one_parameter
-(
- nn_plist_t *dest,
- nn_ipaddress_params_tmp_t *dest_tmp,
- uint64_t pwanted,
- uint64_t qwanted,
- unsigned short pid,
- const struct dd *dd
-)
-{
- int res;
+ /* special-cased ipv4address and port, because they have state beyond that what gets
+ passed into the generic code */
switch (pid)
{
- case PID_PAD:
- case PID_SENTINEL:
- return 0;
-
- /* Extended QoS data: */
-#define Q(NAME_, name_) case PID_##NAME_: \
- if (dd->bufsz < sizeof (nn_##name_##_qospolicy_t)) \
- { \
- DDS_TRACE("plist/init_one_parameter[pid=%s]: buffer too small\n", #NAME_); \
- return Q_ERR_INVALID; \
- } \
- else \
- { \
- nn_##name_##_qospolicy_t *q = &dest->qos.name_; \
- memcpy (q, dd->buf, sizeof (*q)); \
- if (dd->bswap) bswap_##name_##_qospolicy (q); \
- if ((res = validate_##name_##_qospolicy (q)) < 0) \
- return res; \
- dest->qos.present |= QP_##NAME_; \
- } \
- return 0
- Q (DURABILITY, durability);
- Q (LIVELINESS, liveliness);
- Q (DESTINATION_ORDER, destination_order);
- Q (HISTORY, history);
- Q (RESOURCE_LIMITS, resource_limits);
- Q (OWNERSHIP, ownership);
- Q (OWNERSHIP_STRENGTH, ownership_strength);
- Q (PRESENTATION, presentation);
- Q (TRANSPORT_PRIORITY, transport_priority);
-#undef Q
-
- case PID_DURABILITY_SERVICE:
- if (dd->bufsz < sizeof (nn_durability_service_qospolicy_t))
- {
- DDS_TRACE("plist/init_one_parameter[pid=DURABILITY_SERVICE]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- else
- {
- nn_durability_service_qospolicy_t *q = &dest->qos.durability_service;
- /* All-zero durability service is illegal, but at least CoreDX sometimes advertises
- it in some harmless cases. So accept all-zero durability service, then handle it
- in final_validation, where we can determine whether it really is harmless or not */
- memcpy (q, dd->buf, sizeof (*q));
- if (dd->bswap)
- bswap_durability_service_qospolicy (q);
- if ((res = validate_durability_service_qospolicy_acceptzero (q, true)) < 0)
- return res;
- dest->qos.present |= QP_DURABILITY_SERVICE;
- }
- return 0;
-
- /* PID_RELIABILITY handled differently because it (formally, for
- static typing reasons) has a different type on the network
- than internally, with the transformation between the two
- dependent on wheter we are being pedantic. If that weren't
- the case, it would've been an ordinary Q (RELIABILITY,
- reliability). */
- case PID_RELIABILITY:
- if (dd->bufsz < sizeof (nn_external_reliability_qospolicy_t))
- {
- DDS_TRACE("plist/init_one_parameter[pid=RELIABILITY]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- else
- {
- nn_reliability_qospolicy_t *q = &dest->qos.reliability;
- nn_external_reliability_qospolicy_t qext;
- memcpy (&qext, dd->buf, sizeof (qext));
- if (dd->bswap)
- bswap_external_reliability_qospolicy (&qext);
- if ((res = validate_xform_reliability_qospolicy (q, &qext)) < 0)
- return res;
- dest->qos.present |= QP_RELIABILITY;
- }
- return 0;
-
- case PID_TOPIC_NAME:
- return do_string (&dest->qos.topic_name, &dest->qos.present, &dest->qos.aliased, qwanted, QP_TOPIC_NAME, dd);
- case PID_TYPE_NAME:
- return do_string (&dest->qos.type_name, &dest->qos.present, &dest->qos.aliased, qwanted, QP_TYPE_NAME, dd);
-
- case PID_USER_DATA:
- return do_octetseq (&dest->qos.user_data, &dest->qos.present, &dest->qos.aliased, qwanted, QP_USER_DATA, dd);
- case PID_GROUP_DATA:
- return do_octetseq (&dest->qos.group_data, &dest->qos.present, &dest->qos.aliased, qwanted, QP_GROUP_DATA, dd);
- case PID_TOPIC_DATA:
- return do_octetseq (&dest->qos.topic_data, &dest->qos.present, &dest->qos.aliased, qwanted, QP_TOPIC_DATA, dd);
-
- case PID_DEADLINE:
- return do_duration (&dest->qos.deadline.deadline, &dest->qos.present, QP_DEADLINE, dd);
- case PID_LATENCY_BUDGET:
- return do_duration (&dest->qos.latency_budget.duration, &dest->qos.present, QP_LATENCY_BUDGET, dd);
- case PID_LIFESPAN:
- return do_duration (&dest->qos.lifespan.duration, &dest->qos.present, QP_LIFESPAN, dd);
- case PID_TIME_BASED_FILTER:
- return do_duration (&dest->qos.time_based_filter.minimum_separation, &dest->qos.present, QP_TIME_BASED_FILTER, dd);
-
- case PID_PARTITION:
- return do_stringseq (&dest->qos.partition, &dest->qos.present, &dest->qos.aliased, qwanted, QP_PARTITION, dd);
-
- case PID_PRISMTECH_READER_DATA_LIFECYCLE: /* PrismTech specific */
- {
- int ret;
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- if (dd->bufsz >= sizeof (nn_reader_data_lifecycle_qospolicy_t))
- ret = do_reader_data_lifecycle_v1 (&dest->qos.reader_data_lifecycle, dd);
- else if (dd->bufsz >= 2 * sizeof (nn_duration_t))
- ret = do_reader_data_lifecycle_v0 (&dest->qos.reader_data_lifecycle, dd);
- else
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: buffer too small\n");
- ret = Q_ERR_INVALID;
- }
- if (ret >= 0)
- dest->qos.present |= QP_PRISMTECH_READER_DATA_LIFECYCLE;
- return ret;
- }
- case PID_PRISMTECH_WRITER_DATA_LIFECYCLE: /* PrismTech specific */
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- else
- {
- nn_writer_data_lifecycle_qospolicy_t *q = &dest->qos.writer_data_lifecycle;
- if (dd->bufsz < 1)
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- else if (dd->bufsz < sizeof (*q))
- {
- /* Spec form, with just autodispose_unregistered_instances */
- q->autodispose_unregistered_instances = dd->buf[0];
- q->autounregister_instance_delay = nn_to_ddsi_duration (T_NEVER);
- q->autopurge_suspended_samples_delay = nn_to_ddsi_duration (T_NEVER);
- }
- else
- {
- memcpy (q, dd->buf, sizeof (*q));
- if (dd->bswap)
- {
- bswap_duration (&q->autounregister_instance_delay);
- bswap_duration (&q->autopurge_suspended_samples_delay);
- }
- }
- if (q->autodispose_unregistered_instances & ~1)
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: invalid autodispose_unregistered_instances (%d)\n", (int) q->autodispose_unregistered_instances);
- return Q_ERR_INVALID;
- }
- if (validate_duration (&q->autounregister_instance_delay) < 0 ||
- validate_duration (&q->autopurge_suspended_samples_delay) < 0)
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: invalid autounregister_instance_delay or autopurge_suspended_samples_delay\n");
- return Q_ERR_INVALID;
- }
- dest->qos.present |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE;
- return 0;
- }
-
- case PID_PRISMTECH_RELAXED_QOS_MATCHING:
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- else if (dd->bufsz < sizeof (dest->qos.relaxed_qos_matching))
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_RELAXED_QOS_MATCHING]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- else
- {
- nn_relaxed_qos_matching_qospolicy_t *rqm = &dest->qos.relaxed_qos_matching;
- memcpy (rqm, dd->buf, sizeof (*rqm));
- if (rqm->value != 0 && rqm->value != 1)
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_RELAXED_QOS_MATCHING]: invalid\n");
- return Q_ERR_INVALID;
- }
- dest->qos.present |= QP_PRISMTECH_RELAXED_QOS_MATCHING;
- return 0;
- }
-
- case PID_PRISMTECH_SYNCHRONOUS_ENDPOINT: /* PrismTech specific */
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- else if (dd->bufsz < sizeof (dest->qos.synchronous_endpoint))
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SYNCHRONOUS_ENDPOINT]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- else
- {
- nn_synchronous_endpoint_qospolicy_t *q = &dest->qos.synchronous_endpoint;
- memcpy (q, dd->buf, sizeof (*q));
- if (q->value != 0 && q->value != 1)
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SYNCHRONOUS_ENDPOINT]: invalid value for synchronous flag\n");
- return Q_ERR_INVALID;
- }
- dest->qos.present |= QP_PRISMTECH_SYNCHRONOUS_ENDPOINT;
- return 0;
- }
-
- /* Other plist */
- case PID_PROTOCOL_VERSION:
- if (dd->bufsz < sizeof (nn_protocol_version_t))
- {
- DDS_TRACE("plist/init_one_parameter[pid=PROTOCOL_VERSION]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- memcpy (&dest->protocol_version, dd->buf, sizeof (dest->protocol_version));
- if (NN_STRICT_P &&
- (dest->protocol_version.major != dd->protocol_version.major ||
- dest->protocol_version.minor != dd->protocol_version.minor))
- {
- /* Not accepting a submessage advertising a protocol version
- other than that advertised by the message header, unless I
- have good reason to, at least not when being strict. */
- DDS_TRACE("plist/init_one_parameter[pid=PROTOCOL_VERSION,mode=STRICT]: version (%u.%u) mismatch with message (%u.%u)\n",
- dest->protocol_version.major, dest->protocol_version.minor,
- dd->protocol_version.major, dd->protocol_version.minor);
- return Q_ERR_INVALID;
- }
- dest->present |= PP_PROTOCOL_VERSION;
- return 0;
-
- case PID_VENDORID:
- if (dd->bufsz < sizeof (nn_vendorid_t))
- return Q_ERR_INVALID;
- memcpy (&dest->vendorid, dd->buf, sizeof (dest->vendorid));
- if (NN_STRICT_P &&
- (dest->vendorid.id[0] != dd->vendorid.id[0] ||
- dest->vendorid.id[1] != dd->vendorid.id[1]))
- {
- /* see PROTOCOL_VERSION */
- DDS_TRACE("plist/init_one_parameter[pid=VENDORID,mode=STRICT]: vendor (%u.%u) mismatch with message (%u.%u)\n",
- dest->vendorid.id[0], dest->vendorid.id[1], dd->vendorid.id[0], dd->vendorid.id[1]);
- return Q_ERR_INVALID;
- }
- dest->present |= PP_VENDORID;
- return 0;
-
- /* Locators: there may be lists, so we have to allocate memory for them */
-#define XL(NAME_, name_) case PID_##NAME_##_LOCATOR: return do_locator (&dest->name_##_locators, &dest->present, pwanted, PP_##NAME_##_LOCATOR, dd)
- XL (UNICAST, unicast);
- XL (MULTICAST, multicast);
- XL (DEFAULT_UNICAST, default_unicast);
- XL (DEFAULT_MULTICAST, default_multicast);
- XL (METATRAFFIC_UNICAST, metatraffic_unicast);
- XL (METATRAFFIC_MULTICAST, metatraffic_multicast);
-#undef XL
-
- /* IPADDRESS + PORT entries are a nuisance ... I'd prefer
- converting them to locators right away, so that the rest of
- the code only has to deal with locators, but that is
- impossible because the locators require both the address &
- the port to be known.
-
- The wireshark dissector suggests IPvAdress_t is just the 32
- bits of the IP address but it doesn't say so anywhere
- ... Similarly for ports, but contrary to the expections they
- seem to be 32-bits, too. Apparently in host-endianness.
-
- And, to be honest, I have no idea what port to use for
- MULTICAST_IPADDRESS ... */
-#define XA(NAME_) case PID_##NAME_##_IPADDRESS: return do_ipv4address (dest, dest_tmp, pwanted, PPTMP_##NAME_##_IPADDRESS, dd)
-#define XP(NAME_) case PID_##NAME_##_PORT: return do_port (dest, dest_tmp, pwanted, PPTMP_##NAME_##_PORT, dd)
- XA (MULTICAST);
- XA (DEFAULT_UNICAST);
- XP (DEFAULT_UNICAST);
- XA (METATRAFFIC_UNICAST);
- XP (METATRAFFIC_UNICAST);
- XA (METATRAFFIC_MULTICAST);
- XP (METATRAFFIC_MULTICAST);
+#define XA(NAME_) case PID_##NAME_##_IPADDRESS: return do_ipv4address (plist, dest_tmp, pwanted, PPTMP_##NAME_##_IPADDRESS, dd, factory)
+#define XP(NAME_) case PID_##NAME_##_PORT: return do_port (plist, dest_tmp, pwanted, PPTMP_##NAME_##_PORT, dd, factory)
+ XA (MULTICAST);
+ XA (DEFAULT_UNICAST);
+ XP (DEFAULT_UNICAST);
+ XA (METATRAFFIC_UNICAST);
+ XP (METATRAFFIC_UNICAST);
+ XA (METATRAFFIC_MULTICAST);
+ XP (METATRAFFIC_MULTICAST);
#undef XP
#undef XA
-
- case PID_EXPECTS_INLINE_QOS:
- if (dd->bufsz < sizeof (dest->expects_inline_qos))
- {
- DDS_TRACE("plist/init_one_parameter[pid=EXPECTS_INLINE_QOS]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- dest->expects_inline_qos = dd->buf[0];
- /* boolean: only lsb may be set */
- if (dest->expects_inline_qos & ~1)
- {
- DDS_TRACE("plist/init_one_parameter[pid=EXPECTS_INLINE_QOS]: invalid expects_inline_qos (%d)\n",
- (int) dest->expects_inline_qos);
- return Q_ERR_INVALID;
- }
- dest->present |= PP_EXPECTS_INLINE_QOS;
- return 0;
-
- case PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT:
- /* Spec'd as "incremented monotonically" (DDSI 2.1, table 8.13),
- but 32 bits signed is not such a smart choice for that. We'll
- simply accept any value. */
- if (dd->bufsz < sizeof (dest->participant_manual_liveliness_count))
- {
- DDS_TRACE("plist/init_one_parameter[pid=PARTICIPANT_MANUAL_LIVELINESS_COUNT]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- memcpy (&dest->participant_manual_liveliness_count, dd->buf, sizeof (dest->participant_manual_liveliness_count));
- if (dd->bswap)
- dest->participant_manual_liveliness_count = bswap4 (dest->participant_manual_liveliness_count);
- dest->present |= PP_PARTICIPANT_MANUAL_LIVELINESS_COUNT;
- return 0;
-
- case PID_PARTICIPANT_LEASE_DURATION:
- return do_duration (&dest->participant_lease_duration, &dest->present, PP_PARTICIPANT_LEASE_DURATION, dd);
-
- case PID_CONTENT_FILTER_PROPERTY:
- /* FIXME */
- return 0;
-
- case PID_PARTICIPANT_GUID:
- return do_guid (&dest->participant_guid, &dest->present, PP_PARTICIPANT_GUID, valid_participant_guid, dd);
-
- case PID_GROUP_GUID:
- return do_guid (&dest->group_guid, &dest->present, PP_GROUP_GUID, valid_group_guid, dd);
-
- case PID_PARTICIPANT_ENTITYID:
- case PID_GROUP_ENTITYID:
- /* DDSI 2.1 table 9.13: reserved for future use */
- return 0;
-
- case PID_PARTICIPANT_BUILTIN_ENDPOINTS:
- /* FIXME: I assume it is the same as the BUILTIN_ENDPOINT_SET,
- which is the set that DDSI2 has been using so far. */
- /* FALLS THROUGH */
- case PID_BUILTIN_ENDPOINT_SET:
- if (dd->bufsz < sizeof (dest->builtin_endpoint_set))
- {
- DDS_TRACE("plist/init_one_parameter[pid=BUILTIN_ENDPOINT_SET(%u)]: buffer too small\n", pid);
- return Q_ERR_INVALID;
- }
- memcpy (&dest->builtin_endpoint_set, dd->buf, sizeof (dest->builtin_endpoint_set));
- if (dd->bswap)
- dest->builtin_endpoint_set = bswap4u (dest->builtin_endpoint_set);
- if (NN_STRICT_P && !protocol_version_is_newer (dd->protocol_version) &&
- (dest->builtin_endpoint_set & ~(NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER |
- NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR |
- NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER |
- NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_DETECTOR |
- NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER |
- NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_DETECTOR |
- NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER |
- NN_DISC_BUILTIN_ENDPOINT_TOPIC_DETECTOR |
- /* undefined ones: */
- NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_PROXY_ANNOUNCER |
- NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_PROXY_DETECTOR |
- NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_STATE_ANNOUNCER |
- NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_STATE_DETECTOR |
- /* defined ones again: */
- NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER |
- NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER)) != 0)
- {
- DDS_TRACE("plist/init_one_parameter[pid=BUILTIN_ENDPOINT_SET(%u),mode=STRICT,proto=%u.%u]: invalid set (0x%x)\n",
- pid, dd->protocol_version.major, dd->protocol_version.minor, dest->builtin_endpoint_set);
- return Q_ERR_INVALID;
- }
- dest->present |= PP_BUILTIN_ENDPOINT_SET;
- return 0;
-
- case PID_PRISMTECH_BUILTIN_ENDPOINT_SET:
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- else if (dd->bufsz < sizeof (dest->prismtech_builtin_endpoint_set))
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_BUILTIN_ENDPOINT_SET(%u)]: buffer too small\n", pid);
- return Q_ERR_INVALID;
- }
- else
- {
- memcpy (&dest->prismtech_builtin_endpoint_set, dd->buf, sizeof (dest->prismtech_builtin_endpoint_set));
- if (dd->bswap)
- dest->prismtech_builtin_endpoint_set = bswap4u (dest->prismtech_builtin_endpoint_set);
- dest->present |= PP_PRISMTECH_BUILTIN_ENDPOINT_SET;
- }
- return 0;
-
- case PID_PROPERTY_LIST:
- case PID_TYPE_MAX_SIZE_SERIALIZED:
- /* FIXME */
- return 0;
-
- case PID_ENTITY_NAME:
- return do_string (&dest->entity_name, &dest->present, &dest->aliased, pwanted, PP_ENTITY_NAME, dd);
-
- case PID_KEYHASH:
- if (dd->bufsz < sizeof (dest->keyhash))
- {
- DDS_TRACE("plist/init_one_parameter[pid=KEYHASH]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- memcpy (&dest->keyhash, dd->buf, sizeof (dest->keyhash));
- dest->present |= PP_KEYHASH;
- return 0;
-
- case PID_STATUSINFO:
- if (dd->bufsz < sizeof (dest->statusinfo))
- {
- DDS_TRACE("plist/init_one_parameter[pid=STATUSINFO]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- memcpy (&dest->statusinfo, dd->buf, sizeof (dest->statusinfo));
- dest->statusinfo = fromBE4u (dest->statusinfo);
- if (NN_STRICT_P && !protocol_version_is_newer (dd->protocol_version) &&
- (dest->statusinfo & ~NN_STATUSINFO_STANDARDIZED))
- {
- /* Spec says I may not interpret the reserved bits. But no-one
- may use them in this version of the specification */
- DDS_TRACE("plist/init_one_parameter[pid=STATUSINFO,mode=STRICT,proto=%u.%u]: invalid statusinfo (0x%x)\n",
- dd->protocol_version.major, dd->protocol_version.minor, dest->statusinfo);
- return Q_ERR_INVALID;
- }
- /* Clear all bits we don't understand, then add the extended bits if present */
- dest->statusinfo &= NN_STATUSINFO_STANDARDIZED;
- if (dd->bufsz >= 2 * sizeof (dest->statusinfo) && vendor_is_eclipse_or_opensplice(dd->vendorid))
- {
- uint32_t statusinfox;
- Q_STATIC_ASSERT_CODE (sizeof(statusinfox) == sizeof(dest->statusinfo));
- memcpy (&statusinfox, dd->buf + sizeof (dest->statusinfo), sizeof (statusinfox));
- statusinfox = fromBE4u (statusinfox);
- if (statusinfox & NN_STATUSINFOX_OSPL_AUTO)
- dest->statusinfo |= NN_STATUSINFO_OSPL_AUTO;
- }
- dest->present |= PP_STATUSINFO;
- return 0;
-
- case PID_COHERENT_SET:
- if (dd->bufsz < sizeof (dest->coherent_set_seqno))
- {
- DDS_TRACE("plist/init_one_parameter[pid=COHERENT_SET]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- else
- {
- nn_sequence_number_t *q = &dest->coherent_set_seqno;
- seqno_t seqno;
- memcpy (q, dd->buf, sizeof (*q));
- if (dd->bswap)
- {
- q->high = bswap4 (q->high);
- q->low = bswap4u (q->low);
- }
- seqno = fromSN(dest->coherent_set_seqno);
- if (seqno <= 0 && seqno != NN_SEQUENCE_NUMBER_UNKNOWN)
- {
- DDS_TRACE("plist/init_one_parameter[pid=COHERENT_SET]: invalid sequence number (%" PRId64 ")\n", seqno);
- return Q_ERR_INVALID;
- }
- dest->present |= PP_COHERENT_SET;
- return 0;
- }
-
- case PID_CONTENT_FILTER_INFO:
- case PID_DIRECTED_WRITE:
- case PID_ORIGINAL_WRITER_INFO:
- /* FIXME */
- return 0;
-
- case PID_ENDPOINT_GUID:
- if (NN_PEDANTIC_P && !protocol_version_is_newer (dd->protocol_version))
- {
- /* ENDPOINT_GUID is not specified in the 2.1 standard, so
- reject it: in (really) strict mode we do not accept
- undefined things, even though we are -arguably- supposed to
- ignore it. */
- DDS_TRACE("plist/init_one_parameter[pid=ENDPOINT_GUID,mode=PEDANTIC,proto=%u.%u]: undefined pid\n",
- dd->protocol_version.major, dd->protocol_version.minor);
- return Q_ERR_INVALID;
- }
- return do_guid (&dest->endpoint_guid, &dest->present, PP_ENDPOINT_GUID, valid_endpoint_guid, dd);
-
- case PID_PRISMTECH_ENDPOINT_GUID: /* case PID_RTI_TYPECODE: */
- if (vendor_is_eclipse_or_prismtech (dd->vendorid))
- {
- /* PrismTech specific variant of ENDPOINT_GUID, for strict compliancy */
- return do_guid (&dest->endpoint_guid, &dest->present, PP_ENDPOINT_GUID, valid_endpoint_guid, dd);
- }
- else if (vendor_is_rti (dd->vendorid))
- {
- /* For RTI it is a typecode */
- return do_blob (&dest->qos.rti_typecode, &dest->qos.present, &dest->qos.aliased, qwanted, QP_RTI_TYPECODE, dd);
-
- }
- else
- {
- return 0;
- }
-
-
- case PID_PRISMTECH_PARTICIPANT_VERSION_INFO:
- return do_prismtech_participant_version_info(&dest->prismtech_participant_version_info, &dest->present, &dest->aliased, dd);
-
- case PID_PRISMTECH_SUBSCRIPTION_KEYS:
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- return do_subscription_keys_qospolicy (&dest->qos.subscription_keys, &dest->qos.present, &dest->qos.aliased, QP_PRISMTECH_SUBSCRIPTION_KEYS, dd);
-
- case PID_PRISMTECH_READER_LIFESPAN:
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- return do_reader_lifespan_qospolicy (&dest->qos.reader_lifespan, &dest->qos.present, QP_PRISMTECH_READER_LIFESPAN, dd);
-
-
- case PID_PRISMTECH_ENTITY_FACTORY:
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- return do_entity_factory_qospolicy (&dest->qos.entity_factory, &dest->qos.present, QP_PRISMTECH_ENTITY_FACTORY, dd);
-
- case PID_PRISMTECH_NODE_NAME:
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- return do_string (&dest->node_name, &dest->present, &dest->aliased, pwanted, PP_PRISMTECH_NODE_NAME, dd);
-
- case PID_PRISMTECH_EXEC_NAME:
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- return do_string (&dest->exec_name, &dest->present, &dest->aliased, pwanted, PP_PRISMTECH_EXEC_NAME, dd);
-
- case PID_PRISMTECH_SERVICE_TYPE:
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- if (dd->bufsz < sizeof (dest->service_type))
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SERVICE_TYPE]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- memcpy (&dest->service_type, dd->buf, sizeof (dest->service_type));
- if (dd->bswap)
- dest->service_type = bswap4u (dest->service_type);
- dest->present |= PP_PRISMTECH_SERVICE_TYPE;
- return 0;
-
- case PID_PRISMTECH_PROCESS_ID:
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- if (dd->bufsz < sizeof (dest->process_id))
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_PROCESS_ID]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- memcpy (&dest->process_id, dd->buf, sizeof (dest->process_id));
- if (dd->bswap)
- dest->process_id = bswap4u (dest->process_id);
- dest->present |= PP_PRISMTECH_PROCESS_ID;
- return 0;
-
- case PID_PRISMTECH_TYPE_DESCRIPTION:
- if (!vendor_is_eclipse_or_prismtech (dd->vendorid))
- return 0;
- return do_string (&dest->type_description, &dest->present, &dest->aliased, pwanted, PP_PRISMTECH_TYPE_DESCRIPTION, dd);
-
- case PID_PRISMTECH_EOTINFO:
- if (!vendor_is_eclipse_or_opensplice (dd->vendorid))
- return 0;
- else if (dd->bufsz < 2*sizeof (uint32_t))
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_EOTINFO]: buffer too small (1)\n");
- return Q_ERR_INVALID;
- }
- else
- {
- nn_prismtech_eotinfo_t *q = &dest->eotinfo;
- uint32_t i;
- q->transactionId = ((const uint32_t *) dd->buf)[0];
- q->n = ((const uint32_t *) dd->buf)[1];
- if (dd->bswap)
- {
- q->n = bswap4u (q->n);
- q->transactionId = bswap4u (q->transactionId);
- }
- if (q->n > (dd->bufsz - 2*sizeof (uint32_t)) / sizeof (nn_prismtech_eotgroup_tid_t))
- {
- DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_EOTINFO]: buffer too small (2)\n");
- return Q_ERR_INVALID;
- }
- if (q->n == 0)
- q->tids = NULL;
- else
- q->tids = (nn_prismtech_eotgroup_tid_t *) (dd->buf + 2*sizeof (uint32_t));
- for (i = 0; i < q->n; i++)
- {
- q->tids[i].writer_entityid.u = fromBE4u (q->tids[i].writer_entityid.u);
- if (dd->bswap)
- q->tids[i].transactionId = bswap4u (q->tids[i].transactionId);
- }
- dest->present |= PP_PRISMTECH_EOTINFO;
- dest->aliased |= PP_PRISMTECH_EOTINFO;
- if (dds_get_log_mask() & DDS_LC_PLIST)
- {
- DDS_LOG(DDS_LC_PLIST, "eotinfo: txn %"PRIu32" {", q->transactionId);
- for (i = 0; i < q->n; i++)
- DDS_LOG(DDS_LC_PLIST, " %"PRIx32":%"PRIu32, q->tids[i].writer_entityid.u, q->tids[i].transactionId);
- DDS_LOG(DDS_LC_PLIST, " }\n");
- }
- return 0;
- }
-
-#ifdef DDSI_INCLUDE_SSM
- case PID_READER_FAVOURS_SSM:
- if (dd->bufsz < sizeof (dest->reader_favours_ssm))
- {
- DDS_TRACE("plist/init_one_parameter[pid=READER_FAVOURS_SSM]: buffer too small\n");
- return Q_ERR_INVALID;
- }
- else
- {
- nn_reader_favours_ssm_t *rfssm = &dest->reader_favours_ssm;
- memcpy (rfssm, dd->buf, sizeof (*rfssm));
- if (dd->bswap)
- rfssm->state = bswap4u (rfssm->state);
- if (rfssm->state != 0 && rfssm->state != 1)
- {
- DDS_TRACE("plist/init_one_parameter[pid=READER_FAVOURS_SSM]: unsupported value: %u\n", rfssm->state);
- rfssm->state = 0;
- }
- dest->present |= PP_READER_FAVOURS_SSM;
- return 0;
- }
-#endif
-
- /* Deprecated ones (used by RTI, but not relevant to DDSI) */
- case PID_PERSISTENCE:
- case PID_TYPE_CHECKSUM:
- case PID_TYPE2_NAME:
- case PID_TYPE2_CHECKSUM:
- case PID_EXPECTS_ACK:
- case PID_MANAGER_KEY:
- case PID_SEND_QUEUE_SIZE:
- case PID_RELIABILITY_ENABLED:
- case PID_VARGAPPS_SEQUENCE_NUMBER_LAST:
- case PID_RECV_QUEUE_SIZE:
- case PID_RELIABILITY_OFFERED:
- return 0;
-
- default:
- /* Ignore unrecognised parameters (disregarding vendor-specific
- ones, of course) if the protocol version is newer than the
- one implemented, and fail it if it isn't. I know all RFPs say
- to be tolerant in what is accepted, but that is where the
- bugs & the buffer overflows originate! */
- if (pid & PID_UNRECOGNIZED_INCOMPATIBLE_FLAG) {
- dest->present |= PP_INCOMPATIBLE;
- return Q_ERR_INCOMPATIBLE;
- } else if (pid & PID_VENDORSPECIFIC_FLAG) {
- return 0;
- } else if (!protocol_version_is_newer (dd->protocol_version) && NN_STRICT_P) {
- DDS_TRACE("plist/init_one_parameter[pid=%u,mode=STRICT,proto=%u.%u]: undefined paramter id\n",
- pid, dd->protocol_version.major, dd->protocol_version.minor);
- return Q_ERR_INVALID;
- } else {
- return 0;
- }
}
- assert (0);
- DDS_TRACE("plist/init_one_parameter: can't happen\n");
- return Q_ERR_INVALID;
-}
+ const struct piddesc_index *index;
+ if (!(pid & PID_VENDORSPECIFIC_FLAG))
+ index = &piddesc_vendor_index[0];
+ else if (dd->vendorid.id[0] != 1 || dd->vendorid.id[1] < 1)
+ return return_unrecognized_pid (plist, pid);
+ else if (dd->vendorid.id[1] >= sizeof (piddesc_vendor_index) / sizeof (piddesc_vendor_index[0]))
+ return return_unrecognized_pid (plist, pid);
+ else if (piddesc_vendor_index[dd->vendorid.id[1]].index == NULL)
+ return return_unrecognized_pid (plist, pid);
+ else
+ index = &piddesc_vendor_index[dd->vendorid.id[1]];
-static void default_resource_limits (nn_resource_limits_qospolicy_t *q)
-{
- q->max_instances = NN_DDS_LENGTH_UNLIMITED;
- q->max_samples = NN_DDS_LENGTH_UNLIMITED;
- q->max_samples_per_instance = NN_DDS_LENGTH_UNLIMITED;
-}
-
-static void default_history (nn_history_qospolicy_t *q)
-{
- q->kind = NN_KEEP_LAST_HISTORY_QOS;
- q->depth = 1;
-}
-
-void nn_plist_init_empty (nn_plist_t *dest)
-{
-#ifndef NDEBUG
- memset (dest, 0, sizeof (*dest));
-#endif
- dest->present = dest->aliased = 0;
- nn_xqos_init_empty (&dest->qos);
-}
-
-void nn_plist_mergein_missing (nn_plist_t *a, const nn_plist_t *b)
-{
- /* Adds entries's from B to A (duplicating memory) (only those not
- present in A, obviously) */
-
- /* Simple ones (that don't need memory): everything but topic, type,
- partition, {group,topic|user} data */
-#define CQ(fl_, name_) do { \
- if (!(a->present & PP_##fl_) && (b->present & PP_##fl_)) { \
- a->name_ = b->name_; \
- a->present |= PP_##fl_; \
- } \
- } while (0)
- CQ (PROTOCOL_VERSION, protocol_version);
- CQ (VENDORID, vendorid);
- CQ (EXPECTS_INLINE_QOS, expects_inline_qos);
- CQ (PARTICIPANT_MANUAL_LIVELINESS_COUNT, participant_manual_liveliness_count);
- CQ (PARTICIPANT_BUILTIN_ENDPOINTS, participant_builtin_endpoints);
- CQ (PARTICIPANT_LEASE_DURATION, participant_lease_duration);
- CQ (PARTICIPANT_GUID, participant_guid);
- CQ (ENDPOINT_GUID, endpoint_guid);
- CQ (GROUP_GUID, group_guid);
- CQ (BUILTIN_ENDPOINT_SET, builtin_endpoint_set);
- CQ (KEYHASH, keyhash);
- CQ (STATUSINFO, statusinfo);
- CQ (COHERENT_SET, coherent_set_seqno);
- CQ (PRISMTECH_SERVICE_TYPE, service_type);
- CQ (PRISMTECH_PROCESS_ID, process_id);
- CQ (PRISMTECH_BUILTIN_ENDPOINT_SET, prismtech_builtin_endpoint_set);
-#ifdef DDSI_INCLUDE_SSM
- CQ (READER_FAVOURS_SSM, reader_favours_ssm);
-#endif
-#undef CQ
-
- /* For allocated ones it is Not strictly necessary to use tmp, as
- a->name_ may only be interpreted if the present flag is set, but
- this keeps a clean on failure and may thereby save us from a
- nasty surprise. */
-#define CQ(fl_, name_, type_, tmp_type_) do { \
- if (!(a->present & PP_##fl_) && (b->present & PP_##fl_)) { \
- tmp_type_ tmp = b->name_; \
- unalias_##type_ (&tmp, -1); \
- a->name_ = tmp; \
- a->present |= PP_##fl_; \
- } \
- } while (0)
- CQ (UNICAST_LOCATOR, unicast_locators, locators, nn_locators_t);
- CQ (MULTICAST_LOCATOR, unicast_locators, locators, nn_locators_t);
- CQ (DEFAULT_UNICAST_LOCATOR, default_unicast_locators, locators, nn_locators_t);
- CQ (DEFAULT_MULTICAST_LOCATOR, default_multicast_locators, locators, nn_locators_t);
- CQ (METATRAFFIC_UNICAST_LOCATOR, metatraffic_unicast_locators, locators, nn_locators_t);
- CQ (METATRAFFIC_MULTICAST_LOCATOR, metatraffic_multicast_locators, locators, nn_locators_t);
- CQ (ENTITY_NAME, entity_name, string, char *);
- CQ (PRISMTECH_NODE_NAME, node_name, string, char *);
- CQ (PRISMTECH_EXEC_NAME, exec_name, string, char *);
- CQ (PRISMTECH_TYPE_DESCRIPTION, type_description, string, char *);
- CQ (PRISMTECH_EOTINFO, eotinfo, eotinfo, nn_prismtech_eotinfo_t);
-#undef CQ
- if (!(a->present & PP_PRISMTECH_PARTICIPANT_VERSION_INFO) &&
- (b->present & PP_PRISMTECH_PARTICIPANT_VERSION_INFO))
+ const struct piddesc *entry;
+ if (pid_without_flags (pid) > index->index_max || (entry = index->index[pid_without_flags (pid)]) == NULL)
+ return return_unrecognized_pid (plist, pid);
+ assert (pid_without_flags (pid) == pid_without_flags (entry->pid));
+ if (pid != entry->pid)
{
- nn_prismtech_participant_version_info_t tmp = b->prismtech_participant_version_info;
- unalias_string (&tmp.internals, -1);
- a->prismtech_participant_version_info = tmp;
- a->present |= PP_PRISMTECH_PARTICIPANT_VERSION_INFO;
+ DDS_CERROR (logcfg, "error processing parameter list (vendor %u.%u, version %u.%u): pid %"PRIx16" mapped to pid %"PRIx16"\n",
+ dd->vendorid.id[0], dd->vendorid.id[1],
+ dd->protocol_version.major, dd->protocol_version.minor,
+ pid, entry->pid);
+ return return_unrecognized_pid (plist, pid);
+ }
+ assert (pid != PID_PAD);
+
+ struct flagset flagset;
+ if (entry->flags & PDF_QOS)
+ {
+ flagset.present = &plist->qos.present;
+ flagset.aliased = &plist->qos.aliased;
+ flagset.wanted = qwanted;
+ }
+ else
+ {
+ flagset.present = &plist->present;
+ flagset.aliased = &plist->aliased;
+ flagset.wanted = pwanted;
}
- nn_xqos_mergein_missing (&a->qos, &b->qos);
+ /* Disallow multiple copies of the same parameter unless explicit allowed
+ (which is needed for handling locators). String sequences will leak
+ memory if deserialized repeatedly */
+ if ((*flagset.present & entry->present_flag) && !(entry->flags & PDF_ALLOWMULTI))
+ {
+ DDS_CWARNING (logcfg, "invalid parameter list (vendor %u.%u, version %u.%u): pid %"PRIx16" (%s) multiply defined\n",
+ dd->vendorid.id[0], dd->vendorid.id[1],
+ dd->protocol_version.major, dd->protocol_version.minor,
+ pid, entry->name);
+ return DDS_RETCODE_BAD_PARAMETER;
+ }
+ if (!(flagset.wanted & entry->present_flag))
+ {
+ /* skip don't cares -- the point of skipping them is performance and
+ avoiding unnecessary allocations, so validating them would be silly */
+ return 0;
+ }
+
+ /* String sequences are not allowed in parameters that may occur multiple
+ times because they will leak the arrays of pointers. Fixing this is
+ not worth the bother as long as such parameters don't exist. */
+ dds_return_t ret;
+ void * const dst = (char *) plist + entry->plist_offset;
+ size_t dstoff = 0;
+ size_t srcoff = 0;
+ if (entry->flags & PDF_FUNCTION)
+ ret = entry->op.f.deser (dst, &dstoff, &flagset, entry->present_flag, dd, &srcoff);
+ else
+ ret = deser_generic (dst, &dstoff, &flagset, entry->present_flag, dd, &srcoff, entry->op.desc);
+ if (ret == 0 && entry->deser_validate_xform)
+ ret = entry->deser_validate_xform (dst, dd);
+ if (ret < 0)
+ {
+ DDS_CWARNING (logcfg, "invalid parameter list (vendor %u.%u, version %u.%u): pid %"PRIx16" (%s) invalid, input = ",
+ dd->vendorid.id[0], dd->vendorid.id[1],
+ dd->protocol_version.major, dd->protocol_version.minor,
+ pid, entry->name);
+ log_octetseq (DDS_LC_WARNING, logcfg, (uint32_t) dd->bufsz, dd->buf);
+ DDS_CWARNING (logcfg, "\n");
+ }
+ return ret;
+}
+
+void nn_plist_mergein_missing (nn_plist_t *a, const nn_plist_t *b, uint64_t pmask, uint64_t qmask)
+{
+ plist_or_xqos_mergein_missing (a, b, 0, pmask, qmask);
+}
+
+void nn_xqos_mergein_missing (dds_qos_t *a, const dds_qos_t *b, uint64_t mask)
+{
+ plist_or_xqos_mergein_missing (a, b, offsetof (nn_plist_t, qos), 0, mask);
}
void nn_plist_copy (nn_plist_t *dst, const nn_plist_t *src)
{
nn_plist_init_empty (dst);
- nn_plist_mergein_missing (dst, src);
+ nn_plist_mergein_missing (dst, src, ~(uint64_t)0, ~(uint64_t)0);
}
nn_plist_t *nn_plist_dup (const nn_plist_t *src)
@@ -2299,28 +2012,45 @@ nn_plist_t *nn_plist_dup (const nn_plist_t *src)
return dst;
}
-static int final_validation (nn_plist_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid)
+void nn_plist_init_empty (nn_plist_t *dest)
{
+#ifndef NDEBUG
+ memset (dest, 0, sizeof (*dest));
+#endif
+ dest->present = dest->aliased = 0;
+ nn_xqos_init_empty (&dest->qos);
+}
+
+static dds_return_t final_validation_qos (const dds_qos_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid, bool *dursvc_accepted_allzero, bool strict)
+{
+ /* input is const, but we need to validate the combination of
+ history & resource limits: so use a copy of those two policies */
+ dds_history_qospolicy_t tmphist = {
+ .kind = DDS_HISTORY_KEEP_LAST,
+ .depth = 1
+ };
+ dds_resource_limits_qospolicy_t tmpreslim = {
+ .max_samples = DDS_LENGTH_UNLIMITED,
+ .max_instances = DDS_LENGTH_UNLIMITED,
+ .max_samples_per_instance = DDS_LENGTH_UNLIMITED
+ };
+ dds_return_t res;
+
/* Resource limits & history are related, so if only one is given,
set the other to the default, claim it has been provided &
validate the combination. They can't be changed afterward, so
this is a reasonable interpretation. */
- if ((dest->qos.present & QP_HISTORY) && !(dest->qos.present & QP_RESOURCE_LIMITS))
+ if (dest->present & QP_HISTORY)
+ tmphist = dest->history;
+ if (dest->present & QP_RESOURCE_LIMITS)
+ tmpreslim = dest->resource_limits;
+ if ((res = validate_history_and_resource_limits (&tmphist, &tmpreslim)) < 0)
+ return res;
+
+ if ((dest->present & QP_DEADLINE) && (dest->present & QP_TIME_BASED_FILTER))
{
- default_resource_limits (&dest->qos.resource_limits);
- dest->qos.present |= QP_RESOURCE_LIMITS;
- }
- if (!(dest->qos.present & QP_HISTORY) && (dest->qos.present & QP_RESOURCE_LIMITS))
- {
- default_history (&dest->qos.history);
- dest->qos.present |= QP_HISTORY;
- }
- if (dest->qos.present & (QP_HISTORY | QP_RESOURCE_LIMITS))
- {
- int res;
- assert ((dest->qos.present & (QP_HISTORY | QP_RESOURCE_LIMITS)) == (QP_HISTORY | QP_RESOURCE_LIMITS));
- if ((res = validate_history_and_resource_limits (&dest->qos.history, &dest->qos.resource_limits)) < 0)
- return res;
+ if (dest->deadline.deadline < dest->time_based_filter.minimum_separation)
+ return DDS_RETCODE_INCONSISTENT_POLICY;
}
/* Durability service is sort-of accepted if all zeros, but only
@@ -2329,50 +2059,51 @@ static int final_validation (nn_plist_t *dest, nn_protocol_version_t protocol_ve
parsed we know the setting of the durability QoS (the default
is always VOLATILE), and hence we can verify that the setting
is valid or delete it if irrelevant. */
- if (dest->qos.present & QP_DURABILITY_SERVICE)
+ if (dursvc_accepted_allzero)
+ *dursvc_accepted_allzero = false;
+ if (dest->present & QP_DURABILITY_SERVICE)
{
- const nn_durability_kind_t durkind = (dest->qos.present & QP_DURABILITY) ? dest->qos.durability.kind : NN_VOLATILE_DURABILITY_QOS;
+ const dds_durability_kind_t durkind = (dest->present & QP_DURABILITY) ? dest->durability.kind : DDS_DURABILITY_VOLATILE;
bool acceptzero;
+ bool check_dursvc = true;
/* Use a somewhat convoluted rule to decide whether or not to
"accept" an all-zero durability service setting, to find a
reasonable mix of strictness and compatibility */
- if (protocol_version_is_newer (protocol_version))
+ if (dursvc_accepted_allzero == NULL)
+ acceptzero = false;
+ else if (protocol_version_is_newer (protocol_version))
acceptzero = true;
- else if (NN_STRICT_P)
+ else if (strict)
acceptzero = vendor_is_twinoaks (vendorid);
else
acceptzero = !vendor_is_eclipse (vendorid);
switch (durkind)
{
- case NN_VOLATILE_DURABILITY_QOS:
- case NN_TRANSIENT_LOCAL_DURABILITY_QOS:
- /* pretend we never saw it if it is all zero */
- if (acceptzero && durability_service_qospolicy_allzero (&dest->qos.durability_service))
- dest->qos.present &= ~QP_DURABILITY_SERVICE;
+ case DDS_DURABILITY_VOLATILE:
+ case DDS_DURABILITY_TRANSIENT_LOCAL:
+ /* let caller now if we accepted all-zero: our input is const and we can't patch it out */
+ if (acceptzero && durability_service_qospolicy_allzero (&dest->durability_service) && dursvc_accepted_allzero)
+ {
+ *dursvc_accepted_allzero = true;
+ check_dursvc = false;
+ }
break;
- case NN_TRANSIENT_DURABILITY_QOS:
- case NN_PERSISTENT_DURABILITY_QOS:
+ case DDS_DURABILITY_TRANSIENT:
+ case DDS_DURABILITY_PERSISTENT:
break;
}
- /* if it is still present, it must be valid */
- if (dest->qos.present & QP_DURABILITY_SERVICE)
- {
- int res;
- if ((res = validate_durability_service_qospolicy (&dest->qos.durability_service)) < 0)
- return res;
- }
+ if (check_dursvc && (res = validate_durability_service_qospolicy_acceptzero (&dest->durability_service, false)) < 0)
+ return res;
}
return 0;
}
-int nn_plist_init_frommsg
-(
- nn_plist_t *dest,
- char **nextafterplist,
- uint64_t pwanted,
- uint64_t qwanted,
- const nn_plist_src_t *src
-)
+static dds_return_t final_validation (nn_plist_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid, bool *dursvc_accepted_allzero, bool strict)
+{
+ return final_validation_qos (&dest->qos, protocol_version, vendorid, dursvc_accepted_allzero, strict);
+}
+
+dds_return_t nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uint64_t pwanted, uint64_t qwanted, const nn_plist_src_t *src)
{
const unsigned char *pl;
struct dd dd;
@@ -2386,6 +2117,7 @@ int nn_plist_init_frommsg
*nextafterplist = NULL;
dd.protocol_version = src->protocol_version;
dd.vendorid = src->vendorid;
+ dd.factory = src->factory;
switch (src->encoding)
{
case PL_CDR_LE:
@@ -2403,73 +2135,77 @@ int nn_plist_init_frommsg
#endif
break;
default:
- DDS_WARNING ("plist(vendor %u.%u): unknown encoding (%d)\n",
- src->vendorid.id[0], src->vendorid.id[1], src->encoding);
- return Q_ERR_INVALID;
+ DDS_CWARNING (src->logconfig, "plist(vendor %u.%u): unknown encoding (%d)\n",
+ src->vendorid.id[0], src->vendorid.id[1], src->encoding);
+ return DDS_RETCODE_BAD_PARAMETER;
}
nn_plist_init_empty (dest);
- dest->unalias_needs_bswap = dd.bswap;
dest_tmp.present = 0;
- DDS_LOG(DDS_LC_PLIST, "NN_PLIST_INIT (bswap %d)\n", dd.bswap);
+ DDS_CLOG (DDS_LC_PLIST, src->logconfig, "NN_PLIST_INIT (bswap %d)\n", dd.bswap);
pl = src->buf;
while (pl + sizeof (nn_parameter_t) <= src->buf + src->bufsz)
{
nn_parameter_t *par = (nn_parameter_t *) pl;
nn_parameterid_t pid;
- unsigned short length;
- int res;
+ uint16_t length;
+ dds_return_t res;
/* swapping header partially based on wireshark dissector
output, partially on intuition, and in a small part based on
the spec */
pid = (nn_parameterid_t) (dd.bswap ? bswap2u (par->parameterid) : par->parameterid);
- length = (unsigned short) (dd.bswap ? bswap2u (par->length) : par->length);
+ length = (uint16_t) (dd.bswap ? bswap2u (par->length) : par->length);
if (pid == PID_SENTINEL)
{
/* Sentinel terminates list, the length is ignored, DDSI 9.4.2.11. */
- DDS_LOG(DDS_LC_PLIST, "%4x PID %x\n", (unsigned) (pl - src->buf), pid);
- if ((res = final_validation (dest, src->protocol_version, src->vendorid)) < 0)
+ bool dursvc_accepted_allzero;
+ DDS_CLOG (DDS_LC_PLIST, src->logconfig, "%4"PRIx32" PID %"PRIx16"\n", (uint32_t) (pl - src->buf), pid);
+ if ((res = final_validation (dest, src->protocol_version, src->vendorid, &dursvc_accepted_allzero, src->strict)) < 0)
{
nn_plist_fini (dest);
- return Q_ERR_INVALID;
+ return res;
}
else
{
+ /* If we accepted an all-zero durability service, that's awfully friendly of ours,
+ but we'll pretend we never saw it */
+ if (dursvc_accepted_allzero)
+ dest->qos.present &= ~QP_DURABILITY_SERVICE;
pl += sizeof (*par);
if (nextafterplist)
*nextafterplist = (char *) pl;
return 0;
}
}
- if (length > src->bufsz - sizeof (*par) - (unsigned) (pl - src->buf))
+ if (length > src->bufsz - sizeof (*par) - (uint32_t) (pl - src->buf))
{
- DDS_WARNING("plist(vendor %u.%u): parameter length %u out of bounds\n",
- src->vendorid.id[0], src->vendorid.id[1], length);
+ DDS_CWARNING (src->logconfig, "plist(vendor %u.%u): parameter length %"PRIu16" out of bounds\n",
+ src->vendorid.id[0], src->vendorid.id[1], length);
nn_plist_fini (dest);
- return Q_ERR_INVALID;
+ return DDS_RETCODE_BAD_PARAMETER;
}
if ((length % 4) != 0) /* DDSI 9.4.2.11 */
{
- DDS_WARNING("plist(vendor %u.%u): parameter length %u mod 4 != 0\n",
- src->vendorid.id[0], src->vendorid.id[1], length);
+ DDS_CWARNING (src->logconfig, "plist(vendor %u.%u): parameter length %"PRIu16" mod 4 != 0\n",
+ src->vendorid.id[0], src->vendorid.id[1], length);
nn_plist_fini (dest);
- return Q_ERR_INVALID;
+ return DDS_RETCODE_BAD_PARAMETER;
}
- if (dds_get_log_mask() & DDS_LC_PLIST)
+ if (src->logconfig->c.mask & DDS_LC_PLIST)
{
- DDS_LOG(DDS_LC_PLIST, "%4x PID %x len %u ", (unsigned) (pl - src->buf), pid, length);
- log_octetseq(DDS_LC_PLIST, length, (const unsigned char *) (par + 1));
- DDS_LOG(DDS_LC_PLIST, "\n");
+ DDS_CLOG (DDS_LC_PLIST, src->logconfig, "%4"PRIx32" PID %"PRIx16" len %"PRIu16" ", (uint32_t) (pl - src->buf), pid, length);
+ log_octetseq (DDS_LC_PLIST, src->logconfig, length, (const unsigned char *) (par + 1));
+ DDS_CLOG (DDS_LC_PLIST, src->logconfig, "\n");
}
dd.buf = (const unsigned char *) (par + 1);
dd.bufsz = length;
- if ((res = init_one_parameter (dest, &dest_tmp, pwanted, qwanted, pid, &dd)) < 0)
+ if ((res = init_one_parameter (dest, &dest_tmp, pwanted, qwanted, pid, &dd, src->factory, src->logconfig)) < 0)
{
/* make sure we print a trace message on error */
- DDS_TRACE("plist(vendor %u.%u): failed at pid=%u\n", src->vendorid.id[0], src->vendorid.id[1], pid);
+ DDS_CTRACE (src->logconfig, "plist(vendor %u.%u): failed at pid=%"PRIx16"\n", src->vendorid.id[0], src->vendorid.id[1], pid);
nn_plist_fini (dest);
return res;
}
@@ -2477,10 +2213,10 @@ int nn_plist_init_frommsg
}
/* If we get here, that means we reached the end of the message
without encountering a sentinel. That is an error */
- DDS_WARNING("plist(vendor %u.%u): invalid parameter list: sentinel missing\n",
- src->vendorid.id[0], src->vendorid.id[1]);
+ DDS_CWARNING (src->logconfig, "plist(vendor %u.%u): invalid parameter list: sentinel missing\n",
+ src->vendorid.id[0], src->vendorid.id[1]);
nn_plist_fini (dest);
- return Q_ERR_INVALID;
+ return DDS_RETCODE_BAD_PARAMETER;
}
const unsigned char *nn_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid)
@@ -2526,11 +2262,11 @@ unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn
#endif
break;
default:
- DDS_WARNING("plist(vendor %u.%u): quickscan: unknown encoding (%d)\n",
- src->vendorid.id[0], src->vendorid.id[1], src->encoding);
+ DDS_CWARNING (src->logconfig, "plist(vendor %u.%u): quickscan: unknown encoding (%d)\n",
+ src->vendorid.id[0], src->vendorid.id[1], src->encoding);
return NULL;
}
- DDS_LOG(DDS_LC_PLIST, "NN_PLIST_QUICKSCAN (bswap %d)\n", dest->bswap);
+ DDS_CLOG (DDS_LC_PLIST, src->logconfig, "NN_PLIST_QUICKSCAN (bswap %d)\n", dest->bswap);
pl = src->buf;
while (pl + sizeof (nn_parameter_t) <= src->buf + src->bufsz)
{
@@ -2544,14 +2280,14 @@ unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn
return (unsigned char *) pl;
if (length > src->bufsz - (size_t)(pl - src->buf))
{
- DDS_WARNING("plist(vendor %u.%u): quickscan: parameter length %u out of bounds\n",
- src->vendorid.id[0], src->vendorid.id[1], length);
+ DDS_CWARNING (src->logconfig, "plist(vendor %u.%u): quickscan: parameter length %"PRIu16" out of bounds\n",
+ src->vendorid.id[0], src->vendorid.id[1], length);
return NULL;
}
if ((length % 4) != 0) /* DDSI 9.4.2.11 */
{
- DDS_WARNING("plist(vendor %u.%u): quickscan: parameter length %u mod 4 != 0\n",
- src->vendorid.id[0], src->vendorid.id[1], length);
+ DDS_CWARNING (src->logconfig, "plist(vendor %u.%u): quickscan: parameter length %"PRIu16" mod 4 != 0\n",
+ src->vendorid.id[0], src->vendorid.id[1], length);
return NULL;
}
switch (pid)
@@ -2561,24 +2297,24 @@ unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn
case PID_STATUSINFO:
if (length < 4)
{
- DDS_TRACE("plist(vendor %u.%u): quickscan(PID_STATUSINFO): buffer too small\n",
- src->vendorid.id[0], src->vendorid.id[1]);
+ DDS_CTRACE (src->logconfig, "plist(vendor %u.%u): quickscan(PID_STATUSINFO): buffer too small\n",
+ src->vendorid.id[0], src->vendorid.id[1]);
return NULL;
}
else
{
- unsigned stinfo = fromBE4u (*((unsigned *) pl));
- unsigned stinfox = (length < 8 || !vendor_is_eclipse_or_opensplice(src->vendorid)) ? 0 : fromBE4u (*((unsigned *) pl + 1));
-#if (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER) != 3
-#error "expected dispose/unregister to be in lowest 2 bits"
-#endif
+ /* can only represent 2 LSBs of statusinfo in "dest", so if others are set,
+ mark it as a "complex_qos" and accept the hit of parsing the data completely. */
+ uint32_t stinfo = fromBE4u (*((uint32_t *) pl));
dest->statusinfo = stinfo & 3u;
- if ((stinfo & ~3u) || stinfox)
+ if ((stinfo & ~3u))
dest->complex_qos = 1;
}
break;
+ case PID_KEYHASH:
+ break;
default:
- DDS_LOG(DDS_LC_PLIST, "(pid=%x complex_qos=1)", pid);
+ DDS_CLOG (DDS_LC_PLIST, src->logconfig, "(pid=%"PRIx16" complex_qos=1)", pid);
dest->complex_qos = 1;
break;
}
@@ -2586,13 +2322,12 @@ unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn
}
/* If we get here, that means we reached the end of the message
without encountering a sentinel. That is an error */
- DDS_WARNING("plist(vendor %u.%u): quickscan: invalid parameter list: sentinel missing\n",
- src->vendorid.id[0], src->vendorid.id[1]);
+ DDS_CWARNING (src->logconfig, "plist(vendor %u.%u): quickscan: invalid parameter list: sentinel missing\n",
+ src->vendorid.id[0], src->vendorid.id[1]);
return NULL;
}
-
-void nn_xqos_init_empty (nn_xqos_t *dest)
+void nn_xqos_init_empty (dds_qos_t *dest)
{
#ifndef NDEBUG
memset (dest, 0, sizeof (*dest));
@@ -2600,89 +2335,100 @@ void nn_xqos_init_empty (nn_xqos_t *dest)
dest->present = dest->aliased = 0;
}
-int nn_plist_init_default_participant (nn_plist_t *plist)
+void nn_plist_init_default_participant (nn_plist_t *plist)
{
nn_plist_init_empty (plist);
+
plist->qos.present |= QP_PRISMTECH_ENTITY_FACTORY;
plist->qos.entity_factory.autoenable_created_entities = 0;
- return 0;
+
+ plist->qos.present |= QP_USER_DATA;
+ plist->qos.user_data.length = 0;
+ plist->qos.user_data.value = NULL;
}
-static void xqos_init_default_common (nn_xqos_t *xqos)
+static void xqos_init_default_common (dds_qos_t *xqos)
{
nn_xqos_init_empty (xqos);
- xqos->present |= QP_PARTITION;
- xqos->partition.n = 0;
- xqos->partition.strs = NULL;
-
xqos->present |= QP_PRESENTATION;
- xqos->presentation.access_scope = NN_INSTANCE_PRESENTATION_QOS;
+ xqos->presentation.access_scope = DDS_PRESENTATION_INSTANCE;
xqos->presentation.coherent_access = 0;
xqos->presentation.ordered_access = 0;
xqos->present |= QP_DURABILITY;
- xqos->durability.kind = NN_VOLATILE_DURABILITY_QOS;
+ xqos->durability.kind = DDS_DURABILITY_VOLATILE;
xqos->present |= QP_DEADLINE;
- xqos->deadline.deadline = nn_to_ddsi_duration (T_NEVER);
+ xqos->deadline.deadline = T_NEVER;
xqos->present |= QP_LATENCY_BUDGET;
- xqos->latency_budget.duration = nn_to_ddsi_duration (0);
+ xqos->latency_budget.duration = 0;
xqos->present |= QP_LIVELINESS;
- xqos->liveliness.kind = NN_AUTOMATIC_LIVELINESS_QOS;
- xqos->liveliness.lease_duration = nn_to_ddsi_duration (T_NEVER);
+ xqos->liveliness.kind = DDS_LIVELINESS_AUTOMATIC;
+ xqos->liveliness.lease_duration = T_NEVER;
xqos->present |= QP_DESTINATION_ORDER;
- xqos->destination_order.kind = NN_BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS;
+ xqos->destination_order.kind = DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP;
xqos->present |= QP_HISTORY;
- xqos->history.kind = NN_KEEP_LAST_HISTORY_QOS;
+ xqos->history.kind = DDS_HISTORY_KEEP_LAST;
xqos->history.depth = 1;
xqos->present |= QP_RESOURCE_LIMITS;
- xqos->resource_limits.max_samples = NN_DDS_LENGTH_UNLIMITED;
- xqos->resource_limits.max_instances = NN_DDS_LENGTH_UNLIMITED;
- xqos->resource_limits.max_samples_per_instance = NN_DDS_LENGTH_UNLIMITED;
+ xqos->resource_limits.max_samples = DDS_LENGTH_UNLIMITED;
+ xqos->resource_limits.max_instances = DDS_LENGTH_UNLIMITED;
+ xqos->resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED;
xqos->present |= QP_TRANSPORT_PRIORITY;
xqos->transport_priority.value = 0;
xqos->present |= QP_OWNERSHIP;
- xqos->ownership.kind = NN_SHARED_OWNERSHIP_QOS;
-
- xqos->present |= QP_PRISMTECH_RELAXED_QOS_MATCHING;
- xqos->relaxed_qos_matching.value = 0;
-
- xqos->present |= QP_PRISMTECH_SYNCHRONOUS_ENDPOINT;
- xqos->synchronous_endpoint.value = 0;
+ xqos->ownership.kind = DDS_OWNERSHIP_SHARED;
xqos->present |= QP_CYCLONE_IGNORELOCAL;
- xqos->ignorelocal.value = NN_NONE_IGNORELOCAL_QOS;
+ xqos->ignorelocal.value = DDS_IGNORELOCAL_NONE;
}
-void nn_xqos_init_default_reader (nn_xqos_t *xqos)
+static void nn_xqos_init_default_endpoint (dds_qos_t *xqos)
{
xqos_init_default_common (xqos);
+ xqos->present |= QP_TOPIC_DATA;
+ xqos->topic_data.length = 0;
+ xqos->topic_data.value = NULL;
+
+ xqos->present |= QP_GROUP_DATA;
+ xqos->group_data.length = 0;
+ xqos->group_data.value = NULL;
+
+ xqos->present |= QP_USER_DATA;
+ xqos->user_data.length = 0;
+ xqos->user_data.value = NULL;
+
+ xqos->present |= QP_PARTITION;
+ xqos->partition.n = 0;
+ xqos->partition.strs = NULL;
+}
+
+void nn_xqos_init_default_reader (dds_qos_t *xqos)
+{
+ nn_xqos_init_default_endpoint (xqos);
+
xqos->present |= QP_RELIABILITY;
- xqos->reliability.kind = NN_BEST_EFFORT_RELIABILITY_QOS;
+ xqos->reliability.kind = DDS_RELIABILITY_BEST_EFFORT;
xqos->present |= QP_TIME_BASED_FILTER;
- xqos->time_based_filter.minimum_separation = nn_to_ddsi_duration (0);
+ xqos->time_based_filter.minimum_separation = 0;
xqos->present |= QP_PRISMTECH_READER_DATA_LIFECYCLE;
- xqos->reader_data_lifecycle.autopurge_nowriter_samples_delay = nn_to_ddsi_duration (T_NEVER);
- xqos->reader_data_lifecycle.autopurge_disposed_samples_delay = nn_to_ddsi_duration (T_NEVER);
- xqos->reader_data_lifecycle.autopurge_dispose_all = 0;
- xqos->reader_data_lifecycle.enable_invalid_samples = 1;
- xqos->reader_data_lifecycle.invalid_sample_visibility = NN_MINIMUM_INVALID_SAMPLE_VISIBILITY_QOS;
+ xqos->reader_data_lifecycle.autopurge_nowriter_samples_delay = T_NEVER;
+ xqos->reader_data_lifecycle.autopurge_disposed_samples_delay = T_NEVER;
xqos->present |= QP_PRISMTECH_READER_LIFESPAN;
xqos->reader_lifespan.use_lifespan = 0;
- xqos->reader_lifespan.duration = nn_to_ddsi_duration (T_NEVER);
-
+ xqos->reader_lifespan.duration = T_NEVER;
xqos->present |= QP_PRISMTECH_SUBSCRIPTION_KEYS;
xqos->subscription_keys.use_key_list = 0;
@@ -2690,21 +2436,21 @@ void nn_xqos_init_default_reader (nn_xqos_t *xqos)
xqos->subscription_keys.key_list.strs = NULL;
}
-void nn_xqos_init_default_writer (nn_xqos_t *xqos)
+void nn_xqos_init_default_writer (dds_qos_t *xqos)
{
- xqos_init_default_common (xqos);
+ nn_xqos_init_default_endpoint (xqos);
xqos->present |= QP_DURABILITY_SERVICE;
- xqos->durability_service.service_cleanup_delay = nn_to_ddsi_duration (0);
- xqos->durability_service.history.kind = NN_KEEP_LAST_HISTORY_QOS;
+ xqos->durability_service.service_cleanup_delay = 0;
+ xqos->durability_service.history.kind = DDS_HISTORY_KEEP_LAST;
xqos->durability_service.history.depth = 1;
- xqos->durability_service.resource_limits.max_samples = NN_DDS_LENGTH_UNLIMITED;
- xqos->durability_service.resource_limits.max_instances = NN_DDS_LENGTH_UNLIMITED;
- xqos->durability_service.resource_limits.max_samples_per_instance = NN_DDS_LENGTH_UNLIMITED;
+ xqos->durability_service.resource_limits.max_samples = DDS_LENGTH_UNLIMITED;
+ xqos->durability_service.resource_limits.max_instances = DDS_LENGTH_UNLIMITED;
+ xqos->durability_service.resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED;
xqos->present |= QP_RELIABILITY;
- xqos->reliability.kind = NN_RELIABLE_RELIABILITY_QOS;
- xqos->reliability.max_blocking_time = nn_to_ddsi_duration (100 * T_MILLISECOND);
+ xqos->reliability.kind = DDS_RELIABILITY_RELIABLE;
+ xqos->reliability.max_blocking_time = 100 * T_MILLISECOND;
xqos->present |= QP_OWNERSHIP_STRENGTH;
xqos->ownership_strength.value = 0;
@@ -2713,41 +2459,39 @@ void nn_xqos_init_default_writer (nn_xqos_t *xqos)
xqos->transport_priority.value = 0;
xqos->present |= QP_LIFESPAN;
- xqos->lifespan.duration = nn_to_ddsi_duration (T_NEVER);
+ xqos->lifespan.duration = T_NEVER;
xqos->present |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE;
xqos->writer_data_lifecycle.autodispose_unregistered_instances = 1;
- xqos->writer_data_lifecycle.autounregister_instance_delay = nn_to_ddsi_duration (T_NEVER);
- xqos->writer_data_lifecycle.autopurge_suspended_samples_delay = nn_to_ddsi_duration (T_NEVER);
}
-void nn_xqos_init_default_writer_noautodispose (nn_xqos_t *xqos)
+void nn_xqos_init_default_writer_noautodispose (dds_qos_t *xqos)
{
nn_xqos_init_default_writer (xqos);
xqos->writer_data_lifecycle.autodispose_unregistered_instances = 0;
}
-void nn_xqos_init_default_topic (nn_xqos_t *xqos)
+void nn_xqos_init_default_topic (dds_qos_t *xqos)
{
xqos_init_default_common (xqos);
xqos->present |= QP_DURABILITY_SERVICE;
- xqos->durability_service.service_cleanup_delay = nn_to_ddsi_duration (0);
- xqos->durability_service.history.kind = NN_KEEP_LAST_HISTORY_QOS;
+ xqos->durability_service.service_cleanup_delay = 0;
+ xqos->durability_service.history.kind = DDS_HISTORY_KEEP_LAST;
xqos->durability_service.history.depth = 1;
- xqos->durability_service.resource_limits.max_samples = NN_DDS_LENGTH_UNLIMITED;
- xqos->durability_service.resource_limits.max_instances = NN_DDS_LENGTH_UNLIMITED;
- xqos->durability_service.resource_limits.max_samples_per_instance = NN_DDS_LENGTH_UNLIMITED;
+ xqos->durability_service.resource_limits.max_samples = DDS_LENGTH_UNLIMITED;
+ xqos->durability_service.resource_limits.max_instances = DDS_LENGTH_UNLIMITED;
+ xqos->durability_service.resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED;
xqos->present |= QP_RELIABILITY;
- xqos->reliability.kind = NN_BEST_EFFORT_RELIABILITY_QOS;
- xqos->reliability.max_blocking_time = nn_to_ddsi_duration (100 * T_MILLISECOND);
+ xqos->reliability.kind = DDS_RELIABILITY_BEST_EFFORT;
+ xqos->reliability.max_blocking_time = 100 * T_MILLISECOND;
xqos->present |= QP_TRANSPORT_PRIORITY;
xqos->transport_priority.value = 0;
xqos->present |= QP_LIFESPAN;
- xqos->lifespan.duration = nn_to_ddsi_duration (T_NEVER);
+ xqos->lifespan.duration = T_NEVER;
xqos->present |= QP_PRISMTECH_SUBSCRIPTION_KEYS;
xqos->subscription_keys.use_key_list = 0;
@@ -2755,22 +2499,13 @@ void nn_xqos_init_default_topic (nn_xqos_t *xqos)
xqos->subscription_keys.key_list.strs = NULL;
}
-void nn_xqos_init_default_subscriber (nn_xqos_t *xqos)
+static void nn_xqos_init_default_publisher_subscriber (dds_qos_t *xqos)
{
nn_xqos_init_empty (xqos);
- xqos->present |= QP_PRISMTECH_ENTITY_FACTORY;
- xqos->entity_factory.autoenable_created_entities = 1;
-
-
- xqos->present |= QP_PARTITION;
- xqos->partition.n = 0;
- xqos->partition.strs = NULL;
-}
-
-void nn_xqos_init_default_publisher (nn_xqos_t *xqos)
-{
- nn_xqos_init_empty (xqos);
+ xqos->present |= QP_GROUP_DATA;
+ xqos->group_data.length = 0;
+ xqos->group_data.value = NULL;
xqos->present |= QP_PRISMTECH_ENTITY_FACTORY;
xqos->entity_factory.autoenable_created_entities = 1;
@@ -2780,203 +2515,57 @@ void nn_xqos_init_default_publisher (nn_xqos_t *xqos)
xqos->partition.strs = NULL;
}
-void nn_xqos_mergein_missing (nn_xqos_t *a, const nn_xqos_t *b)
+void nn_xqos_init_default_subscriber (dds_qos_t *xqos)
{
- /* Adds QoS's from B to A (duplicating memory) (only those not
- present in A, obviously) */
-
- /* Simple ones (that don't need memory): everything but topic, type,
- partition, {group,topic|user} data */
-#define CQ(fl_, name_) do { \
- if (!(a->present & QP_##fl_) && (b->present & QP_##fl_)) { \
- a->name_ = b->name_; \
- a->present |= QP_##fl_; \
- } \
- } while (0)
- CQ (PRESENTATION, presentation);
- CQ (DURABILITY, durability);
- CQ (DURABILITY_SERVICE, durability_service);
- CQ (DEADLINE, deadline);
- CQ (LATENCY_BUDGET, latency_budget);
- CQ (LIVELINESS, liveliness);
- CQ (RELIABILITY, reliability);
- CQ (DESTINATION_ORDER, destination_order);
- CQ (HISTORY, history);
- CQ (RESOURCE_LIMITS, resource_limits);
- CQ (TRANSPORT_PRIORITY, transport_priority);
- CQ (LIFESPAN, lifespan);
- CQ (OWNERSHIP, ownership);
- CQ (OWNERSHIP_STRENGTH, ownership_strength);
- CQ (TIME_BASED_FILTER, time_based_filter);
- CQ (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle);
- CQ (PRISMTECH_WRITER_DATA_LIFECYCLE, writer_data_lifecycle);
- CQ (PRISMTECH_RELAXED_QOS_MATCHING, relaxed_qos_matching);
- CQ (PRISMTECH_READER_LIFESPAN, reader_lifespan);
- CQ (PRISMTECH_ENTITY_FACTORY, entity_factory);
- CQ (PRISMTECH_SYNCHRONOUS_ENDPOINT, synchronous_endpoint);
- CQ (CYCLONE_IGNORELOCAL, ignorelocal);
-#undef CQ
-
- /* For allocated ones it is Not strictly necessary to use tmp, as
- a->name_ may only be interpreted if the present flag is set, but
- this keeps a clean on failure and may thereby save us from a
- nasty surprise. */
-#define CQ(fl_, name_, type_, tmp_type_) do { \
- if (!(a->present & QP_##fl_) && (b->present & QP_##fl_)) { \
- tmp_type_ tmp = b->name_; \
- unalias_##type_ (&tmp, -1); \
- a->name_ = tmp; \
- a->present |= QP_##fl_; \
- } \
- } while (0)
- CQ (GROUP_DATA, group_data, octetseq, nn_octetseq_t);
- CQ (TOPIC_DATA, topic_data, octetseq, nn_octetseq_t);
- CQ (USER_DATA, user_data, octetseq, nn_octetseq_t);
- CQ (TOPIC_NAME, topic_name, string, char *);
- CQ (TYPE_NAME, type_name, string, char *);
- CQ (RTI_TYPECODE, rti_typecode, octetseq, nn_octetseq_t);
-#undef CQ
- if (!(a->present & QP_PRISMTECH_SUBSCRIPTION_KEYS) && (b->present & QP_PRISMTECH_SUBSCRIPTION_KEYS))
- {
- a->subscription_keys.use_key_list = b->subscription_keys.use_key_list;
- duplicate_stringseq (&a->subscription_keys.key_list, &b->subscription_keys.key_list);
- a->present |= QP_PRISMTECH_SUBSCRIPTION_KEYS;
- }
- if (!(a->present & QP_PARTITION) && (b->present & QP_PARTITION))
- {
- duplicate_stringseq (&a->partition, &b->partition);
- a->present |= QP_PARTITION;
- }
+ nn_xqos_init_default_publisher_subscriber (xqos);
}
-void nn_xqos_copy (nn_xqos_t *dst, const nn_xqos_t *src)
+void nn_xqos_init_default_publisher (dds_qos_t *xqos)
+{
+ nn_xqos_init_default_publisher_subscriber (xqos);
+}
+
+void nn_xqos_copy (dds_qos_t *dst, const dds_qos_t *src)
{
nn_xqos_init_empty (dst);
- nn_xqos_mergein_missing (dst, src);
+ nn_xqos_mergein_missing (dst, src, ~(uint64_t)0);
}
-void nn_xqos_unalias (nn_xqos_t *xqos)
+void nn_xqos_fini (dds_qos_t *xqos)
{
- DDS_LOG(DDS_LC_PLIST, "NN_XQOS_UNALIAS\n");
-#define Q(name_, func_, field_) do { \
- if ((xqos->present & QP_##name_) && (xqos->aliased & QP_##name_)) { \
- unalias_##func_ (&xqos->field_, -1); \
- xqos->aliased &= ~QP_##name_; \
- } \
- } while (0)
- Q (GROUP_DATA, octetseq, group_data);
- Q (TOPIC_DATA, octetseq, topic_data);
- Q (USER_DATA, octetseq, user_data);
- Q (TOPIC_NAME, string, topic_name);
- Q (TYPE_NAME, string, type_name);
- Q (PARTITION, stringseq, partition);
- Q (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys_qospolicy, subscription_keys);
- Q (RTI_TYPECODE, octetseq, rti_typecode);
-#undef Q
- assert (xqos->aliased == 0);
+ plist_or_xqos_fini (xqos, offsetof (nn_plist_t, qos), ~(uint64_t)0, ~(uint64_t)0);
}
-void nn_xqos_fini (nn_xqos_t *xqos)
+void nn_xqos_fini_mask (dds_qos_t *xqos, uint64_t mask)
{
- struct t { uint64_t fl; size_t off; };
- static const struct t qos_simple[] = {
- { QP_GROUP_DATA, offsetof (nn_xqos_t, group_data.value) },
- { QP_TOPIC_DATA, offsetof (nn_xqos_t, topic_data.value) },
- { QP_USER_DATA, offsetof (nn_xqos_t, user_data.value) },
- { QP_TOPIC_NAME, offsetof (nn_xqos_t, topic_name) },
- { QP_TYPE_NAME, offsetof (nn_xqos_t, type_name) },
- { QP_RTI_TYPECODE, offsetof (nn_xqos_t, rti_typecode.value) }
- };
- int i;
- DDS_LOG(DDS_LC_PLIST, "NN_XQOS_FINI\n");
- for (i = 0; i < (int) (sizeof (qos_simple) / sizeof (*qos_simple)); i++)
- {
- if ((xqos->present & qos_simple[i].fl) && !(xqos->aliased & qos_simple[i].fl))
- {
- void **pp = (void **) ((char *) xqos + qos_simple[i].off);
- DDS_LOG(DDS_LC_PLIST, "NN_XQOS_FINI free %p\n", *pp);
- ddsrt_free (*pp);
- }
- }
- if (xqos->present & QP_PARTITION)
- {
- if (!(xqos->aliased & QP_PARTITION))
- {
- free_stringseq (&xqos->partition);
- }
- else
- {
- /* until proper message buffers arrive */
- DDS_LOG(DDS_LC_PLIST, "NN_XQOS_FINI free %p\n", (void *) xqos->partition.strs);
- ddsrt_free (xqos->partition.strs);
- }
- }
- if (xqos->present & QP_PRISMTECH_SUBSCRIPTION_KEYS)
- {
- if (!(xqos->aliased & QP_PRISMTECH_SUBSCRIPTION_KEYS))
- free_stringseq (&xqos->subscription_keys.key_list);
- else
- {
- /* until proper message buffers arrive */
- DDS_LOG(DDS_LC_PLIST, "NN_XQOS_FINI free %p\n", (void *) xqos->subscription_keys.key_list.strs);
- ddsrt_free (xqos->subscription_keys.key_list.strs);
- }
- }
- xqos->present = 0;
+ plist_or_xqos_fini (xqos, offsetof (nn_plist_t, qos), ~(uint64_t)0, mask);
}
-nn_xqos_t * nn_xqos_dup (const nn_xqos_t *src)
+void nn_xqos_unalias (dds_qos_t *xqos)
{
- nn_xqos_t *dst = ddsrt_malloc (sizeof (*dst));
+ plist_or_xqos_unalias (xqos, offsetof (nn_plist_t, qos));
+}
+
+dds_qos_t * nn_xqos_dup (const dds_qos_t *src)
+{
+ dds_qos_t *dst = ddsrt_malloc (sizeof (*dst));
nn_xqos_copy (dst, src);
assert (dst->aliased == 0);
return dst;
}
-static int octetseqs_differ (const nn_octetseq_t *a, const nn_octetseq_t *b)
+static int partition_is_default (const dds_partition_qospolicy_t *a)
{
- return (a->length != b->length || memcmp (a->value, b->value, a->length) != 0);
-}
-
-static int durations_differ (const nn_duration_t *a, const nn_duration_t *b)
-{
- return (a->seconds != b->seconds || a->fraction != b->fraction);
-}
-
-static int stringseqs_differ (const nn_stringseq_t *a, const nn_stringseq_t *b)
-{
- unsigned i;
- if (a->n != b->n)
- return 1;
- for (i = 0; i < a->n; i++)
- if (strcmp (a->strs[i], b->strs[i]))
- return 1;
- return 0;
-}
-
-static int histories_differ (const nn_history_qospolicy_t *a, const nn_history_qospolicy_t *b)
-{
- return (a->kind != b->kind || (a->kind == NN_KEEP_LAST_HISTORY_QOS && a->depth != b->depth));
-}
-
-static int resource_limits_differ (const nn_resource_limits_qospolicy_t *a, const nn_resource_limits_qospolicy_t *b)
-{
- return (a->max_samples != b->max_samples || a->max_instances != b->max_instances ||
- a->max_samples_per_instance != b->max_samples_per_instance);
-}
-
-static int partition_is_default (const nn_partition_qospolicy_t *a)
-{
- unsigned i;
+ uint32_t i;
for (i = 0; i < a->n; i++)
if (strcmp (a->strs[i], "") != 0)
return 0;
return 1;
}
-static int partitions_equal_n2 (const nn_partition_qospolicy_t *a, const nn_partition_qospolicy_t *b)
+static int partitions_equal_n2 (const dds_partition_qospolicy_t *a, const dds_partition_qospolicy_t *b)
{
- unsigned i, j;
+ uint32_t i, j;
for (i = 0; i < a->n; i++)
{
for (j = 0; j < b->n; j++)
@@ -2988,22 +2577,29 @@ static int partitions_equal_n2 (const nn_partition_qospolicy_t *a, const nn_part
return 1;
}
-static int partitions_equal_nlogn (const nn_partition_qospolicy_t *a, const nn_partition_qospolicy_t *b)
+static int strcmp_wrapper (const void *va, const void *vb)
+{
+ char const * const *a = va;
+ char const * const *b = vb;
+ return strcmp (*a, *b);
+}
+
+static int partitions_equal_nlogn (const dds_partition_qospolicy_t *a, const dds_partition_qospolicy_t *b)
{
char *statictab[8], **tab;
int equal = 1;
- unsigned i;
+ uint32_t i;
- if (a->n <= (int) (sizeof (statictab) / sizeof (*statictab)))
+ if (a->n <= sizeof (statictab) / sizeof (*statictab))
tab = statictab;
else
tab = ddsrt_malloc (a->n * sizeof (*tab));
for (i = 0; i < a->n; i++)
tab[i] = a->strs[i];
- qsort (tab, a->n, sizeof (*tab), (int (*) (const void *, const void *)) strcmp);
+ qsort (tab, a->n, sizeof (*tab), strcmp_wrapper);
for (i = 0; i < b->n; i++)
- if (bsearch (b->strs[i], tab, a->n, sizeof (*tab), (int (*) (const void *, const void *)) strcmp) == NULL)
+ if (bsearch (&b->strs[i], tab, a->n, sizeof (*tab), strcmp_wrapper) == NULL)
{
equal = 0;
break;
@@ -3013,7 +2609,7 @@ static int partitions_equal_nlogn (const nn_partition_qospolicy_t *a, const nn_p
return equal;
}
-static int partitions_equal (const nn_partition_qospolicy_t *a, const nn_partition_qospolicy_t *b)
+static int partitions_equal (const dds_partition_qospolicy_t *a, const dds_partition_qospolicy_t *b)
{
/* Return true iff (the set a->strs) equals (the set b->strs); that
is, order doesn't matter. One could argue that "**" and "*" are
@@ -3034,7 +2630,7 @@ static int partitions_equal (const nn_partition_qospolicy_t *a, const nn_partiti
assuming that |A| >= |B|. */
if (a->n < b->n)
{
- const nn_partition_qospolicy_t *x = a;
+ const dds_partition_qospolicy_t *x = a;
a = b;
b = x;
}
@@ -3051,333 +2647,38 @@ static int partitions_equal (const nn_partition_qospolicy_t *a, const nn_partiti
}
}
-uint64_t nn_xqos_delta (const nn_xqos_t *a, const nn_xqos_t *b, uint64_t mask)
-{
- /* Returns QP_... set for RxO settings where a differs from b; if
- present in a but not in b (or in b but not in a) it counts as a
- difference. */
- uint64_t delta = (a->present ^ b->present) & mask;
- uint64_t check = (a->present & b->present) & mask;
- if (check & QP_TOPIC_NAME) {
- if (strcmp (a->topic_name, b->topic_name))
- delta |= QP_TOPIC_NAME;
- }
- if (check & QP_TYPE_NAME) {
- if (strcmp (a->type_name, b->type_name))
- delta |= QP_TYPE_NAME;
- }
- if (check & QP_PRESENTATION) {
- if (a->presentation.access_scope != b->presentation.access_scope ||
- a->presentation.coherent_access != b->presentation.coherent_access ||
- a->presentation.ordered_access != b->presentation.ordered_access)
- delta |= QP_PRESENTATION;
- }
- if (check & QP_PARTITION) {
- if (!partitions_equal (&a->partition, &b->partition))
- delta |= QP_PARTITION;
- }
- if (check & QP_GROUP_DATA) {
- if (octetseqs_differ (&a->group_data, &b->group_data))
- delta |= QP_GROUP_DATA;
- }
- if (check & QP_TOPIC_DATA) {
- if (octetseqs_differ (&a->topic_data, &b->topic_data))
- delta |= QP_TOPIC_DATA;
- }
- if (check & QP_DURABILITY) {
- if (a->durability.kind != b->durability.kind)
- delta |= QP_DURABILITY;
- }
- if (check & QP_DURABILITY_SERVICE)
- {
- const nn_durability_service_qospolicy_t *qa = &a->durability_service;
- const nn_durability_service_qospolicy_t *qb = &b->durability_service;
- if (durations_differ (&qa->service_cleanup_delay, &qb->service_cleanup_delay) ||
- histories_differ (&qa->history, &qb->history) ||
- resource_limits_differ (&qa->resource_limits, &qb->resource_limits))
- delta |= QP_DURABILITY_SERVICE;
- }
- if (check & QP_DEADLINE) {
- if (durations_differ (&a->deadline.deadline, &b->deadline.deadline))
- delta |= QP_DEADLINE;
- }
- if (check & QP_LATENCY_BUDGET) {
- if (durations_differ (&a->latency_budget.duration, &b->latency_budget.duration))
- delta |= QP_LATENCY_BUDGET;
- }
- if (check & QP_LIVELINESS) {
- if (a->liveliness.kind != b->liveliness.kind ||
- durations_differ (&a->liveliness.lease_duration, &b->liveliness.lease_duration))
- delta |= QP_LIVELINESS;
- }
- if (check & QP_RELIABILITY) {
- if (a->reliability.kind != b->reliability.kind ||
- durations_differ (&a->reliability.max_blocking_time, &b->reliability.max_blocking_time))
- delta |= QP_RELIABILITY;
- }
- if (check & QP_DESTINATION_ORDER) {
- if (a->destination_order.kind != b->destination_order.kind)
- delta |= QP_DESTINATION_ORDER;
- }
- if (check & QP_HISTORY) {
- if (histories_differ (&a->history, &b->history))
- delta |= QP_HISTORY;
- }
- if (check & QP_RESOURCE_LIMITS) {
- if (resource_limits_differ (&a->resource_limits, &b->resource_limits))
- delta |= QP_RESOURCE_LIMITS;
- }
- if (check & QP_TRANSPORT_PRIORITY) {
- if (a->transport_priority.value != b->transport_priority.value)
- delta |= QP_TRANSPORT_PRIORITY;
- }
- if (check & QP_LIFESPAN) {
- if (durations_differ (&a->lifespan.duration, &b->lifespan.duration))
- delta |= QP_LIFESPAN;
- }
- if (check & QP_USER_DATA) {
- if (octetseqs_differ (&a->user_data, &b->user_data))
- delta |= QP_USER_DATA;
- }
- if (check & QP_OWNERSHIP) {
- if (a->ownership.kind != b->ownership.kind)
- delta |= QP_OWNERSHIP;
- }
- if (check & QP_OWNERSHIP_STRENGTH) {
- if (a->ownership_strength.value != b->ownership_strength.value)
- delta |= QP_OWNERSHIP_STRENGTH;
- }
- if (check & QP_TIME_BASED_FILTER) {
- if (durations_differ (&a->time_based_filter.minimum_separation, &b->time_based_filter.minimum_separation))
- delta |= QP_TIME_BASED_FILTER;
- }
- if (check & QP_PRISMTECH_READER_DATA_LIFECYCLE) {
- if (durations_differ (&a->reader_data_lifecycle.autopurge_disposed_samples_delay,
- &b->reader_data_lifecycle.autopurge_disposed_samples_delay) ||
- durations_differ (&a->reader_data_lifecycle.autopurge_nowriter_samples_delay,
- &b->reader_data_lifecycle.autopurge_nowriter_samples_delay) ||
- a->reader_data_lifecycle.autopurge_dispose_all != b->reader_data_lifecycle.autopurge_dispose_all ||
- a->reader_data_lifecycle.enable_invalid_samples != b->reader_data_lifecycle.enable_invalid_samples ||
- a->reader_data_lifecycle.invalid_sample_visibility != b->reader_data_lifecycle.invalid_sample_visibility)
- delta |= QP_PRISMTECH_READER_DATA_LIFECYCLE;
- }
- if (check & QP_PRISMTECH_WRITER_DATA_LIFECYCLE) {
- if (a->writer_data_lifecycle.autodispose_unregistered_instances !=
- b->writer_data_lifecycle.autodispose_unregistered_instances ||
- durations_differ (&a->writer_data_lifecycle.autopurge_suspended_samples_delay,
- &b->writer_data_lifecycle.autopurge_suspended_samples_delay) ||
- durations_differ (&a->writer_data_lifecycle.autounregister_instance_delay,
- &b->writer_data_lifecycle.autounregister_instance_delay))
- delta |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE;
- }
- if (check & QP_PRISMTECH_RELAXED_QOS_MATCHING) {
- if (a->relaxed_qos_matching.value !=
- b->relaxed_qos_matching.value)
- delta |= QP_PRISMTECH_RELAXED_QOS_MATCHING;
- }
- if (check & QP_PRISMTECH_READER_LIFESPAN) {
- /* Note: the conjunction need not test both a & b for having use_lifespan set */
- if (a->reader_lifespan.use_lifespan != b->reader_lifespan.use_lifespan ||
- (a->reader_lifespan.use_lifespan && b->reader_lifespan.use_lifespan &&
- durations_differ (&a->reader_lifespan.duration, &b->reader_lifespan.duration)))
- delta |= QP_PRISMTECH_READER_LIFESPAN;
- }
- if (check & QP_PRISMTECH_SUBSCRIPTION_KEYS) {
- /* Note: the conjunction need not test both a & b for having use_lifespan set */
- if (a->subscription_keys.use_key_list != b->subscription_keys.use_key_list ||
- (a->subscription_keys.use_key_list && b->subscription_keys.use_key_list &&
- stringseqs_differ (&a->subscription_keys.key_list, &b->subscription_keys.key_list)))
- delta |= QP_PRISMTECH_SUBSCRIPTION_KEYS;
- }
- if (check & QP_PRISMTECH_ENTITY_FACTORY) {
- if (a->entity_factory.autoenable_created_entities !=
- b->entity_factory.autoenable_created_entities)
- delta |= QP_PRISMTECH_ENTITY_FACTORY;
- }
- if (check & QP_PRISMTECH_SYNCHRONOUS_ENDPOINT) {
- if (a->synchronous_endpoint.value != b->synchronous_endpoint.value)
- delta |= QP_PRISMTECH_SYNCHRONOUS_ENDPOINT;
- }
- if (check & QP_RTI_TYPECODE) {
- if (octetseqs_differ (&a->rti_typecode, &b->rti_typecode))
- delta |= QP_RTI_TYPECODE;
- }
- if (check & QP_CYCLONE_IGNORELOCAL) {
- if (a->ignorelocal.value != b->ignorelocal.value)
- delta |= QP_CYCLONE_IGNORELOCAL;
- }
- return delta;
-}
-
/*************************/
-void nn_xqos_addtomsg (struct nn_xmsg *m, const nn_xqos_t *xqos, uint64_t wanted)
+void nn_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, uint64_t wanted)
{
- /* Returns new nn_xmsg pointer (currently, reallocs may happen) */
-
- uint64_t w = xqos->present & wanted;
- char *tmp;
-#define SIMPLE(name_, field_) \
- do { \
- if (w & QP_##name_) { \
- tmp = nn_xmsg_addpar (m, PID_##name_, sizeof (xqos->field_)); \
- *((nn_##field_##_qospolicy_t *) tmp) = xqos->field_; \
- } \
- } while (0)
-#define FUNC_BY_REF(name_, field_, func_) \
- do { \
- if (w & QP_##name_) { \
- nn_xmsg_addpar_##func_ (m, PID_##name_, &xqos->field_); \
- } \
- } while (0)
-#define FUNC_BY_VAL(name_, field_, func_) \
- do { \
- if (w & QP_##name_) { \
- nn_xmsg_addpar_##func_ (m, PID_##name_, xqos->field_); \
- } \
- } while (0)
-
- FUNC_BY_VAL (TOPIC_NAME, topic_name, string);
- FUNC_BY_VAL (TYPE_NAME, type_name, string);
- SIMPLE (PRESENTATION, presentation);
- FUNC_BY_REF (PARTITION, partition, stringseq);
- FUNC_BY_REF (GROUP_DATA, group_data, octetseq);
- FUNC_BY_REF (TOPIC_DATA, topic_data, octetseq);
- SIMPLE (DURABILITY, durability);
- SIMPLE (DURABILITY_SERVICE, durability_service);
- SIMPLE (DEADLINE, deadline);
- SIMPLE (LATENCY_BUDGET, latency_budget);
- SIMPLE (LIVELINESS, liveliness);
- FUNC_BY_REF (RELIABILITY, reliability, reliability);
- SIMPLE (DESTINATION_ORDER, destination_order);
- SIMPLE (HISTORY, history);
- SIMPLE (RESOURCE_LIMITS, resource_limits);
- SIMPLE (TRANSPORT_PRIORITY, transport_priority);
- SIMPLE (LIFESPAN, lifespan);
- FUNC_BY_REF (USER_DATA, user_data, octetseq);
- SIMPLE (OWNERSHIP, ownership);
- SIMPLE (OWNERSHIP_STRENGTH, ownership_strength);
- SIMPLE (TIME_BASED_FILTER, time_based_filter);
- SIMPLE (PRISMTECH_READER_DATA_LIFECYCLE, reader_data_lifecycle);
- SIMPLE (PRISMTECH_WRITER_DATA_LIFECYCLE, writer_data_lifecycle);
- SIMPLE (PRISMTECH_RELAXED_QOS_MATCHING, relaxed_qos_matching);
- SIMPLE (PRISMTECH_READER_LIFESPAN, reader_lifespan);
- FUNC_BY_REF (PRISMTECH_SUBSCRIPTION_KEYS, subscription_keys, subscription_keys);
- SIMPLE (PRISMTECH_ENTITY_FACTORY, entity_factory);
- SIMPLE (PRISMTECH_SYNCHRONOUS_ENDPOINT, synchronous_endpoint);
- FUNC_BY_REF (RTI_TYPECODE, rti_typecode, octetseq);
- /* CYCLONE_IGNORELOCAL is not visible on the wire */
-#undef FUNC_BY_REF
-#undef FUNC_BY_VAL
-#undef SIMPLE
-}
-
-static void add_locators (struct nn_xmsg *m, uint64_t present, uint64_t flag, const nn_locators_t *ls, unsigned pid)
-{
- const struct nn_locators_one *l;
- if (present & flag)
- {
- for (l = ls->first; l != NULL; l = l->next)
- {
- char *tmp = nn_xmsg_addpar (m, pid, sizeof (nn_locator_t));
- memcpy (tmp, &l->loc, sizeof (nn_locator_t));
- }
- }
+ plist_or_xqos_addtomsg (m, xqos, offsetof (struct nn_plist, qos), 0, wanted);
}
void nn_plist_addtomsg (struct nn_xmsg *m, const nn_plist_t *ps, uint64_t pwanted, uint64_t qwanted)
{
- /* Returns new nn_xmsg pointer (currently, reallocs may happen), or NULL
- on out-of-memory. (In which case the original nn_xmsg is freed, cos
- that is then required anyway */
- uint64_t w = ps->present & pwanted;
- char *tmp;
-#define SIMPLE_TYPE(name_, field_, type_) \
- do { \
- if (w & PP_##name_) { \
- tmp = nn_xmsg_addpar (m, PID_##name_, sizeof (ps->field_)); \
- *((type_ *) tmp) = ps->field_; \
- } \
- } while (0)
-#define FUNC_BY_VAL(name_, field_, func_) \
- do { \
- if (w & PP_##name_) { \
- nn_xmsg_addpar_##func_ (m, PID_##name_, ps->field_); \
- } \
- } while (0)
-#define FUNC_BY_REF(name_, field_, func_) \
- do { \
- if (w & PP_##name_) { \
- nn_xmsg_addpar_##func_ (m, PID_##name_, &ps->field_); \
- } \
- } while (0)
-
- nn_xqos_addtomsg (m, &ps->qos, qwanted);
- SIMPLE_TYPE (PROTOCOL_VERSION, protocol_version, nn_protocol_version_t);
- SIMPLE_TYPE (VENDORID, vendorid, nn_vendorid_t);
-
- add_locators (m, ps->present, PP_UNICAST_LOCATOR, &ps->unicast_locators, PID_UNICAST_LOCATOR);
- add_locators (m, ps->present, PP_MULTICAST_LOCATOR, &ps->multicast_locators, PID_MULTICAST_LOCATOR);
- add_locators (m, ps->present, PP_DEFAULT_UNICAST_LOCATOR, &ps->default_unicast_locators, PID_DEFAULT_UNICAST_LOCATOR);
- add_locators (m, ps->present, PP_DEFAULT_MULTICAST_LOCATOR, &ps->default_multicast_locators, PID_DEFAULT_MULTICAST_LOCATOR);
- add_locators (m, ps->present, PP_METATRAFFIC_UNICAST_LOCATOR, &ps->metatraffic_unicast_locators, PID_METATRAFFIC_UNICAST_LOCATOR);
- add_locators (m, ps->present, PP_METATRAFFIC_MULTICAST_LOCATOR, &ps->metatraffic_multicast_locators, PID_METATRAFFIC_MULTICAST_LOCATOR);
-
- SIMPLE_TYPE (EXPECTS_INLINE_QOS, expects_inline_qos, unsigned char);
- SIMPLE_TYPE (PARTICIPANT_LEASE_DURATION, participant_lease_duration, nn_duration_t);
- FUNC_BY_REF (PARTICIPANT_GUID, participant_guid, guid);
- SIMPLE_TYPE (BUILTIN_ENDPOINT_SET, builtin_endpoint_set, unsigned);
- SIMPLE_TYPE (KEYHASH, keyhash, nn_keyhash_t);
- if (w & PP_STATUSINFO)
- nn_xmsg_addpar_statusinfo (m, ps->statusinfo);
- SIMPLE_TYPE (COHERENT_SET, coherent_set_seqno, nn_sequence_number_t);
- if (! NN_PEDANTIC_P)
- FUNC_BY_REF (ENDPOINT_GUID, endpoint_guid, guid);
- else
- {
- if (w & PP_ENDPOINT_GUID)
- {
- nn_xmsg_addpar_guid (m, PID_PRISMTECH_ENDPOINT_GUID, &ps->endpoint_guid);
- }
- }
- FUNC_BY_REF (GROUP_GUID, group_guid, guid);
- SIMPLE_TYPE (PRISMTECH_BUILTIN_ENDPOINT_SET, prismtech_builtin_endpoint_set, unsigned);
- FUNC_BY_REF (PRISMTECH_PARTICIPANT_VERSION_INFO, prismtech_participant_version_info, parvinfo);
- FUNC_BY_VAL (ENTITY_NAME, entity_name, string);
- FUNC_BY_VAL (PRISMTECH_NODE_NAME, node_name, string);
- FUNC_BY_VAL (PRISMTECH_EXEC_NAME, exec_name, string);
- SIMPLE_TYPE (PRISMTECH_PROCESS_ID, process_id, unsigned);
- SIMPLE_TYPE (PRISMTECH_SERVICE_TYPE, service_type, unsigned);
- FUNC_BY_VAL (PRISMTECH_TYPE_DESCRIPTION, type_description, string);
- FUNC_BY_REF (PRISMTECH_EOTINFO, eotinfo, eotinfo);
-#ifdef DDSI_INCLUDE_SSM
- SIMPLE_TYPE (READER_FAVOURS_SSM, reader_favours_ssm, nn_reader_favours_ssm_t);
-#endif
-#undef FUNC_BY_REF
-#undef FUNC_BY_VAL
-#undef SIMPLE
+ plist_or_xqos_addtomsg (m, ps, 0, pwanted, qwanted);
}
/*************************/
-static unsigned isprint_runlen (unsigned n, const unsigned char *xs)
+static uint32_t isprint_runlen (uint32_t n, const unsigned char *xs)
{
- unsigned m;
- for (m = 0; m < n && xs[m] != '"' && isprint (xs[m]); m++)
+ uint32_t m;
+ for (m = 0; m < n && xs[m] != '"' && isprint (xs[m]) && xs[m] < 127; m++)
;
return m;
}
-static void log_octetseq (uint32_t cat, unsigned n, const unsigned char *xs)
+static void log_octetseq (uint32_t cat, const struct ddsrt_log_cfg *logcfg, uint32_t n, const unsigned char *xs)
{
- unsigned i = 0;
+ uint32_t i = 0;
while (i < n)
{
- unsigned m = isprint_runlen(n - i, xs);
- if (m >= 4)
+ uint32_t m = isprint_runlen (n - i, xs);
+ if (m >= 4 || (i == 0 && m == n))
{
- DDS_LOG(cat, "%s\"%*.*s\"", i == 0 ? "" : ",", m, m, xs);
+ DDS_CLOG (cat, logcfg, "%s\"%*.*s\"", i == 0 ? "" : ",", m, m, xs);
xs += m;
i += m;
}
@@ -3387,96 +2688,80 @@ static void log_octetseq (uint32_t cat, unsigned n, const unsigned char *xs)
m = 1;
while (m--)
{
- DDS_LOG(cat, "%s%u", i == 0 ? "" : ",", *xs++);
+ DDS_CLOG (cat, logcfg, "%s%u", i == 0 ? "" : ",", *xs++);
i++;
}
}
}
}
-void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos)
+void nn_log_xqos (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos)
{
uint64_t p = xqos->present;
const char *prefix = "";
-#define LOGB0(fmt_) DDS_LOG(cat, "%s" fmt_, prefix)
-#define LOGB1(fmt_, arg0_) DDS_LOG(cat, "%s" fmt_, prefix, arg0_)
-#define LOGB2(fmt_, arg0_, arg1_) DDS_LOG(cat, "%s" fmt_, prefix, arg0_, arg1_)
-#define LOGB3(fmt_, arg0_, arg1_, arg2_) DDS_LOG(cat, "%s" fmt_, prefix, arg0_, arg1_, arg2_)
-#define LOGB4(fmt_, arg0_, arg1_, arg2_, arg3_) DDS_LOG(cat, "%s" fmt_, prefix, arg0_, arg1_, arg2_, arg3_)
-#define LOGB5(fmt_, arg0_, arg1_, arg2_, arg3_, arg4_) DDS_LOG(cat, "%s" fmt_, prefix, arg0_, arg1_, arg2_, arg3_, arg4_)
+#define LOGB0(fmt_) DDS_CLOG (cat, logcfg, "%s" fmt_, prefix)
+#define LOGB1(fmt_, ...) DDS_CLOG (cat, logcfg, "%s" fmt_, prefix, __VA_ARGS__)
#define DO(name_, body_) do { if (p & QP_##name_) { { body_ } prefix = ","; } } while (0)
-#define FMT_DUR "%d.%09d"
-#define PRINTARG_DUR(d) (d).seconds, (int) ((d).fraction/4.294967296)
+#define FMT_DUR "%"PRId64".%09"PRId32
+#define PRINTARG_DUR(d) ((int64_t) ((d) / 1000000000)), ((int32_t) ((d) % 1000000000))
DO (TOPIC_NAME, { LOGB1 ("topic=%s", xqos->topic_name); });
DO (TYPE_NAME, { LOGB1 ("type=%s", xqos->type_name); });
- DO (PRESENTATION, { LOGB3 ("presentation=%d:%u:%u", xqos->presentation.access_scope, xqos->presentation.coherent_access, xqos->presentation.ordered_access); });
+ DO (PRESENTATION, { LOGB1 ("presentation=%d:%u:%u", xqos->presentation.access_scope, xqos->presentation.coherent_access, xqos->presentation.ordered_access); });
DO (PARTITION, {
- unsigned i;
LOGB0 ("partition={");
- for (i = 0; i < xqos->partition.n; i++) {
- DDS_LOG(cat, "%s%s", (i == 0) ? "" : ",", xqos->partition.strs[i]);
+ for (uint32_t i = 0; i < xqos->partition.n; i++) {
+ DDS_CLOG (cat, logcfg, "%s%s", (i == 0) ? "" : ",", xqos->partition.strs[i]);
}
- DDS_LOG(cat, "}");
+ DDS_CLOG (cat, logcfg, "}");
});
DO (GROUP_DATA, {
LOGB1 ("group_data=%"PRIu32"<", xqos->group_data.length);
- log_octetseq (cat, xqos->group_data.length, xqos->group_data.value);
- DDS_LOG(cat, ">");
+ log_octetseq (cat, logcfg, xqos->group_data.length, xqos->group_data.value);
+ DDS_CLOG (cat, logcfg, ">");
});
DO (TOPIC_DATA, {
LOGB1 ("topic_data=%"PRIu32"<", xqos->topic_data.length);
- log_octetseq (cat, xqos->topic_data.length, xqos->topic_data.value);
- DDS_LOG(cat, ">");
+ log_octetseq (cat, logcfg, xqos->topic_data.length, xqos->topic_data.value);
+ DDS_CLOG(cat, logcfg, ">");
});
DO (DURABILITY, { LOGB1 ("durability=%d", xqos->durability.kind); });
DO (DURABILITY_SERVICE, {
LOGB0 ("durability_service=");
- DDS_LOG(cat, FMT_DUR, PRINTARG_DUR (xqos->durability_service.service_cleanup_delay));
- DDS_LOG(cat, ":{%u:%"PRId32"}", xqos->durability_service.history.kind, xqos->durability_service.history.depth);
- DDS_LOG(cat, ":{%"PRId32":%"PRId32":%"PRId32"}", xqos->durability_service.resource_limits.max_samples, xqos->durability_service.resource_limits.max_instances, xqos->durability_service.resource_limits.max_samples_per_instance);
+ DDS_CLOG(cat, logcfg, FMT_DUR, PRINTARG_DUR (xqos->durability_service.service_cleanup_delay));
+ DDS_CLOG(cat, logcfg, ":{%u:%"PRId32"}", xqos->durability_service.history.kind, xqos->durability_service.history.depth);
+ DDS_CLOG(cat, logcfg, ":{%"PRId32":%"PRId32":%"PRId32"}", xqos->durability_service.resource_limits.max_samples, xqos->durability_service.resource_limits.max_instances, xqos->durability_service.resource_limits.max_samples_per_instance);
});
DO (DEADLINE, { LOGB1 ("deadline="FMT_DUR, PRINTARG_DUR (xqos->deadline.deadline)); });
DO (LATENCY_BUDGET, { LOGB1 ("latency_budget="FMT_DUR, PRINTARG_DUR (xqos->latency_budget.duration)); });
- DO (LIVELINESS, { LOGB2 ("liveliness=%d:"FMT_DUR, xqos->liveliness.kind, PRINTARG_DUR (xqos->liveliness.lease_duration)); });
- DO (RELIABILITY, { LOGB2 ("reliability=%d:"FMT_DUR, xqos->reliability.kind, PRINTARG_DUR (xqos->reliability.max_blocking_time)); });
+ DO (LIVELINESS, { LOGB1 ("liveliness=%d:"FMT_DUR, xqos->liveliness.kind, PRINTARG_DUR (xqos->liveliness.lease_duration)); });
+ DO (RELIABILITY, { LOGB1 ("reliability=%d:"FMT_DUR, xqos->reliability.kind, PRINTARG_DUR (xqos->reliability.max_blocking_time)); });
DO (DESTINATION_ORDER, { LOGB1 ("destination_order=%d", xqos->destination_order.kind); });
- DO (HISTORY, { LOGB2 ("history=%d:%"PRId32, xqos->history.kind, xqos->history.depth); });
- DO (RESOURCE_LIMITS, { LOGB3 ("resource_limits=%"PRId32":%"PRId32":%"PRId32, xqos->resource_limits.max_samples, xqos->resource_limits.max_instances, xqos->resource_limits.max_samples_per_instance); });
+ DO (HISTORY, { LOGB1 ("history=%d:%"PRId32, xqos->history.kind, xqos->history.depth); });
+ DO (RESOURCE_LIMITS, { LOGB1 ("resource_limits=%"PRId32":%"PRId32":%"PRId32, xqos->resource_limits.max_samples, xqos->resource_limits.max_instances, xqos->resource_limits.max_samples_per_instance); });
DO (TRANSPORT_PRIORITY, { LOGB1 ("transport_priority=%"PRId32, xqos->transport_priority.value); });
DO (LIFESPAN, { LOGB1 ("lifespan="FMT_DUR, PRINTARG_DUR (xqos->lifespan.duration)); });
DO (USER_DATA, {
LOGB1 ("user_data=%"PRIu32"<", xqos->user_data.length);
- log_octetseq (cat, xqos->user_data.length, xqos->user_data.value);
- DDS_LOG(cat, ">");
+ log_octetseq (cat, logcfg, xqos->user_data.length, xqos->user_data.value);
+ DDS_CLOG (cat, logcfg, ">");
});
DO (OWNERSHIP, { LOGB1 ("ownership=%d", xqos->ownership.kind); });
DO (OWNERSHIP_STRENGTH, { LOGB1 ("ownership_strength=%"PRId32, xqos->ownership_strength.value); });
DO (TIME_BASED_FILTER, { LOGB1 ("time_based_filter="FMT_DUR, PRINTARG_DUR (xqos->time_based_filter.minimum_separation)); });
- DO (PRISMTECH_READER_DATA_LIFECYCLE, { LOGB5 ("reader_data_lifecycle="FMT_DUR":"FMT_DUR":%u:%u:%d", PRINTARG_DUR (xqos->reader_data_lifecycle.autopurge_nowriter_samples_delay), PRINTARG_DUR (xqos->reader_data_lifecycle.autopurge_disposed_samples_delay), xqos->reader_data_lifecycle.autopurge_dispose_all, xqos->reader_data_lifecycle.enable_invalid_samples, (int) xqos->reader_data_lifecycle.invalid_sample_visibility); });
+ DO (PRISMTECH_READER_DATA_LIFECYCLE, { LOGB1 ("reader_data_lifecycle="FMT_DUR":"FMT_DUR, PRINTARG_DUR (xqos->reader_data_lifecycle.autopurge_nowriter_samples_delay), PRINTARG_DUR (xqos->reader_data_lifecycle.autopurge_disposed_samples_delay)); });
DO (PRISMTECH_WRITER_DATA_LIFECYCLE, {
- LOGB3 ("writer_data_lifecycle={%u,"FMT_DUR","FMT_DUR"}",
- xqos->writer_data_lifecycle.autodispose_unregistered_instances,
- PRINTARG_DUR (xqos->writer_data_lifecycle.autounregister_instance_delay),
- PRINTARG_DUR (xqos->writer_data_lifecycle.autopurge_suspended_samples_delay)); });
- DO (PRISMTECH_RELAXED_QOS_MATCHING, { LOGB1 ("relaxed_qos_matching=%u", xqos->relaxed_qos_matching.value); });
- DO (PRISMTECH_READER_LIFESPAN, { LOGB2 ("reader_lifespan={%u,"FMT_DUR"}", xqos->reader_lifespan.use_lifespan, PRINTARG_DUR (xqos->reader_lifespan.duration)); });
+ LOGB1 ("writer_data_lifecycle={%u}", xqos->writer_data_lifecycle.autodispose_unregistered_instances); });
+ DO (PRISMTECH_READER_LIFESPAN, { LOGB1 ("reader_lifespan={%u,"FMT_DUR"}", xqos->reader_lifespan.use_lifespan, PRINTARG_DUR (xqos->reader_lifespan.duration)); });
DO (PRISMTECH_SUBSCRIPTION_KEYS, {
- unsigned i;
LOGB1 ("subscription_keys={%u,{", xqos->subscription_keys.use_key_list);
- for (i = 0; i < xqos->subscription_keys.key_list.n; i++) {
- DDS_LOG(cat, "%s%s", (i == 0) ? "" : ",", xqos->subscription_keys.key_list.strs[i]);
+ for (uint32_t i = 0; i < xqos->subscription_keys.key_list.n; i++) {
+ DDS_CLOG (cat, logcfg, "%s%s", (i == 0) ? "" : ",", xqos->subscription_keys.key_list.strs[i]);
}
- DDS_LOG(cat, "}}");
+ DDS_CLOG (cat, logcfg, "}}");
});
DO (PRISMTECH_ENTITY_FACTORY, { LOGB1 ("entity_factory=%u", xqos->entity_factory.autoenable_created_entities); });
- DO (PRISMTECH_SYNCHRONOUS_ENDPOINT, { LOGB1 ("synchronous_endpoint=%u", xqos->synchronous_endpoint.value); });
- DO (RTI_TYPECODE, {
- LOGB1 ("rti_typecode=%"PRIu32"<", xqos->rti_typecode.length);
- log_octetseq (cat, xqos->rti_typecode.length, xqos->rti_typecode.value);
- DDS_LOG(cat, ">");
- });
DO (CYCLONE_IGNORELOCAL, { LOGB1 ("ignorelocal=%u", xqos->ignorelocal.value); });
#undef PRINTARG_DUR
diff --git a/src/core/ddsi/src/q_qosmatch.c b/src/core/ddsi/src/q_qosmatch.c
index abac093..721a010 100644
--- a/src/core/ddsi/src/q_qosmatch.c
+++ b/src/core/ddsi/src/q_qosmatch.c
@@ -17,7 +17,7 @@
#include "dds/ddsi/q_misc.h"
#include "dds/ddsi/q_qosmatch.h"
-int is_wildcard_partition (const char *str)
+static int is_wildcard_partition (const char *str)
{
return strchr (str, '*') || strchr (str, '?');
}
@@ -35,18 +35,17 @@ static int partition_patmatch_p (const char *pat, const char *name)
return ddsi2_patmatch (pat, name);
}
-static int partitions_match_default (const nn_xqos_t *x)
+static int partitions_match_default (const dds_qos_t *x)
{
- unsigned i;
if (!(x->present & QP_PARTITION) || x->partition.n == 0)
return 1;
- for (i = 0; i < x->partition.n; i++)
+ for (uint32_t i = 0; i < x->partition.n; i++)
if (partition_patmatch_p (x->partition.strs[i], ""))
return 1;
return 0;
}
-int partitions_match_p (const nn_xqos_t *a, const nn_xqos_t *b)
+int partitions_match_p (const dds_qos_t *a, const dds_qos_t *b)
{
if (!(a->present & QP_PARTITION) || a->partition.n == 0)
return partitions_match_default (b);
@@ -54,9 +53,8 @@ int partitions_match_p (const nn_xqos_t *a, const nn_xqos_t *b)
return partitions_match_default (a);
else
{
- unsigned i, j;
- for (i = 0; i < a->partition.n; i++)
- for (j = 0; j < b->partition.n; j++)
+ for (uint32_t i = 0; i < a->partition.n; i++)
+ for (uint32_t j = 0; j < b->partition.n; j++)
{
if (partition_patmatch_p (a->partition.strs[i], b->partition.strs[j]) ||
partition_patmatch_p (b->partition.strs[j], a->partition.strs[i]))
@@ -66,157 +64,73 @@ int partitions_match_p (const nn_xqos_t *a, const nn_xqos_t *b)
}
}
-int partition_match_based_on_wildcard_in_left_operand (const nn_xqos_t *a, const nn_xqos_t *b, const char **realname)
-{
- assert (partitions_match_p (a, b));
- if (!(a->present & QP_PARTITION) || a->partition.n == 0)
- {
- return 0;
- }
- else if (!(b->present & QP_PARTITION) || b->partition.n == 0)
- {
- /* Either A explicitly includes the default partition, or it is a
- wildcard that matches it */
- unsigned i;
- for (i = 0; i < a->partition.n; i++)
- if (strcmp (a->partition.strs[i], "") == 0)
- return 0;
- *realname = "";
- return 1;
- }
- else
- {
- unsigned i, j;
- int maybe_yes = 0;
- for (i = 0; i < a->partition.n; i++)
- for (j = 0; j < b->partition.n; j++)
- {
- if (partition_patmatch_p (a->partition.strs[i], b->partition.strs[j]))
- {
- if (!is_wildcard_partition (a->partition.strs[i]))
- return 0;
- else
- {
- *realname = b->partition.strs[j];
- maybe_yes = 1;
- }
- }
- }
- return maybe_yes;
- }
-}
-
-static int ddsi_duration_is_lt (nn_duration_t a0, nn_duration_t b0)
-{
- /* inf counts as <= inf */
- const int64_t a = nn_from_ddsi_duration (a0);
- const int64_t b = nn_from_ddsi_duration (b0);
- if (a == T_NEVER)
- return 0;
- else if (b == T_NEVER)
- return 1;
- else
- return a < b;
-}
-
-/* Duplicates of DDS policy ids to avoid inclusion of actual definitions */
-
-#define Q_INVALID_QOS_POLICY_ID 0
-#define Q_USERDATA_QOS_POLICY_ID 1
-#define Q_DURABILITY_QOS_POLICY_ID 2
-#define Q_PRESENTATION_QOS_POLICY_ID 3
-#define Q_DEADLINE_QOS_POLICY_ID 4
-#define Q_LATENCYBUDGET_QOS_POLICY_ID 5
-#define Q_OWNERSHIP_QOS_POLICY_ID 6
-#define Q_OWNERSHIPSTRENGTH_QOS_POLICY_ID 7
-#define Q_LIVELINESS_QOS_POLICY_ID 8
-#define Q_TIMEBASEDFILTER_QOS_POLICY_ID 9
-#define Q_PARTITION_QOS_POLICY_ID 10
-#define Q_RELIABILITY_QOS_POLICY_ID 11
-#define Q_DESTINATIONORDER_QOS_POLICY_ID 12
-#define Q_HISTORY_QOS_POLICY_ID 13
-#define Q_RESOURCELIMITS_QOS_POLICY_ID 14
-#define Q_ENTITYFACTORY_QOS_POLICY_ID 15
-#define Q_WRITERDATALIFECYCLE_QOS_POLICY_ID 16
-#define Q_READERDATALIFECYCLE_QOS_POLICY_ID 17
-#define Q_TOPICDATA_QOS_POLICY_ID 18
-#define Q_GROUPDATA_QOS_POLICY_ID 19
-#define Q_TRANSPORTPRIORITY_QOS_POLICY_ID 20
-#define Q_LIFESPAN_QOS_POLICY_ID 21
-#define Q_DURABILITYSERVICE_QOS_POLICY_ID 22
-
-int32_t qos_match_p (const nn_xqos_t *rd, const nn_xqos_t *wr)
+bool qos_match_mask_p (const dds_qos_t *rd, const dds_qos_t *wr, uint64_t mask, dds_qos_policy_id_t *reason)
{
#ifndef NDEBUG
- unsigned musthave = (QP_RXO_MASK | QP_PARTITION | QP_TOPIC_NAME | QP_TYPE_NAME);
+ unsigned musthave = (QP_RXO_MASK | QP_PARTITION | QP_TOPIC_NAME | QP_TYPE_NAME) & mask;
assert ((rd->present & musthave) == musthave);
assert ((wr->present & musthave) == musthave);
#endif
- if (strcmp (rd->topic_name, wr->topic_name) != 0)
- {
- return Q_INVALID_QOS_POLICY_ID;
+ mask &= rd->present & wr->present;
+ *reason = DDS_INVALID_QOS_POLICY_ID;
+ if ((mask & QP_TOPIC_NAME) && strcmp (rd->topic_name, wr->topic_name) != 0)
+ return false;
+ if ((mask & QP_TYPE_NAME) && strcmp (rd->type_name, wr->type_name) != 0)
+ return false;
+
+ if ((mask & QP_RELIABILITY) && rd->reliability.kind > wr->reliability.kind) {
+ *reason = DDS_RELIABILITY_QOS_POLICY_ID;
+ return false;
}
- if (strcmp (rd->type_name, wr->type_name) != 0)
- {
- return Q_INVALID_QOS_POLICY_ID;
+ if ((mask & QP_DURABILITY) && rd->durability.kind > wr->durability.kind) {
+ *reason = DDS_DURABILITY_QOS_POLICY_ID;
+ return false;
}
- if (rd->relaxed_qos_matching.value || wr->relaxed_qos_matching.value)
- {
- if (rd->reliability.kind != wr->reliability.kind)
- {
- return Q_RELIABILITY_QOS_POLICY_ID;
- }
+ if ((mask & QP_PRESENTATION) && rd->presentation.access_scope > wr->presentation.access_scope) {
+ *reason = DDS_PRESENTATION_QOS_POLICY_ID;
+ return false;
}
- else
- {
- if (rd->reliability.kind > wr->reliability.kind)
- {
- return Q_RELIABILITY_QOS_POLICY_ID;
- }
- if (rd->durability.kind > wr->durability.kind)
- {
- return Q_DURABILITY_QOS_POLICY_ID;
- }
- if (rd->presentation.access_scope > wr->presentation.access_scope)
- {
- return Q_PRESENTATION_QOS_POLICY_ID;
- }
- if (rd->presentation.coherent_access > wr->presentation.coherent_access)
- {
- return Q_PRESENTATION_QOS_POLICY_ID;
- }
- if (rd->presentation.ordered_access > wr->presentation.ordered_access)
- {
- return Q_PRESENTATION_QOS_POLICY_ID;
- }
- if (ddsi_duration_is_lt (rd->deadline.deadline, wr->deadline.deadline))
- {
- return Q_DEADLINE_QOS_POLICY_ID;
- }
- if (ddsi_duration_is_lt (rd->latency_budget.duration, wr->latency_budget.duration))
- {
- return Q_LATENCYBUDGET_QOS_POLICY_ID;
- }
- if (rd->ownership.kind != wr->ownership.kind)
- {
- return Q_OWNERSHIP_QOS_POLICY_ID;
- }
- if (rd->liveliness.kind > wr->liveliness.kind)
- {
- return Q_LIVELINESS_QOS_POLICY_ID;
- }
- if (ddsi_duration_is_lt (rd->liveliness.lease_duration, wr->liveliness.lease_duration))
- {
- return Q_LIVELINESS_QOS_POLICY_ID;
- }
- if (rd->destination_order.kind > wr->destination_order.kind)
- {
- return Q_DESTINATIONORDER_QOS_POLICY_ID;
- }
+ if ((mask & QP_PRESENTATION) && rd->presentation.coherent_access > wr->presentation.coherent_access) {
+ *reason = DDS_PRESENTATION_QOS_POLICY_ID;
+ return false;
}
- if (!partitions_match_p (rd, wr))
- {
- return Q_PARTITION_QOS_POLICY_ID;
+ if ((mask & QP_PRESENTATION) && rd->presentation.ordered_access > wr->presentation.ordered_access) {
+ *reason = DDS_PRESENTATION_QOS_POLICY_ID;
+ return false;
}
- return -1;
+ if ((mask & QP_DEADLINE) && rd->deadline.deadline < wr->deadline.deadline) {
+ *reason = DDS_DEADLINE_QOS_POLICY_ID;
+ return false;
+ }
+ if ((mask & QP_LATENCY_BUDGET) && rd->latency_budget.duration < wr->latency_budget.duration) {
+ *reason = DDS_LATENCYBUDGET_QOS_POLICY_ID;
+ return false;
+ }
+ if ((mask & QP_OWNERSHIP) && rd->ownership.kind != wr->ownership.kind) {
+ *reason = DDS_OWNERSHIP_QOS_POLICY_ID;
+ return false;
+ }
+ if ((mask & QP_LIVELINESS) && rd->liveliness.kind > wr->liveliness.kind) {
+ *reason = DDS_LIVELINESS_QOS_POLICY_ID;
+ return false;
+ }
+ if ((mask & QP_LIVELINESS) && rd->liveliness.lease_duration < wr->liveliness.lease_duration) {
+ *reason = DDS_LIVELINESS_QOS_POLICY_ID;
+ return false;
+ }
+ if ((mask & QP_DESTINATION_ORDER) && rd->destination_order.kind > wr->destination_order.kind) {
+ *reason = DDS_DESTINATIONORDER_QOS_POLICY_ID;
+ return false;
+ }
+ if ((mask & QP_PARTITION) && !partitions_match_p (rd, wr)) {
+ *reason = DDS_PARTITION_QOS_POLICY_ID;
+ return false;
+ }
+ return true;
+}
+
+bool qos_match_p (const dds_qos_t *rd, const dds_qos_t *wr, dds_qos_policy_id_t *reason)
+{
+ dds_qos_policy_id_t dummy;
+ return qos_match_mask_p (rd, wr, ~(uint64_t)0, reason ? reason : &dummy);
}
diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c
index a45d4e0..46578cc 100644
--- a/src/core/ddsi/src/q_radmin.c
+++ b/src/core/ddsi/src/q_radmin.c
@@ -284,6 +284,8 @@ struct nn_rbufpool {
struct nn_rbuf *current;
uint32_t rbuf_size;
uint32_t max_rmsg_size;
+ const struct ddsrt_log_cfg *logcfg;
+ bool trace;
#ifndef NDEBUG
/* Thread that owns this pool, so we can check that no other thread
is calling functions only the owner may use. */
@@ -291,9 +293,16 @@ struct nn_rbufpool {
#endif
};
-static struct nn_rbuf *nn_rbuf_alloc_new (struct nn_rbufpool *rbufpool);
+static struct nn_rbuf *nn_rbuf_alloc_new (struct nn_rbufpool *rbp);
static void nn_rbuf_release (struct nn_rbuf *rbuf);
+#define TRACE_CFG(obj, logcfg, ...) ((obj)->trace ? (void) DDS_CLOG (DDS_LC_RADMIN, (logcfg), __VA_ARGS__) : (void) 0)
+#define TRACE(obj, ...) TRACE_CFG ((obj), (obj)->logcfg, __VA_ARGS__)
+#define RBPTRACE(...) TRACE_CFG (rbp, rbp->logcfg, __VA_ARGS__)
+#define RBUFTRACE(...) TRACE_CFG (rbuf, rbuf->rbufpool->logcfg, __VA_ARGS__)
+#define RMSGTRACE(...) TRACE_CFG (rmsg, rmsg->chunk.rbuf->rbufpool->logcfg, __VA_ARGS__)
+#define RDATATRACE(rdata, ...) TRACE_CFG ((rdata)->rmsg, (rdata)->rmsg->chunk.rbuf->rbufpool->logcfg, __VA_ARGS__)
+
static uint32_t align8uint32 (uint32_t x)
{
return (x + 7u) & (uint32_t)-8;
@@ -320,12 +329,12 @@ static uint32_t max_rmsg_size_w_hdr (uint32_t max_rmsg_size)
allocate for the worst case, and may waste a few bytes here or
there. */
return
- max_uint32 ((uint32_t) offsetof (struct nn_rmsg, chunk.u.payload),
- (uint32_t) offsetof (struct nn_rmsg_chunk, u.payload))
+ max_uint32 ((uint32_t) (offsetof (struct nn_rmsg, chunk) + sizeof (struct nn_rmsg_chunk)),
+ (uint32_t) sizeof (struct nn_rmsg_chunk))
+ max_rmsg_size;
}
-struct nn_rbufpool *nn_rbufpool_new (uint32_t rbuf_size, uint32_t max_rmsg_size)
+struct nn_rbufpool *nn_rbufpool_new (const struct ddsrt_log_cfg *logcfg, uint32_t rbuf_size, uint32_t max_rmsg_size)
{
struct nn_rbufpool *rbp;
@@ -348,6 +357,8 @@ struct nn_rbufpool *nn_rbufpool_new (uint32_t rbuf_size, uint32_t max_rmsg_size)
rbp->rbuf_size = rbuf_size;
rbp->max_rmsg_size = max_rmsg_size;
+ rbp->logcfg = logcfg;
+ rbp->trace = (logcfg->c.mask & DDS_LC_RADMIN) != 0;
#if USE_VALGRIND
VALGRIND_CREATE_MEMPOOL (rbp, 0, 0);
@@ -398,6 +409,7 @@ struct nn_rbuf {
uint32_t size;
uint32_t max_rmsg_size;
struct nn_rbufpool *rbufpool;
+ bool trace;
/* Allocating sequentially, releasing in random order, not bothering
to reuse memory as soon as it becomes available again. I think
@@ -405,48 +417,49 @@ struct nn_rbuf {
approach. Changes would be confined rmsg_new and rmsg_free. */
unsigned char *freeptr;
+ /* to ensure reasonable alignment of raw[] */
union {
- /* raw data array, nn_rbuf::size bytes long in reality */
- unsigned char raw[1];
-
- /* to ensure reasonable alignment of raw[] */
int64_t l;
double d;
void *p;
} u;
+
+ /* raw data array, nn_rbuf::size bytes long in reality */
+ unsigned char raw[];
};
-static struct nn_rbuf *nn_rbuf_alloc_new (struct nn_rbufpool *rbufpool)
+static struct nn_rbuf *nn_rbuf_alloc_new (struct nn_rbufpool *rbp)
{
struct nn_rbuf *rb;
- ASSERT_RBUFPOOL_OWNER (rbufpool);
+ ASSERT_RBUFPOOL_OWNER (rbp);
- if ((rb = ddsrt_malloc (offsetof (struct nn_rbuf, u.raw) + rbufpool->rbuf_size)) == NULL)
+ if ((rb = ddsrt_malloc (sizeof (struct nn_rbuf) + rbp->rbuf_size)) == NULL)
return NULL;
#if USE_VALGRIND
- VALGRIND_MAKE_MEM_NOACCESS (rb->u.raw, rbufpool->rbuf_size);
+ VALGRIND_MAKE_MEM_NOACCESS (rb->raw, rbp->rbuf_size);
#endif
- rb->rbufpool = rbufpool;
+ rb->rbufpool = rbp;
ddsrt_atomic_st32 (&rb->n_live_rmsg_chunks, 1);
- rb->size = rbufpool->rbuf_size;
- rb->max_rmsg_size = rbufpool->max_rmsg_size;
- rb->freeptr = rb->u.raw;
- DDS_LOG(DDS_LC_RADMIN, "rbuf_alloc_new(%p) = %p\n", (void *) rbufpool, (void *) rb);
+ rb->size = rbp->rbuf_size;
+ rb->max_rmsg_size = rbp->max_rmsg_size;
+ rb->freeptr = rb->raw;
+ rb->trace = rbp->trace;
+ RBPTRACE ("rbuf_alloc_new(%p) = %p\n", (void *) rbp, (void *) rb);
return rb;
}
-static struct nn_rbuf *nn_rbuf_new (struct nn_rbufpool *rbufpool)
+static struct nn_rbuf *nn_rbuf_new (struct nn_rbufpool *rbp)
{
struct nn_rbuf *rb;
- assert (rbufpool->current);
- ASSERT_RBUFPOOL_OWNER (rbufpool);
- if ((rb = nn_rbuf_alloc_new (rbufpool)) != NULL)
+ assert (rbp->current);
+ ASSERT_RBUFPOOL_OWNER (rbp);
+ if ((rb = nn_rbuf_alloc_new (rbp)) != NULL)
{
- ddsrt_mutex_lock (&rbufpool->lock);
- nn_rbuf_release (rbufpool->current);
- rbufpool->current = rb;
- ddsrt_mutex_unlock (&rbufpool->lock);
+ ddsrt_mutex_lock (&rbp->lock);
+ nn_rbuf_release (rbp->current);
+ rbp->current = rb;
+ ddsrt_mutex_unlock (&rbp->lock);
}
return rb;
}
@@ -454,10 +467,10 @@ static struct nn_rbuf *nn_rbuf_new (struct nn_rbufpool *rbufpool)
static void nn_rbuf_release (struct nn_rbuf *rbuf)
{
struct nn_rbufpool *rbp = rbuf->rbufpool;
- DDS_LOG(DDS_LC_RADMIN, "rbuf_release(%p) pool %p current %p\n", (void *) rbuf, (void *) rbp, (void *) rbp->current);
+ RBPTRACE ("rbuf_release(%p) pool %p current %p\n", (void *) rbuf, (void *) rbp, (void *) rbp->current);
if (ddsrt_atomic_dec32_ov (&rbuf->n_live_rmsg_chunks) == 1)
{
- DDS_LOG(DDS_LC_RADMIN, "rbuf_release(%p) free\n", (void *) rbuf);
+ RBPTRACE ("rbuf_release(%p) free\n", (void *) rbuf);
ddsrt_free (rbuf);
}
}
@@ -479,31 +492,31 @@ static void nn_rbuf_release (struct nn_rbuf *rbuf)
#define ASSERT_RMSG_UNCOMMITTED(rmsg) ((void) 0)
#endif
-static void *nn_rbuf_alloc (struct nn_rbufpool *rbufpool)
+static void *nn_rbuf_alloc (struct nn_rbufpool *rbp)
{
/* Note: only one thread calls nn_rmsg_new on a pool */
- uint32_t asize = max_rmsg_size_w_hdr (rbufpool->max_rmsg_size);
+ uint32_t asize = max_rmsg_size_w_hdr (rbp->max_rmsg_size);
struct nn_rbuf *rb;
- DDS_LOG(DDS_LC_RADMIN, "rmsg_rbuf_alloc(%p, %"PRIu32")\n", (void *) rbufpool, asize);
- ASSERT_RBUFPOOL_OWNER (rbufpool);
- rb = rbufpool->current;
+ RBPTRACE ("rmsg_rbuf_alloc(%p, %"PRIu32")\n", (void *) rbp, asize);
+ ASSERT_RBUFPOOL_OWNER (rbp);
+ rb = rbp->current;
assert (rb != NULL);
- assert (rb->freeptr >= rb->u.raw);
- assert (rb->freeptr <= rb->u.raw + rb->size);
+ assert (rb->freeptr >= rb->raw);
+ assert (rb->freeptr <= rb->raw + rb->size);
- if ((uint32_t) (rb->u.raw + rb->size - rb->freeptr) < asize)
+ if ((uint32_t) (rb->raw + rb->size - rb->freeptr) < asize)
{
/* not enough space left for new rmsg */
- if ((rb = nn_rbuf_new (rbufpool)) == NULL)
+ if ((rb = nn_rbuf_new (rbp)) == NULL)
return NULL;
/* a new one should have plenty of space */
- assert ((uint32_t) (rb->u.raw + rb->size - rb->freeptr) >= asize);
+ assert ((uint32_t) (rb->raw + rb->size - rb->freeptr) >= asize);
}
- DDS_LOG(DDS_LC_RADMIN, "rmsg_rbuf_alloc(%p, %"PRIu32") = %p\n", (void *) rbufpool, asize, (void *) rb->freeptr);
+ RBPTRACE ("rmsg_rbuf_alloc(%p, %"PRIu32") = %p\n", (void *) rbp, asize, (void *) rb->freeptr);
#if USE_VALGRIND
- VALGRIND_MEMPOOL_ALLOC (rbufpool, rb->freeptr, asize);
+ VALGRIND_MEMPOOL_ALLOC (rbp, rb->freeptr, asize);
#endif
return rb->freeptr;
}
@@ -512,42 +525,43 @@ static void init_rmsg_chunk (struct nn_rmsg_chunk *chunk, struct nn_rbuf *rbuf)
{
chunk->rbuf = rbuf;
chunk->next = NULL;
- chunk->size = 0;
+ chunk->u.size = 0;
ddsrt_atomic_inc32 (&rbuf->n_live_rmsg_chunks);
}
-struct nn_rmsg *nn_rmsg_new (struct nn_rbufpool *rbufpool)
+struct nn_rmsg *nn_rmsg_new (struct nn_rbufpool *rbp)
{
/* Note: only one thread calls nn_rmsg_new on a pool */
struct nn_rmsg *rmsg;
- DDS_LOG(DDS_LC_RADMIN, "rmsg_new(%p)\n", (void *) rbufpool);
+ RBPTRACE ("rmsg_new(%p)\n", (void *) rbp);
- rmsg = nn_rbuf_alloc (rbufpool);
+ rmsg = nn_rbuf_alloc (rbp);
if (rmsg == NULL)
return NULL;
/* Reference to this rmsg, undone by rmsg_commit(). */
ddsrt_atomic_st32 (&rmsg->refcount, RMSG_REFCOUNT_UNCOMMITTED_BIAS);
/* Initial chunk */
- init_rmsg_chunk (&rmsg->chunk, rbufpool->current);
+ init_rmsg_chunk (&rmsg->chunk, rbp->current);
+ rmsg->trace = rbp->trace;
rmsg->lastchunk = &rmsg->chunk;
/* Incrementing freeptr happens in commit(), so that discarding the
message is really simple. */
- DDS_LOG(DDS_LC_RADMIN, "rmsg_new(%p) = %p\n", (void *) rbufpool, (void *) rmsg);
+ RBPTRACE ("rmsg_new(%p) = %p\n", (void *) rbp, (void *) rmsg);
return rmsg;
}
void nn_rmsg_setsize (struct nn_rmsg *rmsg, uint32_t size)
{
uint32_t size8 = align8uint32 (size);
- DDS_LOG(DDS_LC_RADMIN, "rmsg_setsize(%p, %"PRIu32" => %"PRIu32")\n", (void *) rmsg, size, size8);
+ RMSGTRACE ("rmsg_setsize(%p, %"PRIu32" => %"PRIu32")\n", (void *) rmsg, size, size8);
ASSERT_RBUFPOOL_OWNER (rmsg->chunk.rbuf->rbufpool);
ASSERT_RMSG_UNCOMMITTED (rmsg);
assert (ddsrt_atomic_ld32 (&rmsg->refcount) == RMSG_REFCOUNT_UNCOMMITTED_BIAS);
- assert (rmsg->chunk.size == 0);
+ assert (rmsg->chunk.u.size == 0);
assert (size8 <= rmsg->chunk.rbuf->max_rmsg_size);
assert (rmsg->lastchunk == &rmsg->chunk);
- rmsg->chunk.size = size8;
+ rmsg->chunk.u.size = size8;
#if USE_VALGRIND
VALGRIND_MEMPOOL_CHANGE (rmsg->chunk.rbuf->rbufpool, rmsg, rmsg, offsetof (struct nn_rmsg, chunk.u.payload) + rmsg->chunk.size);
#endif
@@ -563,7 +577,7 @@ void nn_rmsg_free (struct nn_rmsg *rmsg)
free() which we don't do currently. And ideally, you'd use
compare-and-swap for this. */
struct nn_rmsg_chunk *c;
- DDS_LOG(DDS_LC_RADMIN, "rmsg_free(%p)\n", (void *) rmsg);
+ RMSGTRACE ("rmsg_free(%p)\n", (void *) rmsg);
assert (ddsrt_atomic_ld32 (&rmsg->refcount) == 0);
c = &rmsg->chunk;
while (c)
@@ -586,8 +600,8 @@ void nn_rmsg_free (struct nn_rmsg *rmsg)
static void commit_rmsg_chunk (struct nn_rmsg_chunk *chunk)
{
struct nn_rbuf *rbuf = chunk->rbuf;
- DDS_LOG(DDS_LC_RADMIN, "commit_rmsg_chunk(%p)\n", (void *) chunk);
- rbuf->freeptr = chunk->u.payload + chunk->size;
+ RBUFTRACE ("commit_rmsg_chunk(%p)\n", (void *) chunk);
+ rbuf->freeptr = (unsigned char *) (chunk + 1) + chunk->u.size;
}
void nn_rmsg_commit (struct nn_rmsg *rmsg)
@@ -601,12 +615,12 @@ void nn_rmsg_commit (struct nn_rmsg *rmsg)
happens to be such that any asynchronous activities have
completed before we got to commit. */
struct nn_rmsg_chunk *chunk = rmsg->lastchunk;
- DDS_LOG(DDS_LC_RADMIN, "rmsg_commit(%p) refcount 0x%"PRIx32" last-chunk-size %"PRIu32"\n",
- (void *) rmsg, rmsg->refcount.v, chunk->size);
+ RMSGTRACE ("rmsg_commit(%p) refcount 0x%"PRIx32" last-chunk-size %"PRIu32"\n",
+ (void *) rmsg, rmsg->refcount.v, chunk->u.size);
ASSERT_RBUFPOOL_OWNER (chunk->rbuf->rbufpool);
ASSERT_RMSG_UNCOMMITTED (rmsg);
- assert (chunk->size <= chunk->rbuf->max_rmsg_size);
- assert ((chunk->size % 8) == 0);
+ assert (chunk->u.size <= chunk->rbuf->max_rmsg_size);
+ assert ((chunk->u.size % 8) == 0);
assert (ddsrt_atomic_ld32 (&rmsg->refcount) >= RMSG_REFCOUNT_UNCOMMITTED_BIAS);
assert (ddsrt_atomic_ld32 (&rmsg->chunk.rbuf->n_live_rmsg_chunks) > 0);
assert (ddsrt_atomic_ld32 (&chunk->rbuf->n_live_rmsg_chunks) > 0);
@@ -617,7 +631,7 @@ void nn_rmsg_commit (struct nn_rmsg *rmsg)
{
/* Other references exist, so either stored in defrag, reorder
and/or delivery queue */
- DDS_LOG(DDS_LC_RADMIN, "rmsg_commit(%p) => keep\n", (void *) rmsg);
+ RMSGTRACE ("rmsg_commit(%p) => keep\n", (void *) rmsg);
commit_rmsg_chunk (chunk);
}
}
@@ -630,7 +644,7 @@ static void nn_rmsg_addbias (struct nn_rmsg *rmsg)
However, other threads (e.g., delivery threads) may have been
triggered already, so the increment must be done atomically. */
- DDS_LOG(DDS_LC_RADMIN, "rmsg_addbias(%p)\n", (void *) rmsg);
+ RMSGTRACE ("rmsg_addbias(%p)\n", (void *) rmsg);
ASSERT_RBUFPOOL_OWNER (rmsg->chunk.rbuf->rbufpool);
ASSERT_RMSG_UNCOMMITTED (rmsg);
ddsrt_atomic_add32 (&rmsg->refcount, RMSG_REFCOUNT_RDATA_BIAS);
@@ -642,7 +656,7 @@ static void nn_rmsg_rmbias_and_adjust (struct nn_rmsg *rmsg, int adjust)
progressing through the pipeline, but only by a receive
thread. Can't require it to be uncommitted. */
uint32_t sub;
- DDS_LOG(DDS_LC_RADMIN, "rmsg_rmbias_and_adjust(%p, %d)\n", (void *) rmsg, adjust);
+ RMSGTRACE ("rmsg_rmbias_and_adjust(%p, %d)\n", (void *) rmsg, adjust);
assert (adjust >= 0);
assert ((uint32_t) adjust < RMSG_REFCOUNT_RDATA_BIAS);
sub = RMSG_REFCOUNT_RDATA_BIAS - (uint32_t) adjust;
@@ -653,7 +667,7 @@ static void nn_rmsg_rmbias_and_adjust (struct nn_rmsg *rmsg, int adjust)
static void nn_rmsg_unref (struct nn_rmsg *rmsg)
{
- DDS_LOG(DDS_LC_RADMIN, "rmsg_unref(%p)\n", (void *) rmsg);
+ RMSGTRACE ("rmsg_unref(%p)\n", (void *) rmsg);
assert (ddsrt_atomic_ld32 (&rmsg->refcount) > 0);
if (ddsrt_atomic_dec32_ov (&rmsg->refcount) == 1)
nn_rmsg_free (rmsg);
@@ -665,32 +679,32 @@ void *nn_rmsg_alloc (struct nn_rmsg *rmsg, uint32_t size)
struct nn_rbuf *rbuf = chunk->rbuf;
uint32_t size8 = align8uint32 (size);
void *ptr;
- DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %"PRIu32" => %"PRIu32")\n", (void *) rmsg, size, size8);
+ RMSGTRACE ("rmsg_alloc(%p, %"PRIu32" => %"PRIu32")\n", (void *) rmsg, size, size8);
ASSERT_RBUFPOOL_OWNER (rbuf->rbufpool);
ASSERT_RMSG_UNCOMMITTED (rmsg);
- assert ((chunk->size % 8) == 0);
+ assert ((chunk->u.size % 8) == 0);
assert (size8 <= rbuf->max_rmsg_size);
- if (chunk->size + size8 > rbuf->max_rmsg_size)
+ if (chunk->u.size + size8 > rbuf->max_rmsg_size)
{
- struct nn_rbufpool *rbufpool = rbuf->rbufpool;
+ struct nn_rbufpool *rbp = rbuf->rbufpool;
struct nn_rmsg_chunk *newchunk;
- DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %"PRIu32") limit hit - new chunk\n", (void *) rmsg, size);
+ RMSGTRACE ("rmsg_alloc(%p, %"PRIu32") limit hit - new chunk\n", (void *) rmsg, size);
commit_rmsg_chunk (chunk);
- newchunk = nn_rbuf_alloc (rbufpool);
+ newchunk = nn_rbuf_alloc (rbp);
if (newchunk == NULL)
{
- DDS_WARNING ("nn_rmsg_alloc: can't allocate more memory (%"PRIu32" bytes) ... giving up\n", size);
+ DDS_CWARNING (rbp->logcfg, "nn_rmsg_alloc: can't allocate more memory (%"PRIu32" bytes) ... giving up\n", size);
return NULL;
}
- init_rmsg_chunk (newchunk, rbufpool->current);
+ init_rmsg_chunk (newchunk, rbp->current);
rmsg->lastchunk = chunk->next = newchunk;
chunk = newchunk;
}
- ptr = chunk->u.payload + chunk->size;
- chunk->size += size8;
- DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %"PRIu32") = %p\n", (void *) rmsg, size, ptr);
+ ptr = (unsigned char *) (chunk + 1) + chunk->u.size;
+ chunk->u.size += size8;
+ RMSGTRACE ("rmsg_alloc(%p, %"PRIu32") = %p\n", (void *) rmsg, size, ptr);
#if USE_VALGRIND
if (chunk == &rmsg->chunk) {
VALGRIND_MEMPOOL_CHANGE (rbuf->rbufpool, rmsg, rmsg, offsetof (struct nn_rmsg, chunk.u.payload) + chunk->size);
@@ -717,35 +731,39 @@ struct nn_rdata *nn_rdata_new (struct nn_rmsg *rmsg, uint32_t start, uint32_t en
#ifndef NDEBUG
ddsrt_atomic_st32 (&d->refcount_bias_added, 0);
#endif
- DDS_LOG(DDS_LC_RADMIN, "rdata_new(%p, bytes [%"PRIu32",%"PRIu32"), submsg @ %u, payload @ %u) = %p\n", (void *) rmsg, start, endp1, NN_RDATA_SUBMSG_OFF (d), NN_RDATA_PAYLOAD_OFF (d), (void *) d);
+ RMSGTRACE ("rdata_new(%p, bytes [%"PRIu32",%"PRIu32"), submsg @ %u, payload @ %u) = %p\n",
+ (void *) rmsg, start, endp1, NN_RDATA_SUBMSG_OFF (d), NN_RDATA_PAYLOAD_OFF (d), (void *) d);
return d;
}
static void nn_rdata_addbias (struct nn_rdata *rdata)
{
- DDS_LOG(DDS_LC_RADMIN, "rdata_addbias(%p)\n", (void *) rdata);
+ struct nn_rmsg *rmsg = rdata->rmsg;
+ RMSGTRACE ("rdata_addbias(%p)\n", (void *) rdata);
#ifndef NDEBUG
- ASSERT_RBUFPOOL_OWNER (rdata->rmsg->chunk.rbuf->rbufpool);
+ ASSERT_RBUFPOOL_OWNER (rmsg->chunk.rbuf->rbufpool);
if (ddsrt_atomic_inc32_nv (&rdata->refcount_bias_added) != 1)
abort ();
#endif
- nn_rmsg_addbias (rdata->rmsg);
+ nn_rmsg_addbias (rmsg);
}
static void nn_rdata_rmbias_and_adjust (struct nn_rdata *rdata, int adjust)
{
- DDS_LOG(DDS_LC_RADMIN, "rdata_rmbias_and_adjust(%p, %d)\n", (void *) rdata, adjust);
+ struct nn_rmsg *rmsg = rdata->rmsg;
+ RMSGTRACE ("rdata_rmbias_and_adjust(%p, %d)\n", (void *) rdata, adjust);
#ifndef NDEBUG
if (ddsrt_atomic_dec32_ov (&rdata->refcount_bias_added) != 1)
abort ();
#endif
- nn_rmsg_rmbias_and_adjust (rdata->rmsg, adjust);
+ nn_rmsg_rmbias_and_adjust (rmsg, adjust);
}
static void nn_rdata_unref (struct nn_rdata *rdata)
{
- DDS_LOG(DDS_LC_RADMIN, "rdata_rdata_unref(%p)\n", (void *) rdata);
- nn_rmsg_unref (rdata->rmsg);
+ struct nn_rmsg *rmsg = rdata->rmsg;
+ RMSGTRACE ("rdata_rdata_unref(%p)\n", (void *) rdata);
+ nn_rmsg_unref (rmsg);
}
/* DEFRAG --------------------------------------------------------------
@@ -842,6 +860,8 @@ struct nn_defrag {
uint32_t n_samples;
uint32_t max_samples;
enum nn_defrag_drop_mode drop_mode;
+ const struct ddsrt_log_cfg *logcfg;
+ bool trace;
};
static int compare_uint32 (const void *va, const void *vb);
@@ -864,7 +884,7 @@ static int compare_seqno (const void *va, const void *vb)
return (a == b) ? 0 : (a < b) ? -1 : 1;
}
-struct nn_defrag *nn_defrag_new (enum nn_defrag_drop_mode drop_mode, uint32_t max_samples)
+struct nn_defrag *nn_defrag_new (const struct ddsrt_log_cfg *logcfg, enum nn_defrag_drop_mode drop_mode, uint32_t max_samples)
{
struct nn_defrag *d;
assert (max_samples >= 1);
@@ -875,12 +895,14 @@ struct nn_defrag *nn_defrag_new (enum nn_defrag_drop_mode drop_mode, uint32_t ma
d->max_samples = max_samples;
d->n_samples = 0;
d->max_sample = NULL;
+ d->logcfg = logcfg;
+ d->trace = (logcfg->c.mask & DDS_LC_RADMIN) != 0;
return d;
}
void nn_fragchain_adjust_refcount (struct nn_rdata *frag, int adjust)
{
- DDS_LOG(DDS_LC_RADMIN, "fragchain_adjust_refcount(%p, %d)\n", (void *) frag, adjust);
+ RDATATRACE (frag, "fragchain_adjust_refcount(%p, %d)\n", (void *) frag, adjust);
while (frag)
{
struct nn_rdata * const frag1 = frag->nextfrag;
@@ -905,12 +927,16 @@ static void defrag_rsample_drop (struct nn_defrag *defrag, struct nn_rsample *rs
inorder treewalk does provide. */
ddsrt_avl_iter_t iter;
struct nn_defrag_iv *iv;
- DDS_LOG(DDS_LC_RADMIN, " defrag_rsample_drop (%p, %p)\n", (void *) defrag, (void *) rsample);
+ TRACE (defrag, " defrag_rsample_drop (%p, %p)\n", (void *) defrag, (void *) rsample);
ddsrt_avl_delete (&defrag_sampletree_treedef, &defrag->sampletree, rsample);
assert (defrag->n_samples > 0);
defrag->n_samples--;
for (iv = ddsrt_avl_iter_first (&rsample_defrag_fragtree_treedef, &rsample->u.defrag.fragtree, &iter); iv; iv = ddsrt_avl_iter_next (&iter))
- nn_fragchain_rmbias (iv->first);
+ {
+ if (iv->first)
+ /* if the first fragment is missing, a sentinel "iv" is inserted with an empty chain */
+ nn_fragchain_rmbias (iv->first);
+ }
}
void nn_defrag_free (struct nn_defrag *defrag)
@@ -919,7 +945,7 @@ void nn_defrag_free (struct nn_defrag *defrag)
s = ddsrt_avl_find_min (&defrag_sampletree_treedef, &defrag->sampletree);
while (s)
{
- DDS_LOG(DDS_LC_RADMIN, "defrag_free(%p, sample %p seq %"PRId64")\n", (void *) defrag, (void *) s, s->u.defrag.seq);
+ TRACE (defrag, "defrag_free(%p, sample %p seq %"PRId64")\n", (void *) defrag, (void *) s, s->u.defrag.seq);
defrag_rsample_drop (defrag, s);
s = ddsrt_avl_find_min (&defrag_sampletree_treedef, &defrag->sampletree);
}
@@ -927,25 +953,24 @@ void nn_defrag_free (struct nn_defrag *defrag)
ddsrt_free (defrag);
}
-static int defrag_try_merge_with_succ (struct nn_rsample_defrag *sample, struct nn_defrag_iv *node)
+static int defrag_try_merge_with_succ (const struct nn_defrag *defrag, struct nn_rsample_defrag *sample, struct nn_defrag_iv *node)
{
struct nn_defrag_iv *succ;
- DDS_LOG(DDS_LC_RADMIN, " defrag_try_merge_with_succ(%p [%"PRIu32"..%"PRIu32")):\n",
- (void *) node, node->min, node->maxp1);
+ TRACE (defrag, " defrag_try_merge_with_succ(%p [%"PRIu32"..%"PRIu32")):\n", (void *) node, node->min, node->maxp1);
if (node == sample->lastfrag)
{
/* there is no interval following node */
- DDS_LOG(DDS_LC_RADMIN, " node is lastfrag\n");
+ TRACE (defrag, " node is lastfrag\n");
return 0;
}
succ = ddsrt_avl_find_succ (&rsample_defrag_fragtree_treedef, &sample->fragtree, node);
assert (succ != NULL);
- DDS_LOG(DDS_LC_RADMIN, " succ is %p [%"PRIu32"..%"PRIu32")\n", (void *) succ, succ->min, succ->maxp1);
+ TRACE (defrag, " succ is %p [%"PRIu32"..%"PRIu32")\n", (void *) succ, succ->min, succ->maxp1);
if (succ->min > node->maxp1)
{
- DDS_LOG(DDS_LC_RADMIN, " gap between node and succ\n");
+ TRACE (defrag, " gap between node and succ\n");
return 0;
}
else
@@ -958,7 +983,7 @@ static int defrag_try_merge_with_succ (struct nn_rsample_defrag *sample, struct
ddsrt_avl_delete (&rsample_defrag_fragtree_treedef, &sample->fragtree, succ);
if (sample->lastfrag == succ)
{
- DDS_LOG(DDS_LC_RADMIN, " succ is lastfrag\n");
+ TRACE (defrag, " succ is lastfrag\n");
sample->lastfrag = node;
}
@@ -973,9 +998,9 @@ static int defrag_try_merge_with_succ (struct nn_rsample_defrag *sample, struct
references to rmsgs of the rdata in succ, freeing it may cause
the rsample to be freed as well. */
if (node->maxp1 < succ_maxp1)
- DDS_LOG(DDS_LC_RADMIN, " succ adds data to node\n");
+ TRACE (defrag, " succ adds data to node\n");
else
- DDS_LOG(DDS_LC_RADMIN, " succ is contained in node\n");
+ TRACE (defrag, " succ is contained in node\n");
node->last->nextfrag = succ->first;
node->last = succ->last;
@@ -1129,7 +1154,7 @@ static void rsample_convert_defrag_to_reorder (struct nn_rsample *sample)
sample->u.reorder.n_samples = 1;
}
-static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct nn_rdata *rdata, const struct nn_rsample_info *sampleinfo)
+static struct nn_rsample *defrag_add_fragment (const struct nn_defrag *defrag, struct nn_rsample *sample, struct nn_rdata *rdata, const struct nn_rsample_info *sampleinfo)
{
struct nn_rsample_defrag *dfsample = &sample->u.defrag;
struct nn_defrag_iv *predeq, *succ;
@@ -1147,9 +1172,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct
/* relatively expensive test: lastfrag, tree must be consistent */
assert (dfsample->lastfrag == ddsrt_avl_find_max (&rsample_defrag_fragtree_treedef, &dfsample->fragtree));
- DDS_LOG(DDS_LC_RADMIN, " lastfrag %p [%"PRIu32"..%"PRIu32")\n",
- (void *) dfsample->lastfrag,
- dfsample->lastfrag->min, dfsample->lastfrag->maxp1);
+ TRACE (defrag, " lastfrag %p [%"PRIu32"..%"PRIu32")\n", (void *) dfsample->lastfrag, dfsample->lastfrag->min, dfsample->lastfrag->maxp1);
/* Interval tree is sorted on min offset; each key is unique:
otherwise one would be wholly contained in another. */
@@ -1157,15 +1180,14 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct
{
/* Assumed normal case: fragment appends data */
predeq = dfsample->lastfrag;
- DDS_LOG(DDS_LC_RADMIN, " fast path: predeq = lastfrag\n");
+ TRACE (defrag, " fast path: predeq = lastfrag\n");
}
else
{
/* Slow path: find preceding fragment by tree search */
predeq = ddsrt_avl_lookup_pred_eq (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &min);
assert (predeq);
- DDS_LOG(DDS_LC_RADMIN, " slow path: predeq = lookup %"PRIu32" => %p [%"PRIu32"..%"PRIu32")\n",
- min, (void *) predeq, predeq->min, predeq->maxp1);
+ TRACE (defrag, " slow path: predeq = lookup %"PRIu32" => %p [%"PRIu32"..%"PRIu32")\n", min, (void *) predeq, predeq->min, predeq->maxp1);
}
/* we have a sentinel interval of [0,0) until we receive a packet
@@ -1177,7 +1199,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct
{
/* new is contained in predeq, discard new; rdata did not cause
completion of a sample */
- DDS_LOG(DDS_LC_RADMIN, " new contained in predeq\n");
+ TRACE (defrag, " new contained in predeq\n");
return NULL;
}
else if (min <= predeq->maxp1)
@@ -1185,7 +1207,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct
/* new extends predeq, add it to the chain (necessarily at the
end); this may close the gap to the successor of predeq; predeq
need not have a fragment chain yet (it may be the sentinel) */
- DDS_LOG(DDS_LC_RADMIN, " grow predeq with new\n");
+ TRACE (defrag, " grow predeq with new\n");
nn_rdata_addbias (rdata);
rdata->nextfrag = NULL;
if (predeq->first)
@@ -1201,7 +1223,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct
predeq->last = rdata;
predeq->maxp1 = maxp1;
/* it may now be possible to merge with the successor */
- while (defrag_try_merge_with_succ (dfsample, predeq))
+ while (defrag_try_merge_with_succ (defrag, dfsample, predeq))
;
return is_complete (dfsample) ? sample : NULL;
}
@@ -1213,8 +1235,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct
fragment in the chain adds value); but doesn't overlap with
predeq so the tree structure doesn't change even though the key
does change */
- DDS_LOG(DDS_LC_RADMIN, " extending succ %p [%"PRIu32"..%"PRIu32") at head\n",
- (void *) succ, succ->min, succ->maxp1);
+ TRACE (defrag, " extending succ %p [%"PRIu32"..%"PRIu32") at head\n", (void *) succ, succ->min, succ->maxp1);
nn_rdata_addbias (rdata);
rdata->nextfrag = succ->first;
succ->first = rdata;
@@ -1224,9 +1245,9 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct
succ-succ */
if (maxp1 > succ->maxp1)
{
- DDS_LOG(DDS_LC_RADMIN, " extending succ at end as well\n");
+ TRACE (defrag, " extending succ at end as well\n");
succ->maxp1 = maxp1;
- while (defrag_try_merge_with_succ (dfsample, succ))
+ while (defrag_try_merge_with_succ (defrag, dfsample, succ))
;
}
assert (!is_complete (dfsample));
@@ -1237,7 +1258,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct
/* doesn't extend either predeq at the end or succ at the head =>
new interval; rdata did not cause completion of sample */
ddsrt_avl_ipath_t path;
- DDS_LOG(DDS_LC_RADMIN, " new interval\n");
+ TRACE (defrag, " new interval\n");
if (ddsrt_avl_lookup_ipath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &min, &path))
assert (0);
defrag_rsample_addiv (dfsample, rdata, &path);
@@ -1260,25 +1281,25 @@ static int defrag_limit_samples (struct nn_defrag *defrag, seqno_t seq, seqno_t
return 1;
/* max_samples >= 1 => some sample present => max_sample != NULL */
assert (defrag->max_sample != NULL);
- DDS_LOG(DDS_LC_RADMIN, " max samples reached\n");
+ TRACE (defrag, " max samples reached\n");
switch (defrag->drop_mode)
{
case NN_DEFRAG_DROP_LATEST:
- DDS_LOG(DDS_LC_RADMIN, " drop mode = DROP_LATEST\n");
+ TRACE (defrag, " drop mode = DROP_LATEST\n");
if (seq > defrag->max_sample->u.defrag.seq)
{
- DDS_LOG(DDS_LC_RADMIN, " new sample is new latest => discarding it\n");
+ TRACE (defrag, " new sample is new latest => discarding it\n");
return 0;
}
sample_to_drop = defrag->max_sample;
break;
case NN_DEFRAG_DROP_OLDEST:
- DDS_LOG(DDS_LC_RADMIN, " drop mode = DROP_OLDEST\n");
+ TRACE (defrag, " drop mode = DROP_OLDEST\n");
sample_to_drop = ddsrt_avl_find_min (&defrag_sampletree_treedef, &defrag->sampletree);
assert (sample_to_drop);
if (seq < sample_to_drop->u.defrag.seq)
{
- DDS_LOG(DDS_LC_RADMIN, " new sample is new oldest => discarding it\n");
+ TRACE (defrag, " new sample is new oldest => discarding it\n");
return 0;
}
break;
@@ -1289,9 +1310,8 @@ static int defrag_limit_samples (struct nn_defrag *defrag, seqno_t seq, seqno_t
{
defrag->max_sample = ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree);
*max_seq = defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0;
- DDS_LOG(DDS_LC_RADMIN, " updating max_sample: now %p %"PRId64"\n",
- (void *) defrag->max_sample,
- defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0);
+ TRACE (defrag, " updating max_sample: now %p %"PRId64"\n",
+ (void *) defrag->max_sample, defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0);
}
return 1;
}
@@ -1336,20 +1356,20 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata
consistent. Max_sample must be consistent with tree */
assert (defrag->max_sample == ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree));
max_seq = defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0;
- DDS_LOG(DDS_LC_RADMIN, "defrag_rsample(%p, %p [%"PRIu32"..%"PRIu32") msg %p, %p seq %"PRId64" size %"PRIu32") max_seq %p %"PRId64":\n",
- (void *) defrag, (void *) rdata, rdata->min, rdata->maxp1, (void *) rdata->rmsg,
- (void *) sampleinfo, sampleinfo->seq, sampleinfo->size,
- (void *) defrag->max_sample, max_seq);
+ TRACE (defrag, "defrag_rsample(%p, %p [%"PRIu32"..%"PRIu32") msg %p, %p seq %"PRId64" size %"PRIu32") max_seq %p %"PRId64":\n",
+ (void *) defrag, (void *) rdata, rdata->min, rdata->maxp1, (void *) rdata->rmsg,
+ (void *) sampleinfo, sampleinfo->seq, sampleinfo->size,
+ (void *) defrag->max_sample, max_seq);
/* fast path: rdata is part of message with the highest sequence
number we're currently defragmenting, or is beyond that */
if (sampleinfo->seq == max_seq)
{
- DDS_LOG(DDS_LC_RADMIN, " add fragment to max_sample\n");
- result = defrag_add_fragment (defrag->max_sample, rdata, sampleinfo);
+ TRACE (defrag, " add fragment to max_sample\n");
+ result = defrag_add_fragment (defrag, defrag->max_sample, rdata, sampleinfo);
}
else if (!defrag_limit_samples (defrag, sampleinfo->seq, &max_seq))
{
- DDS_LOG(DDS_LC_RADMIN, " discarding sample\n");
+ TRACE (defrag, " discarding sample\n");
result = NULL;
}
else if (sampleinfo->seq > max_seq)
@@ -1357,7 +1377,7 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata
/* a node with a key greater than the maximum always is the right
child of the old maximum node */
/* FIXME: MERGE THIS ONE WITH THE NEXT */
- DDS_LOG(DDS_LC_RADMIN, " new max sample\n");
+ TRACE (defrag, " new max sample\n");
ddsrt_avl_lookup_ipath (&defrag_sampletree_treedef, &defrag->sampletree, &sampleinfo->seq, &path);
if ((sample = defrag_rsample_new (rdata, sampleinfo)) == NULL)
return NULL;
@@ -1369,7 +1389,7 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata
else if ((sample = ddsrt_avl_lookup_ipath (&defrag_sampletree_treedef, &defrag->sampletree, &sampleinfo->seq, &path)) == NULL)
{
/* a new sequence number, but smaller than the maximum */
- DDS_LOG(DDS_LC_RADMIN, " new sample less than max\n");
+ TRACE (defrag, " new sample less than max\n");
assert (sampleinfo->seq < max_seq);
if ((sample = defrag_rsample_new (rdata, sampleinfo)) == NULL)
return NULL;
@@ -1380,8 +1400,8 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata
else
{
/* adds (or, as the case may be, doesn't add) to a known message */
- DDS_LOG(DDS_LC_RADMIN, " add fragment to %p\n", (void *) sample);
- result = defrag_add_fragment (sample, rdata, sampleinfo);
+ TRACE (defrag, " add fragment to %p\n", (void *) sample);
+ result = defrag_add_fragment (defrag, sample, rdata, sampleinfo);
}
if (result != NULL)
@@ -1389,16 +1409,15 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata
/* Once completed, remove from defrag sample tree and convert to
reorder format. If it is the sample with the maximum sequence in
the tree, an update of max_sample is required. */
- DDS_LOG(DDS_LC_RADMIN, " complete\n");
+ TRACE (defrag, " complete\n");
ddsrt_avl_delete (&defrag_sampletree_treedef, &defrag->sampletree, result);
assert (defrag->n_samples > 0);
defrag->n_samples--;
if (result == defrag->max_sample)
{
defrag->max_sample = ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree);
- DDS_LOG(DDS_LC_RADMIN, " updating max_sample: now %p %"PRId64"\n",
- (void *) defrag->max_sample,
- defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0);
+ TRACE (defrag, " updating max_sample: now %p %"PRId64"\n",
+ (void *) defrag->max_sample, defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0);
}
rsample_convert_defrag_to_reorder (result);
}
@@ -1422,7 +1441,7 @@ void nn_defrag_notegap (struct nn_defrag *defrag, seqno_t min, seqno_t maxp1)
defrag->max_sample = ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree);
}
-int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnum, struct nn_fragment_number_set *map, uint32_t maxsz)
+int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnum, struct nn_fragment_number_set_header *map, uint32_t *mapbits, uint32_t maxsz)
{
struct nn_rsample *s;
struct nn_defrag_iv *iv;
@@ -1446,7 +1465,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu
else
map->numbits = maxfragnum + 1;
map->bitmap_base = 0;
- nn_bitset_one (map->numbits, map->bits);
+ nn_bitset_one (map->numbits, mapbits);
return (int) map->numbits;
}
}
@@ -1491,7 +1510,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu
/* Clear bitmap, then set bits for gaps in available fragments */
if (map->numbits > maxsz)
map->numbits = maxsz;
- nn_bitset_zero (map->numbits, map->bits);
+ nn_bitset_zero (map->numbits, mapbits);
i = map->bitmap_base;
while (iv && i < map->bitmap_base + map->numbits)
{
@@ -1509,7 +1528,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu
for (; i < map->bitmap_base + map->numbits && i < bound; i++)
{
unsigned x = (unsigned) (i - map->bitmap_base);
- nn_bitset_set (map->numbits, map->bits, x);
+ nn_bitset_set (map->numbits, mapbits, x);
}
/* next sequence of fragments to request retranmsission of starts
at fragment containing maxp1 (because we don't have that byte
@@ -1521,7 +1540,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu
for (; i < map->bitmap_base + map->numbits; i++)
{
unsigned x = (unsigned) (i - map->bitmap_base);
- nn_bitset_set (map->numbits, map->bits, x);
+ nn_bitset_set (map->numbits, mapbits, x);
}
return (int) map->numbits;
}
@@ -1609,12 +1628,15 @@ struct nn_reorder {
enum nn_reorder_mode mode;
uint32_t max_samples;
uint32_t n_samples;
+ const struct ddsrt_log_cfg *logcfg;
+ bool late_ack_mode;
+ bool trace;
};
static const ddsrt_avl_treedef_t reorder_sampleivtree_treedef =
DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct nn_rsample, u.reorder.avlnode), offsetof (struct nn_rsample, u.reorder.min), compare_seqno, 0);
-struct nn_reorder *nn_reorder_new (enum nn_reorder_mode mode, uint32_t max_samples)
+struct nn_reorder *nn_reorder_new (const struct ddsrt_log_cfg *logcfg, enum nn_reorder_mode mode, uint32_t max_samples, bool late_ack_mode)
{
struct nn_reorder *r;
if ((r = ddsrt_malloc (sizeof (*r))) == NULL)
@@ -1625,6 +1647,9 @@ struct nn_reorder *nn_reorder_new (enum nn_reorder_mode mode, uint32_t max_sampl
r->mode = mode;
r->max_samples = max_samples;
r->n_samples = 0;
+ r->late_ack_mode = late_ack_mode;
+ r->logcfg = logcfg;
+ r->trace = (logcfg->c.mask & DDS_LC_RADMIN) != 0;
return r;
}
@@ -1695,28 +1720,28 @@ static int reorder_try_append_and_discard (struct nn_reorder *reorder, struct nn
{
if (todiscard == NULL)
{
- DDS_LOG(DDS_LC_RADMIN, " try_append_and_discard: fail: todiscard = NULL\n");
+ TRACE (reorder, " try_append_and_discard: fail: todiscard = NULL\n");
return 0;
}
else if (appendto->u.reorder.maxp1 < todiscard->u.reorder.min)
{
- DDS_LOG(DDS_LC_RADMIN, " try_append_and_discard: fail: appendto = [%"PRId64",%"PRId64") @ %p, "
- "todiscard = [%"PRId64",%"PRId64") @ %p - gap\n",
- appendto->u.reorder.min, appendto->u.reorder.maxp1, (void *) appendto,
- todiscard->u.reorder.min, todiscard->u.reorder.maxp1, (void *) todiscard);
+ TRACE (reorder, " try_append_and_discard: fail: appendto = [%"PRId64",%"PRId64") @ %p, "
+ "todiscard = [%"PRId64",%"PRId64") @ %p - gap\n",
+ appendto->u.reorder.min, appendto->u.reorder.maxp1, (void *) appendto,
+ todiscard->u.reorder.min, todiscard->u.reorder.maxp1, (void *) todiscard);
return 0;
}
else
{
- DDS_LOG(DDS_LC_RADMIN, " try_append_and_discard: success: appendto = [%"PRId64",%"PRId64") @ %p, "
- "todiscard = [%"PRId64",%"PRId64") @ %p\n",
- appendto->u.reorder.min, appendto->u.reorder.maxp1, (void *) appendto,
- todiscard->u.reorder.min, todiscard->u.reorder.maxp1, (void *) todiscard);
+ TRACE (reorder, " try_append_and_discard: success: appendto = [%"PRId64",%"PRId64") @ %p, "
+ "todiscard = [%"PRId64",%"PRId64") @ %p\n",
+ appendto->u.reorder.min, appendto->u.reorder.maxp1, (void *) appendto,
+ todiscard->u.reorder.min, todiscard->u.reorder.maxp1, (void *) todiscard);
assert (todiscard->u.reorder.min == appendto->u.reorder.maxp1);
ddsrt_avl_delete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, todiscard);
append_rsample_interval (appendto, todiscard);
- DDS_LOG(DDS_LC_RADMIN, " try_append_and_discard: max_sampleiv needs update? %s\n",
- (todiscard == reorder->max_sampleiv) ? "yes" : "no");
+ TRACE (reorder, " try_append_and_discard: max_sampleiv needs update? %s\n",
+ (todiscard == reorder->max_sampleiv) ? "yes" : "no");
/* Inform caller whether reorder->max must be updated -- the
expected thing to do is to update it to appendto here, but that
fails if appendto isn't actually in the tree. And that happens
@@ -1726,7 +1751,7 @@ static int reorder_try_append_and_discard (struct nn_reorder *reorder, struct nn
}
}
-struct nn_rsample *nn_reorder_rsample_dup (struct nn_rmsg *rmsg, struct nn_rsample *rsampleiv)
+struct nn_rsample *nn_reorder_rsample_dup_first (struct nn_rmsg *rmsg, struct nn_rsample *rsampleiv)
{
/* Duplicates the rsampleiv without updating any reference counts:
that is left to the caller, as they do not need to be updated if
@@ -1738,7 +1763,6 @@ struct nn_rsample *nn_reorder_rsample_dup (struct nn_rmsg *rmsg, struct nn_rsamp
rsampleiv. */
struct nn_rsample *rsampleiv_new;
struct nn_rsample_chain_elem *sce;
- assert (rsample_is_singleton (&rsampleiv->u.reorder));
#ifndef NDEBUG
{
struct nn_rdata *d = rsampleiv->u.reorder.sc.first->fragchain;
@@ -1754,7 +1778,9 @@ struct nn_rsample *nn_reorder_rsample_dup (struct nn_rmsg *rmsg, struct nn_rsamp
sce->fragchain = rsampleiv->u.reorder.sc.first->fragchain;
sce->next = NULL;
sce->sampleinfo = rsampleiv->u.reorder.sc.first->sampleinfo;
- *rsampleiv_new = *rsampleiv;
+ rsampleiv_new->u.reorder.min = rsampleiv->u.reorder.min;
+ rsampleiv_new->u.reorder.maxp1 = rsampleiv_new->u.reorder.min + 1;
+ rsampleiv_new->u.reorder.n_samples = 1;
rsampleiv_new->u.reorder.sc.first = rsampleiv_new->u.reorder.sc.last = sce;
return rsampleiv_new;
}
@@ -1791,7 +1817,7 @@ static void delete_last_sample (struct nn_reorder *reorder)
{
/* Last sample is in an interval of its own - delete it, and
recalc max_sampleiv. */
- DDS_LOG(DDS_LC_RADMIN, " delete_last_sample: in singleton interval\n");
+ TRACE (reorder, " delete_last_sample: in singleton interval\n");
fragchain = last->sc.first->fragchain;
ddsrt_avl_delete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, reorder->max_sampleiv);
reorder->max_sampleiv = ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree);
@@ -1807,8 +1833,7 @@ static void delete_last_sample (struct nn_reorder *reorder)
large!). Can't be a singleton list, so might as well chop off
one evaluation of the loop condition. */
struct nn_rsample_chain_elem *e, *pe;
- DDS_LOG(DDS_LC_RADMIN, " delete_last_sample: scanning last interval [%"PRId64"..%"PRId64")\n",
- last->min, last->maxp1);
+ TRACE (reorder, " delete_last_sample: scanning last interval [%"PRId64"..%"PRId64")\n", last->min, last->maxp1);
assert (last->n_samples >= 1);
assert (last->min + last->n_samples <= last->maxp1);
e = last->sc.first;
@@ -1838,7 +1863,9 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r
refcount_adjust is incremented if the sample is not discarded. */
struct nn_rsample_reorder *s = &rsampleiv->u.reorder;
- DDS_LOG(DDS_LC_RADMIN, "reorder_sample(%p %c, %"PRId64" @ %p) expecting %"PRId64":\n", (void *) reorder, reorder_mode_as_char (reorder), rsampleiv->u.reorder.min, (void *) rsampleiv, reorder->next_seq);
+ TRACE (reorder, "reorder_sample(%p %c, %"PRId64" @ %p) expecting %"PRId64":\n",
+ (void *) reorder, reorder_mode_as_char (reorder), rsampleiv->u.reorder.min,
+ (void *) rsampleiv, reorder->next_seq);
/* Incoming rsample must be a singleton */
assert (rsample_is_singleton (s));
@@ -1849,7 +1876,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r
{
struct nn_rsample *min = ddsrt_avl_find_min (&reorder_sampleivtree_treedef, &reorder->sampleivtree);
if (min)
- DDS_LOG(DDS_LC_RADMIN, " min = %"PRId64" @ %p\n", min->u.reorder.min, (void *) min);
+ TRACE (reorder, " min = %"PRId64" @ %p\n", min->u.reorder.min, (void *) min);
assert (min == NULL || reorder->next_seq < min->u.reorder.min);
assert ((reorder->max_sampleiv == NULL && min == NULL) ||
(reorder->max_sampleiv != NULL && min != NULL));
@@ -1859,7 +1886,8 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r
assert (reorder->max_sampleiv == NULL || reorder->max_sampleiv == ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree));
assert (reorder->n_samples <= reorder->max_samples);
if (reorder->max_sampleiv)
- DDS_LOG(DDS_LC_RADMIN, " max = [%"PRId64",%"PRId64") @ %p\n", reorder->max_sampleiv->u.reorder.min, reorder->max_sampleiv->u.reorder.maxp1, (void *) reorder->max_sampleiv);
+ TRACE (reorder, " max = [%"PRId64",%"PRId64") @ %p\n", reorder->max_sampleiv->u.reorder.min,
+ reorder->max_sampleiv->u.reorder.maxp1, (void *) reorder->max_sampleiv);
if (s->min == reorder->next_seq ||
(s->min > reorder->next_seq && reorder->mode == NN_REORDER_MODE_MONOTONICALLY_INCREASING) ||
@@ -1873,7 +1901,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r
admin, or things go wrong very quickly.) */
if (delivery_queue_full_p)
{
- DDS_LOG(DDS_LC_RADMIN, " discarding deliverable sample: delivery queue is full\n");
+ TRACE (reorder, " discarding deliverable sample: delivery queue is full\n");
return NN_REORDER_REJECT;
}
@@ -1884,14 +1912,14 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r
if (reorder->max_sampleiv != NULL)
{
struct nn_rsample *min = ddsrt_avl_find_min (&reorder_sampleivtree_treedef, &reorder->sampleivtree);
- DDS_LOG(DDS_LC_RADMIN, " try append_and_discard\n");
+ TRACE (reorder, " try append_and_discard\n");
if (reorder_try_append_and_discard (reorder, rsampleiv, min))
reorder->max_sampleiv = NULL;
}
reorder->next_seq = s->maxp1;
*sc = rsampleiv->u.reorder.sc;
(*refcount_adjust)++;
- DDS_LOG(DDS_LC_RADMIN, " return [%"PRId64",%"PRId64")\n", s->min, s->maxp1);
+ TRACE (reorder, " return [%"PRId64",%"PRId64")\n", s->min, s->maxp1);
/* Adjust reorder->n_samples, new sample is not counted yet */
assert (s->maxp1 - s->min >= 1);
@@ -1905,7 +1933,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r
{
/* we've moved beyond this one: discard it; no need to adjust
n_samples */
- DDS_LOG(DDS_LC_RADMIN, " discard: too old\n");
+ TRACE (reorder, " discard: too old\n");
return NN_REORDER_TOO_OLD; /* don't want refcount increment */
}
else if (ddsrt_avl_is_empty (&reorder->sampleivtree))
@@ -1914,10 +1942,10 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r
is technically allowed, and potentially useful, so check for
it */
assert (reorder->n_samples == 0);
- DDS_LOG(DDS_LC_RADMIN, " adding to empty store\n");
+ TRACE (reorder, " adding to empty store\n");
if (reorder->max_samples == 0)
{
- DDS_LOG(DDS_LC_RADMIN, " NOT - max_samples hit\n");
+ TRACE (reorder, " NOT - max_samples hit\n");
return NN_REORDER_REJECT;
}
else
@@ -1933,12 +1961,12 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r
if (delivery_queue_full_p)
{
/* growing last inteval will not be accepted when this flag is set */
- DDS_LOG(DDS_LC_RADMIN, " discarding sample: only accepting delayed samples due to backlog in delivery queue\n");
+ TRACE (reorder, " discarding sample: only accepting delayed samples due to backlog in delivery queue\n");
return NN_REORDER_REJECT;
}
/* grow the last interval, if we're still accepting samples */
- DDS_LOG(DDS_LC_RADMIN, " growing last interval\n");
+ TRACE (reorder, " growing last interval\n");
if (reorder->n_samples < reorder->max_samples)
{
append_rsample_interval (reorder->max_sampleiv, rsampleiv);
@@ -1946,7 +1974,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r
}
else
{
- DDS_LOG(DDS_LC_RADMIN, " discarding sample: max_samples reached and sample at end\n");
+ TRACE (reorder, " discarding sample: max_samples reached and sample at end\n");
return NN_REORDER_REJECT;
}
}
@@ -1955,19 +1983,19 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r
if (delivery_queue_full_p)
{
/* new interval at the end will not be accepted when this flag is set */
- DDS_LOG(DDS_LC_RADMIN, " discarding sample: only accepting delayed samples due to backlog in delivery queue\n");
+ TRACE (reorder, " discarding sample: only accepting delayed samples due to backlog in delivery queue\n");
return NN_REORDER_REJECT;
}
if (reorder->n_samples < reorder->max_samples)
{
- DDS_LOG(DDS_LC_RADMIN, " new interval at end\n");
+ TRACE (reorder, " new interval at end\n");
reorder_add_rsampleiv (reorder, rsampleiv);
reorder->max_sampleiv = rsampleiv;
reorder->n_samples++;
}
else
{
- DDS_LOG(DDS_LC_RADMIN, " discarding sample: max_samples reached and sample at end\n");
+ TRACE (reorder, " discarding sample: max_samples reached and sample at end\n");
return NN_REORDER_REJECT;
}
}
@@ -1981,37 +2009,37 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r
- if immsucc exists we can prepend s to immsucc
- and possibly join predeq, s, and immsucc */
struct nn_rsample *predeq, *immsucc;
- DDS_LOG(DDS_LC_RADMIN, " hard case ...\n");
+ TRACE (reorder, " hard case ...\n");
- if (config.late_ack_mode && delivery_queue_full_p)
+ if (reorder->late_ack_mode && delivery_queue_full_p)
{
- DDS_LOG(DDS_LC_RADMIN, " discarding sample: delivery queue full\n");
+ TRACE (reorder, " discarding sample: delivery queue full\n");
return NN_REORDER_REJECT;
}
predeq = ddsrt_avl_lookup_pred_eq (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &s->min);
if (predeq)
- DDS_LOG(DDS_LC_RADMIN, " predeq = [%"PRId64",%"PRId64") @ %p\n",
- predeq->u.reorder.min, predeq->u.reorder.maxp1, (void *) predeq);
+ TRACE (reorder, " predeq = [%"PRId64",%"PRId64") @ %p\n",
+ predeq->u.reorder.min, predeq->u.reorder.maxp1, (void *) predeq);
else
- DDS_LOG(DDS_LC_RADMIN, " predeq = null\n");
+ TRACE (reorder, " predeq = null\n");
if (predeq && s->min >= predeq->u.reorder.min && s->min < predeq->u.reorder.maxp1)
{
/* contained in predeq */
- DDS_LOG(DDS_LC_RADMIN, " discard: contained in predeq\n");
+ TRACE (reorder, " discard: contained in predeq\n");
return NN_REORDER_REJECT;
}
immsucc = ddsrt_avl_lookup (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &s->maxp1);
if (immsucc)
- DDS_LOG(DDS_LC_RADMIN, " immsucc = [%"PRId64",%"PRId64") @ %p\n",
- immsucc->u.reorder.min, immsucc->u.reorder.maxp1, (void *) immsucc);
+ TRACE (reorder, " immsucc = [%"PRId64",%"PRId64") @ %p\n",
+ immsucc->u.reorder.min, immsucc->u.reorder.maxp1, (void *) immsucc);
else
- DDS_LOG(DDS_LC_RADMIN, " immsucc = null\n");
+ TRACE (reorder, " immsucc = null\n");
if (predeq && s->min == predeq->u.reorder.maxp1)
{
/* grow predeq at end, and maybe append immsucc as well */
- DDS_LOG(DDS_LC_RADMIN, " growing predeq at end ...\n");
+ TRACE (reorder, " growing predeq at end ...\n");
append_rsample_interval (predeq, rsampleiv);
if (reorder_try_append_and_discard (reorder, predeq, immsucc))
reorder->max_sampleiv = predeq;
@@ -2021,7 +2049,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r
/* no predecessor, grow immsucc at head, which _does_ alter the
key of the node in the tree, but _doesn't_ change the tree's
structure. */
- DDS_LOG(DDS_LC_RADMIN, " growing immsucc at head\n");
+ TRACE (reorder, " growing immsucc at head\n");
s->sc.last->next = immsucc->u.reorder.sc.first;
immsucc->u.reorder.sc.first = s->sc.first;
immsucc->u.reorder.min = s->min;
@@ -2047,7 +2075,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r
else
{
/* neither extends predeq nor immsucc */
- DDS_LOG(DDS_LC_RADMIN, " new interval\n");
+ TRACE (reorder, " new interval\n");
reorder_add_rsampleiv (reorder, rsampleiv);
}
@@ -2174,18 +2202,18 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord
struct nn_rsample *coalesced;
int valuable;
- DDS_LOG(DDS_LC_RADMIN, "reorder_gap(%p %c, [%"PRId64",%"PRId64") data %p) expecting %"PRId64":\n",
- (void *) reorder, reorder_mode_as_char (reorder),
- min, maxp1, (void *) rdata, reorder->next_seq);
+ TRACE (reorder, "reorder_gap(%p %c, [%"PRId64",%"PRId64") data %p) expecting %"PRId64":\n",
+ (void *) reorder, reorder_mode_as_char (reorder),
+ min, maxp1, (void *) rdata, reorder->next_seq);
if (maxp1 <= reorder->next_seq)
{
- DDS_LOG(DDS_LC_RADMIN, " too old\n");
+ TRACE (reorder, " too old\n");
return NN_REORDER_TOO_OLD;
}
if (reorder->mode != NN_REORDER_MODE_NORMAL)
{
- DDS_LOG(DDS_LC_RADMIN, " special mode => don't care\n");
+ TRACE (reorder, " special mode => don't care\n");
return NN_REORDER_REJECT;
}
@@ -2193,10 +2221,10 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord
if ((coalesced = coalesce_intervals_touching_range (reorder, min, maxp1, &valuable)) == NULL)
{
nn_reorder_result_t res;
- DDS_LOG(DDS_LC_RADMIN, " coalesced = null\n");
+ TRACE (reorder, " coalesced = null\n");
if (min <= reorder->next_seq)
{
- DDS_LOG(DDS_LC_RADMIN, " next expected: %"PRId64"\n", maxp1);
+ TRACE (reorder, " next expected: %"PRId64"\n", maxp1);
reorder->next_seq = maxp1;
res = NN_REORDER_ACCEPT;
}
@@ -2204,17 +2232,17 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord
(reorder->max_sampleiv == NULL || min > reorder->max_sampleiv->u.reorder.maxp1))
{
/* n_samples = max_samples => (max_sampleiv = NULL <=> max_samples = 0) */
- DDS_LOG(DDS_LC_RADMIN, " discarding gap: max_samples reached and gap at end\n");
+ TRACE (reorder, " discarding gap: max_samples reached and gap at end\n");
res = NN_REORDER_REJECT;
}
else if (!reorder_insert_gap (reorder, rdata, min, maxp1))
{
- DDS_LOG(DDS_LC_RADMIN, " store gap failed: no memory\n");
+ TRACE (reorder, " store gap failed: no memory\n");
res = NN_REORDER_REJECT;
}
else
{
- DDS_LOG(DDS_LC_RADMIN, " storing gap\n");
+ TRACE (reorder, " storing gap\n");
res = NN_REORDER_ACCEPT;
/* do not let radmin grow beyond max_samples; there is a small
possibility that we insert it & delete it immediately
@@ -2230,15 +2258,15 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord
}
else if (coalesced->u.reorder.min <= reorder->next_seq)
{
- DDS_LOG(DDS_LC_RADMIN, " coalesced = [%"PRId64",%"PRId64") @ %p containing %"PRId32" samples\n",
- coalesced->u.reorder.min, coalesced->u.reorder.maxp1,
- (void *) coalesced, coalesced->u.reorder.n_samples);
+ TRACE (reorder, " coalesced = [%"PRId64",%"PRId64") @ %p containing %"PRId32" samples\n",
+ coalesced->u.reorder.min, coalesced->u.reorder.maxp1,
+ (void *) coalesced, coalesced->u.reorder.n_samples);
ddsrt_avl_delete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, coalesced);
if (coalesced->u.reorder.min <= reorder->next_seq)
assert (min <= reorder->next_seq);
reorder->next_seq = coalesced->u.reorder.maxp1;
reorder->max_sampleiv = ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree);
- DDS_LOG(DDS_LC_RADMIN, " next expected: %"PRId64"\n", reorder->next_seq);
+ TRACE (reorder, " next expected: %"PRId64"\n", reorder->next_seq);
*sc = coalesced->u.reorder.sc;
/* Adjust n_samples */
@@ -2249,8 +2277,8 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord
}
else
{
- DDS_LOG(DDS_LC_RADMIN, " coalesced = [%"PRId64",%"PRId64") @ %p - that is all\n",
- coalesced->u.reorder.min, coalesced->u.reorder.maxp1, (void *) coalesced);
+ TRACE (reorder, " coalesced = [%"PRId64",%"PRId64") @ %p - that is all\n",
+ coalesced->u.reorder.min, coalesced->u.reorder.maxp1, (void *) coalesced);
reorder->max_sampleiv = ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree);
return valuable ? NN_REORDER_ACCEPT : NN_REORDER_REJECT;
}
@@ -2268,7 +2296,7 @@ int nn_reorder_wantsample (struct nn_reorder *reorder, seqno_t seq)
return (s == NULL || s->u.reorder.maxp1 <= seq);
}
-unsigned nn_reorder_nackmap (struct nn_reorder *reorder, seqno_t base, seqno_t maxseq, struct nn_sequence_number_set *map, uint32_t maxsz, int notail)
+unsigned nn_reorder_nackmap (struct nn_reorder *reorder, seqno_t base, seqno_t maxseq, struct nn_sequence_number_set_header *map, uint32_t *mapbits, uint32_t maxsz, int notail)
{
struct nn_rsample *iv;
seqno_t i;
@@ -2290,13 +2318,13 @@ unsigned nn_reorder_nackmap (struct nn_reorder *reorder, seqno_t base, seqno_t m
#else
if (base > reorder->next_seq)
{
- DDS_ERROR("nn_reorder_nackmap: incorrect base sequence number supplied (%"PRId64" > %"PRId64")\n", base, reorder->next_seq);
+ DDS_CERROR (reorder->logcfg, "nn_reorder_nackmap: incorrect base sequence number supplied (%"PRId64" > %"PRId64")\n", base, reorder->next_seq);
base = reorder->next_seq;
}
#endif
if (maxseq + 1 < base)
{
- DDS_ERROR("nn_reorder_nackmap: incorrect max sequence number supplied (maxseq %"PRId64" base %"PRId64")\n", maxseq, base);
+ DDS_CERROR (reorder->logcfg, "nn_reorder_nackmap: incorrect max sequence number supplied (maxseq %"PRId64" base %"PRId64")\n", maxseq, base);
maxseq = base - 1;
}
@@ -2305,7 +2333,7 @@ unsigned nn_reorder_nackmap (struct nn_reorder *reorder, seqno_t base, seqno_t m
map->numbits = maxsz;
else
map->numbits = (uint32_t) (maxseq + 1 - base);
- nn_bitset_zero (map->numbits, map->bits);
+ nn_bitset_zero (map->numbits, mapbits);
if ((iv = ddsrt_avl_find_min (&reorder_sampleivtree_treedef, &reorder->sampleivtree)) != NULL)
assert (iv->u.reorder.min > base);
@@ -2315,7 +2343,7 @@ unsigned nn_reorder_nackmap (struct nn_reorder *reorder, seqno_t base, seqno_t m
for (; i < base + map->numbits && i < iv->u.reorder.min; i++)
{
unsigned x = (unsigned) (i - base);
- nn_bitset_set (map->numbits, map->bits, x);
+ nn_bitset_set (map->numbits, mapbits, x);
}
i = iv->u.reorder.maxp1;
iv = ddsrt_avl_find_succ (&reorder_sampleivtree_treedef, &reorder->sampleivtree, iv);
@@ -2327,7 +2355,7 @@ unsigned nn_reorder_nackmap (struct nn_reorder *reorder, seqno_t base, seqno_t m
for (; i < base + map->numbits; i++)
{
unsigned x = (unsigned) (i - base);
- nn_bitset_set (map->numbits, map->bits, x);
+ nn_bitset_set (map->numbits, mapbits, x);
}
}
return map->numbits;
@@ -2398,6 +2426,7 @@ static enum dqueue_elem_kind dqueue_elem_kind (const struct nn_rsample_chain_ele
static uint32_t dqueue_thread (struct nn_dqueue *q)
{
struct thread_state1 * const ts1 = lookup_thread_state ();
+ struct q_globals const * const gv = ddsrt_atomic_ldvoidp (&ts1->gv);
nn_mtime_t next_thread_cputime = { 0 };
int keepgoing = 1;
nn_guid_t rdguid, *prdguid = NULL;
@@ -2408,7 +2437,7 @@ static uint32_t dqueue_thread (struct nn_dqueue *q)
{
struct nn_rsample_chain sc;
- LOG_THREAD_CPUTIME (next_thread_cputime);
+ LOG_THREAD_CPUTIME (&gv->logconfig, next_thread_cputime);
if (q->sc.first == NULL)
ddsrt_cond_wait (&q->cond, &q->lock);
@@ -2416,7 +2445,7 @@ static uint32_t dqueue_thread (struct nn_dqueue *q)
q->sc.first = q->sc.last = NULL;
ddsrt_mutex_unlock (&q->lock);
- thread_state_awake (ts1);
+ thread_state_awake_fixed_domain (ts1);
while (sc.first)
{
struct nn_rsample_chain_elem *e = sc.first;
@@ -2484,7 +2513,7 @@ static uint32_t dqueue_thread (struct nn_dqueue *q)
return 0;
}
-struct nn_dqueue *nn_dqueue_new (const char *name, uint32_t max_samples, nn_dqueue_handler_t handler, void *arg)
+struct nn_dqueue *nn_dqueue_new (const char *name, const struct q_globals *gv, uint32_t max_samples, nn_dqueue_handler_t handler, void *arg)
{
struct nn_dqueue *q;
char *thrname;
@@ -2507,7 +2536,7 @@ struct nn_dqueue *nn_dqueue_new (const char *name, uint32_t max_samples, nn_dque
if ((thrname = ddsrt_malloc (thrnamesz)) == NULL)
goto fail_thrname;
snprintf (thrname, thrnamesz, "dq.%s", name);
- if (create_thread (&q->ts, thrname, (uint32_t (*) (void *)) dqueue_thread, q) != DDS_RETCODE_OK)
+ if (create_thread (&q->ts, gv, thrname, (uint32_t (*) (void *)) dqueue_thread, q) != DDS_RETCODE_OK)
goto fail_thread;
ddsrt_free (thrname);
return q;
diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c
index a706067..00b678c 100644
--- a/src/core/ddsi/src/q_receive.c
+++ b/src/core/ddsi/src/q_receive.c
@@ -19,6 +19,7 @@
#include "dds/ddsrt/md5.h"
#include "dds/ddsrt/sync.h"
#include "dds/ddsrt/string.h"
+#include "dds/ddsrt/static_assert.h"
#include "dds/ddsrt/avl.h"
#include "dds__stream.h"
@@ -36,7 +37,6 @@
#include "dds/ddsi/q_addrset.h"
#include "dds/ddsi/q_ddsi_discovery.h"
#include "dds/ddsi/q_radmin.h"
-#include "dds/ddsi/q_error.h"
#include "dds/ddsi/q_thread.h"
#include "dds/ddsi/q_ephash.h"
#include "dds/ddsi/q_lease.h"
@@ -44,10 +44,10 @@
#include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_xmsg.h"
#include "dds/ddsi/q_receive.h"
+#include "dds/ddsi/q_rhc.h"
#include "dds/ddsi/q_transmit.h"
#include "dds/ddsi/q_globals.h"
-#include "dds/ddsi/q_static_assert.h"
#include "dds/ddsi/q_init.h"
#include "dds/ddsi/ddsi_tkmap.h"
#include "dds/ddsi/ddsi_mcgroup.h"
@@ -74,7 +74,7 @@ Notes:
*/
-static void deliver_user_data_synchronously (struct nn_rsample_chain *sc);
+static void deliver_user_data_synchronously (struct nn_rsample_chain *sc, const nn_guid_t *rdguid);
static void maybe_set_reader_in_sync (struct proxy_writer *pwr, struct pwr_rd_match *wn, seqno_t last_deliv_seq)
{
@@ -87,13 +87,15 @@ static void maybe_set_reader_in_sync (struct proxy_writer *pwr, struct pwr_rd_ma
if (last_deliv_seq >= wn->u.not_in_sync.end_of_tl_seq)
{
wn->in_sync = PRMSS_SYNC;
- pwr->n_readers_out_of_sync--;
+ if (--pwr->n_readers_out_of_sync == 0)
+ local_reader_ary_setfastpath_ok (&pwr->rdary, true);
}
break;
case PRMSS_OUT_OF_SYNC:
- if (nn_reorder_next_seq (wn->u.not_in_sync.reorder) - 1 >= wn->u.not_in_sync.end_of_out_of_sync_seq)
+ assert (nn_reorder_next_seq (wn->u.not_in_sync.reorder) <= nn_reorder_next_seq (pwr->reorder));
+ if (pwr->have_seen_heartbeat && nn_reorder_next_seq (wn->u.not_in_sync.reorder) == nn_reorder_next_seq (pwr->reorder))
{
- DDS_TRACE(" msr_in_sync("PGUIDFMT" out-of-sync to tlcatchup)", PGUID (wn->rd_guid));
+ ETRACE (pwr, " msr_in_sync("PGUIDFMT" out-of-sync to tlcatchup)", PGUID (wn->rd_guid));
wn->in_sync = PRMSS_TLCATCHUP;
maybe_set_reader_in_sync (pwr, wn, last_deliv_seq);
}
@@ -101,25 +103,17 @@ static void maybe_set_reader_in_sync (struct proxy_writer *pwr, struct pwr_rd_ma
}
}
-static int valid_sequence_number_set (const nn_sequence_number_set_t *snset)
+static int valid_sequence_number_set (const nn_sequence_number_set_header_t *snset)
{
- if (fromSN (snset->bitmap_base) <= 0)
- return 0;
- if (snset->numbits <= 0 || snset->numbits > 256)
- return 0;
- return 1;
+ return (fromSN (snset->bitmap_base) > 0 && snset->numbits <= 256);
}
-static int valid_fragment_number_set (const nn_fragment_number_set_t *fnset)
+static int valid_fragment_number_set (const nn_fragment_number_set_header_t *fnset)
{
- if (fnset->bitmap_base <= 0)
- return 0;
- if (fnset->numbits <= 0 || fnset->numbits > 256)
- return 0;
- return 1;
+ return (fnset->bitmap_base > 0 && fnset->numbits <= 256);
}
-static int valid_AckNack (AckNack_t *msg, size_t size, int byteswap)
+static int valid_AckNack (const struct receiver_state *rst, AckNack_t *msg, size_t size, int byteswap)
{
nn_count_t *count; /* this should've preceded the bitmap */
if (size < ACKNACK_SIZE (0))
@@ -136,32 +130,21 @@ static int valid_AckNack (AckNack_t *msg, size_t size, int byteswap)
/* Validation following 8.3.7.1.3 + 8.3.5.5 */
if (!valid_sequence_number_set (&msg->readerSNState))
{
- if (NN_STRICT_P)
- return 0;
+ /* FastRTPS sends invalid pre-emptive ACKs -- patch the message so we can process it */
+ if (! NN_STRICT_P (rst->gv->config) && vendor_is_eprosima (rst->vendor) &&
+ fromSN (msg->readerSNState.bitmap_base) == 0 && msg->readerSNState.numbits == 0)
+ msg->readerSNState.bitmap_base = toSN (1);
else
- {
- /* RTI generates AckNacks with bitmapBase = 0 and numBits = 0
- (and possibly others that I don't know about) - their
- Wireshark RTPS dissector says that such a message has a
- length-0 bitmap, which is to expected given the way the
- length is computed from numbits */
- if (fromSN (msg->readerSNState.bitmap_base) == 0 &&
- msg->readerSNState.numbits == 0)
- ; /* accept this one known case */
- else if (msg->readerSNState.numbits == 0)
- ; /* maybe RTI, definitely Twinoaks */
- else
- return 0;
- }
+ return 0;
}
/* Given the number of bits, we can compute the size of the AckNack
submessage, and verify that the submessage is large enough */
if (size < ACKNACK_SIZE (msg->readerSNState.numbits))
return 0;
- count = (nn_count_t *) ((char *) &msg->readerSNState + NN_SEQUENCE_NUMBER_SET_SIZE (msg->readerSNState.numbits));
+ count = (nn_count_t *) ((char *) &msg->bits + NN_SEQUENCE_NUMBER_SET_BITS_SIZE (msg->readerSNState.numbits));
if (byteswap)
{
- bswap_sequence_number_set_bitmap (&msg->readerSNState);
+ bswap_sequence_number_set_bitmap (&msg->readerSNState, msg->bits);
*count = bswap4 (*count);
}
return 1;
@@ -181,16 +164,13 @@ static int valid_Gap (Gap_t *msg, size_t size, int byteswap)
if (fromSN (msg->gapStart) <= 0)
return 0;
if (!valid_sequence_number_set (&msg->gapList))
- {
- if (NN_STRICT_P || msg->gapList.numbits != 0)
- return 0;
- }
+ return 0;
/* One would expect gapStart < gapList.base, but it is not required by
the spec for the GAP to valid. */
if (size < GAP_SIZE (msg->gapList.numbits))
return 0;
if (byteswap)
- bswap_sequence_number_set_bitmap (&msg->gapList);
+ bswap_sequence_number_set_bitmap (&msg->gapList, msg->bits);
return 1;
}
@@ -251,24 +231,9 @@ static int valid_Heartbeat (Heartbeat_t *msg, size_t size, int byteswap)
}
msg->readerId = nn_ntoh_entityid (msg->readerId);
msg->writerId = nn_ntoh_entityid (msg->writerId);
- /* Validation following 8.3.7.5.3 */
- if (fromSN (msg->firstSN) <= 0 ||
- /* fromSN (msg->lastSN) <= 0 || -- implicit in last < first */
- fromSN (msg->lastSN) < fromSN (msg->firstSN))
- {
- if (NN_STRICT_P)
- return 0;
- else
- {
- /* Note that we don't actually know the set of all possible
- malformed messages that we have to process, so we stick to
- the ones we've seen */
- if (fromSN (msg->firstSN) == fromSN (msg->lastSN) + 1)
- ; /* ok */
- else
- return 0;
- }
- }
+ /* Validation following 8.3.7.5.3; lastSN + 1 == firstSN: no data */
+ if (fromSN (msg->firstSN) <= 0 || fromSN (msg->lastSN) + 1 < fromSN (msg->firstSN))
+ return 0;
return 1;
}
@@ -311,19 +276,18 @@ static int valid_NackFrag (NackFrag_t *msg, size_t size, int byteswap)
submessage, and verify that the submessage is large enough */
if (size < NACKFRAG_SIZE (msg->fragmentNumberState.numbits))
return 0;
- count = (nn_count_t *) ((char *) &msg->fragmentNumberState +
- NN_FRAGMENT_NUMBER_SET_SIZE (msg->fragmentNumberState.numbits));
+ count = (nn_count_t *) ((char *) &msg->bits + NN_FRAGMENT_NUMBER_SET_BITS_SIZE (msg->fragmentNumberState.numbits));
if (byteswap)
{
- bswap_fragment_number_set_bitmap (&msg->fragmentNumberState);
+ bswap_fragment_number_set_bitmap (&msg->fragmentNumberState, msg->bits);
*count = bswap4 (*count);
}
return 1;
}
-static void set_sampleinfo_proxy_writer (struct nn_rsample_info *sampleinfo, nn_guid_t * pwr_guid)
+static void set_sampleinfo_proxy_writer (struct nn_rsample_info *sampleinfo, nn_guid_t *pwr_guid)
{
- struct proxy_writer * pwr = ephash_lookup_proxy_writer_guid (pwr_guid);
+ struct proxy_writer * pwr = ephash_lookup_proxy_writer_guid (sampleinfo->rst->gv->guid_hash, pwr_guid);
sampleinfo->pwr = pwr;
}
@@ -386,6 +350,8 @@ static int valid_Data (const struct receiver_state *rst, struct nn_rmsg *rmsg, D
src.encoding = (msg->x.smhdr.flags & SMFLAG_ENDIANNESS) ? PL_CDR_LE : PL_CDR_BE;
src.buf = ptr;
src.bufsz = (unsigned) ((unsigned char *) msg + size - src.buf); /* end of message, that's all we know */
+ src.factory = NULL;
+ src.logconfig = &rst->gv->logconfig;
/* just a quick scan, gathering only what we _really_ need */
if ((ptr = nn_plist_quickscan (sampleinfo, rmsg, &src)) == NULL)
return 0;
@@ -460,7 +426,7 @@ static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rms
pwr_guid.prefix = rst->src_guid_prefix;
pwr_guid.entityid = msg->x.writerId;
- if (NN_STRICT_P && msg->fragmentSize <= 1024 && msg->fragmentSize < config.fragment_size)
+ if (NN_STRICT_P (rst->gv->config) && msg->fragmentSize <= 1024 && msg->fragmentSize < rst->gv->config.fragment_size)
{
/* Spec says fragments must > 1kB; not allowing 1024 bytes is IMHO
totally ridiculous; and I really don't care how small the
@@ -471,7 +437,7 @@ static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rms
}
if (msg->fragmentSize == 0 || msg->fragmentStartingNum == 0 || msg->fragmentsInSubmessage == 0)
return 0;
- if (NN_STRICT_P && msg->fragmentSize >= msg->sampleSize)
+ if (NN_STRICT_P (rst->gv->config) && msg->fragmentSize >= msg->sampleSize)
/* may not fragment if not needed -- but I don't care */
return 0;
if ((msg->fragmentStartingNum + msg->fragmentsInSubmessage - 2) * msg->fragmentSize >= msg->sampleSize)
@@ -506,6 +472,8 @@ static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rms
src.encoding = (msg->x.smhdr.flags & SMFLAG_ENDIANNESS) ? PL_CDR_LE : PL_CDR_BE;
src.buf = ptr;
src.bufsz = (unsigned) ((unsigned char *) msg + size - src.buf); /* end of message, that's all we know */
+ src.factory = NULL;
+ src.logconfig = &rst->gv->logconfig;
/* just a quick scan, gathering only what we _really_ need */
if ((ptr = nn_plist_quickscan (sampleinfo, rmsg, &src)) == NULL)
return 0;
@@ -563,7 +531,6 @@ static int add_Gap (struct nn_xmsg *msg, struct writer *wr, struct proxy_reader
struct nn_xmsg_marker sm_marker;
Gap_t *gap;
ASSERT_MUTEX_HELD (wr->e.lock);
- assert (numbits > 0);
gap = nn_xmsg_append (msg, &sm_marker, GAP_SIZE (numbits));
nn_xmsg_submsg_init (msg, sm_marker, SMID_GAP);
gap->readerId = nn_hton_entityid (prd->e.guid.entityid);
@@ -571,7 +538,7 @@ static int add_Gap (struct nn_xmsg *msg, struct writer *wr, struct proxy_reader
gap->gapStart = toSN (start);
gap->gapList.bitmap_base = toSN (base);
gap->gapList.numbits = numbits;
- memcpy (gap->gapList.bits, bits, NN_SEQUENCE_NUMBER_SET_BITS_SIZE (numbits));
+ memcpy (gap->bits, bits, NN_SEQUENCE_NUMBER_SET_BITS_SIZE (numbits));
nn_xmsg_submsg_setnext (msg, sm_marker);
return 0;
}
@@ -583,7 +550,7 @@ static void force_heartbeat_to_peer (struct writer *wr, const struct whc_state *
ASSERT_MUTEX_HELD (&wr->e.lock);
assert (wr->reliable);
- m = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_CONTROL);
+ m = nn_xmsg_new (wr->e.gv->xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_CONTROL);
if (nn_xmsg_setdstPRD (m, prd) < 0)
{
/* If we don't have an address, give up immediately */
@@ -593,8 +560,8 @@ static void force_heartbeat_to_peer (struct writer *wr, const struct whc_state *
/* Send a Heartbeat just to this peer */
add_Heartbeat (m, wr, whcst, hbansreq, prd->e.guid.entityid, 0);
- DDS_TRACE("force_heartbeat_to_peer: "PGUIDFMT" -> "PGUIDFMT" - queue for transmit\n",
- PGUID (wr->e.guid), PGUID (prd->e.guid));
+ ETRACE (wr, "force_heartbeat_to_peer: "PGUIDFMT" -> "PGUIDFMT" - queue for transmit\n",
+ PGUID (wr->e.guid), PGUID (prd->e.guid));
qxev_msg (wr->evq, m);
}
@@ -619,12 +586,12 @@ static int acknack_is_nack (const AckNack_t *msg)
even we generate them) */
return 0;
for (i = 0; i < (int) NN_SEQUENCE_NUMBER_SET_BITS_SIZE (msg->readerSNState.numbits) / 4 - 1; i++)
- x |= msg->readerSNState.bits[i];
+ x |= msg->bits[i];
if ((msg->readerSNState.numbits % 32) == 0)
mask = ~0u;
else
mask = ~(~0u >> (msg->readerSNState.numbits % 32));
- x |= msg->readerSNState.bits[i] & mask;
+ x |= msg->bits[i] & mask;
return x != 0;
}
@@ -656,7 +623,7 @@ static int accept_ack_or_hb_w_timeout (nn_count_t new_count, nn_count_t *exp_cou
return 1;
}
-static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const AckNack_t *msg, nn_ddsi_time_t timestamp)
+static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const AckNack_t *msg, nn_wctime_t timestamp)
{
struct proxy_reader *prd;
struct wr_prd_match *rn;
@@ -678,56 +645,53 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
seqno_t max_seq_in_reply;
struct whc_node *deferred_free_list = NULL;
struct whc_state whcst;
- unsigned i;
int hb_sent_in_response = 0;
memset (gapbits, 0, sizeof (gapbits));
- countp = (nn_count_t *) ((char *) msg + offsetof (AckNack_t, readerSNState) +
- NN_SEQUENCE_NUMBER_SET_SIZE (msg->readerSNState.numbits));
+ countp = (nn_count_t *) ((char *) msg + offsetof (AckNack_t, bits) + NN_SEQUENCE_NUMBER_SET_BITS_SIZE (msg->readerSNState.numbits));
src.prefix = rst->src_guid_prefix;
src.entityid = msg->readerId;
dst.prefix = rst->dst_guid_prefix;
dst.entityid = msg->writerId;
- DDS_TRACE("ACKNACK(%s#%"PRId32":%"PRId64"/%"PRIu32":", msg->smhdr.flags & ACKNACK_FLAG_FINAL ? "F" : "",
- *countp, fromSN (msg->readerSNState.bitmap_base), msg->readerSNState.numbits);
- for (i = 0; i < msg->readerSNState.numbits; i++)
- DDS_TRACE("%c", nn_bitset_isset (msg->readerSNState.numbits, msg->readerSNState.bits, i) ? '1' : '0');
+ RSTTRACE ("ACKNACK(%s#%"PRId32":%"PRId64"/%"PRIu32":", msg->smhdr.flags & ACKNACK_FLAG_FINAL ? "F" : "",
+ *countp, fromSN (msg->readerSNState.bitmap_base), msg->readerSNState.numbits);
+ for (uint32_t i = 0; i < msg->readerSNState.numbits; i++)
+ RSTTRACE ("%c", nn_bitset_isset (msg->readerSNState.numbits, msg->bits, i) ? '1' : '0');
seqbase = fromSN (msg->readerSNState.bitmap_base);
if (!rst->forme)
{
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst));
return 1;
}
- if ((wr = ephash_lookup_writer_guid (&dst)) == NULL)
+ if ((wr = ephash_lookup_writer_guid (rst->gv->guid_hash, &dst)) == NULL)
{
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"?)", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT"?)", PGUID (src), PGUID (dst));
return 1;
}
/* Always look up the proxy reader -- even though we don't need for
the normal pure ack steady state. If (a big "if"!) this shows up
as a significant portion of the time, we can always rewrite it to
only retrieve it when needed. */
- if ((prd = ephash_lookup_proxy_reader_guid (&src)) == NULL)
+ if ((prd = ephash_lookup_proxy_reader_guid (rst->gv->guid_hash, &src)) == NULL)
{
- DDS_TRACE(" "PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst));
return 1;
}
/* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
- if (prd->assert_pp_lease)
- lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow);
+ lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow);
if (!wr->reliable) /* note: reliability can't be changed */
{
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not a reliable writer!)", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT" not a reliable writer!)", PGUID (src), PGUID (dst));
return 1;
}
ddsrt_mutex_lock (&wr->e.lock);
if ((rn = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &src)) == NULL)
{
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not a connection)", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT" not a connection)", PGUID (src), PGUID (dst));
goto out;
}
@@ -747,23 +711,22 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
if (!accept_ack_or_hb_w_timeout (*countp, &rn->next_acknack, tnow, &rn->t_acknack_accepted, is_preemptive_ack))
{
- DDS_TRACE(" ["PGUIDFMT" -> "PGUIDFMT"])", PGUID (src), PGUID (dst));
+ RSTTRACE (" ["PGUIDFMT" -> "PGUIDFMT"])", PGUID (src), PGUID (dst));
goto out;
}
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst));
/* Update latency estimates if we have a timestamp -- won't actually
work so well if the timestamp can be a left over from some other
submessage -- but then, it is no more than a quick hack at the
moment. */
- if (config.meas_hb_to_ack_latency && valid_ddsi_timestamp (timestamp))
+ if (rst->gv->config.meas_hb_to_ack_latency && timestamp.v)
{
nn_wctime_t tstamp_now = now ();
- nn_wctime_t tstamp_msg = nn_wctime_from_ddsi_time (timestamp);
- nn_lat_estim_update (&rn->hb_to_ack_latency, tstamp_now.v - tstamp_msg.v);
- if ((dds_get_log_mask() & DDS_LC_TRACE) && tstamp_now.v > rn->hb_to_ack_latency_tlastlog.v + 10 * T_SECOND)
+ nn_lat_estim_update (&rn->hb_to_ack_latency, tstamp_now.v - timestamp.v);
+ if ((rst->gv->logconfig.c.mask & DDS_LC_TRACE) && tstamp_now.v > rn->hb_to_ack_latency_tlastlog.v + 10 * T_SECOND)
{
- nn_lat_estim_log (DDS_LC_TRACE, NULL, &rn->hb_to_ack_latency);
+ nn_lat_estim_log (DDS_LC_TRACE, &rst->gv->logconfig, NULL, &rn->hb_to_ack_latency);
rn->hb_to_ack_latency_tlastlog = tstamp_now;
}
}
@@ -783,7 +746,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
}
ddsrt_avl_augment_update (&wr_readers_treedef, rn);
n = remove_acked_messages (wr, &whcst, &deferred_free_list);
- DDS_TRACE(" ACK%"PRId64" RM%u", n_ack, n);
+ RSTTRACE (" ACK%"PRId64" RM%u", n_ack, n);
}
else
{
@@ -793,7 +756,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
/* If this reader was marked as "non-responsive" in the past, it's now responding again,
so update its status */
- if (rn->seq == MAX_SEQ_NUMBER && prd->c.xqos->reliability.kind == NN_RELIABLE_RELIABILITY_QOS)
+ if (rn->seq == MAX_SEQ_NUMBER && prd->c.xqos->reliability.kind == DDS_RELIABILITY_RELIABLE)
{
seqno_t oldest_seq;
oldest_seq = WHCST_ISEMPTY(&whcst) ? wr->seq : whcst.max_seq;
@@ -809,7 +772,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
rn->seq = wr->seq;
}
ddsrt_avl_augment_update (&wr_readers_treedef, rn);
- DDS_LOG(DDS_LC_THROTTLE, "writer "PGUIDFMT" considering reader "PGUIDFMT" responsive again\n", PGUID (wr->e.guid), PGUID (rn->prd_guid));
+ DDS_CLOG (DDS_LC_THROTTLE, &rst->gv->logconfig, "writer "PGUIDFMT" considering reader "PGUIDFMT" responsive again\n", PGUID (wr->e.guid), PGUID (rn->prd_guid));
}
/* Second, the NACK bits (literally, that is). To do so, attempt to
@@ -821,7 +784,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
max_seq_in_reply = 0;
if (!rn->has_replied_to_hb && seqbase > 1 && is_pure_nonhist_ack)
{
- DDS_TRACE(" setting-has-replied-to-hb");
+ RSTTRACE (" setting-has-replied-to-hb");
rn->has_replied_to_hb = 1;
/* walk the whole tree to ensure all proxy readers for this writer
have their unack'ed info updated */
@@ -835,19 +798,19 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
reader start-up and we respond with a heartbeat and, if we have
data in our WHC, we start sending it regardless of whether the
remote reader asked for it */
- DDS_TRACE(" preemptive-nack");
+ RSTTRACE (" preemptive-nack");
if (WHCST_ISEMPTY(&whcst))
{
- DDS_TRACE(" whc-empty ");
+ RSTTRACE (" whc-empty ");
force_heartbeat_to_peer (wr, &whcst, prd, 0);
hb_sent_in_response = 1;
}
else
{
- DDS_TRACE(" rebase ");
+ RSTTRACE (" rebase ");
force_heartbeat_to_peer (wr, &whcst, prd, 0);
hb_sent_in_response = 1;
- numbits = config.accelerate_rexmit_block_size;
+ numbits = rst->gv->config.accelerate_rexmit_block_size;
seqbase = whcst.min_seq;
}
}
@@ -860,19 +823,19 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
that doesn't play too nicely with this. */
if (is_pure_nonhist_ack)
{
- DDS_TRACE(" happy-now");
+ RSTTRACE (" happy-now");
rn->assumed_in_sync = 1;
}
- else if (msg->readerSNState.numbits < config.accelerate_rexmit_block_size)
+ else if (msg->readerSNState.numbits < rst->gv->config.accelerate_rexmit_block_size)
{
- DDS_TRACE(" accelerating");
+ RSTTRACE (" accelerating");
accelerate_rexmit = 1;
- if (accelerate_rexmit && numbits < config.accelerate_rexmit_block_size)
- numbits = config.accelerate_rexmit_block_size;
+ if (accelerate_rexmit && numbits < rst->gv->config.accelerate_rexmit_block_size)
+ numbits = rst->gv->config.accelerate_rexmit_block_size;
}
else
{
- DDS_TRACE(" complying");
+ RSTTRACE (" complying");
}
}
/* Retransmit requested messages, including whatever we decided to
@@ -887,28 +850,30 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
a future request'll fix it. */
enqueued = 1;
seq_xmit = READ_SEQ_XMIT(wr);
- for (i = 0; i < numbits && seqbase + i <= seq_xmit && enqueued; i++)
+ const bool gap_for_already_acked = vendor_is_eclipse (rst->vendor) && prd->c.xqos->durability.kind == DDS_DURABILITY_VOLATILE && seqbase <= rn->seq;
+ const seqno_t min_seq_to_rexmit = gap_for_already_acked ? rn->seq + 1 : 0;
+ for (uint32_t i = 0; i < numbits && seqbase + i <= seq_xmit && enqueued; i++)
{
/* Accelerated schedule may run ahead of sequence number set
contained in the acknack, and assumes all messages beyond the
set are NACK'd -- don't feel like tracking where exactly we
left off ... */
- if (i >= msg->readerSNState.numbits || nn_bitset_isset (numbits, msg->readerSNState.bits, i))
+ if (i >= msg->readerSNState.numbits || nn_bitset_isset (numbits, msg->bits, i))
{
seqno_t seq = seqbase + i;
struct whc_borrowed_sample sample;
- if (whc_borrow_sample (wr->whc, seq, &sample))
+ if (seqbase + i >= min_seq_to_rexmit && whc_borrow_sample (wr->whc, seq, &sample))
{
if (!wr->retransmitting && sample.unacked)
writer_set_retransmitting (wr);
- if (config.retransmit_merging != REXMIT_MERGE_NEVER && rn->assumed_in_sync)
+ if (rst->gv->config.retransmit_merging != REXMIT_MERGE_NEVER && rn->assumed_in_sync)
{
/* send retransmit to all receivers, but skip if recently done */
nn_mtime_t tstamp = now_mt ();
- if (tstamp.v > sample.last_rexmit_ts.v + config.retransmit_merging_period)
+ if (tstamp.v > sample.last_rexmit_ts.v + rst->gv->config.retransmit_merging_period)
{
- DDS_TRACE(" RX%"PRId64, seqbase + i);
+ RSTTRACE (" RX%"PRId64, seqbase + i);
enqueued = (enqueue_sample_wrlock_held (wr, seq, sample.plist, sample.serdata, NULL, 0) >= 0);
if (enqueued)
{
@@ -919,13 +884,13 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
}
else
{
- DDS_TRACE(" RX%"PRId64" (merged)", seqbase + i);
+ RSTTRACE (" RX%"PRId64" (merged)", seqbase + i);
}
}
else
{
/* no merging, send directed retransmit */
- DDS_TRACE(" RX%"PRId64"", seqbase + i);
+ RSTTRACE (" RX%"PRId64"", seqbase + i);
enqueued = (enqueue_sample_wrlock_held (wr, seq, sample.plist, sample.serdata, prd, 0) >= 0);
if (enqueued)
{
@@ -939,21 +904,21 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
}
else if (gapstart == -1)
{
- DDS_TRACE(" M%"PRId64, seqbase + i);
+ RSTTRACE (" M%"PRId64, seqbase + i);
gapstart = seqbase + i;
gapend = gapstart + 1;
msgs_lost++;
}
else if (seqbase + i == gapend)
{
- DDS_TRACE(" M%"PRId64, seqbase + i);
+ RSTTRACE (" M%"PRId64, seqbase + i);
gapend = seqbase + i + 1;
msgs_lost++;
}
else if (seqbase + i - gapend < 256)
{
- unsigned idx = (unsigned) (seqbase + i - gapend);
- DDS_TRACE(" M%"PRId64, seqbase + i);
+ uint32_t idx = (uint32_t) (seqbase + i - gapend);
+ RSTTRACE (" M%"PRId64, seqbase + i);
gapnumbits = idx + 1;
nn_bitset_set (gapnumbits, gapbits, idx);
msgs_lost++;
@@ -961,7 +926,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
}
}
if (!enqueued)
- DDS_TRACE(" rexmit-limit-hit");
+ RSTTRACE (" rexmit-limit-hit");
/* Generate a Gap message if some of the sequence is missing */
if (gapstart > 0)
{
@@ -973,23 +938,16 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
to the remote reader. */
gapend = grow_gap_to_next_seq (wr, gapend);
}
- if (gapnumbits == 0)
- {
- /* Avoid sending an invalid bitset */
- gapnumbits = 1;
- nn_bitset_set (gapnumbits, gapbits, 0);
- gapend--;
- }
/* The non-bitmap part of a gap message says everything <=
gapend-1 is no more (so the maximum sequence number it informs
the peer of is gapend-1); each bit adds one sequence number to
that. */
if (gapend-1 + gapnumbits > max_seq_in_reply)
max_seq_in_reply = gapend-1 + gapnumbits;
- DDS_TRACE(" XGAP%"PRId64"..%"PRId64"/%u:", gapstart, gapend, gapnumbits);
- for (i = 0; i < gapnumbits; i++)
- DDS_TRACE("%c", nn_bitset_isset (gapnumbits, gapbits, i) ? '1' : '0');
- m = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_CONTROL);
+ RSTTRACE (" XGAP%"PRId64"..%"PRId64"/%u:", gapstart, gapend, gapnumbits);
+ for (uint32_t i = 0; i < gapnumbits; i++)
+ RSTTRACE ("%c", nn_bitset_isset (gapnumbits, gapbits, i) ? '1' : '0');
+ m = nn_xmsg_new (rst->gv->xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_CONTROL);
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
nn_xmsg_setencoderid (m, wr->partition_id);
#endif
@@ -1011,7 +969,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
it might ... [NB writer->seq is the last msg sent so far] */
if (msgs_sent && max_seq_in_reply < seq_xmit)
{
- DDS_TRACE(" rexmit#%"PRIu32" maxseq:%"PRId64"<%"PRId64"<=%"PRId64"", msgs_sent, max_seq_in_reply, seq_xmit, wr->seq);
+ RSTTRACE (" rexmit#%"PRIu32" maxseq:%"PRId64"<%"PRId64"<=%"PRId64"", msgs_sent, max_seq_in_reply, seq_xmit, wr->seq);
force_heartbeat_to_peer (wr, &whcst, prd, 1);
hb_sent_in_response = 1;
@@ -1026,7 +984,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
now if we haven't done so already */
if (!(msg->smhdr.flags & ACKNACK_FLAG_FINAL) && !hb_sent_in_response)
force_heartbeat_to_peer (wr, &whcst, prd, 0);
- DDS_TRACE(")");
+ RSTTRACE (")");
out:
ddsrt_mutex_unlock (&wr->e.lock);
whc_free_deferred_free_list (wr->whc, deferred_free_list);
@@ -1085,13 +1043,14 @@ struct handle_Heartbeat_helper_arg {
struct receiver_state *rst;
const Heartbeat_t *msg;
struct proxy_writer *pwr;
- nn_ddsi_time_t timestamp;
+ nn_wctime_t timestamp;
nn_etime_t tnow;
nn_mtime_t tnow_mt;
};
static void handle_Heartbeat_helper (struct pwr_rd_match * const wn, struct handle_Heartbeat_helper_arg * const arg)
{
+ struct receiver_state * const rst = arg->rst;
Heartbeat_t const * const msg = arg->msg;
struct proxy_writer * const pwr = arg->pwr;
seqno_t refseq;
@@ -1101,7 +1060,7 @@ static void handle_Heartbeat_helper (struct pwr_rd_match * const wn, struct hand
/* Not supposed to respond to repeats and old heartbeats. */
if (!accept_ack_or_hb_w_timeout (msg->count, &wn->next_heartbeat, arg->tnow, &wn->t_heartbeat_accepted, 0))
{
- DDS_TRACE(" ("PGUIDFMT")", PGUID (wn->rd_guid));
+ RSTTRACE (" ("PGUIDFMT")", PGUID (wn->rd_guid));
return;
}
@@ -1112,7 +1071,7 @@ static void handle_Heartbeat_helper (struct pwr_rd_match * const wn, struct hand
refseq = nn_reorder_next_seq (pwr->reorder) - 1;
else
refseq = nn_reorder_next_seq (wn->u.not_in_sync.reorder) - 1;
- DDS_TRACE(" "PGUIDFMT"@%"PRId64"%s", PGUID (wn->rd_guid), refseq, (wn->in_sync == PRMSS_SYNC) ? "(sync)" : (wn->in_sync == PRMSS_TLCATCHUP) ? "(tlcatchup)" : "");
+ RSTTRACE (" "PGUIDFMT"@%"PRId64"%s", PGUID (wn->rd_guid), refseq, (wn->in_sync == PRMSS_SYNC) ? "(sync)" : (wn->in_sync == PRMSS_TLCATCHUP) ? "(tlcatchup)" : "");
/* Reschedule AckNack transmit if deemed appropriate; unreliable
readers have acknack_xevent == NULL and can't do this.
@@ -1127,13 +1086,13 @@ static void handle_Heartbeat_helper (struct pwr_rd_match * const wn, struct hand
tsched.v = T_NEVER;
if (pwr->last_seq > refseq)
{
- DDS_TRACE("/NAK");
- if (arg->tnow_mt.v >= wn->t_last_nack.v + config.nack_delay || refseq >= wn->seq_last_nack)
+ RSTTRACE ("/NAK");
+ if (arg->tnow_mt.v >= wn->t_last_nack.v + rst->gv->config.nack_delay || refseq >= wn->seq_last_nack)
tsched = arg->tnow_mt;
else
{
- tsched.v = arg->tnow_mt.v + config.nack_delay;
- DDS_TRACE("d");
+ tsched.v = arg->tnow_mt.v + rst->gv->config.nack_delay;
+ RSTTRACE ("d");
}
}
else if (!(msg->smhdr.flags & HEARTBEAT_FLAG_FINAL))
@@ -1142,13 +1101,13 @@ static void handle_Heartbeat_helper (struct pwr_rd_match * const wn, struct hand
}
if (resched_xevent_if_earlier (wn->acknack_xevent, tsched))
{
- if (config.meas_hb_to_ack_latency && valid_ddsi_timestamp (arg->timestamp))
- wn->hb_timestamp = nn_wctime_from_ddsi_time (arg->timestamp);
+ if (rst->gv->config.meas_hb_to_ack_latency && arg->timestamp.v)
+ wn->hb_timestamp = arg->timestamp;
}
}
}
-static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Heartbeat_t *msg, nn_ddsi_time_t timestamp)
+static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Heartbeat_t *msg, nn_wctime_t timestamp)
{
/* We now cheat: and process the heartbeat for _all_ readers,
always, regardless of the destination address in the Heartbeat
@@ -1172,44 +1131,48 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct
dst.prefix = rst->dst_guid_prefix;
dst.entityid = msg->readerId;
- DDS_TRACE("HEARTBEAT(%s#%"PRId32":%"PRId64"..%"PRId64" ", msg->smhdr.flags & HEARTBEAT_FLAG_FINAL ? "F" : "", msg->count, firstseq, lastseq);
+ RSTTRACE ("HEARTBEAT(%s#%"PRId32":%"PRId64"..%"PRId64" ", msg->smhdr.flags & HEARTBEAT_FLAG_FINAL ? "F" : "", msg->count, firstseq, lastseq);
if (!rst->forme)
{
- DDS_TRACE(""PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst));
+ RSTTRACE (PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst));
return 1;
}
- if ((pwr = ephash_lookup_proxy_writer_guid (&src)) == NULL)
+ if ((pwr = ephash_lookup_proxy_writer_guid (rst->gv->guid_hash, &src)) == NULL)
{
- DDS_TRACE(""PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst));
+ RSTTRACE (PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst));
return 1;
}
- /* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
- if (pwr->assert_pp_lease)
- lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
+ /* liveliness is still only implemented partially (with all set to AUTOMATIC,
+ BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
+ lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
- DDS_TRACE(""PGUIDFMT" -> "PGUIDFMT":", PGUID (src), PGUID (dst));
+ RSTTRACE (PGUIDFMT" -> "PGUIDFMT":", PGUID (src), PGUID (dst));
ddsrt_mutex_lock (&pwr->e.lock);
+ if (pwr->n_reliable_readers == 0)
+ {
+ RSTTRACE (PGUIDFMT" -> "PGUIDFMT" no-reliable-readers)", PGUID (src), PGUID (dst));
+ ddsrt_mutex_unlock (&pwr->e.lock);
+ return 1;
+ }
+
if (!pwr->have_seen_heartbeat)
{
struct nn_rdata *gap;
struct nn_rsample_chain sc;
int refc_adjust = 0;
nn_reorder_result_t res;
-
nn_defrag_notegap (pwr->defrag, 1, lastseq + 1);
gap = nn_rdata_newgap (rmsg);
- if ((res = nn_reorder_gap (&sc, pwr->reorder, gap, 1, lastseq + 1, &refc_adjust)) > 0)
- {
- if (pwr->deliver_synchronously)
- deliver_user_data_synchronously (&sc);
- else
- nn_dqueue_enqueue (pwr->dqueue, &sc, res);
- }
+ res = nn_reorder_gap (&sc, pwr->reorder, gap, 1, lastseq + 1, &refc_adjust);
+ /* proxy writer is not accepting data until it has received a heartbeat, so
+ there can't be any data to deliver */
+ assert (res <= 0);
+ (void) res;
nn_fragchain_adjust_refcount (gap, refc_adjust);
pwr->have_seen_heartbeat = 1;
}
@@ -1243,7 +1206,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct
if ((res = nn_reorder_gap (&sc, pwr->reorder, gap, 1, firstseq, &refc_adjust)) > 0)
{
if (pwr->deliver_synchronously)
- deliver_user_data_synchronously (&sc);
+ deliver_user_data_synchronously (&sc, NULL);
else
nn_dqueue_enqueue (pwr->dqueue, &sc, res);
}
@@ -1262,14 +1225,19 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct
case PRMSS_OUT_OF_SYNC: {
struct nn_reorder *ro = wn->u.not_in_sync.reorder;
if ((res = nn_reorder_gap (&sc, ro, gap, 1, firstseq, &refc_adjust)) > 0)
- nn_dqueue_enqueue1 (pwr->dqueue, &wn->rd_guid, &sc, res);
+ {
+ if (pwr->deliver_synchronously)
+ deliver_user_data_synchronously (&sc, &wn->rd_guid);
+ else
+ nn_dqueue_enqueue1 (pwr->dqueue, &wn->rd_guid, &sc, res);
+ }
last_deliv_seq = nn_reorder_next_seq (wn->u.not_in_sync.reorder) - 1;
}
}
if (wn->u.not_in_sync.end_of_tl_seq == MAX_SEQ_NUMBER)
{
- wn->u.not_in_sync.end_of_out_of_sync_seq = wn->u.not_in_sync.end_of_tl_seq = fromSN (msg->lastSN);
- DDS_TRACE(" end-of-tl-seq(rd "PGUIDFMT" #%"PRId64")", PGUID(wn->rd_guid), wn->u.not_in_sync.end_of_tl_seq);
+ wn->u.not_in_sync.end_of_tl_seq = fromSN (msg->lastSN);
+ RSTTRACE (" end-of-tl-seq(rd "PGUIDFMT" #%"PRId64")", PGUID(wn->rd_guid), wn->u.not_in_sync.end_of_tl_seq);
}
maybe_set_reader_in_sync (pwr, wn, last_deliv_seq);
}
@@ -1283,7 +1251,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct
arg.tnow = tnow;
arg.tnow_mt = now_mt ();
handle_forall_destinations (&dst, pwr, (ddsrt_avl_walk_t) handle_Heartbeat_helper, &arg);
- DDS_TRACE(")");
+ RSTTRACE (")");
ddsrt_mutex_unlock (&pwr->e.lock);
return 1;
@@ -1301,24 +1269,23 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime
dst.prefix = rst->dst_guid_prefix;
dst.entityid = msg->readerId;
- DDS_TRACE("HEARTBEATFRAG(#%"PRId32":%"PRId64"/[1,%u]", msg->count, seq, fragnum+1);
+ RSTTRACE ("HEARTBEATFRAG(#%"PRId32":%"PRId64"/[1,%u]", msg->count, seq, fragnum+1);
if (!rst->forme)
{
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst));
return 1;
}
- if ((pwr = ephash_lookup_proxy_writer_guid (&src)) == NULL)
+ if ((pwr = ephash_lookup_proxy_writer_guid (rst->gv->guid_hash, &src)) == NULL)
{
- DDS_TRACE(" "PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst));
return 1;
}
/* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
- if (pwr->assert_pp_lease)
- lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
+ lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst));
ddsrt_mutex_lock (&pwr->e.lock);
if (seq > pwr->last_seq)
@@ -1339,7 +1306,7 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime
handle_Heartbeat's scheduling of an AckNack event when it must
respond. Why? Just because. */
if (ddsrt_avl_is_empty (&pwr->readers) || pwr->local_matching_inprogress)
- DDS_TRACE(" no readers");
+ RSTTRACE (" no readers");
else
{
struct pwr_rd_match *m = NULL;
@@ -1377,25 +1344,26 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime
}
if (m == NULL)
- DDS_TRACE(" no interested reliable readers");
+ RSTTRACE (" no interested reliable readers");
else
{
/* Check if we are missing something */
- union {
- struct nn_fragment_number_set set;
- char pad[NN_FRAGMENT_NUMBER_SET_SIZE (256)];
+ DDSRT_STATIC_ASSERT ((NN_FRAGMENT_NUMBER_SET_MAX_BITS % 32) == 0);
+ struct {
+ struct nn_fragment_number_set_header set;
+ uint32_t bits[NN_FRAGMENT_NUMBER_SET_MAX_BITS / 32];
} nackfrag;
- if (nn_defrag_nackmap (pwr->defrag, seq, fragnum, &nackfrag.set, 256) > 0)
+ if (nn_defrag_nackmap (pwr->defrag, seq, fragnum, &nackfrag.set, nackfrag.bits, NN_FRAGMENT_NUMBER_SET_MAX_BITS) > 0)
{
/* Yes we are (note that this potentially also happens for
samples we no longer care about) */
- int64_t delay = config.nack_delay;
- DDS_TRACE("/nackfrag");
+ int64_t delay = rst->gv->config.nack_delay;
+ RSTTRACE ("/nackfrag");
resched_xevent_if_earlier (m->acknack_xevent, add_duration_to_mtime (now_mt(), delay));
}
}
}
- DDS_TRACE(")");
+ RSTTRACE (")");
ddsrt_mutex_unlock (&pwr->e.lock);
return 1;
}
@@ -1409,64 +1377,62 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N
nn_guid_t src, dst;
nn_count_t *countp;
seqno_t seq = fromSN (msg->writerSN);
- unsigned i;
- countp = (nn_count_t *) ((char *) msg + offsetof (NackFrag_t, fragmentNumberState) + NN_FRAGMENT_NUMBER_SET_SIZE (msg->fragmentNumberState.numbits));
+ countp = (nn_count_t *) ((char *) msg + offsetof (NackFrag_t, bits) + NN_FRAGMENT_NUMBER_SET_BITS_SIZE (msg->fragmentNumberState.numbits));
src.prefix = rst->src_guid_prefix;
src.entityid = msg->readerId;
dst.prefix = rst->dst_guid_prefix;
dst.entityid = msg->writerId;
- DDS_TRACE("NACKFRAG(#%"PRId32":%"PRId64"/%u/%"PRIu32":", *countp, seq, msg->fragmentNumberState.bitmap_base, msg->fragmentNumberState.numbits);
- for (i = 0; i < msg->fragmentNumberState.numbits; i++)
- DDS_TRACE("%c", nn_bitset_isset (msg->fragmentNumberState.numbits, msg->fragmentNumberState.bits, i) ? '1' : '0');
+ RSTTRACE ("NACKFRAG(#%"PRId32":%"PRId64"/%u/%"PRIu32":", *countp, seq, msg->fragmentNumberState.bitmap_base, msg->fragmentNumberState.numbits);
+ for (uint32_t i = 0; i < msg->fragmentNumberState.numbits; i++)
+ RSTTRACE ("%c", nn_bitset_isset (msg->fragmentNumberState.numbits, msg->bits, i) ? '1' : '0');
if (!rst->forme)
{
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst));
return 1;
}
- if ((wr = ephash_lookup_writer_guid (&dst)) == NULL)
+ if ((wr = ephash_lookup_writer_guid (rst->gv->guid_hash, &dst)) == NULL)
{
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"?)", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT"?)", PGUID (src), PGUID (dst));
return 1;
}
/* Always look up the proxy reader -- even though we don't need for
the normal pure ack steady state. If (a big "if"!) this shows up
as a significant portion of the time, we can always rewrite it to
only retrieve it when needed. */
- if ((prd = ephash_lookup_proxy_reader_guid (&src)) == NULL)
+ if ((prd = ephash_lookup_proxy_reader_guid (rst->gv->guid_hash, &src)) == NULL)
{
- DDS_TRACE(" "PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst));
return 1;
}
/* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
- if (prd->assert_pp_lease)
- lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow);
+ lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow);
if (!wr->reliable) /* note: reliability can't be changed */
{
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not a reliable writer)", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT" not a reliable writer)", PGUID (src), PGUID (dst));
return 1;
}
ddsrt_mutex_lock (&wr->e.lock);
if ((rn = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &src)) == NULL)
{
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not a connection", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT" not a connection", PGUID (src), PGUID (dst));
goto out;
}
/* Ignore old NackFrags (see also handle_AckNack) */
if (*countp < rn->next_nackfrag)
{
- DDS_TRACE(" ["PGUIDFMT" -> "PGUIDFMT"]", PGUID (src), PGUID (dst));
+ RSTTRACE (" ["PGUIDFMT" -> "PGUIDFMT"]", PGUID (src), PGUID (dst));
goto out;
}
rn->next_nackfrag = *countp + 1;
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst));
/* Resend the requested fragments if we still have the sample, send
a Gap if we don't have them anymore. */
@@ -1474,10 +1440,10 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N
{
const unsigned base = msg->fragmentNumberState.bitmap_base - 1;
int enqueued = 1;
- DDS_TRACE(" scheduling requested frags ...\n");
- for (i = 0; i < msg->fragmentNumberState.numbits && enqueued; i++)
+ RSTTRACE (" scheduling requested frags ...\n");
+ for (uint32_t i = 0; i < msg->fragmentNumberState.numbits && enqueued; i++)
{
- if (nn_bitset_isset (msg->fragmentNumberState.numbits, msg->fragmentNumberState.bits, i))
+ if (nn_bitset_isset (msg->fragmentNumberState.numbits, msg->bits, i))
{
struct nn_xmsg *reply;
if (create_fragment_message (wr, seq, sample.plist, sample.serdata, base + i, prd, &reply, 0) < 0)
@@ -1492,8 +1458,8 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N
{
static uint32_t zero = 0;
struct nn_xmsg *m;
- DDS_TRACE(" msg not available: scheduling Gap\n");
- m = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_CONTROL);
+ RSTTRACE (" msg not available: scheduling Gap\n");
+ m = nn_xmsg_new (rst->gv->xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_CONTROL);
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
nn_xmsg_setencoderid (m, wr->partition_id);
#endif
@@ -1520,14 +1486,14 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N
out:
ddsrt_mutex_unlock (&wr->e.lock);
- DDS_TRACE(")");
+ RSTTRACE (")");
return 1;
}
static int handle_InfoDST (struct receiver_state *rst, const InfoDST_t *msg, const nn_guid_prefix_t *dst_prefix)
{
rst->dst_guid_prefix = nn_ntoh_guid_prefix (msg->guid_prefix);
- DDS_TRACE("INFODST(%"PRIx32":%"PRIx32":%"PRIx32")", PGUIDPREFIX (rst->dst_guid_prefix));
+ RSTTRACE ("INFODST(%"PRIx32":%"PRIx32":%"PRIx32")", PGUIDPREFIX (rst->dst_guid_prefix));
if (rst->dst_guid_prefix.u[0] == 0 && rst->dst_guid_prefix.u[1] == 0 && rst->dst_guid_prefix.u[2] == 0)
{
if (dst_prefix)
@@ -1539,7 +1505,8 @@ static int handle_InfoDST (struct receiver_state *rst, const InfoDST_t *msg, con
nn_guid_t dst;
dst.prefix = rst->dst_guid_prefix;
dst.entityid = to_entityid(NN_ENTITYID_PARTICIPANT);
- rst->forme = (ephash_lookup_participant_guid (&dst) != NULL) || is_deleted_participant_guid (&dst, DPG_LOCAL);
+ rst->forme = (ephash_lookup_participant_guid (rst->gv->guid_hash, &dst) != NULL ||
+ is_deleted_participant_guid (rst->gv->deleted_participants, &dst, DPG_LOCAL));
}
return 1;
}
@@ -1549,29 +1516,26 @@ static int handle_InfoSRC (struct receiver_state *rst, const InfoSRC_t *msg)
rst->src_guid_prefix = nn_ntoh_guid_prefix (msg->guid_prefix);
rst->protocol_version = msg->version;
rst->vendor = msg->vendorid;
- DDS_TRACE("INFOSRC(%"PRIx32":%"PRIx32":%"PRIx32" vendor %u.%u)",
+ RSTTRACE ("INFOSRC(%"PRIx32":%"PRIx32":%"PRIx32" vendor %u.%u)",
PGUIDPREFIX (rst->src_guid_prefix), rst->vendor.id[0], rst->vendor.id[1]);
return 1;
}
-static int handle_InfoTS (const InfoTS_t *msg, nn_ddsi_time_t *timestamp)
+static int handle_InfoTS (const struct receiver_state *rst, const InfoTS_t *msg, nn_wctime_t *timestamp)
{
- DDS_TRACE("INFOTS(");
+ RSTTRACE ("INFOTS(");
if (msg->smhdr.flags & INFOTS_INVALIDATE_FLAG)
{
- *timestamp = invalid_ddsi_timestamp;
- DDS_TRACE("invalidate");
+ *timestamp = NN_WCTIME_INVALID;
+ RSTTRACE ("invalidate");
}
else
{
- *timestamp = msg->time;
- if (dds_get_log_mask() & DDS_LC_TRACE)
- {
- nn_wctime_t t = nn_wctime_from_ddsi_time (* timestamp);
- DDS_TRACE("%d.%09d", (int) (t.v / 1000000000), (int) (t.v % 1000000000));
- }
+ *timestamp = nn_wctime_from_ddsi_time (msg->time);
+ if (rst->gv->logconfig.c.mask & DDS_LC_TRACE)
+ RSTTRACE ("%d.%09d", (int) (timestamp->v / 1000000000), (int) (timestamp->v % 1000000000));
}
- DDS_TRACE(")");
+ RSTTRACE (")");
return 1;
}
@@ -1591,7 +1555,7 @@ static int handle_one_gap (struct proxy_writer *pwr, struct pwr_rd_match *wn, se
if ((res = nn_reorder_gap (&sc, pwr->reorder, gap, a, b, refc_adjust)) > 0)
{
if (pwr->deliver_synchronously)
- deliver_user_data_synchronously (&sc);
+ deliver_user_data_synchronously (&sc, NULL);
else
nn_dqueue_enqueue (pwr->dqueue, &sc, res);
}
@@ -1600,7 +1564,7 @@ static int handle_one_gap (struct proxy_writer *pwr, struct pwr_rd_match *wn, se
anything useful, or there was insufficient memory to store it.
When the result is either ACCEPT or a sample chain, it clearly
meant something. */
- Q_STATIC_ASSERT_CODE (NN_REORDER_ACCEPT == 0);
+ DDSRT_STATIC_ASSERT_CODE (NN_REORDER_ACCEPT == 0);
if (res >= 0)
gap_was_valuable = 1;
@@ -1617,13 +1581,15 @@ static int handle_one_gap (struct proxy_writer *pwr, struct pwr_rd_match *wn, se
case PRMSS_TLCATCHUP:
break;
case PRMSS_OUT_OF_SYNC:
- if (a <= wn->u.not_in_sync.end_of_out_of_sync_seq)
+ if ((res = nn_reorder_gap (&sc, wn->u.not_in_sync.reorder, gap, a, b, refc_adjust)) > 0)
{
- if ((res = nn_reorder_gap (&sc, wn->u.not_in_sync.reorder, gap, a, b, refc_adjust)) > 0)
+ if (pwr->deliver_synchronously)
+ deliver_user_data_synchronously (&sc, &wn->rd_guid);
+ else
nn_dqueue_enqueue1 (pwr->dqueue, &wn->rd_guid, &sc, res);
- if (res >= 0)
- gap_was_valuable = 1;
}
+ if (res >= 0)
+ gap_was_valuable = 1;
break;
}
@@ -1659,8 +1625,8 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm
struct pwr_rd_match *wn;
nn_guid_t src, dst;
seqno_t gapstart, listbase;
- int64_t last_included_rel;
- unsigned listidx;
+ int32_t last_included_rel;
+ uint32_t listidx;
src.prefix = rst->src_guid_prefix;
src.entityid = msg->writerId;
@@ -1668,44 +1634,43 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm
dst.entityid = msg->readerId;
gapstart = fromSN (msg->gapStart);
listbase = fromSN (msg->gapList.bitmap_base);
- DDS_TRACE("GAP(%"PRId64"..%"PRId64"/%"PRIu32" ", gapstart, listbase, msg->gapList.numbits);
+ RSTTRACE ("GAP(%"PRId64"..%"PRId64"/%"PRIu32" ", gapstart, listbase, msg->gapList.numbits);
/* There is no _good_ reason for a writer to start the bitmap with a
1 bit, but check for it just in case, to reduce the number of
sequence number gaps to be processed. */
for (listidx = 0; listidx < msg->gapList.numbits; listidx++)
- if (!nn_bitset_isset (msg->gapList.numbits, msg->gapList.bits, listidx))
+ if (!nn_bitset_isset (msg->gapList.numbits, msg->bits, listidx))
break;
- last_included_rel = (int)listidx - 1;
+ last_included_rel = (int32_t) listidx - 1;
if (!rst->forme)
{
- DDS_TRACE(""PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst));
+ RSTTRACE (""PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst));
return 1;
}
- if ((pwr = ephash_lookup_proxy_writer_guid (&src)) == NULL)
+ if ((pwr = ephash_lookup_proxy_writer_guid (rst->gv->guid_hash, &src)) == NULL)
{
- DDS_TRACE(""PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst));
+ RSTTRACE (""PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst));
return 1;
}
/* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
- if (pwr->assert_pp_lease)
- lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
+ lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
ddsrt_mutex_lock (&pwr->e.lock);
if ((wn = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, &dst)) == NULL)
{
- DDS_TRACE(PGUIDFMT" -> "PGUIDFMT" not a connection)", PGUID (src), PGUID (dst));
+ RSTTRACE (PGUIDFMT" -> "PGUIDFMT" not a connection)", PGUID (src), PGUID (dst));
ddsrt_mutex_unlock (&pwr->e.lock);
return 1;
}
- DDS_TRACE(PGUIDFMT" -> "PGUIDFMT, PGUID (src), PGUID (dst));
+ RSTTRACE (PGUIDFMT" -> "PGUIDFMT, PGUID (src), PGUID (dst));
if (!pwr->have_seen_heartbeat && pwr->n_reliable_readers > 0)
{
- DDS_TRACE(": no heartbeat seen yet");
+ RSTTRACE (": no heartbeat seen yet");
ddsrt_mutex_unlock (&pwr->e.lock);
return 1;
}
@@ -1726,20 +1691,20 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm
}
while (listidx < msg->gapList.numbits)
{
- if (!nn_bitset_isset (msg->gapList.numbits, msg->gapList.bits, listidx))
+ if (!nn_bitset_isset (msg->gapList.numbits, msg->bits, listidx))
listidx++;
else
{
- unsigned j;
- for (j = listidx+1; j < msg->gapList.numbits; j++)
- if (!nn_bitset_isset (msg->gapList.numbits, msg->gapList.bits, j))
+ uint32_t j;
+ for (j = listidx + 1; j < msg->gapList.numbits; j++)
+ if (!nn_bitset_isset (msg->gapList.numbits, msg->bits, j))
break;
/* spec says gapList (2) identifies an additional list of sequence numbers that
are invalid (8.3.7.4.2), so by that rule an insane start would simply mean the
initial interval is to be ignored and the bitmap to be applied */
(void) handle_one_gap (pwr, wn, listbase + listidx, listbase + j, gap, &refc_adjust);
assert(j >= 1);
- last_included_rel = j - 1;
+ last_included_rel = (int32_t) j - 1;
listidx = j;
}
}
@@ -1758,7 +1723,7 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm
pwr->last_fragnum = ~0u;
pwr->last_fragnum_reset = 0;
}
- DDS_TRACE(")");
+ RSTTRACE (")");
ddsrt_mutex_unlock (&pwr->e.lock);
return 1;
}
@@ -1766,8 +1731,11 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm
static struct ddsi_serdata *get_serdata (struct ddsi_sertopic const * const topic, const struct nn_rdata *fragchain, uint32_t sz, int justkey, unsigned statusinfo, nn_wctime_t tstamp)
{
struct ddsi_serdata *sd = ddsi_serdata_from_ser (topic, justkey ? SDK_KEY : SDK_DATA, fragchain, sz);
- sd->statusinfo = statusinfo;
- sd->timestamp = tstamp;
+ if (sd)
+ {
+ sd->statusinfo = statusinfo;
+ sd->timestamp = tstamp;
+ }
return sd;
}
@@ -1789,11 +1757,11 @@ static struct ddsi_serdata *extract_sample_from_data
{
const struct proxy_writer *pwr = sampleinfo->pwr;
nn_guid_t guid = pwr ? pwr->e.guid : null_guid; /* can't be null _yet_, but that might change some day */
- DDS_TRACE("data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64
- ": write without proper payload (data_smhdr_flags 0x%x size %"PRIu32")\n",
- sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
- PGUID (guid), sampleinfo->seq,
- data_smhdr_flags, sampleinfo->size);
+ DDS_CTRACE (&sampleinfo->rst->gv->logconfig,
+ "data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": write without proper payload (data_smhdr_flags 0x%x size %"PRIu32")\n",
+ sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
+ PGUID (guid), sampleinfo->seq,
+ data_smhdr_flags, sampleinfo->size);
return NULL;
}
sample = get_serdata (topic, fragchain, sampleinfo->size, 0, statusinfo, tstamp);
@@ -1817,7 +1785,7 @@ static struct ddsi_serdata *extract_sample_from_data
{
/* RTI always tries to make us survive on the keyhash. RTI must
mend its ways. */
- if (NN_STRICT_P)
+ if (NN_STRICT_P (sampleinfo->rst->gv->config))
failmsg = "no content";
else if (!(qos->present & PP_KEYHASH))
failmsg = "qos present but without keyhash";
@@ -1838,14 +1806,12 @@ static struct ddsi_serdata *extract_sample_from_data
/* No message => error out */
const struct proxy_writer *pwr = sampleinfo->pwr;
nn_guid_t guid = pwr ? pwr->e.guid : null_guid; /* can't be null _yet_, but that might change some day */
- DDS_WARNING
- (
- "data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": deserialization %s/%s failed (%s)\n",
- sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
- PGUID (guid), sampleinfo->seq,
- topic->name, topic->type_name,
- failmsg ? failmsg : "for reasons unknown"
- );
+ DDS_CWARNING (&sampleinfo->rst->gv->logconfig,
+ "data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": deserialization %s/%s failed (%s)\n",
+ sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
+ PGUID (guid), sampleinfo->seq,
+ topic->name, topic->type_name,
+ failmsg ? failmsg : "for reasons unknown");
}
return sample;
}
@@ -1859,7 +1825,7 @@ unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr)
case SMID_DATA_FRAG:
{
unsigned char common = smhdr->flags & DATA_FLAG_INLINE_QOS;
- Q_STATIC_ASSERT_CODE (DATA_FLAG_INLINE_QOS == DATAFRAG_FLAG_INLINE_QOS);
+ DDSRT_STATIC_ASSERT_CODE (DATA_FLAG_INLINE_QOS == DATAFRAG_FLAG_INLINE_QOS);
if (smhdr->flags & DATAFRAG_FLAG_KEYFLAG)
return common | DATA_FLAG_KEYFLAG;
else
@@ -1934,17 +1900,21 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st
{
nn_plist_src_t src;
size_t qos_offset = NN_RDATA_SUBMSG_OFF (fragchain) + offsetof (Data_DataFrag_common_t, octetsToInlineQos) + sizeof (msg->octetsToInlineQos) + msg->octetsToInlineQos;
- int plist_ret;
+ dds_return_t plist_ret;
src.protocol_version = rst->protocol_version;
src.vendorid = rst->vendor;
src.encoding = (msg->smhdr.flags & SMFLAG_ENDIANNESS) ? PL_CDR_LE : PL_CDR_BE;
src.buf = NN_RMSG_PAYLOADOFF (fragchain->rmsg, qos_offset);
src.bufsz = NN_RDATA_PAYLOAD_OFF (fragchain) - qos_offset;
- if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH | PP_COHERENT_SET | PP_PRISMTECH_EOTINFO, 0, &src)) < 0)
+ src.strict = NN_STRICT_P (rst->gv->config);
+ src.factory = rst->gv->m_factory;
+ src.logconfig = &rst->gv->logconfig;
+ if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH | PP_COHERENT_SET, 0, &src)) < 0)
{
- if (plist_ret != Q_ERR_INCOMPATIBLE)
- DDS_WARNING ("data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n",
- src.vendorid.id[0], src.vendorid.id[1], PGUID (pwr->e.guid), sampleinfo->seq);
+ if (plist_ret != DDS_RETCODE_UNSUPPORTED)
+ DDS_CWARNING (&sampleinfo->rst->gv->logconfig,
+ "data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n",
+ src.vendorid.id[0], src.vendorid.id[1], PGUID (pwr->e.guid), sampleinfo->seq);
return 0;
}
statusinfo = (qos.present & PP_STATUSINFO) ? qos.statusinfo : 0;
@@ -1956,8 +1926,8 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st
worry about it. */
{
nn_wctime_t tstamp;
- if (valid_ddsi_timestamp (sampleinfo->timestamp))
- tstamp = nn_wctime_from_ddsi_time (sampleinfo->timestamp);
+ if (sampleinfo->timestamp.v != NN_WCTIME_INVALID.v)
+ tstamp = sampleinfo->timestamp;
else
tstamp.v = 0;
payload = extract_sample_from_data (sampleinfo, data_smhdr_flags, &qos, fragchain, statusinfo, tstamp, topic);
@@ -1967,94 +1937,87 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st
goto no_payload;
}
-
/* Generate the DDS_SampleInfo (which is faked to some extent
- because we don't actually have a data reader); also note that
- the PRISMTECH_WRITER_INFO thing is completely meaningless to
- us */
+ because we don't actually have a data reader) */
+ struct ddsi_tkmap_instance *tk;
+ if ((tk = ddsi_tkmap_lookup_instance_ref (pwr->e.gv->m_tkmap, payload)) != NULL)
{
- struct ddsi_tkmap_instance * tk;
- tk = ddsi_tkmap_lookup_instance_ref(payload);
- if (tk)
+ struct proxy_writer_info pwr_info;
+ make_proxy_writer_info (&pwr_info, &pwr->e, pwr->c.xqos);
+
+ if (rdguid == NULL)
{
- struct proxy_writer_info pwr_info;
- make_proxy_writer_info(&pwr_info, &pwr->e, pwr->c.xqos);
+ ETRACE (pwr, " %"PRId64"=>EVERYONE\n", sampleinfo->seq);
- if (rdguid == NULL)
+ /* FIXME: pwr->rdary is an array of pointers to attached
+ readers. There's only one thread delivering data for the
+ proxy writer (as long as there is only one receive thread),
+ so could get away with not locking at all, and doing safe
+ updates + GC of rdary instead. */
+
+ /* Retry loop, for re-delivery of rejected reliable samples. Is a
+ temporary hack till throttling back of writer is implemented
+ (with late acknowledgement of sample and nack). */
+ retry:
+
+ ddsrt_mutex_lock (&pwr->rdary.rdary_lock);
+ if (pwr->rdary.fastpath_ok)
{
- DDS_TRACE(" %"PRId64"=>EVERYONE\n", sampleinfo->seq);
-
- /* FIXME: pwr->rdary is an array of pointers to attached
- readers. There's only one thread delivering data for the
- proxy writer (as long as there is only one receive thread),
- so could get away with not locking at all, and doing safe
- updates + GC of rdary instead. */
-
- /* Retry loop, for re-delivery of rejected reliable samples. Is a
- temporary hack till throttling back of writer is implemented
- (with late acknowledgement of sample and nack). */
-retry:
-
- ddsrt_mutex_lock (&pwr->rdary.rdary_lock);
- if (pwr->rdary.fastpath_ok)
+ struct reader ** const rdary = pwr->rdary.rdary;
+ for (uint32_t i = 0; rdary[i]; i++)
{
- struct reader ** const rdary = pwr->rdary.rdary;
- unsigned i;
- for (i = 0; rdary[i]; i++)
+ ETRACE (pwr, "reader "PGUIDFMT"\n", PGUID (rdary[i]->e.guid));
+ if (!rhc_store (rdary[i]->rhc, &pwr_info, payload, tk))
{
- DDS_TRACE("reader "PGUIDFMT"\n", PGUID (rdary[i]->e.guid));
- if (! (ddsi_plugin.rhc_plugin.rhc_store_fn) (rdary[i]->rhc, &pwr_info, payload, tk))
- {
- if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock);
- ddsrt_mutex_unlock (&pwr->rdary.rdary_lock);
- dds_sleepfor (DDS_MSECS (10));
- if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock);
- goto retry;
- }
+ if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock);
+ ddsrt_mutex_unlock (&pwr->rdary.rdary_lock);
+ dds_sleepfor (DDS_MSECS (10));
+ if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock);
+ goto retry;
}
- ddsrt_mutex_unlock (&pwr->rdary.rdary_lock);
}
- else
- {
- /* When deleting, pwr is no longer accessible via the hash
- tables, and consequently, a reader may be deleted without
- it being possible to remove it from rdary. The primary
- reason rdary exists is to avoid locking the proxy writer
- but this is less of an issue when we are deleting it, so
- we fall back to using the GUIDs so that we can deliver all
- samples we received from it. As writer being deleted any
- reliable samples that are rejected are simply discarded. */
- ddsrt_avl_iter_t it;
- struct pwr_rd_match *m;
- ddsrt_mutex_unlock (&pwr->rdary.rdary_lock);
- if (!pwr_locked) ddsrt_mutex_lock (&pwr->e.lock);
- for (m = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); m != NULL; m = ddsrt_avl_iter_next (&it))
- {
- struct reader *rd;
- if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL)
- {
- DDS_TRACE("reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid));
- (void) (ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk);
- }
- }
- if (!pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock);
- }
-
- ddsrt_atomic_st32 (&pwr->next_deliv_seq_lowword, (uint32_t) (sampleinfo->seq + 1));
+ ddsrt_mutex_unlock (&pwr->rdary.rdary_lock);
}
else
{
- struct reader *rd = ephash_lookup_reader_guid (rdguid);;
- DDS_TRACE(" %"PRId64"=>"PGUIDFMT"%s\n", sampleinfo->seq, PGUID (*rdguid), rd ? "" : "?");
- while (rd && ! (ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk) && ephash_lookup_proxy_writer_guid (&pwr->e.guid))
+ /* When deleting, pwr is no longer accessible via the hash
+ tables, and consequently, a reader may be deleted without
+ it being possible to remove it from rdary. The primary
+ reason rdary exists is to avoid locking the proxy writer
+ but this is less of an issue when we are deleting it, so
+ we fall back to using the GUIDs so that we can deliver all
+ samples we received from it. As writer being deleted any
+ reliable samples that are rejected are simply discarded. */
+ ddsrt_avl_iter_t it;
+ struct pwr_rd_match *m;
+ ddsrt_mutex_unlock (&pwr->rdary.rdary_lock);
+ if (!pwr_locked) ddsrt_mutex_lock (&pwr->e.lock);
+ for (m = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); m != NULL; m = ddsrt_avl_iter_next (&it))
{
- if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock);
- dds_sleepfor (DDS_MSECS (1));
- if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock);
+ struct reader *rd;
+ if ((rd = ephash_lookup_reader_guid (pwr->e.gv->guid_hash, &m->rd_guid)) != NULL && m->in_sync == PRMSS_SYNC)
+ {
+ ETRACE (pwr, "reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid));
+ (void) rhc_store (rd->rhc, &pwr_info, payload, tk);
+ }
}
+ if (!pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock);
}
- ddsi_tkmap_instance_unref (tk);
+
+ ddsrt_atomic_st32 (&pwr->next_deliv_seq_lowword, (uint32_t) (sampleinfo->seq + 1));
}
+ else
+ {
+ struct reader *rd = ephash_lookup_reader_guid (pwr->e.gv->guid_hash, rdguid);
+ ETRACE (pwr, " %"PRId64"=>"PGUIDFMT"%s\n", sampleinfo->seq, PGUID (*rdguid), rd ? "" : "?");
+ while (rd && ! rhc_store (rd->rhc, &pwr_info, payload, tk) && ephash_lookup_proxy_writer_guid (pwr->e.gv->guid_hash, &pwr->e.guid))
+ {
+ if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock);
+ dds_sleepfor (DDS_MSECS (1));
+ if (pwr_locked) ddsrt_mutex_lock (&pwr->e.lock);
+ }
+ }
+ ddsi_tkmap_instance_unref (pwr->e.gv->m_tkmap, tk);
}
ddsi_serdata_unref (payload);
no_payload:
@@ -2069,7 +2032,7 @@ int user_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct
return res;
}
-static void deliver_user_data_synchronously (struct nn_rsample_chain *sc)
+static void deliver_user_data_synchronously (struct nn_rsample_chain *sc, const nn_guid_t *rdguid)
{
while (sc->first)
{
@@ -2081,7 +2044,7 @@ static void deliver_user_data_synchronously (struct nn_rsample_chain *sc)
sample_lost events. Also note that the synchronous path is
_never_ used for historical data, and therefore never has the
GUID of a reader to deliver to */
- deliver_user_data (e->sampleinfo, e->fragchain, NULL, 1);
+ deliver_user_data (e->sampleinfo, e->fragchain, rdguid, 1);
}
nn_fragchain_unref (e->fragchain);
}
@@ -2121,17 +2084,14 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct
nn_guid_t src;
src.prefix = rst->src_guid_prefix;
src.entityid = msg->writerId;
- DDS_TRACE(" "PGUIDFMT"? -> "PGUIDFMT, PGUID (src), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT"? -> "PGUIDFMT, PGUID (src), PGUID (dst));
return;
}
/* liveliness is still only implemented partially (with all set to
AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy
participant's lease. */
- if (pwr->assert_pp_lease)
- {
- lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
- }
+ lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
/* Shouldn't lock the full writer, but will do so for now */
ddsrt_mutex_lock (&pwr->e.lock);
@@ -2150,14 +2110,14 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct
if (!pwr->have_seen_heartbeat && pwr->n_reliable_readers > 0)
{
ddsrt_mutex_unlock (&pwr->e.lock);
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT": no heartbeat seen yet", PGUID (pwr->e.guid), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT": no heartbeat seen yet", PGUID (pwr->e.guid), PGUID (dst));
return;
}
if (ddsrt_avl_is_empty (&pwr->readers) || pwr->local_matching_inprogress)
{
ddsrt_mutex_unlock (&pwr->e.lock);
- DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT": no readers", PGUID (pwr->e.guid), PGUID (dst));
+ RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT": no readers", PGUID (pwr->e.guid), PGUID (dst));
return;
}
@@ -2212,7 +2172,7 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct
by the current mishandling of resource limits */
if (*deferred_wakeup)
dd_dqueue_enqueue_trigger (*deferred_wakeup);
- deliver_user_data_synchronously (&sc);
+ deliver_user_data_synchronously (&sc, NULL);
}
else
{
@@ -2223,31 +2183,27 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct
*deferred_wakeup = pwr->dqueue;
}
}
- if (pwr->n_readers_out_of_sync > 0)
- {
- /* Those readers catching up with TL but in sync with the proxy
- writer may have become in sync with the proxy writer and the
- writer; those catching up with TL all by themselves go through
- the "TOO_OLD" path below. */
- ddsrt_avl_iter_t it;
- struct pwr_rd_match *wn;
- for (wn = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); wn != NULL; wn = ddsrt_avl_iter_next (&it))
- if (wn->in_sync == PRMSS_TLCATCHUP)
- maybe_set_reader_in_sync (pwr, wn, sampleinfo->seq);
- }
}
- else if (rres == NN_REORDER_TOO_OLD)
+
+ if (pwr->n_readers_out_of_sync > 0)
{
+ /* Those readers catching up with TL but in sync with the proxy
+ writer may have become in sync with the proxy writer and the
+ writer; those catching up with TL all by themselves go through
+ the "TOO_OLD" path below. */
+ ddsrt_avl_iter_t it;
struct pwr_rd_match *wn;
struct nn_rsample *rsample_dup = NULL;
int reuse_rsample_dup = 0;
- for (wn = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); wn != NULL; wn = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, wn))
+ for (wn = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); wn != NULL; wn = ddsrt_avl_iter_next (&it))
{
nn_reorder_result_t rres2;
- if (wn->in_sync != PRMSS_OUT_OF_SYNC || sampleinfo->seq > wn->u.not_in_sync.end_of_out_of_sync_seq)
+ if (wn->in_sync == PRMSS_SYNC)
continue;
+ /* only need to get a copy of the first sample, because that's the one
+ that triggered delivery */
if (!reuse_rsample_dup)
- rsample_dup = nn_reorder_rsample_dup (rmsg, rsample);
+ rsample_dup = nn_reorder_rsample_dup_first (rmsg, rsample);
rres2 = nn_reorder_rsample (&sc, wn->u.not_in_sync.reorder, rsample_dup, &refc_adjust, nn_dqueue_is_full (pwr->dqueue));
switch (rres2)
{
@@ -2270,17 +2226,26 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct
in-order, and those few microseconds can't hurt in
catching up on transient-local data. See also
NN_REORDER_DELIVER case in outer switch. */
- nn_dqueue_enqueue1 (pwr->dqueue, &wn->rd_guid, &sc, rres2);
+ if (pwr->deliver_synchronously)
+ {
+ /* FIXME: just in case the synchronous delivery runs into a delay caused
+ by the current mishandling of resource limits */
+ deliver_user_data_synchronously (&sc, &wn->rd_guid);
+ }
+ else
+ {
+ if (*deferred_wakeup && *deferred_wakeup != pwr->dqueue)
+ {
+ dd_dqueue_enqueue_trigger (*deferred_wakeup);
+ *deferred_wakeup = NULL;
+ }
+ nn_dqueue_enqueue1 (pwr->dqueue, &wn->rd_guid, &sc, rres2);
+ }
break;
}
}
}
-#ifndef NDEBUG
- else
- {
- assert (rres == NN_REORDER_ACCEPT || rres == NN_REORDER_REJECT);
- }
-#endif
+
nn_fragchain_adjust_refcount (fragchain, refc_adjust);
}
ddsrt_mutex_unlock (&pwr->e.lock);
@@ -2289,18 +2254,19 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct
static int handle_SPDP (const struct nn_rsample_info *sampleinfo, struct nn_rdata *rdata)
{
+ struct q_globals * const gv = sampleinfo->rst->gv;
struct nn_rsample *rsample;
struct nn_rsample_chain sc;
struct nn_rdata *fragchain;
nn_reorder_result_t rres;
int refc_adjust = 0;
- ddsrt_mutex_lock (&gv.spdp_lock);
- rsample = nn_defrag_rsample (gv.spdp_defrag, rdata, sampleinfo);
+ ddsrt_mutex_lock (&gv->spdp_lock);
+ rsample = nn_defrag_rsample (gv->spdp_defrag, rdata, sampleinfo);
fragchain = nn_rsample_fragchain (rsample);
- if ((rres = nn_reorder_rsample (&sc, gv.spdp_reorder, rsample, &refc_adjust, nn_dqueue_is_full (gv.builtins_dqueue))) > 0)
- nn_dqueue_enqueue (gv.builtins_dqueue, &sc, rres);
+ if ((rres = nn_reorder_rsample (&sc, gv->spdp_reorder, rsample, &refc_adjust, nn_dqueue_is_full (gv->builtins_dqueue))) > 0)
+ nn_dqueue_enqueue (gv->builtins_dqueue, &sc, rres);
nn_fragchain_adjust_refcount (fragchain, refc_adjust);
- ddsrt_mutex_unlock (&gv.spdp_lock);
+ ddsrt_mutex_unlock (&gv->spdp_lock);
return 0;
}
@@ -2314,9 +2280,9 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con
cause periodic warnings. */
if (msg->writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)
{
- DDS_WARNING ("dropping oversize (%"PRIu32" > %"PRIu32") SPDP sample %"PRId64" from remote writer "PGUIDFMT"\n",
- sampleinfo->size, config.max_sample_size, sampleinfo->seq,
- PGUIDPREFIX (rst->src_guid_prefix), msg->writerId.u);
+ DDS_CWARNING (&rst->gv->logconfig, "dropping oversize (%"PRIu32" > %"PRIu32") SPDP sample %"PRId64" from remote writer "PGUIDFMT"\n",
+ sampleinfo->size, rst->gv->config.max_sample_size, sampleinfo->seq,
+ PGUIDPREFIX (rst->src_guid_prefix), msg->writerId.u);
}
}
else
@@ -2344,27 +2310,27 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con
{
const char *tname = pwr->c.topic ? pwr->c.topic->name : "(null)";
const char *ttname = pwr->c.topic ? pwr->c.topic->type_name : "(null)";
- DDS_WARNING ("dropping oversize (%"PRIu32" > %"PRIu32") sample %"PRId64" from remote writer "PGUIDFMT" %s/%s\n",
- sampleinfo->size, config.max_sample_size, sampleinfo->seq,
- PGUIDPREFIX (rst->src_guid_prefix), msg->writerId.u,
- tname, ttname);
+ DDS_CWARNING (&rst->gv->logconfig, "dropping oversize (%"PRIu32" > %"PRIu32") sample %"PRId64" from remote writer "PGUIDFMT" %s/%s\n",
+ sampleinfo->size, rst->gv->config.max_sample_size, sampleinfo->seq,
+ PGUIDPREFIX (rst->src_guid_prefix), msg->writerId.u,
+ tname, ttname);
}
}
}
static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup)
{
- DDS_TRACE("DATA("PGUIDFMT" -> "PGUIDFMT" #%"PRId64,
- PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u,
- PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u,
- fromSN (msg->x.writerSN));
+ RSTTRACE ("DATA("PGUIDFMT" -> "PGUIDFMT" #%"PRId64,
+ PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u,
+ PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u,
+ fromSN (msg->x.writerSN));
if (!rst->forme)
{
- DDS_TRACE(" not-for-me)");
+ RSTTRACE (" not-for-me)");
return 1;
}
- if (sampleinfo->size > config.max_sample_size)
+ if (sampleinfo->size > rst->gv->config.max_sample_size)
drop_oversize (rst, rmsg, &msg->x, sampleinfo);
else
{
@@ -2392,24 +2358,24 @@ static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_r
handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, ~0u, rdata, deferred_wakeup);
}
}
- DDS_TRACE(")");
+ RSTTRACE (")");
return 1;
}
static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const DataFrag_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup)
{
- DDS_TRACE("DATAFRAG("PGUIDFMT" -> "PGUIDFMT" #%"PRId64"/[%u..%u]",
- PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u,
- PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u,
- fromSN (msg->x.writerSN),
- msg->fragmentStartingNum, msg->fragmentStartingNum + msg->fragmentsInSubmessage - 1);
+ RSTTRACE ("DATAFRAG("PGUIDFMT" -> "PGUIDFMT" #%"PRId64"/[%u..%u]",
+ PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u,
+ PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u,
+ fromSN (msg->x.writerSN),
+ msg->fragmentStartingNum, msg->fragmentStartingNum + msg->fragmentsInSubmessage - 1);
if (!rst->forme)
{
- DDS_TRACE(" not-for-me)");
+ RSTTRACE (" not-for-me)");
return 1;
}
- if (sampleinfo->size > config.max_sample_size)
+ if (sampleinfo->size > rst->gv->config.max_sample_size)
drop_oversize (rst, rmsg, &msg->x, sampleinfo);
else
{
@@ -2418,9 +2384,9 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct
uint32_t begin, endp1;
if (msg->x.writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)
{
- DDS_WARNING ("DATAFRAG("PGUIDFMT" #%"PRId64" -> "PGUIDFMT") - fragmented builtin data not yet supported\n",
- PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, fromSN (msg->x.writerSN),
- PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u);
+ DDS_CWARNING (&rst->gv->logconfig, "DATAFRAG("PGUIDFMT" #%"PRId64" -> "PGUIDFMT") - fragmented builtin data not yet supported\n",
+ PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, fromSN (msg->x.writerSN),
+ PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u);
return 1;
}
@@ -2451,7 +2417,7 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct
here */
endp1 = msg->sampleSize;
}
- DDS_TRACE("/[%"PRIu32"..%"PRIu32") of %"PRIu32, begin, endp1, msg->sampleSize);
+ RSTTRACE ("/[%"PRIu32"..%"PRIu32") of %"PRIu32, begin, endp1, msg->sampleSize);
rdata = nn_rdata_new (rmsg, begin, endp1, submsg_offset, payload_offset);
@@ -2464,7 +2430,7 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct
dealing with that. */
handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, msg->fragmentStartingNum + msg->fragmentsInSubmessage - 2, rdata, deferred_wakeup);
}
- DDS_TRACE(")");
+ RSTTRACE (")");
return 1;
}
@@ -2484,12 +2450,7 @@ static size_t decode_container (unsigned char *submsg, size_t len)
}
#endif /* DDSI_INCLUDE_ENCRYPTION */
-static void malformed_packet_received_nosubmsg
-(
- const unsigned char * msg,
- ssize_t len,
- const char *state,
- nn_vendorid_t vendorid
+static void malformed_packet_received_nosubmsg (const struct q_globals *gv, const unsigned char * msg, ssize_t len, const char *state, nn_vendorid_t vendorid
)
{
char tmp[1024];
@@ -2503,18 +2464,10 @@ static void malformed_packet_received_nosubmsg
if (pos < sizeof (tmp))
pos += (size_t) snprintf (tmp + pos, sizeof (tmp) - pos, "> (note: maybe partially bswap'd)");
assert (pos < sizeof (tmp));
- DDS_WARNING ("%s\n", tmp);
+ GVWARNING ("%s\n", tmp);
}
-static void malformed_packet_received
-(
- const unsigned char *msg,
- const unsigned char *submsg,
- size_t len,
- const char *state,
- SubmessageKind_t smkind,
- nn_vendorid_t vendorid
-)
+static void malformed_packet_received (const struct q_globals *gv, const unsigned char *msg, const unsigned char *submsg, size_t len, const char *state, SubmessageKind_t smkind, nn_vendorid_t vendorid)
{
char tmp[1024];
size_t i, pos, smsize;
@@ -2610,7 +2563,7 @@ static void malformed_packet_received
break;
}
- DDS_WARNING ("%s\n", tmp);
+ GVWARNING ("%s\n", tmp);
}
static struct receiver_state *rst_cow_if_needed (int *rst_live, struct nn_rmsg *rmsg, struct receiver_state *rst)
@@ -2629,6 +2582,7 @@ static struct receiver_state *rst_cow_if_needed (int *rst_live, struct nn_rmsg *
static int handle_submsg_sequence
(
struct thread_state1 * const ts1,
+ struct q_globals *gv,
ddsi_tran_conn_t conn,
const nn_locator_t *srcloc,
nn_wctime_t tnowWC,
@@ -2646,7 +2600,7 @@ static int handle_submsg_sequence
Header_t * hdr = (Header_t *) msg;
struct receiver_state *rst;
int rst_live, ts_for_latmeas;
- nn_ddsi_time_t timestamp;
+ nn_wctime_t timestamp;
size_t submsg_size = 0;
unsigned char * end = msg + len;
struct nn_dqueue *deferred_wakeup = NULL;
@@ -2674,12 +2628,13 @@ static int handle_submsg_sequence
rst->vendor = hdr->vendorid;
rst->protocol_version = hdr->version;
rst->srcloc = *srcloc;
+ rst->gv = gv;
rst_live = 0;
ts_for_latmeas = 0;
- timestamp = invalid_ddsi_timestamp;
+ timestamp = NN_WCTIME_INVALID;
assert (thread_is_asleep ());
- thread_state_awake (ts1);
+ thread_state_awake_fixed_domain (ts1);
while (submsg <= (end - sizeof (SubmessageHeader_t)))
{
Submessage_t *sm = (Submessage_t *) submsg;
@@ -2712,11 +2667,11 @@ static int handle_submsg_sequence
{
submsg_size = (unsigned) (end - submsg);
}
- /*DDS_TRACE(("submsg_size %d\n", submsg_size));*/
+ /*GVTRACE ("submsg_size %d\n", submsg_size);*/
if (submsg + submsg_size > end)
{
- DDS_TRACE(" BREAK (%u %"PRIuSIZE": %p %u)\n", (unsigned) (submsg - msg), submsg_size, (void *) msg, (unsigned) len);
+ GVTRACE (" BREAK (%u %"PRIuSIZE": %p %u)\n", (unsigned) (submsg - msg), submsg_size, (void *) msg, (unsigned) len);
break;
}
@@ -2725,20 +2680,20 @@ static int handle_submsg_sequence
switch (sm->smhdr.submessageId)
{
case SMID_PAD:
- DDS_TRACE("PAD");
+ GVTRACE ("PAD");
break;
case SMID_ACKNACK:
state = "parse:acknack";
- if (!valid_AckNack (&sm->acknack, submsg_size, byteswap))
+ if (!valid_AckNack (rst, &sm->acknack, submsg_size, byteswap))
goto malformed;
- handle_AckNack (rst, tnowE, &sm->acknack, ts_for_latmeas ? timestamp : invalid_ddsi_timestamp);
+ handle_AckNack (rst, tnowE, &sm->acknack, ts_for_latmeas ? timestamp : NN_WCTIME_INVALID);
ts_for_latmeas = 0;
break;
case SMID_HEARTBEAT:
state = "parse:heartbeat";
if (!valid_Heartbeat (&sm->heartbeat, submsg_size, byteswap))
goto malformed;
- handle_Heartbeat (rst, tnowE, rmsg, &sm->heartbeat, ts_for_latmeas ? timestamp : invalid_ddsi_timestamp);
+ handle_Heartbeat (rst, tnowE, rmsg, &sm->heartbeat, ts_for_latmeas ? timestamp : NN_WCTIME_INVALID);
ts_for_latmeas = 0;
break;
case SMID_GAP:
@@ -2757,7 +2712,7 @@ static int handle_submsg_sequence
state = "parse:info_ts";
if (!valid_InfoTS (&sm->infots, submsg_size, byteswap))
goto malformed;
- handle_InfoTS (&sm->infots, ×tamp);
+ handle_InfoTS (rst, &sm->infots, ×tamp);
ts_for_latmeas = 1;
break;
case SMID_INFO_SRC:
@@ -2772,7 +2727,7 @@ static int handle_submsg_sequence
#if 0
state = "parse:info_reply_ip4";
#endif
- DDS_TRACE("INFO_REPLY_IP4");
+ GVTRACE ("INFO_REPLY_IP4");
/* no effect on ts_for_latmeas */
break;
case SMID_INFO_DST:
@@ -2787,7 +2742,7 @@ static int handle_submsg_sequence
#if 0
state = "parse:info_reply";
#endif
- DDS_TRACE("INFO_REPLY");
+ GVTRACE ("INFO_REPLY");
/* no effect on ts_for_latmeas */
break;
case SMID_NACK_FRAG:
@@ -2839,7 +2794,7 @@ static int handle_submsg_sequence
if (vendor_is_eclipse_or_prismtech (rst->vendor))
{
state = "parse:pt_info_container";
- DDS_TRACE("PT_INFO_CONTAINER(");
+ GVTRACE ("PT_INFO_CONTAINER(");
if (!valid_PT_InfoContainer (&sm->pt_infocontainer, submsg_size, byteswap))
goto malformed;
switch (sm->pt_infocontainer.id)
@@ -2865,7 +2820,7 @@ static int handle_submsg_sequence
#endif /* DDSI_INCLUDE_ENCRYPTION */
break;
default:
- DDS_TRACE("(unknown id %"PRIu32"?)\n", sm->pt_infocontainer.id);
+ GVTRACE ("(unknown id %"PRIu32"?)\n", sm->pt_infocontainer.id);
}
}
break;
@@ -2874,7 +2829,7 @@ static int handle_submsg_sequence
#if 0
state = "parse:msg_len";
#endif
- DDS_TRACE("MSG_LEN(%"PRIu32")", ((MsgLen_t*) sm)->length);
+ GVTRACE ("MSG_LEN(%"PRIu32")", ((MsgLen_t*) sm)->length);
break;
}
case SMID_PT_ENTITY_ID:
@@ -2882,12 +2837,12 @@ static int handle_submsg_sequence
#if 0
state = "parse:entity_id";
#endif
- DDS_TRACE("ENTITY_ID");
+ GVTRACE ("ENTITY_ID");
break;
}
default:
state = "parse:undefined";
- DDS_TRACE("UNDEFINED(%x)", sm->smhdr.submessageId);
+ GVTRACE ("UNDEFINED(%x)", sm->smhdr.submessageId);
if (sm->smhdr.submessageId <= 0x7f)
{
/* Other submessages in the 0 .. 0x7f range may be added in
@@ -2916,13 +2871,13 @@ static int handle_submsg_sequence
break;
}
submsg += submsg_size;
- DDS_TRACE("\n");
+ GVTRACE ("\n");
}
if (submsg != end)
{
state = "parse:shortmsg";
state_smkind = SMID_PAD;
- DDS_TRACE("short (size %"PRIuSIZE" exp %p act %p)", submsg_size, (void *) submsg, (void *) end);
+ GVTRACE ("short (size %"PRIuSIZE" exp %p act %p)", submsg_size, (void *) submsg, (void *) end);
goto malformed_asleep;
}
thread_state_asleep (ts1);
@@ -2936,23 +2891,17 @@ malformed:
assert (thread_is_asleep ());
malformed_asleep:
assert (thread_is_asleep ());
- malformed_packet_received (msg, submsg, len, state, state_smkind, hdr->vendorid);
+ malformed_packet_received (rst->gv, msg, submsg, len, state, state_smkind, hdr->vendorid);
if (deferred_wakeup)
dd_dqueue_enqueue_trigger (deferred_wakeup);
return -1;
}
-static bool do_packet
-(
- struct thread_state1 * const ts1,
- ddsi_tran_conn_t conn,
- const nn_guid_prefix_t * guidprefix,
- struct nn_rbufpool *rbpool
-)
+static bool do_packet (struct thread_state1 * const ts1, struct q_globals *gv, ddsi_tran_conn_t conn, const nn_guid_prefix_t *guidprefix, struct nn_rbufpool *rbpool)
{
/* UDP max packet size is 64kB */
- const size_t maxsz = config.rmsg_chunk_size < 65536 ? config.rmsg_chunk_size : 65536;
+ const size_t maxsz = gv->config.rmsg_chunk_size < 65536 ? gv->config.rmsg_chunk_size : 65536;
const size_t ddsi_msg_len_size = 8;
const size_t stream_hdr_size = RTPS_MESSAGE_HEADER_SIZE + ddsi_msg_len_size;
ssize_t sz;
@@ -3009,7 +2958,7 @@ static bool do_packet
if (ml->smhdr.submessageId != SMID_PT_MSG_LEN)
{
- malformed_packet_received_nosubmsg (buff, sz, "header", hdr->vendorid);
+ malformed_packet_received_nosubmsg (gv, buff, sz, "header", hdr->vendorid);
sz = -1;
}
else
@@ -3029,7 +2978,7 @@ static bool do_packet
sz = ddsi_conn_read (conn, buff, buff_len, true, &srcloc);
}
- if (sz > 0 && !gv.deaf)
+ if (sz > 0 && !gv->deaf)
{
nn_rmsg_setsize (rmsg, (uint32_t) sz);
assert (thread_is_asleep ());
@@ -3041,24 +2990,24 @@ static bool do_packet
else if (hdr->version.major != RTPS_MAJOR || (hdr->version.major == RTPS_MAJOR && hdr->version.minor < RTPS_MINOR_MINIMUM))
{
if ((hdr->version.major == RTPS_MAJOR && hdr->version.minor < RTPS_MINOR_MINIMUM))
- DDS_TRACE("HDR(%"PRIx32":%"PRIx32":%"PRIx32" vendor %d.%d) len %lu\n, version mismatch: %d.%d\n",
- PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, hdr->version.major, hdr->version.minor);
- if (NN_PEDANTIC_P)
- malformed_packet_received_nosubmsg (buff, sz, "header", hdr->vendorid);
+ GVTRACE ("HDR(%"PRIx32":%"PRIx32":%"PRIx32" vendor %d.%d) len %lu\n, version mismatch: %d.%d\n",
+ PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, hdr->version.major, hdr->version.minor);
+ if (NN_PEDANTIC_P (gv->config))
+ malformed_packet_received_nosubmsg (gv, buff, sz, "header", hdr->vendorid);
}
else
{
hdr->guid_prefix = nn_ntoh_guid_prefix (hdr->guid_prefix);
- if (dds_get_log_mask() & DDS_LC_TRACE)
+ if (gv->logconfig.c.mask & DDS_LC_TRACE)
{
char addrstr[DDSI_LOCSTRLEN];
- ddsi_locator_to_string(addrstr, sizeof(addrstr), &srcloc);
- DDS_TRACE("HDR(%"PRIx32":%"PRIx32":%"PRIx32" vendor %d.%d) len %lu from %s\n",
- PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, addrstr);
+ ddsi_locator_to_string(gv, addrstr, sizeof(addrstr), &srcloc);
+ GVTRACE ("HDR(%"PRIx32":%"PRIx32":%"PRIx32" vendor %d.%d) len %lu from %s\n",
+ PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, addrstr);
}
- handle_submsg_sequence (ts1, conn, &srcloc, now (), now_et (), &hdr->guid_prefix, guidprefix, buff, (size_t) sz, buff + RTPS_MESSAGE_HEADER_SIZE, rmsg);
+ handle_submsg_sequence (ts1, gv, conn, &srcloc, now (), now_et (), &hdr->guid_prefix, guidprefix, buff, (size_t) sz, buff + RTPS_MESSAGE_HEADER_SIZE, rmsg);
}
}
nn_rmsg_commit (rmsg);
@@ -3107,15 +3056,15 @@ static size_t dedup_sorted_array (void *base, size_t nel, size_t width, int (*co
struct local_participant_set {
struct local_participant_desc *ps;
- unsigned nps;
+ uint32_t nps;
uint32_t gen;
};
-static void local_participant_set_init (struct local_participant_set *lps)
+static void local_participant_set_init (struct local_participant_set *lps, ddsrt_atomic_uint32_t *ppset_generation)
{
lps->ps = NULL;
lps->nps = 0;
- lps->gen = ddsrt_atomic_ld32 (&gv.participant_set_generation) - 1;
+ lps->gen = ddsrt_atomic_ld32 (ppset_generation) - 1;
}
static void local_participant_set_fini (struct local_participant_set *lps)
@@ -3123,23 +3072,23 @@ static void local_participant_set_fini (struct local_participant_set *lps)
ddsrt_free (lps->ps);
}
-static void rebuild_local_participant_set (struct thread_state1 * const ts1, struct local_participant_set *lps)
+static void rebuild_local_participant_set (struct thread_state1 * const ts1, struct q_globals *gv, struct local_participant_set *lps)
{
struct ephash_enum_participant est;
struct participant *pp;
unsigned nps_alloc;
- DDS_TRACE("pp set gen changed: local %"PRIu32" global %"PRIu32"\n", lps->gen, ddsrt_atomic_ld32(&gv.participant_set_generation));
- thread_state_awake (ts1);
+ GVTRACE ("pp set gen changed: local %"PRIu32" global %"PRIu32"\n", lps->gen, ddsrt_atomic_ld32 (&gv->participant_set_generation));
+ thread_state_awake_fixed_domain (ts1);
restart:
- lps->gen = ddsrt_atomic_ld32 (&gv.participant_set_generation);
+ lps->gen = ddsrt_atomic_ld32 (&gv->participant_set_generation);
/* Actual local set of participants may never be older than the
local generation count => membar to guarantee the ordering */
ddsrt_atomic_fence_acq ();
- nps_alloc = gv.nparticipants;
+ nps_alloc = gv->nparticipants;
ddsrt_free (lps->ps);
lps->nps = 0;
lps->ps = (nps_alloc == 0) ? NULL : ddsrt_malloc (nps_alloc * sizeof (*lps->ps));
- ephash_enum_participant_init (&est);
+ ephash_enum_participant_init (&est, gv->guid_hash);
while ((pp = ephash_enum_participant_next (&est)) != NULL)
{
if (lps->nps == nps_alloc)
@@ -3149,14 +3098,14 @@ static void rebuild_local_participant_set (struct thread_state1 * const ts1, str
turns out we didn't allocate enough memory [an
alternative would be to realloc on the fly]. */
ephash_enum_participant_fini (&est);
- DDS_TRACE(" need more memory - restarting\n");
+ GVTRACE (" need more memory - restarting\n");
goto restart;
}
else
{
lps->ps[lps->nps].m_conn = pp->m_conn;
lps->ps[lps->nps].guid_prefix = pp->e.guid.prefix;
- DDS_TRACE(" pp "PGUIDFMT" handle %"PRIdSOCK"\n", PGUID (pp->e.guid), ddsi_conn_handle (pp->m_conn));
+ GVTRACE (" pp "PGUIDFMT" handle %"PRIdSOCK"\n", PGUID (pp->e.guid), ddsi_conn_handle (pp->m_conn));
lps->nps++;
}
}
@@ -3169,9 +3118,9 @@ static void rebuild_local_participant_set (struct thread_state1 * const ts1, str
explicit destination. Membar because we must have completed
the loop before testing the generation again. */
ddsrt_atomic_fence_acq ();
- if (lps->gen != ddsrt_atomic_ld32 (&gv.participant_set_generation))
+ if (lps->gen != ddsrt_atomic_ld32 (&gv->participant_set_generation))
{
- DDS_TRACE(" set changed - restarting\n");
+ GVTRACE (" set changed - restarting\n");
goto restart;
}
thread_state_asleep (ts1);
@@ -3186,22 +3135,23 @@ static void rebuild_local_participant_set (struct thread_state1 * const ts1, str
qsort (lps->ps, lps->nps, sizeof (*lps->ps), local_participant_cmp);
lps->nps = (unsigned) dedup_sorted_array (lps->ps, lps->nps, sizeof (*lps->ps), local_participant_cmp);
}
- DDS_TRACE(" nparticipants %u\n", lps->nps);
+ GVTRACE (" nparticipants %u\n", lps->nps);
}
-uint32_t listen_thread (struct ddsi_tran_listener * listener)
+uint32_t listen_thread (struct ddsi_tran_listener *listener)
{
+ struct q_globals *gv = listener->m_base.gv;
ddsi_tran_conn_t conn;
- while (gv.rtps_keepgoing)
+ while (ddsrt_atomic_ld32 (&gv->rtps_keepgoing))
{
/* Accept connection from listener */
conn = ddsi_listener_accept (listener);
if (conn)
{
- os_sockWaitsetAdd (gv.recv_threads[0].arg.u.many.ws, conn);
- os_sockWaitsetTrigger (gv.recv_threads[0].arg.u.many.ws);
+ os_sockWaitsetAdd (gv->recv_threads[0].arg.u.many.ws, conn);
+ os_sockWaitsetTrigger (gv->recv_threads[0].arg.u.many.ws);
}
}
return 0;
@@ -3209,13 +3159,16 @@ uint32_t listen_thread (struct ddsi_tran_listener * listener)
static int recv_thread_waitset_add_conn (os_sockWaitset ws, ddsi_tran_conn_t conn)
{
- unsigned i;
if (conn == NULL)
return 0;
- for (i = 0; i < gv.n_recv_threads; i++)
- if (gv.recv_threads[i].arg.mode == RTM_SINGLE && gv.recv_threads[i].arg.u.single.conn == conn)
- return 0;
- return os_sockWaitsetAdd (ws, conn);
+ else
+ {
+ struct q_globals *gv = conn->m_base.gv;
+ for (uint32_t i = 0; i < gv->n_recv_threads; i++)
+ if (gv->recv_threads[i].arg.mode == RTM_SINGLE && gv->recv_threads[i].arg.u.single.conn == conn)
+ return 0;
+ return os_sockWaitsetAdd (ws, conn);
+ }
}
enum local_deaf_state_recover {
@@ -3229,12 +3182,12 @@ struct local_deaf_state {
nn_mtime_t tnext;
};
-static int check_and_handle_deafness_recover(struct local_deaf_state *st, unsigned num_fixed_uc)
+static int check_and_handle_deafness_recover (struct q_globals *gv, struct local_deaf_state *st, unsigned num_fixed_uc)
{
int rebuildws = 0;
if (now_mt().v < st->tnext.v)
{
- DDS_TRACE("check_and_handle_deafness_recover: state %d too early\n", (int)st->state);
+ GVTRACE ("check_and_handle_deafness_recover: state %d too early\n", (int)st->state);
return 0;
}
switch (st->state)
@@ -3243,21 +3196,21 @@ static int check_and_handle_deafness_recover(struct local_deaf_state *st, unsign
assert(0);
break;
case LDSR_DEAF: {
- ddsi_tran_conn_t disc = gv.disc_conn_mc, data = gv.data_conn_mc;
- DDS_TRACE("check_and_handle_deafness_recover: state %d create new sockets\n", (int)st->state);
- if (!create_multicast_sockets())
+ ddsi_tran_conn_t disc = gv->disc_conn_mc, data = gv->data_conn_mc;
+ GVTRACE ("check_and_handle_deafness_recover: state %d create new sockets\n", (int) st->state);
+ if (!create_multicast_sockets (gv))
goto error;
- DDS_TRACE("check_and_handle_deafness_recover: state %d transfer group membership admin\n", (int)st->state);
- ddsi_transfer_group_membership(disc, gv.disc_conn_mc);
- ddsi_transfer_group_membership(data, gv.data_conn_mc);
- DDS_TRACE("check_and_handle_deafness_recover: state %d drop from waitset and add new\n", (int)st->state);
+ GVTRACE ("check_and_handle_deafness_recover: state %d transfer group membership admin\n", (int) st->state);
+ ddsi_transfer_group_membership (gv->mship, disc, gv->disc_conn_mc);
+ ddsi_transfer_group_membership (gv->mship, data, gv->data_conn_mc);
+ GVTRACE ("check_and_handle_deafness_recover: state %d drop from waitset and add new\n", (int) st->state);
/* see waitset construction code in recv_thread */
- os_sockWaitsetPurge (gv.recv_threads[0].arg.u.many.ws, num_fixed_uc);
- if (recv_thread_waitset_add_conn (gv.recv_threads[0].arg.u.many.ws, gv.disc_conn_mc) < 0)
+ os_sockWaitsetPurge (gv->recv_threads[0].arg.u.many.ws, num_fixed_uc);
+ if (recv_thread_waitset_add_conn (gv->recv_threads[0].arg.u.many.ws, gv->disc_conn_mc) < 0)
DDS_FATAL("check_and_handle_deafness_recover: failed to add disc_conn_mc to waitset\n");
- if (recv_thread_waitset_add_conn (gv.recv_threads[0].arg.u.many.ws, gv.data_conn_mc) < 0)
+ if (recv_thread_waitset_add_conn (gv->recv_threads[0].arg.u.many.ws, gv->data_conn_mc) < 0)
DDS_FATAL("check_and_handle_deafness_recover: failed to add data_conn_mc to waitset\n");
- DDS_TRACE("check_and_handle_deafness_recover: state %d close sockets\n", (int)st->state);
+ GVTRACE ("check_and_handle_deafness_recover: state %d close sockets\n", (int)st->state);
ddsi_conn_free(disc);
ddsi_conn_free(data);
rebuildws = 1;
@@ -3265,73 +3218,72 @@ static int check_and_handle_deafness_recover(struct local_deaf_state *st, unsign
}
/* FALLS THROUGH */
case LDSR_REJOIN:
- DDS_TRACE("check_and_handle_deafness_recover: state %d rejoin on disc socket\n", (int)st->state);
- if (ddsi_rejoin_transferred_mcgroups(gv.disc_conn_mc) < 0)
+ GVTRACE ("check_and_handle_deafness_recover: state %d rejoin on disc socket\n", (int)st->state);
+ if (ddsi_rejoin_transferred_mcgroups (gv, gv->mship, gv->disc_conn_mc) < 0)
goto error;
- DDS_TRACE("check_and_handle_deafness_recover: state %d rejoin on data socket\n", (int)st->state);
- if (ddsi_rejoin_transferred_mcgroups(gv.data_conn_mc) < 0)
+ GVTRACE ("check_and_handle_deafness_recover: state %d rejoin on data socket\n", (int)st->state);
+ if (ddsi_rejoin_transferred_mcgroups (gv, gv->mship, gv->data_conn_mc) < 0)
goto error;
- DDS_TRACE("check_and_handle_deafness_recover: state %d done\n", (int)st->state);
+ GVTRACE ("check_and_handle_deafness_recover: state %d done\n", (int)st->state);
st->state = LDSR_NORMAL;
break;
}
- DDS_TRACE("check_and_handle_deafness_recover: state %d returning %d\n", (int)st->state, rebuildws);
+ GVTRACE ("check_and_handle_deafness_recover: state %d returning %d\n", (int)st->state, rebuildws);
return rebuildws;
error:
-DDS_TRACE("check_and_handle_deafness_recover: state %d failed, returning %d\n", (int)st->state, rebuildws);
+ GVTRACE ("check_and_handle_deafness_recover: state %d failed, returning %d\n", (int)st->state, rebuildws);
st->state = LDSR_DEAF;
st->tnext = add_duration_to_mtime(now_mt(), T_SECOND);
return rebuildws;
}
-static int check_and_handle_deafness(struct local_deaf_state *st, unsigned num_fixed_uc)
+static int check_and_handle_deafness (struct q_globals *gv, struct local_deaf_state *st, unsigned num_fixed_uc)
{
- const int gv_deaf = gv.deaf;
+ const int gv_deaf = gv->deaf;
assert (gv_deaf == 0 || gv_deaf == 1);
if (gv_deaf == (int)st->state)
return 0;
else if (gv_deaf)
{
- DDS_TRACE("check_and_handle_deafness: going deaf (%d -> %d)\n", (int)st->state, (int)LDSR_DEAF);
+ GVTRACE ("check_and_handle_deafness: going deaf (%d -> %d)\n", (int)st->state, (int)LDSR_DEAF);
st->state = LDSR_DEAF;
st->tnext = now_mt();
return 0;
}
- else if (!config.allowMulticast)
+ else if (!gv->config.allowMulticast)
{
- DDS_TRACE("check_and_handle_deafness: no longer deaf (multicast disabled)\n");
+ GVTRACE ("check_and_handle_deafness: no longer deaf (multicast disabled)\n");
st->state = LDSR_NORMAL;
return 0;
}
else
{
- return check_and_handle_deafness_recover(st, num_fixed_uc);
+ return check_and_handle_deafness_recover (gv, st, num_fixed_uc);
}
}
-void trigger_recv_threads (void)
+void trigger_recv_threads (const struct q_globals *gv)
{
- unsigned i;
- for (i = 0; i < gv.n_recv_threads; i++)
+ for (uint32_t i = 0; i < gv->n_recv_threads; i++)
{
- if (gv.recv_threads[i].ts == NULL)
+ if (gv->recv_threads[i].ts == NULL)
continue;
- switch (gv.recv_threads[i].arg.mode)
+ switch (gv->recv_threads[i].arg.mode)
{
case RTM_SINGLE: {
char buf[DDSI_LOCSTRLEN];
char dummy = 0;
- const nn_locator_t *dst = gv.recv_threads[i].arg.u.single.loc;
+ const nn_locator_t *dst = gv->recv_threads[i].arg.u.single.loc;
ddsrt_iovec_t iov;
iov.iov_base = &dummy;
iov.iov_len = 1;
- DDS_TRACE("trigger_recv_threads: %d single %s\n", i, ddsi_locator_to_string (buf, sizeof (buf), dst));
- ddsi_conn_write (gv.data_conn_uc, dst, 1, &iov, 0);
+ GVTRACE ("trigger_recv_threads: %d single %s\n", i, ddsi_locator_to_string (gv, buf, sizeof (buf), dst));
+ ddsi_conn_write (gv->data_conn_uc, dst, 1, &iov, 0);
break;
}
case RTM_MANY: {
- DDS_TRACE("trigger_recv_threads: %d many %p\n", i, (void *) gv.recv_threads[i].arg.u.many.ws);
- os_sockWaitsetTrigger (gv.recv_threads[i].arg.u.many.ws);
+ GVTRACE ("trigger_recv_threads: %d many %p\n", i, (void *) gv->recv_threads[i].arg.u.many.ws);
+ os_sockWaitsetTrigger (gv->recv_threads[i].arg.u.many.ws);
break;
}
}
@@ -3342,6 +3294,7 @@ uint32_t recv_thread (void *vrecv_thread_arg)
{
struct thread_state1 * const ts1 = lookup_thread_state ();
struct recv_thread_arg *recv_thread_arg = vrecv_thread_arg;
+ struct q_globals * const gv = recv_thread_arg->gv;
struct nn_rbufpool *rbpool = recv_thread_arg->rbpool;
os_sockWaitset waitset = recv_thread_arg->mode == RTM_MANY ? recv_thread_arg->u.many.ws : NULL;
nn_mtime_t next_thread_cputime = { 0 };
@@ -3349,10 +3302,11 @@ uint32_t recv_thread (void *vrecv_thread_arg)
nn_rbufpool_setowner (rbpool, ddsrt_thread_self ());
if (waitset == NULL)
{
- while (gv.rtps_keepgoing)
+ struct ddsi_tran_conn *conn = recv_thread_arg->u.single.conn;
+ while (ddsrt_atomic_ld32 (&gv->rtps_keepgoing))
{
- LOG_THREAD_CPUTIME (next_thread_cputime);
- (void) do_packet (ts1, recv_thread_arg->u.single.conn, NULL, rbpool);
+ LOG_THREAD_CPUTIME (&gv->logconfig, next_thread_cputime);
+ (void) do_packet (ts1, gv, conn, NULL, rbpool);
}
}
else
@@ -3360,50 +3314,49 @@ uint32_t recv_thread (void *vrecv_thread_arg)
struct local_participant_set lps;
unsigned num_fixed = 0, num_fixed_uc = 0;
os_sockWaitsetCtx ctx;
- unsigned i;
struct local_deaf_state lds;
- lds.state = gv.deaf ? LDSR_DEAF : LDSR_NORMAL;
+ lds.state = gv->deaf ? LDSR_DEAF : LDSR_NORMAL;
lds.tnext = now_mt();
- local_participant_set_init (&lps);
- if (gv.m_factory->m_connless)
+ local_participant_set_init (&lps, &gv->participant_set_generation);
+ if (gv->m_factory->m_connless)
{
int rc;
- if ((rc = recv_thread_waitset_add_conn (waitset, gv.disc_conn_uc)) < 0)
+ if ((rc = recv_thread_waitset_add_conn (waitset, gv->disc_conn_uc)) < 0)
DDS_FATAL("recv_thread: failed to add disc_conn_uc to waitset\n");
num_fixed_uc += (unsigned)rc;
- if ((rc = recv_thread_waitset_add_conn (waitset, gv.data_conn_uc)) < 0)
+ if ((rc = recv_thread_waitset_add_conn (waitset, gv->data_conn_uc)) < 0)
DDS_FATAL("recv_thread: failed to add data_conn_uc to waitset\n");
num_fixed_uc += (unsigned)rc;
num_fixed += num_fixed_uc;
- if ((rc = recv_thread_waitset_add_conn (waitset, gv.disc_conn_mc)) < 0)
+ if ((rc = recv_thread_waitset_add_conn (waitset, gv->disc_conn_mc)) < 0)
DDS_FATAL("recv_thread: failed to add disc_conn_mc to waitset\n");
num_fixed += (unsigned)rc;
- if ((rc = recv_thread_waitset_add_conn (waitset, gv.data_conn_mc)) < 0)
+ if ((rc = recv_thread_waitset_add_conn (waitset, gv->data_conn_mc)) < 0)
DDS_FATAL("recv_thread: failed to add data_conn_mc to waitset\n");
num_fixed += (unsigned)rc;
}
- while (gv.rtps_keepgoing)
+ while (ddsrt_atomic_ld32 (&gv->rtps_keepgoing))
{
int rebuildws;
- LOG_THREAD_CPUTIME (next_thread_cputime);
- rebuildws = check_and_handle_deafness(&lds, num_fixed_uc);
- if (config.many_sockets_mode != MSM_MANY_UNICAST)
+ LOG_THREAD_CPUTIME (&gv->logconfig, next_thread_cputime);
+ rebuildws = check_and_handle_deafness (gv, &lds, num_fixed_uc);
+ if (gv->config.many_sockets_mode != MSM_MANY_UNICAST)
{
/* no other sockets to check */
}
- else if (ddsrt_atomic_ld32 (&gv.participant_set_generation) != lps.gen)
+ else if (ddsrt_atomic_ld32 (&gv->participant_set_generation) != lps.gen)
{
rebuildws = 1;
}
- if (rebuildws && waitset && config.many_sockets_mode == MSM_MANY_UNICAST)
+ if (rebuildws && waitset && gv->config.many_sockets_mode == MSM_MANY_UNICAST)
{
/* first rebuild local participant set - unless someone's toggling "deafness", this
only happens when the participant set has changed, so might as well rebuild it */
- rebuild_local_participant_set (ts1, &lps);
+ rebuild_local_participant_set (ts1, gv, &lps);
os_sockWaitsetPurge (waitset, num_fixed);
- for (i = 0; i < lps.nps; i++)
+ for (uint32_t i = 0; i < lps.nps; i++)
{
if (lps.ps[i].m_conn)
os_sockWaitsetAdd (waitset, lps.ps[i].m_conn);
@@ -3417,12 +3370,12 @@ uint32_t recv_thread (void *vrecv_thread_arg)
while ((idx = os_sockWaitsetNextEvent (ctx, &conn)) >= 0)
{
const nn_guid_prefix_t *guid_prefix;
- if (((unsigned)idx < num_fixed) || config.many_sockets_mode != MSM_MANY_UNICAST)
+ if (((unsigned)idx < num_fixed) || gv->config.many_sockets_mode != MSM_MANY_UNICAST)
guid_prefix = NULL;
else
guid_prefix = &lps.ps[(unsigned)idx - num_fixed].guid_prefix;
/* Process message and clean out connection if failed or closed */
- if (!do_packet (ts1, conn, guid_prefix, rbpool) && !conn->m_connless)
+ if (!do_packet (ts1, gv, conn, guid_prefix, rbpool) && !conn->m_connless)
ddsi_conn_free (conn);
}
}
diff --git a/src/core/ddsi/src/ddsi_rhc_plugin.c b/src/core/ddsi/src/q_rhc.c
similarity index 50%
rename from src/core/ddsi/src/ddsi_rhc_plugin.c
rename to src/core/ddsi/src/q_rhc.c
index 969c753..187521f 100644
--- a/src/core/ddsi/src/ddsi_rhc_plugin.c
+++ b/src/core/ddsi/src/q_rhc.c
@@ -9,11 +9,17 @@
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
-#include "dds/ddsi/q_entity.h"
+#include "dds/ddsi/q_rhc.h"
#include "dds/ddsi/q_xqos.h"
-#include "dds/ddsi/ddsi_rhc_plugin.h"
+#include "dds/ddsi/q_entity.h"
-DDS_EXPORT void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct nn_xqos *xqos)
+extern inline void rhc_free (struct rhc *rhc);
+extern inline bool rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk);
+extern inline void rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info);
+extern inline void rhc_relinquish_ownership (struct rhc * __restrict rhc, const uint64_t wr_iid);
+extern inline void rhc_set_qos (struct rhc *rhc, const struct dds_qos *qos);
+
+void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct dds_qos *xqos)
{
pwr_info->guid = e->guid;
pwr_info->ownership_strength = xqos->ownership_strength.value;
diff --git a/src/core/ddsi/src/q_security.c b/src/core/ddsi/src/q_security.c
index 408c077..0a94204 100644
--- a/src/core/ddsi/src/q_security.c
+++ b/src/core/ddsi/src/q_security.c
@@ -14,7 +14,6 @@
#include "dds/ddsi/q_security.h"
#include "dds/ddsi/q_config.h"
#include "dds/ddsi/q_log.h"
-#include "dds/ddsi/q_error.h"
#include "os/os_stdlib.h"
#include "os/os_process.h"
#include "os/os_thread.h"
@@ -1657,16 +1656,15 @@ static os_ssize_t q_security_sendmsg
char stbuf[2048], *buf;
size_t sz, data_size;
uint32_t sz32, data_size32;
- ssize_t ret = Q_ERR_UNSPECIFIED;
+ ssize_t ret = DDS_RETCODE_ERROR;
PT_InfoContainer_t * securityHeader;
- unsigned i;
assert (niov > 2);
securityHeader = iov[1].iov_base;
/* first determine the size of the message, then select the
on-stack buffer or allocate one on the heap ... */
sz = q_securityEncoderSetHeaderSize (*codec); /* reserve appropriate headersize */
- for (i = 2; i < niov; i++)
+ for (uint32_t i = 2; i < niov; i++)
{
sz += iov[i].iov_len;
}
@@ -1680,7 +1678,7 @@ static os_ssize_t q_security_sendmsg
}
/* ... then copy data into buffer */
data_size = 0;
- for (i = 2; i < niov; i++)
+ for (uint32_t i = 2; i < niov; i++)
{
memcpy (buf + data_size, iov[i].iov_base, iov[i].iov_len);
data_size += iov[i].iov_len;
diff --git a/src/core/ddsi/src/q_sockwaitset.c b/src/core/ddsi/src/q_sockwaitset.c
index f8a761f..e0cecef 100644
--- a/src/core/ddsi/src/q_sockwaitset.c
+++ b/src/core/ddsi/src/q_sockwaitset.c
@@ -118,7 +118,7 @@ os_sockWaitset os_sockWaitsetNew (void)
ws->ctx.nevs = 0;
ws->ctx.index = 0;
ws->ctx.evs_sz = sz;
- if ((ws->ctx.evs = malloc (ws->ctx.evs_sz * sizeof (*ws->ctx.evs))) == NULL)
+ if ((ws->ctx.evs = ddsrt_malloc (ws->ctx.evs_sz * sizeof (*ws->ctx.evs))) == NULL)
goto fail_ctx_evs;
if ((ws->kqueue = kqueue ()) == -1)
goto fail_kqueue;
@@ -311,9 +311,7 @@ os_sockWaitset os_sockWaitsetNew (void)
void os_sockWaitsetFree (os_sockWaitset ws)
{
- unsigned i;
-
- for (i = 0; i < ws->ctx.n; i++)
+ for (unsigned i = 0; i < ws->ctx.n; i++)
{
WSACloseEvent (ws->ctx.events[i]);
}
@@ -323,10 +321,8 @@ void os_sockWaitsetFree (os_sockWaitset ws)
void os_sockWaitsetPurge (os_sockWaitset ws, unsigned index)
{
- unsigned i;
-
ddsrt_mutex_lock (&ws->mutex);
- for (i = index + 1; i < ws->ctx.n; i++)
+ for (unsigned i = index + 1; i < ws->ctx.n; i++)
{
ws->ctx.conns[i] = NULL;
if (!WSACloseEvent (ws->ctx.events[i]))
@@ -340,10 +336,8 @@ void os_sockWaitsetPurge (os_sockWaitset ws, unsigned index)
void os_sockWaitsetRemove (os_sockWaitset ws, ddsi_tran_conn_t conn)
{
- unsigned i;
-
ddsrt_mutex_lock (&ws->mutex);
- for (i = 0; i < ws->ctx.n; i++)
+ for (unsigned i = 0; i < ws->ctx.n; i++)
{
if (conn == ws->ctx.conns[i])
{
@@ -509,7 +503,7 @@ int os_sockWaitsetNextEvent (os_sockWaitsetCtx ctx, ddsi_tran_conn_t * conn)
#define OSPL_PIPENAMESIZE 26
#endif
-#ifndef _WIN32
+#if !_WIN32 && !LWIP_SOCKET
#ifndef __VXWORKS__
#include
@@ -524,7 +518,7 @@ int os_sockWaitsetNextEvent (os_sockWaitsetCtx ctx, ddsi_tran_conn_t * conn)
#include
#endif
-#endif /* _WIN32 */
+#endif /* !_WIN32 && !LWIP_SOCKET */
typedef struct os_sockWaitsetSet
{
@@ -586,7 +580,7 @@ fail:
closesocket (s2);
return -1;
}
-#elif defined (VXWORKS_RTP) || defined (_WRS_KERNEL)
+#elif defined(__VXWORKS__)
static int make_pipe (int pfd[2])
{
char pipename[OSPL_PIPENAMESIZE];
@@ -609,7 +603,7 @@ fail_open0:
fail_pipedev:
return -1;
}
-#else
+#elif !defined(LWIP_SOCKET)
static int make_pipe (int pfd[2])
{
return pipe (pfd);
@@ -644,7 +638,11 @@ os_sockWaitset os_sockWaitsetNew (void)
ws->fdmax_plus_1 = FD_SETSIZE;
#endif
-#if defined (VXWORKS_RTP) || defined (_WRS_KERNEL)
+#if defined(LWIP_SOCKET)
+ ws->pipe[0] = -1;
+ ws->pipe[1] = -1;
+ result = 0;
+#elif defined(__VXWORKS__)
int make_pipe (int pfd[2])
{
char pipename[OSPL_PIPENAMESIZE];
@@ -679,15 +677,21 @@ os_sockWaitset os_sockWaitsetNew (void)
assert (result != -1);
(void) result;
+#if !defined(LWIP_SOCKET)
ws->set.fds[0] = ws->pipe[0];
+#else
+ ws->set.fds[0] = 0;
+#endif
ws->set.conns[0] = NULL;
-#if ! defined (VXWORKS_RTP) && ! defined ( _WRS_KERNEL ) && ! defined (_WIN32)
+#if !defined(__VXWORKS__) && !defined(_WIN32) && !defined(LWIP_SOCKET)
fcntl (ws->pipe[0], F_SETFD, fcntl (ws->pipe[0], F_GETFD) | FD_CLOEXEC);
fcntl (ws->pipe[1], F_SETFD, fcntl (ws->pipe[1], F_GETFD) | FD_CLOEXEC);
#endif
+#if !defined(LWIP_SOCKET)
FD_SET (ws->set.fds[0], &ws->ctx.rdset);
-#if ! defined (_WIN32)
+#endif
+#if !defined(_WIN32)
ws->fdmax_plus_1 = ws->set.fds[0] + 1;
#endif
@@ -716,18 +720,18 @@ static void os_sockWaitsetFreeCtx (os_sockWaitsetCtx ctx)
void os_sockWaitsetFree (os_sockWaitset ws)
{
-#ifdef VXWORKS_RTP
+#if defined(__VXWORKS__) && defined(__RTP__)
char nameBuf[OSPL_PIPENAMESIZE];
ioctl (ws->pipe[0], FIOGETNAME, &nameBuf);
#endif
-#if defined (_WIN32)
+#if defined(_WIN32)
closesocket (ws->pipe[0]);
closesocket (ws->pipe[1]);
-#else
+#elif !defined(LWIP_SOCKET)
close (ws->pipe[0]);
close (ws->pipe[1]);
#endif
-#ifdef VXWORKS_RTP
+#if defined(__VXWORKS__) && defined(__RTP__)
pipeDevDelete ((char*) &nameBuf, 0);
#endif
os_sockWaitsetFreeSet (&ws->set);
@@ -738,6 +742,9 @@ void os_sockWaitsetFree (os_sockWaitset ws)
void os_sockWaitsetTrigger (os_sockWaitset ws)
{
+#if defined(LWIP_SOCKET)
+ (void)ws;
+#else
char buf = 0;
int n;
@@ -750,6 +757,7 @@ void os_sockWaitsetTrigger (os_sockWaitset ws)
{
DDS_WARNING("os_sockWaitsetTrigger: write failed on trigger pipe\n");
}
+#endif
}
int os_sockWaitsetAdd (os_sockWaitset ws, ddsi_tran_conn_t conn)
@@ -791,13 +799,12 @@ int os_sockWaitsetAdd (os_sockWaitset ws, ddsi_tran_conn_t conn)
void os_sockWaitsetPurge (os_sockWaitset ws, unsigned index)
{
- unsigned i;
os_sockWaitsetSet * set = &ws->set;
ddsrt_mutex_lock (&ws->mutex);
if (index + 1 <= set->n)
{
- for (i = index + 1; i < set->n; i++)
+ for (unsigned i = index + 1; i < set->n; i++)
{
set->conns[i] = NULL;
set->fds[i] = 0;
@@ -809,11 +816,10 @@ void os_sockWaitsetPurge (os_sockWaitset ws, unsigned index)
void os_sockWaitsetRemove (os_sockWaitset ws, ddsi_tran_conn_t conn)
{
- unsigned i;
os_sockWaitsetSet * set = &ws->set;
ddsrt_mutex_lock (&ws->mutex);
- for (i = 0; i < set->n; i++)
+ for (unsigned i = 0; i < set->n; i++)
{
if (conn == set->conns[i])
{
@@ -863,14 +869,23 @@ os_sockWaitsetCtx os_sockWaitsetWait (os_sockWaitset ws)
rdset = &ctx->rdset;
FD_ZERO (rdset);
+#if !defined(LWIP_SOCKET)
for (u = 0; u < dst->n; u++)
{
FD_SET (dst->fds[u], rdset);
}
+#else
+ for (u = 1; u < dst->n; u++)
+ {
+ DDSRT_WARNING_GNUC_OFF(sign-conversion)
+ FD_SET (dst->fds[u], rdset);
+ DDSRT_WARNING_GNUC_ON(sign-conversion)
+ }
+#endif /* LWIP_SOCKET */
do
{
- dds_retcode_t rc = ddsrt_select (fdmax, rdset, NULL, NULL, DDS_INFINITY, &n);
+ dds_return_t rc = ddsrt_select (fdmax, rdset, NULL, NULL, DDS_INFINITY, &n);
if (rc != DDS_RETCODE_OK && rc != DDS_RETCODE_INTERRUPTED && rc != DDS_RETCODE_TRY_AGAIN)
{
DDS_WARNING("os_sockWaitsetWait: select failed, retcode = %"PRId32, rc);
@@ -883,6 +898,7 @@ os_sockWaitsetCtx os_sockWaitsetWait (os_sockWaitset ws)
{
/* this simply skips the trigger fd */
ctx->index = 1;
+#if ! defined(LWIP_SOCKET)
if (FD_ISSET (dst->fds[0], rdset))
{
char buf;
@@ -898,19 +914,26 @@ os_sockWaitsetCtx os_sockWaitsetWait (os_sockWaitset ws)
assert (0);
}
}
+#endif /* LWIP_SOCKET */
return ctx;
}
return NULL;
}
+#if defined(LWIP_SOCKET)
+DDSRT_WARNING_GNUC_OFF(sign-conversion)
+#endif
+
int os_sockWaitsetNextEvent (os_sockWaitsetCtx ctx, ddsi_tran_conn_t * conn)
{
while (ctx->index < ctx->set.n)
{
unsigned idx = ctx->index++;
ddsrt_socket_t fd = ctx->set.fds[idx];
+#if ! defined (LWIP_SOCKET)
assert(idx > 0);
+#endif
if (FD_ISSET (fd, &ctx->rdset))
{
*conn = ctx->set.conns[idx];
@@ -921,6 +944,10 @@ int os_sockWaitsetNextEvent (os_sockWaitsetCtx ctx, ddsi_tran_conn_t * conn)
return -1;
}
+#if defined(LWIP_SOCKET)
+DDSRT_WARNING_GNUC_ON(sign-conversion)
+#endif
+
#else
#error "no mode selected"
#endif
diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c
index 6cf4a47..171888a 100644
--- a/src/core/ddsi/src/q_thread.c
+++ b/src/core/ddsi/src/q_thread.c
@@ -23,7 +23,6 @@
#include "dds/ddsi/q_thread.h"
#include "dds/ddsi/ddsi_threadmon.h"
-#include "dds/ddsi/q_error.h"
#include "dds/ddsi/q_log.h"
#include "dds/ddsi/q_config.h"
#include "dds/ddsi/q_globals.h"
@@ -42,12 +41,14 @@ extern inline struct thread_state1 *lookup_thread_state (void);
extern inline bool thread_is_asleep (void);
extern inline bool thread_is_awake (void);
extern inline void thread_state_asleep (struct thread_state1 *ts1);
-extern inline void thread_state_awake (struct thread_state1 *ts1);
+extern inline void thread_state_awake (struct thread_state1 *ts1, const struct q_globals *gv);
+extern inline void thread_state_awake_domain_ok (struct thread_state1 *ts1);
+extern inline void thread_state_awake_fixed_domain (struct thread_state1 *ts1);
extern inline void thread_state_awake_to_awake_no_nest (struct thread_state1 *ts1);
-static struct thread_state1 *init_thread_state (const char *tname, enum thread_state state);
+static struct thread_state1 *init_thread_state (const char *tname, const struct q_globals *gv, enum thread_state state);
-void *ddsrt_malloc_aligned_cacheline (size_t size)
+static void *ddsrt_malloc_aligned_cacheline (size_t size)
{
/* This wastes some space, but we use it only once and it isn't a
huge amount of memory, just a little over a cache line.
@@ -76,35 +77,32 @@ static void ddsrt_free_aligned (void *ptr)
void thread_states_init_static (void)
{
static struct thread_state1 ts = {
- .state = THREAD_STATE_ALIVE, .vtime = 0u, .name = "(anon)"
+ .state = THREAD_STATE_ALIVE, .vtime = DDSRT_ATOMIC_UINT32_INIT (0), .name = "(anon)"
};
tsd_thread_state = &ts;
}
void thread_states_init (unsigned maxthreads)
{
- unsigned i;
-
ddsrt_mutex_init (&thread_states.lock);
thread_states.nthreads = maxthreads;
thread_states.ts =
ddsrt_malloc_aligned_cacheline (maxthreads * sizeof (*thread_states.ts));
memset (thread_states.ts, 0, maxthreads * sizeof (*thread_states.ts));
-/* The compiler doesn't realize that ts is large enough. */
-DDSRT_WARNING_MSVC_OFF(6386);
- for (i = 0; i < thread_states.nthreads; i++)
+ /* The compiler doesn't realize that ts is large enough. */
+ DDSRT_WARNING_MSVC_OFF(6386);
+ for (uint32_t i = 0; i < thread_states.nthreads; i++)
{
thread_states.ts[i].state = THREAD_STATE_ZERO;
- thread_states.ts[i].vtime = 0u;
- thread_states.ts[i].name = NULL;
+ ddsrt_atomic_st32 (&thread_states.ts[i].vtime, 0);
+ memset (thread_states.ts[i].name, 0, sizeof (thread_states.ts[i].name));
}
-DDSRT_WARNING_MSVC_ON(6386);
+ DDSRT_WARNING_MSVC_ON(6386);
}
void thread_states_fini (void)
{
- unsigned i;
- for (i = 0; i < thread_states.nthreads; i++)
+ for (uint32_t i = 0; i < thread_states.nthreads; i++)
assert (thread_states.ts[i].state != THREAD_STATE_ALIVE);
ddsrt_mutex_destroy (&thread_states.lock);
ddsrt_free_aligned (thread_states.ts);
@@ -117,14 +115,14 @@ void thread_states_fini (void)
thread_states.ts = NULL;
}
+ddsrt_attribute_no_sanitize (("thread"))
static struct thread_state1 *find_thread_state (ddsrt_thread_t tid)
{
if (thread_states.ts) {
- unsigned i;
- for (i = 0; i < thread_states.nthreads; i++) {
- if (ddsrt_thread_equal (thread_states.ts[i].tid, tid)) {
+ for (uint32_t i = 0; i < thread_states.nthreads; i++)
+ {
+ if (ddsrt_thread_equal (thread_states.ts[i].tid, tid))
return &thread_states.ts[i];
- }
}
}
return NULL;
@@ -137,7 +135,7 @@ static void cleanup_thread_state (void *data)
if (ts)
{
assert(ts->state == THREAD_STATE_LAZILY_CREATED);
- assert(vtime_asleep_p(ts->vtime));
+ assert(vtime_asleep_p(ddsrt_atomic_ld32 (&ts->vtime)));
reset_thread_state(ts);
}
ddsrt_fini();
@@ -152,11 +150,11 @@ static struct thread_state1 *lazy_create_thread_state (ddsrt_thread_t self)
char name[128];
ddsrt_thread_getname (name, sizeof (name));
ddsrt_mutex_lock (&thread_states.lock);
- if ((ts1 = init_thread_state (name, THREAD_STATE_LAZILY_CREATED)) != NULL) {
+ if ((ts1 = init_thread_state (name, NULL, THREAD_STATE_LAZILY_CREATED)) != NULL) {
ddsrt_init ();
ts1->extTid = self;
ts1->tid = self;
- DDS_TRACE ("started application thread %s\n", name);
+ DDS_LOG (DDS_LC_TRACE, "started application thread %s\n", name);
ddsrt_thread_cleanup_push (&cleanup_thread_state, NULL);
}
ddsrt_mutex_unlock (&thread_states.lock);
@@ -187,7 +185,9 @@ static uint32_t create_thread_wrapper (void *ptr)
{
uint32_t ret;
struct thread_context *ctx = ptr;
- DDS_TRACE ("started new thread %"PRIdTID": %s\n", ddsrt_gettid (), ctx->self->name);
+ struct q_globals const * const gv = ddsrt_atomic_ldvoidp (&ctx->self->gv);
+ if (gv)
+ GVTRACE ("started new thread %"PRIdTID": %s\n", ddsrt_gettid (), ctx->self->name);
ctx->self->tid = ddsrt_thread_self ();
ret = ctx->f (ctx->arg);
ddsrt_free (ctx);
@@ -196,10 +196,10 @@ static uint32_t create_thread_wrapper (void *ptr)
static int find_free_slot (const char *name)
{
- for (unsigned i = 0; i < thread_states.nthreads; i++)
+ for (uint32_t i = 0; i < thread_states.nthreads; i++)
if (thread_states.ts[i].state == THREAD_STATE_ZERO)
return (int) i;
- DDS_FATAL("create_thread: %s: no free slot\n", name ? name : "(anon)");
+ DDS_FATAL ("create_thread: %s: no free slot\n", name ? name : "(anon)");
return -1;
}
@@ -212,24 +212,27 @@ void upgrade_main_thread (void)
abort ();
ts1 = &thread_states.ts[cand];
if (ts1->state == THREAD_STATE_ZERO)
- assert (vtime_asleep_p (ts1->vtime));
+ assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts1->vtime)));
ts1->state = THREAD_STATE_LAZILY_CREATED;
ts1->tid = ddsrt_thread_self ();
- ts1->name = main_thread_name;
+ DDSRT_WARNING_MSVC_OFF(4996);
+ strncpy (ts1->name, main_thread_name, sizeof (ts1->name));
+ DDSRT_WARNING_MSVC_ON(4996);
+ ts1->name[sizeof (ts1->name) - 1] = 0;
ddsrt_mutex_unlock (&thread_states.lock);
tsd_thread_state = ts1;
}
-const struct config_thread_properties_listelem *lookup_thread_properties (const char *name)
+const struct config_thread_properties_listelem *lookup_thread_properties (const struct config *config, const char *name)
{
const struct config_thread_properties_listelem *e;
- for (e = config.thread_properties; e != NULL; e = e->next)
+ for (e = config->thread_properties; e != NULL; e = e->next)
if (strcmp (e->name, name) == 0)
break;
return e;
}
-static struct thread_state1 *init_thread_state (const char *tname, enum thread_state state)
+static struct thread_state1 *init_thread_state (const char *tname, const struct q_globals *gv, enum thread_state state)
{
int cand;
struct thread_state1 *ts;
@@ -238,23 +241,26 @@ static struct thread_state1 *init_thread_state (const char *tname, enum thread_s
return NULL;
ts = &thread_states.ts[cand];
- assert (vtime_asleep_p (ts->vtime));
- ts->name = ddsrt_strdup (tname);
+ ddsrt_atomic_stvoidp (&ts->gv, (struct q_globals *) gv);
+ assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts->vtime)));
+ DDSRT_WARNING_MSVC_OFF(4996);
+ strncpy (ts->name, tname, sizeof (ts->name));
+ DDSRT_WARNING_MSVC_ON(4996);
+ ts->name[sizeof (ts->name) - 1] = 0;
ts->state = state;
return ts;
}
-dds_retcode_t create_thread (struct thread_state1 **ts1, const char *name, uint32_t (*f) (void *arg), void *arg)
+static dds_return_t create_thread_int (struct thread_state1 **ts1, const struct q_globals *gv, struct config_thread_properties_listelem const * const tprops, const char *name, uint32_t (*f) (void *arg), void *arg)
{
- struct config_thread_properties_listelem const * const tprops = lookup_thread_properties (name);
ddsrt_threadattr_t tattr;
ddsrt_thread_t tid;
struct thread_context *ctxt;
ctxt = ddsrt_malloc (sizeof (*ctxt));
ddsrt_mutex_lock (&thread_states.lock);
- *ts1 = init_thread_state (name, THREAD_STATE_ALIVE);
+ *ts1 = init_thread_state (name, gv, THREAD_STATE_ALIVE);
if (*ts1 == NULL)
goto fatal;
@@ -270,18 +276,21 @@ dds_retcode_t create_thread (struct thread_state1 **ts1, const char *name, uint3
if (!tprops->stack_size.isdefault)
tattr.stackSize = tprops->stack_size.value;
}
- DDS_TRACE("create_thread: %s: class %d priority %"PRId32" stack %"PRIu32"\n", name, (int) tattr.schedClass, tattr.schedPriority, tattr.stackSize);
+ if (gv)
+ {
+ GVTRACE ("create_thread: %s: class %d priority %"PRId32" stack %"PRIu32"\n", name, (int) tattr.schedClass, tattr.schedPriority, tattr.stackSize);
+ }
if (ddsrt_thread_create (&tid, name, &tattr, &create_thread_wrapper, ctxt) != DDS_RETCODE_OK)
{
(*ts1)->state = THREAD_STATE_ZERO;
- DDS_FATAL("create_thread: %s: ddsrt_thread_create failed\n", name);
+ DDS_FATAL ("create_thread: %s: ddsrt_thread_create failed\n", name);
goto fatal;
}
(*ts1)->extTid = tid; /* overwrite the temporary value with the correct external one */
ddsrt_mutex_unlock (&thread_states.lock);
return DDS_RETCODE_OK;
- fatal:
+fatal:
ddsrt_mutex_unlock (&thread_states.lock);
ddsrt_free (ctxt);
*ts1 = NULL;
@@ -289,56 +298,57 @@ dds_retcode_t create_thread (struct thread_state1 **ts1, const char *name, uint3
return DDS_RETCODE_ERROR;
}
-static void reap_thread_state (struct thread_state1 *ts1, int sync_with_servicelease)
+dds_return_t create_thread_with_properties (struct thread_state1 **ts1, struct config_thread_properties_listelem const * const tprops, const char *name, uint32_t (*f) (void *arg), void *arg)
+{
+ return create_thread_int (ts1, NULL, tprops, name, f, arg);
+}
+
+dds_return_t create_thread (struct thread_state1 **ts1, const struct q_globals *gv, const char *name, uint32_t (*f) (void *arg), void *arg)
+{
+ struct config_thread_properties_listelem const * const tprops = lookup_thread_properties (&gv->config, name);
+ return create_thread_int (ts1, gv, tprops, name, f, arg);
+}
+
+static void reap_thread_state (struct thread_state1 *ts1)
{
ddsrt_mutex_lock (&thread_states.lock);
ts1->state = THREAD_STATE_ZERO;
- if (sync_with_servicelease && gv.threadmon)
- ddsi_threadmon_statechange_barrier (gv.threadmon);
- if (ts1->name != main_thread_name)
- ddsrt_free (ts1->name);
ddsrt_mutex_unlock (&thread_states.lock);
}
-int join_thread (struct thread_state1 *ts1)
+dds_return_t join_thread (struct thread_state1 *ts1)
{
- int ret;
+ dds_return_t ret;
assert (ts1->state == THREAD_STATE_ALIVE);
- if (ddsrt_thread_join (ts1->extTid, NULL) == DDS_RETCODE_OK)
- ret = 0;
- else
- ret = Q_ERR_UNSPECIFIED;
- assert (vtime_asleep_p (ts1->vtime));
- reap_thread_state (ts1, 1);
+ ret = ddsrt_thread_join (ts1->extTid, NULL);
+ assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts1->vtime)));
+ reap_thread_state (ts1);
return ret;
}
void reset_thread_state (struct thread_state1 *ts1)
{
if (ts1)
- {
- reap_thread_state (ts1, 1);
- ts1->name = NULL;
- }
+ reap_thread_state (ts1);
}
void downgrade_main_thread (void)
{
struct thread_state1 *ts1 = lookup_thread_state ();
- assert (vtime_asleep_p (ts1->vtime));
+ assert (vtime_asleep_p (ddsrt_atomic_ld32 (&ts1->vtime)));
/* no need to sync with service lease: already stopped */
- reap_thread_state (ts1, 0);
+ reap_thread_state (ts1);
thread_states_init_static ();
}
-void log_stack_traces (void)
+void log_stack_traces (const struct ddsrt_log_cfg *logcfg, const struct q_globals *gv)
{
- unsigned i;
- for (i = 0; i < thread_states.nthreads; i++)
+ for (uint32_t i = 0; i < thread_states.nthreads; i++)
{
- if (thread_states.ts[i].state != THREAD_STATE_ZERO)
+ if (thread_states.ts[i].state != THREAD_STATE_ZERO &&
+ (gv == NULL || ddsrt_atomic_ldvoidp (&thread_states.ts[i].gv) == gv))
{
- log_stacktrace (thread_states.ts[i].name, thread_states.ts[i].tid);
+ log_stacktrace (logcfg, thread_states.ts[i].name, thread_states.ts[i].tid);
}
}
}
diff --git a/src/core/ddsi/src/q_time.c b/src/core/ddsi/src/q_time.c
index 05878b3..79cfcf3 100644
--- a/src/core/ddsi/src/q_time.c
+++ b/src/core/ddsi/src/q_time.c
@@ -14,10 +14,6 @@
#include "dds/ddsrt/time.h"
#include "dds/ddsi/q_time.h"
-const nn_ddsi_time_t invalid_ddsi_timestamp = { -1, UINT32_MAX };
-const nn_ddsi_time_t ddsi_time_infinite = { INT32_MAX, UINT32_MAX };
-const nn_duration_t duration_infinite = { INT32_MAX, UINT32_MAX };
-
nn_wctime_t now (void)
{
/* This function uses the wall clock.
@@ -131,21 +127,21 @@ nn_etime_t add_duration_to_etime (nn_etime_t t, int64_t d)
return u;
}
-int valid_ddsi_timestamp (nn_ddsi_time_t t)
+int valid_ddsi_timestamp (ddsi_time_t t)
{
- return t.seconds != invalid_ddsi_timestamp.seconds && t.fraction != invalid_ddsi_timestamp.fraction;
+ return t.seconds != DDSI_TIME_INVALID.seconds && t.fraction != DDSI_TIME_INVALID.fraction;
}
-static nn_ddsi_time_t nn_to_ddsi_time (int64_t t)
+static ddsi_time_t nn_to_ddsi_time (int64_t t)
{
if (t == T_NEVER)
- return ddsi_time_infinite;
+ return DDSI_TIME_INFINITE;
else
{
/* ceiling(ns * 2^32/10^9) -- can't change the ceiling to round-to-nearest
because that would break backwards compatibility, but round-to-nearest
of the inverse is correctly rounded anyway, so it shouldn't ever matter. */
- nn_ddsi_time_t x;
+ ddsi_time_t x;
int ns = (int) (t % T_SECOND);
x.seconds = (int) (t / T_SECOND);
x.fraction = (unsigned) (((T_SECOND-1) + ((int64_t) ns << 32)) / T_SECOND);
@@ -153,14 +149,14 @@ static nn_ddsi_time_t nn_to_ddsi_time (int64_t t)
}
}
-nn_ddsi_time_t nn_wctime_to_ddsi_time (nn_wctime_t t)
+ddsi_time_t nn_wctime_to_ddsi_time (nn_wctime_t t)
{
return nn_to_ddsi_time (t.v);
}
-static int64_t nn_from_ddsi_time (nn_ddsi_time_t x)
+static int64_t nn_from_ddsi_time (ddsi_time_t x)
{
- if (x.seconds == ddsi_time_infinite.seconds && x.fraction == ddsi_time_infinite.fraction)
+ if (x.seconds == DDSI_TIME_INFINITE.seconds && x.fraction == DDSI_TIME_INFINITE.fraction)
return T_NEVER;
else
{
@@ -170,19 +166,19 @@ static int64_t nn_from_ddsi_time (nn_ddsi_time_t x)
}
}
-nn_wctime_t nn_wctime_from_ddsi_time (nn_ddsi_time_t x)
+nn_wctime_t nn_wctime_from_ddsi_time (ddsi_time_t x)
{
nn_wctime_t t;
t.v = nn_from_ddsi_time (x);
return t;
}
-nn_duration_t nn_to_ddsi_duration (int64_t x)
+ddsi_duration_t nn_to_ddsi_duration (int64_t x)
{
return nn_to_ddsi_time (x);
}
-int64_t nn_from_ddsi_duration (nn_duration_t x)
+int64_t nn_from_ddsi_duration (ddsi_duration_t x)
{
return nn_from_ddsi_time (x);
}
diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c
index cc086a6..2bdaa70 100644
--- a/src/core/ddsi/src/q_transmit.c
+++ b/src/core/ddsi/src/q_transmit.c
@@ -14,6 +14,7 @@
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/sync.h"
+#include "dds/ddsrt/static_assert.h"
#include "dds/ddsrt/avl.h"
#include "dds/ddsi/q_entity.h"
@@ -26,12 +27,10 @@
#include "dds/ddsi/q_time.h"
#include "dds/ddsi/q_config.h"
#include "dds/ddsi/q_globals.h"
-#include "dds/ddsi/q_error.h"
#include "dds/ddsi/q_transmit.h"
#include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_unused.h"
#include "dds/ddsi/q_hbcontrol.h"
-#include "dds/ddsi/q_static_assert.h"
#include "dds/ddsi/ddsi_tkmap.h"
#include "dds/ddsi/ddsi_serdata.h"
#include "dds/ddsi/ddsi_sertopic.h"
@@ -39,16 +38,6 @@
#include "dds/ddsi/sysdeps.h"
#include "dds__whc.h"
-#if __STDC_VERSION__ >= 199901L
-#define POS_INFINITY_DOUBLE INFINITY
-#elif defined HUGE_VAL
-/* Hope for the best -- the only consequence of getting this wrong is
- that T_NEVER may be printed as a fugly value instead of as +inf. */
-#define POS_INFINITY_DOUBLE (HUGE_VAL + HUGE_VAL)
-#else
-#define POS_INFINITY_DOUBLE 1e1000
-#endif
-
static const struct wr_prd_match *root_rdmatch (const struct writer *wr)
{
return ddsrt_avl_root (&wr_readers_treedef, &wr->readers);
@@ -88,14 +77,15 @@ static void writer_hbcontrol_note_hb (struct writer *wr, nn_mtime_t tnow, int an
int64_t writer_hbcontrol_intv (const struct writer *wr, const struct whc_state *whcst, UNUSED_ARG (nn_mtime_t tnow))
{
+ struct q_globals const * const gv = wr->e.gv;
struct hbcontrol const * const hbc = &wr->hbcontrol;
- int64_t ret = config.const_hb_intv_sched;
+ int64_t ret = gv->config.const_hb_intv_sched;
size_t n_unacked;
if (hbc->hbs_since_last_write > 2)
{
unsigned cnt = hbc->hbs_since_last_write;
- while (cnt-- > 2 && 2 * ret < config.const_hb_intv_sched_max)
+ while (cnt-- > 2 && 2 * ret < gv->config.const_hb_intv_sched_max)
ret *= 2;
}
@@ -106,13 +96,14 @@ int64_t writer_hbcontrol_intv (const struct writer *wr, const struct whc_state *
ret /= 2;
if (wr->throttling)
ret /= 2;
- if (ret < config.const_hb_intv_sched_min)
- ret = config.const_hb_intv_sched_min;
+ if (ret < gv->config.const_hb_intv_sched_min)
+ ret = gv->config.const_hb_intv_sched_min;
return ret;
}
void writer_hbcontrol_note_asyncwrite (struct writer *wr, nn_mtime_t tnow)
{
+ struct q_globals const * const gv = wr->e.gv;
struct hbcontrol * const hbc = &wr->hbcontrol;
nn_mtime_t tnext;
@@ -122,7 +113,7 @@ void writer_hbcontrol_note_asyncwrite (struct writer *wr, nn_mtime_t tnow)
/* We know this is new data, so we want a heartbeat event after one
base interval */
- tnext.v = tnow.v + config.const_hb_intv_sched;
+ tnext.v = tnow.v + gv->config.const_hb_intv_sched;
if (tnext.v < hbc->tsched.v)
{
/* Insertion of a message with WHC locked => must now have at
@@ -141,6 +132,7 @@ int writer_hbcontrol_must_send (const struct writer *wr, const struct whc_state
struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const struct whc_state *whcst, nn_mtime_t tnow, int hbansreq, int issync)
{
+ struct q_globals const * const gv = wr->e.gv;
struct nn_xmsg *msg;
const nn_guid_t *prd_guid;
@@ -148,7 +140,7 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru
assert (wr->reliable);
assert (hbansreq >= 0);
- if ((msg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (InfoTS_t) + sizeof (Heartbeat_t), NN_XMSG_KIND_CONTROL)) == NULL)
+ if ((msg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, sizeof (InfoTS_t) + sizeof (Heartbeat_t), NN_XMSG_KIND_CONTROL)) == NULL)
/* out of memory at worst slows down traffic */
return NULL;
@@ -185,12 +177,12 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru
}
}
- DDS_TRACE("writer_hbcontrol: wr "PGUIDFMT" ", PGUID (wr->e.guid));
+ ETRACE (wr, "writer_hbcontrol: wr "PGUIDFMT" ", PGUID (wr->e.guid));
if (prd_guid == NULL)
- DDS_TRACE("multicasting ");
+ ETRACE (wr, "multicasting ");
else
- DDS_TRACE("unicasting to prd "PGUIDFMT" ", PGUID (*prd_guid));
- DDS_TRACE("(rel-prd %d seq-eq-max %d seq %"PRId64" maxseq %"PRId64")\n",
+ ETRACE (wr, "unicasting to prd "PGUIDFMT" ", PGUID (*prd_guid));
+ ETRACE (wr, "(rel-prd %d seq-eq-max %d seq %"PRId64" maxseq %"PRId64")\n",
wr->num_reliable_readers,
ddsrt_avl_is_empty (&wr->readers) ? -1 : root_rdmatch (wr)->num_reliable_readers_where_seq_equals_max,
wr->seq,
@@ -207,9 +199,9 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru
else
{
struct proxy_reader *prd;
- if ((prd = ephash_lookup_proxy_reader_guid (prd_guid)) == NULL)
+ if ((prd = ephash_lookup_proxy_reader_guid (gv->guid_hash, prd_guid)) == NULL)
{
- DDS_TRACE("writer_hbcontrol: wr "PGUIDFMT" unknown prd "PGUIDFMT"\n", PGUID (wr->e.guid), PGUID (*prd_guid));
+ ETRACE (wr, "writer_hbcontrol: wr "PGUIDFMT" unknown prd "PGUIDFMT"\n", PGUID (wr->e.guid), PGUID (*prd_guid));
nn_xmsg_free (msg);
return NULL;
}
@@ -232,8 +224,9 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru
static int writer_hbcontrol_ack_required_generic (const struct writer *wr, const struct whc_state *whcst, nn_mtime_t tlast, nn_mtime_t tnow, int piggyback)
{
+ struct q_globals const * const gv = wr->e.gv;
struct hbcontrol const * const hbc = &wr->hbcontrol;
- const int64_t hb_intv_ack = config.const_hb_intv_sched;
+ const int64_t hb_intv_ack = gv->config.const_hb_intv_sched;
assert(wr->heartbeat_xevent != NULL && whcst != NULL);
if (piggyback)
@@ -256,9 +249,9 @@ static int writer_hbcontrol_ack_required_generic (const struct writer *wr, const
if (whcst->unacked_bytes >= wr->whc_low + (wr->whc_high - wr->whc_low) / 2)
{
- if (tnow.v >= hbc->t_of_last_ackhb.v + config.const_hb_intv_sched_min)
+ if (tnow.v >= hbc->t_of_last_ackhb.v + gv->config.const_hb_intv_sched_min)
return 2;
- else if (tnow.v >= hbc->t_of_last_ackhb.v + config.const_hb_intv_min)
+ else if (tnow.v >= hbc->t_of_last_ackhb.v + gv->config.const_hb_intv_min)
return 1;
}
@@ -271,10 +264,10 @@ int writer_hbcontrol_ack_required (const struct writer *wr, const struct whc_sta
return writer_hbcontrol_ack_required_generic (wr, whcst, hbc->t_of_last_write, tnow, 0);
}
-struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_state *whcst, nn_mtime_t tnow, unsigned packetid, int *hbansreq)
+struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_state *whcst, nn_mtime_t tnow, uint32_t packetid, int *hbansreq)
{
struct hbcontrol * const hbc = &wr->hbcontrol;
- unsigned last_packetid;
+ uint32_t last_packetid;
nn_mtime_t tlast;
struct nn_xmsg *msg;
@@ -308,10 +301,10 @@ struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_
if (msg)
{
- DDS_TRACE("heartbeat(wr "PGUIDFMT"%s) piggybacked, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n",
+ ETRACE (wr, "heartbeat(wr "PGUIDFMT"%s) piggybacked, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n",
PGUID (wr->e.guid),
*hbansreq ? "" : " final",
- (hbc->tsched.v == T_NEVER) ? POS_INFINITY_DOUBLE : (double) (hbc->tsched.v - tnow.v) / 1e9,
+ (hbc->tsched.v == T_NEVER) ? INFINITY : (double) (hbc->tsched.v - tnow.v) / 1e9,
ddsrt_avl_is_empty (&wr->readers) ? -1 : root_rdmatch (wr)->min_seq,
ddsrt_avl_is_empty (&wr->readers) || root_rdmatch (wr)->all_have_replied_to_hb ? "" : "!",
whcst->max_seq, READ_SEQ_XMIT(wr));
@@ -322,6 +315,7 @@ struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_
void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_state *whcst, int hbansreq, nn_entityid_t dst, int issync)
{
+ struct q_globals const * const gv = wr->e.gv;
struct nn_xmsg_marker sm_marker;
Heartbeat_t * hb;
seqno_t max = 0, min = 1;
@@ -331,7 +325,7 @@ void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_sta
assert (wr->reliable);
assert (hbansreq >= 0);
- if (config.meas_hb_to_ack_latency)
+ if (gv->config.meas_hb_to_ack_latency)
{
/* If configured to measure heartbeat-to-ack latency, we must add
a timestamp. No big deal if it fails. */
@@ -387,12 +381,13 @@ void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_sta
nn_xmsg_submsg_setnext (msg, sm_marker);
}
-static int create_fragment_message_simple (struct writer *wr, seqno_t seq, struct ddsi_serdata *serdata, struct nn_xmsg **pmsg)
+static dds_return_t create_fragment_message_simple (struct writer *wr, seqno_t seq, struct ddsi_serdata *serdata, struct nn_xmsg **pmsg)
{
#define TEST_KEYHASH 0
/* actual expected_inline_qos_size is typically 0, but always claiming 32 bytes won't make
a difference, so no point in being precise */
const size_t expected_inline_qos_size = /* statusinfo */ 8 + /* keyhash */ 20 + /* sentinel */ 4;
+ struct q_globals const * const gv = wr->e.gv;
struct nn_xmsg_marker sm_marker;
unsigned char contentflag = 0;
Data_t *data;
@@ -416,8 +411,8 @@ static int create_fragment_message_simple (struct writer *wr, seqno_t seq, struc
ASSERT_MUTEX_HELD (&wr->e.lock);
/* INFO_TS: 12 bytes, Data_t: 24 bytes, expected inline QoS: 32 => should be single chunk */
- if ((*pmsg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (Data_t) + expected_inline_qos_size, NN_XMSG_KIND_DATA)) == NULL)
- return Q_ERR_OUT_OF_MEMORY;
+ if ((*pmsg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (Data_t) + expected_inline_qos_size, NN_XMSG_KIND_DATA)) == NULL)
+ return DDS_RETCODE_OUT_OF_RESOURCES;
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
/* use the partition_id from the writer to select the proper encoder */
@@ -425,7 +420,7 @@ static int create_fragment_message_simple (struct writer *wr, seqno_t seq, struc
#endif
nn_xmsg_setdstN (*pmsg, wr->as, wr->as_group);
- nn_xmsg_setmaxdelay (*pmsg, nn_from_ddsi_duration (wr->xqos->latency_budget.duration));
+ nn_xmsg_setmaxdelay (*pmsg, wr->xqos->latency_budget.duration);
nn_xmsg_add_timestamp (*pmsg, serdata->timestamp);
data = nn_xmsg_append (*pmsg, &sm_marker, sizeof (Data_t));
@@ -461,7 +456,7 @@ static int create_fragment_message_simple (struct writer *wr, seqno_t seq, struc
return 0;
}
-int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, unsigned fragnum, struct proxy_reader *prd, struct nn_xmsg **pmsg, int isnew)
+dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, unsigned fragnum, struct proxy_reader *prd, struct nn_xmsg **pmsg, int isnew)
{
/* We always fragment into FRAGMENT_SIZEd fragments, which are near
the smallest allowed fragment size & can't be bothered (yet) to
@@ -477,6 +472,7 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli
actual expected_inline_qos_size is typically 0, but always claiming 32 bytes won't make
a difference, so no point in being precise */
const size_t expected_inline_qos_size = /* statusinfo */ 8 + /* keyhash */ 20 + /* sentinel */ 4;
+ struct q_globals const * const gv = wr->e.gv;
struct nn_xmsg_marker sm_marker;
void *sm;
Data_DataFrag_common_t *ddcmn;
@@ -484,25 +480,25 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli
uint32_t fragstart, fraglen;
enum nn_xmsg_kind xmsg_kind = isnew ? NN_XMSG_KIND_DATA : NN_XMSG_KIND_DATA_REXMIT;
const uint32_t size = ddsi_serdata_size (serdata);
- int ret = 0;
+ dds_return_t ret = 0;
(void)plist;
ASSERT_MUTEX_HELD (&wr->e.lock);
- if (fragnum * config.fragment_size >= size && size > 0)
+ if (fragnum * gv->config.fragment_size >= size && size > 0)
{
/* This is the first chance to detect an attempt at retransmitting
an non-existent fragment, which a malicious (or buggy) remote
reader can trigger. So we return an error instead of asserting
as we used to. */
- return Q_ERR_INVALID;
+ return DDS_RETCODE_BAD_PARAMETER;
}
- fragging = (config.fragment_size < size);
+ fragging = (gv->config.fragment_size < size);
/* INFO_TS: 12 bytes, DataFrag_t: 36 bytes, expected inline QoS: 32 => should be single chunk */
- if ((*pmsg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (DataFrag_t) + expected_inline_qos_size, xmsg_kind)) == NULL)
- return Q_ERR_OUT_OF_MEMORY;
+ if ((*pmsg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (DataFrag_t) + expected_inline_qos_size, xmsg_kind)) == NULL)
+ return DDS_RETCODE_OUT_OF_RESOURCES;
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
/* use the partition_id from the writer to select the proper encoder */
@@ -515,14 +511,14 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli
{
nn_xmsg_free (*pmsg);
*pmsg = NULL;
- return Q_ERR_NO_ADDRESS;
+ return DDS_RETCODE_PRECONDITION_NOT_MET;
}
/* retransmits: latency budget doesn't apply */
}
else
{
nn_xmsg_setdstN (*pmsg, wr->as, wr->as_group);
- nn_xmsg_setmaxdelay (*pmsg, nn_from_ddsi_duration (wr->xqos->latency_budget.duration));
+ nn_xmsg_setmaxdelay (*pmsg, wr->xqos->latency_budget.duration);
}
/* Timestamp only needed once, for the first fragment */
@@ -565,18 +561,18 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli
frag->fragmentStartingNum = fragnum + 1;
frag->fragmentsInSubmessage = 1;
- frag->fragmentSize = (unsigned short) config.fragment_size;
+ frag->fragmentSize = (unsigned short) gv->config.fragment_size;
frag->sampleSize = (uint32_t)size;
- fragstart = fragnum * config.fragment_size;
+ fragstart = fragnum * gv->config.fragment_size;
#if MULTIPLE_FRAGS_IN_SUBMSG /* ugly hack for testing only */
- if (fragstart + config.fragment_size < ddsi_serdata_size (serdata) &&
- fragstart + 2 * config.fragment_size >= ddsi_serdata_size (serdata))
+ if (fragstart + gv->config.fragment_size < ddsi_serdata_size (serdata) &&
+ fragstart + 2 * gv->config.fragment_size >= ddsi_serdata_size (serdata))
frag->fragmentsInSubmessage++;
ret = frag->fragmentsInSubmessage;
#endif
- fraglen = config.fragment_size * frag->fragmentsInSubmessage;
+ fraglen = gv->config.fragment_size * frag->fragmentsInSubmessage;
if (fragstart + fraglen > size)
fraglen = (uint32_t)(size - fragstart);
ddcmn->octetsToInlineQos = (unsigned short) ((char*) (frag+1) - ((char*) &ddcmn->octetsToInlineQos + 2));
@@ -599,7 +595,7 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli
if (xmsg_kind == NN_XMSG_KIND_DATA_REXMIT)
nn_xmsg_set_data_readerId (*pmsg, &ddcmn->readerId);
- Q_STATIC_ASSERT_CODE (DATA_FLAG_INLINE_QOS == DATAFRAG_FLAG_INLINE_QOS);
+ DDSRT_STATIC_ASSERT_CODE (DATA_FLAG_INLINE_QOS == DATAFRAG_FLAG_INLINE_QOS);
assert (!(ddcmn->smhdr.flags & DATAFRAG_FLAG_INLINE_QOS));
if (fragnum == 0)
@@ -625,9 +621,9 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli
nn_xmsg_serdata (*pmsg, serdata, fragstart, fraglen);
nn_xmsg_submsg_setnext (*pmsg, sm_marker);
#if 0
- DDS_TRACE("queue data%s "PGUIDFMT" #%lld/%u[%u..%u)\n",
- fragging ? "frag" : "", PGUID (wr->e.guid),
- seq, fragnum+1, fragstart, fragstart + fraglen);
+ GVTRACE ("queue data%s "PGUIDFMT" #%lld/%u[%u..%u)\n",
+ fragging ? "frag" : "", PGUID (wr->e.guid),
+ seq, fragnum+1, fragstart, fragstart + fraglen);
#endif
return ret;
@@ -635,10 +631,11 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli
static void create_HeartbeatFrag (struct writer *wr, seqno_t seq, unsigned fragnum, struct proxy_reader *prd, struct nn_xmsg **pmsg)
{
+ struct q_globals const * const gv = wr->e.gv;
struct nn_xmsg_marker sm_marker;
HeartbeatFrag_t *hbf;
ASSERT_MUTEX_HELD (&wr->e.lock);
- if ((*pmsg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (HeartbeatFrag_t), NN_XMSG_KIND_CONTROL)) == NULL)
+ if ((*pmsg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, sizeof (HeartbeatFrag_t), NN_XMSG_KIND_CONTROL)) == NULL)
return; /* ignore out-of-memory: HeartbeatFrag is only advisory anyway */
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
nn_xmsg_setencoderid (*pmsg, wr->partition_id);
@@ -692,16 +689,15 @@ static int must_skip_frag (const char *frags_to_skip, unsigned frag)
}
#endif
-static void transmit_sample_lgmsg_unlocked (struct nn_xpack *xp, struct writer *wr, const struct whc_state *whcst, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew, unsigned nfrags)
+static void transmit_sample_lgmsg_unlocked (struct nn_xpack *xp, struct writer *wr, const struct whc_state *whcst, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew, uint32_t nfrags)
{
- unsigned i;
#if 0
const char *frags_to_skip = getenv ("SKIPFRAGS");
#endif
assert(xp);
assert((wr->heartbeat_xevent != NULL) == (whcst != NULL));
- for (i = 0; i < nfrags; i++)
+ for (uint32_t i = 0; i < nfrags; i++)
{
struct nn_xmsg *fmsg = NULL;
struct nn_xmsg *hmsg = NULL;
@@ -753,17 +749,18 @@ static void transmit_sample_lgmsg_unlocked (struct nn_xpack *xp, struct writer *
static void transmit_sample_unlocks_wr (struct nn_xpack *xp, struct writer *wr, const struct whc_state *whcst, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew)
{
/* on entry: &wr->e.lock held; on exit: lock no longer held */
+ struct q_globals const * const gv = wr->e.gv;
struct nn_xmsg *fmsg;
uint32_t sz;
assert(xp);
assert((wr->heartbeat_xevent != NULL) == (whcst != NULL));
sz = ddsi_serdata_size (serdata);
- if (sz > config.fragment_size || !isnew || plist != NULL || prd != NULL)
+ if (sz > gv->config.fragment_size || !isnew || plist != NULL || prd != NULL)
{
uint32_t nfrags;
ddsrt_mutex_unlock (&wr->e.lock);
- nfrags = (sz + config.fragment_size - 1) / config.fragment_size;
+ nfrags = (sz + gv->config.fragment_size - 1) / gv->config.fragment_size;
transmit_sample_lgmsg_unlocked (xp, wr, whcst, seq, plist, serdata, prd, isnew, nfrags);
return;
}
@@ -794,13 +791,14 @@ static void transmit_sample_unlocks_wr (struct nn_xpack *xp, struct writer *wr,
int enqueue_sample_wrlock_held (struct writer *wr, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew)
{
+ struct q_globals const * const gv = wr->e.gv;
uint32_t i, sz, nfrags;
int enqueued = 1;
ASSERT_MUTEX_HELD (&wr->e.lock);
sz = ddsi_serdata_size (serdata);
- nfrags = (sz + config.fragment_size - 1) / config.fragment_size;
+ nfrags = (sz + gv->config.fragment_size - 1) / gv->config.fragment_size;
if (nfrags == 0)
{
/* end-of-transaction messages are empty, but still need to be sent */
@@ -853,7 +851,7 @@ static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist
ASSERT_MUTEX_HELD (&wr->e.lock);
- if (dds_get_log_mask() & DDS_LC_TRACE)
+ if (wr->e.gv->logconfig.c.mask & DDS_LC_TRACE)
{
char ppbuf[1024];
int tmp;
@@ -861,10 +859,10 @@ static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist
const char *ttname = wr->topic ? wr->topic->type_name : "(null)";
ppbuf[0] = '\0';
tmp = sizeof (ppbuf) - 1;
- DDS_TRACE("write_sample "PGUIDFMT" #%"PRId64, PGUID (wr->e.guid), seq);
+ ETRACE (wr, "write_sample "PGUIDFMT" #%"PRId64, PGUID (wr->e.guid), seq);
if (plist != 0 && (plist->present & PP_COHERENT_SET))
- DDS_TRACE(" C#%"PRId64"", fromSN (plist->coherent_set_seqno));
- DDS_TRACE(": ST%"PRIu32" %s/%s:%s%s\n", serdata->statusinfo, tname, ttname, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)");
+ ETRACE (wr, " C#%"PRId64"", fromSN (plist->coherent_set_seqno));
+ ETRACE (wr, ": ST%"PRIu32" %s/%s:%s%s\n", serdata->statusinfo, tname, ttname, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)");
}
assert (wr->reliable || have_reliable_subs (wr) == 0);
@@ -901,7 +899,7 @@ static int writer_may_continue (const struct writer *wr, const struct whc_state
}
-static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr)
+static dds_return_t throttle_writer (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr)
{
/* Sleep (cond_wait) without updating the thread's vtime: the
garbage collector won't free the writer while we leave it
@@ -936,10 +934,10 @@ static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct n
resent to them, until a ACKNACK is received from that
reader. This implicitly clears the whc and unblocks the
writer. */
-
- dds_retcode_t result = DDS_RETCODE_OK;
+ struct q_globals const * const gv = wr->e.gv;
+ dds_return_t result = DDS_RETCODE_OK;
nn_mtime_t tnow = now_mt ();
- const nn_mtime_t abstimeout = add_duration_to_mtime (tnow, nn_from_ddsi_duration (wr->xqos->reliability.max_blocking_time));
+ const nn_mtime_t abstimeout = add_duration_to_mtime (tnow, wr->xqos->reliability.max_blocking_time);
struct whc_state whcst;
whc_get_state (wr->whc, &whcst);
@@ -950,7 +948,9 @@ static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct n
assert (!is_builtin_entityid(wr->e.guid.entityid, NN_VENDORID_ECLIPSE));
}
- DDS_LOG(DDS_LC_THROTTLE, "writer "PGUIDFMT" waiting for whc to shrink below low-water mark (whc %"PRIuSIZE" low=%"PRIu32" high=%"PRIu32")\n", PGUID (wr->e.guid), whcst.unacked_bytes, wr->whc_low, wr->whc_high);
+ GVLOG (DDS_LC_THROTTLE,
+ "writer "PGUIDFMT" waiting for whc to shrink below low-water mark (whc %"PRIuSIZE" low=%"PRIu32" high=%"PRIu32")\n",
+ PGUID (wr->e.guid), whcst.unacked_bytes, wr->whc_low, wr->whc_high);
wr->throttling++;
wr->throttle_count++;
@@ -970,7 +970,7 @@ static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct n
whc_get_state (wr->whc, &whcst);
}
- while (gv.rtps_keepgoing && !writer_may_continue (wr, &whcst))
+ while (ddsrt_atomic_ld32 (&gv->rtps_keepgoing) && !writer_may_continue (wr, &whcst))
{
int64_t reltimeout;
tnow = now_mt ();
@@ -981,7 +981,7 @@ static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct n
thread_state_asleep (ts1);
if (ddsrt_cond_waitfor (&wr->throttle_cond, &wr->e.lock, reltimeout))
result = DDS_RETCODE_OK;
- thread_state_awake (ts1);
+ thread_state_awake_domain_ok (ts1);
whc_get_state(wr->whc, &whcst);
}
if (result == DDS_RETCODE_TIMEOUT)
@@ -997,20 +997,23 @@ static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct n
ddsrt_cond_broadcast (&wr->throttle_cond);
}
- DDS_LOG(DDS_LC_THROTTLE, "writer "PGUIDFMT" done waiting for whc to shrink below low-water mark (whc %"PRIuSIZE" low=%"PRIu32" high=%"PRIu32")\n", PGUID (wr->e.guid), whcst.unacked_bytes, wr->whc_low, wr->whc_high);
+ GVLOG (DDS_LC_THROTTLE,
+ "writer "PGUIDFMT" done waiting for whc to shrink below low-water mark (whc %"PRIuSIZE" low=%"PRIu32" high=%"PRIu32")\n",
+ PGUID (wr->e.guid), whcst.unacked_bytes, wr->whc_low, wr->whc_high);
return result;
}
static int maybe_grow_whc (struct writer *wr)
{
- if (!wr->retransmitting && config.whc_adaptive && wr->whc_high < config.whc_highwater_mark)
+ struct q_globals const * const gv = wr->e.gv;
+ if (!wr->retransmitting && gv->config.whc_adaptive && wr->whc_high < gv->config.whc_highwater_mark)
{
nn_etime_t tnow = now_et();
nn_etime_t tgrow = add_duration_to_etime (wr->t_whc_high_upd, 10 * T_MILLISECOND);
if (tnow.v >= tgrow.v)
{
- uint32_t m = (config.whc_highwater_mark - wr->whc_high) / 32;
- wr->whc_high = (m == 0) ? config.whc_highwater_mark : wr->whc_high + m;
+ uint32_t m = (gv->config.whc_highwater_mark - wr->whc_high) / 32;
+ wr->whc_high = (m == 0) ? gv->config.whc_highwater_mark : wr->whc_high + m;
wr->t_whc_high_upd = tnow;
return 1;
}
@@ -1020,15 +1023,16 @@ static int maybe_grow_whc (struct writer *wr)
static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk, int end_of_txn, int gc_allowed)
{
+ struct q_globals const * const gv = wr->e.gv;
int r;
seqno_t seq;
nn_mtime_t tnow;
/* If GC not allowed, we must be sure to never block when writing. That is only the case for (true, aggressive) KEEP_LAST writers, and also only if there is no limit to how much unacknowledged data the WHC may contain. */
- assert(gc_allowed || (wr->xqos->history.kind == NN_KEEP_LAST_HISTORY_QOS && wr->whc_low == INT32_MAX));
- (void)gc_allowed;
+ assert (gc_allowed || (wr->xqos->history.kind == DDS_HISTORY_KEEP_LAST && wr->whc_low == INT32_MAX));
+ (void) gc_allowed;
- if (ddsi_serdata_size (serdata) > config.max_sample_size)
+ if (ddsi_serdata_size (serdata) > gv->config.max_sample_size)
{
char ppbuf[1024];
int tmp;
@@ -1036,11 +1040,11 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack *
const char *ttname = wr->topic ? wr->topic->type_name : "(null)";
ppbuf[0] = '\0';
tmp = sizeof (ppbuf) - 1;
- DDS_WARNING ("dropping oversize (%"PRIu32" > %"PRIu32") sample from local writer "PGUIDFMT" %s/%s:%s%s\n",
- ddsi_serdata_size (serdata), config.max_sample_size,
- PGUID (wr->e.guid), tname, ttname, ppbuf,
- tmp < (int) sizeof (ppbuf) ? "" : " (trunc)");
- r = Q_ERR_INVALID_DATA;
+ GVWARNING ("dropping oversize (%"PRIu32" > %"PRIu32") sample from local writer "PGUIDFMT" %s/%s:%s%s\n",
+ ddsi_serdata_size (serdata), gv->config.max_sample_size,
+ PGUID (wr->e.guid), tname, ttname, ppbuf,
+ tmp < (int) sizeof (ppbuf) ? "" : " (trunc)");
+ r = DDS_RETCODE_BAD_PARAMETER;
goto drop;
}
@@ -1057,9 +1061,9 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack *
whc_get_state(wr->whc, &whcst);
if (whcst.unacked_bytes > wr->whc_high)
{
- dds_retcode_t ores;
+ dds_return_t ores;
assert(gc_allowed); /* also see beginning of the function */
- if (config.prioritize_retransmit && wr->retransmitting)
+ if (gv->config.prioritize_retransmit && wr->retransmitting)
ores = throttle_writer (ts1, xp, wr);
else
{
@@ -1072,7 +1076,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack *
if (ores == DDS_RETCODE_TIMEOUT)
{
ddsrt_mutex_unlock (&wr->e.lock);
- r = Q_ERR_TIMEOUT;
+ r = DDS_RETCODE_TIMEOUT;
goto drop;
}
}
@@ -1105,6 +1109,22 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack *
ddsrt_free (plist);
}
}
+ else if (addrset_empty (wr->as) && (wr->as_group == NULL || addrset_empty (wr->as_group)))
+ {
+ /* No network destination, so no point in doing all the work involved
+ in going all the way. We do have to record that we "transmitted"
+ this sample, or it might not be retransmitted on request.
+
+ (Note that no network destination is very nearly the same as no
+ matching proxy readers. The exception is the SPDP writer.) */
+ UPDATE_SEQ_XMIT_LOCKED (wr, seq);
+ ddsrt_mutex_unlock (&wr->e.lock);
+ if (plist != NULL)
+ {
+ nn_plist_fini (plist);
+ ddsrt_free (plist);
+ }
+ }
else
{
/* Note the subtlety of enqueueing with the lock held but
@@ -1173,9 +1193,9 @@ int write_sample_gc_notk (struct thread_state1 * const ts1, struct nn_xpack *xp,
struct ddsi_tkmap_instance *tk;
int res;
assert (thread_is_awake ());
- tk = ddsi_tkmap_lookup_instance_ref (serdata);
+ tk = ddsi_tkmap_lookup_instance_ref (wr->e.gv->m_tkmap, serdata);
res = write_sample_eot (ts1, xp, wr, NULL, serdata, tk, 0, 1);
- ddsi_tkmap_instance_unref (tk);
+ ddsi_tkmap_instance_unref (wr->e.gv->m_tkmap, tk);
return res;
}
@@ -1184,9 +1204,8 @@ int write_sample_nogc_notk (struct thread_state1 * const ts1, struct nn_xpack *x
struct ddsi_tkmap_instance *tk;
int res;
assert (thread_is_awake ());
- tk = ddsi_tkmap_lookup_instance_ref (serdata);
+ tk = ddsi_tkmap_lookup_instance_ref (wr->e.gv->m_tkmap, serdata);
res = write_sample_eot (ts1, xp, wr, NULL, serdata, tk, 0, 0);
- ddsi_tkmap_instance_unref (tk);
+ ddsi_tkmap_instance_unref (wr->e.gv->m_tkmap, tk);
return res;
}
-
diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c
index dc959c0..e38361a 100644
--- a/src/core/ddsi/src/q_xevent.c
+++ b/src/core/ddsi/src/q_xevent.c
@@ -30,7 +30,6 @@
#include "dds/ddsi/q_globals.h"
#include "dds/ddsi/q_ephash.h"
#include "dds/ddsi/q_transmit.h"
-#include "dds/ddsi/q_error.h"
#include "dds/ddsi/q_bswap.h"
#include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_misc.h"
@@ -45,18 +44,12 @@
#include "dds/ddsi/sysdeps.h"
+#define EVQTRACE(...) DDS_CTRACE (&evq->gv->logconfig, __VA_ARGS__)
+
/* This is absolute bottom for signed integers, where -x = x and yet x
!= 0 -- and note that it had better be 2's complement machine! */
#define TSCHED_DELETE ((int64_t) ((uint64_t) 1 << 63))
-#if __STDC_VERSION__ >= 199901L
-#define POS_INFINITY_DOUBLE INFINITY
-#else
-/* Hope for the best -- the only consequence of getting this wrong is
- that T_NEVER may be printed as a fugly value instead of as +inf. */
-#define POS_INFINITY_DOUBLE (HUGE_VAL + HUGE_VAL)
-#endif
-
enum xeventkind
{
XEVK_HEARTBEAT,
@@ -148,6 +141,7 @@ struct xeventq {
size_t max_queued_rexmit_msgs;
int terminate;
struct thread_state1 *ts;
+ struct q_globals *gv;
ddsrt_mutex_t lock;
ddsrt_cond_t cond;
ddsi_tran_conn_t tev_conn;
@@ -158,6 +152,7 @@ static uint32_t xevent_thread (struct xeventq *xevq);
static nn_mtime_t earliest_in_xeventq (struct xeventq *evq);
static int msg_xevents_cmp (const void *a, const void *b);
static int compare_xevent_tsched (const void *va, const void *vb);
+static void handle_nontimed_xevent (struct xevent_nt *xev, struct nn_xpack *xp);
static const ddsrt_avl_treedef_t msg_xevents_treedef = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct xevent_nt, u.msg_rexmit.msg_avlnode), offsetof (struct xevent_nt, u.msg_rexmit.msg), msg_xevents_cmp, 0);
@@ -173,7 +168,7 @@ static int compare_xevent_tsched (const void *va, const void *vb)
static void update_rexmit_counts (struct xeventq *evq, struct xevent_nt *ev)
{
#if 0
- DDS_TRACE(("ZZZ(%p,%"PA_PRIuSIZE")", (void *) ev, ev->u.msg_rexmit.queued_rexmit_bytes);
+ EVQTRACE ("ZZZ(%p,%"PRIuSIZE")", (void *) ev, ev->u.msg_rexmit.queued_rexmit_bytes);
#endif
assert (ev->kind == XEVK_MSG_REXMIT);
assert (ev->u.msg_rexmit.queued_rexmit_bytes <= evq->queued_rexmit_bytes);
@@ -183,7 +178,7 @@ static void update_rexmit_counts (struct xeventq *evq, struct xevent_nt *ev)
}
#if 0
-static void trace_msg (const char *func, const struct nn_xmsg *m)
+static void trace_msg (struct xeventq *evq, const char *func, const struct nn_xmsg *m)
{
if (dds_get_log_mask() & DDS_LC_TRACE)
{
@@ -191,11 +186,11 @@ static void trace_msg (const char *func, const struct nn_xmsg *m)
seqno_t wrseq;
nn_fragment_number_t wrfragid;
nn_xmsg_guid_seq_fragid (m, &wrguid, &wrseq, &wrfragid);
- DDS_TRACE(" %s("PGUIDFMT"/%"PRId64"/%u)", func, PGUID (wrguid), wrseq, wrfragid);
+ EVQTRACE(" %s("PGUIDFMT"/%"PRId64"/%u)", func, PGUID (wrguid), wrseq, wrfragid);
}
}
#else
-static void trace_msg (UNUSED_ARG (const char *func), UNUSED_ARG (const struct nn_xmsg *m))
+static void trace_msg (UNUSED_ARG (struct xeventq *evq), UNUSED_ARG (const char *func), UNUSED_ARG (const struct nn_xmsg *m))
{
}
#endif
@@ -203,21 +198,21 @@ static void trace_msg (UNUSED_ARG (const char *func), UNUSED_ARG (const struct n
static struct xevent_nt *lookup_msg (struct xeventq *evq, struct nn_xmsg *msg)
{
assert (nn_xmsg_kind (msg) == NN_XMSG_KIND_DATA_REXMIT);
- trace_msg ("lookup-msg", msg);
+ trace_msg (evq, "lookup-msg", msg);
return ddsrt_avl_lookup (&msg_xevents_treedef, &evq->msg_xevents, msg);
}
static void remember_msg (struct xeventq *evq, struct xevent_nt *ev)
{
assert (ev->kind == XEVK_MSG_REXMIT);
- trace_msg ("remember-msg", ev->u.msg_rexmit.msg);
+ trace_msg (evq, "remember-msg", ev->u.msg_rexmit.msg);
ddsrt_avl_insert (&msg_xevents_treedef, &evq->msg_xevents, ev);
}
static void forget_msg (struct xeventq *evq, struct xevent_nt *ev)
{
assert (ev->kind == XEVK_MSG_REXMIT);
- trace_msg ("forget-msg", ev->u.msg_rexmit.msg);
+ trace_msg (evq, "forget-msg", ev->u.msg_rexmit.msg);
ddsrt_avl_delete (&msg_xevents_treedef, &evq->msg_xevents, ev);
}
@@ -315,26 +310,6 @@ static void free_xevent (struct xeventq *evq, struct xevent *ev)
ddsrt_free (ev);
}
-static void free_xevent_nt (struct xeventq *evq, struct xevent_nt *ev)
-{
- assert (!nontimed_xevent_in_queue (evq, ev));
- switch (ev->kind)
- {
- case XEVK_MSG:
- nn_xmsg_free (ev->u.msg.msg);
- break;
- case XEVK_MSG_REXMIT:
- assert (ddsrt_avl_lookup (&msg_xevents_treedef, &evq->msg_xevents, ev->u.msg_rexmit.msg) == NULL);
- update_rexmit_counts (evq, ev);
- nn_xmsg_free (ev->u.msg_rexmit.msg);
- break;
- case XEVK_ENTITYID:
- nn_xmsg_free (ev->u.entityid.msg);
- break;
- }
- ddsrt_free (ev);
-}
-
void delete_xevent (struct xevent *ev)
{
struct xeventq *evq = ev->evq;
@@ -393,7 +368,7 @@ int resched_xevent_if_earlier (struct xevent *ev, nn_mtime_t tsched)
return is_resched;
}
-static struct xevent * qxev_common (struct xeventq *evq, nn_mtime_t tsched, enum xeventkind kind)
+static struct xevent *qxev_common (struct xeventq *evq, nn_mtime_t tsched, enum xeventkind kind)
{
/* qxev_common is the route by which all timed xevents are
created. */
@@ -403,10 +378,10 @@ static struct xevent * qxev_common (struct xeventq *evq, nn_mtime_t tsched, enum
ASSERT_MUTEX_HELD (&evq->lock);
/* round up the scheduled time if required */
- if (tsched.v != T_NEVER && config.schedule_time_rounding != 0)
+ if (tsched.v != T_NEVER && evq->gv->config.schedule_time_rounding != 0)
{
- nn_mtime_t tsched_rounded = mtime_round_up (tsched, config.schedule_time_rounding);
- DDS_TRACE("rounded event scheduled for %"PRId64" to %"PRId64"\n", tsched.v, tsched_rounded.v);
+ nn_mtime_t tsched_rounded = mtime_round_up (tsched, evq->gv->config.schedule_time_rounding);
+ EVQTRACE ("rounded event scheduled for %"PRId64" to %"PRId64"\n", tsched.v, tsched_rounded.v);
tsched = tsched_rounded;
}
@@ -459,7 +434,7 @@ static void qxev_insert_nt (struct xevent_nt *ev)
struct xeventq *evq = ev->evq;
ASSERT_MUTEX_HELD (&evq->lock);
add_to_non_timed_xmit_list (evq, ev);
- DDS_TRACE("non-timed queue now has %d items\n", compute_non_timed_xmit_list_size (evq));
+ EVQTRACE ("non-timed queue now has %d items\n", compute_non_timed_xmit_list_size (evq));
}
static int msg_xevents_cmp (const void *a, const void *b)
@@ -491,14 +466,15 @@ struct xeventq * xeventq_new
evq->queued_rexmit_bytes = 0;
evq->queued_rexmit_msgs = 0;
evq->tev_conn = conn;
+ evq->gv = conn->m_base.gv;
ddsrt_mutex_init (&evq->lock);
ddsrt_cond_init (&evq->cond);
return evq;
}
-int xeventq_start (struct xeventq *evq, const char *name)
+dds_return_t xeventq_start (struct xeventq *evq, const char *name)
{
- dds_retcode_t rc;
+ dds_return_t rc;
char * evqname = "tev";
assert (evq->ts == NULL);
@@ -510,13 +486,13 @@ int xeventq_start (struct xeventq *evq, const char *name)
}
evq->terminate = 0;
- rc = create_thread (&evq->ts, evqname, (uint32_t (*) (void *)) xevent_thread, evq);
+ rc = create_thread (&evq->ts, evq->gv, evqname, (uint32_t (*) (void *)) xevent_thread, evq);
if (name)
{
ddsrt_free (evqname);
}
- return (rc != DDS_RETCODE_OK) ? Q_ERR_UNSPECIFIED : 0;
+ return rc;
}
void xeventq_stop (struct xeventq *evq)
@@ -546,13 +522,27 @@ void xeventq_free (struct xeventq *evq)
{
union { void *v; void (*f) (struct xevent *ev, void *arg, nn_mtime_t tnow); } fp;
fp.f = ev->u.callback.cb;
- DDS_WARNING("xeventq_free: callback %p did not schedule deletion as required, deleting event anyway\n", fp.v);
+ DDS_CWARNING (&evq->gv->logconfig, "xeventq_free: callback %p did not schedule deletion as required, deleting event anyway\n", fp.v);
delete_xevent (ev);
}
}
}
- while (!non_timed_xmit_list_is_empty(evq))
- free_xevent_nt (evq, getnext_from_non_timed_xmit_list (evq));
+
+ {
+ struct nn_xpack *xp = nn_xpack_new (evq->tev_conn, evq->auxiliary_bandwidth_limit, false);
+ thread_state_awake (lookup_thread_state (), evq->gv);
+ ddsrt_mutex_lock (&evq->lock);
+ while (!non_timed_xmit_list_is_empty (evq))
+ {
+ thread_state_awake_to_awake_no_nest (lookup_thread_state ());
+ handle_nontimed_xevent (getnext_from_non_timed_xmit_list (evq), xp);
+ }
+ ddsrt_mutex_unlock (&evq->lock);
+ nn_xpack_send (xp, false);
+ nn_xpack_free (xp);
+ thread_state_asleep (lookup_thread_state ());
+ }
+
assert (ddsrt_avl_is_empty (&evq->msg_xevents));
ddsrt_cond_destroy (&evq->cond);
ddsrt_mutex_destroy (&evq->lock);
@@ -590,21 +580,21 @@ static void handle_xevk_entityid (struct nn_xpack *xp, struct xevent_nt *ev)
static void handle_xevk_heartbeat (struct nn_xpack *xp, struct xevent *ev, nn_mtime_t tnow /* monotonic */)
{
+ struct q_globals const * const gv = ev->evq->gv;
struct nn_xmsg *msg;
struct writer *wr;
nn_mtime_t t_next;
int hbansreq = 0;
struct whc_state whcst;
- if ((wr = ephash_lookup_writer_guid (&ev->u.heartbeat.wr_guid)) == NULL)
+ if ((wr = ephash_lookup_writer_guid (gv->guid_hash, &ev->u.heartbeat.wr_guid)) == NULL)
{
- DDS_TRACE("heartbeat(wr "PGUIDFMT") writer gone\n",
- PGUID (ev->u.heartbeat.wr_guid));
+ GVTRACE("heartbeat(wr "PGUIDFMT") writer gone\n", PGUID (ev->u.heartbeat.wr_guid));
return;
}
- assert (wr->reliable);
ddsrt_mutex_lock (&wr->e.lock);
+ assert (wr->reliable);
whc_get_state(wr->whc, &whcst);
if (!writer_must_have_hb_scheduled (wr, &whcst))
{
@@ -625,14 +615,14 @@ static void handle_xevk_heartbeat (struct nn_xpack *xp, struct xevent *ev, nn_mt
t_next.v = tnow.v + writer_hbcontrol_intv (wr, &whcst, tnow);
}
- DDS_TRACE("heartbeat(wr "PGUIDFMT"%s) %s, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n",
- PGUID (wr->e.guid),
- hbansreq ? "" : " final",
- msg ? "sent" : "suppressed",
- (t_next.v == T_NEVER) ? POS_INFINITY_DOUBLE : (double)(t_next.v - tnow.v) / 1e9,
- ddsrt_avl_is_empty (&wr->readers) ? (seqno_t) -1 : ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->min_seq,
- ddsrt_avl_is_empty (&wr->readers) || ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->all_have_replied_to_hb ? "" : "!",
- whcst.max_seq, READ_SEQ_XMIT(wr));
+ GVTRACE ("heartbeat(wr "PGUIDFMT"%s) %s, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n",
+ PGUID (wr->e.guid),
+ hbansreq ? "" : " final",
+ msg ? "sent" : "suppressed",
+ (t_next.v == T_NEVER) ? INFINITY : (double)(t_next.v - tnow.v) / 1e9,
+ ddsrt_avl_is_empty (&wr->readers) ? (seqno_t) -1 : ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->min_seq,
+ ddsrt_avl_is_empty (&wr->readers) || ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->all_have_replied_to_hb ? "" : "!",
+ whcst.max_seq, READ_SEQ_XMIT(wr));
resched_xevent_if_earlier (ev, t_next);
wr->hbcontrol.tsched = t_next;
ddsrt_mutex_unlock (&wr->e.lock);
@@ -709,13 +699,13 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p
struct nn_reorder *reorder;
AckNack_t *an;
struct nn_xmsg_marker sm_marker;
- unsigned i, numbits;
+ uint32_t i, numbits;
seqno_t base;
- unsigned ui;
- union {
- struct nn_fragment_number_set set;
- char pad[NN_FRAGMENT_NUMBER_SET_SIZE (256)];
+ DDSRT_STATIC_ASSERT ((NN_FRAGMENT_NUMBER_SET_MAX_BITS % 32) == 0);
+ struct {
+ struct nn_fragment_number_set_header set;
+ uint32_t bits[NN_FRAGMENT_NUMBER_SET_MAX_BITS / 32];
} nackfrag;
int nackfrag_numbits;
seqno_t nackfrag_seq = 0;
@@ -728,7 +718,7 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p
if (rwn->in_sync != PRMSS_OUT_OF_SYNC)
{
reorder = pwr->reorder;
- if (!config.late_ack_mode)
+ if (!pwr->e.gv->config.late_ack_mode)
bitmap_base = nn_reorder_next_seq (reorder);
else
{
@@ -750,7 +740,7 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p
/* Make bitmap; note that we've made sure to have room for the
maximum bitmap size. */
- numbits = nn_reorder_nackmap (reorder, bitmap_base, pwr->last_seq, &an->readerSNState, max_numbits, notail);
+ numbits = nn_reorder_nackmap (reorder, bitmap_base, pwr->last_seq, &an->readerSNState, an->bits, max_numbits, notail);
base = fromSN (an->readerSNState.bitmap_base);
/* Scan through bitmap, cutting it off at the first missing sample
@@ -761,13 +751,13 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p
{
uint32_t fragnum;
nackfrag_seq = base + i;
- if (!nn_bitset_isset (numbits, an->readerSNState.bits, i))
+ if (!nn_bitset_isset (numbits, an->bits, i))
continue;
if (nackfrag_seq == pwr->last_seq)
fragnum = pwr->last_fragnum;
else
fragnum = UINT32_MAX;
- nackfrag_numbits = nn_defrag_nackmap (pwr->defrag, nackfrag_seq, fragnum, &nackfrag.set, max_numbits);
+ nackfrag_numbits = nn_defrag_nackmap (pwr->defrag, nackfrag_seq, fragnum, &nackfrag.set, nackfrag.bits, max_numbits);
}
if (nackfrag_numbits >= 0) {
/* Cut the NACK short, NACKFRAG will be added after the NACK's is
@@ -802,8 +792,7 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p
{
/* Count field is at a variable offset ... silly DDSI spec. */
nn_count_t *countp =
- (nn_count_t *) ((char *) an + offsetof (AckNack_t, readerSNState) +
- NN_SEQUENCE_NUMBER_SET_SIZE (an->readerSNState.numbits));
+ (nn_count_t *) ((char *) an + offsetof (AckNack_t, bits) + NN_SEQUENCE_NUMBER_SET_BITS_SIZE (an->readerSNState.numbits));
*countp = ++rwn->count;
/* Reset submessage size, now that we know the real size, and update
@@ -811,11 +800,11 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p
nn_xmsg_shrink (msg, sm_marker, ACKNACK_SIZE (an->readerSNState.numbits));
nn_xmsg_submsg_setnext (msg, sm_marker);
- DDS_TRACE("acknack "PGUIDFMT" -> "PGUIDFMT": #%"PRId32":%"PRId64"/%"PRIu32":",
+ ETRACE (pwr, "acknack "PGUIDFMT" -> "PGUIDFMT": #%"PRId32":%"PRId64"/%"PRIu32":",
PGUID (rwn->rd_guid), PGUID (pwr->e.guid), rwn->count,
base, an->readerSNState.numbits);
- for (ui = 0; ui != an->readerSNState.numbits; ui++)
- DDS_TRACE("%c", nn_bitset_isset (numbits, an->readerSNState.bits, ui) ? '1' : '0');
+ for (uint32_t ui = 0; ui != an->readerSNState.numbits; ui++)
+ ETRACE (pwr, "%c", nn_bitset_isset (numbits, an->bits, ui) ? '1' : '0');
}
if (nackfrag_numbits > 0)
@@ -834,21 +823,21 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p
nf->writerSN = toSN (nackfrag_seq);
nf->fragmentNumberState.bitmap_base = nackfrag.set.bitmap_base + 1;
nf->fragmentNumberState.numbits = nackfrag.set.numbits;
- memcpy (nf->fragmentNumberState.bits, nackfrag.set.bits, NN_FRAGMENT_NUMBER_SET_BITS_SIZE (nackfrag_numbits));
+ memcpy (nf->bits, nackfrag.bits, NN_FRAGMENT_NUMBER_SET_BITS_SIZE (nackfrag_numbits));
{
nn_count_t *countp =
- (nn_count_t *) ((char *) nf + offsetof (NackFrag_t, fragmentNumberState) + NN_FRAGMENT_NUMBER_SET_SIZE (nf->fragmentNumberState.numbits));
+ (nn_count_t *) ((char *) nf + offsetof (NackFrag_t, bits) + NN_FRAGMENT_NUMBER_SET_BITS_SIZE (nf->fragmentNumberState.numbits));
*countp = ++pwr->nackfragcount;
nn_xmsg_submsg_setnext (msg, sm_marker);
- DDS_TRACE(" + nackfrag #%"PRId32":%"PRId64"/%u/%"PRIu32":", *countp, fromSN (nf->writerSN), nf->fragmentNumberState.bitmap_base, nf->fragmentNumberState.numbits);
- for (ui = 0; ui != nf->fragmentNumberState.numbits; ui++)
- DDS_TRACE("%c", nn_bitset_isset (nf->fragmentNumberState.numbits, nf->fragmentNumberState.bits, ui) ? '1' : '0');
+ ETRACE (pwr, " + nackfrag #%"PRId32":%"PRId64"/%u/%"PRIu32":", *countp, fromSN (nf->writerSN), nf->fragmentNumberState.bitmap_base, nf->fragmentNumberState.numbits);
+ for (uint32_t ui = 0; ui != nf->fragmentNumberState.numbits; ui++)
+ ETRACE (pwr, "%c", nn_bitset_isset (nf->fragmentNumberState.numbits, nf->bits, ui) ? '1' : '0');
}
}
- DDS_TRACE("\n");
+ ETRACE (pwr, "\n");
}
static void handle_xevk_acknack (UNUSED_ARG (struct nn_xpack *xp), struct xevent *ev, nn_mtime_t tnow)
@@ -862,12 +851,13 @@ static void handle_xevk_acknack (UNUSED_ARG (struct nn_xpack *xp), struct xevent
A little snag is that the defragmenter can throw out partial samples in
favour of others, so MUST ensure that the defragmenter won't start
threshing and fail to make progress! */
+ struct q_globals *gv = ev->evq->gv;
struct proxy_writer *pwr;
struct nn_xmsg *msg;
struct pwr_rd_match *rwn;
nn_locator_t loc;
- if ((pwr = ephash_lookup_proxy_writer_guid (&ev->u.acknack.pwr_guid)) == NULL)
+ if ((pwr = ephash_lookup_proxy_writer_guid (gv->guid_hash, &ev->u.acknack.pwr_guid)) == NULL)
{
return;
}
@@ -882,10 +872,10 @@ static void handle_xevk_acknack (UNUSED_ARG (struct nn_xpack *xp), struct xevent
if (addrset_any_uc (pwr->c.as, &loc) || addrset_any_mc (pwr->c.as, &loc))
{
seqno_t nack_seq;
- if ((msg = nn_xmsg_new (gv.xmsgpool, &ev->u.acknack.rd_guid.prefix, ACKNACK_SIZE_MAX, NN_XMSG_KIND_CONTROL)) == NULL)
+ if ((msg = nn_xmsg_new (gv->xmsgpool, &ev->u.acknack.rd_guid.prefix, ACKNACK_SIZE_MAX, NN_XMSG_KIND_CONTROL)) == NULL)
goto outofmem;
nn_xmsg_setdst1 (msg, &ev->u.acknack.pwr_guid.prefix, &loc);
- if (config.meas_hb_to_ack_latency && rwn->hb_timestamp.v)
+ if (gv->config.meas_hb_to_ack_latency && rwn->hb_timestamp.v)
{
/* If HB->ACK latency measurement is enabled, and we have a
timestamp available, add it and clear the time stamp. There
@@ -905,15 +895,15 @@ static void handle_xevk_acknack (UNUSED_ARG (struct nn_xpack *xp), struct xevent
HEARTBEAT, I've seen too many cases of not sending an NACK
because the writing side got confused ... Better to recover
eventually. */
- resched_xevent_if_earlier (ev, add_duration_to_mtime (tnow, config.auto_resched_nack_delay));
+ resched_xevent_if_earlier (ev, add_duration_to_mtime (tnow, gv->config.auto_resched_nack_delay));
}
- DDS_TRACE("send acknack(rd "PGUIDFMT" -> pwr "PGUIDFMT")\n",
- PGUID (ev->u.acknack.rd_guid), PGUID (ev->u.acknack.pwr_guid));
+ GVTRACE ("send acknack(rd "PGUIDFMT" -> pwr "PGUIDFMT")\n",
+ PGUID (ev->u.acknack.rd_guid), PGUID (ev->u.acknack.pwr_guid));
}
else
{
- DDS_TRACE("skip acknack(rd "PGUIDFMT" -> pwr "PGUIDFMT"): no address\n",
- PGUID (ev->u.acknack.rd_guid), PGUID (ev->u.acknack.pwr_guid));
+ GVTRACE ("skip acknack(rd "PGUIDFMT" -> pwr "PGUIDFMT"): no address\n",
+ PGUID (ev->u.acknack.rd_guid), PGUID (ev->u.acknack.pwr_guid));
msg = NULL;
}
@@ -952,18 +942,19 @@ static bool resend_spdp_sample_by_guid_key (struct writer *wr, const nn_guid_t *
/* Look up data in (transient-local) WHC by key value -- FIXME: clearly
a slightly more efficient and elegant way of looking up the key value
is to be preferred */
+ struct q_globals *gv = wr->e.gv;
bool sample_found;
nn_plist_t ps;
nn_plist_init_empty (&ps);
ps.present |= PP_PARTICIPANT_GUID;
ps.participant_guid = *guid;
- struct nn_xmsg *mpayload = nn_xmsg_new (gv.xmsgpool, &guid->prefix, 0, NN_XMSG_KIND_DATA);
+ struct nn_xmsg *mpayload = nn_xmsg_new (gv->xmsgpool, &guid->prefix, 0, NN_XMSG_KIND_DATA);
nn_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0);
nn_xmsg_addpar_sentinel (mpayload);
nn_plist_fini (&ps);
struct ddsi_plist_sample plist_sample;
nn_xmsg_payload_to_plistsample (&plist_sample, PID_PARTICIPANT_GUID, mpayload);
- struct ddsi_serdata *sd = ddsi_serdata_from_sample (gv.plist_topic, SDK_KEY, &plist_sample);
+ struct ddsi_serdata *sd = ddsi_serdata_from_sample (gv->plist_topic, SDK_KEY, &plist_sample);
struct whc_borrowed_sample sample;
nn_xmsg_free (mpayload);
@@ -987,15 +978,15 @@ static bool resend_spdp_sample_by_guid_key (struct writer *wr, const nn_guid_t *
static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *ev, nn_mtime_t tnow)
{
/* Like the writer pointer in the heartbeat event, the participant pointer in the spdp event is assumed valid. */
+ struct q_globals *gv = ev->evq->gv;
struct participant *pp;
struct proxy_reader *prd;
struct writer *spdp_wr;
bool do_write;
- if ((pp = ephash_lookup_participant_guid (&ev->u.spdp.pp_guid)) == NULL)
+ if ((pp = ephash_lookup_participant_guid (gv->guid_hash, &ev->u.spdp.pp_guid)) == NULL)
{
- DDS_TRACE("handle_xevk_spdp "PGUIDFMT" - unknown guid\n",
- PGUID (ev->u.spdp.pp_guid));
+ GVTRACE ("handle_xevk_spdp "PGUIDFMT" - unknown guid\n", PGUID (ev->u.spdp.pp_guid));
if (ev->u.spdp.directed)
delete_xevent (ev);
return;
@@ -1003,8 +994,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e
if ((spdp_wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL)
{
- DDS_TRACE("handle_xevk_spdp "PGUIDFMT" - spdp writer of participant not found\n",
- PGUID (ev->u.spdp.pp_guid));
+ GVTRACE ("handle_xevk_spdp "PGUIDFMT" - spdp writer of participant not found\n", PGUID (ev->u.spdp.pp_guid));
if (ev->u.spdp.directed)
delete_xevent (ev);
return;
@@ -1022,10 +1012,10 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e
nn_guid_t guid;
guid.prefix = ev->u.spdp.dest_proxypp_guid_prefix;
guid.entityid.u = NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER;
- prd = ephash_lookup_proxy_reader_guid (&guid);
+ prd = ephash_lookup_proxy_reader_guid (gv->guid_hash, &guid);
do_write = (prd != NULL);
if (!do_write)
- DDS_TRACE("xmit spdp: no proxy reader "PGUIDFMT"\n", PGUID (guid));
+ GVTRACE ("xmit spdp: no proxy reader "PGUIDFMT"\n", PGUID (guid));
}
if (do_write && !resend_spdp_sample_by_guid_key (spdp_wr, &ev->u.spdp.pp_guid, prd))
@@ -1050,8 +1040,8 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e
}
else
{
- DDS_TRACE("xmit spdp: suppressing early spdp response from "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x\n",
- PGUID (pp->e.guid), PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_PARTICIPANT);
+ GVTRACE ("xmit spdp: suppressing early spdp response from "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x\n",
+ PGUID (pp->e.guid), PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_PARTICIPANT);
}
#endif
}
@@ -1060,15 +1050,15 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e
{
/* Directed events are used to send SPDP packets to newly
discovered peers, and used just once. */
- if (--ev->u.spdp.directed == 0 || config.spdp_interval < T_SECOND || pp->lease_duration < T_SECOND)
+ if (--ev->u.spdp.directed == 0 || gv->config.spdp_interval < T_SECOND || pp->lease_duration < T_SECOND)
delete_xevent (ev);
else
{
nn_mtime_t tnext = add_duration_to_mtime (tnow, T_SECOND);
- DDS_TRACE("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %gs)\n",
- PGUID (pp->e.guid),
- PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER,
- (double)(tnext.v - tnow.v) / 1e9);
+ GVTRACE ("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %gs)\n",
+ PGUID (pp->e.guid),
+ PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER,
+ (double)(tnext.v - tnow.v) / 1e9);
resched_xevent_if_earlier (ev, tnext);
}
}
@@ -1077,8 +1067,8 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e
/* schedule next when 80% of the interval has elapsed, or 2s
before the lease ends, whichever comes first (similar to PMD),
but never wait longer than spdp_interval */
- const int64_t mindelta = 10 * T_MILLISECOND;
- const int64_t ldur = pp->lease_duration;
+ const dds_duration_t mindelta = 10 * T_MILLISECOND;
+ const dds_duration_t ldur = pp->lease_duration;
nn_mtime_t tnext;
int64_t intv;
@@ -1088,14 +1078,14 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e
intv = 4 * ldur / 5;
else
intv = ldur - 2 * T_SECOND;
- if (intv > config.spdp_interval)
- intv = config.spdp_interval;
+ if (intv > gv->config.spdp_interval)
+ intv = gv->config.spdp_interval;
tnext = add_duration_to_mtime (tnow, intv);
- DDS_TRACE("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %gs)\n",
- PGUID (pp->e.guid),
- PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER,
- (double)(tnext.v - tnow.v) / 1e9);
+ GVTRACE ("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %gs)\n",
+ PGUID (pp->e.guid),
+ PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER,
+ (double)(tnext.v - tnow.v) / 1e9);
resched_xevent_if_earlier (ev, tnext);
}
}
@@ -1103,6 +1093,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e
static void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack *xp, struct participant *pp, unsigned pmd_kind)
{
#define PMD_DATA_LENGTH 1
+ struct q_globals * const gv = pp->e.gv;
struct writer *wr;
union {
ParticipantMessageData_t pmd;
@@ -1113,7 +1104,7 @@ static void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack
if ((wr = get_builtin_writer (pp, NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER)) == NULL)
{
- DDS_TRACE("write_pmd_message("PGUIDFMT") - builtin pmd writer not found\n", PGUID (pp->e.guid));
+ GVTRACE ("write_pmd_message("PGUIDFMT") - builtin pmd writer not found\n", PGUID (pp->e.guid));
return;
}
@@ -1128,22 +1119,23 @@ static void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack
.key = &u.pmd,
.keysize = 16
};
- serdata = ddsi_serdata_from_sample (gv.rawcdr_topic, SDK_DATA, &raw);
+ serdata = ddsi_serdata_from_sample (gv->rawcdr_topic, SDK_DATA, &raw);
serdata->timestamp = now ();
- tk = ddsi_tkmap_lookup_instance_ref(serdata);
+ tk = ddsi_tkmap_lookup_instance_ref (gv->m_tkmap, serdata);
write_sample_nogc (ts1, xp, wr, serdata, tk);
- ddsi_tkmap_instance_unref(tk);
+ ddsi_tkmap_instance_unref (gv->m_tkmap, tk);
#undef PMD_DATA_LENGTH
}
static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_xpack *xp, struct xevent *ev, nn_mtime_t tnow)
{
+ struct q_globals * const gv = ev->evq->gv;
struct participant *pp;
- int64_t intv;
+ dds_duration_t intv;
nn_mtime_t tnext;
- if ((pp = ephash_lookup_participant_guid (&ev->u.pmd_update.pp_guid)) == NULL)
+ if ((pp = ephash_lookup_participant_guid (gv->guid_hash, &ev->u.pmd_update.pp_guid)) == NULL)
{
return;
}
@@ -1163,7 +1155,7 @@ static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_
if (intv == T_NEVER)
{
tnext.v = T_NEVER;
- DDS_TRACE("resched pmd("PGUIDFMT"): never\n", PGUID (pp->e.guid));
+ GVTRACE ("resched pmd("PGUIDFMT"): never\n", PGUID (pp->e.guid));
}
else
{
@@ -1173,7 +1165,7 @@ static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_
tnext.v = tnow.v + intv - 2 * T_SECOND;
else
tnext.v = tnow.v + 4 * intv / 5;
- DDS_TRACE("resched pmd("PGUIDFMT"): %gs\n", PGUID (pp->e.guid), (double)(tnext.v - tnow.v) / 1e9);
+ GVTRACE ("resched pmd("PGUIDFMT"): %gs\n", PGUID (pp->e.guid), (double)(tnext.v - tnow.v) / 1e9);
}
resched_xevent_if_earlier (ev, tnext);
@@ -1183,8 +1175,9 @@ static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_
static void handle_xevk_delete_writer (UNUSED_ARG (struct nn_xpack *xp), struct xevent *ev, UNUSED_ARG (nn_mtime_t tnow))
{
/* don't worry if the writer is already gone by the time we get here. */
- DDS_TRACE("handle_xevk_delete_writer: "PGUIDFMT"\n", PGUID (ev->u.delete_writer.guid));
- delete_writer_nolinger (&ev->u.delete_writer.guid);
+ struct q_globals * const gv = ev->evq->gv;
+ GVTRACE ("handle_xevk_delete_writer: "PGUIDFMT"\n", PGUID (ev->u.delete_writer.guid));
+ delete_writer_nolinger (gv, &ev->u.delete_writer.guid);
delete_xevent (ev);
}
@@ -1332,16 +1325,16 @@ static uint32_t xevent_thread (struct xeventq * xevq)
struct nn_xpack *xp;
nn_mtime_t next_thread_cputime = { 0 };
- xp = nn_xpack_new (xevq->tev_conn, xevq->auxiliary_bandwidth_limit, config.xpack_send_async);
+ xp = nn_xpack_new (xevq->tev_conn, xevq->auxiliary_bandwidth_limit, xevq->gv->config.xpack_send_async);
ddsrt_mutex_lock (&xevq->lock);
while (!xevq->terminate)
{
nn_mtime_t tnow = now_mt ();
- LOG_THREAD_CPUTIME (next_thread_cputime);
+ LOG_THREAD_CPUTIME (&xevq->gv->logconfig, next_thread_cputime);
- thread_state_awake (ts1);
+ thread_state_awake_fixed_domain (ts1);
handle_xevents (ts1, xevq, xp, tnow);
/* Send to the network unlocked, as it may sleep due to bandwidth limitation */
ddsrt_mutex_unlock (&xevq->lock);
@@ -1394,25 +1387,26 @@ void qxev_msg (struct xeventq *evq, struct nn_xmsg *msg)
ddsrt_mutex_unlock (&evq->lock);
}
-void qxev_prd_entityid (struct proxy_reader * prd, nn_guid_prefix_t * id)
+void qxev_prd_entityid (struct proxy_reader *prd, nn_guid_prefix_t *id)
{
+ struct q_globals * const gv = prd->e.gv;
struct nn_xmsg *msg;
struct xevent_nt *ev;
/* For connected transports, may need to establish and identify connection */
- if (! gv.xevents->tev_conn->m_connless)
+ if (! gv->xevents->tev_conn->m_connless)
{
- msg = nn_xmsg_new (gv.xmsgpool, id, sizeof (EntityId_t), NN_XMSG_KIND_CONTROL);
+ msg = nn_xmsg_new (gv->xmsgpool, id, sizeof (EntityId_t), NN_XMSG_KIND_CONTROL);
if (nn_xmsg_setdstPRD (msg, prd) == 0)
{
- DDS_TRACE(" qxev_prd_entityid (%"PRIx32":%"PRIx32":%"PRIx32")\n", PGUIDPREFIX (*id));
+ GVTRACE (" qxev_prd_entityid (%"PRIx32":%"PRIx32":%"PRIx32")\n", PGUIDPREFIX (*id));
nn_xmsg_add_entityid (msg);
- ddsrt_mutex_lock (&gv.xevents->lock);
- ev = qxev_common_nt (gv.xevents, XEVK_ENTITYID);
+ ddsrt_mutex_lock (&gv->xevents->lock);
+ ev = qxev_common_nt (gv->xevents, XEVK_ENTITYID);
ev->u.entityid.msg = msg;
qxev_insert_nt (ev);
- ddsrt_mutex_unlock (&gv.xevents->lock);
+ ddsrt_mutex_unlock (&gv->xevents->lock);
}
else
{
@@ -1421,8 +1415,9 @@ void qxev_prd_entityid (struct proxy_reader * prd, nn_guid_prefix_t * id)
}
}
-void qxev_pwr_entityid (struct proxy_writer * pwr, nn_guid_prefix_t * id)
+void qxev_pwr_entityid (struct proxy_writer *pwr, nn_guid_prefix_t *id)
{
+ struct q_globals * const gv = pwr->e.gv;
struct nn_xmsg *msg;
struct xevent_nt *ev;
@@ -1430,10 +1425,10 @@ void qxev_pwr_entityid (struct proxy_writer * pwr, nn_guid_prefix_t * id)
if (! pwr->evq->tev_conn->m_connless)
{
- msg = nn_xmsg_new (gv.xmsgpool, id, sizeof (EntityId_t), NN_XMSG_KIND_CONTROL);
+ msg = nn_xmsg_new (gv->xmsgpool, id, sizeof (EntityId_t), NN_XMSG_KIND_CONTROL);
if (nn_xmsg_setdstPWR (msg, pwr) == 0)
{
- DDS_TRACE(" qxev_pwr_entityid (%"PRIx32":%"PRIx32":%"PRIx32")\n", PGUIDPREFIX (*id));
+ GVTRACE (" qxev_pwr_entityid (%"PRIx32":%"PRIx32":%"PRIx32")\n", PGUIDPREFIX (*id));
nn_xmsg_add_entityid (msg);
ddsrt_mutex_lock (&pwr->evq->lock);
ev = qxev_common_nt (pwr->evq, XEVK_ENTITYID);
@@ -1450,13 +1445,14 @@ void qxev_pwr_entityid (struct proxy_writer * pwr, nn_guid_prefix_t * id)
int qxev_msg_rexmit_wrlock_held (struct xeventq *evq, struct nn_xmsg *msg, int force)
{
+ struct q_globals * const gv = evq->gv;
size_t msg_size = nn_xmsg_size (msg);
struct xevent_nt *ev;
assert (evq);
assert (nn_xmsg_kind (msg) == NN_XMSG_KIND_DATA_REXMIT);
ddsrt_mutex_lock (&evq->lock);
- if ((ev = lookup_msg (evq, msg)) != NULL && nn_xmsg_merge_rexmit_destinations_wrlock_held (ev->u.msg_rexmit.msg, msg))
+ if ((ev = lookup_msg (evq, msg)) != NULL && nn_xmsg_merge_rexmit_destinations_wrlock_held (gv, ev->u.msg_rexmit.msg, msg))
{
/* MSG got merged with a pending retransmit, so it has effectively been queued */
ddsrt_mutex_unlock (&evq->lock);
@@ -1471,8 +1467,8 @@ int qxev_msg_rexmit_wrlock_held (struct xeventq *evq, struct nn_xmsg *msg, int f
ddsrt_mutex_unlock (&evq->lock);
nn_xmsg_free (msg);
#if 0
- DDS_TRACE(" qxev_msg_rexmit%s drop (sz %"PA_PRIuSIZE" qb %"PA_PRIuSIZE" qm %"PA_PRIuSIZE")", force ? "!" : "",
- msg_size, evq->queued_rexmit_bytes, evq->queued_rexmit_msgs);
+ GVTRACE (" qxev_msg_rexmit%s drop (sz %"PA_PRIuSIZE" qb %"PA_PRIuSIZE" qm %"PA_PRIuSIZE")", force ? "!" : "",
+ msg_size, evq->queued_rexmit_bytes, evq->queued_rexmit_msgs);
#endif
return 0;
}
@@ -1485,7 +1481,7 @@ int qxev_msg_rexmit_wrlock_held (struct xeventq *evq, struct nn_xmsg *msg, int f
evq->queued_rexmit_msgs++;
qxev_insert_nt (ev);
#if 0
- DDS_TRACE("AAA(%p,%"PA_PRIuSIZE")", (void *) ev, msg_size);
+ GVTRACE ("AAA(%p,%"PA_PRIuSIZE")", (void *) ev, msg_size);
#endif
ddsrt_mutex_unlock (&evq->lock);
return 2;
@@ -1520,11 +1516,11 @@ struct xevent *qxev_acknack (struct xeventq *evq, nn_mtime_t tsched, const nn_gu
return ev;
}
-struct xevent *qxev_spdp (nn_mtime_t tsched, const nn_guid_t *pp_guid, const nn_guid_t *dest_proxypp_guid)
+struct xevent *qxev_spdp (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *pp_guid, const nn_guid_t *dest_proxypp_guid)
{
struct xevent *ev;
- ddsrt_mutex_lock (&gv.xevents->lock);
- ev = qxev_common (gv.xevents, tsched, XEVK_SPDP);
+ ddsrt_mutex_lock (&evq->lock);
+ ev = qxev_common (evq, tsched, XEVK_SPDP);
ev->u.spdp.pp_guid = *pp_guid;
if (dest_proxypp_guid == NULL)
ev->u.spdp.directed = 0;
@@ -1534,40 +1530,40 @@ struct xevent *qxev_spdp (nn_mtime_t tsched, const nn_guid_t *pp_guid, const nn_
ev->u.spdp.directed = 4;
}
qxev_insert (ev);
- ddsrt_mutex_unlock (&gv.xevents->lock);
+ ddsrt_mutex_unlock (&evq->lock);
return ev;
}
-struct xevent *qxev_pmd_update (nn_mtime_t tsched, const nn_guid_t *pp_guid)
+struct xevent *qxev_pmd_update (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *pp_guid)
{
struct xevent *ev;
- ddsrt_mutex_lock (&gv.xevents->lock);
- ev = qxev_common (gv.xevents, tsched, XEVK_PMD_UPDATE);
+ ddsrt_mutex_lock (&evq->lock);
+ ev = qxev_common (evq, tsched, XEVK_PMD_UPDATE);
ev->u.pmd_update.pp_guid = *pp_guid;
qxev_insert (ev);
- ddsrt_mutex_unlock (&gv.xevents->lock);
+ ddsrt_mutex_unlock (&evq->lock);
return ev;
}
-struct xevent *qxev_delete_writer (nn_mtime_t tsched, const nn_guid_t *guid)
+struct xevent *qxev_delete_writer (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *guid)
{
struct xevent *ev;
- ddsrt_mutex_lock (&gv.xevents->lock);
- ev = qxev_common (gv.xevents, tsched, XEVK_DELETE_WRITER);
+ ddsrt_mutex_lock (&evq->lock);
+ ev = qxev_common (evq, tsched, XEVK_DELETE_WRITER);
ev->u.delete_writer.guid = *guid;
qxev_insert (ev);
- ddsrt_mutex_unlock (&gv.xevents->lock);
+ ddsrt_mutex_unlock (&evq->lock);
return ev;
}
-struct xevent *qxev_callback (nn_mtime_t tsched, void (*cb) (struct xevent *ev, void *arg, nn_mtime_t tnow), void *arg)
+struct xevent *qxev_callback (struct xeventq *evq, nn_mtime_t tsched, void (*cb) (struct xevent *ev, void *arg, nn_mtime_t tnow), void *arg)
{
struct xevent *ev;
- ddsrt_mutex_lock (&gv.xevents->lock);
- ev = qxev_common (gv.xevents, tsched, XEVK_CALLBACK);
+ ddsrt_mutex_lock (&evq->lock);
+ ev = qxev_common (evq, tsched, XEVK_CALLBACK);
ev->u.callback.cb = cb;
ev->u.callback.arg = arg;
qxev_insert (ev);
- ddsrt_mutex_unlock (&gv.xevents->lock);
+ ddsrt_mutex_unlock (&evq->lock);
return ev;
}
diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c
index 3c0eae0..3e34458 100644
--- a/src/core/ddsi/src/q_xmsg.c
+++ b/src/core/ddsi/src/q_xmsg.c
@@ -31,7 +31,6 @@
#include "dds/ddsi/q_bswap.h"
#include "dds/ddsi/q_rtps.h"
#include "dds/ddsi/q_addrset.h"
-#include "dds/ddsi/q_error.h"
#include "dds/ddsi/q_misc.h"
#include "dds/ddsi/q_log.h"
#include "dds/ddsi/q_unused.h"
@@ -53,7 +52,7 @@ struct nn_xmsgpool {
struct nn_xmsg_data {
InfoSRC_t src;
InfoDST_t dst;
- char payload[1]; /* of size maxsz */
+ char payload[]; /* of size maxsz */
};
struct nn_xmsg_chain_elem {
@@ -135,7 +134,7 @@ struct nn_xmsg_chain {
#define NN_BW_UNLIMITED (0)
struct nn_bw_limiter {
- uint32_t bandwidth; /*Config in bytes/s (0 = UNLIMITED)*/
+ uint32_t bandwidth; /*gv.config in bytes/s (0 = UNLIMITED)*/
int64_t balance;
nn_mtime_t last_update;
};
@@ -148,7 +147,7 @@ typedef struct {
ddsrt_cond_t cv;
} ddsi_sem_t;
-dds_retcode_t
+static dds_return_t
ddsi_sem_init (ddsi_sem_t *sem, uint32_t value)
{
sem->value = value;
@@ -157,7 +156,7 @@ ddsi_sem_init (ddsi_sem_t *sem, uint32_t value)
return DDS_RETCODE_OK;
}
-dds_retcode_t
+static dds_return_t
ddsi_sem_destroy (ddsi_sem_t *sem)
{
ddsrt_cond_destroy (&sem->cv);
@@ -165,7 +164,7 @@ ddsi_sem_destroy (ddsi_sem_t *sem)
return DDS_RETCODE_OK;
}
-dds_retcode_t
+static dds_return_t
ddsi_sem_post (ddsi_sem_t *sem)
{
ddsrt_mutex_lock (&sem->mtx);
@@ -175,7 +174,7 @@ ddsi_sem_post (ddsi_sem_t *sem)
return DDS_RETCODE_OK;
}
-dds_retcode_t
+static dds_return_t
ddsi_sem_wait (ddsi_sem_t *sem)
{
ddsrt_mutex_lock (&sem->mtx);
@@ -201,8 +200,9 @@ struct nn_xpack
ddsi_tran_conn_t conn;
ddsi_sem_t sem;
size_t niov;
- ddsrt_iovec_t iov[NN_XMSG_MAX_MESSAGE_IOVECS];
+ ddsrt_iovec_t *iov;
enum nn_xmsg_dstmode dstmode;
+ struct q_globals *gv;
union
{
@@ -264,7 +264,6 @@ static void nn_xmsg_realfree_wrap (void *elem)
void nn_xmsgpool_free (struct nn_xmsgpool *pool)
{
nn_freelist_fini (&pool->freelist, nn_xmsg_realfree_wrap);
- DDS_TRACE("xmsgpool_free(%p)\n", (void *)pool);
ddsrt_free (pool);
}
@@ -507,7 +506,7 @@ void *nn_xmsg_submsg_from_marker (struct nn_xmsg *msg, struct nn_xmsg_marker mar
return msg->data->payload + marker.offset;
}
-void * nn_xmsg_append (struct nn_xmsg *m, struct nn_xmsg_marker *marker, size_t sz)
+void *nn_xmsg_append (struct nn_xmsg *m, struct nn_xmsg_marker *marker, size_t sz)
{
static const size_t a = 4;
@@ -586,7 +585,7 @@ void nn_xmsg_setdst1 (struct nn_xmsg *m, const nn_guid_prefix_t *gp, const nn_lo
m->data->dst.guid_prefix = nn_hton_guid_prefix (*gp);
}
-int nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd)
+dds_return_t nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd)
{
nn_locator_t loc;
if (addrset_any_uc (prd->c.as, &loc) || addrset_any_mc (prd->c.as, &loc))
@@ -596,12 +595,12 @@ int nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd)
}
else
{
- DDS_WARNING("nn_xmsg_setdstPRD: no address for "PGUIDFMT"", PGUID (prd->e.guid));
- return Q_ERR_NO_ADDRESS;
+ DDS_CWARNING (&prd->e.gv->logconfig, "nn_xmsg_setdstPRD: no address for "PGUIDFMT"", PGUID (prd->e.guid));
+ return DDS_RETCODE_PRECONDITION_NOT_MET;
}
}
-int nn_xmsg_setdstPWR (struct nn_xmsg *m, const struct proxy_writer *pwr)
+dds_return_t nn_xmsg_setdstPWR (struct nn_xmsg *m, const struct proxy_writer *pwr)
{
nn_locator_t loc;
if (addrset_any_uc (pwr->c.as, &loc) || addrset_any_mc (pwr->c.as, &loc))
@@ -609,8 +608,8 @@ int nn_xmsg_setdstPWR (struct nn_xmsg *m, const struct proxy_writer *pwr)
nn_xmsg_setdst1 (m, &pwr->e.guid.prefix, &loc);
return 0;
}
- DDS_WARNING("nn_xmsg_setdstPRD: no address for "PGUIDFMT, PGUID (pwr->e.guid));
- return Q_ERR_NO_ADDRESS;
+ DDS_CWARNING (&pwr->e.gv->logconfig, "nn_xmsg_setdstPRD: no address for "PGUIDFMT, PGUID (pwr->e.guid));
+ return DDS_RETCODE_PRECONDITION_NOT_MET;
}
void nn_xmsg_setdstN (struct nn_xmsg *m, struct addrset *as, struct addrset *as_group)
@@ -652,7 +651,7 @@ static int readerId_compatible (const struct nn_xmsg *m, const struct nn_xmsg *m
return e.u == NN_ENTITYID_UNKNOWN || e.u == eadd.u;
}
-int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct nn_xmsg *m, const struct nn_xmsg *madd)
+int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct q_globals *gv, struct nn_xmsg *m, const struct nn_xmsg *madd)
{
assert (m->kindspecific.data.wrseq >= 1);
assert (m->kindspecific.data.wrguid.prefix.u[0] != 0);
@@ -665,8 +664,7 @@ int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct nn_xmsg *m, const stru
assert (m->kindspecific.data.readerId_off != 0);
assert (madd->kindspecific.data.readerId_off != 0);
- DDS_TRACE(" ("PGUIDFMT"#%"PRId64"/%u:",
- PGUID (m->kindspecific.data.wrguid), m->kindspecific.data.wrseq, m->kindspecific.data.wrfragid + 1);
+ GVTRACE (" ("PGUIDFMT"#%"PRId64"/%u:", PGUID (m->kindspecific.data.wrguid), m->kindspecific.data.wrseq, m->kindspecific.data.wrfragid + 1);
switch (m->dstmode)
{
@@ -675,7 +673,7 @@ int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct nn_xmsg *m, const stru
return 0;
case NN_XMSG_DST_ALL:
- DDS_TRACE("*->*)");
+ GVTRACE ("*->*)");
return 1;
case NN_XMSG_DST_ONE:
@@ -686,7 +684,7 @@ int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct nn_xmsg *m, const stru
return 0;
case NN_XMSG_DST_ALL:
- DDS_TRACE("1+*->*)");
+ GVTRACE ("1+*->*)");
clear_readerId (m);
m->dstmode = NN_XMSG_DST_ALL;
m->dstaddr.all.as = ref_addrset (madd->dstaddr.all.as);
@@ -703,14 +701,14 @@ int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct nn_xmsg *m, const stru
an addrset in rebuild_writer_addrset: then we don't
need the lock anymore, and the '_wrlock_held' suffix
can go and everyone's life will become easier! */
- if ((wr = ephash_lookup_writer_guid (&m->kindspecific.data.wrguid)) == NULL)
+ if ((wr = ephash_lookup_writer_guid (gv->guid_hash, &m->kindspecific.data.wrguid)) == NULL)
{
- DDS_TRACE("writer-dead)");
+ GVTRACE ("writer-dead)");
return 0;
}
else
{
- DDS_TRACE("1+1->*)");
+ GVTRACE ("1+1->*)");
clear_readerId (m);
m->dstmode = NN_XMSG_DST_ALL;
m->dstaddr.all.as = ref_addrset (wr->as);
@@ -720,12 +718,12 @@ int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct nn_xmsg *m, const stru
}
else if (readerId_compatible (m, madd))
{
- DDS_TRACE("1+1->1)");
+ GVTRACE ("1+1->1)");
return 1;
}
else
{
- DDS_TRACE("1+1->2)");
+ GVTRACE ("1+1->2)");
clear_readerId (m);
return 1;
}
@@ -764,99 +762,24 @@ void nn_xmsg_setwriterseq_fragid (struct nn_xmsg *msg, const nn_guid_t *wrguid,
msg->kindspecific.data.wrfragid = wrfragid;
}
-size_t nn_xmsg_add_string_padded(unsigned char *buf, char *str)
+void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len)
{
- size_t len = strlen (str) + 1;
- assert (len <= UINT32_MAX);
- if (buf) {
- /* Add cdr string */
- struct cdrstring *p = (struct cdrstring *) buf;
- p->length = (uint32_t)len;
- memcpy (p->contents, str, len);
- /* clear padding */
- if (len < align4u (len)) {
- memset (p->contents + len, 0, align4u (len) - len);
- }
- }
- len = 4 + /* cdr string len arg + */
- align4u(len); /* strlen + possible padding */
- return len;
-}
-
-size_t nn_xmsg_add_octseq_padded(unsigned char *buf, nn_octetseq_t *seq)
-{
- unsigned len = seq->length;
- if (buf) {
- /* Add cdr octet seq */
- *((unsigned *)buf) = len;
- buf += sizeof (int);
- memcpy (buf, seq->value, len);
- /* clear padding */
- if (len < align4u (len)) {
- memset (buf + len, 0, align4u (len) - len);
- }
- }
- return 4 + /* cdr sequence len arg + */
- align4u(len); /* seqlen + possible padding */
-}
-
-void * nn_xmsg_addpar (struct nn_xmsg *m, unsigned pid, size_t len)
-{
- const size_t len4 = (len + 3) & (size_t)-4; /* must alloc a multiple of 4 */
+ const size_t len4 = (len + 3) & ~(size_t)3; /* must alloc a multiple of 4 */
nn_parameter_t *phdr;
char *p;
+ assert (len4 < UINT16_MAX); /* FIXME: return error */
m->have_params = 1;
phdr = nn_xmsg_append (m, NULL, sizeof (nn_parameter_t) + len4);
- phdr->parameterid = (nn_parameterid_t) pid;
- phdr->length = (unsigned short) len4;
+ phdr->parameterid = pid;
+ phdr->length = (uint16_t) len4;
p = (char *) (phdr + 1);
- if (len4 > len)
- {
- /* zero out padding bytes added to satisfy parameter alignment --
- alternative: zero out, but this way valgrind/purify can tell us
- where we forgot to initialize something */
- memset (p + len, 0, len4 - len);
- }
+ /* zero out padding bytes added to satisfy parameter alignment: this way
+ valgrind can tell us where we forgot to initialize something */
+ while (len < len4)
+ p[len++] = 0;
return p;
}
-void nn_xmsg_addpar_string (struct nn_xmsg *m, unsigned pid, const char *str)
-{
- struct cdrstring *p;
- unsigned len = (unsigned) strlen (str) + 1;
- p = nn_xmsg_addpar (m, pid, 4 + len);
- p->length = len;
- memcpy (p->contents, str, len);
-}
-
-void nn_xmsg_addpar_octetseq (struct nn_xmsg *m, unsigned pid, const nn_octetseq_t *oseq)
-{
- char *p = nn_xmsg_addpar (m, pid, 4 + oseq->length);
- *((unsigned *) p) = oseq->length;
- memcpy (p + sizeof (int), oseq->value, oseq->length);
-}
-
-void nn_xmsg_addpar_stringseq (struct nn_xmsg *m, unsigned pid, const nn_stringseq_t *sseq)
-{
- unsigned char *tmp;
- uint32_t i;
- size_t len = 0;
-
- for (i = 0; i < sseq->n; i++)
- {
- len += nn_xmsg_add_string_padded(NULL, sseq->strs[i]);
- }
-
- tmp = nn_xmsg_addpar (m, pid, 4 + len);
-
- *((uint32_t *) tmp) = sseq->n;
- tmp += sizeof (uint32_t);
- for (i = 0; i < sseq->n; i++)
- {
- tmp += nn_xmsg_add_string_padded(tmp, sseq->strs[i]);
- }
-}
-
void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata)
{
if (serdata->kind != SDK_EMPTY)
@@ -867,62 +790,9 @@ void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serda
}
}
-void nn_xmsg_addpar_guid (struct nn_xmsg *m, unsigned pid, const nn_guid_t *guid)
+static void nn_xmsg_addpar_BE4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x)
{
- unsigned *pu;
- int i;
- pu = nn_xmsg_addpar (m, pid, 16);
- for (i = 0; i < 3; i++)
- {
- pu[i] = toBE4u (guid->prefix.u[i]);
- }
- pu[i] = toBE4u (guid->entityid.u);
-}
-
-void nn_xmsg_addpar_reliability (struct nn_xmsg *m, unsigned pid, const struct nn_reliability_qospolicy *rq)
-{
- struct nn_external_reliability_qospolicy *p;
- p = nn_xmsg_addpar (m, pid, sizeof (*p));
- if (NN_PEDANTIC_P)
- {
- switch (rq->kind)
- {
- case NN_BEST_EFFORT_RELIABILITY_QOS:
- p->kind = NN_PEDANTIC_BEST_EFFORT_RELIABILITY_QOS;
- break;
- case NN_RELIABLE_RELIABILITY_QOS:
- p->kind = NN_PEDANTIC_RELIABLE_RELIABILITY_QOS;
- break;
- default:
- assert (0);
- }
- }
- else
- {
- switch (rq->kind)
- {
- case NN_BEST_EFFORT_RELIABILITY_QOS:
- p->kind = NN_INTEROP_BEST_EFFORT_RELIABILITY_QOS;
- break;
- case NN_RELIABLE_RELIABILITY_QOS:
- p->kind = NN_INTEROP_RELIABLE_RELIABILITY_QOS;
- break;
- default:
- assert (0);
- }
- }
- p->max_blocking_time = rq->max_blocking_time;
-}
-
-void nn_xmsg_addpar_4u (struct nn_xmsg *m, unsigned pid, unsigned x)
-{
- unsigned *p = nn_xmsg_addpar (m, pid, 4);
- *p = x;
-}
-
-void nn_xmsg_addpar_BE4u (struct nn_xmsg *m, unsigned pid, unsigned x)
-{
- unsigned *p = nn_xmsg_addpar (m, pid, 4);
+ unsigned *p = nn_xmsg_addpar (m, pid, sizeof (x));
*p = toBE4u (x);
}
@@ -942,62 +812,6 @@ void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, unsigned statusinfo)
}
}
-
-void nn_xmsg_addpar_share (struct nn_xmsg *m, unsigned pid, const struct nn_share_qospolicy *q)
-{
- /* Written thus to allow q->name to be a null pointer if enable = false */
- const unsigned fixed_len = 4 + 4;
- const unsigned len = (q->enable ? (unsigned) strlen (q->name) : 0) + 1;
- unsigned char *p;
- struct cdrstring *ps;
- p = nn_xmsg_addpar (m, pid, fixed_len + len);
- p[0] = q->enable;
- p[1] = 0;
- p[2] = 0;
- p[3] = 0;
- ps = (struct cdrstring *) (p + 4);
- ps->length = len;
- if (q->enable)
- memcpy (ps->contents, q->name, len);
- else
- ps->contents[0] = 0;
-}
-
-void nn_xmsg_addpar_subscription_keys (struct nn_xmsg *m, unsigned pid, const struct nn_subscription_keys_qospolicy *q)
-{
- unsigned char *tmp;
- size_t len = 8; /* use_key_list, length of key_list */
- unsigned i;
-
- for (i = 0; i < q->key_list.n; i++)
- {
- size_t len1 = strlen (q->key_list.strs[i]) + 1;
- len += 4 + align4u (len1);
- }
-
- tmp = nn_xmsg_addpar (m, pid, len);
-
- tmp[0] = q->use_key_list;
- for (i = 1; i < sizeof (int); i++)
- {
- tmp[i] = 0;
- }
- tmp += sizeof (int);
- *((uint32_t *) tmp) = q->key_list.n;
- tmp += sizeof (uint32_t);
- for (i = 0; i < q->key_list.n; i++)
- {
- struct cdrstring *p = (struct cdrstring *) tmp;
- size_t len1 = strlen (q->key_list.strs[i]) + 1;
- assert (len1 <= UINT32_MAX);
- p->length = (uint32_t)len1;
- memcpy (p->contents, q->key_list.strs[i], len1);
- if (len1 < align4u (len1))
- memset (p->contents + len1, 0, align4u (len1) - len1);
- tmp += 4 + align4u (len1);
- }
-}
-
void nn_xmsg_addpar_sentinel (struct nn_xmsg * m)
{
nn_xmsg_addpar (m, PID_SENTINEL, 0);
@@ -1013,40 +827,6 @@ int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg * m)
return 0;
}
-void nn_xmsg_addpar_parvinfo (struct nn_xmsg *m, unsigned pid, const struct nn_prismtech_participant_version_info *pvi)
-{
- int i;
- unsigned slen;
- unsigned *pu;
- struct cdrstring *ps;
-
- /* pvi->internals cannot be NULL here */
- slen = (unsigned) strlen(pvi->internals) + 1; /* +1 for '\0' terminator */
- pu = nn_xmsg_addpar (m, pid, NN_PRISMTECH_PARTICIPANT_VERSION_INFO_FIXED_CDRSIZE + slen);
- pu[0] = pvi->version;
- pu[1] = pvi->flags;
- for (i = 0; i < 3; i++)
- {
- pu[i+2] = (pvi->unused[i]);
- }
- ps = (struct cdrstring *)&pu[5];
- ps->length = slen;
- memcpy(ps->contents, pvi->internals, slen);
-}
-
-void nn_xmsg_addpar_eotinfo (struct nn_xmsg *m, unsigned pid, const struct nn_prismtech_eotinfo *txnid)
-{
- uint32_t *pu, i;
- pu = nn_xmsg_addpar (m, pid, 2 * sizeof (uint32_t) + txnid->n * sizeof (txnid->tids[0]));
- pu[0] = txnid->transactionId;
- pu[1] = txnid->n;
- for (i = 0; i < txnid->n; i++)
- {
- pu[2*i + 2] = toBE4u (txnid->tids[i].writer_entityid.u);
- pu[2*i + 3] = txnid->tids[i].transactionId;
- }
-}
-
/* XMSG_CHAIN ----------------------------------------------------------
Xpacks refer to xmsgs and need to release these after having been
@@ -1056,7 +836,7 @@ void nn_xmsg_addpar_eotinfo (struct nn_xmsg *m, unsigned pid, const struct nn_pr
pointer we compute the address of the xmsg from the address of the
chain element, &c. */
-static void nn_xmsg_chain_release (struct nn_xmsg_chain *chain)
+static void nn_xmsg_chain_release (struct q_globals *gv, struct nn_xmsg_chain *chain)
{
nn_guid_t wrguid;
memset (&wrguid, 0, sizeof (wrguid));
@@ -1087,7 +867,7 @@ static void nn_xmsg_chain_release (struct nn_xmsg_chain *chain)
struct writer *wr;
assert (m->kindspecific.data.wrseq != 0);
wrguid = m->kindspecific.data.wrguid;
- if ((wr = ephash_lookup_writer_guid (&m->kindspecific.data.wrguid)) != NULL)
+ if ((wr = ephash_lookup_writer_guid (gv->guid_hash, &m->kindspecific.data.wrguid)) != NULL)
UPDATE_SEQ_XMIT_UNLOCKED(wr, m->kindspecific.data.wrseq);
}
}
@@ -1114,7 +894,7 @@ static void nn_xmsg_chain_add (struct nn_xmsg_chain *chain, struct nn_xmsg *m)
#define NN_BW_LIMIT_MAX_BUFFER (-30 * T_MILLISECOND)
#define NN_BW_LIMIT_MIN_SLEEP (2 * T_MILLISECOND)
-static void nn_bw_limit_sleep_if_needed(struct nn_bw_limiter* this, ssize_t size)
+static void nn_bw_limit_sleep_if_needed (struct q_globals const * const gv, struct nn_bw_limiter *this, ssize_t size)
{
if ( this->bandwidth > 0 ) {
nn_mtime_t tnow = now_mt();
@@ -1130,27 +910,27 @@ static void nn_bw_limit_sleep_if_needed(struct nn_bw_limiter* this, ssize_t size
this->balance += (target_interval - actual_interval);
- DDS_TRACE(" balance < NN_BW_LIMIT_MAX_BUFFER )
{
/* We're below the bandwidth limit, do not further accumulate */
this->balance = NN_BW_LIMIT_MAX_BUFFER;
- DDS_TRACE(":%"PRId64":max",this->balance/1000);
+ GVTRACE (":%"PRId64":max",this->balance/1000);
}
else if ( this->balance > NN_BW_LIMIT_MIN_SLEEP )
{
/* We're over the bandwidth limit far enough, to warrent a sleep. */
- DDS_TRACE(":%"PRId64":sleep",this->balance/1000);
+ GVTRACE (":%"PRId64":sleep",this->balance/1000);
thread_state_blocked (lookup_thread_state ());
dds_sleepfor (this->balance);
thread_state_unblocked (lookup_thread_state ());
}
else
{
- DDS_TRACE(":%"PRId64"",this->balance/1000);
+ GVTRACE (":%"PRId64"",this->balance/1000);
}
- DDS_TRACE(">");
+ GVTRACE (">");
}
}
@@ -1192,11 +972,13 @@ struct nn_xpack * nn_xpack_new (ddsi_tran_conn_t conn, uint32_t bw_limit, bool a
/* Disallow setting async_mode if not configured to enable async mode: this way we
can avoid starting the async send thread altogether */
- assert (!async_mode || config.xpack_send_async);
+ assert (!async_mode || conn->m_base.gv->config.xpack_send_async);
xp = ddsrt_malloc (sizeof (*xp));
memset (xp, 0, sizeof (*xp));
xp->async_mode = async_mode;
+ xp->iov = NULL;
+ xp->gv = conn->m_base.gv;
/* Fixed header fields, initialized just once */
xp->hdr.protocol.id[0] = 'R';
@@ -1216,7 +998,7 @@ struct nn_xpack * nn_xpack_new (ddsi_tran_conn_t conn, uint32_t bw_limit, bool a
xp->conn = conn;
nn_xpack_reinit (xp);
- if (gv.thread_pool)
+ if (xp->gv->thread_pool)
ddsi_sem_init (&xp->sem, 0);
#ifdef DDSI_INCLUDE_ENCRYPTION
@@ -1247,29 +1029,31 @@ void nn_xpack_free (struct nn_xpack *xp)
(q_security_plugin.free_encoder) (xp->codec);
}
#endif
- if (gv.thread_pool)
+ if (xp->gv->thread_pool)
ddsi_sem_destroy (&xp->sem);
+ ddsrt_free (xp->iov);
ddsrt_free (xp);
}
static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg)
{
- struct nn_xpack * xp = varg;
+ struct nn_xpack *xp = varg;
+ struct q_globals const * const gv = xp->gv;
ssize_t nbytes = 0;
- if (dds_get_log_mask() & DDS_LC_TRACE)
+ if (gv->logconfig.c.mask & DDS_LC_TRACE)
{
char buf[DDSI_LOCSTRLEN];
- DDS_TRACE(" %s", ddsi_locator_to_string (buf, sizeof(buf), loc));
+ GVTRACE (" %s", ddsi_locator_to_string (gv, buf, sizeof(buf), loc));
}
- if (config.xmit_lossiness > 0)
+ if (gv->config.xmit_lossiness > 0)
{
/* We drop APPROXIMATELY a fraction of xmit_lossiness * 10**(-3)
of all packets to be sent */
- if ((ddsrt_random () % 1000) < (uint32_t) config.xmit_lossiness)
+ if ((ddsrt_random () % 1000) < (uint32_t) gv->config.xmit_lossiness)
{
- DDS_TRACE("(dropped)");
+ GVTRACE ("(dropped)");
xp->call_flags = 0;
return 0;
}
@@ -1285,7 +1069,7 @@ static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg)
else
#endif
{
- if (!gv.mute)
+ if (!gv->mute)
{
nbytes = ddsi_conn_write (xp->conn, loc, xp->niov, xp->iov, xp->call_flags);
#ifndef NDEBUG
@@ -1300,7 +1084,7 @@ static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg)
}
else
{
- DDS_TRACE("(dropped)");
+ GVTRACE ("(dropped)");
nbytes = (ssize_t) xp->msg_len.length;
}
}
@@ -1312,7 +1096,7 @@ static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg)
#ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING
if (nbytes > 0)
{
- nn_bw_limit_sleep_if_needed (&xp->limiter, nbytes);
+ nn_bw_limit_sleep_if_needed (gv, &xp->limiter, nbytes);
}
#endif
@@ -1346,11 +1130,12 @@ static void nn_xpack_send1_threaded (const nn_locator_t *loc, void * varg)
arg->xp = (struct nn_xpack *) varg;
arg->loc = loc;
ddsrt_atomic_inc32 (&arg->xp->calls);
- ddsrt_thread_pool_submit (gv.thread_pool, nn_xpack_send1_thread, arg);
+ ddsrt_thread_pool_submit (arg->xp->gv->thread_pool, nn_xpack_send1_thread, arg);
}
-static void nn_xpack_send_real (struct nn_xpack * xp)
+static void nn_xpack_send_real (struct nn_xpack *xp)
{
+ struct q_globals const * const gv = xp->gv;
size_t calls;
assert (xp->niov <= NN_XMSG_MAX_MESSAGE_IOVECS);
@@ -1362,17 +1147,17 @@ static void nn_xpack_send_real (struct nn_xpack * xp)
assert (xp->dstmode != NN_XMSG_DST_UNSET);
- if (dds_get_log_mask() & DDS_LC_TRACE)
+ if (gv->logconfig.c.mask & DDS_LC_TRACE)
{
int i;
- DDS_TRACE("nn_xpack_send %"PRIu32":", xp->msg_len.length);
+ GVTRACE ("nn_xpack_send %"PRIu32":", xp->msg_len.length);
for (i = 0; i < (int) xp->niov; i++)
{
- DDS_TRACE(" %p:%lu", (void *) xp->iov[i].iov_base, (unsigned long) xp->iov[i].iov_len);
+ GVTRACE (" %p:%lu", (void *) xp->iov[i].iov_base, (unsigned long) xp->iov[i].iov_len);
}
}
- DDS_TRACE(" [");
+ GVTRACE (" [");
if (xp->dstmode == NN_XMSG_DST_ONE)
{
calls = 1;
@@ -1386,7 +1171,7 @@ static void nn_xpack_send_real (struct nn_xpack * xp)
calls = 0;
if (xp->dstaddr.all.as)
{
- if (gv.thread_pool == NULL)
+ if (xp->gv->thread_pool == NULL)
{
calls = addrset_forall_count (xp->dstaddr.all.as, nn_xpack_send1v, xp);
}
@@ -1415,12 +1200,12 @@ static void nn_xpack_send_real (struct nn_xpack * xp)
unref_addrset (xp->dstaddr.all.as_group);
}
}
- DDS_TRACE(" ]\n");
+ GVTRACE (" ]\n");
if (calls)
{
- DDS_LOG(DDS_LC_TRAFFIC, "traffic-xmit (%lu) %"PRIu32"\n", (unsigned long) calls, xp->msg_len.length);
+ GVLOG (DDS_LC_TRAFFIC, "traffic-xmit (%lu) %"PRIu32"\n", (unsigned long) calls, xp->msg_len.length);
}
- nn_xmsg_chain_release (&xp->included_msgs);
+ nn_xmsg_chain_release (xp->gv, &xp->included_msgs);
nn_xpack_reinit (xp);
}
@@ -1428,60 +1213,61 @@ static void nn_xpack_send_real (struct nn_xpack * xp)
#define SENDQ_HW 10
#define SENDQ_LW 0
-static uint32_t nn_xpack_sendq_thread (UNUSED_ARG (void *arg))
+static uint32_t nn_xpack_sendq_thread (void *vgv)
{
- ddsrt_mutex_lock (&gv.sendq_lock);
- while (!(gv.sendq_stop && gv.sendq_head == NULL))
+ struct q_globals *gv = vgv;
+ ddsrt_mutex_lock (&gv->sendq_lock);
+ while (!(gv->sendq_stop && gv->sendq_head == NULL))
{
struct nn_xpack *xp;
- if ((xp = gv.sendq_head) == NULL)
+ if ((xp = gv->sendq_head) == NULL)
{
- ddsrt_cond_waitfor (&gv.sendq_cond, &gv.sendq_lock, 1000000);
+ ddsrt_cond_waitfor (&gv->sendq_cond, &gv->sendq_lock, 1000000);
}
else
{
- gv.sendq_head = xp->sendq_next;
- if (--gv.sendq_length == SENDQ_LW)
- ddsrt_cond_broadcast (&gv.sendq_cond);
- ddsrt_mutex_unlock (&gv.sendq_lock);
+ gv->sendq_head = xp->sendq_next;
+ if (--gv->sendq_length == SENDQ_LW)
+ ddsrt_cond_broadcast (&gv->sendq_cond);
+ ddsrt_mutex_unlock (&gv->sendq_lock);
nn_xpack_send_real (xp);
nn_xpack_free (xp);
- ddsrt_mutex_lock (&gv.sendq_lock);
+ ddsrt_mutex_lock (&gv->sendq_lock);
}
}
- ddsrt_mutex_unlock (&gv.sendq_lock);
+ ddsrt_mutex_unlock (&gv->sendq_lock);
return 0;
}
-void nn_xpack_sendq_init (void)
+void nn_xpack_sendq_init (struct q_globals *gv)
{
- gv.sendq_stop = 0;
- gv.sendq_head = NULL;
- gv.sendq_tail = NULL;
- gv.sendq_length = 0;
- ddsrt_mutex_init (&gv.sendq_lock);
- ddsrt_cond_init (&gv.sendq_cond);
+ gv->sendq_stop = 0;
+ gv->sendq_head = NULL;
+ gv->sendq_tail = NULL;
+ gv->sendq_length = 0;
+ ddsrt_mutex_init (&gv->sendq_lock);
+ ddsrt_cond_init (&gv->sendq_cond);
}
-void nn_xpack_sendq_start (void)
+void nn_xpack_sendq_start (struct q_globals *gv)
{
- create_thread (&gv.sendq_ts, "sendq", nn_xpack_sendq_thread, NULL);
+ create_thread (&gv->sendq_ts, gv, "sendq", nn_xpack_sendq_thread, NULL);
}
-void nn_xpack_sendq_stop (void)
+void nn_xpack_sendq_stop (struct q_globals *gv)
{
- ddsrt_mutex_lock (&gv.sendq_lock);
- gv.sendq_stop = 1;
- ddsrt_cond_broadcast (&gv.sendq_cond);
- ddsrt_mutex_unlock (&gv.sendq_lock);
+ ddsrt_mutex_lock (&gv->sendq_lock);
+ gv->sendq_stop = 1;
+ ddsrt_cond_broadcast (&gv->sendq_cond);
+ ddsrt_mutex_unlock (&gv->sendq_lock);
}
-void nn_xpack_sendq_fini (void)
+void nn_xpack_sendq_fini (struct q_globals *gv)
{
- assert (gv.sendq_head == NULL);
- join_thread(gv.sendq_ts);
- ddsrt_cond_destroy(&gv.sendq_cond);
- ddsrt_mutex_destroy(&gv.sendq_lock);
+ assert (gv->sendq_head == NULL);
+ join_thread (gv->sendq_ts);
+ ddsrt_cond_destroy (&gv->sendq_cond);
+ ddsrt_mutex_destroy (&gv->sendq_lock);
}
void nn_xpack_send (struct nn_xpack *xp, bool immediately)
@@ -1492,27 +1278,28 @@ void nn_xpack_send (struct nn_xpack *xp, bool immediately)
}
else
{
+ struct q_globals * const gv = xp->gv;
struct nn_xpack *xp1 = ddsrt_malloc (sizeof (*xp));
memcpy (xp1, xp, sizeof (*xp1));
nn_xpack_reinit (xp);
xp1->sendq_next = NULL;
- ddsrt_mutex_lock (&gv.sendq_lock);
- if (immediately || gv.sendq_length == SENDQ_HW)
- ddsrt_cond_broadcast (&gv.sendq_cond);
- if (gv.sendq_length >= SENDQ_MAX)
+ ddsrt_mutex_lock (&gv->sendq_lock);
+ if (immediately || gv->sendq_length == SENDQ_HW)
+ ddsrt_cond_broadcast (&gv->sendq_cond);
+ if (gv->sendq_length >= SENDQ_MAX)
{
- while (gv.sendq_length > SENDQ_LW)
- ddsrt_cond_wait (&gv.sendq_cond, &gv.sendq_lock);
+ while (gv->sendq_length > SENDQ_LW)
+ ddsrt_cond_wait (&gv->sendq_cond, &gv->sendq_lock);
}
- if (gv.sendq_head)
- gv.sendq_tail->sendq_next = xp1;
+ if (gv->sendq_head)
+ gv->sendq_tail->sendq_next = xp1;
else
{
- gv.sendq_head = xp1;
+ gv->sendq_head = xp1;
}
- gv.sendq_tail = xp1;
- gv.sendq_length++;
- ddsrt_mutex_unlock (&gv.sendq_lock);
+ gv->sendq_tail = xp1;
+ gv->sendq_length++;
+ ddsrt_mutex_unlock (&gv->sendq_lock);
}
}
@@ -1554,7 +1341,7 @@ static int addressing_info_eq_onesidederr (const struct nn_xpack *xp, const stru
static int nn_xpack_mayaddmsg (const struct nn_xpack *xp, const struct nn_xmsg *m, const uint32_t flags)
{
- unsigned max_msg_size = config.max_msg_size;
+ unsigned max_msg_size = xp->gv->config.max_msg_size;
unsigned payload_size;
if (xp->niov == 0)
@@ -1606,7 +1393,7 @@ static int guid_prefix_eq (const nn_guid_prefix_t *a, const nn_guid_prefix_t *b)
int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flags)
{
/* Returns > 0 if pack got sent out before adding m */
-
+ struct q_globals const * const gv = xp->gv;
static InfoDST_t static_zero_dst = {
{ SMID_INFO_DST, (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? SMFLAG_ENDIANNESS : 0), sizeof (nn_guid_prefix_t) },
{ { 0,0,0,0, 0,0,0,0, 0,0,0,0 } }
@@ -1630,6 +1417,9 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag
assert ((m->sz % 4) == 0);
assert (m->refd_payload == NULL || (m->refd_payload_iov.iov_len % 4) == 0);
+ if (xp->iov == NULL)
+ xp->iov = malloc (NN_XMSG_MAX_MESSAGE_IOVECS * sizeof (*xp->iov));
+
if (!nn_xpack_mayaddmsg (xp, m, flags))
{
assert (xp->niov > 0);
@@ -1647,22 +1437,22 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag
But do make sure we can't run out of iovecs. */
assert (niov + NN_XMSG_MAX_SUBMESSAGE_IOVECS <= NN_XMSG_MAX_MESSAGE_IOVECS);
- DDS_TRACE("xpack_addmsg %p %p %"PRIu32"(", (void *) xp, (void *) m, flags);
+ GVTRACE ("xpack_addmsg %p %p %"PRIu32"(", (void *) xp, (void *) m, flags);
switch (m->kind)
{
case NN_XMSG_KIND_CONTROL:
- DDS_TRACE("control");
+ GVTRACE ("control");
break;
case NN_XMSG_KIND_DATA:
case NN_XMSG_KIND_DATA_REXMIT:
- DDS_TRACE("%s("PGUIDFMT":#%"PRId64"/%u)",
- (m->kind == NN_XMSG_KIND_DATA) ? "data" : "rexmit",
- PGUID (m->kindspecific.data.wrguid),
- m->kindspecific.data.wrseq,
- m->kindspecific.data.wrfragid + 1);
+ GVTRACE ("%s("PGUIDFMT":#%"PRId64"/%u)",
+ (m->kind == NN_XMSG_KIND_DATA) ? "data" : "rexmit",
+ PGUID (m->kindspecific.data.wrguid),
+ m->kindspecific.data.wrseq,
+ m->kindspecific.data.wrfragid + 1);
break;
}
- DDS_TRACE("): niov %d sz %"PRIuSIZE, (int) niov, sz);
+ GVTRACE ("): niov %d sz %"PRIuSIZE, (int) niov, sz);
/* If a fresh xp has been provided, add an RTPS header */
@@ -1788,9 +1578,10 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag
xp->msg_len.length = (uint32_t) sz;
xp->niov = niov;
- if (xpo_niov > 0 && sz > config.max_msg_size)
+ if (xpo_niov > 0 && sz > xp->gv->config.max_msg_size)
{
- DDS_TRACE(" => now niov %d sz %"PRIuSIZE" > max_msg_size %"PRIu32", nn_xpack_send niov %d sz %"PRIu32" now\n", (int) niov, sz, config.max_msg_size, (int) xpo_niov, xpo_sz);
+ GVTRACE (" => now niov %d sz %"PRIuSIZE" > max_msg_size %"PRIu32", nn_xpack_send niov %d sz %"PRIu32" now\n",
+ (int) niov, sz, gv->config.max_msg_size, (int) xpo_niov, xpo_sz);
xp->msg_len.length = xpo_sz;
xp->niov = xpo_niov;
nn_xpack_send (xp, false);
@@ -1800,7 +1591,7 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag
{
xp->call_flags = flags;
nn_xmsg_chain_add (&xp->included_msgs, m);
- DDS_TRACE(" => now niov %d sz %"PRIuSIZE"\n", (int) niov, sz);
+ GVTRACE (" => now niov %d sz %"PRIuSIZE"\n", (int) niov, sz);
}
return result;
diff --git a/src/core/ddsi/src/sysdeps.c b/src/core/ddsi/src/sysdeps.c
index 13fa3f1..e7b2915 100644
--- a/src/core/ddsi/src/sysdeps.c
+++ b/src/core/ddsi/src/sysdeps.c
@@ -15,13 +15,11 @@
#include "dds/ddsrt/atomics.h"
#include "dds/ddsrt/misc.h"
-#include "dds/ddsi/q_error.h"
#include "dds/ddsi/q_log.h"
-#include "dds/ddsi/q_config.h"
#include "dds/ddsi/sysdeps.h"
-#if !(defined __APPLE__ || defined __linux) || (__GNUC__ > 0 && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40100)
-void log_stacktrace (const char *name, ddsrt_thread_t tid)
+#if DDSRT_WITH_FREERTOS || !(defined __APPLE__ || defined __linux) || (__GNUC__ > 0 && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40100)
+void log_stacktrace (const struct ddsrt_log_cfg *logcfg, const char *name, ddsrt_thread_t tid)
{
DDSRT_UNUSED_ARG (name);
DDSRT_UNUSED_ARG (tid);
@@ -46,42 +44,35 @@ static void log_stacktrace_sigh (int sig __attribute__ ((unused)))
errno = e;
}
-void log_stacktrace (const char *name, ddsrt_thread_t tid)
+void log_stacktrace (const struct ddsrt_log_cfg *logcfg, const char *name, ddsrt_thread_t tid)
{
- if (dds_get_log_mask() == 0)
- ; /* no op if nothing logged */
- else if (!config.noprogress_log_stacktraces)
- DDS_LOG(~DDS_LC_FATAL, "-- stack trace of %s requested, but traces disabled --\n", name);
+ const dds_time_t d = 1000000;
+ struct sigaction act, oact;
+ char **strs;
+ int i;
+ DDS_CLOG (~DDS_LC_FATAL, logcfg, "-- stack trace of %s requested --\n", name);
+ act.sa_handler = log_stacktrace_sigh;
+ act.sa_flags = 0;
+ sigfillset (&act.sa_mask);
+ while (!ddsrt_atomic_cas32 (&log_stacktrace_flag, 0, 1))
+ dds_sleepfor (d);
+ sigaction (SIGXCPU, &act, &oact);
+ pthread_kill (tid.v, SIGXCPU);
+ while (!ddsrt_atomic_cas32 (&log_stacktrace_flag, 2, 3) && pthread_kill (tid.v, 0) == 0)
+ dds_sleepfor (d);
+ sigaction (SIGXCPU, &oact, NULL);
+ if (pthread_kill (tid.v, 0) != 0)
+ DDS_CLOG (~DDS_LC_FATAL, logcfg, "-- thread exited --\n");
else
{
- const dds_time_t d = 1000000;
- struct sigaction act, oact;
- char **strs;
- int i;
- DDS_LOG(~DDS_LC_FATAL, "-- stack trace of %s requested --\n", name);
- act.sa_handler = log_stacktrace_sigh;
- act.sa_flags = 0;
- sigfillset (&act.sa_mask);
- while (!ddsrt_atomic_cas32 (&log_stacktrace_flag, 0, 1))
- dds_sleepfor (d);
- sigaction (SIGXCPU, &act, &oact);
- pthread_kill (tid.v, SIGXCPU);
- while (!ddsrt_atomic_cas32 (&log_stacktrace_flag, 2, 3) && pthread_kill (tid.v, 0) == 0)
- dds_sleepfor (d);
- sigaction (SIGXCPU, &oact, NULL);
- if (pthread_kill (tid.v, 0) != 0)
- DDS_LOG(~DDS_LC_FATAL, "-- thread exited --\n");
- else
- {
- DDS_LOG(~DDS_LC_FATAL, "-- stack trace follows --\n");
- strs = backtrace_symbols (log_stacktrace_stk.stk, log_stacktrace_stk.depth);
- for (i = 0; i < log_stacktrace_stk.depth; i++)
- DDS_LOG(~DDS_LC_FATAL, "%s\n", strs[i]);
- free (strs);
- DDS_LOG(~DDS_LC_FATAL, "-- end of stack trace --\n");
- }
- ddsrt_atomic_st32 (&log_stacktrace_flag, 0);
+ DDS_CLOG (~DDS_LC_FATAL, logcfg, "-- stack trace follows --\n");
+ strs = backtrace_symbols (log_stacktrace_stk.stk, log_stacktrace_stk.depth);
+ for (i = 0; i < log_stacktrace_stk.depth; i++)
+ DDS_CLOG (~DDS_LC_FATAL, logcfg, "%s\n", strs[i]);
+ free (strs);
+ DDS_CLOG (~DDS_LC_FATAL, logcfg, "-- end of stack trace --\n");
}
+ ddsrt_atomic_st32 (&log_stacktrace_flag, 0);
}
#endif
diff --git a/src/core/xtests/CMakeLists.txt b/src/core/xtests/CMakeLists.txt
index 02b7bfd..72bdb94 100644
--- a/src/core/xtests/CMakeLists.txt
+++ b/src/core/xtests/CMakeLists.txt
@@ -9,18 +9,5 @@
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
-idlc_generate(RhcTypes RhcTypes.idl)
-
-add_executable(rhc_torture rhc_torture.c)
-
-target_include_directories(
- rhc_torture PRIVATE
- "$"
- "$")
-
-target_link_libraries(rhc_torture RhcTypes ddsc)
-
-add_test(
- NAME rhc_torture
- COMMAND rhc_torture 314159265 0 5000 0)
-set_property(TEST rhc_torture PROPERTY TIMEOUT 20)
+add_subdirectory(rhc_torture)
+add_subdirectory(initsampledeliv)
diff --git a/src/core/xtests/cdrtest/CMakeLists.txt b/src/core/xtests/cdrtest/CMakeLists.txt
new file mode 100644
index 0000000..1535a9c
--- /dev/null
+++ b/src/core/xtests/cdrtest/CMakeLists.txt
@@ -0,0 +1,40 @@
+#
+# Copyright(c) 2019 ADLINK Technology Limited and others
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0 which is available at
+# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+# v. 1.0 which is available at
+# http://www.eclipse.org/org/documents/edl-v10.php.
+#
+# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+#
+cmake_minimum_required(VERSION 3.5)
+
+add_compile_options("-I${PROJECT_SOURCE_DIR}/src/ddsrt/include")
+add_compile_options("-I${PROJECT_SOURCE_DIR}/src/core/ddsc/include")
+add_compile_options("-I${PROJECT_SOURCE_DIR}/src/core/ddsc/src")
+add_compile_options("-I${PROJECT_SOURCE_DIR}/src/core/ddsi/include")
+
+add_compile_options("-I$ENV{OSPL_HOME}/src/abstraction/os/include")
+add_compile_options("-I$ENV{OSPL_HOME}/src/database/database/include")
+add_compile_options("-I$ENV{OSPL_HOME}/src/database/serialization/include")
+add_compile_options("-I$ENV{OSPL_HOME}/src/utilities/include")
+add_compile_options("-I$ENV{OSPL_HOME}/src/kernel/include")
+add_compile_options("-I$ENV{OSPL_HOME}/src/kernel/bld/$ENV{SPLICE_TARGET}")
+add_compile_options("-I$ENV{OSPL_HOME}/src/user/include")
+add_compile_options("-I$ENV{OSPL_HOME}/src/api/dcps/sac/include")
+add_compile_options("-I$ENV{OSPL_HOME}/src/api/dcps/sac/code")
+
+# This is a convenience function, provided by the CycloneDDS package,
+# that will supply a library target related the the given idl file.
+# In short, it takes the idl file, generates the source files with
+# the proper data types and compiles them into a library.
+idlc_generate(xxx_lib "xxx.idl")
+
+# Both executables have only one related source file.
+add_executable(xxx xxx-cyc.c)
+
+# Both executables need to be linked to the idl data type library and
+# the ddsc API library.
+target_link_libraries(xxx xxx_lib CycloneDDS::ddsc -L$ENV{OSPL_HOME}/lib/$ENV{SPLICE_TARGET} -Wl,-rpath,$ENV{OSPL_HOME}/lib/$ENV{SPLICE_TARGET} ddskernel dcpssac)
diff --git a/src/core/xtests/cdrtest/cdrtest.pl b/src/core/xtests/cdrtest/cdrtest.pl
new file mode 100644
index 0000000..e850927
--- /dev/null
+++ b/src/core/xtests/cdrtest/cdrtest.pl
@@ -0,0 +1,403 @@
+#
+# Copyright(c) 2019 ADLINK Technology Limited and others
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0 which is available at
+# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+# v. 1.0 which is available at
+# http://www.eclipse.org/org/documents/edl-v10.php.
+#
+# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+#
+
+#use strict;
+
+use Data::Dumper;
+$Data::Dumper::Terse = 1;
+$Data::Dumper::Useqq = 1;
+
+my $outfn = "xxx";
+local $nextident = "a0000";
+
+my @types = qw(u0 u1 u2 u3 u4 seq ary str uni);
+my @idltype = ("octet", "unsigned short", "unsigned long", "unsigned long long", "string");
+# unions cannot have an octet as a discriminator ...
+my @idltype_unidisc = ("char", "unsigned short", "unsigned long", "unsigned long long", "string");
+my @ctype = ("uint8_t", "uint16_t", "uint32_t", "uint64_t", "char *");
+my @probs = do {
+ my @ps = qw(0.3 0.3 0.3 0.3 0.3 1 1 1 1);
+ my (@xs, $sum);
+ for (@ps) { $sum += $_; push @xs, $sum; }
+ @xs;
+};
+my @noaryprobs = do {
+ my @ps = qw(0.3 0.3 0.3 0.3 0.3 1 0 1 1);
+ my (@xs, $sum);
+ for (@ps) { $sum += $_; push @xs, $sum; }
+ @xs;
+};
+my @unicaseprobs = do {
+ my @ps = qw(0.3 0.3 0.3 0.3 0.3 1 0 1 0);
+ my (@xs, $sum);
+ for (@ps) { $sum += $_; push @xs, $sum; }
+ @xs;
+};
+
+open IDL, ">${outfn}.idl" or die "can't open ${outfn}.idl";
+open CYC, ">${outfn}-cyc.c" or die "can't open ${outfn}-cyc.c";
+print CYC <
+#include
+#include
+#include
+#include "dds/dds.h"
+#include "dds/ddsrt/random.h"
+#include "dds/ddsrt/sockets.h"
+#include "dds/ddsi/ddsi_serdata_default.h"
+#include "dds__stream.h"
+
+#include "c_base.h"
+#include "sd_cdr.h"
+#include "sd_serializerXMLTypeinfo.h"
+#include "v_copyIn.h"
+#include "sac_genericCopyIn.h"
+
+#include "xxx.h"
+int main()
+{
+ unsigned char garbage[1000];
+ struct ddsi_sertopic_default ddd;
+ uint32_t deser_garbage = 0;
+ memset (&ddd, 0, sizeof (ddd));
+ dds_istream_t is;
+ c_base base = c_create ("X", NULL, 0, 0);
+ dds_entity_t dp = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
+ if (dp < 0) abort ();
+EOF
+;
+for (1 .. 300) {
+ my $t = genstr (0);
+ my $idl = genidltd ($t);
+ print IDL $idl;
+ (my $idlcmt = $idl) =~ s,^,//,mg;
+ print CYC $idlcmt;
+ gencyc ($t);
+}
+print CYC <[1]_desc, \"$t->[1]\", NULL, NULL);
+ if (tp < 0) abort ();
+ dds_entity_t rd = dds_create_reader (dp, tp, NULL, NULL);
+ if (rd < 0) abort ();
+ dds_entity_t wr = dds_create_writer (dp, tp, NULL, NULL);
+ if (wr < 0) abort ();
+EOF
+ ;
+ print CYC geninit ($t);
+ print CYC <[1]) < 0) abort ();
+ void *msg = NULL;
+ dds_sample_info_t info;
+ if (dds_take (rd, &msg, &info, 1, 1) != 1) abort ();
+ const $t->[1] *b = msg;
+EOF
+ ;
+ print CYC gencmp ($t);
+ print CYC <[1]_desc;
+ for (uint32_t i = 0; i < 1000; i++) {
+ for (size_t j = 0; j < sizeof (garbage); j++)
+ garbage[j] = (unsigned char) ddsrt_random ();
+ if (dds_stream_normalize (garbage, (uint32_t) sizeof (garbage), false, &ddd, false)) {
+ is.m_buffer = garbage;
+ is.m_size = 1000;
+ is.m_index = 0;
+ dds_stream_read_sample (&is, msg, &ddd);
+ deser_garbage++;
+ }
+ }
+ sd_serializer serializer = sd_serializerXMLTypeinfoNew (base, 0);
+ sd_serializedData meta_data = sd_serializerFromString (serializer, $t->[1]_desc.m_meta);
+ if (sd_serializerDeserialize (serializer, meta_data) == NULL) abort ();
+ c_type type = c_resolve (base, "$t->[1]"); if (!type) abort ();
+ sd_serializedDataFree (meta_data);
+ sd_serializerFree (serializer);
+ struct sd_cdrInfo *ci = sd_cdrInfoNew (type);
+ if (sd_cdrCompile (ci) < 0) abort ();
+ DDS_copyCache cc = DDS_copyCacheNew ((c_metaObject) type);
+ struct DDS_srcInfo_s src = { .src = &v$t->[1], cc };
+ void *samplecopy = c_new (type);
+ DDS_copyInStruct (base, &src, samplecopy);
+ struct sd_cdrSerdata *sd = sd_cdrSerializeBSwap (ci, samplecopy);
+ const void *blob;
+ uint32_t blobsz = sd_cdrSerdataBlob (&blob, sd);
+ /* hack alert: modifying read-only blob ...*/
+ if (!dds_stream_normalize ((void *) blob, blobsz, true, &ddd, false)) abort ();
+ is.m_buffer = blob;
+ is.m_size = blobsz;
+ is.m_index = 0;
+ dds_stream_read_sample (&is, msg, &ddd);
+ sd_cdrSerdataFree (sd);
+ sd = sd_cdrSerialize (ci, samplecopy);
+ blobsz = sd_cdrSerdataBlob (&blob, sd);
+ if (!dds_stream_normalize ((void *) blob, blobsz, false, &ddd, false)) abort ();
+ for (uint32_t i = 1; i < blobsz && i <= 16; i++) {
+ if (dds_stream_normalize ((void *) blob, blobsz - i, false, &ddd, false)) abort ();
+ }
+ sd_cdrSerdataFree (sd);
+EOF
+;
+ print CYC gencmp ($t);
+ print CYC <[1] v$t->[1] = $res;\n";
+}
+
+sub gencmp {
+ my ($t) = @_;
+ my $res = gencmp1 ($t, "v$t->[1]", "");
+ return $res;
+}
+
+sub geninit1 {
+ my ($ind, $out, $t, $idxsuf) = @_;
+ if ($t->[0] =~ /^u([0-3])$/) {
+ return int (rand (10));
+ } elsif ($t->[0] eq "u4") {
+ return "\"".("x"x(int (rand (8))))."\"";
+ } elsif ($t->[0] eq "seq") {
+ my $len = int (rand (10));
+ my $bufref;
+ if ($len == 0) {
+ $bufref = "0";
+ } else {
+ my $buf = "vb$t->[1]_$idxsuf";
+ $bufref = "$buf";
+ my $ctype = ($t->[2]->[0] =~ /^u(\d+)$/) ? $ctype[$1] : $t->[2]->[1];
+ my $tmp = " $ctype $buf\[\] = {";
+ for (1..$len) {
+ $tmp .= geninit1 ("$ind", $out, $t->[2], "${idxsuf}_$_");
+ $tmp .= "," if $_ < $len;
+ }
+ $tmp .= "};\n";
+ push @$out, $tmp;
+ }
+ return "{$len,$len,$bufref,0}";
+ } elsif ($t->[0] eq "ary") {
+ my $len = $t->[3]; die unless $len > 0;
+ my $tmp = "{";
+ for (1..$len) {
+ $tmp .= geninit1 ("$ind", $out, $t->[2], "${idxsuf}_$_");
+ $tmp .= "," if $_ < $len;
+ }
+ $tmp .= "}";
+ return $tmp;
+ } elsif ($t->[0] eq "str") {
+ my $tmp = "{";
+ for (my $i = 2; $i < @$t; $i++) {
+ my ($name, $st) = @{$t->[$i]};
+ $tmp .= geninit1 ("", $out, $st, "${idxsuf}_");
+ $tmp .= "," if $i + 1 < @$t;
+ }
+ $tmp .= "}";
+ return $tmp;
+ } elsif ($t->[0] eq "uni") { # uni name disctype hasdef case...
+ my $discval = int(rand(@$t - 3)); # -3 so we generate values outside label range as well
+ my $hasdef = $t->[3];
+ my $case = (4 + $discval < @$t) ? $discval : $hasdef ? @$t-1 : 0;
+ $discval = ("'".chr ($discval + ord ("A"))."'") if $t->[2] eq "u0";
+ # $case matches have a label or default; if no default generate an initializer for the
+ # first case to avoid compiler warnings
+ my ($name, $st) = @{$t->[4+$case]};
+ my $tmp = "{$discval,{.$name=";
+ $tmp .= geninit1 ("", $out, $st, "${idxsuf}_");
+ $tmp .= "}}";
+ return $tmp;
+ } else {
+ die;
+ }
+}
+
+sub gencmp1 {
+ my ($t, $toplevel, $path) = @_;
+ if ($t->[0] =~ /^u([0-3])$/) {
+ return " if ($toplevel.$path != b->$path) abort ();\n";
+ } elsif ($t->[0] eq "u4") {
+ return " if (strcmp ($toplevel.$path, b->$path) != 0) abort ();\n";
+ } elsif ($t->[0] eq "seq") {
+ my $idx = "i".length $path;
+ return ("if ($toplevel.$path._length != b->$path._length) abort ();\n" .
+ "for (uint32_t $idx = 0; $idx < $toplevel.$path._length; $idx++) {\n" .
+ gencmp1 ($t->[2], $toplevel, "$path._buffer[$idx]") .
+ "}\n");
+ } elsif ($t->[0] eq "ary") {
+ my $len = $t->[3]; die unless $len > 0;
+ my $idx = "i".length $path;
+ return ("for (uint32_t $idx = 0; $idx < $len; $idx++) {\n" .
+ gencmp1 ($t->[2], $toplevel, "$path\[$idx]") .
+ "}\n");
+ } elsif ($t->[0] eq "str") {
+ my $sep = length $path == 0 ? "" : ".";
+ my $tmp = "";
+ for (my $i = 2; $i < @$t; $i++) {
+ my ($name, $st) = @{$t->[$i]};
+ $tmp .= gencmp1 ($st, $toplevel, "$path$sep$name");
+ }
+ return $tmp;
+ } elsif ($t->[0] eq "uni") { # uni name disctype hasdef case...
+ my $tmp = "if ($toplevel.$path._d != b->$path._d) abort ();\n";
+ my $hasdef = $t->[3];
+ $tmp .= "switch ($toplevel.$path._d) {\n";
+ for (my $i = 4; $i < @$t; $i++) {
+ my ($name, $st) = @{$t->[$i]};
+ my $discval = $i - 4;
+ $discval = "'".chr ($discval + ord ("A"))."'" if $t->[2] eq "u0";
+ $tmp .= ($i == @$t && $hasdef) ? " default:\n" : " case $discval:\n";
+ $tmp .= gencmp1 ($st, $toplevel, "$path._u.$name");
+ $tmp .= "break;\n";
+ }
+ $tmp .= "}\n";
+ return $tmp;
+ } else {
+ die;
+ }
+}
+
+sub genidltd {
+ my ($t) = @_;
+ my @out = ();
+ my $res = genidl1td ("", \@out, $t);
+ return (join "", @out) . $res . "#pragma keylist $t->[1]\n//------------\n";
+};
+
+sub genidl1 {
+ my ($ind, $out, $name, $t) = @_;
+ my $res = "";
+ if ($t->[0] =~ /^u(\d+)$/) {
+ $res = "${ind}$idltype[$1] $name;\n";
+ } elsif ($t->[0] eq "seq") {
+ push @$out, genidl1td ("", $out, $t);
+ $res = "${ind}$t->[1] $name;\n";
+ } elsif ($t->[0] eq "ary") {
+ if ($t->[2]->[0] =~ /^u(\d+)$/) {
+ $res = "${ind}$idltype[$1] ${name}[$t->[3]];\n";
+ } else {
+ push @$out, genidl1td ("", $out, $t->[2]);
+ $res = "${ind}$t->[2]->[1] ${name}[$t->[3]];\n";
+ }
+ } elsif ($t->[0] eq "str") {
+ push @$out, genidl1td ("", $out, $t);
+ $res = "${ind}$t->[1] $name;\n";
+ } elsif ($t->[0] eq "uni") {
+ push @$out, genidl1td ("", $out, $t);
+ $res = "${ind}$t->[1] $name;\n";
+ } else {
+ die;
+ }
+ return $res;
+}
+
+sub genidl1td {
+ my ($ind, $out, $t) = @_;
+ if ($t->[0] eq "seq") {
+ if ($t->[2]->[0] =~ /^u(\d+)$/) {
+ return "${ind}typedef sequence<$idltype[$1]> $t->[1];\n";
+ } else {
+ push @$out, genidl1td ("", $out, $t->[2]);
+ return "${ind}typedef sequence<$t->[2]->[1]> $t->[1];\n";
+ }
+ } elsif ($t->[0] eq "ary") {
+ if ($t->[2]->[0] =~ /^u(\d+)$/) {
+ return "${ind}typedef ${idltype[$1]} $t->[1]"."[$t->[3]];\n";
+ } else {
+ push @$out, genidl1td ("", $out, $t->[2]);
+ return "${ind}typedef $t->[2]->[1] $t->[1]"."[$t->[3]];\n";
+ }
+ } elsif ($t->[0] eq "str") {
+ my $res = "struct $t->[1] {\n";
+ for (my $i = 2; $i < @$t; $i++) {
+ $res .= genidl1 ($ind." ", $out, @{$t->[$i]});
+ }
+ $res .= "};\n";
+ return $res;
+ } elsif ($t->[0] eq "uni") {
+ my $hasdef = $t->[3];
+ die unless $t->[2] =~ /^u([0-2])$/;
+ my $res = "${ind}union $t->[1] switch ($idltype_unidisc[$1]) {\n";
+ for (my $i = 4; $i < @$t; $i++) {
+ my $discval = $i - 4;
+ $discval = "'".(chr ($discval + ord ("A")))."'" if $t->[2] eq "u0";
+ $res .= ($i == @$t && $hasdef) ? "$ind default: " : "$ind case $discval: ";
+ $res .= genidl1 ($ind." ", $out, @{$t->[$i]});
+ }
+ $res .= "};\n";
+ return $res;
+ } else {
+ die;
+ }
+};
+
+sub genu0 { return ["u0"]; }
+sub genu1 { return ["u1"]; }
+sub genu2 { return ["u2"]; }
+sub genu3 { return ["u3"]; }
+sub genu4 { return ["u4"]; }
+sub genseq { return ["seq", nextident (), gentype ($_[0] + 1, @probs)]; }
+sub genary { return ["ary", nextident (), gentype ($_[0] + 1, @noaryprobs), 1 + int (rand (4))]; }
+sub genstr {
+ my @ts = ("str", nextident ());
+ my $n = 1 + int (rand (4));
+ push @ts, [ nextident (), gentype ($_[0] + 1, @probs) ] while $n--;
+ return \@ts;
+}
+sub genuni {
+ my @ts = ("uni", nextident (), "u".(int (rand (2))), int (rand (1))); # uni name disctype hasdef case...
+ my $ncases = 1 + int (rand (4));
+ push @ts, [ nextident (), gentype ($_[0] + 1, @unicaseprobs) ] while $ncases--;
+ return \@ts;
+}
+
+sub gentype {
+ my $t = choosetype (@_);
+ my $f = "gen$t";
+ return &$f (@_);
+}
+
+sub choosetype {
+ my ($lev, @probs) = @_;
+ my $r = rand ($_[0] == 4 ? $probs[3] : $probs[$#probs]);
+ my $i;
+ for ($i = 0; $i < $#probs; $i++) {
+ last if $r < $probs[$i];
+ }
+ return $types[$i];
+}
+
+sub nextident {
+ return $nextident++;
+}
diff --git a/src/core/xtests/initsampledeliv/CMakeLists.txt b/src/core/xtests/initsampledeliv/CMakeLists.txt
new file mode 100644
index 0000000..e4804fa
--- /dev/null
+++ b/src/core/xtests/initsampledeliv/CMakeLists.txt
@@ -0,0 +1,20 @@
+#
+# Copyright(c) 2019 ADLINK Technology Limited and others
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0 which is available at
+# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+# v. 1.0 which is available at
+# http://www.eclipse.org/org/documents/edl-v10.php.
+#
+# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+#
+cmake_minimum_required(VERSION 3.5)
+
+idlc_generate(InitSampleDeliv_lib InitSampleDelivData.idl)
+
+add_executable(InitSampleDelivPub publisher.c)
+add_executable(InitSampleDelivSub subscriber.c)
+
+target_link_libraries(InitSampleDelivPub InitSampleDeliv_lib ddsc)
+target_link_libraries(InitSampleDelivSub InitSampleDeliv_lib ddsc)
diff --git a/src/core/xtests/initsampledeliv/InitSampleDelivData.idl b/src/core/xtests/initsampledeliv/InitSampleDelivData.idl
new file mode 100644
index 0000000..1064232
--- /dev/null
+++ b/src/core/xtests/initsampledeliv/InitSampleDelivData.idl
@@ -0,0 +1,19 @@
+// Copyright(c) 2019 ADLINK Technology Limited and others
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+// v. 1.0 which is available at
+// http://www.eclipse.org/org/documents/edl-v10.php.
+//
+// SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+
+struct Msg {
+ long keyval;
+ long seq;
+ long tldepth;
+ long final_seq;
+ long seq_at_match[2];
+};
+
+#pragma keylist Msg keyval
diff --git a/src/core/xtests/initsampledeliv/publisher.c b/src/core/xtests/initsampledeliv/publisher.c
new file mode 100644
index 0000000..a690c16
--- /dev/null
+++ b/src/core/xtests/initsampledeliv/publisher.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright(c) 2019 ADLINK Technology Limited and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+ * v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+#include "dds/dds.h"
+#include "dds/ddsrt/atomics.h"
+#include "InitSampleDelivData.h"
+#include
+#include
+#include
+
+static void oops (const char *file, int line)
+{
+ fflush (stdout);
+ fprintf (stderr, "%s:%d\n", file, line);
+ abort ();
+}
+
+#define oops() oops(__FILE__, __LINE__)
+
+static void on_pub_matched (dds_entity_t wr, const dds_publication_matched_status_t st, void *varg)
+{
+ ddsrt_atomic_uint32_t *new_readers = varg;
+ dds_sample_info_t info;
+ void *raw = NULL;
+ dds_entity_t rd;
+ printf ("pubmatched\n");
+ if ((rd = dds_create_reader (dds_get_participant (wr), DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL)) < 0)
+ oops ();
+ if (dds_read_instance (rd, &raw, &info, 1, 1, st.last_subscription_handle) != 1)
+ oops ();
+ const dds_builtintopic_endpoint_t *sample = raw;
+ /* in our test the user data must be present */
+ void *ud;
+ size_t udsz;
+ if (!dds_qget_userdata (sample->qos, &ud, &udsz))
+ oops ();
+ int rdid = atoi (ud);
+ if (rdid < 0 || rdid > 31)
+ oops ();
+ printf ("pubmatched: %d\n", rdid);
+ fflush (stdout);
+ ddsrt_atomic_or32 (new_readers, UINT32_C (1) << rdid);
+ dds_free (ud);
+ dds_return_loan (rd, &raw, 1);
+}
+
+static uint32_t get_publication_matched_count (dds_entity_t wr)
+{
+ dds_publication_matched_status_t status;
+ if (dds_get_publication_matched_status (wr, &status) < 0)
+ oops ();
+ return status.current_count;
+}
+
+int main (int argc, char ** argv)
+{
+ dds_entity_t ppant;
+ dds_entity_t tp;
+ dds_entity_t wr;
+ dds_qos_t *qos;
+ ddsrt_atomic_uint32_t newreaders = DDSRT_ATOMIC_UINT32_INIT (0);
+ int opt;
+ bool flag_prewrite = false;
+ bool flag_translocal = false;
+ const int32_t tlhist = 10;
+
+ while ((opt = getopt (argc, argv, "tp")) != EOF)
+ {
+ switch (opt)
+ {
+ case 't':
+ flag_translocal = true;
+ break;
+ case 'p':
+ flag_prewrite = true;
+ break;
+ default:
+ fprintf (stderr, "usage error: see source code\n");
+ exit (2);
+ }
+ }
+
+ if ((ppant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL)) < 0)
+ oops ();
+
+ qos = dds_create_qos ();
+ dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_SECS (10));
+ dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL);
+ if ((tp = dds_create_topic (ppant, &Msg_desc, "Msg", qos, NULL)) < 0)
+ oops ();
+
+ /* Writer has overrides for history, durability */
+ dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0);
+ dds_qset_durability (qos, flag_translocal ? DDS_DURABILITY_TRANSIENT_LOCAL : DDS_DURABILITY_VOLATILE);
+ dds_qset_durability_service (qos, 0, DDS_HISTORY_KEEP_LAST, tlhist, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED);
+
+ dds_listener_t *list = dds_create_listener (&newreaders);
+ dds_lset_publication_matched (list, on_pub_matched);
+ if ((wr = dds_create_writer (ppant, tp, qos, list)) < 0)
+ oops ();
+ dds_delete_listener (list);
+ dds_delete_qos (qos);
+
+ Msg sample = {
+ .keyval = 0,
+ .seq = 1,
+ .tldepth = tlhist,
+ .final_seq = 30,
+ .seq_at_match = { 0, 0 }
+ };
+ dds_time_t tlast = 0, tnewrd = 0;
+ while (sample.seq <= sample.final_seq)
+ {
+ uint32_t newrd = ddsrt_atomic_and32_ov (&newreaders, 0);
+ for (uint32_t i = 0; i < 32; i++)
+ {
+ if (newrd & (UINT32_C (1) << i))
+ {
+ if (i >= (uint32_t) (sizeof (sample.seq_at_match) / sizeof (sample.seq_at_match[0])))
+ oops ();
+ if (sample.seq_at_match[i] != 0)
+ oops ();
+ sample.seq_at_match[i] = sample.seq;
+ tnewrd = dds_time ();
+ printf ("%d.%09d newreader %d: start seq %d\n", (int) (tnewrd / DDS_NSECS_IN_SEC), (int) (tnewrd % DDS_NSECS_IN_SEC), (int) i, (int) sample.seq_at_match[i]);
+ fflush (stdout);
+ }
+ }
+
+ if (get_publication_matched_count (wr) || (flag_prewrite && sample.seq <= tlhist + 1))
+ {
+ dds_time_t tnow = dds_time ();
+ if (tnow - tlast > DDS_MSECS (100) || newrd)
+ {
+ if (dds_write (wr, &sample) < 0)
+ oops ();
+ sample.seq++;
+ tlast = tnow;
+ if (sample.seq > sample.final_seq)
+ {
+ tnow = dds_time ();
+ printf ("%d.%09d done writing\n", (int) (tnow / DDS_NSECS_IN_SEC), (int) (tnow % DDS_NSECS_IN_SEC));
+ fflush (stdout);
+ }
+ }
+ }
+
+ dds_sleepfor (DDS_MSECS (1));
+ }
+
+ dds_sleepfor (DDS_MSECS (100));
+ dds_wait_for_acks (wr, DDS_INFINITY);
+ dds_delete (ppant);
+ return 0;
+}
diff --git a/src/core/xtests/initsampledeliv/runtest b/src/core/xtests/initsampledeliv/runtest
new file mode 100644
index 0000000..9ba03b8
--- /dev/null
+++ b/src/core/xtests/initsampledeliv/runtest
@@ -0,0 +1,46 @@
+#!/bin/bash
+#
+# Copyright(c) 2019 ADLINK Technology Limited and others
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0 which is available at
+# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+# v. 1.0 which is available at
+# http://www.eclipse.org/org/documents/edl-v10.php.
+#
+# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+#
+ok=true
+for sd in "" "-d1" "-d12" ; do
+ for st in "" "-t" ; do
+ for sT in "" "-T" ; do
+ if [ "$st" = "-t" -o "$sT" = "-T" ] ; then
+ maybeV=false
+ else
+ maybeV=true
+ fi
+ for sw in "" "-w" ; do
+ for pt in "" "-t" ; do
+ for pp in "" "-p" ; do
+ if [ "$sT" = "" -a "$sd" != "" -a \( "$pt" = "-t" -o $maybeV = true \) ] ; then
+ if $ok ; then
+ echo "bin/InitSampleDelivSub $sw $sd $st $sT & bin/InitSampleDelivPub $pt $pp"
+ bin/InitSampleDelivSub $sw $sd $st $sT & spid=$!
+ bin/InitSampleDelivPub $pt $pp
+ wait $spid || ok=false
+ fi
+ if $ok ; then
+ echo "bin/InitSampleDelivPub $pt $pp & sleep 2 ; bin/InitSampleDelivSub $sw $sd $st $sT "
+ bin/InitSampleDelivPub $pt $pp & ppid=$!
+ sleep 2
+ bin/InitSampleDelivSub $sw $sd $st $sT & spid=$!
+ wait $spid || ok=false
+ wait
+ fi
+ fi
+ done
+ done
+ done
+ done
+ done
+done
diff --git a/src/core/xtests/initsampledeliv/subscriber.c b/src/core/xtests/initsampledeliv/subscriber.c
new file mode 100644
index 0000000..1cb6ad6
--- /dev/null
+++ b/src/core/xtests/initsampledeliv/subscriber.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright(c) 2019 ADLINK Technology Limited and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+ * v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+#include "dds/dds.h"
+#include "InitSampleDelivData.h"
+#include
+#include
+#include
+#include
+#include
+
+static void oops (const char *file, int line)
+{
+ fflush (stdout);
+ fprintf (stderr, "%s:%d\n", file, line);
+ abort ();
+}
+
+#define oops() oops(__FILE__, __LINE__)
+
+static void wait_for_writer (dds_entity_t ppant)
+{
+ dds_entity_t rd;
+ dds_sample_info_t info;
+ void *raw = NULL;
+ int32_t n;
+ if ((rd = dds_create_reader (ppant, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, NULL, NULL)) < 0)
+ oops ();
+ bool done = false;
+ do {
+ dds_sleepfor (DDS_MSECS (100));
+ while ((n = dds_take (rd, &raw, &info, 1, 1)) == 1)
+ {
+ const dds_builtintopic_endpoint_t *sample = raw;
+ if (strcmp (sample->topic_name, "Msg") == 0)
+ done = true;
+ dds_return_loan (rd, &raw, n);
+ }
+ if (n < 0) oops ();
+ } while (!done);
+ dds_delete (rd);
+}
+
+static uint32_t get_subscription_matched_count (dds_entity_t rd)
+{
+ dds_subscription_matched_status_t status;
+ if (dds_get_subscription_matched_status (rd, &status) < 0)
+ oops ();
+ return status.current_count;
+}
+
+int main (int argc, char ** argv)
+{
+ dds_entity_t ppant;
+ dds_entity_t tp;
+ dds_entity_t rd[2] = { 0, 0 };
+ dds_qos_t *qos;
+ int opt;
+ bool flag_wait = false;
+ bool flag_translocal[sizeof (rd) / sizeof (rd[0])] = { false };
+ int flag_create_2nd_rd = -1;
+
+ while ((opt = getopt (argc, argv, "d:tTw")) != EOF)
+ {
+ switch (opt)
+ {
+ case 'd':
+ flag_create_2nd_rd = atoi (optarg);
+ break;
+ case 't':
+ flag_translocal[0] = true;
+ break;
+ case 'T':
+ flag_translocal[1] = true;
+ break;
+ case 'w':
+ flag_wait = true;
+ break;
+ default:
+ fprintf (stderr, "usage error: see source code\n");
+ exit (2);
+ }
+ }
+
+ if ((ppant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL)) < 0)
+ oops ();
+
+ qos = dds_create_qos ();
+ dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_SECS (10));
+ dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL);
+ if ((tp = dds_create_topic (ppant, &Msg_desc, "Msg", qos, NULL)) < 0)
+ oops ();
+
+ if (flag_wait)
+ {
+ printf ("waiting for writer ...\n");
+ fflush (stdout);
+ wait_for_writer (ppant);
+ printf ("writer seen; giving it some time to discover us and publish data ...\n");
+ fflush (stdout);
+ dds_sleepfor (DDS_SECS (1));
+ printf ("continuing ...\n");
+ fflush (stdout);
+ }
+
+ /* Reader has overrides for history, durability */
+ dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0);
+ dds_qset_durability (qos, flag_translocal[0] ? DDS_DURABILITY_TRANSIENT_LOCAL : DDS_DURABILITY_VOLATILE);
+ dds_qset_userdata (qos, "0", 1);
+ if ((rd[0] = dds_create_reader (ppant, tp, qos, NULL)) < 0)
+ oops ();
+
+ dds_qset_durability (qos, flag_translocal[1] ? DDS_DURABILITY_TRANSIENT_LOCAL : DDS_DURABILITY_VOLATILE);
+ dds_qset_userdata (qos, "1", 1);
+
+ int32_t firstmsg[2] = { 0 };
+ int32_t prevmsg[2] = { 0 };
+ int32_t seqatmatch[2] = { 0 };
+ int32_t tldepth = 0;
+ int32_t endmsg = 0;
+ while (prevmsg[0] == 0 || get_subscription_matched_count (rd[0]) > 0)
+ {
+ void *raw = NULL;
+ dds_sample_info_t info;
+ int32_t n;
+ for (int i = 0; i < 2 && rd[i]; i++)
+ {
+ if ((n = dds_take (rd[i], &raw, &info, 1, 1)) < 0)
+ oops ();
+ else if (n > 0 && info.valid_data)
+ {
+ const Msg *msg = raw;
+ if (prevmsg[i] == 0)
+ {
+ /* have to postpone first seq# check for transient-local data because the limit
+ t-l history means the first sample we read may have an arbitrary sequence
+ that antedated the matching */
+ printf ("reader %d: first seq %d\n", i, (int) msg->seq);
+ fflush (stdout);
+ firstmsg[i] = msg->seq;
+ }
+ else if (msg->seq != prevmsg[i] + 1)
+ {
+ printf ("reader %d: received %d, previous %d\n", i, (int) msg->seq, (int) prevmsg[i]);
+ oops ();
+ }
+ prevmsg[i] = msg->seq;
+ endmsg = msg->final_seq;
+ tldepth = msg->tldepth;
+ if (seqatmatch[i] == 0)
+ seqatmatch[i] = msg->seq_at_match[i];
+ dds_return_loan (rd[i], &raw, n);
+ }
+ }
+ if (rd[1] == 0 && prevmsg[0] == flag_create_2nd_rd)
+ {
+ if ((rd[1] = dds_create_reader (ppant, tp, qos, NULL)) < 0)
+ oops ();
+ }
+ dds_sleepfor (DDS_MSECS (10));
+ }
+ if (tldepth == 0 || endmsg == 0)
+ oops ();
+ for (int i = 0; i < 2; i++)
+ {
+ if (rd[i] == 0)
+ continue;
+ if (prevmsg[i] != endmsg)
+ oops ();
+ int32_t refseq;
+ if (!flag_translocal[i])
+ refseq = seqatmatch[i];
+ else if (seqatmatch[i] <= tldepth)
+ refseq = 1;
+ else
+ refseq = seqatmatch[i] - tldepth;
+ if (flag_translocal[i] ? (firstmsg[i] > refseq + 1) : firstmsg[i] > refseq)
+ {
+ /* allow the rare cases where an additional sample was received for volatile data
+ (for t-l data, the publisher waits to give so the subscriber can get the data
+ in time */
+ printf ("reader %d: first seq %d but refseq %d\n", i, (int) firstmsg[i], refseq);
+ oops ();
+ }
+ }
+
+ dds_delete_qos (qos);
+ dds_delete (ppant);
+ return 0;
+}
diff --git a/src/core/xtests/rhc_torture/CMakeLists.txt b/src/core/xtests/rhc_torture/CMakeLists.txt
new file mode 100644
index 0000000..4aa3a5f
--- /dev/null
+++ b/src/core/xtests/rhc_torture/CMakeLists.txt
@@ -0,0 +1,26 @@
+#
+# Copyright(c) 2019 ADLINK Technology Limited and others
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0 which is available at
+# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+# v. 1.0 which is available at
+# http://www.eclipse.org/org/documents/edl-v10.php.
+#
+# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+#
+idlc_generate(RhcTypes RhcTypes.idl)
+
+add_executable(rhc_torture rhc_torture.c)
+
+target_include_directories(
+ rhc_torture PRIVATE
+ "$"
+ "$")
+
+target_link_libraries(rhc_torture RhcTypes ddsc)
+
+add_test(
+ NAME rhc_torture
+ COMMAND rhc_torture 314159265 0 5000 0)
+set_property(TEST rhc_torture PROPERTY TIMEOUT 20)
diff --git a/src/core/xtests/RhcTypes.idl b/src/core/xtests/rhc_torture/RhcTypes.idl
similarity index 100%
rename from src/core/xtests/RhcTypes.idl
rename to src/core/xtests/rhc_torture/RhcTypes.idl
diff --git a/src/core/xtests/rhc_torture.c b/src/core/xtests/rhc_torture/rhc_torture.c
similarity index 86%
rename from src/core/xtests/rhc_torture.c
rename to src/core/xtests/rhc_torture/rhc_torture.c
index 245d057..5dba7b4 100644
--- a/src/core/xtests/rhc_torture.c
+++ b/src/core/xtests/rhc_torture/rhc_torture.c
@@ -31,6 +31,7 @@
#include "dds/ddsi/ddsi_serdata.h"
#include "dds__topic.h"
#include "dds__rhc.h"
+#include "dds__rhc_default.h"
#include "dds/ddsi/ddsi_iid.h"
#include "RhcTypes.h"
@@ -103,13 +104,14 @@ static struct ddsi_serdata *mkkeysample (int32_t keyval, unsigned statusinfo)
return sd;
}
-static uint64_t store (struct rhc *rhc, struct proxy_writer *wr, struct ddsi_serdata *sd, bool print)
+static uint64_t store (struct ddsi_tkmap *tkmap, struct dds_rhc *rhc, struct proxy_writer *wr, struct ddsi_serdata *sd, bool print)
{
/* beware: unrefs sd */
struct ddsi_tkmap_instance *tk;
struct proxy_writer_info pwr_info;
- thread_state_awake (lookup_thread_state ());
- tk = ddsi_tkmap_lookup_instance_ref(sd);
+ /* single-domain application ... so domain won't change */
+ thread_state_awake_domain_ok (lookup_thread_state ());
+ tk = ddsi_tkmap_lookup_instance_ref (tkmap, sd);
uint64_t iid = tk->m_iid;
if (print)
{
@@ -131,23 +133,23 @@ static uint64_t store (struct rhc *rhc, struct proxy_writer *wr, struct ddsi_ser
pwr_info.iid = wr->e.iid;
pwr_info.ownership_strength = wr->c.xqos->ownership_strength.value;
dds_rhc_store (rhc, &pwr_info, sd, tk);
- ddsi_tkmap_instance_unref (tk);
+ ddsi_tkmap_instance_unref (tkmap, tk);
thread_state_asleep (lookup_thread_state ());
ddsi_serdata_unref (sd);
return iid;
}
-static struct proxy_writer *mkwr (bool auto_dispose)
+static struct proxy_writer *mkwr (const struct q_globals *gv, bool auto_dispose)
{
struct proxy_writer *pwr;
- struct nn_xqos *xqos;
+ struct dds_qos *xqos;
uint64_t wr_iid;
pwr = ddsrt_malloc (sizeof (*pwr));
xqos = ddsrt_malloc (sizeof (*xqos));
wr_iid = ddsi_iid_gen ();
memset (pwr, 0, sizeof (*pwr));
nn_xqos_init_empty (xqos);
- nn_xqos_mergein_missing (xqos, &gv.default_xqos_wr);
+ nn_xqos_mergein_missing (xqos, &gv->default_xqos_wr, ~(uint64_t)0);
xqos->ownership_strength.value = 0;
xqos->writer_data_lifecycle.autodispose_unregistered_instances = auto_dispose;
pwr->e.iid = wr_iid;
@@ -161,26 +163,26 @@ static void fwr (struct proxy_writer *wr)
free (wr);
}
-static struct rhc *mkrhc (dds_reader *rd, nn_history_kind_t hk, int32_t hdepth, nn_destination_order_kind_t dok)
+static struct dds_rhc *mkrhc (struct q_globals *gv, dds_reader *rd, dds_history_kind_t hk, int32_t hdepth, dds_destination_order_kind_t dok)
{
- struct rhc *rhc;
- nn_xqos_t rqos;
+ struct dds_rhc *rhc;
+ dds_qos_t rqos;
nn_xqos_init_empty (&rqos);
rqos.present |= QP_HISTORY | QP_DESTINATION_ORDER;
rqos.history.kind = hk;
rqos.history.depth = hdepth;
rqos.destination_order.kind = dok;
- nn_xqos_mergein_missing (&rqos, &gv.default_xqos_rd);
- thread_state_awake (lookup_thread_state ());
- rhc = dds_rhc_new (rd, mdtopic);
+ nn_xqos_mergein_missing (&rqos, &gv->default_xqos_rd, ~(uint64_t)0);
+ thread_state_awake_domain_ok (lookup_thread_state ());
+ rhc = dds_rhc_default_new_xchecks (rd, gv, mdtopic, true);
dds_rhc_set_qos(rhc, &rqos);
thread_state_asleep (lookup_thread_state ());
return rhc;
}
-static void frhc (struct rhc *rhc)
+static void frhc (struct dds_rhc *rhc)
{
- thread_state_awake (lookup_thread_state ());
+ thread_state_awake_domain_ok (lookup_thread_state ());
dds_rhc_free (rhc);
thread_state_asleep (lookup_thread_state ());
}
@@ -281,14 +283,14 @@ static void print_seq (int n, const dds_sample_info_t *iseq, const RhcTypes_T *m
}
}
-static void rdtkcond (struct rhc *rhc, dds_readcond *cond, const struct check *chk, bool print, int max, const char *opname, int (*op) (struct rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond), uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2])
+static void rdtkcond (struct dds_rhc *rhc, dds_readcond *cond, const struct check *chk, bool print, int max, const char *opname, int (*op) (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond), uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2])
{
int cnt;
if (print)
printf ("%s:\n", opname);
- thread_state_awake (lookup_thread_state ());
+ thread_state_awake_domain_ok (lookup_thread_state ());
cnt = op (rhc, true, rres_ptrs, rres_iseq, (max <= 0) ? (uint32_t) (sizeof (rres_iseq) / sizeof (rres_iseq[0])) : (uint32_t) max, cond ? NO_STATE_MASK_SET : (DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE), 0, cond);
thread_state_asleep (lookup_thread_state ());
if (max > 0 && cnt > max) {
@@ -379,12 +381,12 @@ static void rdtkcond (struct rhc *rhc, dds_readcond *cond, const struct check *c
}
}
-static void rdall (struct rhc *rhc, const struct check *chk, bool print, uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2])
+static void rdall (struct dds_rhc *rhc, const struct check *chk, bool print, uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2])
{
rdtkcond (rhc, NULL, chk, print, 0, "READ ALL", dds_rhc_read, states_seen);
}
-static void tkall (struct rhc *rhc, const struct check *chk, bool print, uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2])
+static void tkall (struct dds_rhc *rhc, const struct check *chk, bool print, uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2])
{
rdtkcond (rhc, NULL, chk, print, 0, "TAKE ALL", dds_rhc_take, states_seen);
}
@@ -440,7 +442,7 @@ static void print_condmask (char *buf, size_t bufsz, const dds_readcond *cond)
snprintf (buf + pos, bufsz - pos, "]");
}
-static void rdcond (struct rhc *rhc, dds_readcond *cond, const struct check *chk, int max, bool print, uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2])
+static void rdcond (struct dds_rhc *rhc, dds_readcond *cond, const struct check *chk, int max, bool print, uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2])
{
char buf[100];
int pos;
@@ -449,7 +451,7 @@ static void rdcond (struct rhc *rhc, dds_readcond *cond, const struct check *chk
rdtkcond (rhc, cond, chk, print, max, buf, dds_rhc_read, states_seen);
}
-static void tkcond (struct rhc *rhc, dds_readcond *cond, const struct check *chk, int max, bool print, uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2])
+static void tkcond (struct dds_rhc *rhc, dds_readcond *cond, const struct check *chk, int max, bool print, uint32_t states_seen[STATIC_ARRAY_DIM 2*2*3][2])
{
char buf[100];
int pos;
@@ -467,10 +469,10 @@ static void wait_gc_cycle_impl (struct gcreq *gcreq)
gcreq_free (gcreq);
}
-static void wait_gc_cycle (void)
+static void wait_gc_cycle (struct gcreq_queue *gcreq_queue)
{
/* only single-threaded for now */
- struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, wait_gc_cycle_impl);
+ struct gcreq *gcreq = gcreq_new (gcreq_queue, wait_gc_cycle_impl);
#ifndef NDEBUG
ddsrt_mutex_lock (&wait_gc_cycle_lock);
assert (wait_gc_cycle_trig == 0);
@@ -530,6 +532,17 @@ static dds_entity_t readcond_wrapper (dds_entity_t reader, uint32_t mask, dds_qu
return dds_create_readcondition (reader, mask);
}
+static struct q_globals *get_gv (dds_entity_t e)
+{
+ struct q_globals *gv;
+ dds_entity *x;
+ if (dds_entity_pin (e, &x) < 0)
+ abort ();
+ gv = &x->m_domain->gv;
+ dds_entity_unpin (x);
+ return gv;
+}
+
static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, dds_entity_t (*create_cond) (dds_entity_t reader, uint32_t mask, dds_querycondition_filter_fn filter), dds_querycondition_filter_fn filter0, dds_querycondition_filter_fn filter1, bool print)
{
dds_qos_t *qos = dds_create_qos ();
@@ -539,17 +552,20 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count,
dds_entity_t rd[] = { dds_create_reader (pp, tp, qos, NULL), dds_create_reader (pp, tp, qos, NULL) };
const size_t nrd = sizeof (rd) / sizeof (rd[0]);
dds_delete_qos (qos);
- struct rhc *rhc[sizeof (rd) / sizeof (rd[0])];
+ struct dds_rhc *rhc[sizeof (rd) / sizeof (rd[0])];
for (size_t i = 0; i < sizeof (rd) / sizeof (rd[0]); i++)
{
struct dds_entity *x;
if (dds_entity_lock (rd[i], DDS_KIND_READER, &x) < 0)
abort ();
dds_reader *rdp = (dds_reader *) x;
- rhc[i] = rdp->m_rd->rhc;
+ rhc[i] = rdp->m_rhc;
dds_entity_unlock (x);
}
- struct proxy_writer *wr[] = { mkwr (0), mkwr (1), mkwr (1) };
+
+ const struct q_globals *gv = get_gv (pp);
+ struct ddsi_tkmap *tkmap = gv->m_tkmap;
+ struct proxy_writer *wr[] = { mkwr (gv, 0), mkwr (gv, 1), mkwr (gv, 1) };
static const uint32_t stab[] = {
DDS_READ_SAMPLE_STATE, DDS_NOT_READ_SAMPLE_STATE,
@@ -699,42 +715,42 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count,
case 0: { /* wr */
struct ddsi_serdata *s = mksample (keyval, 0);
for (size_t k = 0; k < nrd; k++)
- store (rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0);
+ store (tkmap, rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0);
ddsi_serdata_unref (s);
break;
}
case 1: { /* wr disp */
struct ddsi_serdata *s = mksample (keyval, NN_STATUSINFO_DISPOSE);
for (size_t k = 0; k < nrd; k++)
- store (rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0);
+ store (tkmap, rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0);
ddsi_serdata_unref (s);
break;
}
case 2: { /* disp */
struct ddsi_serdata *s = mkkeysample (keyval, NN_STATUSINFO_DISPOSE);
for (size_t k = 0; k < nrd; k++)
- store (rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0);
+ store (tkmap, rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0);
ddsi_serdata_unref (s);
break;
}
case 3: { /* unreg */
struct ddsi_serdata *s = mkkeysample (keyval, NN_STATUSINFO_UNREGISTER);
for (size_t k = 0; k < nrd; k++)
- store (rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0);
+ store (tkmap, rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0);
ddsi_serdata_unref (s);
break;
}
case 4: { /* disp unreg */
struct ddsi_serdata *s = mkkeysample (keyval, NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER);
for (size_t k = 0; k < nrd; k++)
- store (rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0);
+ store (tkmap, rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0);
ddsi_serdata_unref (s);
break;
}
case 5: { /* wr disp unreg */
struct ddsi_serdata *s = mksample (keyval, NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER);
for (size_t k = 0; k < nrd; k++)
- store (rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0);
+ store (tkmap, rhc[k], wr[which], ddsi_serdata_ref (s), print && k == 0);
ddsi_serdata_unref (s);
break;
}
@@ -765,7 +781,7 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count,
break;
}
case 11: {
- thread_state_awake (lookup_thread_state ());
+ thread_state_awake_domain_ok (lookup_thread_state ());
struct proxy_writer_info wr_info;
wr_info.auto_dispose = wr[which]->c.xqos->writer_data_lifecycle.autodispose_unregistered_instances;
wr_info.guid = wr[which]->e.guid;
@@ -779,7 +795,7 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count,
}
if ((i % 200) == 0)
- wait_gc_cycle ();
+ wait_gc_cycle (gv->gcreq_queue);
}
for (size_t oper = 0; oper < sizeof (opcount) / sizeof (opcount[0]); oper++)
@@ -837,6 +853,7 @@ int main (int argc, char **argv)
tref_dds = dds_time();
mainthread = lookup_thread_state ();
+ assert (ddsrt_atomic_ldvoidp (&mainthread->gv) != NULL);
{
struct dds_entity *x;
if (dds_entity_lock(tp, DDS_KIND_TOPIC, &x) < 0) abort();
@@ -846,20 +863,22 @@ int main (int argc, char **argv)
if (0 >= first)
{
+ struct q_globals *gv = get_gv (pp);
+ struct ddsi_tkmap *tkmap = gv->m_tkmap;
if (print)
printf ("************* 0 *************\n");
- struct rhc *rhc = mkrhc (NULL, NN_KEEP_LAST_HISTORY_QOS, 1, NN_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS);
- struct proxy_writer *wr0 = mkwr (1);
+ struct dds_rhc *rhc = mkrhc (gv, NULL, DDS_HISTORY_KEEP_LAST, 1, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP);
+ struct proxy_writer *wr0 = mkwr (gv, 1);
uint64_t iid0, iid1, iid_t;
- iid0 = store (rhc, wr0, mksample (0, 0), print);
- iid1 = store (rhc, wr0, mksample (1, NN_STATUSINFO_DISPOSE), print);
+ iid0 = store (tkmap, rhc, wr0, mksample (0, 0), print);
+ iid1 = store (tkmap, rhc, wr0, mksample (1, NN_STATUSINFO_DISPOSE), print);
const struct check c0[] = {
{ "NNA", iid0, wr0->e.iid, 0,0, 1, 0,1 },
{ "NND", iid1, wr0->e.iid, 0,0, 1, 1,2 },
{ 0, 0, 0, 0, 0, 0, 0, 0 }
};
rdall (rhc, c0, print, states_seen);
- iid_t = store (rhc, wr0, mkkeysample (0, NN_STATUSINFO_UNREGISTER), print);
+ iid_t = store (tkmap, rhc, wr0, mkkeysample (0, NN_STATUSINFO_UNREGISTER), print);
assert (iid_t == iid0);
(void)iid0;
(void)iid_t;
@@ -870,7 +889,7 @@ int main (int argc, char **argv)
{ 0, 0, 0, 0, 0, 0, 0, 0 }
};
rdall (rhc, c1, print, states_seen);
- thread_state_awake (lookup_thread_state ());
+ thread_state_awake_domain_ok (lookup_thread_state ());
struct proxy_writer_info wr0_info;
wr0_info.auto_dispose = wr0->c.xqos->writer_data_lifecycle.autodispose_unregistered_instances;
wr0_info.guid = wr0->e.guid;
@@ -892,15 +911,17 @@ int main (int argc, char **argv)
if (1 >= first)
{
+ struct q_globals *gv = get_gv (pp);
+ struct ddsi_tkmap *tkmap = gv->m_tkmap;
if (print)
printf ("************* 1 *************\n");
- struct rhc *rhc = mkrhc (NULL, NN_KEEP_LAST_HISTORY_QOS, 4, NN_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS);
- struct proxy_writer *wr[] = { mkwr (0), mkwr (0), mkwr (0) };
+ struct dds_rhc *rhc = mkrhc (gv, NULL, DDS_HISTORY_KEEP_LAST, 4, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP);
+ struct proxy_writer *wr[] = { mkwr (gv, 0), mkwr (gv, 0), mkwr (gv, 0) };
uint64_t iid0, iid_t;
int nregs = 3, isreg[] = { 1, 1, 1 };
- iid0 = store (rhc, wr[0], mksample (0, 0), print);
- iid_t = store (rhc, wr[1], mksample (0, 0), print); assert (iid0 == iid_t);
- iid_t = store (rhc, wr[2], mksample (0, 0), print); assert (iid0 == iid_t);
+ iid0 = store (tkmap, rhc, wr[0], mksample (0, 0), print);
+ iid_t = store (tkmap, rhc, wr[1], mksample (0, 0), print); assert (iid0 == iid_t);
+ iid_t = store (tkmap, rhc, wr[2], mksample (0, 0), print); assert (iid0 == iid_t);
(void)iid0;
tkall (rhc, NULL, print, states_seen);
for (int i = 0; i < 3*3 * 3*3 * 3*3 * 3*3; i++)
@@ -912,17 +933,17 @@ int main (int argc, char **argv)
switch (oper)
{
case 0:
- iid_t = store (rhc, wr[which], mksample (0, 0), print);
+ iid_t = store (tkmap, rhc, wr[which], mksample (0, 0), print);
if (!isreg[which]) { nregs++; isreg[which] = 1; }
break;
case 1:
- iid_t = store (rhc, wr[which], mkkeysample (0, NN_STATUSINFO_DISPOSE), print);
+ iid_t = store (tkmap, rhc, wr[which], mkkeysample (0, NN_STATUSINFO_DISPOSE), print);
if (!isreg[which]) { nregs++; isreg[which] = 1; }
break;
case 2:
if (nregs > 1 || !isreg[which])
{
- iid_t = store (rhc, wr[which], mkkeysample (0, NN_STATUSINFO_UNREGISTER), print);
+ iid_t = store (tkmap, rhc, wr[which], mkkeysample (0, NN_STATUSINFO_UNREGISTER), print);
if (isreg[which]) { isreg[which] = 0; nregs--; }
}
break;
@@ -931,13 +952,13 @@ int main (int argc, char **argv)
}
}
tkall (rhc, 0, print, states_seen);
- wait_gc_cycle ();
+ wait_gc_cycle (gv->gcreq_queue);
assert (nregs > 0);
for (int i = 0; i < 3; i++)
{
if (isreg[i])
{
- iid_t = store (rhc, wr[i], mkkeysample (0, NN_STATUSINFO_UNREGISTER), print);
+ iid_t = store (tkmap, rhc, wr[i], mkkeysample (0, NN_STATUSINFO_UNREGISTER), print);
assert (iid_t == iid0);
isreg[i] = 0;
nregs--;
@@ -945,11 +966,11 @@ int main (int argc, char **argv)
}
assert (nregs == 0);
tkall (rhc, 0, print, states_seen);
- wait_gc_cycle ();
- iid_t = store (rhc, wr[0], mksample (0, 0), print);
+ wait_gc_cycle (gv->gcreq_queue);
+ iid_t = store (tkmap, rhc, wr[0], mksample (0, 0), print);
assert (iid_t != iid0);
iid0 = iid_t;
- iid_t = store (rhc, wr[0], mkkeysample (0, NN_STATUSINFO_UNREGISTER), print);
+ iid_t = store (tkmap, rhc, wr[0], mkkeysample (0, NN_STATUSINFO_UNREGISTER), print);
assert (iid_t == iid0);
frhc (rhc);
@@ -982,6 +1003,7 @@ int main (int argc, char **argv)
for (size_t i = 0; i < sizeof (rres_iseq) / sizeof (rres_iseq[0]); i++)
RhcTypes_T_free (&rres_mseq[i], DDS_FREE_CONTENTS);
+ ddsi_sertopic_unref (mdtopic);
dds_delete(pp);
return 0;
}
diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt
index 2b5171a..492136d 100644
--- a/src/ddsrt/CMakeLists.txt
+++ b/src/ddsrt/CMakeLists.txt
@@ -11,12 +11,44 @@
#
include(CheckCSourceCompiles)
include(CheckLibraryExists)
+include(GenerateDummyExportHeader)
+
+# Lightweight IP stack can be used on non-embedded targets too, but the
+# runtime must be instructed to use it instead of the native stack. Of course
+# for embedded targets there is no "native" stack and the runtime module must
+# always be instructed to use an "alternative" stack.
+option(WITH_LWIP "Use lightweight IP stack" OFF)
+option(WITH_DNS "Enable domain name lookups" ON)
+option(WITH_FREERTOS "Build for FreeRTOS" OFF)
function(check_runtime_feature SOURCE_FILE)
+ get_target_property(_defs ddsrt INTERFACE_COMPILE_DEFINITIONS)
+ foreach(_def ${_defs})
+ set(_strdefs "${_strdefs} -D${_def}")
+ endforeach()
+
+ # Generate dummy export header required by feature tests.
+ generate_dummy_export_header(
+ ddsrt
+ BASE_NAME dds
+ EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/cmake/include/dds/export.h")
+ set(_strincs "${CMAKE_CURRENT_BINARY_DIR}/cmake/include")
+
+ get_target_property(_incs ddsrt INTERFACE_INCLUDE_DIRECTORIES)
+ foreach(_inc ${_incs})
+ set(_strincs "${_strincs};${_inc}")
+ endforeach()
+
+ if(_strincs)
+ set(_strincs "-DINCLUDE_DIRECTORIES:STRING=${_strincs}")
+ endif()
+
set(expr "cmake_([_a-zA-Z0-9]+)=([_a-zA-Z0-9]+)")
try_compile(
foo "${CMAKE_BINARY_DIR}"
SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE}"
+ CMAKE_FLAGS "${_strincs}"
+ COMPILE_DEFINITIONS "${_strdefs}"
OUTPUT_VARIABLE output)
string(REGEX MATCHALL "${expr}" matches "${output}")
foreach(match ${matches})
@@ -26,7 +58,9 @@ function(check_runtime_feature SOURCE_FILE)
endforeach()
endfunction()
-if(APPLE)
+if(WITH_FREERTOS)
+ set(system_name freertos)
+elseif(APPLE)
set(system_name darwin)
else()
string(TOLOWER ${CMAKE_SYSTEM_NAME} system_name)
@@ -38,6 +72,15 @@ endif()
# ship an older version, so an interface library with public sources is used
# as a workaround for now.
add_library(ddsrt INTERFACE)
+
+foreach(opt WITH_LWIP WITH_DNS WITH_FREERTOS)
+ if(${opt})
+ target_compile_definitions(ddsrt INTERFACE DDSRT_${opt}=1)
+ else()
+ target_compile_definitions(ddsrt INTERFACE DDSRT_${opt}=0)
+ endif()
+endforeach()
+
target_include_directories(
ddsrt INTERFACE
"$"
@@ -69,7 +112,9 @@ list(APPEND headers
"${include_path}/dds/ddsrt/dynlib.h"
"${include_path}/dds/ddsrt/strtod.h"
"${include_path}/dds/ddsrt/strtol.h"
- "${include_path}/dds/ddsrt/types.h")
+ "${include_path}/dds/ddsrt/types.h"
+ "${include_path}/dds/ddsrt/countargs.h"
+ "${include_path}/dds/ddsrt/static_assert.h")
list(APPEND sources
"${source_path}/io.c"
@@ -79,10 +124,10 @@ list(APPEND sources
"${source_path}/strtol.c")
list(APPEND headers
- "${source_path}/dds/ddsrt/avl.h"
- "${source_path}/dds/ddsrt/fibheap.h"
- "${source_path}/dds/ddsrt/hopscotch.h"
- "${source_path}/dds/ddsrt/thread_pool.h")
+ "${include_path}/dds/ddsrt/avl.h"
+ "${include_path}/dds/ddsrt/fibheap.h"
+ "${include_path}/dds/ddsrt/hopscotch.h"
+ "${include_path}/dds/ddsrt/thread_pool.h")
list(APPEND sources
"${source_path}/avl.c"
@@ -103,13 +148,13 @@ list(APPEND sources
# network stack. In order to mix-and-match various compilers, architectures,
# operating systems, etc input from the build system is required.
foreach(feature atomics cdtors environ heap ifaddrs random rusage
- sockets string sync threads time md5 process dynlib)
+ sockets string sync threads time md5 process netstat dynlib)
if(EXISTS "${include_path}/dds/ddsrt/${feature}.h")
list(APPEND headers "${include_path}/dds/ddsrt/${feature}.h")
- file(GLOB
+ file(GLOB_RECURSE
files
CONFIGURE_DEPENDS
- "${include_path}/dds/ddsrt/${feature}/**.h")
+ "${include_path}/dds/ddsrt/${feature}/*.h")
list(APPEND headers ${files})
# Do not add any sources if a feature is not offered by the target. The
@@ -125,10 +170,9 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage
# feature does not exist in cmake, the feature is expected to be
# implemented for all targets.
string(TOUPPER "${feature}" feature_uc)
+ set(HAVE_${feature_uc} TRUE)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/${feature}.c")
- check_runtime_feature(cmake/${feature}.c)
- else()
- set(HAVE_${feature_uc} TRUE)
+ check_runtime_feature("cmake/${feature}.c")
endif()
if(HAVE_${feature_uc})
@@ -138,24 +182,32 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage
list(APPEND sources "${source_path}/${feature}.c")
endif()
set(system_exists FALSE)
- foreach(system ${system_name} posix)
+
+ # Allow custom implementations for a feature. e.g. lwip as opposed to
+ # windows or posix.
+ set(_system_name "${system_name}")
+ if(NOT HAVE_${feature_uc} MATCHES "[tT][rR][uU][eE]")
+ set(_system_name "${HAVE_${feature_uc}}")
+ endif()
+
+ foreach(system ${_system_name} posix)
# Headers that must remain private but are required by other runtime
# source files must be located in src//dds/ddsrt.
if(IS_DIRECTORY "${source_path}/${feature}/include")
- file(GLOB
+ file(GLOB_RECURSE
files
CONFIGURE_DEPENDS
- "${source_path}/${feature}/include/**.h")
- list(APPEND sources ${files})
+ "${source_path}/${feature}/include/*.h")
+ list(APPEND headers ${files})
target_include_directories(
ddsrt INTERFACE
"$")
endif()
if(IS_DIRECTORY "${source_path}/${feature}/${system}")
- file(GLOB
+ file(GLOB_RECURSE
files
CONFIGURE_DEPENDS
- "${source_path}/${feature}/${system}/**.c")
+ "${source_path}/${feature}/${system}/*.c")
list(APPEND sources ${files})
set(system_exists TRUE)
endif()
@@ -172,12 +224,16 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage
endif()
endforeach()
-target_sources(ddsrt INTERFACE ${sources})
+target_sources(ddsrt INTERFACE ${sources} ${headers})
-set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
-find_package(Threads REQUIRED)
-target_link_libraries(ddsrt INTERFACE Threads::Threads)
-target_link_libraries(ddsrt INTERFACE ${CMAKE_DL_LIBS})
+set(HAVE_MULTI_PROCESS ${HAVE_MULTI_PROCESS} PARENT_SCOPE)
+
+if(NOT WITH_FREERTOS)
+ set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+ find_package(Threads REQUIRED)
+ target_link_libraries(ddsrt INTERFACE Threads::Threads)
+ target_link_libraries(ddsrt INTERFACE ${CMAKE_DL_LIBS})
+endif()
if(WIN32)
target_link_libraries(ddsrt INTERFACE wsock32 ws2_32 iphlpapi bcrypt)
diff --git a/src/core/ddsc/src/dds__err.h b/src/ddsrt/cmake/ifaddrs.c
similarity index 65%
rename from src/core/ddsc/src/dds__err.h
rename to src/ddsrt/cmake/ifaddrs.c
index a54be27..aaa61f5 100644
--- a/src/core/ddsc/src/dds__err.h
+++ b/src/ddsrt/cmake/ifaddrs.c
@@ -9,20 +9,15 @@
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
-#ifndef _DDS_ERR_H_
-#define _DDS_ERR_H_
+#include "dds/ddsrt/ifaddrs.h"
-#include
-
-#include "dds/ddsrt/retcode.h"
-
-#if defined (__cplusplus)
-extern "C" {
+#if DDSRT_WITH_LWIP
+# if LWIP_SOCKET
+# error "cmake_HAVE_IFADDRS=lwip"
+# else
+# error "cmake_HAVE_IFADDRS=false"
+# endif
+#else
+# error "cmake_HAVE_IFADDRS=true"
#endif
-#define DDS_ERRNO(err) (assert(err > DDS_RETCODE_OK), -(err))
-
-#if defined (__cplusplus)
-}
-#endif
-#endif
diff --git a/src/ddsrt/cmake/netstat.c b/src/ddsrt/cmake/netstat.c
new file mode 100644
index 0000000..a64b512
--- /dev/null
+++ b/src/ddsrt/cmake/netstat.c
@@ -0,0 +1,18 @@
+/*
+ * 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 "dds/ddsrt/netstat.h"
+
+#if DDSRT_HAVE_NETSTAT
+# error "cmake_HAVE_NETSTAT=true"
+#else
+# error "cmake_HAVE_NETSTAT=false"
+#endif
diff --git a/src/ddsrt/cmake/process.c b/src/ddsrt/cmake/process.c
new file mode 100644
index 0000000..84e13f0
--- /dev/null
+++ b/src/ddsrt/cmake/process.c
@@ -0,0 +1,18 @@
+/*
+ * 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 "dds/ddsrt/process.h"
+
+#if DDSRT_HAVE_MULTI_PROCESS
+# error "cmake_HAVE_MULTI_PROCESS=true"
+#else
+# error "cmake_HAVE_MULTI_PROCESS=false"
+#endif
diff --git a/src/ddsrt/cmake/rusage.c b/src/ddsrt/cmake/rusage.c
new file mode 100644
index 0000000..c9c6154
--- /dev/null
+++ b/src/ddsrt/cmake/rusage.c
@@ -0,0 +1,19 @@
+/*
+ * 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 "dds/ddsrt/rusage.h"
+
+#if DDSRT_HAVE_RUSAGE
+# error "cmake_HAVE_RUSAGE=TRUE"
+#else
+# error "cmake_HAVE_RUSAGE=FALSE"
+#endif
+
diff --git a/src/ddsrt/include/dds/ddsrt/atomics.h b/src/ddsrt/include/dds/ddsrt/atomics.h
index 5acbed4..294085e 100644
--- a/src/ddsrt/include/dds/ddsrt/atomics.h
+++ b/src/ddsrt/include/dds/ddsrt/atomics.h
@@ -59,6 +59,34 @@ typedef ddsrt_atomic_uintptr_t ddsrt_atomic_voidp_t;
#error "Atomic operations are not supported"
#endif
+#if ! DDSRT_HAVE_ATOMIC64
+/* 64-bit atomics are not supported by all hardware, but it would be a shame not to use them when
+ they are available. That necessitates an alternative implementation when they are not, either in
+ the form of a different implementation where it is used, or as an emulation using a mutex in
+ ddsrt. It seems that the places where they'd be used end up adding a mutex, so an emulation in
+ ddsrt while being able to check whether it is supported by hardware is a sensible approach. */
+DDS_EXPORT uint64_t ddsrt_atomic_ld64 (const volatile ddsrt_atomic_uint64_t *x);
+DDS_EXPORT void ddsrt_atomic_st64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
+DDS_EXPORT void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x);
+DDS_EXPORT uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x);
+DDS_EXPORT void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x);
+DDS_EXPORT uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x);
+DDS_EXPORT void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
+DDS_EXPORT uint64_t ddsrt_atomic_add64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
+DDS_EXPORT void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
+DDS_EXPORT uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
+DDS_EXPORT void ddsrt_atomic_and64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
+DDS_EXPORT uint64_t ddsrt_atomic_and64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
+DDS_EXPORT uint64_t ddsrt_atomic_and64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
+DDS_EXPORT void ddsrt_atomic_or64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
+DDS_EXPORT uint64_t ddsrt_atomic_or64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
+DDS_EXPORT uint64_t ddsrt_atomic_or64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
+DDS_EXPORT int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_t exp, uint64_t des);
+#endif
+
+void ddsrt_atomics_init (void);
+void ddsrt_atomics_fini (void);
+
#if defined(__cplusplus)
}
#endif
diff --git a/src/ddsrt/include/dds/ddsrt/atomics/arm.h b/src/ddsrt/include/dds/ddsrt/atomics/arm.h
index 863e483..c035883 100644
--- a/src/ddsrt/include/dds/ddsrt/atomics/arm.h
+++ b/src/ddsrt/include/dds/ddsrt/atomics/arm.h
@@ -85,6 +85,9 @@ inline void *ddsrt_atomic_addvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff
inline void ddsrt_atomic_add32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
(void) ddsrt_atomic_add32_nv (x, v);
}
+inline uint32_t ddsrt_atomic_add32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
+ return ddsrt_atomic_add32_nv (x, v) - v;
+}
inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
(void) ddsrt_atomic_addptr_nv (x, v);
}
@@ -115,6 +118,9 @@ inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v
/* INC */
+inline uint32_t ddsrt_atomic_inc32_ov (volatile ddsrt_atomic_uint32_t *x) {
+ return ddsrt_atomic_add32_nv (x, 1) - 1;
+}
inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) {
return ddsrt_atomic_add32_nv (x, 1);
}
@@ -130,6 +136,9 @@ inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) {
/* DEC */
+inline uint32_t ddsrt_atomic_dec32_ov (volatile ddsrt_atomic_uint32_t *x) {
+ return ddsrt_atomic_sub32_nv (x, 1) + 1;
+}
inline uint32_t ddsrt_atomic_dec32_nv (volatile ddsrt_atomic_uint32_t *x) {
return ddsrt_atomic_sub32_nv (x, 1);
}
@@ -206,6 +215,12 @@ inline void ddsrt_atomic_orptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v)
inline void ddsrt_atomic_fence (void) {
__asm volatile ("dmb" : : : "memory");
}
+inline void ddsrt_atomic_fence_ldld (void) {
+ ddsrt_atomic_fence ();
+}
+inline void ddsrt_atomic_fence_stst (void) {
+ ddsrt_atomic_fence ();
+}
inline void ddsrt_atomic_fence_acq (void) {
ddsrt_atomic_fence ();
}
diff --git a/src/ddsrt/include/dds/ddsrt/atomics/gcc.h b/src/ddsrt/include/dds/ddsrt/atomics/gcc.h
index 4da5f29..8b6cc98 100644
--- a/src/ddsrt/include/dds/ddsrt/atomics/gcc.h
+++ b/src/ddsrt/include/dds/ddsrt/atomics/gcc.h
@@ -13,6 +13,7 @@
#define DDSRT_ATOMICS_GCC_H
#include "dds/ddsrt/misc.h"
+#include "dds/ddsrt/attributes.h"
#if defined (__cplusplus)
extern "C" {
@@ -25,19 +26,51 @@ extern "C" {
/* LD, ST */
-inline uint32_t ddsrt_atomic_ld32(const volatile ddsrt_atomic_uint32_t *x) { return x->v; }
+ddsrt_attribute_no_sanitize (("thread"))
+inline uint32_t ddsrt_atomic_ld32(const volatile ddsrt_atomic_uint32_t *x)
+{
+ return x->v;
+}
#if DDSRT_HAVE_ATOMIC64
-inline uint64_t ddsrt_atomic_ld64(const volatile ddsrt_atomic_uint64_t *x) { return x->v; }
+ddsrt_attribute_no_sanitize (("thread"))
+inline uint64_t ddsrt_atomic_ld64(const volatile ddsrt_atomic_uint64_t *x)
+{
+ return x->v;
+}
#endif
-inline uintptr_t ddsrt_atomic_ldptr(const volatile ddsrt_atomic_uintptr_t *x) { return x->v; }
-inline void *ddsrt_atomic_ldvoidp(const volatile ddsrt_atomic_voidp_t *x) { return (void *) ddsrt_atomic_ldptr(x); }
+ddsrt_attribute_no_sanitize (("thread"))
+inline uintptr_t ddsrt_atomic_ldptr(const volatile ddsrt_atomic_uintptr_t *x)
+{
+ return x->v;
+}
+ddsrt_attribute_no_sanitize (("thread"))
+inline void *ddsrt_atomic_ldvoidp(const volatile ddsrt_atomic_voidp_t *x)
+{
+ return (void *) ddsrt_atomic_ldptr(x);
+}
-inline void ddsrt_atomic_st32(volatile ddsrt_atomic_uint32_t *x, uint32_t v) { x->v = v; }
+ddsrt_attribute_no_sanitize (("thread"))
+inline void ddsrt_atomic_st32(volatile ddsrt_atomic_uint32_t *x, uint32_t v)
+{
+ x->v = v;
+}
#if DDSRT_HAVE_ATOMIC64
-inline void ddsrt_atomic_st64(volatile ddsrt_atomic_uint64_t *x, uint64_t v) { x->v = v; }
+ddsrt_attribute_no_sanitize (("thread"))
+inline void ddsrt_atomic_st64(volatile ddsrt_atomic_uint64_t *x, uint64_t v)
+{
+ x->v = v;
+}
#endif
-inline void ddsrt_atomic_stptr(volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) { x->v = v; }
-inline void ddsrt_atomic_stvoidp(volatile ddsrt_atomic_voidp_t *x, void *v) { ddsrt_atomic_stptr(x, (uintptr_t)v); }
+ddsrt_attribute_no_sanitize (("thread"))
+inline void ddsrt_atomic_stptr(volatile ddsrt_atomic_uintptr_t *x, uintptr_t v)
+{
+ x->v = v;
+}
+ddsrt_attribute_no_sanitize (("thread"))
+inline void ddsrt_atomic_stvoidp(volatile ddsrt_atomic_voidp_t *x, void *v)
+{
+ ddsrt_atomic_stptr(x, (uintptr_t)v);
+}
/* INC */
@@ -52,6 +85,9 @@ inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) {
inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) {
__sync_fetch_and_add (&x->v, 1);
}
+inline uint32_t ddsrt_atomic_inc32_ov (volatile ddsrt_atomic_uint32_t *x) {
+ return __sync_fetch_and_add (&x->v, 1);
+}
inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) {
return __sync_add_and_fetch (&x->v, 1);
}
@@ -116,6 +152,9 @@ inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v
inline void ddsrt_atomic_addvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
ddsrt_atomic_addptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
}
+inline uint32_t ddsrt_atomic_add32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
+ return __sync_fetch_and_add (&x->v, v);
+}
inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
return __sync_add_and_fetch (&x->v, v);
}
@@ -147,6 +186,9 @@ inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v
inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
ddsrt_atomic_subptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
}
+inline uint32_t ddsrt_atomic_sub32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
+ return __sync_fetch_and_sub (&x->v, v);
+}
inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
return __sync_sub_and_fetch (&x->v, v);
}
@@ -284,11 +326,24 @@ inline void ddsrt_atomic_fence_ldld (void) {
__sync_synchronize ();
#endif
}
+inline void ddsrt_atomic_fence_stst (void) {
+#if !(defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64)
+ __sync_synchronize ();
+#endif
+}
inline void ddsrt_atomic_fence_acq (void) {
+#if !(defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64)
ddsrt_atomic_fence ();
+#else
+ asm volatile ("" ::: "memory");
+#endif
}
inline void ddsrt_atomic_fence_rel (void) {
+#if !(defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64)
ddsrt_atomic_fence ();
+#else
+ asm volatile ("" ::: "memory");
+#endif
}
#if defined (__cplusplus)
diff --git a/src/ddsrt/include/dds/ddsrt/atomics/msvc.h b/src/ddsrt/include/dds/ddsrt/atomics/msvc.h
index e4418e1..6a16241 100644
--- a/src/ddsrt/include/dds/ddsrt/atomics/msvc.h
+++ b/src/ddsrt/include/dds/ddsrt/atomics/msvc.h
@@ -74,6 +74,9 @@ inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) {
inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) {
DDSRT_ATOMIC_PTROP (InterlockedIncrement) (&x->v);
}
+inline uint32_t ddsrt_atomic_inc32_ov (volatile ddsrt_atomic_uint32_t *x) {
+ return InterlockedIncrement (&x->v) - 1;
+}
inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) {
return InterlockedIncrement (&x->v);
}
@@ -138,6 +141,9 @@ inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v
inline void ddsrt_atomic_addvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
ddsrt_atomic_addptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
}
+inline uint32_t ddsrt_atomic_add32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
+ return InterlockedExchangeAdd (&x->v, v);
+}
inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
return InterlockedExchangeAdd (&x->v, v) + v;
}
@@ -157,46 +163,52 @@ inline void *ddsrt_atomic_addvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff
inline void ddsrt_atomic_sub32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
/* disable unary minus applied to unsigned type, result still unsigned */
-DDSRT_WARNING_MSVC_OFF(4146)
+ DDSRT_WARNING_MSVC_OFF(4146)
InterlockedExchangeAdd (&x->v, -v);
-DDSRT_WARNING_MSVC_ON(4146)
+ DDSRT_WARNING_MSVC_ON(4146)
}
#if DDSRT_HAVE_ATOMIC64
inline void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
/* disable unary minus applied to unsigned type, result still unsigned */
-DDSRT_WARNING_MSVC_OFF(4146)
+ DDSRT_WARNING_MSVC_OFF(4146)
InterlockedExchangeAdd64 (&x->v, -v);
-DDSRT_WARNING_MSVC_ON(4146)
+ DDSRT_WARNING_MSVC_ON(4146)
}
#endif
inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
/* disable unary minus applied to unsigned type, result still unsigned */
-DDSRT_WARNING_MSVC_OFF(4146)
+ DDSRT_WARNING_MSVC_OFF(4146)
DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, -v);
-DDSRT_WARNING_MSVC_ON(4146)
+ DDSRT_WARNING_MSVC_ON(4146)
}
inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
ddsrt_atomic_subptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
}
+inline uint32_t ddsrt_atomic_sub32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
+ /* disable unary minus applied to unsigned type, result still unsigned */
+ DDSRT_WARNING_MSVC_OFF(4146)
+ return InterlockedExchangeAdd (&x->v, -v);
+ DDSRT_WARNING_MSVC_ON(4146)
+}
inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
/* disable unary minus applied to unsigned type, result still unsigned */
-DDSRT_WARNING_MSVC_OFF(4146)
+ DDSRT_WARNING_MSVC_OFF(4146)
return InterlockedExchangeAdd (&x->v, -v) - v;
-DDSRT_WARNING_MSVC_ON(4146)
+ DDSRT_WARNING_MSVC_ON(4146)
}
#if DDSRT_HAVE_ATOMIC64
inline uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
/* disable unary minus applied to unsigned type, result still unsigned */
-DDSRT_WARNING_MSVC_OFF(4146)
+ DDSRT_WARNING_MSVC_OFF(4146)
return InterlockedExchangeAdd64 (&x->v, -v) - v;
-DDSRT_WARNING_MSVC_ON(4146)
+ DDSRT_WARNING_MSVC_ON(4146)
}
#endif
inline uintptr_t ddsrt_atomic_subptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
/* disable unary minus applied to unsigned type, result still unsigned */
-DDSRT_WARNING_MSVC_OFF(4146)
+ DDSRT_WARNING_MSVC_OFF(4146)
return DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, -v) - v;
-DDSRT_WARNING_MSVC_ON(4146)
+ DDSRT_WARNING_MSVC_ON(4146)
}
inline void *ddsrt_atomic_subvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
return (void *) ddsrt_atomic_subptr_nv ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
@@ -280,16 +292,21 @@ inline void ddsrt_atomic_fence (void) {
/* 28113: accessing a local variable tmp via an Interlocked
function: This is an unusual usage which could be reconsidered.
It is too heavyweight, true, but it does the trick. */
-DDSRT_WARNING_MSVC_OFF(28113)
+ DDSRT_WARNING_MSVC_OFF(28113)
volatile LONG tmp = 0;
InterlockedExchange (&tmp, 0);
-DDSRT_WARNING_MSVC_ON(28113)
+ DDSRT_WARNING_MSVC_ON(28113)
}
inline void ddsrt_atomic_fence_ldld (void) {
#if !(defined _M_IX86 || defined _M_X64)
ddsrt_atomic_fence ();
#endif
}
+inline void ddsrt_atomic_fence_stst (void) {
+#if !(defined _M_IX86 || defined _M_X64)
+ ddsrt_atomic_fence ();
+#endif
+}
inline void ddsrt_atomic_fence_acq (void) {
ddsrt_atomic_fence ();
}
diff --git a/src/ddsrt/include/dds/ddsrt/atomics/sun.h b/src/ddsrt/include/dds/ddsrt/atomics/sun.h
index 74a7469..c5f871b 100644
--- a/src/ddsrt/include/dds/ddsrt/atomics/sun.h
+++ b/src/ddsrt/include/dds/ddsrt/atomics/sun.h
@@ -40,6 +40,11 @@ inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) {
inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) {
atomic_inc_ulong (&x->v);
}
+inline uint32_t ddsrt_atomic_inc32_ov (volatile ddsrt_atomic_uint32_t *x) {
+ uint32_t oldval, newval;
+ do { oldval = x->v; newval = oldval + 1; } while (atomic_cas_32 (&x->v, oldval, newval) != oldval);
+ return oldval;
+}
inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) {
return atomic_inc_32_nv (&x->v);
}
@@ -100,6 +105,9 @@ inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v
inline void ddsrt_atomic_addvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
atomic_add_ptr (&x->v, v);
}
+inline uint32_t ddsrt_atomic_add32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
+ return atomic_add_32_nv (&x->v, v) - v;
+}
inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
return atomic_add_32_nv (&x->v, v);
}
@@ -127,6 +135,9 @@ inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v
inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
atomic_add_ptr (&x->v, -v);
}
+inline uint32_t ddsrt_atomic_sub32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
+ return atomic_add_32_nv (&x->v, -v) + v;
+}
inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
return atomic_add_32_nv (&x->v, -v);
}
@@ -234,7 +245,10 @@ inline void ddsrt_atomic_fence (void) {
membar_enter ();
}
inline void ddsrt_atomic_fence_ldld (void) {
- membar_enter ();
+ membar_consumer ();
+}
+inline void ddsrt_atomic_fence_stst (void) {
+ membar_producer ();
}
inline void ddsrt_atomic_fence_acq (void) {
membar_enter ();
diff --git a/src/ddsrt/include/dds/ddsrt/attributes.h b/src/ddsrt/include/dds/ddsrt/attributes.h
index c91584d..08e1e0a 100644
--- a/src/ddsrt/include/dds/ddsrt/attributes.h
+++ b/src/ddsrt/include/dds/ddsrt/attributes.h
@@ -105,4 +105,22 @@
# define ddsrt_attribute_assume_aligned(params)
#endif
+#if ddsrt_has_attribute(packed)
+# define ddsrt_attribute_packed __attribute__ ((__packed__))
+#else
+# define ddsrt_attribute_packed
+#endif
+
+#if ddsrt_has_attribute(no_sanitize)
+# define ddsrt_attribute_no_sanitize(params) __attribute__ ((__no_sanitize__ params))
+#else
+# define ddsrt_attribute_no_sanitize(params)
+#endif
+
+#if defined(__has_feature)
+# define ddsrt_has_feature_thread_sanitizer __has_feature(thread_sanitizer)
+#else
+# define ddsrt_has_feature_thread_sanitizer 0
+#endif
+
#endif /* DDSRT_ATTRIBUTES_H */
diff --git a/src/ddsrt/include/dds/ddsrt/countargs.h b/src/ddsrt/include/dds/ddsrt/countargs.h
new file mode 100644
index 0000000..69e6773
--- /dev/null
+++ b/src/ddsrt/include/dds/ddsrt/countargs.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright(c) 2019 ADLINK Technology Limited and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+ * v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+#ifndef DDSRT_COUNTARGS_H
+#define DDSRT_COUNTARGS_H
+
+#define DDSRT_COUNT_ARGS_MSVC_WORKAROUND(x) x
+#define DDSRT_COUNT_ARGS(...) DDSRT_COUNT_ARGS1 (__VA_ARGS__, 10,9,8,7,6,5,4,3,2,1,0)
+#define DDSRT_COUNT_ARGS1(...) DDSRT_COUNT_ARGS_MSVC_WORKAROUND (DDSRT_COUNT_ARGS_ARGN (__VA_ARGS__))
+#define DDSRT_COUNT_ARGS_ARGN(a,b,c,d,e,f,g,h,i,j,n,...) n
+
+#endif
diff --git a/src/ddsrt/include/dds/ddsrt/dynlib.h b/src/ddsrt/include/dds/ddsrt/dynlib.h
index 1f9270e..554438b 100644
--- a/src/ddsrt/include/dds/ddsrt/dynlib.h
+++ b/src/ddsrt/include/dds/ddsrt/dynlib.h
@@ -47,7 +47,7 @@ typedef struct ddsrt_dynlib *ddsrt_dynlib_t;
* @param[in] translate Automatic name translation on/off.
* @param[out] handle Library handle that will be assigned after successfull operation. It is assigned to NULL if loading fails.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Library handle was successfully loaded.
@@ -57,7 +57,7 @@ typedef struct ddsrt_dynlib *ddsrt_dynlib_t;
* Loading failed.
* Use ddsrt_dlerror() to diagnose the failure.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_dlopen(
const char *name,
bool translate,
@@ -73,7 +73,7 @@ ddsrt_dlopen(
*
* @param[in] handle Library handle.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Library handle was successfully closed.
@@ -81,7 +81,7 @@ ddsrt_dlopen(
* Library closing failed.
* Use ddsrt_dlerror() to diagnose the failure.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_dlclose(
ddsrt_dynlib_t handle);
@@ -95,7 +95,7 @@ ddsrt_dlclose(
* @param[in] symbol Symbol name.
* @param[out] address The memory address of the loaded symbol (void*).
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Symbol was found in the loaded library.
@@ -104,7 +104,7 @@ ddsrt_dlclose(
* Symbol was not found.
* Use ddsrt_dlerror() to diagnose the failure.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_dlsym(
ddsrt_dynlib_t handle,
const char *symbol,
@@ -124,14 +124,14 @@ ddsrt_dlsym(
* function should be called immediately after calling ddsrt_dlopen or ddsrt_dlsym
* function.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Most recent library related error returned.
* @retval DDS_RETCODE_NOT_FOUND
* No library related error found.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_dlerror(
char *buf,
size_t buflen);
diff --git a/src/ddsrt/include/dds/ddsrt/endian.h b/src/ddsrt/include/dds/ddsrt/endian.h
index a046b09..c1b831b 100644
--- a/src/ddsrt/include/dds/ddsrt/endian.h
+++ b/src/ddsrt/include/dds/ddsrt/endian.h
@@ -25,7 +25,15 @@ extern "C" {
# else
# define DDSRT_ENDIAN DDSRT_LITTLE_ENDIAN
# endif
-#else /* _WIN32 */
+/* _WIN32 */
+#elif defined(__IAR_SYSTEMS_ICC__)
+# if __LITTLE_ENDIAN__ == 1
+# define DDSRT_ENDIAN DDSRT_LITTLE_ENDIAN
+# else
+# define DDSRT_ENDIAN DDSRT_BIG_ENDIAN
+# endif
+/* __IAR_SYSTEMS_ICC__ */
+#else
# if defined(__BYTE_ORDER__)
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define DDSRT_ENDIAN DDSRT_BIG_ENDIAN
diff --git a/src/ddsrt/include/dds/ddsrt/environ.h b/src/ddsrt/include/dds/ddsrt/environ.h
index 67a8c29..d5d895e 100644
--- a/src/ddsrt/include/dds/ddsrt/environ.h
+++ b/src/ddsrt/include/dds/ddsrt/environ.h
@@ -24,13 +24,9 @@ extern "C" {
* @brief Get value for environment variable.
*
* @param[in] name Environment variable name.
- * @param[in] buf Buffer to write value to.
- * @param[in] sz Size of buffer.
- * @param[out] reqsz Number of bytes written (excluding the terminating null
- * byte), or would have been written would @buf have been
- * sufficiently large enough.
+ * @param[out] value Alias to value of environment variable - must not be modified
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Environment variable written to @buf.
@@ -43,7 +39,7 @@ extern "C" {
* @retval DDS_RETCODE_ERROR
* Unspecified error.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_getenv(
const char *name,
char **value)
@@ -58,7 +54,7 @@ ddsrt_nonnull_all;
* @param[in] name Environment variable name.
* @param[in] value Value to set environment variable to.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Environment variable successfully set to @value.
@@ -69,7 +65,7 @@ ddsrt_nonnull_all;
* @retval DDS_RETCODE_ERROR
* Unspecified system error.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_setenv(
const char *name,
const char *value)
@@ -80,7 +76,7 @@ ddsrt_nonnull_all;
*
* @param[in] name Environment variable name.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Environment variable successfully unset.
@@ -91,7 +87,7 @@ ddsrt_nonnull_all;
* @retval DDS_RETCODE_ERROR
* Unspecified system error.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_unsetenv(
const char *name)
ddsrt_nonnull_all;
@@ -104,6 +100,10 @@ ddsrt_nonnull_all;
* The result string should be freed with ddsrt_free().
*
* @param[in] string String to expand.
+ * @param[in] domid Domain id that this is relevant to
+ * UINT32_MAX means none (see logging)
+ * also made available as
+ * ${CYCLONEDDS_DOMAIN_ID}
*
* @returns Allocated char*.
*
@@ -115,7 +115,8 @@ ddsrt_nonnull_all;
*/
DDS_EXPORT char*
ddsrt_expand_envvars(
- const char *string);
+ const char *string,
+ uint32_t domid);
/**
* @brief Expand environment variables within string.
@@ -137,7 +138,8 @@ ddsrt_expand_envvars(
*/
DDS_EXPORT char*
ddsrt_expand_envvars_sh(
- const char *string);
+ const char *string,
+ uint32_t domid);
#if defined(__cplusplus)
diff --git a/src/ddsrt/include/dds/ddsrt/hopscotch.h b/src/ddsrt/include/dds/ddsrt/hopscotch.h
index 24d9213..dbb4004 100644
--- a/src/ddsrt/include/dds/ddsrt/hopscotch.h
+++ b/src/ddsrt/include/dds/ddsrt/hopscotch.h
@@ -20,15 +20,6 @@
extern "C" {
#endif
-/* Concurrent version */
-struct ddsrt_chh;
-struct ddsrt_chh_bucket;
-struct ddsrt_chh_iter {
- struct ddsrt_chh_bucket *bs;
- uint32_t size;
- uint32_t cursor;
-};
-
/*
* The hopscotch hash table is dependent on a proper functioning hash.
* If the hash function generates a lot of hash collisions, then it will
@@ -39,29 +30,20 @@ struct ddsrt_chh_iter {
* When proper distributed hash values are generated, then hopscotch
* works nice and quickly.
*/
-typedef uint32_t (*ddsrt_hh_hash_fn) (const void *);
+typedef uint32_t (*ddsrt_hh_hash_fn) (const void *a);
/*
* Hopscotch needs to be able to compare two elements.
* Returns 0 when not equal.
*/
-typedef int (*ddsrt_hh_equals_fn) (const void *, const void *);
+typedef int (*ddsrt_hh_equals_fn) (const void *a, const void *b);
/*
* Hopscotch is will resize its internal buckets list when needed. It will
* call this garbage collection function with the old buckets list. The
* caller has to delete the list when it deems it safe to do so.
*/
-typedef void (*ddsrt_hh_buckets_gc_fn) (void *);
-
-DDS_EXPORT struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets);
-DDS_EXPORT void ddsrt_chh_free (struct ddsrt_chh * __restrict hh);
-DDS_EXPORT void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict rt, const void * __restrict template);
-DDS_EXPORT int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data);
-DDS_EXPORT int ddsrt_chh_remove (struct ddsrt_chh * __restrict rt, const void * __restrict template);
-DDS_EXPORT void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */
-void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_iter *it);
-void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it);
+typedef void (*ddsrt_hh_buckets_gc_fn) (void *bs, void *arg);
/* Sequential version */
struct ddsrt_hh;
@@ -80,6 +62,31 @@ DDS_EXPORT void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void
DDS_EXPORT void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter); /* may delete nodes */
DDS_EXPORT void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter);
+/* Concurrent version */
+struct ddsrt_chh;
+struct ddsrt_chh_bucket;
+
+#if ! ddsrt_has_feature_thread_sanitizer
+struct ddsrt_chh_iter {
+ struct ddsrt_chh_bucket *bs;
+ uint32_t size;
+ uint32_t cursor;
+};
+#else
+struct ddsrt_chh_iter {
+ struct ddsrt_chh *chh;
+ struct ddsrt_hh_iter it;
+};
+#endif
+
+DDS_EXPORT struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets, void *gc_buckets_arg);
+DDS_EXPORT void ddsrt_chh_free (struct ddsrt_chh * __restrict hh);
+DDS_EXPORT void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict rt, const void * __restrict template);
+DDS_EXPORT int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data);
+DDS_EXPORT int ddsrt_chh_remove (struct ddsrt_chh * __restrict rt, const void * __restrict template);
+DDS_EXPORT void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */
+DDS_EXPORT void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_iter *it);
+DDS_EXPORT void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it);
/* Sequential version, embedded data */
struct ddsrt_ehh;
diff --git a/src/ddsrt/include/dds/ddsrt/ifaddrs.h b/src/ddsrt/include/dds/ddsrt/ifaddrs.h
index b98d5b8..3eea634 100644
--- a/src/ddsrt/include/dds/ddsrt/ifaddrs.h
+++ b/src/ddsrt/include/dds/ddsrt/ifaddrs.h
@@ -18,11 +18,18 @@
extern "C" {
#endif
+enum ddsrt_iftype {
+ DDSRT_IFTYPE_UNKNOWN,
+ DDSRT_IFTYPE_WIRED,
+ DDSRT_IFTYPE_WIFI
+};
+
struct ddsrt_ifaddrs {
struct ddsrt_ifaddrs *next;
char *name;
uint32_t index;
uint32_t flags;
+ enum ddsrt_iftype type;
struct sockaddr *addr;
struct sockaddr *netmask;
struct sockaddr *broadaddr;
@@ -30,7 +37,7 @@ struct ddsrt_ifaddrs {
typedef struct ddsrt_ifaddrs ddsrt_ifaddrs_t;
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_getifaddrs(
ddsrt_ifaddrs_t **ifap,
const int *afs);
diff --git a/src/ddsrt/include/dds/ddsrt/log.h b/src/ddsrt/include/dds/ddsrt/log.h
index 360f9c6..d3fbc2b 100644
--- a/src/ddsrt/include/dds/ddsrt/log.h
+++ b/src/ddsrt/include/dds/ddsrt/log.h
@@ -92,6 +92,8 @@ extern "C" {
typedef struct {
/** Log category the message falls into. */
uint32_t priority;
+ /** Log domain id, UINT32_MAX is global. */
+ uint32_t domid;
/** Filename where message was generated. */
const char *file;
/** Line number in file where message was generated. */
@@ -102,10 +104,38 @@ typedef struct {
const char *message;
/** Size of log message. */
size_t size;
+ /** Default log message header length */
+ size_t hdrsize;
} dds_log_data_t;
/** Function signature that log and trace callbacks must adhere too. */
-typedef void(*dds_log_write_fn_t)(void *, const dds_log_data_t *);
+typedef void (*dds_log_write_fn_t) (void *, const dds_log_data_t *);
+
+/** Semi-opaque type for log/trace configuration. */
+struct ddsrt_log_cfg_common {
+ /** Mask for testing whether the xLOG macro should forward to the
+ function (and so incur the cost of constructing the parameters).
+ Messages in DDS_LOG_MASK are rare, so the overhead of calling
+ the function and then dropping the message is not an issue, unlike
+ for messages in DDS_TRACE_MASK. */
+ uint32_t mask;
+
+ /** The actual configured trace mask */
+ uint32_t tracemask;
+
+ /** Domain id for reporting; UINT32_MAX = no domain */
+ uint32_t domid;
+};
+
+typedef struct ddsrt_log_cfg {
+ struct ddsrt_log_cfg_common c;
+ union {
+ dds_log_write_fn_t fnptr;
+ void *ptr;
+ uint32_t u32;
+ unsigned char pad[72];
+ } u;
+} ddsrt_log_cfg_t;
DDS_EXPORT extern uint32_t *const dds_log_mask;
@@ -186,14 +216,84 @@ dds_set_trace_sink(
void *userdata);
/**
- * @brief Write a log or trace message.
+ * @brief Initialize a struct ddsrt_log_cfg for use with dds_log_cfg
+ *
+ * Callbacks registered to handle log messages will receive messages of type
+ * info, warning, error and fatal. Messages that fall into the trace category
+ * will never be delivered to the callback.
+ *
+ * Callbacks registered to handle trace messages will receive messages of type
+ * info, warning, error and fatal as well as all message types that fall into
+ * the trace category depending on the log mask.
+ *
+ * This operation is synchronous and only returns once the operation is
+ * registered with all threads. Meaning that neither callback or
+ * userdata will be referenced by the DDS stack on return.
+ *
+ * @param[out] cfg On return, initialised to make dds_log_cfg invoked
+ * with this config object behave as specified by the
+ * other parameters.
+ * @param[in] domid Numerical identifier in log/trace, UINT32_MAX is
+ * reserved for global logging.
+ * @param[in] tracemask Mask determining which traces should be written.
+ * @param[in] log_fp File for default sink.
+ * @param[in] trace_fp File for default sink.
+ */
+DDS_EXPORT void
+dds_log_cfg_init(
+ struct ddsrt_log_cfg *cfg,
+ uint32_t domid,
+ uint32_t tracemask,
+ FILE *log_fp,
+ FILE *trace_fp);
+
+/**
+ * @brief Write a log or trace message for a specific logging configuraiton
+ * (categories, id, sinks).
+ *
+ * Direct use of #dds_log is discouraged. Use #DDS_CINFO, #DDS_CWARNING,
+ * #DDS_CERROR, #DDS_CTRACE or #DDS_CLOG instead.
+ */
+DDS_EXPORT void
+dds_log_cfg(
+ const struct ddsrt_log_cfg *cfg,
+ uint32_t prio,
+ const char *file,
+ uint32_t line,
+ const char *func,
+ const char *fmt,
+ ...)
+ ddsrt_attribute_format((__printf__, 6, 7));
+
+/**
+ * @brief Write a log or trace message to the global configuration but with
+ * specific domain (intended solely for use during domain start-up, while
+ * the domain-specific logging/tracing hasn't been set yet).
+ *
+ * Write a log or trace message to one (or both) of the currently active sinks.
+ *
+ * Direct use of #dds_log_id is discouraged. Use #DDS_ILOG instead.
+ */
+DDS_EXPORT void
+dds_log_id(
+ uint32_t prio,
+ uint32_t domid,
+ const char *file,
+ uint32_t line,
+ const char *func,
+ const char *fmt,
+ ...)
+ ddsrt_attribute_format((__printf__, 6, 7));
+
+/**
+ * @brief Write a log or trace message to the global log/trace.
*
* Write a log or trace message to one (or both) of the currently active sinks.
*
* Direct use of #dds_log is discouraged. Use #DDS_INFO, #DDS_WARNING,
* #DDS_ERROR, #DDS_FATAL or #DDS_LOG instead.
*/
-DDS_EXPORT int
+DDS_EXPORT void
dds_log(
uint32_t prio,
const char *file,
@@ -279,23 +379,70 @@ dds_log(
*/
#define DDS_LOG(cat, ...) \
((dds_get_log_mask() & (cat)) ? \
- dds_log(cat, __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) : 0)
+ dds_log((cat), __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) : 0)
-/** Write a log message of type #DDS_LC_INFO. */
+/**
+ * @brief Write a log message with a domain id override.
+ *
+ * Write a log or trace message to the currently active log and/or trace sinks
+ * if the log category is enabled. Whether or not the category is enabled is
+ * checked before any dds_log-related activities to save a couple of % CPU.
+ *
+ * Only messages that fall into one of the log categories are passed onto
+ * dds_log. While messages that fall into a trace category could have been
+ * passed just as easily, they are rejected so that tracing is kept entirely
+ * separate from logging, if only cosmetic.
+ */
+#define DDS_ILOG(cat, domid, ...) \
+ ((dds_get_log_mask() & (cat)) ? \
+ dds_log_id((cat), (domid), __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) : 0)
+
+/**
+ * @brief Write a log message using a specific config.
+ *
+ * Write a log or trace message to the currently active log and/or trace sinks
+ * if the log category is enabled. Whether or not the category is enabled is
+ * checked before any dds_log-related activities to save a couple of % CPU.
+ *
+ * Only messages that fall into one of the log categories are passed onto
+ * dds_log. While messages that fall into a trace category could have been
+ * passed just as easily, they are rejected so that tracing is kept entirely
+ * separate from logging, if only cosmetic.
+ */
+#define DDS_CLOG(cat, cfg, ...) \
+ (((cfg)->c.mask & (cat)) ? \
+ dds_log_cfg((cfg), (cat), __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) : 0)
+
+/** Write a log message of type #DDS_LC_INFO into global log. */
#define DDS_INFO(...) \
DDS_LOG(DDS_LC_INFO, __VA_ARGS__)
-/** Write a log message of type #DDS_LC_WARNING. */
+/** Write a log message of type #DDS_LC_WARNING into global log. */
#define DDS_WARNING(...) \
DDS_LOG(DDS_LC_WARNING, __VA_ARGS__)
-/** Write a log message of type #DDS_LC_ERROR. */
+/** Write a log message of type #DDS_LC_ERROR into global log. */
#define DDS_ERROR(...) \
DDS_LOG(DDS_LC_ERROR, __VA_ARGS__)
-/** Write a log message of type #DDS_LC_ERROR and abort. */
+/** Write a log message of type #DDS_LC_ERROR into global log and abort. */
#define DDS_FATAL(...) \
dds_log(DDS_LC_FATAL, __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__)
-/** Write a #DDS_LC_TRACE message. */
-#define DDS_TRACE(...) \
- DDS_LOG(DDS_LC_TRACE, __VA_ARGS__)
+
+/* MSVC mishandles __VA_ARGS__ while claiming to be conforming -- and even
+ if they have a defensible implement, they still differ from every other
+ compiler out there. An extra layer of macro expansion works around it. */
+#define DDS_CLOG_MSVC_WORKAROUND(x) x
+
+/** Write a log message of type #DDS_LC_INFO using specific logging config. */
+#define DDS_CINFO(...) \
+ DDS_CLOG_MSVC_WORKAROUND(DDS_CLOG(DDS_LC_INFO, __VA_ARGS__))
+/** Write a log message of type #DDS_LC_WARNING using specific logging config. */
+#define DDS_CWARNING(...) \
+ DDS_CLOG_MSVC_WORKAROUND(DDS_CLOG(DDS_LC_WARNING, __VA_ARGS__))
+/** Write a log message of type #DDS_LC_ERROR using specific logging config. */
+#define DDS_CERROR(...) \
+ DDS_CLOG_MSVC_WORKAROUND(DDS_CLOG(DDS_LC_ERROR, __VA_ARGS__))
+/** Write a #DDS_LC_TRACE message using specific logging config. */
+#define DDS_CTRACE(...) \
+ DDS_CLOG_MSVC_WORKAROUND(DDS_CLOG(DDS_LC_TRACE, __VA_ARGS__))
#if defined (__cplusplus)
}
diff --git a/src/ddsrt/include/dds/ddsrt/misc.h b/src/ddsrt/include/dds/ddsrt/misc.h
index 1d165b1..582a52d 100644
--- a/src/ddsrt/include/dds/ddsrt/misc.h
+++ b/src/ddsrt/include/dds/ddsrt/misc.h
@@ -18,29 +18,45 @@
extern "C" {
#endif
-#if defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
-# define DDSRT_GNUC_STR(s) #s
-# define DDSRT_GNUC_JOINSTR(x,y) DDSRT_GNUC_STR(x ## y)
-# define DDSRT_GNUC_DO_PRAGMA(x) _Pragma (#x)
-# define DDSRT_GNUC_PRAGMA(x) DDSRT_GNUC_DO_PRAGMA(GCC diagnostic x)
-# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
+#if defined(__clang__) || \
+ defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
+# define DDSRT_STR(s) #s
+# define DDSRT_JOINSTR(x,y) DDSRT_STR(x ## y)
+# define DDSRT_DO_PRAGMA(x) _Pragma(#x)
+# define DDSRT_PRAGMA(x) DDSRT_DO_PRAGMA(GCC diagnostic x)
+
+# if defined(__clang__)
+# define DDSRT_WARNING_CLANG_OFF(x) \
+ DDSRT_PRAGMA(push) \
+ DDSRT_PRAGMA(ignored DDSRT_JOINSTR(-W,x))
+# define DDSRT_WARNING_CLANG_ON(x) \
+ DDSRT_PRAGMA(pop)
+# elif ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
# define DDSRT_WARNING_GNUC_OFF(x) \
- DDSRT_GNUC_PRAGMA(push) \
- DDSRT_GNUC_PRAGMA(ignored DDSRT_GNUC_JOINSTR(-W,x))
+ DDSRT_PRAGMA(push) \
+ DDSRT_PRAGMA(ignored DDSRT_JOINSTR(-W,x))
# define DDSRT_WARNING_GNUC_ON(x) \
- DDSRT_GNUC_PRAGMA(pop)
+ DDSRT_PRAGMA(pop)
# else
# define DDSRT_WARNING_GNUC_OFF(x) \
- DDSRT_GNUC_PRAGMA(ignored DDSRT_GNUC_JOINSTR(-W,x))
+ DDSRT_PRAGMA(ignored DDSRT_JOINSTR(-W,x))
# define DDSRT_WARNING_GNUC_ON(x) \
- DDSRT_GNUC_PRAGMA(warning DDSRT_GNUC_JOINSTR(-W,x))
+ DDSRT_PRAGMA(warning DDSRT_JOINSTR(-W,x))
# endif
-#else
+#endif
+
+#if !defined(DDSRT_WARNING_CLANG_OFF) && \
+ !defined(DDSRT_WARNING_CLANG_ON)
+# define DDSRT_WARNING_CLANG_OFF(x)
+# define DDSRT_WARNING_CLANG_ON(x)
+#endif
+
+#if !defined(DDSRT_WARNING_GNUC_OFF) && \
+ !defined(DDSRT_WARNING_GNUC_ON)
# define DDSRT_WARNING_GNUC_OFF(x)
# define DDSRT_WARNING_GNUC_ON(x)
#endif
-
#if defined(_MSC_VER)
# define DDSRT_WARNING_MSVC_OFF(x) \
__pragma (warning(push)) \
@@ -52,23 +68,6 @@ extern "C" {
# define DDSRT_WARNING_MSVC_ON(x)
#endif
-/**
- * @brief Calculate maximum value of an integer type
- *
- * A somewhat complex, but efficient way to calculate the maximum value of an
- * integer type at compile time.
- *
- * For unsigned numerical types the first part up to XOR is enough. The second
- * part is to make up for signed numerical types.
- */
-#define DDSRT_MAX_INTEGER(T) \
- ((T)(((T)~0) ^ ((T)!((T)~0 > 0) << (CHAR_BIT * sizeof(T) - 1))))
-/**
- * @brief Calculate minimum value of an integer type
- */
-#define DDSRT_MIN_INTEGER(T) \
- ((-DDSRT_MAX_INTEGER(T)) - 1)
-
/**
* @brief Macro to disable unused argument warnings
*/
diff --git a/src/ddsrt/include/dds/ddsrt/netstat.h b/src/ddsrt/include/dds/ddsrt/netstat.h
new file mode 100644
index 0000000..49151d2
--- /dev/null
+++ b/src/ddsrt/include/dds/ddsrt/netstat.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright(c) 2019 ADLINK Technology Limited and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+ * v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+#ifndef DDSRT_NETSTAT_H
+#define DDSRT_NETSTAT_H
+
+#include
+
+#include "dds/export.h"
+#include "dds/ddsrt/retcode.h"
+
+#if defined (__linux) || defined (__APPLE__) || defined (_WIN32)
+#define DDSRT_HAVE_NETSTAT (1)
+#else
+#define DDSRT_HAVE_NETSTAT (0)
+#endif
+
+#if DDSRT_HAVE_NETSTAT
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct ddsrt_netstat {
+ uint64_t ipkt;
+ uint64_t opkt;
+ uint64_t ibytes;
+ uint64_t obytes;
+};
+
+/**
+ * @brief Platform dependent control structure for network statistics
+ */
+struct ddsrt_netstat_control;
+
+/**
+ * @brief Prepare for gathering network statistics for specified interface.
+ */
+DDS_EXPORT dds_return_t
+ddsrt_netstat_new (
+ struct ddsrt_netstat_control **control,
+ const char *device);
+
+/**
+ * @brief Release resources for gathering network statistics.
+ */
+DDS_EXPORT dds_return_t
+ddsrt_netstat_free (
+ struct ddsrt_netstat_control *control);
+
+/**
+ * @brief Get network statistics.
+ */
+DDS_EXPORT dds_return_t
+ddsrt_netstat_get (
+ struct ddsrt_netstat_control *control,
+ struct ddsrt_netstat *stats);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* DDSRT_HAVE_NETSTAT */
+
+#endif /* DDSRT_NETSTAT_H */
diff --git a/src/ddsrt/include/dds/ddsrt/process.h b/src/ddsrt/include/dds/ddsrt/process.h
index 45e7099..2d59130 100644
--- a/src/ddsrt/include/dds/ddsrt/process.h
+++ b/src/ddsrt/include/dds/ddsrt/process.h
@@ -17,19 +17,30 @@
#include "dds/ddsrt/types.h"
#include "dds/ddsrt/retcode.h"
-#if defined(_WIN32)
+#if DDSRT_WITH_FREERTOS
+#include
+#include
+typedef TaskHandle_t ddsrt_pid_t; /* typedef void *TaskHandle_t */
+#define PRIdPID "p"
+#define DDSRT_HAVE_MULTI_PROCESS 0
+/* DDSRT_WITH_FREERTOS */
+#elif defined(_WIN32)
typedef DWORD ddsrt_pid_t;
#define PRIdPID "u"
-#else /* _WIN32 */
+#define DDSRT_HAVE_MULTI_PROCESS 1
+/* _WIN32 */
+#else
#include
#if defined(_WRS_KERNEL)
typedef RTP_ID ddsrt_pid_t; /* typedef struct wind_rtp *RTP_ID */
#define PRIdPID PRIuPTR
+#define DDSRT_HAVE_MULTI_PROCESS 0
#else
typedef pid_t ddsrt_pid_t;
#define PRIdPID "d"
+#define DDSRT_HAVE_MULTI_PROCESS 1
+#endif
#endif
-#endif /* _WIN32 */
#if defined (__cplusplus)
@@ -44,6 +55,7 @@ extern "C" {
DDS_EXPORT ddsrt_pid_t
ddsrt_getpid(void);
+#if DDSRT_HAVE_MULTI_PROCESS
/**
* @brief Create new process.
@@ -60,7 +72,7 @@ ddsrt_getpid(void);
* @param[in] argv Arguments array.
* @param[out] pid ID of the created process.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Process successfully created.
@@ -73,7 +85,7 @@ ddsrt_getpid(void);
* @retval DDS_RETCODE_ERROR
* Process could not be created.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_proc_create(
const char *executable,
char *const argv[],
@@ -94,10 +106,10 @@ ddsrt_proc_create(
* See ddsrt_proc_waitpids() for waiting on all child processes.
*
* @param[in] pid Process ID (PID) to get the exit code from.
- * @param[in] timemout Time within the process is expected to finish.
+ * @param[in] timeout Time within the process is expected to finish.
* @param[out] code The exit code of the process.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Process has terminated and its exit code has been captured.
@@ -112,7 +124,7 @@ ddsrt_proc_create(
* @retval DDS_RETCODE_ERROR
* Getting the exit code failed for an unknown reason.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_proc_waitpid(
ddsrt_pid_t pid,
dds_duration_t timeout,
@@ -133,11 +145,11 @@ ddsrt_proc_waitpid(
*
* See ddsrt_proc_waitpid() for waiting on a specific child process.
*
- * @param[in] timemout Time within a process is expected to finish.
+ * @param[in] timeout Time within a process is expected to finish.
* @param[out] pid Process ID (PID) of the finished process.
* @param[out] code The exit code of the process.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* A process has terminated.
@@ -153,7 +165,7 @@ ddsrt_proc_waitpid(
* @retval DDS_RETCODE_ERROR
* Getting the exit code failed for an unknown reason.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_proc_waitpids(
dds_duration_t timeout,
ddsrt_pid_t *pid,
@@ -164,7 +176,7 @@ ddsrt_proc_waitpids(
*
* @param[in] pid Process ID (PID) to check if it exists.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* The process exists.
@@ -173,7 +185,7 @@ ddsrt_proc_waitpids(
* @retval DDS_RETCODE_ERROR
* Determining if a process exists or not, failed.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_proc_exists(
ddsrt_pid_t pid);
@@ -190,7 +202,7 @@ ddsrt_proc_exists(
*
* @param[in] pid Process ID (PID) of the process to terminate.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Kill attempt has been started.
@@ -201,10 +213,11 @@ ddsrt_proc_exists(
* @retval DDS_RETCODE_ERROR
* Kill failed for an unknown reason.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_proc_kill(
ddsrt_pid_t pid);
+#endif /* DDSRT_HAVE_MULTI_PROCESS */
#if defined (__cplusplus)
}
diff --git a/src/ddsrt/include/dds/ddsrt/retcode.h b/src/ddsrt/include/dds/ddsrt/retcode.h
index f57626d..20b106f 100644
--- a/src/ddsrt/include/dds/ddsrt/retcode.h
+++ b/src/ddsrt/include/dds/ddsrt/retcode.h
@@ -9,7 +9,7 @@
extern "C" {
#endif
-typedef int32_t dds_retcode_t;
+typedef int32_t dds_return_t;
/*
State is unchanged following a function call returning an error
@@ -29,25 +29,25 @@ typedef int32_t dds_retcode_t;
* @{
*/
#define DDS_RETCODE_OK 0 /**< Success */
-#define DDS_RETCODE_ERROR 1 /**< Non specific error */
-#define DDS_RETCODE_UNSUPPORTED 2 /**< Feature unsupported */
-#define DDS_RETCODE_BAD_PARAMETER 3 /**< Bad parameter value */
-#define DDS_RETCODE_PRECONDITION_NOT_MET 4 /**< Precondition for operation not met */
-#define DDS_RETCODE_OUT_OF_RESOURCES 5 /**< When an operation fails because of a lack of resources */
-#define DDS_RETCODE_NOT_ENABLED 6 /**< When a configurable feature is not enabled */
-#define DDS_RETCODE_IMMUTABLE_POLICY 7 /**< When an attempt is made to modify an immutable policy */
-#define DDS_RETCODE_INCONSISTENT_POLICY 8 /**< When a policy is used with inconsistent values */
-#define DDS_RETCODE_ALREADY_DELETED 9 /**< When an attempt is made to delete something more than once */
-#define DDS_RETCODE_TIMEOUT 10 /**< When a timeout has occurred */
-#define DDS_RETCODE_NO_DATA 11 /**< When expected data is not provided */
-#define DDS_RETCODE_ILLEGAL_OPERATION 12 /**< When a function is called when it should not be */
-#define DDS_RETCODE_NOT_ALLOWED_BY_SECURITY 13 /**< When credentials are not enough to use the function */
+#define DDS_RETCODE_ERROR -1 /**< Non specific error */
+#define DDS_RETCODE_UNSUPPORTED -2 /**< Feature unsupported */
+#define DDS_RETCODE_BAD_PARAMETER -3 /**< Bad parameter value */
+#define DDS_RETCODE_PRECONDITION_NOT_MET -4 /**< Precondition for operation not met */
+#define DDS_RETCODE_OUT_OF_RESOURCES -5 /**< When an operation fails because of a lack of resources */
+#define DDS_RETCODE_NOT_ENABLED -6 /**< When a configurable feature is not enabled */
+#define DDS_RETCODE_IMMUTABLE_POLICY -7 /**< When an attempt is made to modify an immutable policy */
+#define DDS_RETCODE_INCONSISTENT_POLICY -8 /**< When a policy is used with inconsistent values */
+#define DDS_RETCODE_ALREADY_DELETED -9 /**< When an attempt is made to delete something more than once */
+#define DDS_RETCODE_TIMEOUT -10 /**< When a timeout has occurred */
+#define DDS_RETCODE_NO_DATA -11 /**< When expected data is not provided */
+#define DDS_RETCODE_ILLEGAL_OPERATION -12 /**< When a function is called when it should not be */
+#define DDS_RETCODE_NOT_ALLOWED_BY_SECURITY -13 /**< When credentials are not enough to use the function */
/* Extended return codes are not in the DDS specification and are meant
exclusively for internal use and must not be returned by the C API. */
-#define DDS_XRETCODE_BASE (50)
-#define DDS_XRETCODE(x) (DDS_XRETCODE_BASE + (x))
+#define DDS_XRETCODE_BASE (-50)
+#define DDS_XRETCODE(x) (DDS_XRETCODE_BASE - (x))
/** Requested resource is busy */
#define DDS_RETCODE_IN_PROGRESS DDS_XRETCODE(1)
@@ -84,11 +84,11 @@ typedef int32_t dds_retcode_t;
/**
* @brief Takes the error value and outputs a string corresponding to it.
*
- * @param[in] err Error value to be converted to a string
+ * @param[in] ret Error value to be converted to a string
*
* @returns String corresponding to the error value
*/
-DDS_EXPORT const char *dds_strretcode(dds_retcode_t ret);
+DDS_EXPORT const char *dds_strretcode(dds_return_t ret);
#if defined (__cplusplus)
}
diff --git a/src/ddsrt/include/dds/ddsrt/rusage.h b/src/ddsrt/include/dds/ddsrt/rusage.h
index 040ce2e..a8906ac 100644
--- a/src/ddsrt/include/dds/ddsrt/rusage.h
+++ b/src/ddsrt/include/dds/ddsrt/rusage.h
@@ -14,8 +14,23 @@
#include
+#if DDSRT_WITH_FREERTOS
+#include
+# if configUSE_TRACE_FACILITY == 1 && \
+ configGENERATE_RUN_TIME_STATS == 1
+# define DDSRT_HAVE_RUSAGE 1
+# else
+# define DDSRT_HAVE_RUSAGE 0
+#endif
+#elif defined (_WIN32) || defined (__linux) || defined (__APPLE__)
+# define DDSRT_HAVE_RUSAGE 1
+#else
+# define DDSRT_HAVE_RUSAGE 0
+#endif
+
#include "dds/ddsrt/time.h"
#include "dds/ddsrt/retcode.h"
+#include "dds/ddsrt/threads.h"
#if defined (__cplusplus)
extern "C" {
@@ -31,8 +46,10 @@ typedef struct {
size_t nivcsw; /* Involuntary context switches. Not maintained on Windows. */
} ddsrt_rusage_t;
-#define DDSRT_RUSAGE_SELF (0)
-#define DDSRT_RUSAGE_THREAD (1)
+enum ddsrt_getrusage_who {
+ DDSRT_RUSAGE_SELF,
+ DDSRT_RUSAGE_THREAD
+};
/**
* @brief Get resource usage for the current thread or process.
@@ -40,7 +57,7 @@ typedef struct {
* @param[in] who DDSRT_RUSAGE_SELF or DDSRT_RUSAGE_THREAD.
* @param[in] usage Structure where resource usage is returned.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Resource usage successfully returned in @usage.
@@ -49,7 +66,26 @@ typedef struct {
* @retval DDS_RETCODE_ERROR
* An unidentified error occurred.
*/
-DDS_EXPORT dds_retcode_t ddsrt_getrusage(int who, ddsrt_rusage_t *usage);
+DDS_EXPORT dds_return_t ddsrt_getrusage(enum ddsrt_getrusage_who who, ddsrt_rusage_t *usage);
+
+#if DDSRT_HAVE_THREAD_LIST
+/**
+ * @brief Get resource usage for some thread.
+ *
+ * @param[in] tid id of the thread of to get the resource usage for
+ * @param[in] usage Structure where resource usage is returned.
+ *
+ * @returns A dds_return_t indicating success or failure.
+ *
+ * @retval DDS_RETCODE_OK
+ * Resource usage successfully returned in @usage.
+ * @retval DDS_RETCODE_OUT_OF_RESOURCES
+ * There were not enough resources to get resource usage.
+ * @retval DDS_RETCODE_ERROR
+ * An unidentified error occurred.
+ */
+DDS_EXPORT dds_return_t ddsrt_getrusage_anythread (ddsrt_thread_list_id_t tid, ddsrt_rusage_t * __restrict usage);
+#endif
#if defined (__cplusplus)
}
diff --git a/src/ddsrt/include/dds/ddsrt/sockets.h b/src/ddsrt/include/dds/ddsrt/sockets.h
index ec5efa3..0f55e2b 100644
--- a/src/ddsrt/include/dds/ddsrt/sockets.h
+++ b/src/ddsrt/include/dds/ddsrt/sockets.h
@@ -3,6 +3,10 @@
#include
+#if !defined(DDSRT_WITH_DNS)
+# define DDSRT_WITH_DNS 1
+#endif
+
#include "dds/export.h"
#include "dds/ddsrt/types.h"
#include "dds/ddsrt/attributes.h"
@@ -28,53 +32,53 @@ extern const struct in6_addr ddsrt_in6addr_loopback;
#define DDSRT_AF_TERM (-1)
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_gethostname(
char *hostname,
size_t buffersize);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_socket(
ddsrt_socket_t *sockptr,
int domain,
int type,
int protocol);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_close(
ddsrt_socket_t sock);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_connect(
ddsrt_socket_t sock,
const struct sockaddr *addr,
socklen_t addrlen);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_accept(
ddsrt_socket_t sock,
struct sockaddr *addr,
socklen_t *addrlen,
ddsrt_socket_t *connptr);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_listen(
ddsrt_socket_t sock,
int backlog);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_bind(
ddsrt_socket_t sock,
const struct sockaddr *addr,
socklen_t addrlen);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_getsockname(
ddsrt_socket_t sock,
struct sockaddr *addr,
socklen_t *addrlen);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_send(
ddsrt_socket_t sock,
const void *buf,
@@ -82,14 +86,14 @@ ddsrt_send(
int flags,
ssize_t *sent);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_sendmsg(
ddsrt_socket_t sock,
const ddsrt_msghdr_t *msg,
int flags,
ssize_t *sent);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_recv(
ddsrt_socket_t sock,
void *buf,
@@ -97,14 +101,14 @@ ddsrt_recv(
int flags,
ssize_t *rcvd);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_recvmsg(
ddsrt_socket_t sock,
ddsrt_msghdr_t *msg,
int flags,
ssize_t *rcvd);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_getsockopt(
ddsrt_socket_t sock,
int32_t level, /* SOL_SOCKET */
@@ -112,7 +116,7 @@ ddsrt_getsockopt(
void *optval,
socklen_t *optlen);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_setsockopt(
ddsrt_socket_t sock,
int32_t level, /* SOL_SOCKET */
@@ -126,7 +130,7 @@ ddsrt_setsockopt(
* @param[in] sock Socket to set I/O mode for.
* @param[in] nonblock true for nonblocking, or false for blocking I/O.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* I/O mode successfully set to (non)blocking.
@@ -137,7 +141,7 @@ ddsrt_setsockopt(
* @retval DDS_RETCODE_ERROR
* An unknown error error occurred.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_setsocknonblocking(
ddsrt_socket_t sock,
bool nonblock);
@@ -224,11 +228,11 @@ ddsrt_sockaddr_insamesubnet(
const struct sockaddr *mask)
ddsrt_nonnull_all;
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_sockaddrfromstr(
int af, const char *str, void *sa);
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_sockaddrtostr(
const void *sa, char *buf, size_t size);
@@ -243,9 +247,9 @@ typedef struct {
*
* @param[in] name Host name to resolve.
* @param[in] af Address family, either AF_INET, AF_INET6 or AF_UNSPEC.
- * @param[out] hent Structure of type ddsrt_hostent_t.
+ * @param[out] hentp Structure of type ddsrt_hostent_t.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Host name successfully resolved to address(es).
@@ -258,7 +262,7 @@ typedef struct {
* @retval DDS_RETCODE_TRY_AGAIN
* Nonauthoratitative host not found.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_gethostbyname(
const char *name,
int af,
diff --git a/src/ddsrt/include/dds/ddsrt/sockets/posix.h b/src/ddsrt/include/dds/ddsrt/sockets/posix.h
index a9697af..21cc327 100644
--- a/src/ddsrt/include/dds/ddsrt/sockets/posix.h
+++ b/src/ddsrt/include/dds/ddsrt/sockets/posix.h
@@ -12,12 +12,17 @@
#ifndef DDSRT_SOCKETS_POSIX_H
#define DDSRT_SOCKETS_POSIX_H
+#if DDSRT_WITH_LWIP
+#include
+#include
+#else
+#include
#include
#include
#include
#include
#include
-#include
+#endif
#if defined(__cplusplus)
extern "C" {
@@ -27,21 +32,51 @@ typedef int ddsrt_socket_t;
#define DDSRT_INVALID_SOCKET (-1)
#define PRIdSOCK "d"
-#define DDSRT_HAVE_IPV6 1
-#define DDSRT_HAVE_DNS 1
-#define DDSRT_HAVE_SSM 1
+#if LWIP_SOCKET
+# if LWIP_IPV6
+# define DDSRT_HAVE_IPV6 1
+# endif
+# if LWIP_DNS && LWIP_SOCKET
+# define DDSRT_HAVE_DNS DDSRT_WITH_DNS
+# define DDSRT_HAVE_GETADDRINFO DDSRT_WITH_DNS
+# endif
+# define DDSRT_HAVE_SSM 0
+# define DDSRT_HAVE_INET_NTOP 1
+# define DDSRT_HAVE_INET_PTON 1
+
+# define IFF_UP 0x1
+# define IFF_BROADCAST 0x2
+# define IFF_LOOPBACK 0x8
+# define IFF_POINTOPOINT 0x10
+# define IFF_MULTICAST 0x1000
+#elif __SunOS_5_6
+# define DDSRT_HAVE_IPV6 0
+# define DDSRT_HAVE_DNS DDSRT_WITH_DNS
+# define DDSRT_HAVE_GETADDRINFO 0
+# define DDSRT_HAVE_SSM 0
+# define DDSRT_HAVE_INET_NTOP 0
+# define DDSRT_HAVE_INET_PTON 0
+#else /* LWIP_SOCKET */
+# define DDSRT_HAVE_IPV6 1
+# define DDSRT_HAVE_DNS DDSRT_WITH_DNS
+# define DDSRT_HAVE_GETADDRINFO DDSRT_WITH_DNS
+# define DDSRT_HAVE_SSM 1
+# define DDSRT_HAVE_INET_NTOP 1
+# define DDSRT_HAVE_INET_PTON 1
+#endif /* LWIP_SOCKET */
typedef struct iovec ddsrt_iovec_t;
typedef size_t ddsrt_iov_len_t;
-#if defined(__linux)
+#if defined(__linux) && !LWIP_SOCKET
typedef size_t ddsrt_msg_iovlen_t;
#else /* POSIX says int (which macOS, FreeBSD, Solaris do) */
typedef int ddsrt_msg_iovlen_t;
#endif
typedef struct msghdr ddsrt_msghdr_t;
-#if defined(__sun) && !defined(_XPG4_2)
+#if (defined(__sun) && !defined(_XPG4_2)) || \
+ (defined(LWIP_SOCKET))
# define DDSRT_MSGHDR_FLAGS 0
#else
# define DDSRT_MSGHDR_FLAGS 1
diff --git a/src/ddsrt/include/dds/ddsrt/sockets/windows.h b/src/ddsrt/include/dds/ddsrt/sockets/windows.h
index 277dfe7..b557a21 100644
--- a/src/ddsrt/include/dds/ddsrt/sockets/windows.h
+++ b/src/ddsrt/include/dds/ddsrt/sockets/windows.h
@@ -12,8 +12,11 @@ typedef SOCKET ddsrt_socket_t;
#define DDSRT_INVALID_SOCKET (INVALID_SOCKET)
#define PRIdSOCK PRIuPTR
-#define DDSRT_HAVE_IPV6 1
-#define DDSRT_HAVE_DNS 1
+#define DDSRT_HAVE_IPV6 1
+#define DDSRT_HAVE_DNS DDSRT_WITH_DNS
+#define DDSRT_HAVE_GETADDRINFO DDSRT_WITH_DNS
+#define DDSRT_HAVE_INET_NTOP 1
+#define DDSRT_HAVE_INET_PTON 1
#if defined(NTDDI_VERSION) && \
defined(_WIN32_WINNT_WS03) && \
diff --git a/src/core/ddsi/include/dds/ddsi/q_static_assert.h b/src/ddsrt/include/dds/ddsrt/static_assert.h
similarity index 58%
rename from src/core/ddsi/include/dds/ddsi/q_static_assert.h
rename to src/ddsrt/include/dds/ddsrt/static_assert.h
index 078ed62..f21d44f 100644
--- a/src/core/ddsi/include/dds/ddsi/q_static_assert.h
+++ b/src/ddsrt/include/dds/ddsrt/static_assert.h
@@ -1,5 +1,5 @@
/*
- * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
+ * Copyright(c) 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -9,29 +9,34 @@
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
-#ifndef Q_STATIC_ASSERT_H
-#define Q_STATIC_ASSERT_H
+#ifndef DDSRT_STATIC_ASSERT_H
+#define DDSRT_STATIC_ASSERT_H
/* There are many tricks to use a constant expression to yield an
illegal type or expression at compile time, such as zero-sized
arrays and duplicate case or enum labels. So this is but one of the
many tricks. */
+#define DDSRT_STATIC_ASSERT2(line, pred) \
+ struct static_assert_##line { \
+ char cond[(pred) ? 1 : -1]; \
+ }
+#define DDSRT_STATIC_ASSERT1(line, pred) \
+ DDSRT_STATIC_ASSERT2 (line, pred)
+#define DDSRT_STATIC_ASSERT(pred) \
+ DDSRT_STATIC_ASSERT1 (__LINE__, pred)
+
#ifndef _MSC_VER
-
-#define Q_STATIC_ASSERT_CODE(pred) do { switch(0) { case 0: case pred: ; } } while (0)
-
+#define DDSRT_STATIC_ASSERT_CODE(pred) do { switch(0) { case 0: case (pred): ; } } while (0)
#else
-
/* Temporarily disabling warning C6326: Potential comparison of a
constant with another constant. */
-#define Q_STATIC_ASSERT_CODE(pred) do { \
+#define DDSRT_STATIC_ASSERT_CODE(pred) do { \
__pragma (warning (push)) \
__pragma (warning (disable : 6326)) \
- switch(0) { case 0: case pred: ; } \
+ switch(0) { case 0: case (pred): ; } \
__pragma (warning (pop)) \
} while (0)
-
#endif
-#endif /* Q_STATIC_ASSERT_H */
+#endif
diff --git a/src/ddsrt/include/dds/ddsrt/string.h b/src/ddsrt/include/dds/ddsrt/string.h
index 1d8f184..7fca58c 100644
--- a/src/ddsrt/include/dds/ddsrt/string.h
+++ b/src/ddsrt/include/dds/ddsrt/string.h
@@ -12,7 +12,6 @@
#ifndef DDSRT_STRING_H
#define DDSRT_STRING_H
-#include
#include "dds/export.h"
#include "dds/ddsrt/attributes.h"
#include "dds/ddsrt/retcode.h"
@@ -53,21 +52,6 @@ ddsrt_strncasecmp(
size_t n)
ddsrt_nonnull((1,2));
-/**
- * @brief Split string into tokens.
- *
- * @param[in] str String to split into tokens.
- * @param[in] delim Characters that delimit a token.
- * @param[inout] saveptr Pointer to a char * used internally.
- *
- * @returns The next token or NULL if there are no more tokens.
- */
-DDS_EXPORT char *
-ddsrt_strtok_r(
- char *str,
- const char *delim,
- char **saveptr);
-
/**
* @brief Extract token from string.
*
@@ -75,7 +59,7 @@ ddsrt_strtok_r(
* @delim. The delimiter is overwritten with a null byte, terminating the
* token and @stringp is updated to point past the delimiter.
*
- * @param[inout] stringp String to extract token from.
+ * @param[in,out] stringp String to extract token from.
* @param[in] delim Characters that delimit a token.
*
* @returns The original value of @stringp.
@@ -154,7 +138,7 @@ ddsrt_nonnull((1,2));
* string is truncated if there is not enough space. The resulting string
* guaranteed to be null terminated if there is space.
*
- * @param[inout] dest Destination buffer.
+ * @param[in,out] dest Destination buffer.
* @param[in] src Null terminated string to append to dest.
* @param[in] size Number of bytes available in dest.
*
@@ -170,8 +154,6 @@ ddsrt_strlcat(
size_t size)
ddsrt_nonnull((1,2));
-
-
/**
* @brief Get description for specified system error number.
*
@@ -179,7 +161,7 @@ ddsrt_nonnull((1,2));
* @param[in] buf Buffer where description is copied to.
* @param[in] buflen Number of bytes available in @buf.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Description for @errnum was successfully copied to @buf.
@@ -188,7 +170,7 @@ ddsrt_nonnull((1,2));
* @retval DDS_RETCODE_NOT_ENOUGH_SPACE
* Buffer was not large enough to hold the description.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_strerror_r(
int errnum,
char *buf,
diff --git a/src/ddsrt/include/dds/ddsrt/strtod.h b/src/ddsrt/include/dds/ddsrt/strtod.h
index f8bb511..4db08e7 100644
--- a/src/ddsrt/include/dds/ddsrt/strtod.h
+++ b/src/ddsrt/include/dds/ddsrt/strtod.h
@@ -34,9 +34,9 @@ extern "C" {
* character is stored.
* @param[out] dblptr A double where the result is stored.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_strtod(const char *nptr, char **endptr, double *dblptr);
/**
@@ -47,9 +47,9 @@ ddsrt_strtod(const char *nptr, char **endptr, double *dblptr);
* character is stored.
* @param[out] fltptr A float where the floating-point number is stored.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_strtof(const char *nptr, char **endptr, float *fltptr);
/**
diff --git a/src/ddsrt/include/dds/ddsrt/strtol.h b/src/ddsrt/include/dds/ddsrt/strtol.h
index a862c06..c4cb059 100644
--- a/src/ddsrt/include/dds/ddsrt/strtol.h
+++ b/src/ddsrt/include/dds/ddsrt/strtol.h
@@ -37,7 +37,7 @@ extern "C" {
* determine from @str.
* @param[out] llng A long long integer where the number is stored.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* String successfully converted to an integer.
@@ -46,7 +46,7 @@ extern "C" {
* @retval DDS_RETCODE_OUT_OF_RANGE
* String converted to an integer, but was out of range.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_strtoll(
const char *str,
char **endptr,
@@ -69,7 +69,7 @@ ddsrt_strtoll(
* determine from @str.
* @param[out] ullng A long long integer where the number is stored.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* String successfully converted to an integer.
@@ -78,7 +78,7 @@ ddsrt_strtoll(
* @retval DDS_RETCODE_OUT_OF_RANGE
* String converted to an integer, but was out of range.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_strtoull(
const char *str,
char **endptr,
@@ -91,7 +91,7 @@ ddsrt_strtoull(
* @param[in] str String to convert into a long long integer.
* @param[in] llng A long long integer where the number is stored.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* String successfully converted to an integer.
@@ -100,7 +100,7 @@ ddsrt_strtoull(
* @retval DDS_RETCODE_OUT_OF_RANGE
* String converted to an integer, but was out of range.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_atoll(
const char *str,
long long *llng);
@@ -111,7 +111,7 @@ ddsrt_atoll(
* @param[in] str String to conver into an unsigned long long integer.
* @param[out] ullng An unsigned long long integer where the number is stored.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* String successfully converted to an integer.
@@ -120,7 +120,7 @@ ddsrt_atoll(
* @retval DDS_RETCODE_OUT_OF_RANGE
* String converted to an integer, but was out of range.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_atoull(
const char *str,
unsigned long long *ullng);
diff --git a/src/ddsrt/include/dds/ddsrt/sync.h b/src/ddsrt/include/dds/ddsrt/sync.h
index 8228aab..a9e62e3 100644
--- a/src/ddsrt/include/dds/ddsrt/sync.h
+++ b/src/ddsrt/include/dds/ddsrt/sync.h
@@ -18,8 +18,12 @@
#include "dds/ddsrt/retcode.h"
#include "dds/ddsrt/attributes.h"
-#if _WIN32
+#if DDSRT_WITH_FREERTOS
+#include "dds/ddsrt/sync/freertos.h"
+#elif _WIN32
#include "dds/ddsrt/sync/windows.h"
+#elif __SunOS_5_6
+#include "dds/ddsrt/sync/solaris2.6.h"
#else
#include "dds/ddsrt/sync/posix.h"
#endif
diff --git a/src/ddsrt/include/dds/ddsrt/sync/freertos.h b/src/ddsrt/include/dds/ddsrt/sync/freertos.h
new file mode 100644
index 0000000..4d05578
--- /dev/null
+++ b/src/ddsrt/include/dds/ddsrt/sync/freertos.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+ * v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+#ifndef DDSRT_SYNC_FREERTOS_H
+#define DDSRT_SYNC_FREERTOS_H
+
+#include
+#include
+#include
+#include
+
+#include "dds/ddsrt/atomics.h"
+
+#if (INCLUDE_vTaskSuspend != 1)
+/* INCLUDE_vTaskSuspend must be set to 1 to make xSemaphoreTake wait
+ indefinitely when passed portMAX_DELAY. See reference manual. */
+#error "INCLUDE_vTaskSuspend != 1 in FreeRTOSConfig.h"
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef struct {
+ SemaphoreHandle_t sem;
+} ddsrt_mutex_t;
+
+typedef struct {
+ size_t len;
+ size_t cnt;
+ size_t off;
+ size_t end;
+ TaskHandle_t *tasks;
+} ddsrt_tasklist_t;
+
+typedef struct {
+ SemaphoreHandle_t sem;
+ ddsrt_tasklist_t tasks;
+} ddsrt_cond_t;
+
+/* This readers-writer lock implementation does not prefer writers over readers
+ or vice versa. Multiple readers are allowed to hold the lock simultaneously
+ and can acquire it directly if no writers are queued. However, if a writer
+ is queued, new readers and writers are queued behind it in order. Any reader
+ that acquires the lock after a writer frees it, notifies the next task. If
+ that task tries to acquire a write lock it waits until the reader frees the
+ lock. However, if the task tries to acquire a read lock it will succeed, and
+ notify the next task, etc. */
+typedef struct {
+ SemaphoreHandle_t sem;
+ ddsrt_tasklist_t tasks;
+ int32_t state;
+ uint32_t cnt;
+ uint32_t rdcnt;
+ uint32_t wrcnt;
+} ddsrt_rwlock_t;
+
+typedef ddsrt_atomic_uint32_t ddsrt_once_t;
+#define DDSRT_ONCE_INIT { .v = (1<<0) /* ONCE_NOT_STARTED */ }
+
+
+/* The declarations below are here for tests and must be considered private. */
+
+/* Number of buckets to grow buffer by. */
+#define DDSRT_TASKLIST_CHUNK (5)
+/* Number of buckets to allocate initially. */
+#define DDSRT_TASKLIST_INITIAL (DDSRT_TASKLIST_CHUNK * 2)
+
+int ddsrt_tasklist_init(ddsrt_tasklist_t *list);
+void ddsrt_tasklist_fini(ddsrt_tasklist_t *list);
+void ddsrt_tasklist_ltrim(ddsrt_tasklist_t *list);
+void ddsrt_tasklist_rtrim(ddsrt_tasklist_t *list);
+void ddsrt_tasklist_pack(ddsrt_tasklist_t *list);
+int ddsrt_tasklist_shrink(ddsrt_tasklist_t *list);
+int ddsrt_tasklist_grow(ddsrt_tasklist_t *list);
+ssize_t ddsrt_tasklist_find(ddsrt_tasklist_t *list, TaskHandle_t task);
+TaskHandle_t ddsrt_tasklist_peek(ddsrt_tasklist_t *list, TaskHandle_t task);
+TaskHandle_t ddsrt_tasklist_pop(ddsrt_tasklist_t *list, TaskHandle_t task);
+int ddsrt_tasklist_push(ddsrt_tasklist_t *list, TaskHandle_t task);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* DDSRT_SYNC_FREERTOS_H */
diff --git a/src/ddsrt/include/dds/ddsrt/sync/solaris2.6.h b/src/ddsrt/include/dds/ddsrt/sync/solaris2.6.h
new file mode 100644
index 0000000..34b1956
--- /dev/null
+++ b/src/ddsrt/include/dds/ddsrt/sync/solaris2.6.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+ * v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+#ifndef DDSRT_POSIX_SYNC_H
+#define DDSRT_POSIX_SYNC_H
+
+#include
+#include
+#if HAVE_LKST
+#include "lkst.h"
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef struct {
+ pthread_cond_t cond;
+} ddsrt_cond_t;
+
+typedef struct {
+ pthread_mutex_t mutex;
+} ddsrt_mutex_t;
+
+typedef struct {
+ pthread_mutex_t rwlock;
+} ddsrt_rwlock_t;
+
+typedef pthread_once_t ddsrt_once_t;
+#define DDSRT_ONCE_INIT PTHREAD_ONCE_INIT
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* DDSRT_POSIX_SYNC_H */
diff --git a/src/ddsrt/include/dds/ddsrt/thread_pool.h b/src/ddsrt/include/dds/ddsrt/thread_pool.h
index f03fe46..4bcdc77 100644
--- a/src/ddsrt/include/dds/ddsrt/thread_pool.h
+++ b/src/ddsrt/include/dds/ddsrt/thread_pool.h
@@ -55,7 +55,7 @@ DDS_EXPORT void ddsrt_thread_pool_purge (ddsrt_thread_pool pool);
Note that if the pool queue has reached it's maximum DDS_RETCODE_TRY_AGAIN is returned.
*/
-DDS_EXPORT dds_retcode_t ddsrt_thread_pool_submit
+DDS_EXPORT dds_return_t ddsrt_thread_pool_submit
(
ddsrt_thread_pool pool, /* Thread pool instance */
void (*fn) (void *arg), /* Function to be invoked by thread from pool */
diff --git a/src/ddsrt/include/dds/ddsrt/threads.h b/src/ddsrt/include/dds/ddsrt/threads.h
index 7497002..e258218 100644
--- a/src/ddsrt/include/dds/ddsrt/threads.h
+++ b/src/ddsrt/include/dds/ddsrt/threads.h
@@ -25,7 +25,9 @@
#include "dds/ddsrt/attributes.h"
#include "dds/ddsrt/retcode.h"
-#if _WIN32
+#if DDSRT_WITH_FREERTOS
+#include "dds/ddsrt/threads/freertos.h"
+#elif _WIN32
#include "dds/ddsrt/threads/windows.h"
#else
#include "dds/ddsrt/threads/posix.h"
@@ -119,14 +121,14 @@ ddsrt_nonnull_all;
* @param[in] start_routine Function to execute in created thread.
* @param[in] arg Argument passed to @start_routine.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Thread successfully created.
* @retval DDS_RETCODE_ERROR
* Thread could not be created.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_thread_create(
ddsrt_thread_t *thread,
const char *name,
@@ -170,14 +172,14 @@ ddsrt_thread_equal(ddsrt_thread_t t1, ddsrt_thread_t t2);
* @param[in] thread Id of thread to wait for.
* @param[out] thread_result Location where thread result is stored.
*
- * @returns A dds_retcode_t indicating success or failure.
+ * @returns A dds_return_t indicating success or failure.
*
* @retval DDS_RETCODE_OK
* Target thread terminated.
* @retval DDS_RETCODE_ERROR
* An error occurred while waiting for the thread to terminate.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_thread_join(
ddsrt_thread_t thread,
uint32_t *thread_result);
@@ -206,9 +208,58 @@ ddsrt_thread_getname(
*
* @param[in] name Name for current thread.
*/
+#if DDSRT_HAVE_THREAD_SETNAME
DDS_EXPORT void
ddsrt_thread_setname(
const char *__restrict name);
+#endif
+
+#if DDSRT_HAVE_THREAD_LIST
+/**
+ * @brief Get a list of threads in the calling process
+ *
+ * @param[out] tids Array of size elements to be filled with thread
+ * identifiers, may be NULL if size is 0
+ * @param[in] size The size of the tids array; 0 is allowed
+ *
+ * @returns A dds_return_t indicating the number of threads in the process
+ * or an error code on failure.
+ *
+ * @retval > 0
+ * Number of threads in the process, may be larger than size
+ * tids[0 .. (return - 1)] are valid
+ * @retval DDS_RETCODE_ERROR
+ * Something went wrong, contents of tids is undefined
+ * @retval DDS_RETCODE_UNSUPPORTED
+ * Not supported on the platform
+ */
+DDS_EXPORT dds_return_t ddsrt_thread_list (ddsrt_thread_list_id_t * __restrict tids, size_t size);
+
+/**
+ * @brief Get the name of the specified thread (in the calling process)
+ *
+ * @param[in] tid Thread identifier for which the name is sought
+ * @param[out] name Filled with the thread name (or a synthesized one)
+ * on successful return; name is silently truncated
+ * if the actual name is longer than name can hold;
+ * always 0-terminated if size > 0
+ * @param[in] size Number of bytes of name that may be assigned, size
+ * is 0 is allowed, though somewhat useless
+ *
+ * @returns A dds_return_t indicating success or failure.
+ *
+ * @retval DDS_RETCODE_OK
+ * Possibly truncated name is returned as a null-terminated
+ * string in name (provided size > 0).
+ * @retval DDS_RETCODE_NOT_FOUND
+ * Thread not found; the contents of name is unchanged
+ * @retval DDS_RETCODE_ERROR
+ * Unspecified failure, the contents of name is undefined
+ * @retval DDS_RETCODE_UNSUPPORTED
+ * Not supported on the platform
+ */
+DDS_EXPORT dds_return_t ddsrt_thread_getname_anythread (ddsrt_thread_list_id_t tid, char *__restrict name, size_t size);
+#endif
/**
* @brief Push cleanup handler onto the cleanup stack
@@ -220,7 +271,7 @@ ddsrt_thread_setname(
* @param[in] routine Cleanup handler to push onto the thread cleanup stack.
* @param[in] arg Argument that will be passed to the cleanup handler.
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_thread_cleanup_push(
void (*routine)(void*),
void *arg);
@@ -231,7 +282,7 @@ ddsrt_thread_cleanup_push(
* Remove routine at the top of the calling thread's cleanup stack and
* optionally invoke it (if execute is non-zero).
*/
-DDS_EXPORT dds_retcode_t
+DDS_EXPORT dds_return_t
ddsrt_thread_cleanup_pop(
int execute);
diff --git a/src/ddsrt/include/dds/ddsrt/threads/freertos.h b/src/ddsrt/include/dds/ddsrt/threads/freertos.h
new file mode 100644
index 0000000..50b517f
--- /dev/null
+++ b/src/ddsrt/include/dds/ddsrt/threads/freertos.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+ * v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+#ifndef DDSRT_THREADS_FREERTOS_H
+#define DDSRT_THREADS_FREERTOS_H
+
+#include
+#include
+
+#define DDSRT_HAVE_THREAD_SETNAME (0)
+#define DDSRT_HAVE_THREAD_LIST (0)
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef struct {
+ TaskHandle_t task;
+} ddsrt_thread_t;
+
+typedef UBaseType_t ddsrt_tid_t;
+#define PRIdTID "lu"
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* DDSRT_THREADS_FREERTOS_H */
diff --git a/src/ddsrt/include/dds/ddsrt/threads/posix.h b/src/ddsrt/include/dds/ddsrt/threads/posix.h
index 63d193d..9324c73 100644
--- a/src/ddsrt/include/dds/ddsrt/threads/posix.h
+++ b/src/ddsrt/include/dds/ddsrt/threads/posix.h
@@ -14,6 +14,17 @@
#include
+#if defined(__VXWORKS__)
+#define DDSRT_HAVE_THREAD_SETNAME (0)
+#else
+#define DDSRT_HAVE_THREAD_SETNAME (1)
+#endif
+#if defined (__linux) || defined (__APPLE__)
+#define DDSRT_HAVE_THREAD_LIST (1)
+#else
+#define DDSRT_HAVE_THREAD_LIST (0)
+#endif
+
#if defined (__cplusplus)
extern "C" {
#endif
@@ -21,6 +32,7 @@ extern "C" {
#if defined(__linux)
typedef long int ddsrt_tid_t;
#define PRIdTID "ld"
+typedef long int ddsrt_thread_list_id_t;
/* __linux */
#elif defined(__FreeBSD__) && (__FreeBSD_version >= 900031)
/* FreeBSD >= 9.0 */
@@ -32,6 +44,8 @@ typedef int ddsrt_tid_t;
/* macOS X >= 10.6 */
typedef uint64_t ddsrt_tid_t;
#define PRIdTID PRIu64
+/* ddsrt_thread_list_id_t is actually a mach_port_t */
+typedef uint32_t ddsrt_thread_list_id_t;
/* __APPLE__ */
#elif defined(__VXWORKS__)
/* TODO: Verify taskIdSelf is the right function to use on VxWorks */
@@ -43,7 +57,7 @@ typedef TASK_ID ddsrt_tid_t;
# endif
/* __VXWORKS__ */
#else
-typedef uintmax_t ddsrt_tid_t;
+typedef uintptr_t ddsrt_tid_t;
#define PRIdTID PRIuPTR
#endif
diff --git a/src/ddsrt/include/dds/ddsrt/threads/windows.h b/src/ddsrt/include/dds/ddsrt/threads/windows.h
index e7eda64..1fdce54 100644
--- a/src/ddsrt/include/dds/ddsrt/threads/windows.h
+++ b/src/ddsrt/include/dds/ddsrt/threads/windows.h
@@ -14,6 +14,9 @@
#include "dds/ddsrt/types.h"
+#define DDSRT_HAVE_THREAD_SETNAME (1)
+#define DDSRT_HAVE_THREAD_LIST (1)
+
#if defined (__cplusplus)
extern "C" {
#endif
@@ -26,6 +29,8 @@ typedef struct {
typedef DWORD ddsrt_tid_t;
#define PRIdTID "u"
+typedef HANDLE ddsrt_thread_list_id_t;
+
#if defined (__cplusplus)
}
#endif
diff --git a/src/ddsrt/include/dds/ddsrt/time.h b/src/ddsrt/include/dds/ddsrt/time.h
index 37fcfa3..a474fb4 100644
--- a/src/ddsrt/include/dds/ddsrt/time.h
+++ b/src/ddsrt/include/dds/ddsrt/time.h
@@ -146,4 +146,8 @@ DDS_EXPORT size_t ddsrt_ctime(dds_time_t abstime, char *str, size_t size);
}
#endif
+#if DDSRT_WITH_FREERTOS
+#include "dds/ddsrt/time/freertos.h"
+#endif
+
#endif /* DDSRT_TIME_H */
diff --git a/src/ddsrt/include/dds/ddsrt/time/freertos.h b/src/ddsrt/include/dds/ddsrt/time/freertos.h
new file mode 100644
index 0000000..09525ee
--- /dev/null
+++ b/src/ddsrt/include/dds/ddsrt/time/freertos.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
+ * v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+#ifndef DDSRT_TIME_FREERTOS_H
+#define DDSRT_TIME_FREERTOS_H
+
+#include
+#include
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define DDSRT_NSECS_PER_TICK (DDS_NSECS_IN_SEC / configTICK_RATE_HZ)
+
+inline TickType_t
+ddsrt_duration_to_ticks_ceil(
+ dds_duration_t reltime)
+{
+ TickType_t ticks = 0;
+
+ assert(portMAX_DELAY > configTICK_RATE_HZ);
+
+ if (reltime == DDS_INFINITY) {
+ ticks = portMAX_DELAY;
+ } else if (reltime > 0) {
+ dds_duration_t max_nsecs =
+ (DDS_INFINITY / DDSRT_NSECS_PER_TICK < portMAX_DELAY
+ ? DDS_INFINITY - 1 : portMAX_DELAY * DDSRT_NSECS_PER_TICK);
+
+ if (reltime > max_nsecs - (DDSRT_NSECS_PER_TICK - 1)) {
+ ticks = portMAX_DELAY;
+ } else {
+ ticks = (TickType_t)((reltime + (DDSRT_NSECS_PER_TICK - 1)) / DDSRT_NSECS_PER_TICK);
+ }
+ }
+
+ return ticks;
+}
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* DDSRT_TIME_FREERTOS_H */
diff --git a/src/ddsrt/include/dds/ddsrt/types/posix.h b/src/ddsrt/include/dds/ddsrt/types/posix.h
index 6088737..1344dc1 100644
--- a/src/ddsrt/include/dds/ddsrt/types/posix.h
+++ b/src/ddsrt/include/dds/ddsrt/types/posix.h
@@ -14,6 +14,10 @@
#include
#include
+#if defined(__IAR_SYSTEMS_ICC__)
+typedef long int ssize_t;
+#else
#include
+#endif
#endif /* DDSRT_TYPES_POSIX_H */
diff --git a/src/ddsrt/include/dds/ddsrt/xmlparser.h b/src/ddsrt/include/dds/ddsrt/xmlparser.h
index e33815b..93bd92d 100644
--- a/src/ddsrt/include/dds/ddsrt/xmlparser.h
+++ b/src/ddsrt/include/dds/ddsrt/xmlparser.h
@@ -20,10 +20,10 @@
extern "C" {
#endif
- typedef int (*ddsrt_xmlp_proc_elem_open_t) (void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name);
- typedef int (*ddsrt_xmlp_proc_attr_t) (void *varg, uintptr_t eleminfo, const char *name, const char *value);
- typedef int (*ddsrt_xmlp_proc_elem_data_t) (void *varg, uintptr_t eleminfo, const char *data);
- typedef int (*ddsrt_xmlp_proc_elem_close_t) (void *varg, uintptr_t eleminfo);
+ typedef int (*ddsrt_xmlp_proc_elem_open_t) (void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name, int line);
+ typedef int (*ddsrt_xmlp_proc_attr_t) (void *varg, uintptr_t eleminfo, const char *name, const char *value, int line);
+ typedef int (*ddsrt_xmlp_proc_elem_data_t) (void *varg, uintptr_t eleminfo, const char *data, int line);
+ typedef int (*ddsrt_xmlp_proc_elem_close_t) (void *varg, uintptr_t eleminfo, int line);
typedef void (*ddsrt_xmlp_error) (void *varg, const char *msg, int line);
struct ddsrt_xmlp_callbacks {
@@ -36,9 +36,9 @@ extern "C" {
struct ddsrt_xmlp_state;
-#define DDSRT_XMLP_REQUIRE_EOF 1u /* set by default; if not set, junk may follow top-level closing tag */
-#define DDSRT_XMLP_ANONYMOUS_CLOSE_TAG 2u /* clear by default; if set allow closing an element with > instead of */
-
+#define DDSRT_XMLP_REQUIRE_EOF 1u /* set by default; if not set, junk may follow top-level closing tag */
+#define DDSRT_XMLP_ANONYMOUS_CLOSE_TAG 2u /* clear by default; if set allow closing an element with > instead of */
+#define DDSRT_XMLP_MISSING_CLOSE_AS_EOF 4u /* clear by default; if set, treat missing close tag as EOF */
DDS_EXPORT struct ddsrt_xmlp_state *ddsrt_xmlp_new_file (FILE *fp, void *varg, const struct ddsrt_xmlp_callbacks *cb);
DDS_EXPORT struct ddsrt_xmlp_state *ddsrt_xmlp_new_string (const char *string, void *varg, const struct ddsrt_xmlp_callbacks *cb);
DDS_EXPORT void ddsrt_xmlp_set_options (struct ddsrt_xmlp_state *st, unsigned options);
@@ -46,8 +46,6 @@ extern "C" {
DDS_EXPORT void ddsrt_xmlp_free (struct ddsrt_xmlp_state *st);
DDS_EXPORT int ddsrt_xmlp_parse (struct ddsrt_xmlp_state *st);
- DDS_EXPORT int ddsrt_xmlUnescapeInsitu (char *buffer, size_t *n);
-
#if defined (__cplusplus)
}
#endif
diff --git a/src/ddsrt/src/atomics.c b/src/ddsrt/src/atomics.c
index bc87a7b..829be41 100644
--- a/src/ddsrt/src/atomics.c
+++ b/src/ddsrt/src/atomics.c
@@ -30,6 +30,7 @@ extern inline void ddsrt_atomic_inc32 (volatile ddsrt_atomic_uint32_t *x);
extern inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x);
#endif
extern inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x);
+extern inline uint32_t ddsrt_atomic_inc32_ov (volatile ddsrt_atomic_uint32_t *x);
extern inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x);
#if DDSRT_HAVE_ATOMIC64
extern inline uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x);
@@ -58,6 +59,7 @@ extern inline void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64
#endif
extern inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v);
extern inline void ddsrt_atomic_addvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v);
+extern inline uint32_t ddsrt_atomic_add32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
extern inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
#if DDSRT_HAVE_ATOMIC64
extern inline uint64_t ddsrt_atomic_add64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
@@ -71,6 +73,7 @@ extern inline void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64
#endif
extern inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v);
extern inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v);
+extern inline uint32_t ddsrt_atomic_sub32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
extern inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
#if DDSRT_HAVE_ATOMIC64
extern inline uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
@@ -122,6 +125,7 @@ extern inline int ddsrt_atomic_casvoidp2 (volatile ddsrt_atomic_uintptr2_t *x, u
/* FENCES */
extern inline void ddsrt_atomic_fence (void);
extern inline void ddsrt_atomic_fence_ldld (void);
+extern inline void ddsrt_atomic_fence_stst (void);
extern inline void ddsrt_atomic_fence_acq (void);
extern inline void ddsrt_atomic_fence_rel (void);
@@ -161,3 +165,182 @@ void ddsrt_atomic_lifo_pushmany (ddsrt_atomic_lifo_t *head, void *first, void *l
} while (!ddsrt_atomic_casvoidp2 (&head->aba_head, a0, b0, a0+1, (uintptr_t)first));
}
#endif
+
+/* On platforms that don't provide 64-bit atomic operations, emulate them by hashing
+ the variable's address to a small set of mutexes.
+
+ This also defines the GCC builtins on SPARCv8 for 32-bit operations. It would be
+ more appropriate to simply define the ddsrt_atomic_... functions properly in that
+ case and avoid squatting in the __sync_... namespace, but SPARCv8 support really
+ is just for fun and it doesn't seem worth the bother right now */
+
+#if DDSRT_HAVE_ATOMIC64
+
+void ddsrt_atomics_init (void) { }
+void ddsrt_atomics_fini (void) { }
+
+#else
+
+#include "dds/ddsrt/sync.h"
+
+/* SPARCv8 depends on these mutexes already for one-shot initialisation of the ddsrt
+ code. Using PTHREAD_MUTEX_INITIALIZER guarantees they are properly initialized.
+ Once a platform shows up that defines that macro where we don't used pthread mutexes
+ something else will have to be done. */
+#define N_MUTEXES_LG2 4
+#define N_MUTEXES (1 << N_MUTEXES_LG2)
+#ifndef PTHREAD_MUTEX_INITIALIZER
+static ddsrt_mutex_t mutexes[N_MUTEXES];
+
+void ddsrt_atomics_init (void)
+{
+ for (int i = 0; i < N_MUTEXES; i++)
+ ddsrt_mutex_init (&mutexes[i]);
+}
+
+void ddsrt_atomics_fini (void)
+{
+ for (int i = 0; i < N_MUTEXES; i++)
+ ddsrt_mutex_destroy (&mutexes[i]);
+}
+#else
+static ddsrt_mutex_t mutexes[N_MUTEXES] = {
+ { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
+ { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
+ { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
+ { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
+ { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
+ { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
+ { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
+ { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }
+};
+void ddsrt_atomics_init (void) { }
+void ddsrt_atomics_fini (void) { }
+#endif
+
+static uint32_t atomic64_lock_index (const volatile ddsrt_atomic_uint64_t *x)
+{
+ const uint32_t u = (uint16_t) ((uintptr_t) x >> 3);
+ const uint32_t v = u * 0xb4817365;
+ return v >> (32 - N_MUTEXES_LG2);
+}
+
+int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_t exp, uint64_t des)
+{
+ const uint32_t idx = atomic64_lock_index (x);
+ ddsrt_mutex_lock (&mutexes[idx]);
+ if (x->v == exp)
+ {
+ x->v = des;
+ ddsrt_mutex_unlock (&mutexes[idx]);
+ return true;
+ }
+ else
+ {
+ ddsrt_mutex_unlock (&mutexes[idx]);
+ return false;
+ }
+}
+
+#define DDSRT_FAKE_ATOMIC64(name, oper, ret) \
+ uint64_t ddsrt_atomic_##name##64_##ret (volatile ddsrt_atomic_uint64_t *x, uint64_t v) \
+ { \
+ const uint64_t idx = atomic64_lock_index (x); \
+ ddsrt_mutex_lock (&mutexes[idx]); \
+ const uint64_t ov = x->v; \
+ const uint64_t nv = ov oper v; \
+ x->v = nv; \
+ ddsrt_mutex_unlock (&mutexes[idx]); \
+ return ret; \
+ }
+#define DDSRT_FAKE_ATOMIC64_TRIPLET(name, oper) \
+ DDSRT_FAKE_ATOMIC64(name, oper, nv) \
+ DDSRT_FAKE_ATOMIC64(name, oper, ov) \
+ void ddsrt_atomic_##name##64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) { \
+ (void) ddsrt_atomic_##name##64_ov (x, v); \
+ }
+
+uint64_t ddsrt_atomic_ld64 (const volatile ddsrt_atomic_uint64_t *x)
+{
+ const uint32_t idx = atomic64_lock_index (x);
+ ddsrt_mutex_lock (&mutexes[idx]);
+ const uint64_t v = x->v;
+ ddsrt_mutex_unlock (&mutexes[idx]);
+ return v;
+}
+
+void ddsrt_atomic_st64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v)
+{
+ const uint32_t idx = atomic64_lock_index (x);
+ ddsrt_mutex_lock (&mutexes[idx]);
+ x->v = v;
+ ddsrt_mutex_unlock (&mutexes[idx]);
+}
+
+DDSRT_FAKE_ATOMIC64_TRIPLET(add, +)
+DDSRT_FAKE_ATOMIC64_TRIPLET(sub, -)
+DDSRT_FAKE_ATOMIC64_TRIPLET(or, |)
+DDSRT_FAKE_ATOMIC64_TRIPLET(and, &)
+
+void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) {
+ ddsrt_atomic_add64 (x, 1);
+}
+uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x) {
+ return ddsrt_atomic_add64_nv (x, 1);
+}
+void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x) {
+ ddsrt_atomic_sub64 (x, 1);
+}
+uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x) {
+ return ddsrt_atomic_sub64_nv (x, 1);
+}
+
+#undef DDSRT_FAKE_ATOMIC64_TRIPLET
+#undef DDSRT_FAKE_ATOMIC64
+
+/* SPARCv8 doesn't support any atomic operations beyond a simple atomic exchange. GCC happily
+ compiles the __sync_* functions into library calls, and implementing them as such will do
+ the trick. The rarity of SPARCv8 machines (EOL'd 2 decades ago) */
+#ifdef __sparc_v8__
+#define DDSRT_FAKE_SYNC(name, size, oper, ret) \
+ unsigned __sync_##name##_##size (volatile unsigned *x, unsigned v) \
+ { \
+ const uint32_t idx = atomic64_lock_index ((const volatile ddsrt_atomic_uint64_t *) x); \
+ ddsrt_mutex_lock (&mutexes[idx]); \
+ const uint32_t ov = *x; \
+ const uint32_t nv = ov oper v; \
+ *x = nv; \
+ ddsrt_mutex_unlock (&mutexes[idx]); \
+ return ret; \
+ }
+#define DDSRT_FAKE_SYNC_PAIR(name, size, oper) \
+ DDSRT_FAKE_SYNC(name##_and_fetch, size, oper, nv) \
+ DDSRT_FAKE_SYNC(fetch_and_##name, size, oper, ov)
+
+DDSRT_FAKE_SYNC_PAIR (add, 4, +)
+DDSRT_FAKE_SYNC_PAIR (sub, 4, -)
+DDSRT_FAKE_SYNC_PAIR (or, 4, |)
+DDSRT_FAKE_SYNC_PAIR (and, 4, &)
+
+bool __sync_bool_compare_and_swap_4 (volatile unsigned *x, unsigned exp, unsigned des)
+{
+ const uint32_t idx = atomic64_lock_index ((const volatile ddsrt_atomic_uint64_t *) x);
+ ddsrt_mutex_lock (&mutexes[idx]);
+ if (*x == exp)
+ {
+ *x = des;
+ ddsrt_mutex_unlock (&mutexes[idx]);
+ return true;
+ }
+ else
+ {
+ ddsrt_mutex_unlock (&mutexes[idx]);
+ return false;
+ }
+}
+
+#undef DDSRT_FAKE_SYNC_PAIR
+#undef DDSRT_FAKE_SYNC
+#endif /* SPARCv8 hack */
+
+#endif /* DDSRT_HAVE_ATOMIC64 */
diff --git a/src/ddsrt/src/cdtors.c b/src/ddsrt/src/cdtors.c
index 3888c87..e184098 100644
--- a/src/ddsrt/src/cdtors.c
+++ b/src/ddsrt/src/cdtors.c
@@ -43,6 +43,7 @@ retry:
ddsrt_time_init();
#endif
ddsrt_random_init();
+ ddsrt_atomics_init();
ddsrt_atomic_or32(&init_status, INIT_STATUS_OK);
} else {
while (v > 1 && !(v & INIT_STATUS_OK)) {
@@ -68,6 +69,7 @@ void ddsrt_fini (void)
{
ddsrt_mutex_destroy(&init_mutex);
ddsrt_random_fini();
+ ddsrt_atomics_fini();
#if _WIN32
ddsrt_winsock_fini();
ddsrt_time_fini();
@@ -139,6 +141,9 @@ ddsrt_cdtor(
#pragma data_seg()
#endif
#else /* _WIN32 */
+void __attribute__((constructor)) ddsrt_ctor(void);
+void __attribute__((destructor)) ddsrt_dtor(void);
+
void __attribute__((constructor)) ddsrt_ctor(void)
{
ddsrt_init();
diff --git a/src/ddsrt/src/dynlib/posix/dynlib.c b/src/ddsrt/src/dynlib/posix/dynlib.c
index cb538d8..ec97397 100644
--- a/src/ddsrt/src/dynlib/posix/dynlib.c
+++ b/src/ddsrt/src/dynlib/posix/dynlib.c
@@ -17,9 +17,9 @@
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/io.h"
-dds_retcode_t ddsrt_dlopen(const char *name, bool translate,
+dds_return_t ddsrt_dlopen(const char *name, bool translate,
ddsrt_dynlib_t *handle) {
- dds_retcode_t retcode = DDS_RETCODE_OK;
+ dds_return_t retcode = DDS_RETCODE_OK;
assert( handle );
*handle = NULL;
@@ -53,16 +53,16 @@ dds_retcode_t ddsrt_dlopen(const char *name, bool translate,
return retcode;
}
-dds_retcode_t ddsrt_dlclose(ddsrt_dynlib_t handle) {
+dds_return_t ddsrt_dlclose(ddsrt_dynlib_t handle) {
assert ( handle );
return (dlclose(handle) == 0) ? DDS_RETCODE_OK : DDS_RETCODE_ERROR;
}
-dds_retcode_t ddsrt_dlsym(ddsrt_dynlib_t handle, const char *symbol,
+dds_return_t ddsrt_dlsym(ddsrt_dynlib_t handle, const char *symbol,
void **address) {
- dds_retcode_t retcode = DDS_RETCODE_OK;
+ dds_return_t retcode = DDS_RETCODE_OK;
assert( handle );
assert( address );
@@ -76,10 +76,10 @@ dds_retcode_t ddsrt_dlsym(ddsrt_dynlib_t handle, const char *symbol,
return retcode;
}
-dds_retcode_t ddsrt_dlerror(char *buf, size_t buflen) {
+dds_return_t ddsrt_dlerror(char *buf, size_t buflen) {
const char *err;
- dds_retcode_t retcode = DDS_RETCODE_OK;
+ dds_return_t retcode = DDS_RETCODE_OK;
assert (buf );
diff --git a/src/ddsrt/src/environ/posix/environ.c b/src/ddsrt/src/environ/posix/environ.c
index b05769c..1f8b84f 100644
--- a/src/ddsrt/src/environ/posix/environ.c
+++ b/src/ddsrt/src/environ/posix/environ.c
@@ -23,7 +23,7 @@ isenvvar(const char *name)
return (*name == '\0' || strchr(name, '=') != NULL) == 0;
}
-dds_retcode_t
+dds_return_t
ddsrt_getenv(const char *name, char **value)
{
char *env;
@@ -40,7 +40,7 @@ ddsrt_getenv(const char *name, char **value)
return DDS_RETCODE_NOT_FOUND;
}
-dds_retcode_t
+dds_return_t
ddsrt_setenv(const char *name, const char *value)
{
assert(name != NULL);
@@ -65,7 +65,7 @@ ddsrt_setenv(const char *name, const char *value)
return DDS_RETCODE_ERROR;
}
-dds_retcode_t
+dds_return_t
ddsrt_unsetenv(const char *name)
{
assert(name != NULL);
diff --git a/src/ddsrt/src/environ/solaris2.6/environ.c b/src/ddsrt/src/environ/solaris2.6/environ.c
new file mode 100644
index 0000000..83f0d8f
--- /dev/null
+++ b/src/ddsrt/src/environ/solaris2.6/environ.c
@@ -0,0 +1,100 @@
+/*
+ * 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
+#include
+#include
+#include
+#include
+
+#include "dds/ddsrt/environ.h"
+#include "dds/ddsrt/retcode.h"
+
+extern char **environ;
+
+static int
+isenvvar(const char *name)
+{
+ return (*name == '\0' || strchr(name, '=') != NULL) == 0;
+}
+
+dds_return_t
+ddsrt_getenv(const char *name, char **value)
+{
+ char *env;
+
+ assert(name != NULL);
+ assert(value != NULL);
+
+ if (!isenvvar(name))
+ return DDS_RETCODE_BAD_PARAMETER;
+ if ((env = getenv(name)) != NULL) {
+ *value = env;
+ return DDS_RETCODE_OK;
+ }
+ return DDS_RETCODE_NOT_FOUND;
+}
+
+dds_return_t
+ddsrt_setenv(const char *name, const char *value)
+{
+ /* Not MT-Safe -- but it is only used in a tests to set
+ CYCLONEDDS_URI, so for Solaris 2.6 support it is not worth the
+ bother to do a better job. Same for a bit of leakage. */
+ assert(name != NULL);
+ assert(value != NULL);
+
+ if (strlen(value) == 0)
+ return ddsrt_unsetenv(name);
+ if (!isenvvar(name))
+ return DDS_RETCODE_BAD_PARAMETER;
+
+ const size_t namelen = strlen (name);
+ const size_t entrysize = namelen + 1 + strlen (value) + 1;
+ char *entry = malloc (entrysize);
+ snprintf (entry, entrysize, "%s=%s", name, value);
+ size_t n = 0;
+ while (environ[n] != NULL)
+ {
+ if (strncmp (environ[n], name, namelen) == 0 && environ[n][namelen] == '=')
+ {
+ environ[n] = entry;
+ return DDS_RETCODE_OK;
+ }
+ n++;
+ }
+ environ = realloc (environ, (n + 2) * sizeof (*environ));
+ environ[n] = entry;
+ environ[n+1] = NULL;
+ return DDS_RETCODE_OK;
+}
+
+dds_return_t
+ddsrt_unsetenv(const char *name)
+{
+ /* Same considerations as setenv. */
+ assert(name != NULL);
+
+ if (!isenvvar(name))
+ return DDS_RETCODE_BAD_PARAMETER;
+
+ const size_t namelen = strlen (name);
+ size_t n = 0, idx = SIZE_MAX;
+ while (environ[n] != NULL)
+ {
+ if (idx > n && strncmp (environ[n], name, namelen) == 0 && environ[n][namelen] == '=')
+ idx = n;
+ n++;
+ }
+ if (idx < n)
+ memmove (&environ[idx], &environ[idx + 1], (n - idx) * sizeof (*environ));
+ return DDS_RETCODE_OK;
+}
diff --git a/src/ddsrt/src/environ/windows/environ.c b/src/ddsrt/src/environ/windows/environ.c
index 076aea1..a5b2f90 100644
--- a/src/ddsrt/src/environ/windows/environ.c
+++ b/src/ddsrt/src/environ/windows/environ.c
@@ -25,7 +25,7 @@ isenvvar(const char *name)
}
DDSRT_WARNING_MSVC_OFF(4996)
-dds_retcode_t
+dds_return_t
ddsrt_getenv(const char *name, char **value)
{
char *env;
@@ -43,7 +43,7 @@ ddsrt_getenv(const char *name, char **value)
}
DDSRT_WARNING_MSVC_ON(4996)
-dds_retcode_t
+dds_return_t
ddsrt_setenv(const char *name, const char *value)
{
assert(name != NULL);
@@ -65,7 +65,7 @@ ddsrt_setenv(const char *name, const char *value)
return DDS_RETCODE_ERROR;
}
-dds_retcode_t
+dds_return_t
ddsrt_unsetenv(const char *name)
{
assert(name != NULL);
diff --git a/src/ddsrt/src/expand_envvars.c b/src/ddsrt/src/expand_envvars.c
index dbaa33a..bd988c7 100644
--- a/src/ddsrt/src/expand_envvars.c
+++ b/src/ddsrt/src/expand_envvars.c
@@ -19,8 +19,9 @@
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/log.h"
#include "dds/ddsrt/string.h"
+#include "dds/ddsrt/process.h"
-typedef char * (*expand_fn)(const char *src0);
+typedef char * (*expand_fn)(const char *src0, uint32_t domid);
static void expand_append (char **dst, size_t *sz, size_t *pos, char c)
{
@@ -32,34 +33,46 @@ static void expand_append (char **dst, size_t *sz, size_t *pos, char c)
(*pos)++;
}
-static char *expand_env (const char *name, char op, const char *alt, expand_fn expand)
+static char *expand_env (const char *name, char op, const char *alt, expand_fn expand, uint32_t domid)
{
+ char idstr[20];
char *env = NULL;
- (void)ddsrt_getenv (name, &env);
+ dds_return_t ret;
+
+ if ((ret = ddsrt_getenv (name, &env)) == DDS_RETCODE_OK) {
+ /* ok */
+ } else if (strcmp (name, "$") == 0 || strcmp (name, "CYCLONEDDS_PID") == 0) {
+ snprintf (idstr, sizeof (idstr), "%"PRIdPID, ddsrt_getpid ());
+ env = idstr;
+ } else if (strcmp (name, "CYCLONEDDS_DOMAIN_ID") == 0 && domid != UINT32_MAX) {
+ snprintf (idstr, sizeof (idstr), "%"PRIu32, domid);
+ env = idstr;
+ }
+
switch (op)
{
case 0:
return ddsrt_strdup (env ? env : "");
case '-':
- return env && *env ? ddsrt_strdup (env) : expand (alt);
+ return env && *env ? ddsrt_strdup (env) : expand (alt, domid);
case '?':
if (env && *env) {
return ddsrt_strdup (env);
} else {
- char *altx = expand (alt);
- DDS_ERROR("%s: %s\n", name, altx);
+ char *altx = expand (alt, domid);
+ DDS_ILOG (DDS_LC_ERROR, domid, "%s: %s\n", name, altx);
ddsrt_free (altx);
return NULL;
}
case '+':
- return env && *env ? expand (alt) : ddsrt_strdup ("");
+ return env && *env ? expand (alt, domid) : ddsrt_strdup ("");
default:
abort ();
return NULL;
}
}
-static char *expand_envbrace (const char **src, expand_fn expand)
+static char *expand_envbrace (const char **src, expand_fn expand, uint32_t domid)
{
const char *start = *src + 1;
char *name, *x;
@@ -76,7 +89,7 @@ static char *expand_envbrace (const char **src, expand_fn expand)
name[*src - start] = 0;
if (**src == '}') {
(*src)++;
- x = expand_env (name, 0, NULL, expand);
+ x = expand_env (name, 0, NULL, expand, domid);
ddsrt_free (name);
return x;
} else {
@@ -120,7 +133,7 @@ static char *expand_envbrace (const char **src, expand_fn expand)
memcpy (alt, altstart, (size_t) (*src - altstart));
alt[*src - altstart] = 0;
(*src)++;
- x = expand_env (name, op, alt, expand);
+ x = expand_env (name, op, alt, expand, domid);
ddsrt_free (alt);
ddsrt_free (name);
return x;
@@ -130,7 +143,7 @@ err:
return NULL;
}
-static char *expand_envsimple (const char **src, expand_fn expand)
+static char *expand_envsimple (const char **src, expand_fn expand, uint32_t domid)
{
const char *start = *src;
char *name, *x;
@@ -141,22 +154,22 @@ static char *expand_envsimple (const char **src, expand_fn expand)
name = ddsrt_malloc ((size_t) (*src - start) + 1);
memcpy (name, start, (size_t) (*src - start));
name[*src - start] = 0;
- x = expand_env (name, 0, NULL, expand);
+ x = expand_env (name, 0, NULL, expand, domid);
ddsrt_free (name);
return x;
}
-static char *expand_envchar (const char **src, expand_fn expand)
+static char *expand_envchar (const char **src, expand_fn expand, uint32_t domid)
{
char name[2];
assert (**src);
name[0] = **src;
name[1] = 0;
(*src)++;
- return expand_env (name, 0, NULL, expand);
+ return expand_env (name, 0, NULL, expand, domid);
}
-char *ddsrt_expand_envvars_sh (const char *src0)
+char *ddsrt_expand_envvars_sh (const char *src0, uint32_t domid)
{
/* Expands $X, ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms; $ and \ can be escaped with \ */
const char *src = src0;
@@ -179,11 +192,11 @@ char *ddsrt_expand_envvars_sh (const char *src0)
ddsrt_free(dst);
return NULL;
} else if (*src == '{') {
- x = expand_envbrace (&src, &ddsrt_expand_envvars_sh);
+ x = expand_envbrace (&src, &ddsrt_expand_envvars_sh, domid);
} else if (isalnum ((unsigned char) *src) || *src == '_') {
- x = expand_envsimple (&src, &ddsrt_expand_envvars_sh);
+ x = expand_envsimple (&src, &ddsrt_expand_envvars_sh, domid);
} else {
- x = expand_envchar (&src, &ddsrt_expand_envvars_sh);
+ x = expand_envchar (&src, &ddsrt_expand_envvars_sh, domid);
}
if (x == NULL) {
ddsrt_free(dst);
@@ -202,7 +215,7 @@ char *ddsrt_expand_envvars_sh (const char *src0)
return dst;
}
-char *ddsrt_expand_envvars (const char *src0)
+char *ddsrt_expand_envvars (const char *src0, uint32_t domid)
{
/* Expands ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, but not $X */
const char *src = src0;
@@ -212,7 +225,7 @@ char *ddsrt_expand_envvars (const char *src0)
if (*src == '$' && *(src + 1) == '{') {
char *x, *xp;
src++;
- x = expand_envbrace (&src, &ddsrt_expand_envvars);
+ x = expand_envbrace (&src, &ddsrt_expand_envvars, domid);
if (x == NULL) {
ddsrt_free(dst);
return NULL;
diff --git a/src/ddsrt/src/fibheap.c b/src/ddsrt/src/fibheap.c
index 2e3bcf8..e9b122b 100644
--- a/src/ddsrt/src/fibheap.c
+++ b/src/ddsrt/src/fibheap.c
@@ -207,7 +207,7 @@ void *ddsrt_fibheap_extract_min (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap
keys anyway to find the minimum */
{
ddsrt_fibheap_node_t *mark, *cursor, *newmin;
- unsigned i;
+ uint32_t i;
for (i = 0; roots[i] == NULL; i++) {
assert (i+1 < min_degree_noninit);
}
diff --git a/src/ddsrt/src/heap/freertos/heap.c b/src/ddsrt/src/heap/freertos/heap.c
new file mode 100644
index 0000000..01782c4
--- /dev/null
+++ b/src/ddsrt/src/heap/freertos/heap.c
@@ -0,0 +1,136 @@
+/*
+ * 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
+
+#if defined(configSUPPORT_DYNAMIC_ALLOCATION) && \
+ (configSUPPORT_DYNAMIC_ALLOCATION == 0)
+# error Dynamic memory allocation is not supported
+#endif
+
+#include
+#include
+#include
+#include
+
+static const size_t ofst = sizeof(size_t);
+
+void *ddsrt_malloc_s(size_t size)
+{
+ void *ptr = NULL;
+
+ if (size == 0) {
+ size = 1;
+ }
+
+ if ((SIZE_MAX - size) < ofst) {
+ errno = ERANGE;
+ } else {
+ ptr = pvPortMalloc(size + ofst);
+ if (ptr == NULL) {
+ errno = ENOMEM;
+ } else {
+ *((size_t *)ptr) = size;
+ ptr += ofst;
+ }
+ }
+
+ return ptr;
+}
+
+void *ddsrt_malloc(size_t size)
+{
+ void *ptr;
+
+ if ((ptr = ddsrt_malloc_s(size)) == NULL) {
+ abort();
+ }
+
+ return ptr;
+}
+
+void *ddsrt_calloc_s(size_t nmemb, size_t size)
+{
+ void *ptr = NULL;
+
+ if (nmemb == 0 || size == 0) {
+ nmemb = size = 1;
+ }
+
+ if ((SIZE_MAX / nmemb) <= size) {
+ errno = ERANGE;
+ } else {
+ ptr = ddsrt_malloc_s(nmemb * size);
+ (void)memset(ptr, 0, nmemb * size);
+ }
+
+ return ptr;
+}
+
+void *ddsrt_calloc(size_t nmemb, size_t size)
+{
+ void *ptr = NULL;
+
+ if ((ptr = ddsrt_calloc_s(nmemb, size)) == NULL) {
+ abort();
+ }
+
+ return ptr;
+}
+
+/* pvPortMalloc may be used instead of directly invoking malloc and free as
+ offered by the standard C library. Unfortunately FreeRTOS does not offer a
+ realloc compatible function and extra information must be embedded in every
+ memory block in order to support reallocation of memory (otherwise the
+ number of bytes that must be copied is unavailable). */
+void *ddsrt_realloc_s(void *memblk, size_t size)
+{
+ void *ptr = NULL;
+ size_t origsize = 0;
+
+ if (memblk != NULL) {
+ origsize = *((size_t *)(memblk - ofst));
+ }
+
+ if (size != origsize || origsize == 0) {
+ if ((ptr = ddsrt_malloc_s(size)) == NULL) {
+ return NULL;
+ }
+ if (memblk != NULL) {
+ if (size > 0) {
+ (void)memcpy(ptr, memblk, size > origsize ? origsize : size);
+ }
+ vPortFree(memblk - ofst);
+ }
+ memblk = ptr;
+ }
+
+ return memblk;
+}
+
+void *ddsrt_realloc(void *memblk, size_t size)
+{
+ void *ptr = NULL;
+
+ if ((ptr = ddsrt_realloc_s(memblk, size)) == NULL) {
+ abort();
+ }
+
+ return ptr;
+}
+
+void
+ddsrt_free(void *ptr)
+{
+ if (ptr != NULL) {
+ vPortFree(ptr - ofst);
+ }
+}
diff --git a/src/ddsrt/src/hopscotch.c b/src/ddsrt/src/hopscotch.c
index eef7efb..b6869b1 100644
--- a/src/ddsrt/src/hopscotch.c
+++ b/src/ddsrt/src/hopscotch.c
@@ -12,6 +12,7 @@
#include
#include
+#include "dds/ddsrt/attributes.h"
#include "dds/ddsrt/atomics.h"
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/sync.h"
@@ -22,8 +23,255 @@
#define NOT_A_BUCKET (~(uint32_t)0)
+/************* SEQUENTIAL VERSION ***************/
+
+struct ddsrt_hh_bucket {
+ uint32_t hopinfo;
+ void *data;
+};
+
+struct ddsrt_hh {
+ uint32_t size; /* power of 2 */
+ struct ddsrt_hh_bucket *buckets;
+ ddsrt_hh_hash_fn hash;
+ ddsrt_hh_equals_fn equals;
+};
+
+static void ddsrt_hh_init (struct ddsrt_hh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals)
+{
+ uint32_t size;
+ uint32_t i;
+ /* degenerate case to minimize memory use */
+ if (init_size == 1) {
+ size = 1;
+ } else {
+ size = HH_HOP_RANGE;
+ while (size < init_size) {
+ size *= 2;
+ }
+ }
+ rt->hash = hash;
+ rt->equals = equals;
+ rt->size = size;
+ rt->buckets = ddsrt_malloc (size * sizeof (*rt->buckets));
+ for (i = 0; i < size; i++) {
+ rt->buckets[i].hopinfo = 0;
+ rt->buckets[i].data = NULL;
+ }
+}
+
+static void ddsrt_hh_fini (struct ddsrt_hh *rt)
+{
+ ddsrt_free (rt->buckets);
+}
+
+struct ddsrt_hh *ddsrt_hh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals)
+{
+ struct ddsrt_hh *hh = ddsrt_malloc (sizeof (*hh));
+ ddsrt_hh_init (hh, init_size, hash, equals);
+ return hh;
+}
+
+void ddsrt_hh_free (struct ddsrt_hh * __restrict hh)
+{
+ ddsrt_hh_fini (hh);
+ ddsrt_free (hh);
+}
+
+static void *ddsrt_hh_lookup_internal (const struct ddsrt_hh *rt, const uint32_t bucket, const void *template)
+{
+ const uint32_t idxmask = rt->size - 1;
+ uint32_t hopinfo = rt->buckets[bucket].hopinfo;
+ uint32_t idx;
+ for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) {
+ const uint32_t bidx = (bucket + idx) & idxmask;
+ void *data = rt->buckets[bidx].data;
+ if (data && rt->equals (data, template))
+ return data;
+ }
+ return NULL;
+}
+
+void *ddsrt_hh_lookup (const struct ddsrt_hh * __restrict rt, const void * __restrict template)
+{
+ const uint32_t hash = rt->hash (template);
+ const uint32_t idxmask = rt->size - 1;
+ const uint32_t bucket = hash & idxmask;
+ return ddsrt_hh_lookup_internal (rt, bucket, template);
+}
+
+static uint32_t ddsrt_hh_find_closer_free_bucket (struct ddsrt_hh *rt, uint32_t free_bucket, uint32_t *free_distance)
+{
+ const uint32_t idxmask = rt->size - 1;
+ uint32_t move_bucket, free_dist;
+ move_bucket = (free_bucket - (HH_HOP_RANGE - 1)) & idxmask;
+ for (free_dist = HH_HOP_RANGE - 1; free_dist > 0; free_dist--) {
+ uint32_t move_free_distance = NOT_A_BUCKET;
+ uint32_t mask = 1;
+ uint32_t i;
+ for (i = 0; i < free_dist; i++, mask <<= 1) {
+ if (mask & rt->buckets[move_bucket].hopinfo) {
+ move_free_distance = i;
+ break;
+ }
+ }
+ if (move_free_distance != NOT_A_BUCKET) {
+ uint32_t new_free_bucket = (move_bucket + move_free_distance) & idxmask;
+ rt->buckets[move_bucket].hopinfo |= 1u << free_dist;
+ rt->buckets[free_bucket].data = rt->buckets[new_free_bucket].data;
+ rt->buckets[new_free_bucket].data = NULL;
+ rt->buckets[move_bucket].hopinfo &= ~(1u << move_free_distance);
+ *free_distance -= free_dist - move_free_distance;
+ return new_free_bucket;
+ }
+ move_bucket = (move_bucket + 1) & idxmask;
+ }
+ return NOT_A_BUCKET;
+}
+
+static void ddsrt_hh_resize (struct ddsrt_hh *rt)
+{
+ if (rt->size == 1) {
+ assert (rt->size == 1);
+ assert (rt->buckets[0].hopinfo == 1);
+ assert (rt->buckets[0].data != NULL);
+
+ rt->size = HH_HOP_RANGE;
+ const uint32_t hash = rt->hash (rt->buckets[0].data);
+ const uint32_t idxmask = rt->size - 1;
+ const uint32_t start_bucket = hash & idxmask;
+
+ struct ddsrt_hh_bucket *newbs = ddsrt_malloc (rt->size * sizeof (*newbs));
+ for (uint32_t i = 0; i < rt->size; i++) {
+ newbs[i].hopinfo = 0;
+ newbs[i].data = NULL;
+ }
+ newbs[start_bucket] = rt->buckets[0];
+ ddsrt_free (rt->buckets);
+ rt->buckets = newbs;
+ } else {
+ struct ddsrt_hh_bucket *bs1;
+ uint32_t i, idxmask0, idxmask1;
+
+ bs1 = ddsrt_malloc (2 * rt->size * sizeof (*rt->buckets));
+
+ for (i = 0; i < 2 * rt->size; i++) {
+ bs1[i].hopinfo = 0;
+ bs1[i].data = NULL;
+ }
+ idxmask0 = rt->size - 1;
+ idxmask1 = 2 * rt->size - 1;
+ for (i = 0; i < rt->size; i++) {
+ void *data = rt->buckets[i].data;
+ if (data) {
+ const uint32_t hash = rt->hash (data);
+ const uint32_t old_start_bucket = hash & idxmask0;
+ const uint32_t new_start_bucket = hash & idxmask1;
+ const uint32_t dist = (i >= old_start_bucket) ? (i - old_start_bucket) : (rt->size + i - old_start_bucket);
+ const uint32_t newb = (new_start_bucket + dist) & idxmask1;
+ assert (dist < HH_HOP_RANGE);
+ bs1[new_start_bucket].hopinfo |= 1u << dist;
+ bs1[newb].data = data;
+ }
+ }
+
+ ddsrt_free (rt->buckets);
+ rt->size *= 2;
+ rt->buckets = bs1;
+ }
+}
+
+int ddsrt_hh_add (struct ddsrt_hh * __restrict rt, const void * __restrict data)
+{
+ const uint32_t hash = rt->hash (data);
+ const uint32_t idxmask = rt->size - 1;
+ const uint32_t start_bucket = hash & idxmask;
+ uint32_t free_distance, free_bucket;
+
+ if (ddsrt_hh_lookup_internal (rt, start_bucket, data)) {
+ return 0;
+ }
+
+ free_bucket = start_bucket;
+ for (free_distance = 0; free_distance < HH_ADD_RANGE; free_distance++) {
+ if (rt->buckets[free_bucket].data == NULL)
+ break;
+ free_bucket = (free_bucket + 1) & idxmask;
+ }
+ if (free_distance < HH_ADD_RANGE) {
+ do {
+ if (free_distance < HH_HOP_RANGE) {
+ assert ((uint32_t) free_bucket == ((start_bucket + free_distance) & idxmask));
+ rt->buckets[start_bucket].hopinfo |= 1u << free_distance;
+ rt->buckets[free_bucket].data = (void *) data;
+ return 1;
+ }
+ free_bucket = ddsrt_hh_find_closer_free_bucket (rt, free_bucket, &free_distance);
+ assert (free_bucket == NOT_A_BUCKET || free_bucket <= idxmask);
+ } while (free_bucket != NOT_A_BUCKET);
+ }
+
+ ddsrt_hh_resize (rt);
+ return ddsrt_hh_add (rt, data);
+}
+
+int ddsrt_hh_remove (struct ddsrt_hh * __restrict rt, const void * __restrict template)
+{
+ const uint32_t hash = rt->hash (template);
+ const uint32_t idxmask = rt->size - 1;
+ const uint32_t bucket = hash & idxmask;
+ uint32_t hopinfo;
+ uint32_t idx;
+ hopinfo = rt->buckets[bucket].hopinfo;
+ for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) {
+ if (hopinfo & 1) {
+ const uint32_t bidx = (bucket + idx) & idxmask;
+ void *data = rt->buckets[bidx].data;
+ if (data && rt->equals (data, template)) {
+ rt->buckets[bidx].data = NULL;
+ rt->buckets[bucket].hopinfo &= ~(1u << idx);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg)
+{
+ uint32_t i;
+ for (i = 0; i < rt->size; i++) {
+ void *data = rt->buckets[i].data;
+ if (data) {
+ f (data, f_arg);
+ }
+ }
+}
+
+void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter)
+{
+ iter->hh = rt;
+ iter->cursor = 0;
+ return ddsrt_hh_iter_next (iter);
+}
+
+void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter)
+{
+ struct ddsrt_hh *rt = iter->hh;
+ while (iter->cursor < rt->size) {
+ void *data = rt->buckets[iter->cursor].data;
+ iter->cursor++;
+ if (data) {
+ return data;
+ }
+ }
+ return NULL;
+}
+
/********** CONCURRENT VERSION ************/
+#if ! ddsrt_has_feature_thread_sanitizer
+
#define N_BACKING_LOCKS 32
#define N_RESIZE_LOCKS 8
@@ -51,6 +299,7 @@ struct ddsrt_chh {
ddsrt_hh_equals_fn equals;
ddsrt_rwlock_t resize_locks[N_RESIZE_LOCKS];
ddsrt_hh_buckets_gc_fn gc_buckets;
+ void *gc_buckets_arg;
};
#define CHH_MAX_TRIES 4
@@ -61,7 +310,7 @@ static int ddsrt_chh_data_valid_p (void *data)
return data != NULL && data != CHH_BUSY;
}
-static int ddsrt_chh_init (struct ddsrt_chh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets)
+static int ddsrt_chh_init (struct ddsrt_chh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets, void *gc_buckets_arg)
{
uint32_t size;
uint32_t i;
@@ -74,6 +323,7 @@ static int ddsrt_chh_init (struct ddsrt_chh *rt, uint32_t init_size, ddsrt_hh_ha
rt->hash = hash;
rt->equals = equals;
rt->gc_buckets = gc_buckets;
+ rt->gc_buckets_arg = gc_buckets_arg;
buckets = ddsrt_malloc (offsetof (struct ddsrt_chh_bucket_array, bs) + size * sizeof (*buckets->bs));
ddsrt_atomic_stvoidp (&rt->buckets, buckets);
@@ -111,10 +361,10 @@ static void ddsrt_chh_fini (struct ddsrt_chh *rt)
}
}
-struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets)
+struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets, void *gc_buckets_arg)
{
struct ddsrt_chh *hh = ddsrt_malloc (sizeof (*hh));
- if (ddsrt_chh_init (hh, init_size, hash, equals, gc_buckets) < 0) {
+ if (ddsrt_chh_init (hh, init_size, hash, equals, gc_buckets, gc_buckets_arg) < 0) {
ddsrt_free (hh);
return NULL;
} else {
@@ -228,7 +478,7 @@ static void *ddsrt_chh_lookup_internal (struct ddsrt_chh_bucket_array const * co
#define ddsrt_atomic_rmw32_nonatomic(var_, tmp_, expr_) do { \
ddsrt_atomic_uint32_t *var__ = (var_); \
- uint32_t tmp_ = ddsrt_atomic_ld32 (var__); \
+ uint32_t tmp_ = ddsrt_atomic_ld32 (var__); \
ddsrt_atomic_st32 (var__, (expr_)); \
} while (0)
@@ -324,7 +574,7 @@ static void ddsrt_chh_resize (struct ddsrt_chh *rt)
ddsrt_atomic_fence ();
ddsrt_atomic_stvoidp (&rt->buckets, bsary1);
- rt->gc_buckets (bsary0);
+ rt->gc_buckets (bsary0, rt->gc_buckets_arg);
}
int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data)
@@ -467,224 +717,78 @@ void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_i
return ddsrt_chh_iter_next (it);
}
-/************* SEQUENTIAL VERSION ***************/
+#else
-struct ddsrt_hh_bucket {
- uint32_t hopinfo;
- void *data;
+struct ddsrt_chh {
+ ddsrt_mutex_t lock;
+ struct ddsrt_hh rt;
};
-struct ddsrt_hh {
- uint32_t size; /* power of 2 */
- struct ddsrt_hh_bucket *buckets;
- ddsrt_hh_hash_fn hash;
- ddsrt_hh_equals_fn equals;
-};
-
-static void ddsrt_hh_init (struct ddsrt_hh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals)
+struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc)
{
- uint32_t size = HH_HOP_RANGE;
- uint32_t i;
- while (size < init_size) {
- size *= 2;
- }
- rt->hash = hash;
- rt->equals = equals;
- rt->size = size;
- rt->buckets = ddsrt_malloc (size * sizeof (*rt->buckets));
- for (i = 0; i < size; i++) {
- rt->buckets[i].hopinfo = 0;
- rt->buckets[i].data = NULL;
- }
+ struct ddsrt_chh *hh = ddsrt_malloc (sizeof (*hh));
+ (void) gc;
+ ddsrt_mutex_init (&hh->lock);
+ ddsrt_hh_init (&hh->rt, init_size, hash, equals);
+ return hh;
}
-static void ddsrt_hh_fini (struct ddsrt_hh *rt)
+void ddsrt_chh_free (struct ddsrt_chh * __restrict hh)
{
- ddsrt_free (rt->buckets);
+ ddsrt_hh_fini (&hh->rt);
+ ddsrt_mutex_destroy (&hh->lock);
+ ddsrt_free (hh);
}
-struct ddsrt_hh *ddsrt_hh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals)
+void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict hh, const void * __restrict template)
{
- struct ddsrt_hh *hh = ddsrt_malloc (sizeof (*hh));
- ddsrt_hh_init (hh, init_size, hash, equals);
- return hh;
+ ddsrt_mutex_lock (&hh->lock);
+ void *x = ddsrt_hh_lookup (&hh->rt, template);
+ ddsrt_mutex_unlock (&hh->lock);
+ return x;
}
-void ddsrt_hh_free (struct ddsrt_hh * __restrict hh)
+int ddsrt_chh_add (struct ddsrt_chh * __restrict hh, const void * __restrict data)
{
- ddsrt_hh_fini (hh);
- ddsrt_free (hh);
+ ddsrt_mutex_lock (&hh->lock);
+ int x = ddsrt_hh_add (&hh->rt, data);
+ ddsrt_mutex_unlock (&hh->lock);
+ return x;
}
-static void *ddsrt_hh_lookup_internal (const struct ddsrt_hh *rt, const uint32_t bucket, const void *template)
+int ddsrt_chh_remove (struct ddsrt_chh * __restrict hh, const void * __restrict template)
{
- const uint32_t idxmask = rt->size - 1;
- uint32_t hopinfo = rt->buckets[bucket].hopinfo;
- uint32_t idx;
- for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) {
- const uint32_t bidx = (bucket + idx) & idxmask;
- void *data = rt->buckets[bidx].data;
- if (data && rt->equals (data, template))
- return data;
- }
- return NULL;
+ ddsrt_mutex_lock (&hh->lock);
+ int x = ddsrt_hh_remove (&hh->rt, template);
+ ddsrt_mutex_unlock (&hh->lock);
+ return x;
}
-void *ddsrt_hh_lookup (const struct ddsrt_hh * __restrict rt, const void * __restrict template)
+void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict hh, void (*f) (void *a, void *f_arg), void *f_arg)
{
- const uint32_t hash = rt->hash (template);
- const uint32_t idxmask = rt->size - 1;
- const uint32_t bucket = hash & idxmask;
- return ddsrt_hh_lookup_internal (rt, bucket, template);
+ ddsrt_mutex_lock (&hh->lock);
+ ddsrt_hh_enum (&hh->rt, f, f_arg);
+ ddsrt_mutex_unlock (&hh->lock);
}
-static uint32_t ddsrt_hh_find_closer_free_bucket (struct ddsrt_hh *rt, uint32_t free_bucket, uint32_t *free_distance)
+void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict hh, struct ddsrt_chh_iter *it)
{
- const uint32_t idxmask = rt->size - 1;
- uint32_t move_bucket, free_dist;
- move_bucket = (free_bucket - (HH_HOP_RANGE - 1)) & idxmask;
- for (free_dist = HH_HOP_RANGE - 1; free_dist > 0; free_dist--) {
- uint32_t move_free_distance = NOT_A_BUCKET;
- uint32_t mask = 1;
- uint32_t i;
- for (i = 0; i < free_dist; i++, mask <<= 1) {
- if (mask & rt->buckets[move_bucket].hopinfo) {
- move_free_distance = i;
- break;
- }
- }
- if (move_free_distance != NOT_A_BUCKET) {
- uint32_t new_free_bucket = (move_bucket + move_free_distance) & idxmask;
- rt->buckets[move_bucket].hopinfo |= 1u << free_dist;
- rt->buckets[free_bucket].data = rt->buckets[new_free_bucket].data;
- rt->buckets[new_free_bucket].data = NULL;
- rt->buckets[move_bucket].hopinfo &= ~(1u << move_free_distance);
- *free_distance -= free_dist - move_free_distance;
- return new_free_bucket;
- }
- move_bucket = (move_bucket + 1) & idxmask;
- }
- return NOT_A_BUCKET;
+ ddsrt_mutex_lock (&hh->lock);
+ it->chh = hh;
+ void *x = ddsrt_hh_iter_first (&hh->rt, &it->it);
+ ddsrt_mutex_unlock (&hh->lock);
+ return x;
}
-static void ddsrt_hh_resize (struct ddsrt_hh *rt)
+void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it)
{
- struct ddsrt_hh_bucket *bs1;
- uint32_t i, idxmask0, idxmask1;
-
- bs1 = ddsrt_malloc (2 * rt->size * sizeof (*rt->buckets));
-
- for (i = 0; i < 2 * rt->size; i++) {
- bs1[i].hopinfo = 0;
- bs1[i].data = NULL;
- }
- idxmask0 = rt->size - 1;
- idxmask1 = 2 * rt->size - 1;
- for (i = 0; i < rt->size; i++) {
- void *data = rt->buckets[i].data;
- if (data) {
- const uint32_t hash = rt->hash (data);
- const uint32_t old_start_bucket = hash & idxmask0;
- const uint32_t new_start_bucket = hash & idxmask1;
- const uint32_t dist = (i >= old_start_bucket) ? (i - old_start_bucket) : (rt->size + i - old_start_bucket);
- const uint32_t newb = (new_start_bucket + dist) & idxmask1;
- assert (dist < HH_HOP_RANGE);
- bs1[new_start_bucket].hopinfo |= 1u << dist;
- bs1[newb].data = data;
- }
- }
-
- ddsrt_free (rt->buckets);
- rt->size *= 2;
- rt->buckets = bs1;
+ ddsrt_mutex_lock (&it->chh->lock);
+ void *x = ddsrt_hh_iter_next (&it->it);
+ ddsrt_mutex_unlock (&it->chh->lock);
+ return x;
}
-int ddsrt_hh_add (struct ddsrt_hh * __restrict rt, const void * __restrict data)
-{
- const uint32_t hash = rt->hash (data);
- const uint32_t idxmask = rt->size - 1;
- const uint32_t start_bucket = hash & idxmask;
- uint32_t free_distance, free_bucket;
-
- if (ddsrt_hh_lookup_internal (rt, start_bucket, data)) {
- return 0;
- }
-
- free_bucket = start_bucket;
- for (free_distance = 0; free_distance < HH_ADD_RANGE; free_distance++) {
- if (rt->buckets[free_bucket].data == NULL)
- break;
- free_bucket = (free_bucket + 1) & idxmask;
- }
- if (free_distance < HH_ADD_RANGE) {
- do {
- if (free_distance < HH_HOP_RANGE) {
- assert ((uint32_t) free_bucket == ((start_bucket + free_distance) & idxmask));
- rt->buckets[start_bucket].hopinfo |= 1u << free_distance;
- rt->buckets[free_bucket].data = (void *) data;
- return 1;
- }
- free_bucket = ddsrt_hh_find_closer_free_bucket (rt, free_bucket, &free_distance);
- assert (free_bucket == NOT_A_BUCKET || free_bucket <= idxmask);
- } while (free_bucket != NOT_A_BUCKET);
- }
-
- ddsrt_hh_resize (rt);
- return ddsrt_hh_add (rt, data);
-}
-
-int ddsrt_hh_remove (struct ddsrt_hh * __restrict rt, const void * __restrict template)
-{
- const uint32_t hash = rt->hash (template);
- const uint32_t idxmask = rt->size - 1;
- const uint32_t bucket = hash & idxmask;
- uint32_t hopinfo;
- uint32_t idx;
- hopinfo = rt->buckets[bucket].hopinfo;
- for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) {
- if (hopinfo & 1) {
- const uint32_t bidx = (bucket + idx) & idxmask;
- void *data = rt->buckets[bidx].data;
- if (data && rt->equals (data, template)) {
- rt->buckets[bidx].data = NULL;
- rt->buckets[bucket].hopinfo &= ~(1u << idx);
- return 1;
- }
- }
- }
- return 0;
-}
-
-void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg)
-{
- uint32_t i;
- for (i = 0; i < rt->size; i++) {
- void *data = rt->buckets[i].data;
- if (data) {
- f (data, f_arg);
- }
- }
-}
-
-void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter)
-{
- iter->hh = rt;
- iter->cursor = 0;
- return ddsrt_hh_iter_next (iter);
-}
-
-void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter)
-{
- struct ddsrt_hh *rt = iter->hh;
- while (iter->cursor < rt->size) {
- void *data = rt->buckets[iter->cursor].data;
- iter->cursor++;
- if (data) {
- return data;
- }
- }
- return NULL;
-}
+#endif
/************* SEQUENTIAL VERSION WITH EMBEDDED DATA ***************/
diff --git a/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c b/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c
new file mode 100644
index 0000000..68b4401
--- /dev/null
+++ b/src/ddsrt/src/ifaddrs/lwip/ifaddrs.c
@@ -0,0 +1,208 @@
+/*
+ * 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
+#include
+#include
+#include /* netif_list */
+#include
+
+#include "dds/ddsrt/heap.h"
+#include "dds/ddsrt/io.h"
+#include "dds/ddsrt/ifaddrs.h"
+#include "dds/ddsrt/retcode.h"
+#include "dds/ddsrt/string.h"
+
+extern const int *const os_supp_afs;
+
+static uint32_t
+getflags(
+ const struct netif *netif,
+ const ip_addr_t *addr)
+{
+ uint32_t flags = 0;
+
+ if (netif->flags & NETIF_FLAG_UP) {
+ flags |= IFF_UP;
+ }
+ if (netif->flags & NETIF_FLAG_BROADCAST) {
+ flags |= IFF_BROADCAST;
+ }
+ if (netif->flags & NETIF_FLAG_IGMP) {
+ flags |= IFF_MULTICAST;
+ }
+ if (ip_addr_isloopback(addr)) {
+ flags |= IFF_LOOPBACK;
+ }
+
+ return flags;
+}
+
+static void
+sockaddr_from_ip_addr(
+ struct sockaddr *sockaddr,
+ const ip_addr_t *addr)
+{
+ if (IP_IS_V4(addr)) {
+ memset(sockaddr, 0, sizeof(struct sockaddr_in));
+ ((struct sockaddr_in *)sockaddr)->sin_len = sizeof(struct sockaddr_in);
+ ((struct sockaddr_in *)sockaddr)->sin_family = AF_INET;
+ inet_addr_from_ip4addr(&((struct sockaddr_in *)sockaddr)->sin_addr, addr);
+#if DDSRT_HAVE_IPV6
+ } else {
+ assert(IP_IS_V6(addr));
+ memset(sockaddr, 0, sizeof(struct sockaddr_in6));
+ ((struct sockaddr_in6 *)sockaddr)->sin6_len = sizeof(struct sockaddr_in6);
+ ((struct sockaddr_in6 *)sockaddr)->sin6_family = AF_INET6;
+ inet6_addr_from_ip6addr(&((struct sockaddr_in6 *)sockaddr)->sin6_addr, addr);
+#endif
+ }
+}
+
+static dds_return_t
+copyaddr(
+ ddsrt_ifaddrs_t **ifap,
+ const struct netif *netif,
+ const ip_addr_t *addr)
+{
+ dds_return_t rc = DDS_RETCODE_OK;
+ ddsrt_ifaddrs_t *ifa;
+ struct sockaddr_storage sa;
+
+ assert(ifap != NULL);
+ assert(netif != NULL);
+ assert(addr != NULL);
+
+ sockaddr_from_ip_addr((struct sockaddr *)&sa, addr);
+
+ /* Network interface name is of the form "et0", where the first two letters
+ are the "name" field and the digit is the num field of the netif
+ structure as described in lwip/netif.h */
+
+ if ((ifa = ddsrt_calloc_s(1, sizeof(*ifa))) == NULL ||
+ (ifa->addr = ddsrt_memdup(&sa, sa.s2_len)) == NULL ||
+ (ddsrt_asprintf(&ifa->name, "%s%d", netif->name, netif->num) == -1))
+ {
+ rc = DDS_RETCODE_OUT_OF_RESOURCES;
+ } else {
+ ifa->flags = getflags(netif, addr);
+ ifa->index = netif->num;
+ ifa->type = DDSRT_IFTYPE_UNKNOWN;
+
+ if (IP_IS_V4(addr)) {
+ static const size_t sz = sizeof(struct sockaddr_in);
+ if ((ifa->netmask = ddsrt_calloc_s(1, sz)) == NULL ||
+ (ifa->broadaddr = ddsrt_calloc_s(1, sz)) == NULL)
+ {
+ rc = DDS_RETCODE_OUT_OF_RESOURCES;
+ } else {
+ ip_addr_t broadaddr = IPADDR4_INIT(
+ ip_2_ip4(&netif->ip_addr)->addr |
+ ip_2_ip4(&netif->netmask)->addr);
+
+ sockaddr_from_ip_addr((struct sockaddr*)ifa->netmask, &netif->netmask);
+ sockaddr_from_ip_addr((struct sockaddr*)ifa->broadaddr, &broadaddr);
+ }
+ }
+ }
+
+ if (rc == DDS_RETCODE_OK) {
+ *ifap = ifa;
+ } else {
+ ddsrt_freeifaddrs(ifa);
+ }
+
+ return rc;
+}
+
+dds_return_t
+ddsrt_getifaddrs(
+ ddsrt_ifaddrs_t **ifap,
+ const int *afs)
+{
+ dds_return_t rc = DDS_RETCODE_OK;
+ int use_ip4, use_ip6;
+ struct netif *netif;
+ ddsrt_ifaddrs_t *ifa, *next_ifa, *root_ifa;
+
+ assert(ifap != NULL);
+
+ if (afs == NULL) {
+ afs = os_supp_afs;
+ }
+
+ use_ip4 = use_ip6 = 0;
+ for (int i = 0; afs[i] != DDSRT_AF_TERM; i++) {
+ if (afs[i] == AF_INET) {
+ use_ip4 = 1;
+ } else if (afs[i] == AF_INET6) {
+ use_ip6 = 1;
+ }
+ }
+
+ ifa = next_ifa = root_ifa = NULL;
+
+ for (netif = netif_list;
+ netif != NULL && rc == DDS_RETCODE_OK;
+ netif = netif->next)
+ {
+ if (use_ip4 && IP_IS_V4(&netif->ip_addr)) {
+ rc = copyaddr(&next_ifa, netif, &netif->ip_addr);
+ if (rc == DDS_RETCODE_OK) {
+ if (ifa == NULL) {
+ ifa = root_ifa = next_ifa;
+ } else {
+ ifa->next = next_ifa;
+ ifa = next_ifa;
+ }
+ }
+ }
+
+#if DDSRT_HAVE_IPV6
+ if (use_ip6) {
+ int pref = 1;
+again:
+ /* List preferred IPv6 address first. */
+ for (int i = 0;
+ i < LWIP_IPV6_NUM_ADDRESSES && rc == DDS_RETCODE_OK;
+ i++)
+ {
+ if ((ip6_addr_ispreferred(netif->ip_addr_state[i]) && pref) ||
+ (ip6_addr_isvalid(netif->ip_addr_state[i]) && !pref))
+ {
+ rc = copyaddr(&next_ifa, netif, &netif->ip_addr[i]);
+ if (rc == DDS_RETCODE_OK) {
+ if (ifa == NULL) {
+ ifa = root_ifa = next_ifa;
+ } else {
+ ifa->next = next_ifa;
+ ifa = next_ifa;
+ }
+ }
+ }
+ }
+
+ if (rc == DDS_RETCODE_OK && pref) {
+ pref = 0;
+ goto again;
+ }
+ }
+#endif
+ }
+
+ if (rc == DDS_RETCODE_OK) {
+ *ifap = ifa;
+ } else {
+ ddsrt_freeifaddrs(root_ifa);
+ }
+
+ return rc;
+}
diff --git a/src/ddsrt/src/ifaddrs/posix/ifaddrs.c b/src/ddsrt/src/ifaddrs/posix/ifaddrs.c
index 88606b1..8bf8f52 100644
--- a/src/ddsrt/src/ifaddrs/posix/ifaddrs.c
+++ b/src/ddsrt/src/ifaddrs/posix/ifaddrs.c
@@ -21,10 +21,115 @@
extern const int *const os_supp_afs;
-static dds_retcode_t
-copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa)
+#if defined __linux
+#include
+
+static enum ddsrt_iftype guess_iftype (const struct ifaddrs *sys_ifa)
{
- dds_retcode_t err = DDS_RETCODE_OK;
+ FILE *fp;
+ char ifnam[IFNAMSIZ + 1]; /* not sure whether IFNAMSIZ includes a terminating 0, can't be bothered */
+ int c;
+ size_t np;
+ enum ddsrt_iftype type = DDSRT_IFTYPE_UNKNOWN;
+ if ((fp = fopen ("/proc/net/wireless", "r")) == NULL)
+ return type;
+ /* expected format:
+ :Inter-| sta-| Quality | Discarded packets | Missed | WE
+ : face | tus | link level noise | nwid crypt frag retry misc | beacon | 22
+ : wlan0: 0000 67. -43. -256 0 0 0 0 0 0
+ (where : denotes the start of the line)
+
+ SKIP_HEADER_1 skips up to and including the first newline; then SKIP_TO_EOL skips
+ up to and including the second newline, so the first line that gets interpreted is
+ the third.
+ */
+ enum { SKIP_HEADER_1, SKIP_WHITE, READ_NAME, SKIP_TO_EOL } state = SKIP_HEADER_1;
+ np = 0;
+ while (type != DDSRT_IFTYPE_WIFI && (c = fgetc (fp)) != EOF) {
+ switch (state) {
+ case SKIP_HEADER_1:
+ if (c == '\n') {
+ state = SKIP_TO_EOL;
+ }
+ break;
+ case SKIP_WHITE:
+ if (c != ' ' && c != '\t') {
+ ifnam[np++] = (char) c;
+ state = READ_NAME;
+ }
+ break;
+ case READ_NAME:
+ if (c == ':') {
+ ifnam[np] = 0;
+ if (strcmp (ifnam, sys_ifa->ifa_name) == 0)
+ type = DDSRT_IFTYPE_WIFI;
+ state = SKIP_TO_EOL;
+ np = 0;
+ } else if (np < sizeof (ifnam) - 1) {
+ ifnam[np++] = (char) c;
+ }
+ break;
+ case SKIP_TO_EOL:
+ if (c == '\n') {
+ state = SKIP_WHITE;
+ }
+ break;
+ }
+ }
+ fclose (fp);
+ return type;
+}
+#elif defined __APPLE__ /* probably works for all BSDs */
+#include
+#include
+#include
+#include
+
+static enum ddsrt_iftype guess_iftype (const struct ifaddrs *sys_ifa)
+{
+ int sock;
+ if ((sock = socket (sys_ifa->ifa_addr->sa_family, SOCK_DGRAM, 0)) == -1)
+ return DDSRT_IFTYPE_UNKNOWN;
+
+ struct ifmediareq ifmr;
+ enum ddsrt_iftype type;
+ memset (&ifmr, 0, sizeof (ifmr));
+ ddsrt_strlcpy (ifmr.ifm_name, sys_ifa->ifa_name, sizeof (ifmr.ifm_name));
+ if (ioctl (sock, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0)
+ {
+ type = DDSRT_IFTYPE_UNKNOWN;
+ }
+ else
+ {
+ switch (IFM_TYPE (ifmr.ifm_active))
+ {
+ case IFM_ETHER:
+ case IFM_TOKEN:
+ case IFM_FDDI:
+ type = DDSRT_IFTYPE_WIRED;
+ break;
+ case IFM_IEEE80211:
+ type = DDSRT_IFTYPE_WIFI;
+ break;
+ default:
+ type = DDSRT_IFTYPE_UNKNOWN;
+ break;
+ }
+ }
+ close (sock);
+ return type;
+}
+#else
+static enum ddsrt_iftype guess_iftype (const struct ifaddrs *sys_ifa)
+{
+ return DDSRT_IFTYPE_UNKNOWN;
+}
+#endif
+
+static dds_return_t
+copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa, enum ddsrt_iftype type)
+{
+ dds_return_t err = DDS_RETCODE_OK;
ddsrt_ifaddrs_t *ifa;
size_t sz;
@@ -37,6 +142,7 @@ copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa)
err = DDS_RETCODE_OUT_OF_RESOURCES;
} else {
ifa->index = if_nametoindex(sys_ifa->ifa_name);
+ ifa->type = type;
ifa->flags = sys_ifa->ifa_flags;
if ((ifa->name = ddsrt_strdup(sys_ifa->ifa_name)) == NULL ||
(ifa->addr = ddsrt_memdup(sys_ifa->ifa_addr, sz)) == NULL ||
@@ -64,12 +170,12 @@ copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa)
return err;
}
-dds_retcode_t
+dds_return_t
ddsrt_getifaddrs(
ddsrt_ifaddrs_t **ifap,
const int *afs)
{
- dds_retcode_t err = DDS_RETCODE_OK;
+ dds_return_t err = DDS_RETCODE_OK;
int use;
ddsrt_ifaddrs_t *ifa, *ifa_root, *ifa_next;
struct ifaddrs *sys_ifa, *sys_ifa_root;
@@ -109,7 +215,8 @@ ddsrt_getifaddrs(
}
if (use) {
- err = copyaddr(&ifa_next, sys_ifa);
+ enum ddsrt_iftype type = guess_iftype (sys_ifa);
+ err = copyaddr(&ifa_next, sys_ifa, type);
if (err == DDS_RETCODE_OK) {
if (ifa == NULL) {
ifa = ifa_root = ifa_next;
diff --git a/src/ddsrt/src/ifaddrs/solaris2.6/ifaddrs.c b/src/ddsrt/src/ifaddrs/solaris2.6/ifaddrs.c
new file mode 100644
index 0000000..11e2231
--- /dev/null
+++ b/src/ddsrt/src/ifaddrs/solaris2.6/ifaddrs.c
@@ -0,0 +1,84 @@
+/*
+ * 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
+#include
+#include "dds/ddsrt/ifaddrs.h"
+#include
+#include
+
+#include "dds/ddsrt/heap.h"
+#include "dds/ddsrt/retcode.h"
+#include "dds/ddsrt/string.h"
+
+extern const int *const os_supp_afs;
+
+#include
+#include
+#include
+#include
+
+dds_return_t
+ddsrt_getifaddrs(
+ ddsrt_ifaddrs_t **ret_ifap,
+ const int *afs)
+{
+ int sock;
+ char *buf;
+ int32_t n;
+ struct ifconf ifc;
+ struct ifreq *ifr;
+
+ /* get interfaces */
+ buf = ddsrt_malloc (8192);
+ memset (&ifc, 0, sizeof (ifc));
+ ifc.ifc_len = 8192;
+ ifc.ifc_buf = buf;
+ sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (ioctl (sock, SIOCGIFCONF, (char *) &ifc) < 0)
+ {
+ perror ("ioctl (SIOCGIFCONF)");
+ exit (77);
+ }
+
+ ddsrt_ifaddrs_t **ifap, *ifa_root;
+ ifap = &ifa_root; ifa_root = NULL;
+ ifr = ifc.ifc_req;
+ for (n = ifc.ifc_len / sizeof (struct ifreq); --n >= 0; ifr++)
+ {
+ ddsrt_ifaddrs_t *ifa;
+ if (ifr->ifr_name[0] == '\0')
+ continue; /* Forget about anonymous network devices */
+
+ if (ifr->ifr_addr.sa_family != AF_INET) {
+ printf ("%s: not INET\n", ifr->ifr_name);
+ continue;
+ }
+
+ ifa = ddsrt_malloc (sizeof (*ifa));
+ memset (ifa, 0, sizeof (*ifa));
+ ifa->index = (int) (ifr - ifc.ifc_req);
+ ifa->flags = IFF_UP | ((strcmp(ifr->ifr_name, "lo0")==0) ? IFF_LOOPBACK : IFF_MULTICAST);
+ ifa->name = strdup (ifr->ifr_name);
+ ifa->addr = ddsrt_memdup (&ifr->ifr_addr, sizeof (struct sockaddr_in));
+ ifa->netmask = ddsrt_memdup (&ifr->ifr_addr, sizeof (struct sockaddr_in));
+ ((struct sockaddr_in *) ifa->netmask)->sin_addr.s_addr = htonl (0xffffff00);
+ ifa->broadaddr = NULL;
+ ifa->next = NULL;
+ *ifap = ifa;
+ ifap = &ifa->next;
+ }
+
+ ddsrt_free (buf);
+ close (sock);
+ *ret_ifap = ifa_root;
+ return DDS_RETCODE_OK;
+}
diff --git a/src/ddsrt/src/ifaddrs/windows/ifaddrs.c b/src/ddsrt/src/ifaddrs/windows/ifaddrs.c
index 1bd41da..7c5045c 100644
--- a/src/ddsrt/src/ifaddrs/windows/ifaddrs.c
+++ b/src/ddsrt/src/ifaddrs/windows/ifaddrs.c
@@ -23,10 +23,10 @@
extern const int *const os_supp_afs;
-static dds_retcode_t
+static dds_return_t
getifaces(PIP_ADAPTER_ADDRESSES *ptr)
{
- dds_retcode_t err = DDS_RETCODE_NOT_ENOUGH_SPACE;
+ dds_return_t err = DDS_RETCODE_NOT_ENOUGH_SPACE;
PIP_ADAPTER_ADDRESSES buf = NULL;
ULONG bufsz = 0; /* Size is determined on first iteration. */
ULONG ret;
@@ -72,10 +72,10 @@ getifaces(PIP_ADAPTER_ADDRESSES *ptr)
return err;
}
-static dds_retcode_t
+static dds_return_t
getaddrtable(PMIB_IPADDRTABLE *ptr)
{
- dds_retcode_t err = DDS_RETCODE_NOT_ENOUGH_SPACE;
+ dds_return_t err = DDS_RETCODE_NOT_ENOUGH_SPACE;
PMIB_IPADDRTABLE buf = NULL;
ULONG bufsz = 0;
DWORD ret;
@@ -152,6 +152,21 @@ getflags(const PIP_ADAPTER_ADDRESSES iface)
return flags;
}
+static enum ddsrt_iftype
+guess_iftype (const PIP_ADAPTER_ADDRESSES iface)
+{
+ switch (iface->IfType) {
+ case IF_TYPE_IEEE80211:
+ return DDSRT_IFTYPE_WIFI;
+ case IF_TYPE_ETHERNET_CSMACD:
+ case IF_TYPE_IEEE1394:
+ case IF_TYPE_ISO88025_TOKENRING:
+ return DDSRT_IFTYPE_WIRED;
+ default:
+ return DDSRT_IFTYPE_UNKNOWN;
+ }
+}
+
static int
copyaddr(
ddsrt_ifaddrs_t **ifap,
@@ -159,7 +174,7 @@ copyaddr(
const PMIB_IPADDRTABLE addrtable,
const PIP_ADAPTER_UNICAST_ADDRESS addr)
{
- dds_retcode_t err = DDS_RETCODE_OK;
+ dds_return_t err = DDS_RETCODE_OK;
ddsrt_ifaddrs_t *ifa;
struct sockaddr *sa;
size_t sz;
@@ -175,6 +190,7 @@ copyaddr(
err = DDS_RETCODE_OUT_OF_RESOURCES;
} else {
ifa->flags = getflags(iface);
+ ifa->type = guess_iftype(iface);
ifa->addr = ddsrt_memdup(sa, sz);
(void)ddsrt_asprintf(&ifa->name, "%wS", iface->FriendlyName);
if (ifa->addr == NULL || ifa->name == NULL) {
@@ -220,7 +236,7 @@ copyaddr(
return err;
}
-dds_retcode_t
+dds_return_t
ddsrt_getifaddrs(
ddsrt_ifaddrs_t **ifap,
const int *afs)
diff --git a/src/ddsrt/src/log.c b/src/ddsrt/src/log.c
index 558f56e..b7aef78 100644
--- a/src/ddsrt/src/log.c
+++ b/src/ddsrt/src/log.c
@@ -18,10 +18,12 @@
#include "dds/ddsrt/log.h"
#include "dds/ddsrt/sync.h"
#include "dds/ddsrt/threads.h"
+#include "dds/ddsrt/static_assert.h"
+#define MAX_ID_LEN (10)
#define MAX_TIMESTAMP_LEN (10 + 1 + 6)
#define MAX_TID_LEN (10)
-#define HDR_LEN (MAX_TIMESTAMP_LEN + 1 + MAX_TID_LEN + 2)
+#define HDR_LEN (MAX_TIMESTAMP_LEN + 2 + MAX_ID_LEN + 2 + MAX_TID_LEN + 2)
#define BUF_OFFSET HDR_LEN
@@ -31,7 +33,7 @@ typedef struct {
} log_buffer_t;
typedef struct {
- dds_log_write_fn_t funcs[2];
+ dds_log_write_fn_t func;
void *ptr;
FILE *out;
} log_sink_t;
@@ -41,50 +43,58 @@ static ddsrt_thread_local log_buffer_t log_buffer;
static ddsrt_once_t lock_inited = DDSRT_ONCE_INIT;
static ddsrt_rwlock_t lock;
-static uint32_t log_mask = DDS_LC_ERROR | DDS_LC_WARNING;
+struct ddsrt_log_cfg_impl {
+ struct ddsrt_log_cfg_common c;
+ FILE *sink_fps[2];
+};
-static void default_sink(void *ptr, const dds_log_data_t *data)
-{
- fwrite(data->message - HDR_LEN, 1, HDR_LEN + data->size + 1, (FILE *)ptr);
- fflush((FILE *)ptr);
-}
+DDSRT_STATIC_ASSERT (sizeof (struct ddsrt_log_cfg_impl) <= sizeof (struct ddsrt_log_cfg));
-static void nop_sink(void *ptr, const dds_log_data_t *data)
+static void default_sink (void *ptr, const dds_log_data_t *data)
{
- (void)ptr;
- (void)data;
- return;
+ if (ptr)
+ {
+ fwrite (data->message - data->hdrsize, 1, data->hdrsize + data->size + 1, (FILE *) ptr);
+ fflush ((FILE *) ptr);
+ }
}
#define LOG (0)
#define TRACE (1)
-#define USE (0)
-#define SET (1)
-static log_sink_t sinks[] = {
- /* Log */
- { .funcs = { default_sink, default_sink }, .ptr = NULL, .out = NULL },
- /* Trace */
- { .funcs = { nop_sink, default_sink }, .ptr = NULL, .out = NULL }
+static struct ddsrt_log_cfg_impl logconfig = {
+ .c = {
+ .mask = DDS_LC_ERROR | DDS_LC_WARNING,
+ .tracemask = 0,
+ .domid = UINT32_MAX
+ },
+ .sink_fps = {
+ [LOG] = NULL,
+ [TRACE] = NULL
+ }
};
-uint32_t *const dds_log_mask = &log_mask;
+static log_sink_t sinks[2] = {
+ [LOG] = { .func = default_sink, .ptr = NULL, .out = NULL },
+ [TRACE] = { .func = default_sink, .ptr = NULL, .out = NULL }
+};
-#define RDLOCK (1)
-#define WRLOCK (2)
+uint32_t * const dds_log_mask = &logconfig.c.mask;
-static void init_lock(void)
+static void init_lock (void)
{
- ddsrt_rwlock_init(&lock);
+ ddsrt_rwlock_init (&lock);
sinks[LOG].ptr = sinks[TRACE].ptr = stderr;
sinks[LOG].out = sinks[TRACE].out = stderr;
+ logconfig.sink_fps[LOG] = sinks[LOG].ptr;
+ logconfig.sink_fps[TRACE] = sinks[TRACE].ptr;
}
-static void lock_sink(int type)
-{
- assert(type == RDLOCK || type == WRLOCK);
- ddsrt_once(&lock_inited, &init_lock);
+enum lock_type { RDLOCK, WRLOCK };
+static void lock_sink (enum lock_type type)
+{
+ ddsrt_once (&lock_inited, &init_lock);
if (type == RDLOCK) {
ddsrt_rwlock_read(&lock);
} else {
@@ -92,154 +102,134 @@ static void lock_sink(int type)
}
}
-static void unlock_sink(void)
+static void unlock_sink (void)
{
- ddsrt_rwlock_unlock(&lock);
+ ddsrt_rwlock_unlock (&lock);
}
-static void set_active_log_sinks(void)
+static void set_log_sink (log_sink_t *sink, dds_log_write_fn_t func, void *ptr)
{
- if (dds_get_log_mask() & DDS_LOG_MASK) {
- sinks[LOG].funcs[USE] = sinks[LOG].funcs[SET];
- } else {
- sinks[LOG].funcs[USE] = nop_sink;
- }
- if (dds_get_log_mask() & DDS_TRACE_MASK) {
- sinks[TRACE].funcs[USE] = sinks[TRACE].funcs[SET];
- } else {
- sinks[TRACE].funcs[USE] = nop_sink;
- }
- if (sinks[LOG].funcs[USE] == sinks[TRACE].funcs[USE] &&
- sinks[LOG].ptr == sinks[TRACE].ptr)
- {
- sinks[LOG].funcs[USE] = nop_sink;
- }
-}
-
-static void
-set_log_sink(
- log_sink_t *sink,
- dds_log_write_fn_t func,
- void *ptr)
-{
- assert(sink != NULL);
+ assert (sink != NULL);
+ assert (sink == &sinks[0] || sink == &sinks[1]);
/* No life cycle management is done for log sinks, the caller is
responsible for that. Ensure this operation is deterministic and that on
return, no thread in the DDS stack still uses the deprecated sink. */
- lock_sink(WRLOCK);
-
- if (func == 0) {
- sink->funcs[SET] = default_sink;
- sink->ptr = sink->out;
- } else {
- sink->funcs[SET] = func;
- sink->ptr = ptr;
- }
-
- set_active_log_sinks();
- unlock_sink();
+ lock_sink (WRLOCK);
+ sink->func = (func != 0) ? func : default_sink;
+ sink->ptr = ptr;
+ unlock_sink ();
}
/* dds_set_log_file must be considered private. */
-void dds_set_log_file(FILE *file)
+void dds_set_log_file (FILE *file)
{
- lock_sink(WRLOCK);
- sinks[LOG].out = (file == NULL ? stderr : file);
- if (sinks[LOG].funcs[SET] == default_sink) {
- sinks[LOG].ptr = sinks[LOG].out;
- }
- set_active_log_sinks();
- unlock_sink();
+ lock_sink (WRLOCK);
+ logconfig.sink_fps[LOG] = (file == NULL ? stderr : file);
+ unlock_sink ();
}
-void dds_set_trace_file(FILE *file)
+void dds_set_trace_file (FILE *file)
{
- lock_sink(WRLOCK);
- sinks[TRACE].out = (file == NULL ? stderr : file);
- if (sinks[TRACE].funcs[SET] == default_sink) {
- sinks[TRACE].ptr = sinks[TRACE].out;
- }
- set_active_log_sinks();
- unlock_sink();
+ lock_sink (WRLOCK);
+ logconfig.sink_fps[TRACE] = (file == NULL ? stderr : file);
+ unlock_sink ();
}
-void dds_set_log_sink(
- dds_log_write_fn_t callback,
- void *userdata)
+void dds_set_log_sink (dds_log_write_fn_t callback, void *userdata)
{
- set_log_sink(&sinks[LOG], callback, userdata);
+ set_log_sink (&sinks[LOG], callback, userdata);
}
-void dds_set_trace_sink(
- dds_log_write_fn_t callback,
- void *userdata)
+void dds_set_trace_sink (dds_log_write_fn_t callback, void *userdata)
{
- set_log_sink(&sinks[TRACE], callback, userdata);
+ set_log_sink (&sinks[TRACE], callback, userdata);
}
-extern inline uint32_t
-dds_get_log_mask(void);
+extern inline uint32_t dds_get_log_mask (void);
-void
-dds_set_log_mask(uint32_t cats)
+void dds_set_log_mask (uint32_t cats)
{
- lock_sink(WRLOCK);
- *dds_log_mask = (cats & (DDS_LOG_MASK | DDS_TRACE_MASK));
- set_active_log_sinks();
- unlock_sink();
+ lock_sink (WRLOCK);
+ logconfig.c.tracemask = cats & DDS_TRACE_MASK;
+ logconfig.c.mask = (cats & (DDS_LOG_MASK | DDS_TRACE_MASK)) | DDS_LC_FATAL;
+ unlock_sink ();
}
-static void print_header(char *str)
+void dds_log_cfg_init (struct ddsrt_log_cfg *cfg, uint32_t domid, uint32_t tracemask, FILE *log_fp, FILE *trace_fp)
{
- int cnt;
+ struct ddsrt_log_cfg_impl *cfgimpl = (struct ddsrt_log_cfg_impl *) cfg;
+ assert (domid != UINT32_MAX); /* because that's reserved for global use */
+ memset (cfgimpl, 0, sizeof (*cfgimpl));
+ cfgimpl->c.mask = tracemask | DDS_LOG_MASK;
+ cfgimpl->c.tracemask = tracemask;
+ cfgimpl->c.domid = domid;
+ cfgimpl->sink_fps[LOG] = log_fp;
+ cfgimpl->sink_fps[TRACE] = trace_fp;
+}
+
+static size_t print_header (char *str, uint32_t id)
+{
+ int cnt, off;
char *tid, buf[MAX_TID_LEN+1] = { 0 };
- static const char fmt[] = "%10u.%06d/%*.*s:";
+ static const char fmt_no_id[] = "%10u.%06d [] %*.*s:";
+ static const char fmt_with_id[] = "%10u.%06d [%"PRIu32"] %*.*s:";
dds_time_t time;
unsigned sec;
int usec;
- (void)ddsrt_thread_getname(buf, sizeof(buf));
+ (void) ddsrt_thread_getname (buf, sizeof (buf));
tid = (buf[0] == '\0' ? "(anon)" : buf);
- time = dds_time();
- sec = (unsigned)(time / DDS_NSECS_IN_SEC);
- usec = (int)((time % DDS_NSECS_IN_SEC) / DDS_NSECS_IN_USEC);
+ time = dds_time ();
+ sec = (unsigned) (time / DDS_NSECS_IN_SEC);
+ usec = (int) ((time % DDS_NSECS_IN_SEC) / DDS_NSECS_IN_USEC);
- cnt = snprintf(
- str, HDR_LEN, fmt, sec, usec, MAX_TID_LEN, MAX_TID_LEN, tid);
- assert(cnt == (HDR_LEN - 1));
- str[cnt] = ' '; /* Replace snprintf null byte by space. */
+ if (id == UINT32_MAX)
+ {
+ off = MAX_ID_LEN;
+ cnt = snprintf (str + off, HDR_LEN, fmt_no_id, sec, usec, MAX_TID_LEN, MAX_TID_LEN, tid);
+ }
+ else
+ {
+ /* low domain ids tend to be most used from what I have seen */
+ off = 9;
+ if (id >= 10)
+ for (uint32_t thres = 10; off > 0 && id >= thres; off--, thres *= 10);
+ cnt = snprintf (str + off, HDR_LEN, fmt_with_id, sec, usec, id, MAX_TID_LEN, MAX_TID_LEN, tid);
+ }
+ assert (off + cnt == (HDR_LEN - 1));
+ str[off + cnt] = ' '; /* Replace snprintf null byte by space. */
+ return (size_t) cnt;
}
-static void vlog(
- uint32_t cat,
- const char *file,
- uint32_t line,
- const char *func,
- const char *fmt,
- va_list ap)
+static void vlog1 (const struct ddsrt_log_cfg_impl *cfg, uint32_t cat, uint32_t domid, const char *file, uint32_t line, const char *func, const char *fmt, va_list ap)
{
int n, trunc = 0;
size_t nrem;
log_buffer_t *lb;
dds_log_data_t data;
+ /* id can be used to override the id in logconfig, so that the global
+ logging configuration can be used for reporting errors while inlcuding
+ a domain id. This simply verifies that the id override is only ever
+ used with the global one. */
+ assert (domid == cfg->c.domid || cfg == &logconfig);
+
if (*fmt == 0) {
return;
}
- lock_sink(RDLOCK);
lb = &log_buffer;
/* Thread-local buffer is always initialized with all zeroes. The pos
member must always be greater or equal to BUF_OFFSET. */
if (lb->pos < BUF_OFFSET) {
- lb->pos = BUF_OFFSET;
- lb->buf[lb->pos] = 0;
+ lb->pos = BUF_OFFSET;
+ lb->buf[lb->pos] = 0;
}
nrem = sizeof (lb->buf) - lb->pos;
if (nrem > 0) {
- n = vsnprintf(lb->buf + lb->pos, nrem, fmt, ap);
+ n = vsnprintf (lb->buf + lb->pos, nrem, fmt, ap);
if (n >= 0 && (size_t) n < nrem) {
lb->pos += (size_t) n;
} else {
@@ -249,54 +239,89 @@ static void vlog(
if (trunc) {
static const char msg[] = "(trunc)\n";
const size_t msglen = sizeof (msg) - 1;
- assert(lb->pos <= sizeof (lb->buf));
- assert(lb->pos >= msglen);
- memcpy(lb->buf + lb->pos - msglen, msg, msglen);
+ assert (lb->pos <= sizeof (lb->buf));
+ assert (lb->pos >= msglen);
+ memcpy (lb->buf + lb->pos - msglen, msg, msglen);
}
}
- if (fmt[strlen (fmt) - 1] == '\n') {
- print_header(lb->buf);
+ if (fmt[strlen (fmt) - 1] == '\n' && lb->pos > BUF_OFFSET + 1) {
+ assert (lb->pos > BUF_OFFSET);
+ size_t hdrsize = print_header (lb->buf, domid);
data.priority = cat;
data.file = file;
data.function = func;
data.line = line;
data.message = lb->buf + BUF_OFFSET;
- data.size = strlen(data.message) - 1;
+ data.size = lb->pos - BUF_OFFSET - 1;
+ data.hdrsize = hdrsize;
- for (size_t i = (cat & DDS_LOG_MASK) ? LOG : TRACE;
- i < sizeof(sinks) / sizeof(sinks[0]);
- i++)
+ dds_log_write_fn_t f = 0;
+ void *f_arg = NULL;
+ if (cat & DDS_LOG_MASK)
{
- sinks[i].funcs[USE](sinks[i].ptr, &data);
+ f = sinks[LOG].func;
+ f_arg = (f == default_sink) ? cfg->sink_fps[LOG] : sinks[LOG].ptr;
+ assert (f != 0);
+ f (f_arg, &data);
+ }
+ /* if tracing is enabled, then print to trace if it matches the
+ trace flags or if it got written to the log
+ (mask == (tracemask | DDS_LOG_MASK)) */
+ if (cfg->c.tracemask && (cat & cfg->c.mask))
+ {
+ dds_log_write_fn_t const g = sinks[TRACE].func;
+ void * const g_arg = (g == default_sink) ? cfg->sink_fps[TRACE] : sinks[TRACE].ptr;
+ assert (g != 0);
+ if (g != f || g_arg != f_arg)
+ g (g_arg, &data);
}
lb->pos = BUF_OFFSET;
lb->buf[lb->pos] = 0;
}
-
- unlock_sink();
}
-int
-dds_log(
- uint32_t cat,
- const char *file,
- uint32_t line,
- const char *func,
- const char *fmt,
- ...)
+static void vlog (const struct ddsrt_log_cfg_impl *cfg, uint32_t cat, uint32_t domid, const char *file, uint32_t line, const char *func, const char *fmt, va_list ap)
{
- if ((dds_get_log_mask() & cat) || (cat & DDS_LC_FATAL)) {
- va_list ap;
- va_start(ap, fmt);
- vlog(cat, file, line, func, fmt, ap);
- va_end(ap);
- }
- if (cat & DDS_LC_FATAL) {
+ lock_sink (RDLOCK);
+ vlog1 (cfg, cat, domid, file, line, func, fmt, ap);
+ unlock_sink ();
+ if (cat & DDS_LC_FATAL)
abort();
- }
-
- return 0;
+}
+
+void dds_log_cfg (const struct ddsrt_log_cfg *cfg, uint32_t cat, const char *file, uint32_t line, const char *func, const char *fmt, ...)
+{
+ const struct ddsrt_log_cfg_impl *cfgimpl = (const struct ddsrt_log_cfg_impl *) cfg;
+ /* cfgimpl->c.mask is too weak a test because it has all DDS_LOG_MASK bits set,
+ rather than just the ones in dds_get_log_mask() (so as not to cache the latter
+ and have to keep them synchronized */
+ if ((cfgimpl->c.mask & cat) && ((dds_get_log_mask () | cfgimpl->c.tracemask) & cat)) {
+ va_list ap;
+ va_start (ap, fmt);
+ vlog (cfgimpl, cat, cfgimpl->c.domid, file, line, func, fmt, ap);
+ va_end (ap);
+ }
+}
+
+void dds_log_id (uint32_t cat, uint32_t id, const char *file, uint32_t line, const char *func, const char *fmt, ...)
+{
+ if (dds_get_log_mask () & cat) {
+ va_list ap;
+ va_start (ap, fmt);
+ vlog (&logconfig, cat, id, file, line, func, fmt, ap);
+ va_end (ap);
+ }
+}
+
+void dds_log (uint32_t cat, const char *file, uint32_t line, const char *func, const char *fmt, ...)
+{
+ if (dds_get_log_mask () & cat) {
+ va_list ap;
+ va_start (ap, fmt);
+ vlog (&logconfig, cat, UINT32_MAX, file, line, func, fmt, ap);
+ va_end (ap);
+ }
}
diff --git a/src/ddsrt/src/netstat/darwin/netstat.c b/src/ddsrt/src/netstat/darwin/netstat.c
new file mode 100644
index 0000000..7ffd7c8
--- /dev/null
+++ b/src/ddsrt/src/netstat/darwin/netstat.c
@@ -0,0 +1,130 @@
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+struct ddsrt_netstat_control {
+ char *name;
+ int cached_row;
+};
+
+static dds_return_t ddsrt_netstat_get_int (struct ddsrt_netstat_control *control, struct ddsrt_netstat *stats)
+{
+ int name[6];
+ size_t len;
+ int count;
+ struct ifmibdata ifmd;
+
+ if (control->cached_row > 0)
+ {
+ name[0] = CTL_NET;
+ name[1] = PF_LINK;
+ name[2] = NETLINK_GENERIC;
+ name[3] = IFMIB_IFDATA;
+ name[4] = control->cached_row;
+ name[5] = IFDATA_GENERAL;
+ len = sizeof (ifmd);
+ if (sysctl (name, 6, &ifmd, &len, NULL, 0) != 0)
+ control->cached_row = 0;
+ else if (strcmp (ifmd.ifmd_name, control->name) != 0)
+ control->cached_row = 0;
+ }
+
+ if (control->cached_row == 0)
+ {
+ name[0] = CTL_NET;
+ name[1] = PF_LINK;
+ name[2] = NETLINK_GENERIC;
+ name[3] = IFMIB_SYSTEM;
+ name[4] = IFMIB_IFCOUNT;
+ len = sizeof (count);
+ if (sysctl (name, 5, &count, &len, NULL, 0) != 0)
+ goto error;
+ for (int row = 1; row <= count; row++)
+ {
+ name[0] = CTL_NET;
+ name[1] = PF_LINK;
+ name[2] = NETLINK_GENERIC;
+ name[3] = IFMIB_IFDATA;
+ name[4] = row;
+ name[5] = IFDATA_GENERAL;
+ len = sizeof (ifmd);
+ if (sysctl (name, 6, &ifmd, &len, NULL, 0) != 0)
+ {
+ if (errno != ENOENT)
+ goto error;
+ }
+ else if (strcmp (control->name, ifmd.ifmd_name) == 0)
+ {
+ control->cached_row = row;
+ break;
+ }
+ }
+ }
+
+ if (control->cached_row == 0)
+ return DDS_RETCODE_NOT_FOUND;
+ else
+ {
+ stats->ipkt = ifmd.ifmd_data.ifi_ipackets;
+ stats->opkt = ifmd.ifmd_data.ifi_opackets;
+ stats->ibytes = ifmd.ifmd_data.ifi_ibytes;
+ stats->obytes = ifmd.ifmd_data.ifi_obytes;
+ return DDS_RETCODE_OK;
+ }
+
+ error:
+ control->cached_row = -1;
+ return DDS_RETCODE_ERROR;
+}
+
+dds_return_t ddsrt_netstat_new (struct ddsrt_netstat_control **control, const char *device)
+{
+ struct ddsrt_netstat_control *c = ddsrt_malloc (sizeof (*c));
+ struct ddsrt_netstat dummy;
+ c->name = ddsrt_strdup (device);
+ c->cached_row = 0;
+ if (ddsrt_netstat_get_int (c, &dummy) != DDS_RETCODE_OK)
+ {
+ ddsrt_free (c->name);
+ ddsrt_free (c);
+ *control = NULL;
+ return DDS_RETCODE_ERROR;
+ }
+ else
+ {
+ *control = c;
+ return DDS_RETCODE_OK;
+ }
+}
+
+dds_return_t ddsrt_netstat_free (struct ddsrt_netstat_control *control)
+{
+ ddsrt_free (control->name);
+ ddsrt_free (control);
+ return DDS_RETCODE_OK;
+}
+
+dds_return_t ddsrt_netstat_get (struct ddsrt_netstat_control *control, struct ddsrt_netstat *stats)
+{
+ if (control->cached_row < 0)
+ return DDS_RETCODE_ERROR;
+ else
+ return ddsrt_netstat_get_int (control, stats);
+}
diff --git a/src/ddsrt/src/netstat/linux/netstat.c b/src/ddsrt/src/netstat/linux/netstat.c
new file mode 100644
index 0000000..b0c2c81
--- /dev/null
+++ b/src/ddsrt/src/netstat/linux/netstat.c
@@ -0,0 +1,146 @@
+#include
+#include
+#include
+#include
+
+#include