\label{doc_decisions_0_drafts_operation_sequences_md_md_doc_decisions_0_drafts_operation_sequences}%
\Hypertarget{doc_decisions_0_drafts_operation_sequences_md_md_doc_decisions_0_drafts_operation_sequences}%
 \hypertarget{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1776}{}\doxysection{Problem}\label{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1776}
The current public API allows various kind of sequences of {\ttfamily kdb\+Get} and {\ttfamily kdb\+Set} calls. There is no real guideline of allowed and/or prohibited sequences, other than {\ttfamily kdb\+Get} for a certain parent key must be called before {\ttfamily kdb\+Set}\+:


\begin{DoxyItemize}
\item initially after {\ttfamily kdb\+Open}
\item after conflict errors in {\ttfamily kdb\+Set}
\end{DoxyItemize}

We discovered that some sequences are currently legal but problematic for change tracking and maybe also other use cases.

Currently, notification plugins assume that a {\ttfamily kdb\+Set} operation for a certain parent key always directly follows the {\ttfamily kdb\+Get} operation for that same key. However, this is not enforced in any way within Elektra, nor is it documented that it should.

In applications, {\ttfamily kdb\+Get} and {\ttfamily kdb\+Set} of different parent keys might be interwoven in any way. This is problematic, as plugins may store the result of {\ttfamily kdb\+Get} and use the stored data in the following {\ttfamily kdb\+Set} to calculate a changeset. Plugins have to do this, as there isn\textquotesingle{}t any other Elektra-\/provided mechanism currently to do change tracking for them.

Note, that erroneous behavior only occurs if plugins are used globally, i.\+e. as {\ttfamily notification-\/send} hook plugins. If they are mounted for specific backends (via {\ttfamily kdb mount}), this behavior will not occur as plugins from different backends are isolated.\hypertarget{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1777}{}\doxysubsection{Reproducible Example}\label{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1777}
The following example will demonstrate the problematic sequence as real, runnable code. This example will show the erroneous behavior for the {\ttfamily dbus} and {\ttfamily logchange} plugins, if used as {\ttfamily notification-\/send} hooks. These both plugins just serve as a general demonstration, and there may be more plugins that do change tracking this way.

