MergeResult ThreeWayMerge::mergeKeySet (const KeySet & base, const KeySet & ours, const KeySet & theirs, const Key & mergeRoot)
{
	Key ourkey = ours.head ().dup ();
	Key theirkey = theirs.head ().dup ();
	Key basekey = base.head ().dup ();

	MergeResult merged = mergeKeySet (
		MergeTask (BaseMergeKeys (base, basekey), OurMergeKeys (ours, ourkey), TheirMergeKeys (theirs, theirkey), mergeRoot));

	return merged;
}
Beispiel #2
0
void MetaMergeStrategy::resolveConflict(const MergeTask& task, Key& conflictKey, MergeResult& result)
{
	conflictKey.rewindMeta();
	Key currentMeta;

	string baseLookup = rebasePath (conflictKey, task.mergeRoot, task.baseParent);
	string ourLookup = rebasePath (conflictKey, task.mergeRoot, task.ourParent);
	string theirLookup = rebasePath (conflictKey, task.mergeRoot, task.theirParent);

	Key baseKey = task.base.lookup(baseLookup);
	Key ourKey = task.ours.lookup(ourLookup);
	Key theirKey = task.theirs.lookup(theirLookup);

	Key root ("user/", KEY_END);
	KeySet baseMeta = getMetaKeys (baseKey);
	KeySet ourMeta = getMetaKeys (ourKey);
	KeySet theirMeta = getMetaKeys (theirKey);

	MergeTask metaTask(BaseMergeKeys (baseMeta, root), OurMergeKeys (ourMeta, root),
			TheirMergeKeys (theirMeta, root), root);

	MergeResult metaResult = innerMerger.mergeKeySet(metaTask);

	KeySet mergedMeta = metaResult.getMergedKeys();
	Key current;
	mergedMeta.rewind();
	while ((current = mergedMeta.next()))
	{
		string metaName = current.getName().substr(string("user/").length());
		conflictKey.setMeta(metaName, current.getString());
	}

	ConflictOperation ourOperation = getOurConflictOperation(conflictKey);
	ConflictOperation theirOperation = getTheirConflictOperation(conflictKey);

	if (!metaResult.hasConflicts ())
	{
		if (ourOperation == CONFLICT_META && theirOperation == CONFLICT_META)
		{
			// TODO: addConflict deletes the key content
			// without this strategy restoring the value the value would be lost
			// this happens only for CONFLICT_META <--> CONFLICT_META conflicts
			// add a test for this behaviour
			copyKeyValue(ourKey, conflictKey);
			result.resolveConflict (conflictKey);
			result.addMergeKey (conflictKey);
		}
	}

}
Beispiel #3
0
int MergingKDB::synchronize (KeySet & returned, Key & parentKey, ThreeWayMerge & merger)
{
	try
	{
		// write our config
		int ret = KDB::set (returned, parentKey);

		// update our config (if no conflict)
		KDB::get (returned, parentKey);

		return ret;
	}
	catch (KDBException const &)
	{
		// a conflict occurred, see if we can solve it with the merger

		// refresh the key database
		KeySet theirs = returned.dup ();
		KDB::get (theirs, parentKey);

		// try to merge
		MergeResult result = merger.mergeKeySet (MergeTask (BaseMergeKeys (base, parentKey), OurMergeKeys (returned, parentKey),
								    TheirMergeKeys (theirs, parentKey), parentKey));

		if (!result.hasConflicts ())
		{
			// hurray, we solved the issue
			KeySet resultKeys = result.getMergedKeys ();
			int ret = KDB::set (resultKeys, parentKey);
			base = resultKeys;
			return ret;
		}
		else
		{
			// nothing we can do anymore
			KeySet conflictSet = result.getConflictSet ();
			throw MergingKDBException (parentKey, conflictSet);
		}
	}
}
Beispiel #4
0
	MergeTask reverse () const
	{
		return MergeTask (BaseMergeKeys (base, baseParent), OurMergeKeys (theirs, theirParent), TheirMergeKeys (ours, ourParent),
				  mergeRoot);
	}