Exemple #1
0
int GetCommand::execute (Cmdline const & cl)
{
	if (cl.arguments.size () != 1) throw invalid_argument ("Need one argument");

	KeySet conf;

	kdb::Key root = cl.createKey (0);
	kdb::KDB kdb (root);

	std::string n;
	if (cl.all)
	{
		n = root.getName ();
		root.setName ("/");
	}

	kdb.get (conf, root);

	if (cl.all)
	{
		root.setName (n);
	}

	// do a lookup without tracer to warm up default cache
	conf.lookup (root);

	root.setCallback (warnOnMeta);
	if (cl.verbose)
	{
		cout << "got " << conf.size () << " keys" << std::endl;
		root.setCallback (printTrace);
	}
	Key k = conf.lookup (root);

	int ret = 0;

	if (k)
	{
		if (cl.verbose)
		{
			cout << "The resulting keyname is " << k.getName () << std::endl;
		}
		cout << k.getString ();
	}
	else
	{
		cerr << "Did not find key";
		ret = 1;
	}

	if (!cl.noNewline)
	{
		cout << endl;
	}

	printWarnings (cerr, root);
	printError (cerr, root);

	return ret;
}
Exemple #2
0
/**
 * @brief give info about current mounted backends
 *
 * @param mountConf a keyset that contains everything below
 * Backends::mountpointsPath
 *
 * @return an vector of information about mounted backends
 */
Backends::BackendInfoVector Backends::getBackendInfo (KeySet mountConf)
{
	std::vector<BackendInfo> ret;
	Key rootKey (Backends::mountpointsPath, KEY_END);
	Key cur;

	mountConf.rewind ();
	while ((cur = mountConf.next ()))
	{
		if (cur.isDirectBelow (rootKey))
		{
			BackendInfo bi;

			Key path = mountConf.lookup (cur.getName () + "/config/path");
			if (path)
			{
				bi.path = path.getString ();
			}
			Key mp = mountConf.lookup (cur.getName () + "/mountpoint");
			if (mp)
			{
				bi.mountpoint = mp.getString ();
			}
			bi.name = cur.getBaseName ();

			ret.push_back (bi);
		}
	}
	return ret;
}
Exemple #3
0
	TypeChecker(KeySet config)
	{
		enforce = config.lookup("/enforce");
		Key k = config.lookup("/require_version");
		if (k && k.getString() != "2") throw "Required Version does not match 2";

		types.insert (pair<string, Type*>("short", new MType<kdb::short_t>()));
		types.insert (pair<string, Type*>("unsigned_short", new MType<kdb::unsigned_short_t>()));
		types.insert (pair<string, Type*>("long", new MType<kdb::long_t>()));
		types.insert (pair<string, Type*>("unsigned_long", new MType<kdb::unsigned_long_t>()));
		types.insert (pair<string, Type*>("long_long", new MType<kdb::long_long_t>()));
		types.insert (pair<string, Type*>("unsigned_long_long", new MType<kdb::unsigned_long_long_t>()));

		types.insert (pair<string, Type*>("float", new TType<kdb::float_t>()));
		types.insert (pair<string, Type*>("double", new TType<kdb::double_t>()));
		types.insert (pair<string, Type*>("long_double", new TType<kdb::long_double_t>()));
		types.insert (pair<string, Type*>("char", new TType<kdb::char_t>()));
		types.insert (pair<string, Type*>("boolean", new TType<kdb::boolean_t>()));
		types.insert (pair<string, Type*>("octet", new TType<kdb::octet_t>()));

		// non-standard types (deprecated, just for
		// compatibility):
		types.insert (pair<string, Type*>("any", new AnyType()));
		types.insert (pair<string, Type*>("empty", new EmptyType()));
		types.insert (pair<string, Type*>("FSType", new FSType()));
		types.insert (pair<string, Type*>("string", new StringType()));
	}
