Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

Global plugins: global keyset handle #2307

Merged
merged 12 commits into from
Jan 23, 2019
18 changes: 18 additions & 0 deletions doc/decisions/global_plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ Configuration will be in arrays below the keys:
/rollback
/postrollback
/getresolver
/pregetcache
/pregetstorage
/getstorage
/postgetstorage
/postgetcache
/setresolver
/presetstorage
/setstorage
Expand Down Expand Up @@ -203,6 +205,22 @@ states.

## Related decisions

### Global KeySet handle

Some global plugins need to communicate more data than is possible to do with metadata.
This can limit the functionality of global plugins. One example is a global cache plugin,
which needs to store internal information for the KDB. Some of the information is binary
and can not be stored in metadata.

To make the communication between global plugins easier, global plugins will additionally
get a handle to a global keyset. The global keyset is tied to a KDB handle, initialized on kdbOpen() and
deleted on kdbClose().

The resolver plugin is an exception and also gets a handle to the global keyset. This way it
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not every plugin?

can store and compare timestamps of config files and cache files.

Plugins are responsible for cleaning up their part of the global keyset.

## Notes

### Open Points
Expand Down
2 changes: 1 addition & 1 deletion doc/news/_preparation_next_release.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ compiled against an older 0.8 version of Elektra will continue to work

### Core

- <<TODO>>
- Global plugins now get a handle to a global keyset, which makes communication between global plugins easier. *(Mihael Pranjić)*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

", for communication between plugins"?

- <<TODO>>
- <<TODO>>

Expand Down
1 change: 1 addition & 0 deletions src/include/kdbplugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ KeySet * elektraPluginGetConfig (Plugin * handle);
void elektraPluginSetData (Plugin * plugin, void * handle);
void * elektraPluginGetData (Plugin * plugin);

KeySet * elektraPluginGetGlobalKeySet (Plugin * plugin);

#define PLUGINVERSION "1"

Expand Down
14 changes: 11 additions & 3 deletions src/include/kdbprivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@ struct _KDB

Plugin * notificationPlugin; /*!< reference to global plugin for notifications.*/
ElektraNotificationCallbackContext * notificationCallbackContext; /*!< reference to context for notification callbacks.*/

KeySet * global; /*!< This keyset can be used by global plugins and the resolver
to pass data through the KDB and communicate with other global plugins.*/
};


Expand Down Expand Up @@ -413,6 +416,11 @@ struct _Plugin

void * data; /*!< This handle can be used for a plugin to store
any data its want to. */

KeySet * global; /*!< This keyset can be used by global plugins and the resolver
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why special handling of resolver?

to pass data through the KDB and communicate with other global plugins.
Plugins shall clean up their parts of the global keyset, which
they do not need any more.*/
};


Expand Down Expand Up @@ -587,9 +595,9 @@ int keyNameIsSystem (const char * keyname);
int keyNameIsUser (const char * keyname);

/* global plugin calls */
void elektraGlobalGet (KDB * handle, KeySet * ks, Key * parentKey, int position, int subPosition);
void elektraGlobalSet (KDB * handle, KeySet * ks, Key * parentKey, int position, int subPosition);
void elektraGlobalError (KDB * handle, KeySet * ks, Key * parentKey, int position, int subPosition);
int elektraGlobalGet (KDB * handle, KeySet * ks, Key * parentKey, int position, int subPosition);
int elektraGlobalSet (KDB * handle, KeySet * ks, Key * parentKey, int position, int subPosition);
int elektraGlobalError (KDB * handle, KeySet * ks, Key * parentKey, int position, int subPosition);

/** Test a bit. @see set_bit(), clear_bit() */
#define test_bit(var, bit) ((var) & (bit))
Expand Down
18 changes: 12 additions & 6 deletions src/libs/elektra/global.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,35 @@
* Helper functions to execute global plugins
*/

void elektraGlobalGet (KDB * handle, KeySet * ks, Key * parentKey, int position, int subPosition)
int elektraGlobalGet (KDB * handle, KeySet * ks, Key * parentKey, int position, int subPosition)
{
int ret = 0;
Plugin * plugin;
if (handle && (plugin = handle->globalPlugins[position][subPosition]))
{
plugin->kdbGet (plugin, ks, parentKey);
ret = plugin->kdbGet (plugin, ks, parentKey);
}
return ret;
}

void elektraGlobalSet (KDB * handle, KeySet * ks, Key * parentKey, int position, int subPosition)
int elektraGlobalSet (KDB * handle, KeySet * ks, Key * parentKey, int position, int subPosition)
{
int ret = 0;
Plugin * plugin;
if (handle && (plugin = handle->globalPlugins[position][subPosition]))
{
plugin->kdbSet (plugin, ks, parentKey);
ret = plugin->kdbSet (plugin, ks, parentKey);
}
return ret;
}

