19static void *s_capability_context;
24 s_capability_context = context;
29static size_t skip_ws(
const char *buf,
size_t len,
size_t pos)
32 ((buf[pos] ==
' ') || (buf[pos] ==
'\t') || (buf[pos] ==
'\n') || (buf[pos] ==
'\r'))) {
45 const char *key,
size_t *out_value_pos)
52 (void)strncpy(&needle[1], key,
sizeof(needle) - 2U);
53 needle[
sizeof(needle) - 1U] =
'\0';
54 needle_len = strlen(needle);
55 if ((needle_len + 1U) >=
sizeof(needle)) {
58 needle[needle_len] =
'"';
60 needle[needle_len] =
'\0';
62 if ((start_pos + needle_len) > end_pos) {
66 for (i = start_pos; (i + needle_len) <= end_pos; i++) {
67 if (memcmp(&buf[i], needle, needle_len) == 0) {
68 size_t pos = i + needle_len;
69 pos =
skip_ws(buf, end_pos, pos);
70 if ((pos >= end_pos) || (buf[pos] !=
':')) {
74 pos =
skip_ws(buf, end_pos, pos);
82static rte_status_t find_key_value_pos(
const char *buf,
size_t len,
const char *key,
size_t *out_value_pos)
89 char *out,
size_t out_size,
size_t *out_end_pos)
94 if ((pos >= len) || (buf[pos] !=
'"')) {
99 while ((pos < len) && (buf[pos] !=
'"')) {
109 (void)memcpy(out, &buf[start], n);
111 *out_end_pos = pos + 1U;
121 while ((pos < len) && (buf[pos] >=
'0') && (buf[pos] <=
'9')) {
122 value = (value * 10U) + (uint32_t)(buf[pos] -
'0');
154 while ((status ==
RTE_STATUS_OK) && (idx < len) && (buf[idx] >=
'0') && (buf[idx] <=
'9')) {
155 uint32_t digit = (uint32_t)((uint8_t)buf[idx]) - (uint32_t)((uint8_t)
'0');
156 if (value > ((UINT32_MAX - digit) / 10U)) {
159 value = (value * 10U) + digit;
171 if ((idx < len) && (buf[idx] !=
',')) {
196 const char *key, uint32_t *out)
210 uint32_t max_items, uint32_t *out_count)
214 if ((pos >= len) || (buf[pos] !=
'[')) {
220 while ((pos < len) && (buf[pos] !=
']')) {
224 if (count >= max_items) {
232 pos =
skip_ws(buf, len, end_pos);
233 if ((pos < len) && (buf[pos] ==
',')) {
238 if ((pos >= len) || (buf[pos] !=
']')) {
247 if ((name == NULL) || (out_transport == NULL)) {
250 if ((strcmp(name,
"flow") == 0) || (strcmp(name,
"FLOW") == 0)) {
251 *out_transport = RTE_CHANNEL_TRANSPORT_FLOW;
254 if ((strcmp(name,
"netlink") == 0) || (strcmp(name,
"posix") == 0) || (strcmp(name,
"POSIX") == 0)) {
255 *out_transport = RTE_CHANNEL_TRANSPORT_POSIX_NETLINK;
258 if ((strcmp(name,
"dds") == 0) || (strcmp(name,
"DDS") == 0)) {
259 *out_transport = RTE_CHANNEL_TRANSPORT_DDS;
267 if ((name == NULL) || (out_role == NULL)) {
270 if ((strcmp(name,
"listen") == 0) || (strcmp(name,
"LISTEN") == 0) ||
271 (strcmp(name,
"subscriber") == 0) || (strcmp(name,
"SUBSCRIBER") == 0)) {
272 *out_role = RTE_CHANNEL_ROLE_LISTEN;
275 if ((strcmp(name,
"connect") == 0) || (strcmp(name,
"CONNECT") == 0) ||
276 (strcmp(name,
"publisher") == 0) || (strcmp(name,
"PUBLISHER") == 0)) {
277 *out_role = RTE_CHANNEL_ROLE_CONNECT;
283static rte_status_t parse_channel_object(
const char *buf,
size_t obj_start,
size_t obj_end,
291 (void)memset(out_channel, 0,
sizeof(*out_channel));
308 sizeof(out_channel->name), &end_pos);
314 out_channel->transport = RTE_CHANNEL_TRANSPORT_FLOW;
317 status =
parse_string_value(buf, obj_end, val_pos, str_buf,
sizeof(str_buf), &end_pos);
324 out_channel->role = RTE_CHANNEL_ROLE_CONNECT;
327 status =
parse_string_value(buf, obj_end, val_pos, str_buf,
sizeof(str_buf), &end_pos);
337 sizeof(out_channel->host), &end_pos);
343 uint32_t port_val = 0U;
345 out_channel->port = (uint16_t)port_val;
358 (void)
parse_uint_value(buf, obj_end, val_pos, &out_channel->connect_timeout_ms);
375static rte_status_t parse_channels_array(
const char *buf,
size_t len,
size_t pos,
377 uint32_t max_channels, uint32_t *out_count)
381 if ((pos >= len) || (buf[pos] !=
'[')) {
387 while ((pos < len) && (buf[pos] !=
']')) {
392 if (count >= max_channels) {
395 if (buf[pos] !=
'{') {
400 while ((pos < len) && (buf[pos] !=
'}')) {
409 status = parse_channel_object(buf, obj_start, obj_end, &out_channels[count]);
416 if ((pos < len) && (buf[pos] ==
',')) {
421 if ((pos >= len) || (buf[pos] !=
']')) {
430 if ((name == NULL) || (out_topology == NULL)) {
433 if (strcmp(name,
"2oo2") == 0) {
437 if (strcmp(name,
"2oo2_redundant") == 0) {
441 if (strcmp(name,
"2oo3") == 0) {
445 if (strcmp(name,
"nmr") == 0) {
461 result =
"2oo2_redundant";
478 if ((name == NULL) || (out_mode == NULL)) {
481 if (strcmp(name,
"hot") == 0) {
485 if (strcmp(name,
"warm") == 0) {
489 if (strcmp(name,
"cold") == 0) {
525 char topology_name[24];
528 status = find_key_value_pos(buf, len,
"topology", &value_pos);
534 status =
parse_string_value(buf, len, value_pos, topology_name,
sizeof(topology_name), &end_pos);
544 status = find_key_value_pos(buf, len,
"replicas", &value_pos);
557 status = find_key_value_pos(buf, len,
"quorum", &value_pos);
603 status = find_key_value_pos(buf, len,
"standby_mode", &value_pos);
605 char standby_mode_name[8];
607 status =
parse_string_value(buf, len, value_pos, standby_mode_name,
sizeof(standby_mode_name), &end_pos);
626 status = find_key_value_pos(buf, len,
"roles", &value_pos);
647 status = find_key_value_pos(buf, len,
"channels", &value_pos);
649 status = parse_channels_array(buf, len, value_pos, result->
channels,
668 if ((path == NULL) || (out_config == NULL)) {
672 fp = fopen(path,
"rb");
676 len = fread(buf, 1U,
sizeof(buf), fp);
677 if ((ferror(fp) != 0) || (feof(fp) == 0)) {
685 (void)memset(&result, 0,
sizeof(result));
687 status = parse_topology_replicas_and_quorum(buf, len, &result);
692 status = parse_optional_standby_mode(buf, len, &result);
697 status = parse_optional_roles(buf, len, &result);
702 status = parse_optional_channels(buf, len, &result);
707 if ((s_capability_fn != NULL) && (!s_capability_fn(result.
topology, result.
replica_count, s_capability_context))) {
711 *out_config = result;
719 if ((config == NULL) || (voter_cfg == NULL)) {
732 if ((config == NULL) || (name == NULL) || (out_channel == NULL)) {
736 if (strncmp(config->
channels[i].name, name,
sizeof(config->
channels[i].name)) == 0) {
750 if ((config == NULL) || (out_channel == NULL)) {
763static bool s_has_active_config =
false;
767 return s_has_active_config ? &s_active_config : NULL;
772 if (config != NULL) {
773 s_active_config = *config;
774 s_has_active_config =
true;
776 s_has_active_config =
false;
rte_status_t
Common result/status codes.
@ RTE_STATUS_INTERNAL_ERROR
@ RTE_STATUS_INVALID_STATE
@ RTE_STATUS_INVALID_PARAM
@ RTE_STATUS_NOT_SUPPORTED
void rte_redundancy_config_set_active(const rte_redundancy_config_t *config)
Set the active configuration explicitly (or automatically by rte_redundancy_config_load).
const rte_redundancy_config_t * rte_redundancy_config_get_active(void)
Get the currently active loaded redundancy/channel configuration (if any).
rte_status_t rte_redundancy_config_standby_mode_from_string(const char *name, rte_standby_mode_t *out_mode)
Parse a standby-mode name string ("hot", "warm", "cold") into its enum value.
rte_status_t rte_redundancy_config_find_channel_by_id(const rte_redundancy_config_t *config, uint32_t id, rte_channel_def_t *out_channel)
Find channel definition by ID in the given configuration.
rte_status_t rte_redundancy_config_topology_from_string(const char *name, rte_redundancy_topology_t *out_topology)
Parse a topology name string ("2oo2", "2oo2_redundant", "2oo3", "nmr") into its enum value.
rte_status_t rte_redundancy_config_register_capability(rte_redundancy_capability_fn fn, void *context)
Registers the capability callback rte_redundancy_config_load() consults after successfully parsing a ...
const char * rte_redundancy_config_standby_mode_to_string(rte_standby_mode_t mode)
Inverse of rte_redundancy_config_standby_mode_from_string() - for logging/diagnostics.
#define RTE_CHANNEL_CONFIG_MAX_CHANNELS
const char * rte_redundancy_config_topology_to_string(rte_redundancy_topology_t topology)
Inverse of rte_redundancy_config_topology_from_string() - for logging/diagnostics.
#define RTE_REDUNDANCY_CONFIG_MAX_REPLICAS
rte_status_t rte_channel_config_transport_from_string(const char *name, rte_channel_transport_t *out_transport)
Parse transport name string ("flow", "netlink", "posix", "dds") into enum.
rte_status_t rte_redundancy_config_find_channel_by_name(const rte_redundancy_config_t *config, const char *name, rte_channel_def_t *out_channel)
Find channel definition by name in the given configuration.
rte_status_t rte_channel_config_role_from_string(const char *name, rte_channel_role_t *out_role)
Parse channel role name string ("listen", "connect", "publisher", "subscriber") into enum.
rte_standby_mode_t
How a non-active replica ("standby") keeps itself ready to take over, and how rte_state_transfer (red...
#define RTE_REDUNDANCY_CONFIG_MAX_ROLE_NAME_LEN
rte_status_t rte_redundancy_config_load(const char *path, rte_redundancy_config_t *out_config)
Load a redundancy topology config from a JSON file.
bool(*) rte_redundancy_capability_fn(rte_redundancy_topology_t topology, uint32_t replica_count, void *context)
Integrator-supplied capability query: can THIS application actually run the given topology/replica_co...
rte_redundancy_topology_t
rte_status_t rte_redundancy_config_apply_to_voter(const rte_redundancy_config_t *config, rte_voter_config_t *voter_cfg)
Copy the resolved quorum from a loaded redundancy config into a rte_voter_config_t,...
#define RTE_REDUNDANCY_CONFIG_MAX_FILE_SIZE
@ RTE_REDUNDANCY_TOPOLOGY_2OO2_REDUNDANT
@ RTE_REDUNDANCY_TOPOLOGY_2OO3
@ RTE_REDUNDANCY_TOPOLOGY_NMR
@ RTE_REDUNDANCY_TOPOLOGY_2OO2
static rte_status_t parse_string_array(const char *buf, size_t len, size_t pos, char out[][RTE_REDUNDANCY_CONFIG_MAX_ROLE_NAME_LEN], uint32_t max_items, uint32_t *out_count)
static rte_status_t parse_optional_channel_u32(const char *buf, size_t obj_start, size_t obj_end, const char *key, uint32_t *out)
Optional checked unsigned key inside one channel object (REQ-REDCFG-001).
static size_t skip_ws(const char *buf, size_t len, size_t pos)
static rte_status_t parse_string_value(const char *buf, size_t len, size_t pos, char *out, size_t out_size, size_t *out_end_pos)
static rte_status_t parse_uint_value(const char *buf, size_t len, size_t pos, uint32_t *out)
static rte_status_t find_key_value_pos_bounded(const char *buf, size_t start_pos, size_t end_pos, const char *key, size_t *out_value_pos)
Find "key" followed by a colon, return the index just past the colon (and any whitespace),...
static rte_status_t parse_uint32_checked(const char *buf, size_t len, size_t pos, uint32_t *out)
Checked variant of parse_uint_value(), used for the socket buffer keys (REQ-REDCFG-001)....
Application-level redundancy topology configuration (2oo2 / 2oo2 with redundancy / 2oo3 / NMR),...
rte_standby_mode_t standby_mode
rte_channel_def_t channels[RTE_CHANNEL_CONFIG_MAX_CHANNELS]
rte_redundancy_topology_t topology
char roles[RTE_REDUNDANCY_CONFIG_MAX_REPLICAS][RTE_REDUNDANCY_CONFIG_MAX_ROLE_NAME_LEN]
Configuration for rte_voter_init().