Skip to content

Commit

Permalink
Implement support for restoring modified attributes
Browse files Browse the repository at this point in the history
Also fix a glitch with ModifyAttribute and original_attributes
storage.

fixes #9935
  • Loading branch information
Michael Friedrich committed Sep 18, 2015
1 parent f7b5aa3 commit 95bcbec
Showing 1 changed file with 69 additions and 7 deletions.
76 changes: 69 additions & 7 deletions lib/base/configobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ void ConfigObject::ModifyAttribute(const String& attr, const Value& value, bool
SetOriginalAttributes(original_attributes, true);
}

if (!original_attributes->Contains(attr)) {
if (!original_attributes->Contains(fieldName)) {
updated_original_attributes = true;
original_attributes->Set(attr, oldValue);
original_attributes->Set(fieldName, oldValue);
}
}

Expand Down Expand Up @@ -194,16 +194,78 @@ void ConfigObject::ModifyAttribute(const String& attr, const Value& value, bool

void ConfigObject::RestoreAttribute(const String& attr)
{
//TODO-MA: vars.os
Type::Ptr type = GetReflectionType();

std::vector<String> tokens;
boost::algorithm::split(tokens, attr, boost::is_any_of("."));

String fieldName = tokens[0];

int fid = type->GetFieldId(fieldName);
Field field = type->GetFieldInfo(fid);

Value currentValue = GetField(fid);

Dictionary::Ptr original_attributes = GetOriginalAttributes();

if (!original_attributes || !original_attributes->Contains(attr))
if (!original_attributes || !original_attributes->Contains(fieldName))
return;

Value attrVal = original_attributes->Get(attr);
Value newValue;

if (tokens.size() > 1) {
newValue = currentValue.Clone();
Value current = newValue;

if (current.IsEmpty())
BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot restore non-existing object attribute"));

Value old = original_attributes->Get(fieldName);

for (std::vector<String>::size_type i = 1; i < tokens.size() - 1; i++) {
if (!current.IsObjectType<Dictionary>() || !old.IsObjectType<Dictionary>())
BOOST_THROW_EXCEPTION(std::invalid_argument("Value must be a dictionary."));

Dictionary::Ptr currentDict = current;
Dictionary::Ptr oldDict = old;

const String& key = tokens[i];

if (!currentDict->Contains(key))
BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot restore non-existing object attribute"));

/* silently ignore missing old values */
if (!oldDict->Contains(key))
return;

current = currentDict->Get(key);
old = oldDict->Get(key);
}

if (!current.IsObjectType<Dictionary>() || !old.IsObjectType<Dictionary>())
BOOST_THROW_EXCEPTION(std::invalid_argument("Value must be a dictionary."));

Dictionary::Ptr currentDict = current;
Dictionary::Ptr oldDict = old;

const String& key = tokens[tokens.size() - 1];

Value oldValue = oldDict->Get(key).Clone();
currentDict->Set(key, oldValue);

oldDict->Remove(key);
} else {
newValue = original_attributes->Get(fieldName);
original_attributes->Remove(fieldName);
}

SetField(fid, newValue);

SetField(GetReflectionType()->GetFieldId(attr), attrVal);
original_attributes->Remove(attr);
/* increment the version. although restoring would mean
* decrementing the version, but we cannot notify other
* cluster nodes without increment.
*/
SetVersion(GetVersion() + 1);
}

bool ConfigObject::IsAttributeModified(const String& attr) const
Expand Down

0 comments on commit 95bcbec

Please sign in to comment.