LCOV - code coverage report
Current view: top level - src/libs/elektra - split.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 224 397 56.4 %
Date: 2019-09-12 12:28:41 Functions: 19 25 76.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Interna of splitting functionality.
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : #ifdef HAVE_KDBCONFIG_H
      10             : #include "kdbconfig.h"
      11             : #endif
      12             : 
      13             : #if VERBOSE && defined(HAVE_STDIO_H)
      14             : #include <stdio.h>
      15             : #endif
      16             : 
      17             : #ifdef HAVE_STDLIB_H
      18             : #include <stdlib.h>
      19             : #endif
      20             : 
      21             : #ifdef HAVE_STDARG_H
      22             : #include <stdarg.h>
      23             : #endif
      24             : 
      25             : #ifdef HAVE_CTYPE_H
      26             : #include <ctype.h>
      27             : #endif
      28             : 
      29             : #ifdef HAVE_STRING_H
      30             : #include <string.h>
      31             : #endif
      32             : 
      33             : #ifdef HAVE_ERRNO_H
      34             : #include <errno.h>
      35             : #endif
      36             : 
      37             : #include <kdbassert.h>
      38             : #include <kdberrors.h>
      39             : #include <kdbinternal.h>
      40             : 
      41             : 
      42             : /**
      43             :  * Allocates a new split object.
      44             :  *
      45             :  * Splits up a keyset into multiple keysets where each
      46             :  * of them will passed to the correct kdbSet().
      47             :  *
      48             :  * Initially the size is 0 and alloc is APPROXIMATE_NR_OF_BACKENDS.
      49             :  *
      50             :  * @return a fresh allocated split object
      51             :  * @ingroup split
      52             :  * @see splitDel()
      53             :  **/
      54       50155 : Split * splitNew (void)
      55             : {
      56       50155 :         Split * ret = elektraCalloc (sizeof (Split));
      57             : 
      58       50155 :         ret->size = 0;
      59       50155 :         ret->alloc = APPROXIMATE_NR_OF_BACKENDS;
      60             : 
      61       50155 :         ret->keysets = elektraCalloc (sizeof (KeySet *) * ret->alloc);
      62       50155 :         ret->handles = elektraCalloc (sizeof (KDB *) * ret->alloc);
      63       50155 :         ret->parents = elektraCalloc (sizeof (Key *) * ret->alloc);
      64       50155 :         ret->syncbits = elektraCalloc (sizeof (int) * ret->alloc);
      65             : 
      66       50155 :         return ret;
      67             : }
      68             : 
      69             : 
      70             : /**
      71             :  * Delete a split object.
      72             :  *
      73             :  * Will free all allocated resources of a split keyset.
      74             :  *
      75             :  * @param keysets the split object to work with
      76             :  * @ingroup split
      77             :  */
      78       50155 : void splitDel (Split * keysets)
      79             : {
      80      261224 :         for (size_t i = 0; i < keysets->size; ++i)
      81             :         {
      82      211069 :                 ksDel (keysets->keysets[i]);
      83      211069 :                 keyDecRef (keysets->parents[i]);
      84      211069 :                 keyDel (keysets->parents[i]);
      85             :         }
      86       50155 :         elektraFree (keysets->keysets);
      87       50155 :         elektraFree (keysets->handles);
      88       50155 :         elektraFree (keysets->parents);
      89       50155 :         elektraFree (keysets->syncbits);
      90       50155 :         elektraFree (keysets);
      91       50155 : }
      92             : 
      93             : /**
      94             :  * @brief Remove one part of split.
      95             :  *
      96             :  * @param split the split object to work with
      97             :  * @param where the position to cut away
      98             :  *
      99             :  * @pre where must be within the size of the split
     100             :  * @post split will be removed
     101             :  *
     102             :  * @ingroup split
     103             :  */
     104         871 : void splitRemove (Split * split, size_t where)
     105             : {
     106         871 :         ELEKTRA_ASSERT (where < split->size, "cannot remove behind size: %zu smaller than %zu", where, split->size);
     107         871 :         ksDel (split->keysets[where]);
     108         871 :         keyDel (split->parents[where]);
     109         871 :         --split->size; // reduce size
     110        3140 :         for (size_t i = where; i < split->size; ++i)
     111             :         {
     112        2269 :                 split->keysets[i] = split->keysets[i + 1];
     113        2269 :                 split->handles[i] = split->handles[i + 1];
     114        2269 :                 split->parents[i] = split->parents[i + 1];
     115        2269 :                 split->syncbits[i] = split->syncbits[i + 1];
     116             :         }
     117         871 : }
     118             : 
     119             : /**
     120             :  * Doubles the size of how many parts of keysets can be appended.
     121             :  *
     122             :  * @param split the split object to work with
     123             :  * @ingroup split
     124             :  */
     125         686 : static void splitResize (Split * split)
     126             : {
     127         686 :         split->alloc *= 2;
     128             : 
     129         686 :         elektraRealloc ((void **) &split->keysets, split->alloc * sizeof (KeySet *));
     130         686 :         elektraRealloc ((void **) &split->handles, split->alloc * sizeof (KDB *));
     131         686 :         elektraRealloc ((void **) &split->parents, split->alloc * sizeof (Key *));
     132         686 :         elektraRealloc ((void **) &split->syncbits, split->alloc * sizeof (int));
     133         686 : }
     134             : 
     135             : /**
     136             :  * Increases the size of split and appends a new empty keyset.
     137             :  *
     138             :  * Initializes the element with the given parameters
     139             :  * at size-1 to be used.
     140             :  *
     141             :  * Will automatically resize split if needed.
     142             :  *
     143             :  * @param split the split object to work with
     144             :  * @param backend the backend which should be appended
     145             :  * @param parentKey the parentKey which should be appended
     146             :  * @param syncbits the initial syncstate which should be appended
     147             :  * @ingroup split
     148             :  * @retval -1 if no split is found
     149             :  * @return the position of the new element: size-1
     150             :  */
     151      211940 : ssize_t splitAppend (Split * split, Backend * backend, Key * parentKey, int syncbits)
     152             : {
     153      211940 :         if (!split)
     154             :         {
     155             :                 /* To make test cases work & valgrind clean */
     156           0 :                 keyDel (parentKey);
     157           0 :                 return -1;
     158             :         }
     159             : 
     160      211940 :         ++split->size;
     161      211940 :         if (split->size > split->alloc) splitResize (split);
     162             : 
     163             :         // index of the new element
     164      211940 :         const int n = split->size - 1;
     165             : 
     166      211940 :         split->keysets[n] = ksNew (0, KS_END);
     167      211940 :         split->handles[n] = backend;
     168      211940 :         split->parents[n] = parentKey;
     169      211940 :         split->syncbits[n] = syncbits;
     170             : 
     171      211940 :         return n;
     172             : }
     173             : 
     174             : /**
     175             :  * Determines if the backend is already inserted or not.
     176             :  *
     177             :  * @warning If no parent Key is given, the default/root backends won't
     178             :  * be searched.
     179             :  *
     180             :  * @param split the split object to work with
     181             :  * @param backend the backend to search for
     182             :  * @param parent the key to check for domains in default/root backends.
     183             :  * @return pos of backend if it already exist
     184             :  * @retval -1 if it does not exist
     185             :  * @ingroup split
     186             :  */
     187      194189 : static ssize_t splitSearchBackend (Split * split, Backend * backend, Key * parent)
     188             : {
     189      249139 :         for (size_t i = 0; i < split->size; ++i)
     190             :         {
     191      241205 :                 if (backend == split->handles[i])
     192             :                 {
     193      188106 :                         if (test_bit (split->syncbits[i], SPLIT_FLAG_CASCADING))
     194             :                         {
     195      185470 :                                 switch (keyGetNamespace (parent))
     196             :                                 {
     197             :                                 case KEY_NS_SPEC:
     198         192 :                                         if (keyIsSpec (split->parents[i])) return i;
     199             :                                         break;
     200             :                                 case KEY_NS_DIR:
     201         285 :                                         if (keyIsDir (split->parents[i])) return i;
     202             :                                         break;
     203             :                                 case KEY_NS_USER:
     204      143259 :                                         if (keyIsUser (split->parents[i])) return i;
     205             :                                         break;
     206             :                                 case KEY_NS_SYSTEM:
     207       30397 :                                         if (keyIsSystem (split->parents[i])) return i;
     208             :                                         break;
     209             :                                 case KEY_NS_PROC:
     210             :                                         return -1;
     211             :                                 case KEY_NS_EMPTY:
     212             :                                         return -1;
     213             :                                 case KEY_NS_NONE:
     214             :                                         return -1;
     215             :                                 case KEY_NS_META:
     216             :                                         return -1;
     217             :                                 case KEY_NS_CASCADING:
     218             :                                         return -1;
     219             :                                 }
     220        1851 :                                 continue;
     221             :                         }
     222             :                         /* We already have this backend, so leave */
     223        2636 :                         return i;
     224             :                 }
     225             :         }
     226             :         return -1;
     227             : }
     228             : 
     229             : /**
     230             :  * @brief Map namespace to string and decide if it should be used for kdbGet()
     231             :  *
     232             :  * @param parentKey the key name that should be changed
     233             :  * @param ns the namespace it should be changed to
     234             :  *
     235             :  * @retval 0 invalid namespace for kdbGet(), no action required
     236             :  * @retval 1 valid namespace for kdbGet()
     237             :  */
     238       59235 : static int elektraKeySetNameByNamespace (Key * parentKey, elektraNamespace ns)
     239             : {
     240       59235 :         switch (ns)
     241             :         {
     242             :         case KEY_NS_SPEC:
     243       11847 :                 keySetName (parentKey, "spec");
     244       11847 :                 break;
     245             :         case KEY_NS_PROC:
     246             :                 /* only transient, should fail */
     247             :                 return 0;
     248             :         case KEY_NS_DIR:
     249       11847 :                 keySetName (parentKey, "dir");
     250       11847 :                 break;
     251             :         case KEY_NS_USER:
     252       11847 :                 keySetName (parentKey, "user");
     253       11847 :                 break;
     254             :         case KEY_NS_SYSTEM:
     255       11847 :                 keySetName (parentKey, "system");
     256       11847 :                 break;
     257             :         case KEY_NS_EMPTY:
     258             :         case KEY_NS_NONE:
     259             :         case KEY_NS_META:
     260             :         case KEY_NS_CASCADING:
     261             :                 return 0;
     262             :         }
     263             :         return 1;
     264             : }
     265             : 
     266             : 
     267             : /**
     268             :  * Walks through kdb->split and adds all backends below parentKey to split.
     269             :  *
     270             :  * Sets syncbits to 2 if it is a default or root backend (which needs splitting).
     271             :  * The information is copied from kdb->split.
     272             :  *
     273             :  * @pre split needs to be empty, directly after creation with splitNew().
     274             :  *
     275             :  * @pre there needs to be a valid defaultBackend
     276             :  *      but its ok not to have a trie inside KDB.
     277             :  *
     278             :  * @pre parentKey must be a valid key! (could be implemented more generally,
     279             :  *      but that would require splitting up of keysets of the same backend)
     280             :  *
     281             :  * @param split will get all backends appended
     282             :  * @param kdb the handle to get information about backends
     283             :  * @param parentKey the information below which key the backends are from interest
     284             :  * @ingroup split
     285             :  * @retval 1 always
     286             :  */
     287       76398 : int splitBuildup (Split * split, KDB * kdb, Key * parentKey)
     288             : {
     289             :         /* For compatibility reasons invalid names are accepted, too.
     290             :          * This solution is faster than checking the name of parentKey
     291             :          * every time in loop.
     292             :          * The parentKey might be null in some unit tests, so also check
     293             :          * for this. */
     294       76398 :         const char * name = keyName (parentKey);
     295       76398 :         if (!parentKey || !name || !strcmp (name, "") || !strcmp (name, "/"))
     296             :         {
     297             :                 parentKey = 0;
     298             :         }
     299       76345 :         else if (name[0] == '/')
     300             :         {
     301       11847 :                 Key * key = keyNew (0, KEY_END);
     302       71082 :                 for (elektraNamespace ins = KEY_NS_FIRST; ins <= KEY_NS_LAST; ++ins)
     303             :                 {
     304       59235 :                         if (!elektraKeySetNameByNamespace (key, ins)) continue;
     305       47388 :                         keyAddName (key, keyName (parentKey));
     306       47388 :                         splitBuildup (split, kdb, key);
     307             :                 }
     308       11847 :                 keyDel (key);
     309       11847 :                 return 1;
     310             :         }
     311             : 
     312             :         /* Returns the backend the key is in or the default backend
     313             :            otherwise */
     314       64551 :         Backend * backend = mountGetBackend (kdb, parentKey);
     315             : 
     316             : #if DEBUG && VERBOSE
     317             :         printf (" with parent %s\n", keyName (parentKey));
     318             : #endif
     319      706906 :         for (size_t i = 0; i < kdb->split->size; ++i)
     320             :         {
     321             : #if DEBUG && VERBOSE
     322             :                 printf ("  %zu with parent %s\n", i, keyName (kdb->split->parents[i]));
     323             : #endif
     324      642355 :                 if (!parentKey)
     325             :                 {
     326             : #if DEBUG && VERBOSE
     327             :                         printf ("   def add %s\n", keyName (kdb->split->parents[i]));
     328             : #endif
     329             :                         /* Catch all: add all mountpoints */
     330         359 :                         splitAppend (split, kdb->split->handles[i], keyDup (kdb->split->parents[i]), kdb->split->syncbits[i]);
     331             :                 }
     332      641996 :                 else if (backend == kdb->split->handles[i] && keyRel (kdb->split->parents[i], parentKey) >= 0)
     333             :                 {
     334             : #if DEBUG && VERBOSE
     335             :                         printf ("   exa add %s\n", keyName (kdb->split->parents[i]));
     336             : #endif
     337             :                         /* parentKey is exactly in this backend, so add it! */
     338       64498 :                         splitAppend (split, kdb->split->handles[i], keyDup (kdb->split->parents[i]), kdb->split->syncbits[i]);
     339             :                 }
     340      577498 :                 else if (keyRel (parentKey, kdb->split->parents[i]) >= 0)
     341             :                 {
     342             : #if DEBUG && VERBOSE
     343             :                         printf ("   rel add %s\n", keyName (kdb->split->parents[i]));
     344             : #endif
     345             :                         /* this backend is completely below the parentKey, so lets add it. */
     346        1117 :                         splitAppend (split, kdb->split->handles[i], keyDup (kdb->split->parents[i]), kdb->split->syncbits[i]);
     347             :                 }
     348             :         }
     349             : 
     350             :         return 1;
     351             : }
     352             : 
     353             : 
     354             : /**
     355             :  * Splits up the keysets and search for a sync bit in every key.
     356             :  *
     357             :  * It does not check if there were removed keys,
     358             :  * see splitSync() for the next step.
     359             :  *
     360             :  * It does not create new backends, this has to be
     361             :  * done by buildup before.
     362             :  *
     363             :  * @pre splitBuildup() need to be executed before.
     364             :  *
     365             :  * @param split the split object to work with
     366             :  * @param handle to get information where the individual keys belong
     367             :  * @param ks the keyset to divide
     368             :  *
     369             :  * @retval 0 if there were no sync bits
     370             :  * @retval 1 if there were sync bits
     371             :  * @retval -1 if no backend was found for any key
     372             :  * @ingroup split
     373             :  */
     374        2810 : int splitDivide (Split * split, KDB * handle, KeySet * ks)
     375             : {
     376        2810 :         int needsSync = 0;
     377        2810 :         Key * curKey = 0;
     378             : 
     379        2810 :         ksRewind (ks);
     380      173228 :         while ((curKey = ksNext (ks)) != 0)
     381             :         {
     382             :                 // TODO: handle keys in wrong namespaces
     383      167608 :                 Backend * curHandle = mountGetBackend (handle, curKey);
     384      167608 :                 if (!curHandle) return -1;
     385             : 
     386             :                 /* If key could be appended to any of the existing split keysets */
     387      167608 :                 ssize_t curFound = splitSearchBackend (split, curHandle, curKey);
     388             : 
     389      167608 :                 if (curFound == -1)
     390             :                 {
     391             :                         ELEKTRA_LOG_DEBUG ("SKIPPING NOT RELEVANT KEY: %p key: %s, string: %s", (void *) curKey, keyName (curKey),
     392             :                                            keyString (curKey));
     393        7571 :                         continue; // key not relevant in this kdbSet
     394             :                 }
     395             : 
     396      160037 :                 ksAppendKey (split->keysets[curFound], curKey);
     397      160037 :                 if (keyNeedSync (curKey) == 1)
     398             :                 {
     399       10733 :                         split->syncbits[curFound] |= 1;
     400       10733 :                         needsSync = 1;
     401             :                 }
     402             :         }
     403             : 
     404             :         return needsSync;
     405             : }
     406             : 
     407             : /**
     408             :  * @brief Update the (configuration) file name for the parent key
     409             :  *
     410             :  * @param split the split to work with
     411             :  * @param handle the handle to work with
     412             :  * @param key the parentKey that should be updated (name must be
     413             :  * correct)
     414             :  */
     415       26178 : void splitUpdateFileName (Split * split, KDB * handle, Key * key)
     416             : {
     417       26178 :         Backend * curHandle = mountGetBackend (handle, key);
     418       26178 :         if (!curHandle) return;
     419       26178 :         ssize_t curFound = splitSearchBackend (split, curHandle, key);
     420       26178 :         if (curFound == -1) return;
     421             : #if DEBUG && VERBOSE
     422             :         printf ("Update string from %s to %s\n", keyString (key), keyString (split->parents[curFound]));
     423             :         printf ("Names are: %s and %s\n\n", keyName (key), keyName (split->parents[curFound]));
     424             : #endif
     425       14651 :         keySetString (key, keyString (split->parents[curFound]));
     426             : }
     427             : 
     428             : 
     429             : /**
     430             :  * Appoints all keys from ks to yet unsynced splits.
     431             :  *
     432             :  * @pre splitBuildup() need to be executed before.
     433             :  *
     434             :  * @param split the split object to work with
     435             :  * @param handle to determine to which backend a key belongs
     436             :  * @param ks the keyset to appoint to split
     437             :  *
     438             :  * @retval 1 on success
     439             :  * @retval -1 if no backend was found for a key
     440             :  * @ingroup split
     441             :  */
     442       15784 : int splitAppoint (Split * split, KDB * handle, KeySet * ks)
     443             : {
     444       15784 :         Key * curKey = 0;
     445       15784 :         ssize_t defFound = splitAppend (split, 0, 0, 0);
     446             : 
     447       15784 :         ksRewind (ks);
     448       31971 :         while ((curKey = ksNext (ks)) != 0)
     449             :         {
     450         403 :                 Backend * curHandle = mountGetBackend (handle, curKey);
     451         403 :                 if (!curHandle) return -1;
     452             : 
     453             :                 /* If key could be appended to any of the existing split keysets */
     454         403 :                 ssize_t curFound = splitSearchBackend (split, curHandle, curKey);
     455             : 
     456         403 :                 if (curFound == -1) curFound = defFound;
     457             : 
     458         403 :                 if (split->syncbits[curFound] & SPLIT_FLAG_SYNC)
     459             :                 {
     460         136 :                         continue;
     461             :                 }
     462             : 
     463         267 :                 ksAppendKey (split->keysets[curFound], curKey);
     464             :         }
     465             : 
     466             :         return 1;
     467             : }
     468             : 
     469           6 : static void elektraDropCurrentKey (KeySet * ks, Key * warningKey, const Backend * curHandle, const Backend * otherHandle, const char * msg)
     470             : {
     471           6 :         const Key * k = ksCurrent (ks);
     472             : 
     473           6 :         const size_t sizeOfStaticText = 300;
     474           6 :         size_t size = keyGetNameSize (curHandle->mountpoint) + keyGetValueSize (curHandle->mountpoint) + keyGetNameSize (k) + strlen (msg) +
     475             :                       sizeOfStaticText;
     476           6 :         if (otherHandle)
     477             :         {
     478           2 :                 size += keyGetNameSize (otherHandle->mountpoint) + keyGetValueSize (otherHandle->mountpoint);
     479             :         }
     480           6 :         char * warningMsg = elektraMalloc (size);
     481           6 :         strcpy (warningMsg, "drop key ");
     482           6 :         const char * name = keyName (k);
     483           6 :         if (name)
     484             :         {
     485           6 :                 strcat (warningMsg, name);
     486             :         }
     487             :         else
     488             :         {
     489           0 :                 strcat (warningMsg, "(no name)");
     490             :         }
     491           6 :         strcat (warningMsg, " not belonging to \"");
     492           6 :         strcat (warningMsg, keyName (curHandle->mountpoint));
     493           6 :         strcat (warningMsg, "\" with name \"");
     494           6 :         strcat (warningMsg, keyString (curHandle->mountpoint));
     495           6 :         if (otherHandle)
     496             :         {
     497           2 :                 strcat (warningMsg, "\" but instead to \"");
     498           2 :                 strcat (warningMsg, keyName (otherHandle->mountpoint));
     499           2 :                 strcat (warningMsg, "\" with name \"");
     500           2 :                 strcat (warningMsg, keyString (otherHandle->mountpoint));
     501             :         }
     502           6 :         strcat (warningMsg, "\" because ");
     503           6 :         strcat (warningMsg, msg);
     504           6 :         ELEKTRA_ADD_INTERFACE_WARNINGF (warningKey, "Postcondition of backend was violated: %s", warningMsg);
     505           6 :         elektraFree (warningMsg);
     506           6 :         cursor_t c = ksGetCursor (ks);
     507           6 :         keyDel (elektraKsPopAtCursor (ks, c));
     508           6 :         ksSetCursor (ks, c);
     509           6 :         elektraKsPrev (ks); // next ksNext() will point correctly again
     510           6 : }
     511             : 
     512             : 
     513             : /**
     514             :  * @brief Filter out keys not in the correct keyset
     515             :  *
     516             :  * @param split the split where to do it
     517             :  * @param i for which split
     518             :  * @param warningKey the key
     519             :  * @param handle where to do backend lookups
     520             :  *
     521             :  * @retval -1 on error (no backend, wrong namespace)
     522             :  * @retval 0 otherwise
     523             :  */
     524       23408 : static int elektraSplitPostprocess (Split * split, int i, Key * warningKey, KDB * handle)
     525             : {
     526       23408 :         Key * cur = 0;
     527       23408 :         ksRewind (split->keysets[i]);
     528      215302 :         while ((cur = ksNext (split->keysets[i])) != 0)
     529             :         {
     530      168486 :                 Backend * curHandle = mountGetBackend (handle, cur);
     531      168486 :                 if (!curHandle) return -1;
     532             : 
     533      168486 :                 keyClearSync (cur);
     534             : 
     535      168486 :                 if (curHandle != split->handles[i])
     536             :                 {
     537           2 :                         elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, split->handles[i],
     538             :                                                "it is hidden by other mountpoint");
     539             :                 }
     540             :                 else
     541      168484 :                         switch (keyGetNamespace (cur))
     542             :                         {
     543             :                         case KEY_NS_SPEC:
     544         517 :                                 if (!keyIsSpec (split->parents[i]))
     545           0 :                                         elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, 0, "it is not spec");
     546             :                                 break;
     547             :                         case KEY_NS_DIR:
     548          49 :                                 if (!keyIsDir (split->parents[i]))
     549           0 :                                         elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, 0, "it is not dir");
     550             :                                 break;
     551             :                         case KEY_NS_USER:
     552        5813 :                                 if (!keyIsUser (split->parents[i]))
     553           0 :                                         elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, 0, "it is not user");
     554             :                                 break;
     555             :                         case KEY_NS_SYSTEM:
     556      162105 :                                 if (!keyIsSystem (split->parents[i]))
     557           4 :                                         elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, 0, "it is not system");
     558             :                                 break;
     559             :                         case KEY_NS_PROC:
     560           0 :                                 elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, 0, "it has a proc key name");
     561           0 :                                 break;
     562             :                         case KEY_NS_EMPTY:
     563           0 :                                 elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, 0, "it has an empty name");
     564           0 :                                 break;
     565             :                         case KEY_NS_META:
     566           0 :                                 elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, 0, "it has a metaname");
     567           0 :                                 break;
     568             :                         case KEY_NS_CASCADING:
     569           0 :                                 elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, 0, "it has a cascading name");
     570           0 :                                 break;
     571             :                         case KEY_NS_NONE:
     572           0 :                                 ELEKTRA_ASSERT (0, "wrong key namespace `none'");
     573             :                                 return -1;
     574             :                         }
     575             :         }
     576             :         return 0;
     577             : }
     578             : 
     579             : 
     580             : /**
     581             :  * Does some work after getting of backends is finished.
     582             :  *
     583             :  * - Update sizes
     584             :  * - Removal of wrong keys
     585             :  *
     586             :  * @pre splitAppoint() needs to be executed before.
     587             :  *
     588             :  * - check if keys are in correct backend
     589             :  * - remove syncbits
     590             :  * - update sizes in the backends
     591             :  *
     592             :  * @param split the split object to work with
     593             :  * @param warningKey postcondition violations are reported here
     594             :  * @param handle the handle to preprocess the keys
     595             :  * @retval 1 on success
     596             :  * @retval -1 if no backend was found for a key or split->parents
     597             :  *         has invalid namespace
     598             :  * @ingroup split
     599             :  */
     600       15767 : int splitGet (Split * split, Key * warningKey, KDB * handle)
     601             : {
     602       15767 :         int ret = 1;
     603             :         /* Dont iterate the default split part */
     604       15767 :         const int bypassedSplits = 1;
     605             : 
     606       39175 :         for (size_t i = 0; i < split->size - bypassedSplits; ++i)
     607             :         {
     608             :                 if (test_bit (split->syncbits[i], 0))
     609             :                 {
     610             :                         /* Dont process keysets which come from the user
     611             :                            and not from the backends */
     612             :                         continue;
     613             :                 }
     614             : 
     615             : /* Update sizes */
     616             : #if DEBUG && VERBOSE
     617             :                 printf ("Update size for %s\n", keyName (split->parents[i]));
     618             : #endif
     619             :                 // first we need postprocessing because that might
     620             :                 // reduce sizes
     621       23408 :                 if (elektraSplitPostprocess (split, i, warningKey, handle) == -1) ret = -1;
     622             :                 // then we can set the size
     623             :                 ELEKTRA_LOG_DEBUG ("splitGet : backendUpdateSize thingy");
     624       23408 :                 if (backendUpdateSize (split->handles[i], split->parents[i], ksGetSize (split->keysets[i])) == -1) ret = -1;
     625             :         }
     626             : 
     627       15767 :         return ret;
     628             : }
     629             : 
     630             : /**
     631             :  * Also update sizes after kdbSet() to recognize multiple kdbSet() attempts.
     632             :  *
     633             :  * @warning cant use the same code with splitGet because there is
     634             :  * no default split part for kdbSet().
     635             :  */
     636        2535 : int splitUpdateSize (Split * split)
     637             : {
     638             :         /* Iterate everything */
     639        5104 :         for (size_t i = 0; i < split->size; ++i)
     640             :         {
     641        2569 :                 switch (keyGetNamespace (split->parents[i]))
     642             :                 {
     643             :                 case KEY_NS_SPEC:
     644          56 :                         split->handles[i]->specsize = ksGetSize (split->keysets[i]);
     645          56 :                         break;
     646             :                 case KEY_NS_DIR:
     647           8 :                         split->handles[i]->dirsize = ksGetSize (split->keysets[i]);
     648           8 :                         break;
     649             :                 case KEY_NS_USER:
     650        1295 :                         split->handles[i]->usersize = ksGetSize (split->keysets[i]);
     651        1295 :                         break;
     652             :                 case KEY_NS_SYSTEM:
     653        1210 :                         split->handles[i]->systemsize = ksGetSize (split->keysets[i]);
     654        1210 :                         break;
     655             :                 case KEY_NS_PROC:
     656             :                 case KEY_NS_EMPTY:
     657             :                 case KEY_NS_NONE:
     658             :                 case KEY_NS_META:
     659             :                 case KEY_NS_CASCADING:
     660             :                         return -1;
     661             :                 }
     662             :         }
     663             :         return 1;
     664             : }
     665             : 
     666             : /**
     667             :  * Merges together the backend based parts of split into dest,
     668             :  * but bypasses the default split.
     669             :  *
     670             :  * @param split the split object to work with
     671             :  * @param dest the destination keyset where all keysets are appended.
     672             :  * @retval 1 on success
     673             :  * @ingroup split
     674             :  */
     675       15747 : int splitMergeBackends (Split * split, KeySet * dest)
     676             : {
     677             :         /* Bypass default split */
     678       15751 :         const int bypassedSplits = 1;
     679       39133 :         for (size_t i = 0; i < split->size - bypassedSplits; ++i)
     680             :         {
     681             :                 if (test_bit (split->syncbits[i], 0))
     682             :                 {
     683             :                         /* Dont process keysets which come from the user
     684             :                            and not from the backends */
     685             :                         continue;
     686             :                 }
     687       23382 :                 ksAppend (dest, split->keysets[i]);
     688             :         }
     689       15747 :         return 1;
     690             : }
     691             : 
     692             : /**
     693             :  * Merges the default split into dest.
     694             :  *
     695             :  * @param split the split object to work with
     696             :  * @param dest the destination keyset where all keysets are appended.
     697             :  * @retval 1 on success
     698             :  * @ingroup split
     699             :  */
     700       15744 : int splitMergeDefault (Split * split, KeySet * dest)
     701             : {
     702             :         /* Merge default split */
     703       15748 :         ksAppend (dest, split->keysets[split->size - 1]);
     704       15744 :         return 1;
     705             : }
     706             : 
     707             : /** Add sync bits everywhere keys were removed/added.
     708             :  *
     709             :  * - checks if the size of a previous kdbGet() is unchanged.
     710             :  * - checks if in correct state (kdbGet() needs to be executed before)
     711             :  *
     712             :  * Only splitDivide() together with this function can really decide
     713             :  * if sync is needed or not.
     714             :  *
     715             :  * @pre split needs to be processed with splitDivide() before.
     716             :  *
     717             :  * @retval 0 if kdbSet() is not needed
     718             :  * @retval 1 if kdbSet() is needed
     719             :  * @retval -1 on wrong keys (also has assert, should not happen)
     720             :  * @retval -2 wrong spec state: kdbGet() was not executed before
     721             :  * @retval -3 wrong dir state: kdbGet() was not executed before
     722             :  * @retval -4 wrong user state: kdbGet() was not executed before
     723             :  * @retval -5 wrong system state: kdbGet() was not executed before
     724             :  * @pre user/system was split before.
     725             :  * @param split the split object to work with
     726             :  * @ingroup split
     727             :  *
     728             :  **/
     729        2786 : int splitSync (Split * split)
     730             : {
     731        2786 :         int needsSync = 0;
     732             : 
     733        6842 :         for (size_t i = 0; i < split->size; ++i)
     734             :         {
     735             :                 // first check for wrong states etc.
     736        4068 :                 switch (keyGetNamespace (split->parents[i]))
     737             :                 {
     738             :                 case KEY_NS_SPEC:
     739             :                         // Check if we are in correct state
     740         405 :                         if (split->handles[i]->specsize == -1)
     741             :                         {
     742           6 :                                 return -(int) i - 2;
     743             :                         }
     744             :                         /* Check for spec keyset for removed keys */
     745         399 :                         if (split->handles[i]->specsize != ksGetSize (split->keysets[i]))
     746             :                         {
     747          55 :                                 set_bit (split->syncbits[i], SPLIT_FLAG_SYNC);
     748          55 :                                 needsSync = 1;
     749             :                         }
     750             :                         break;
     751             :                 case KEY_NS_DIR:
     752             :                         // Check if we are in correct state
     753         379 :                         if (split->handles[i]->dirsize == -1)
     754             :                         {
     755           0 :                                 return -(int) i - 2;
     756             :                         }
     757             :                         /* Check for dir keyset for removed keys */
     758         379 :                         if (split->handles[i]->dirsize != ksGetSize (split->keysets[i]))
     759             :                         {
     760          12 :                                 set_bit (split->syncbits[i], SPLIT_FLAG_SYNC);
     761          12 :                                 needsSync = 1;
     762             :                         }
     763             :                         break;
     764             :                 case KEY_NS_USER:
     765             :                         // Check if we are in correct state
     766        1718 :                         if (split->handles[i]->usersize == -1)
     767             :                         {
     768           4 :                                 return -(int) i - 2;
     769             :                         }
     770             :                         /* Check for user keyset for removed keys */
     771        1714 :                         if (split->handles[i]->usersize != ksGetSize (split->keysets[i]))
     772             :                         {
     773         590 :                                 set_bit (split->syncbits[i], SPLIT_FLAG_SYNC);
     774         590 :                                 needsSync = 1;
     775             :                         }
     776             :                         break;
     777             :                 case KEY_NS_SYSTEM:
     778             :                         // Check if we are in correct state
     779        1566 :                         if (split->handles[i]->systemsize == -1)
     780             :                         {
     781           2 :                                 return -(int) i - 2;
     782             :                         }
     783             :                         /* Check for system keyset for removed keys */
     784        1564 :                         if (split->handles[i]->systemsize != ksGetSize (split->keysets[i]))
     785             :                         {
     786        1267 :                                 set_bit (split->syncbits[i], SPLIT_FLAG_SYNC);
     787        1267 :                                 needsSync = 1;
     788             :                         }
     789             :                         break;
     790             :                 case KEY_NS_PROC:
     791             :                 case KEY_NS_EMPTY:
     792             :                 case KEY_NS_META:
     793             :                 case KEY_NS_CASCADING:
     794             :                 case KEY_NS_NONE:
     795           0 :                         ELEKTRA_ASSERT (0, "Got keys in wrong namespace %d in split %zu", keyGetNamespace (split->parents[i]), i);
     796             :                         return -1;
     797             :                 }
     798             :         }
     799             : 
     800             :         return needsSync;
     801             : }
     802             : 
     803             : /** Prepares for kdbSet() mainloop afterwards.
     804             :  *
     805             :  * All splits which do not need sync are removed and a deep copy
     806             :  * of the remaining keysets is done.
     807             :  *
     808             :  * @param split the split object to work with
     809             :  * @ingroup split
     810             :  */
     811        2637 : void splitPrepare (Split * split)
     812             : {
     813        8827 :         for (size_t i = 0; i < split->size;)
     814             :         {
     815        3553 :                 int inc = 1;
     816        3553 :                 if ((split->syncbits[i] & 1) == 1)
     817             :                 {
     818        2688 :                         KeySet * n = ksDeepDup (split->keysets[i]);
     819        2688 :                         ksDel (split->keysets[i]);
     820        2688 :                         split->keysets[i] = n;
     821             :                 }
     822             :                 else
     823             :                 {
     824             :                         /* We don't need i anymore */
     825         865 :                         splitRemove (split, i);
     826         865 :                         inc = 0;
     827             :                 }
     828        3553 :                 i += inc;
     829             :         }
     830        2637 : }
     831             : 
     832           0 : static char * elektraStrConcat (const char * a, const char * b)
     833             : {
     834           0 :         size_t len = strlen (a) + strlen (b) + 1;
     835           0 :         char * ret = elektraMalloc (len);
     836           0 :         ret = strcpy (ret, a);
     837           0 :         ret = strcat (ret, b);
     838           0 :         return ret;
     839             : }
     840             : 
     841           0 : void splitCacheStoreState (KDB * handle, Split * split, KeySet * global, Key * parentKey, Key * initialParent)
     842             : {
     843           0 :         Key * mountPoint = mountGetMountpoint (handle, parentKey);
     844           0 :         Key * lastParentName = keyNew (KDB_CACHE_PREFIX "/lastParentName", KEY_VALUE, keyName (mountPoint), KEY_END);
     845           0 :         Key * lastParentValue = keyNew (KDB_CACHE_PREFIX "/lastParentValue", KEY_VALUE, keyString (mountPoint), KEY_END);
     846           0 :         Key * lastInitalParentName = keyNew (KDB_CACHE_PREFIX "/lastInitialParentName", KEY_VALUE, keyName (initialParent), KEY_END);
     847           0 :         Key * lastSplitSize =
     848           0 :                 keyNew (KDB_CACHE_PREFIX "/lastSplitSize", KEY_BINARY, KEY_SIZE, sizeof (size_t), KEY_VALUE, &(split->size), KEY_END);
     849           0 :         ksAppendKey (global, lastParentName);
     850           0 :         ksAppendKey (global, lastParentValue);
     851           0 :         ksAppendKey (global, lastInitalParentName);
     852           0 :         ksAppendKey (global, lastSplitSize);
     853             : 
     854             :         ELEKTRA_LOG_DEBUG ("SIZE STORAGE STORE STUFF");
     855           0 :         for (size_t i = 0; i < split->size; ++i)
     856             :         {
     857             :                 // TODO: simplify this code below, seems like this affacts only the last split anyway
     858           0 :                 if (!split->handles[i] || !split->handles[i]->mountpoint)
     859             :                 {
     860             :                         ELEKTRA_LOG_DEBUG (">>>> Skipping split->handle[%ld]: pseudo-backend or no mountpoint", i);
     861           0 :                         ELEKTRA_ASSERT (i == (split->size - 1), "ERROR: NOT THE LAST SPLIT");
     862           0 :                         continue;
     863             :                 }
     864             :                 if (test_bit (split->syncbits[i], 0))
     865             :                 {
     866             :                         /* Dont process keysets which come from the user
     867             :                            and not from the backends */
     868             :                         ELEKTRA_LOG_DEBUG (">>>> Skipping split->handle[%ld]: syncbits is 0, keyset from user", i);
     869             :                         ELEKTRA_ASSERT (i == (split->size - 1), "ERROR: NOT THE LAST SPLIT");
     870             :                         continue;
     871             :                 }
     872             :                 // TODO: simplify this code above, seems like this affacts only the last split anyway
     873             : 
     874           0 :                 char * name = 0;
     875           0 :                 if (strlen (keyName (split->handles[i]->mountpoint)) != 0)
     876             :                 {
     877           0 :                         name = elektraStrConcat (KDB_CACHE_PREFIX "/splitState/mountpoint/", keyName (split->handles[i]->mountpoint));
     878             :                 }
     879             :                 else
     880             :                 {
     881           0 :                         name = elektraStrConcat (KDB_CACHE_PREFIX "/splitState/", "default/");
     882             :                 }
     883             :                 // Append parent name for uniqueness (spec, dir, user, system, ...)
     884           0 :                 char * tmp = name;
     885           0 :                 name = elektraStrConcat (name, keyName (split->parents[i]));
     886           0 :                 elektraFree (tmp);
     887             : 
     888             :                 ELEKTRA_LOG_DEBUG (">>>> STORING split->handle[%ld] with name: %s :::: parentName: %s, parentValue: %s", i, name,
     889             :                                    keyName (split->parents[i]), keyString (split->parents[i]));
     890             : 
     891           0 :                 Key * key = keyNew (name, KEY_END);
     892           0 :                 keyAddBaseName (key, "splitParentName");
     893           0 :                 keySetString (key, keyName (split->parents[i]));
     894           0 :                 ksAppendKey (global, key);
     895             :                 ELEKTRA_LOG_DEBUG (">>>> STORING key: %s, string: %s, strlen: %ld, valSize: %ld", keyName (key), keyString (key),
     896             :                                    strlen (keyString (key)), keyGetValueSize (key));
     897           0 :                 keyDel (key);
     898             : 
     899           0 :                 key = keyNew (name, KEY_END);
     900           0 :                 keyAddBaseName (key, "splitParentValue");
     901           0 :                 keySetString (key, keyString (split->parents[i]));
     902           0 :                 ksAppendKey (global, key);
     903             :                 ELEKTRA_LOG_DEBUG (">>>> STORING key: %s, string: %s, strlen: %ld, valSize: %ld", keyName (key), keyString (key),
     904             :                                    strlen (keyString (key)), keyGetValueSize (key));
     905           0 :                 keyDel (key);
     906             : 
     907           0 :                 key = keyNew (name, KEY_END);
     908           0 :                 keyAddBaseName (key, "specsize");
     909           0 :                 keySetBinary (key, &(split->handles[i]->specsize), sizeof (ssize_t));
     910           0 :                 ksAppendKey (global, key);
     911             :                 ELEKTRA_LOG_DEBUG (">>>> STORING key: %s, string: %s, strlen: %ld, valSize: %ld", keyName (key), keyString (key),
     912             :                                    strlen (keyString (key)), keyGetValueSize (key));
     913           0 :                 keyDel (key);
     914             : 
     915           0 :                 key = keyNew (name, KEY_END);
     916           0 :                 keyAddBaseName (key, "dirsize");
     917           0 :                 keySetBinary (key, &(split->handles[i]->dirsize), sizeof (ssize_t));
     918           0 :                 ksAppendKey (global, key);
     919             :                 ELEKTRA_LOG_DEBUG (">>>> STORING key: %s, string: %s, strlen: %ld, valSize: %ld", keyName (key), keyString (key),
     920             :                                    strlen (keyString (key)), keyGetValueSize (key));
     921           0 :                 keyDel (key);
     922             : 
     923           0 :                 key = keyNew (name, KEY_END);
     924           0 :                 keyAddBaseName (key, "usersize");
     925           0 :                 keySetBinary (key, &(split->handles[i]->usersize), sizeof (ssize_t));
     926           0 :                 ksAppendKey (global, key);
     927             :                 ELEKTRA_LOG_DEBUG (">>>> STORING key: %s, string: %s, strlen: %ld, valSize: %ld", keyName (key), keyString (key),
     928             :                                    strlen (keyString (key)), keyGetValueSize (key));
     929           0 :                 keyDel (key);
     930             : 
     931           0 :                 key = keyNew (name, KEY_END);
     932           0 :                 keyAddBaseName (key, "systemsize");
     933           0 :                 keySetBinary (key, &(split->handles[i]->systemsize), sizeof (ssize_t));
     934           0 :                 ksAppendKey (global, key);
     935             :                 ELEKTRA_LOG_DEBUG (">>>> STORING key: %s, string: %s, strlen: %ld, valSize: %ld", keyName (key), keyString (key),
     936             :                                    strlen (keyString (key)), keyGetValueSize (key));
     937           0 :                 keyDel (key);
     938             : 
     939           0 :                 key = keyNew (name, KEY_END);
     940           0 :                 keyAddBaseName (key, "syncbits");
     941           0 :                 keySetBinary (key, &(split->syncbits[i]), sizeof (splitflag_t));
     942           0 :                 ksAppendKey (global, key);
     943             :                 ELEKTRA_LOG_DEBUG (">>>> STORING key: %s, string: %s, strlen: %ld, valSize: %ld", keyName (key), keyString (key),
     944             :                                    strlen (keyString (key)), keyGetValueSize (key));
     945           0 :                 keyDel (key);
     946             : 
     947           0 :                 elektraFree (name);
     948             :         }
     949           0 : }
     950             : 
     951           0 : int splitCacheCheckState (Split * split, KeySet * global)
     952             : {
     953             :         ELEKTRA_LOG_DEBUG ("SIZE STORAGE CHCK");
     954           0 :         Key * key = 0;
     955           0 :         char * name = 0;
     956             : 
     957           0 :         Key * lastSplitSize = ksLookupByName (global, KDB_CACHE_PREFIX "/lastSplitSize", KDB_O_NONE);
     958           0 :         if (lastSplitSize && keyGetValueSize (lastSplitSize) == sizeof (size_t))
     959             :         {
     960           0 :                 size_t lastSize = 0;
     961           0 :                 keyGetBinary (lastSplitSize, &lastSize, sizeof (size_t));
     962             :                 ELEKTRA_LOG_DEBUG ("Split size check: lastSize %ld, cur size: %ld", lastSize, split->size);
     963           0 :                 int bypassedSplits = 1;
     964           0 :                 if (lastSize != split->size + bypassedSplits) return -1;
     965             :         }
     966             :         else
     967             :         {
     968             :                 return -1;
     969             :         }
     970             : 
     971           0 :         for (size_t i = 0; i < split->size; ++i)
     972             :         {
     973           0 :                 if (strlen (keyName (split->handles[i]->mountpoint)) != 0)
     974             :                 {
     975           0 :                         name = elektraStrConcat (KDB_CACHE_PREFIX "/splitState/mountpoint/", keyName (split->handles[i]->mountpoint));
     976             :                 }
     977             :                 else
     978             :                 {
     979           0 :                         name = elektraStrConcat (KDB_CACHE_PREFIX "/splitState/", "default/");
     980             :                 }
     981             :                 // Append parent name for uniqueness (spec, dir, user, system, ...)
     982           0 :                 char * tmp = name;
     983           0 :                 name = elektraStrConcat (name, keyName (split->parents[i]));
     984           0 :                 elektraFree (tmp);
     985           0 :                 key = keyNew (name, KEY_END);
     986             : 
     987           0 :                 keyAddBaseName (key, "splitParentName");
     988           0 :                 Key * found = ksLookup (global, key, KDB_O_NONE);
     989           0 :                 if (!(found && elektraStrCmp (keyString (found), keyName (split->parents[i])) == 0))
     990             :                 {
     991             :                         goto error;
     992             :                 }
     993             : 
     994           0 :                 keySetBaseName (key, "splitParentValue");
     995           0 :                 found = ksLookup (global, key, KDB_O_NONE);
     996           0 :                 if (!(found && elektraStrCmp (keyString (found), keyString (split->parents[i])) == 0))
     997             :                 {
     998             :                         goto error;
     999             :                 }
    1000             : 
    1001           0 :                 keySetBaseName (key, "specsize");
    1002           0 :                 found = ksLookup (global, key, KDB_O_NONE);
    1003           0 :                 if (!(found && keyGetValueSize (found) == sizeof (ssize_t)) || (split->handles[i]->specsize > 0))
    1004             :                 {
    1005             :                         goto error;
    1006             :                 }
    1007             : 
    1008           0 :                 keySetBaseName (key, "dirsize");
    1009           0 :                 found = ksLookup (global, key, KDB_O_NONE);
    1010           0 :                 if (!(found && keyGetValueSize (found) == sizeof (ssize_t)) || (split->handles[i]->dirsize > 0))
    1011             :                 {
    1012             :                         goto error;
    1013             :                 }
    1014             : 
    1015           0 :                 keySetBaseName (key, "usersize");
    1016           0 :                 found = ksLookup (global, key, KDB_O_NONE);
    1017           0 :                 if (!(found && keyGetValueSize (found) == sizeof (ssize_t)) || (split->handles[i]->usersize > 0))
    1018             :                 {
    1019             :                         goto error;
    1020             :                 }
    1021             : 
    1022           0 :                 keySetBaseName (key, "systemsize");
    1023           0 :                 found = ksLookup (global, key, KDB_O_NONE);
    1024           0 :                 if (!(found && keyGetValueSize (found) == sizeof (ssize_t)) || (split->handles[i]->systemsize > 0))
    1025             :                 {
    1026             :                         goto error;
    1027             :                 }
    1028             : 
    1029           0 :                 keySetBaseName (key, "syncbits");
    1030           0 :                 found = ksLookup (global, key, KDB_O_NONE);
    1031           0 :                 if (!(found && keyGetValueSize (found) == sizeof (splitflag_t)) || test_bit (split->syncbits[i], 0))
    1032             :                 {
    1033             :                         goto error;
    1034             :                 }
    1035             : 
    1036           0 :                 elektraFree (name);
    1037           0 :                 name = 0;
    1038           0 :                 keyDel (key);
    1039             :         }
    1040             : 
    1041             :         return 0;
    1042             : 
    1043             : error:
    1044             :         ELEKTRA_LOG_WARNING ("SIZE STORAGE KEY NOT FOUND");
    1045             :         ELEKTRA_LOG_DEBUG (">>>> MISSING key: %s, string: %s, strlen: %ld, valSize: %ld", keyName (key), keyString (key),
    1046             :                            strlen (keyString (key)), keyGetValueSize (key));
    1047           0 :         keyDel (key);
    1048           0 :         if (name) elektraFree (name);
    1049             :         return -1;
    1050             : }
    1051             : 
    1052           0 : int splitCacheLoadState (Split * split, KeySet * global)
    1053             : {
    1054             :         ELEKTRA_LOG_DEBUG ("SIZE STORAGE LOAD");
    1055           0 :         Key * key = 0;
    1056           0 :         char * name = 0;
    1057             : 
    1058           0 :         Key * lastSplitSize = ksLookupByName (global, KDB_CACHE_PREFIX "/lastSplitSize", KDB_O_NONE);
    1059           0 :         if (lastSplitSize && keyGetValueSize (lastSplitSize) == sizeof (size_t))
    1060             :         {
    1061           0 :                 size_t lastSize = 0;
    1062           0 :                 keyGetBinary (lastSplitSize, &lastSize, sizeof (size_t));
    1063             :                 ELEKTRA_LOG_DEBUG ("Split size check: lastSize %ld, cur size: %ld", lastSize, split->size);
    1064           0 :                 int bypassedSplits = 1;
    1065           0 :                 if (lastSize != split->size + bypassedSplits) return -1;
    1066             :         }
    1067             :         else
    1068             :         {
    1069             :                 return -1;
    1070             :         }
    1071             : 
    1072           0 :         for (size_t i = 0; i < split->size; ++i)
    1073             :         {
    1074           0 :                 if (strlen (keyName (split->handles[i]->mountpoint)) != 0)
    1075             :                 {
    1076           0 :                         name = elektraStrConcat (KDB_CACHE_PREFIX "/splitState/mountpoint/", keyName (split->handles[i]->mountpoint));
    1077             :                 }
    1078             :                 else
    1079             :                 {
    1080           0 :                         name = elektraStrConcat (KDB_CACHE_PREFIX "/splitState/", "default/");
    1081             :                 }
    1082             :                 // Append parent name for uniqueness (spec, dir, user, system, ...)
    1083           0 :                 char * tmp = name;
    1084           0 :                 name = elektraStrConcat (name, keyName (split->parents[i]));
    1085           0 :                 elektraFree (tmp);
    1086           0 :                 key = keyNew (name, KEY_END);
    1087             : 
    1088           0 :                 keyAddBaseName (key, "splitParentName");
    1089           0 :                 Key * found = ksLookup (global, key, KDB_O_NONE);
    1090           0 :                 if (!(found && elektraStrCmp (keyString (found), keyName (split->parents[i])) == 0))
    1091             :                 {
    1092             :                         goto error;
    1093             :                 }
    1094             : 
    1095           0 :                 keySetBaseName (key, "splitParentValue");
    1096           0 :                 found = ksLookup (global, key, KDB_O_NONE);
    1097           0 :                 if (!(found && elektraStrCmp (keyString (found), keyString (split->parents[i])) == 0))
    1098             :                 {
    1099             :                         goto error;
    1100             :                 }
    1101             : 
    1102           0 :                 keySetBaseName (key, "specsize");
    1103           0 :                 found = ksLookup (global, key, KDB_O_NONE);
    1104           0 :                 if (found && keyGetValueSize (found) == sizeof (ssize_t))
    1105             :                 {
    1106           0 :                         keyGetBinary (found, &(split->handles[i]->specsize), sizeof (ssize_t));
    1107             :                 }
    1108             :                 else
    1109             :                 {
    1110             :                         goto error;
    1111             :                 }
    1112             : 
    1113           0 :                 keySetBaseName (key, "dirsize");
    1114           0 :                 found = ksLookup (global, key, KDB_O_NONE);
    1115           0 :                 if (found && keyGetValueSize (found) == sizeof (ssize_t))
    1116             :                 {
    1117           0 :                         keyGetBinary (found, &(split->handles[i]->dirsize), sizeof (ssize_t));
    1118             :                 }
    1119             :                 else
    1120             :                 {
    1121             :                         goto error;
    1122             :                 }
    1123             : 
    1124           0 :                 keySetBaseName (key, "usersize");
    1125           0 :                 found = ksLookup (global, key, KDB_O_NONE);
    1126           0 :                 if (found && keyGetValueSize (found) == sizeof (ssize_t))
    1127             :                 {
    1128           0 :                         keyGetBinary (found, &(split->handles[i]->usersize), sizeof (ssize_t));
    1129             :                 }
    1130             :                 else
    1131             :                 {
    1132             :                         goto error;
    1133             :                 }
    1134             : 
    1135           0 :                 keySetBaseName (key, "systemsize");
    1136           0 :                 found = ksLookup (global, key, KDB_O_NONE);
    1137           0 :                 if (found && keyGetValueSize (found) == sizeof (ssize_t))
    1138             :                 {
    1139           0 :                         keyGetBinary (found, &(split->handles[i]->systemsize), sizeof (ssize_t));
    1140             :                 }
    1141             :                 else
    1142             :                 {
    1143             :                         goto error;
    1144             :                 }
    1145             : 
    1146           0 :                 keySetBaseName (key, "syncbits");
    1147           0 :                 found = ksLookup (global, key, KDB_O_NONE);
    1148           0 :                 if (found && keyGetValueSize (found) == sizeof (splitflag_t))
    1149             :                 {
    1150           0 :                         keyGetBinary (found, &(split->syncbits[i]), sizeof (splitflag_t));
    1151             :                 }
    1152             :                 else
    1153             :                 {
    1154             :                         goto error;
    1155             :                 }
    1156             : 
    1157           0 :                 elektraFree (name);
    1158           0 :                 name = 0;
    1159           0 :                 keyDel (key);
    1160             :         }
    1161             : 
    1162             :         return 0;
    1163             : 
    1164             : error:
    1165             :         ELEKTRA_LOG_WARNING ("SIZE STORAGE KEY NOT FOUND");
    1166             :         ELEKTRA_LOG_DEBUG (">>>> MISSING key: %s, string: %s, strlen: %ld, valSize: %ld", keyName (key), keyString (key),
    1167             :                            strlen (keyString (key)), keyGetValueSize (key));
    1168           0 :         keyDel (key);
    1169           0 :         if (name) elektraFree (name);
    1170             :         return -1;
    1171             : }

Generated by: LCOV version 1.13