pntOS Registry Overview
One goal of pntOS is to enable extensible and flexible communication between plugins. For example, a particular implementation of a state modeling plugin for a camera may want to have a configurable setting for focal length. In addition, a separate GUI plugin may want to display the value being used for the camera’s focal length, allow the user to modify the focal length, and communicate that change back to the state modeling plugin.
One simple approach to solving this problem would be to enumerate all the possible configuration values that any plugin might need, and encode them into a set of statically typed structures as part of the pntOS API. However, this quickly becomes infeasible as developers add new plugin implementations to the system, as each one will have specific nuanced needs for configuration and shared data between other plugins.
pntOS instead solves this problem by introducing a data registry which is
available to all plugins to store values, retrieve values, and listen for
changes to values by other plugins. Any pntOS plugin has access to the registry
by accessing the PntosRegistry pointer on the PntosMediator
struct that was passed to it during initialization.
By creating a shared plugin that can store, retrieve, and provide a way to listen
for changes, the pntOS PntosRegistry supports the following use cases.
Loading configuration data at startup
Communicating and recording runtime information during pntOS operation
An alternative method for inter-plugin-communication for scenarios the current API does not support
Keys, Values, and Groups
The PntosRegistry (or pointer to one) is a structure which a plugin
may use to store or retrieve values from the Registry. The Registry is shared
with all other plugins. When a plugin wants to store a value in the registry, it
must follow the API and first access the group, then set the value associated
with the key within that group. For example, a plugin called MyPlugin might
want to store the number of messages it has received so far (for example, 2)
into a group my_plugin/config and key num_messages_received.
The plugin would operate on the PntosRegistry pointer it has available
on the PntosMediator to start a batch for the group
my_plugin/config, and use the set_int
function on the PntosKeyValueStore it returned with
num_messages_received as the key, and 2 as the value.
Example:
1PntosRegistry* registry = <access registry pointer through mediator>;
2PntosKeyValueStore* kv_store = registry->batch_start(registry,"my_plugin/config");
3kv_store->set_int(kv_store,"num_messages_received",2);
4kv_store->batch_end(kv_store);
While conceptually a PntosKeyValueStore is similar to a traditional
key-value (k-v) store, one difference is the addition of a group string. Whereas
a traditional k-v store has a single key that identifies values, a
PntosKeyValueStore has a pair of strings (group, key). The reason for
this is because the pntOS registry could be used for passing large amounts
of data between various plugins at high data rates, and a monolithic
implementation of a single k-v store for all of those transactions would pose a
bottleneck risk to overall system performance. By splitting the lookup key from
the group, the registry can be implemented to more efficiently segment data
access by group, isolating different physical data stores by group. This
approach allows plugins to better optimize performance, as efficient registry
implementations can isolate registry access by group. Thus a plugin
that needs to communicate a large volume of data at high data rates might select
an isolated group for those keys.
Concurrency Summary
The behavior and structure for accessing groups, the associated concurrency
rules, and the resulting behavior should be shared by all
PntosRegistryPlugin plugins. A detailed description of the concurrency
rules and requirements for pntOS can be found in the Concurrency section of the
documentation.
Below is a summary of concurrency related behaviors that impact registry design and usage (assuming a threaded model).
As stated in the API, a
PntosKeyValueStoreis accessed via abatch_startcall on aPntosRegistrywith a “group” argumentThe
PntosKeyValueStorereturned frombatch_startis safe to access from a single threadPntosKeyValueStores returned from differentbatch_startcalls with different groups can be accessed by different threads concurrently
Example, a batch_start call with “group1” and a
batch_start call with “group2” could have one thread
accessing the “group1” PntosKeyValueStore and one thread accessing the
“group2” PntosKeyValueStore.
Counter example: the “group1” PntosKeyValueStore can not be accessed
by two threads concurrently.
Raw Operations
While one goal of the PntosKeyValueStore is to provide an efficient mechanism for storing
values of a specific type which can be retrieved exactly as stored, another goal is to permit direct
interaction with the PntosRegistry's data representation specified in
data_format. This is the purpose of
set_raw and get_raw. It may be noted
that these resemble get_str and
set_str. While set_str is guaranteed to store a string to
the registry that one can get back precisely with get_str, set_raw differs in that
it does implementation-specific (following data_format) maintenance
to the group, which could modify anything in the group in an arbitrary way. Similarly,
get_raw can return the value of a key or an entire group, formatted to conform to the data
format. In an effort to support any data format and to avoid requiring the user to escape the data,
set_raw accepts a length which permits the use of \0 throughout its parameter
bytes. get_raw also returns a length in the returned PntosByteArray.
Note
While the user of set_raw and get_raw is required to interact with the data
format, the implementation of the registry is free to use whatever backing storage mechanism
makes sense to the implementation.
Examples
For instance, if data_format is set to
PNTOS_KV_STORE_INI, this would declare the data format in
use is the INI file format.
1PntosKeyValueStore* store = registry->batch_start(registry, "my_group");
2char* my_double_array = "1.0;2.3;4.1";
3store->set_raw(store, "my_key", my_double_array, strlen(my_double_array));
Note
The implementation of the registry may allow for the retrieval of the key set with
set_raw by other functions, such as get_double_array.
An example of the capability of set_raw to set an entire group is shown here:
1PntosKeyValueStore* store = registry->batch_start(registry, "my_group");
2char* my_group = "A=1.0;2.3;4.1\nB=my string\n";
3store->set_raw(store, NULL, my_group, strlen(my_group));