Elektra
0.9.7
|
General methods to access the Key database. More...
Macros | |
#define | KDB_VERSION "x.y.z" |
The version information in x.y.z format as string. More... | |
#define | KDB_VERSION_MAJOR x |
The version information of the major version as number. More... | |
#define | KDB_VERSION_MINOR y |
The version information of the minor version as number. More... | |
#define | KDB_VERSION_PATCH z |
The version information of the patch version as number. More... | |
Functions | |
KeySet * | ksRenameKeys (KeySet *config, const char *name) |
Takes the first key and cuts off this common part for all other keys, instead name will be prepended. More... | |
int | elektraOpenBootstrap (KDB *handle, KeySet *keys, Key *errorKey) |
Bootstrap, first phase with fallback. | |
KDB * | kdbOpen (const KeySet *contract, Key *errorKey) |
Opens the session with the Key database. More... | |
int | kdbClose (KDB *handle, Key *errorKey) |
Closes the session with the Key database. More... | |
int | kdbGet (KDB *handle, KeySet *ks, Key *parentKey) |
Retrieve Keys from a Key database in an atomic and universal way. More... | |
int | kdbSet (KDB *handle, KeySet *ks, Key *parentKey) |
Set Keys to a Key database in an atomic and universal way. More... | |
General methods to access the Key database.
To use them:
The kdb*() methods are used to access the storage, to get and set KeySets.
Parameters common for all these functions are:
KDB uses different backend implementations that know the details about how to access the storage. One backend consists of multiple plugins. See writing a new plugin for information about how to write a plugin. Backends are state-less regarding the configuration (because of that you must pass back the whole configuration for every backend), but have a state for:
As we see in the figure, kdbOpen() can be called arbitrarily often in any number of threads.
For every handle you got from kdbOpen(), for every parentKey with a different name, only the shown state transitions are valid. From a freshly opened KDB, only kdbGet() and kdbClose() are allowed, because otherwise conflicts (error C02000) would not be detected.
Once kdbGet() was called (for a specific handle+parentKey), any number of kdbGet() and kdbSet() can be used with this handle respective parentKey, unless kdbSet() had a conflict (error C02000) with another application. Every affair with KDB needs to be finished with kdbClose().
The name of the parentKey in kdbOpen() and kdbClose() does not matter.
In the usual case we just have one parentKey and one handle. In these cases we just have to remember to use kdbGet() before kdbSet():
To output warnings, you can use following code:
To output the error, you can use following code:
#define KDB_VERSION "x.y.z" |
The version information in x.y.z format as string.
To get the version at run-time, you can get the key system:/elektra/version/constants/KDB_VERSION
#define KDB_VERSION_MAJOR x |
The version information of the major version as number.
To get the version at run-time, you can get the key system:/elektra/version/constants/KDB_VERSION_MAJOR
#define KDB_VERSION_MINOR y |
The version information of the minor version as number.
To get the version at run-time, you can get the key system:/elektra/version/constants/KDB_VERSION_MINOR
#define KDB_VERSION_PATCH z |
The version information of the patch version as number.
To get the version at run-time, you can get the key system:/elektra/version/constants/KDB_VERSION_PATCH
int kdbClose | ( | KDB * | handle, |
Key * | errorKey | ||
) |
Closes the session with the Key database.
This is the counterpart of kdbOpen().
You must call this method when you are finished working with the Key database. You can manipulate Key and KeySet objects also after kdbClose(), but you must not use any kdb*() call afterwards.
The handle
parameter will be finalized and all resources associated to it will be freed. After a kdbClose(), the handle
cannot be used anymore.
handle | contains internal information of opened key database |
errorKey | the key which holds error/warning information |
0 | on success |
-1 | on NULL pointer |
int kdbGet | ( | KDB * | handle, |
KeySet * | ks, | ||
Key * | parentKey | ||
) |
Retrieve Keys from a Key database in an atomic and universal way.
handle
must be passed as returned from kdbOpen(). returned
KeySet must be a valid KeySet, e.g. constructed with ksNew(). parentKey
Key must be a valid Key, e.g. constructed with keyNew().If you pass NULL on any parameter, kdbGet() will fail immediately without doing anything.
The returned KeySet ks
may already contain some keys, e.g. from previous kdbGet() calls. The newly retrieved Keys will be appended using ksAppendKey().
If not done earlier, kdbGet() will fully retrieve all keys under the parentKey
folder recursively (See Optimization below when it will not be done). Cascading Keys (starting with /) will retrieve the same path in all namespaces. /
will retrieve all Keys in handle
.
proc:/
keys, must be passed to calls of kdbSet(), otherwise they will be lost. This stems from the fact that the user has the only copy of the whole configuration and backends only write configuration that was passed to them. For example, if you kdbGet() "system:/mountpoint/interest" you will not only get all Keys below system:/mountpoint/interest, but also all Keys below system:/mountpoint (if system:/mountpoint is a mountpoint as the name suggests, but system:/mountpoint/interest is not a mountpoint). Make sure to not touch or remove Keys outside the Keys of interest, because others may need them!When a backend fails kdbGet() will return -1 with all error and warning information in the parentKey
. The parameter returned
will not be changed.
It is your responsibility to save the original KeySet if you need it afterwards.
If you want to be sure to get a fresh KeySet again, you need to open a second handle to the Key database using kdbOpen().
handle | contains internal information of opened key database |
parentKey | Keys below parentKey will be retrieved from handle It is also used to add warnings and set error information. |
ks | the (pre-initialized) KeySet returned with all keys found will not be changed on error or if no update is required |
1 | if the Keys were retrieved successfully |
0 | if there was no update - no changes are made to the KeySet then |
-1 | on failure - no changes are made to the KeySet then |
KDB* kdbOpen | ( | const KeySet * | contract, |
Key * | errorKey | ||
) |
Opens the session with the Key database.
You must always call this method before retrieving or committing any keys to the database. At the end of a program, after using the Key database (KDB), you must not forget to call kdbClose() to free resources.
The method will bootstrap itself in the following way. The first step is to open the default backend. With it system:/elektra/mountpoints
will be loaded and all needed libraries and mountpoints will be determined. Then the global plugins and global keyset data from the contract
is processed. Finally, the libraries for backends will be loaded and with it the KDB
data structure will be initialized.
The pointer to the KDB
structure returned will be initialized like described above, and it must be passed along on any kdb*() method your application calls.
Get a KDB
handle for every thread using elektra. Don't share the handle across threads, and also not the pointer accessing it:
You don't need kdbOpen() if you only want to manipulate plain in-memory Key or KeySet objects.
contract | the contract that should be ensured before opening the KDB all data is copied and the KeySet can safely be used for e.g. kdbGet() later |
errorKey | the key which holds errors and warnings which were issued |
NULL | on failure |
int kdbSet | ( | KDB * | handle, |
KeySet * | ks, | ||
Key * | parentKey | ||
) |
Set Keys to a Key database in an atomic and universal way.
returned
KeySet must be a valid KeySet, e.g. constructed with ksNew(). parentKey
Key must be a valid Key, e.g. constructed with keyNew(). It must not have read-only name, value or metadata.If you pass NULL on any parameter, kdbSet() will fail immediately without doing anything.
With parentKey
you can specify which part of the given keyset is of interest for you. Then you promise to only modify or remove keys below this key. All others would be passed back as they were retrieved by kdbGet(). Cascading keys (starting with /) will set the path in all namespaces. /
will commit all keys. Meta-names in parentKey
will be rejected (error C01320). Empty/Invalid Keys will also be rejected (error C01320).
parentKey == NULL
or parentKey
has read-only metadata, kdbSet() will immediately return the error code -1. In all other error cases the following happens:In case of errors you should present the error message to the user and let the user decide what to do. Possible solutions are:
showElektraErrorDialog() and doElektraMerge() need to be implemented by the user of Elektra. For doElektraMerge a 3-way merge algorithm exists in libelektra-tools.
handle | contains internal information of opened key database |
ks | a KeySet which should contain changed keys, otherwise nothing is done |
parentKey | Keys below parentKey will be set to handle . It is also used to add warnings and set error information. |
1 | on success |
0 | if nothing had to be done, no changes in KDB |
-1 | on failure, no changes in KDB, an error will be set on parentKey if possible (see "Errors" above) |
handle
KeySet* ksRenameKeys | ( | KeySet * | config, |
const char * | name | ||
) |
Takes the first key and cuts off this common part for all other keys, instead name will be prepended.
The first key is removed in the resulting keyset.