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
main.c
Go to the documentation of this file.
1
142#include <stdbool.h>
143#include <stdio.h>
144#include <string.h>
145
146#include "rte/app/appmanager/rte_appmanager.h"
147#include "rte/oal/log/rte_log.h"
148#include "rte/oal/memory/rte_mem_util.h"
149#include "rte/posix_osadapter/rte_posix_osadapter.h"
150
152#include "../com/ab_gp_channel.h"
157
158#include "rte/core/rte_core_version.h"
159#include "rte_rbc2oo2_version.h"
160#include "rte_gp_run.h" /* declares rte_gp_run() itself - included so the
161 * definition below is checked against it */
162
163
165
167
169
171
173static int fatal_setup_step_failed(const char *step, rte_status_t status, ab_gp_channel_handle_t handle);
174static rte_appmanager_config_t ab_gp_channel_make_config(ab_gp_channel_handle_t handle);
175static const char *ab_gp_channel_get_name(void);
176static const char *ab_gp_channel_get_version(void);
177
178
179
180
189int rte_gp_run(int argc, char **argv)
190{
191 rte_status_t status;
193 bool is_role_a;
194 ab_gp_channel_handle_t handle = NULL;
195 rte_appmanager_config_t config;
196 const char *framework_actual_version;
197
198 /* Printed unconditionally, before arg validation, so even a
199 * usage-error run identifies itself - see rte_rbc2oo2_version.h.in's
200 * own doc for why the framework-version comparison matters (catches a
201 * stale statically-linked framework .a / wrong RTE_FRAMEWORK_DIST_DIR
202 * that wouldn't otherwise be visible until something broke at
203 * runtime). Plain fprintf, not rte_log_write_event() - this runs
204 * before app_main_common_init() below, which is what initializes
205 * logging. */
206 framework_actual_version = rte_core_get_version();
207 (void)fprintf(stdout, "%s version %s (framework %s, expected %s)\n", argv[0], RTE_RBC2OO2_VERSION,
208 framework_actual_version, RTE_FRAMEWORK_EXPECTED_VERSION);
209 if (strcmp(framework_actual_version, RTE_FRAMEWORK_EXPECTED_VERSION) != 0)
210 {
211 (void)fprintf(stderr,
212 "WARNING: linked safeAPIFreamwork version (%s) does not match what this binary was "
213 "built against (%s) - a stale library archive or wrong framework dist/ may be linked in\n",
214 framework_actual_version, RTE_FRAMEWORK_EXPECTED_VERSION);
215 }
216
217 if (argc < 3)
218 {
219 (void)fprintf(stderr, "usage: %s {A|B} {WEST|EAST}\n", argv[0]);
220 return 1;
221 }
222 if (!site_config_parse(argv[2], &site))
223 {
224 (void)fprintf(stderr, "unknown site '%s' - expected WEST or EAST\n", argv[2]);
225 return 1;
226 }
227 if (strcmp(argv[1], "A") == 0)
228 {
229 is_role_a = true;
230 }
231 else if (strcmp(argv[1], "B") == 0)
232 {
233 is_role_a = false;
234 }
235 else
236 {
237 (void)fprintf(stderr, "unknown role '%s' - expected A or B\n", argv[1]);
238 return 1;
239 }
240
241 status = app_main_common_init(argc, argv);
242 if (status != RTE_STATUS_OK)
243 {
244 return 1;
245 }
246
247 /* Overrides the plain POSIX log OSAdapter app_main_common_init() just registered with a
248 * wrapper that delegates to it (identical local stderr behaviour) and additionally
249 * forwards INFO+ events to Gateway once the channel below opens - see
250 * Platform_Protocol_JRU/CLAUDE.md's "Wiring" section. Best-effort, non-safety
251 * (ADR-001 section 4); a failure here only means this process loses log forwarding to
252 * Gateway, never local logging. */
253 (void)ab_gp_jru_forward_install(rte_posix_osadapter_log());
254
255 /* Composition root: this function owns every setup step described in
256 * this file's own "Startup sequence" header doc, in order, before
257 * handing off to rte_appmanager_run() for the cyclic executive
258 * proper - see that doc for each step's fatal/non-fatal posture. */
259 status = ab_gp_channel_open_link(is_role_a, site, &handle);
260 if (status != RTE_STATUS_OK)
261 {
262 /* Step 1 alone: self-cleaned already, must NOT call ab_gp_channel_close_link() - see its own doc. */
263 char msg[64];
264
265 (void)snprintf(msg, sizeof(msg), "channel open failed: %s", rte_status_to_string(status));
266 rte_log_write(RTE_LOG_LEVEL_ERROR, "MAIN", msg);
267 return 1;
268 }
269
270 /* From here on, every rte_log_write()/rte_log_write_event() call in this process also
271 * republishes (INFO+) to Gateway over the just-opened relay channel - see
272 * ab_gp_jru_forward_install() above. */
273 ab_gp_jru_forward_set_channel(handle, is_role_a ? (uint8_t)RBC_UTIL_SRC_A : (uint8_t)RBC_UTIL_SRC_B);
274
275 status = ab_gp_channel_train_codec_setup(handle);
276 if (status != RTE_STATUS_OK)
277 {
278 return fatal_setup_step_failed("train codec setup", status, handle);
279 }
280
281 status = ab_gp_channel_ga_setup(handle);
282 if (status != RTE_STATUS_OK)
283 {
284 return fatal_setup_step_failed("GA setup", status, handle);
285 }
286
287 ab_gp_channel_relay_queues_setup(handle); /* cannot fail */
288
289 status = ab_gp_channel_saf_train_setup(handle);
290 if (status != RTE_STATUS_OK)
291 {
292 return fatal_setup_step_failed("train-link SaF setup", status, handle);
293 }
294
295 status = ab_gp_channel_negotiate_setup(handle);
296 if (status != RTE_STATUS_OK)
297 {
298 return fatal_setup_step_failed("negotiate setup", status, handle);
299 }
300
301 (void)ab_gp_channel_checkpoint_setup(handle); /* non-fatal - see its own doc */
302 (void)ab_gp_channel_dual_setup(handle); /* non-fatal - see its own doc */
303 (void)ab_gp_channel_watchdog_setup(handle); /* non-fatal - see its own doc */
304
305 status = ab_gp_channel_crosscompare_setup(handle);
306 if (status != RTE_STATUS_OK)
307 {
308 return fatal_setup_step_failed("cross-comparator setup", status, handle);
309 }
310
311 status = ab_gp_channel_cycle_timer_setup(handle);
312 if (status != RTE_STATUS_OK)
313 {
314 return fatal_setup_step_failed("cycle timer setup", status, handle);
315 }
316
317 config = ab_gp_channel_make_config(handle);
318 return rte_appmanager_run(&config);
319}
320
321
322/****Local functions ****/
323
330static int fatal_setup_step_failed(const char *step, rte_status_t status, ab_gp_channel_handle_t handle)
331{
332 char msg[64];
333
334 (void)snprintf(msg, sizeof(msg), "%s failed: %s", step, rte_status_to_string(status));
335 rte_log_write(RTE_LOG_LEVEL_ERROR, "MAIN", msg);
337 return 1;
338}
339
351static rte_appmanager_config_t ab_gp_channel_make_config(ab_gp_channel_handle_t handle)
352{
353 /* ADR-019 (safeAPIFreamwork): the original single-function execute()
354 * is now split across pre_execute()/execute()/post_execute() - see
355 * this file's own header for the phase mapping. Designated
356 * initializers, not positional: a positional initializer here would
357 * silently shift fields if this struct's layout ever changes again. */
358 static const rte_appmanager_operations_t ops = {
359 .init = ab_gp_channel_init,
360 .pre_execute = ab_gp_channel_pre_execute,
361 .execute = ab_gp_channel_execute,
362 .post_execute = ab_gp_channel_post_execute,
363 .on_checkpoint_result = ab_gp_channel_on_checkpoint_result,
364 .shutdown = ab_gp_channel_shutdown,
365 .get_name = ab_gp_channel_get_name,
366 .get_version = ab_gp_channel_get_version
367 };
368 rte_appmanager_config_t config;
369
370 rte_mem_set(&config, 0, sizeof(config));
371 config.ops = &ops;
372 config.context = (void *)handle;
373 config.max_iterations = 0U; /* infinite: runs until signalled - see main()'s own SIGINT/SIGTERM handling */
374 config.error_threshold = 0U; /* no limit: a robust always-on cycle does not give up on a transient error
375 * - the two truly fatal conditions (CRC-64 corruption, logical M24/M15
376 * disagreement) bypass this entirely via RTE_SAFESTATE. */
377 config.checkpoint = ab_gp_channel_checkpoint_config(handle); /* ADR-019 addendum (ADR-025 rewiring).
378 * NULL until (and unless) ab_gp_channel_checkpoint_setup() ran and
379 * succeeded on this handle - rte_appmanager_run() does not treat that
380 * as a startup error; the pointed-to config's own voter field is also
381 * toggled back to NULL by ab_gp_channel_io.c whenever the peer link is
382 * known down, so a transient reconnect never risks the built-in
383 * checkpoint's own mandatory SAFE-state reaction. */
384
385 return config;
386}
387
391static const char *ab_gp_channel_get_name(void)
392{
393 return "safeAPIRBC2oo2-AB";
394}
395
398static const char *ab_gp_channel_get_version(void)
399{
400 return "3.0.0";
401}
402
rte_status_t ab_gp_channel_saf_train_setup(ab_gp_channel_handle_t handle)
Reads RTE_SAFECOMM_TRAIN_RBC_ID and sets up the train-link SaF termination: unset leaves it off (plai...
rte_status_t ab_gp_channel_open_link(bool is_role_a, rte_example_site_t site, ab_gp_channel_handle_t *out_handle)
Opens this process's own A<->B peer channel and C relay channels.
void ab_gp_channel_relay_queues_setup(ab_gp_channel_handle_t handle)
Initializes relay queues (no-op in single-threaded channel_service).
rte_status_t ab_gp_channel_cycle_timer_setup(ab_gp_channel_handle_t handle)
Creates and starts periodic cycle timer.
void ab_gp_channel_close_link(ab_gp_channel_handle_t handle)
Full teardown of a channel opened by ab_gp_channel_open_link().
rte_status_t ab_gp_channel_ga_setup(ab_gp_channel_handle_t handle)
GA registration for ma_logic_adaptation / il / ctc.
rte_status_t ab_gp_channel_negotiate_setup(ab_gp_channel_handle_t handle)
Opens inter-site negotiation link and runs startup tie-break.
const rte_appmanager_checkpoint_config_t * ab_gp_channel_checkpoint_config(ab_gp_channel_handle_t handle)
Accessor for checkpoint config.
rte_status_t ab_gp_channel_shutdown(void *context)
rte_appmanager_operations_t::shutdown hook.
rte_status_t ab_gp_channel_crosscompare_setup(ab_gp_channel_handle_t handle)
Creates cross-comparator on an already-open channel.
rte_status_t ab_gp_channel_dual_setup(ab_gp_channel_handle_t handle)
Wires dual-transfer liveness watchdog.
rte_status_t ab_gp_channel_init(void *context)
rte_appmanager_operations_t::init hook.
rte_status_t ab_gp_channel_checkpoint_setup(ab_gp_channel_handle_t handle)
Wires AppManager checkpoint mechanism onto peer channel.
rte_status_t ab_gp_channel_train_codec_setup(ab_gp_channel_handle_t handle)
GP-internal registration for train codec.
rte_status_t ab_gp_channel_watchdog_setup(ab_gp_channel_handle_t handle)
Arms general health watchdog.
struct ab_gp_channel_context_s * ab_gp_channel_handle_t
Opaque handle over this component's own static per-process context.
Shared declarations for the four rte_appmanager_operations_t cyclic-executive hooks this component's ...
rte_status_t ab_gp_channel_pre_execute(void *context)
rte_status_t ab_gp_channel_execute(void *context)
Definition execute.c:19
rte_status_t ab_gp_channel_post_execute(void *context)
rte_status_t ab_gp_channel_on_checkpoint_result(void *context, bool committed)
rte_appmanager_operations_t::on_checkpoint_result for the AB channel (ADR-034) - flushes or discards ...
rte_status_t ab_gp_jru_forward_install(const rte_osadapter_log_t *delegate)
Wraps delegate (the real local log OSAdapter, e.g. rte_posix_osadapter_log()) and registers the wrapp...
void ab_gp_jru_forward_set_channel(ab_gp_channel_handle_t handle, uint8_t source_id)
Attaches the open AB<->C relay channel: from this call on, write() also republishes INFO+ events to G...
A/B -> Gateway log-event forwarding (Platform_Protocol_JRU/CLAUDE.md's "Wiring" section)....
rte_status_t app_main_common_init(int argc, char **argv)
Runs this process's one-time runtime setup, common to every role: unbuffered stdout,...
Process-wide runtime setup shared by every one of this example's binaries (main.c for A/B,...
static const char * ab_gp_channel_get_name(void)
Definition main.c:391
static int fatal_setup_step_failed(const char *step, rte_status_t status, ab_gp_channel_handle_t handle)
Definition main.c:330
static rte_appmanager_config_t ab_gp_channel_make_config(ab_gp_channel_handle_t handle)
Builds the rte_appmanager_config_t for running an already-opened, already-wired channel (ab_gp_channe...
Definition main.c:351
static const char * ab_gp_channel_get_version(void)
Definition main.c:398
int rte_gp_run(int argc, char **argv)
Definition main.c:189
ADR-038: the wire frame for the A/B<->C util side channel (RTE_EXAMPLE_RELAY_KIND_UTIL) and the C-sid...
@ RBC_UTIL_SRC_B
@ RBC_UTIL_SRC_A
The one function librte_gp (this project's own shared library, see CMakeLists.txt's own doc on why rt...
bool site_config_parse(const char *arg, rte_example_site_t *out_site)
Parses a site name argument ("WEST"/"EAST", case-insensitive).
Definition site_config.c:33
West/East site identity and the per-site config derived from it (ports, container host lookup) - see ...
rte_example_site_t
Definition site_config.h:20