BIND 10 trac922, updated. 94d43a69237b5d2bf671e384ff8b2b9a5ce445b4 [trac922] Call the update function
BIND 10 source code commits
bind10-changes at lists.isc.org
Fri May 13 11:34:58 UTC 2011
The branch, trac922 has been updated
via 94d43a69237b5d2bf671e384ff8b2b9a5ce445b4 (commit)
via c3e1e45419104bdb01dd385b22eae85bb8799611 (commit)
via 946b527467c19236814cae6e35191ce19db3284a (commit)
via 02e2f3a3c2ae669824d595bc9b42f37d9624b22c (commit)
via 54210ba456b4e0822c5e333fd1f996bb35c6bee9 (commit)
from fd08a0dc40846f58aaa8a7df7726ac83e5e4c038 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 94d43a69237b5d2bf671e384ff8b2b9a5ce445b4
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Fri May 13 13:29:19 2011 +0200
[trac922] Call the update function
commit c3e1e45419104bdb01dd385b22eae85bb8799611
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Fri May 13 13:29:06 2011 +0200
[trac922] Tests for the handler function
commit 946b527467c19236814cae6e35191ce19db3284a
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Fri May 13 12:52:07 2011 +0200
[trac922] Request the spec from config manager
If the module name is passed instead of filename, the spec is downloaded
from the config manager.
commit 02e2f3a3c2ae669824d595bc9b42f37d9624b22c
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Fri May 13 12:37:58 2011 +0200
[trac922] Test for module name add
commit 54210ba456b4e0822c5e333fd1f996bb35c6bee9
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Fri May 13 11:47:09 2011 +0200
[trac922] Update interface
-----------------------------------------------------------------------
Summary of changes:
src/lib/config/ccsession.cc | 48 ++++++++++++-
src/lib/config/ccsession.h | 36 ++++++++---
src/lib/config/tests/ccsession_unittests.cc | 96 +++++++++++++++++++++++++++
3 files changed, 167 insertions(+), 13 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/config/ccsession.cc b/src/lib/config/ccsession.cc
index 1b5e47d..81eadab 100644
--- a/src/lib/config/ccsession.cc
+++ b/src/lib/config/ccsession.cc
@@ -356,9 +356,38 @@ ModuleCCSession::checkCommand() {
}
std::string
-ModuleCCSession::addRemoteConfig(const std::string& spec_file_name) {
- ModuleSpec rmod_spec = readModuleSpecification(spec_file_name);
- std::string module_name = rmod_spec.getFullSpec()->get("module_name")->stringValue();
+ModuleCCSession::addRemoteConfig(const std::string& spec_name,
+ void (*handler)(const std::string& module,
+ ConstElementPtr))
+{
+ std::string module_name;
+ ModuleSpec rmod_spec;
+ if (spec_name.find_first_of("./") != std::string::npos) {
+ // It's a file name, so load it
+ rmod_spec = readModuleSpecification(spec_name);
+ module_name =
+ rmod_spec.getFullSpec()->get("module_name")->stringValue();
+ } else {
+ // It's module name, request it from config manager
+ ConstElementPtr cmd = Element::fromJSON("{ \"command\": ["
+ "\"get_module_spec\","
+ "{\"module_name\": \"" +
+ module_name + "\"} ] }");
+ unsigned int seq = session_.group_sendmsg(cmd, "ConfigManager");
+ ConstElementPtr env, answer;
+ session_.group_recvmsg(env, answer, false, seq);
+ int rcode;
+ ConstElementPtr spec_data = parseAnswer(rcode, answer);
+ if (rcode == 0 && spec_data) {
+ rmod_spec = ModuleSpec(spec_data);
+ module_name = spec_name;
+ if (module_name != rmod_spec.getModuleName()) {
+ isc_throw(CCSessionError, "Module name mismatch");
+ }
+ } else {
+ isc_throw(CCSessionError, "Error getting config for " + module_name + ": " + answer->str());
+ }
+ }
ConfigData rmod_config = ConfigData(rmod_spec);
session_.subscribe(module_name);
@@ -370,8 +399,9 @@ ModuleCCSession::addRemoteConfig(const std::string& spec_file_name) {
session_.group_recvmsg(env, answer, false, seq);
int rcode;
ConstElementPtr new_config = parseAnswer(rcode, answer);
+ ElementPtr local_config;
if (rcode == 0 && new_config) {
- ElementPtr local_config = rmod_config.getLocalConfig();
+ local_config = rmod_config.getLocalConfig();
isc::data::merge(local_config, new_config);
rmod_config.setLocalConfig(local_config);
} else {
@@ -380,6 +410,10 @@ ModuleCCSession::addRemoteConfig(const std::string& spec_file_name) {
// all ok, add it
remote_module_configs_[module_name] = rmod_config;
+ if (handler) {
+ remote_module_handlers_[module_name] = handler;
+ handler(module_name, local_config);
+ }
return (module_name);
}
@@ -390,6 +424,7 @@ ModuleCCSession::removeRemoteConfig(const std::string& module_name) {
it = remote_module_configs_.find(module_name);
if (it != remote_module_configs_.end()) {
remote_module_configs_.erase(it);
+ remote_module_handlers_.erase(module_name);
session_.unsubscribe(module_name);
}
}
@@ -419,6 +454,11 @@ ModuleCCSession::updateRemoteConfig(const std::string& module_name,
if (it != remote_module_configs_.end()) {
ElementPtr rconf = (*it).second.getLocalConfig();
isc::data::merge(rconf, new_config);
+ std::map<std::string, RemoteHandler>::iterator hit =
+ remote_module_handlers_.find(module_name);
+ if (hit != remote_module_handlers_.end()) {
+ hit->second(module_name, new_config);
+ }
}
}
diff --git a/src/lib/config/ccsession.h b/src/lib/config/ccsession.h
index 7364876..5c21ba0 100644
--- a/src/lib/config/ccsession.h
+++ b/src/lib/config/ccsession.h
@@ -234,24 +234,38 @@ public:
/**
* Gives access to the configuration values of a different module
* Once this function has been called with the name of the specification
- * file of the module you want the configuration of, you can use
+ * file or the module you want the configuration of, you can use
* \c getRemoteConfigValue() to get a specific setting.
- * Changes are automatically updated, but you cannot specify handlers
- * for those changes, must use \c getRemoteConfigValue() to get a value
- * This function will subscribe to the relevant module channel.
+ * Changes are automatically updated, and you can specify handlers
+ * for those changes. This function will subscribe to the relevant module
+ * channel.
*
- * \param spec_file_name The path to the specification file of
- * the module we want to have configuration
- * values from
+ * \param spec_name This specifies the module to add. It is either a
+ * filename of the spec file to use or a name of module
+ * (in case it's a module name, the spec data is
+ * downloaded from the configuration manager, therefore
+ * the configuration manager must know it). A heuristic
+ * is used to guess which should be used - if it contains
+ * a slash or dot, filename is assumed, otherwise
+ * name of module is assumed.
+ * \param handler The handler function called whenever there's a change.
+ * Called once initally from this function. May be NULL
+ * if you don't want any handler to be called and you're
+ * fine with requesting the data through
+ * getRemoteConfigValue() each time.
* \return The name of the module specified in the given specification
* file
*/
- std::string addRemoteConfig(const std::string& spec_file_name);
+ std::string addRemoteConfig(const std::string& spec_name,
+ void (*handler)(const std::string& module_name,
+ isc::data::ConstElementPtr
+ update) = NULL);
/**
* Removes the module with the given name from the remote config
* settings. If the module was not added with \c addRemoteConfig(),
- * nothing happens.
+ * nothing happens. If there was a handler for this config, it is
+ * removed as well.
*/
void removeRemoteConfig(const std::string& module_name);
@@ -296,7 +310,11 @@ private:
const std::string& command,
isc::data::ConstElementPtr args);
+ typedef void (*RemoteHandler)(const std::string&,
+ isc::data::ConstElementPtr);
std::map<std::string, ConfigData> remote_module_configs_;
+ std::map<std::string, RemoteHandler> remote_module_handlers_;
+
void updateRemoteConfig(const std::string& module_name,
isc::data::ConstElementPtr new_config);
};
diff --git a/src/lib/config/tests/ccsession_unittests.cc b/src/lib/config/tests/ccsession_unittests.cc
index f566949..bce3e51 100644
--- a/src/lib/config/tests/ccsession_unittests.cc
+++ b/src/lib/config/tests/ccsession_unittests.cc
@@ -346,6 +346,18 @@ TEST_F(CCSessionTest, checkCommand2) {
EXPECT_EQ(2, mccs.getValue("item1")->intValue());
}
+std::string remote_module_name;
+int remote_item1(0);
+ConstElementPtr remote_config;
+ModuleCCSession *remote_mccs(NULL);
+
+void remoteHandler(const std::string& module_name, ConstElementPtr config) {
+ remote_module_name = module_name;
+ remote_item1 = remote_mccs->getRemoteConfigValue("Spec2", "item1")->
+ intValue();
+ remote_config = config;
+}
+
TEST_F(CCSessionTest, remoteConfig) {
std::string module_name;
int item1;
@@ -392,6 +404,90 @@ TEST_F(CCSessionTest, remoteConfig) {
session.getMessages()->add(createAnswer());
EXPECT_THROW(mccs.addRemoteConfig(ccspecfile("spec2.spec")), CCSessionError);
+
+ {
+ SCOPED_TRACE("With module name");
+ // Try adding it with downloading the spec from config manager
+ ModuleSpec spec(moduleSpecFromFile(ccspecfile("spec2.spec")));
+ session.getMessages()->add(createAnswer(0, spec.getFullSpec()));
+ session.getMessages()->add(createAnswer(0, el("{}")));
+
+ EXPECT_NO_THROW(module_name = mccs.addRemoteConfig("Spec2"));
+
+ EXPECT_EQ("Spec2", module_name);
+ EXPECT_NO_THROW(item1 =
+ mccs.getRemoteConfigValue(module_name,
+ "item1")->intValue());
+ EXPECT_EQ(1, item1);
+
+ mccs.removeRemoteConfig(module_name);
+ }
+
+ {
+ // Try adding it with a handler.
+ // Pass non-default value to see the handler is called after
+ // downloading the configuration, not too soon.
+ SCOPED_TRACE("With handler");
+ session.getMessages()->add(createAnswer(0, el("{ \"item1\": 2 }")));
+ remote_mccs = &mccs;
+ module_name = mccs.addRemoteConfig(ccspecfile("spec2.spec"),
+ remoteHandler);
+ {
+ SCOPED_TRACE("Before update");
+ EXPECT_EQ("Spec2", module_name);
+ EXPECT_TRUE(session.haveSubscription("Spec2", "*"));
+ // Now check the parameters the remote handler stored
+ // This also checks it was called
+ EXPECT_EQ("Spec2", remote_module_name);
+ remote_module_name = "";
+ EXPECT_EQ(2, remote_item1);
+ remote_item1 = 0;
+ if (remote_config) {
+ EXPECT_EQ(2, remote_config->get("item1")->intValue());
+ } else {
+ ADD_FAILURE() << "Remote config not set";
+ }
+ remote_config.reset();
+ // Make sure normal way still works
+ item1 = mccs.getRemoteConfigValue(module_name,
+ "item1")->intValue();
+ EXPECT_EQ(2, item1);
+ }
+
+ {
+ SCOPED_TRACE("After update");
+ session.addMessage(el("{ \"command\": [ \"config_update\", "
+ "{ \"item1\": 3 } ] }"), module_name, "*");
+ mccs.checkCommand();
+ EXPECT_EQ("Spec2", remote_module_name);
+ remote_module_name = "";
+ EXPECT_EQ(3, remote_item1);
+ remote_item1 = 0;
+ if (remote_config) {
+ EXPECT_EQ(3, remote_config->get("item1")->intValue());
+ } else {
+ ADD_FAILURE() << "Remote config not set";
+ }
+ remote_config.reset();
+ // Make sure normal way still works
+ item1 = mccs.getRemoteConfigValue(module_name,
+ "item1")->intValue();
+ EXPECT_EQ(3, item1);
+ }
+
+ remote_mccs = NULL;
+ mccs.removeRemoteConfig(module_name);
+
+ {
+ SCOPED_TRACE("When removed");
+ // Make sure nothing is called any more
+ session.addMessage(el("{ \"command\": [ \"config_update\", "
+ "{ \"item1\": 4 } ] }"), module_name, "*");
+ EXPECT_EQ("", remote_module_name);
+ EXPECT_EQ(0, remote_item1);
+ EXPECT_FALSE(remote_config);
+ }
+ }
}
TEST_F(CCSessionTest, ignoreRemoteConfigCommands) {
More information about the bind10-changes
mailing list