KeySet * doElektraMerge (KeySet * ours, KeySet * theirs, KeySet * base) { printf ("see libelektra-tools for merging" " sizes are: %d %d %d\n", (int)ksGetSize (ours), (int)ksGetSize (theirs), (int)ksGetSize (base)); return ksNew (0, KS_END); }
void output_split(Split *split) { for (size_t i=0; i<split->size; ++i) { if (split->handles[i]) { printf ("split #%zd size: %zd, handle: %p, sync: %d, parent: %s (%s), us: %zd, ss: %zd\n", i, ksGetSize(split->keysets[i]), (void*)split->handles[i], split->syncbits[i], keyName(split->parents[i]), keyString(split->parents[i]), split->handles[i]->usersize, split->handles[i]->systemsize ); } else { printf ("split #%zd, size: %zd, default split, sync: %d\n", i, ksGetSize(split->keysets[i]), split->syncbits[i] ); } } }
static void test_lookupDefaultCascading () { printf ("Test lookup default with cascading\n"); Key * specKey = keyNew ("/abc", KEY_CASCADING_NAME, KEY_END); Key * k = 0; KeySet * ks = ksNew (20, KS_END); succeed_if (ksGetSize (ks) == 0, "wrong size"); succeed_if (ksLookup (ks, specKey, KDB_O_SPEC) == 0, "found wrong key"); keySetMeta (specKey, "default", "xyz"); k = ksLookup (ks, specKey, KDB_O_SPEC); succeed_if (k != 0, "found no default key"); succeed_if (ksGetSize (ks) == 1, "wrong size"); succeed_if_same_string (keyName (k), "/abc"); succeed_if_same_string (keyString (k), "xyz"); succeed_if (ksLookup (ks, specKey, KDB_O_SPEC) == k, "did not find default key again"); succeed_if (ksGetSize (ks) == 1, "wrong size"); keySetMeta (specKey, "default", ""); succeed_if (ksLookup (ks, specKey, KDB_O_SPEC) == k, "did not find default key again"); succeed_if (ksGetSize (ks) == 1, "wrong size"); keyDel (specKey); ksDel (ks); }
static void test_ksPop (const size_t storagePlugin, const char * tmpFile) { Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END); open_storage_plugin (storagePlugin); Plugin * plugin = plugins[storagePlugin]; KeySet * ks = simpleTestKeySet (); succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful"); succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful"); KeySet * poppedKeys = ksNew (0, KS_END); succeed_if (ksAppendKey (poppedKeys, ksPop (ks)) != -1, "ksAppendKey failed"); succeed_if (ksAppendKey (poppedKeys, ksPop (ks)) != -1, "ksAppendKey failed"); succeed_if (ksGetSize (ks) == 1, "ksGetSize after ksPop should be decremented"); succeed_if (ksAppendKey (poppedKeys, ksPop (ks)) != -1, "ksAppendKey failed"); succeed_if (ksGetSize (poppedKeys) == 3, "expecting three keys to be in ks"); succeed_if (ksPop (ks) == 0, "ks should be empty"); succeed_if (ksAppendKey (poppedKeys, ksPop (ks)) == -1, "ks should be empty, but is not"); KeySet * test = simpleTestKeySet (); compare_keyset (poppedKeys, test); ksDel (test); ksDel (poppedKeys); keyDel (parentKey); ksDel (ks); closeStoragePlugin (storagePlugin); }
/** * Also update sizes after kdbSet() to recognize multiple kdbSet() attempts. * * @warning cant use the same code with elektraSplitGet because there is * no default split part for kdbSet(). */ int elektraSplitUpdateSize (Split * split) { /* Iterate everything */ for (size_t i = 0; i < split->size; ++i) { switch (keyGetNamespace (split->parents[i])) { case KEY_NS_SPEC: split->handles[i]->specsize = ksGetSize (split->keysets[i]); break; case KEY_NS_DIR: split->handles[i]->dirsize = ksGetSize (split->keysets[i]); break; case KEY_NS_USER: split->handles[i]->usersize = ksGetSize (split->keysets[i]); break; case KEY_NS_SYSTEM: split->handles[i]->systemsize = ksGetSize (split->keysets[i]); break; case KEY_NS_PROC: case KEY_NS_EMPTY: case KEY_NS_NONE: case KEY_NS_META: case KEY_NS_CASCADING: return -1; } } return 1; }
static void test_ksAppendKey (const size_t storagePlugin, const char * tmpFile) { Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END); open_storage_plugin (storagePlugin); Plugin * plugin = plugins[storagePlugin]; KeySet * ks = simpleTestKeySet (); ssize_t origSize = ksGetSize (ks); succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful"); succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful"); ssize_t appendSize = 0; Key * toAppend = keyNew (TEST_ROOT_KEY "/my/new/key", KEY_END); if ((appendSize = ksAppendKey (ks, toAppend)) == -1) { yield_error ("ksAppendKey failed"); } succeed_if (appendSize == (origSize + 1), "ksAppendKey after append should be incremented"); succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful"); ksDel (ks); ks = ksNew (0, KS_END); succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful"); ssize_t returnedSize = ksGetSize (ks); succeed_if (returnedSize == (origSize + 1), "ksGetSize after append should be incremented"); keyDel (parentKey); ksDel (ks); closeStoragePlugin (storagePlugin); }
static int saveTree (augeas * augeasHandle, KeySet * ks, const char * lensPath, Key * parentKey) { int ret = 0; size_t prefixSize = keyGetNameSize (parentKey) - 1; size_t arraySize = ksGetSize (ks); Key ** keyArray = calloc (ksGetSize (ks), sizeof (Key *)); ret = elektraKsToMemArray (ks, keyArray); if (ret < 0) goto memoryerror; qsort (keyArray, arraySize, sizeof (Key *), keyCmpOrderWrapper); /* convert the Elektra KeySet to an Augeas tree */ for (size_t i = 0; i < arraySize; i++) { Key * key = keyArray[i]; char * nodeName; ret = asprintf (&nodeName, AUGEAS_TREE_ROOT "%s", (keyName (key) + prefixSize)); if (ret < 0) goto memoryerror; aug_set (augeasHandle, nodeName, keyString (key)); elektraFree (nodeName); } elektraFree (keyArray); /* remove keys not present in the KeySet */ struct OrphanSearch * data = elektraMalloc (sizeof (struct OrphanSearch)); if (!data) return -1; data->ks = ks; data->parentKey = parentKey; ret = foreachAugeasNode (augeasHandle, AUGEAS_TREE_ROOT, &removeOrphan, data); elektraFree (data); /* build the tree */ ret = aug_text_retrieve (augeasHandle, lensPath, AUGEAS_CONTENT_ROOT, AUGEAS_TREE_ROOT, AUGEAS_OUTPUT_ROOT); if (ret < 0) { /* report the augeas specific error */ ELEKTRA_SET_ERROR (85, parentKey, getAugeasError (augeasHandle)); } return ret; memoryerror: elektraFree (keyArray); ELEKTRA_SET_ERROR (87, parentKey, "Unable to allocate memory while saving the augeas tree"); return -1; }
static void compareKeySets(KeySet* ks, KeySet* expected) { succeed_if(ksGetSize (expected) == ksGetSize (ks), "KeySet on set does not contain the same amount of keys"); Key* current; ksRewind (expected); while ((current = ksNext (expected))) { Key *key = ksLookup (ks, current, KDB_O_NONE); succeed_if (key, "Expected key was not found in KeySet"); succeed_if (!strcmp(keyString(key), keyString(current)), "Value of key was modified"); } }
static void test_lookupIndirect () { printf ("Test lookup by indirect spec\n"); Key * s; Key * p; Key * d; Key * u; Key * y; Key * e; KeySet * ks = ksNew (20, s = keyNew ("spec/abc", KEY_END), p = keyNew ("proc/abc", KEY_END), d = keyNew ("dir/abc", KEY_END), u = keyNew ("user/abc", KEY_END), y = keyNew ("system/abc", KEY_END), e = keyNew ("system/else", KEY_END), KS_END); succeed_if (ksGetSize (ks) == 6, "wrong size"); Key * k = ksLookupByName (ks, "/abc", 0); succeed_if (k == p, "did not find proc key"); keySetMeta (s, "namespace/#0", "no"); keySetMeta (s, "default", "80"); k = ksLookupByName (ks, "/abc", 0); succeed_if (k != 0, "should find default"); succeed_if (ksGetSize (ks) == 7, "default key not added"); succeed_if_same_string (keyString (k), "80"); Key * k2 = ksLookupByName (ks, "/abc", 0); succeed_if (k == k2, "did not get same default"); keySetMeta (s, "fallback/#0", "/else"); k = ksLookupByName (ks, "/abc", 0); succeed_if (k == e, "did not find else"); keySetMeta (s, "namespace/#0", "system"); k = ksLookupByName (ks, "/abc", 0); succeed_if (k == y, "did not find system key"); keySetMeta (s, "namespace/#0", "system"); keySetMeta (s, "namespace/#1", "user"); k = ksLookupByName (ks, "/abc", 0); succeed_if (k == y, "did not find system key"); keySetMeta (s, "namespace/#0", "proc"); keySetMeta (s, "namespace/#1", "user"); k = ksLookupByName (ks, "/abc", 0); succeed_if (k == p, "did not find proc key"); keySetMeta (s, "override/#0", "/else"); k = ksLookupByName (ks, "/abc", 0); succeed_if (k == e, "did not find override key"); ksDel (ks); }
static int saveTree(augeas* augeasHandle, KeySet* ks, const char* lensPath, Key *parentKey) { int ret = 0; size_t prefixSize = keyGetNameSize (parentKey) - 1; size_t arraySize = ksGetSize (ks); Key **keyArray = calloc (ksGetSize(ks), sizeof (Key *)); ret = elektraKsToMemArray (ks, keyArray); if (ret < 0) { free (keyArray); return -1; } qsort (keyArray, arraySize, sizeof(Key *), keyCmpOrderWrapper); /* convert the Elektra KeySet to an Augeas tree */ for (size_t i = 0; i < arraySize; i++) { Key *key = keyArray[i]; char *nodeName; asprintf (&nodeName, AUGEAS_TREE_ROOT "%s", (keyName (key) + prefixSize)); aug_set (augeasHandle, nodeName, keyString (key)); free (nodeName); } free (keyArray); /* remove keys not present in the KeySet */ struct OrphanSearch *data = malloc (sizeof(struct OrphanSearch)); if (!data) return -1; data->ks = ks; data->parentKey = parentKey; foreachAugeasNode (augeasHandle, AUGEAS_TREE_ROOT, &removeOrphan, data); free (data); /* build the tree */ ret = aug_text_retrieve (augeasHandle, lensPath, AUGEAS_CONTENT_ROOT, AUGEAS_TREE_ROOT, AUGEAS_OUTPUT_ROOT); return ret; }
/** * Does some work after getting of backends is finished. * * - Update sizes * - Removal of wrong keys * * @pre elektraSplitAppoint() needs to be executed before. * * - check if keys are in correct backend * - remove syncbits * - update sizes in the backends * * @param split the split object to work with * @param warningKey postcondition violations are reported here * @param handle the handle to preprocess the keys * @retval 1 on success * @retval -1 if no backend was found for a key or split->parents * has invalid namespace * @ingroup split */ int elektraSplitGet (Split * split, Key * warningKey, KDB * handle) { int ret = 1; /* Dont iterate the default split part */ const int bypassedSplits = 1; for (size_t i = 0; i < split->size - bypassedSplits; ++i) { if (test_bit (split->syncbits[i], 0)) { /* Dont process keysets which come from the user and not from the backends */ continue; } /* Update sizes */ #if DEBUG && VERBOSE printf ("Update size for %s\n", keyName (split->parents[i])); #endif // first we need postprocessing because that might // reduce sizes if (elektraSplitPostprocess (split, i, warningKey, handle) == -1) ret = -1; // then we can set the size if (elektraBackendUpdateSize (split->handles[i], split->parents[i], ksGetSize (split->keysets[i])) == -1) ret = -1; } return ret; }
static void test_ksToArray () { KeySet * ks = ksNew (5, keyNew ("user/test1", KEY_END), keyNew ("user/test2", KEY_END), keyNew ("user/test3", KEY_END), KS_END); Key ** keyArray = calloc (ksGetSize (ks), sizeof (Key *)); elektraKsToMemArray (ks, keyArray); succeed_if_same_string ("user/test1", keyName (keyArray[0])); succeed_if_same_string ("user/test2", keyName (keyArray[1])); succeed_if_same_string ("user/test3", keyName (keyArray[2])); /* test if cursor is restored */ ksNext (ks); cursor_t cursor = ksGetCursor (ks); elektraKsToMemArray (ks, keyArray); succeed_if (ksGetCursor (ks) == cursor, "cursor was not restored"); succeed_if (elektraKsToMemArray (0, keyArray) < 0, "wrong result on null pointer"); succeed_if (elektraKsToMemArray (ks, 0) < 0, "wrong result on null buffer"); KeySet * empty = ksNew (0, KS_END); succeed_if (elektraKsToMemArray (empty, keyArray) == 0, "wrong result on empty keyset"); ksDel (empty); elektraFree (keyArray); ksDel (ks); }
/** * @brief Remove ___empty_map if thats the only thing which would be * returned. * * @param returned to remove the key from */ static void elektraYajlParseSuppressEmpty (KeySet * returned, Key * parentKey) { if (ksGetSize (returned) == 2) { Key * lookupKey = keyDup (parentKey); keyAddBaseName (lookupKey, "___empty_map"); Key * toRemove = ksLookup (returned, lookupKey, KDB_O_POP); #ifdef ELEKTRA_YAJL_VERBOSE if (toRemove) { printf ("remove %s\n", keyName (toRemove)); } else { ksRewind (returned); Key * cur; while ((cur = ksNext (returned)) != 0) { printf ("key %s has value %s\n", keyName (cur), keyString (cur)); } printf ("did not find %s\n", keyName (lookupKey)); ksRewind (returned); } #endif if (toRemove) { keyDel (toRemove); } keyDel (lookupKey); } }
void test_structure() { printf ("Test structure of keys returned from uname plugin"); Key *parentKey = keyNew("user/test/key", KEY_END); KeySet *keys = ksNew(0, KS_END); KeySet *conf = 0; PLUGIN_OPEN("uname"); succeed_if (plugin->kdbGet(plugin, keys, parentKey) == 1, "could not call kdbGet"); succeed_if (ksGetSize(keys) == 6, "size not correct"); succeed_if (ksLookupByName(keys, "user/test/key", 0), "parentkey not found"); succeed_if (ksLookupByName(keys, "user/test/key/sysname", 0), "sysname key not found"); succeed_if (ksLookupByName(keys, "user/test/key/nodename", 0), "nodename key not found"); succeed_if (ksLookupByName(keys, "user/test/key/release", 0), "release key not found"); succeed_if (ksLookupByName(keys, "user/test/key/version", 0), "version key not found"); succeed_if (ksLookupByName(keys, "user/test/key/machine", 0), "machine key not found"); ksDel(keys); keyDel(parentKey); PLUGIN_CLOSE(); }
/** * @brief Takes the first key and cuts off this common part * for all other keys, instead name will be prepended * * @return a new allocated keyset with keys in user namespace. * * The first key is removed in the resulting keyset. */ KeySet* elektraRenameKeys(KeySet *config, const char* name) { Key *root; Key *cur; ssize_t rootSize = 0; ksRewind(config); root = ksNext (config); rootSize = keyGetNameSize(root); keyDel (ksLookup (config, root, KDB_O_POP)); KeySet *newConfig = ksNew(ksGetSize(config), KS_END); if (rootSize == -1) return newConfig; while ((cur = ksPop(config)) != 0) { Key *dupKey = keyDup(cur); keySetName(dupKey, name); keyAddName(dupKey, keyName(cur)+rootSize-1); ksAppendKey(newConfig, dupKey); keyDel(cur); } return newConfig; }
static void test_lookupDoubleIndirectDefault () { printf ("Test lookup by double indirect spec with default\n"); Key * s; Key * p; Key * u; Key * y; Key * se; Key * pe; KeySet * ks = ksNew (20, se = keyNew ("spec/first", KEY_END), pe = keyNew ("proc/first", KEY_END), s = keyNew ("spec/abc", KEY_END), p = keyNew ("proc/abc", KEY_END), u = keyNew ("user/abc", KEY_END), y = keyNew ("system/abc", KEY_END), KS_END); succeed_if (ksGetSize (ks) == 6, "wrong size"); keySetMeta (se, "default", "default is ok"); keySetMeta (s, "default", "default is NOT ok"); Key * k = ksLookupByName (ks, "/first", 0); succeed_if (k == pe, "did not find proc key"); keySetMeta (se, "namespace/#0", "system"); k = ksLookupByName (ks, "/first", 0); succeed_if_same_string (keyString (k), "default is ok"); keySetMeta (se, "override/#0", "/abc"); k = ksLookupByName (ks, "/first", 0); succeed_if (k == p, "did not find proc/abc"); keySetMeta (s, "namespace/#0", "system"); k = ksLookupByName (ks, "/first", 0); succeed_if (k == y, "did not find system key"); keySetMeta (s, "namespace/#0", "system"); keySetMeta (s, "namespace/#1", "user"); k = ksLookupByName (ks, "/first", 0); succeed_if (k == y, "did not find system key"); keySetMeta (s, "namespace/#0", "proc"); keySetMeta (s, "namespace/#1", "user"); k = ksLookupByName (ks, "/first", 0); succeed_if (k == p, "did not find proc key"); keySetMeta (s, "namespace/#0", "dir"); keySetMeta (s, "namespace/#1", 0); k = ksLookupByName (ks, "/first", 0); succeed_if_same_string (keyString (k), "default is ok"); keySetMeta (s, "override/#0", "proc/first"); k = ksLookupByName (ks, "/first", 0); succeed_if (k == pe, "did not find override key (double indirect)"); keySetMeta (s, "override/#0", "dir/first"); k = ksLookupByName (ks, "/first", 0); succeed_if_same_string (keyString (k), "default is ok"); ksDel (ks); }
/** * Gets the size of an array. * * @param elektra The Elektra instance to use. * @param name The (relative) name of the array. * @return the size of the array */ size_t elektraArraySize (Elektra * elektra, const char * name) { elektraSetLookupKey (elektra, name); KeySet * arrayKeys = elektraArrayGet (elektra->lookupKey, elektra->config); size_t size = (size_t) ksGetSize (arrayKeys); ksDel (arrayKeys); return size; }
/** * Return all the array keys below the given arrayparent * The arrayparent itself is not returned. * For example, if user/config/# is an array, * user/config is the array parent. * Only the direct array keys will be returned. This means * that for example user/config/#1/key will not be included, * but only user/config/#1. * * A new keyset will be allocated for the resulting keys. * This means that the caller must ksDel the resulting keyset. * * @param arrayParent the parent of the array to be returned * @param keys the keyset containing the array keys. * * @return a keyset containing the arraykeys (if any) * @retval NULL on NULL pointers */ KeySet *elektraArrayGet(const Key *arrayParent, KeySet *keys) { if (!arrayParent) return 0; if (!keys) return 0; KeySet *arrayKeys = ksNew(ksGetSize(keys), KS_END); elektraKsFilter(arrayKeys, keys, &arrayFilter, (void *)arrayParent); return arrayKeys; }
/** * @brief Bootstrap, first phase with fallback * @internal * * @param handle already allocated, but without defaultBackend * @param [out] keys for bootstrapping * @param errorKey key to add errors too * * @retval -1 failure: cannot initialize defaultBackend * @retval 0 warning: could not get initial config * @retval 1 success * @retval 2 success in fallback mode */ int elektraOpenBootstrap (KDB * handle, KeySet * keys, Key * errorKey) { handle->defaultBackend = backendOpenDefault (handle->modules, KDB_DB_INIT, errorKey); if (!handle->defaultBackend) return -1; handle->split = splitNew (); splitAppend (handle->split, handle->defaultBackend, keyNew (KDB_SYSTEM_ELEKTRA, KEY_END), 2); keySetName (errorKey, KDB_SYSTEM_ELEKTRA); keySetString (errorKey, "kdbOpen(): get"); int funret = 1; int ret = kdbGet (handle, keys, errorKey); int fallbackret = 0; if (ret == 0 || ret == -1) { // could not get KDB_DB_INIT, try KDB_DB_FILE // first cleanup: ksClear (keys); backendClose (handle->defaultBackend, errorKey); splitDel (handle->split); // then create new setup: handle->defaultBackend = backendOpenDefault (handle->modules, KDB_DB_FILE, errorKey); if (!handle->defaultBackend) { elektraRemoveMetaData (errorKey, "error"); // fix errors from kdbGet() return -1; } handle->split = splitNew (); splitAppend (handle->split, handle->defaultBackend, keyNew (KDB_SYSTEM_ELEKTRA, KEY_END), 2); keySetName (errorKey, KDB_SYSTEM_ELEKTRA); keySetString (errorKey, "kdbOpen(): get fallback"); fallbackret = kdbGet (handle, keys, errorKey); keySetName (errorKey, "system/elektra/mountpoints"); KeySet * cutKeys = ksCut (keys, errorKey); if (fallbackret == 1 && ksGetSize (cutKeys) != 0) { funret = 2; } ksAppend (keys, cutKeys); ksDel (cutKeys); } if (ret == -1 && fallbackret == -1) { funret = 0; } elektraRemoveMetaData (errorKey, "error"); // fix errors from kdbGet() return funret; }
static void test_ksGetSize (const size_t storagePlugin, const char * tmpFile) { Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END); open_storage_plugin (storagePlugin); Plugin * plugin = plugins[storagePlugin]; KeySet * ks = simpleTestKeySet (); ssize_t origSize = ksGetSize (ks); succeed_if (origSize > 0, "ks was empty before kdbSet"); succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful"); ksDel (ks); ks = ksNew (0, KS_END); succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful"); ssize_t returnedSize = ksGetSize (ks); succeed_if (origSize == returnedSize, "ksGetSize before and after kdbSet, kdbGet differ"); keyDel (parentKey); ksDel (ks); closeStoragePlugin (storagePlugin); }
// test simple variable passing static void test_variable_passing (void) { printf ("Testing simple variable passing...\n"); KeySet * conf = ksNew (1, keyNew ("user/script", KEY_VALUE, srcdir_file ("lua/lua_plugin.lua"), KEY_END), keyNew ("user/print", KEY_END), KS_END); PLUGIN_OPEN ("lua"); Key * parentKey = keyNew ("user/from_c", KEY_END); KeySet * ks = ksNew (0, KS_END); succeed_if (plugin->kdbGet (plugin, ks, parentKey) >= 1, "call to kdbGet was not successful"); succeed_if (ksGetSize (ks) == 1, "keyset size is still 0"); succeed_if (ksGetSize (ks) == 1 && !strcmp (keyName (ksHead (ks)), "user/from_lua"), "key in keyset has wrong name"); succeed_if (output_warnings (parentKey), "warnings in kdbOpen"); succeed_if (output_error (parentKey), "errors in kdbOpen"); ksDel (ks); keyDel (parentKey); PLUGIN_CLOSE (); }
/* The KeySet MUST be sorted alphabetically (or at least ascending * by the length of keynames) for this function to work */ static Key * findNearestParent (Key * key, KeySet * ks) { Key * current; ksSetCursor (ks, ksGetSize (ks) - 1); while ((current = ksPrev (ks)) != 0) { if (keyIsBelow (current, key)) { return current; } } return 0; }
static void test_mmap_empty_after_clear (const char * tmpFile) { Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END); KeySet * conf = ksNew (0, KS_END); PLUGIN_OPEN ("mmapstorage"); KeySet * returned = ksNew (0, KS_END); succeed_if (plugin->kdbGet (plugin, returned, parentKey) == 1, "kdbGet was not successful"); succeed_if (ksGetSize (returned) == 0, "KeySet not empty after clear (or nullptr)"); ksDel (returned); keyDel (parentKey); PLUGIN_CLOSE (); }
//! [f] void f (KeySet * iterator, KeySet * lookup) { KeySet * append = ksNew (ksGetSize (lookup), KS_END); Key * key; Key * current; ksRewind (iterator); while ((current = ksNext (iterator))) { key = ksLookup (lookup, current, KDB_O_POP); // do something... ksAppendKey (append, key); // now append it to append, not lookup! keyDel (key); // make sure to ALWAYS delete poped keys. } ksAppend (lookup, append); // now lookup needs to be sorted only once, append never ksDel (append); }
static void flushConvertedKeys (Key * target, KeySet * converted, KeySet * orig) { if (ksGetSize (converted) == 0) return; ksRewind (converted); Key * current; Key * appendTarget; while ((current = ksNext (converted))) { appendTarget = target; const char * metaName = keyString (keyGetMeta (current, CONVERT_METANAME)); Key * currentDup = keyDup (current); Key * targetDup = keyDup (appendTarget); keySetBaseName (currentDup, 0); keySetBaseName (targetDup, 0); /* the convert key request to be converted to a key * on the same level, but the target is below or above */ if (keyGetMeta (current, CONVERT_APPEND_SAMELEVEL) && keyCmp (currentDup, targetDup)) { appendTarget = 0; } keyDel (currentDup); keyDel (targetDup); /* no target key was found of the target * was discarded for some reason. Revert to the parent */ if (!appendTarget) { appendTarget = findNearestParent (current, orig); } elektraKeyAppendMetaLine (appendTarget, metaName, keyString (current)); removeKeyFromResult (current, target, orig); } ksClear (converted); }
/** * Generate a C-Style keyset and stream it. * * This keyset can be used to include as c-code for * applikations using elektra. * * The options takes the same options as kdbGet() * and kdbSet(). * * @param ks the keyset to work with * @param stream the file pointer where to send the stream * @param options which keys not to output * @retval 1 on success * @ingroup stream */ int ksGenerate (const KeySet * ks, FILE * stream, option_t options) { Key * key; KeySet * cks = ksDup (ks); ksRewind (cks); fprintf (stream, "ksNew (%d,\n", (int) ksGetSize (cks)); while ((key = ksNext (cks)) != 0) { if (options & KDB_O_INACTIVE) if (key && keyIsInactive (key)) continue; keyGenerate (key, stream, options); fprintf (stream, ",\n"); } fprintf (stream, "\tKS_END);\n"); ksDel (cks); return 1; }
/** * Output all information of a keyset. * * The format is not very strict and only intend to be read * by human eyes for debugging purposes. Don't rely on the * format in your applications. * * Keys are printed line per line with keyOutput(). * * The same options as keyOutput() are taken and passed * to them. * * Additional KDB_O_HEADER will print the number of keys * as first line. * * @param ks the keyset to work with * @param stream the file pointer where to send the stream * @param options * @see keyOutput() * @retval 1 on success * @retval -1 on allocation errors * @ingroup stream */ int ksOutput(const KeySet *ks, FILE *stream, option_t options) { Key *key; KeySet *cks = ksDup (ks); size_t size = 0; ksRewind (cks); if (KDB_O_HEADER & options) { fprintf(stream,"Output keyset of size %d\n", (int)ksGetSize(cks)); } while ( (key = ksNext(cks)) != NULL) { if (options & KDB_O_SHOWINDICES) fprintf(stream, "[%d] ", (int)size); keyOutput (key,stream,options); size ++; } ksDel (cks); return 1; }
static void test_getArray (void) { printf ("Test get array"); KeySet * keys = ksNew (10, keyNew ("user/test/key1", KEY_END), keyNew ("user/test/key2", KEY_END), keyNew ("user/test/array", KEY_END), keyNew ("user/test/array/#0", KEY_END), keyNew ("user/test/array/#0/below", KEY_END), keyNew ("user/test/array/#1", KEY_END), keyNew ("user/test/yetanotherkey", KEY_END), KS_END); Key * arrayParent = keyNew ("user/test/array", KEY_END); KeySet * array = elektraArrayGet (arrayParent, keys); succeed_if (array, "The getarray function did not return a proper keyset"); succeed_if (ksGetSize (array) == 2, "the array contains a wrong number of elements"); succeed_if (ksLookupByName (array, "user/test/array/#0", KDB_O_NONE), "the array does not contain #0"); succeed_if (ksLookupByName (array, "user/test/array/#1", KDB_O_NONE), "the array does not contain #1"); keyDel (arrayParent); ksDel (array); ksDel (keys); }
/** * Builds an array of pointers to the keys in the supplied keyset. * The keys are not copied, calling keyDel may remove them from * the keyset. * * The size of the buffer can be easily allocated via ksGetSize. Example: * @code * KeySet *ks = somekeyset; * Key **keyArray = calloc (ksGetSize(ks), sizeof (Key *)); * elektraKsToMemArray (ks, keyArray); * ... work with the array ... * elektraFree (keyArray); * @endcode * * @param ks the keyset object to work with * @param buffer the buffer to put the result into * @return the number of elements in the array if successful * @return a negative number on null pointers or if an error occurred */ int elektraKsToMemArray (KeySet * ks, Key ** buffer) { if (!ks) return -1; if (!buffer) return -1; /* clear the received buffer */ memset (buffer, 0, ksGetSize (ks) * sizeof (Key *)); cursor_t cursor = ksGetCursor (ks); ksRewind (ks); size_t idx = 0; Key * key; while ((key = ksNext (ks)) != 0) { buffer[idx] = key; ++idx; } ksSetCursor (ks, cursor); return idx; }
static void test_revmoreiterate() { printf ("Test revmoreiterate trie\n"); for (int i=0; i<5; ++i) { Trie *trie = 0; switch (i) { case 0: trie = test_insert (trie, "user/tests", "tests"); trie = test_insert (trie, "user/tests/hosts", "hosts"); trie = test_insert (trie, "user/tests/hosts/below", "below"); trie = test_insert (trie, "system/tests", "systests"); trie = test_insert (trie, "system/tests/hosts", "syshosts"); trie = test_insert (trie, "system/tests/hosts/below", "sysbelow"); trie = test_insert (trie, "system", "system"); trie = test_insert (trie, "user", "user"); break; case 1: trie = test_insert (trie, "system/tests/hosts", "syshosts"); trie = test_insert (trie, "system", "system"); trie = test_insert (trie, "user/tests", "tests"); trie = test_insert (trie, "user/tests/hosts", "hosts"); trie = test_insert (trie, "user/tests/hosts/below", "below"); trie = test_insert (trie, "system/tests", "systests"); trie = test_insert (trie, "user", "user"); trie = test_insert (trie, "system/tests/hosts/below", "sysbelow"); break; case 2: trie = test_insert (trie, "system/tests/hosts/below", "sysbelow"); trie = test_insert (trie, "system/tests/hosts", "syshosts"); trie = test_insert (trie, "user/tests/hosts/below", "below"); trie = test_insert (trie, "user/tests/hosts", "hosts"); trie = test_insert (trie, "user/tests", "tests"); trie = test_insert (trie, "user", "user"); trie = test_insert (trie, "system/tests", "systests"); trie = test_insert (trie, "system", "system"); break; case 3: trie = test_insert (trie, "user/tests/hosts/below", "below"); trie = test_insert (trie, "user/tests/hosts", "hosts"); trie = test_insert (trie, "user/tests", "tests"); trie = test_insert (trie, "user", "user"); trie = test_insert (trie, "system/tests/hosts/below", "sysbelow"); trie = test_insert (trie, "system/tests/hosts", "syshosts"); trie = test_insert (trie, "system/tests", "systests"); trie = test_insert (trie, "system", "system"); break; case 4: trie = test_insert (trie, "system/tests/hosts/below", "sysbelow"); trie = test_insert (trie, "system/tests/hosts", "syshosts"); trie = test_insert (trie, "system/tests", "systests"); trie = test_insert (trie, "system", "system"); trie = test_insert (trie, "user/tests/hosts/below", "below"); trie = test_insert (trie, "user/tests/hosts", "hosts"); trie = test_insert (trie, "user/tests", "tests"); trie = test_insert (trie, "user", "user"); break; } KeySet *mps = set_mountpoints(); exit_if_fail (trie, "trie was not build up successfully"); Key *searchKey = keyNew(0); keySetName(searchKey, "user"); Backend *backend = elektraTrieLookup(trie, searchKey); succeed_if (backend, "there should be a backend"); compare_key(backend->mountpoint, ksLookupByName(mps, "user",0)); // printf ("backend: %p\n", (void*)backend); keySetName(searchKey, "user/tests/hosts/other/below"); Backend *b2 = elektraTrieLookup(trie, searchKey); succeed_if (b2, "there should be a backend"); compare_key(b2->mountpoint, ksLookupByName(mps, "user/tests/hosts",0)); // printf ("b2: %p\n", (void*)b2); keySetName(searchKey, "user/tests/hosts/other/deep/below"); b2 = elektraTrieLookup(trie, searchKey); succeed_if (b2, "there should be a backend"); compare_key(b2->mountpoint, ksLookupByName(mps, "user/tests/hosts",0)); keySetName(searchKey, "user/tests/hosts/below"); Backend *b3 = elektraTrieLookup(trie, searchKey); succeed_if (b3, "there should be a backend"); compare_key(b3->mountpoint, ksLookupByName(mps, "user/tests/hosts/below",0)); backend = b3; // printf ("b3: %p\n", (void*)b3); keySetName(searchKey, "user/tests/hosts/below/other/deep/below"); b2 = elektraTrieLookup(trie, searchKey); succeed_if (b3, "there should be a backend"); compare_key(b3->mountpoint, ksLookupByName(mps, "user/tests/hosts/below",0)); keySetName(searchKey, "system"); backend = elektraTrieLookup(trie, searchKey); succeed_if (backend, "there should be a backend"); compare_key(backend->mountpoint, ksLookupByName(mps, "system",0)); // printf ("backend: %p\n", (void*)backend); keySetName(searchKey, "system/tests/hosts/other/below"); b2 = elektraTrieLookup(trie, searchKey); succeed_if (b2, "there should be a backend"); compare_key(b2->mountpoint, ksLookupByName(mps, "system/tests/hosts",0)); // printf ("b2: %p\n", (void*)b2); keySetName(searchKey, "system/tests/hosts/other/deep/below"); b2 = elektraTrieLookup(trie, searchKey); succeed_if (b2, "there should be a backend"); compare_key(b2->mountpoint, ksLookupByName(mps, "system/tests/hosts",0)); keySetName(searchKey, "system/tests/hosts/below"); b3 = elektraTrieLookup(trie, searchKey); succeed_if (b3, "there should be a backend"); compare_key(b3->mountpoint, ksLookupByName(mps, "system/tests/hosts/below",0)); backend = b3; // printf ("b3: %p\n", (void*)b3); keySetName(searchKey, "system/tests/hosts/below/other/deep/below"); b2 = elektraTrieLookup(trie, searchKey); succeed_if (b3, "there should be a backend"); compare_key(b3->mountpoint, ksLookupByName(mps, "system/tests/hosts/below",0)); /* printf ("---------\n"); output_trie(trie); */ KeySet *mps_cmp = ksNew(0, KS_END); collect_mountpoints(trie, mps_cmp); succeed_if (ksGetSize(mps_cmp) == 8, "size should be 8"); compare_keyset(mps, mps_cmp); ksDel (mps_cmp); ksDel (mps); elektraTrieClose(trie, 0); keyDel (searchKey); } // end for }