Provided by: elektra-doc_0.8.14-5_all bug

NAME

       plugin - Plugins

       Elektra plugin framework.

   Macros
       #define ELEKTRA_PLUGIN_FUNCTION(module,  function)   libelektra_##module##_LTX_elektraPlugin##function
           Declare a plugin's function name suitable for compilation variants (see doc/tutorials).
       #define ELEKTRA_README(module)   ELEKTRA_README2(module)
           The filename for inclusion of the readme for compilation variants (see doc/tutorials).
       #define ELEKTRA_SET_ERROR(number,  key,  text)
           Sets the error in the keys metadata.
       #define ELEKTRA_SET_ERRORF(number,  key,  formatstring, ...)
           Sets the error in the keys metadata.
       #define ELEKTRA_ADD_WARNINGF(number,  key,  formatstring, ...)
           Adds an warning in the keys metadata.
       #define ELEKTRA_ADD_WARNING(number,  key,  text)
           Adds an warning in the keys metadata.

   Functions
       Plugin * elektraPluginExport (const char *pluginName,...)
           Allows one to Export Methods for a Plugin.
       KeySet * elektraPluginGetConfig (Plugin *handle)
           Returns the configuration of that plugin.
       void elektraPluginSetData (Plugin *plugin, void *data)
           Store a pointer to any plugin related data.
       void * elektraPluginGetData (Plugin *plugin)
           Get a pointer to any plugin related data stored before.
       int elektraDocOpen (Plugin *handle, Key *warningsKey)
           Initialize data for the plugin.
       int elektraDocClose (Plugin *handle, Key *warningsKey)
           Finalize the plugin.
       int elektraDocGet (Plugin *handle, KeySet *returned, Key *parentKey)
           Get data from storage to application.
       int elektraDocSet (Plugin *handle, KeySet *returned, Key *parentKey)
           Set data from application to storage.
       int elektraDocError (Plugin *handle, KeySet *returned, Key *parentKey)
           Rollback in case of errors.

Detailed Description

       Elektra plugin framework.

       Since:
           version 0.4.9, Elektra can dynamically load different key storage plugins.

           version 0.7.0 Elektra can have multiple backends, mounted at any place in the key database.

           version 0.8.0 Elektra backends are composed out of multiple plugins.

       To get started with writing plugins, first read our plugin tutorial in doc/tutorials!

       A plugin can implement any functionality related to configuration. There are 6 possible entry points for
       a plugin.

       • elektraDocGet()  will  be  called when configuration or the plugin's contract is retrieved from the key
         database

       • elektraDocSet() will be called when configuration is written to the key database

       • elektraDocOpen() will be called before any other method of the plugin is called

       • elektraDocClose() will be called as last method

       • elektraDocError() will be called when kdbSet() failed (to give the plugin a chance to recover/undo  its
         actions)

       • elektraPluginExport() exports all methods for the plugin.

       The names described here contain 'Doc' within the method's name just because the plugin described in this
       document  is called doc (the doxygen source was generated from src/plugins/doc/doc.h). Always replace Doc
       with the name of the plugin you are going to implement or use ELEKTRA_PLUGIN_FUNCTION.

       Overview
           There are different types of plugins for different concerns. They all only have the entry  points  as
           defined above. The types of plugins handled in this document:

           • A  storage plugin gets an empty keyset in elektraDocGet() and constructs the information out from a
             file. In elektraDocSet() the keyset is written to a file.
              Other persistent storage then a file is not handled within this document because it involves  many
             other  issues.  For  files the resolver plugin already takes care for transactions and rollback. So
             the storage plugin is the source and dump as known from pipes and filters.

           • A filter plugin is a plugin which operates on existing keys. It may process or change  the  keyset.
             Or it may reject specific keysets which do not meet some criteria.

       Use following include to have the functions that are not implement by you available:

       #include <kdbplugin.h>

       Error and Warnings
           In  case  of trouble, in some methods you can use the macro ELEKTRA_SET_ERROR (in other methods it is
           not allowed). You might add warnings with the macro ELEKTRA_ADD_WARNING. Read  the  documentation  of
           the individual methods to decide what you should do.

       Use following include to have the macros for setting the error and adding the warnings available:

       #include <kdberrors.h>

        Do not hesitate to open an issue if anything is unclear.

