\subsection*{Preface}

{\bfseries Not all of the features described in this document are implemented yet.}

Development state\+:


\begin{DoxyItemize}
\item \mbox{[}x\mbox{]} internalnotification plugin (support for int and callback)
\item \mbox{[}x\mbox{]} notification wrapper (support for int and callback)
\item \mbox{[}X\mbox{]} transport plugin dbus
\item \mbox{[} \mbox{]} transport plugin zeromq
\item \mbox{[} \mbox{]} transport plugin redis
\item \mbox{[} \mbox{]} internalnotification plugin \& notfication wrapper (support for Elektra\textquotesingle{}s basic types)
\end{DoxyItemize}

This document explains how notifications are implemented in Elektra and how they can be used by application developers.

\subsection*{Notifications -\/ Overview \& Concept}

Elektra\textquotesingle{}s notification feature consists of several components. While sending and receiving notifications is implemented by plugins, applications use A\+P\+Is provided by wrappers in order to use different plugins.

A \href{https://doc.libelektra.org/api/current/html/group__kdbnotification.html}{\tt wrapper for notifications} provides the A\+PI for receiving and handling notifications. A \href{https://doc.libelektra.org/api/current/html/group__kdbio.html}{\tt wrapper for I/O operations} allows asynchronous notification processing by compatible plugins. The I/O wrapper consists of an {\itshape interface} used by transport plugins and multiple implementations of that interface called {\itshape I/O bindings}. A I/O binding implements the actual I/O management functions for a specific I/O management library. Applications typically use one I/O binding but can also use none or multiple I/O bindings.

Transport plugins exchange notifications via different protocols like D-\/\+Bus, Redis and Zero\+MQ. For each type of transport there are two types of plugins\+: One for sending and one for receiving notifications. Developers do not interact with those plugins directly. The underlying transports are transparent to them. An internal-\/notification plugin implements notification handling functions and feeds back configuration changes from within the application.



When a configuration key is changed Elektra can generate change notifications that allow applications to process those changes. Developers can choose whether and how they want to receive and handle those notifications but not whether notifications are sent or which transport is used. How notifications are sent is specified in the {\itshape notification configuration} by the system operator.

\subsection*{Notification configuration}

System operators can mount the desired transport plugins and configure them (e.\+g. set channel, host, port and credentials) either globally or when mounting a configuration file.

They need to mount both sending and receiving plugins in order to use a transport.


\begin{DoxyCode}
kdb mount file.ini system/example ini dbussend dbusreceive
\end{DoxyCode}


\subsection*{How to integrate an I/O binding and send notifications asynchronously}

Developers do not need to change their programs in order to start sending notifications. However without the integration of an I/O binding notifications are sent synchronously which will block normal program execution. For programs without time constraints (e.\+g. C\+LI programs) this may not be important, but for G\+U\+Is or network services this will have negative impact.

Since many different I/O management libraries exist (e.\+g. libuv, glib or libev) the transport plugins use the I/O interface for their I/O operations. Each I/O management library needs its own I/O binding. Developers can also create their own I/O binding for the I/O management library of their choice. This is described in the last section.

Each I/O binding has its own initialization function that creates a new I/O binding and connects it to the I/O management library. For this tutorial we will assume that libuv is used. For details on how to use a specific binding please look at the bindings\textquotesingle{} R\+E\+A\+D\+M\+E.\+md in {\ttfamily src/bindings/io/$<$binding$>$}.


\begin{DoxyCode}
\textcolor{preprocessor}{#include <elektra/kdb.h>}
\textcolor{preprocessor}{#include <elektra/kdbio.h>}
\textcolor{preprocessor}{#include <elektra/kdbio\_uv.h>}
\textcolor{preprocessor}{#include <elektra/kdbnotification.h>}

\textcolor{preprocessor}{#include <uv.h>}

\textcolor{keywordtype}{void} \hyperlink{testio__doc_8c_a3c04138a5bfe5d72780bb7e82a18e627}{main} (\textcolor{keywordtype}{void})
\{
        KDB* repo;

        \textcolor{comment}{// .. open KDB}

        \textcolor{comment}{// Create libuv event loop}
        uv\_loop\_t * loop = uv\_default\_loop ();

        \textcolor{comment}{// Initialize I/O binding tied to event loop}
        \hyperlink{kdbio_8h_aabcd87b8c09d4d4c1033fc1baa417391}{ElektraIoInterface} * binding = \hyperlink{kdbio__uv_8h_a45e8a50dca7d8097bc2c38c54b49958b}{elektraIoUvNew} (loop);

  \textcolor{comment}{// Use I/O binding for our kdb instance}
  \hyperlink{group__kdbio_ga187345483bdfbb404919c6797bc2db77}{elektraIoSetBinding} (\hyperlink{namespacekdb}{kdb}, binding);

        \textcolor{comment}{// Initialize notification wrapper}
        \hyperlink{notification_8c_aeae96154abdb5fdbf1b34a01e2b23e44}{elektraNotificationOpen} (\hyperlink{namespacekdb}{kdb});

        \textcolor{comment}{// Start the event loop}
        uv\_run (loop, UV\_RUN\_DEFAULT);

        \textcolor{comment}{// Cleanup}
  \hyperlink{notification_8c_a5685dafbd4131011365628d6d9213594}{elektraNotificationClose} (\hyperlink{namespacekdb}{kdb});
  \hyperlink{io_8c_a062e9d7d5305201dfe5ba437f3f03224}{elektraIoBindingCleanup} (binding);
        uv\_loop\_close (loop);
\}

\textcolor{keywordtype}{void} someFunction (\textcolor{keywordtype}{void})
\{
        \textcolor{comment}{// notifications are sent asynchronously on kdbSet}
        \textcolor{comment}{// over configured transports using our uv event loop}
        \hyperlink{group__kdb_ga11436b058408f83d303ca5e996832bcf}{kdbSet} (repo, key, parentKey);
\}
\end{DoxyCode}


\subsection*{How to receive notifications}

We extend the example from the previous section where we already created our I/O binding and initialized the notification-\/wrapper. In order to handle change notifications a developer can either register a variable or a callback.

\subsubsection*{Register a variable}

Values of registered variables are automatically updated when the value of the assigned key has changed. In the following example we will register an integer variable\+:


\begin{DoxyCode}
KDB * repo;

\textcolor{comment}{//  ... initialization of KDB and I/O binding}

Key * key = \hyperlink{group__key_gad23c65b44bf48d773759e1f9a4d43b89}{keyNew} (\textcolor{stringliteral}{"/sw/myorg/myprogram/#0/current/value"}, \hyperlink{group__key_gga91fb3178848bd682000958089abbaf40aa8adb6fcb92dec58fb19410eacfdd403}{KEY\_END});
\textcolor{keywordtype}{int} \hyperlink{group__keyvalue_ga6f29609c5da53c6dc26a98678d5752af}{keyValue};

\textcolor{keywordtype}{int} result = \hyperlink{notification_8c_a362d557489c4199f6c765480a8a3cade}{elektraNotificationRegisterInt} (repo, key, &keyValue);
\textcolor{keywordflow}{if} (!result)
\{
        printf (\textcolor{stringliteral}{"could not register variable!\(\backslash\)n"});
        \textcolor{keywordflow}{return};
\}

\textcolor{comment}{// repeatedly print variable}
\textcolor{keywordflow}{while} (1) \{
        printf (\textcolor{stringliteral}{"value is %d\(\backslash\)n"}, keyValue);

        sleep(2);
\}
\end{DoxyCode}


After calling {\ttfamily elektra\+Notification\+Register\+Int} the variable {\ttfamily key\+Value} will be automatically updated if the key in the program above is changed by another program (e.\+g. by using the {\ttfamily kdb} C\+LI command). For automatic updates to work transport plugins have to be in place either at a mountpoint above the configuration or mounted globally.

\subsubsection*{Callbacks}

Registering a variable is suitable for programs where the key\textquotesingle{}s value is simply displayed or used repeatedly (e.\+g. by a timer or in a loop). If an initialization code needs to be redone after configuration changes (e.\+g. a value sets the number of worker threads) updating a registered variable will not suffice. For these situations a callback should be used.

The following snippet shows how a callback can be used if the value of the changed key needs further processing.


\begin{DoxyCode}
\textcolor{preprocessor}{#include <signal.h>}
\textcolor{preprocessor}{#include <stdio.h>}
\textcolor{preprocessor}{#include <string.h>}

\textcolor{comment}{// from https://en.wikipedia.org/wiki/ANSI\_escape\_code#Colors}
\textcolor{preprocessor}{#define ANSI\_COLOR\_RED                  "\(\backslash\)x1b[31m"}
\textcolor{preprocessor}{#define ANSI\_COLOR\_GREEN                "\(\backslash\)x1b[32m"}

\textcolor{keywordtype}{void} setTerminalColor (Key * color)
\{
        \textcolor{keywordtype}{char} * value = \hyperlink{group__keyvalue_ga880936f2481d28e6e2acbe7486a21d05}{keyString} (color);

        \textcolor{keywordflow}{if} (strcmp (value, \textcolor{stringliteral}{"red"}) == 0)
        \{
                printf (ANSI\_COLOR\_RED);
        \}
        \textcolor{keywordflow}{if} (strcmp (value, \textcolor{stringliteral}{"green"}) == 0)
        \{
                printf (ANSI\_COLOR\_GREEN);
        \}
\}

\textcolor{keywordtype}{int} \hyperlink{testio__doc_8c_a3c04138a5bfe5d72780bb7e82a18e627}{main} (\textcolor{keywordtype}{void})
\{
        KDB * repo;

        \textcolor{comment}{// ... initialization of KDB, I/O binding and notifications}

        Key * configBase = \hyperlink{group__key_gad23c65b44bf48d773759e1f9a4d43b89}{keyNew} (\textcolor{stringliteral}{"/sw/myorg/myprogram/#0/current"}, 
      \hyperlink{group__key_gga91fb3178848bd682000958089abbaf40aa8adb6fcb92dec58fb19410eacfdd403}{KEY\_END});
        Key * color = \hyperlink{group__key_gad23c65b44bf48d773759e1f9a4d43b89}{keyNew} (\textcolor{stringliteral}{"/sw/myorg/myprogram/#0/current/color"}, 
      \hyperlink{group__key_gga91fb3178848bd682000958089abbaf40aa8adb6fcb92dec58fb19410eacfdd403}{KEY\_END});

        \textcolor{comment}{// Retrieve key from kdb}
        KeySet * ks = \hyperlink{group__keyset_ga671e1aaee3ae9dc13b4834a4ddbd2c3c}{ksNew} (10, \hyperlink{kdbenum_8c_a7a28fce3773b2c873c94ac80b8b4cd54}{KS\_END});
        \hyperlink{group__kdb_ga28e385fd9cb7ccfe0b2f1ed2f62453a1}{kdbGet} (repo, ks, configBase);
        Key * key = \hyperlink{group__keyset_gaa34fc43a081e6b01e4120daa6c112004}{ksLookup} (ks, color, 0);
        \textcolor{keywordflow}{if} (key) \{
                \textcolor{comment}{// Initialization}
                setTerminalColor (key);
        \}

        \textcolor{comment}{// Re-Initialize on key changes}
        \textcolor{keywordtype}{int} result = \hyperlink{notification_8c_aec859714220d1e6a476910433bb77d83}{elektraNotificationRegisterCallback}(repo, color, &
      setTerminalColor);
        \textcolor{keywordflow}{if} (!result) \{
                printf (\textcolor{stringliteral}{"could not register callback!\(\backslash\)n"});
                \textcolor{keywordflow}{return} -1;
        \}

        \textcolor{comment}{// ... start loop, etc.}
\}
\end{DoxyCode}


\subsection*{How to create your own I/O Binding}

Developers can create their own bindings if the I/O management library of their choice is not supported by an existing I/O binding.

For details on see the \hyperlink{md_src_bindings_io_doc_README_src_bindings_io_doc_README_md}{example }doc\char`\"{} binding\char`\"{} or the \href{https://doc.libelektra.org/api/current/html/group__kdbio.html}{\tt A\+PI documentation}. Existing I/O bindings provide a good inspiration on how to implement a custom binding. Since a binding is generic and not application specific it is much appreciated if you contribute your I/O binding back to the Elektra project. 