TEST (test_contextual_policy, setPolicy)
{
	using namespace kdb;
	KeySet ks;
	Context c;
	// clang-format off
	ContextualValue<int, SetPolicyIs<MySetPolicy<int>>> cv
		(ks, c, Key("/test",
			KEY_CASCADING_NAME,
			KEY_VALUE, "/test",
			KEY_META, "default", "88",
			KEY_END));
	// clang-format on
	EXPECT_EQ (cv, 88);
	EXPECT_EQ (cv, 88);
	EXPECT_TRUE (ks.lookup ("/test")) << "did not find /test";
	EXPECT_FALSE (ks.lookup ("dir/test")) << "found dir/test wrongly";
	cv = 40;
	EXPECT_EQ (cv, 40);
	cv.syncKeySet ();
	EXPECT_EQ (cv, 40);
	// TODO: setPolicy not working correctly
	EXPECT_TRUE (ks.lookup ("/test")) << "did not find /test";
	EXPECT_TRUE (ks.lookup ("dir/test")) << "could not find dir/test";
}
Exemple #5
0
std::vector<PluginSpec> PluginVariantDatabase::getPluginVariantsFromSysconf (PluginSpec const & whichplugin, KeySet const & sysconf,
									     KeySet const & genconfToIgnore) const
{
	std::vector<PluginSpec> result;

	KeySet ksSysconf (sysconf);

	// first find possible variants
	Key kVariantBase ("system/elektra/plugins", KEY_END);
	kVariantBase.addBaseName (whichplugin.getName ());
	kVariantBase.addBaseName ("variants");

	KeySet ksPluginVariantSysconf (ksSysconf.cut (kVariantBase));
	KeySet ksToIterate (ksPluginVariantSysconf);
	for (auto kCurrent : ksToIterate)
	{
		Key kCurrentTest (kVariantBase);
		kCurrentTest.addBaseName (kCurrent.getBaseName ());
		if (kCurrentTest == kCurrent)
		{
			PluginSpec variant (whichplugin);
			KeySet ksVariantConfToAdd;

			// new base for plugin conf
			Key kVariantPluginConf ("system/", KEY_END);

			// add system conf for plugin variant
			Key kVariantSysconf (this->buildVariantSysconfKey (whichplugin, kCurrent.getBaseName (), "config"));
			this->addKeysBelowKeyToConf (kVariantSysconf, ksPluginVariantSysconf, kVariantPluginConf, ksVariantConfToAdd);

			// check if the variant was disabled : system/elektra/plugins/simpleini/variants/space/disable
			Key kDisable = sysconf.lookup (this->buildVariantSysconfKey (whichplugin, kCurrent.getBaseName (), "disable"));
			if (kDisable && kDisable.getString () == "1")
			{
				continue; // skip this variant
			}

			// check if the variant is in the genconfToIgnore list
			Key kGenconfVariant (kVariantPluginConf);
			kGenconfVariant.addBaseName (kCurrent.getBaseName ());
			Key kIgnore = genconfToIgnore.lookup (kGenconfVariant);
			if (kIgnore)
			{
				continue; // this variant was added by genconf already
			}

			if (ksVariantConfToAdd.size () == 0)
			{
				continue; // no config means no variant
			}

			variant.appendConfig (ksVariantConfToAdd);
			result.push_back (variant);
		}
	}

	return result;
}
Exemple #6
0
std::vector<PluginSpec> PluginVariantDatabase::getPluginVariantsFromGenconf (PluginSpec const & whichplugin, KeySet const & genconf,
									     KeySet const & sysconf) const
{
	std::vector<PluginSpec> result;

	KeySet ksToIterate (genconf);
	for (auto kCurrent : ksToIterate)
	{
		Key kCurrentTest (kCurrent.getNamespace () + "/", KEY_END);
		kCurrentTest.addBaseName (kCurrent.getBaseName ()); // e.g. system/space
		if (kCurrentTest == kCurrent)
		{
			PluginSpec variant (whichplugin);
			KeySet ksVariantConfToAdd;

			// new base for plugin conf
			Key kVariantPluginConf ("system/", KEY_END);

			// take variant config from genconf and transform it to proper plugin conf,
			// e.g. system/space/config/format -> system/format
			Key kVariantConf (kCurrentTest);
			kVariantConf.addBaseName ("config"); // e.g. system/space/config
			this->addKeysBelowKeyToConf (kVariantConf, genconf, kVariantPluginConf, ksVariantConfToAdd);

			// TODO plugin infos

			// check if the variant was disabled : system/elektra/plugins/simpleini/variants/space/disable
			Key kDisable = sysconf.lookup (this->buildVariantSysconfKey (whichplugin, kCurrent.getBaseName (), "disable"));
			if (kDisable && kDisable.getString () == "1")
			{
				continue; // skip this variant
			}

			// check if an override is available : system/elektra/plugins/simpleini/variants/space/override
			Key kOverride = sysconf.lookup (this->buildVariantSysconfKey (whichplugin, kCurrent.getBaseName (), "override"));
			if (kOverride && kOverride.getString () == "1")
			{
				// first delete config from genconf entirely
				ksVariantConfToAdd.clear ();
				Key kVariantSysconf (this->buildVariantSysconfKey (whichplugin, kCurrent.getBaseName (), "config"));
				this->addKeysBelowKeyToConf (kVariantSysconf, sysconf, kVariantPluginConf, ksVariantConfToAdd);
			}

			if (ksVariantConfToAdd.size () == 0)
			{
				continue; // no config means no variant
			}

			variant.appendConfig (ksVariantConfToAdd);
			result.push_back (variant);
		}
	}

	std::vector<PluginSpec> resFromSysconf (this->getPluginVariantsFromSysconf (whichplugin, sysconf, genconf));
	result.insert (result.end (), resFromSysconf.begin (), resFromSysconf.end ());

	return result;
}
Exemple #7
0
	Point operator() (KeySet const & ks, std::string const & name, option_t const options) const
	{
		Key x = ks.lookup (name + "/x", options);
		if (!x) throw KeyNotFoundException (name + "/x not found");
		Key y = ks.lookup (name + "/y", options);
		if (!y) throw KeyNotFoundException (name + "/y not found");

		return Point (x.get<int> (), y.get<int> ());
	}
