Enumerations | Functions

KDB :: Low Level Methods

General methods to access the Key database. More...

Enumerations

enum  option_t {
  KDB_O_NONE = 0, KDB_O_DEL = 1, KDB_O_POP = 1<<1, KDB_O_NODIR = 1<<2,
  KDB_O_DIRONLY = 1<<3, KDB_O_NOREMOVE = 1<<6, KDB_O_REMOVEONLY = 1<<7, KDB_O_INACTIVE = 1<<8,
  KDB_O_SYNC = 1<<9, KDB_O_SORT = 1<<10, KDB_O_NORECURSIVE = 1<<11, KDB_O_NOCASE = 1<<12,
  KDB_O_WITHOWNER = 1<<13, KDB_O_NOALL = 1<<14
}

Functions

KDBkdbOpen (Key *errorKey)
int kdbClose (KDB *handle, Key *errorKey)
int kdbGet (KDB *handle, KeySet *ks, Key *parentKey)
int kdbSet (KDB *handle, KeySet *ks, Key *parentKey)

Detailed Description

General methods to access the Key database.

To use them:

 #include <kdb.h>

The kdb*() class of methods are used to access the storage, to get and set Keys or KeySets .

The most important functions are:

The two essential functions for dynamic information about backends are:

They use some backend implementation to know the details about how to access the storage. Currently we have this backends:

Backends are physically a library named /lib/libelektra-{NAME}.so.

See writing a new plugin for information about how to write a plugin.

Language binding writers should follow the same rules:


Enumeration Type Documentation

enum option_t

Options to change the default behavior of kdbGet(), kdbSet() and ksLookup() functions.

These options can be ORed. That is the |-Operator in C.

See also:
kdbGet(), kdbSet()
Enumerator:
KDB_O_NONE 

No Option set. Will be recursive with no inactive keys.

See also:
kdbGet(), kdbSet(), ksLookup()
KDB_O_DEL 

Delete parentKey key in kdbGet(), kdbSet() or ksLookup().

See also:
kdbGet(), kdbSet()
KDB_O_POP 

Pop Parent out of keyset key in kdbGet().

See also:
ksPop().
KDB_O_NODIR 

Exclude keys containing other keys in result.

Only return leaves.

See also:
keyIsDir()
KDB_O_DIRONLY 

Retrieve only directory keys (keys containing other keys). This will give you an skeleton without leaves. This must not be used together with KDB_O_NODIR.

See also:
keyIsDir()
KDB_O_NOREMOVE 

Don't remove any keys. This must not be used together with KDB_O_REMOVEONLY.

KDB_O_REMOVEONLY 

Only remove keys. This must not be used together with KDB_O_NOREMOVE.

KDB_O_INACTIVE 

Do not ignore inactive keys (that name begins with .).

See also:
keyIsInactive()
KDB_O_SYNC 

Set keys independent of sync status.

See also:
keyNeedSync()
KDB_O_SORT 

This option has no effect. KeySets are always sorted.

Deprecated:
dont use
KDB_O_NORECURSIVE 

Do not call kdbGet() for every key containing other keys (keyIsDir()).

KDB_O_NOCASE 

Ignore case.

KDB_O_WITHOWNER 

Search with owner.

KDB_O_NOALL 

Only search from start -> cursor to cursor -> end.


Function Documentation

int kdbClose ( KDB handle,
Key errorKey 
)

Closes the session with the Key database.

You should call this method when you finished your affairs with the key database. You can manipulate Key and KeySet objects also after kdbClose(). You must not use any kdb* call afterwards. You can implement kdbClose() in the atexit() handler.

This is the counterpart of kdbOpen().

The handle parameter will be finalized and all resources associated to it will be freed. After a kdbClose(), this handle can't be used anymore, unless it gets initialized again with another call to kdbOpen().

See also:
kdbOpen()
Parameters:
handle contains internal information of opened key database
errorKey the key which holds error information
Returns:
0 on success
-1 on NULL pointer
int kdbGet ( KDB handle,
KeySet ks,
Key parentKey 
)

Retrieve keys in an atomic and universal way, all other kdbGet Functions rely on that one.

The returned KeySet must be initialized or may already contain some keys. The new retrieved keys will be appended using ksAppendKey().

It will fully retrieve all keys under the parentKey folder, with all subfolders and their children.

Example

This example demonstrates the typical usecase within an application without updating.

Example:
KeySet *myConfig = ksNew(0);
Key *key = keyNew("system/sw/MyApp",KEY_END);
KDB *handle = kdbOpen(key);

kdbGet(handle, myConfig, key);

keySetName(key, "user/sw/MyApp");
kdbGet(handle, myConfig, key);

