$darkmode
Elektra 0.11.0
KDB Operations

There are four main operations in libelektra-kdb: open, get, set and close. For each of these there is a kdb* function the user calls to trigger the operation and plugins export a function for each of the operations they support (at least get).

Additionally, plugins may implement commit and error. These are part of the set operation and there is no corresponding kdbCommit or kdbError function available in libelektra-kdb.

The operations get and set also have different phases:

These phases are implemented by a backend plugin. Read the Documentation on Backend Plugins for more information on what backend plugins do.

Note The steps of the operations described below, are referenced in the source code with // Step X comments.

open Operation

The open operation implemented in kdbOpen is the first thing that happens to all KDB instances.

The basic flow of this operation is:

  1. Create empty KDB instance
  2. Configure KDB instance for bootstrap
  3. Run bootstrap get operation: This loads the contents of system:/elektra/mountpoints so that the mountpoints can be configured.
  4. Process contract and set up plugins for hooks (see Hooks)
  5. Parse mountpoints: This transforms the contents of system:/elektra/mountpoints into the internal state stored in a KDB instance.
  6. Reconfigure KDB with real mountpoints: This switches the KDB instance from bootstrap mode to use the real mountpoint state created above.
  7. Add hard coded mountpoints to KDB instance: There are a few hard coded mountpoints (root mountpoints, system:/elektra/modules, system:/elektra/version, etc.) that are always present. They are added in this step.

Namespaces in mountpoint configs:

Note The special treatments of the various namespaces are explained below in the sections for the get and set operation.

Reserved sections:

get Operation

The purpose of the get operation is to read data stored in backends into a KDB instance.

Note: Some details of a get operation are defined in the contract with backend plugins.

Properties of kdbGet():

To the caller it looks as if kdbGet() had removed all keys below parentKey, as well as some others, from ks and then loaded the data from the backends. Which backends are actually read is an implementation detail. Which keys are removed from ks depends on the backends that are read.

kdbGet() will always try to be efficient in achieving its goal of reading the keys below parentKey. It is only guaranteed that below parentKey the KeySet ks correctly represents the state of the KDB. For the rest of ks there are no such guarantees.

Note: In the list below "phase" always refers to a phase of the get operation as described in the backend plugin contract.

The flow of this operation is:

  1. Determine the backends needed to read all keys below parentKey
  2. Run the open operation for all required backends that haven't been opened
  3. Run the init phase on all the backends that haven't been initialized
  4. Run the resolver phase on all backends
  5. From now on ignore all backends, which indicated that there is no update.
  6. If all backends are now ignored, return.
  7. If a global cache plugin is enabled: Ask the global cache plugin for the cache handles (normally modification times) for all backends.
  8. If all backends have an existing cache entry: Run the cachecheck phase on all backends
  9. If all backends indicated the cache is still valid: Ask the global cache plugin for the cached data and return.
  10. Run the prestorage and storage phase on all backends.
  11. Run the poststorage phase of all spec:/ backends.
  12. Merge the data from all backends
  13. If enabled, run the gopts/get hook.
  14. Run the spec/copy hook.
  15. Split data back into individual backends.
  16. Run the poststorage phase for all non-spec:/ backends.
  17. Remove all keys which are below the parent key of any backend that has been read from ks.
  18. Merge the data from all backends into ks.
  19. If a global cache plugin is enabled, update cache.
  20. Run the notification/send hook. Then return.

Note: In case of error, we abort immediately, restore ks to its original state and return.

Influence of namespaces:

set Operation

The purpose of the set operation is to write data from a KDB instance into backends.

Note: Some details of a set operation are defined in the contract with backend plugins.

Properties of kdbSet():

The flow of this operation is:

  1. Determine the backends needed to write all keys below parentKey.
  2. Check that all backends are opened and initialized (i.e. kdbGet() was called).
  3. Run the spec/copy hook on ks (to add metakeys to newly created keys).
  4. Deep-Copy ks (below parentKey) into a new KeySet set_ks
  5. Split set_ks into individual backends
  6. Determine which backends contain changed data. Any backend that contains a key that needs sync (via KEY_FLAG_SYNC) could contain changed data. From now on ignore all backends that have not changed. From now on also ignore all backends that were initialized as read-only. Issue a warning, if a change was detected (via KEY_FLAG_SYNC) in a read-only backend.

    Note: Steps 4-6 might be combined into a single procedure that deep-copies only keys from changed backends into separate KeySets per backend

  7. Run the resolver and prestorage on all backends (abort immediately on error and go to e).
  8. Merge the results into a new version of set_ks.
  9. Run the spec/remove hook on set_ks (to remove copied metakeys).
  10. Split set_ks into individual backends again.
  11. Run the storage and poststorage phases on all backends (abort immediately on error and go to e).
  12. If everything was successful: Run the precommit and commit phases on all backends (abort immediately on error and go to e), then run the postcommit phase on all backends (record all errors as warnings and ignore them) and return.
  1. If there was an error: Run the prerollback, rollback and postrollback phases on all backends and return.

Influence of namespaces:

close Operation

The close operation is very simple. It simply frees up all resources used by a KDB instance.