\subsection*{Issue}

Projects usually do not want to use low-\/level A\+P\+Is. {\ttfamily K\+DB} and {\ttfamily Key\+Set} is useful for plugins and to implement A\+P\+Is but not to be directly used in applications.

\subsection*{Constraints}


\begin{DoxyEnumerate}
\item should be extremely easy to get started with
\item should be very hard to use it wrong
\item all high-\/level A\+P\+Is should work together very nicely
\begin{DoxyItemize}
\item same principles
\item same A\+PI style
\item same error handling
\item can be arbitrarily intermixed
\end{DoxyItemize}
\end{DoxyEnumerate}

\subsection*{Assumptions}


\begin{DoxyItemize}
\item Thread-\/safety\+: a handle is the accepted better solution than having to care about whether it is reentrant, thread-\/safe, ...
\item assumes that spec is available (either by compiled-\/in {\ttfamily Key\+Set} or exit after elektra\+Open)
\item many projects do not care about some limitations (no binary, no metadata) but prefer a straightforward way to get/set config
\item When people hit limitations they fall back to direct use of $^\wedge$\+Key\+Set$^\wedge$, $^\wedge$\+Key$^\wedge$
\end{DoxyItemize}

\subsection*{Considered Alternatives}


\begin{DoxyItemize}
\item storing errors in the handle\+:
\begin{DoxyItemize}
\item Maintenance problem if error handling is added later
\end{DoxyItemize}
\item only provide {\ttfamily K\+DB}, applications need to implement their own A\+P\+Is\+:
\begin{DoxyItemize}
\item reduces consistency of how the A\+PI is used
\end{DoxyItemize}
\item only provide generated A\+PI
\item assume type as {\ttfamily string} if not given
\item force {\ttfamily default} to be part of parameters
\end{DoxyItemize}

\subsection*{Decision}

We provide 3 high-\/level C A\+P\+Is\+:


\begin{DoxyEnumerate}
\item libelektra-\/highlevel (generic key-\/value getter/setter)
\item libelektra-\/hierarchy (generic hierarchical getter/setter in a tree)
\item code generator (specified key-\/value getter/setter with function names, Key\+Sets, or strings from specifications)
\end{DoxyEnumerate}

Furthermore, we will\+:


\begin{DoxyItemize}
\item have as goal that no errors in specified keys with default can occur
\item if you use {\ttfamily elektra\+Get\+Type} before getting a value, no error can occur when getting it later
\item enforce that every key has a type
\item use {\ttfamily elektra\+Error} as extra parameter (for prototyping and examples you can pass 0)
\end{DoxyItemize}

\subsubsection*{Basic}

(needed for lcdproc)


