Commit af72796a authored by Jelte Jansen's avatar Jelte Jansen
Browse files

same remote config stuff for the c++ side of modulesessions


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1218 e5f2f494-b856-4b98-b285-d166d9295462
parent c5a54508
......@@ -38,7 +38,6 @@
#include <cc/session.h>
#include <exceptions/exceptions.h>
//#include "common.h"
#include "ccsession.h"
#include "config.h"
......@@ -139,10 +138,11 @@ parseCommand(ElementPtr& arg, const ElementPtr command)
return "";
}
void
ModuleSpec
ModuleCCSession::read_module_specification(const std::string& filename) {
std::ifstream file;
ModuleSpec module_spec;
// this file should be declared in a @something@ directive
file.open(filename.c_str());
if (!file) {
......@@ -151,7 +151,7 @@ ModuleCCSession::read_module_specification(const std::string& filename) {
}
try {
module_specification_ = moduleSpecFromFile(file, true);
module_spec = moduleSpecFromFile(file, true);
} catch (ParseError pe) {
cout << "Error parsing module specification file: " << pe.what() << endl;
exit(1);
......@@ -160,6 +160,7 @@ ModuleCCSession::read_module_specification(const std::string& filename) {
exit(1);
}
file.close();
return module_spec;
}
ModuleCCSession::ModuleCCSession(std::string spec_file_name,
......@@ -167,7 +168,7 @@ ModuleCCSession::ModuleCCSession(std::string spec_file_name,
isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args)
) throw (isc::cc::SessionError)
{
read_module_specification(spec_file_name);
module_specification_ = read_module_specification(spec_file_name);
sleep(1);
module_name_ = module_specification_.getFullSpec()->get("module_name")->stringValue();
......@@ -251,6 +252,7 @@ ModuleCCSession::check_command()
{
ElementPtr cmd, routing, data;
if (session_.group_recvmsg(routing, data, true)) {
/* ignore result messages (in case we're out of sync, to prevent
* pingpongs */
if (!data->getType() == Element::map || data->contains("result")) {
......@@ -260,7 +262,16 @@ ModuleCCSession::check_command()
std::string cmd_str = parseCommand(arg, data);
ElementPtr answer;
if (cmd_str == "config_update") {
answer = handleConfigUpdate(arg);
std::string target_module = routing->get("group")->stringValue();
if (target_module == module_name_) {
answer = handleConfigUpdate(arg);
} else {
// ok this update is not for us, if we have this module
// in our remote config list, update that
updateRemoteConfig(target_module, arg);
// we're not supposed to answer to this, so return
return 0;
}
} else {
if (command_handler_) {
answer = command_handler_(cmd_str, arg);
......@@ -274,5 +285,69 @@ ModuleCCSession::check_command()
return 0;
}
std::string
ModuleCCSession::addRemoteConfig(const std::string& spec_file_name)
{
ModuleSpec rmod_spec = read_module_specification(spec_file_name);
std::string module_name = rmod_spec.getFullSpec()->get("module_name")->stringValue();
ConfigData rmod_config = ConfigData(rmod_spec);
session_.subscribe(module_name);
// Get the current configuration values for that module
ElementPtr cmd = Element::createFromString("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name + "\"} ] }");
ElementPtr env, answer;
int rcode;
session_.group_sendmsg(cmd, "ConfigManager");
session_.group_recvmsg(env, answer, false);
ElementPtr new_config = parseAnswer(rcode, answer);
if (rcode == 0) {
rmod_config.setLocalConfig(new_config);
} else {
isc_throw(CCSessionError, "Error getting config for " + module_name + ": " + answer->str());
}
// all ok, add it
remote_module_configs_[module_name] = rmod_config;
return module_name;
}
void
ModuleCCSession::removeRemoteConfig(const std::string& module_name)
{
std::map<std::string, ConfigData>::iterator it;
it = remote_module_configs_.find(module_name);
if (it != remote_module_configs_.end()) {
remote_module_configs_.erase(it);
session_.unsubscribe(module_name);
}
}
ElementPtr
ModuleCCSession::getRemoteConfigValue(const std::string& module_name, const std::string& identifier)
{
std::map<std::string, ConfigData>::iterator it;
it = remote_module_configs_.find(module_name);
if (it != remote_module_configs_.end()) {
return remote_module_configs_[module_name].getValue(identifier);
} else {
isc_throw(CCSessionError, "Remote module " + module_name + " not found.");
}
}
void
ModuleCCSession::updateRemoteConfig(const std::string& module_name, ElementPtr new_config)
{
std::map<std::string, ConfigData>::iterator it;
it = remote_module_configs_.find(module_name);
if (it != remote_module_configs_.end()) {
ElementPtr rconf = (*it).second.getLocalConfig();
isc::data::merge(rconf, new_config);
}
}
}
}
......@@ -90,8 +90,46 @@ public:
*/
void set_command_handler(isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args)) { command_handler_ = command_handler; };
/**
* 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
* \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.
*
* \param spec_file_name The path to the specification file of
* the module we want to have configuration
* values from
* \return The name of the module specified in the given specification
* file
*/
std::string addRemoteConfig(const std::string& spec_file_name);
/**
* Removes the module with the given name from the remote config
* settings. If the module was not added with \c addRemoteConfig(),
* nothing happens.
*/
void removeRemoteConfig(const std::string& module_name);
/**
* Returns the current configuration value for the given module
* name at the given identifier. See \c ConfigData::getValue() for
* more details.
* Raises a ModuleCCSessionError if the module name is unknown
* Raises a DataNotFoundError if the identifier does not exist
* in the specification.
*
* \param module_name The name of the module to get a config value for
* \param identifier The identifier of the config value
* \return The configuration setting at the given identifier
*/
ElementPtr getRemoteConfigValue(const std::string& module_name, const std::string& identifier);
private:
void read_module_specification(const std::string& filename);
ModuleSpec read_module_specification(const std::string& filename);
std::string module_name_;
isc::cc::Session session_;
......@@ -101,6 +139,9 @@ private:
isc::data::ElementPtr(*config_handler_)(isc::data::ElementPtr new_config);
isc::data::ElementPtr(*command_handler_)(const std::string& command, const isc::data::ElementPtr args);
std::map<std::string, ConfigData> remote_module_configs_;
void updateRemoteConfig(const std::string& module_name, ElementPtr new_config);
};
ElementPtr createAnswer(const int rcode);
......
......@@ -195,8 +195,6 @@ class ModuleCCSession(ConfigData):
newc = self._remote_module_configs[module_name].get_local_config()
isc.cc.data.merge(newc, new_config)
self._remote_module_configs[module_name].set_local_config(newc)
print("[XX] updated remote config value: ")
print(newc)
return
# ok, so apparently this update is for us.
......
......@@ -267,8 +267,10 @@ class ConfigManager:
got_error = False
err_list = []
for module in self.config.data:
if module != "version":
if module != "version" and self.config.data[module] != old_data[module]:
update_cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, self.config.data[module])
print("[XX] send update: " + str(update_cmd))
print("[XX] to: " + str(module))
self.cc.group_sendmsg(update_cmd, module)
answer, env = self.cc.group_recvmsg(False)
if answer == None:
......
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