$darkmode
Elektra 0.11.0
|
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:
get
operation has: init
, resolver
, cachecheck
, prestorage
, storage
and poststorage
.set
operation has: resolver
, prestorage
, storage
and poststorage
followed by precommit
, commit
and postcommit
if the previous phases where successful or by prerollback
, rollback
and postrollback
if the previous phases failed.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.
The open
operation implemented in kdbOpen
is the first thing that happens to all KDB
instances.
The basic flow of this operation is:
KDB
instanceKDB
instance for bootstrapget
operation: This loads the contents of system:/elektra/mountpoints
so that the mountpoints can be configured.system:/elektra/mountpoints
into the internal state stored in a KDB
instance.KDB
with real mountpoints: This switches the KDB
instance from bootstrap mode to use the real mountpoint state created above.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:
dir:/
, user:/
and system:/
mountpoints can be created without restrictions, except for the reserved sections listed below.spec:/
mountpoints can be created with the same restrictions, but they are also treated specially during get
and set
.proc:/
mountpoints are always read-only and receive special treatment during get
default:/
mountpoints are read-only and receive special treatment during get
, specifically they only go through the poststorage
phaseNote The special treatments of the various namespaces are explained below in the sections for the
get
andset
operation.
Reserved sections:
/elektra
or below in any namespace is forbidden. This section of the KDB is reserved for Elektra's own config.system:/elektra/mountpoints
, user:/elektra/mountpoints
and dir:/elektra/mountpoints
are all required for the bootstrap process and use a hard coded backend. The backends are implemented by a standard file-based backend plugin that is defined at compile-time of libelektra-kdb
.system:/elektra/version
and system:/elektra/modules
will always use hard coded read-only backends containing information about this Elektra installation. The backends are implemented by special purpose backend plugins.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()
:
kdbGet (kdb, ks, parentKey)
, the KeySet ks
will contain all keys (including their values) that are stored in any backend with a mountpoint that is below parentKey
.kdbGet (kdb, ks, parentKey)
, below parentKey
the KeySet ks
will mostly contain keys that are stored in a backend. The exception here are proc:/
and spec:/
keys. For other namespaces, all keys below parentKey
will be removed from ks
. For proc:/
and spec:/
only keys that overlap with a backend that was loaded will be removed from ks
.ks
may contain other keys not below parentKey
:parentKey
, but are stored in a backend that contains other keys which are below parentKey
. These keys are returned, because backends are treated as one atomic unit. Either all keys within a backend are read, or none of them are.ks
when kdbGet()
was called and do not conflict with the goal of representing the current state of the KDB below parentKey
.kdbGet (kdb, ks, parentKey)
, the Key parentKey
will only have the meta:/error/*
or meta:/warnings/#/*
metakeys, if the errors/warnings originate from this kdbGet()
call. In other words, kdbGet ()
first clears any existing errors/warnings and only then starts doing the actual work.parentKey
with a namespace other than: default:/
, proc:/
, spec:
, dir:/
, user:/
, system:/
or cascadingTo 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:
parentKey
open
operation for all required backends that haven't been openedinit
phase on all the backends that haven't been initializedresolver
phase on all backendscachecheck
phase on all backendsprestorage
and storage
phase on all backends.poststorage
phase of all spec:/
backends.gopts/get
hook.spec/copy
hook.poststorage
phase for all non-spec:/
backends.ks
.ks
.notification/send
hook. Then return.Note: In case of error, we abort immediately, restore
ks
to its original state and return.
Influence of namespaces:
spec:/
backends go through init
, resolver
, cache
, presetstorage
and storage
phases as normal, but their poststorage
phase is called earlier. This is required, because any validation and post-processing of spec:/
keys needs to happen, before they are used as the specification for other keys in the actual poststorage
phase.dir:/
, user:/
and system:/
go through all phases as described above.proc:/
mountpoints go through all the phases as described above, but they are not stored in the cache.default:/
backends only go through the poststorage
phase. This is because default:/
keys are generated from the specification (stored as spec:/
keys). Therefore, no default:/
keys can exist before the specification is processed by the spec/copy
hook.ks
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()
:
kdbSet (kdb, ks, parentKey)
the contents (key names, values and metadata) of ks
will mostly not be modified. The only modifications that are made to ks
are those that originate from the spec/copy
hook.ks
that are below parentKey
will be persisted in the KDB, when a kdbSet (kdb, ks, parentKey)
call returns successfully. Additionally, any key in ks
that shares a backend with another key which is below parentKey
will also be persisted.kdbSet
may result in an error, if kdbGet
wasn't called on this KDB
instance with the same parentKey
at least once.kdbSet (kdb, ks, parentKey)
, the Key parentKey
will only have the meta:/error/*
or meta:/warnings/#/*
metakeys, if the errors/warnings originate from this kdbSet()
call. In other words, kdbSet ()
first clears any existing errors/warnings and only then starts doing the actual work.parentKey
with a namespace other than: default:/
, proc:/
, spec:
, dir:/
, user:/
, system:/
or cascadingThe flow of this operation is:
parentKey
.kdbGet()
was called).spec/copy
hook on ks
(to add metakeys to newly created keys).ks
(below parentKey
) into a new KeySet set_ks
set_ks
into individual backendsKEY_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. 7. Run theNote: Steps 4-6 might be combined into a single procedure that deep-copies only keys from changed backends into separate KeySets per backend
resolver
and prestorage
on all backends (abort immediately on error and go to e).set_ks
.spec/remove
hook on set_ks
(to remove copied metakeys).set_ks
into individual backends again.storage
and poststorage
phases on all backends (abort immediately on error and go to e).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.prerollback
, rollback
and postrollback
phases on all backends and return. Influence of namespaces:
default:/
and proc:/
keys are completely ignored by kdbSet()
spec:/
, dir:/
, user:/
and system:/
go through all phases as described above.ks
The close
operation is very simple. It simply frees up all resources used by a KDB
instance.