\begin{DoxyCode}
Elektra * elektraOpen (\textcolor{keyword}{const} \textcolor{keywordtype}{char} * application, \textcolor{keyword}{const} KeySet * defaultSpec, ElektraError ** error);
\textcolor{keywordtype}{void} elektraReload (Elektra * handle, ElektraError ** error);
\textcolor{keywordtype}{void} elektraParse (Elektra * handle, \textcolor{keywordtype}{int} argc, \textcolor{keywordtype}{char} ** argv, \textcolor{keywordtype}{char} ** environ); \textcolor{comment}{// pass environ?}
\textcolor{keywordtype}{void} elektraDefault (Elektra * handle);
\textcolor{keywordtype}{void} elektraClose (Elektra * handle);
\end{DoxyCode}


If {\ttfamily N\+U\+LL} is passed as error, the A\+PI will try to continue if possible. On fatal errors, i.\+e. on A\+PI misuse or when it is not safe to use the handle afterwards, the A\+PI aborts with {\ttfamily exit}.

If you want to avoid {\ttfamily elektra\+Open} or later {\ttfamily elektra\+Reload} to fail, make sure to use pass a {\ttfamily Key\+Set}, that has your whole specification included (and defaults everywhere needed).

\subsubsection*{Error Handling}


\begin{DoxyCode}
\textcolor{keyword}{const} \textcolor{keywordtype}{char} * elektraErrorMessage (\textcolor{keyword}{const} ElektraError * error);
kdb\_boolean\_t elektraErrorAbort (\textcolor{keyword}{const} ElektraError * error);
\textcolor{keywordtype}{void} elektraErrorFree (ElektraError * error)
\end{DoxyCode}


{\ttfamily elektra\+Error\+Abort} tells you if you need to quit your application because of severe issues that are permanent. Otherwise, developers can just print the message and continue. (Default settings might be used then.)

\subsubsection*{Simple Getters}

(most of them needed for lcdproc)


\begin{DoxyCode}
\textcolor{comment}{// getters}
\textcolor{keyword}{const} \textcolor{keywordtype}{char} * elektraGetString (Elektra * elektra, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
kdb\_boolean\_t elektraGetBoolean (Elektra * elektra, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
kdb\_char\_t elektraGetChar (Elektra * elektra, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
kdb\_octet\_t elektraGetOctet (Elektra * elektra, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
kdb\_short\_t elektraGetShort (Elektra * elektra, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
kdb\_unsigned\_short\_t elektraGetUnsignedShort (Elektra * elektra, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
kdb\_long\_t elektraGetLong (Elektra * elektra, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
kdb\_unsigned\_long\_t elektraGetUnsignedLong (Elektra * elektra, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
kdb\_long\_long\_t elektraGetLongLong (Elektra * elektra, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
kdb\_unsigned\_long\_long\_t elektraGetUnsignedLongLong (Elektra * elektra, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
kdb\_float\_t elektraGetFloat (Elektra * elektra, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
kdb\_double\_t elektraGetDouble (Elektra * elektra, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
kdb\_long\_double\_t elektraGetLongDouble (Elektra * elektra, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
\end{DoxyCode}


\subsubsection*{Arrays}

(needed for lcdproc)


\begin{DoxyCode}
\textcolor{keywordtype}{size\_t} elektraArraySize (Elektra * handle, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name);
kdb\_long\_t elektraArrayLong (Elektra * handle, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name, \textcolor{keywordtype}{size\_t} elem);
\textcolor{comment}{// same types as above}
\end{DoxyCode}


\subsection*{Code-\/\+Generation}

(needed for lcdproc)

For every entry in the specification, such as\+:


\begin{DoxyCode}
[key]
default=10
type=long
\end{DoxyCode}


The code generator yields\+:


\begin{DoxyItemize}
\item {\ttfamily kdb\+\_\+long\+\_\+t elektra\+Get\+Key(\+Elektra $\ast$ handle);}
\item a {\ttfamily Key\+Set} to be used as default\+Spec
\item {\ttfamily elektra\+Open\+Org\+Application()}
\end{DoxyItemize}

All spec keys together are part of the Key\+Set that is automatically applied on failures in lower-\/level calls when using\+: {\ttfamily elektra\+Open\+Org\+Application()} where {\ttfamily Org\+Application} is the org and application name.

\subsection*{Enum}

In the specification\+:


\begin{DoxyCode}
[server/serverScreen]
check/enum/#0=off
check/enum/#1=on
check/enum/#2=blank
\end{DoxyCode}


The code generator emits\+:


\begin{DoxyCode}
typedef enum
\{
        ELEKTRA\_ENUM\_SERVER\_SERVERSCREEN\_OFF = 0,
        ELEKTRA\_ENUM\_SERVER\_SERVERSCREEN\_ON = 1,
        ELEKTRA\_ENUM\_SERVER\_SERVERSCREEN\_BLANK = 2,
\} ElektraEnumScreen;
\end{DoxyCode}


Which can be used as\+:


\begin{DoxyCode}
ElektraEnumScreen elektraGetEnum(...);
\end{DoxyCode}



\begin{DoxyCode}
[server]
define/type/serverscreenstatus
define/type/serverscreenstatus/check/enum/#0=off
define/type/serverscreenstatus/check/enum/#1=on
define/type/serverscreenstatus/check/enum/#2=blank
\end{DoxyCode}


Then we can define\+:


\begin{DoxyCode}
[server/serverScreen]
type = serverscreenstatus
\end{DoxyCode}



\begin{DoxyCode}
typedef enum
\{
        ELEKTRA\_ENUM\_SERVER\_SERVERSCREEN\_OFF = 0,
        ELEKTRA\_ENUM\_SERVER\_SERVERSCREEN\_ON = 1,
        ELEKTRA\_ENUM\_SERVER\_SERVERSCREEN\_BLANK = 2,
\} ElektraEnumScreenStatus;
\end{DoxyCode}


\subsection*{Extensions}

(not needed for lcdproc)


\begin{DoxyCode}
\textcolor{comment}{// gives you a duplicate for other threads (same application+version), automatically calls
       elektraErrorClear}
Elektra * elektraDup (Elektra * handle);

\textcolor{keyword}{enum} ElektraType
\{
        ELEKTRA\_TYPE\_BOOLEAN,
        ELEKTRA\_TYPE\_NONE,
        ...
\};

ElektraType elektraGetType (Elektra * handle);

KDB * elektraGetKDB (Elektra * handle);
KeySet * elektraGetKeySet (Elektra * handle, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * cutkey);
KeySet * elektraGetKeyHierarchy (Elektra * handle, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * cutkey);

\textcolor{comment}{// enum, int, tristate}
\textcolor{keywordtype}{void} elektraSetInt (Elektra * handle, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name, \textcolor{keywordtype}{int} value);
\end{DoxyCode}


\subsubsection*{Lower-\/level type A\+PI}

(not needed for lcdproc)


\begin{DoxyCode}
\textcolor{comment}{// will be used internally in elektraGetInt, are for other APIs useful, too}
\textcolor{keywordtype}{int} keyGetInt (Key * key);

\textcolor{comment}{// and so on}
\end{DoxyCode}


\subsubsection*{recursive Key\+Hierarchy}

(needed for lcdproc in a client)

A tree of {\ttfamily Key\+Hierarchy} elements, each element has a {\ttfamily Key} embedded. Can be transformed from/to keysets. With iterators to iterate over sub {\ttfamily Key\+Hierarchy} elements.


\begin{DoxyCode}
keyhHasChildren (KeyHierarchy * kh);

\textcolor{comment}{// TODO, add rest of API}
\end{DoxyCode}


\subsubsection*{todos}


\begin{DoxyItemize}
\item const char $\ast$ vs. string type?
\item merging on conflicts? (maybe libelektra-\/tools dynamically loaded?)
\item some A\+PI calls have a question mark next to it
\end{DoxyItemize}

\subsection*{Argument}


\begin{DoxyEnumerate}
\item Very easy to get started with, to get a key needs 3 lines of codes\+:
\end{DoxyEnumerate}


\begin{DoxyCode}
Elektra *handle = elektraOpen (\textcolor{stringliteral}{"/sw/elektra/kdb/#0/current"}, 0);
printf (\textcolor{stringliteral}{"number /mykey is "} ELEKTRA\_LONG\_F \textcolor{stringliteral}{"\(\backslash\)n"}, elektraGetLong (handle, \textcolor{stringliteral}{"/mykey"}));
elektraClose (handle);
\end{DoxyCode}



\begin{DoxyEnumerate}
\item It is also easier to get started with writing new bindings.
\item User can combine the different A\+P\+Is.
\end{DoxyEnumerate}

\subsection*{Implications}

\subsection*{Related decisions}

\subsection*{Notes}

\href{https://issues.libelektra.org/1359}{\tt https\+://issues.\+libelektra.\+org/1359} 