RTE RBC 2oo2 Reference Application 0.1.0 build 0006685
SIL 4 2oo2 Dual-Site Fault-Tolerant ERTMS Radio Block Centre Reference Architecture
Loading...
Searching...
No Matches
ab_gp_logic.c
Go to the documentation of this file.
1
6#include "ab_gp_logic.h"
7
8#include "rte/utils/lifecycle/rte_lifecycle.h"
9#include "rte/utils/notify/rte_notify.h"
10#include "rte/oal/log/rte_log.h"
11
13#include "ab_siteGP.h"
15
17
19/* GA callback registries - module-private storage (same "static
20 * singleton" convention as ab_gp_channel.c's own g_ab_ctx). Relies on C's
21 * static zero-initialization (count == 0, every slot NULL) rather than
22 * a separate explicit list-init step - see rte_notify.h's own doc
23 * (safeAPIFreamwork, ADR-030) for the storage shape these are declared
24 * from and why init/register/dispatch are hand-written here, not
25 * macro-generated. */
28
29RTE_DECLARE_CALLBACK_LIST(ab_gp_logic_shunting_validator_list_t, ab_gp_logic_shunting_validator_fn,
31
33static ab_gp_logic_route_validator_list_t g_validators;
34static ab_gp_logic_shunting_validator_list_t g_shunting_validators;
35
37
42static bool route_validators_all_agree(uint16_t route_id, uint8_t train_id);
43
44
47{
48 rte_status_t lifecycle_status;
49
50 if (fn == NULL)
51 {
52 return RTE_STATUS_INVALID_PARAM;
53 }
54 lifecycle_status = rte_lifecycle_check_setup_allowed();
55 if (lifecycle_status != RTE_STATUS_OK)
56 {
57 return lifecycle_status;
58 }
60 {
61 return RTE_STATUS_RESOURCE_EXHAUSTED;
62 }
63 g_validators.slots[g_validators.count].fn = fn;
64 g_validators.slots[g_validators.count].context = context;
65 g_validators.count++;
66 return RTE_STATUS_OK;
67}
68
70{
71 rte_status_t lifecycle_status;
72
73 if (fn == NULL)
74 {
75 return RTE_STATUS_INVALID_PARAM;
76 }
77 lifecycle_status = rte_lifecycle_check_setup_allowed();
78 if (lifecycle_status != RTE_STATUS_OK)
79 {
80 return lifecycle_status;
81 }
83 {
84 return RTE_STATUS_RESOURCE_EXHAUSTED;
85 }
87 g_shunting_validators.slots[g_shunting_validators.count].context = context;
89 return RTE_STATUS_OK;
90}
91
92bool ab_gp_logic_shunting_allowed(uint8_t train_id)
93{
94 uint32_t i;
95 bool result = true;
96
97 if (g_shunting_validators.count == 0U)
98 {
99 /* Default-deny, reported here so it does not look like a silent refusal (same as the route gate). */
100 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_WARNING, "LOGIC", 0U, "GP", "GA", "SHUNTING_VALIDATION",
101 "train %u: no GA shunting validator registered - refusing SH",
102 (unsigned int)train_id);
103 return false;
104 }
105
106 for (i = 0U; i < g_shunting_validators.count; i++)
107 {
108 if ((g_shunting_validators.slots[i].fn != NULL)
109 && (!g_shunting_validators.slots[i].fn(g_shunting_validators.slots[i].context, train_id)))
110 {
111 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_DEBUG, "LOGIC", 0U, "GP", "GA", "SHUNTING_VALIDATION",
112 "validator #%u refused SH for train %u",
113 (unsigned int)i, (unsigned int)train_id);
114 result = false;
115 }
116 }
117 return result;
118}
119
121{
122 uint32_t nid_lrbg = 0U;
123 uint32_t i;
124 bool connected_any = false;
125 uint32_t connected_count = 0U;
126
127 if (!ab_gp_train_get_last_position(db, train_id, &nid_lrbg))
128 {
129 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_DEBUG, "LOGIC", 0U, "GP", "GA", "ROUTE_CONNECT",
130 "train %u not currently connected - skipping route connect",
131 (unsigned int)train_id);
132 return false; /* not a currently-connected train */
133 }
134 if (nid_lrbg == 0U)
135 {
136 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_DEBUG, "LOGIC", 0U, "GP", "GA", "ROUTE_CONNECT",
137 "train %u has not reported a position yet (nid_lrbg=0) - skipping",
138 (unsigned int)train_id);
139 return false;
140 }
141
142 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_DEBUG, "LOGIC", 0U, "GP", "GA", "ROUTE_CONNECT",
143 "train %u at nid_lrbg=%u: checking every tracked route for a connect",
144 (unsigned int)train_id, (unsigned int)nid_lrbg);
145
146 for (i = 0U; i < (uint32_t)RTE_EXAMPLE_MAX_ROUTES; i++)
147 {
148 uint16_t route_id = db->routes[i].id;
149 if (route_id == 0U)
150 {
151 continue; /* unused slot - not logged, this loop runs every cycle */
152 }
153
154 if (db->routes[i].used_in_ma)
155 {
156 if (db->routes[i].train_id == train_id)
157 {
158 connected_any = true;
159 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_DEBUG, "LOGIC", 0U, "GP", "GA", "ROUTE_CONNECT",
160 "route %u already connected to train %u - no-op",
161 (unsigned int)route_id, (unsigned int)train_id);
162 }
163 else
164 {
165 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_DEBUG, "LOGIC", 0U, "GP", "GA", "ROUTE_CONNECT",
166 "route %u already connected to train %u - skipping for train %u",
167 (unsigned int)route_id, (unsigned int)db->routes[i].train_id,
168 (unsigned int)train_id);
169 }
170 continue; /* route already assigned */
171 }
172
173 if (!route_validators_all_agree(route_id, train_id))
174 {
175 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_DEBUG, "LOGIC", 0U, "GP", "GA", "ROUTE_CONNECT",
176 "route %u -> train %u: no GA validator approved - not connecting",
177 (unsigned int)route_id, (unsigned int)train_id);
178 continue; /* no registered GA validator approved - see that function's own doc */
179 }
180
181 /* AB/GP/db/ab_gp_db.h's own ab_gp_db_route_connect_train() fires its OWN
182 * registered-subscriber notification on success - see this file's
183 * own module doc for why this function itself does not do that. */
184 if (ab_gp_db_route_connect_train(db, route_id, train_id))
185 {
186 connected_any = true;
187 connected_count++;
188 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_INFO, "LOGIC", 0U, "GP", "GA", "ROUTE_CONNECT",
189 "connected route %u to train %u (at nid_lrbg=%u)",
190 (unsigned int)route_id, (unsigned int)train_id,
191 (unsigned int)nid_lrbg);
192 }
193 else
194 {
195 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_WARNING, "LOGIC", 0U, "GP", "GA", "ROUTE_CONNECT",
196 "route %u -> train %u: ab_gp_db_route_connect_train() refused",
197 (unsigned int)route_id, (unsigned int)train_id);
198 }
199 }
200
201 if (connected_count > 0U)
202 {
203 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_INFO, "LOGIC", 0U, "GP", "GA", "ROUTE_CONNECT",
204 "train %u: %u route(s) newly connected this pass (holds %s)",
205 (unsigned int)train_id, (unsigned int)connected_count,
206 connected_any ? "at least one route" : "no route");
207 }
208 else
209 {
210 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_DEBUG, "LOGIC", 0U, "GP", "GA", "ROUTE_CONNECT",
211 "train %u: %u route(s) newly connected this pass (holds %s)",
212 (unsigned int)train_id, (unsigned int)connected_count,
213 connected_any ? "at least one route" : "no route");
214 }
215
216 return connected_any;
217}
218
220{
221 uint8_t train_id;
222
223 /* Per-train "attempting" logging lives in
224 * ab_gp_logic_connect_route_for_train() itself - not duplicated here. */
225 for (train_id = 1U; train_id <= (uint8_t)RTE_EXAMPLE_MAX_TRAINS; train_id++)
226 {
227 if (ab_gp_train_is_connected(db, train_id))
228 {
229 (void)ab_gp_logic_connect_route_for_train(db, train_id);
230 }
231 }
232}
233
234
235/****Local functions ****/
236
237static bool route_validators_all_agree(uint16_t route_id, uint8_t train_id)
238{
239 uint32_t i;
240 bool result = true;
241
242 if (g_validators.count == 0U)
243 {
244 /* Doc contract (ab_gp_ga_register_init()): default-DENY when no
245 * validator is registered - reported once here rather than
246 * looking like a silent rejection at the call site. */
247 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_WARNING, "LOGIC", 0U, "GP", "GA", "ROUTE_VALIDATION",
248 "route %u -> train %u: no GA route validator registered - denying",
249 (unsigned int)route_id, (unsigned int)train_id);
250 return false;
251 }
252
253 for (i = 0U; i < g_validators.count; i++)
254 {
255 if ((g_validators.slots[i].fn != NULL)
256 && (!g_validators.slots[i].fn(g_validators.slots[i].context, route_id, train_id)))
257 {
258 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_DEBUG, "LOGIC", 0U, "GP", "GA", "ROUTE_VALIDATION",
259 "validator #%u rejected route %u -> train %u",
260 (unsigned int)i, (unsigned int)route_id, (unsigned int)train_id);
261 result = false;
262 }
263 }
264 if (result)
265 {
266 RTE_LOG_WRITE_EVENT_F(RTE_LOG_LEVEL_DEBUG, "LOGIC", 0U, "GP", "GA", "ROUTE_VALIDATION",
267 "route %u -> train %u: all %u registered validator(s) approved",
268 (unsigned int)route_id, (unsigned int)train_id,
269 (unsigned int)g_validators.count);
270 }
271 return result;
272}
bool ab_gp_db_route_connect_train(ab_gp_db_t *db, uint16_t route_id, uint8_t train_id)
Connects route_id to train_id: appends the route to that train's own route_ids[] and marks the route ...
Definition ab_gp_db.c:150
RTE_DECLARE_CALLBACK_LIST(ab_gp_db_route_context_list_t, ab_gp_route_context_notify_fn, AB_GP_DB_MAX_ROUTE_CONTEXT_SUBSCRIBERS)
bool ab_gp_logic_connect_route_for_train(ab_gp_db_t *db, uint8_t train_id)
Connects one train's own currently-reported route to it: looks up which route the balise at db->train...
static ab_gp_logic_route_validator_list_t g_validators
Definition ab_gp_logic.c:33
bool ab_gp_logic_shunting_allowed(uint8_t train_id)
Asks every registered shunting validator about train_id.
Definition ab_gp_logic.c:92
static ab_gp_logic_shunting_validator_list_t g_shunting_validators
Definition ab_gp_logic.c:34
static bool route_validators_all_agree(uint16_t route_id, uint8_t train_id)
void ab_gp_logic_connect_routes_and_trains(ab_gp_db_t *db)
THE cyclic sweep: calls ab_gp_logic_connect_route_for_train() for every currently-connected train (ab...
A/B's own RBC decision logic - today's slice: connect a train's currently-reported route to that trai...
#define AB_GP_LOGIC_MAX_ROUTE_VALIDATORS
#define AB_GP_LOGIC_MAX_SHUNTING_VALIDATORS
bool ab_gp_train_is_connected(const ab_gp_db_t *db, uint8_t train_id)
A/B's own train lifecycle handling against db/'s runtime table.
#define RTE_EXAMPLE_MAX_ROUTES
#define RTE_EXAMPLE_MAX_TRAINS
#define RTE_LOG_WRITE_EVENT_F(level, site, cycle, source, dest, type, info_fmt,...)
bool ab_gp_train_get_last_position(const ab_gp_db_t *db, uint8_t train_id, uint32_t *out_nid_lrbg)
bool(*) ab_gp_logic_shunting_validator_fn(void *context, uint8_t train_id)
rte_status_t ab_gp_ga_register_shunting_validator(ab_gp_logic_shunting_validator_fn fn, void *context)
Definition ab_gp_logic.c:69
bool(*) ab_gp_logic_route_validator_fn(void *context, uint16_t route_id, uint8_t train_id)
rte_status_t ab_gp_ga_register_init(ab_gp_logic_route_validator_fn fn, void *context)
Definition ab_gp_logic.c:46
uint8_t train_id
Definition ab_gp_db.h:83
uint16_t id
Definition ab_gp_db.h:67
ab_gp_db_route_t routes[RTE_EXAMPLE_MAX_ROUTES]
Definition ab_gp_db.h:135