// check for errors by in key
keyDel(key);

key = ksLookupByName(myConfig,"/sw/MyApp/key", 0);
// check if key is not 0 and work with it...

ksDel (myConfig); // delete the in-memory configuration


// maybe you want kdbSet() myConfig here

kdbClose(handle, 0); // no more affairs with the key database.

Details

When no backend could be found (e.g. no backend mounted) the default backend will be used.

If you pass NULL on any parameter kdbGet() will fail immediately without doing anything.

When a backend fails kdbGet() will return -1 without any changes to one of the parameter.

Updating

In the first run of kdbGet all keys are retrieved. On subsequent calls only the keys are retrieved where something was changed inside the key database. The other keys stay unchanged in the keyset, even when they were manipulated.

It is your responsibility to save the original keyset if you need it afterwards. If you must get it again, e.g. in another thread a second connection to the key database must be opened using kdbOpen().

Parameters:
handle contains internal information of opened key database
parentKey parent key - invalid name gets all keys
ks the (pre-initialized) KeySet returned with all keys found will not be changed on error or if no update is required
See also:
kdb higher level Methods that rely on kdbGet()
ksLookupByName() for powerful lookups after the KeySet was retrieved
Returns:
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 ( Key errorKey  ) 

Opens the session with the Key database.

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. These libraries for backends will be loaded and with it the KDB datastructure will be initialized.

You must always call this method before retrieving or commiting any keys to the database. In the end of the program, after using the key database, you must not forget to kdbClose(). You can use the atexit () handler for it.

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:

thread1 {
        KDB * h;
        h = kdbOpen(0);
        // fetch keys and work with them
        kdbClose(h, 0);
}
thread2 {
        KDB * h;
        h = kdbOpen(0);
        // fetch keys and work with them
        kdbClose(h, 0);
}

You don't need to use the kdbOpen() if you only want to manipulate plain in-memory Key or KeySet objects without any affairs with the backend key database,

Parameters:
errorKey the key which holds errors and warnings which were issued must be given
See also:
kdbClose() to end all affairs to the Key :: Basic Methods database.
Returns:
a KDB pointer on success
NULL on failure
int kdbSet ( KDB handle,
KeySet ks,
Key parentKey 
)

Set keys in an atomic and universal way.

All other kdbSet Functions rely on that one.

parentKey

With parentKey you can only store a part of the given keyset.

KeySet *ks = ksNew(0);
Key *parentKey = keyNew("user/app/myapp/default", KEY_END);
kdbGet (h, ks, parentKey));

//now only set everything below user
if (kdbSet (h, ks, parentKey) == -1)
{
        // in parentKey you can check the error cause
        // ksCurrent(ks) is the faulty key
}

ksDel (ks);

If you pass a parentKey without a name the whole keyset will be set in an atomic way.

Update

Each key is checked with keyNeedSync() before being actually committed. So only changed keys are updated. If no key of a backend needs to be synced any affairs to backends omitted and 0 is returned.

Error Situations

If some error occurs, kdbSet() will stop. In this situation the KeySet internal cursor will be set on the key that generated the error.

None of the keys are actually commited.

You should present the error message to the user and let the user decide what to do. Possible solutions are:

  • repeat the same kdbSet (for temporary errors)
  • remove the key and set it again (for validation or type errors)
  • change the value and try it again (for validation errors)
  • do a kdbGet and then (for conflicts ...)
    • set the same keyset again (in favour of what was set by this user)
    • drop the old keyset (in favour of what was set elsewhere)
  • export the configuration into a file (for unresolvable errors)
Example of how this method can be used:
int i;
KeySet *ks;  // the KeySet I want to set
// fill ks with some keys
for (i=0; i< NR_OF_TRIES; i++) // limit to NR_OF_TRIES tries
{
        ret=kdbSet(handle, ks, parentKey);
        if (ret == -1)
        {
                // We got an error. Warn user.
                Key *problemKey = ksCurrent(ks);
                // parentKey has the errorInformation
                // problemKey is the faulty key (may be null)
                int userInput = showElektraErrorDialog (parentKey, problemKey);
                switch (userInput)
                {
                case INPUT_REPEAT: continue;
                case INPUT_REMOVE: ksLookup (ks, parentKey, KDB_O_POP); break;
                ...
                }
        }
}
Parameters:
handle contains internal information of opened key database
ks a KeySet which should contain changed keys, otherwise nothing is done
parentKey holds the information below which key keys should be set, see above
Returns:
1 on success
0 if nothing had to be done
-1 on failure
See also:
keyNeedSync(), ksNext(), ksCurrent()