Elektra
0.8.7
|
Elektra plugin framework. More...
Functions | |
int | docOpen (Plugin *handle, Key *errorKey) |
int | docClose (Plugin *handle, Key *errorKey) |
int | docGet (Plugin *handle, KeySet *returned, Key *parentKey) |
int | docSet (Plugin *handle, KeySet *returned, Key *parentKey) |
int | docError (Plugin *handle, KeySet *returned, Key *parentKey) |
Plugin * | ELEKTRA_PLUGIN_EXPORT (doc) |
Elektra plugin framework.
See the descriptions below what each of them is supposed to do.
int docClose | ( | Plugin * | handle, |
Key * | errorKey | ||
) |
Finalize the plugin.
Called prior to unloading the plugin dynamic module. Should ensure that no functions or static/global variables from the module will ever be accessed again.
Make sure to free all memory that your plugin requested at runtime.
After this call, libelektra.so will unload the plugin library, so this is the point to shutdown any affairs with the storage.
handle | contains internal information of the plugin |
errorKey | is needed to add warnings using ELEKTRA_ADD_WARNING |
0 | on success |
int docError | ( | Plugin * | handle, |
KeySet * | returned, | ||
Key * | parentKey | ||
) |
Rollback in case of errors.
handle | contains internal information of the plugin |
returned | contains a keyset with relevant keys |
parentKey | contains the information where to set the keys |
1 | on success |
0 | on success with no action |
-1 | on failure |
int docGet | ( | Plugin * | handle, |
KeySet * | returned, | ||
Key * | parentKey | ||
) |
Retrieve information from a permanent storage to construct a keyset.
The elektraDocGet() function handle everything related to receiving keys.
For storage plugins the filename is written in the value of the parentKey. So the first task of the plugin is to open that file. Then it should parse its content and construct a keyset with all information of that file.
You need to be able to reconstruct the same file with the information of the keyset. So be sure to copy all comments, whitespaces and so on into some metadata of the keys. Otherwise the information is lost after writing the file the next time.
Now lets look at an example how the typical elektraDocGet() might be implemented. To explain we introduce some pseudo functions which do all the work with the storage (which is of course 90% of the work for a real plugin):
The typical loop for a storage plugin will be like:
For filter plugins the actual task is rather unspecified. You basically can do anything with the keyset. To get roundtrip properties you might want to undo any changes you did in elektraDocSet().
The pseudo functions (which do the real work) are:
all
keys with the flag KEY_FLAG_SYNC set.returned
has the parentKey
and all keys direct below (keyIsDirectBelow()) with all information from the storage. Make sure to return all keys, all directories and also all hidden keys. If some of them are not wished, the caller kdbGet() will drop these keys, see above.To get all keys out of the storage over and over again can be very inefficient. You might know a more efficient method to know if the key needs update or not, e.g. by stating it or by an external time stamp info. For file storage plugins this is automatically done for you. For other types (e.g. databases) you need to implement your own resolver doing this.
handle | contains internal information of opened key database |
returned | contains a keyset where the function need to append the keys got from the storage. There might be also some keys inside it, see conditions. You may use them to support efficient updating of keys, see Updating. |
parentKey | contains the information below which key the keys should be gotten. |
int docOpen | ( | Plugin * | handle, |
Key * | errorKey | ||
) |
Initialize the plugin.
This is the first method called after dynamically loading this plugin.
This method is responsible for:
You may also read the configuration you can get with elektraPluginGetConfig() and transform it into other structures used by your plugin.
Instead you can use elektraPluginGetData() and elektraPluginSetData() to store and get any information related to your plugin.
The correct substitute for global variables will be:
If your plugin has no useful way to startup without config, the module loader would not be able to load the module, too. To solve that problem the module loader adds the configuration key /module. Even if your plugin is basically not able to startup successfully, it should still provide a fallback when /module is present, so that docGet() on system/elektra/modules can be called successfully later on.
handle | contains internal information of the plugin |
errorKey | defines an errorKey |
int docSet | ( | Plugin * | handle, |
KeySet * | returned, | ||
Key * | parentKey | ||
) |
Store a keyset permanently.
This function does everything related to set and remove keys in a plugin. There is only one function for that purpose to make implementation and locking much easier.
The keyset returned
was filled in with information from the application using elektra and the task of this function is to store it in a permanent way so that a subsequent call of elektraPluginGet() can rebuild the keyset as it was before. See the live cycle of a comment to understand:
Of course not only the comment, but all information of every key in the keyset returned
need to be stored permanetly. So this specification needs to give an exhaustive list of information present in a key.
returned
holds all keys which must be saved permanently for this keyset. The keyset is sorted and rewinded. All keys having children must be true for keyIsDir().parentKey
is the key which is the ancestor for all other keys in the keyset. The first key of the keyset returned
has the same keyname. The parentKey is below the mountpoint, see kdbhGetMountpoint().returned
need to be stored permanently.returned
is stored permanently.Lock your permanent storage in an exclusive way, no access of a concurrent elektraPluginSet_plugin() or kdbGet() is possible and these methods block until the function has finished. Otherwise declare kdbcGetnoLock().
handle | contains internal information of the plugin |
returned | contains a keyset with relevant keys |
parentKey | contains the information where to set the keys |
1 | on success |
0 | on success with no changed key in database |
-1 | on failure. The cause of the error needs to beadded in parentKey |
You also have to make sure that ksGetCursor() shows to the position where the error appeared.
Plugin* ELEKTRA_PLUGIN_EXPORT | ( | doc | ) |
All KDB methods implemented by the plugin can have random names, except ELEKTRA_PLUGIN_EXPORT. This is the single symbol that will be looked up when loading the plugin, and the first method of the backend implementation that will be called.
You need to use a macro so that both dynamic and static loading of the plugin works.
The first parameter is the name of the plugin. Then every plugin should have: ELEKTRA_PLUGIN_OPEN
, ELEKTRA_PLUGIN_CLOSE
, ELEKTRA_PLUGIN_GET
, ELEKTRA_PLUGIN_SET
and optionally ELEKTRA_PLUGIN_ERROR
.
The list is terminated with ELEKTRA_PLUGIN_END
.
You must use static "char arrays" in a read only segment. Don't allocate storage, it won't be freed.