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_election.c
Go to the documentation of this file.
1
6
7#include <stddef.h>
8
10
12
14static bool find_own_index(const rte_election_candidate_t *candidates, uint32_t candidate_count, uint32_t own_id,
15 uint32_t *out_index);
16static uint32_t find_winner_index(const rte_election_candidate_t *candidates, uint32_t candidate_count);
17
19
22{
23 if ((election == NULL) || (config == NULL))
24 {
26 }
27
28 election->own_id = config->own_id;
29 election->own_last_state = RTE_DUAL_STATE_IDLE;
30 election->winner_id = 0U;
31 election->have_winner = false;
32
33 return RTE_STATUS_OK;
34}
35
37 uint32_t candidate_count)
38{
39 uint32_t own_index;
40 uint32_t winner_index;
41
42 if (election == NULL)
43 {
45 }
46 if (candidate_count > (uint32_t)RTE_REDUNDANCY_CONFIG_MAX_REPLICAS)
47 {
49 }
50 if ((candidates == NULL) && (candidate_count > 0U))
51 {
53 }
54
55 if (!find_own_index(candidates, candidate_count, election->own_id, &own_index))
56 {
57 /* No quorum this round to decide anything from - report, do not react
58 * (REQ-ELECTION-003), matching rte_dual_negotiator_execute()'s own lost-peer posture. */
59 election->own_last_state = RTE_DUAL_STATE_UNKNOWN;
60 return RTE_STATUS_OK;
61 }
62
63 winner_index = find_winner_index(candidates, candidate_count);
64 election->winner_id = candidates[winner_index].id;
65 election->have_winner = true;
66
67 if (winner_index == own_index)
68 {
69 election->own_last_state = RTE_DUAL_STATE_ONLINE;
70 }
71 else if (candidates[winner_index].degraded)
72 {
73 election->own_last_state = RTE_DUAL_STATE_COLDSTANDBY;
74 }
75 else
76 {
77 election->own_last_state = RTE_DUAL_STATE_HOTSTANDBY;
78 }
79
80 return RTE_STATUS_OK;
81}
82
84{
85 if (election == NULL)
86 {
88 }
89 return election->own_last_state;
90}
91
92rte_status_t rte_election_get_winner_id(const rte_election_t *election, uint32_t *out_id)
93{
94 if ((election == NULL) || (out_id == NULL))
95 {
97 }
98 if (!election->have_winner)
99 {
101 }
102 *out_id = election->winner_id;
103 return RTE_STATUS_OK;
104}
105
106/****Local functions ****/
107
108static bool find_own_index(const rte_election_candidate_t *candidates, uint32_t candidate_count, uint32_t own_id,
109 uint32_t *out_index)
110{
111 uint32_t i;
112
113 for (i = 0U; i < candidate_count; i++)
114 {
115 if (candidates[i].id == own_id)
116 {
117 *out_index = i;
118 return true;
119 }
120 }
121 return false;
122}
123
124/* REQ-ELECTION-002: oldest (smallest) startup_timestamp_ms wins; smallest id breaks an exact
125 * tie. candidate_count is always > 0 here - the only caller (rte_election_execute()) already
126 * confirmed the own-id candidate exists, so there is always at least one entry. */
127static uint32_t find_winner_index(const rte_election_candidate_t *candidates, uint32_t candidate_count)
128{
129 uint32_t winner = 0U;
130 uint32_t i;
131
132 for (i = 1U; i < candidate_count; i++)
133 {
134 if ((candidates[i].startup_timestamp_ms < candidates[winner].startup_timestamp_ms) ||
135 ((candidates[i].startup_timestamp_ms == candidates[winner].startup_timestamp_ms) &&
136 (candidates[i].id < candidates[winner].id)))
137 {
138 winner = i;
139 }
140 }
141 return winner;
142}
rte_dual_state_t
State of one instance in a dual (two-redundant-instance) relationship, as decided by rte_dual_negotia...
@ RTE_DUAL_STATE_HOTSTANDBY
@ RTE_DUAL_STATE_UNKNOWN
@ RTE_DUAL_STATE_ONLINE
@ RTE_DUAL_STATE_IDLE
@ RTE_DUAL_STATE_COLDSTANDBY
rte_dual_state_t rte_election_get_own_state(const rte_election_t *election)
Returns this instance's own current rte_dual_state_t, as of the last rte_election_execute() call.
rte_status_t rte_election_init(rte_election_t *election, const rte_election_config_t *config)
Initializes a rte_election_t. own_last_state starts at RTE_DUAL_STATE_IDLE (never yet evaluated).
rte_status_t rte_election_get_winner_id(const rte_election_t *election, uint32_t *out_id)
Returns the last-elected winner's id.
rte_status_t rte_election_execute(rte_election_t *election, const rte_election_candidate_t *candidates, uint32_t candidate_count)
Evaluates one round of election against the caller-supplied candidate snapshot (REQ-ELECTION-002 thro...
rte_status_t
Common result/status codes.
Definition rte_status.h:27
@ RTE_STATUS_OK
Definition rte_status.h:28
@ RTE_STATUS_INVALID_PARAM
Definition rte_status.h:29
@ RTE_STATUS_NOT_INITIALIZED
Definition rte_status.h:30
#define RTE_REDUNDANCY_CONFIG_MAX_REPLICAS
static bool find_own_index(const rte_election_candidate_t *candidates, uint32_t candidate_count, uint32_t own_id, uint32_t *out_index)
N-way election primitive (ADR-039): generalizes rte_dual_negotiator's pairwise older-startup-timestam...
One candidate's info for one rte_election_execute() call. The caller builds this array fresh each cal...
Configuration for rte_election_init().
One rte_election_t instance's state. Caller-owned storage; every field is private - reach it only thr...