Safe API Framework 0.1.0 build 384e6ae
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
Loading...
Searching...
No Matches
rte_redundancy_config.c
Go to the documentation of this file.
1
13
14#include <stdio.h>
15#include <string.h>
16#include <stdbool.h>
17
18static rte_redundancy_capability_fn s_capability_fn;
19static void *s_capability_context;
20
22{
23 s_capability_fn = fn;
24 s_capability_context = context;
25 return RTE_STATUS_OK;
26}
27
29static size_t skip_ws(const char *buf, size_t len, size_t pos)
30{
31 while ((pos < len) &&
32 ((buf[pos] == ' ') || (buf[pos] == '\t') || (buf[pos] == '\n') || (buf[pos] == '\r'))) {
33 pos++;
34 }
35 return pos;
36}
37
44static rte_status_t find_key_value_pos_bounded(const char *buf, size_t start_pos, size_t end_pos,
45 const char *key, size_t *out_value_pos)
46{
47 char needle[40];
48 size_t needle_len;
49 size_t i;
50
51 needle[0] = '"';
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)) {
57 }
58 needle[needle_len] = '"';
59 needle_len++;
60 needle[needle_len] = '\0';
61
62 if ((start_pos + needle_len) > end_pos) {
64 }
65
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] != ':')) {
71 continue;
72 }
73 pos++;
74 pos = skip_ws(buf, end_pos, pos);
75 *out_value_pos = pos;
76 return RTE_STATUS_OK;
77 }
78 }
80}
81
82static rte_status_t find_key_value_pos(const char *buf, size_t len, const char *key, size_t *out_value_pos)
83{
84 return find_key_value_pos_bounded(buf, 0U, len, key, out_value_pos);
85}
86
88static rte_status_t parse_string_value(const char *buf, size_t len, size_t pos,
89 char *out, size_t out_size, size_t *out_end_pos)
90{
91 size_t start;
92 size_t n;
93
94 if ((pos >= len) || (buf[pos] != '"')) {
96 }
97 pos++;
98 start = pos;
99 while ((pos < len) && (buf[pos] != '"')) {
100 pos++;
101 }
102 if (pos >= len) {
104 }
105 n = pos - start;
106 if (n >= out_size) {
108 }
109 (void)memcpy(out, &buf[start], n);
110 out[n] = '\0';
111 *out_end_pos = pos + 1U;
112 return RTE_STATUS_OK;
113}
114
116static rte_status_t parse_uint_value(const char *buf, size_t len, size_t pos, uint32_t *out)
117{
118 size_t start = pos;
119 uint32_t value = 0U;
120
121 while ((pos < len) && (buf[pos] >= '0') && (buf[pos] <= '9')) {
122 value = (value * 10U) + (uint32_t)(buf[pos] - '0');
123 pos++;
124 }
125 if (pos == start) {
127 }
128 *out = value;
129 return RTE_STATUS_OK;
130}
131
148static rte_status_t parse_uint32_checked(const char *buf, size_t len, size_t pos, uint32_t *out)
149{
150 size_t idx = pos;
151 uint32_t value = 0U;
153
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)) {
158 } else {
159 value = (value * 10U) + digit;
160 idx++;
161 }
162 }
163 if ((status == RTE_STATUS_OK) && (idx == pos)) {
165 }
166 if (status == RTE_STATUS_OK) {
167 /* Only whitespace may separate the digits from the ',' or the object end
168 * (len is the index of the object's '}'): "1 000 000", "256 * 1024" and
169 * "262144 KB" are rejected, not read as their first number. */
170 idx = skip_ws(buf, len, idx);
171 if ((idx < len) && (buf[idx] != ',')) {
173 }
174 }
175 if (status == RTE_STATUS_OK) {
176 *out = value;
177 }
178 return status;
179}
180
195static rte_status_t parse_optional_channel_u32(const char *buf, size_t obj_start, size_t obj_end,
196 const char *key, uint32_t *out)
197{
198 size_t val_pos;
200
201 if (find_key_value_pos_bounded(buf, obj_start, obj_end, key, &val_pos) == RTE_STATUS_OK) {
202 status = parse_uint32_checked(buf, obj_end, val_pos, out);
203 }
204 return status;
205}
206
208static rte_status_t parse_string_array(const char *buf, size_t len, size_t pos,
210 uint32_t max_items, uint32_t *out_count)
211{
212 uint32_t count = 0U;
213
214 if ((pos >= len) || (buf[pos] != '[')) {
216 }
217 pos++;
218 pos = skip_ws(buf, len, pos);
219
220 while ((pos < len) && (buf[pos] != ']')) {
221 size_t end_pos;
222 rte_status_t status;
223
224 if (count >= max_items) {
226 }
227 status = parse_string_value(buf, len, pos, out[count], RTE_REDUNDANCY_CONFIG_MAX_ROLE_NAME_LEN, &end_pos);
228 if (status != RTE_STATUS_OK) {
229 return status;
230 }
231 count++;
232 pos = skip_ws(buf, len, end_pos);
233 if ((pos < len) && (buf[pos] == ',')) {
234 pos++;
235 pos = skip_ws(buf, len, pos);
236 }
237 }
238 if ((pos >= len) || (buf[pos] != ']')) {
240 }
241 *out_count = count;
242 return RTE_STATUS_OK;
243}
244
246{
247 if ((name == NULL) || (out_transport == NULL)) {
249 }
250 if ((strcmp(name, "flow") == 0) || (strcmp(name, "FLOW") == 0)) {
251 *out_transport = RTE_CHANNEL_TRANSPORT_FLOW;
252 return RTE_STATUS_OK;
253 }
254 if ((strcmp(name, "netlink") == 0) || (strcmp(name, "posix") == 0) || (strcmp(name, "POSIX") == 0)) {
255 *out_transport = RTE_CHANNEL_TRANSPORT_POSIX_NETLINK;
256 return RTE_STATUS_OK;
257 }
258 if ((strcmp(name, "dds") == 0) || (strcmp(name, "DDS") == 0)) {
259 *out_transport = RTE_CHANNEL_TRANSPORT_DDS;
260 return RTE_STATUS_OK;
261 }
263}
264
266{
267 if ((name == NULL) || (out_role == NULL)) {
269 }
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;
273 return RTE_STATUS_OK;
274 }
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;
278 return RTE_STATUS_OK;
279 }
281}
282
283static rte_status_t parse_channel_object(const char *buf, size_t obj_start, size_t obj_end,
284 rte_channel_def_t *out_channel)
285{
286 size_t val_pos;
287 size_t end_pos;
288 char str_buf[64];
289 rte_status_t status;
290
291 (void)memset(out_channel, 0, sizeof(*out_channel));
292
293 /* id (optional) */
294 status = find_key_value_pos_bounded(buf, obj_start, obj_end, "id", &val_pos);
295 if (status == RTE_STATUS_OK) {
296 status = parse_uint_value(buf, obj_end, val_pos, &out_channel->id);
297 if (status != RTE_STATUS_OK) {
299 }
300 }
301
302 /* name (required) */
303 status = find_key_value_pos_bounded(buf, obj_start, obj_end, "name", &val_pos);
304 if (status != RTE_STATUS_OK) {
306 }
307 status = parse_string_value(buf, obj_end, val_pos, out_channel->name,
308 sizeof(out_channel->name), &end_pos);
309 if (status != RTE_STATUS_OK) {
311 }
312
313 /* transport (optional, defaults to FLOW) */
314 out_channel->transport = RTE_CHANNEL_TRANSPORT_FLOW;
315 status = find_key_value_pos_bounded(buf, obj_start, obj_end, "transport", &val_pos);
316 if (status == RTE_STATUS_OK) {
317 status = parse_string_value(buf, obj_end, val_pos, str_buf, sizeof(str_buf), &end_pos);
318 if (status == RTE_STATUS_OK) {
319 (void)rte_channel_config_transport_from_string(str_buf, &out_channel->transport);
320 }
321 }
322
323 /* role (optional, defaults to CONNECT) */
324 out_channel->role = RTE_CHANNEL_ROLE_CONNECT;
325 status = find_key_value_pos_bounded(buf, obj_start, obj_end, "role", &val_pos);
326 if (status == RTE_STATUS_OK) {
327 status = parse_string_value(buf, obj_end, val_pos, str_buf, sizeof(str_buf), &end_pos);
328 if (status == RTE_STATUS_OK) {
329 (void)rte_channel_config_role_from_string(str_buf, &out_channel->role);
330 }
331 }
332
333 /* host (optional) */
334 status = find_key_value_pos_bounded(buf, obj_start, obj_end, "host", &val_pos);
335 if (status == RTE_STATUS_OK) {
336 (void)parse_string_value(buf, obj_end, val_pos, out_channel->host,
337 sizeof(out_channel->host), &end_pos);
338 }
339
340 /* port (optional) */
341 status = find_key_value_pos_bounded(buf, obj_start, obj_end, "port", &val_pos);
342 if (status == RTE_STATUS_OK) {
343 uint32_t port_val = 0U;
344 if (parse_uint_value(buf, obj_end, val_pos, &port_val) == RTE_STATUS_OK) {
345 out_channel->port = (uint16_t)port_val;
346 }
347 }
348
349 /* message_size (optional) */
350 status = find_key_value_pos_bounded(buf, obj_start, obj_end, "message_size", &val_pos);
351 if (status == RTE_STATUS_OK) {
352 (void)parse_uint_value(buf, obj_end, val_pos, &out_channel->message_size);
353 }
354
355 /* connect_timeout_ms (optional) */
356 status = find_key_value_pos_bounded(buf, obj_start, obj_end, "connect_timeout_ms", &val_pos);
357 if (status == RTE_STATUS_OK) {
358 (void)parse_uint_value(buf, obj_end, val_pos, &out_channel->connect_timeout_ms);
359 }
360
361 /* rcvbuf_bytes / sndbuf_bytes (optional, 0 = OS default; a malformed or
362 * out-of-range value fails the load, REQ-REDCFG-001) */
363 status = parse_optional_channel_u32(buf, obj_start, obj_end, "rcvbuf_bytes", &out_channel->rcvbuf_bytes);
364 if (status != RTE_STATUS_OK) {
366 }
367 status = parse_optional_channel_u32(buf, obj_start, obj_end, "sndbuf_bytes", &out_channel->sndbuf_bytes);
368 if (status != RTE_STATUS_OK) {
370 }
371
372 return RTE_STATUS_OK;
373}
374
375static rte_status_t parse_channels_array(const char *buf, size_t len, size_t pos,
376 rte_channel_def_t *out_channels,
377 uint32_t max_channels, uint32_t *out_count)
378{
379 uint32_t count = 0U;
380
381 if ((pos >= len) || (buf[pos] != '[')) {
383 }
384 pos++;
385 pos = skip_ws(buf, len, pos);
386
387 while ((pos < len) && (buf[pos] != ']')) {
388 size_t obj_start;
389 size_t obj_end;
390 rte_status_t status;
391
392 if (count >= max_channels) {
394 }
395 if (buf[pos] != '{') {
397 }
398 obj_start = pos;
399 pos++;
400 while ((pos < len) && (buf[pos] != '}')) {
401 pos++;
402 }
403 if (pos >= len) {
405 }
406 obj_end = pos;
407 pos++; /* past '}' */
408
409 status = parse_channel_object(buf, obj_start, obj_end, &out_channels[count]);
410 if (status != RTE_STATUS_OK) {
411 return status;
412 }
413 count++;
414
415 pos = skip_ws(buf, len, pos);
416 if ((pos < len) && (buf[pos] == ',')) {
417 pos++;
418 pos = skip_ws(buf, len, pos);
419 }
420 }
421 if ((pos >= len) || (buf[pos] != ']')) {
423 }
424 *out_count = count;
425 return RTE_STATUS_OK;
426}
427
429{
430 if ((name == NULL) || (out_topology == NULL)) {
432 }
433 if (strcmp(name, "2oo2") == 0) {
434 *out_topology = RTE_REDUNDANCY_TOPOLOGY_2OO2;
435 return RTE_STATUS_OK;
436 }
437 if (strcmp(name, "2oo2_redundant") == 0) {
439 return RTE_STATUS_OK;
440 }
441 if (strcmp(name, "2oo3") == 0) {
442 *out_topology = RTE_REDUNDANCY_TOPOLOGY_2OO3;
443 return RTE_STATUS_OK;
444 }
445 if (strcmp(name, "nmr") == 0) {
446 *out_topology = RTE_REDUNDANCY_TOPOLOGY_NMR;
447 return RTE_STATUS_OK;
448 }
450}
451
453{
454 const char *result;
455
456 switch (topology) {
458 result = "2oo2";
459 break;
461 result = "2oo2_redundant";
462 break;
464 result = "2oo3";
465 break;
467 result = "nmr";
468 break;
469 default:
470 result = "unknown";
471 break;
472 }
473 return result;
474}
475
477{
478 if ((name == NULL) || (out_mode == NULL)) {
480 }
481 if (strcmp(name, "hot") == 0) {
482 *out_mode = RTE_STANDBY_MODE_HOT;
483 return RTE_STATUS_OK;
484 }
485 if (strcmp(name, "warm") == 0) {
486 *out_mode = RTE_STANDBY_MODE_WARM;
487 return RTE_STATUS_OK;
488 }
489 if (strcmp(name, "cold") == 0) {
490 *out_mode = RTE_STANDBY_MODE_COLD;
491 return RTE_STATUS_OK;
492 }
494}
495
497{
498 const char *result;
499
500 switch (mode) {
502 result = "hot";
503 break;
505 result = "warm";
506 break;
508 result = "cold";
509 break;
510 default:
511 result = "unknown";
512 break;
513 }
514 return result;
515}
516
517/* Required "topology" and "replicas" keys, plus quorum_size (either the explicit "quorum" key,
518 * or the topology's own implicit default - 2oo2/2oo2_redundant and 2oo3 both default to 2; NMR
519 * has none, "quorum" is required in the file for it). Extracted from
520 * rte_redundancy_config_load()'s own former inline sequence - no behavior change. */
521static rte_status_t parse_topology_replicas_and_quorum(const char *buf, size_t len, rte_redundancy_config_t *result)
522{
523 size_t value_pos;
524 rte_status_t status;
525 char topology_name[24];
526 bool has_quorum;
527
528 status = find_key_value_pos(buf, len, "topology", &value_pos);
529 if (status != RTE_STATUS_OK) {
531 }
532 {
533 size_t end_pos;
534 status = parse_string_value(buf, len, value_pos, topology_name, sizeof(topology_name), &end_pos);
535 if (status != RTE_STATUS_OK) {
537 }
538 }
539 status = rte_redundancy_config_topology_from_string(topology_name, &result->topology);
540 if (status != RTE_STATUS_OK) {
542 }
543
544 status = find_key_value_pos(buf, len, "replicas", &value_pos);
545 if (status != RTE_STATUS_OK) {
547 }
548 status = parse_uint_value(buf, len, value_pos, &result->replica_count);
549 if (status != RTE_STATUS_OK) {
551 }
552 if ((result->replica_count < 1U) || (result->replica_count > RTE_REDUNDANCY_CONFIG_MAX_REPLICAS)) {
554 }
555
556 has_quorum = false;
557 status = find_key_value_pos(buf, len, "quorum", &value_pos);
558 if (status == RTE_STATUS_OK) {
559 status = parse_uint_value(buf, len, value_pos, &result->quorum_size);
560 if (status != RTE_STATUS_OK) {
562 }
563 has_quorum = true;
564 }
565
566 if (!has_quorum) {
567 switch (result->topology) {
570 if (result->replica_count < 2U) {
572 }
573 result->quorum_size = 2U;
574 break;
576 if (result->replica_count != 3U) {
578 }
579 result->quorum_size = 2U;
580 break;
582 default:
583 /* No implicit majority default for NMR - "quorum" is
584 * required in the file for this topology (see header doc). */
586 }
587 }
588
589 if ((result->quorum_size < 1U) || (result->quorum_size > result->replica_count)) {
591 }
592 return RTE_STATUS_OK;
593}
594
595/* Optional "standby_mode" key, defaulting to COLD. Extracted the same way as
596 * parse_topology_replicas_and_quorum() above - no behavior change. */
597static rte_status_t parse_optional_standby_mode(const char *buf, size_t len, rte_redundancy_config_t *result)
598{
599 size_t value_pos;
600 rte_status_t status;
601
603 status = find_key_value_pos(buf, len, "standby_mode", &value_pos);
604 if (status == RTE_STATUS_OK) {
605 char standby_mode_name[8];
606 size_t end_pos;
607 status = parse_string_value(buf, len, value_pos, standby_mode_name, sizeof(standby_mode_name), &end_pos);
608 if (status != RTE_STATUS_OK) {
610 }
611 status = rte_redundancy_config_standby_mode_from_string(standby_mode_name, &result->standby_mode);
612 if (status != RTE_STATUS_OK) {
614 }
615 }
616 return RTE_STATUS_OK;
617}
618
619/* Optional "roles" key (a string array), defaulting to role_count=0 when absent. Extracted the
620 * same way as parse_topology_replicas_and_quorum() above - no behavior change. */
621static rte_status_t parse_optional_roles(const char *buf, size_t len, rte_redundancy_config_t *result)
622{
623 size_t value_pos;
624 rte_status_t status;
625
626 status = find_key_value_pos(buf, len, "roles", &value_pos);
627 if (status == RTE_STATUS_OK) {
628 status = parse_string_array(buf, len, value_pos, result->roles,
630 if (status != RTE_STATUS_OK) {
632 }
633 } else {
634 result->role_count = 0U;
635 }
636 return RTE_STATUS_OK;
637}
638
639/* Optional "channels" key (an array of channel objects), defaulting to channel_count=0 when
640 * absent. Extracted the same way as parse_topology_replicas_and_quorum() above - no behavior
641 * change. */
642static rte_status_t parse_optional_channels(const char *buf, size_t len, rte_redundancy_config_t *result)
643{
644 size_t value_pos;
645 rte_status_t status;
646
647 status = find_key_value_pos(buf, len, "channels", &value_pos);
648 if (status == RTE_STATUS_OK) {
649 status = parse_channels_array(buf, len, value_pos, result->channels,
651 if (status != RTE_STATUS_OK) {
653 }
654 } else {
655 result->channel_count = 0U;
656 }
657 return RTE_STATUS_OK;
658}
659
661{
662 FILE *fp;
664 size_t len;
665 rte_status_t status;
667
668 if ((path == NULL) || (out_config == NULL)) {
670 }
671
672 fp = fopen(path, "rb");
673 if (fp == NULL) {
675 }
676 len = fread(buf, 1U, sizeof(buf), fp);
677 if ((ferror(fp) != 0) || (feof(fp) == 0)) {
678 /* Either a read error, or the file was too large to fit (no EOF
679 * reached within RTE_REDUNDANCY_CONFIG_MAX_FILE_SIZE bytes). */
680 (void)fclose(fp);
682 }
683 (void)fclose(fp);
684
685 (void)memset(&result, 0, sizeof(result));
686
687 status = parse_topology_replicas_and_quorum(buf, len, &result);
688 if (status != RTE_STATUS_OK) {
689 return status;
690 }
691
692 status = parse_optional_standby_mode(buf, len, &result);
693 if (status != RTE_STATUS_OK) {
694 return status;
695 }
696
697 status = parse_optional_roles(buf, len, &result);
698 if (status != RTE_STATUS_OK) {
699 return status;
700 }
701
702 status = parse_optional_channels(buf, len, &result);
703 if (status != RTE_STATUS_OK) {
704 return status;
705 }
706
707 if ((s_capability_fn != NULL) && (!s_capability_fn(result.topology, result.replica_count, s_capability_context))) {
709 }
710
711 *out_config = result;
713 return RTE_STATUS_OK;
714}
715
717 rte_voter_config_t *voter_cfg)
718{
719 if ((config == NULL) || (voter_cfg == NULL)) {
721 }
722 voter_cfg->quorum_size = config->quorum_size;
723 return RTE_STATUS_OK;
724}
725
727 const char *name,
728 rte_channel_def_t *out_channel)
729{
730 uint32_t i;
731
732 if ((config == NULL) || (name == NULL) || (out_channel == NULL)) {
734 }
735 for (i = 0U; i < config->channel_count; i++) {
736 if (strncmp(config->channels[i].name, name, sizeof(config->channels[i].name)) == 0) {
737 *out_channel = config->channels[i];
738 return RTE_STATUS_OK;
739 }
740 }
742}
743
745 uint32_t id,
746 rte_channel_def_t *out_channel)
747{
748 uint32_t i;
749
750 if ((config == NULL) || (out_channel == NULL)) {
752 }
753 for (i = 0U; i < config->channel_count; i++) {
754 if (config->channels[i].id == id) {
755 *out_channel = config->channels[i];
756 return RTE_STATUS_OK;
757 }
758 }
760}
761
762static rte_redundancy_config_t s_active_config;
763static bool s_has_active_config = false;
764
766{
767 return s_has_active_config ? &s_active_config : NULL;
768}
769
771{
772 if (config != NULL) {
773 s_active_config = *config;
774 s_has_active_config = true;
775 } else {
776 s_has_active_config = false;
777 }
778}
rte_status_t
Common result/status codes.
Definition rte_status.h:27
@ RTE_STATUS_INTERNAL_ERROR
Definition rte_status.h:38
@ RTE_STATUS_INVALID_STATE
Definition rte_status.h:40
@ RTE_STATUS_OK
Definition rte_status.h:28
@ RTE_STATUS_INVALID_PARAM
Definition rte_status.h:29
@ RTE_STATUS_NOT_SUPPORTED
Definition rte_status.h:34
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 ...
rte_channel_transport_t
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_STANDBY_MODE_WARM
@ RTE_STANDBY_MODE_COLD
@ RTE_STANDBY_MODE_HOT
@ 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_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().
Definition rte_voter.h:87
uint32_t quorum_size
Definition rte_voter.h:92