SpecBackendBuilder SpecMountpointReader::readMountpointSpecification (KeySet const & cks)
{
	ks = cks;
	mp = ks.head ().dup ();

	Key rmp (mp.dup ());
	helper::removeNamespace (rmp);

	bb.setMountpoint (rmp, mountConf);

	processKey (mp);
	bb.nodes++; // count mp

	ks.lookup (mp, KDB_O_POP);

	ks.rewind (); // we need old fashioned loop, because it can handle ks.cut during iteration
	for (Key k = ks.next (); k; k = ks.next ())
	{
		// search for mountpoint
		Key m = k.getMeta<const Key> ("mountpoint");
		if (m)
		{
			SpecMountpointReader smr (backends, bbi);
			backends[k] = smr.readMountpointSpecification (ks.cut (k));
			continue;
		}

		processKey (k);
		bb.nodes++;
	}

	bb.setBackendConfig (backendConfig);
	bb.useConfigFile (mp.getMeta<std::string> ("mountpoint"));
	return bb;
}
Exemple #9
0
void TestCommand::doBasicTest ()
{
	{
		KDB kdb;
		Key t = root.dup ();
		t.addBaseName ("basic");
		t.setString ("BasicString");
		KeySet basic;
		basic.append (t);

		KeySet test;
		kdb.get (test, root);
		kdb.set (basic, root);
	}

	{
		KDB kdb;
		Key t = root.dup ();
		t.addBaseName ("basic");
		t.setString ("BasicString");

		KeySet test;
		kdb.get (test, root);

		nrTest++;
		if (!test.lookup (t))
		{
			nrError++;
			cerr << "Basic test failed" << endl;
		}
	}
}
Exemple #10
0
	int operator() (KeySet const & ks, std::string const & name, option_t const options) const
	{
		Key k = ks.lookup (name, options);
		if (!k) return -5;
		if (k.getStringSize () <= 1) return -3;
		return k.get<int> () + 5;
	}
