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_db.h File Reference

A/B's own simplified Train/Route database - fixed-size arrays describing the domain objects logic/ (planned) will reason about when granting/extending a Movement Authority. More...

#include <stdbool.h>
#include <stdint.h>
#include "rte/utils/status/rte_status.h"
#include "../../common/common_config.h"
Include dependency graph for ab_gp_db.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ab_gp_db_route_t
 One track section A/B's simplified layout knows about. More...
struct  ab_gp_db_train_t
 One train A/B's simplified database knows about. More...
struct  ab_gp_db_t
struct  ab_gp_route_context_t

Macros

#define AB_GP_DB_ROUTE_IL_STATUS_T_DEFINED
 IL's own last-reported status for a route (planned - today's ILRBCSim only ever sends ROUTE_ADD, so LOCKED is the only value reachable in practice yet; the rest exist so logic/ has somewhere to put a richer IL status later without another struct-shape change). An enum, not a struct - GA sees this type in full (a closed set of named integers carries no layout to hide), unlike ab_gp_db_t below.
#define AB_GP_DB_T_DEFINED
 A/B's whole simplified Train/Route database - fixed-size tables, one instance per channel (owned by whatever context logic/ ends up threading this through, same "caller-owned storage, no hidden state" convention as ab_gp_channel_context_t - see ab_gp_channel_types.h). Tagged struct ab_gp_db_s (not an anonymous struct) specifically so it can be forward-declared elsewhere - see this file's own header doc.

Enumerations

enum  ab_gp_db_route_il_status_t { AB_GP_DB_ROUTE_IL_STATUS_UNKNOWN = 0 , AB_GP_DB_ROUTE_IL_STATUS_FREE , AB_GP_DB_ROUTE_IL_STATUS_RESERVED , AB_GP_DB_ROUTE_IL_STATUS_LOCKED }

Functions

Mechanical route<->train connect/disconnect (the "repository"

layer) Genuinely mechanical bookkeeping only - no business judgment (does this route exist, is it valid, should it be granted at all - that stays il/'s own concern, AB/GA/il/ab_ga_il.h's own ab_ga_il_route_verify()/_route_add()). This is the ONE place that mutates ab_gp_db_route_t.used_in_ma/train_id and ab_gp_db_train_t.route_ids[]/route_count together - moved here (this session's own GA/GP split) from what used to be il/'s own ab_ga_il_route_assign_train()/_unassign_train() bodies, which reached directly into these fields with no setter existing at all; il/'s own functions of the same name are now thin wrappers over these. Callers: AB/GP/ma_logic/ab_gp_logic.c's own ab_gp_logic_connect_route_for_train() (GP, after its own registered GA validator has approved), and il/'s own wrappers (unchanged real ROUTE_ADD wire path, AB/GA/il/ab_ga_il.c's ab_ga_il_apply_envelope()).

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 used_in_ma.
bool ab_gp_db_route_disconnect_train (ab_gp_db_t *db, uint16_t route_id)
 Reverses ab_gp_db_route_connect_train(): clears the route's own used_in_ma/train_id and removes it from its owning train's route_ids[] (compacting the remaining entries down).
Route table getters/setters (the encapsulation boundary for GA)

