/** * Closes the session with the Key database. * * @pre The handle must be a valid handle as returned from kdbOpen() * * @pre errorKey must be a valid key, e.g. created with keyNew() * * This is the counterpart of kdbOpen(). * * You must call this method when you finished your affairs with the key * database. You can manipulate Key and KeySet objects also after * kdbClose(), but you must not use any kdb*() call afterwards. * * The @p handle parameter will be finalized and all resources associated to it * will be freed. After a kdbClose(), the @p handle cannot be used anymore. * * @param handle contains internal information of * @link kdbOpen() opened @endlink key database * @param errorKey the key which holds error/warning information * @retval 0 on success * @retval -1 on NULL pointer * @ingroup kdb */ int kdbClose (KDB * handle, Key * errorKey) { if (!handle) { return -1; } Key * initialParent = keyDup (errorKey); int errnosave = errno; splitDel (handle->split); trieClose (handle->trie, errorKey); backendClose (handle->defaultBackend, errorKey); handle->defaultBackend = 0; // not set in fallback mode, so lets check: if (handle->initBackend) { backendClose (handle->initBackend, errorKey); handle->initBackend = 0; } for (int i = 0; i < NR_GLOBAL_POSITIONS; ++i) { for (int j = 0; j < NR_GLOBAL_SUBPOSITIONS; ++j) { elektraPluginClose (handle->globalPlugins[i][j], errorKey); } } if (handle->modules) { elektraModulesClose (handle->modules, errorKey); ksDel (handle->modules); } else { ELEKTRA_ADD_WARNING (47, errorKey, "modules were not open"); } elektraFree (handle); keySetName (errorKey, keyName (initialParent)); keySetString (errorKey, keyString (initialParent)); keyDel (initialParent); errno = errnosave; return 0; }
static void test_default () { printf ("Test default " KDB_DEFAULT_STORAGE "\n"); KeySet * modules = ksNew (0, KS_END); elektraModulesInit (modules, 0); Plugin * plugin = elektraPluginOpen (KDB_DEFAULT_STORAGE, modules, set_pluginconf (), 0); exit_if_fail (plugin, "KDB_DEFAULT_STORAGE: " KDB_DEFAULT_STORAGE " plugin could not be loaded"); KeySet * test_config = set_pluginconf (); KeySet * config = elektraPluginGetConfig (plugin); succeed_if (config != 0, "there should be a config"); compare_keyset (config, test_config); ksDel (test_config); succeed_if (plugin->kdbGet != 0, "no get pointer"); succeed_if (plugin->kdbSet != 0, "no set pointer"); elektraPluginClose (plugin, 0); Backend * backend = backendOpenDefault (modules, KDB_DB_FILE, 0); Key * mp; succeed_if ((mp = backend->mountpoint) != 0, "no mountpoint found"); succeed_if_same_string (keyName (mp), ""); succeed_if_same_string (keyString (mp), "default"); backendClose (backend, 0); elektraModulesClose (modules, 0); ksDel (modules); }
static void kdb_del (KDB * kdb) { backendClose (kdb->defaultBackend, 0); trieClose (kdb->trie, 0); splitDel (kdb->split); elektraFree (kdb); }
/** * @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_backref () { printf ("Test back references\n"); KeySet * modules = ksNew (0, KS_END); elektraModulesInit (modules, 0); Backend * backend = backendOpen (set_backref (), modules, 0); succeed_if (backend != 0, "there should be a backend"); succeed_if (backend->getplugins[0] == 0, "there should be no plugin"); exit_if_fail (backend->getplugins[1] != 0, "there should be a plugin"); succeed_if (backend->getplugins[2] == 0, "there should be no plugin"); succeed_if (backend->setplugins[0] == 0, "there should be no plugin"); exit_if_fail (backend->setplugins[1] != 0, "there should be a plugin"); succeed_if (backend->setplugins[2] == 0, "there should be no plugin"); Key * mp; succeed_if ((mp = backend->mountpoint) != 0, "no mountpoint found"); succeed_if_same_string (keyName (mp), "user/tests/backend/backref"); succeed_if_same_string (keyString (mp), "backref"); Plugin * plugin1 = backend->getplugins[1]; Plugin * plugin2 = backend->setplugins[1]; Plugin * plugin3 = backend->errorplugins[1]; succeed_if (plugin1 != 0, "there should be a plugin"); succeed_if (plugin2 != 0, "there should be a plugin"); succeed_if (plugin3 != 0, "there should be a plugin"); succeed_if (plugin1 == plugin2, "it should be the same plugin"); succeed_if (plugin2 == plugin3, "it should be the same plugin"); succeed_if (plugin1 == plugin3, "it should be the same plugin"); succeed_if (plugin1->refcounter == 3, "ref counter should be 3"); KeySet * test_config = set_pluginconf (); KeySet * config = elektraPluginGetConfig (plugin1); succeed_if (config != 0, "there should be a config"); compare_keyset (config, test_config); ksDel (test_config); succeed_if (plugin1->kdbGet != 0, "no get pointer"); succeed_if (plugin1->kdbSet != 0, "no set pointer"); succeed_if (plugin2->kdbGet != 0, "no get pointer"); succeed_if (plugin2->kdbSet != 0, "no set pointer"); backendClose (backend, 0); elektraModulesClose (modules, 0); ksDel (modules); }
static void test_simple () { printf ("Test simple building of backend\n"); KeySet * modules = ksNew (0, KS_END); elektraModulesInit (modules, 0); Key * errorKey = 0; Backend * backend = backendOpen (set_simple (), modules, errorKey); succeed_if (backend->errorplugins[0] == 0, "there should be no plugin"); succeed_if (backend->errorplugins[2] == 0, "there should be no plugin"); succeed_if (backend->errorplugins[3] == 0, "there should be no plugin"); succeed_if (backend->errorplugins[4] == 0, "there should be no plugin"); succeed_if (backend->errorplugins[5] == 0, "there should be no plugin"); succeed_if (backend->errorplugins[6] == 0, "there should be no plugin"); succeed_if (backend->errorplugins[7] == 0, "there should be no plugin"); succeed_if (backend->errorplugins[8] == 0, "there should be no plugin"); succeed_if (backend->errorplugins[9] == 0, "there should be no plugin"); exit_if_fail (backend->errorplugins[1] != 0, "there should be a plugin"); succeed_if (backend->getplugins[0] == 0, "there should be no plugin"); succeed_if (backend->getplugins[2] == 0, "there should be no plugin"); succeed_if (backend->getplugins[3] == 0, "there should be no plugin"); succeed_if (backend->getplugins[4] == 0, "there should be no plugin"); succeed_if (backend->getplugins[5] == 0, "there should be no plugin"); succeed_if (backend->getplugins[6] == 0, "there should be no plugin"); succeed_if (backend->getplugins[7] == 0, "there should be no plugin"); succeed_if (backend->getplugins[8] == 0, "there should be no plugin"); succeed_if (backend->getplugins[9] == 0, "there should be no plugin"); exit_if_fail (backend->getplugins[1] != 0, "there should be a plugin"); succeed_if (backend->setplugins[0] == 0, "there should be no plugin"); succeed_if (backend->setplugins[2] == 0, "there should be no plugin"); succeed_if (backend->setplugins[3] == 0, "there should be no plugin"); succeed_if (backend->setplugins[4] == 0, "there should be no plugin"); succeed_if (backend->setplugins[5] == 0, "there should be no plugin"); succeed_if (backend->setplugins[6] == 0, "there should be no plugin"); succeed_if (backend->setplugins[7] == 0, "there should be no plugin"); succeed_if (backend->setplugins[8] == 0, "there should be no plugin"); succeed_if (backend->setplugins[9] == 0, "there should be no plugin"); exit_if_fail (backend->setplugins[1] != 0, "there should be a plugin"); Key * mp; succeed_if ((mp = backend->mountpoint) != 0, "no mountpoint found"); succeed_if_same_string (keyName (mp), "user/tests/backend/simple"); succeed_if_same_string (keyString (mp), "simple"); Plugin * plugin = backend->getplugins[1]; KeySet * test_config = set_pluginconf (); KeySet * config = elektraPluginGetConfig (plugin); succeed_if (config != 0, "there should be a config"); compare_keyset (config, test_config); ksDel (test_config); succeed_if (plugin->kdbGet != 0, "no get pointer"); succeed_if (plugin->kdbSet != 0, "no set pointer"); backendClose (backend, errorKey); elektraModulesClose (modules, 0); ksDel (modules); }
/** * @brief Opens the session with the Key database. * * @pre errorKey must be a valid key, e.g. created with keyNew() * * The method will bootstrap itself the following way. * The first step is to open the default backend. With it * system/elektra/mountpoints will be loaded and all needed * libraries and mountpoints will be determined. * These libraries for backends will be loaded and with it the * @p KDB data structure will be initialized. * * You must always call this method before retrieving or committing any * keys to the database. In the end of the program, * after using the key database, you must not forget to kdbClose(). * * The pointer to the @p KDB structure returned will be initialized * like described above, and it must be passed along on any kdb*() * method your application calls. * * Get a @p KDB handle for every thread using elektra. Don't share the * handle across threads, and also not the pointer accessing it: * * @snippet kdbopen.c open * * You don't need kdbOpen() if you only want to * manipulate plain in-memory Key or KeySet objects. * * @pre errorKey must be a valid key, e.g. created with keyNew() * * @param errorKey the key which holds errors and warnings which were issued * @see kdbGet(), kdbClose() to end all affairs to the key database. * @retval handle on success * @retval NULL on failure * @ingroup kdb */ KDB * kdbOpen (Key * errorKey) { if (!errorKey) { ELEKTRA_LOG ("no error key passed"); return 0; } ELEKTRA_LOG ("called with %s", keyName (errorKey)); int errnosave = errno; KDB * handle = elektraCalloc (sizeof (struct _KDB)); Key * initialParent = keyDup (errorKey); handle->modules = ksNew (0, KS_END); if (elektraModulesInit (handle->modules, errorKey) == -1) { ksDel (handle->modules); elektraFree (handle); ELEKTRA_SET_ERROR (94, errorKey, "elektraModulesInit returned with -1"); keySetName (errorKey, keyName (initialParent)); keySetString (errorKey, keyString (initialParent)); keyDel (initialParent); errno = errnosave; return 0; } KeySet * keys = ksNew (0, KS_END); int inFallback = 0; switch (elektraOpenBootstrap (handle, keys, errorKey)) { case -1: ksDel (handle->modules); elektraFree (handle); ELEKTRA_SET_ERROR (40, errorKey, "could not open default backend"); keySetName (errorKey, keyName (initialParent)); keySetString (errorKey, keyString (initialParent)); keyDel (initialParent); errno = errnosave; return 0; case 0: ELEKTRA_ADD_WARNING (17, errorKey, "Initial kdbGet() failed, you should either fix " KDB_DB_INIT " or the fallback " KDB_DB_FILE); break; case 2: ELEKTRA_LOG ("entered fallback code for bootstrapping"); inFallback = 1; break; } keySetString (errorKey, "kdbOpen(): mountGlobals"); if (mountGlobals (handle, ksDup (keys), handle->modules, errorKey) == -1) { // mountGlobals also sets a warning containing the name of the plugin that failed to load ELEKTRA_ADD_WARNING (139, errorKey, "Mounting global plugins failed"); } keySetName (errorKey, keyName (initialParent)); keySetString (errorKey, "kdbOpen(): backendClose"); backendClose (handle->defaultBackend, errorKey); splitDel (handle->split); handle->defaultBackend = 0; handle->trie = 0; #ifdef HAVE_LOGGER if (inFallback) ELEKTRA_LOG_WARNING ("fallback for bootstrapping: you might want to run `kdb upgrade-bootstrap`"); Key * key; ksRewind (keys); for (key = ksNext (keys); key; key = ksNext (keys)) { ELEKTRA_LOG_DEBUG ("config for createTrie name: %s value: %s", keyName (key), keyString (key)); } #endif handle->split = splitNew (); keySetString (errorKey, "kdbOpen(): mountOpen"); // Open the trie, keys will be deleted within mountOpen if (mountOpen (handle, keys, handle->modules, errorKey) == -1) { ELEKTRA_ADD_WARNING (93, errorKey, "Initial loading of trie did not work"); } keySetString (errorKey, "kdbOpen(): mountDefault"); if (mountDefault (handle, handle->modules, inFallback, errorKey) == -1) { ELEKTRA_SET_ERROR (40, errorKey, "could not reopen and mount default backend"); keySetString (errorKey, "kdbOpen(): close"); kdbClose (handle, errorKey); keySetName (errorKey, keyName (initialParent)); keySetString (errorKey, keyString (initialParent)); keyDel (initialParent); errno = errnosave; return 0; } keySetString (errorKey, "kdbOpen(): mountVersion"); mountVersion (handle, errorKey); keySetString (errorKey, "kdbOpen(): mountModules"); if (mountModules (handle, handle->modules, errorKey) == -1) { ELEKTRA_ADD_WARNING (92, errorKey, "Mounting modules did not work"); } keySetName (errorKey, keyName (initialParent)); keySetString (errorKey, keyString (initialParent)); keyDel (initialParent); errno = errnosave; return handle; }