Exemple #11
0
int MetaRemoveCommand::execute (Cmdline const & cl)
{
	if (cl.arguments.size () != 2)
	{
		throw invalid_argument ("Need 2 arguments");
	}
	Key parentKey = cl.createKey (0);
	string metaname = cl.arguments[1];

	KeySet conf;
	kdb.get (conf, parentKey);
	printWarnings (cerr, parentKey);

	Key k = conf.lookup (parentKey);

	if (!k)
	{
		cerr << "Key not found" << endl;
		return 1;
	}

	k.delMeta (metaname);

	kdb.set (conf, parentKey);

	return 0;
}
void test_kdbGetSet()
{
	cout << "testing kdbSet() and kdbGet()" << endl;

	{
		KeySet ks_set (5,
			*Key ("user/tests/key3", KEY_DIR, KEY_END),
			*Key ("user/tests/key3/1", KEY_END),
			*Key ("user/tests/key3/2", KEY_END),
			*Key ("user/tests/key3/3", KEY_VALUE, "value", KEY_END),
			KS_END);
		KeySet ks;
		KDB kdb;
		kdb.get (ks, "user/tests/key3");
		ks.append(ks_set);
		kdb.set (ks, "user/tests/key3");
	}

	// check if they were written
	{
		KDB kdb;
		KeySet ks;
		kdb.get (ks, "user/tests/key3");
		exit_if_fail(ks.lookup("user/tests/key3/3"), "could not find previously written key");
		succeed_if(ks.lookup("user/tests/key3/3").get<std::string>() == "value", "could not get value");
		succeed_if(!ks.lookup("user/tests/key3/3").needSync(), "should not need sync");
	}

	// now remove keys (cleanup)
	{
		KeySet ks;
		KDB kdb;
		kdb.get (ks, "user/tests/key3");
		ks.cut(Key("user/tests/key3", KEY_END));
		kdb.set (ks, "user/tests/key3");
	}

	// check if its gone now
	{
		KDB kdb;
		KeySet ks;
		kdb.get (ks, "user/tests/key3");
		succeed_if(!ks.lookup("user/tests/key3/3"), "key was not removed");
	}

}
TEST_F (AutoMergeStrategyTest, EqualsModifyMerges)
{
	task.theirs.lookup ("user/parentt/config/key1").setString ("modifiedvalue");
	Key conflictKey = mergeKeys.lookup (mk1);
	result.addConflict (conflictKey, CONFLICT_SAME, CONFLICT_MODIFY);
	conflictKey = result.getConflictSet ().at (0);

	strategy.resolveConflict (task, conflictKey, result);

	EXPECT_FALSE (result.hasConflicts ()) << "Invalid conflict detected";
	KeySet merged = result.getMergedKeys ();
	EXPECT_EQ (4, merged.size ());

	EXPECT_EQ (mk1, merged.lookup (mk1));
	EXPECT_EQ ("modifiedvalue", merged.lookup (mk1).getString ()) << "Key " << merged.lookup (mk1) << "was not modified correctly";

	compareAllExceptKey1 (merged);
}
Exemple #14
0
void TestCommand::doStringTest ()
{
	vector<string> teststrings;
	teststrings.push_back ("");
	teststrings.push_back ("value");
	teststrings.push_back ("value with spaces");
	teststrings.push_back (" a very long value with many spaces and basically very very long, but only text ... ");
	for (int i = 1; i < 256; ++i)
		teststrings.back () += " very very long, but only text ... ";


	for (auto & teststring : teststrings)
	{
		{
			KDB kdb;
			Key t = root.dup ();
			t.addBaseName ("string");
			t.setString (teststring);

			KeySet basic;
			basic.append (t);

			KeySet test;
			kdb.get (test, root);
			kdb.set (basic, root);
		}

		{
			KDB kdb;

			KeySet test;
			kdb.get (test, root);

			Key t = root.dup ();
			t.addBaseName ("string");

			Key res = test.lookup (t);

			nrTest++;
			if (!res)
			{
				nrError++;
				cerr << "String test failed (key not found)" << t.getName () << endl;
				continue;
			}

			nrTest++;
			if (res.getString () != teststring)
			{
				nrError++;
				cerr << "String test failed (value is not equal)" << endl;
				cerr << "We got: \"" << res.getString () << "\"" << endl;
				cerr << "We wanted: \"" << teststring << "\"" << endl;
			}
		}
	}
}
TEST (test_contextual_nocontext, integer)
{
	using namespace kdb;
	KeySet ks;
	NoContext c;
	const char * name = "/%language%/%country%/%dialect%/test";
	ASSERT_TRUE (!ks.lookup (name));
	Value<int, ContextPolicyIs<NoContext>> i (ks, c, Key (name, KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
	ASSERT_EQ (i, i_value);
	ASSERT_TRUE (ks.lookup (name));
	i = 5;
	ASSERT_EQ (i, 5);
	ASSERT_EQ (i.getSpec ().getName (), name);
	i.syncKeySet ();
	ASSERT_EQ (ks.lookup (name).getString (), "5");
	i = 10;
	ASSERT_EQ (i, 10);
	ASSERT_EQ (ks.lookup (name).getString (), "10");
}
Exemple #16
0
int MetaSetCommand::execute (Cmdline const & cl)
{
	if (cl.arguments.size () < 2 || cl.arguments.size () > 3)
	{
		throw invalid_argument ("Need 2 or 3 arguments");
	}
	string metaname = cl.arguments[1];

	Key parentKey = cl.createKey (0);
	string keyname = parentKey.getName ();
	if (keyname[0] == '/')
	{
		// fix name for lookup
		keyname = "spec" + keyname;
		if (!cl.quiet) std::cout << "Using keyname " << keyname << std::endl;

		// fix k for kdb.set later
		parentKey.setName (keyname);
	}

	KeySet conf;
	kdb.get (conf, parentKey);
	Key k = conf.lookup (parentKey);

	if (!k)
	{
		k = Key (keyname, KEY_END);
		// k.setBinary(0, 0); // conceptually maybe better, but would have confusing "binary" metadata
		conf.append (k);
		if (cl.verbose) cout << "Creating key " << keyname << endl;
	}
	if (!k.isValid ())
	{
		cerr << "Could not create key " << keyname << endl;
		return 1;
	}

	if (cl.arguments.size () == 2)
	{
		if (!cl.quiet) cout << "Only two arguments, thus deleting metaname " << metaname << endl;
		k.delMeta (metaname);
	}
	else
	{
		std::string metavalue = cl.arguments[2];
		if (metaname == "atime" || metaname == "mtime" || metaname == "ctime")
		{
			stringstream str (metavalue);
			time_t t;
			str >> t;
			if (!str.good ()) throw "conversion failure";
			k.setMeta<time_t> (metaname, t);
		}
		else
		{
Exemple #17
0
int FstabCommand::execute (Cmdline const & cl)
{
	int argc = cl.arguments.size ();
	if (argc != 5 && argc != 6 && argc != 7)
	{
		throw invalid_argument ("number of arguments not correct, need 5, 6 or 7");
	}

	KeySet conf;
	Key parentKey = cl.createKey (0);
	kdb.get (conf, parentKey);
	printWarnings (cerr, parentKey);
	Key k = conf.lookup (parentKey);

	if (!k)
	{
		k = cl.createKey (0);
		conf.append (k);
	}

	std::string keyname = k.getName ();

	string dumpfreq = "0";
	if (argc >= 6)
	{
		dumpfreq = cl.arguments[5].c_str ();
	}

	string passno = "0";
	if (argc >= 7)
	{
		passno = cl.arguments[6].c_str ();
	}

	kdb::KeySet config (20, *kdb::Key (keyname + "/ZZZNewFstabName", KEY_END),
			    *kdb::Key (keyname + "/ZZZNewFstabName/device", KEY_VALUE, cl.arguments[1].c_str (), KEY_END),
			    *kdb::Key (keyname + "/ZZZNewFstabName/mpoint", KEY_VALUE, cl.arguments[2].c_str (), KEY_END),
			    *kdb::Key (keyname + "/ZZZNewFstabName/type", KEY_VALUE, cl.arguments[3].c_str (), KEY_END),
			    *kdb::Key (keyname + "/ZZZNewFstabName/options", KEY_VALUE, cl.arguments[4].c_str (), KEY_END),
			    *kdb::Key (keyname + "/ZZZNewFstabName/dumpfreq", KEY_VALUE, dumpfreq.c_str (), KEY_END),
			    *kdb::Key (keyname + "/ZZZNewFstabName/passno", KEY_VALUE, passno.c_str (), KEY_END), KS_END);

	conf.append (config);

	if (cl.verbose)
	{
		cout << conf;
	}

	kdb.set (conf, parentKey);
	printWarnings (cerr, parentKey);

	return 0;
}
/**
 * @brief Allows for updating of a database entry.
 *
 * Will renew the entry and all its subkeys (configuration).
 *
 * @param entry A custom Entry object holding current information.
 * @return true if the entry was updated, false if not
 * @throw kdbrest::exception::EntryNotFoundException in case the entry
 * to update does not exist.
 */
bool StorageEngine::updateEntry (model::Entry & entry)
{
    using namespace kdb;

    // register exclusive access
    boost::unique_lock<boost::shared_mutex> lock (m_mutex_entryCache);

    bool found = false;
    std::vector<model::Entry> & entries = this->m_entryCache;
    unsigned int i = 0;
    while (i < entries.size ())
    {
        if (entries[i].getName ().compare (entry.getName ()) == 0)
        {
            found = true;
            break;
        }
        i++;
    }

    if (!found)
    {
        throw exception::EntryNotFoundException ();
    }

    KDB kdb;
    KeySet ks;
    kdb.get (ks, entry.getName ());

    Key k = ks.lookup (entry.getName ());
    if (!k)
    {
        throw kdbrest::exception::EntryNotFoundException ();
    }

    ks.cut (entry);
    ks.append (entry);
    ks.append (entry.getSubkeys ());

    if (kdb.set (ks, entry.getName ()) >= 1)
    {
        entries.erase (entries.begin () + i);
        entries.push_back (entry);
        return true;
    }
    else
    {
        return false;
    }
}
TEST_F(ThreeWayMergeTest, SameAddedEqualValueMerges)
{
	ours.append (Key ("user/parento/config/key5", KEY_VALUE, "newvalue", KEY_END));
	theirs.append (Key ("user/parentt/config/key5", KEY_VALUE, "newvalue", KEY_END));

	MergeResult result = merger.mergeKeySet (base, ours, theirs, mergeParent);
	EXPECT_FALSE(result.hasConflicts()) << "Invalid conflict detected";

	KeySet merged = result.getMergedKeys ();

	EXPECT_EQ(6, merged.size ());
	compareAllKeys (merged);

	compareKeys (Key ("user/parentm/config/key5", KEY_VALUE, "newvalue", KEY_END), merged.lookup (mk5));
}
/**
 * @brief Allows for deleting of an user entry.
 *
 * Will delete the entry iteself as well as all subkeys (additional user information).
 *
 * @param user A custom User object that should be deleted.
 * @return true if the user was deleted successfully, false otherwise
 * @throw kdbrest::exception::UserNotFoundException in case the user
 * to delete does not exist.
 */
bool StorageEngine::deleteUser (model::User & user)
{
    using namespace kdb;

    // register exclusive access
    boost::unique_lock<boost::shared_mutex> lock (m_mutex_userCache);

    bool found = false;
    std::vector<model::User> & users = this->m_userCache;
    unsigned int i = 0;
    while (i < users.size ())
    {
        if (users[i].getName ().compare (user.getName ()) == 0)
        {
            found = true;
            break;
        }
        i++;
    }

    if (!found)
    {
        throw exception::UserNotFoundException ();
    }

    KDB kdb;
    KeySet ks;
    kdb.get (ks, user.getName ());

    Key k = ks.lookup (user.getName ());
    if (!k)
    {
        throw kdbrest::exception::UserNotFoundException ();
    }

    ks.cut (user);

    if (kdb.set (ks, user.getName ()) >= 1)
    {
        users.erase (users.begin () + i);
        return true;
    }
    else
    {
        return false;
    }
}
TEST_F(OneSideStrategyTest, TheirsWinsCorrectly)
{
	base.lookup ("user/parentb/config/key1").setString ("valueb");
	ours.lookup ("user/parento/config/key1").setString ("valueo");
	theirs.lookup ("user/parentt/config/key1").setString ("valuet");
	Key conflictKey = mk1;
	result.addConflict (conflictKey, MODIFY, MODIFY);
	conflictKey = result.getConflictSet ().at (0);

	OneSideStrategy strategy (THEIRS);
	strategy.resolveConflict (task, conflictKey, result);

	EXPECT_FALSE(result.hasConflicts()) << "Invalid conflict detected";
	KeySet merged = result.getMergedKeys ();
	cout << merged << endl;
	EXPECT_EQ(4, merged.size ());

	compareKeys (Key ("user/parentm/config/key1", KEY_VALUE, "valuet", KEY_END), merged.lookup (mk1));
}
int main ()
{
	KeySet config;
	KDB kdb;
	kdb.get (config, "/sw/MyApp");

	Key k = config.lookup ("/sw/MyApp/mykey");
	if (k)
	{
		k.set<int> (k.get<int> () + 1);
	}
	else
	{
		Key n;
		n.setName ("user/sw/MyApp/mykey");
		n.set<int> (0);
		config.append (n);
	}

	kdb.set (config, "/sw/MyApp");
}
Exemple #23
0
int ValidationCommand::execute(Cmdline const& cl)
{
	size_t argc = cl.arguments.size();
	if (argc != 3 && argc != 4)
	{
		throw invalid_argument("need 3 or 4 arguments");
	}

	KeySet conf;
	Key parentKey = cl.createKey(0);
	string keyname = parentKey.getName();
	kdb.get(conf, parentKey);
	Key k = conf.lookup(keyname);

	if (!k)
	{
		k = Key(keyname, KEY_END);
		conf.append (k);
	}

	if (!k.isValid())
	{
		throw invalid_argument("keyname not valid");
	}

	string value = cl.arguments[1];
	string validationregex = cl.arguments[2];
	string validationmessage;
	if (argc == 4) validationmessage = cl.arguments[3];
	else validationmessage = "Regular expression " + validationregex + " does not match the supplied value";

	k.setString (value);
	k.setMeta<string> ("validation/regex", validationregex);
	k.setMeta<string> ("validation/message", validationmessage);

	kdb.set(conf,parentKey);

	return 0;
}
/**
 * @brief Can be used to create an entry in the database.
 *
 * Will add the entry and all subkeys to the database (configuration).
 *
 * @param entry A custom Entry object holding information to store.
 * @return true if the entry was stored, false if something went wrong
 * @throws kdbrest::exception::EntryAlreadyExistsException in case an
 * entry with the given name does already exist in the key database.
 */
bool StorageEngine::createEntry (model::Entry & entry)
{
    using namespace kdb;

    // register exclusive access
    boost::unique_lock<boost::shared_mutex> lock (m_mutex_entryCache);

    std::vector<model::Entry> & entries = this->m_entryCache;
    for (auto & elem : entries)
    {
        if (elem.getName ().compare (entry.getName ()) == 0)
        {
            throw exception::EntryAlreadyExistsException ();
        }
    }

    KDB kdb;
    KeySet ks;
    kdb.get (ks, entry.getName ());

    Key k = ks.lookup (entry.getName ());
    if (k)
    {
        throw kdbrest::exception::EntryAlreadyExistsException ();
    }

    ks.append (entry);
    ks.append (entry.getSubkeys ());

    if (kdb.set (ks, entry.getName ()) >= 1)
    {
        entries.push_back (entry);
        return true;
    }
    else
    {
        return false;
    }
}
/**
 * @brief Can be used to create an user entry in the database.
 *
 * Will add the user and all subkeys to the database (additional information).
 *
 * @param user A custom User object holding information to store.
 * @return true if the user was stored, false if something went wrong
 * @throws kdbrest::exception::UserAlreadyExistsException in case an
 * user with the given name does already exist in the key database.
 */
bool StorageEngine::createUser (model::User & user)
{
    using namespace kdb;

    // register exclusive access
    boost::unique_lock<boost::shared_mutex> lock (m_mutex_userCache);

    std::vector<model::User> & users = this->m_userCache;
    for (auto & elem : users)
    {
        if (elem.getName ().compare (user.getName ()) == 0)
        {
            throw exception::UserAlreadyExistsException ();
        }
    }

    KDB kdb;
    KeySet ks;
    kdb.get (ks, user.getName ());

    Key k = ks.lookup (user.getName ());
    if (k)
    {
        throw exception::UserAlreadyExistsException ();
    }

    ks.append (user);
    ks.append (user.getSubkeys ());

    if (kdb.set (ks, user.getName ()) >= 1)
    {
        users.push_back (user);
        return true;
    }
    else
    {
        return false;
    }
}
TEST_F(MetaMergeStrategyTest, MergesMetaWithInnerStrategy)
{
	base.lookup ("user/parentb/config/key1").setMeta ("testmeta", "valueb");
	ours.lookup ("user/parento/config/key1").setMeta ("testmeta", "valueo");
	theirs.lookup ("user/parentt/config/key1").setMeta ("testmeta", "valuet");
	Key conflictKey = mk1;
	result.addConflict (conflictKey, CONFLICT_META, CONFLICT_META);
	conflictKey = result.getConflictSet ().at (0);

	ThreeWayMerge merger;
	MergeConflictStrategy *strategy = new OneSideStrategy (OURS);
	merger.addConflictStrategy (strategy);
	MetaMergeStrategy metaStrategy (merger);
	metaStrategy.resolveConflict (task, conflictKey, result);
	delete (strategy);

	EXPECT_FALSE(result.hasConflicts()) << "Invalid conflict detected";
	KeySet merged = result.getMergedKeys ();
	cout << merged << endl;
	EXPECT_EQ(4, merged.size ());

	EXPECT_EQ("valueo", merged.lookup (mk1).getMeta<string> ("testmeta"));
}
int MetaGetCommand::execute (Cmdline const& cl)
{
	if (cl.arguments.size() != 2)
	{
		throw invalid_argument ("Need 2 arguments");
	}
	string keyname = cl.arguments[0];
	string metaname = cl.arguments[1];

	KeySet conf;
	Key parentKey(keyname, KEY_END);
	kdb.get(conf, parentKey);
	printWarnings(cerr,parentKey);

	Key k = conf.lookup(keyname);

	if (!k)
	{
		cerr << "Key not found" << endl;
		return 1;
	}

	if (!k.getMeta<const Key>(metaname))
	{
		cerr << "Metakey not found" << endl;
		return 2;
	}

	cout << k.getMeta<string>(metaname);
	
	if (!cl.noNewline)
	{
		cout << endl;
	}

	return 0;
}
int MetaSetCommand::execute (Cmdline const& cl)
{
	if (cl.arguments.size() != 3)
	{
		throw invalid_argument ("Need 3 arguments");
	}
	string keyname = cl.arguments[0];
	string metaname = cl.arguments[1];

	KeySet conf;
	Key parentKey(keyname, KEY_END);
	kdb.get(conf, parentKey);
	Key k = conf.lookup(keyname);

	if (!k)
	{
		k = Key(keyname, KEY_END);
		// k.setBinary(0, 0); // conceptually maybe better, but would have confusing "binary" metadata
		conf.append(k);
		if (cl.verbose) cout << "Creating key " << keyname << endl;
	}
	if (!k.isValid())
	{
		cout << "Could not create key" << endl;
		return 1;
	}

	std::string metavalue = cl.arguments[2];
	if (metaname == "atime" || metaname == "mtime" || metaname == "ctime")
	{
		stringstream str (metavalue);
		time_t t;
		str >> t;
		if (!str.good()) throw "conversion failure";
		k.setMeta<time_t> (metaname, t);
	} else {
Exemple #29
0
int main()
{
	KeySet ours;
	KeySet theirs;
	KeySet base;

	// the root of the subtree containing our keys (i.e. our side of the merge)
	Key oursRoot ("user/ours", KEY_END);

	// the root of the subtree containing their keys (i.e. their side of the merge)
	Key theirsRoot ("user/theirs", KEY_END);

	// the root of the subtree containing the base keys (i.e. the common ancestor of the merge)
	Key baseRoot ("user/base", KEY_END);

	// the root of the subtree that will contain the merge result
	Key resultRoot ("user/result", KEY_END);

	// Step 1: retrieve clean KeySets containing only those
	// keys that should be merged. This is a bit trickier than
	// it seems at first. Have a look at the documentation of kdbGet
	// for detailed information
	// things to note:
	//   * use blocks with local KDB instances so we don't have to worry about
	//     writing the keys back
	//   * remove the root key itself from the result KeySet because it usually
	//     contains the mounted filename and cannot be merged anyway
	// Also have a look at the documentation of kdbSet()
	// (http://doc.libelektra.org/api/latest/html/group__kdb.html#ga11436b058408f83d303ca5e996832bcf).
	// The merging framework can also be used to resolve conflicts resulting from
	// concurrent calls to kdbSet() as described in the example of kdbSet().
	{
		KDB lkdb;
		lkdb.get (ours, oursRoot);
		ours = ours.cut (oursRoot);
		ours.lookup(oursRoot, KDB_O_POP);
		lkdb.get (theirs, theirsRoot);
		theirs = theirs.cut (theirsRoot);
		theirs.lookup(theirsRoot, KDB_O_POP);
		lkdb.get (base, baseRoot);
		base = base.cut (baseRoot);
		base.lookup(baseRoot, KDB_O_POP);
	}


	// Step 2: Make sure that no keys reside below the intended merge result root
	// Usually the merge can be either aborted if this is the case or the existing
	// keys can be overwritten.
	KeySet resultKeys;
	kdb::KDB kdb;
	kdb.get (resultKeys, resultRoot);

	KeySet discard = resultKeys.cut (resultRoot);
	if (discard.size () != 0)
	{
		// handle existing keys below the result root
		return -1;
	}

	ThreeWayMerge merger;

	// Step 3: Decide which resolution strategies to use. The strategies are registered
	// with the merge and applied in order as soon as a conflict is detected. If a strategy
	// marks a conflict as resolved, no further strategies are consulted. Therefore the order
	// in which they are registered is absolutely crucial. With this chaining the strategies
	// remain simple, but can be combined to powerful resolution strategies.
	// Have a look at the strategy documentation for further details on what they do and how they work.
	// The unit tests also provide insight into how the strategies work.

	// In order to simplify the initialization, predefined merge configurations exist.
	// in this example we first resolve all the keys that can be automatically
	// resolved (e.g. only one side was modified). This is exactly the use case of the
	// AutoMergeConfiguration.

	AutoMergeConfiguration configuration;
	configuration.configureMerger(merger);

	// Step 4: Perform the actual merge
	MergeResult result = merger.mergeKeySet (
			MergeTask (BaseMergeKeys (base, baseRoot), OurMergeKeys (ours, oursRoot),
					TheirMergeKeys (theirs, theirsRoot), resultRoot));

	// Step 5: work with the result. The merger will return an object containing information
	// about the merge result.
	if (!result.hasConflicts ())
	{
		// output some statistical information
		cout << result.getMergedKeys().size() << " keys in the result" << endl;
		cout << result.getNumberOfEqualKeys() << " keys were equal" << endl;
		cout << result.getNumberOfResolvedKeys() << " keys were resolved" << endl;

		// write the result
		resultKeys.append(result.getMergedKeys());
		kdb.set (resultKeys, resultRoot);

		return 0;
	}
	else
	{
		KeySet conflicts = result.getConflictSet();

		cerr << conflicts.size() << " conflicts were detected that could not be resolved automatically:" << endl;
		conflicts.rewind();
		Key current;
		while ((current = conflicts.next()))
		{
			// For each unresolved conflict there is a conflict key in the merge result.
			// This conflict key contains meta information about the reason of the conflict.
			// In particular the metakeys conflict/operation/our and conflict/operation/their contain
			// the operations done on our version of the key and their version of the key relative to
			// the base version of the key.
			string ourConflict = current.getMeta<string> ("conflict/operation/our");
			string theirConflict = current.getMeta<string> ("conflict/operation/their");

			cerr << current << endl;
			cerr << "ours: " << ourConflict << ", theirs: " << theirConflict << endl;
			cerr << endl;
		}

		cerr << "Merge unsuccessful." << endl;

		return -1;
	}
}
Exemple #30
0
void TestCommand::doMetaTest ()
{
	vector<string> teststrings;
	teststrings.push_back ("");
	teststrings.push_back ("value");
	teststrings.push_back ("value with spaces");
	teststrings.push_back (" a very long value with many spaces and basically very very long, but only text ... ");
	for (int i = 1; i < 256; ++i)
		teststrings.back () += " very very long, but only text ... ";
	teststrings.push_back ("ascii umlauts !\"§$%&/()=?`\\}][{");
	teststrings.push_back ("utf8 umlauts ¸¬½¼³²¹ł€¶øæßð𳽫»¢“”nµ─·");
	teststrings.push_back ("all chars:");
	for (int i = 1; i < 256; ++i)
		teststrings.back ().push_back (i);
	teststrings.push_back ("€");
	for (int i = 1; i < 256; ++i)
	{
		string s;
		s.push_back (i);
		teststrings.push_back (s);
	}

	vector<string> testnames;
	testnames.push_back ("keyname");
	testnames.push_back ("deep/below/keyname");
	testnames.push_back ("keyname with spaces");
	testnames.push_back ("deep/belowkeyname with spaces");
	testnames.push_back (" a very long value with many spaces and basically very very long, but only text ");
	for (int i = 1; i < 256; ++i)
		testnames.back () += "/ very very long, but only text ... ";
	testnames.push_back ("ascii umlauts !\"§$%&/()=?`\\}][{");
	testnames.push_back ("utf8 umlauts ¸¬½¼³²¹ł€¶øæßð𳽫»¢“”nµ─·");
	testnames.push_back ("all chars:");
	for (int i = 1; i < 256; ++i)
		testnames.back ().push_back (i);
	testnames.push_back ("€");
	for (int i = 1; i < 256; ++i)
	{
		if (i == 46) continue; // ignore .
		string s;
		s.push_back (i);
		testnames.push_back (s);
	}


	for (auto & testname : testnames)
		for (auto & teststring : teststrings)
		{
			{
				KDB kdb;
				Key t = root.dup ();
				t.addBaseName (testname);
				t.setMeta<string> ("key", teststring);

				KeySet basic;
				basic.append (t);

				KeySet test;
				kdb.get (test, root);
				kdb.set (basic, root);
			}

			{
				KDB kdb;

				KeySet test;
				kdb.get (test, root);

				Key t = root.dup ();
				t.addBaseName (testname);
				Key res = test.lookup (t);

				nrTest++;
				if (!res)
				{
					nrError++;
					cerr << "Meta test failed (key not found)" << t.getName () << endl;
					continue;
				}

				std::string meta = res.getMeta<std::string> ("key");

				nrTest++;
				if (meta != teststring)
				{
					nrError++;
					cerr << "Meta test failed (name is not equal)" << endl;
					cerr << "We got: \"" << meta << "\"" << endl;
					cerr << "We wanted: \"" << teststring << "\"" << endl;
				}
			}
		}
}