void elektraGlobalError (KDB * handle, KeySet * ks, Key * parentKey, int position, int subPosition)
int elektraGlobalError (KDB * handle, KeySet * ks, Key * parentKey, int position, int subPosition)
{
int ret = 0;
Plugin * plugin;
if (handle && (plugin = handle->globalPlugins[position][subPosition]))
{
plugin->kdbError (plugin, ks, parentKey);
ret = plugin->kdbError (plugin, ks, parentKey);
}
return ret;
}
5 changes: 5 additions & 0 deletions src/libs/elektra/kdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,11 @@ KDB * kdbOpen (Key * errorKey)
KDB * handle = elektraCalloc (sizeof (struct _KDB));
Key * initialParent = keyDup (errorKey);

handle->global = ksNew (0, KS_END);
handle->modules = ksNew (0, KS_END);
if (elektraModulesInit (handle->modules, errorKey) == -1)
{
ksDel (handle->global);
ksDel (handle->modules);
elektraFree (handle);
ELEKTRA_SET_ERROR (94, errorKey, "elektraModulesInit returned with -1");
Expand All @@ -282,6 +284,7 @@ KDB * kdbOpen (Key * errorKey)
switch (elektraOpenBootstrap (handle, keys, errorKey))
{
case -1:
ksDel (handle->global);
ksDel (handle->modules);
elektraFree (handle);
ELEKTRA_SET_ERROR (40, errorKey, "could not open default backend");
Expand Down Expand Up @@ -433,6 +436,8 @@ int kdbClose (KDB * handle, Key * errorKey)
ELEKTRA_ADD_WARNING (47, errorKey, "modules were not open");
}

if (handle->global) ksDel (handle->global);

elektraFree (handle);

keySetName (errorKey, keyName (initialParent));
Expand Down
3 changes: 3 additions & 0 deletions src/libs/elektra/mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,9 @@ int mountGlobals (KDB * kdb, KeySet * keys, KeySet * modules, Key * errorKey)
else
kdb->globalPlugins[i][MAXONCE] = plugin;

// set handle to global keyset
plugin->global = kdb->global;

// load plugins in explicit placements
const char * placementName = keyName (cur);
Key * placementKey = ksLookupByName (global, placementName, 0);
Expand Down
18 changes: 18 additions & 0 deletions src/libs/plugin/plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,21 @@ void * elektraPluginGetData (Plugin * plugin)
{
return plugin->data;
}

/**
* @brief Get a pointer to the global keyset.
*
* Only initialized for global plugins and the resolver.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above

*
* Plugins using this keyset are responsible for cleaning up
* their parts of the keyset which they do not need any more.
*
* If kdbOpen() was not called earlier, NULL will be returned.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this happen?

* @param plugin a pointer to the plugin
* @return a pointer to the global keyset
* @ingroup plugin
*/
KeySet * elektraPluginGetGlobalKeySet (Plugin * plugin)
{
return plugin->global;
}
14 changes: 14 additions & 0 deletions src/plugins/doc/doc.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,20 @@ int elektraDocGet (Plugin * plugin ELEKTRA_UNUSED, KeySet * returned, Key * pare
fclose (fp);
//![get storage]

//![get global keyset]
KeySet * globalKS = elektraPluginGetGlobalKeySet (plugin);
// now we can read something from the global keyset
// or add something for us or others to read
Key * important = keyNew ("user/global/myDocKey", KEY_VALUE, "global plugins can see me", KEY_END);
ksAppendKey (globalKS, important);
//![get global keyset]

//![get global keyset cleanup]
// clean up parts of the global keyset which we do not need
Key * cutKey = keyNew ("user/global/myDocKey", KEY_END);
KeySet * notNeeded = ksCut (globalKS, cutKey);
ksDel (notNeeded);
//![get global keyset cleanup]

//![get filter]
Key * k;
Expand Down
14 changes: 14 additions & 0 deletions src/plugins/doc/doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,20 @@
* Note that you also need to return -1 in the case of error.
* See individual description of entry points to implement below.
*
* @par Global KeySet Handle
*
* Global plugins and the resolver will get a handle to a global keyset.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is it constructed and deleted?

* This allows them to exchange information with other global plugins.
*
* Obtain a handle to the global keyset and work with it:
*
* @snippet doc.c get global keyset
*
* Clean up keys which you do not need any more,
* to keep the global keyset compact:
*
* @snippet doc.c get global keyset cleanup
*
* @par Further help
* Do not hesitate to open an issue if anything
* is unclear.
Expand Down
1 change: 1 addition & 0 deletions tests/icheck.suppression
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
// To ignore a function just add the function definition as regex here.
// For example, to ignore the function `int elektraArrayDecName(Key * key)` you can use
// the following entry: elektraArrayDecName
elektraPluginGetGlobalKeySet