$darkmode
Elektra 0.9.12
|
The plugin tutorial already covers some of the most interesting parts on how to write a (storage) plugin. This text will tell you a little bit more about how a storage plugin should act. While it is usually relatively easy to create a plugin that stores basic key-value pairs, adding advanced features such as support for
takes more work. Before you continue with this text, please make sure that you read all of the linked documents above.
One common problem of storage plugins is, that they store too many keys. For example, if the user adds the keys
user:/tests/storage/root
anduser:/tests/storage/root/level1/level2/level3
,then your plugin should only store those two keys. Do not add the keys
user:/tests/storage/root/level1
, oruser:/tests/storage/root/level1/level2
to the key set. One plugin that handles this situation properly is YAML CPP, as the following Markdown Shell Recorder test shows:
. For more information on why we allow “holes” in the hierarchy, please take a look here.
Elektra supports both binary and textual values. The main difference between binary and textual data is that textual data always ends with a null byte. Therefore you are not allowed to store the code point 0
inside textual data. Binary data does not have this limitation.
The simplest textual data is the empty string (""
= 0
) and has length 1, while the simplest binary data stores nothing at all and therefore has length 0. In the kdb
utility you can disambiguate between these value by checking for the metakey `binary`. The following Markdown Shell Recorder test shows how a storage plugin should handle empty values.
Elektra uses `0` and `1` to represent binary data. A storage plugin that uses other values (e.g. false
and true
) needs to convert these values to 0
and 1
. The Markdown Shell Recorder test below shows that YAML CPP handles the conversion from and to YAML’s boolean type properly. In the test we also use the `type` plugin to makes sure that YAML CPP interacts correctly with this essential plugin.
Sometimes the most “natural” mapping of key-value pairs to a file format might cause a storage plugin to not be able to store values in so-called directory (non-leaf) keys.
For example, in a key set that contains the keys:
, all keys at the bottom of the hierarchy:
, such as
user:/directory/leaf1
user:/directory/leaf2
user:/leaf3
are called leaf keys, while user:/directory
is a directory key. Plugins such as YAJL or YAML CPP will not be able to store data in the key with the name user:/directory
directly. To work around this issue these plugin use the Directory Value plugin. In the ReadMe of the Directory Value plugin and YAML CPP you will find more information about this issue, and how to handle it.
The following Markdown Shell Recorder test shows the proper behavior:
. To make sure that your storage plugin works correctly, please just replace yamlcpp
with the name of your plugin and verify that the test above still works.
You already learned about the array syntax and the mandatory array
metakey in the array tutorial. Now it is time to check, if your storage plugin supports array and non-array keys properly. Let us look at a concrete example. We use a key set that contains the following keys as example:
. If we assume that only user:/tests/storage/array
stores the metakey array
, then the keys
user:/tests/storage/array/#0
, anduser:/tests/storage/array/#1
represent array elements, while
user:/tests/storage/map/#0
, anduser:/tests/storage/map/#1
are normal key-value pairs. The following example shows that the storage plugin YAML CPP handles this situation properly:
Most markup languages provide the possibility of adding comments. Elektra can store those comments in its metadata as well. This can be achieved by setting the meta Keys comment/#
for the respective configuration Key. Also the hosts
plugin stores the comments of the file in the respective Elektra configuration Key:
```
sudo kdb mount –with-recommends hosts user:/tests/hosts hosts
echo '127.0.0.1 localhost # test comment' > kdb file user:/tests/hosts
kdb get user:/tests/hosts/ipv4/localhost #> 127.0.0.1
kdb meta-ls user:/tests/hosts/ipv4/localhost #> comment/#0 #> comment/#0/space #> comment/#0/start #> order
kdb meta-get user:/tests/hosts/ipv4/localhost 'comment/#0' #> test comment
kdb rm -r user:/tests/hosts sudo kdb umount user:/tests/hosts
sudo kdb mount –with-recommends hosts user:/tests/hosts hosts
echo '127.0.0.1 localhost.1' > kdb file user:/tests/hosts
echo '127.0.0.1 localhost.2' >> kdb file user:/tests/hosts
kdb ls user:/tests/hosts/ipv4 #> user:/tests/hosts/ipv4/localhost.1 #> user:/tests/hosts/ipv4/localhost.2
kdb meta-ls user:/tests/hosts/ipv4/localhost.1 #> comment/#0 #> order
kdb meta-get user:/tests/hosts/ipv4/localhost.1 order #> 1
kdb meta-get user:/tests/hosts/ipv4/localhost.2 order #> 2
kdb set user:/tests/hosts/ipv4/localhost.4 127.0.0.1 kdb set user:/tests/hosts/ipv4/localhost.3 127.0.0.1
cat kdb file user:/tests/hosts
#> 127.0.0.1 localhost.3 #> 127.0.0.1 localhost.4 #> 127.0.0.1 localhost.1 #> 127.0.0.1 localhost.2
kdb meta-set user:/tests/hosts/ipv4/localhost.4 order 4 kdb meta-set user:/tests/hosts/ipv4/localhost.3 order 3
cat kdb file user:/tests/hosts
#> 127.0.0.1 localhost.1 #> 127.0.0.1 localhost.2 #> 127.0.0.1 localhost.3 #> 127.0.0.1 localhost.4
kdb rm -r user:/tests/hosts sudo kdb umount user:/tests/hosts ```
As you can see by setting the order metakey in the respective KDB entries, we can manipulate the order in which entries get written to the hosts file. Also when importing from the initial hosts file, the plugin stores the correct order in the meta KeySet.