Repository navigation
Replies: 2 comments 5 replies
|
Seconding this feature request |
0 replies
|
One thing worth considering is just integrating an off the shelf database such as SQLite into an F Prime component. Maybe not flyable for some missions but that could be a good choice for many |
5 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Overview
This is a design proposal for a component that is a more feature-rich version of
Svc.PolyDb. It is a central database that components can write values to and read values from. Each entry in the database includes the value, a timestamp, and a status. The component tracks watermarks (minimums and maximums) for integer and floating-point typed entries. The component maintains a history of values for each entry, each with an individually-configurable depth. More details on these features are below.Value Storage
This component can store entries whose values are typed as integers, floating-points, booleans, strings, structs, or byte-arrays (perhaps this can be generalized to anything that is F-Prime-serializable). For storing entries, it provides 2 port types: a standard poly-typed port and another that is specialized for storing telemetry (i.e. the value is serialized into a
Fw::TlmBuffer).Each entry is stored with a timestamp. These timestamps are either provided by the client or automatically generated by the component using the standard F-Prime time port (the client signals this by using a designated "invalid" time value).
Each entry is stored with a status. This indicates the validity of the entry and represents valid, uninitialized (never written), invalid (as determined by the client, maybe can be combined with the previous status), and stale (not written to since the last read) values.
Watermarks
This component tracks watermarks – minimum and maximum values – for entries typed as integers and floating-points. Watermarks are reported in response to a command, either in an event for individual entries or in a data product for all entries in the database. Watermarks are cleared in response to a command or input port, either for individual entries or for all entries in the database.
History Buffers
This component tracks the history of values for each entry in the database, with each entry having an individually-configurable depth that is defined at compile time. The depth must be a minimum of 2 in order to support a double-buffering scheme.
The history of individual entries is reported in a data product in response to a command. It is also sent to other components in response to a port call.
Autocoding and Data Storage
This component relies on autocoding to generate configuration data structures given the entry inputs, which are specified in FPP. This component also autocodes entries for all telemetry channels in the given deployment. Each entry is defined using a struct:
This relies on the type of the entry being specified as a string i.e.
"U8"since FPP has no concept of types as values, but the autocoder will validate types at build time and has access to all standard and FPP-defined types using Python interfaces included in thefprime-gdsAPIs. The get/set methods will verify that the size of the value being read/written is consistent with the expected type size.Entry IDs
Each entry is assigned an ID by the autocoder which also defines an enumeration in the dictionary that maps IDs to entry names, so that the representative names can be used in commands and events in lieu of the IDs. The autocoder also generates a table which maps telemetry IDs to entry IDs.
Data Structures
The autocoder determines how much memory will be needed by the component to hold the entry values, given the type size (which can be determined given the type name) and history depth of each entry. It also determines how much memory will be needed to hold the watermarks. The component uses these sizes to allocate its state and watermark buffers during initialization.
The autocoder creates an array that is indexed by entry ID which contains (1) the size of the type of its values (2) its history depth (3) the offset of its history buffer into the overall state buffer and (4) the offset of its watermarks into the overall watermarks buffer (or some defined invalid offset if the entry's type is not integer/floating-point). This provides constant-time lookups for entry offsets and the structure can be stored in
.rodata.Partitioning
The design of
Svc.PolyDballows any component to read and write any entry in the database, but we need to have targeted read and write permissions on individual entries or groups of entries, i.e. any component can read entry X but only component Y is allowed to write to it.The details of a partitioning scheme still need to be worked out – how granular is the control of permissions, by what mechanisms should it be specified, separate permissions for history buffers vs. watermark buffers, etc. – but heritage design relied on encoding the partitions (and therefore the permissions) into the entry IDs so that it could be quickly determined at call sites.
Concurrency
Entries in this component require concurrency protections in order to prevent race conditions. These protections must come with assurances that there are bounded latencies for reading and writing values. The previous design of
Svc.PolyDbused guarded ports for reading and writing but these lock the entire component when we only care about guarding individual entries. This could potentially provide bounded latencies but it would rely on the implementation that is selected forOs::Mutex.This component instead stores a coherency counter along with each entry in the database. When the entry is written to, the coherency counter is atomically incremented prior to the value being modified. When the entry is read from, the value of the coherency counter is compared before and after the read. If the values do not match, the read is retried. There is a (configurable) upper bound on the number of retries, after which a failure status is returned to the client. Note that this relies on the availability of atomic operations for the platform, however.
Notes on F-Prime Telemetry Components
The standard F-Prime telemetry components,
Svc.TlmChanandSvc.TlmPacketizercan also be viewed as central state databases. Components can write values to these databases using autocoded telemetry ports (or by writing directly to theTlmRecvport) and components can read values from these databases using theTlmGetport. However, both components suffer from the same lack of features asSvc.PolyDb. Neither track high/low watermarks for integer and floating-point telemetry values nor do they maintain a history of the telemetry values. The autocoded telemetry ports enable a psuedo-partitioning scheme (components can only write their own telemetry using these ports) but other components can always write directly to theTlmRecvport in order to subvert that.All reactions