Every field of ab_gp_db_route_t that AB/GA/il/ab_ga_il.c used to touch directly (before this session's own GA/GP opacity pass) now has its own accessor here - il/'s own route_add()/_remove()/_set_status() are thin wrappers over these, exactly like the connect/disconnect pair above. All take/return plain values, never a pointer into the table itself (no ab_gp_db_route_t * ever crosses into GA), so GA can only ever read a SNAPSHOT of a field or request a new value be written - never alias or hold a live reference into db->routes[].

bool ab_gp_db_route_exists (const ab_gp_db_t *db, uint16_t route_id)
bool ab_gp_db_route_add (ab_gp_db_t *db, uint16_t route_id, uint16_t start_signal, uint16_t end_signal)
 Adds a new route to db->routes[]. New entry starts fully idle: occupied=false, il_status=AB_GP_DB_ROUTE_IL_STATUS_UNKNOWN, used_in_ma=false, train_id=0. Purely mechanical - does NOT verify route_id/start_signal/end_signal against any site layout (that stays il/'s own business, ab_ga_il_route_verify(), called before this).
bool ab_gp_db_route_remove (ab_gp_db_t *db, uint16_t route_id)
 Removes a tracked route from db->routes[], freeing its slot.
bool ab_gp_db_route_set_status (ab_gp_db_t *db, uint16_t route_id, ab_gp_db_route_il_status_t status)
bool ab_gp_db_route_set_type (ab_gp_db_t *db, uint16_t route_id, uint32_t route_type)
bool ab_gp_db_route_set_fsm_state (ab_gp_db_t *db, uint16_t route_id, uint32_t fsm_state)
 Get/set the per-route FSM state (ab_ga_route_state_t, raw uint32_t - GA owns the value space, GP just stores it).
uint32_t ab_gp_db_route_get_fsm_state (const ab_gp_db_t *db, uint16_t route_id)
uint8_t ab_gp_db_route_get_count (const ab_gp_db_t *db)
 Returns total number of active routes currently in the GP database.
bool ab_gp_db_route_get_by_index (const ab_gp_db_t *db, uint8_t index, uint16_t *out_route_id, uint16_t *out_start_signal, uint16_t *out_end_signal, uint8_t *out_train_id, bool *out_used_in_ma)
 Retrieves route snapshot by table index for GA/GP route list synchronization.
bool ab_gp_db_train_is_connected (const ab_gp_db_t *db, uint8_t train_id)
 Checks if a train has an active connection session in the DB.
bool ab_gp_db_train_get_routes (const ab_gp_db_t *db, uint8_t train_id, uint16_t out_routes[RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN], uint8_t *out_count)
 Retrieves routes currently allocated to a train.
Database Wire Serialization & Deserialization (State Transfer)
rte_status_t ab_gp_db_encode (const ab_gp_db_t *db, uint8_t *out_bytes, uint32_t out_capacity, uint32_t *out_written)
 Encodes the full route and train database into a deterministic wire format.
rte_status_t ab_gp_db_decode (ab_gp_db_t *db, const uint8_t *in_bytes, uint32_t in_size)
 Decodes the full route and train database from a deterministic wire format.

GA notification - db/'s own single GP->GA route hook

db/ is the module that actually mutates db->routes[], so db/ is the module that notifies about it (same "whichever GP module performs a mutation is the one that fires the matching notify" rule AB/GP/train/ab_gp_train.h's own notify hook follows too). ONE subscription (ab_gp_db_register_route_context_notify() below) covers every route change (added/status-changed/connected/disconnected - see ab_gp_route_update_type_t's own doc) - collapsed from four separate registrations on direct instruction (the GP<->GA interface had grown too complicated: one callback typedef, one subscriber list, and one registration call site per event, most with zero real GA subscribers). Fan-out, fail-open (zero subscribers is fine - unlike AB/GP/ma_logic/ab_gp_logic.h's own route-connect VALIDATOR, this is observational, not a gate - that one stays its own, separate registration, since it needs a synchronous bool return to approve/veto a connection, which a fire-and-forget notify can't do). Setup-phase only (rte_lifecycle_check_setup_allowed()), same contract as every other registration function in this codebase - GA's own single dispatch module (safeAPIRBC2oo2GA/src/AB/main/ab_ga_dispatch.c) is the ONLY registrant, called once from its own _init(), itself called once from ab_gp_channel_ga_setup() (AB/GP/com/ab_gp_channel.c) - GP has no knowledge that il/ctc/logic exist as separate GA modules.

#define AB_GP_ROUTE_UPDATE_TYPE_T_DEFINED
 What kind of change a single ab_gp_route_context_notify_fn call is reporting - see that typedef's own doc. Collapses what used to be four separate notify types (added/status/connected/ disconnected) into one subscription, on direct request - see this file's own module doc for the full rationale.
#define AB_GP_ROUTE_CONTEXT_T_DEFINED
 A flat, fully-visible (NOT opaque, unlike ab_gp_db_t itself) snapshot of one route's current state - what ab_gp_route_context_notify_fn hands its subscriber. A copy, not a live pointer into db->routes[] - GA reads real struct fields directly (no getter calls needed), while still never touching GP's actual internal storage.
#define AB_GP_DB_ROUTE_NOTIFY_FN_DEFINED
#define AB_GP_DB_MAX_ROUTE_CONTEXT_SUBSCRIBERS   4U
enum  ab_gp_route_update_type_t { AB_ROUTE_ADDED , AB_ROUTE_STATUS_CHANGED , AB_ROUTE_CONNECTED , AB_ROUTE_DISCONNECTED }
typedef void(*) ab_gp_route_context_notify_fn(const void *context, const ab_gp_route_context_t *ctx, ab_gp_route_update_type_t update_type)
rte_status_t ab_gp_db_register_route_context_notify (ab_gp_route_context_notify_fn fn, const void *context)
bool ab_gp_db_get_route_context (const ab_gp_db_t *db, uint16_t route_id, ab_gp_route_context_t *out_ctx)
 One-shot pull equivalent of the push notification above - the SAME snapshot-building logic (real impl: ab_gp_db.c's own build_route_context(), shared with notify_route_context()), for a caller that just needs route_id's current state right now rather than reacting to a change. Replaces the individual ab_gp_db_route_get_status()/_get_used_in_ma()/_get_type() getters GA used to call one field at a time (later session, on direct request). Mutation still goes through the individual setters - this is READ-ONLY, deliberately.

Detailed Description

A/B's own simplified Train/Route database - fixed-size arrays describing the domain objects logic/ (planned) will reason about when granting/extending a Movement Authority.

Deliberately separate from com/'s own ab_gp_train_session_t (ab_gp_channel_types.h): that struct is transport/cross-compare/ negotiation session bookkeeping (in_use, granted_length, ma_seq, the wire-encoded fields ab_gp_channel_negotiate.c carries across a STANDBY->ONLINE promotion) - this module is the track-layout domain model above it (which train has which route, what a route's own signals/occupancy/IL status are). com/ does not know this struct exists; a later pass wires the two together (logic/ reads both).

Fixed-size arrays only (RTE_EXAMPLE_MAX_TRAINS/_MAX_ROUTES/ _MAX_ROUTES_PER_TRAIN, common_config.h) - never a dynamic list, same convention as every other table in this project (CLAUDE.md: no malloc/free/realloc).

GA/GP encapsulation (this session's own addition): ab_gp_db_t is declared here with a real tag (struct ab_gp_db_s) specifically so AB/GP/ga_interface/ga_interface.h can forward-declare it as an INCOMPLETE type - GA (AB/GA/il/, AB/GA/ctc/) never includes this header and never sees ab_gp_db_route_t's/ab_gp_db_train_t's own field layout; it only ever holds/passes an ab_gp_db_t * and reads/writes through the getter/setter functions below, re-declared verbatim in ga_interface.h. This is enforced by the C type system, not just convention: GA's own translation units cannot compile a db->field expression at all, since they never see this struct's body.

Definition in file ab_gp_db.h.

Macro Definition Documentation

◆ AB_GP_DB_ROUTE_IL_STATUS_T_DEFINED

#define AB_GP_DB_ROUTE_IL_STATUS_T_DEFINED

IL's own last-reported status for a route (planned - today's ILRBCSim only ever sends ROUTE_ADD, so LOCKED is the only value reachable in practice yet; the rest exist so logic/ has somewhere to put a richer IL status later without another struct-shape change). An enum, not a struct - GA sees this type in full (a closed set of named integers carries no layout to hide), unlike ab_gp_db_t below.

Definition at line 52 of file ab_gp_db.h.

◆ AB_GP_DB_T_DEFINED

#define AB_GP_DB_T_DEFINED

A/B's whole simplified Train/Route database - fixed-size tables, one instance per channel (owned by whatever context logic/ ends up threading this through, same "caller-owned storage, no hidden state" convention as ab_gp_channel_context_t - see ab_gp_channel_types.h). Tagged struct ab_gp_db_s (not an anonymous struct) specifically so it can be forward-declared elsewhere - see this file's own header doc.

Definition at line 131 of file ab_gp_db.h.

◆ AB_GP_ROUTE_UPDATE_TYPE_T_DEFINED

#define AB_GP_ROUTE_UPDATE_TYPE_T_DEFINED

What kind of change a single ab_gp_route_context_notify_fn call is reporting - see that typedef's own doc. Collapses what used to be four separate notify types (added/status/connected/ disconnected) into one subscription, on direct request - see this file's own module doc for the full rationale.

Definition at line 308 of file ab_gp_db.h.

◆ AB_GP_ROUTE_CONTEXT_T_DEFINED

#define AB_GP_ROUTE_CONTEXT_T_DEFINED

A flat, fully-visible (NOT opaque, unlike ab_gp_db_t itself) snapshot of one route's current state - what ab_gp_route_context_notify_fn hands its subscriber. A copy, not a live pointer into db->routes[] - GA reads real struct fields directly (no getter calls needed), while still never touching GP's actual internal storage.

Definition at line 329 of file ab_gp_db.h.

◆ AB_GP_DB_ROUTE_NOTIFY_FN_DEFINED

#define AB_GP_DB_ROUTE_NOTIFY_FN_DEFINED

Definition at line 345 of file ab_gp_db.h.

◆ AB_GP_DB_MAX_ROUTE_CONTEXT_SUBSCRIBERS

#define AB_GP_DB_MAX_ROUTE_CONTEXT_SUBSCRIBERS   4U

One subscriber (GA's own dispatch module) with headroom to spare.

Definition at line 358 of file ab_gp_db.h.

Typedef Documentation

◆ ab_gp_route_context_notify_fn

typedef void(*) ab_gp_route_context_notify_fn(const void *context, const ab_gp_route_context_t *ctx, ab_gp_route_update_type_t update_type)

Fired once per real route change (see ab_gp_route_update_type_t) with a snapshot of that route's CURRENT state - one subscription replaces what used to be four (added/status/connected/disconnected). GA's own dispatch module (safeAPIRBC2oo2GA/src/AB/main/ab_ga_dispatch.c) is the ONLY registrant; it fans out internally to whichever of GA's own modules (il/ctc) care about which update_type - GP has no knowledge that those are separate GA modules.

Definition at line 353 of file ab_gp_db.h.

Enumeration Type Documentation

◆ ab_gp_db_route_il_status_t

Enumerator
AB_GP_DB_ROUTE_IL_STATUS_UNKNOWN 

No status received from IL yet.

AB_GP_DB_ROUTE_IL_STATUS_FREE 

IL reports this route is free to allocate.

AB_GP_DB_ROUTE_IL_STATUS_RESERVED 

IL has reserved this route but not yet locked it.

AB_GP_DB_ROUTE_IL_STATUS_LOCKED 

IL has locked this route for a Movement Authority (ROUTE_ADD).

Definition at line 53 of file ab_gp_db.h.

◆ ab_gp_route_update_type_t

Enumerator
AB_ROUTE_ADDED 

ab_gp_db_route_add() just added this route.

AB_ROUTE_STATUS_CHANGED 

ab_gp_db_route_set_status() just changed il_status.

AB_ROUTE_CONNECTED 

ab_gp_db_route_connect_train() just connected this route to ctx->train_id.

AB_ROUTE_DISCONNECTED 

ab_gp_db_route_disconnect_train() just disconnected this route - ctx->train_id is the train it WAS connected to (captured before the disconnect cleared it), same identity a subscriber would have seen in the matching earlier AB_ROUTE_CONNECTED.

Definition at line 309 of file ab_gp_db.h.

Function Documentation

◆ ab_gp_db_route_connect_train()

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 used_in_ma.

Parameters
dbAB's own Train/Route database. Must not be NULL.
route_idMust already be tracked (db->routes[], e.g. via ab_gp_db_route_add() - this function does not add it).
train_id1..RTE_EXAMPLE_MAX_TRAINS.
Returns
false if route_id is not tracked, train_id is out of range, the route is already used_in_ma (disconnect first, never silently reassigned), it is already in that same train's route_ids[], or that train's route_ids[] (RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN) is full. true once connected.

Definition at line 150 of file ab_gp_db.c.

◆ ab_gp_db_route_disconnect_train()

bool ab_gp_db_route_disconnect_train ( ab_gp_db_t * db,
uint16_t route_id )

Reverses ab_gp_db_route_connect_train(): clears the route's own used_in_ma/train_id and removes it from its owning train's route_ids[] (compacting the remaining entries down).

Returns
false if route_id is not tracked, or it is not currently used_in_ma (nothing to disconnect).

Definition at line 197 of file ab_gp_db.c.

◆ ab_gp_db_route_exists()

bool ab_gp_db_route_exists ( const ab_gp_db_t * db,
uint16_t route_id )
Returns
true if route_id is already tracked in db->routes[].

Definition at line 253 of file ab_gp_db.c.

◆ ab_gp_db_route_add()

bool ab_gp_db_route_add ( ab_gp_db_t * db,
uint16_t route_id,
uint16_t start_signal,
uint16_t end_signal )

Adds a new route to db->routes[]. New entry starts fully idle: occupied=false, il_status=AB_GP_DB_ROUTE_IL_STATUS_UNKNOWN, used_in_ma=false, train_id=0. Purely mechanical - does NOT verify route_id/start_signal/end_signal against any site layout (that stays il/'s own business, ab_ga_il_route_verify(), called before this).

Returns
false if route_id is already tracked (call ab_gp_db_route_remove() first to replace it), or db->routes[] (RTE_EXAMPLE_MAX_ROUTES) is full.

Definition at line 258 of file ab_gp_db.c.

◆ ab_gp_db_route_remove()

bool ab_gp_db_route_remove ( ab_gp_db_t * db,
uint16_t route_id )

Removes a tracked route from db->routes[], freeing its slot.

Returns
false if route_id is not tracked, or it is still used_in_ma (ab_gp_db_route_disconnect_train() first - a route actively backing a train's Movement Authority is never silently dropped).

Definition at line 291 of file ab_gp_db.c.

◆ ab_gp_db_route_set_status()

bool ab_gp_db_route_set_status ( ab_gp_db_t * db,
uint16_t route_id,
ab_gp_db_route_il_status_t status )
Returns
false if route_id is not tracked; otherwise true with the field updated. Does not touch occupied (a separate, non-IL-sourced concept - see ab_gp_db_route_t's own doc).

Definition at line 310 of file ab_gp_db.c.

◆ ab_gp_db_route_set_type()

bool ab_gp_db_route_set_type ( ab_gp_db_t * db,
uint16_t route_id,
uint32_t route_type )
Returns
false if route_id is not tracked; otherwise true with the field updated (rbc_route_type_t value, raw uint32_t) - IL's latest report always wins, no notify (route_type is not observed by anything yet - unlike il_status, which already has GA subscribers).

Definition at line 335 of file ab_gp_db.c.

◆ ab_gp_db_route_set_fsm_state()

bool ab_gp_db_route_set_fsm_state ( ab_gp_db_t * db,
uint16_t route_id,
uint32_t fsm_state )

Get/set the per-route FSM state (ab_ga_route_state_t, raw uint32_t - GA owns the value space, GP just stores it).

Returns
set: false if route_id is not tracked, else true. get: the stored value, or AB_GA_ROUTE_STATE_NO_ROUTE (0) for an unknown route.

Definition at line 347 of file ab_gp_db.c.

◆ ab_gp_db_route_get_fsm_state()

uint32_t ab_gp_db_route_get_fsm_state ( const ab_gp_db_t * db,
uint16_t route_id )

Definition at line 359 of file ab_gp_db.c.

◆ ab_gp_db_route_get_count()

uint8_t ab_gp_db_route_get_count ( const ab_gp_db_t * db)

Returns total number of active routes currently in the GP database.

Definition at line 375 of file ab_gp_db.c.

◆ ab_gp_db_route_get_by_index()

bool ab_gp_db_route_get_by_index ( const ab_gp_db_t * db,
uint8_t index,
uint16_t * out_route_id,
uint16_t * out_start_signal,
uint16_t * out_end_signal,
uint8_t * out_train_id,
bool * out_used_in_ma )

Retrieves route snapshot by table index for GA/GP route list synchronization.

Definition at line 395 of file ab_gp_db.c.

◆ ab_gp_db_train_is_connected()

bool ab_gp_db_train_is_connected ( const ab_gp_db_t * db,
uint8_t train_id )

Checks if a train has an active connection session in the DB.

Definition at line 435 of file ab_gp_db.c.

◆ ab_gp_db_train_get_routes()

bool ab_gp_db_train_get_routes ( const ab_gp_db_t * db,
uint8_t train_id,
uint16_t out_routes[RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN],
uint8_t * out_count )

Retrieves routes currently allocated to a train.

Definition at line 444 of file ab_gp_db.c.

◆ ab_gp_db_register_route_context_notify()

rte_status_t ab_gp_db_register_route_context_notify ( ab_gp_route_context_notify_fn fn,
const void * context )
Returns
RTE_STATUS_OK on success; RTE_STATUS_INVALID_PARAM if fn is NULL; RTE_STATUS_INVALID_STATE if the setup phase is already locked; RTE_STATUS_RESOURCE_EXHAUSTED if AB_GP_DB_MAX_ROUTE_CONTEXT_SUBSCRIBERS are already registered.

Definition at line 25 of file ab_gp_db.c.

◆ ab_gp_db_get_route_context()

bool ab_gp_db_get_route_context ( const ab_gp_db_t * db,
uint16_t route_id,
ab_gp_route_context_t * out_ctx )

One-shot pull equivalent of the push notification above - the SAME snapshot-building logic (real impl: ab_gp_db.c's own build_route_context(), shared with notify_route_context()), for a caller that just needs route_id's current state right now rather than reacting to a change. Replaces the individual ab_gp_db_route_get_status()/_get_used_in_ma()/_get_type() getters GA used to call one field at a time (later session, on direct request). Mutation still goes through the individual setters - this is READ-ONLY, deliberately.

Returns
false if route_id is not tracked; otherwise true with *out_ctx fully populated.

Definition at line 323 of file ab_gp_db.c.

◆ ab_gp_db_encode()

rte_status_t ab_gp_db_encode ( const ab_gp_db_t * db,
uint8_t * out_bytes,
uint32_t out_capacity,
uint32_t * out_written )

Encodes the full route and train database into a deterministic wire format.

Parameters
dbDatabase to encode.
out_bytesDestination buffer.
out_capacitySize of destination buffer (must be at least RTE_EXAMPLE_DB_WIRE_SIZE).
out_writtenBytes written.
Returns
RTE_STATUS_OK on success; RTE_STATUS_INVALID_PARAM or RTE_STATUS_BUFFER_TOO_SMALL on error.

Definition at line 474 of file ab_gp_db.c.

◆ ab_gp_db_decode()

rte_status_t ab_gp_db_decode ( ab_gp_db_t * db,
const uint8_t * in_bytes,
uint32_t in_size )

Decodes the full route and train database from a deterministic wire format.

Parameters
dbDestination database to populate.
in_bytesBuffer containing wire format.
in_sizeSize of buffer (must be at least RTE_EXAMPLE_DB_WIRE_SIZE).
Returns
RTE_STATUS_OK on success; RTE_STATUS_INVALID_PARAM or RTE_STATUS_BUFFER_TOO_SMALL on error.

Definition at line 557 of file ab_gp_db.c.