Macro Definition Documentation

   #define ELEKTRA_ADD_WARNING(number, key, text)
       Adds an warning in the keys metadata. Include kdberrors.h to make it work:

       #include <kdberrors.h>

       Parameters:
           number the warning number from src/liberror/specification
           key to write the error to
           text additional text for the user

   #define ELEKTRA_ADD_WARNINGF(number, key, formatstring,  ...)
       Adds an warning in the keys metadata. Include kdberrors.h to make it work:

       #include <kdberrors.h>

       Parameters:
           number the warning number from src/liberror/specification
           key to write the error to
           formatstring a format string as in printf
           ... further arguments as in printf

   #define ELEKTRA_PLUGIN_FUNCTION(module, function)   libelektra_##module##_LTX_elektraPlugin##function
       Declare a plugin's function name suitable for compilation variants (see doc/tutorials). It can be used in
       the same way as elektraPluginExport().

       See also:
           ELEKTRA_PLUGIN_EXPORT

       Parameters:
           plugin the name of the plugin
           which which function it is (open, close, get, set, error)

   #define ELEKTRA_README(module)   ELEKTRA_README2(module)
       The filename for inclusion of the readme for compilation variants (see doc/tutorials).

       Parameters:
           plugin the name of the plugin

   #define ELEKTRA_SET_ERROR(number, key, text)
       Sets the error in the keys metadata. Include kdberrors.h to make it work:

       #include <kdberrors.h>

       Parameters:
           number the error number from src/liberror/specification
           key to write the error to
           text additional text for the user

   #define ELEKTRA_SET_ERRORF(number, key, formatstring,  ...)
       Sets the error in the keys metadata. Include kdberrors.h to make it work:

       #include <kdberrors.h>

       Parameters:
           number the error number from src/liberror/specification
           key to write the error to
           formatstring a format string as in printf
           ... further arguments as in printf

Function Documentation

   int elektraDocClose (Plugin * handle, Key * warningsKey)
       Finalize  the plugin. Called prior to unloading the plugin dynamic module. After this function is called,
       it is ensured that no functions from your plugin will ever be accessed again.

       Make sure to free all memory that your plugin requested at runtime. Also  make  sure  to  free  what  you
       stored by elektraPluginSetData() before.

       So for the Doc plugin we need to:

       int elektraDocClose(Plugin *handle, Key *warningsKey ELEKTRA_UNUSED)
       {
               free (elektraPluginGetData(handle));

               return 0; /* success */
       }

        After  this  call,  libelektra.so  will  unload the plugin library, so this is the point to shutdown any
       affairs with the storage.

       Parameters:
           handle contains internal information of the plugin
           warningsKey can be used to to add warnings using ELEKTRA_ADD_WARNING (Do not add errors!)

       Return values:
           0 on success (no other return value currently allowed)
           -1 on problems (only use ELEKTRA_ADD_WARNING, but never set an error).

       See also:
           kdbClose()

           elektraPluginGetData(), elektraPluginSetData() and elektraPluginGetConfig()

   int elektraDocError (Plugin * handle, KeySet * returned, Key * parentKey)
       Rollback in case of errors. First for all plugins elektraDocSet() will  be  called.  If  any  plugin  had
       problems before the commit (done by the resolver plugin), we can safely rollback our changes.

       This  method  is  rarely  used  by plugins, it is mainly used for resolvers (to implement rollback) or by
       logging plugins. It is not needed for storage plugins, because  they  only  operate  on  temporary  files
       created by the resolver.

       Parameters:
           handle contains internal information of the plugin
           returned contains a keyset with relevant keys
           parentKey  contains the information where to set the keys. can be used to add warnings with the macro
           ELEKTRA_ADD_WARNING, but do not add errors!

       Return values:
           1 on success
           0 on success with no action
           -1 on failure (you can add warnings, but we are already in an error state, so do not set the error).

   int elektraDocGet (Plugin * handle, KeySet * returned, Key * parentKey)
       Get data from storage to application. Retrieve information  from  a  permanent  storage  to  construct  a
       keyset.

