Commit bb8fe679 authored by Jelte Jansen's avatar Jelte Jansen

added isc::data::merge(element, element), that merges the values in the second...

added isc::data::merge(element, element), that merges the values in the second mapelement into the first (copies the pointers that are present in the second element, and removes from a the values that are empty pointers in the second)

the ElementPtr passed to the module's config handler now only contains the data that has actually changed (settings that are the same as before are removed from what is passed to the config handler)


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1041 e5f2f494-b856-4b98-b285-d166d9295462
parent 2f66bfbe
......@@ -128,10 +128,8 @@ AuthSrv::processMessage() {
void
AuthSrv::setDbFile(const std::string& db_file)
{
if (_db_file != db_file) {
cout << "Change data source file, call our data source's function to now read " << db_file << endl;
_db_file = db_file;
}
cout << "Change data source file, call our data source's function to now read " << db_file << endl;
_db_file = db_file;
}
ElementPtr
......@@ -140,9 +138,7 @@ AuthSrv::updateConfig(isc::data::ElementPtr new_config) {
// the ModuleCCSession has already checked if we have
// the correct ElementPtr type as specified in our .spec file
if (new_config->contains("database_file")) {
// Since we also get this value if it hasn't changed,
// but is non-default, setDbFile here should only really
// do anything if it has actually changed
// We only get this if the value has actually changed.
setDbFile(new_config->get("database_file")->stringValue());
}
}
......
......@@ -1005,21 +1005,40 @@ isc::data::isNull(ElementPtr p)
void
isc::data::removeIdentical(ElementPtr a, const ElementPtr b)
{
if (!b) {
return;
}
if (a->getType() != Element::map || b->getType() != Element::map) {
dns_throw(TypeError, "Non-map Elements passed to removeIdentical");
}
std::cout<<"[XX] removeidentical from " << a << " and " << b << std::endl;
std::map<std::string, ElementPtr> m = a->mapValue();
for (std::map<std::string, ElementPtr>::iterator it = m.begin() ;
it != m.end() ; ++it) {
if (b->contains((*it).first)) {
if (a->get((*it).first)->equals(b->get((*it).first))) {
std::cout<<"[XX] remove " << (*it).first << std::endl;
a->remove((*it).first);
}
}
}
std::cout<<"[XX] a now " << a << std::endl;
}
void
isc::data::merge(ElementPtr element, const ElementPtr other)
{
if (element->getType() != Element::map ||
other->getType() != Element::map) {
dns_throw(TypeError, "merge arguments not MapElements");
}
std::map<std::string, ElementPtr> m = other->mapValue();
for (std::map<std::string, ElementPtr>::iterator it = m.begin() ;
it != m.end() ; ++it) {
if ((*it).second) {
element->set((*it).first, (*it).second);
} else if (element->contains((*it).first)) {
element->remove((*it).first);
}
}
}
......@@ -455,13 +455,23 @@ bool isNull(ElementPtr p);
///
/// \brief Remove all values from the first ElementPtr that are
/// also present in the second. Both ElementPtrs MUST be MapElements
/// equal in the second. Both ElementPtrs MUST be MapElements
/// The use for this function is to end up with a MapElement that
/// only contains new and changed values (for ModuleCCSession and
/// configuration update handlers)
/// Raises a TypeError if a or b are not MapElements
void removeIdentical(ElementPtr a, const ElementPtr b);
/// \brief Merges the data from other into element.
/// (on the first level). Both elements must be
/// MapElements.
/// Every string,value pair in other is copied into element
/// (the ElementPtr of value is copied, this is not a new object)
/// Unless the value is an empty ElementPtr, in which case the
/// whole key is removed from element.
/// Raises a TypeError if either ElementPtr is not a MapElement
void merge(ElementPtr element, const ElementPtr other);
} }
///
......
......@@ -380,3 +380,35 @@ TEST(Element, removeIdentical) {
removeIdentical(a, b);
EXPECT_TRUE(a == c);
}
TEST(Element, merge)
{
ElementPtr a = Element::createFromString("{}");
ElementPtr b = Element::createFromString("{}");
ElementPtr c = Element::createFromString("{}");
merge(a, b);
EXPECT_TRUE(a == c);
a = Element::createFromString("1");
b = Element::createFromString("{}");
EXPECT_THROW(merge(a, b), TypeError);
a = Element::createFromString("{}");
b = Element::createFromString("{ \"a\": 1 }");
c = Element::createFromString("{ \"a\": 1 }");
merge(a, b);
EXPECT_TRUE(a == c);
a = Element::createFromString("{ \"a\": 1 }");
b = Element::createFromString("{ \"a\": 2 }");
c = Element::createFromString("{ \"a\": 2 }");
merge(a, b);
EXPECT_TRUE(a == c);
a = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
b = Element::createFromString("{ \"a\": { \"b\": \"d\" } }");
c = Element::createFromString("{ \"a\": { \"b\": \"d\" } }");
merge(a, b);
EXPECT_TRUE(a == c);
}
......@@ -189,7 +189,8 @@ ModuleCCSession::ModuleCCSession(std::string spec_file_name,
ElementPtr spec_msg = createCommand("module_spec", module_specification_.getFullSpec());
session_.group_sendmsg(spec_msg, "ConfigManager");
session_.group_recvmsg(env, answer, false);
config_ = Element::createFromString("{}");
// get any stored configuration from the manager
if (config_handler_) {
ElementPtr cmd = Element::createFromString("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name_ + "\"} ] }");
......@@ -202,7 +203,7 @@ ModuleCCSession::ModuleCCSession(std::string spec_file_name,
}
/// Validates the new config values, if they are correct,
/// call the config handler
/// call the config handler with the values that have changed
/// If that results in success, store the new config
ElementPtr
ModuleCCSession::handleConfigUpdate(ElementPtr new_config)
......@@ -220,13 +221,15 @@ ModuleCCSession::handleConfigUpdate(ElementPtr new_config)
}
answer = createAnswer(2, ss.str());
} else {
// remove the values that have not changed
isc::data::removeIdentical(new_config, getConfig());
// handle config update
std::cout << "handleConfigUpdate " << new_config << std::endl;
answer = config_handler_(new_config);
int rcode;
parseAnswer(rcode, answer);
if (rcode == 0) {
config_ = new_config;
isc::data::merge(config_, new_config);
}
}
std::cout << "end handleConfigUpdate " << new_config << std::endl;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment