xenial (7) elektra-plugins-framework.7.gz

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

NAME

       elektra-plugins-framework - Background about plugins framework

       Many  component systems pass information between the various components by calling methods of each other.
       This is not the way Elektra´s plugin system works. Instead, the  core  passes  a  KeySet  object  in  one
       direction  from  plugin  to  plugin.  So  they form a so called pipes-and-filter. Each of the plugins can
       modify the configuration or add any other information using metakeys. While this approach is  in  general
       less  flexible,  this  information  flow  still  allows powerful chaining. Because plugins do not have to
       bother to call other plugins, the plugin development is also easier. The ordering of plugins in  backends
       is controlled using contracts.

Contracts

       Every plugin should provide a full contract to give information how it will work with other plugins. Most
       parts of the contract are obligatory. Plugins cannot be loaded without  this  information.  For  example,
       plugins  must provide the clause infos/version. It is vital so that the plugin loader knows which version
       of Elektra the plugin was built for.

Conditions

       It is, however, up to the plugin not to have every clause of the contract. For example, the plugin  might
       not  tell  what  it  provides  or  needs.  It can also leave any description out. In this situation it is
       unclear what the plugin will do. Such a plugin can add or remove keys, and changes  values  and  metadata
       regardless  what  other  plugins  expect.  If only such plugins existed there would be chaos. It would be
       impossible to determine the behaviour of a backend which uses a multiple of such plugins.

       To avoid this situation, every plugin exports a contract describing how the plugin  modifies  the  KeySet
       returned. Most often it is enough to state that it is a storage plugin or that it will filter keys.

       The  data  structures,  however,  are  already responsible for most of the pre- and postconditions. Every
       condition the data structure guarantees, takes away a concern for the plugins. All  the  parts  that  are
       already guaranteed by data structures do not need to be stated in the contract.

       Plugins  should  not  be burdened to check too many postconditions. Instead, plugins focus on their task.
       The plugin does not need to check the sync flag of keys or if the keys are below  the  mount  point.  The
       core already guarantees correct behaviour as described in algorithm /doc/help/elektra-algorithm.md.

       To  sum  up, contracts give the information how a plugin interacts with others. It describes if, and how,
       the KeySet returned is changed. Using contracts, we get a predictable behaviour, but still support  every
       kind of plugin.

Exporting Contracts

       As  already stated, some parts of the contracts are obligatory. kdb mount needs to know which symbols the
       plugin exports. Only the elektraPluginGet() symbol is mandatory - it is used to yield  this  information.
       Elektra´s  core also uses the functions elektraPluginSet(), elektraPluginError(), elektraPluginOpen() and
       elektraPluginClose() if available. Other functions like serialise, unserialise or lookup which  implement
       special  features  can  be  supported,  but  are  ignored  by the core. For the user of the library these
       functions can be very useful. These functions shall either belong to the concern  of  the  plugin  or  be
       implemented within the plugin because of the dependences.

       As  described  in  infos/provides /doc/CONTRACT.ini, the plugin can also provide descriptive information,
       for example about the author and the licence. Advanced plugins can also export plugin  configuration  for
       other  plugins  so  that  the  overall  backend  works  properly.  Last,  but not least, as enumerated in
       infos/placement /doc/CONTRACT.ini dependency and placement information  makes  the  system  reliable  and
       robust. With that information, plugins can be placed into a backend in an automatic and secure way.

       system/elektra/modules provides for every module the information described above. The entry exists once a
       plugin of that module is loaded. For each module a special module backend is  generated  and  mounted  at
       system/elektra/modules/<pluginname>. The elektraPluginGet() function generates this described contract on
       requests.

       For example, the ccode plugin, implements:

           int elektraCcodeGet(Plugin *handle, KeySet *returned, Key *parentKey)
           {
               if (!strcmp (keyName(parentKey), "system/elektra/modules/ccode"))
               {
                   KeySet *contract = ksNew (30,
                       keyNew ("system/elektra/modules/ccode",
                           KEY_END),
                       keyNew ("system/elektra/modules/ccode/exports",
                           KEY_END),
                       //...
                       KS_END);
                   ksAppend (returned, contract);
                   ksDel (contract);
                   return 1;
               }
               // implementation of elektraCcodeGet

       We see in Listing above that the plugin generates and returns the contract if, and only if, the  name  of
       the  parentKey is system/elektra/modules/ccode. The user and the contract checker can access the contract
       of ccode below the key system/elektra/modules/ccode in the same way other configuration is accessed. Note
       that  we also have to return 1 at the end of the contract to not execute the regular functionality of the
       plugin.

Changing Plugins

       This configuration is static and contains the contract  information.  In  theory,  the  contract  can  be
       changed without any problems in ways that it provides more and obligates less. But the problem is that it
       will not be checked if this is the case because  a  recheck  of  the  contracts  of  a  backend  is  very
       expensive.  The  contract  checker doing this, only runs once during mount time. Changing contracts in an
       incompatible way forces the user to remove all mount points where the plugin is and mount it again.  Such
       actions are only sustainable in a development phase and not in a productive environment.

       But  the  plugin´s  implementation is allowed to change without being remounted if it is a subtype of the
       earlier version. Only in this situation it can be a drop-in placement. With a good testing framework  the
       behaviour can be checked to some extent.

       We  also  see in Listing above that the code responsible for generating the contract and the code for the
       implementation are next to each other. Plugins need to satisfy those self-imposed  obligations  that  are
       described  in contracts. They ensure that plugins interact in predictable ways. So the process of writing
       individual plugins and composing them together can be described as Component-Based Software Engineering.

       Plugins can also be viewed as framework extensions. A component  abstracts  plugins.  But  this  term  is
       misleading  in our case, because components usually can choose which interfaces they implement. Elektra´s
       plugins, however, are restricted to implement one specific interface. Without  contracts,  plugins  could
       not interact as described in this chapter.

SEE ALSO

elektra-plugins-ordering(7) elektra-plugins-ordering.mdelektra-contracts(7) elektra-contracts.md

                                                  November 2015                     ELEKTRA-PLUGINS-FRAMEWORK(7)