First, run some setup steps\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{\# enable the dbus plugin as a notification-\/send hook}
\DoxyCodeLine{kdb set system:/elektra/hook/notification/send/plugins/\#0 dbus}
\DoxyCodeLine{}
\DoxyCodeLine{\# enable the logchange plugin as a notification-\/send hook}
\DoxyCodeLine{kdb set system:/elektra/hook/notification/send/plugins/\#1 logchange}
\DoxyCodeLine{}
\DoxyCodeLine{\# mount user:/a and user:/b as two backends}
\DoxyCodeLine{kdb mount a.ecf user:/a}
\DoxyCodeLine{kdb mount b.ecf user:/b}
\DoxyCodeLine{}
\DoxyCodeLine{\# populate user:/a and user:/b with values}
\DoxyCodeLine{kdb set user:/a/brightness 1}
\DoxyCodeLine{kdb set user:/a/saturation 1}
\DoxyCodeLine{kdb set user:/b/foreground 1}
\DoxyCodeLine{kdb set user:/b/background 1}

\end{DoxyCode}


Then, run the following command to monitor the notifications by the {\ttfamily dbus} plugins\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{dbus-\/monitor -\/-\/session type='signal',interface='org.libelektra'}

\end{DoxyCode}


Finally, execute the following program\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{preprocessor}{\#include <kdb.h>}}
\DoxyCodeLine{\textcolor{preprocessor}{\#include <stdio.h>}}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keywordtype}{int} \mbox{\hyperlink{testio__doc_8c_a3c04138a5bfe5d72780bb7e82a18e627}{main}} (\textcolor{keywordtype}{void})}
\DoxyCodeLine{\{}
\DoxyCodeLine{        Key * root = \mbox{\hyperlink{group__key_gad23c65b44bf48d773759e1f9a4d43b89}{keyNew}} (\textcolor{stringliteral}{"{}/"{}}, \mbox{\hyperlink{group__key_gga9b703ca49f48b482def322b77d3e6bc8aa8adb6fcb92dec58fb19410eacfdd403}{KEY\_END}});}
\DoxyCodeLine{        KDB * handle = \mbox{\hyperlink{group__kdb_ga844e1299a84c3fbf1d3a905c5c893ba5}{kdbOpen}} (NULL, root);}
\DoxyCodeLine{}
\DoxyCodeLine{        Key * keyA = \mbox{\hyperlink{group__key_gad23c65b44bf48d773759e1f9a4d43b89}{keyNew}} (\textcolor{stringliteral}{"{}user:/a"{}}, \mbox{\hyperlink{group__key_gga9b703ca49f48b482def322b77d3e6bc8aa8adb6fcb92dec58fb19410eacfdd403}{KEY\_END}});}
\DoxyCodeLine{        Key * keyB = \mbox{\hyperlink{group__key_gad23c65b44bf48d773759e1f9a4d43b89}{keyNew}} (\textcolor{stringliteral}{"{}user:/b"{}}, \mbox{\hyperlink{group__key_gga9b703ca49f48b482def322b77d3e6bc8aa8adb6fcb92dec58fb19410eacfdd403}{KEY\_END}});}
\DoxyCodeLine{}
\DoxyCodeLine{        KeySet * a = \mbox{\hyperlink{group__keyset_ga671e1aaee3ae9dc13b4834a4ddbd2c3c}{ksNew}} (0, \mbox{\hyperlink{group__keyset_ga7a28fce3773b2c873c94ac80b8b4cd54}{KS\_END}});}
\DoxyCodeLine{        KeySet * b = \mbox{\hyperlink{group__keyset_ga671e1aaee3ae9dc13b4834a4ddbd2c3c}{ksNew}} (0, \mbox{\hyperlink{group__keyset_ga7a28fce3773b2c873c94ac80b8b4cd54}{KS\_END}});}
\DoxyCodeLine{}
\DoxyCodeLine{        \mbox{\hyperlink{group__kdb_ga28e385fd9cb7ccfe0b2f1ed2f62453a1}{kdbGet}} (handle, a, keyA);  \textcolor{comment}{// (A)}}
\DoxyCodeLine{        \mbox{\hyperlink{group__kdb_ga28e385fd9cb7ccfe0b2f1ed2f62453a1}{kdbGet}} (handle, b, keyB);  \textcolor{comment}{// (B)}}
\DoxyCodeLine{}
\DoxyCodeLine{        \textcolor{comment}{// we need to change *something*, otherwise the backend would assume nothing changed}}
\DoxyCodeLine{        \textcolor{comment}{// and never even execute all of kdbSet}}
\DoxyCodeLine{        \mbox{\hyperlink{group__keyset_gaa5a1d467a4d71041edce68ea7748ce45}{ksAppendKey}} (a, \mbox{\hyperlink{group__key_gad23c65b44bf48d773759e1f9a4d43b89}{keyNew}} (\textcolor{stringliteral}{"{}user:/a/test"{}}, \mbox{\hyperlink{group__key_gga9b703ca49f48b482def322b77d3e6bc8ac66e4a49d09212b79f5754ca6db5bd2e}{KEY\_VALUE}}, \textcolor{stringliteral}{"{}hi"{}}, \mbox{\hyperlink{group__key_gga9b703ca49f48b482def322b77d3e6bc8aa8adb6fcb92dec58fb19410eacfdd403}{KEY\_END}}));}
\DoxyCodeLine{}
\DoxyCodeLine{        \mbox{\hyperlink{group__kdb_ga11436b058408f83d303ca5e996832bcf}{kdbSet}} (handle, a, keyA);  \textcolor{comment}{// (C)}}
\DoxyCodeLine{}
\DoxyCodeLine{        \mbox{\hyperlink{group__keyset_ga27e5c16473b02a422238c8d970db7ac8}{ksDel}} (a);}
\DoxyCodeLine{        \mbox{\hyperlink{group__keyset_ga27e5c16473b02a422238c8d970db7ac8}{ksDel}} (b);}
\DoxyCodeLine{        \mbox{\hyperlink{group__key_ga3df95bbc2494e3e6703ece5639be5bb1}{keyDel}} (keyA);}
\DoxyCodeLine{        \mbox{\hyperlink{group__key_ga3df95bbc2494e3e6703ece5639be5bb1}{keyDel}} (keyB);}
\DoxyCodeLine{        \mbox{\hyperlink{group__key_ga3df95bbc2494e3e6703ece5639be5bb1}{keyDel}} (root);}
\DoxyCodeLine{}
\DoxyCodeLine{        \mbox{\hyperlink{group__kdb_gadb54dc9fda17ee07deb9444df745c96f}{kdbClose}} (handle, 0);}
\DoxyCodeLine{        \textcolor{keywordflow}{return} 0;}
\DoxyCodeLine{\}}

\end{DoxyCode}



\begin{DoxyItemize}
\item At point {\ttfamily (A)} the plugins internally store the data below the parent {\ttfamily keyA}.
\item At point {\ttfamily (B)} the same thing happens for the data below the parent {\ttfamily keyB}. This {\bfseries{replaces}} the data from {\ttfamily (A)}.
\item At point {\ttfamily (C)} plugins that do change tracking need to generate a changeset. The changeset will be calculated between the stored data and the new data in the Key\+Set {\ttfamily a}. Because the stored data is now from {\ttfamily (B)} and {\bfseries{not}} from {\ttfamily (A)}, this changeset will be wrong. The calculation will wrongly assume everything in Key\+Set {\ttfamily b} was removed and everything in Key\+Set {\ttfamily a} is newly added.
\end{DoxyItemize}

Right after {\ttfamily (B)}, the two keysets are filled with the following values\+:

\tabulinesep=1mm
\begin{longtabu}spread 0pt [c]{*{2}{|X[-1]}|}
\hline
\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ {\ttfamily a}   }&\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ {\ttfamily b}    }\\\cline{1-2}
\endfirsthead
\hline
\endfoot
\hline
\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ {\ttfamily a}   }&\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ {\ttfamily b}    }\\\cline{1-2}
\endhead
{\ttfamily user\+:/a/brightness}   &{\ttfamily user\+:/b/background}    \\\cline{1-2}
{\ttfamily user\+:/a/saturation}   &{\ttfamily user\+:/b/foreground}   \\\cline{1-2}
\end{longtabu}


If a plugin calculates a changeset during {\ttfamily kdb\+Set} by comparing to the {\ttfamily Key\+Set} from the last {\ttfamily kdb\+Get} (as described above), the plugin will wrongly calculate the following changeset at {\ttfamily (C)}\+:

\tabulinesep=1mm
\begin{longtabu}spread 0pt [c]{*{3}{|X[-1]}|}
\hline
\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ Added Keys   }&\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ Removed Keys   }&\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ Modified Keys    }\\\cline{1-3}
\endfirsthead
\hline
\endfoot
\hline
\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ Added Keys   }&\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ Removed Keys   }&\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ Modified Keys    }\\\cline{1-3}
\endhead
{\ttfamily user\+:/a/brightness}   &{\ttfamily user\+:/b/background}   &\\\cline{1-3}
{\ttfamily user\+:/a/saturation}   &{\ttfamily user\+:/b/foreground}   &\\\cline{1-3}
{\ttfamily user\+:/a/test}   &&\\\cline{1-3}
\end{longtabu}


This is obviously wrong. Looking at the example above, the changeset should only contain {\ttfamily user\+:/a/test}, as nothing else has been changed in keyset {\ttfamily a}. So the correct changeset should look like\+:

\tabulinesep=1mm
\begin{longtabu}spread 0pt [c]{*{3}{|X[-1]}|}
\hline
\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ Added Keys   }&\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ Removed Keys   }&\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ Modified Keys    }\\\cline{1-3}
\endfirsthead
\hline
\endfoot
\hline
\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ Added Keys   }&\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ Removed Keys   }&\PBS\centering \cellcolor{\tableheadbgcolor}\textbf{ Modified Keys    }\\\cline{1-3}
\endhead
{\ttfamily user\+:/a/test}   &&\\\cline{1-3}
\end{longtabu}


The erroneous behavior can be noticed by the output of {\ttfamily dbus-\/monitor}\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{signal time=1666993066.749997 sender=:1.364 -\/> destination=(null destination) serial=2 path=/org/libelektra/configuration; interface=org.libelektra; member=KeyAdded}
\DoxyCodeLine{   string "{}user:/a/brightness"{}}
\DoxyCodeLine{signal time=1666993066.750161 sender=:1.364 -\/> destination=(null destination) serial=3 path=/org/libelektra/configuration; interface=org.libelektra; member=KeyAdded}
\DoxyCodeLine{   string "{}user:/a/saturation"{}}
\DoxyCodeLine{signal time=1666993066.750551 sender=:1.364 -\/> destination=(null destination) serial=4 path=/org/libelektra/configuration; interface=org.libelektra; member=KeyAdded}
\DoxyCodeLine{   string "{}user:/a/test"{}}
\DoxyCodeLine{signal time=1666993066.750628 sender=:1.364 -\/> destination=(null destination) serial=5 path=/org/libelektra/configuration; interface=org.libelektra; member=KeyDeleted}
\DoxyCodeLine{   string "{}user:/b/background"{}}
\DoxyCodeLine{signal time=1666993066.750866 sender=:1.364 -\/> destination=(null destination) serial=6 path=/org/libelektra/configuration; interface=org.libelektra; member=KeyDeleted}
\DoxyCodeLine{   string "{}user:/b/foreground"{}}

\end{DoxyCode}


The same behavior is present in the {\ttfamily logchange} plugin. Notice its output onto {\ttfamily stdout}\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{added key: user:/a/brightness}
\DoxyCodeLine{added key: user:/a/saturation}
\DoxyCodeLine{added key: user:/a/test}
\DoxyCodeLine{removed key: user:/b/background}
\DoxyCodeLine{removed key: user:/b/foreground}

\end{DoxyCode}


As can be seen, the change tracking within the {\ttfamily dbus} and {\ttfamily logchange} plugins wrongly calculates everything below {\ttfamily user\+:/a} are new keys that have been added, and everything below {\ttfamily user\+:/b} was removed.\hypertarget{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1778}{}\doxysection{Constraints}\label{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1778}

\begin{DoxyEnumerate}
\item As far as possible, we must check for illegal sequences and raise an error when an illegal sequence occurs
\end{DoxyEnumerate}\hypertarget{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1779}{}\doxysection{Assumptions}\label{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1779}
1. 2. 3.\hypertarget{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1780}{}\doxysection{Considered Alternatives}\label{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1780}

\begin{DoxyEnumerate}
\item Document which sequences are allowed without raising errors in all illegal cases. Least-\/effort approach, but at least offers some transparency for developers. Developers utilizing Elektra can still ignore it, and may cause problems in certain setups without knowing.

(Violates constraint 1)
\item Enforce that the {\ttfamily parent\+Key} used in {\ttfamily kdb\+Set} is below the one used in the last {\ttfamily kdb\+Get}. If this is not the case, {\ttfamily kdb\+Set} will abort and report an error in {\ttfamily parent\+Key}. Developers might still wrongly mix the sequences, but they will get an error and have to fix it.
\begin{DoxyItemize}
\item Adding a {\ttfamily Key $\ast$ last\+Get\+Parent} to {\ttfamily struct \+\_\+\+KDB}
\item Doing {\ttfamily key\+Copy (handle-\/$>$last\+Get\+Parent, parent\+Key, KEY\+\_\+\+CP\+\_\+\+NAME)} in {\ttfamily kdb\+Get}
\item And checking {\ttfamily key\+Is\+Same\+Or\+Below (handle-\/$>$last\+Get\+Parent, parent\+Key) == 1} in {\ttfamily kdb\+Set}
\end{DoxyItemize}
\end{DoxyEnumerate}


\begin{DoxyCode}{0}
\DoxyCodeLine{KDB * \mbox{\hyperlink{namespacekdb}{kdb}} = ...;}
\DoxyCodeLine{}
\DoxyCodeLine{Key * keyA = ...;}
\DoxyCodeLine{Key * keyB = ...;}
\DoxyCodeLine{}
\DoxyCodeLine{KeySet * a = ...;}
\DoxyCodeLine{KeySet * b = ...;}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{comment}{// These sequences will work fine}}
\DoxyCodeLine{assert (\mbox{\hyperlink{group__kdb_ga28e385fd9cb7ccfe0b2f1ed2f62453a1}{kdbGet}} (\mbox{\hyperlink{namespacekdb}{kdb}}, a, keyA) == 0);}
\DoxyCodeLine{assert (\mbox{\hyperlink{group__kdb_ga11436b058408f83d303ca5e996832bcf}{kdbSet}} (\mbox{\hyperlink{namespacekdb}{kdb}}, a, keyA) == 0);}
\DoxyCodeLine{assert (\mbox{\hyperlink{group__kdb_ga28e385fd9cb7ccfe0b2f1ed2f62453a1}{kdbGet}} (\mbox{\hyperlink{namespacekdb}{kdb}}, b, keyB) == 0);}
\DoxyCodeLine{assert (\mbox{\hyperlink{group__kdb_ga11436b058408f83d303ca5e996832bcf}{kdbSet}} (\mbox{\hyperlink{namespacekdb}{kdb}}, b, keyB) == 0);}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{comment}{// These will not}}
\DoxyCodeLine{assert (\mbox{\hyperlink{group__kdb_ga28e385fd9cb7ccfe0b2f1ed2f62453a1}{kdbGet}} (\mbox{\hyperlink{namespacekdb}{kdb}}, a, keyA) == 0);}
\DoxyCodeLine{assert (\mbox{\hyperlink{group__kdb_ga28e385fd9cb7ccfe0b2f1ed2f62453a1}{kdbGet}} (\mbox{\hyperlink{namespacekdb}{kdb}}, b, keyB) == 0);}
\DoxyCodeLine{assert (\mbox{\hyperlink{group__kdb_ga11436b058408f83d303ca5e996832bcf}{kdbSet}} (\mbox{\hyperlink{namespacekdb}{kdb}}, a, keyA) == -\/1); \textcolor{comment}{// Error! keyA is different from last used key in kdbGet (keyB)}}

\end{DoxyCode}



\begin{DoxyEnumerate}
\item Enforce that {\ttfamily ks} used in {\ttfamily kdb\+Set} is the same as in the last {\ttfamily kdb\+Get} Similar to (2), but we check for the pointer of the {\ttfamily Key\+Set} instead of having a copy of the parent key, which saves some memory.
\begin{DoxyItemize}
\item Adding a {\ttfamily Key\+Set $\ast$ last\+Get\+Ks} to {\ttfamily struct \+\_\+\+KDB}
\item Doing {\ttfamily handle-\/$>$last\+Get\+Ks = ks} in {\ttfamily kdb\+Get}
\item And checking {\ttfamily last\+Get\+Ks == ks} in {\ttfamily kdb\+Set}
\end{DoxyItemize}
\item Change the API so that a single instance of KDB can only contain a single instance of a {\ttfamily Key\+Set}. This solution completely eliminates problematic sequences.
\end{DoxyEnumerate}


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{comment}{// same as before but uses handle-\/>data instead of the ks argument}}
\DoxyCodeLine{\textcolor{keywordtype}{int} \mbox{\hyperlink{group__kdb_ga28e385fd9cb7ccfe0b2f1ed2f62453a1}{kdbGet}} (KDB * handle, Key * parentKey);}
\DoxyCodeLine{\textcolor{comment}{// same as before but uses handle-\/>data instead of the ks argument}}
\DoxyCodeLine{\textcolor{keywordtype}{int} \mbox{\hyperlink{group__kdb_ga11436b058408f83d303ca5e996832bcf}{kdbSet}} (KDB * handle, Key * parentKey);}
\DoxyCodeLine{}
\DoxyCodeLine{KeySet * kdbData (KDB * handle) \{}
\DoxyCodeLine{    \textcolor{keywordflow}{return} handle-\/>data;}
\DoxyCodeLine{\}}

\end{DoxyCode}



\begin{DoxyEnumerate}
\item Allow arbitrary sequences and let each plugin deal with it on a case-\/by-\/case basis. This alternative would put most of the burden onto the plugin authors. Depending on what the plugins do, every plugin may also need to deep-\/dup every keyset of every parent it ever receives via {\ttfamily kdb\+Get}. This will increase memory usage. However, this could be paired with the \mbox{\hyperlink{doc_decisions_4_decided_internal_cache_md}{COW semantics}} so the memory toll would not be that big of a deal. The biggest problem with this approach would be the unnecessary duplication of the non-\/trivial change tracking algorithm.
\item Don\textquotesingle{}t restrict sequences further and provide a common framework to handle change tracking correctly.

As the problem has only been observed with plugins doing their own change tracking, we could provide a general change tracking framework within Elektra. This way, we have only one such algorithm in a central place, and plugin authors don\textquotesingle{}t have to think about the sequences their plugins are called by developers.

This approach can also be paired with \mbox{\hyperlink{doc_decisions_4_decided_internal_cache_md}{COW semantics}}, so that memory toll will be kept low. A separate \mbox{\hyperlink{doc_decisions_1_problem_clear_change_tracking_md}{decision for change tracking}} is currently in progress.

Should we observe this problem with use cases other than change tracking, we can provide general frameworks for those too.
\end{DoxyEnumerate}\hypertarget{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1781}{}\doxysection{Decision}\label{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1781}
\hypertarget{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1782}{}\doxysection{Rationale}\label{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1782}
\hypertarget{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1783}{}\doxysection{Implications}\label{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1783}

\begin{DoxyItemize}
\item 
\item 
\item 
\end{DoxyItemize}\hypertarget{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1784}{}\doxysection{Related Decisions}\label{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1784}

\begin{DoxyItemize}
\item \mbox{\hyperlink{doc_decisions_1_problem_clear_change_tracking_md}{Change Tracking}}
\item \mbox{\hyperlink{doc_decisions_4_decided_internal_cache_md}{Internal Key\+Set Cache}}
\item \mbox{[}\mbox{]}(doc\+\_\+decisions\+\_\+0\+\_\+drafts\+\_\+\+\_\+\+README\+\_\+md)
\end{DoxyItemize}\hypertarget{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1785}{}\doxysection{Notes}\label{doc_decisions_0_drafts_operation_sequences_md_autotoc_md1785}

\begin{DoxyItemize}
\item Issue \href{https://issues.libelektra.org/4514}{\texttt{ \#4514}} uncovered a problem in the current change tracking approach relating to sequences of {\ttfamily kdb\+Get} and {\ttfamily kdb\+Set}
\item Issue \href{https://issues.libelektra.org/4520}{\texttt{ \#4512}} explored some possible solutions 
\end{DoxyItemize}