static void test_mount() { printf ("test mount backend\n"); KDB *kdb = kdb_new(); elektraMountBackend (kdb, b_new("user", "user"), 0); succeed_if (kdb->trie, "there should be a trie"); Key *mp = keyNew ("user", KEY_VALUE, "user", KEY_END); Key *sk = keyNew ("user", KEY_VALUE, "user", KEY_END); succeed_if (kdb->split->size == 1, "size of split not correct"); compare_key(mp, kdb->split->parents[0]); compare_key(elektraMountGetBackend (kdb, sk)->mountpoint, mp); compare_key(elektraMountGetMountpoint (kdb, sk), mp); keySetName (sk, "user/below"); compare_key(elektraMountGetBackend (kdb, sk)->mountpoint, mp); compare_key(elektraMountGetMountpoint (kdb, sk), mp); keySetName (sk, "system"); kdb->defaultBackend = b_new("", "default"); succeed_if (elektraMountGetBackend (kdb, sk) == kdb->defaultBackend, "did not return default backend"); keySetName (mp, ""); keySetString (mp, "default"); compare_key(elektraMountGetBackend (kdb, sk)->mountpoint, mp); compare_key(elektraMountGetMountpoint (kdb, sk), mp); keyDel (sk); keyDel (mp); kdb_del (kdb); }
/** * Appoints all keys from ks to yet unsynced splits. * * @pre elektraSplitBuildup() need to be executed before. * * @param split the split object to work with * @param handle to determine to which backend a key belongs * @param ks the keyset to appoint to split * * @retval 1 on success * @retval -1 if no backend was found for a key * @ingroup split */ int elektraSplitAppoint (Split * split, KDB * handle, KeySet * ks) { ssize_t curFound = 0; /* If key could be appended to any of the existing split keysets */ Key * curKey = 0; Backend * curHandle = 0; ssize_t defFound = elektraSplitAppend (split, 0, 0, 0); ksRewind (ks); while ((curKey = ksNext (ks)) != 0) { curHandle = elektraMountGetBackend (handle, curKey); if (!curHandle) return -1; curFound = elektraSplitSearchBackend (split, curHandle, curKey); if (curFound == -1) curFound = defFound; if (split->syncbits[curFound] & SPLIT_FLAG_SYNC) { continue; } ksAppendKey (split->keysets[curFound], curKey); } return 1; }
/** * Splits up the keysets and search for a sync bit in every key. * * It does not check if there were removed keys, * see elektraSplitSync() for the next step. * * It does not create new backends, this has to be * done by buildup before. * * @pre elektraSplitBuildup() need to be executed before. * * @param split the split object to work with * @param handle to get information where the individual keys belong * @param ks the keyset to divide * * @retval 0 if there were no sync bits * @retval 1 if there were sync bits * @retval -1 if no backend was found for any key * @ingroup split */ int elektraSplitDivide (Split * split, KDB * handle, KeySet * ks) { ssize_t curFound = 0; /* If key could be appended to any of the existing split keysets */ int needsSync = 0; Key * curKey = 0; Backend * curHandle = 0; ksRewind (ks); while ((curKey = ksNext (ks)) != 0) { // TODO: handle keys in wrong namespaces curHandle = elektraMountGetBackend (handle, curKey); if (!curHandle) return -1; curFound = elektraSplitSearchBackend (split, curHandle, curKey); if (curFound == -1) continue; // key not relevant in this kdbSet ksAppendKey (split->keysets[curFound], curKey); if (keyNeedSync (curKey) == 1) { split->syncbits[curFound] |= 1; needsSync = 1; } } return needsSync; }
/** * @brief Filter out keys not in the correct keyset * * @param split the split where to do it * @param i for which split * @param warningKey the key * @param handle where to do backend lookups * * @retval -1 on error (no backend, wrong namespace) * @retval 0 otherwise */ static int elektraSplitPostprocess (Split * split, int i, Key * warningKey, KDB * handle) { Key * cur = 0; Backend * curHandle = 0; ksRewind (split->keysets[i]); while ((cur = ksNext (split->keysets[i])) != 0) { curHandle = elektraMountGetBackend (handle, cur); if (!curHandle) return -1; keyClearSync (cur); if (curHandle != split->handles[i]) { elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, "it is hidden by other mountpoint"); } else switch (keyGetNamespace (cur)) { case KEY_NS_SPEC: if (!keyIsSpec (split->parents[i])) elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, "it is not spec"); break; case KEY_NS_DIR: if (!keyIsDir (split->parents[i])) elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, "it is not dir"); break; case KEY_NS_USER: if (!keyIsUser (split->parents[i])) elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, "it is not user"); break; case KEY_NS_SYSTEM: if (!keyIsSystem (split->parents[i])) elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, "it is not system"); break; case KEY_NS_PROC: elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, "it has a proc key name"); break; case KEY_NS_EMPTY: elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, "it has an empty name"); break; case KEY_NS_META: elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, "it has a meta name"); break; case KEY_NS_CASCADING: elektraDropCurrentKey (split->keysets[i], warningKey, curHandle, "it has a cascading name"); break; case KEY_NS_NONE: ELEKTRA_ASSERT (0 && "wrong key namespace, should not be none"); return -1; } } return 0; }
/** * @brief Update the (configuration) file name for the parent key * * @param split the split to work with * @param handle the handle to work with * @param key the parentKey that should be updated (name must be * correct) */ void elektraSplitUpdateFileName (Split * split, KDB * handle, Key * key) { Backend * curHandle = elektraMountGetBackend (handle, key); if (!curHandle) return; ssize_t curFound = elektraSplitSearchBackend (split, curHandle, key); if (curFound == -1) return; #if DEBUG && VERBOSE printf ("Update string from %s to %s\n", keyString (key), keyString (split->parents[curFound])); printf ("Names are: %s and %s\n\n", keyName (key), keyName (split->parents[curFound])); #endif keySetString (key, keyString (split->parents[curFound])); }
/** * Walks through kdb->split and adds all backends below parentKey to split. * * Sets syncbits to 2 if it is a default or root backend (which needs splitting). * The information is copied from kdb->split. * * @pre split needs to be empty, directly after creation with elektraSplitNew(). * * @pre there needs to be a valid defaultBackend * but its ok not to have a trie inside KDB. * * @pre parentKey must be a valid key! (could be implemented more generally, * but that would require splitting up of keysets of the same backend) * * @param split will get all backends appended * @param kdb the handle to get information about backends * @param parentKey the information below which key the backends are from interest * @ingroup split * @retval 1 always */ int elektraSplitBuildup (Split * split, KDB * kdb, Key * parentKey) { /* For compatibility reasons invalid names are accepted, too. * This solution is faster than checking the name of parentKey * every time in loop. * The parentKey might be null in some unit tests, so also check * for this. */ const char * name = keyName (parentKey); if (!parentKey || !name || !strcmp (name, "") || !strcmp (name, "/")) { parentKey = 0; } else if (name[0] == '/') { Key * key = keyNew (0, KEY_END); for (elektraNamespace ins = KEY_NS_FIRST; ins <= KEY_NS_LAST; ++ins) { if (!elektraKeySetNameByNamespace (key, ins)) continue; keyAddName (key, keyName (parentKey)); elektraSplitBuildup (split, kdb, key); } keyDel (key); return 1; } /* Returns the backend the key is in or the default backend otherwise */ Backend * backend = elektraMountGetBackend (kdb, parentKey); #if DEBUG && VERBOSE printf (" with parent %s\n", keyName (parentKey)); #endif for (size_t i = 0; i < kdb->split->size; ++i) { #if DEBUG && VERBOSE printf (" %zu with parent %s\n", i, keyName (kdb->split->parents[i])); #endif if (!parentKey) { #if DEBUG && VERBOSE printf (" def add %s\n", keyName (kdb->split->parents[i])); #endif /* Catch all: add all mountpoints */ elektraSplitAppend (split, kdb->split->handles[i], keyDup (kdb->split->parents[i]), kdb->split->syncbits[i]); } else if (backend == kdb->split->handles[i] && keyRel (kdb->split->parents[i], parentKey) >= 0) { #if DEBUG && VERBOSE printf (" exa add %s\n", keyName (kdb->split->parents[i])); #endif /* parentKey is exactly in this backend, so add it! */ elektraSplitAppend (split, kdb->split->handles[i], keyDup (kdb->split->parents[i]), kdb->split->syncbits[i]); } else if (keyRel (parentKey, kdb->split->parents[i]) >= 0) { #if DEBUG && VERBOSE printf (" rel add %s\n", keyName (kdb->split->parents[i])); #endif /* this backend is completely below the parentKey, so lets add it. */ elektraSplitAppend (split, kdb->split->handles[i], keyDup (kdb->split->parents[i]), kdb->split->syncbits[i]); } } return 1; }