.TH "md_doc_dev_plugins_framework" 3elektra "Sat Jun 5 2021" "Version 0.9.6" "Elektra" \" -*- nroff -*-
.ad l
.nh
.SH NAME
md_doc_dev_plugins_framework \- 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 \fCKeySet\fP 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\&.
.SH "Contracts"
.PP
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 \fCinfos/version\fP\&. It is vital so that the plugin loader knows which version of Elektra the plugin was built for\&.
.SH "Conditions"
.PP
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 behavior of a backend which uses a multiple of such plugins\&.
.PP
To avoid this situation, every plugin exports a contract describing how the plugin modifies the \fCKeySet\fP \fCreturned\fP\&. Most often it is enough to state that it is a \fIstorage\fP plugin or that it will \fIfilter\fP keys\&.
.PP
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\&.
.PP
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 behavior as described in \fBalgorithm\fP\&.
.PP
To sum up, contracts give the information how a plugin interacts with others\&. It describes if, and how, the \fCKeySet\fP \fCreturned\fP is changed\&. Using contracts, we get a predictable behavior, but still support every kind of plugin\&.
.SH "Exporting Contracts"
.PP
As already stated, some parts of the contracts are obligatory\&. \fCkdb mount\fP needs to know which symbols the plugin exports\&. Only the \fCelektraPluginGet()\fP symbol is mandatory - it is used to yield this information\&. Elektra’s core also uses the functions \fCelektraPluginSet()\fP, \fCelektraPluginError()\fP, \fC\fBelektraPluginOpen()\fP\fP and \fCelektraPluginClose()\fP if available\&. Other functions like \fCserialize\fP, \fCunserialize\fP or \fClookup\fP 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\&.
.PP
As described in \fCinfos/provides\fP, 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 \fCinfos/placement\fP 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\&.
.PP
\fCsystem:/elektra/modules\fP provides for every module the information described above\&. The entry exists once a plugin of that module is loaded\&. For each module a special \fImodule backend\fP is generated and mounted at \fCsystem:/elektra/modules/<pluginname>\fP\&. The \fCelektraPluginGet()\fP function generates this described contract on requests\&.
.PP
For example, the ccode plugin, implements:
.PP
.PP
.nf
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
}
.fi
.PP
.PP
We see in the listing above that the plugin generates and returns the contract if, and only if, the name of the \fCparentKey\fP is \fCsystem:/elektra/modules/ccode\fP\&. The user and the contract checker can access the contract of ccode below the key \fCsystem:/elektra/modules/ccode\fP in the same way other configuration is accessed\&. Note that we also have to \fCreturn 1\fP at the end of the contract to not execute the regular functionality of the plugin\&.
.SH "Exports"
.PP
Plugins can also export arbitrary additional functions\&. To export it, simply add another \fCexports\fP symbol to the contract:
.PP
.PP
.nf
keyNew ("system:/elektra/modules/dump/exports/checkconf", KEY_FUNC,
        elektraCcodeCheckConf, KEY_END);
.fi
.PP
.PP
\fCcheckconf\fP is the most important function that is not available as built-in function\&. It is used to validate or even correct/finish the plugin's configuration\&.
.PP
If you want to use an exported function from a symbol, please look at \fCPlugin::parse\fP\&.
.SH "Changing Plugins"
.PP
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\&.
.PP
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 replacement\&. With a good testing framework the behavior can be checked to some extent\&.
.PP
We also see in the 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\&.
.PP
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\&.
.SH "SEE ALSO"
.PP
.IP "\(bu" 2
\fBplugins-ordering\fP
.IP "\(bu" 2
\fBelektra-contracts(7)\fP 
.PP