.

       The elektraDocGet() function handle everything related to receiving keys.

   Contract Handling
       The    contract    is    a    keyset    that    needs    to    be    returned   if   the   parentKey   is
       system/elektra/modules/yourpluginname.

       Which keys and their meaning is specified in doc/CONTRACT.ini

       Here is an example for our doc plugin:

       int elektraDocGet(Plugin *plugin ELEKTRA_UNUSED, KeySet *returned, Key *parentKey)
       {
               if (!strcmp(keyName(parentKey), "system/elektra/modules/doc"))
               {
                       KeySet *contract = ksNew (30,
                       keyNew ("system/elektra/modules/doc",
                               KEY_VALUE, "doc plugin waits for your orders", KEY_END),
                       keyNew ("system/elektra/modules/doc/exports", KEY_END),
                       keyNew ("system/elektra/modules/doc/exports/open",
                               KEY_FUNC, elektraDocOpen, KEY_END),
                       keyNew ("system/elektra/modules/doc/exports/close",
                               KEY_FUNC, elektraDocClose, KEY_END),
                       keyNew ("system/elektra/modules/doc/exports/get",
                               KEY_FUNC, elektraDocGet, KEY_END),
                       keyNew ("system/elektra/modules/doc/exports/set",
                               KEY_FUNC, elektraDocSet, KEY_END),
                       keyNew ("system/elektra/modules/doc/exports/error",
                               KEY_FUNC, elektraDocError, KEY_END),
       #include ELEKTRA_README(doc)
                       keyNew ("system/elektra/modules/doc/infos/version",
                               KEY_VALUE, PLUGINVERSION, KEY_END),
                       KS_END);
                       ksAppend (returned, contract);
                       ksDel (contract);

                       return 1; /* success */
               }

        Some clauses of the contract, especially the description of the plugin can  be  done  more  conveniently
       directly in a README.md that is included by ELEKTRA_README.

   Storage Plugins
       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):

       • parse_key will parse a key and a value from an open file handle

       The typical loop for a storage plugin will be like:

               FILE *fp = fopen (keyString(parentKey), "r");
               char *key;
               char *value;

               while (parseKey(fp, &key, &value) >= 1)
               {
                       Key *read = keyNew(0);
                       if (keySetName(read, key) == -1)
                       {
                               fclose (fp);
                               keyDel (read);
                               ELEKTRA_SET_ERROR(59, parentKey, key);
                               return -1;
                       }
                       keySetString(read, value);

                       ksAppendKey (returned, read);
                       free (key);
                       free (value);
               }

               if (feof(fp) == 0)
               {
                       fclose (fp);
                       ELEKTRA_SET_ERROR(60, parentKey, "not at the end of file");
                       return -1;
               }

               fclose (fp);

   Filter Plugins
       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:

       • do_action() which processes every key in this filter

               Key *k;
               ksRewind (returned);
               while ((k = ksNext (returned)) != 0)
               {
                       doAction(k);
               }

               return 1; // success
       }

       Precondition:
           The caller kdbGet() will make sure before you are called that the parentKey:

           • is a valid key (means that it is a system or user key).

           • is your mountpoint and that your plugin is responsible for it.

           and that the returned:

           • is a valid keyset.

           • your plugin is only called when needed (e.g. only if file was modified)

           • has all keys related to your plugin.

           • contains only valid keys below (see keyIsBelow()) your parentKey.

           • is in a sorted order (given implicit by KeySet)

           and that the handle:

           • is valid for your plugin.

           • that elektraPluginGetData() contains the same handle for lifetime of your plugin.

           The caller kdbGet() will make sure that afterwards you were called, that:

           • other plugins below your plugin will be called again recursively.

           • that all keys are merged to one keyset the user gets

           • that all keys (that should not be removed) are passed to kdbSet() if writing to disc is needed.

       Invariant:
           There are no global variables and elektraPluginSetData() stores all information. The handle is to  be
           guaranteed to be the same if it is the same plugin.

       Postcondition:
           The keyset returned has the parentKey and all keys below (keyIsBelow()) 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 with additional plugins.

       Updating
           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 by the resolver. For other
           types (e.g. databases) you need to implement your own resolver doing this.

       See also:
           kdbGet() for caller.

       Parameters:
           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.

       Return values:
           1 on success
           0 when nothing was to do
           -1 on failure, the current key in returned shows the position. use ELEKTRA_SET_ERROR  of  kdberrors.h
           to define the error code. You additionally can add as many warnings as you would like to add.

   int elektraDocOpen (Plugin * handle, Key * warningsKey)
       Initialize data for the plugin. This is the first method called after dynamically loading this plugin. It
       is guaranteed, that this method will be called before any other method.

       This method is responsible for:

       • plugin's specific configuration gathering

       • initialization of all plugin's internal structs

       • initial  setup of all I/O details such as opening a file, connecting to a database, setup connection to
         a server, iff this cannot be done per invocation in elektraDocGet() and elektraDocSet().

       You may also read the configuration you can get with elektraPluginGetConfig() and transform it into other
       structures used by your plugin.

       Note:
           The plugin must not have any global variables. If you have one Elektra will not be threadsafe. Do not
           assume that your plugin will be opened only once or will not be reopened at a later time.

       Instead of global variables the methods elektraPluginGetData() and elektraPluginSetData() exist to  store
       and get any information related to your plugin.

       The correct substitute for global variables will be:

       typedef struct { int global; } GlobalData;

        and then initialize it using:

       int elektraDocOpen(Plugin *handle, Key *warningsKey ELEKTRA_UNUSED)
       {
               GlobalData *data;
               KeySet *config = elektraPluginGetConfig(handle);
               Key * kg = ksLookupByName(config, "/global", 0);

               data=malloc(sizeof(GlobalData));
               data->global = 0;
               if (kg) data->global = atoi(keyString(kg));
               elektraPluginSetData(handle,data);

        Make sure to free everything you allocate within elektraDocClose().

       If  your  plugin has no useful way to startup without config, the module loader would not be able to load
       the module. 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 elektraDocGet() on system/elektra/modules can be called successfully later on.

               if (ksLookupByName(config, "/module", 0))
               {
                       return 0;
               }
               // do some setup that will fail without configuration

       Return values:
           -1 on  error,  your  plugin  will  be  removed  then  and  the  missing  plugin  added  instead.  Use
           ELEKTRA_ADD_WARNING  to  indicate the problem. The system will automatically add the information that
           the plugin was removed, so you do not need the user give that information.
           0 on success

       Parameters:
           handle contains internal information of the plugin
           warningsKey can be used to add warnings with the macro ELEKTRA_ADD_WARNING (Do not add errors!)

       See also:
           elektraPluginGetData(), elektraPluginSetData() and elektraPluginGetConfig()

           elektraDocClose()

   int elektraDocSet (Plugin * handle, KeySet * returned, Key * parentKey)
       Set data from application to storage. This function does everything related to set and remove keys  in  a
       plugin.  There  is  only  one function for that purpose to make implementation of file based plugins 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 to understand:

       static void usercode (KDB *handle, KeySet *keyset, Key *key)
       {
               // some more user code
               keySetString (key, "mycomment"); // the user changes the key
               ksAppendKey(keyset, key); // append the key to the keyset
               kdbSet (handle, keyset, 0); // and syncs it to disc
       }

       // so now kdbSet is called
       int elektraKdbSet(KDB *handle, KeySet *keyset, Key *parentKey)
       {
               int ret = 0;
               // find appropriate plugin and then call it:
               Plugin *plugin = findPlugin(handle);
               ret = elektraDocSet (plugin, keyset, parentKey);
               // the keyset with the key (and others for this plugin)
               // will be passed to this function
               return ret;
       }

       // so now elektraPluginSet(), which is the function described here,
       // is called:
       int elektraPluginSet(Plugin *plugin ELEKTRA_UNUSED, KeySet *returned, Key *parentKey ELEKTRA_UNUSED)
       {
               // the task of elektraPluginSet is now to store the keys
               Key *k;
               ksRewind (returned);
               while ((k = ksNext (returned)) != 0)
               {
                       saveToDisc (k);
               }

               return 1; /* success */
       }

        Of course all information of every key in the keyset returned need to be  stored  permanently.  So  this
       specification needs to give an exhaustive list of information present in a key.

       Precondition:
           The  keyset  returned  holds  all keys which must be saved permanently for this keyset. The keyset is
           sorted and rewinded.

           The 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 name of the parentKey marks the mountpoint. The  string  of
           the parentKey is the filename to write to.

       Make  sure to set all keys, all directories and also all hidden keys. If some of them are not wished, the
       caller kdbSet() and plugins will sort them out.

       Invariant:
           There are no global variables, but instead elektraPluginGetData() will be used.  The  handle  is  the
           same when it is the same plugin.

       Postcondition:
           The information of the keyset returned is stored permanently.

       See also:
           kdbSet() for caller.

       Parameters:
           handle contains internal information of the plugin
           returned contains a keyset with relevant keys
           parentKey  contains the information where to set the keys (name is mountpoint your plugin is mounted,
           string is the file to write to)

       Returns:
           When everything works gracefully return the number of keys you set. The cursor position and the  keys
           remaining in the keyset are not important.

       Return values:
           1 on success
           0 on success with no changed key in database
           -1  on failure. The cause of the error needs to be added in parentKey You also have to make sure that
           ksGetCursor() shows to the position where the error appeared. Set an error using ELEKTRA_SET_ERROR to
           inform  the  user  what  went  wrong.  Additionally  you  can  add  any  number  of   warnings   with
           ELEKTRA_ADD_WARNING.

   Plugin* elektraPluginExport (const char * pluginName,  ...)
       Allows  one to Export Methods for a Plugin. This function must be called within ELEKTRA_PLUGIN_EXPORT. It
       define the plugin's methods that will be exported.

       All KDB methods implemented by the plugin basically could have random names (convention is elektraName*),
       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. For example for the
       doc plugin:

       Plugin *ELEKTRA_PLUGIN_EXPORT(doc)
       {
               return elektraPluginExport(DOC_PLUGIN_NAME,
                       ELEKTRA_PLUGIN_OPEN,    &elektraDocOpen,
                       ELEKTRA_PLUGIN_CLOSE,   &elektraDocClose,
                       ELEKTRA_PLUGIN_GET,     &elektraDocGet,
                       ELEKTRA_PLUGIN_SET,     &elektraDocSet,
                       ELEKTRA_PLUGIN_ERROR,   &elektraDocError,
                       ELEKTRA_PLUGIN_END);
       }

        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.

       Parameters:
           pluginName the name of this plugin

       Returns:
           an object that contains all plugin information needed by libelektra.so

   KeySet* elektraPluginGetConfig (Plugin * handle)
       Returns the configuration of that plugin.

       • The user/ config holds plugin specific configuration

       • The system/ config holds backend specific configuration

       So prefer cascading lookups to honor both.

       Parameters:
           handle a pointer to the plugin

       Returns:
           keyset to the configuration for that plugin

   void* elektraPluginGetData (Plugin * plugin)
       Get a pointer to any plugin related data stored before.

       Parameters:
           plugin a pointer to the plugin

       Returns:
           a pointer to the data

   void elektraPluginSetData (Plugin * plugin, void * data)
       Store a pointer to any plugin related data.

       Parameters:
           plugin a pointer to the plugin
           data the pointer to the data

Author

       Generated automatically by Doxygen for Elektra from the source code.

Version 0.8.14                                   Tue Dec 15 2015                                plugin(3elektra)