\label{doc_tutorials_storage-plugins_md_md_doc_tutorials_storage_plugins}%
\Hypertarget{doc_tutorials_storage-plugins_md_md_doc_tutorials_storage_plugins}%
 The \mbox{\hyperlink{doc_tutorials_plugins_md}{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


\begin{DoxyItemize}
\item \mbox{\hyperlink{doc_tutorials_arrays_md}{arrays}}, and
\item \mbox{\hyperlink{doc_dev_metadata_md}{metadata}},
\end{DoxyItemize}

takes more work. Before you continue with this text, please make sure that you read all of the linked documents above.\hypertarget{doc_tutorials_storage-plugins_md_autotoc_md3689}{}\doxysection{Don’t Add Additional Keys}\label{doc_tutorials_storage-plugins_md_autotoc_md3689}
One common problem of storage plugins is, that they store too many keys. For example, if the user adds the keys


\begin{DoxyItemize}
\item {\ttfamily user\+:/tests/storage/root} and
\item {\ttfamily user\+:/tests/storage/root/level1/level2/level3},
\end{DoxyItemize}

then your plugin should only store those two keys. {\bfseries{Do not}} add the keys


\begin{DoxyItemize}
\item {\ttfamily user\+:/tests/storage/root/level1}, or
\item {\ttfamily user\+:/tests/storage/root/level1/level2}
\end{DoxyItemize}

to the key set. One plugin that handles this situation properly is \mbox{\hyperlink{md_src_plugins_yamlcpp_README_src_plugins_yamlcpp_README_md}{YAML CPP}}, as the following \href{https://master.libelektra.org/tests/shell/shell_recorder/tutorial_wrapper}{\texttt{ Markdown Shell Recorder}} test shows\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{\# Mount plugin}
\DoxyCodeLine{sudo kdb mount config.yaml user:/tests/storage yamlcpp}
\DoxyCodeLine{}
\DoxyCodeLine{\# Add key-\/value pairs}
\DoxyCodeLine{kdb set user:/tests/storage/root 🐓}
\DoxyCodeLine{kdb set user:/tests/storage/root/level1/level2/level3 🐣}
\DoxyCodeLine{}
\DoxyCodeLine{\# Make sure that YAML CPP did not store any additional keys}
\DoxyCodeLine{kdb ls user:/tests/storage/root}
\DoxyCodeLine{\#> user:/tests/storage/root}
\DoxyCodeLine{\#> user:/tests/storage/root/level1/level2/level3}
\DoxyCodeLine{}
\DoxyCodeLine{\# Undo modifications to the key database}
\DoxyCodeLine{kdb rm -\/r user:/tests/storage}
\DoxyCodeLine{sudo kdb umount user:/tests/storage}

\end{DoxyCode}


. For more information on why we allow “holes” in the hierarchy, please take a look \mbox{\hyperlink{doc_decisions_holes_md}{here}}.\hypertarget{doc_tutorials_storage-plugins_md_autotoc_md3690}{}\doxysection{Differentiate Between Empty Keys and Keys Containing an Empty String}\label{doc_tutorials_storage-plugins_md_autotoc_md3690}
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 {\ttfamily 0} inside textual data. Binary data does not have this limitation.

The simplest textual data is the empty string ({\ttfamily \char`\"{}\char`\"{}} = {\ttfamily 0}) and has length 1, while the simplest binary data stores nothing at all and therefore has length 0. In the {\ttfamily kdb} utility you can disambiguate between these value by checking for the \mbox{\hyperlink{doc_help_elektra-metadata_md}{metakey \`{}binary\`{}}}. The following \href{https://master.libelektra.org/tests/shell/shell_recorder/tutorial_wrapper}{\texttt{ Markdown Shell Recorder}} test shows how a storage plugin should handle empty values.


\begin{DoxyCode}{0}
\DoxyCodeLine{\# Mount plugin}
\DoxyCodeLine{sudo kdb mount config.yaml user:/tests/storage yamlcpp}
\DoxyCodeLine{}
\DoxyCodeLine{kdb set user:/tests/storage/empty ''}
\DoxyCodeLine{\#> Create a new key user:/tests/storage/empty with string "{}"{}}
\DoxyCodeLine{kdb get user:/tests/storage/empty}
\DoxyCodeLine{\#>}
\DoxyCodeLine{kdb meta-\/ls user:/tests/storage/empty}
\DoxyCodeLine{\#>}
\DoxyCodeLine{}
\DoxyCodeLine{\# Undo modifications to the key database}
\DoxyCodeLine{kdb rm -\/r user:/tests/storage}
\DoxyCodeLine{sudo kdb umount user:/tests/storage}

\end{DoxyCode}
\hypertarget{doc_tutorials_storage-plugins_md_autotoc_md3691}{}\doxysection{Convert Boolean Data}\label{doc_tutorials_storage-plugins_md_autotoc_md3691}
Elektra uses \mbox{\hyperlink{doc_decisions_boolean_md}{\`{}0\`{} and \`{}1\`{} to represent binary data}}. A storage plugin that uses other values (e.\+g. {\ttfamily false} and {\ttfamily true}) needs to convert these values to {\ttfamily 0} and {\ttfamily 1}. The \href{https://master.libelektra.org/tests/shell/shell_recorder/tutorial_wrapper}{\texttt{ Markdown Shell Recorder}} test below shows that \mbox{\hyperlink{md_src_plugins_yamlcpp_README_src_plugins_yamlcpp_README_md}{YAML CPP}} handles the conversion from and to \href{https://yaml.org/spec/1.2/spec.html\#id2803629}{\texttt{ YAML’s boolean type}} properly. In the test we also use the \mbox{\hyperlink{md_src_plugins_type_README_src_plugins_type_README_md}{\`{}type\`{} plugin}} to makes sure that YAML CPP interacts correctly with this essential plugin.


\begin{DoxyCode}{0}
\DoxyCodeLine{\# Mount plugin}
\DoxyCodeLine{sudo kdb mount config.yaml user:/tests/storage yamlcpp type}
\DoxyCodeLine{}
\DoxyCodeLine{kdb set user:/tests/storage/bool/value true}
\DoxyCodeLine{kdb meta-\/set user:/tests/storage/bool/value type boolean}
\DoxyCodeLine{kdb get user:/tests/storage/bool/value}
\DoxyCodeLine{\#> 1}
\DoxyCodeLine{}
\DoxyCodeLine{kdb set user:/tests/storage/bool/value 1}
\DoxyCodeLine{kdb get user:/tests/storage/bool/value}
\DoxyCodeLine{\#> 1}
\DoxyCodeLine{}
\DoxyCodeLine{kdb set user:/tests/storage/bool/value false}
\DoxyCodeLine{kdb get user:/tests/storage/bool/value}
\DoxyCodeLine{\#> 0}
\DoxyCodeLine{}
\DoxyCodeLine{kdb set user:/tests/storage/bool/value 'non boolean'}
\DoxyCodeLine{\# RET: 5}
\DoxyCodeLine{}
\DoxyCodeLine{kdb get user:/tests/storage/bool/value}
\DoxyCodeLine{\#> 0}
\DoxyCodeLine{}
\DoxyCodeLine{\# Undo modifications to the key database}
\DoxyCodeLine{kdb rm -\/r user:/tests/storage}
\DoxyCodeLine{sudo kdb umount user:/tests/storage}

\end{DoxyCode}
\hypertarget{doc_tutorials_storage-plugins_md_autotoc_md3692}{}\doxysection{Support Values Inside Non-\/\+Leaf Keys}\label{doc_tutorials_storage-plugins_md_autotoc_md3692}
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\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{user:/directory}
\DoxyCodeLine{user:/directory/leaf1}
\DoxyCodeLine{user:/directory/leaf2}
\DoxyCodeLine{user:/leaf3}

\end{DoxyCode}


, all keys at the bottom of the hierarchy\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{        user}
\DoxyCodeLine{      /      \(\backslash\)}
\DoxyCodeLine{  directory  leaf3}
\DoxyCodeLine{   /     \(\backslash\)}
\DoxyCodeLine{leaf1   leaf2}

\end{DoxyCode}


, such as


\begin{DoxyItemize}
\item {\ttfamily user\+:/directory/leaf1}
\item {\ttfamily user\+:/directory/leaf2}
\item {\ttfamily user\+:/leaf3}
\end{DoxyItemize}

are called leaf keys, while {\ttfamily user\+:/directory} is a directory key. Plugins such as \mbox{\hyperlink{md_src_plugins_yajl_README_src_plugins_yajl_README_md}{YAJL}} or \mbox{\hyperlink{md_src_plugins_yamlcpp_README_src_plugins_yamlcpp_README_md}{YAML CPP}} will not be able to store data in the key with the name {\ttfamily user\+:/directory} directly. To work around this issue these plugin use the \mbox{\hyperlink{md_src_plugins_directoryvalue_README_src_plugins_directoryvalue_README_md}{Directory Value plugin}}. In the Read\+Me of the \href{https://www.libelektra.org/plugins/directoryvalue}{\texttt{ Directory Value plugin}} and \href{https://www.libelektra.org/plugins/yamlcpp}{\texttt{ YAML CPP}} you will find more information about this issue, and how to handle it.

The following Markdown Shell Recorder test shows {\bfseries{the proper behavior}}\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{\# Mount plugin}
\DoxyCodeLine{sudo kdb mount config.yaml user:/tests/storage yamlcpp}
\DoxyCodeLine{}
\DoxyCodeLine{\# Add key-\/value pair (leaf key)}
\DoxyCodeLine{kdb set user:/tests/storage/root 🐓}
\DoxyCodeLine{\# Since we add a key below `user:/tests/storage/root`, the key}
\DoxyCodeLine{\# `user:/tests/storage/root` turns from a leaf key to a directory key.}
\DoxyCodeLine{kdb set user:/tests/storage/root/level1/level2/level3 🐣}
\DoxyCodeLine{}
\DoxyCodeLine{\# Make sure that the directory key still stores the correct value}
\DoxyCodeLine{kdb get user:/tests/storage/root}
\DoxyCodeLine{\#> 🐓}
\DoxyCodeLine{}
\DoxyCodeLine{\# Check the value of the leaf key}
\DoxyCodeLine{kdb get user:/tests/storage/root/level1/level2/level3}
\DoxyCodeLine{\#> 🐣}
\DoxyCodeLine{}
\DoxyCodeLine{\# Undo modifications to the key database}
\DoxyCodeLine{kdb rm -\/r user:/tests/storage}
\DoxyCodeLine{sudo kdb umount user:/tests/storage}

\end{DoxyCode}


. To make sure that your storage plugin works correctly, please just replace {\ttfamily yamlcpp} with the name of your plugin and verify that the test above still works.\hypertarget{doc_tutorials_storage-plugins_md_autotoc_md3693}{}\doxysection{Support Array And Non-\/\+Array Data Properly}\label{doc_tutorials_storage-plugins_md_autotoc_md3693}
You already learned about the array syntax and the mandatory {\ttfamily array} metakey in the \mbox{\hyperlink{doc_tutorials_arrays_md}{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\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{user:/tests/storage/array}
\DoxyCodeLine{user:/tests/storage/array/\#0}
\DoxyCodeLine{user:/tests/storage/array/\#1}
\DoxyCodeLine{user:/tests/storage/map}
\DoxyCodeLine{user:/tests/storage/map/\#0}
\DoxyCodeLine{user:/tests/storage/map/\#1}

\end{DoxyCode}


. If we assume that only {\ttfamily user\+:/tests/storage/array} stores the metakey {\ttfamily array}, then the keys


\begin{DoxyItemize}
\item {\ttfamily user\+:/tests/storage/array/\#0}, and
\item {\ttfamily user\+:/tests/storage/array/\#1}
\end{DoxyItemize}

represent array elements, while


\begin{DoxyItemize}
\item {\ttfamily user\+:/tests/storage/map/\#0}, and
\item {\ttfamily user\+:/tests/storage/map/\#1}
\end{DoxyItemize}

are normal key-\/value pairs. The following example shows that the storage plugin \href{https://www.libelektra.org/plugins/yamlcpp}{\texttt{ YAML CPP}} handles this situation properly\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{\# Mount plugin}
\DoxyCodeLine{sudo kdb mount config.yaml user:/tests/storage yamlcpp}
\DoxyCodeLine{}
\DoxyCodeLine{\# Create an array containing two elements}
\DoxyCodeLine{kdb meta-\/set user:/tests/storage/array array ''}
\DoxyCodeLine{kdb set user:/tests/storage/array/\#0 one}
\DoxyCodeLine{kdb set user:/tests/storage/array/\#1 two}
\DoxyCodeLine{}
\DoxyCodeLine{\# The array parent key stores the basename of the last element}
\DoxyCodeLine{kdb meta-\/get user:/tests/storage/array array}
\DoxyCodeLine{\#> \#1}
\DoxyCodeLine{}
\DoxyCodeLine{\# If you do not add the metakey `array`, then keys}
\DoxyCodeLine{\# containing array syntax `\#0`, `\#1`, … will not be}
\DoxyCodeLine{\# interpreted as arrays.}
\DoxyCodeLine{kdb set user:/tests/storage/map "{}"{}}
\DoxyCodeLine{kdb set user:/tests/storage/map/\#0 "{}"{}}
\DoxyCodeLine{kdb set user:/tests/storage/map/\#1 "{}"{}}
\DoxyCodeLine{kdb meta-\/get user:/tests/storage/map array}
\DoxyCodeLine{\# RET: 2}
\DoxyCodeLine{}
\DoxyCodeLine{\# Undo modifications to the key database}
\DoxyCodeLine{kdb rm -\/r user:/tests/storage}
\DoxyCodeLine{sudo kdb umount user:/tests/storage}

\end{DoxyCode}
